RSS Git Download  Clone
Raw Blame History
/*******************************************************************************
 *	NetworkHttp.cc		NetworkHttp class
 *			T.Barnaby,	BEAM Ltd,	2006-08-01
 *******************************************************************************
 */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <sys/time.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <math.h>
#include <BPoll.h>
#include <BFile.h>
#include <BHtmlPage.h>
#include <BNameValue.h>
#include <NetworkHttp.h>
#include <Debug.h>
#include <Control.h>
#include <TmsD.h>
#include <TmsC.h>

using namespace Tms;
using namespace std;

static const char* const suffixTable [] = {
	".htm.html",	"text/html",
	".jpg.jpeg",	"image/jpeg",
	".gif",		"image/gif",
	".png",		"image/png",
	".txt.h.c.cc.cpp",	"text/plain",
	".css",		"text/css",
	".wav",		"audio/wav",
	".avi",		"video/x-msvideo",
	".qt.mov",	"video/quicktime",
	".mpe.mpeg",	"video/mpeg",
	".mid.midi",	"audio/midi",
	".mp3",		"audio/mpeg",
#if 0                        /* unpopular */
	".au",		"audio/basic",
	".pac",		"application/x-ns-proxy-autoconfig",
	".vrml.wrl",	"model/vrml",
#endif
	0,		"application/octet-stream" /* default */
};

typedef enum {
	HTTP_OK = 200,
	HTTP_MOVED_TEMPORARILY = 302,
	HTTP_BAD_REQUEST = 400,       /* malformed syntax */
	HTTP_UNAUTHORIZED = 401, /* authentication needed, respond with auth hdr */
	HTTP_NOT_FOUND = 404,
	HTTP_FORBIDDEN = 403,
	HTTP_REQUEST_TIMEOUT = 408,
	HTTP_NOT_IMPLEMENTED = 501,   /* used for unrecognized requests */
	HTTP_INTERNAL_SERVER_ERROR = 500,
	HTTP_CONTINUE = 100,
	HTTP_SWITCHING_PROTOCOLS = 101,
	HTTP_CREATED = 201,
	HTTP_ACCEPTED = 202,
	HTTP_NON_AUTHORITATIVE_INFO = 203,
	HTTP_NO_CONTENT = 204,
	HTTP_MULTIPLE_CHOICES = 300,
	HTTP_MOVED_PERMANENTLY = 301,
	HTTP_NOT_MODIFIED = 304,
	HTTP_PAYMENT_REQUIRED = 402,
	HTTP_BAD_GATEWAY = 502,
	HTTP_SERVICE_UNAVAILABLE = 503, /* overload, maintenance */
	HTTP_RESPONSE_SETSIZE = 0xffffffff
} HttpResponseNum;

typedef struct {
	HttpResponseNum	type;
	const char*	name;
	const char*	info;
} HttpEnumString;

static const HttpEnumString httpResponseNames[] = {
	{ HTTP_OK, "OK", NULL },
	{ HTTP_MOVED_TEMPORARILY, "Found", "Directories must end with a slash." },
	{ HTTP_REQUEST_TIMEOUT, "Request Timeout",
		"No request appeared within a reasonable time period." },
	{ HTTP_NOT_IMPLEMENTED, "Not Implemented",
		"The requested method is not recognized by this server." },
	{ HTTP_UNAUTHORIZED, "Unauthorized", "" },
	{ HTTP_NOT_FOUND, "Not Found",
		"The requested URL was not found on this server." },
	{ HTTP_BAD_REQUEST, "Bad Request", "Unsupported method." },
	{ HTTP_FORBIDDEN, "Forbidden", "" },
	{ HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error",
		"Internal Server Error" },
#if 0                               /* not implemented */
	{ HTTP_CREATED, "Created" },
	{ HTTP_ACCEPTED, "Accepted" },
	{ HTTP_NO_CONTENT, "No Content" },
	{ HTTP_MULTIPLE_CHOICES, "Multiple Choices" },
	{ HTTP_MOVED_PERMANENTLY, "Moved Permanently" },
	{ HTTP_NOT_MODIFIED, "Not Modified" },
	{ HTTP_BAD_GATEWAY, "Bad Gateway", "" },
	{ HTTP_SERVICE_UNAVAILABLE, "Service Unavailable", "" },
#endif
};


static const char RFC1123FMT[] = "%a, %d %b %Y %H:%M:%S GMT";



