Skip to content
Snippets Groups Projects
mailsrvr.c 150 KiB
Newer Older

			FD_ZERO(&socket_set);
			FD_SET(server_socket,&socket_set);
			high_socket_set=server_socket+1;
			if(startup->options&MAIL_OPT_ALLOW_POP3 
				&& pop3_socket!=INVALID_SOCKET) {
				FD_SET(pop3_socket,&socket_set);
				if(pop3_socket+1>high_socket_set)
					high_socket_set=pop3_socket+1;
			if(startup->options&MAIL_OPT_USE_SUBMISSION_PORT 
				&& submission_socket!=INVALID_SOCKET) {
				FD_SET(submission_socket,&socket_set);
				if(submission_socket+1>high_socket_set)
					high_socket_set=submission_socket+1;
			}
			tv.tv_sec=startup->sem_chk_freq;
			if((i=select(high_socket_set,&socket_set,NULL,NULL,&tv))<1) {
					lprintf(LOG_DEBUG,"%04d Mail Server listening interrupted",server_socket);
				else if(ERROR_VALUE == ENOTSOCK)
            		lprintf(LOG_NOTICE,"%04d Mail Server sockets closed",server_socket);
					lprintf(LOG_WARNING,"%04d !ERROR %d selecting sockets",server_socket,ERROR_VALUE);
			if(server_socket!=INVALID_SOCKET && !terminate_server
				&& (FD_ISSET(server_socket,&socket_set) 
					|| (startup->options&MAIL_OPT_USE_SUBMISSION_PORT
						&& FD_ISSET(submission_socket,&socket_set)))) {
				client_addr_len = sizeof(client_addr);
				client_socket = accept(
					FD_ISSET(server_socket,&socket_set) ? server_socket:submission_socket
					,(struct sockaddr *)&client_addr
				if(client_socket == INVALID_SOCKET)
#if 0	/* is this necessary still? */
					if(ERROR_VALUE == ENOTSOCK || ERROR_VALUE == EINVAL) {
            			lprintf(LOG_NOTICE,"%04d SMTP socket closed while listening"
							,server_socket);
						break;
					}
#endif
					lprintf(LOG_WARNING,"%04d SMTP !ERROR %d accepting connection"
						,FD_ISSET(server_socket,&socket_set) ? server_socket:submission_socket
						,ERROR_VALUE);
#ifdef _WIN32
					if(WSAGetLastError()==WSAENOBUFS)	/* recycle (re-init WinSock) on this error */
						break;
#endif
					continue;
					startup->socket_open(startup->cbdata,TRUE);
				if(trashcan(&scfg,inet_ntoa(client_addr.sin_addr),"ip-silent")) {
					mail_close_socket(client_socket);
					continue;
				}

				if(active_clients>=startup->max_clients) {
runderwo's avatar
 
runderwo committed
					lprintf(LOG_WARNING,"%04d SMTP !MAXIMUM CLIENTS (%u) reached, access denied"
						,client_socket, startup->max_clients);
					sockprintf(client_socket,"421 Maximum active clients reached, please try again later.");
					mswait(3000);
					mail_close_socket(client_socket);
					continue;
				}
				if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) {
					lprintf(LOG_ERR,"%04d SMTP !ERROR %d (%d) disabling blocking on socket"
						,client_socket, i, ERROR_VALUE);
					mail_close_socket(client_socket);
					continue;
				}
				if((smtp=malloc(sizeof(smtp_t)))==NULL) {
					lprintf(LOG_CRIT,"%04d SMTP !ERROR allocating %u bytes of memory for smtp_t"
						,client_socket, sizeof(smtp_t));
					mail_close_socket(client_socket);
					continue;
				}

				smtp->socket=client_socket;
				smtp->client_addr=client_addr;
			if(pop3_socket!=INVALID_SOCKET
				&& FD_ISSET(pop3_socket,&socket_set)) {
				client_addr_len = sizeof(client_addr);
				client_socket = accept(pop3_socket, (struct sockaddr *)&client_addr
        			,&client_addr_len);
				if(client_socket == INVALID_SOCKET)
#if 0	/* is this necessary still? */
					if(ERROR_VALUE == ENOTSOCK || ERROR_VALUE == EINVAL) {
            			lprintf(LOG_NOTICE,"%04d POP3 socket closed while listening",pop3_socket);
						break;
					}
#endif
					lprintf(LOG_WARNING,"%04d POP3 !ERROR %d accepting connection"
						,pop3_socket, ERROR_VALUE);
#ifdef _WIN32
					if(WSAGetLastError()==WSAENOBUFS)	/* recycle (re-init WinSock) on this error */
						break;
#endif
					continue;
					startup->socket_open(startup->cbdata,TRUE);
				if(trashcan(&scfg,inet_ntoa(client_addr.sin_addr),"ip-silent")) {
					mail_close_socket(client_socket);
					continue;
				}

				if(active_clients>=startup->max_clients) {
runderwo's avatar
 
runderwo committed
					lprintf(LOG_WARNING,"%04d POP3 !MAXIMUM CLIENTS (%u) reached, access denied"
						,client_socket, startup->max_clients);
					sockprintf(client_socket,"-ERR Maximum active clients reached, please try again later.");
					mswait(3000);
					mail_close_socket(client_socket);
					continue;
				}
				l=1;

				if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) {
					lprintf(LOG_ERR,"%04d POP3 !ERROR %d (%d) disabling blocking on socket"
						,client_socket, i, ERROR_VALUE);
					sockprintf(client_socket,"-ERR System error, please try again later.");
					mswait(3000);
					mail_close_socket(client_socket);
					continue;
				}

				if((pop3=malloc(sizeof(pop3_t)))==NULL) {
					lprintf(LOG_CRIT,"%04d POP3 !ERROR allocating %u bytes of memory for pop3_t"
						,client_socket,sizeof(pop3_t));
					sockprintf(client_socket,"-ERR System error, please try again later.");
					mswait(3000);
					mail_close_socket(client_socket);
					continue;
				}
				pop3->socket=client_socket;
				pop3->client_addr=client_addr;

			lprintf(LOG_DEBUG,"%04d Waiting for %d active clients to disconnect..."
				,server_socket, active_clients);
			start=time(NULL);
			while(active_clients) {
				if(time(NULL)-start>startup->max_inactivity) {
					lprintf(LOG_WARNING,"%04d !TIMEOUT waiting for %d active clients"
						,server_socket, active_clients);
			sem_post(&sendmail_wakeup_sem);
			mswait(100);
			lprintf(LOG_DEBUG,"%04d Waiting for SendMail thread to terminate..."
				,server_socket);
			start=time(NULL);
			while(sendmail_running) {
				if(time(NULL)-start>TIMEOUT_THREAD_WAIT) {
					lprintf(LOG_WARNING,"%04d !TIMEOUT waiting for sendmail thread to terminate"
						,server_socket);
deuce's avatar
deuce committed
		if(!sendmail_running) {
			while(sem_destroy(&sendmail_wakeup_sem)==-1 && errno==EBUSY) {
				mswait(1);
deuce's avatar
deuce committed
				sem_post(&sendmail_wakeup_sem);
deuce's avatar
deuce committed
			}
		}
			lprintf(LOG_INFO,"Recycling server...");
			mswait(2000);
			if(startup->recycle!=NULL)
				startup->recycle(startup->cbdata);