user can sepcify the max connections piler-smtp can handle

Change-Id: Id92d625d354838558a63dfdd668143168bb7ebee
Signed-off-by: SJ <sj@acts.hu>
This commit is contained in:
SJ 2016-10-30 22:53:49 +01:00
parent 49348fd261
commit 4a1c1785d1
4 changed files with 27 additions and 11 deletions

View File

@ -35,7 +35,13 @@ default_retention_days=2557
encrypt_messages=1 encrypt_messages=1
; number of worker processes, ie. the number of simultaneous smtp connections to piler. ; number of worker processes, ie. the number of simultaneous smtp connections to piler.
number_of_worker_processes=10 ; This value should be the number of cpus + 1, ie. 2 for a single cpu host
number_of_worker_processes=2
; max. number of parallel connections piler-smtp can handle.
; Important! If you want to change this value, then you must first
; stop piler-smtp, change the value, then start piler-smtp.
max_connections=256
; number of processed emails per each piler process ; number of processed emails per each piler process
max_requests_per_child=1000 max_requests_per_child=1000

View File

@ -80,6 +80,7 @@ struct _parse_rule config_parse_rules[] =
{ "listen_addr", "string", (void*) string_parser, offsetof(struct __config, listen_addr), "0.0.0.0", MAXVAL-1}, { "listen_addr", "string", (void*) string_parser, offsetof(struct __config, listen_addr), "0.0.0.0", MAXVAL-1},
{ "listen_port", "integer", (void*) int_parser, offsetof(struct __config, listen_port), "25", sizeof(int)}, { "listen_port", "integer", (void*) int_parser, offsetof(struct __config, listen_port), "25", sizeof(int)},
{ "locale", "string", (void*) string_parser, offsetof(struct __config, locale), "", MAXVAL-1}, { "locale", "string", (void*) string_parser, offsetof(struct __config, locale), "", MAXVAL-1},
{ "max_connections", "integer", (void*) int_parser, offsetof(struct __config, max_connections), "256", sizeof(int)},
{ "max_requests_per_child", "integer", (void*) int_parser, offsetof(struct __config, max_requests_per_child), "1000", sizeof(int)}, { "max_requests_per_child", "integer", (void*) int_parser, offsetof(struct __config, max_requests_per_child), "1000", sizeof(int)},
{ "memcached_servers", "string", (void*) string_parser, offsetof(struct __config, memcached_servers), "127.0.0.1", MAXVAL-1}, { "memcached_servers", "string", (void*) string_parser, offsetof(struct __config, memcached_servers), "127.0.0.1", MAXVAL-1},
{ "memcached_to_db_interval", "integer", (void*) int_parser, offsetof(struct __config, memcached_to_db_interval), "900", sizeof(int)}, { "memcached_to_db_interval", "integer", (void*) int_parser, offsetof(struct __config, memcached_to_db_interval), "900", sizeof(int)},

View File

