/* 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_mark_failure(Client * const client)
{
    if (client->server->status > 0U) {
        client->server->status--;
        if (client->server->status <= 0U) {
            plb_log(LL_WARNING, "[%s] is down\n", client->server->name);
        }
    }
}

int connect_server(Client * const client)
{
    static int all_servers_down;
    const Server * const serverpool_previous = serverpool_current;
    int server_fd;

    for (;;) {
        if (serverpool_current->next == NULL) {
            serverpool_current = serverpool_head;
        } else {
            serverpool_current = serverpool_current->next;
        }
        if (serverpool_current->status > 0U) {
            break;
        }
        if (serverpool_current == serverpool_previous) {
            if (all_servers_down == 0) {
                plb_log(LL_WARNING, "All servers are down");
                all_servers_down = 1;
            }
            return -1;
        }
    }
    all_servers_down = 0;
    if ((server_fd = socket(serverpool_current->ai_family,
                            SOCK_STREAM, IPPROTO_TCP)) == -1) {
        plb_log(LL_ERROR, "unable to create a backend socket : [%s]",
                strerror(errno));
        return -1;
    }
    setsockopt_aggressive(server_fd);
    socket_nonblock(server_fd);
    client->server = serverpool_current;    
    for (;;) {
        if (connect(server_fd, 
                    (struct sockaddr *) &serverpool_current->ai_addr,
                    (socklen_t) serverpool_current->ai_addrlen) != 0 &&
            errno != EINPROGRESS) {
            if (errno == EINTR) {
                continue;
            }
            plb_log(LL_WARNING, "Unable to connect to a backend server : [%s]",
                    strerror(errno));
            while (close(server_fd) != 0 && errno == EINTR);
            server_mark_failure(client);
            return -1;
        }
        break;
    }
    client->server_fd = server_fd;
    event_set(&client->server_write_ev, server_fd, EV_WRITE,
              server_send_header, client);
    event_add(&client->server_write_ev, &timeout_header_server_write);
    
    return 0;
}



syntax highlighted by Code2HTML, v. 0.9.1