/* 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
void server_send_header(int evfd, short event, void *client_)
{
Client * const client = client_;
ssize_t written;
(void) evfd;
if (event == EV_TIMEOUT) {
server_mark_failure(client);
client_disconnect(client);
return;
}
if (client->header == NULL) {
client_disconnect(client);
return;
}
if (client->header_len <= (size_t) 0U) {
goto already_written;
}
if ((written = write(client->server_fd,
client->header + client->header_written,
client->header_len - client->header_written)) !=
(ssize_t) (client->header_len - client->header_written)) {
if (written <= (ssize_t) 0) {
if (errno == EINTR) {
event_add(&client->server_write_ev,
&timeout_header_server_write);
return;
}
switch (errno) {
#ifdef ETIMEDOUT
case ETIMEDOUT:
#endif
#ifdef ECONNREFUSED
case ECONNREFUSED:
#endif
#ifdef EHOSTDOWN
case EHOSTDOWN:
#endif
#ifdef EHOSTUNREACH
case EHOSTUNREACH:
#endif
#ifdef ECONNRESET
case ECONNRESET:
#endif
#ifdef ECONNABORTED
case ECONNABORTED:
#endif
#ifdef ENETRESET
case ENETRESET:
#endif
#ifdef ENETUNREACH
case ENETUNREACH:
#endif
#ifdef ENETDOWN
case ENETDOWN:
#endif
#ifdef EREMCHG
case EREMCHG:
#endif
server_mark_failure(client);
break;
default:
plb_log(LL_NOTIFY, "While connecting to a real server : [%s]",
strerror(errno));
}
client_disconnect(client);
return;
}
if (client->server->status <= 0U) {
plb_log(LL_WARNING, "[%s] is up again\n", client->server->name);
}
client->server->status = server_retry;
client->header_written += written;
event_add(&client->server_write_ev, &timeout_header_server_write);
return;
}
client->header_len = (size_t) 0U;
already_written:
client->state = STATE_HEADER_SENT;
free(client->header);
client->header = NULL;
client->header_len = (size_t) 0U;
client->header_written = (size_t) 0U;
event_set(&client->server_read_ev, client->server_fd, EV_READ,
server_forward_reply, client);
event_add(&client->server_read_ev, &timeout_header_server_read);
}
void client_read_header(Client * const client)
{
ssize_t readen;
if (client->header == NULL) {
if ((client->header = malloc(HEADER_MAX)) == NULL) {
plb_log(LL_ERROR, "Out of memory to read the client query : [%s]",
strerror(errno));
client_disconnect(client);
return;
}
client->header_len = (size_t) 0U;
client->header_written = (size_t) 0U;
}
if ((readen = read(client->client_fd, client->header + client->header_len,
HEADER_MAX - client->header_len))
<= (ssize_t) 0) {
if (readen < (ssize_t) 0) {
if (errno == EINTR) {
return;
}
plb_log(LL_NOTIFY, "Client read error : [%s]",
strerror(errno));
}
client_disconnect(client);
return;
}
client->header_len += (size_t) readen;
if (client->header_len >= HEADER_MAX) {
plb_log(LOG_WARNING, "Client sent a very large request");
client_disconnect(client);
}
do {
register const char *s;
const char *s_end;
if (client->header_len <= protocol_header_end_len + (size_t) 1U) {
break;
}
s = client->header;
s_end = client->header + client->header_len
- (protocol_header_end_len - (size_t) 1U);
do {
if (memcmp(s, protocol_header_end,
protocol_header_end_len) == 0) {
client->state = STATE_SEND_HEADER;
if (connect_server(client) != 0) {
client_disconnect(client);
return;
}
break;
}
s++;
} while (s != s_end);
} while(0);
event_add(&client->client_read_ev, &timeout_header_client_read);
}
syntax highlighted by Code2HTML, v. 0.9.1