NetworkHttpThread::NetworkHttpThread(NetworkHttp& netOutput) : onetOutput(netOutput){
}

void* NetworkHttpThread::function(){
	dprintf(DBG_THREADS, "NetworkHttpThread: %d\n", gettid());
	onetOutput.run();
	return 0;
}



HttpConnection::HttpConnection(Control& control, int fd, BSocketAddressINET from)
	: BSocket(fd), ocontrol(control), ofrom(from){
	BString	s;
	
	if((s = ocontrol.oconfig.findValue("HtmlDir:")) != "")
		ohtmlDir = s;
	else
		ohtmlDir = "html";

	ofile = fdopen(fd, "rw");
}

HttpConnection::~HttpConnection(){
	fclose(ofile);
}

BError HttpConnection::recvLine(BString& line){
	BError	err;
	char	buf[BufSize];
	
	if(fgets(buf, sizeof(buf), ofile))
		line = buf;
	else
		err.set(1);
	
	return err;
}

BError HttpConnection::sendString(BString line){
	BSize	n;
	
	return send(line, line.len(), n);
}

BString encodeString(BString str)
{
	int	n;
	char*	res = new char [str.len() * 6 + 1];
	char*	p = res;
	BString	rstr;
	
	for(n = 0; n < str.len(); n++){
		if(isalnum(str[n]))
			*p++ = str[n];
		else
			p += sprintf(p, "&#%d;", (unsigned char)str[n]);
	}
	*p = '\0';
	rstr = res;
	delete[] res;
	
	return rstr;
}

BString decodeString(BString str, int option)
{
	const char*	pin = str.retStr();
	char*		res = new char [str.len() + 1];
	char*		pout = res;
	BString		rstr;
	char		c;

	while((c = *pin++) != '\0') {
		unsigned value1, value2;

		if(option && c == '+'){
			*pout++ = ' ';
			continue;
		}
		if(c != '%'){
			*pout++ = c;
			continue;
		}
		if(sscanf(pin, "%1X", &value1) != 1  || sscanf(pin+1, "%1X", &value2) != 1){
			if(!option)
				return "";
			*pout++ = '%';
			continue;
		}
		value1 = value1 * 16 + value2;
		if(!option && (value1 == '/' || value1 == '\0')){
			return pin + 1;
		}
		*pout++ = value1;
		pin += 2;
	}
	*pout = '\0';

	rstr = res;
	delete[] res;
	
	return rstr;
}

BError HttpConnection::sendHttpError(int num, BString str){
	BError	err;
	
	sendString(BString("HTTP/1.0 ") + num + " " + str + "\r\n");
	sendString("Content-type: text/html; charset=UTF-8\r\n");
	sendString("Connection : close\r\n");
	sendString("\r\n");
	return err;
}

BError HttpConnection::sendHeader(int num, BString contentType){
	unsigned	i;
	unsigned	numNames = sizeof(httpResponseNames) / sizeof(httpResponseNames[0]);
	BString		responseString;
	BString		infoString;
	time_t		timer = time(0);
	char		timeStr[80];
	BString		header;
	
	for(i = 0; i < numNames; i++) {
		if(int(httpResponseNames[i].type) == num){
			responseString = httpResponseNames[i].name;
			infoString = httpResponseNames[i].info;
			break;
		}
	}

	strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer));

	header = BString("HTTP/1.0 ") + num + " " + responseString + "\r\n";
//	header += BString("Content-type: ") + contentType + "\r\n";
	header += BString("Content-type: ") + contentType + "; charset=UTF-8\r\n";
	header += BString("Date: ") + timeStr + "\r\n";
	header += BString("Connection: close\r\n");
#ifdef ZAP
	strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&timer));
	header += BString("Last-Modified: ") + timeStr + "\r\n";
	header += BString("Content-length: ") +contentLength + "\r\n";
#endif
	header += BString("\r\n");
	
	return sendString(header);
}

void HttpConnection::start(){
	BThread::start();
}

void* HttpConnection::function(){
	BError	err;
	
	dprintf(DBG_HTTP, "%s: Starting\n", __FUNCTION__);
	while(1){
		if(err = process()){
			break;
		}
	}
	dprintf(DBG_HTTP, "%s: Exiting\n", __FUNCTION__);
	
	return 0;
}

