#include #include #include #include #include #include #include #include #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::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 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); }