2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #include "private-libwebsockets.h"
23 #include "lextable-strings.h"
25 const unsigned char *lws_token_to_string(enum lws_token_indexes token)
27 if ((unsigned int)token >= ARRAY_SIZE(set))
30 return (unsigned char *)set[token];
34 lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name,
35 const unsigned char *value, int length,
36 unsigned char **p, unsigned char *end)
39 if (wsi->mode == LWSCM_HTTP2_SERVING)
40 return lws_add_http2_header_by_name(wsi, name,
41 value, length, p, end);
46 while (*p < end && *name)
52 if (*p + length + 3 >= end)
55 memcpy(*p, value, length);
63 int lws_finalize_http_header(struct lws *wsi, unsigned char **p,
67 if (wsi->mode == LWSCM_HTTP2_SERVING)
72 if ((long)(end - *p) < 3)
81 lws_add_http_header_by_token(struct lws *wsi, enum lws_token_indexes token,
82 const unsigned char *value, int length,
83 unsigned char **p, unsigned char *end)
85 const unsigned char *name;
87 if (wsi->mode == LWSCM_HTTP2_SERVING)
88 return lws_add_http2_header_by_token(wsi, token, value, length, p, end);
90 name = lws_token_to_string(token);
93 return lws_add_http_header_by_name(wsi, name, value, length, p, end);
96 int lws_add_http_header_content_length(struct lws *wsi,
97 unsigned long content_length,
98 unsigned char **p, unsigned char *end)
103 n = sprintf(b, "%lu", content_length);
104 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
105 (unsigned char *)b, n, p, end))
107 wsi->u.http.content_length = content_length;
108 wsi->u.http.content_remain = content_length;
113 static const char *err400[] = {
119 "Method Not Allowed",
121 "Proxy Auth Required",
126 "Precondition Failed",
127 "Request Entity Too Large",
128 "Request URI too Long",
129 "Unsupported Media Type",
130 "Requested Range Not Satisfiable",
134 static const char *err500[] = {
135 "Internal Server Error",
138 "Service Unavailable",
140 "HTTP Version Not Supported"
144 lws_add_http_header_status(struct lws *wsi, unsigned int code,
145 unsigned char **p, unsigned char *end)
147 unsigned char code_and_desc[60];
148 const char *description = "";
152 if (wsi->mode == LWSCM_HTTP2_SERVING)
153 return lws_add_http2_header_status(wsi, code, p, end);
155 if (code >= 400 && code < (400 + ARRAY_SIZE(err400)))
156 description = err400[code - 400];
157 if (code >= 500 && code < (500 + ARRAY_SIZE(err500)))
158 description = err500[code - 500];
160 n = sprintf((char *)code_and_desc, "HTTP/1.0 %u %s", code, description);
162 return lws_add_http_header_by_name(wsi, NULL, code_and_desc,
167 * lws_return_http_status() - Return simple http status
168 * @wsi: Websocket instance (available from user callback)
169 * @code: Status index, eg, 404
170 * @html_body: User-readable HTML description < 1KB, or NULL
172 * Helper to report HTTP errors back to the client cleanly and
176 lws_return_http_status(struct lws *wsi, unsigned int code,
177 const char *html_body)
179 struct lws_context *context = lws_get_context(wsi);
180 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
181 unsigned char *p = pt->serv_buf + LWS_PRE;
182 unsigned char *start = p, *body = p + 512;
183 unsigned char *end = p + LWS_MAX_SOCKET_IO_BUF - LWS_PRE;
190 len = sprintf((char *)body, "<html><body><h1>%u</h1>%s</body></html>",
193 if (lws_add_http_header_status(wsi, code, &p, end))
195 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER,
196 (unsigned char *)"libwebsockets", 13,
199 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
200 (unsigned char *)"text/html", 9,
203 n = sprintf(slen, "%d", len);
204 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH,
205 (unsigned char *)slen, n,
209 if (lws_finalize_http_header(wsi, &p, end))
212 m = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
213 if (m != (int)(p - start))
216 m = lws_write(wsi, body, len, LWS_WRITE_HTTP);