| 
          #include "httpd.h" | 
        
        
           | 
          
 | 
        
        
           | 
          #include <stdio.h> | 
        
        
           | 
          #include <string.h> | 
        
        
           | 
          #include <stdlib.h> | 
        
        
           | 
          #include <unistd.h> | 
        
        
           | 
          #include <sys/types.h> | 
        
        
           | 
          #include <sys/stat.h> | 
        
        
           | 
          #include <sys/socket.h> | 
        
        
           | 
          #include <arpa/inet.h> | 
        
        
           | 
          #include <netdb.h> | 
        
        
           | 
          #include <fcntl.h> | 
        
        
           | 
          #include <signal.h> | 
        
        
           | 
          
 | 
        
        
           | 
          #define CONNMAX 1000 | 
        
        
           | 
          
 | 
        
        
           | 
          static int listenfd, clients[CONNMAX]; | 
        
        
           | 
          static void error(char *); | 
        
        
           | 
          static void startServer(const char *); | 
        
        
           | 
          static void respond(int); | 
        
        
           | 
          
 | 
        
        
           | 
          typedef struct { char *name, *value; } header_t; | 
        
        
           | 
          static header_t reqhdr[17] = { {"\0", "\0"} }; | 
        
        
           | 
          static int clientfd; | 
        
        
           | 
          
 | 
        
        
           | 
          static char *buf; | 
        
        
           | 
          
 | 
        
        
           | 
          void serve_forever(const char *PORT) | 
        
        
           | 
          { | 
        
        
           | 
              struct sockaddr_in clientaddr; | 
        
        
           | 
              socklen_t addrlen; | 
        
        
           | 
              char c;     | 
        
        
           | 
               | 
        
        
           | 
              int slot=0; | 
        
        
           | 
               | 
        
        
           | 
              printf( | 
        
        
           | 
                      "Server started %shttp://127.0.0.1:%s%s\n", | 
        
        
           | 
                      "\033[92m",PORT,"\033[0m" | 
        
        
           | 
                      ); | 
        
        
           | 
          
 | 
        
        
           | 
              // Setting all elements to -1: signifies there is no client connected | 
        
        
           | 
              int i; | 
        
        
           | 
              for (i=0; i<CONNMAX; i++) | 
        
        
           | 
                  clients[i]=-1; | 
        
        
           | 
              startServer(PORT); | 
        
        
           | 
               | 
        
        
           | 
              // Ignore SIGCHLD to avoid zombie threads | 
        
        
           | 
              signal(SIGCHLD,SIG_IGN); | 
        
        
           | 
          
 | 
        
        
           | 
              // ACCEPT connections | 
        
        
           | 
              while (1) | 
        
        
           | 
              { | 
        
        
           | 
                  addrlen = sizeof(clientaddr); | 
        
        
           | 
                  clients[slot] = accept (listenfd, (struct sockaddr *) &clientaddr, &addrlen); | 
        
        
           | 
          
 | 
        
        
           | 
                  if (clients[slot]<0) | 
        
        
           | 
                  { | 
        
        
           | 
                      perror("accept() error"); | 
        
        
           | 
                  } | 
        
        
           | 
                  else | 
        
        
           | 
                  { | 
        
        
           | 
                      if ( fork()==0 ) | 
        
        
           | 
                      { | 
        
        
           | 
                          respond(slot); | 
        
        
           | 
                          exit(0); | 
        
        
           | 
                      } | 
        
        
           | 
                  } | 
        
        
           | 
          
 | 
        
        
           | 
                  while (clients[slot]!=-1) slot = (slot+1)%CONNMAX; | 
        
        
           | 
              } | 
        
        
           | 
          } | 
        
        
           | 
          
 | 
        
        
           | 
          //start server | 
        
        
           | 
          void startServer(const char *port) | 
        
        
           | 
          { | 
        
        
           | 
              struct addrinfo hints, *res, *p; | 
        
        
           | 
          
 | 
        
        
           | 
              // getaddrinfo for host | 
        
        
           | 
              memset (&hints, 0, sizeof(hints)); | 
        
        
           | 
              hints.ai_family = AF_INET; | 
        
        
           | 
              hints.ai_socktype = SOCK_STREAM; | 
        
        
           | 
              hints.ai_flags = AI_PASSIVE; | 
        
        
           | 
              if (getaddrinfo( NULL, port, &hints, &res) != 0) | 
        
        
           | 
              { | 
        
        
           | 
                  perror ("getaddrinfo() error"); | 
        
        
           | 
                  exit(1); | 
        
        
           | 
              } | 
        
        
           | 
              // socket and bind | 
        
        
           | 
              for (p = res; p!=NULL; p=p->ai_next) | 
        
        
           | 
              { | 
        
        
           | 
                  int option = 1; | 
        
        
           | 
                  listenfd = socket (p->ai_family, p->ai_socktype, 0); | 
        
        
           | 
                  setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); | 
        
        
           | 
                  if (listenfd == -1) continue; | 
        
        
           | 
                  if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break; | 
        
        
           | 
              } | 
        
        
           | 
              if (p==NULL) | 
        
        
           | 
              { | 
        
        
           | 
                  perror ("socket() or bind()"); | 
        
        
           | 
                  exit(1); | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              freeaddrinfo(res); | 
        
        
           | 
          
 | 
        
        
           | 
              // listen for incoming connections | 
        
        
           | 
              if ( listen (listenfd, 1000000) != 0 ) | 
        
        
           | 
              { | 
        
        
           | 
                  perror("listen() error"); | 
        
        
           | 
                  exit(1); | 
        
        
           | 
              } | 
        
        
           | 
          } | 
        
        
           | 
          
 | 
        
        
           | 
          
 | 
        
        
           | 
          // get request header | 
        
        
           | 
          char *request_header(const char* name) | 
        
        
           | 
          { | 
        
        
           | 
              header_t *h = reqhdr; | 
        
        
           | 
              while(h->name) { | 
        
        
           | 
                  if (strcmp(h->name, name) == 0) return h->value; | 
        
        
           | 
                  h++; | 
        
        
           | 
              } | 
        
        
           | 
              return NULL; | 
        
        
           | 
          } | 
        
        
           | 
          
 | 
        
        
           | 
          //client connection | 
        
        
           | 
          void respond(int n) | 
        
        
           | 
          { | 
        
        
           | 
              int rcvd, fd, bytes_read; | 
        
        
           | 
              char *ptr; | 
        
        
           | 
          
 | 
        
        
           | 
              buf = malloc(65535); | 
        
        
           | 
              rcvd=recv(clients[n], buf, 65535, 0); | 
        
        
           | 
          
 | 
        
        
           | 
              if (rcvd<0)    // receive error | 
        
        
           | 
                  fprintf(stderr,("recv() error\n")); | 
        
        
           | 
              else if (rcvd==0)    // receive socket closed | 
        
        
           | 
                  fprintf(stderr,"Client disconnected upexpectedly.\n"); | 
        
        
           | 
              else    // message received | 
        
        
           | 
              { | 
        
        
           | 
                  buf[rcvd] = '\0'; | 
        
        
           | 
          
 | 
        
        
           | 
                  method = strtok(buf,  " \t\r\n"); | 
        
        
           | 
                  uri    = strtok(NULL, " \t"); | 
        
        
           | 
                  prot   = strtok(NULL, " \t\r\n");  | 
        
        
           | 
          
 | 
        
        
           | 
                  fprintf(stderr, "\x1b[32m + [%s] %s\x1b[0m\n", method, uri); | 
        
        
           | 
                   | 
        
        
           | 
                  if (qs = strchr(uri, '?')) | 
        
        
           | 
                  { | 
        
        
           | 
                      *qs++ = '\0'; //split URI | 
        
        
           | 
                  } else { | 
        
        
           | 
                      qs = uri - 1; //use an empty string | 
        
        
           | 
                  } | 
        
        
           | 
          
 | 
        
        
           | 
                  header_t *h = reqhdr; | 
        
        
           | 
                  char *t, *t2; | 
        
        
           | 
                  while(h < reqhdr+16) { | 
        
        
           | 
                      char *k,*v,*t; | 
        
        
           | 
                      k = strtok(NULL, "\r\n: \t"); if (!k) break; | 
        
        
           | 
                      v = strtok(NULL, "\r\n");     while(*v && *v==' ') v++; | 
        
        
           | 
                      h->name  = k; | 
        
        
           | 
                      h->value = v; | 
        
        
           | 
                      h++; | 
        
        
           | 
                      fprintf(stderr, "[H] %s: %s\n", k, v); | 
        
        
           | 
                      t = v + 1 + strlen(v); | 
        
        
           | 
                      if (t[1] == '\r' && t[2] == '\n') break; | 
        
        
           | 
                  } | 
        
        
           | 
                  t++; // now the *t shall be the beginning of user payload | 
        
        
           | 
                  t2 = request_header("Content-Length"); // and the related header if there is   | 
        
        
           | 
                  payload = t; | 
        
        
           | 
                  payload_size = t2 ? atol(t2) : (rcvd-(t-buf)); | 
        
        
           | 
          
 | 
        
        
           | 
                  // bind clientfd to stdout, making it easier to write | 
        
        
           | 
                  clientfd = clients[n]; | 
        
        
           | 
                  dup2(clientfd, STDOUT_FILENO); | 
        
        
           | 
                  close(clientfd); | 
        
        
           | 
          
 | 
        
        
           | 
                  // call router | 
        
        
           | 
                  route(); | 
        
        
           | 
          
 | 
        
        
           | 
                  // tidy up | 
        
        
           | 
                  fflush(stdout); | 
        
        
           | 
                  shutdown(STDOUT_FILENO, SHUT_WR); | 
        
        
           | 
                  close(STDOUT_FILENO); | 
        
        
           | 
              } | 
        
        
           | 
          
 | 
        
        
           | 
              //Closing SOCKET | 
        
        
           | 
              shutdown(clientfd, SHUT_RDWR);         //All further send and recieve operations are DISABLED... | 
        
        
           | 
              close(clientfd); | 
        
        
           | 
              clients[n]=-1; | 
        
        
           | 
          } | 
        
  
Hi! Greate job.
It would be great, that you resolve a small memory leak from
bufvariable.You can just add one line, at the end of
respondfunction like