Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <arpa/inet.h>
- #include <sys/wait.h>
- #include <signal.h>
- #include <string>
- #include <unistd.h>
- using namespace std;
- string replace_string(string str, const string from, const string to) {
- size_t start_pos = str.find(from);
- if(start_pos == string::npos)
- return str;
- str.replace(start_pos, from.length(), to);
- return str;
- }
- void sigchld_handler(int s)
- {
- while(waitpid(-1, NULL, WNOHANG) > 0);
- }
- class Server
- {
- private:
- string PORT;
- int MAXDATASIZE;
- public:
- Server()
- {
- PORT = "3490";
- MAXDATASIZE = 14096;
- }
- // get sockaddr, IPv4 or IPv6:
- void *get_in_addr(struct sockaddr *sa)
- {
- if (sa->sa_family == AF_INET) {
- return &(((struct sockaddr_in*)sa)->sin_addr);
- }
- return &(((struct sockaddr_in6*)sa)->sin6_addr);
- }
- int start_server()
- {
- // first, load up address structs with getaddrinfo():
- int socketfd, new_socketfd;
- struct addrinfo hints, *servinfo, *p;
- struct sockaddr_storage their_addr;
- socklen_t their_addr_size, addr_size;
- struct sigaction sa;
- char s[INET6_ADDRSTRLEN];
- int rv;
- int yes = 1;
- int BACKLOG = 10;
- int numbytes;
- unsigned char buf[MAXDATASIZE];
- memset(&hints, 0, sizeof hints); // Make sure it is cleared
- hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
- hints.ai_socktype = SOCK_STREAM; // TCP socket
- hints.ai_flags = AI_PASSIVE; // fill in my IP for me
- if ((rv = getaddrinfo(NULL, PORT.c_str(), &hints, &servinfo)) != 0) {
- cerr << "getaddrinfo: " << gai_strerror(rv) << endl;
- return -1;
- }
- // make a socket, bind it asap
- for(p = servinfo; p != NULL; p = p->ai_next)
- {
- if ((socketfd = socket(p->ai_family, p->ai_socktype,
- p->ai_protocol)) == -1) {
- //perror("server: socket");
- cerr << "ERROR: Server: socket" << endl;
- continue;
- }
- if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &yes,
- sizeof(int)) == -1) {
- //perror("setsockopt");
- cerr << "ERROR: setsockopt" << endl;
- exit(1);
- }
- if (bind(socketfd, p->ai_addr, p->ai_addrlen) == -1) {
- close(socketfd);
- //perror("server: bind");
- cerr << "ERROR: server: bind" << endl;
- continue;
- }
- break;
- }
- //If the binding failed
- if ( p == NULL)
- {
- cerr << "Server: failed to bind" << endl;
- return -1;
- }
- //Free space, we do not need it anymore.
- freeaddrinfo(servinfo);
- //Listen to the socket (port)
- if ( listen(socketfd, BACKLOG) == -1)
- {
- cerr << "ERROR: listen" << endl;
- }
- // killing zombie processs (all dead processes)
- sa.sa_handler = sigchld_handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- if (sigaction(SIGCHLD, &sa, NULL) == -1) {
- perror("sigaction");
- exit(1);
- }
- cout << "Server: waiting for connections ...\n"<<endl;
- //Main loop
- for(;;)
- {
- their_addr_size = sizeof their_addr;
- //Create a new socket when we got a connection
- if ((new_socketfd = accept(socketfd, (struct sockaddr *)&their_addr, &their_addr_size))== -1) {
- continue;
- }
- if (!fork())
- {
- //Converts IP address to 127.0.0.1 (or IPv6 format..) format instead of binary
- inet_ntop(their_addr.ss_family,get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
- if ((numbytes = recv(new_socketfd, buf, MAXDATASIZE-1, 0)) == -1) {
- cerr << "ERROR: Failed to receive from user-agent" << endl;
- exit(1);
- }
- else
- {
- /*Parse the header and change some things.*/
- string buffer_str(reinterpret_cast<char*>(buf), MAXDATASIZE); // Convert to unsigned char array to make it easier to handle
- buffer_str = replace_string(buffer_str, "Proxy-Connection: keep-alive","Connection: close"); // Make it connection Close instead of Keep-Alive
- buffer_str = replace_string(buffer_str, "Connection: keep-alive","Connection: close"); // Make it connection Close instead of Keep-Alive
- // removes host from GET, and saves it
- int first = buffer_str.find_first_of("/");
- int last = buffer_str.find_first_of("/", first+2);
- int size_of_buf=buffer_str.size();
- unsigned char host_request[MAXDATASIZE];
- for (int a=0;a<=size_of_buf;a++)
- host_request[a]=buffer_str[a];
- host_request[size_of_buf]='\0';
- string host_name = "";
- for(int i=first+2;i<last;++i)
- host_name += buffer_str[i];
- buffer_str.erase(4, buffer_str.find_first_of("/", first+2)-4);
- /*Set up the socket for the proxy-host */
- int host_sockfd, host_numbytes;
- unsigned char host_buf[MAXDATASIZE];
- struct addrinfo host_hints, *host_servinfo, *host_p;
- int host_rv;
- char host_s[INET6_ADDRSTRLEN];
- memset(&host_hints, 0, sizeof(host_hints));
- host_hints.ai_family = AF_UNSPEC;
- host_hints.ai_socktype = SOCK_STREAM;
- if ((rv = getaddrinfo(host_name.c_str(), "80", &host_hints, &host_servinfo)) != 0) {
- fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
- cerr << "host: " << host_name << endl;
- return 1;
- }
- // loop through all the results and connect to the first we can
- for(host_p = host_servinfo; host_p != NULL; host_p = host_p->ai_next) {
- if ((host_sockfd = socket(host_p->ai_family, host_p->ai_socktype,
- host_p->ai_protocol)) == -1) {
- perror("client: socket");
- continue;
- }
- if (connect(host_sockfd, host_p->ai_addr, host_p->ai_addrlen) == -1) {
- close(host_sockfd);
- perror("client: connect");
- continue;
- }
- break;
- }
- if (host_p == NULL) {
- fprintf(stderr, "client: failed to connect\n");
- return 2;
- }
- inet_ntop(host_p->ai_family, get_in_addr((struct sockaddr *)host_p->ai_addr),s, sizeof s); //Converts the IP address from binary to IPv4/6-format
- //printf("client: connecting to %s\n", s);
- freeaddrinfo(host_servinfo); // all done with this structure
- /*Send the GET request to the server*/
- send_message(host_sockfd, host_request, sizeof(host_request), "Webserver");
- memset(&host_buf, 0, MAXDATASIZE);
- while (recv(host_sockfd, &host_buf, MAXDATASIZE, 0) > 0 ) {
- int len;
- len = sizeof(host_buf);
- if ( send_message(new_socketfd, (unsigned char *)host_buf, MAXDATASIZE, "Browser") == -1) {
- perror("sendall");
- printf("We only sent %d bytes because of the error!\n", len);
- }
- memset(&host_buf, 0, MAXDATASIZE);
- }
- //close(host_sockfd);
- exit(0);
- }
- close(new_socketfd);
- }
- //cout << "server: got connection from " << s << endl;
- close(new_socketfd); // parent doesn't need this
- }
- return 1;
- }
- int send_message(int &socket,unsigned char msg[], int length, string too)
- {
- int total = 0; // how many bytes we've sent
- int bytesleft = length; // how many we have left to send
- int data_sent;
- while(total < length) {
- if ((data_sent = (send(socket, msg+total, bytesleft, 0))) == -1)
- {
- cerr << "ERROR: sending to " << too << endl;
- cerr << "We will lose a packet due to" << endl;
- perror("send");
- cerr << "-------------------MEDDELANDE-------------------\n\n" << msg << endl <<
- "--------------------------------------------------\n\n";
- cerr << "Closing the connection\n";
- return -1;
- }
- if (data_sent == -1) { break; }
- total += data_sent;
- bytesleft -= data_sent;
- }
- return total;
- }
- };
- int main()
- {
- Server srv;
- srv.start_server();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement