src/server/protocol.c

changeset 4
998844b5ed25
child 7
3c2ed7a7a5fd
equal deleted inserted replaced
3:137197831306 4:998844b5ed25
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2011 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "protocol.h"
30
31 #include "pblock.h"
32 #include "pool.h"
33 #include "session.h"
34 #include "io.h"
35
36
37
38
39 void protocol_status(Session *sn, Request *rq, int n, const char *m) {
40 rq->status_num = n;
41
42 const char *msg = m ? m : protocol_status_message(n);
43
44 pb_param *pp = pblock_removekey(pb_key_status, rq->srvhdrs);
45 if (pp != NULL) {
46 param_free(pp);
47 }
48
49 pp = pblock_key_param_create(rq->srvhdrs, pb_key_status, msg, strlen(msg));
50 pblock_kpinsert(pb_key_status, pp, rq->srvhdrs);
51 }
52
53
54 /*
55 * http_status_message from Open Webserver (frame/http.cpp)
56 * TODO: replace, use sstr_t
57 */
58 NSAPI_PUBLIC const char * protocol_status_message (int code)
59 {
60 const char *r;
61
62 switch (code)
63 {
64 case PROTOCOL_CONTINUE : // 100
65 r = "Continue";
66 break;
67 case PROTOCOL_SWITCHING: //101
68 r = "Switching Protocols";
69 break;
70 case PROTOCOL_OK: // 200
71 r = "OK";
72 break;
73 case PROTOCOL_CREATED: // 201
74 r = "Created";
75 break;
76 case PROTOCOL_ACCEPTED: // 202
77 r = "Accepted";
78 break;
79 case PROTOCOL_NONAUTHORITATIVE: // 203
80 r = "Non-Authoritative Information";
81 break;
82 case PROTOCOL_NO_CONTENT: //204
83 /* There is another define to PROTOCOL_NO_RESPONSE for 204 in nsapi.h
84 The spec maps this to No Content.
85 Hence cahnging this to No Content
86 */
87 r = "No Content";
88 break;
89 case PROTOCOL_RESET_CONTENT: // 205
90 r = "Reset Content";
91 break;
92 case PROTOCOL_PARTIAL_CONTENT: // 206
93 r = "Partial Content";
94 break;
95 case PROTOCOL_MULTI_STATUS: // 207
96 r = "Multi Status";
97 break;
98 case PROTOCOL_MULTIPLE_CHOICES: // 300
99 r = "Multiple Choices";
100 break;
101 case PROTOCOL_MOVED_PERMANENTLY: // 301
102 r = "Moved Permanently";
103 break;
104 case PROTOCOL_REDIRECT: // 302
105 r = "Moved Temporarily"; /* The spec actually says "Found" */
106 break;
107 case PROTOCOL_SEE_OTHER: // 303
108 r = "See Other";
109 break;
110 case PROTOCOL_NOT_MODIFIED: // 304
111 r = "Use local copy"; /* The spec actually says "Not Modified" */
112 break;
113 case PROTOCOL_USE_PROXY: // 305
114 r = "Use Proxy";
115 break;
116 case PROTOCOL_TEMPORARY_REDIRECT: // 307
117 r = "Temporary Redirect";
118 break;
119 case PROTOCOL_BAD_REQUEST: // 400
120 r = "Bad request";
121 break;
122 case PROTOCOL_UNAUTHORIZED: // 401
123 r = "Unauthorized";
124 break;
125 case PROTOCOL_PAYMENT_REQUIRED: // 402
126 r = "Payment Required";
127 break;
128 case PROTOCOL_FORBIDDEN: // 403
129 r = "Forbidden";
130 break;
131 case PROTOCOL_NOT_FOUND: // 404
132 r = "Not found";
133 break;
134 case PROTOCOL_METHOD_NOT_ALLOWED: // 405 /* HTTP/1.1 */
135 r = "Method Not Allowed";
136 break;
137 case PROTOCOL_NOT_ACCEPTABLE: // 406 /* HTTP/1.1 */
138 r = "Not Acceptable";
139 break;
140 case PROTOCOL_PROXY_UNAUTHORIZED: // 407
141 r = "Proxy Authentication Required";
142 break;
143 case PROTOCOL_REQUEST_TIMEOUT: // 408 /* HTTP/1.1 */
144 r = "Request Timeout";
145 break;
146 case PROTOCOL_CONFLICT: // 409
147 r = "Conflict"; /* HTTP/1.1 */
148 break;
149 case PROTOCOL_GONE: // 410
150 r = "Gone"; /* HTTP/1.1 */
151 break;
152 case PROTOCOL_LENGTH_REQUIRED: // 411 /* HTTP/1.1 */
153 r = "Length Required";
154 break;
155 case PROTOCOL_PRECONDITION_FAIL: // 412 /* HTTP/1.1 */
156 r = "Precondition Failed";
157 break;
158 case PROTOCOL_ENTITY_TOO_LARGE: // 413 /* HTTP/1.1 */
159 r = "Request Entity Too Large";
160 break;
161 case PROTOCOL_URI_TOO_LARGE: // 414 /* HTTP/1.1 */
162 r = "Request-URI Too Large";
163 break;
164 case PROTOCOL_UNSUPPORTED_MEDIA_TYPE: // 415
165 r = "Unsupported Media Type";
166 break;
167 case PROTOCOL_REQUESTED_RANGE_NOT_SATISFIABLE: // 416
168 r = "Requested range not satisfiable";
169 break;
170 case PROTOCOL_EXPECTATION_FAILED: // 417
171 r = "Expectation Failed";
172 break;
173 case PROTOCOL_LOCKED: // 423
174 r = "Locked";
175 break;
176 case PROTOCOL_FAILED_DEPENDENCY: // 424
177 r = "Failed Dependency";
178 break;
179 case PROTOCOL_SERVER_ERROR: // 500
180 r = "Server Error"; /* The spec actually says "Internal Server Error" */
181 break;
182 case PROTOCOL_NOT_IMPLEMENTED: // 501
183 r = "Not Implemented";
184 break;
185 case PROTOCOL_BAD_GATEWAY: // 502
186 r = "Bad Gateway";
187 break;
188 case PROTOCOL_SERVICE_UNAVAILABLE: // 503
189 r = "Service Unavailable";
190 break;
191 case PROTOCOL_GATEWAY_TIMEOUT: // 504 /* HTTP/1.1 */
192 r = "Gateway Timeout";
193 break;
194 case PROTOCOL_VERSION_NOT_SUPPORTED: // 505 /* HTTP/1.1 */
195 r = "HTTP Version Not Supported";
196 break;
197 case PROTOCOL_INSUFFICIENT_STORAGE: // 507
198 r = "Insufficient Storage";
199 break;
200 default:
201 switch (code / 100)
202 {
203 case 1:
204 r = "Information";
205 break;
206 case 2:
207 r = "Success";
208 break;
209 case 3:
210 r = "Redirect";
211 break;
212 case 4:
213 r = "Client error";
214 break;
215 case 5:
216 r = "Server error";
217 break;
218 default:
219 r = "Unknown reason";
220 break;
221 }
222 break;
223 }
224
225 return r;
226 }
227
228
229 void add_http_status_line(iovec_buf_t *out, Request *rq) {
230 iovec_buf_write(out, "HTTP/1.1 ", 9);
231
232 char *status_code_str = pool_malloc(out->pool, 8);
233 int sc_len = snprintf(status_code_str, 8, "%d ", rq->status_num);
234 iovec_buf_write(out, status_code_str, sc_len);
235
236 char *scmsg = pblock_findkeyval(pb_key_status, rq->srvhdrs);
237 iovec_buf_write(out, scmsg, strlen(scmsg));
238
239 iovec_buf_write(out, "\r\n", 2);
240 }
241
242 int http_start_response(Session *sn, Request *rq) {
243 int fd = ((SystemIOStream*)sn->csd)->fd;
244
245 /* set socket blocking */
246 int flags;
247 flags = fcntl(fd, F_GETFL, 0);
248 fcntl(fd, F_SETFL, flags ^ O_NONBLOCK);
249
250 /* iovec output buffer */
251 iovec_buf_t *out = iovec_buf_create(sn->pool);
252
253 /* add the http status line to the output buffer */
254 add_http_status_line(out, rq);
255
256 /* add server header */
257 iovec_buf_write(out, "Server: WS uap-dev\r\n", 20);
258
259 // TODO: add header from rq->srvhdrs
260 iovec_buf_write(out, "\r\n", 2);
261
262 /* flush buffer to the socket */
263 iovec_buf_flush(out, fd);
264
265 rq->senthdrs = 1;
266 }
267
268

mercurial