source: uKadecot/trunk/uip/apps/webserver/http_pcb.c@ 108

Last change on this file since 108 was 108, checked in by coas-nagasima, 9 years ago

MIMEプロパティの変更

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-chdr; charset=SHIFT_JIS
File size: 6.4 KB
Line 
1/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 */
21
22#include "httpd.h"
23#include "http_pcb.h"
24#include <string.h>
25#include <stdlib.h>
26
27#define TRUE 1
28#define FALSE 0
29
30#ifndef _MSC_VER
31/* strnlen() is a POSIX.2008 addition. Can't rely on it being available so
32 * define it ourselves.
33 */
34size_t
35strnlen(const char *s, size_t maxlen)
36{
37 const char *p;
38
39 p = memchr(s, '\0', maxlen);
40 if (p == NULL)
41 return maxlen;
42
43 return p - s;
44}
45#endif
46
47size_t
48strlncat(char *dst, size_t len, const char *src, size_t n)
49{
50 size_t slen;
51 size_t dlen;
52 size_t rlen;
53 size_t ncpy;
54
55 slen = strnlen(src, n);
56 dlen = strnlen(dst, len);
57
58 if (dlen < len) {
59 rlen = len - dlen;
60 ncpy = slen < rlen ? slen : (rlen - 1);
61 memcpy(dst + dlen, src, ncpy);
62 dst[dlen + ncpy] = '\0';
63 }
64
65 assert(len > slen + dlen);
66 return slen + dlen;
67}
68
69int
70websvr_request_url(http_parser *p, const char *buf, size_t len)
71{
72 struct httpd_state *context = get_context(p);
73 strlncat(context->message.request_url,
74 sizeof(context->message.request_url),
75 buf,
76 len);
77 return 0;
78}
79
80int
81websvr_header_field(http_parser *p, const char *buf, size_t len)
82{
83 struct httpd_state *context = get_context(p);
84 struct message *m = &context->message;
85
86 if (strncmp("Referer", buf, len) == 0) {
87 m->num_headers = 1;
88 } else if (strncmp("Host", buf, len) == 0) {
89 m->num_headers = 2;
90 } else if (strncmp("Upgrade", buf, len) == 0) {
91 m->num_headers = 3;
92 } else if (strncmp("Connection", buf, len) == 0) {
93 m->num_headers = 4;
94 } else if (strncmp("Sec-WebSocket-Key", buf, len) == 0) {
95 m->num_headers = 5;
96 } else if (strncmp("Origin", buf, len) == 0) {
97 m->num_headers = 6;
98 } else if (strncmp("Sec-WebSocket-Protocol", buf, len) == 0) {
99 m->num_headers = 7;
100 } else if (strncmp("Sec-WebSocket-Version", buf, len) == 0) {
101 m->num_headers = 8;
102 } else {
103 m->num_headers = 0;
104 }
105
106 return 0;
107}
108
109int
110websvr_header_value(http_parser *p, const char *buf, size_t len)
111{
112 struct httpd_state *context = get_context(p);
113 struct message *m = &context->message;
114
115 switch (m->num_headers) {
116 case 1:
117 strlncat(m->referer, sizeof(m->referer), buf, len);
118 break;
119 case 2:
120 strlncat(m->host, sizeof(m->host), buf, len);
121 break;
122 case 3:
123 strlncat(m->upgrade, sizeof(m->upgrade), buf, len);
124 break;
125 case 4:
126 strlncat(m->connection, sizeof(m->connection), buf, len);
127 break;
128 case 5:
129 strlncat(m->sec_websocket_key, sizeof(m->sec_websocket_key), buf, len);
130 break;
131 case 6:
132 strlncat(m->origin, sizeof(m->origin), buf, len);
133 break;
134 case 7:
135 strlncat(m->sec_websocket_protocol, sizeof(m->sec_websocket_protocol), buf, len);
136 break;
137 case 8:
138 strlncat(m->sec_websocket_version, sizeof(m->sec_websocket_version), buf, len);
139 break;
140 }
141
142 return 0;
143}
144
145void
146websvr_check_body_is_final(const http_parser *p)
147{
148 struct httpd_state *context = get_context(p);
149 if (context->message.body_is_final) {
150 printf("\n\n *** Error http_body_is_final() should return 1 "
151 "on last on_body callback call "
152 "but it doesn't! ***\n\n");
153 assert(0);
154 }
155 context->message.body_is_final = http_body_is_final(p);
156}
157
158int
159websvr_body(http_parser *p, const char *buf, size_t len)
160{
161 struct httpd_state *context = get_context(p);
162 strlncat(context->message.body,
163 sizeof(context->message.body),
164 buf,
165 len);
166 context->message.body_size += len;
167 websvr_check_body_is_final(p);
168 // printf("websvr_body: '%s'\n", requests[num_messages].body);
169 return 0;
170}
171
172int
173websvr_count_body(http_parser *p, const char *buf, size_t len)
174{
175 struct httpd_state *context = get_context(p);
176 assert(buf);
177 context->message.body_size += len;
178 websvr_check_body_is_final(p);
179 return 0;
180}
181
182int
183websvr_message_begin(http_parser *p)
184{
185 struct httpd_state *context = get_context(p);
186 context->message.message_begin_cb_called = TRUE;
187 return 0;
188}
189
190int
191websvr_headers_complete(http_parser *p)
192{
193 struct httpd_state *context = get_context(p);
194 context->message.method = p->method;
195 context->message.http_major = p->http_major;
196 context->message.http_minor = p->http_minor;
197 context->message.headers_complete_cb_called = TRUE;
198 context->message.should_keep_alive = http_should_keep_alive(p);
199 return 0;
200}
201
202int
203websvr_message_complete(http_parser *p)
204{
205 struct httpd_state *context = get_context(p);
206 if (context->message.should_keep_alive != http_should_keep_alive(p)) {
207 printf("\n\n *** Error http_should_keep_alive() should have same "
208 "value in both on_message_complete and on_headers_complete "
209 "but it doesn't! ***\n\n");
210 assert(0);
211 }
212
213 if (context->message.body_size &&
214 http_body_is_final(p) &&
215 !context->message.body_is_final) {
216 printf("\n\n *** Error http_body_is_final() should return 1 "
217 "on last on_body callback call "
218 "but it doesn't! ***\n\n");
219 assert(0);
220 }
221
222 context->message.message_complete_cb_called = TRUE;
223 return 0;
224}
225
226int
227websvr_response_status(http_parser *p, const char *buf, size_t len)
228{
229 struct httpd_state *context = get_context(p);
230 strlncat(context->message.response_status,
231 sizeof(context->message.response_status),
232 buf,
233 len);
234 return 0;
235}
236
237http_parser_settings websvr_settings =
238{
239 websvr_message_begin,
240 websvr_request_url,
241 websvr_response_status,
242 websvr_header_field,
243 websvr_header_value,
244 websvr_headers_complete,
245 websvr_body,
246 websvr_message_complete,
247};
248
Note: See TracBrowser for help on using the repository browser.