diff options
Diffstat (limited to 'src/net')
| -rw-r--r-- | src/net/htcd.cc | 153 | ||||
| -rw-r--r-- | src/net/isocket.cc | 58 | ||||
| -rw-r--r-- | src/net/isocket.h | 68 | ||||
| -rw-r--r-- | src/net/redirect.cc | 185 | ||||
| -rw-r--r-- | src/net/route80.cc | 64 | ||||
| -rw-r--r-- | src/net/server.cc | 75 | ||||
| -rw-r--r-- | src/net/server.h | 46 | ||||
| -rw-r--r-- | src/net/test.cc | 44 | ||||
| -rw-r--r-- | src/net/thrserv.cc | 255 | ||||
| -rw-r--r-- | src/net/thrserv.h | 79 |
10 files changed, 1027 insertions, 0 deletions
diff --git a/src/net/htcd.cc b/src/net/htcd.cc new file mode 100644 index 0000000..89729e6 --- /dev/null +++ b/src/net/htcd.cc | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <net/thrserv.h> | ||
| 21 | |||
| 22 | static fp_stream merr(stderr); | ||
| 23 | |||
| 24 | static mstring PATH; | ||
| 25 | static htcServ* SERV; | ||
| 26 | |||
| 27 | const mstring PIDURI="/sys/htcd"; | ||
| 28 | |||
| 29 | const int BACKLOG=4; | ||
| 30 | const int SERVERS=9; | ||
| 31 | const int LOWER=3; | ||
| 32 | const int UPPER=6; | ||
| 33 | const int KEEPALIVE=300; | ||
| 34 | const int SNDBUFSIZE=16384; | ||
| 35 | const int RCVBUFSIZE=16384; | ||
| 36 | |||
| 37 | /////////////////////////////////////////////////////////// | ||
| 38 | |||
| 39 | static thrServ* server[SERVERS]; | ||
| 40 | static thrCron* crontab; | ||
| 41 | |||
| 42 | extern "C" { | ||
| 43 | static void* thr_handler(void* p) { ((thrServ*)p)->enter(); return 0; } | ||
| 44 | static void* thr_cron(void* p) { ((thrCron*)p)->enter(); return 0; } | ||
| 45 | static void onTERM(int sig) { SERV->htcd.running=0; } | ||
| 46 | static void onHUP(int sig) { if(crontab) crontab->running=0; } | ||
| 47 | typedef void (*disp_t)(int); | ||
| 48 | } | ||
| 49 | |||
| 50 | static void MainProc(isocket& sock) | ||
| 51 | { | ||
| 52 | int keep=1; | ||
| 53 | while(SERV->htcd.running) { | ||
| 54 | int nvacant=0; for(int i=0;i<SERVERS;i++) if(server[i]->vacant()) nvacant++; | ||
| 55 | if(nvacant>UPPER) keep=1; else if(nvacant<=LOWER) keep=0; | ||
| 56 | if(!keep) for(int i=0;i<SERVERS;i++) server[i]->shutdown(); | ||
| 57 | time_t timeout=time(0)-KEEPALIVE; | ||
| 58 | for(int i=0;i<SERVERS;i++) if(timeout>server[i]->last) server[i]->disconnect(); | ||
| 59 | int test=sock.test(); | ||
| 60 | if(test>0) { | ||
| 61 | thrServ* p=0; | ||
| 62 | for(int i=0;i<SERVERS;i++) if(server[i]->vacant()) { p=server[i]; break; } | ||
| 63 | if(!p) for(int i=0;i<SERVERS;i++) if(!p||server[i]->first<p->first) p=server[i]; | ||
| 64 | if(p->shutdown()) { | ||
| 65 | try { | ||
| 66 | isocket* s=sock.accept(); | ||
| 67 | if(s) p->reset(s,keep); | ||
| 68 | } | ||
| 69 | catch(const merror_t& e) { | ||
| 70 | merr<<"SOCKET: "<<e.desc<<"\n"; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | else if(test<0) SERV->htcd.running=0; | ||
| 75 | } | ||
| 76 | for(int i=0;i<SERVERS;i++) { | ||
| 77 | server[i]->term(); | ||
| 78 | pthread_join(server[i]->ptid,0); | ||
| 79 | } | ||
| 80 | pthread_kill(crontab->tid,SIGHUP); | ||
| 81 | pthread_join(crontab->ptid,0); | ||
| 82 | } | ||
| 83 | |||
| 84 | /////////////////////////////////////////////////////////////// | ||
| 85 | |||
| 86 | static void httpServer(int overport) | ||
| 87 | { | ||
| 88 | isocket sock(SERV->htcd.node.addr,overport,BACKLOG); | ||
| 89 | sock.keepalive(1); | ||
| 90 | sock.sendbufsize(SNDBUFSIZE); | ||
| 91 | sock.recvbufsize(RCVBUFSIZE); | ||
| 92 | |||
| 93 | sigignore(SIGPIPE); | ||
| 94 | disp_t onterm=signal(SIGTERM,onTERM); | ||
| 95 | disp_t onint=signal(SIGINT,onTERM); | ||
| 96 | disp_t onhup=signal(SIGHUP,onHUP); | ||
| 97 | MainProc(sock); | ||
| 98 | signal(SIGHUP,onhup); | ||
| 99 | signal(SIGINT,onint); | ||
| 100 | signal(SIGTERM,onterm); | ||
| 101 | } | ||
| 102 | |||
| 103 | static void Daemon(int overport) try | ||
| 104 | { | ||
| 105 | PROCLOCK(PATH+PIDURI); | ||
| 106 | SERV=new htcServ(PATH); | ||
| 107 | crontab=new thrCron(*SERV); | ||
| 108 | pthread_create(&crontab->ptid,0,thr_cron,crontab); | ||
| 109 | for(int i=0;i<SERVERS;i++) { | ||
| 110 | server[i]=new thrServ(*SERV); | ||
| 111 | pthread_create(&server[i]->ptid,0,thr_handler,server[i]); | ||
| 112 | } | ||
| 113 | merr<<"htcd: "<<PATH<<" started\n"; | ||
| 114 | httpServer(overport<0?0:overport==0?SERV->htcd.port:overport); | ||
| 115 | merr<<"htcd: "<<PATH<<" terminating\n"; | ||
| 116 | for(int i=0;i<SERVERS;i++) delete server[i]; | ||
| 117 | delete crontab; | ||
| 118 | } | ||
| 119 | catch(const merror_t& e) { | ||
| 120 | if(SERV) { | ||
| 121 | SERV->htcd.errlog<<"["<<time(0)<<"][MAIN]["<<e.desc<<"]\n"; | ||
| 122 | merr<<e.desc<<"\n"; | ||
| 123 | } | ||
| 124 | else if(First(e.desc)!=sref("proclock:")) merr<<e.desc<<"\n"; | ||
| 125 | } | ||
| 126 | catch(...) { | ||
| 127 | if(SERV) SERV->htcd.errlog<<"["<<time(0)<<"][MAIN][FATAL]\n"; | ||
| 128 | merr<<"FATAL\n"; | ||
| 129 | } | ||
| 130 | |||
| 131 | main(int argc,char* argv[]) try | ||
| 132 | { | ||
| 133 | if(argc<3) { | ||
| 134 | merr<<"Usage: "<<argv[0]<<" <path> <overport=-1|0|port> [-1|0|1]\n"; | ||
| 135 | return -1; | ||
| 136 | } | ||
| 137 | PATH=argv[1]; if(PATH.back()=='/') PATH=PATH.popb(); | ||
| 138 | setenv("DOCROOT",PATH.c_str(),1); | ||
| 139 | int overport=atoi(argv[2]); | ||
| 140 | int cmd=argc>3?atoi(argv[3]):0; | ||
| 141 | if(cmd) ProcTerminate(PATH+PIDURI); | ||
| 142 | if(cmd>=0) { if(fork()==0) Daemon(overport); } | ||
| 143 | delete SERV; | ||
| 144 | return 0; | ||
| 145 | } | ||
| 146 | catch(const merror_t& e) { | ||
| 147 | merr<<"ERROR: ["<<e.desc<<"]\n"; | ||
| 148 | return -1; | ||
| 149 | } | ||
| 150 | catch(...) { | ||
| 151 | merr<<"ERROR: [FATAL]\n"; | ||
| 152 | return -1; | ||
| 153 | } | ||
diff --git a/src/net/isocket.cc b/src/net/isocket.cc new file mode 100644 index 0000000..af94189 --- /dev/null +++ b/src/net/isocket.cc | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <net/isocket.h> | ||
| 21 | #include <errno.h> | ||
| 22 | |||
| 23 | isocket::isocket(const in_addr& ia,int port,int backlog): | ||
| 24 | pipe_stream(-1),rd(-1) | ||
| 25 | { | ||
| 26 | if(port) { | ||
| 27 | fd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); | ||
| 28 | if(fd<0) THROW("isocket: Could not create"); | ||
| 29 | reuse(1); | ||
| 30 | } | ||
| 31 | else fd=0; | ||
| 32 | sa.sin_family=2; | ||
| 33 | sa.sin_port=htons(port); | ||
| 34 | sa.sin_addr=ia; | ||
| 35 | if(port) { | ||
| 36 | if(bind(fd,(sockaddr*)&sa,sizeof(sa))==-1) THROW("isocket: Could not bind"); | ||
| 37 | } | ||
| 38 | if(listen(fd,backlog)==-1) THROW("isocket: Could not listen"); | ||
| 39 | rd.setfd(fd); | ||
| 40 | } | ||
| 41 | |||
| 42 | isocket::isocket(int f,const sockaddr_in& ia): | ||
| 43 | pipe_stream(f),rd(f) | ||
| 44 | { | ||
| 45 | sa=ia; | ||
| 46 | setflag(O_NONBLOCK|O_NDELAY); | ||
| 47 | nodelay(1); | ||
| 48 | } | ||
| 49 | |||
| 50 | isocket* isocket::accept() throw(merror_t) | ||
| 51 | { | ||
| 52 | sockaddr_in tsa; socklen_t tsalen; | ||
| 53 | memset(&tsa,0,tsalen=sizeof(tsa)); | ||
| 54 | int tfd=::accept(fd,(sockaddr*)&tsa,&tsalen); | ||
| 55 | if(tfd>0) return new isocket(tfd,tsa); | ||
| 56 | if(errno!=EAGAIN) THROW("isocket: could not accept"); | ||
| 57 | return 0; | ||
| 58 | } | ||
diff --git a/src/net/isocket.h b/src/net/isocket.h new file mode 100644 index 0000000..5ca1ec3 --- /dev/null +++ b/src/net/isocket.h | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef ISOCKETH | ||
| 21 | #define ISOCKETH | ||
| 22 | |||
| 23 | #include <mt/mread.h> | ||
| 24 | #include <mt/mstring.h> | ||
| 25 | #include <sys/socket.h> | ||
| 26 | #include <arpa/inet.h> | ||
| 27 | #include <netinet/in.h> | ||
| 28 | #include <netinet/tcp.h> | ||
| 29 | |||
| 30 | class isocket : public pipe_stream { | ||
| 31 | public: | ||
| 32 | isocket(const in_addr& ia,int port,int backlog); | ||
| 33 | isocket(int f,const sockaddr_in& ia); | ||
| 34 | ~isocket() { close(); } | ||
| 35 | |||
| 36 | void close() { if(fd>=0) { ::close(fd); fd=-1; }} | ||
| 37 | |||
| 38 | int getfd() const { return fd; } | ||
| 39 | int family() const { return sa.sin_family; } | ||
| 40 | int port() const { return ntohs(sa.sin_port); } | ||
| 41 | in_addr address() const { return sa.sin_addr; } | ||
| 42 | |||
| 43 | void reuse(int ok) { set(SOL_SOCKET,SO_REUSEADDR,ok); } | ||
| 44 | void nodelay(int ok) { set(IPPROTO_TCP,TCP_NODELAY,ok); } | ||
| 45 | void keepalive(int ok) { set(SOL_SOCKET,SO_KEEPALIVE,ok); } | ||
| 46 | void sendbufsize(int s) { set(SOL_SOCKET,SO_SNDBUF,s); } | ||
| 47 | void recvbufsize(int s) { set(SOL_SOCKET,SO_RCVBUF,s); } | ||
| 48 | |||
| 49 | isocket* accept() throw(merror_t); | ||
| 50 | |||
| 51 | int test() { return rd.poll(); } | ||
| 52 | int getsome(char* s,int n) { return rd.read(s,n); } | ||
| 53 | int gethead(char* s,int n) { return rd.readpara(s,n); } | ||
| 54 | int getbody(char* s,int n) { return rd.readx(s,n); } | ||
| 55 | |||
| 56 | protected: | ||
| 57 | void setflag(int f) { fcntl(fd,F_SETFL,f); } | ||
| 58 | int getflag() const { return fcntl(fd,F_GETFL,0); } | ||
| 59 | void set(int lev,int opt,int ok) throw(merror_t) { | ||
| 60 | if(setsockopt(fd,lev,opt,(char*)&ok,sizeof(ok))<0) | ||
| 61 | THROW("isocket: Could not set option"); | ||
| 62 | } | ||
| 63 | private: | ||
| 64 | sockaddr_in sa; | ||
| 65 | mread rd; | ||
| 66 | }; | ||
| 67 | |||
| 68 | #endif | ||
diff --git a/src/net/redirect.cc b/src/net/redirect.cc new file mode 100644 index 0000000..7e07e7c --- /dev/null +++ b/src/net/redirect.cc | |||
| @@ -0,0 +1,185 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <net/isocket.h> | ||
| 21 | #include <mail/res.h> | ||
| 22 | #include <http/http.h> | ||
| 23 | #include <mt/lookup.h> | ||
| 24 | #include <mt/lock.h> | ||
| 25 | #include <sys/utsname.h> | ||
| 26 | #include <signal.h> | ||
| 27 | |||
| 28 | static fp_stream merr(stderr); | ||
| 29 | static IPnode NODE; | ||
| 30 | static int PORT; | ||
| 31 | static mstring URL,PATH,SERVER,URL1,URL2; | ||
| 32 | static int volatile RUNNING; | ||
| 33 | |||
| 34 | const mstring REDIRECT="/tmp/redirect."; | ||
| 35 | const int BACKLOG=4; | ||
| 36 | const int SNDBUFSIZE=16384; | ||
| 37 | const int RCVBUFSIZE=16384; | ||
| 38 | const int MAXHEAD=16384; | ||
| 39 | const int SAFEZONE=4096; | ||
| 40 | |||
| 41 | static void BreakURL() | ||
| 42 | { | ||
| 43 | static const mstring pre="//"; | ||
| 44 | int p=URL.find(pre); | ||
| 45 | if(p>=0) { | ||
| 46 | p+=pre.size(); | ||
| 47 | int q=p+URL.right(p).find('/'); | ||
| 48 | if(q>=p) { | ||
| 49 | URL1=URL.left(q); | ||
| 50 | URL2=URL.right(q); | ||
| 51 | } | ||
| 52 | else { | ||
| 53 | URL1=URL; | ||
| 54 | URL2.clear(); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | else throw(0); | ||
| 58 | } | ||
| 59 | |||
| 60 | static mstring Combine(const sref& uri) | ||
| 61 | { | ||
| 62 | const int ncvt=3; | ||
| 63 | static const mstring cvt[ncvt]={"/BODY","/en","/sv"}; | ||
| 64 | mstring d=uri; | ||
| 65 | mstring s=URL1; | ||
| 66 | for(int i=0;i<ncvt;i++) { | ||
| 67 | int p=d.find(cvt[i]); | ||
| 68 | if(p>=0) { | ||
| 69 | d.erase(p,cvt[i].size()); | ||
| 70 | s+=cvt[i]; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | s+=URL2; | ||
| 74 | s+=d; | ||
| 75 | return s; | ||
| 76 | } | ||
| 77 | |||
| 78 | static int Handle(isocket& sock) | ||
| 79 | { | ||
| 80 | mstring buffer(MAXHEAD+SAFEZONE); | ||
| 81 | int nhead=sock.gethead(buffer.data(),MAXHEAD); | ||
| 82 | if(nhead<=0) return 0; | ||
| 83 | httpReq req(sref(buffer.data(),nhead)); | ||
| 84 | httpResp resp; | ||
| 85 | resp.status=HTTP_301; | ||
| 86 | //resp.location=URL+req.uri; | ||
| 87 | resp.location=Combine(req.uri); | ||
| 88 | if(req.arg.nempty()) { resp.location.append(1,'?'); resp.location+=req.arg; } | ||
| 89 | resp.putHead(sock); | ||
| 90 | putend(sock); | ||
| 91 | sock.close(); | ||
| 92 | return 1; | ||
| 93 | } | ||
| 94 | |||
| 95 | /////////////////////////////////////////////////////////////// | ||
| 96 | |||
| 97 | extern "C" { | ||
| 98 | static void onTERM(int sig) { RUNNING=0; } | ||
| 99 | typedef void (*disp_t)(int); | ||
| 100 | } | ||
| 101 | |||
| 102 | static void MainProc(isocket& sock) | ||
| 103 | { | ||
| 104 | RUNNING=1; | ||
| 105 | while(RUNNING) { | ||
| 106 | int test=sock.test(); | ||
| 107 | if(test>0) { | ||
| 108 | try { | ||
| 109 | isocket* s=sock.accept(); | ||
| 110 | if(s) Handle(*s); | ||
| 111 | } | ||
| 112 | catch(const merror_t& e) { | ||
| 113 | merr<<"SOCKET: "<<e.desc<<"\n"; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | else if(test<0) RUNNING=0; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | /////////////////////////////////////////////////////////////// | ||
| 121 | |||
| 122 | static void httpServer() | ||
| 123 | { | ||
| 124 | isocket sock(NODE.addr,PORT,BACKLOG); | ||
| 125 | sock.keepalive(1); | ||
| 126 | sock.sendbufsize(SNDBUFSIZE); | ||
| 127 | sock.recvbufsize(RCVBUFSIZE); | ||
| 128 | sigignore(SIGPIPE); | ||
| 129 | disp_t onterm=signal(SIGTERM,onTERM); | ||
| 130 | disp_t onint=signal(SIGINT,onTERM); | ||
| 131 | MainProc(sock); | ||
| 132 | signal(SIGINT,onint); | ||
| 133 | signal(SIGTERM,onterm); | ||
| 134 | } | ||
| 135 | |||
| 136 | static void Daemon() try | ||
| 137 | { | ||
| 138 | PROCLOCK(PATH); | ||
| 139 | merr<<"redirect: "<<SERVER<<" -> "<<URL<<" started\n"; | ||
| 140 | httpServer(); | ||
| 141 | } | ||
| 142 | catch(const merror_t& e) { | ||
| 143 | if(First(e.desc)!=sref("proclock:")) merr<<e.desc<<"\n"; | ||
| 144 | } | ||
| 145 | catch(...) { | ||
| 146 | merr<<"FATAL\n"; | ||
| 147 | } | ||
| 148 | |||
| 149 | main(int argc,char* argv[]) try | ||
| 150 | { | ||
| 151 | if(argc<3) { | ||
| 152 | merr<<"Usage: "<<argv[0]<<" [host:]<port> <url> [-1|0|1]\n"; | ||
| 153 | return -1; | ||
| 154 | } | ||
| 155 | sref s(argv[1]); | ||
| 156 | mstring host=s.left_last(':'); | ||
| 157 | mstring sport=s.past_last(':'); | ||
| 158 | if(sport.empty()) { | ||
| 159 | sport=host; | ||
| 160 | host.clear(); | ||
| 161 | } | ||
| 162 | PORT=atoi(sport); | ||
| 163 | URL=argv[2]; | ||
| 164 | if(URL.back()=='/') URL=URL.popb(); | ||
| 165 | BreakURL(); | ||
| 166 | if(host.empty()) { | ||
| 167 | struct utsname u; uname(&u); | ||
| 168 | host=u.nodename; | ||
| 169 | } | ||
| 170 | Lookup(NODE,host); | ||
| 171 | SERVER=NODE.name; SERVER.append(1,'-'); SERVER+=itoa(PORT); | ||
| 172 | PATH=REDIRECT; PATH+=SERVER; | ||
| 173 | int cmd=argc>3?atoi(argv[3]):0; | ||
| 174 | if(cmd) ProcTerminate(PATH); | ||
| 175 | if(cmd>=0) { if(fork()==0) Daemon(); } | ||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | catch(const merror_t& e) { | ||
| 179 | merr<<"ERROR: ["<<e.desc<<"]\n"; | ||
| 180 | return -1; | ||
| 181 | } | ||
| 182 | catch(...) { | ||
| 183 | merr<<"ERROR: [FATAL]\n"; | ||
| 184 | return -1; | ||
| 185 | } | ||
diff --git a/src/net/route80.cc b/src/net/route80.cc new file mode 100644 index 0000000..e883aba --- /dev/null +++ b/src/net/route80.cc | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <net/isocket.h> | ||
| 21 | #include <mt/lookup.h> | ||
| 22 | #include <sys/utsname.h> | ||
| 23 | |||
| 24 | static fp_stream merr(stderr); | ||
| 25 | static IPnode NODE; | ||
| 26 | static mstring PATH; | ||
| 27 | static int PORT; | ||
| 28 | |||
| 29 | const int BACKLOG=4; | ||
| 30 | const int SNDBUFSIZE=16384; | ||
| 31 | const int RCVBUFSIZE=16384; | ||
| 32 | |||
| 33 | /////////////////////////////////////////////////////////////// | ||
| 34 | |||
| 35 | static void MainProc(isocket& sock) | ||
| 36 | { | ||
| 37 | int fd=dup2(sock.fd,0); | ||
| 38 | if(fd!=0) { merr<<"Not right\n"; return; } | ||
| 39 | execl("htcd","htcd",PATH.c_str(),"-1",0); | ||
| 40 | } | ||
| 41 | |||
| 42 | /////////////////////////////////////////////////////////////// | ||
| 43 | |||
| 44 | static void httpServer() | ||
| 45 | { | ||
| 46 | isocket sock(NODE.addr,PORT,BACKLOG); | ||
| 47 | sock.keepalive(1); | ||
| 48 | sock.sendbufsize(SNDBUFSIZE); | ||
| 49 | sock.recvbufsize(RCVBUFSIZE); | ||
| 50 | MainProc(sock); | ||
| 51 | } | ||
| 52 | |||
| 53 | main(int argc,char* argv[]) | ||
| 54 | { | ||
| 55 | if(argc<3) { merr<<"Usage: "<<argv[0]<<" <path> <port>\n"; return -1; } | ||
| 56 | PATH=argv[1]; if(PATH.back()=='/') PATH=PATH.popb(); | ||
| 57 | PORT=atoi(argv[2]); | ||
| 58 | struct utsname u; uname(&u); | ||
| 59 | Lookup(NODE,sref(u.nodename)); | ||
| 60 | httpServer(); | ||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | |||
diff --git a/src/net/server.cc b/src/net/server.cc new file mode 100644 index 0000000..6996b20 --- /dev/null +++ b/src/net/server.cc | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <net/server.h> | ||
| 21 | |||
| 22 | const mstring SERVURI="/htc/server.htc"; | ||
| 23 | |||
| 24 | htcServ::htcServ(const sref& path) : htcd(path),user(htcd.toks) | ||
| 25 | { | ||
| 26 | Setup(user,htcd); | ||
| 27 | LoadBuffer(server,path+SERVURI); | ||
| 28 | } | ||
| 29 | |||
| 30 | /////////////////////////////////////////////////////// | ||
| 31 | |||
| 32 | static void Log(fp_stream& tlog,htcd_req& R,const sref& status) | ||
| 33 | { | ||
| 34 | MLOCK(R.htcd()->mutex); | ||
| 35 | tlog<<"["<<time(0)<<"]["<<R.tcp->node.ip<<"][" | ||
| 36 | <<R.tcp->node.name<<":"<<R.tcp->port<<"][" | ||
| 37 | <<R.group<<":"<<R.user.uid()<<"][" | ||
| 38 | <<First(status)<<"]["<<R.req->method<<"][" | ||
| 39 | <<R.req->uri<<"]["<<R.req->arg<<"]\n"; | ||
| 40 | tlog.flush(); | ||
| 41 | } | ||
| 42 | |||
| 43 | /////////////////////////////////////////////////////// | ||
| 44 | |||
| 45 | int SendStatus(isocket& out,htcd_req& R,int keep,const sref& status,const sref& msg) | ||
| 46 | { | ||
| 47 | R.resp.status=status; | ||
| 48 | if(atof(R.req->version.past_first(http_ver))<http_major) R.resp.version=HTTP_V10; | ||
| 49 | if(keep) R.resp.connect=keep_tag; | ||
| 50 | if(R.resp.cont_enc.nempty()|| | ||
| 51 | R.resp.trans_enc.nempty()|| | ||
| 52 | R.resp.status==HTTP_100|| | ||
| 53 | R.resp.status==HTTP_204|| | ||
| 54 | R.resp.status==HTTP_304|| | ||
| 55 | eqn(R.req->method,HTTP_HEAD)) { | ||
| 56 | R.resp.cont_type.clear(); | ||
| 57 | R.resp.cont_length.clear(); | ||
| 58 | } | ||
| 59 | else { | ||
| 60 | if(R.resp.cont_type.empty()) R.resp.cont_type=http_mime_default; | ||
| 61 | R.resp.cont_length=itoa(msg.size()); | ||
| 62 | } | ||
| 63 | Log(R.htcd()->logger,R,status); | ||
| 64 | R.resp.putHead(out); | ||
| 65 | putend(out); | ||
| 66 | out<<msg; | ||
| 67 | #if 0 | ||
| 68 | static fp_stream merr(stderr); | ||
| 69 | merr<<"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"; | ||
| 70 | R.resp.putHead(merr); | ||
| 71 | putend(merr); | ||
| 72 | merr<<"=================================\n"; | ||
| 73 | #endif | ||
| 74 | return out.hup?0:keep; | ||
| 75 | } | ||
diff --git a/src/net/server.h b/src/net/server.h new file mode 100644 index 0000000..65f884c --- /dev/null +++ b/src/net/server.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef SERVERH | ||
| 21 | #define SERVERH | ||
| 22 | |||
| 23 | #include <serv/htcd.h> | ||
| 24 | #include <hdb/buffer.h> | ||
| 25 | #include <net/isocket.h> | ||
| 26 | #include <mt/lock.h> | ||
| 27 | #include <signal.h> | ||
| 28 | |||
| 29 | const mstring http_ver="HTTP/"; | ||
| 30 | const double http_minor=1.0,http_major=1.1; | ||
| 31 | |||
| 32 | const mstring keep_tag="Keep-Alive"; | ||
| 33 | const mstring close_tag="Close"; | ||
| 34 | const mstring expect_continue_tag="100-continue"; | ||
| 35 | |||
| 36 | struct htcServ { | ||
| 37 | HTCd htcd; | ||
| 38 | tokmap user; | ||
| 39 | mstring server; | ||
| 40 | htcServ(const sref& path); | ||
| 41 | }; | ||
| 42 | |||
| 43 | int SendStatus(isocket& out,htcd_req& R,int keep, | ||
| 44 | const sref& status,const sref& msg=ms_empty); | ||
| 45 | |||
| 46 | #endif | ||
diff --git a/src/net/test.cc b/src/net/test.cc new file mode 100644 index 0000000..c0e3b41 --- /dev/null +++ b/src/net/test.cc | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <mt/mlock.h> | ||
| 21 | #include <iostream> | ||
| 22 | using namespace std; | ||
| 23 | |||
| 24 | static mutex_t mutex; | ||
| 25 | static mtcond_t cond; | ||
| 26 | |||
| 27 | static void* thread(void* a) | ||
| 28 | { | ||
| 29 | cerr<<"thread "<<a<<endl; | ||
| 30 | MSUSPEND(mutex,cond); | ||
| 31 | return 0; | ||
| 32 | } | ||
| 33 | |||
| 34 | main() | ||
| 35 | { | ||
| 36 | pthread_t tid; | ||
| 37 | pthread_create(&tid,0,thread,(void*)2); | ||
| 38 | cerr<<"main thread"<<endl; | ||
| 39 | sleep(2); | ||
| 40 | MCONTINUE(cond); | ||
| 41 | pthread_join(tid,0); | ||
| 42 | cerr<<"afer join"<<endl; | ||
| 43 | return 0; | ||
| 44 | } | ||
diff --git a/src/net/thrserv.cc b/src/net/thrserv.cc new file mode 100644 index 0000000..0d91d12 --- /dev/null +++ b/src/net/thrserv.cc | |||
| @@ -0,0 +1,255 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <net/thrserv.h> | ||
| 21 | #include <errno.h> | ||
| 22 | |||
| 23 | const mstring cron_tag="\\run.cron"; | ||
| 24 | const mstring FATAL="FATAL ERROR"; | ||
| 25 | const mstring UNKNOWN="UNKNOWN"; | ||
| 26 | const mstring REJECTED="REJECTED"; | ||
| 27 | |||
| 28 | const int MAXHEAD=16384; | ||
| 29 | const int MAXBODY=2<<21; | ||
| 30 | const int MAXURI=4096; | ||
| 31 | const int MAXARG=4096; | ||
| 32 | const int SAFEZONE=4096; | ||
| 33 | |||
| 34 | /////////////////////////////////////////////////////////////// | ||
| 35 | |||
| 36 | thrServ::thrServ(htcServ& server): | ||
| 37 | pmutex(MUTEX_INIT), | ||
| 38 | pcond(MTCOND_INIT), | ||
| 39 | keepalive(0),running(0),termok(0), | ||
| 40 | first(time(0)),last(time(0)), | ||
| 41 | serv(&server), | ||
| 42 | sock(0), | ||
| 43 | user(server.user,server.htcd.docroot) | ||
| 44 | { | ||
| 45 | } | ||
| 46 | |||
| 47 | thrServ::~thrServ() | ||
| 48 | { | ||
| 49 | delete sock; | ||
| 50 | } | ||
| 51 | |||
| 52 | void thrServ::reset(isocket* s,int keep) | ||
| 53 | { | ||
| 54 | keepalive=keep; | ||
| 55 | running=1; | ||
| 56 | termok=0; | ||
| 57 | first=time(0); | ||
| 58 | last=time(0); | ||
| 59 | sock=s; | ||
| 60 | while(!tid); | ||
| 61 | if(MCONTINUE(pcond)) throw((int)0); | ||
| 62 | } | ||
| 63 | |||
| 64 | void thrServ::Log(const sref& msg) | ||
| 65 | { | ||
| 66 | MLOCK(serv->htcd.mutex); | ||
| 67 | if(sock) serv->htcd.errlog<<"["<<time(0)<<"]["<<tid<<"][" | ||
| 68 | <<inet_ntoa(sock->address())<<":"<<sock->port()<<"][" | ||
| 69 | <<msg<<"]\n"; | ||
| 70 | else serv->htcd.errlog<<"["<<time(0)<<"]["<<tid<<"]["<<msg<<"]\n"; | ||
| 71 | serv->htcd.errlog.flush(); | ||
| 72 | } | ||
| 73 | |||
| 74 | void thrServ::enter() | ||
| 75 | { | ||
| 76 | tid=pthread_self(); | ||
| 77 | MSUSPEND(pmutex,pcond) | ||
| 78 | while(serv->htcd.running&&!termok) { | ||
| 79 | session(); | ||
| 80 | delete sock; | ||
| 81 | sock=0; | ||
| 82 | if(serv->htcd.running&&!termok) { | ||
| 83 | MSUSPEND(pmutex,pcond) | ||
| 84 | } | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | void thrServ::session() try | ||
| 89 | { | ||
| 90 | int keep=1; | ||
| 91 | while(sock&&keep&&running) { | ||
| 92 | int test=sock->test(); | ||
| 93 | if(test>0) { last=time(0); keep=handle(); } | ||
| 94 | else if(test<0) keep=0; | ||
| 95 | } | ||
| 96 | } | ||
| 97 | catch(const merror_t& e) { | ||
| 98 | Log(e.desc); | ||
| 99 | } | ||
| 100 | catch(...) { | ||
| 101 | Log(FATAL); | ||
| 102 | } | ||
| 103 | |||
| 104 | /////////////////////////////////////////////////////////////// | ||
| 105 | |||
| 106 | thrCron::thrCron(htcServ& server): | ||
| 107 | tid(0),running(0),serv(&server),user(server.user,server.htcd.docroot) | ||
| 108 | { | ||
| 109 | } | ||
| 110 | |||
| 111 | void thrCron::Log(const sref& msg) | ||
| 112 | { | ||
| 113 | MLOCK(serv->htcd.mutex); | ||
| 114 | serv->htcd.errlog<<"["<<time(0)<<"][CRON]["<<msg<<"]\n"; | ||
| 115 | serv->htcd.errlog.flush(); | ||
| 116 | } | ||
| 117 | |||
| 118 | void thrCron::enter() try | ||
| 119 | { | ||
| 120 | tid=pthread_self(); | ||
| 121 | tcpReq tcp; tcp.port=0; | ||
| 122 | httpReq req; | ||
| 123 | mstream devnull; | ||
| 124 | htcd_req R(serv->htcd,user.toks,devnull,tcp,req); | ||
| 125 | Env env(serv->htcd.ops,R,XSYSTEM); | ||
| 126 | env.req->running=&running; | ||
| 127 | running=1; | ||
| 128 | mstream m; | ||
| 129 | env.parse(m,cron_tag); | ||
| 130 | } | ||
| 131 | catch(const merror_t& e) { | ||
| 132 | Log(e.desc); | ||
| 133 | } | ||
| 134 | catch(...) { | ||
| 135 | Log(FATAL); | ||
| 136 | } | ||
| 137 | |||
| 138 | |||
| 139 | /////////////////////////////////////////////////////////////// | ||
| 140 | |||
| 141 | int thrServ::handle() | ||
| 142 | { | ||
| 143 | tcpReq tcp; | ||
| 144 | tcp.port=sock->port(); | ||
| 145 | if(!Lookup(tcp.node,sock->address())) { | ||
| 146 | Log(REJECTED); | ||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | ////////////////////////////////////////////////////////////////// | ||
| 151 | |||
| 152 | mstring buffer(MAXHEAD+MAXBODY+SAFEZONE); | ||
| 153 | int nhead=sock->gethead(buffer.data(),MAXHEAD); | ||
| 154 | if(nhead==0) return 0; | ||
| 155 | else if(nhead<0) return 0; | ||
| 156 | |||
| 157 | sref message(buffer.data(),nhead); | ||
| 158 | |||
| 159 | #if 0 | ||
| 160 | static fp_stream merr(stderr); | ||
| 161 | merr<<"QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ\n"; | ||
| 162 | merr<<message<<"\n"; | ||
| 163 | merr<<"=====================================\n"; | ||
| 164 | #endif | ||
| 165 | |||
| 166 | httpReq req(message); | ||
| 167 | |||
| 168 | ////////////////////////////////////////////////////////////////// | ||
| 169 | |||
| 170 | int keep=keepalive; | ||
| 171 | if(!eqn(req.connect,keep_tag)) keep=0; | ||
| 172 | |||
| 173 | mswrite cache; | ||
| 174 | htcd_req R(serv->htcd,user.toks,cache,tcp,req); | ||
| 175 | |||
| 176 | ////////////////////////////////////////////////////////////////// | ||
| 177 | |||
| 178 | if(nhead>=MAXHEAD) return SendStatus(*sock,R,keep,HTTP_413); | ||
| 179 | |||
| 180 | if(eqn(req.method,HTTP_TRACE)) { | ||
| 181 | R.resp.cont_type="message/http"; | ||
| 182 | return SendStatus(*sock,R,keep,HTTP_200,buffer.left(nhead)); | ||
| 183 | } | ||
| 184 | |||
| 185 | if(req.expect.nempty()) { | ||
| 186 | if(eqn(req.expect,expect_continue_tag)) SendStatus(*sock,R,keep,HTTP_100); | ||
| 187 | else return SendStatus(*sock,R,keep,HTTP_417); | ||
| 188 | } | ||
| 189 | |||
| 190 | if(req.trans_enc.nempty()||req.cont_enc.nempty()) return SendStatus(*sock,R,0,HTTP_501); | ||
| 191 | |||
| 192 | ////////////////////////////////////////////////////////////////// | ||
| 193 | |||
| 194 | int ilength=atoi(req.cont_length); | ||
| 195 | if(ilength>MAXBODY) return SendStatus(*sock,R,0,HTTP_413); | ||
| 196 | else if(ilength>0) { | ||
| 197 | int nbody=sock->getbody(buffer.data()+nhead,ilength); | ||
| 198 | if(nbody<0) return 0; | ||
| 199 | else { | ||
| 200 | sref sbody(buffer.data()+nhead,nbody); | ||
| 201 | #if 0 | ||
| 202 | static fp_stream merr(stderr); | ||
| 203 | merr<<"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP\n"; | ||
| 204 | merr<<sbody<<"\n"; | ||
| 205 | merr<<"=====================================\n"; | ||
| 206 | #endif | ||
| 207 | R.AddBody(sbody); | ||
| 208 | if(req.body.size()!=ilength) return 0; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | ////////////////////////////////////////////////////////////////// | ||
| 213 | |||
| 214 | if(eqn(req.method,HTTP_OPTIONS)) { | ||
| 215 | R.resp.allow="HEAD GET PUT POST DELETE"; | ||
| 216 | return SendStatus(*sock,R,keep,HTTP_200); | ||
| 217 | } | ||
| 218 | |||
| 219 | ////////////////////////////////////////////////////////////////// | ||
| 220 | |||
| 221 | if(req.cont_length.empty()&&(eqn(req.method,HTTP_PUT)||eqn(req.method,HTTP_POST))) | ||
| 222 | return SendStatus(*sock,R,0,HTTP_411); | ||
| 223 | |||
| 224 | if(eqn(req.method,HTTP_HEAD)|| | ||
| 225 | eqn(req.method,HTTP_GET)|| | ||
| 226 | eqn(req.method,HTTP_PUT)|| | ||
| 227 | eqn(req.method,HTTP_DELETE)|| | ||
| 228 | eqn(req.method,HTTP_POST)) { | ||
| 229 | R.resp.cont_type=mime_texthtml; | ||
| 230 | R.resp.cont_type_charset=mime_default; | ||
| 231 | try { | ||
| 232 | Env env(serv->htcd.ops,R,XSYSTEM); | ||
| 233 | env.req->running=&running; | ||
| 234 | mstream m; | ||
| 235 | env.parse(m,serv->server); | ||
| 236 | if(!env.req->is_running()) THROW("htc: "<<req.uri<<" ended prematurely; reload"); | ||
| 237 | } | ||
| 238 | catch(const merror_t& e) { | ||
| 239 | Log(e.desc); | ||
| 240 | return SendStatus(*sock,R,0,HTTP_503,e.desc); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | else return SendStatus(*sock,R,keep,HTTP_501); | ||
| 244 | |||
| 245 | if(!keepalive) keep=0; | ||
| 246 | if(req.if_mod.nempty()&&R.resp.lastmod.nempty()) { | ||
| 247 | time_t since=cvtTime(req.if_mod),lst=cvtTime(R.resp.lastmod); | ||
| 248 | if(lst<=since) return SendStatus(*sock,R,keep,HTTP_304); | ||
| 249 | } | ||
| 250 | |||
| 251 | mstring status=R.resp.status; | ||
| 252 | if(eqn(req.method,HTTP_HEAD)) return SendStatus(*sock,R,keep,status); | ||
| 253 | else return SendStatus(*sock,R,keep,status,cache.str()); | ||
| 254 | |||
| 255 | } | ||
diff --git a/src/net/thrserv.h b/src/net/thrserv.h new file mode 100644 index 0000000..09307f6 --- /dev/null +++ b/src/net/thrserv.h | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef THRSERVH | ||
| 21 | #define THRSERVH | ||
| 22 | |||
| 23 | #include <net/server.h> | ||
| 24 | #include <mt/lookup.h> | ||
| 25 | #include <mt/mlock.h> | ||
| 26 | |||
| 27 | //////////////////////////////////////////////////////// | ||
| 28 | // | ||
| 29 | // MT - safe | ||
| 30 | // Note that mutexes aren't needed here, since control | ||
| 31 | // is flowing from main to child, with possible child | ||
| 32 | // override in local variables. | ||
| 33 | |||
| 34 | struct thrServ { | ||
| 35 | pthread_t ptid; | ||
| 36 | mutex_t pmutex; | ||
| 37 | mtcond_t pcond; | ||
| 38 | volatile int tid,keepalive,running,termok; | ||
| 39 | time_t first,last; | ||
| 40 | htcServ* serv; | ||
| 41 | isocket* sock; | ||
| 42 | htcd_user user; | ||
| 43 | |||
| 44 | thrServ(htcServ& server); | ||
| 45 | ~thrServ(); | ||
| 46 | |||
| 47 | void Log(const sref& msg); | ||
| 48 | void reset(isocket* s,int keep); | ||
| 49 | |||
| 50 | int vacant() const { return sock==0; } | ||
| 51 | int shutdown() { keepalive=0; return sock==0; } | ||
| 52 | void disconnect() { keepalive=0; running=0; } | ||
| 53 | void term() { | ||
| 54 | keepalive=0; | ||
| 55 | running=0; | ||
| 56 | termok=1; | ||
| 57 | MCONTINUE(pcond); | ||
| 58 | } | ||
| 59 | |||
| 60 | void enter(); | ||
| 61 | void session(); | ||
| 62 | int handle(); | ||
| 63 | }; | ||
| 64 | |||
| 65 | //////////////////////////////////////////////////////// | ||
| 66 | |||
| 67 | struct thrCron { | ||
| 68 | pthread_t ptid; | ||
| 69 | volatile int tid,running; | ||
| 70 | htcServ* serv; | ||
| 71 | htcd_user user; | ||
| 72 | |||
| 73 | thrCron(htcServ& server); | ||
| 74 | |||
| 75 | void Log(const sref& msg); | ||
| 76 | void enter(); | ||
| 77 | }; | ||
| 78 | |||
| 79 | #endif | ||
