1 /* http.c - Hyper Text Transfer Protocol, 1.0
2 * Copyright (c) 2006,2012 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
3 * This is confidential unpublished proprietary source code of the author.
4 * NO WARRANTY, not even implied warranties. Contains trade secrets.
5 * Distribution prohibited unless authorized in writing. See file COPYING.
6 * Special grant: http.c may be used with zxid open source project under
7 * same licensing terms as zxid itself.
8 * $Id$
9 *
10 * 15.4.2006, started work over Easter holiday --Sampo
11 * 16.8.2012, modified license grant to allow use with ZXID.org --Sampo
12 */
13
14 #include "platform.h"
15 #include "errmac.h"
16 #include "akbox.h"
17 #include "hiios.h"
18
19 #include <ctype.h>
20 #include <memory.h>
21 #include <netinet/in.h> /* htons(3) and friends */
22
23 /* Called by: http_send_data, http_send_err, http_send_file */
http_encode_start(struct hi_thr * hit)24 struct hi_pdu* http_encode_start(struct hi_thr* hit)
25 {
26 struct hi_pdu* resp = hi_pdu_alloc(hit, "http-enc-start");
27 if (!resp) { hi_dump(hit->shf); NEVERNEVER("*** out of pdus in bad place %d", 0); }
28 return resp;
29 }
30
31 /* Called by: http_decode */
http_send_err(struct hi_thr * hit,struct hi_io * io,struct hi_pdu * req,int r,char * m)32 void http_send_err(struct hi_thr* hit, struct hi_io* io, struct hi_pdu* req, int r, char* m)
33 {
34 struct hi_pdu* resp = http_encode_start(hit);
35 resp->need = sprintf(resp->m, "HTTP/1.0 %03d %s\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s", r, m, (int)strlen(m), m);
36 hi_send(hit, io, 0, req, resp);
37 }
38
39 /* Called by: http_decode */
http_send_data(struct hi_thr * hit,struct hi_io * io,struct hi_pdu * req,int len,char * d)40 void http_send_data(struct hi_thr* hit, struct hi_io* io, struct hi_pdu* req, int len, char* d)
41 {
42 //struct hi_pdu* resp = http_encode_start(hit);
43 /*hi_sendv(hit, io, 0, req, resp, len, resp->m, size, req->m + len);*/
44 }
45
46 /* Called by: http_decode */
http_send_file(struct hi_thr * hit,struct hi_io * io,struct hi_pdu * req,int len,char * d)47 void http_send_file(struct hi_thr* hit, struct hi_io* io, struct hi_pdu* req, int len, char* d)
48 {
49 //struct hi_pdu* resp = http_encode_start(hit);
50 /*hi_sendv(hit, io, 0, req, resp, len, resp->m, size, req->m + len);*/
51 }
52
53 #define HTTP_MIN_PDU_SIZE ((int)sizeof("GET / HTTP/1.0\n\n")-1)
54
55 /* Called by: */
http_decode(struct hi_thr * hit,struct hi_io * io)56 int http_decode(struct hi_thr* hit, struct hi_io* io)
57 {
58 struct hi_pdu* req = io->cur_pdu;
59 char* url;
60 char* url_lim = 0;
61 char* p = req->m;
62 int n = req->ap - p;
63
64 if (n < HTTP_MIN_PDU_SIZE) { /* too little, need more */
65 req->need = HTTP_MIN_PDU_SIZE - n;
66 return 0;
67 }
68
69 if (memcmp(p, "GET /", sizeof("GET /")-1)) {
70 ERR("Not a GET HTTP PDU. fd(%x). Got(%.*s)", io->fd, HTTP_MIN_PDU_SIZE, req->m);
71 return HI_CONN_CLOSE;
72 }
73
74 for (p += 5; p < req->ap - (sizeof(" HTTP/1.0")-2); ++p)
75 if (!memcmp(p, " HTTP/1.0\n", sizeof(" HTTP/1.0")-1)) {
76 /* Found end of URL */
77 url = req->m + 4;
78 url_lim = p;
79 break;
80 }
81
82 if (!url_lim) {
83 req->need = 1;
84 return 0;
85 }
86 /* *** Proper processing of content-length and setting need to length of PDU is still needed. */
87 D("need=%d len=%d buf(%.*s)", req->need, (int)(req->ap-req->m), (int)(req->ap-req->m), req->m);
88
89 hi_add_to_reqs(hit, io, req, HTTP_MIN_PDU_SIZE);
90
91 /* 01234567890
92 * GET / HTTP/1.0 */
93 switch (req->m[6]) {
94 case 'a': http_send_data(hit, io, req, url_lim-url, url); break;
95 case 'b': http_send_file(hit, io, req, url_lim-url, url); break; /* *** */
96 default: http_send_err(hit, io, req, 500, "Error"); break;
97 }
98 return HI_CONN_CLOSE; /* HTTP/1.0 without keep-alive: close connection after every req-resp */
99 }
100
101 /* EOF -- http.c */
102