int main(int argc, char *argv[]) { int sock; int retval; void *port = NULL; //Check user effective ID if (geteuid() != 0) { fprintf(stderr, "Must run as root permission!\n"); exit(1); } //setup socket port = (argc == 1) ? NULL:argv[1]; sock = setup_tcp(port); if (sock < 0) { perror("setup_tcp"); exit(1); } int client_sock; struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); while (1) { client_sock = accept(sock, (struct sockaddr*)&addr, &addrlen); if (client_sock < 0) { perror("accept"); continue; } if (0 == fork()) { if ((retval = request_handle(client_sock, &addr, addrlen)) < 0) { perror("request_headle"); printf("%d\n", retval); exit(1); } exit(0); } close(client_sock); } }
int /* select and thread */ RequestHandler::handleClient(int serverfd) { int connfd,clientfd; SOCKADDR_IN cliAddr; socklen_t addrlen; //for select struct timeval timeout = {0,0}; int i,max_index,maxfd; int nready,client[FD_SETSIZE]; ssize_t n; fd_set rset,allset; maxfd = serverfd; max_index = -1; for(i=0;i<FD_SETSIZE;i++) client[i] = -1; FD_ZERO(&allset); FD_SET(serverfd,&allset); while(true) { rset = allset; timeout.tv_sec = 3; timeout.tv_usec = 0; // 3 seconds nready=select(maxfd+1,&rset,NULL,NULL,&timeout); //check read fd sets if(FD_ISSET(serverfd,&rset)) { //client connect addrlen = sizeof(cliAddr); if(0>=(connfd = accept(serverfd, (SOCKADDR*)&cliAddr, &addrlen))) { perror("accept error"); return -1; } cout<<"[DEBUG] accept a new client: "<<inet_ntoa(cliAddr.sin_addr)<<":"<<ntohs(cliAddr.sin_port)<<endl; for(i=0;i<FD_SETSIZE;i++) { if (client[i]<0) { client[i]=connfd; break; } } if(i>=FD_SETSIZE) { cout<<"[DEBUG] too many clients"<<endl; close(connfd); continue; } FD_SET(connfd,&allset); // add connfd into allset if(connfd>maxfd) maxfd=connfd; if(i>max_index) max_index=i; if(--nready<=0) continue; } for(i=0;i<=max_index;i++) { if( 0 > (clientfd=client[i])) continue; if(FD_ISSET(clientfd,&rset)) { //deal with each clientfd request_handle(clientfd); FD_CLR(clientfd,&allset); client[i]=-1; if(--nready<=0) break; } } } }
static void *thread_request_handle(void *v) { int ret; struct list *synnode; struct timespec abstime = {0}; frames_t *frame; su_serv_t *psvr = (su_serv_t*)v; pthread_t tid __attribute__((unused)) = pthread_self(); for (; psvr->run;) { pthread_mutex_lock(&psvr->lock); while ((synnode = psvr->synrecvls.next) == &psvr->synrecvls) { maketimeout_seconds(&abstime, 1); ret = pthread_cond_timedwait(&psvr->syncond, &psvr->lock, &abstime); if (!psvr->run) { pthread_mutex_unlock(&psvr->lock); goto quit; } if ( ret == ETIMEDOUT ) { pthread_mutex_lock(&psvr->cachelock); reliable_ack_unsave(psvr); pthread_mutex_unlock(&psvr->cachelock); } } list_remove(synnode); pthread_mutex_unlock(&psvr->lock); /* have request datagram */ frame = container_of(synnode, frames_t, node); rb_key_cache_t key; memcpy(&key.destaddr, &frame->srcaddr, sizeof(SAUN)); key.destlen = frame->srclen; key.seq = frame->recvhdr.seq; key.sid = frame->recvhdr.sid; struct rb_node *cachenode; cache_t *cache; pthread_mutex_lock(&psvr->cachelock); reliable_ack_unsave(psvr); if (frame->recvhdr.type == SU_RELIABLE) { if ( (cachenode = rb_search(&psvr->rbackcache, &key))) { cache = rb_entry(cachenode, cache_t, rbn); if (cache->frame.len == -1) { #ifdef SU_DEBUG_RBTREE char ipbuff[INET6_ADDRSTRLEN]; int port; su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); log_msg("serv %x %x time %u key(%s:%d:%u:%u)" ColorRed " 0ACK cache %p" ColorEnd, psvr, tid, cache->ts, ipbuff, port, cache->frame.recvhdr.sid, cache->frame.recvhdr.seq, cache); #endif pthread_mutex_unlock(&psvr->cachelock); free(frame); continue; } #ifdef SU_DEBUG_RBTREE char ipbuff[INET6_ADDRSTRLEN]; int port; su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); log_msg("serv %x %x time %u key(%s:%d:%u:%u)" ColorRed " @ACK cache %p" ColorEnd, psvr, tid, cache->ts, ipbuff, port, cache->frame.recvhdr.sid, cache->frame.recvhdr.seq, cache); #endif struct iovec iovsend[2] = {{0}}; struct msghdr msgsend = {0}; /* assumed init to 0 */ frame->recvhdr.act = SU_ACK; msgsend.msg_name = (void*)&cache->frame.srcaddr; msgsend.msg_namelen = cache->frame.srclen; msgsend.msg_iov = &iovsend[0]; msgsend.msg_iovlen = 2; iovsend[0].iov_base = &frame->recvhdr; iovsend[0].iov_len = sizeof(suhdr_t); iovsend[1].iov_base = (void*)cache->frame.data; /* get the cache results */ iovsend[1].iov_len = cache->frame.len; /* resend from cache */ if (sendmsg(psvr->fd, &msgsend, 0) != sizeof(suhdr_t) + cache->frame.len) { char ipbuff[INET6_ADDRSTRLEN]; int port; su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); ERR_RET("retransmit sendmsg %s:%d:%u:%u:%u error", ipbuff, port, frame->recvhdr.seq, frame->recvhdr.ts, frame->recvhdr.sid); } #ifdef SU_DEBUG_PEER_RESEND else { char ipbuff[INET6_ADDRSTRLEN]; int port; su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); log_msg("retransmit sendmsg %s:%d:%u:%u:%u", ipbuff, port, frame->recvhdr.seq, frame->recvhdr.ts, frame->recvhdr.sid); } #endif pthread_mutex_unlock(&psvr->cachelock); free(frame); continue; } else { if (reliable_ack___hold(psvr, frame) < 0) { err_ret("reliable_ack___hold error"); pthread_mutex_unlock(&psvr->cachelock); free(frame); continue; } } } pthread_mutex_unlock(&psvr->cachelock); request_handle(psvr, frame); #if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST log_msg("serv %x %x delete syn "ColorRed"%p"ColorEnd" seq %d datagram len %d", psvr, tid, frame, frame->recvhdr.seq, frame->len); #endif free(frame); } quit: pthread_exit(0); }