Newer
Older
free_crypt_attrstr(ssl_estr);
iniFileName(mime_types_ini,sizeof(mime_types_ini),scfg.ctrl_dir,"mime_types.ini");
mime_types=read_ini_list(mime_types_ini,NULL /* root section */,"MIME types"
,mime_types);
iniFileName(web_handler_ini,sizeof(web_handler_ini),scfg.ctrl_dir,"web_handler.ini");
if((cgi_handlers=read_ini_list(web_handler_ini,"CGI."PLATFORM_DESC,"CGI content handlers"
,cgi_handlers))==NULL)
cgi_handlers=read_ini_list(web_handler_ini,"CGI","CGI content handlers"
,cgi_handlers);
xjs_handlers=read_ini_list(web_handler_ini,"JavaScript","JavaScript content handlers"
,xjs_handlers);
/* Don't do this for *each* CGI request, just once here during [re]init */
iniFileName(cgi_env_ini,sizeof(cgi_env_ini),scfg.ctrl_dir,"cgi_env.ini");
if((fp=iniOpenFile(cgi_env_ini,/* create? */FALSE)) != NULL) {
cgi_env = iniReadFile(fp);
iniCloseFile(fp);
}
if(uptime==0)
uptime=time(NULL); /* this must be done *after* setting the timezone */
update_clients();
/* open a socket and wait for a client */
ws_set = xpms_create(startup->bind_retry_count, startup->bind_retry_delay, lprintf);
if(ws_set == NULL) {
lprintf(LOG_CRIT,"!ERROR %d creating HTTP socket set", ERROR_VALUE);
cleanup(1);
return;
}
xpms_add_list(ws_set, PF_UNSPEC, SOCK_STREAM, 0, startup->interfaces, startup->port, "Web Server", open_socket, startup->seteuid, NULL);
if(scfg.tls_certificate != -1 && startup->options&WEB_OPT_ALLOW_TLS) {
if(do_cryptInit())
xpms_add_list(ws_set, PF_UNSPEC, SOCK_STREAM, 0, startup->tls_interfaces, startup->tls_port, "Secure Web Server", open_socket, startup->seteuid, "TLS");
}
listInit(&log_list,/* flags */ LINK_LIST_MUTEX|LINK_LIST_SEMAPHORE);
if(startup->options&WEB_OPT_HTTP_LOGGING) {
/********************/
/* Start log thread */
/********************/
http_logging_thread_running=TRUE;
(void)protected_uint32_adjust(&thread_count,1);
_beginthread(http_logging_thread, 0, startup->logfile_base);
}
/* Setup recycle/shutdown semaphore file lists */
shutdown_semfiles=semfile_list_init(scfg.ctrl_dir,"shutdown","web");
recycle_semfiles=semfile_list_init(scfg.ctrl_dir,"recycle","web");
semfile_list_add(&recycle_semfiles,startup->ini_fname);
SAFEPRINTF(path,"%swebsrvr.rec",scfg.ctrl_dir); /* legacy */
semfile_list_add(&recycle_semfiles,path);
semfile_list_add(&recycle_semfiles,mime_types_ini);
semfile_list_add(&recycle_semfiles,web_handler_ini);
semfile_list_add(&recycle_semfiles,cgi_env_ini);
if(!initialized) {
semfile_list_check(&initialized,recycle_semfiles);
semfile_list_check(&initialized,shutdown_semfiles);
/* signal caller that we've started up successfully */
if(startup->started!=NULL)
startup->started(startup->cbdata);
YIELD();
/* check for re-cycle/shutdown semaphores */
if(protected_uint32_value(thread_count) <= (unsigned int)(2 /* web_server() and http_output_thread() */ + (http_logging_thread_running?1:0))) {
if(!(startup->options&BBS_OPT_NO_RECYCLE)) {
if((p=semfile_list_check(&initialized,recycle_semfiles))!=NULL) {
if(session!=NULL) {
pthread_mutex_unlock(&session->struct_filled);
session=NULL;
}
break;
}
if(startup->recycle_now==TRUE) {
startup->recycle_now=FALSE;
if(session!=NULL) {
pthread_mutex_unlock(&session->struct_filled);
session=NULL;
}
break;
}
if(((p=semfile_list_check(&initialized,shutdown_semfiles))!=NULL
&& lprintf(LOG_INFO,"Shutdown semaphore file (%s) detected",p))
|| (startup->shutdown_now==TRUE
startup->shutdown_now=FALSE;
terminate_server=TRUE;
if(session!=NULL) {
pthread_mutex_unlock(&session->struct_filled);
session=NULL;
}
if(session==NULL) {
/* FREE()d at the start of the session thread */
if((session=malloc(sizeof(http_session_t)))==NULL) {
lprintf(LOG_CRIT,"!ERROR allocating %lu bytes of memory for http_session_t", (ulong)sizeof(http_session_t));
continue;
}
memset(session, 0, sizeof(http_session_t));
session->socket=INVALID_SOCKET;
pthread_mutex_init(&session->struct_filled,NULL);
pthread_mutex_lock(&session->struct_filled);
(void)protected_uint32_adjust(&thread_count,1);
_beginthread(http_session_thread, 0, session);
/* now wait for connection */
client_socket = xpms_accept(ws_set, &client_addr, &client_addr_len, startup->sem_chk_freq*1000, XPMS_FLAGS_NONE, &acc_type);
continue;
pthread_mutex_unlock(&session->struct_filled);
session=NULL;
if(startup->socket_open!=NULL)
startup->socket_open(startup->cbdata,TRUE);
if(trashcan(&scfg,host_ip,"ip-silent")) {
close_socket(&client_socket);
continue;
}

Rob Swindell
committed
if((count = protected_uint32_value(active_clients)) > client_highwater) {
client_highwater = count;
lprintf(LOG_NOTICE, "%04d New active client highwater mark: %lu"
,client_socket, client_highwater);
}
if(startup->max_clients && protected_uint32_value(active_clients)>=startup->max_clients) {
,client_socket, startup->max_clients);
if (!len_503)
len_503 = strlen(error_503);
sendsocket(client_socket, error_503, len_503);
close_socket(&client_socket);
if (acc_type != NULL && !strcmp(acc_type, "TLS"))
session->is_tls=TRUE;
lprintf(LOG_INFO,"%04d %s connection accepted from: %s port %u"
,session->is_tls ? "HTTPS":"HTTP"
,host_ip, host_port);
SAFECOPY(session->host_ip,host_ip);
memcpy(&session->addr, &client_addr, sizeof(session->addr));
session->addr_len=client_addr_len;
session->socket=client_socket;
session->js_callback.auto_terminate=TRUE;
session->js_callback.terminated=&terminate_server;
session->js_callback.limit=startup->js.time_limit;
session->js_callback.gc_interval=startup->js.gc_interval;
session->js_callback.yield_interval=startup->js.yield_interval;
pthread_mutex_unlock(&session->struct_filled);
session=NULL;
served++;
if(session) {
pthread_mutex_unlock(&session->struct_filled);
session=NULL;
}
/* Wait for active clients to terminate */
if(protected_uint32_value(active_clients)) {
lprintf(LOG_INFO, "Waiting for %d active clients to disconnect..."
start=time(NULL);
while(protected_uint32_value(active_clients)) {
if(time(NULL)-start>startup->max_inactivity) {
lprintf(LOG_WARNING,"!TIMEOUT waiting for %d active clients"
, protected_uint32_value(active_clients));
break;
}
mswait(100);
}
lprintf(LOG_INFO, "Done waiting for active clients to disconnect");
if(http_logging_thread_running) {
terminate_http_logging_thread=TRUE;
listSemPost(&log_list);
mswait(100);
}
if(http_logging_thread_running) {
lprintf(LOG_INFO, "Waiting for HTTP logging thread to terminate...");
start=time(NULL);
while(http_logging_thread_running) {
if(time(NULL)-start>TIMEOUT_THREAD_WAIT) {
lprintf(LOG_WARNING,"!TIMEOUT waiting for HTTP logging thread to "
"terminate");
listSemPost(&log_list);
lprintf(LOG_INFO, "Done waiting for HTTP logging thread to terminate");
if(!terminate_server) {
lprintf(LOG_INFO,"Recycling server...");
if(startup->recycle!=NULL)
startup->recycle(startup->cbdata);
} while(!terminate_server);
protected_uint32_destroy(thread_count);