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 int handle_newconnect(struct timeval *tv, int listen_fd) { struct connect_s *conn; ClientData client_data; /* This loops until the accept() fails, trying to start new connections as * fast as possible so we don't overrun the listen queue. */ nvdbg("New connection(s) on listen_fd %d\n", listen_fd); for (;;) { /* Get the next free connection from the free list */ conn = free_connections; /* Are there any free connections? */ if (!conn) { /* Out of connection slots. Run the timers, then the existing * connections, and maybe we'll free up a slot by the time we get * back here. */ ndbg("No free connections\n"); tmr_run(tv); return -1; } /* Make the httpd_conn if necessary */ if (!conn->hc) { conn->hc = NEW(httpd_conn, 1); if (conn->hc == NULL) { ndbg("out of memory allocating an httpd_conn\n"); exit(1); } conn->hc->initialized = 0; } /* Get the connection */ switch (httpd_get_conn(hs, listen_fd, conn->hc)) { /* Some error happened. Run the timers, then the existing * connections. Maybe the error will clear. */ case GC_FAIL: tmr_run(tv); return -1; /* No more connections to accept for now */ case GC_NO_MORE: return 0; default: break; } nvdbg("New connection fd %d\n", conn->hc->conn_fd); /* Remove the connection entry from the free list */ conn->conn_state = CNST_READING; free_connections = conn->next; conn->next = NULL; client_data.p = conn; conn->active_at = tv->tv_sec; conn->wakeup_timer = NULL; conn->linger_timer = NULL; conn->offset = 0; /* Set the connection file descriptor to no-delay mode */ httpd_set_ndelay(conn->hc->conn_fd); fdwatch_add_fd(fw, conn->hc->conn_fd, conn); } }
static int handle_newconnect( struct timeval* tvP, int listen_fd ) { connecttab* c; ClientData client_data; /* This loops until the accept() fails, trying to start new ** connections as fast as possible so we don't overrun the ** listen queue. */ for (;;) { /* Is there room in the connection table? */ if ( num_connects >= max_connects ) { /* Out of connection slots. Run the timers, then the ** existing connections, and maybe we'll free up a slot ** by the time we get back here. */ tmr_run( tvP ); return 0; } /* Get the first free connection entry off the free list. */ if ( first_free_connect == -1 || connects[first_free_connect].conn_state != CNST_FREE ) { return; } c = &connects[first_free_connect]; /* Make the httpd_conn if necessary. */ if ( c->hc == (httpd_conn*) 0 ) { c->hc = NEW( httpd_conn, 1 ); if ( c->hc == (httpd_conn*) 0 ) { return; } c->hc->initialized = 0; c->hc->conn = c; ++httpd_conn_count; } /* Get the connection. */ switch ( httpd_get_conn( hs, listen_fd, c->hc ) ) { /* Some error happened. Run the timers, then the ** existing connections. Maybe the error will clear. */ case GC_FAIL: tmr_run( tvP ); return 0; /* No more connections to accept for now. */ case GC_NO_MORE: return 1; } c->conn_state = CNST_READING; /* Pop it off the free list. */ first_free_connect = c->next_free_connect; c->next_free_connect = -1; ++num_connects; client_data.p = c; c->active_at = tvP->tv_sec; c->wakeup_timer = (Timer*) 0; c->linger_timer = (Timer*) 0; c->next_byte_index = 0; /* Set the connection file descriptor to no-delay mode. */ httpd_set_ndelay( c->hc->conn_fd ); fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ ); ++stats_connections; if ( num_connects > stats_simultaneous ) stats_simultaneous = num_connects; } }
static int handle_newconnect( struct timeval* tvP, int listen_fd ) { int cnum; connecttab* c; ClientData client_data; /* This loops until the accept() fails, trying to start new ** connections as fast as possible so we don't overrun the ** listen queue. */ for (;;) { /* Is there room in the connection table? */ if ( numconnects >= maxconnects ) { /* Out of connection slots. Run the timers, then the ** existing connections, and maybe we'll free up a slot ** by the time we get back here. **/ syslog( LOG_WARNING, "too many connections!" ); tmr_run( tvP ); return 0; } /* Find a free connection entry. */ for ( cnum = 0; cnum < maxconnects; ++cnum ) if ( connects[cnum].conn_state == CNST_FREE ) break; c = &connects[cnum]; /* Make the httpd_conn if necessary. */ if ( c->hc == (httpd_conn*) 0 ) { c->hc = NEW( httpd_conn, 1 ); if ( c->hc == (httpd_conn*) 0 ) { syslog( LOG_CRIT, "out of memory allocating an httpd_conn" ); exit( 1 ); } c->hc->initialized = 0; ++httpd_conn_count; } /* Get the connection. */ switch ( httpd_get_conn( hs, listen_fd, c->hc ) ) { case GC_FAIL: case GC_NO_MORE: return 1; } c->conn_state = CNST_READING; ++numconnects; client_data.p = c; c->idle_read_timer = tmr_create( tvP, idle_read_connection, client_data, IDLE_READ_TIMELIMIT * 1000L, 0 ); if ( c->idle_read_timer == (Timer*) 0 ) { syslog( LOG_CRIT, "tmr_create(idle_read_connection) failed" ); exit( 1 ); } c->idle_send_timer = (Timer*) 0; c->wakeup_timer = (Timer*) 0; c->linger_timer = (Timer*) 0; c->bytes_sent = 0; c->numtnums = 0; /* Set the connection file descriptor to no-delay mode. */ httpd_set_ndelay( c->hc->conn_fd ); fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ ); ++stats_connections; if ( numconnects > stats_simultaneous ) stats_simultaneous = numconnects; } }