+++ /dev/null
-.deps
-Makefile
-Makefile.in
+++ /dev/null
-INCLUDES = \
- -I$(top_srcdir)/include
-
-noinst_LIBRARIES = libenigma_network.a
-
-libenigma_network_a_SOURCES = \
- httpd.cpp http_dyn.cpp http_file.cpp http.cpp serversocket.cpp socket.cpp
-
-# xmlrpc.cpp
+++ /dev/null
-#include <lib/base/init_num.h>
-#include <lib/base/init.h>
-#include <lib/network/http.h>
-
-eHTTPServer *eHTTPServer::m_instance;
-
-RESULT eHTTPServer::getDynResolver(eHTTPDynPathResolverPtr &ptr)
-{
- ptr = m_dyn;
- if (!m_dyn)
- return -1;
- return 0;
-}
-
-RESULT eHTTPServer::getFileResolver(eHTTPFilePathResolverPtr &ptr)
-{
- ptr = m_file;
- if (!m_file)
- return -1;
- return 0;
-}
-
-eHTTPServer::eHTTPServer(): m_httpd(8080, eApp)
-{
- m_instance = this;
- m_dyn = new eHTTPDynPathResolver();
- m_file = new eHTTPFilePathResolver();
-
- m_httpd.addResolver(m_dyn);
- m_httpd.addResolver(m_file);
-}
-
-eAutoInitP0<eHTTPServer> init_eHTTPServer(eAutoInitNumbers::network, "main http server");
+++ /dev/null
-#ifndef __http_h
-#define __http_h
-
-#include <lib/network/httpd.h>
-#include <lib/network/http_file.h>
-#include <lib/network/http_dyn.h>
-
-class eHTTPDynPathResolver;
-class eHTTPFilePathResolver;
-
-typedef ePtr<eHTTPDynPathResolver> eHTTPDynPathResolverPtr;
-typedef ePtr<eHTTPFilePathResolver> eHTTPFilePathResolverPtr;
-
-class eHTTPServer
-{
- eHTTPD m_httpd;
- static eHTTPServer *m_instance;
- eHTTPDynPathResolverPtr m_dyn;
- eHTTPFilePathResolverPtr m_file;
-public:
- RESULT getDynResolver(eHTTPDynPathResolverPtr &ptr);
- RESULT getFileResolver(eHTTPFilePathResolverPtr &ptr);
-
- eHTTPServer();
- static eHTTPServer *getInstance() { return m_instance; }
-};
-
-#endif
+++ /dev/null
-#include <lib/network/http_dyn.h>
-
-DEFINE_REF(eHTTPDyn);
-eHTTPDyn::eHTTPDyn(eHTTPConnection *c, std::string result): eHTTPDataSource(c), result(result)
-{
- wptr=0;
- char buffer[10];
- snprintf(buffer, 10, "%d", size=result.length());
- c->local_header["Content-Length"]=std::string(buffer);
- if (c->code == -1)
- {
- c->code=200;
- c->code_descr="OK";
- }
-}
-
-eHTTPDyn::~eHTTPDyn()
-{
-}
-
-int eHTTPDyn::doWrite(int hm)
-{
- int tw=size-wptr;
- if (tw>hm)
- tw=hm;
- if (tw<=0)
- return -1;
- connection->writeBlock(result.c_str()+wptr, tw);
- wptr+=tw;
- return (size > wptr) ? 1 : -1;
-}
-
-DEFINE_REF(eHTTPDynPathResolver);
-DEFINE_REF(eHTTPDynPathResolver::eHTTPDynEntry);
-
-eHTTPDynPathResolver::eHTTPDynPathResolver()
-{
-}
-
-void eHTTPDynPathResolver::addDyn(std::string request, std::string path, std::string (*function)(std::string, std::string, std::string, eHTTPConnection*))
-{
- dyn.push_back(new eHTTPDynEntry(request, path, function));
-}
-
-RESULT eHTTPDynPathResolver::getDataSource(eHTTPDataSourcePtr &ptr, std::string request, std::string path, eHTTPConnection *conn)
-{
- std::string p, opt;
- if (path.find('?')!=std::string::npos)
- {
- p=path.substr(0, path.find('?'));
- opt=path.substr(path.find('?')+1);
- } else
- {
- p=path;
- opt="";
- }
- for (eSmartPtrList<eHTTPDynEntry>::iterator i(dyn); i != dyn.end(); ++i)
- if ((i->path==p) && (i->request==request))
- {
- conn->code=-1;
- std::string s=i->function(request, path, opt, conn);
-
- if (!s.empty())
- {
- ptr = new eHTTPDyn(conn, s);
- return 0;
- }
-
- ptr = new eHTTPError(conn, 500);
- return 0;
- }
- ptr = 0;
- return -1;
-}
+++ /dev/null
-#ifndef __http_dyn_h_
-#define __http_dyn_h_
-#include <string>
-#include <lib/network/httpd.h>
-
-class eHTTPDyn: public eHTTPDataSource
-{
- DECLARE_REF(eHTTPDyn);
- std::string result;
- int wptr, size;
-public:
- eHTTPDyn(eHTTPConnection *c, std::string result);
- ~eHTTPDyn();
- int doWrite(int);
-};
-
-class eHTTPDynPathResolver: public iHTTPPathResolver
-{
- DECLARE_REF(eHTTPDynPathResolver);
- struct eHTTPDynEntry: public iObject
- {
- DECLARE_REF(eHTTPDynEntry);
- public:
- std::string request, path;
- std::string (*function)(std::string request, std::string path, std::string opt, eHTTPConnection *content);
-
- eHTTPDynEntry(std::string request, std::string path, std::string (*function)(std::string, std::string, std::string, eHTTPConnection *)): request(request), path(path), function(function)
- {
- }
- };
- eSmartPtrList<eHTTPDynEntry> dyn;
-public:
- void addDyn(std::string request, std::string path, std::string (*function)(std::string, std::string, std::string, eHTTPConnection *conn));
- eHTTPDynPathResolver();
- RESULT getDataSource(eHTTPDataSourcePtr &ptr, std::string request, std::string path, eHTTPConnection *conn);
-};
-
-#endif
+++ /dev/null
-#include <lib/network/http_file.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string>
-#include <shadow.h>
-#include <pwd.h>
-
-DEFINE_REF(eHTTPFile);
-
-eHTTPFile::eHTTPFile(eHTTPConnection *c, int _fd, int method, const char *mime): eHTTPDataSource(c), method(method)
-{
- fd=_fd;
- if (method == methodGET)
- {
- c->local_header["Content-Type"]=std::string(mime);
- size=lseek(fd, 0, SEEK_END);
- char asize[10];
- snprintf(asize, 10, "%d", size);
- lseek(fd, 0, SEEK_SET);
- c->local_header["Content-Length"]=std::string(asize);
- }
- connection->code_descr="OK";
- connection->code=200;
-}
-
-int eHTTPFile::doWrite(int bytes)
-{
- if (method == methodGET)
- {
- char buff[bytes];
- if (!size)
- return -1;
- int len=bytes;
- if (len>size)
- len=size;
- len=read(fd, buff, len);
- if (len<=0)
- return -1;
- size-=connection->writeBlock(buff, len);
- if (!size)
- return -1;
- else
- return 1;
- } else
- return -1;
-}
-
-void eHTTPFile::haveData(void *data, int len)
-{
- if (method != methodPUT)
- return;
- ::write(fd, data, len);
-}
-
-eHTTPFile::~eHTTPFile()
-{
- close(fd);
-}
-
-eHTTPFilePathResolver::eHTTPFilePathResolver()
-{
-}
-
-
-static char _base64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-
-static int unbase64(std::string &dst, const std::string string)
-{
- dst="";
- char c[4];
- int pos=0;
- unsigned int i=0;
-
- while (1)
- {
- if (i == string.size())
- break;
- char *ch=strchr(_base64, string[i++]);
- if (!ch)
- {
- i++;
- continue;
- }
- c[pos++]=ch-_base64;
- if (pos == 4)
- {
- char d[3];
- d[0]=c[0]<<2;
- d[0]|=c[1]>>4;
- d[1]=c[1]<<4;
- d[1]|=c[2]>>2;
- d[2]=c[2]<<6;
- d[2]|=c[3];
-
- dst+=d[0];
- if (c[2] != 64)
- dst+=d[1];
- if (c[3] != 64)
- dst+=d[2];
- pos=0;
- }
- }
- return pos;
-}
-
-int CheckUnixPassword(const char *user, const char *pass)
-{
- passwd *pwd=getpwnam(user);
- if (!pwd)
- return -1;
- char *cpwd=pwd->pw_passwd;
- if (pwd && (!strcmp(pwd->pw_passwd, "x")))
- {
- spwd *sp=getspnam(user);
- if (!sp) // no shadow password defined.
- return -1;
- cpwd=sp->sp_pwdp;
- }
- if (!cpwd)
- return -1;
- if ((*cpwd=='!')||(*cpwd=='*')) // disabled user
- return -2;
- char *cres=crypt(pass, cpwd);
- return !!strcmp(cres, cpwd);
-}
-
-static int checkAuth(const std::string cauth)
-{
- std::string auth;
- if (cauth.substr(0, 6) != "Basic ")
- return -1;
- if (unbase64(auth, cauth.substr(6)))
- return -1;
- std::string username=auth.substr(0, auth.find(":"));
- std::string password=auth.substr(auth.find(":")+1);
- if (CheckUnixPassword(username.c_str(), password.c_str()))
- return -1;
- return 0;
-}
-
-DEFINE_REF(eHTTPFilePathResolver);
-
-RESULT eHTTPFilePathResolver::getDataSource(eHTTPDataSourcePtr &ptr, std::string request, std::string path, eHTTPConnection *conn)
-{
- int method;
- eDebug("request = %s, path = %s", request.c_str(), path.c_str());
- if (request == "GET")
- method=eHTTPFile::methodGET;
- else if (request == "PUT")
- method=eHTTPFile::methodPUT;
- else
- {
- ptr = new eHTTPError(conn, 405); // method not allowed
- return 0;
- }
- if (path.find("../")!=std::string::npos) // evil hax0r
- {
- ptr = new eHTTPError(conn, 403);
- return 0;
- }
- if (path[0] != '/') // prepend '/'
- path.insert(0,"/");
- if (path[path.length()-1]=='/')
- path+="index.html";
-
- eHTTPDataSource *data=0;
- for (ePtrList<eHTTPFilePath>::iterator i(translate); i != translate.end(); ++i)
- {
- if (i->root==path.substr(0, i->root.length()))
- {
- std::string newpath=i->path+path.substr(i->root.length());
- if (newpath.find('?'))
- newpath=newpath.substr(0, newpath.find('?'));
- eDebug("translated %s to %s", path.c_str(), newpath.c_str());
-
- if (i->authorized & ((method==eHTTPFile::methodGET)?1:2))
- {
- std::map<std::string, std::string>::iterator i=conn->remote_header.find("Authorization");
- if ((i == conn->remote_header.end()) || checkAuth(i->second))
- {
- conn->local_header["WWW-Authenticate"]="Basic realm=\"dreambox\"";
- ptr = new eHTTPError(conn, 401); // auth req'ed
- return 0;
- }
- }
-
- int fd=open(newpath.c_str(), (method==eHTTPFile::methodGET)?O_RDONLY:(O_WRONLY|O_CREAT|O_TRUNC), 0644);
-
- if (fd==-1)
- {
- switch (errno)
- {
- case ENOENT:
- data=new eHTTPError(conn, 404);
- break;
- case EACCES:
- data=new eHTTPError(conn, 403);
- break;
- default:
- data=new eHTTPError(conn, 403); // k.a.
- break;
- }
- break;
- }
-
- std::string ext=path.substr(path.rfind('.'));
- const char *mime="text/unknown";
- if ((ext==".html") || (ext==".htm"))
- mime="text/html";
- else if ((ext==".jpeg") || (ext==".jpg"))
- mime="image/jpeg";
- else if (ext==".gif")
- mime="image/gif";
- else if (ext==".css")
- mime="text/css";
- else if (ext==".png")
- mime="image/png";
- else if (ext==".xml")
- mime="text/xml";
- else if (ext==".xsl")
- mime="text/xsl";
-
- data=new eHTTPFile(conn, fd, method, mime);
- break;
- }
- }
- if (!data)
- return -1;
- ptr = data;
- return 0;
-}
-
-void eHTTPFilePathResolver::addTranslation(std::string path, std::string root, int authorized)
-{
- if (path[path.length()-1]!='/')
- path+='/';
- if (root[root.length()-1]!='/')
- root+='/';
- translate.push_back(new eHTTPFilePath(path, root, authorized));
-}
+++ /dev/null
-#ifndef __http_file_h
-#define __http_file_h
-
-#include "httpd.h"
-
-class eHTTPFile: public eHTTPDataSource
-{
- DECLARE_REF(eHTTPFile);
-private:
- int fd, size;
- const char *mime;
- int method;
-public:
- enum { methodGET, methodPUT };
- eHTTPFile(eHTTPConnection *c, int fd, int method, const char *mime);
- ~eHTTPFile();
- int doWrite(int);
- void haveData(void *data, int len);
-};
-
-class eHTTPFilePathResolver: public iHTTPPathResolver
-{
- DECLARE_REF(eHTTPFilePathResolver);
-public:
- struct eHTTPFilePath
- {
- std::string path;
- std::string root;
- int authorized; // must be authorized (1 means read, 2 write)
- eHTTPFilePath(std::string path, std::string root, int authorized): path(path), root(root), authorized(authorized)
- {
- }
- };
- ePtrList<eHTTPFilePath> translate;
-public:
- eHTTPFilePathResolver();
- RESULT getDataSource(eHTTPDataSourcePtr &ptr, std::string request, std::string path, eHTTPConnection *conn);
- void addTranslation(std::string path, std::string root, int auth);
-};
-
-#endif
+++ /dev/null
-// #define DEBUG_HTTPD
-#include <lib/network/httpd.h>
-
-#include <sys/socket.h>
-#include <lib/base/smartptr.h>
-#include <lib/base/estring.h>
-#include <error.h>
-#include <errno.h>
-#include <time.h>
-#include <ctype.h>
-
-#include <lib/network/http_dyn.h>
-#include <lib/network/http_file.h>
-
-eHTTPDataSource::eHTTPDataSource(eHTTPConnection *c): connection(c)
-{
-}
-
-eHTTPDataSource::~eHTTPDataSource()
-{
-}
-
-void eHTTPDataSource::haveData(void *data, int len)
-{
-}
-
-int eHTTPDataSource::doWrite(int)
-{
- return 0;
-}
-
-DEFINE_REF(eHTTPError);
-
-eHTTPError::eHTTPError(eHTTPConnection *c, int errcode): eHTTPDataSource(c), errcode(errcode)
-{
- std::string error="unknown error";
- switch (errcode)
- {
- case 400: error="Bad Request"; break;
- case 401: error="Unauthorized"; break;
- case 403: error="Forbidden"; break;
- case 404: error="Not found"; break;
- case 405: error="Method not allowed"; break;
- case 500: error="Internal server error"; break;
- }
- connection->code_descr=error;
- connection->code=errcode;
-
- connection->local_header["Content-Type"]=std::string("text/html");
-}
-
-int eHTTPError::doWrite(int w)
-{
- std::string html;
- html+="<html><head><title>Error " + getNum(connection->code) + "</title></head>"+
- "<body><h1>Error " + getNum(errcode) + ": " + connection->code_descr + "</h1></body></html>\n";
- connection->writeBlock(html.c_str(), html.length());
- return -1;
-}
-
-eHTTPConnection::eHTTPConnection(int socket, int issocket, eHTTPD *parent, int persistent): eSocket(socket, issocket, parent->ml), parent(parent), persistent(persistent)
-{
-#ifdef DEBUG_HTTPD
- eDebug("eHTTPConnection");
-#endif
- CONNECT(this->readyRead_ , eHTTPConnection::readData);
- CONNECT(this->bytesWritten_ , eHTTPConnection::bytesWritten);
- CONNECT(this->error_ , eHTTPConnection::gotError);
- CONNECT(this->connectionClosed_ , eHTTPConnection::destruct);
- CONNECT(this->hangup , eHTTPConnection::gotHangup);
-
- buffersize=128*1024;
- localstate=stateWait;
- remotestate=stateRequest;
- data=0;
-}
-
-void eHTTPConnection::destruct()
-{
- eDebug("destruct, this %p!", this);
- gotHangup();
- delete this;
-}
-
-eHTTPConnection::eHTTPConnection(eMainloop *ml): eSocket(ml), parent(0), persistent(0)
-{
- CONNECT(this->readyRead_ , eHTTPConnection::readData);
- CONNECT(this->bytesWritten_ , eHTTPConnection::bytesWritten);
- CONNECT(this->error_ , eHTTPConnection::gotError);
- CONNECT(this->connected_ , eHTTPConnection::hostConnected);
- CONNECT(this->connectionClosed_ , eHTTPConnection::destruct);
-
- localstate=stateWait;
- remotestate=stateWait;
-
- buffersize=64*1024;
- data=0;
-}
-
-void eHTTPConnection::hostConnected()
-{
- processLocalState();
-}
-
-void eHTTPConnection::start()
-{
- if (localstate==stateWait)
- {
- localstate=stateRequest;
- processLocalState();
- }
-}
-
-void eHTTPConnection::gotHangup()
-{
- if (data && remotestate == stateData)
- data->haveData(0, 0);
- data = 0;
- transferDone(0);
-
- localstate=stateWait;
- remotestate=stateRequest;
-
- remote_header.clear();
- local_header.clear();
-}
-
-eHTTPConnection *eHTTPConnection::doRequest(const char *uri, eMainloop *ml, int *error)
-{
- if (error)
- *error=0;
-
- char *defaultproto="http";
- std::string proto, host, path;
- int port=80;
-
- int state=0; // 0 proto, 1 host, 2 port 3 path
-
- while (*uri)
- {
- switch (state)
- {
- case 0:
- if (!strncmp(uri, "://", 3))
- {
- state=1;
- uri+=3;
- } else if ((*uri=='/') || (*uri==':'))
- {
- host=proto;
- state=1;
- proto=defaultproto;
- } else
- proto.push_back(*uri++);
- break;
- case 1:
- if (*uri=='/')
- state=3;
- else if (*uri==':')
- {
- state=2;
- port=0;
- uri++;
- } else
- host.push_back(*uri++);
- break;
- case 2:
- if (*uri=='/')
- state=3;
- else
- {
- if (!isdigit(*uri))
- {
- port=-1;
- state=3;
- } else
- {
- port*=10;
- port+=*uri++-'0';
- }
- }
- break;
- case 3:
- path.push_back(*uri++);
- }
- }
-
- if (state==0)
- {
- path=proto;
- proto=defaultproto;
- }
-
-#ifdef DEBUG_HTTPD
- eDebug("proto: '%s', host '%s', path '%s', port '%d'", proto.c_str(), host.c_str(), path.c_str(), port);
-#endif
-
- if (!host.size())
- {
- eDebug("no host given");
- if (error)
- *error=ENOENT;
- return 0;
- }
-
- if (strcmp(proto.c_str(), "http"))
- {
- eDebug("invalid protocol (%s)", proto.c_str());
- if (error)
- *error=EINVAL;
- return 0;
- }
-
- if (port == -1)
- {
- eDebug("invalid port");
- if (error)
- *error=EINVAL;
- return 0;
- }
-
- if (!path.size())
- path="/";
-
- eHTTPConnection *c=new eHTTPConnection(ml);
- c->request="GET";
- c->requestpath=path.c_str();
- c->httpversion="HTTP/1.0";
- c->local_header["Host"]=host;
- if ((*error=c->connectToHost(host, port))) // already deleted by error
- return 0;
- return c;
-}
-
-void eHTTPConnection::readData()
-{
- processRemoteState();
-}
-
-void eHTTPConnection::bytesWritten(int)
-{
- processLocalState();
-}
-
-int eHTTPConnection::processLocalState()
-{
- switch (state())
- {
- case Connection:
- break;
- default:
- return 0;
- }
- int done=0;
- while (!done)
- {
-#ifdef DEBUG_HTTPD
- eDebug("processing local state %d", localstate);
-#endif
- switch (localstate)
- {
- case stateWait:
-#ifdef DEBUG_HTTPD
- eDebug("local wait");
-#endif
- done=1;
- break;
- case stateRequest:
- {
-#ifdef DEBUG_HTTPD
- eDebug("local request");
-#endif
- std::string req=request+" "+requestpath+" "+httpversion+"\r\n";
- writeBlock(req.c_str(), req.length());
- localstate=stateHeader;
- remotestate=stateResponse;
- break;
- }
- case stateResponse:
- {
-#ifdef DEBUG_HTTPD
- eDebug("local Response");
-#endif
- writeString( (httpversion + " " + getNum(code) + " " + code_descr + "\r\n").c_str() );
- localstate=stateHeader;
- local_header["Connection"]="close";
- break;
- }
- case stateHeader:
-#ifdef DEBUG_HTTPD
- eDebug("local header");
-#endif
- for (std::map<std::string,std::string>::iterator cur=local_header.begin(); cur!=local_header.end(); ++cur)
- {
- writeString(cur->first.c_str());
- writeString(": ");
- writeString(cur->second.c_str());
- writeString("\r\n");
- }
- writeString("\r\n");
- if (request=="HEAD")
- localstate=stateDone;
- else
- localstate=stateData;
- break;
- case stateData:
-#ifdef DEBUG_HTTPD
- eDebug("local data");
-#endif
- if (data)
- {
- int btw=buffersize-bytesToWrite();
- if (btw>0)
- {
- if (data->doWrite(btw)<0)
- {
- localstate=stateDone;
- } else
- done=1;
- } else
- done=1;
- } else
- done=1; // wait for remote response
- break;
- case stateDone:
-#if 0
- // move to stateClose
- if (remote_header.find("Connection") != remote_header.end())
- {
- std::string &connection=remote_header["Connection"];
- if (connection == "keep-alive")
- localstate=stateWait;
- else
- localstate=stateClose;
- }
-#endif
-#ifdef DEBUG_HTTPD
- eDebug("locate state done");
-#endif
- if (!persistent)
- localstate=stateClose;
- else
- localstate=stateWait;
- break;
- case stateClose:
-#ifdef DEBUG_HTTPD
- eDebug("closedown");
-#endif
- if (persistent)
- {
- data = 0;
- localstate = stateWait;
- } else
- close(); // bye, bye, remote
- return 1;
- }
- }
-#ifdef DEBUG_HTTPD
- eDebug("end local");
-#endif
- return 0;
-}
-
-int eHTTPConnection::processRemoteState()
-{
- int abort=0, done=0;
-#ifdef DEBUG_HTTPD
- eDebug("%d bytes avail", bytesAvailable());
-#endif
- while (((!done) || bytesAvailable()) && !abort)
- {
- switch (remotestate)
- {
- case stateWait:
- {
- int i=0;
-#ifdef DEBUG_HTTPD
- eDebug("remote stateWait");
-#endif
- char buffer[1024];
- while (bytesAvailable()) {
- i=readBlock(buffer, 1024);
- }
- done=1;
- break;
- }
- case stateRequest:
- {
-#ifdef DEBUG_HTTPD
- eDebug("stateRequest");
-#endif
- std::string line;
- if (!getLine(line))
- {
- done=1;
- abort=1;
- break;
- }
-
- int del[2];
- del[0]=line.find(" ");
- del[1]=line.find(" ", del[0]+1);
- if (del[0]==-1)
- {
- data = 0;
- eDebug("request buggy");
- httpversion="HTTP/1.0";
- data=new eHTTPError(this, 400);
- done=0;
- localstate=stateResponse;
- remotestate=stateDone;
- if (processLocalState())
- return -1;
- break;
- }
- request=line.substr(0, del[0]);
- requestpath=line.substr(del[0]+1, (del[1]==-1)?-1:(del[1]-del[0]-1));
- if (del[1]!=-1)
- {
- is09=0;
- httpversion=line.substr(del[1]+1);
- } else
- is09=1;
-
- if (is09 || (httpversion.substr(0, 7) != "HTTP/1.") || httpversion.size()!=8)
- {
- remotestate=stateData;
- done=0;
- httpversion="HTTP/1.0";
- content_length_remaining=content_length_remaining=0;
- data=new eHTTPError(this, 400); // bad request - not supporting version 0.9 yet
- } else
- remotestate=stateHeader;
- break;
- }
- case stateResponse:
- {
-#ifdef DEBUG_HTTPD
- eDebug("state response..");
-#endif
- std::string line;
- if (!getLine(line))
- {
- done=1;
- abort=1;
- break;
- }
-#ifdef DEBUG_HTTPD
- eDebug("line: %s", line.c_str());
-#endif
- int del[2];
- del[0]=line.find(" ");
- del[1]=line.find(" ", del[0]+1);
- if (del[0]==-1)
- code=-1;
- else
- {
- httpversion=line.substr(0, del[0]);
- code=atoi(line.substr(del[0]+1, (del[1]==-1)?-1:(del[1]-del[0]-1)).c_str());
- if (del[1] != -1)
- code_descr=line.substr(del[1]+1);
- else
- code_descr="";
- }
-
- remotestate=stateHeader;
- break;
- }
- case stateHeader:
- {
-#ifdef DEBUG_HTTPD
- eDebug("remote stateHeader");
-#endif
- std::string line;
- if (!getLine(line))
- {
- done=1;
- abort=1;
- break;
- }
- if (!line.length())
- {
- content_length=0;
- content_length_remaining=-1;
- if (remote_header.count("Content-Length"))
- {
- content_length=atoi(remote_header["Content-Length"].c_str());
- content_length_remaining=content_length;
- }
-
- if (parent)
- {
- for (eSmartPtrList<iHTTPPathResolver>::iterator i(parent->resolver); i != parent->resolver.end(); ++i)
- if (!(i->getDataSource(data, request, requestpath, this)))
- break;
- localstate=stateResponse; // can be overridden by dataSource
- } else
- data=createDataSource(this);
-
- if (!data)
- {
- data = 0;
- data = new eHTTPError(this, 404);
- }
-
- if (content_length || // if content-length is set, we have content
- remote_header.count("Content-Type") || // content-type - the same
- (localstate != stateResponse)) // however, if we are NOT in response-state, so we are NOT server, there's ALWAYS more data to come. (exception: http/1.1 persistent)
- remotestate=stateData;
- else
- {
- data->haveData(0, 0);
- remotestate=stateDone;
- }
- if (processLocalState())
- return -1;
- } else
- {
- int del=line.find(":");
- std::string name=line.substr(0, del), value=line.substr(del+1);
- if (value[0]==' ')
- value=value.substr(1);
- remote_header[std::string(name)]=std::string(value);
- }
- done=1;
- break;
- }
- case stateData:
- {
-#ifdef DEBUG_HTTPD
- eDebug("remote stateData");
-#endif
- ASSERT(data);
- char buffer[16284];
- int len;
- while (bytesAvailable())
- {
- int tr=sizeof(buffer);
- if (content_length_remaining != -1)
- if (tr>content_length_remaining)
- tr=content_length_remaining;
- len=readBlock(buffer, tr);
- data->haveData(buffer, len);
- if (content_length_remaining != -1)
- content_length_remaining-=len;
- if (!content_length_remaining)
- {
- data->haveData(0, 0);
- remotestate=stateDone;
- break;
- }
- }
- done=1;
- if (processLocalState())
- return -1;
- break;
- }
- case stateDone:
- remotestate=stateClose;
- break;
- case stateClose:
-// if (!persistent)
- remotestate=stateWait;
-// else
-// remotestate=stateRequest;
- abort=1;
- break;
- default:
- eDebug("HTTP: invalid state %d", remotestate);
- done=1;
- }
- }
-#ifdef DEBUG_HTTPD
- eDebug("end remote");
-#endif
- return 0;
-}
-
-void eHTTPConnection::writeString(const char *data)
-{
- writeBlock(data, strlen(data));
-}
-
-int eHTTPConnection::getLine(std::string &line)
-{
- if (!canReadLine())
- return 0;
-
- line = readLine();
- line.erase(line.length()-1);
-
- if (line[(line.length()-1)] == '\r')
- line.erase(line.length()-1);
-
- return 1;
-}
-
-void eHTTPConnection::gotError(int err)
-{
- data = 0;
- transferDone(err);
- delete this;
-}
-
-eHTTPD::eHTTPD(int port, eMainloop *ml): eServerSocket(port, ml), ml(ml)
-{
- if (!ok())
- eDebug("[NET] httpd server FAILED on port %d", port);
- else
- eDebug("[NET] httpd server started on port %d", port);
-}
-
-eHTTPConnection::~eHTTPConnection()
-{
- eDebug("HTTP connection destruct");
- if ((!persistent) && (state()!=Idle))
- eWarning("~eHTTPConnection, status still %d", state());
-}
-
-void eHTTPD::newConnection(int socket)
-{
- new eHTTPConnection(socket, 1, this);
-}
+++ /dev/null
-#ifndef __httpd_h
-#define __httpd_h
-
-#include <asm/types.h>
-#include <map>
-
-#include <lib/base/object.h>
-#include <lib/base/eptrlist.h>
-#include <lib/base/ebase.h>
-#include <string>
-#include <lib/base/eerror.h>
-#include <lib/network/socket.h>
-#include <lib/network/serversocket.h>
-
-class eHTTPConnection;
-class eHTTPDataSource;
-class eHTTPD;
-
-class eHTTPDataSource;
-typedef ePtr<eHTTPDataSource> eHTTPDataSourcePtr;
-
-class iHTTPPathResolver: public iObject
-{
-public:
- virtual ~iHTTPPathResolver() {};
- virtual RESULT getDataSource(eHTTPDataSourcePtr &source, std::string request, std::string path, eHTTPConnection *conn)=0;
-};
-
-class eHTTPDataSource: public iObject
-{
-protected:
- eHTTPConnection *connection;
-public:
- eHTTPDataSource(eHTTPConnection *c);
- virtual ~eHTTPDataSource();
- virtual void haveData(void *data, int len);
- virtual int doWrite(int bytes); // number of written bytes, -1 for "no more"
-};
-
-typedef ePtr<eHTTPDataSource> eHTTPDataSourcePtr;
-
-class eHTTPError: public eHTTPDataSource
-{
- DECLARE_REF(eHTTPError);
- int errcode;
-public:
- eHTTPError(eHTTPConnection *c, int errcode);
- ~eHTTPError() { }
- void haveData();
- int doWrite(int bytes);
-};
-
-class eHTTPConnection: public eSocket
-{
- void doError(int error);
-
- int getLine(std::string &line);
-
- int processLocalState();
- int processRemoteState();
- void writeString(const char *data);
-
- eHTTPDataSourcePtr data;
- eHTTPD *parent;
-
- int buffersize;
-private:
- void readData();
- void gotError(int);
- void bytesWritten(int);
- void hostConnected();
- void destruct();
-public:
- Signal1<void,int> transferDone;
- Signal1<eHTTPDataSource*,eHTTPConnection*> createDataSource;
- enum
- {
- /*
-
- < GET / HTTP/1.0
- < If-modified-since: bla
- <
- < Data
- > 200 OK HTTP/1.0
- > Content-Type: text/html
- >
- > Data
- */
-
- stateWait, stateRequest, stateResponse, stateHeader, stateData, stateDone, stateClose
- };
- int localstate, remotestate;
- int persistent;
-
- eHTTPConnection(int socket, int issocket, eHTTPD *parent, int persistent=0);
- eHTTPConnection(eMainloop *ml); // ready to do "connectToHost"
- static eHTTPConnection *doRequest(const char *uri, eMainloop *ml, int *error=0);
- void start();
- void gotHangup();
- ~eHTTPConnection();
-
- // stateRequest
- std::string request, requestpath, httpversion;
- int is09;
-
- // stateResponse
-
- int code;
- std::string code_descr;
-
- std::map<std::string,std::string> remote_header, local_header;
-
- // stateData
- int content_length, content_length_remaining;
-};
-
-class eHTTPD: public eServerSocket
-{
- friend class eHTTPConnection;
- eSmartPtrList<iHTTPPathResolver> resolver;
- eMainloop *ml;
-public:
- eHTTPD(int port, eMainloop *ml);
- void newConnection(int socket);
-
- void addResolver(iHTTPPathResolver *r) { resolver.push_back(r); }
- void removeResolver(iHTTPPathResolver *r) { resolver.remove(r); }
-};
-
-#endif
+++ /dev/null
-#include <lib/network/serversocket.h>
-
-bool eServerSocket::ok()
-{
- return okflag;
-}
-
-void eServerSocket::notifier(int)
-{
- int clientfd, clientlen;
- struct sockaddr_in client_addr;
-
- eDebug("[SERVERSOCKET] incoming connection!");
-
- clientlen=sizeof(client_addr);
- clientfd=accept(getDescriptor(),
- (struct sockaddr *) &client_addr,
- (socklen_t*)&clientlen);
- if(clientfd<0)
- eDebug("[SERVERSOCKET] error on accept()");
-
- newConnection(clientfd);
-}
-
-eServerSocket::eServerSocket(int port, eMainloop *ml): eSocket(ml)
-{
- struct sockaddr_in serv_addr;
-
- serv_addr.sin_family=AF_INET;
- serv_addr.sin_addr.s_addr=INADDR_ANY;
- serv_addr.sin_port=htons(port);
-
- okflag=1;
- int val=1;
-
- setsockopt(getDescriptor(), SOL_SOCKET, SO_REUSEADDR, &val, 4);
-
- if(bind(getDescriptor(),
- (struct sockaddr *) &serv_addr,
- sizeof(serv_addr))<0)
- {
- eDebug("[SERVERSOCKET] ERROR on bind() (%m)");
- okflag=0;
- }
- listen(getDescriptor(), 0);
-
- rsn->setRequested(eSocketNotifier::Read);
-}
-
-eServerSocket::~eServerSocket()
-{
-#if 0
- eDebug("[SERVERSOCKET] destructed");
-#endif
-}
+++ /dev/null
-#ifndef __serversocket_h
-#define __serversocket_h
-
-#include "socket.h"
-
-class eServerSocket: public eSocket
-{
- void notifier(int handle);
- int okflag;
-protected:
- virtual void newConnection(int socket)=0;
-public:
- eServerSocket(int port, eMainloop *ml);
- virtual ~eServerSocket();
- bool ok();
-};
-
-#endif /* __serversocket_h */
+++ /dev/null
-#include <sys/ioctl.h>
-#include <asm/ioctls.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <lib/network/socket.h>
-
-void eSocket::close()
-{
- if (writebuffer.empty())
- {
- int wasconnected=(mystate==Connection) || (mystate==Closing);
- rsn=0;
- ::close(socketdesc);
- socketdesc=-1;
- mystate=Idle;
- if (wasconnected)
- connectionClosed_();
- } else
- {
- mystate=Closing;
- rsn->setRequested(rsn->getRequested()|eSocketNotifier::Write);
- }
-}
-
-void eSocket::enableRead()
-{
- if (rsn)
- rsn->setRequested(rsn->getRequested()|eSocketNotifier::Read);
-}
-
-void eSocket::disableRead()
-{
- if (rsn)
- rsn->setRequested(rsn->getRequested()&~eSocketNotifier::Read);
-}
-
-void eSocket::inject(const char *data, int len)
-{
- readbuffer.write(data, len);
- if (mystate == Connection)
- readyRead_();
-}
-
-std::string eSocket::readLine()
-{
- int size=readbuffer.searchchr('\n');
- if (size == -1)
- return std::string();
- size++; // ich will auch das \n
- char buffer[size+1];
- buffer[size]=0;
- readbuffer.read(buffer, size);
- return std::string(buffer);
-}
-
-bool eSocket::canReadLine()
-{
- return readbuffer.searchchr('\n') != -1;
-}
-
-int eSocket::bytesAvailable()
-{
- return readbuffer.size();
-}
-
-int eSocket::readBlock(char *data, unsigned int maxlen)
-{
- return readbuffer.read(data, maxlen);
-}
-
-int eSocket::bytesToWrite()
-{
- return writebuffer.size();
-}
-
-int eSocket::state()
-{
- return mystate;
-}
-
-int eSocket::setSocket(int s, int iss, eMainloop *ml)
-{
- socketdesc=s;
- issocket=iss;
- fcntl(socketdesc, F_SETFL, O_NONBLOCK);
- last_break = 0xFFFFFFFF;
-
- rsn = 0;
- rsn=eSocketNotifier::create(ml, getDescriptor(),
- eSocketNotifier::Read|eSocketNotifier::Hungup);
- CONNECT(rsn->activated, eSocket::notifier);
- return 0;
-}
-
-void eSocket::notifier(int what)
-{
- if ((what & eSocketNotifier::Read) && (mystate == Connection))
- {
- int bytesavail=256;
- if (issocket)
- if (ioctl(getDescriptor(), FIONREAD, &bytesavail)<0)
- eDebug("FIONREAD failed.\n");
-
- {
- if (issocket)
- {
- if (!bytesavail) // does the REMOTE END has closed the connection? (no Hungup here!)
- {
- writebuffer.clear();
- close();
- return;
- }
- } else // when operating on terminals, check for break
- {
- // where is this struct defined?
- struct async_icount {
- unsigned long cts, dsr, rng, dcd, tx, rx;
- unsigned long frame, parity, overrun, brk;
- unsigned long buf_overrun;
- } icount;
-
- if (!ioctl(getDescriptor(), TIOCGICOUNT, &icount))
- {
- if (last_break == 0xFFFFFFFF)
- last_break = icount.brk;
- else if (last_break != icount.brk)
- {
- last_break = icount.brk;
- readbuffer.fromfile(getDescriptor(), bytesavail);
- readbuffer.clear();
- writebuffer.clear();
- rsn->setRequested(rsn->getRequested()&~eSocketNotifier::Write);
- write(getDescriptor(), "BREAK!", 6);
- hangup();
- return;
- }
- }
- }
- int r;
- if ((r=readbuffer.fromfile(getDescriptor(), bytesavail)) != bytesavail)
- if (issocket)
- eDebug("fromfile failed!");
- readyRead_();
- }
- } else if (what & eSocketNotifier::Write)
- {
- if ((mystate == Connection) || (mystate == Closing))
- {
- if (!writebuffer.empty())
- {
- bytesWritten_(writebuffer.tofile(getDescriptor(), 65536));
- if (writebuffer.empty())
- {
- rsn->setRequested(rsn->getRequested()&~eSocketNotifier::Write);
- if (mystate == Closing)
- {
- close(); // warning, we might get destroyed after close.
- return;
- }
- }
- } else
- eDebug("got ready to write, but nothin in buffer. strange.");
- if (mystate == Closing)
- close();
- } else if (mystate == Connecting)
- {
- mystate=Connection;
- rsn->setRequested(rsn->getRequested()&~eSocketNotifier::Write);
-
- int res;
- socklen_t size=sizeof(res);
- ::getsockopt(getDescriptor(), SOL_SOCKET, SO_ERROR, &res, &size);
- if (!res)
- connected_();
- else
- {
- close();
- error_(res);
- }
- }
- } else if (what & eSocketNotifier::Hungup)
- {
- if (mystate == Connection)
- {
- writebuffer.clear();
- close();
- } else if (mystate == Connecting)
- {
- int res;
- socklen_t size=sizeof(res);
- ::getsockopt(getDescriptor(), SOL_SOCKET, SO_ERROR, &res, &size);
- close();
- error_(res);
- }
- }
-}
-
-int eSocket::writeBlock(const char *data, unsigned int len)
-{
- int w=len;
- if (issocket && writebuffer.empty())
- {
- int tw=::send(getDescriptor(), data, len, MSG_NOSIGNAL);
- if ((tw < 0) && (errno != EWOULDBLOCK))
- eDebug("write: %m");
-
- if (tw < 0)
- tw = 0;
- data+=tw;
- len-=tw;
- }
- if (len)
- writebuffer.write(data, len);
-
- if (!writebuffer.empty())
- rsn->setRequested(rsn->getRequested()|eSocketNotifier::Write);
- return w;
-}
-
-int eSocket::getDescriptor()
-{
- return socketdesc;
-}
-
-int eSocket::connectToHost(std::string hostname, int port)
-{
- struct hostent *server;
- int res;
-
- if(!socketdesc){
- error_(errno);
- return(-1);
- }
- server=gethostbyname(hostname.c_str());
- if(server==NULL)
- {
- eDebug("can't resolve %s", hostname.c_str());
- error_(errno);
- return(-2);
- }
- bzero( (char*)&serv_addr, sizeof(serv_addr));
- serv_addr.sin_family=AF_INET;
- bcopy( (char*)server->h_addr,
- (char*)&serv_addr.sin_addr.s_addr,
- server->h_length);
- serv_addr.sin_port=htons(port);
- res=::connect(socketdesc, (const sockaddr*)&serv_addr, sizeof(serv_addr));
- if ((res < 0) && (errno != EINPROGRESS))
- {
- eDebug("can't connect to host: %s", hostname.c_str());
- close();
- error_(errno);
- return(-3);
- }
- if (res < 0) // EINPROGRESS
- {
- rsn->setRequested(rsn->getRequested()|eSocketNotifier::Write);
- mystate=Connecting;
- } else
- {
- mystate=Connection;
- connected_();
- }
- return(0);
-}
-
-eSocket::eSocket(eMainloop *ml): readbuffer(32768), writebuffer(32768), rsn(0)
-{
- ASSERT(ml);
- int s=socket(AF_INET, SOCK_STREAM, 0);
-#if 0
- eDebug("[SOCKET]: initalized socket %d", socketdesc);
-#endif
- mystate=Idle;
- setSocket(s, 1, ml);
-}
-
-eSocket::eSocket(int socket, int issocket, eMainloop *ml): readbuffer(32768), writebuffer(32768)
-{
- setSocket(socket, issocket, ml);
- mystate=Connection;
-}
-
-eSocket::~eSocket()
-{
- if(socketdesc>=0)
- {
- ::close(socketdesc);
- }
-}
+++ /dev/null
-#ifndef __socket_h
-#define __socket_h
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <fcntl.h>
-
-#include <lib/base/ebase.h>
-#include <lib/base/eerror.h>
-#include <string>
-#include <libsig_comp.h>
-#include <lib/base/buffer.h>
-
-class eSocket: public Object
-{
- int mystate;
- int issocket;
- unsigned int last_break;
-private:
- int socketdesc;
- eIOBuffer readbuffer;
- eIOBuffer writebuffer;
- int writebusy;
- sockaddr_in serv_addr;
-protected:
- ePtr<eSocketNotifier> rsn;
- virtual void notifier(int);
-public:
- eSocket(eMainloop *ml);
- eSocket(int socket, int issocket, eMainloop *ml);
- ~eSocket();
- int connectToHost(std::string hostname, int port);
- int getDescriptor();
- int writeBlock(const char *data, unsigned int len);
- int setSocket(int socketfd, int issocket, eMainloop *ml);
- int bytesToWrite();
- int readBlock(char *data, unsigned int maxlen);
- int bytesAvailable();
- bool canReadLine();
- std::string readLine();
- void close();
- // flow control: start/stop data delivery into read buffer.
- void enableRead();
- void disableRead();
-
- void inject(const char *data, int len);
-
- enum State { Idle, HostLookup, Connecting,
- Listening, Connection, Closing };
- int state();
-
- Signal0<void> connectionClosed_;
- Signal0<void> connected_;
- Signal0<void> readyRead_;
- Signal0<void> hangup;
- Signal1<void,int> bytesWritten_;
- Signal1<void,int> error_;
-};
-
-#endif /* __socket_h */