int32 PoorManServer::_Listener(void* data) { PRINT(("The listener thread is working.\n")); int retval; thread_id tid; httpd_conn* hc; PoorManServer* s = static_cast<PoorManServer*>(data); while (s->fIsRunning) { hc = new httpd_conn; hc->initialized = 0; PRINT(("calling httpd_get_conn()\n")); retval = //accept(), blocked here httpd_get_conn(s->fHttpdServer, s->fHttpdServer->listen4_fd, hc); switch (retval) { case GC_OK: break; case GC_FAIL: httpd_destroy_conn(hc); delete hc; s->fIsRunning = false; return -1; case GC_NO_MORE: //should not happen, since we have a blocking socket httpd_destroy_conn(hc); continue; break; default: //shouldn't happen continue; break; } if (s->fCurConns > s->fMaxConns) { httpd_send_err(hc, 503, httpd_err503title, (char *)"", httpd_err503form, (char *)""); httpd_write_response(hc); continue; } tid = spawn_thread( PoorManServer::_Worker, "www connection", B_NORMAL_PRIORITY, static_cast<void*>(s) ); if (tid < B_OK) { continue; } /*We don't check the return code here. *As we can't kill a thread that doesn't receive the *httpd_conn, we simply let it die itself. */ send_data(tid, 512, &hc, sizeof(httpd_conn*)); atomic_add(&s->fCurConns, 1); resume_thread(tid); }//while return 0; }
static void shut_down(void) { int cnum; for (cnum = 0; cnum < AVAILABLE_FDS; ++cnum) { if (connects[cnum].conn_state != CNST_FREE) { httpd_close_conn(connects[cnum].hc); } if (connects[cnum].hc != NULL) { httpd_destroy_conn(connects[cnum].hc); httpd_free((void *)connects[cnum].hc); connects[cnum].hc = NULL; } } if (hs) { httpd_server *ths = hs; hs = NULL; if (ths->listen_fd != -1) { fdwatch_del_fd(fw, ths->listen_fd); } httpd_terminate(ths); } tmr_destroy(); httpd_free((void *)connects); }
static void shut_down( void ) { int cnum; struct timeval tv; (void) gettimeofday( &tv, (struct timezone*) 0 ); for ( cnum = 0; cnum < max_connects; ++cnum ) { if ( connects[cnum].conn_state != CNST_FREE ) httpd_close_conn( connects[cnum].hc, &tv ); if ( connects[cnum].hc != (httpd_conn*) 0 ) { httpd_destroy_conn( connects[cnum].hc ); free( (void*) connects[cnum].hc ); --httpd_conn_count; connects[cnum].hc = (httpd_conn*) 0; } } if ( hs != (httpd_server*) 0 ) { httpd_server* ths = hs; hs = (httpd_server*) 0; if ( ths->listen4_fd != -1 ) fdwatch_del_fd( ths->listen4_fd ); if ( ths->listen6_fd != -1 ) fdwatch_del_fd( ths->listen6_fd ); httpd_terminate( ths ); } tmr_destroy(); free( (void*) connects ); }
static void shut_down( void ) { int cnum; struct timeval tv; (void) gettimeofday( &tv, (struct timezone*) 0 ); logstats( &tv ); for ( cnum = 0; cnum < maxconnects; ++cnum ) { if ( connects[cnum].conn_state != CNST_FREE ) httpd_close_conn( connects[cnum].hc, &tv ); if ( connects[cnum].hc != (httpd_conn*) 0 ) { httpd_destroy_conn( connects[cnum].hc ); free( (void*) connects[cnum].hc ); --httpd_conn_count; connects[cnum].hc = (httpd_conn*) 0; } } if ( hs != (httpd_server*) 0 ) { httpd_server* ths = hs; hs = (httpd_server*) 0; httpd_terminate( ths ); } mmc_destroy(); tmr_destroy(); free( (void*) connects ); if ( throttles != (throttletab*) 0 ) free( (void*) throttles ); }
int32 PoorManServer::_Worker(void* data) { static const struct timeval kTimeVal = {60, 0}; PoorManServer* s = static_cast<PoorManServer*>(data); httpd_conn* hc; int retval; if (has_data(find_thread(NULL))) { thread_id sender; if (receive_data(&sender, &hc, sizeof(httpd_conn*)) != 512) goto cleanup; } else { // No need to go throught the whole cleanup, as we haven't open // nor allocated ht yet. atomic_add(&s->fCurConns, -1); return 0; } PRINT(("A worker thread starts to work.\n")); setsockopt(hc->conn_fd, SOL_SOCKET, SO_RCVTIMEO, &kTimeVal, sizeof(struct timeval)); retval = recv( hc->conn_fd, &(hc->read_buf[hc->read_idx]), hc->read_size - hc->read_idx, 0 ); if (retval < 0) goto cleanup; hc->read_idx += retval; switch(httpd_got_request(hc)) { case GR_GOT_REQUEST: break; case GR_BAD_REQUEST: httpd_send_err(hc, 400, httpd_err400title, (char *)"", httpd_err400form, (char *)""); httpd_write_response(hc);//fall through case GR_NO_REQUEST: //fall through default: //won't happen goto cleanup; break; } if (httpd_parse_request(hc) < 0) { httpd_write_response(hc); goto cleanup; } retval = httpd_start_request(hc, (struct timeval*)0); if (retval < 0) { httpd_write_response(hc); goto cleanup; } /*true means the connection is already handled *by the directory index generator in httpd_start_request(). */ if (hc->file_address == (char*) 0) { static_cast<PoorManApplication*>(be_app)->GetPoorManWindow()->SetHits( static_cast<PoorManApplication*>(be_app)->GetPoorManWindow()->GetHits() + 1 ); hc->conn_fd = -1; goto cleanup; } switch (hc->method) { case METHOD_GET: s->_HandleGet(hc); break; case METHOD_HEAD: s->_HandleHead(hc); break; case METHOD_POST: s->_HandlePost(hc); break; } cleanup: ; httpd_close_conn(hc, (struct timeval*)0); httpd_destroy_conn(hc); delete hc; atomic_add(&s->fCurConns, -1); return 0; }