BError HttpConnection::initTms(){
	BError		err;
	BString		hostName = "localhost";
	
	// Connect to TMS control objects
	if(err = otmsControl.connectService(BString("//") + hostName + "/tmsControl")){
		cerr << "Error: cannot connect to tmsControl: " << err.getString() << "\n";
		return err;
	}
	if(err = otmsProcess.connectService(BString("//") + hostName + "/tmsProcess")){
		cerr << "Error: cannot connect to tmsProcess: " << err.getString() << "\n";
		return err;
	}

#ifdef ZAP
	if(events){
		if(err = tmsEventsProcess(tmsProcess, hostName)){
			cerr << err.getString() + "\n";
			return 1;	
		}
		
	}
#endif
	return err;
}

BError HttpConnection::process(){
	BError		err;
	BString		line;
	char		cmd[BufSize];
	char		url[BufSize];

	dprintf(DBG_HTTP, "%s: Start\n", __FUNCTION__);

	// Read command
	if(err = recvLine(line))
		return err;
	
	dprintf(DBG_HTTP, "Received: %s\n", __FUNCTION__, line.retStr());
	if(sscanf(line, "%[^ ] %[^ ] HTTP/%*d.%*d", cmd, url) != 2){
		sendHeader(HTTP_BAD_REQUEST);
		return err.set(1, "Invalid HTTP request");
	}
	
	dprintf(DBG_HTTP, "%s: Cmd: %s Url: %s\n", __FUNCTION__, cmd, url);

	// Read header
	while(! (err = recvLine(line))){
//		printf("LenLen: %d\n", line.len()); hd8(line, line.len());
		line.removeNL();
		dprintf(DBG_HTTP, "%s: Received: %d %s\n", __FUNCTION__, line.len(), line.retStr());
		if(line.len() == 1)
			break;
	}
	
	if(strcasecmp(cmd, "GET")){
		sendHeader(HTTP_NOT_IMPLEMENTED);
		return err.set(1, "Invalid HTTP request");
	}
	
	if((BString(url) == "/")
		|| (BString(url) == "index.html")
		|| !strncmp(url, "/config.cgi", 11)
		|| !strncmp(url, "/help.cgi", 9)
		|| !strncmp(url, "/status.cgi", 9)
		|| !strncmp(url, "/statistics.cgi", 9)
		|| !strncmp(url, "/dataraw.cgi", 11)
		){
		err = processInternal(url);
	}
	else {
		err = processFile(url);
	}

	fclose(ofile);
	close();
	err.set(1);

	return err;
}

BError HttpConnection::createPage(BHtmlPage& page){
	BError			err;
	BHtml			h;
	BHtml			t;

	h = BHtml("div");
	h.append("a", "class='plain' href='/'", "Home")->append("br");
	h.append("a", "class='plain' href='/config.cgi'", "Config")->append("br");
	h.append("a", "class='plain' href='/status.cgi'", "Status")->append("br");
	h.append("a", "class='plain' href='/statistics.cgi'", "Statistics")->append("br");
	h.append("a", "class='plain' href='/help.cgi'", "Help")->append("br");
	h.append("a", "class='plain' href='http://www.beam.ltd.uk'", "BEAM")->append("br");
	h.append("a", "class='plain' href='http://www.alphadata.co.uk'", "Alpha Data")->append("br");
	h.append("a", "class='plain' href='http://portal.beam.ltd.uk/support/cern'", "TMS Support")->append("br");

	page.setLeftSide(h.render());

	return err;
}

