/************************************************************************* * * HTCd - Copyright (C) 1998-2006 Henrik Rydberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include const mstring cron_tag="\\run.cron"; const mstring FATAL="FATAL ERROR"; const mstring UNKNOWN="UNKNOWN"; const mstring REJECTED="REJECTED"; const int MAXHEAD=16384; const int MAXBODY=2<<21; const int MAXURI=4096; const int MAXARG=4096; const int SAFEZONE=4096; /////////////////////////////////////////////////////////////// thrServ::thrServ(htcServ& server): pmutex(MUTEX_INIT), pcond(MTCOND_INIT), keepalive(0),running(0),termok(0), first(time(0)),last(time(0)), serv(&server), sock(0), user(server.user,server.htcd.docroot) { } thrServ::~thrServ() { delete sock; } void thrServ::reset(isocket* s,int keep) { keepalive=keep; running=1; termok=0; first=time(0); last=time(0); sock=s; while(!tid); if(MCONTINUE(pcond)) throw((int)0); } void thrServ::Log(const sref& msg) { MLOCK(serv->htcd.mutex); if(sock) serv->htcd.errlog<<"["<address())<<":"<port()<<"][" <htcd.errlog<<"["<htcd.errlog.flush(); } void thrServ::enter() { tid=pthread_self(); MSUSPEND(pmutex,pcond) while(serv->htcd.running&&!termok) { session(); delete sock; sock=0; if(serv->htcd.running&&!termok) { MSUSPEND(pmutex,pcond) } } } void thrServ::session() try { int keep=1; while(sock&&keep&&running) { int test=sock->test(); if(test>0) { last=time(0); keep=handle(); } else if(test<0) keep=0; } } catch(const merror_t& e) { Log(e.desc); } catch(...) { Log(FATAL); } /////////////////////////////////////////////////////////////// thrCron::thrCron(htcServ& server): tid(0),running(0),serv(&server),user(server.user,server.htcd.docroot) { } void thrCron::Log(const sref& msg) { MLOCK(serv->htcd.mutex); serv->htcd.errlog<<"["<htcd.errlog.flush(); } void thrCron::enter() try { tid=pthread_self(); tcpReq tcp; tcp.port=0; httpReq req; mstream devnull; htcd_req R(serv->htcd,user.toks,devnull,tcp,req); Env env(serv->htcd.ops,R,XSYSTEM); env.req->running=&running; running=1; mstream m; env.parse(m,cron_tag); } catch(const merror_t& e) { Log(e.desc); } catch(...) { Log(FATAL); } /////////////////////////////////////////////////////////////// int thrServ::handle() { tcpReq tcp; tcp.port=sock->port(); if(!Lookup(tcp.node,sock->address())) { Log(REJECTED); return 0; } ////////////////////////////////////////////////////////////////// mstring buffer(MAXHEAD+MAXBODY+SAFEZONE); int nhead=sock->gethead(buffer.data(),MAXHEAD); if(nhead==0) return 0; else if(nhead<0) return 0; sref message(buffer.data(),nhead); #if 0 static fp_stream merr(stderr); merr<<"QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ\n"; merr<htcd,user.toks,cache,tcp,req); ////////////////////////////////////////////////////////////////// if(nhead>=MAXHEAD) return SendStatus(*sock,R,keep,HTTP_413); if(eqn(req.method,HTTP_TRACE)) { R.resp.cont_type="message/http"; return SendStatus(*sock,R,keep,HTTP_200,buffer.left(nhead)); } if(req.expect.nempty()) { if(eqn(req.expect,expect_continue_tag)) SendStatus(*sock,R,keep,HTTP_100); else return SendStatus(*sock,R,keep,HTTP_417); } if(req.trans_enc.nempty()||req.cont_enc.nempty()) return SendStatus(*sock,R,0,HTTP_501); ////////////////////////////////////////////////////////////////// int ilength=atoi(req.cont_length); if(ilength>MAXBODY) return SendStatus(*sock,R,0,HTTP_413); else if(ilength>0) { int nbody=sock->getbody(buffer.data()+nhead,ilength); if(nbody<0) return 0; else { sref sbody(buffer.data()+nhead,nbody); #if 0 static fp_stream merr(stderr); merr<<"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP\n"; merr<htcd.ops,R,XSYSTEM); env.req->running=&running; mstream m; env.parse(m,serv->server); if(!env.req->is_running()) THROW("htc: "<