#include "backend"

void Backend::check() {
    debugmsg("About to check back end " << description() << ": " <<
	     backendcheck().description() << '\n');

    ostringstream o;
    Backend tester;
    Httpbuffer httpbuffer;
    
    switch (backendcheck().checktype()) {
    case BackendCheck::c_connect:
	// Assume we test at the true back end address/port.
	// Override if necessary.
	tester = *this;
	if (backendcheck().server() != "")
	    tester.server(backendcheck().server());
	if (backendcheck().port() != 0)
	    tester.port(backendcheck().port());

	// Attempt CONNECT CHECK times (see /etc/Makefile.class)
	for (int i = 0; i < CONNCHECKS; i++) {
	    tester.connect();
	    if (tester.live())
		break;
	}
	live(tester.live());
	debugmsg("Check of back end " << description() <<
		 " by connecting to " << tester.description() <<
		 ", result: " << livestr() << '\n');
	break;
	
    case BackendCheck::c_get:
	// HTTP GET to stated server, port, uri
	tester.server(backendcheck().server());
	tester.port(backendcheck().port());
	tester.connect();
	if (! tester.live()) {
	    warnmsg("HTTP GET checker: host " << backendcheck().server()
		    << ", port " << backendcheck().port() <<
		    "not responding\n");
	    live(false);
	} else {
	    o << "GET " << backendcheck().uri() << " HTTP/1.0\r\n"
		 "Host: " << backendcheck().server() << "\r\n"
		 "Connection: close\r\n"
		"\r\n";
	    httpbuffer.setstring (o.str());
	    httpbuffer.netwrite(tester.sock(), config.backend_write_timeout());
	    httpbuffer.reset();
	    while (!httpbuffer.headersreceived())
		httpbuffer.netread(tester.sock(),
				   config.backend_read_timeout());
	    msg("HTTP GET checker got answer: '" << 
		httpbuffer.firstline() << '\n');		
	    if (httpbuffer.stringat(9, 3) == "200")
		live(true);
	    else 
		debugmsg("Back end assumed dead.\n");
	}
	break;
	
    case BackendCheck::c_external:
	// External program to be called, with arguments:
	// IP:PORT availability current-connections
	o << backendcheck().program() << ' ' << description() << ' '
	  << availablestr() << ' ' << connections();
	FILE *f;
	int result;
	if (! (f = popen(o.str().c_str(), "r")) ) {
	    live(false);
	    warnmsg("Failed to start external checker '" << o.str() <<
		    ": " << strerror(errno) << '\n');
	} else {
	    if (fscanf(f, "%d", &result) < 1) {
		live(false);
		warnmsg("External checker '" << o.str() <<
			"' did not reply with a number\n");
	    } else {
		msg("External checker '" << o.str() << "' replied: " <<
		    result << '\n');
		live(result == 0);
	    }
	    if (pclose(f)) {
		warnmsg("External checker '" << o.str() <<
			"' terminated with error\n");
		live(false);
	    }
	}
	break;
	
    default:
	throw Error("Internal fry in Backend::check()");
    }
}