BError HttpConnection::processFile(BString url){
	BError			err;
	BFile			file;
	BString			ext;
	int			n;
	const char* const*	table;
	const char*		try_suffix;
	BString			mimeType;
	BString			s;
	BString			str;
	BSize			nsent;
	BHtmlPage		page;
	
	dprintf(DBG_HTTP, "HttpConnection::processFile: Url: (%s)\n", url.retStr());
	createPage(page);

	if((url == "") || (url == "/"))
		url = "index.html";
	
	n = url.findReverse('.');
	if(n >= 0)
		ext = url.subString(n + 1, -1);

	for(table = suffixTable; *table; table += 2){
		if((try_suffix = strstr(*table, ext)) != 0){
			try_suffix += strlen(ext);
			if(*try_suffix == 0 || *try_suffix == '.')
				break;
		}
	}
	mimeType = table[1];
	
	if(err = file.open(ohtmlDir + "/" + url, "r")){
		sendHeader(HTTP_NOT_FOUND);
		str = BString("Error: File not found.\r\n");
		send(str, str.len(), nsent);
		return err.set(1, "File not found");
	}	
	
	dprintf(DBG_HTTP, "%s: Send Header Response\n", __FUNCTION__);
	sendHeader(HTTP_OK, mimeType);

	if(mimeType == "text/html"){
		str = "";
		while(file.readString(s) > 0){
			str += s;
		}
		page.setTitle("TMS File");
		page.setContent(htmlStrip(str));
	
		str = page.render();
		send(str, str.len(), nsent);
	}
	else {
		dprintf(DBG_HTTP, "%s: SendFile\n", __FUNCTION__);
		while(1){
			char	buf[1024];
			int	n;
			BSize	nw;

			if((n = file.read(buf, 1024)) > 0)
				send(buf, n, nw);
			else
				break;
		}
	}
	
	return err;
}

