/* Pure Load Balancer - (C)opyleft 2003 Jedi/Sector One <j@pureftpd.org> */
#include <config.h>
#include "plb.h"
#include "plb_globals.h"
#ifdef WITH_DMALLOC
# include <dmalloc.h>
#endif
#define EVENT_FD_(e) ((e)->ev_fd)
void client_disconnect(Client * const client)
{
current_nb_clients--;
if (client->header != NULL) {
free(client->header);
client->header = NULL;
client->header_len = (size_t) 0U;
client->header_written = (size_t) 0U;
}
if (client->replybuf != NULL) {
free(client->replybuf);
client->replybuf = NULL;
client->replybuf_len = (size_t) 0U;
client->replybuf_written = (size_t) 0U;
}
if (client->postbuf != NULL) {
free(client->postbuf);
client->postbuf = NULL;
client->postbuf_len = (size_t) 0U;
client->postbuf_written = (size_t) 0U;
}
if (EVENT_FD((&client->server_read_ev)) != -1) {
event_del(&client->server_read_ev);
EVENT_FD_((&client->server_read_ev)) = -1;
}
if (EVENT_FD((&client->server_write_ev)) != -1) {
event_del(&client->server_write_ev);
EVENT_FD_((&client->server_write_ev)) = -1;
}
if (EVENT_FD((&client->client_read_ev)) != -1) {
event_del(&client->client_read_ev);
EVENT_FD_((&client->client_read_ev)) = -1;
}
if (EVENT_FD((&client->client_write_ev)) != -1) {
event_del(&client->client_write_ev);
EVENT_FD_((&client->client_write_ev)) = -1;
}
if (client->server_fd != -1) {
while (close(client->server_fd) != 0 && errno == EINTR);
client->server_fd = -1;
}
if (client->client_fd != -1) {
while (close(client->client_fd) != 0 && errno == EINTR);
client->client_fd = -1;
}
client->state = STATE_OFFLINE;
}
int handle_timeout(const short event, Client * const client)
{
if ((event & EV_TIMEOUT) != 0) {
plb_log(LL_DEBUG, "Timeout");
client_disconnect(client);
return 1;
}
return 0;
}
static void smtp_banner(const int fd)
{
char banner[300];
char nodename[256];
ssize_t written;
size_t towrite;
if (gethostname(nodename, sizeof nodename - (size_t) 1U) != 0) {
nodename[0] = 'x';
nodename[1] = 0;
}
nodename[sizeof nodename - (size_t) 1U] = 0;
snprintf(banner, sizeof banner,
"220 %s ESMTP - Pure Load Balancer ready\r\n", nodename);
towrite = strlen(banner);
while ((written = write(fd, banner, towrite)) < (ssize_t) 0 &&
errno == EINTR); /* to be rewritten */
if (written < (ssize_t) 0 || (size_t) written != towrite) {
plb_log(LL_NOTIFY,
"Error while sending a banner to a client (nmap scan?): [%s]",
strerror(errno));
}
}
void new_client(const int listenfd, short event, void *ev)
{
static int last_was_full;
Client *client;
struct sockaddr_storage client_sa;
socklen_t client_sa_len;
int client_fd;
(void) ev;
(void) event;
if ((client_fd = accept(listenfd, (struct sockaddr *) &client_sa,
&client_sa_len)) < 0) {
plb_log(LL_ERROR, "Unable to accept a new client connection : [%s]",
strerror(errno));
return;
}
setsockopt_aggressive(client_fd);
socket_nonblock(client_fd);
if (client_fd >= (int) max_clients) {
(void) write(client_fd, SERVER_FULL_MSG,
sizeof SERVER_FULL_MSG - (size_t) 1U);
if (last_was_full == 0) {
plb_log(LL_WARNING, "Server full - too many clients");
last_was_full = 1;
}
while (close(client_fd) != 0 && errno == EINTR);
return;
} else {
last_was_full = 0;
}
if (protocol == PROTOCOL_SMTP) {
smtp_banner(client_fd);
}
current_nb_clients++;
client = &clients[client_fd];
client->client_fd = client_fd;
client->server_fd = -1;
client->state = STATE_HEADER;
client->header = NULL;
client->postbuf = NULL;
client->replybuf = NULL;
client->header_len = (size_t) 0U;
client->header_written = (size_t) 0U;
client->postbuf_len = (size_t) 0U;
client->postbuf_written = (size_t) 0U;
client->replybuf_len = (size_t) 0U;
client->replybuf_written = (size_t) 0U;
EVENT_FD_((&client->client_read_ev)) = -1;
EVENT_FD_((&client->client_write_ev)) = -1;
EVENT_FD_((&client->server_read_ev)) = -1;
EVENT_FD_((&client->server_write_ev)) = -1;
event_set(&client->client_read_ev, client_fd,
EV_READ, client_read, &clients[client_fd]);
event_add(&client->client_read_ev, &timeout_header_client_read);
}
syntax highlighted by Code2HTML, v. 0.9.1