Newer
Older
sbbs_beep(300,500);
sbbs_beep(100,500);
fprintf(stderr, "Invalid startup structure!\n");
return;
}
set_state(SERVER_INIT);
uptime=0;
served=0;
startup->recycle_now=FALSE;
startup->shutdown_now=FALSE;
terminate_server=FALSE;
protected_uint32_init(&thread_count, 0);
listInit(¤t_connections, LINK_LIST_MUTEX);
protected_uint32_init(&active_clients, 0);
/* Setup intelligent defaults */
if(startup->port==0) startup->port=IPPORT_FTP;
if(startup->qwk_timeout==0) startup->qwk_timeout=FTP_DEFAULT_QWK_TIMEOUT; /* seconds */
if(startup->max_inactivity==0) startup->max_inactivity=FTP_DEFAULT_MAX_INACTIVITY; /* seconds */
if(startup->sem_chk_freq==0) startup->sem_chk_freq=DEFAULT_SEM_CHK_FREQ; /* seconds */
if(startup->index_file_name[0]==0) SAFECOPY(startup->index_file_name,"00index");
(void)protected_uint32_adjust(&thread_count,1);
thread_up(FALSE /* setuid */);
memset(&scfg, 0, sizeof(scfg));
lprintf(LOG_INFO,"Synchronet FTP Server Version %s%c%s"
,VERSION, REVISION
#ifdef _DEBUG
," Debug"
lprintf(LOG_INFO,"Compiled %s/%s %s %s with %s", GIT_BRANCH, GIT_HASH, __DATE__, __TIME__, compiler);
sbbs_srand(); /* Seed random number generator */

rswindell
committed
if(!winsock_startup()) {
break;

rswindell
committed
}
t=time(NULL);
lprintf(LOG_INFO,"Initializing on %.24s with options: %x"
if(chdir(startup->ctrl_dir)!=0)
lprintf(LOG_ERR,"!ERROR %d (%s) changing directory to: %s", errno, strerror(errno), startup->ctrl_dir);
/* Initial configuration and load from CNF files */
SAFECOPY(scfg.ctrl_dir, startup->ctrl_dir);
lprintf(LOG_INFO,"Loading configuration files from %s", scfg.ctrl_dir);
scfg.size=sizeof(scfg);
SAFECOPY(error,UNKNOWN_LOAD_ERROR);
if(!load_cfg(&scfg, text, /* prep: */TRUE, /* node: */FALSE, error, sizeof(error))) {
lprintf(LOG_CRIT,"!ERROR %s",error);
lprintf(LOG_CRIT,"!Failed to load configuration files");
break;
mqtt_startup(&mqtt, &scfg, (struct startup*)startup, ftp_ver(), lputs);
if((t=checktime())!=0) { /* Check binary time */
lprintf(LOG_ERR,"!TIME PROBLEM (%ld)",t);
}
if(uptime==0)
uptime=time(NULL); /* this must be done *after* setting the timezone */
if(startup->temp_dir[0])
SAFECOPY(scfg.temp_dir,startup->temp_dir);
else
SAFECOPY(scfg.temp_dir,"../temp");
prep_dir(scfg.ctrl_dir, scfg.temp_dir, sizeof(scfg.temp_dir));
if((i = md(scfg.temp_dir)) != 0) {
lprintf(LOG_CRIT,"!ERROR %d (%s) creating directory: %s", i, strerror(i), scfg.temp_dir);
cleanup(1,__LINE__);
break;
}
lprintf(LOG_DEBUG,"Temporary file directory: %s", scfg.temp_dir);
if(!startup->max_clients) {
startup->max_clients=scfg.sys_nodes;
if(startup->max_clients<10)
startup->max_clients=10;
}
lprintf(LOG_DEBUG,"Maximum clients: %d",startup->max_clients);
/* Sanity-check the passive port range */
if(startup->pasv_port_low || startup->pasv_port_high) {
if(startup->pasv_port_low > startup->pasv_port_high
|| startup->pasv_port_high-startup->pasv_port_low < (startup->max_clients-1)) {
lprintf(LOG_WARNING,"!Correcting Passive Port Range (Low: %u, High: %u)"
,startup->pasv_port_low,startup->pasv_port_high);
if(startup->pasv_port_low)
startup->pasv_port_high = startup->pasv_port_low+(startup->max_clients-1);
else
startup->pasv_port_low = startup->pasv_port_high-(startup->max_clients-1);
}
lprintf(LOG_DEBUG,"Passive Port Low: %u",startup->pasv_port_low);
lprintf(LOG_DEBUG,"Passive Port High: %u",startup->pasv_port_high);
}
lprintf(LOG_DEBUG,"Maximum inactivity: %d seconds",startup->max_inactivity);
update_clients();
/* open a socket and wait for a client */
ftp_set = xpms_create(startup->bind_retry_count, startup->bind_retry_delay, lprintf);
if(ftp_set == NULL) {
lprintf(LOG_CRIT,"!ERROR %d creating FTP socket set", ERROR_VALUE);
cleanup(1, __LINE__);
return;
xpms_add_list(ftp_set, PF_UNSPEC, SOCK_STREAM, 0, startup->interfaces, startup->port, "FTP Server", ftp_open_socket_cb, startup->seteuid, NULL);
/* Setup recycle/shutdown semaphore file lists */
shutdown_semfiles=semfile_list_init(scfg.ctrl_dir,"shutdown", server_abbrev);
recycle_semfiles=semfile_list_init(scfg.ctrl_dir,"recycle", server_abbrev);
semfile_list_add(&recycle_semfiles,startup->ini_fname);
SAFEPRINTF(path,"%sftpsrvr.rec",scfg.ctrl_dir); /* legacy */
semfile_list_add(&recycle_semfiles,path);
if(!initialized) {
semfile_list_check(&initialized,recycle_semfiles);
semfile_list_check(&initialized,shutdown_semfiles);
/* signal caller that we've started up successfully */
set_state(SERVER_READY);
mqtt_client_max(&mqtt, startup->max_clients);
YIELD();
if(protected_uint32_value(thread_count) <= 1) {
if(!(startup->options&FTP_OPT_NO_RECYCLE)) {
if((p=semfile_list_check(&initialized,recycle_semfiles))!=NULL) {
lprintf(LOG_INFO,"0000 Recycle semaphore file (%s) detected",p);
break;
}
if(startup->recycle_now==TRUE) {
lprintf(LOG_NOTICE,"0000 Recycle semaphore signaled");
startup->recycle_now=FALSE;
break;
}
if(((p=semfile_list_check(&initialized,shutdown_semfiles))!=NULL
&& lprintf(LOG_INFO,"0000 Shutdown semaphore file (%s) detected",p))
|| (startup->shutdown_now==TRUE
&& lprintf(LOG_INFO,"0000 Shutdown semaphore signaled"))) {
startup->shutdown_now=FALSE;
terminate_server=TRUE;
break;
}

rswindell
committed
client_addr_len = sizeof(client_addr);
client_socket = xpms_accept(ftp_set, &client_addr, &client_addr_len, startup->sem_chk_freq*1000, XPMS_FLAGS_NONE, NULL);
if(client_socket == INVALID_SOCKET)
continue;
if(startup->socket_open!=NULL)
startup->socket_open(startup->cbdata,TRUE);
if(startup->max_concurrent_connections > 0) {
int ip_len = strlen(client_ip) + 1;
uint connections = listCountMatches(¤t_connections, client_ip, ip_len);
if(connections >= startup->max_concurrent_connections
&& !is_host_exempt(&scfg, client_ip, /* host_name */NULL)) {
lprintf(LOG_NOTICE, "%04d [%s] !Maximum concurrent connections (%u) exceeded"
,client_socket, client_ip, startup->max_concurrent_connections);
sockprintf(client_socket, -1, "421 Maximum connections (%u) exceeded", startup->max_concurrent_connections);
ftp_close_socket(&client_socket,&none,__LINE__);
continue;
}
}
continue;
}
if(protected_uint32_value(active_clients)>=startup->max_clients) {
lprintf(LOG_WARNING,"%04d [%s] !MAXIMUM CLIENTS (%d) reached, access denied"
,client_socket, client_ip, startup->max_clients);
sockprintf(client_socket,-1,"421 Maximum active clients reached, please try again later.");
ftp_close_socket(&client_socket,&none,__LINE__);
continue;
}
if((ftp=malloc(sizeof(ftp_t)))==NULL) {
lprintf(LOG_CRIT,"%04d !ERROR allocating %d bytes of memory for ftp_t"
,client_socket,(int)sizeof(ftp_t));
sockprintf(client_socket,-1,"421 System error, please try again later.");
ftp_close_socket(&client_socket,&none,__LINE__);
continue;
}
ftp->socket=client_socket;
memcpy(&ftp->client_addr, &client_addr, client_addr_len);
ftp->client_addr_len = client_addr_len;
(void)protected_uint32_adjust(&thread_count,1);
_beginthread(ctrl_thread, 0, ftp);
served++;
set_state(terminate_server ? SERVER_STOPPING : SERVER_RELOADING);
lprintf(LOG_DEBUG,"0000 terminate_server: %d",terminate_server);
#endif
if(protected_uint32_value(active_clients)) {
lprintf(LOG_INFO,"0000 Waiting for %d active clients to disconnect..."
start=time(NULL);
while(protected_uint32_value(active_clients)) {
if(time(NULL)-start > startup->max_inactivity * 2) {
lprintf(LOG_WARNING,"0000 !TIMEOUT waiting for %d active clients"
break;
}
mswait(100);
lprintf(LOG_INFO, "0000 Done waiting for active clients to disconnect");
if(!terminate_server) {
lprintf(LOG_INFO,"Recycling server...");
if(startup->recycle!=NULL)
startup->recycle(startup->cbdata);
} while(!terminate_server);
protected_uint32_destroy(thread_count);