BError HttpConnection::processInternal(BString url){
	BError			err;
	BHtmlPage		page;
	BHtml			h;
	BHtml			t;
	BHtml*			r;
	BString			str;
	BSize			nsent;
	BList<BString>		sl;
	BList<BString>		sl1;
	BString			urlBase;
	BNameValueList<BString>	args;
	BIter			i;
	
	dprintf(DBG_HTTP, "%s: Start\n", __FUNCTION__);

	createPage(page);
		
	sl = url.getTokenList("?");
	if(sl.number() >= 2){
		urlBase = sl[0];
		sl = sl[1].getTokenList("&");
		for(sl.start(i); !sl.isEnd(i); sl.next(i)){
			sl1 = sl[i].getTokenList("=");
			if(sl1.number() == 1){
				args.append(BNameValue<BString>("", sl1[0]));
			}
			else if(sl1.number() == 2){
				args.append(BNameValue<BString>(sl1[0], sl1[1]));
			}
		}
	}
	else {
		urlBase = url;
	}

#ifndef ZAP
	printf("Base: %s\n", urlBase.retStr());
	printf("Args: ");
	for(args.start(i); !args.isEnd(i); args.next(i)){
		printf("%s=%s,", args[i].getName().retStr(), args[i].getValue().retStr());
	}
	printf("\n");
#endif

	err = initTms();
		
	if((urlBase == "/") || (urlBase == "/index.html")){
		printf("DoIndex\n");
		page.setTitle("TMS Main");

		h = BHtml("div");
		h.append("h1", "", "TMS Web Interface");
		h.append("p", "", "This web interface provides information on the running TMS system ");
		h.appendText("and provides the ability to fetch data and diagnostics information from the system.");

		page.setContent(h.render());

		str = page.render();

		sendHeader(HTTP_OK, "text/html");
		send(str, str.len(), nsent);
	}
	else if(urlBase == "/config.cgi"){
		unsigned int	n;
		BIter		i;
		BError		e;
		ConfigInfo	configInfo;
		
		page.setTitle("TMS Configuration");

		if(e = otmsControl.getConfiguration(configInfo)){
			str = BString("TMS Access Error: ") + e.getString() + "\r\n";
			sendHeader(HTTP_SERVICE_UNAVAILABLE);
			send(str, str.len(), nsent);
		}
		else {
			t = BHtml("table", "border=1");
			r = t.append("tr");
			r->append("th", "", "Channel");
			r->append("th", "", "Module Number");
			r->append("th", "", "Pupe Number");
			r->append("th", "", "Pupe Channel");
			for(n = 0; n < configInfo.puReferences.size(); n++){
				r = t.append("tr");
				r->append("td", "", n + 1);
				r->append("td", "", configInfo.puReferences[n].moduleNum);
				r->append("td", "", configInfo.puReferences[n].pupeNum);
				r->append("td", "", configInfo.puReferences[n].pupeChan);
			}
		}

		page.setContent(t.render());	

		str = page.render();

		sendHeader(HTTP_OK, "text/html");
		send(str, str.len(), nsent);
	}
	else if(urlBase == "/status.cgi"){
		BIter			i;
		BError			e;
		BList<NameValue>	list;
		
		page.setTitle("TMS Status");

		if(e = otmsControl.getStatus(list)){
			str = BString("TMS Access Error: ") + e.getString() + "\r\n";
			sendHeader(HTTP_SERVICE_UNAVAILABLE);
			send(str, str.len(), nsent);
			return err.set(1, "HTTP_SERVICE_UNAVAILABLE");
		}
		else {
			t = BHtml("table", "border=1");
			for(list.start(i); !list.isEnd(i); list.next(i)){
				r = t.append("tr");
				r->append("td", "", list[i].name);
				r->append("td", "", list[i].value);
			}
		}

		page.setContent(t.render());	

		str = page.render();

		sendHeader(HTTP_OK, "text/html");
		send(str, str.len(), nsent);
	}
	else if(urlBase == "/statistics.cgi"){
		BIter			i;
		BError			e;
		BList<NameValue>	list;
		
		page.setTitle("TMS Statistics");

		if(e = otmsControl.getStatistics(list)){
			str = BString("TMS Access Error: ") + e.getString() + "\r\n";
			sendHeader(HTTP_SERVICE_UNAVAILABLE);
			send(str, str.len(), nsent);
			return err.set(1, "HTTP_SERVICE_UNAVAILABLE");
		}
		else {
			t = BHtml("table", "border=1");
			for(list.start(i); !list.isEnd(i); list.next(i)){
				r = t.append("tr");
				r->append("td", "", list[i].name);
				r->append("td", "", list[i].value);
			}
		}

		page.setContent(t.render());	

		str = page.render();

		sendHeader(HTTP_OK, "text/html");
		send(str, str.len(), nsent);
	}
	else if(urlBase == "/dataraw.cgi"){
		UInt32			i;
		BError			e;
		DataInfo		dataInfo;
		Data			data;
		UInt32			cn = 0;
		BString			ct;
		BString*		v;
		BString			outputType;

		// Set data require and wait for data
		if(e = otmsProcess.getCycleInfo(cn, ct)){
			str = BString("TMS Access Error: ") + e.getString() + "\r\n";
			sendHeader(HTTP_SERVICE_UNAVAILABLE);
			send(str, str.len(), nsent);
			return err.set(1, "HTTP_SERVICE_UNAVAILABLE");
		}

		dataInfo.cycleNumber	= cn;
		dataInfo.channel	= 1;
		dataInfo.cyclePeriod	= 0;
		dataInfo.startTime	= 0;
		dataInfo.orbitNumber	= 0;
		dataInfo.bunchNumber	= 0;
		dataInfo.numValues	= 0;
		dataInfo.beyondPeriod	= 0;
		dataInfo.function	= 0;
		dataInfo.argument	= 0;
		
		if(v = args.find("channel"))
			dataInfo.channel = v->retInt();
		if(v = args.find("cyclePeriod"))
			dataInfo.cyclePeriod = v->retInt();
		if(v = args.find("startTime"))
			dataInfo.startTime = v->retInt();
		if(v = args.find("orbitNumber"))
			dataInfo.orbitNumber = v->retInt();
		if(v = args.find("bunchNumber"))
			dataInfo.bunchNumber = v->retInt();
		if(v = args.find("numValues"))
			dataInfo.numValues = v->retInt();
		if(v = args.find("function"))
			dataInfo.function = v->retInt();
		if(v = args.find("argument"))
			dataInfo.argument = v->retInt();
		if(v = args.find("outputType"))
			outputType = *v;
		
		if(e = otmsProcess.getData(dataInfo, data)){
			str = BString("TMS Access Error: ") + e.getString() + "\r\n";
			sendHeader(HTTP_SERVICE_UNAVAILABLE);
			send(str, str.len(), nsent);
			return err.set(1, "HTTP_SERVICE_UNAVAILABLE");
		}
		else {
			str = "";
			for(i = 0; i < data.dataValues.size(); i++){
				str = str + data.dataValues[i].sigma + " " + data.dataValues[i].deltaX + " " + data.dataValues[i].deltaY + "\n";
			}
		}

		if(outputType == "Graph"){
			BFile	df("/tmp/data.txt", "w");
			BFile	hf(ohtmlDir + "/data.html", "r");
			BString	s;
			BString	hstr;
			
			df.writeString(str);
			df.close();
			
			plotData("/tmp/data.txt", 1, "Sigma", ohtmlDir + "/tmp/data0.png");
			plotData("/tmp/data.txt", 2, "DeltaX", ohtmlDir + "/tmp/data1.png");
			plotData("/tmp/data.txt", 3, "DeltaY", ohtmlDir + "/tmp/data2.png");

			while(hf.readString(s) > 0){
				hstr += s;
			}
			hstr = htmlStrip(hstr);

			t = BHtml("table", "border=1");
			r = t.append("tr");
			r->append("td")->append("img", "src='tmp/data0.png'");
			r = t.append("tr");
			r->append("td")->append("img", "src='tmp/data1.png'");
			r = t.append("tr");
			r->append("td")->append("img", "src='tmp/data2.png'");

			page.setTitle("TMS Data");
			page.setContent(t.render() + hstr);

			str = page.render();

			sendHeader(HTTP_OK, "text/html");
			send(str, str.len(), nsent);
		}
		else {
			sendHeader(HTTP_OK, "text/plain");
			send(str, str.len(), nsent);
		}
	}
	else if(urlBase == "/help.cgi"){
		page.setTitle("TMS Help");

		t = BHtml("div");
		t.append("li")->append("a", "href='/doc/index.html'", "Local Documentation");
		t.append("li")->append("a", "href='http://portal.beam.ltd.uk/support/cern'", "BEAM TMS Support");

		page.setContent(t.render());	

		str = page.render();

		sendHeader(HTTP_OK, "text/html");
		send(str, str.len(), nsent);
	}
	else {
		sendHeader(HTTP_NOT_FOUND);
		str = BString("Error: File not found.\r\n");
		send(str, str.len(), nsent);
		return err.set(1, "HTTP_NOT_FOUND");
	}

	return err;
}