@ -35,6 +35,7 @@ struct __config {
char memcached_servers[MAXVAL]; char memcached_servers[MAXVAL];
int memcached_ttl; int memcached_ttl;
int max_connections;
int number_of_worker_processes; int number_of_worker_processes;
int max_requests_per_child; int max_requests_per_child;

View File

@ -26,12 +26,11 @@
#include <piler.h> #include <piler.h>
#define PROGNAME "piler-smtp" #define PROGNAME "piler-smtp"
#define POLL_SIZE 256
extern char *optarg; extern char *optarg;
extern int optind; extern int optind;
struct pollfd poll_set[POLL_SIZE]; struct pollfd *poll_set=NULL;
int timeout = 20; // checking for timeout this often [sec] int timeout = 20; // checking for timeout this often [sec]
int numfds = 0; int numfds = 0;
int listenerfd = -1; int listenerfd = -1;
@ -39,7 +38,7 @@ int listenerfd = -1;
char *configfile = CONFIG_FILE; char *configfile = CONFIG_FILE;
struct __config cfg; struct __config cfg;
struct passwd *pwd; struct passwd *pwd;
struct smtp_session *session, *sessions[POLL_SIZE]; struct smtp_session *session, **sessions=NULL;
void handle_data(struct smtp_session *session, char *readbuf, int readlen){ void handle_data(struct smtp_session *session, char *readbuf, int readlen){
@ -130,10 +129,8 @@ void init_smtp_session(struct smtp_session *session, int fd_index, int sd){
void free_smtp_session(struct smtp_session *session){ void free_smtp_session(struct smtp_session *session){
if(session){ if(session){
//printf("freeing session\n");
if(session->use_ssl == 1){ if(session->use_ssl == 1){
//printf("shutdown ssl\n");
SSL_shutdown(session->ssl); SSL_shutdown(session->ssl);
SSL_free(session->ssl); SSL_free(session->ssl);
} }
@ -156,6 +153,9 @@ void p_clean_exit(){
free_smtp_session(sessions[i]); free_smtp_session(sessions[i]);
} }
if(sessions) free(sessions);
if(poll_set) free(poll_set);
syslog(LOG_PRIORITY, "%s has been terminated", PROGNAME); syslog(LOG_PRIORITY, "%s has been terminated", PROGNAME);
//unlink(cfg.pidfile); //unlink(cfg.pidfile);
@ -180,7 +180,6 @@ void tear_down_client(int n){
syslog(LOG_PRIORITY, "disconnected from %s", sessions[n]->remote_host); syslog(LOG_PRIORITY, "disconnected from %s", sessions[n]->remote_host);
// new code
free_smtp_session(sessions[n]); free_smtp_session(sessions[n]);
sessions[n] = NULL; sessions[n] = NULL;
@ -286,7 +285,7 @@ void start_new_session(int socket, struct sockaddr_storage client_address, int f
char smtp_banner[SMALLBUFSIZE], remote_host[INET6_ADDRSTRLEN]; char smtp_banner[SMALLBUFSIZE], remote_host[INET6_ADDRSTRLEN];
// Uh-oh! We have enough connections to serve already // Uh-oh! We have enough connections to serve already
if(numfds >= POLL_SIZE){ if(numfds >= cfg.max_connections){
inet_ntop(client_address.ss_family, get_in_addr((struct sockaddr*)&client_address), remote_host, sizeof(remote_host)); inet_ntop(client_address.ss_family, get_in_addr((struct sockaddr*)&client_address), remote_host, sizeof(remote_host));
syslog(LOG_PRIORITY, "too many connections (%d), cannot accept %s", numfds, remote_host); syslog(LOG_PRIORITY, "too many connections (%d), cannot accept %s", numfds, remote_host);
send(socket, SMTP_RESP_421_ERR_ALL_PORTS_ARE_BUSY, strlen(SMTP_RESP_421_ERR_ALL_PORTS_ARE_BUSY), 0); send(socket, SMTP_RESP_421_ERR_ALL_PORTS_ARE_BUSY, strlen(SMTP_RESP_421_ERR_ALL_PORTS_ARE_BUSY), 0);
@ -384,11 +383,12 @@ int main(int argc, char **argv){
(void) openlog(PROGNAME, LOG_PID, LOG_MAIL); (void) openlog(PROGNAME, LOG_PID, LOG_MAIL);
memset(sessions, '\0', sizeof(sessions));
memset(poll_set, '\0', sizeof(poll_set));
initialise_configuration(); initialise_configuration();
// The max_connections variable mustn't be affected by a reload!
if(cfg.max_connections < 10) cfg.max_connections = 10;
if(cfg.max_connections > 10000) cfg.max_connections = 10000;
listenerfd = create_listener_socket(cfg.listen_addr, cfg.listen_port); listenerfd = create_listener_socket(cfg.listen_addr, cfg.listen_port);
if(listenerfd == -1){ if(listenerfd == -1){
syslog(LOG_PRIORITY, "create_listener_socket() error"); syslog(LOG_PRIORITY, "create_listener_socket() error");
@ -397,12 +397,20 @@ int main(int argc, char **argv){
if(drop_privileges(pwd)) fatal(ERR_SETUID); if(drop_privileges(pwd)) fatal(ERR_SETUID);
set_signal_handler(SIGINT, p_clean_exit);
set_signal_handler(SIGTERM, p_clean_exit); set_signal_handler(SIGTERM, p_clean_exit);
set_signal_handler(SIGALRM, check_for_client_timeout); set_signal_handler(SIGALRM, check_for_client_timeout);
set_signal_handler(SIGHUP, initialise_configuration); set_signal_handler(SIGHUP, initialise_configuration);
alarm(timeout); alarm(timeout);
// calloc() initialitizes the allocated memory
sessions = calloc(cfg.max_connections, sizeof(struct smtp_session));
poll_set = calloc(cfg.max_connections, sizeof(struct pollfd));
if(!sessions || !poll_set) fatal("calloc() error");
poll_set[0].fd = listenerfd; poll_set[0].fd = listenerfd;
poll_set[0].events = POLLIN; poll_set[0].events = POLLIN;
numfds = 1; numfds = 1;