File: http_8c-source.html

package info (click to toggle)
klone 1.1.1.dfsg1-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 6,480 kB
  • ctags: 4,238
  • sloc: ansic: 16,288; makefile: 384; sh: 351
file content (647 lines) | stat: -rw-r--r-- 41,803 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>KLone: http.c Source File</title>
<link href="kl.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.9.1 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class="qindex" href="annotated.html">Data&nbsp;Structures</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Data&nbsp;Fields</a> | <a class="qindex" href="globals.html">Globals</a></div>
<div class="nav">
<a class="el" href="dir_000000.html">src</a>&nbsp;/&nbsp;<a class="el" href="dir_000005.html">libhttp</a></div>
<h1>http.c</h1><a href="http_8c.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment">00001 <span class="comment">/*</span>
00002 <span class="comment"> * Copyright (c) 2005, 2006 by KoanLogic s.r.l. &lt;http://www.koanlogic.com&gt;</span>
00003 <span class="comment"> * All rights reserved.</span>
00004 <span class="comment"> *</span>
00005 <span class="comment"> * This file is part of KLone, and as such it is subject to the license stated</span>
00006 <span class="comment"> * in the LICENSE file which you have received as part of this distribution.</span>
00007 <span class="comment"> *</span>
00008 <span class="comment"> * $Id: http.c,v 1.42 2006/05/27 16:34:01 tat Exp $</span>
00009 <span class="comment"> */</span>
00010 
00011 <span class="preprocessor">#include "klone_conf.h"</span>
00012 <span class="preprocessor">#include &lt;sys/types.h&gt;</span>
00013 <span class="preprocessor">#include &lt;stdlib.h&gt;</span>
00014 <span class="preprocessor">#include &lt;unistd.h&gt;</span>
00015 <span class="preprocessor">#ifdef HAVE_LIBOPENSSL</span>
00016 <span class="preprocessor"></span><span class="preprocessor">#include &lt;openssl/ssl.h&gt;</span>
00017 <span class="preprocessor">#include &lt;openssl/err.h&gt;</span>
00018 <span class="preprocessor">#endif  </span><span class="comment">/* HAVE_LIBOPENSSL */</span>
00019 <span class="preprocessor">#include &lt;u/libu.h&gt;</span>
00020 <span class="preprocessor">#include &lt;<a class="code" href="utils_8h.html">klone/utils.h</a>&gt;</span>
00021 <span class="preprocessor">#include &lt;<a class="code" href="klone_8h.html">klone/klone.h</a>&gt;</span>
00022 <span class="preprocessor">#include &lt;<a class="code" href="server_8h.html">klone/server.h</a>&gt;</span>
00023 <span class="preprocessor">#include &lt;<a class="code" href="broker_8h.html">klone/broker.h</a>&gt;</span>
00024 <span class="preprocessor">#include &lt;<a class="code" href="request_8h.html">klone/request.h</a>&gt;</span>
00025 <span class="preprocessor">#include &lt;<a class="code" href="ses__prv_8h.html">klone/ses_prv.h</a>&gt;</span>
00026 <span class="preprocessor">#include &lt;<a class="code" href="response_8h.html">klone/response.h</a>&gt;</span>
00027 <span class="preprocessor">#include &lt;<a class="code" href="backend_8h.html">klone/backend.h</a>&gt;</span>
00028 <span class="preprocessor">#include &lt;<a class="code" href="io_8h.html">klone/io.h</a>&gt;</span>
00029 <span class="preprocessor">#include &lt;<a class="code" href="timer_8h.html">klone/timer.h</a>&gt;</span>
00030 <span class="preprocessor">#include &lt;<a class="code" href="tls_8h.html">klone/tls.h</a>&gt;</span>
00031 <span class="preprocessor">#include &lt;<a class="code" href="ses__prv_8h.html">klone/ses_prv.h</a>&gt;</span>
00032 <span class="preprocessor">#include "<a class="code" href="http__s_8h.html">http_s.h</a>"</span>
00033 
00034 <span class="keyword">struct </span>http_status_map_s
00035 {
00036     <span class="keywordtype">int</span> status;
00037     <span class="keyword">const</span> <span class="keywordtype">char</span> *desc;
00038 } <a class="code" href="http_8c.html#a0">http_status_map</a>[] = {
00039     { HTTP_STATUS_OK                    , <span class="stringliteral">"OK"</span>                      },
00040     { HTTP_STATUS_NOT_MODIFIED          , <span class="stringliteral">"Not Modified"</span>            },
00041     { HTTP_STATUS_NOT_FOUND             , <span class="stringliteral">"Not Found"</span>               },
00042     { HTTP_STATUS_INTERNAL_SERVER_ERROR , <span class="stringliteral">"Internal Server Error"</span>   },
00043     { HTTP_STATUS_MOVED_PERMANENTLY     , <span class="stringliteral">"Moved Permanently"</span>       },
00044     { HTTP_STATUS_MOVED_TEMPORARILY     , <span class="stringliteral">"Moved Temporarily"</span>       },
00045     { HTTP_STATUS_CREATED               , <span class="stringliteral">"Created"</span>                 },
00046     { HTTP_STATUS_ACCEPTED              , <span class="stringliteral">"Accepted"</span>                },
00047     { HTTP_STATUS_NO_CONTENT            , <span class="stringliteral">"No Content"</span>              },
00048     { HTTP_STATUS_BAD_REQUEST           , <span class="stringliteral">"Bad Request"</span>             },
00049     { HTTP_STATUS_UNAUTHORIZED          , <span class="stringliteral">"Unauthorized"</span>            },
00050     { HTTP_STATUS_FORBIDDEN             , <span class="stringliteral">"Forbidden"</span>               },
00051     { HTTP_STATUS_LENGTH_REQUIRED       , <span class="stringliteral">"Content-Length required"</span> },
00052     { HTTP_STATUS_REQUEST_TOO_LARGE     , <span class="stringliteral">"Request data too big"</span>    },
00053     { HTTP_STATUS_NOT_IMPLEMENTED       , <span class="stringliteral">"Not Implemented"</span>         },
00054     { HTTP_STATUS_BAD_GATEWAY           , <span class="stringliteral">"Bad Gateway"</span>             },
00055     { HTTP_STATUS_SERVICE_UNAVAILABLE   , <span class="stringliteral">"Service Unavailable"</span>     },
00056     { 0                                 , NULL                      }
00057 };
00058 
00059 <span class="comment">/* in cgi.c */</span>
00060 <span class="keywordtype">int</span> <a class="code" href="cgi_8h.html#a0">cgi_set_request</a>(<a class="code" href="request_8h.html#a0">request_t</a> *rq);
00061 
<a name="l00062"></a><a class="code" href="http_8h.html#a26">00062</a> <a class="code" href="structsession__opt__s.html">session_opt_t</a> *<a class="code" href="http_8h.html#a26">http_get_session_opt</a>(<a class="code" href="structhttp__s.html">http_t</a> *http)
00063 {
00064     dbg_return_if (http == NULL, NULL);
00065 
00066     <span class="keywordflow">return</span> http-&gt;<a class="code" href="structhttp__s.html#o7">sess_opt</a>;
00067 }
00068 
<a name="l00069"></a><a class="code" href="http_8h.html#a25">00069</a> u_config_t *<a class="code" href="http_8h.html#a25">http_get_config</a>(<a class="code" href="structhttp__s.html">http_t</a>* http)
00070 {
00071     dbg_return_if (http == NULL, NULL);
00072 
00073     <span class="keywordflow">return</span> http-&gt;<a class="code" href="structhttp__s.html#o0">config</a>;
00074 }
00075 
<a name="l00076"></a><a class="code" href="http_8h.html#a28">00076</a> <span class="keyword">const</span> <span class="keywordtype">char</span> *<a class="code" href="http_8h.html#a28">http_get_status_desc</a>(<span class="keywordtype">int</span> status)
00077 {
00078     <span class="keyword">struct </span>http_status_map_s *map = http_status_map;
00079     <span class="keyword">const</span> <span class="keywordtype">char</span> *msg = <span class="stringliteral">"Unknown Status Code"</span>;
00080 
00081     <span class="keywordflow">for</span>( ; map-&gt;status; ++map)
00082         <span class="keywordflow">if</span>(map-&gt;status == status)
00083         {
00084             msg = map-&gt;desc;
00085             <span class="keywordflow">break</span>;
00086         }
00087 
00088     <span class="keywordflow">return</span> msg;
00089 }
00090 
<a name="l00091"></a><a class="code" href="http_8h.html#a27">00091</a> <span class="keywordtype">int</span> <a class="code" href="http_8h.html#a27">http_alias_resolv</a>(<a class="code" href="structhttp__s.html">http_t</a> *h, <span class="keywordtype">char</span> *dst, <span class="keyword">const</span> <span class="keywordtype">char</span> *filename, size_t sz)
00092 {
00093     <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span> *WP = <span class="stringliteral">" \t"</span>;
00094     u_config_t *config;
00095     <span class="keywordtype">int</span> i;
00096     <span class="keyword">const</span> <span class="keywordtype">char</span> *value;
00097     <span class="keywordtype">char</span> *src, *res, *v = NULL,*pp = NULL;
00098 
00099     dbg_err_if (h == NULL);
00100     dbg_err_if (dst == NULL);
00101     dbg_err_if (filename == NULL);
00102 
00103     <span class="comment">/* for each dir_alias config item */</span>
00104     <span class="keywordflow">for</span>(i = 0; !u_config_get_subkey_nth(h-&gt;<a class="code" href="structhttp__s.html#o0">config</a>, <span class="stringliteral">"dir_alias"</span>, i, &amp;config); 
00105         ++i)
00106     {
00107         <span class="keywordflow">if</span>((value = u_config_get_value(config)) == NULL)
00108             <span class="keywordflow">continue</span>; <span class="comment">/* empty key */</span>
00109 
00110         <span class="comment">/* otherwise strtok_r will modify 'value' */</span>
00111         v = u_strdup(value);
00112         dbg_err_if(v == NULL);
00113 
00114         src = strtok_r(v, WP, &amp;pp); 
00115         dbg_err_if(src == NULL);
00116 
00117         <span class="keywordflow">if</span>(strncmp(src, filename, strlen(src)) == 0)
00118         {
00119             <span class="comment">/* alias found, get resolved prefix */</span>
00120             res = strtok_r(NULL, WP, &amp;pp);
00121             dbg_err_if(res == NULL);
00122 
00123             dbg_err_if(u_path_snprintf(dst, sz, <span class="charliteral">'/'</span>, <span class="stringliteral">"%s/%s"</span>, res, 
00124                         filename + strlen(src)));
00125 
00126             U_FREE(v); 
00127             <span class="keywordflow">return</span> 0;
00128         }
00129 
00130         U_FREE(v);
00131     }
00132 
00133     <span class="comment">/* prepend dir_root */</span>
00134     dbg_err_if(u_path_snprintf(dst, sz, <span class="charliteral">'/'</span>, <span class="stringliteral">"%s/%s"</span>, h-&gt;<a class="code" href="structhttp__s.html#o4">dir_root</a>, filename));
00135 
00136     <span class="keywordflow">return</span> 0;
00137 err:
00138     U_FREE(v);
00139     <span class="keywordflow">return</span> ~0;
00140 }
00141 
00142 <span class="keyword">static</span> <span class="keywordtype">int</span> http_is_valid_uri(<span class="keywordtype">void</span> *arg, <span class="keyword">const</span> <span class="keywordtype">char</span> *buf, size_t len)
00143 {
00144     <span class="keyword">enum</span> { URI_MAX = 2048 };
00145     <span class="keywordtype">char</span> resolved[U_FILENAME_MAX], uri[URI_MAX];
00146     <a class="code" href="structhttp__s.html">http_t</a> *h = (<a class="code" href="structhttp__s.html">http_t</a>*)arg;
00147 
00148     dbg_err_if (arg == NULL);
00149     dbg_err_if (buf == NULL);
00150     
00151     strncpy(uri, buf, len);
00152     uri[len] = 0;
00153 
00154     dbg_err_if(<a class="code" href="http_8h.html#a27">http_alias_resolv</a>(h, resolved, uri, URI_MAX));
00155 
00156     <span class="keywordflow">return</span> <a class="code" href="broker_8h.html#a3">broker_is_valid_uri</a>(h-&gt;<a class="code" href="structhttp__s.html#o1">broker</a>, resolved, strlen(resolved));
00157 err:
00158     <span class="keywordflow">return</span> ~0;
00159 }
00160 
00161 <span class="keyword">static</span> <span class="keywordtype">void</span> http_resolv_request(<a class="code" href="structhttp__s.html">http_t</a> *h, <a class="code" href="request_8h.html#a0">request_t</a> *rq)
00162 {
00163     <span class="keyword">const</span> <span class="keywordtype">char</span> *cstr;
00164     <span class="keywordtype">char</span> resolved[U_FILENAME_MAX];
00165 
00166     dbg_ifb(h == NULL) <span class="keywordflow">return</span>;
00167     dbg_ifb(rq == NULL) <span class="keywordflow">return</span>;
00168     
00169     <span class="comment">/* unalias rq-&gt;filename */</span>
00170     cstr = <a class="code" href="group__request__t.html#ga8">request_get_filename</a>(rq);
00171     <span class="keywordflow">if</span>(cstr &amp;&amp; !<a class="code" href="http_8h.html#a27">http_alias_resolv</a>(h, resolved, cstr, U_FILENAME_MAX))
00172         <a class="code" href="group__request__t.html#ga14">request_set_resolved_filename</a>(rq, resolved);
00173 
00174     <span class="comment">/* unalias rq-&gt;path_info */</span>
00175     cstr = <a class="code" href="group__request__t.html#ga11">request_get_path_info</a>(rq);
00176     <span class="keywordflow">if</span>(cstr &amp;&amp; !<a class="code" href="http_8h.html#a27">http_alias_resolv</a>(h, resolved, cstr, U_FILENAME_MAX))
00177         <a class="code" href="group__request__t.html#ga20">request_set_resolved_path_info</a>(rq, resolved);
00178 }
00179 
00180 <span class="keyword">static</span> <span class="keywordtype">int</span> http_set_index_request(<a class="code" href="structhttp__s.html">http_t</a> *h, <a class="code" href="request_8h.html#a0">request_t</a> *rq)
00181 {
00182     <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span> *indexes[] = { <span class="stringliteral">"/index.klone"</span>, <span class="stringliteral">"/index.kl1"</span>,
00183         <span class="stringliteral">"/index.html"</span>, <span class="stringliteral">"/index.htm"</span>, NULL };
00184     <span class="keyword">const</span> <span class="keywordtype">char</span> **pg;
00185     <span class="keywordtype">char</span> resolved[U_FILENAME_MAX];
00186 
00187     dbg_err_if (h == NULL);
00188     dbg_err_if (rq == NULL);
00189 
00190     <span class="comment">/* user provided index page list (FIXME add list support) */</span>
00191     <span class="keywordflow">if</span>(h-&gt;<a class="code" href="structhttp__s.html#o5">index</a> == NULL)
00192     {   
00193         <span class="comment">/* try to find an index page between default index uris */</span>
00194         <span class="keywordflow">for</span>(pg = indexes; *pg; ++pg)
00195         {
00196             resolved[0] = 0;  <span class="comment">/* for valgrind's happyness */</span>
00197             dbg_err_if(u_path_snprintf(resolved, U_FILENAME_MAX, <span class="charliteral">'/'</span>, <span class="stringliteral">"%s/%s"</span>, 
00198                     <a class="code" href="group__request__t.html#ga50">request_get_resolved_filename</a>(rq), *pg));
00199 
00200             <span class="keywordflow">if</span>(<a class="code" href="broker_8h.html#a3">broker_is_valid_uri</a>(h-&gt;<a class="code" href="structhttp__s.html#o1">broker</a>, resolved, strlen(resolved)))
00201             {
00202                 <span class="comment">/* a valid index uri has been found; rewrite request */</span>
00203                 <a class="code" href="group__request__t.html#ga9">request_set_filename</a>(rq, *pg);
00204                 <span class="keywordflow">break</span>;
00205             }
00206         }
00207         <span class="keywordflow">if</span>(*pg == NULL) <span class="comment">/* no index found, set index.html (will return 404 ) */</span>
00208             dbg_if(<a class="code" href="group__request__t.html#ga9">request_set_filename</a>(rq, <span class="stringliteral">"/index.html"</span>));
00209     } <span class="keywordflow">else</span>
00210         dbg_if(<a class="code" href="group__request__t.html#ga9">request_set_filename</a>(rq, h-&gt;<a class="code" href="structhttp__s.html#o5">index</a>));
00211 
00212     http_resolv_request(h, rq);
00213 
00214     <span class="keywordflow">return</span> 0;
00215 err:
00216     <span class="keywordflow">return</span> ~0;
00217 }
00218 
00219 <span class="keyword">static</span> <span class="keywordtype">int</span> http_add_default_header(<a class="code" href="structhttp__s.html">http_t</a> *h, <a class="code" href="response_8h.html#a0">response_t</a> *rs)
00220 {
00221     time_t now;
00222 
00223     dbg_err_if (h == NULL);
00224     dbg_err_if (rs == NULL);
00225     
00226     <span class="comment">/* set server signature */</span>
00227     dbg_err_if(<a class="code" href="group__response__t.html#ga12">response_set_field</a>(rs, <span class="stringliteral">"Server"</span>, h-&gt;<a class="code" href="structhttp__s.html#o3">server_sig</a>));
00228 
00229     now = time(NULL);
00230     dbg_err_if(<a class="code" href="group__response__t.html#ga15">response_set_date</a>(rs, now));
00231 
00232     <span class="keywordflow">return</span> 0;
00233 err:
00234     <span class="keywordflow">return</span> ~0;
00235 }
00236 
00237 <span class="keyword">static</span> <span class="keywordtype">int</span> http_print_error_page(<a class="code" href="structhttp__s.html">http_t</a> *h, <a class="code" href="request_8h.html#a0">request_t</a> *rq, <a class="code" href="response_8h.html#a0">response_t</a> *rs, 
00238     <span class="keywordtype">int</span> http_status)
00239 {
00240     <span class="keyword">enum</span> { BUFSZ = 64 };
00241     <span class="keyword">const</span> <span class="keywordtype">char</span> *err_page;
00242     <span class="keywordtype">char</span> buf[BUFSZ];
00243     <span class="keywordtype">int</span> rc;
00244 
00245     dbg_err_if (h == NULL);
00246     dbg_err_if (rq == NULL);
00247     dbg_err_if (rs == NULL);
00248     dbg_err_if (http_status == 0);
00249     
00250     <span class="comment">/* clean dirty header fields (not for redirects) */</span>
00251     <span class="keywordflow">if</span>(http_status != 302)
00252         dbg_err_if(<a class="code" href="group__header__t.html#ga1">header_clear</a>(<a class="code" href="group__response__t.html#ga19">response_get_header</a>(rs)));
00253 
00254     <span class="comment">/* add default header fields */</span>
00255     dbg_err_if(http_add_default_header(h, rs));
00256 
00257     <span class="comment">/* disable page caching */</span>
00258     dbg_err_if(<a class="code" href="group__response__t.html#ga1">response_disable_caching</a>(rs));
00259 
00260     <span class="comment">/* looking for user provided error page */</span>
00261     dbg_err_if(u_snprintf(buf, BUFSZ, <span class="stringliteral">"error.%d"</span>, http_status));
00262     err_page = u_config_get_subkey_value(h-&gt;<a class="code" href="structhttp__s.html#o0">config</a>, buf);
00263 
00264     <span class="keywordflow">if</span>(err_page &amp;&amp; !<a class="code" href="group__request__t.html#ga21">request_set_uri</a>(rq, err_page, NULL, NULL))
00265     {
00266         http_resolv_request(h, rq);
00267         <span class="keywordflow">if</span>((rc = <a class="code" href="broker_8h.html#a4">broker_serve</a>(h-&gt;<a class="code" href="structhttp__s.html#o1">broker</a>, rq, rs)) == 0)
00268             <span class="keywordflow">return</span> 0; 
00269         <span class="keywordflow">else</span> {
00270             <span class="comment">/* configured error page not found */</span>
00271             http_status = rc;
00272         }
00273     }
00274 
00275     <span class="comment">/* be sure that the status code is properly set */</span>
00276     <a class="code" href="group__response__t.html#ga22">response_set_status</a>(rs, http_status);
00277 
00278     <a class="code" href="group__response__t.html#ga11">response_print_header</a>(rs);
00279 
00280     <span class="keywordflow">if</span>(<a class="code" href="group__request__t.html#ga49">request_get_method</a>(rq) == HM_HEAD)
00281         <span class="keywordflow">return</span> 0; <span class="comment">/* just the header is requested */</span>
00282 
00283     <span class="comment">/* print default error page */</span>
00284     dbg_err_if(<a class="code" href="group__io__t.html#ga15">io_printf</a>(<a class="code" href="group__response__t.html#ga20">response_io</a>(rs), 
00285         <span class="stringliteral">"&lt;html&gt;&lt;head&gt;&lt;title&gt;%d %s&lt;/title&gt;&lt;/head&gt;\n"</span>
00286         <span class="stringliteral">"&lt;body&gt;&lt;h1&gt;%s&lt;/h1&gt;&lt;p&gt;URL: %s&lt;/body&gt;&lt;/html&gt;"</span>, 
00287         http_status, <a class="code" href="http_8h.html#a28">http_get_status_desc</a>(http_status), 
00288         <a class="code" href="http_8h.html#a28">http_get_status_desc</a>(http_status), 
00289         (<a class="code" href="group__request__t.html#ga7">request_get_uri</a>(rq) ? <a class="code" href="group__request__t.html#ga7">request_get_uri</a>(rq) : <span class="stringliteral">""</span>) ) &lt; 0);
00290 
00291     <span class="keywordflow">return</span> 0;
00292 err:
00293     <span class="keywordflow">return</span> ~0;
00294 }
00295 
00296 <span class="keyword">static</span> <span class="keywordtype">int</span> http_serve(<a class="code" href="structhttp__s.html">http_t</a> *h, <span class="keywordtype">int</span> fd)
00297 {
00298     <a class="code" href="request_8h.html#a0">request_t</a> *rq = NULL;
00299     <a class="code" href="response_8h.html#a0">response_t</a> *rs = NULL;
00300     <a class="code" href="structio__s.html">io_t</a> *in = NULL, *out = NULL;
00301     <span class="keywordtype">int</span> cgi = 0, port;
00302     <span class="keyword">const</span> <span class="keywordtype">char</span> *gwi = NULL;
00303     <a class="code" href="timer_8h.html#a1">talarm_t</a> *al = NULL;
00304     <a class="code" href="structaddr__s.html">addr_t</a> *addr;
00305     <span class="keyword">struct </span>sockaddr sa;
00306     <span class="keywordtype">int</span> sasz, rc = HTTP_STATUS_INTERNAL_SERVER_ERROR;
00307 
00308     dbg_err_if (h == NULL);
00309     dbg_err_if (fd &lt; 0);
00310     
00311     <span class="keywordflow">if</span>(fd == 0 &amp;&amp; (gwi = getenv(<span class="stringliteral">"GATEWAY_INTERFACE"</span>)) != NULL)
00312         cgi++;
00313 
00314     <span class="comment">/* create a request object */</span>
00315     dbg_err_if(<a class="code" href="group__request__t.html#ga54">request_create</a>(h, &amp;rq));
00316     <a class="code" href="group__request__t.html#ga28">request_set_cgi</a>(rq, cgi);
00317 
00318     <span class="comment">/* save local and peer address into the request object */</span>
00319     dbg_err_if(<a class="code" href="addr_8h.html#a1">addr_create</a>(&amp;addr));
00320 
00321     <span class="keywordflow">if</span>(cgi)
00322     {
00323         <span class="keywordflow">if</span>(getenv(<span class="stringliteral">"REMOTE_ADDR"</span>) &amp;&amp; getenv(<span class="stringliteral">"REMOTE_PORT"</span>))
00324         {
00325             port = atoi(getenv(<span class="stringliteral">"REMOTE_PORT"</span>));
00326             dbg_err_if(<a class="code" href="addr_8h.html#a4">addr_set</a>(addr, getenv(<span class="stringliteral">"REMOTE_ADDR"</span>), port));
00327             dbg_err_if(<a class="code" href="group__request__t.html#ga57">request_set_addr</a>(rq, addr));
00328         }
00329 
00330         <span class="keywordflow">if</span>(getenv(<span class="stringliteral">"SERVER_ADDR"</span>))
00331         {
00332             <span class="keywordflow">if</span>(getenv(<span class="stringliteral">"SERVER_PORT"</span>))
00333                 port = atoi(getenv(<span class="stringliteral">"SERVER_PORT"</span>));
00334             <span class="keywordflow">else</span>
00335                 port = 80;
00336             dbg_err_if(<a class="code" href="addr_8h.html#a4">addr_set</a>(addr, getenv(<span class="stringliteral">"SERVER_ADDR"</span>), port));
00337             dbg_err_if(<a class="code" href="group__request__t.html#ga58">request_set_peer_addr</a>(rq, addr));
00338         }
00339     } <span class="keywordflow">else</span> {
00340         <span class="comment">/* set local addr */</span>
00341         sasz = <span class="keyword">sizeof</span>(<span class="keyword">struct </span>sockaddr);
00342         dbg_err_if(getsockname(fd, &amp;sa, &amp;sasz));
00343         dbg_err_if(<a class="code" href="addr_8h.html#a3">addr_set_from_sa</a>(addr, &amp;sa, sasz));
00344         dbg_err_if(<a class="code" href="group__request__t.html#ga57">request_set_addr</a>(rq, addr));
00345 
00346         <span class="comment">/* set peer addr */</span>
00347         sasz = <span class="keyword">sizeof</span>(<span class="keyword">struct </span>sockaddr);
00348         dbg_err_if(getpeername(fd, &amp;sa, &amp;sasz));
00349         dbg_err_if(<a class="code" href="addr_8h.html#a3">addr_set_from_sa</a>(addr, &amp;sa, sasz));
00350         dbg_err_if(<a class="code" href="group__request__t.html#ga58">request_set_peer_addr</a>(rq, addr));
00351     }
00352 
00353     <a class="code" href="addr_8h.html#a7">addr_free</a>(addr);
00354     addr = NULL;
00355 
00356 <span class="preprocessor">#ifdef HAVE_LIBOPENSSL</span>
00357 <span class="preprocessor"></span>    <span class="comment">/* create input io buffer (no IO_FD_CLOSE used because 'out' </span>
00358 <span class="comment">       will close it */</span>
00359     <span class="keywordflow">if</span>(h-&gt;<a class="code" href="structhttp__s.html#o2">ssl</a> &amp;&amp; !cgi)
00360         dbg_err_if(<a class="code" href="iossl_8c.html#a5">io_ssl_create</a>(fd, IO_FD_CLOSE, h-&gt;ssl_ctx, &amp;in));
00361     <span class="keywordflow">else</span>
00362         dbg_err_if(<a class="code" href="io_8h.html#a5">io_fd_create</a>(fd, IO_FD_CLOSE, &amp;in));
00363 <span class="preprocessor">#else</span>
00364 <span class="preprocessor"></span>    <span class="comment">/* create input io buffer */</span>
00365     dbg_err_if(<a class="code" href="io_8h.html#a5">io_fd_create</a>(fd, IO_FD_CLOSE, &amp;in));
00366 <span class="preprocessor">#endif</span>
00367 <span class="preprocessor"></span>
00368     <span class="comment">/* bind the request object to the 'in' io_t */</span>
00369     dbg_err_if(<a class="code" href="group__request__t.html#ga16">request_bind</a>(rq, in));
00370     in = NULL; 
00371 
00372     <span class="comment">/* create a response object */</span>
00373     dbg_err_if(<a class="code" href="group__response__t.html#ga24">response_create</a>(h, &amp;rs));
00374 
00375     <a class="code" href="group__response__t.html#ga8">response_set_cgi</a>(rs, cgi);
00376 
00377     <span class="keywordflow">if</span>(cgi)
00378         dbg_err_if(<a class="code" href="cgi_8h.html#a0">cgi_set_request</a>(rq));
00379 
00380     <span class="comment">/* create the output io_t */</span>
00381     <span class="keywordflow">if</span>(cgi)
00382         dbg_err_if(<a class="code" href="io_8h.html#a5">io_fd_create</a>((cgi ? 1 : fd), IO_FD_CLOSE, &amp;out));
00383     <span class="keywordflow">else</span>
00384         <span class="comment">/* create the response io_t dup'ping the request io_t object */</span>
00385         dbg_err_if(<a class="code" href="group__io__t.html#ga1">io_dup</a>(<a class="code" href="group__request__t.html#ga1">request_io</a>(rq), &amp;out));
00386 
00387     <span class="comment">/* default method used if we cannot parse the request (bad request) */</span>
00388     <a class="code" href="group__response__t.html#ga6">response_set_method</a>(rs, HM_GET);
00389 
00390     <span class="comment">/* bind the response to the connection c */</span>
00391     dbg_err_if(<a class="code" href="group__response__t.html#ga23">response_bind</a>(rs, out));
00392     out = NULL;
00393 
00394     dbg_err_if(rc = <a class="code" href="group__request__t.html#ga48">request_parse_header</a>(rq, http_is_valid_uri, h));
00395 
00396     <a class="code" href="group__response__t.html#ga6">response_set_method</a>(rs, <a class="code" href="group__request__t.html#ga49">request_get_method</a>(rq));
00397 
00398     <span class="comment">/* if we're running in server mode then resolv aliases and dir_root */</span>
00399     http_resolv_request(h, rq);
00400 
00401     <span class="comment">/* if / is requested then return one of index.{klone,kl1,html,htm} */</span>
00402     <span class="keywordflow">if</span>(strcmp(<a class="code" href="group__request__t.html#ga8">request_get_filename</a>(rq), <span class="stringliteral">"/"</span>) == 0)
00403         dbg_err_if(http_set_index_request(h, rq)); <span class="comment">/* set the index page */</span>
00404 
00405     <span class="comment">/* add default header fields */</span>
00406     dbg_err_if(http_add_default_header(h, rs));
00407 
00408     <span class="comment">/* set default successfull status code */</span>
00409     dbg_err_if(<a class="code" href="group__response__t.html#ga22">response_set_status</a>(rs, HTTP_STATUS_OK));
00410 
00411     <span class="comment">/* serve the page; on error write out a simple error page */</span>
00412     dbg_err_if(rc = <a class="code" href="broker_8h.html#a4">broker_serve</a>(h-&gt;<a class="code" href="structhttp__s.html#o1">broker</a>, rq, rs));
00413 
00414     <span class="comment">/* page successfully served */</span>
00415 
00416     <a class="code" href="group__request__t.html#ga56">request_free</a>(rq);
00417     <a class="code" href="group__response__t.html#ga25">response_free</a>(rs); <span class="comment">/* must be free'd after the request object because</span>
00418 <span class="comment">                          the rsfilter references the response object during</span>
00419 <span class="comment">                          the flush of the codec (so the response object must</span>
00420 <span class="comment">                          not be free'd) that happens during the io_free call */</span>
00421     <span class="keywordflow">return</span> 0;
00422 err:
00423     <span class="keywordflow">if</span>(rc &amp;&amp; rq &amp;&amp; rs &amp;&amp; <a class="code" href="group__response__t.html#ga20">response_io</a>(rs))
00424         http_print_error_page(h, rq, rs, rc); <span class="comment">/* print the error page */</span>
00425     <span class="keywordflow">if</span>(in)
00426         <a class="code" href="group__io__t.html#ga12">io_free</a>(in);
00427     <span class="keywordflow">if</span>(out)
00428         <a class="code" href="group__io__t.html#ga12">io_free</a>(out);
00429     <span class="keywordflow">if</span>(rq)
00430         <a class="code" href="group__request__t.html#ga56">request_free</a>(rq);
00431     <span class="keywordflow">if</span>(rs)
00432         <a class="code" href="group__response__t.html#ga25">response_free</a>(rs);
00433     <span class="keywordflow">return</span> ~0;
00434 }
00435 
00436 <span class="keyword">static</span> <span class="keywordtype">int</span> http_free(<a class="code" href="structhttp__s.html">http_t</a> *h)
00437 {
00438     dbg_return_if (h == NULL, 0);   <span class="comment">/* it's ok */</span>
00439 
00440     <span class="keywordflow">if</span>(h-&gt;<a class="code" href="structhttp__s.html#o1">broker</a>)
00441         <a class="code" href="broker_8h.html#a2">broker_free</a>(h-&gt;<a class="code" href="structhttp__s.html#o1">broker</a>);
00442 
00443     U_FREE(h);
00444 
00445     <span class="keywordflow">return</span> 0;
00446 }
00447 
00448 <span class="keyword">static</span> <span class="keywordtype">int</span> http_set_config_opt(<a class="code" href="structhttp__s.html">http_t</a> *http)
00449 {
00450     u_config_t *c = http-&gt;<a class="code" href="structhttp__s.html#o0">config</a>;
00451     <span class="keyword">const</span> <span class="keywordtype">char</span> *v;
00452 
00453     dbg_err_if (http == NULL);
00454     
00455     <span class="comment">/* defaults */</span>
00456     http-&gt;<a class="code" href="structhttp__s.html#o3">server_sig</a> = <span class="stringliteral">"klone/"</span> KLONE_VERSION;
00457     http-&gt;<a class="code" href="structhttp__s.html#o4">dir_root</a> = <span class="stringliteral">""</span>;
00458     http-&gt;<a class="code" href="structhttp__s.html#o5">index</a> = NULL;
00459     http-&gt;<a class="code" href="structhttp__s.html#o6">send_enc_deflate</a> = 0; 
00460 
00461     <span class="comment">/* send_enc_deflate (disable if not configured) */</span>
00462     dbg_err_if(u_config_get_subkey_value_b(c, <span class="stringliteral">"send_enc_deflate"</span>, 0, 
00463         &amp;http-&gt;<a class="code" href="structhttp__s.html#o6">send_enc_deflate</a>));
00464 
00465     <span class="comment">/* server signature */</span>
00466     <span class="keywordflow">if</span>((v = u_config_get_subkey_value(c, <span class="stringliteral">"server_sig"</span>)) != NULL)
00467         http-&gt;<a class="code" href="structhttp__s.html#o3">server_sig</a> = v;
00468 
00469     <span class="comment">/* html dir root */</span>
00470     <span class="keywordflow">if</span>((v = u_config_get_subkey_value(c, <span class="stringliteral">"dir_root"</span>)) != NULL)
00471         http-&gt;<a class="code" href="structhttp__s.html#o4">dir_root</a> = v;
00472 
00473     <span class="comment">/* index page */</span>
00474     <span class="keywordflow">if</span>((v = u_config_get_subkey_value(c, <span class="stringliteral">"index"</span>)) != NULL)
00475         http-&gt;<a class="code" href="structhttp__s.html#o5">index</a> = v;
00476 
00477     <span class="keywordflow">return</span> 0;
00478 err:
00479     <span class="keywordflow">return</span> ~0;
00480 }
00481 
00482 
00483 <span class="keyword">static</span> <span class="keywordtype">int</span> http_create(u_config_t *config, <a class="code" href="structhttp__s.html">http_t</a> **ph)
00484 {
00485     <a class="code" href="structhttp__s.html">http_t</a> *h = NULL;
00486 
00487     dbg_err_if (config == NULL);
00488     dbg_err_if (ph == NULL);
00489 
00490     h = u_zalloc(<span class="keyword">sizeof</span>(<a class="code" href="structhttp__s.html">http_t</a>));
00491     dbg_err_if(h == NULL);
00492 
00493     h-&gt;<a class="code" href="structhttp__s.html#o0">config</a> = config;
00494 
00495     <span class="comment">/* init page broker (and page suppliers) */</span>
00496     dbg_err_if(<a class="code" href="broker_8h.html#a1">broker_create</a>(&amp;h-&gt;<a class="code" href="structhttp__s.html#o1">broker</a>));
00497 
00498     <span class="comment">/* set http struct config opt reading from http-&gt;config */</span>
00499     dbg_err_if(http_set_config_opt(h));
00500 
00501     *ph = h;
00502 
00503     <span class="keywordflow">return</span> 0;
00504 err:
00505     <span class="keywordflow">if</span>(h)
00506         http_free(h);
00507     <span class="keywordflow">return</span> ~0;
00508 }
00509 
<a name="l00510"></a><a class="code" href="http_8c.html#a16">00510</a> <span class="keywordtype">int</span> <a class="code" href="http_8c.html#a16">http_backend_serve</a>(<span class="keyword">struct</span> <a class="code" href="structbackend__s.html">backend_s</a> *be, <span class="keywordtype">int</span> fd)
00511 {
00512     <a class="code" href="structhttp__s.html">http_t</a> *h;
00513     <span class="keywordtype">int</span> rc;
00514 
00515     dbg_err_if (be == NULL);
00516     dbg_err_if (be-&gt;<a class="code" href="structbackend__s.html#o9">arg</a> == NULL);
00517     dbg_err_if (fd &lt; 0);
00518     
00519     h = (<a class="code" href="structhttp__s.html">http_t</a> *) be-&gt;<a class="code" href="structbackend__s.html#o9">arg</a>;
00520     
00521     <span class="comment">/* new connection accepted on http listening socket, handle it */</span>
00522     dbg_if((rc = http_serve(h, fd)) != 0);
00523 
00524     <span class="keywordflow">return</span> rc;
00525 err:
00526     <span class="keywordflow">return</span> ~0;
00527 }
00528 
<a name="l00529"></a><a class="code" href="http_8c.html#a17">00529</a> <span class="keywordtype">int</span> <a class="code" href="http_8c.html#a17">http_backend_term</a>(<span class="keyword">struct</span> <a class="code" href="structbackend__s.html">backend_s</a> *be)
00530 {
00531     <a class="code" href="structhttp__s.html">http_t</a> *http;
00532 
00533     dbg_return_if (be == NULL, 0);
00534     dbg_return_if (be-&gt;<a class="code" href="structbackend__s.html#o9">arg</a> == NULL, 0);
00535 
00536     http = (<a class="code" href="structhttp__s.html">http_t</a> *) be-&gt;<a class="code" href="structbackend__s.html#o9">arg</a>;
00537 
00538     dbg_err_if(<a class="code" href="ses__prv_8h.html#a30">session_module_term</a>(http-&gt;<a class="code" href="structhttp__s.html#o7">sess_opt</a>));
00539 
00540     http_free(http);
00541 
00542     <span class="keywordflow">return</span> 0;
00543 err:
00544     <span class="keywordflow">return</span> ~0;
00545 }
00546 
<a name="l00547"></a><a class="code" href="http_8c.html#a18">00547</a> <span class="keywordtype">int</span> <a class="code" href="http_8c.html#a18">http_backend_init</a>(<span class="keyword">struct</span> <a class="code" href="structbackend__s.html">backend_s</a> *be)
00548 {
00549     <a class="code" href="structhttp__s.html">http_t</a> *http = NULL;
00550     <a class="code" href="broker_8h.html#a0">broker_t</a> *broker = NULL;
00551 
00552     dbg_err_if (be == NULL);
00553  
00554     dbg_err_if(http_create(be-&gt;<a class="code" href="structbackend__s.html#o5">config</a>, &amp;http));
00555 
00556     be-&gt;<a class="code" href="structbackend__s.html#o9">arg</a> = http;
00557 
00558     dbg_err_if(<a class="code" href="ses__prv_8h.html#a26">session_module_init</a>(http-&gt;<a class="code" href="structhttp__s.html#o0">config</a>, &amp;http-&gt;<a class="code" href="structhttp__s.html#o7">sess_opt</a>));
00559 
00560     <span class="keywordflow">return</span> 0;
00561 err:
00562     <span class="keywordflow">if</span>(http)
00563         http_free(http);
00564     <span class="keywordflow">if</span>(broker)
00565         <a class="code" href="broker_8h.html#a2">broker_free</a>(broker);
00566     <span class="keywordflow">return</span> ~0;
00567 }
00568 
00569 <span class="preprocessor">#ifdef HAVE_LIBOPENSSL</span>
00570 <span class="preprocessor"></span><span class="keywordtype">int</span> https_backend_init(<span class="keyword">struct</span> <a class="code" href="structbackend__s.html">backend_s</a> *be)
00571 {
00572     <a class="code" href="structhttp__s.html">http_t</a> *https;
00573     tls_ctx_args_t *cargs;
00574 
00575     dbg_err_if (be == NULL);
00576 
00577     dbg_err_if(<a class="code" href="http_8c.html#a18">http_backend_init</a>(be));
00578 
00579     https = (<a class="code" href="structhttp__s.html">http_t</a> *) be-&gt;<a class="code" href="structbackend__s.html#o9">arg</a>;
00580 
00581     <span class="comment">/* turn on SSL encryption */</span>
00582     https-&gt;<a class="code" href="structhttp__s.html#o2">ssl</a> = 1;
00583 
00584     <span class="comment">/* load config values and set SSL_CTX accordingly */</span>
00585     dbg_err_if (tls_load_ctx_args(<a class="code" href="http_8h.html#a25">http_get_config</a>(https), &amp;cargs));
00586     warn_err_ifm (!(https-&gt;ssl_ctx = tls_init_ctx(cargs)), 
00587         <span class="stringliteral">"bad or missing HTTPS credentials"</span>);
00588 
00589     dbg_err_if(<a class="code" href="ses__prv_8h.html#a26">session_module_init</a>(https-&gt;<a class="code" href="structhttp__s.html#o0">config</a>, &amp;https-&gt;<a class="code" href="structhttp__s.html#o7">sess_opt</a>));
00590 
00591     <span class="keywordflow">return</span> 0;
00592 err:
00593     <span class="keywordflow">return</span> ~0;
00594 }
00595 
00596 <span class="keywordtype">int</span> https_backend_term(<span class="keyword">struct</span> <a class="code" href="structbackend__s.html">backend_s</a> *be)
00597 {
00598     <a class="code" href="structhttp__s.html">http_t</a> *https;
00599 
00600     dbg_err_if (be == NULL);
00601 
00602     https = (<a class="code" href="structhttp__s.html">http_t</a> *) be-&gt;<a class="code" href="structbackend__s.html#o9">arg</a>;
00603     <span class="keywordflow">if</span> (https == NULL)
00604         <span class="keywordflow">return</span> 0;
00605 
00606     SSL_CTX_free(https-&gt;ssl_ctx);
00607 
00608     <span class="keywordflow">return</span> <a class="code" href="http_8c.html#a17">http_backend_term</a>(be); 
00609 err:
00610     <span class="keywordflow">return</span> ~0;
00611 }
00612 
00613 <span class="comment">/* same http functions but different '_init' */</span>
00614 <a class="code" href="structbackend__s.html">backend_t</a> be_https =
00615     <a class="code" href="backend_8h.html#a0">BACKEND_STATIC_INITIALIZER</a>( <span class="stringliteral">"https"</span>, 
00616         https_backend_init, 
00617         http_backend_serve, 
00618         https_backend_term );
00619 <span class="preprocessor">#endif </span><span class="comment">/* HAVE_LIBOPENSSL */</span>
00620 
<a name="l00621"></a><a class="code" href="http_8c.html#a1">00621</a> <a class="code" href="structbackend__s.html">backend_t</a> <a class="code" href="backend_8c.html#a0">be_http</a> =
00622     <a class="code" href="backend_8h.html#a0">BACKEND_STATIC_INITIALIZER</a>( <span class="stringliteral">"http"</span>, 
00623         http_backend_init, 
00624         http_backend_serve, 
00625         http_backend_term );
00626 
</pre></div><hr>
<div> 
  <div style="text-align:left">
    <a href="http://www.koanlogic.com/kl/cont/gb/html/products.html">&larr;Products</a>
  </div>
  <div style="text-align:center;">
    &copy; 2005-2006 - <a href="http://www.koanlogic.com">KoanLogic S.r.l.</a> - All rights reserved
  </div>
</div>

</body>
</html>