mlisp/clib/tcpnet.cpp

119 lines
2.7 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "tcpnet.h"
void error(const char *msg) {
// perror(msg);
throw std::runtime_error(msg);
}
// TODO do it as RAII
TcpNet::TcpNet() {}
#define TCPNET_BUFFER_SIZE 16256
int TcpNet::server(int portno, std::function<std::pair<bool, std::string>(std::string)> process_request) {
int sockfd, newsockfd;
socklen_t clilen;
char buffer[TCPNET_BUFFER_SIZE];
struct sockaddr_in serv_addr, cli_addr;
int n;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
int requests_processed = 0;
bool shutdown = false;
while (!shutdown) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,TCPNET_BUFFER_SIZE);
n = read(newsockfd,buffer,TCPNET_BUFFER_SIZE - 1);
if (n < 0) error("ERROR reading from socket");
std::string request{buffer};
std::pair<bool, std::string> response = process_request(request);
shutdown = response.first;
std::string response_str = response.second;
n = write(newsockfd, response_str.c_str(), response_str.size());
if (n < 0)
error("ERROR writing to socket");
close(newsockfd);
requests_processed++;
}
close(sockfd);
return requests_processed;
}
std::string TcpNet::client(const std::string address, int portno, const std::string &content) {
int sockfd, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[TCPNET_BUFFER_SIZE];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(address.c_str());
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
n = write(sockfd, content.c_str(), strlen(content.c_str()));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer, TCPNET_BUFFER_SIZE);
n = read(sockfd,buffer, TCPNET_BUFFER_SIZE - 1);
if (n < 0)
error("ERROR reading from socket");
close(sockfd);
return std::string(buffer);
}