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 == LWS_CONNMODE_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 == LWS_CONNMODE_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 == LWS_CONNMODE_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, (unsigned char *)b, n, p, end))
106 wsi->u.http.content_length = content_length;
107 wsi->u.http.content_remain = content_length;
112 static const char *err400[] = {
118 "Method Not Allowed",
120 "Proxy Auth Required",
125 "Precondition Failed",
126 "Request Entity Too Large",
127 "Request URI too Long",
128 "Unsupported Media Type",
129 "Requested Range Not Satisfiable",
133 static const char *err500[] = {
134 "Internal Server Error",
137 "Service Unavailable",
139 "HTTP Version Not Supported"
143 lws_add_http_header_status(struct lws *wsi,
144 unsigned int code, unsigned char **p,
147 unsigned char code_and_desc[60];
148 const char *description = "";
152 if (wsi->mode == LWS_CONNMODE_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 * @context: libwebsockets context
169 * @wsi: Websocket instance (available from user callback)
170 * @code: Status index, eg, 404
171 * @html_body: User-readable HTML description < 1KB, or NULL
173 * Helper to report HTTP errors back to the client cleanly and
177 lws_return_http_status(struct lws *wsi, unsigned int code, const char *html_body)
180 struct lws_context *context = lws_get_ctx(wsi);
181 unsigned char *p = context->service_buffer +
182 LWS_SEND_BUFFER_PRE_PADDING;
183 unsigned char *start = p;
184 unsigned char *end = p + sizeof(context->service_buffer) -
185 LWS_SEND_BUFFER_PRE_PADDING;
190 if (lws_add_http_header_status(wsi, code, &p, end))
192 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_SERVER,
193 (unsigned char *)"libwebsockets", 13,
196 if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
197 (unsigned char *)"text/html", 9,
200 if (lws_finalize_http_header(wsi, &p, end))
203 m = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS);
204 if (m != (int)(p - start))
207 n = sprintf((char *)start, "<html><body><h1>%u</h1>%s</body></html>",
209 m = lws_write(wsi, start, n, LWS_WRITE_HTTP);