#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "http.h" #include "memory.h" #define PORT 8080 int num_threads=0; static void signal_handler(int sig){ if(sig==SIGCHLD){ int saved_errno=errno; while(true){ int status; pid_t pid=waitpid(-1,&status,WNOHANG); if(pid<=0){ break; } if(WIFEXITED(status)){ num_threads--; } } errno=saved_errno; } } // Returns -1 on error, 0 on success static int sendall(int sock,const char *buf,ssize_t len){ if(len==-1){ len=strlen(buf); } ssize_t sent=0; while(sentmethod); sendallf(sock,"URL: %s\n",headers->url); sendallf(sock,"Version: %s\n",headers->version); for(int i=0;inheaders;i++){ sendallf(sock,"Header '%s': '%s'\n",headers->headers[i][0],headers->headers[i][1]); } } int main(void){ int sock=socket(PF_INET,SOCK_STREAM,0); if(sock<0){ perror("socket"); return 1; } int one=1; if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(int))<0){ perror("setsockopt"); return 1; } struct sockaddr_in sin; sin.sin_family=AF_INET; sin.sin_addr.s_addr=htonl(INADDR_ANY); sin.sin_port=htons(PORT); if(bind(sock,(struct sockaddr*)&sin,sizeof(sin))<0){ close(sock); perror("bind"); return 1; } if(listen(sock,8)<0){ perror("listen"); return 1; } signal(SIGCHLD,signal_handler); printf("Listening on port %d\n",PORT); while(true){ struct sockaddr_storage client_addr; socklen_t client_addr_sz=sizeof(client_addr); int clientsock=accept(sock,(struct sockaddr*)&client_addr,&client_addr_sz); if(clientsock<0){ perror("accept"); continue; } char str[INET_ADDRSTRLEN]; inet_ntop(client_addr.ss_family,&((struct sockaddr_in*)&client_addr)->sin_addr, str,sizeof(str)); pid_t pid=fork(); if(pid==0){ close(sock); connection_handler(clientsock); close(clientsock); exit(0); } if(pid<0){ perror("fork"); return 1; } num_threads++; printf("Accept from %s; child pid %d, %d thread%s\n",str,pid,num_threads, num_threads==1?"":"s"); close(clientsock); } }