#include "webinterface"
#include "balancer/balancer"

void Webinterface::execute() {
    Threadlist::desc("Web interface");

    // Create the server socket, or retry infinitely.
    // This is maybe a too big precaution - previous xr's are responsible
    // for killing off their web interfaces. But we don't want a new xr
    // start to croak and cause downtime just because the web interface,
    // so we just retry for a bit.
    while (true) {
	try {
	    msg("Starting web interface\n");
	    sfd.bind(config.webinterfaceip(), config.webinterfaceport());
	} catch (Error const &e) {
	    mutex_lock(&cerr);
	    if (config.prefixtimestamp()) {
		Timestamp tm;
		cerr << tm.desc() << ' ';
	    }
	    cerr << e.what() << " (webinterface, retrying in a sec)\n";
	    mutex_unlock(&cerr);
	    sleep(1);
	    continue;
	}
	break;
    }

    msg("Web interface started on socket " << sfd.fd() << "\n");
    while (!balancer.terminate()) {
	try {
	    Fdset fdset(0);
	    fdset.add (sfd);
	    fdset.wait_r();
	    if (fdset.readable(sfd)) {
		cfd = sfd.accept();
		serve();
		cfd.close();
	    }
	} catch (Error const &e) {
	    mutex_lock(&cerr);
	    if (config.prefixtimestamp()) {
		Timestamp tm;
		cerr << tm.desc() << ' ';
	    }
	    cerr << e.what() << " (webinterface)\n";
	    mutex_unlock(&cerr);
	    
	    if (cfd.fd() >= 0) {
		ostringstream m;
		m <<
		    "<html>\n"
		    "  <head>\n"
		    "    <title>Web interface error</title>\n"
		    "  </head>\n"
		    "  <body>\n"
		    "    <h1>Web interface error</h1>\n"
		    "    XR's web interface could not handle your request.\n"
		    "    <p/>\n"
		    "    <i>" << e.what() << "</i>\n"
		    "  </body>\n"
		    "</html>\n";
		ostringstream o;
		o << "HTTP/1.0 500 Server Error\r\n"
		     "X-Reason: " << e.what() << "\r\n"
		     "Content-Length: " << m.str().length() << "\r\n"
		     "\r\n" <<
		     m.str();
		Netbuffer buf(o.str());
		buf.netwrite(cfd, config.client_write_timeout());
		cfd.close();
	    }
	}
    }
    
    msg("Web interface stopping.\n");
    sfd.close();
}
