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

void Webinterface::answer_status() {
    string xml =
	"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
	"<?xml-stylesheet type=\"text/xsl\" href=\"/xslt\"?>\n"
	"<status>\n";

    ostringstream o;
    o <<
	"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
	"<?xml-stylesheet type=\"text/xsl\" href=\"/xslt\"?>\n"
	"<status>\n"
	"  <id>\n"
	"    <version>" << VER << "</version>\n"
	"    <distsite>" << DISTSITE << "</distsite>\n"
	"  </id>\n"
	"  <server>\n"
	"    <address>" << config.sipaddr() << ":" << config.sport() << "</address>\n"
	"    <type>" << config.stypestr() << "</type>\n"
	"    <clientreadtimeout>" << config.client_read_timeout() << "</clientreadtimeout>\n"
	"    <clientwritetimeout>" << config.client_write_timeout() << "</clientwritetimeout>\n"
	"    <backendreadtimeout>" << config.backend_read_timeout() << "</backendreadtimeout>\n"
	"    <backendwritetimeout>" << config.backend_write_timeout() << "</backendwritetimeout>\n"
	"    <dispatchmode>" << config.dispatchmodestr() << "</dispatchmode>\n"
	"    <removereservations>" << config.removereservations() << "</removereservations>\n"
	"    <webinterface>" << config.webinterfaceip() << ':' << config.webinterfaceport() << "</webinterface>\n"
	"    <webinterfaceauth>" << config.webinterface_auth() << "</webinterfaceauth>\n"
	"    <webinterfacename>" << config.webinterfacename() << "</webinterfacename>\n"
	"    <dnscachetimeout>" << config.dnscachetimeout() << "</dnscachetimeout>\n"
	"    <buffersize>" << config.buffersize() << "</buffersize>\n"
	"    <closesocketsfast>" << config.fastclose() << "</closesocketsfast>\n"
	"    <onstart>" << config.onstart() << "</onstart>\n"
	"    <onend>" << config.onend() << "</onend>\n"
	"    <onfail>" << config.onfail() << "</onfail>\n"
	"    <checks>\n"
	"      <wakeupinterval>" << config.wakeupsec() << "</wakeupinterval>\n"
	"      <checkupinterval>" << config.checkupsec() << "</checkupinterval>\n"
	"    </checks>\n"
	"    <debugging>\n"
	"      <verbose>" << config.verbose() << "</verbose>\n"
	"      <debug>" << config.debug() << "</debug>\n"
	"      <logtrafficdir>" << config.dumpdir() << "</logtrafficdir>\n"
	"    </debugging>\n"
	"    <dosprotection>\n"
	"      <maxconnections>" << config.maxconn() << "</maxconnections>\n"
	"      <timeinterval>" << config.connrate_time() << "</timeinterval>\n"
	"      <hardmaxconnrate>" << config.hardmaxconnrate() << "</hardmaxconnrate>\n"
	"      <softmaxconnrate>" << config.softmaxconnrate() << "</softmaxconnrate>\n"
	"      <defertime>" << config.defertime() << "</defertime>\n"
	"      <hardmaxconnexcess>" << config.hardmaxconnexcess() << "</hardmaxconnexcess>\n"
	"      <softmaxconnexcess>" << config.softmaxconnexcess() << "</softmaxconnexcess>\n"
	"    </dosprotection>\n"
	"    <acl>\n"
	"      <allow>\n";
    for (unsigned i = 0; i < config.nallow(); i++)
	o <<
	    "        <allowfrom>\n"
	    "          <nr>" << i << "</nr>\n"
	    "          <mask>" << inet2string(config.allow(i)) << "</mask>\n"
	    "        </allowfrom>\n";
    o <<
	"      </allow>\n"
	"      <deny>\n";
    for (unsigned i = 0; i < config.ndeny(); i++)
	o <<
	    "        <denyfrom>\n"
	    "          <nr>" << i << "</nr>\n"
	    "          <mask>" << inet2string(config.deny(i)) << "</mask>\n"
	    "        </denyfrom>\n";
    o <<
	"      </deny>\n"
	"    </acl>\n"
	"    <http>\n"
	"      <addxrversion>" << config.addxrversion() << "</addxrversion>\n"
	"      <addxforwardedfor>" << config.addxforwardedfor() << "</addxforwardedfor>\n"
	"      <stickyhttp>" << config.stickyhttp() << "</stickyhttp>\n"
	"      <replacehostheader>" << config.replacehostheader() << "</replacehostheader>\n"
	"      <serverheaders>\n"
	;
    for (unsigned i = 0; i < config.nserverheaders(); i++)
	o <<
	    "        <serverheader>\n"
	    "          <nr>" << i << "</nr>\n"
	    "          <header>" << config.serverheader(i) << "</header>\n"
	    "        </serverheader>\n"
	    ;
    o <<
	"      </serverheaders>\n"
	"    </http>\n"
	"    <backends>" << balancer.nbackends() << "</backends>\n"
	"    <terminating>" << balancer.terminate() << "</terminating>\n"
	"    <connections>" << balancer.connections() << "</connections>\n"
	"  </server>\n"
	;

    for (unsigned i = 0; i < balancer.nbackends(); i++)
	o <<
	    "  <backend>\n"
	    "    <nr>" << i << "</nr>\n"
	    "    <address>" << balancer.backend(i).description() << "</address>\n"
	    "    <weight>" << balancer.backend(i).weight() << "</weight>\n"
	    "    <maxconnections>" << balancer.backend(i).maxconn() << "</maxconnections>\n"
	    "    <loadavg>" << balancer.backend(i).loadavg() << "</loadavg>\n"
	    "    <up>" << balancer.backend(i).upstr() << "</up>\n"
	    "    <live>" << balancer.backend(i).livestr() << "</live>\n"
	    "    <available>" << balancer.backend(i).availablestr() << "</available>\n"
	    "    <connections>" << balancer.backend(i).connections() << "</connections>\n"
	    "    <connecterrors>" << balancer.backend(i).connecterrors() << "</connecterrors>\n"
	    "    <bytesserved>" << balancer.backend(i).bytesserved() << "</bytesserved>\n"
	    "    <clientsserved>" << balancer.backend(i).clientsserved() << "</clientsserved>\n"
	    "    <hostmatch>" << balancer.backend(i).hostmatch() << "</hostmatch>\n"
	    "    <urlmatch>" << balancer.backend(i).urlmatch() << "</urlmatch>\n"
	    "    <backendcheck>" << balancer.backend(i).backendcheck().setting() << "</backendcheck>\n"
	    "  </backend>\n"
	    ;

    o <<
	"  <activity>\n"
	"    <threadlist>\n";
    unsigned nthreads = 0, max_open_files;
    struct rlimit rl;
    if (getrlimit(RLIMIT_NOFILE, &rl))
	throw Error("Failed to get limit for open files");
    max_open_files = unsigned(rl.rlim_cur);
    for (Threadmap::iterator it = Threadlist::map().begin();
	 it != Threadlist::map().end();
	 it++) {
	nthreads++;
	pthread_t thread_id = (*it).first;
	Threadinfo thread_info = (*it).second;
	o <<
	    "      <thread>\n"
	    "        <id>" << thread_id << "</id>\n"
	    "        <description>" << thread_info.desc() << "</description>\n"
	    "        <backend>" << thread_info.backend() << "</backend>\n"
	    "        <address>";
	if (thread_info.backend() >= 0)
	    o << balancer.backend(thread_info.backend()).description();
	o <<
	    "</address>\n"
	    "        <duration>" << thread_info.timestamp().elapsed() << "</duration>\n"
	    "        <clientip>" << inet2string(thread_info.clientip()) << "</clientip>\n"
	    "      </thread>\n";
    }
    /* The estimate of the number of used fd's is:
     * Base is 5 (stdin/stdout/stderr, listen-fd for service, listen-fd
     * for webinterface
     * Plus 2 x #-threads (1 to client, 1 to backend)
     * There will be fd's in use for shared libs etc., but we don't see
     * those..
     */
    o <<
	"    </threadlist>\n"
	"    <threadcount>" << nthreads << "</threadcount>\n"
	"    <openfiles>" << nthreads * 2 + 5 << "</openfiles>\n"
	"    <maxopenfiles>" << max_open_files << "</maxopenfiles>\n"
	"  </activity>\n";
	 
    o <<
	"</status>\n\n";

    answer_blob (o.str());
}
