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