summaryrefslogtreecommitdiff
path: root/src/net/thrserv.cc
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2011-10-08 20:30:28 +0200
committerHenrik Rydberg <rydberg@euromail.se>2011-10-08 20:30:28 +0200
commit5df79c53745fde5d6c3340a2979b1429cd5892c1 (patch)
tree1a81af141708b826e9c61e8a04019994fcca8298 /src/net/thrserv.cc
Initial import of htcd system 1.0
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'src/net/thrserv.cc')
-rw-r--r--src/net/thrserv.cc255
1 files changed, 255 insertions, 0 deletions
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
23const mstring cron_tag="\\run.cron";
24const mstring FATAL="FATAL ERROR";
25const mstring UNKNOWN="UNKNOWN";
26const mstring REJECTED="REJECTED";
27
28const int MAXHEAD=16384;
29const int MAXBODY=2<<21;
30const int MAXURI=4096;
31const int MAXARG=4096;
32const int SAFEZONE=4096;
33
34///////////////////////////////////////////////////////////////
35
36thrServ::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
47thrServ::~thrServ()
48{
49 delete sock;
50}
51
52void 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
64void 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
74void 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
88void 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}
97catch(const merror_t& e) {
98 Log(e.desc);
99}
100catch(...) {
101 Log(FATAL);
102}
103
104///////////////////////////////////////////////////////////////
105
106thrCron::thrCron(htcServ& server):
107 tid(0),running(0),serv(&server),user(server.user,server.htcd.docroot)
108{
109}
110
111void 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
118void 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}
131catch(const merror_t& e) {
132 Log(e.desc);
133}
134catch(...) {
135 Log(FATAL);
136}
137
138
139///////////////////////////////////////////////////////////////
140
141int 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}