1. #include <iostream>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <errno.h>
  6. #include <string.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <netdb.h>
  11. #include <arpa/inet.h>
  12. #include <sys/wait.h>
  13. #include <signal.h>
  14. #include <string>
  15. #include <unistd.h>
  16.  
  17. using namespace std;
  18.  
  19. string replace_string(string str, const string from, const string to) {
  20.     size_t start_pos = str.find(from);
  21.     if(start_pos == string::npos)
  22.         return str;
  23.     str.replace(start_pos, from.length(), to);
  24.     return str;
  25. }
  26.  
  27. void sigchld_handler(int s)
  28. {
  29.     while(waitpid(-1, NULL, WNOHANG) > 0);
  30. }
  31. class Server
  32. {
  33. private:
  34.     string PORT;
  35.     int MAXDATASIZE;
  36. public:
  37.     Server()
  38.     {
  39.         PORT = "3490";
  40.         MAXDATASIZE = 14096;
  41.    
  42.     }
  43.  
  44.  
  45.  
  46.     // get sockaddr, IPv4 or IPv6:
  47.     void *get_in_addr(struct sockaddr *sa)
  48.     {
  49.         if (sa->sa_family == AF_INET) {
  50.             return &(((struct sockaddr_in*)sa)->sin_addr);
  51.         }
  52.  
  53.         return &(((struct sockaddr_in6*)sa)->sin6_addr);
  54.     }
  55.  
  56.     int start_server()
  57.     {
  58.  
  59.         // first, load up address structs with getaddrinfo():
  60.         int socketfd, new_socketfd;
  61.         struct addrinfo hints, *servinfo, *p;
  62.         struct sockaddr_storage their_addr;
  63.         socklen_t their_addr_size, addr_size;
  64.         struct sigaction sa;
  65.  
  66.         char s[INET6_ADDRSTRLEN];
  67.  
  68.         int rv;
  69.         int yes = 1;
  70.         int BACKLOG = 10;
  71.         int numbytes;
  72.         unsigned char buf[MAXDATASIZE];
  73.        
  74.         memset(&hints, 0, sizeof hints); // Make sure it is cleared
  75.         hints.ai_family = AF_UNSPEC;     // use IPv4 or IPv6, whichever
  76.         hints.ai_socktype = SOCK_STREAM; // TCP socket
  77.         hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
  78.  
  79.         if ((rv = getaddrinfo(NULL, PORT.c_str(), &hints, &servinfo)) != 0) {
  80.             cerr << "getaddrinfo: " << gai_strerror(rv) << endl;
  81.             return -1;
  82.         }
  83.        
  84.         // make a socket, bind it asap
  85.         for(p = servinfo; p != NULL; p = p->ai_next)
  86.         {
  87.             if ((socketfd = socket(p->ai_family, p->ai_socktype,
  88.                                    p->ai_protocol)) == -1) {
  89.                 //perror("server: socket");
  90.                 cerr << "ERROR: Server: socket" << endl;
  91.                 continue;
  92.             }
  93.  
  94.             if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &yes,
  95.                            sizeof(int)) == -1) {
  96.                 //perror("setsockopt");
  97.                 cerr << "ERROR: setsockopt" << endl;
  98.                 exit(1);
  99.             }
  100.  
  101.             if (bind(socketfd, p->ai_addr, p->ai_addrlen) == -1) {
  102.                 close(socketfd);
  103.                 //perror("server: bind");
  104.                 cerr << "ERROR: server: bind" << endl;
  105.                 continue;
  106.             }
  107.             break; 
  108.         }
  109.         //If the binding failed
  110.         if ( p == NULL)
  111.         {
  112.             cerr << "Server: failed to bind" << endl;
  113.             return -1;
  114.         }
  115.  
  116.         //Free space, we do not need it anymore.
  117.         freeaddrinfo(servinfo);
  118.  
  119.         //Listen to the socket (port)
  120.         if ( listen(socketfd, BACKLOG) == -1)
  121.         {
  122.             cerr << "ERROR: listen" << endl;
  123.         }
  124.  
  125.         // killing zombie processs (all dead processes)
  126.         sa.sa_handler = sigchld_handler;
  127.         sigemptyset(&sa.sa_mask);
  128.         sa.sa_flags = SA_RESTART;
  129.         if (sigaction(SIGCHLD, &sa, NULL) == -1) {
  130.             perror("sigaction");
  131.             exit(1);
  132.         }
  133.        
  134.         cout << "Server: waiting for connections ...\n"<<endl;
  135.        
  136.         //Main loop
  137.         for(;;)
  138.         {  
  139.             their_addr_size = sizeof their_addr;          
  140.             //Create a new socket when we got a connection
  141.             if ((new_socketfd = accept(socketfd, (struct sockaddr *)&their_addr, &their_addr_size))== -1) {
  142.                 continue;
  143.             }
  144.             if (!fork())
  145.             {
  146.                 //Converts IP address to 127.0.0.1 (or IPv6 format..) format instead of binary
  147.                 inet_ntop(their_addr.ss_family,get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
  148.  
  149.                 if ((numbytes = recv(new_socketfd, buf, MAXDATASIZE-1, 0)) == -1) {
  150.                     cerr << "ERROR: Failed to receive from user-agent" << endl;
  151.                     exit(1);
  152.                 }
  153.                 else
  154.                 {
  155.                     /*Parse the header and change some things.*/
  156.  
  157.                     string buffer_str(reinterpret_cast<char*>(buf), MAXDATASIZE);   // Convert to unsigned char array to make it easier to handle                              
  158.                     buffer_str = replace_string(buffer_str, "Proxy-Connection: keep-alive","Connection: close"); // Make it connection Close instead of Keep-Alive
  159.                     buffer_str = replace_string(buffer_str, "Connection: keep-alive","Connection: close"); // Make it connection Close instead of Keep-Alive
  160.                     // removes host from GET, and saves it
  161.                     int first = buffer_str.find_first_of("/");                      
  162.                     int last =  buffer_str.find_first_of("/", first+2);
  163.                     int size_of_buf=buffer_str.size();
  164.                     unsigned char host_request[MAXDATASIZE];
  165.                     for (int a=0;a<=size_of_buf;a++)
  166.                         host_request[a]=buffer_str[a];
  167.                     host_request[size_of_buf]='\0';
  168.                     string host_name = "";
  169.                     for(int i=first+2;i<last;++i)
  170.                         host_name += buffer_str[i];
  171.                     buffer_str.erase(4, buffer_str.find_first_of("/", first+2)-4);
  172.      
  173.  
  174.      
  175.                     /*Set up the socket for the proxy-host */
  176.  
  177.                     int host_sockfd, host_numbytes;  
  178.                     unsigned char host_buf[MAXDATASIZE];
  179.                     struct addrinfo host_hints, *host_servinfo, *host_p;
  180.                     int host_rv;
  181.                     char host_s[INET6_ADDRSTRLEN];
  182.  
  183.  
  184.                     memset(&host_hints, 0, sizeof(host_hints));
  185.                     host_hints.ai_family = AF_UNSPEC;
  186.                     host_hints.ai_socktype = SOCK_STREAM;
  187.  
  188.  
  189.                     if ((rv = getaddrinfo(host_name.c_str(), "80", &host_hints, &host_servinfo)) != 0) {
  190.                         fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
  191.                         cerr << "host: " << host_name << endl;
  192.                         return 1;
  193.                     }
  194.  
  195.                     // loop through all the results and connect to the first we can
  196.                     for(host_p = host_servinfo; host_p != NULL; host_p = host_p->ai_next) {
  197.                         if ((host_sockfd = socket(host_p->ai_family, host_p->ai_socktype,
  198.                                                   host_p->ai_protocol)) == -1) {
  199.                             perror("client: socket");
  200.                             continue;
  201.                         }
  202.  
  203.                         if (connect(host_sockfd, host_p->ai_addr, host_p->ai_addrlen) == -1) {
  204.                             close(host_sockfd);
  205.                             perror("client: connect");
  206.                             continue;
  207.                         }
  208.  
  209.                         break;
  210.                     }
  211.  
  212.                     if (host_p == NULL) {
  213.                         fprintf(stderr, "client: failed to connect\n");
  214.                         return 2;
  215.                     }
  216.  
  217.                     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
  218.                     //printf("client: connecting to %s\n", s);
  219.  
  220.                     freeaddrinfo(host_servinfo); // all done with this structure
  221.  
  222.                     /*Send the GET request to the server*/
  223.                     send_message(host_sockfd, host_request, sizeof(host_request), "Webserver");
  224.                
  225.                     memset(&host_buf, 0, MAXDATASIZE);
  226.                    
  227.                     while (recv(host_sockfd, &host_buf, MAXDATASIZE, 0) > 0 ) {
  228.                         int len;
  229.                         len = sizeof(host_buf);
  230.                         if ( send_message(new_socketfd, (unsigned char *)host_buf, MAXDATASIZE, "Browser") == -1) {
  231.                             perror("sendall");
  232.                             printf("We only sent %d bytes because of the error!\n", len);
  233.                         }
  234.                         memset(&host_buf, 0, MAXDATASIZE);
  235.                     }
  236.  
  237.                    
  238.                     //close(host_sockfd);
  239.                     exit(0);
  240.                 }
  241.                 close(new_socketfd);
  242.                
  243.             }
  244.    
  245.      
  246.             //cout << "server: got connection from " << s << endl;
  247.  
  248.             close(new_socketfd);  // parent doesn't need this
  249.          
  250.        }
  251.  
  252.        return 1;
  253.    }
  254.    int send_message(int &socket,unsigned char msg[], int length, string too)
  255.    {
  256.        int total = 0;        // how many bytes we've sent
  257.         int bytesleft = length; // how many we have left to send
  258.         int data_sent;
  259.  
  260.         while(total < length) {
  261.             if ((data_sent = (send(socket, msg+total, bytesleft, 0))) == -1)
  262.             {
  263.                 cerr << "ERROR: sending to " << too << endl;
  264.                 cerr << "We will lose a packet due to" << endl;
  265.                 perror("send");
  266.                 cerr << "-------------------MEDDELANDE-------------------\n\n" << msg << endl <<
  267.                     "--------------------------------------------------\n\n";
  268.                 cerr << "Closing the connection\n";
  269.                 return -1;
  270.             }
  271.             if (data_sent == -1) { break; }
  272.             total += data_sent;
  273.             bytesleft -= data_sent;
  274.         }
  275.        
  276.        
  277.         return total;
  278.     }
  279. };
  280.  
  281. int main()
  282. {
  283.     Server srv;
  284.     srv.start_server();
  285. }