/* Pure Load Balancer - (C)opyleft 2003 Jedi/Sector One */ #include #include "plb.h" #include "plb_globals.h" #ifdef WITH_DMALLOC # include #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); }