void handle_tcp(const unsigned char *bytes, uint16_t segment_len) { struct tcphdr *tcp_hdr = (struct tcphdr *) bytes; tcp_hdr->th_sport = ntohs(tcp_hdr->th_sport); tcp_hdr->th_dport = ntohs(tcp_hdr->th_dport); printf2("TCP %u -> %u, [", tcp_hdr->th_sport, tcp_hdr->th_dport); print_flags(tcp_hdr->th_flags); print2("], "); printf2("seq %u, ack %u, win %u\n", ntohl(tcp_hdr->seq), ntohl(tcp_hdr->ack_seq), ntohs(tcp_hdr->window)); int data_offset = 4 * tcp_hdr->th_off; const unsigned char *end = bytes + data_offset; bytes += sizeof(struct tcphdr); while(bytes < end) { uint8_t kind = *bytes++; uint8_t len = 0; if(kind != 0 && kind != 1) len = *bytes++; printf3(" option %u: ", kind); switch(kind) { case 0: print3("end of options"); break; case 1: print3("no operation (NOP)"); break; case 2: printf3("MSS %u", (*(uint32_t*) bytes)); break; case 3: print3("window scale"); break; case 4: print3("SACK permited"); break; case 5: print3("SACK"); break; case 8: print3("timestamps"); break; default: print3("unknown"); break; } print3("\n"); // advance by the size of the option read if(kind != 0 && kind != 1) bytes += len - 2; } if(tcp_hdr->th_sport == 80 || tcp_hdr->th_dport == 80) { handle_http((const char *) bytes); } else if(tcp_hdr->th_sport == 23 || tcp_hdr->th_dport == 23) { handle_telnet(bytes, segment_len - data_offset); } else { printf1("??? Unknown TCP application with ports %u -> %u\n", tcp_hdr->th_sport, tcp_hdr->th_dport); } }
int run_server(int port, dserve_global_p globalptr) { struct sockaddr_in clientaddr; int rc, sd, connsd, next; thread_data_p tdata; struct common_data *common; long tid, maxtid, tcount, i; size_t clientlen; //struct timeval timeout; #ifdef MULTI_THREAD #if _MSC_VER HANDLE thandle; HANDLE thandlearray[MAX_THREADS]; DWORD threads[MAX_THREADS]; #else pthread_t threads[MAX_THREADS]; pthread_attr_t attr; struct timespec tim, tim2; #endif #ifdef USE_OPENSSL SSL_CTX *ctx; SSL *ssl; #endif #endif #if _MSC_VER void* db=NULL; // actual database pointer WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 0),&wsaData) != 0) { errprint(WSASTART_ERR,NULL); exit(ERR_EX_UNAVAILABLE); } db = wg_attach_existing_database("1000"); //db = wg_attach_database(database,100000000); if (!db) { errprint(DB_ATTACH_ERR,NULL); exit(ERR_EX_UNAVAILABLE); } #else signal(SIGPIPE,SIG_IGN); // important for linux TCP/IP handling #endif tdata=&(globalptr->threads_data[0]); #ifdef MULTI_THREAD #if _MSC_VER #else if (THREADPOOL) { // ---------------- run as server with threadpool ----------- infoprint(THREADPOOL_INFO,NULL); // setup nanosleep for 100 microsec tim.tv_sec = 0; tim.tv_nsec = 100000; #ifdef USE_OPENSSL // prepare openssl ctx=init_openssl(globalptr->conf); #endif // prepare threads common=(struct common_data *)malloc(sizeof(struct common_data)); tid=0; tcount=0; maxtid=0; if (pthread_mutex_init(&(common->mutex),NULL) !=0 || pthread_cond_init(&(common->cond),NULL) != 0 || pthread_attr_init(&attr) !=0) { errprint(MUTEX_ERROR,NULL); exit(ERR_EX_UNAVAILABLE); } common->threads = threads; common->queue = (common_task_t *)malloc(sizeof(common_task_t) * QUEUE_SIZE); common->thread_count = 0; common->queue_size = QUEUE_SIZE; common->head = common->tail = common->count = 0; common->shutdown = common->started = 0; pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); //PTHREAD_CREATE_DETACHED); // create threads for(tid=0;tid<MAX_THREADS;tid++) { // init thread data block tdata[tid].isserver=1; tdata[tid].thread_id=tid; tdata[tid].realthread=2; tdata[tid].common=common; tdata[tid].inuse=0; tdata[tid].conn=0; tdata[tid].ip=NULL; tdata[tid].port=0; tdata[tid].method=0; tdata[tid].res=0; tdata[tid].global=globalptr; //fprintf(stderr,"creating thread %d tcount %d \n",(int)tid,(int)tcount); rc=pthread_create(&threads[tid], &attr, handle_http, (void *) &tdata[tid]); if (rc) { errprint(THREAD_CREATE_ERR,strerror(errno)); exit(ERR_EX_UNAVAILABLE); } tcount++; } // sd=open_listener(port); if (sd<0) { errprint(PORT_LISTEN_ERR, strerror(errno)); return -1; } clientlen = sizeof(clientaddr); // loop forever, servicing requests while (1) { connsd=accept(sd,(struct sockaddr *)&clientaddr, &clientlen); if (connsd<0) { warnprint(CONN_ACCEPT_WARN, strerror(errno)); continue; } if(pthread_mutex_lock(&(common->mutex)) != 0) { errprint(THREADPOOL_LOCK_ERR,NULL); exit(ERR_EX_UNAVAILABLE); } #ifdef USE_OPENSSL ssl = SSL_new(ctx); // get new SSL state with context SSL_set_fd(ssl,connsd); #endif // now we have a connection: add to queue next=common->tail+1; next=(next==common->queue_size) ? 0 : next; do { if(common->count==common->queue_size) { // full? //fprintf(stderr, "queue full\n"); nanosleep(&tim , &tim2); break; //continue; } if(common->shutdown) { warnprint(SHUTDOWN_WARN,NULL); break; } // add to task queue common->queue[common->tail].conn=connsd; #ifdef USE_OPENSSL common->queue[common->tail].ssl=ssl; #endif common->tail=next; common->count+=1; //printf("next %d\n",next); // broadcast if(pthread_cond_signal(&(common->cond)) != 0) { warnprint(COND_SIGNAL_FAIL_WARN,NULL); break; } } while(0); //fprintf(stderr,"starting to unlock \n"); if(pthread_mutex_unlock(&(common->mutex)) != 0) { errprint(THREADPOOL_UNLOCK_ERR,NULL); exit(ERR_EX_UNAVAILABLE); } } return 0; // never come to this } else #endif // threadpool not implemented on windows version: using a non-threadpool version { // ------------- run as server without threadpool ------------- infoprint(MULTITHREAD_INFO,NULL); // setup nanosleep for 100 microsec #if _MSC_VER #else tim.tv_sec = 0; tim.tv_nsec = 100000; #endif // prepare common block common=(struct common_data *)malloc(sizeof(struct common_data)); common->shutdown=0; // mark thread data blocks free for(i=0;i<MAX_THREADS;i++) { tdata[i].inuse=0; tdata[i].common=common; tdata[i].global=globalptr; } // prepare threads tid=0; tcount=0; maxtid=0; #if _MSC_VER #else pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //PTHREAD_CREATE_JOINABLE); #endif sd=open_listener(port); if (sd<0) { errprint(PORT_LISTEN_ERR, strerror(errno)); return -1; } clientlen = sizeof(clientaddr); while (1) { connsd=accept(sd,(struct sockaddr *)&clientaddr, &clientlen); if (common->shutdown==1) break; if (connsd<0) { warnprint(CONN_ACCEPT_WARN, strerror(errno)); continue; } tid=-1; // find first free thread data block // loop until we get a free one while(tid<0) { for(i=0;i<MAX_THREADS;i++) { if (!tdata[i].inuse) { tid=i; break; } } if (tid>=0) break; #if _MSC_VER usleep(1); #else nanosleep(&tim , &tim2); #endif } if (tid>maxtid) maxtid=tid; tcount++; // init thread data block tdata[tid].isserver=1; tdata[tid].thread_id=tid; tdata[tid].realthread=1; tdata[tid].inuse=1; tdata[tid].conn=connsd; tdata[tid].ip=NULL; tdata[tid].port=0; tdata[tid].method=0; tdata[tid].res=0; tdata[tid].global=globalptr; #if _MSC_VER tdata[tid].db=db; thandle=CreateThread(NULL, 0, handle_http, (void *) &tdata[tid], 0, &threads[tid]); if (thandle==NULL) { win_err_handler(TEXT("CreateThread")); ExitProcess(3); } else { thandlearray[tid]=thandle; } #else rc=pthread_create(&threads[tid], &attr, handle_http, (void *) &tdata[tid]); #endif } return 0; // never come to this } #else // ------------ run as an iterative server ------------- sd=open_listener(port); if (sd<0) { errprint(PORT_LISTEN_ERR, strerror(errno)); return -1; } clientlen = sizeof(clientaddr); while (1) { connsd=accept(sd,(struct sockaddr *)&clientaddr, &clientlen); if (connsd<0) { warnprint(CONN_ACCEPT_WARN, strerror(errno)); continue; } tid=0; tdata[tid].isserver=1; tdata[tid].thread_id=tid; tdata[tid].realthread=0; tdata[tid].conn=connsd; tdata[tid].ip=NULL; tdata[tid].port=0; tdata[tid].method=0; tdata[tid].res=0; tdata[tid].global=globalptr; #if _MSC_VER tdata[tid].db=db; #endif handle_http((void *) &tdata[tid]); } return 0; // never come to this #endif }