/* 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_forward_request(int evfd, short event, void *client_)
{
    Client * const client = client_;
    ssize_t written;

    (void) evfd;
    if (handle_timeout(event, client) != 0) {
        return;
    }
    if (client->postbuf == NULL) {
        client_disconnect(client);
        return;
    }    
    if (client->postbuf_len <= (size_t) 0U) {
        goto already_written;
    }
    if ((written = write(client->server_fd,
                         client->postbuf + client->postbuf_written,
                         client->postbuf_len - client->postbuf_written)) !=
        (ssize_t) (client->postbuf_len - client->postbuf_written)) {
        if (written <= (ssize_t) 0) {
            if (errno == EINTR) {
                event_add(&client->server_write_ev,
                          &timeout_forward_server_write);
                return;
            }
            plb_log(LL_NOTIFY,
                    "Error while sending a forwarded request : [%s]",
                    strerror(errno));
            client_disconnect(client);
            return;
        }
        client->postbuf_written += written;
        event_add(&client->server_write_ev, &timeout_forward_server_write);
        return;
    }
    client->postbuf_len = (size_t) 0U;    
    already_written:
    (void) client;
}

void client_forward_request(Client * const client)
{
    ssize_t readen;
    
    if (client->postbuf == NULL) {
        if ((client->postbuf = malloc(POSTBUF_CHUNKS)) == NULL) {
            plb_log(LL_ERROR,
                    "Out of memory for the forwarding buffer : [%s]",
                    strerror(errno));
            client_disconnect(client);            
            return;
        }
        client->postbuf_len = (size_t) 0U;
        client->postbuf_written = (size_t) 0U;        
    }
    if ((readen = read(client->client_fd, client->postbuf, POSTBUF_CHUNKS))
        <= (ssize_t) 0) {
        if (readen < (ssize_t) 0) {
            if (errno == EINTR) {
                return;
            }
            plb_log(LL_NOTIFY,
                    "Error while reading to-be-forwarded data : [%s]",
                    strerror(errno));
        }        
        client_disconnect(client);
        return;        
    }
    client->postbuf_len = (size_t) readen;
    client->postbuf_written = (size_t) 0U;
    
    event_set(&client->server_write_ev, client->server_fd, EV_WRITE,
              server_forward_request, client);
    event_add(&client->server_write_ev, &timeout_forward_server_write);
    event_add(&client->client_read_ev, &timeout_forward_client_read);
}

void server_forward_reply(int evfd, short event, void *client_)
{
    Client * const client = client_;    
    ssize_t readen;

    (void) evfd;
    if (handle_timeout(event, client) != 0) {
        return;
    }
    if (client->replybuf == NULL) {
        if ((client->replybuf = malloc(REPLYBUF_CHUNKS)) == NULL) {
            plb_log(LL_ERROR,
                    "Out of memory when trying to get a reply buffer : [%s]",
                    strerror(errno));
            client_disconnect(client);
            return;
        }
        client->replybuf_len = (size_t) 0U;
        client->replybuf_written = (size_t) 0U;        
    }
    if ((readen = read(client->server_fd, client->replybuf, REPLYBUF_CHUNKS))
        <= (ssize_t) 0) {
        if (errno == EINTR) {
            event_add(&client->server_read_ev, &timeout_forward_server_read);
            return;
        }
        if (readen < (ssize_t) 0) {
            plb_log(LL_NOTIFY,
                    "Error while reading the data to be forwarded : [%s]",
                    strerror(errno));
        }
        client_disconnect(client);
        return;        
    }
    client->replybuf_len = (size_t) readen;
    client->replybuf_written = (size_t) 0U;
    
    event_set(&client->client_write_ev, client->client_fd, EV_WRITE,
              client_forward_reply, client);
    event_add(&client->client_write_ev, &timeout_forward_client_write);
}

void client_forward_reply(int evfd, short event, void *client_)
{
    Client * const client = client_;
    ssize_t written;

    (void) evfd;
    if (handle_timeout(event, client) != 0) {
        return;
    }
    if (client->replybuf == NULL) {
        client_disconnect(client);
        return;
    }
    if (client->replybuf_len <= (size_t) 0U) {
        goto already_written;
    }    
    if ((written = write(client->client_fd, 
                         client->replybuf + client->replybuf_written,
                         client->replybuf_len - client->replybuf_written)) !=
        (ssize_t) (client->replybuf_len - client->replybuf_written)) {        
        if (written <= (ssize_t) 0) {
            if (errno == EINTR) {
                event_add(&client->client_write_ev,
                          &timeout_forward_client_write);
                return;
            }
            plb_log(LL_NOTIFY, "Error while sending content data : [%s]",
                    strerror(errno));
            client_disconnect(client);
            return;
        }
        client->replybuf_written += written;
        event_add(&client->client_write_ev, &timeout_forward_client_write);
        return;                
    }
    client->replybuf_len = (size_t) 0U;    
    already_written:    
    event_set(&client->server_read_ev, client->server_fd, EV_READ,
              server_forward_reply, client);
    event_add(&client->server_read_ev, &timeout_forward_server_read);
}



syntax highlighted by Code2HTML, v. 0.9.1