BString HttpConnection::htmlStrip(BString str){
	const char*	s;
	const char*	e;
	int	start;
	int	num;
	
	s = strcasestr(str, "<body>");
	e = strcasestr(str, "</body>");
	
	if(s && e){
		start = s - str.retStr() + 6;
		num = e - str.retStr() - start;
		return str.subString(start, num);
	}
	else {
		return str;
	}
}

BError HttpConnection::plotData(BString dataFileName, int channel, BString name, BString outFileName){
	BError		err;
	BString		cmd;
	FILE*		f;
	
	cmd = BString("set term png picsize 640 150; set output '") + outFileName + "';";

	cmd = cmd + "set ylabel '" + name + "';";
	cmd = cmd + "plot '" + dataFileName + "' using " + channel + " with lines;";

//	printf("Cmd: %s\n", cmd.retStr());

	f = popen("gnuplot -", "w");
	fwrite(cmd, 1, cmd.len(), f);
	pclose(f);

	return err;
}


NetworkHttp::NetworkHttp(Control& control) :
	BSocket(STREAM),  ocontrol(control), orunThread(*this){
}

NetworkHttp::~NetworkHttp(){
	BIter	i;
	
	for(oconnections.start(i); !oconnections.isEnd(i); ){
		delete oconnections[i];
		oconnections.del(i);
	}
}
			
BError NetworkHttp::init(){
	BError			err;
	BSocketAddressINET	add;
	int			basePort = 80;
	BString			s;

	dprintf(DBG_HTTP, "%s: Starting\n", __FUNCTION__);

	if((s = ocontrol.oconfig.findValue("HttpPort:")) != "")
		basePort = s.retInt();

	// Create control socket
	setReuseAddress(1);

	// Connect up data socket
	add.set("", basePort);
	if(bind(add))
		return BError(BString("Unable to bind to socket: ") + basePort + " " + strerror(errno));

	listen();
	
	// Don't let the threads have these sockets
	fcntl(getFd(), F_SETFD, FD_CLOEXEC);

	orunThread.start();

	return err;
}

BError NetworkHttp::start(){
	BError	err;


	return err;
}

BError NetworkHttp::stop(){
	BError		err;
	

	return err;
}

BError NetworkHttp::run(){
	BError		err;
	BIter		i;
	BPoll		poll;
	int		fd;
	int		nfd;
	HttpConnection*	c;
	BSocketAddressINET	from;

	dprintf(DBG_HTTP, "%s: Thread Started\n", __FUNCTION__);
	
	poll.append(getFd());
	
	while(1){
		poll.doPoll(fd, 1000000);
		if(fd == getFd()){
			dprintf(DBG_HTTP, "%s: Accept connection\n", __FUNCTION__);
			accept(nfd, from);
			c = new HttpConnection(ocontrol, nfd, from);
			oconnections.append(c);
			c->start();
		}
	}
	
	return err;
}