int main(int argc,char **argv) { //服务器socket号 int server_sock; int client_sock; //端口号 int port; int client_addr_len; struct sockaddr_in client_addr; pthread_t thread_id; if(argc!=2){ perror("please run it like: ./tinyweb port"); exit(EXIT_FAILURE); } //把字符串类型端口号转为整型 port = atoi(argv[1]); //初始化服务器socket号 server_sock=start_up(port); client_addr_len=sizeof(client_addr); //不断循环,不断接收客户端的链接请求 while(1){ //accept函数返回值,初始化客户socket号,以后获取客户端的内容和向客户端发送信息都 //通过这个端口号 client_sock = accept(server_sock,(struct sockaddr *)&client_addr,&client_addr_len); if(client_sock == -1){ error_die("accept error\n"); } //创建新的线程来为客户端服务,主要pthread_create这个函数的参数 if(pthread_create(&thread_id,NULL,(void *)deal_request,(void *)&client_sock)!=0) error_die("pthread_create error\n"); } close(server_sock); return 0; }
void check_header_gzip(int src_fd) { union { unsigned char raw[8]; struct { unsigned char method; unsigned char flags; unsigned int mtime; unsigned char xtra_flags; unsigned char os_flags; } formatted; } header; xread(src_fd, header.raw, 8); /* Check the compression method */ if (header.formatted.method != 8) /* error_die("Unknown compression method %d", header.formatted.method);*/ error_die("Unknown compression method"); if (header.formatted.flags & 0x04) { /* bit 2 set: extra field present */ unsigned char extra_short; extra_short = xread_char(src_fd) + (xread_char(src_fd) << 8); while (extra_short > 0) { /* Ignore extra field */ xread_char(src_fd); extra_short--; } } /* Discard original name if any */ if (header.formatted.flags & 0x08) /* bit 3 set: original file name present */ while(xread_char(src_fd) != 0) ; /* Discard file comment if any */ if (header.formatted.flags & 0x10) /* bit 4 set: file comment present */ while(xread_char(src_fd) != 0) ; /* Read the header checksum */ if (header.formatted.flags & 0x02) { xread_char(src_fd); xread_char(src_fd); } }
int startup(u_short *port) { int httpd = 0; struct sockaddr_in name; httpd = socket(PF_INET, SOCK_STREAM, 0); if (httpd == -1) error_die("socket"); memset(&name, 0, sizeof(name)); name.sin_family = AF_INET; name.sin_port = htons(*port); name.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(httpd, (struct sockaddr *)&name, sizeof(name)) < 0) error_die("bind"); if (*port == 0) { /* if dynamically allocating a port */ int namelen = sizeof(name); if (getsockname(httpd, (struct sockaddr *)&name, &namelen) == -1) error_die("getsockname"); *port = ntohs(name.sin_port); } if (listen(httpd, 5) < 0) error_die("listen"); return(httpd); }
int open_target( char * file ) { if(!file) error_die("null arg",1); /* there's only 1 target */ if( target_elf ) free_elf( target_elf ); if(!(target_elf = new_elf(file))) error_ret("can't open elf",-1); #ifdef USE_COMMANDS /* check for info saved in xml file */ if( use_info ) if(open_target_info( target_elf ) < 0 ) error_ret("problem getting info",-1); #endif /* USE_COMMANDS */ disasm_init(); crunch_pltmap(); gather_funcs_by_symtab( get_elf() ); gather_funcs_by_section(NULL); get_objs_from_entry(get_elf()); gather_vars( get_elf() ); sync_func_map(); #if 0 if( do_disasm || do_pltmap ||do_disasm_seg ||do_map_dmp){ crunch_pltmap(); } if( do_dump_funcs || do_disasm || do_disasm_seg || do_map_dmp ){ gather_funcs_by_symtab( get_elf() ); gather_funcs_by_section(NULL); get_objs_from_entry(get_elf()); } if( do_vars || do_disasm || do_disasm_seg || do_map_dmp || do_map_dmp ) gather_vars( get_elf() ); sync_func_map(); #endif return(0); }
int main(void) { int server_sock = -1; u_short port = 0; int client_sock = -1; struct sockaddr_in client_name; int client_name_len = sizeof(client_name); pid_t pid; //pthread_t newthread; //服务器启动,在指定端口或随机选取端口绑定 httpd 服务。 server_sock = startup(&port); printf("httpd running on port %d\n", port); while (1) { //accept返回的是全新的描述符,代表与所返回客户的TCP连接。 //server_sock是监听套接字,仅一个,服务器的生命期内一直存在 client_sock = accept(server_sock, (struct sockaddr *)&client_name, &client_name_len); if (client_sock == -1) error_die("accept"); printf("Receive a request from %s:%d\n" , inet_ntoa(client_name.sin_addr) , client_name.sin_port); if((pid = fork()) == 0) { //因子进程也有指向server_sock文件的表项,且它不关心服务器套接字,它只处理客户套接字,因此close它 //下面的父进程close client_sock也是同一个道理 close(server_sock); accept_request(client_sock); close(client_sock); exit(0); } int status = 0; pid_t pid2 = wait(&status); printf("My pid is %d\n", pid2); close(client_sock); //收到一个 HTTP 请求时(其实就是 listen 的端口 accpet 的时候),派生一个线程运行 accept_request 函数。 // if (pthread_create(&newthread , NULL, accept_request, client_sock) != 0) // perror("pthread_create"); } return(0); }
int main(void) { int server_sock = -1; // 服务端socket描述符 u_short port = 8089; // 端口号 int client_sock = -1; // 客户端socket描述符 struct sockaddr_in client_name; // 客户端地址结构 socklen_t client_name_len = sizeof(client_name); // 客户端地址结构长度 pthread_t newthread; // 线程ID server_sock = startup(&port); // 创建socket、绑定、监听、启动服务端 printf("httpd running on port %d\n", port); char buf[INET_ADDRSTRLEN]; // 在循环中不停接收客户连接 // 每接受一个连接就开一个新的线程去处理 while (1) { client_sock = accept(server_sock, (struct sockaddr *)&client_name, &client_name_len); // 阻塞等待客户端连接 // const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); printf("client connection (%s:%d)\n", inet_ntop(AF_INET, &client_name.sin_addr, buf, INET_ADDRSTRLEN), ntohs(client_name.sin_port)); if (client_sock == -1) error_die("accept"); /* accept_request(client_sock); */ if (pthread_create(&newthread , NULL, accept_request, client_sock) != 0) // 开新线程处理 perror("pthread_create"); } close(server_sock); // 关闭服务端socket return(0); }
int main(int argc, char* argv[]){ int server_sock = -1; u_short port = 4000; int client = -1; struct sockaddr_in client_name; socklen_t client_name_len = sizeof(client_name); pthread_t newthread; server_sock = startup(&port); printf("httpd running on port %d\n", port); while(1){ client = accept(server_sock, (struct sockaddr *)&client_name, &client_name_len); if(client == -1){ error_die("accpet"); } if(pthread_create(&newthread, NULL, (void *)accept_request, (void *)&client) != 0){ perror("pthread_create"); } } close(server_sock); return 0; }
/** * @brief create a soocket * * @param domain [in] This value can be AF_INET,AF_UNIX,AF_LOCAL, * PF_INET, PF_UINX and PF_LOCAL. * @param type [in] can be SOCK_TREAM, SOCK_DGRAM. * * @return socket fd, if succ; -1, if failed. */ int socket_create(int domain, int type) { int fd = socket(domain, type, 0); if (fd == -1) error_die("socket"); return fd; }
/** * @brief listening for an incoming connect. * * @param fd [in] listen socket fd. * @param backlog [in] Maximum length of the queue of pending connections. * * @return 0, if succ; -1, if failed. */ int socket_listen(int fd, int backlog) { if (listen(fd, backlog) < 0) error_die("listen"); return 0; }
int main (int argc, char *argv[]) { // double legit; srand48(time(NULL)); // Seed RNG char *buffer = NULL; // A buffer for the received data long bufsize = 0; FILE* outfile; if (argc != 6) { printf("Arg count was %d.\n", argc); usage_err(); } // For statistical purposes int corrupt_count = 0; int loss_count = 0; int sockfd, portnum, bytes_recv, bytes_sent; int lost_packet = 0; socklen_t sin_size; struct sockaddr_in srv_addr; struct hostent *host; // Send data struct gbnpacket send_data; // Receive data struct gbnpacket recv_data; // recv_data.length = p_size(); // recv_data.sequence = 0; // Parse command line arguments host = (struct hostent *) gethostbyname(argv[1]); portnum = atoi(argv[2]); char* filename = argv[3]; printf("Filename is %s\n", filename); double p_loss = atof(argv[4]); // Probability of packet loss double p_corr = atof(argv[5]); // Probability of packet corruption sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) error_die("Error opening socket.\n"); // Initialize server address srv_addr.sin_family = AF_INET; srv_addr.sin_port = htons(portnum); srv_addr.sin_addr = *((struct in_addr *)host->h_addr); bzero(&(srv_addr.sin_zero),8); sin_size = sizeof(struct sockaddr); //------------------------------------ // SEND request for file //------------------------------------ memset(&send_data, 0, sizeof(struct gbnpacket)); send_data.type = REQUEST; send_data.sequence = 0; send_data.corrupt = 0; strcpy(send_data.data, filename); // Might have to \0 out the last byte of data...not sure yet // send_data.data[strlen(filename)] = '\0'; // send_data.length = p_header_size() + strlen(filename) + 1; // +1 for the null byte? send_data.length = strlen(filename); printf("Sending request to CS118 for %s\n", filename); long expecting_packet = 0; // The sequence number of the expected packet while (1) { if (send_data.type == REQUEST) { // Send // Convert to network byte order convertpacket_hton(&send_data); // bytes_sent = sendto(sockfd, &send_data, send_data.length, 0, bytes_sent = sendto(sockfd, &send_data, sizeof(struct gbnpacket), 0, (struct sockaddr *)&srv_addr, sizeof(struct sockaddr)); // TO-DO: Check to see if bytes_sent matches up with the length of the packet in total. // buffer = NULL; print_packet_info_client(&send_data, CLIENT); // printf("Request sent.\n"); } // -------------------------------- // RECEIVE data response // -------------------------------- printf("Waiting for response from CS118.\n"); // bytes_recv = recvfrom(sockfd, &recv_data, recv_data.length, 0, bytes_recv = recvfrom(sockfd, &recv_data, sizeof(struct gbnpacket), 0, (struct sockaddr*)&srv_addr, &sin_size); // Convert to host byte order convertpacket_ntoh(&recv_data); // Set packet lost or not lost_packet = play_the_odds(p_loss, &loss_count); if (lost_packet) { printf("\nLOST PACKET!\n\n"); continue; // Do nothing else, just receive the packet and move on. } // TO-DO: CHECK TO MAKE SURE THAT THE PROGRAM DOESN'T SEGFAULT IF recvfrom() FAILS! i.e. if bytesrecv == 0 // recv_data.data[bytes_recv] = '\0'; print_packet_info_client(&recv_data, SERVER); // printf("Received : %s\n", recv_data.data); // -------------------------------- // PREPARE acknowledgement // -------------------------------- if (recv_data.type == FIN) { // Send a FIN in return, and end the client process char *msg = "Terminating connection."; memset(&send_data, 0, sizeof(struct gbnpacket)); send_data.type = FIN; send_data.sequence = 0; send_data.corrupt = 0; // set_packet_corruption(); send_data.length = 0; // Don't need to initialize the data because of the memset printf("%s. Sending FIN packet.\n", msg); printf("STATS: Sent %d corrupt ACKs. Treated %d packets as \'lost\'.\n", corrupt_count, loss_count); // Convert to network byte order convertpacket_hton(&send_data); /* send_data.type = htonl(send_data.type); send_data.sequence = htonl(send_data.sequence); send_data.length = htonl(send_data.length); */ bytes_sent = sendto(sockfd, &send_data, sizeof(struct gbnpacket), 0, (struct sockaddr *)&srv_addr, sizeof(struct sockaddr)); // Modify the filename strcat(filename, ".received"); outfile = fopen(filename, "wb"); if (outfile) { fwrite(buffer, bufsize, 1, outfile); printf("Successfully wrote buffer to file \"%s\"\n.", filename); } else error_die("Error writing buffer to file."); return 0; // End the client process } if (!buffer) { bufsize = sizeof(char) * recv_data.total_length; buffer = (char *)malloc(bufsize); if (!buffer) error_die("Not enough space for client file buffer."); } memset(&send_data, 0, sizeof(struct gbnpacket)); send_data.type = ACK; // strcpy(send_data.data, "Acknowledged."); // send_data.data[strlen(send_data.data)] = '\0'; // Zero byte // send_data.length = p_header_size() + strlen(send_data.data) + 1; // Might need +1 for zero byte send_data.length = 0; // ACKs have no data // send_data.corrupt = 0; // send_data.corrupt = set_packet_corruption(p_corr); // ---------------------------------------------------------------- // SEND acknowledgement, depending on the last packet received. // ---------------------------------------------------------------- // Packet is legit if (recv_data.corrupt == 0 && recv_data.sequence <= expecting_packet) // Use <= for duplicate packets { // Copy file data into the buffer memcpy(buffer+recv_data.sequence, recv_data.data, recv_data.length); // send_data.sequence = recv_data.sequence + (bytes_recv - p_header_size()); send_data.sequence = recv_data.sequence + PACKETSIZE; send_data.corrupt = play_the_odds(p_corr, &corrupt_count); // Convert to network byte order /* send_data.type = htonl(send_data.type); send_data.sequence = htonl(send_data.sequence); send_data.length = htonl(send_data.length); */ // expecting_packet = recv_data.sequence + PACKETSIZE; expecting_packet = send_data.sequence; // Send // printf("Sending acknowledgement from else...\n"); // sendto(sockfd, &send_data, send_data.length, 0, // if (legit >= p_loss) // { // Convert to network byte order convertpacket_hton(&send_data); sendto(sockfd, &send_data, sizeof(struct gbnpacket), 0, (struct sockaddr *)&srv_addr, sizeof(struct sockaddr)); print_packet_info_client(&send_data, CLIENT); // } } // else if (recv_data.corrupt == 0 && recv_data.sequence < expecting_packet) // { // printf("\nDUPLICATE PACKET, IGNORING!\n\n"); // continue; // DUPLICATE PACKET // } // if (recv_data.sequence != expecting_packet || recv_data.corrupt == 1) // Packet received OUT OF ORDER or is CORRUPT else // Packet is not legit { // Be sure to send duplicate ACKs? Not in the book // The ACK should be for the last correctly-received packet. send_data.sequence = expecting_packet; send_data.corrupt = play_the_odds(p_corr, &corrupt_count); // Send // printf("Sending acknowledgement from if...\n"); // sendto(sockfd, &send_data, send_data.length, 0, // if (legit >= p_loss) // { // Convert to network byte order /* send_data.type = htonl(send_data.type); send_data.sequence = htonl(send_data.sequence); send_data.length = htonl(send_data.length); send_data.corrupt = htonl(send_data.corrupt); */ convertpacket_hton(&send_data); sendto(sockfd, &send_data, sizeof(struct gbnpacket), 0, (struct sockaddr *)&srv_addr, sizeof(struct sockaddr)); print_packet_info_client(&send_data, CLIENT); // } } } return 0; }
/* 处理客户端发送过来的请求,主要是判断请求是get还是post方法 把 请求方法 url protocol 进行分离 并判断是请求静态内容还是cgi 分别调用deal_static和deal_cgi进行处理 */ void deal_request(void *client_sock){ //客户端sock号 int cli_sock =*(int*)client_sock; int charnum=0; char buf[1024]; //请求方法 char method[10]; char url[255]; char protocol[50]; bool cgi=false; //cgi程序的参数 char *query_string=NULL; char *path=NULL; //文件的各种信息,具体可以查看stat函数 struct stat st; //读取一行 charnum=get_line(cli_sock,buf,sizeof(buf)); if(charnum==0){ error_die("get_line error\n"); } //进行分离 if(EOF==sscanf(buf,"%[^ ] %[^ ] %[^ ]",method,url,protocol)){ error_die("sscanf error"); } //method is not get and post if((strcasecmp(method,"GET")!=0)&&(strcasecmp(method,"POST")!=0)){ uncompleted(cli_sock,method); return; } if(strcasecmp(method,"POST")==0){ cgi=true; } if(strcasecmp(method,"GET")==0){ //找出?字符的位置 query_string=strchr(url,'?'); if(query_string){ cgi=true; *query_string='\0'; query_string++; } //如果是get方法,后面的内容没有用,就丢弃 charnum=get_line(cli_sock,buf,sizeof(buf)); while((charnum>0)&&strcmp("\n",buf)){ //printf("%s",buf); charnum=get_line(cli_sock,buf,sizeof(buf)); } } //url的形式为:/aisi.jpg,而path是存取路径,把第一个/去掉,变为aisi.jpg path=url+1; //判断文件是否存在 if(stat(path,&st)==-1){ not_found(cli_sock,path); }else{ //如果访问的是目录,默认为访问主页 if((st.st_mode&S_IFMT)==S_IFDIR){ sprintf(path,"index.html"); } //查看是否有执行权限,如果有,就是cgi if((st.st_mode&S_IXOTH)||(st.st_mode&S_IXUSR)||(st.st_mode&S_IXGRP)){ cgi=true; } //分别调用对应的处理函数 if(cgi){ deal_cgi(cli_sock,path,method,query_string); }else{ deal_static(cli_sock,path,(int)st.st_size); } } close(cli_sock); }
static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned int my_bl, const unsigned int my_bd, int setup) { static unsigned int e; /* table entry flag/number of extra bits */ static unsigned int n, d; /* length and index for copy */ static unsigned int w; /* current gunzip_window position */ static huft_t *t; /* pointer to table entry */ static unsigned int ml, md; /* masks for bl and bd bits */ static unsigned int b; /* bit buffer */ static unsigned int k; /* number of bits in bit buffer */ static huft_t *tl, *td; static unsigned int bl, bd; if (setup) /* 1st time we are called, copy in variables */ { tl = my_tl; td = my_td; bl = my_bl; bd = my_bd; /* make local copies of globals */ b = gunzip_bb; /* initialize bit buffer */ k = gunzip_bk; w = gunzip_outbuf_count; /* initialize gunzip_window position */ /* inflate the coded data */ ml = mask_bits[bl]; /* precompute masks for speed */ md = mask_bits[bd]; return 0; /* Don't actually do anything the first time */ } if (inflate_codes_resumeCopy) goto do_copy; while (1) /* do until end of block */ { b = fill_bitbuffer(b, &k, bl); if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) do { if (e == 99) error_die("inflate_codes error 1"); b >>= t->b; k -= t->b; e -= 16; b = fill_bitbuffer(b, &k, e); } while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); b >>= t->b; k -= t->b; if (e == 16) /* then it's a literal */ { gunzip_window[w++] = (unsigned char) t->v.n; if (w == gunzip_wsize) { gunzip_outbuf_count = (w); w = 0; return 1; /* We have a block to read */ } } else /* it's an EOB or a length */ { /* exit if end of block */ if (e == 15) break; /* get length of block to copy */ b = fill_bitbuffer(b, &k, e); n = t->v.n + ((unsigned) b & mask_bits[e]); b >>= e; k -= e; /* decode distance of block to copy */ b = fill_bitbuffer(b, &k, bd); if ((e = (t = td + ((unsigned) b & md))->e) > 16) do { if (e == 99) error_die("inflate_codes error 2"); b >>= t->b; k -= t->b; e -= 16; b = fill_bitbuffer(b, &k, e); } while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); b >>= t->b; k -= t->b; b = fill_bitbuffer(b, &k, e); d = w - t->v.n - ((unsigned) b & mask_bits[e]); b >>= e; k -= e; /* do the copy */ do_copy: do { n -= (e = (e = gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e); /* copy to new buffer to prevent possible overwrite */ if (w - d >= e) /* (this test assumes unsigned comparison) */ { memcpy(gunzip_window + w, gunzip_window + d, e); w += e; d += e; } else { /* do it slow to avoid memcpy() overlap */ /* !NOMEMCPY */ do { gunzip_window[w++] = gunzip_window[d++]; } while (--e); } if (w == gunzip_wsize) { gunzip_outbuf_count = (w); if (n) inflate_codes_resumeCopy = 1; else inflate_codes_resumeCopy = 0; w = 0; return 1; } } while (n); inflate_codes_resumeCopy = 0; } } /* restore the globals from the locals */ gunzip_outbuf_count = w; /* restore global gunzip_window pointer */ gunzip_bb = b; /* restore global bit buffer */ gunzip_bk = k; /* normally just after call to inflate_codes, but save code by putting it here */ /* free the decoding tables, return */ huft_free(tl,HUFT_MMP1); huft_free(td,HUFT_MMP2); /* done */ return 0; }
int main(void) { int i; int ifd; int len; int client_sock; struct online_user *user; Client client; struct sockaddr_in client_name; int client_name_len = sizeof(client_name); #define MAX_BUFSIZE 0x100000 char buf[MAX_BUFSIZE]; struct format *package = (struct format *)buf; tcp_server_sock = tcp_startup(SERVER_TCP_PORT); init_mysql(); register_ctrl_c(); kdpfd = epoll_create(MAXEPOLLSIZE); /* 设置要监听的事件。EPOLLIN 表示可读,EPOLLET则指定电平触发 */ ev.events = EPOLLIN; ev.data.fd = tcp_server_sock; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, tcp_server_sock, &ev) < 0) /* 把 tcp sock 加入监听集合,以便接收连接请求 */ error_die("tcp epoll_ctl\n"); /* 记录监听的文件数,同时他也是 epoll_wait 的第三个参数。 因为内核需要知道 events 数组的有效数据有多长 */ curfds = 1; for (;;) { memset(buf,0,sizeof(buf)); printf("waiting...\n"); /* 等待有事件发生。该函数的返回值存放在 nfds 和 events 内 */ nfds = epoll_wait(kdpfd, events, curfds, -1); if (nfds < 0) error_die("epoll_wait"); for (i = 0; i < nfds; i++) { ifd = events[i].data.fd; if (ifd == tcp_server_sock) { //新的 TCP 连接请求到来 if (!(events[i].events & EPOLLIN)) error_die("failed to event is not EPOLLIN\n"); client_sock = accept(tcp_server_sock,(struct sockaddr *)&client_name,&client_name_len); setnonblocking(client_sock); ev.events = EPOLLIN; ev.data.fd = client_sock; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client_sock, &ev) < 0) error_die("epoll_ctl"); curfds++; client = alloc_client(client_sock); add_client(client); } else if ((events[i].events & EPOLLIN)) { /* 客户端有数据发来(POLLIN)或者发生 POLLHUP/POLLERR(这两个事件系统会自动监听) */ client = find_client(ifd); if (client != NULL && client->handler != NULL) { //已经有了处理函数,直接调用这个函数来处理 client->handler(ifd,client->private); } else { //默认的处理方法 //读入数据包头部。 len = read(ifd,package,(sizeof(struct format)-sizeof(package->data))); if (len <= 0) { //对方断线。 close_connect(ifd); continue; } if (package->length >= MAX_BUFSIZE || package->length <= 0) { while(read(ifd,package->data,4) > 0); continue; } if ((len = read(ifd,package->data,package->length) <= 0)) { //读入数据包内容 close_connect(ifd); continue; } // 处理数据 if (handle(ifd,package) == NEED_WRITE) { ev.events = EPOLLOUT; ev.data.fd = ifd; epoll_ctl(kdpfd,EPOLL_CTL_MOD,ifd,&ev); } } } else if(events[i].events & EPOLLOUT) {
void *GallocyServer::work() { LOG_DEBUG("Starting HTTP server on " << address << ":" << port); struct sockaddr_in name; int optval = 1; server_socket = socket(PF_INET, SOCK_STREAM, 0); if (server_socket == -1) { error_die("socket"); } #ifdef __APPLE__ setsockopt(server_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); #else setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); #endif memset(&name, 0, sizeof(name)); name.sin_family = AF_INET; name.sin_port = htons(port); // name.sin_addr.s_addr = htonl(INADDR_ANY); name.sin_addr.s_addr = inet_addr(address.c_str()); if (bind(server_socket, (struct sockaddr *) &name, sizeof(name)) < 0) { error_die("bind"); } if (listen(server_socket, 5) < 0) { error_die("listen"); } int64_t client_sock = -1; struct sockaddr_in client_name; uint64_t client_name_len = sizeof(client_name); pthread_t newthread; while (alive) { client_sock = accept(server_socket, reinterpret_cast<struct sockaddr *>(&client_name), reinterpret_cast<socklen_t *>(&client_name_len)); if (client_sock == -1) { error_die("accept"); } struct RequestContext *ctx = new (internal_malloc(sizeof(struct RequestContext))) struct RequestContext; ctx->server = this; ctx->client_socket = client_sock; ctx->client_name = client_name; if (get_pthread_create_impl()(&newthread, NULL, handle_entry, reinterpret_cast<void *>(ctx)) != 0) { perror("pthread_create1"); } // TODO(sholsapp): This shouldn't block, and we shouldn't just try to // join this thread. if (get_pthread_join_impl()(newthread, nullptr)) { perror("pthread_join1"); } } close(server_socket); return nullptr; }