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"
29 libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi)
33 /* fetch the per-frame nonce */
35 n = libwebsockets_get_random(wsi->protocol->owning_server,
36 wsi->frame_masking_nonce_04, 4);
38 lwsl_parser("Unable to read from random device %s %d\n",
39 SYSTEM_RANDOM_FILEPATH, n);
43 /* start masking from first byte of masking key buffer */
44 wsi->frame_mask_index = 0;
51 void lwsl_hexdump(void *vbuf, size_t len)
56 unsigned char *buf = (unsigned char *)vbuf;
62 for (n = 0; n < len;) {
66 p += sprintf(p, "%04X: ", start);
68 for (m = 0; m < 16 && n < len; m++)
69 p += sprintf(p, "%02X ", buf[n++]);
75 for (m = 0; m < 16 && (start + m) < len; m++) {
76 if (buf[start + m] >= ' ' && buf[start + m] < 127)
77 *p++ = buf[start + m];
86 lwsl_debug("%s", line);
93 int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)
96 #ifndef LWS_NO_EXTENSIONS
100 * one of the extensions is carrying our data itself? Like mux?
103 for (n = 0; n < wsi->count_active_extensions; n++) {
105 * there can only be active extensions after handshake completed
106 * so we can rely on protocol being set already in here
108 m = wsi->active_extensions[n]->callback(
109 wsi->protocol->owning_server,
110 wsi->active_extensions[n], wsi,
111 LWS_EXT_CALLBACK_PACKET_TX_DO_SEND,
112 wsi->active_extensions_user[n], &buf, len);
114 lwsl_ext("Extension reports fatal error\n");
117 if (m) /* handled */ {
118 /* lwsl_ext("ext sent it\n"); */
124 lwsl_warn("** error 0 sock but expected to send\n");
127 * nope, send it on the socket directly
132 lws_hexdump(buf, len);
135 #ifdef LWS_OPENSSL_SUPPORT
137 n = SSL_write(wsi->ssl, buf, len);
139 lwsl_debug("ERROR writing to socket\n");
144 n = send(wsi->sock, buf, len, MSG_NOSIGNAL);
146 lwsl_debug("ERROR writing len %d to socket %d\n", len, n);
149 #ifdef LWS_OPENSSL_SUPPORT
155 #ifdef LWS_NO_EXTENSIONS
157 lws_issue_raw_ext_access(struct libwebsocket *wsi,
158 unsigned char *buf, size_t len)
160 return lws_issue_raw(wsi, buf, len);
164 lws_issue_raw_ext_access(struct libwebsocket *wsi,
165 unsigned char *buf, size_t len)
168 struct lws_tokens eff_buf;
172 eff_buf.token = (char *)buf;
173 eff_buf.token_len = len;
176 * while we have original buf to spill ourselves, or extensions report
177 * more in their pipeline
183 /* default to nobody has more to spill */
187 /* show every extension the new incoming data */
189 for (n = 0; n < wsi->count_active_extensions; n++) {
190 m = wsi->active_extensions[n]->callback(
191 wsi->protocol->owning_server,
192 wsi->active_extensions[n], wsi,
193 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
194 wsi->active_extensions_user[n], &eff_buf, 0);
196 lwsl_ext("Extension: fatal error\n");
201 * at least one extension told us he has more
202 * to spill, so we will go around again after
207 /* assuming they left us something to send, send it */
209 if (eff_buf.token_len)
210 if (lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
214 lwsl_parser("written %d bytes to client\n", eff_buf.token_len);
216 /* no extension has more to spill */
221 /* we used up what we had */
223 eff_buf.token = NULL;
224 eff_buf.token_len = 0;
227 * Did that leave the pipe choked?
230 if (!lws_send_pipe_choked(wsi))
231 /* no we could add more */
234 lwsl_debug("choked\n");
237 * Yes, he's choked. Don't spill the rest now get a callback
238 * when he is ready to send and take care of it there
240 libwebsocket_callback_on_writable(
241 wsi->protocol->owning_server, wsi);
242 wsi->extension_data_pending = 1;
251 * libwebsocket_write() - Apply protocol then write data to client
252 * @wsi: Websocket instance (available from user callback)
253 * @buf: The data to send. For data being sent on a websocket
254 * connection (ie, not default http), this buffer MUST have
255 * LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
256 * and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
257 * in the buffer after (buf + len). This is so the protocol
258 * header and trailer data can be added in-situ.
259 * @len: Count of the data bytes in the payload starting from buf
260 * @protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one
261 * of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
262 * data on a websockets connection. Remember to allow the extra
263 * bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
266 * This function provides the way to issue data back to the client
267 * for both http and websocket protocols.
269 * In the case of sending using websocket protocol, be sure to allocate
270 * valid storage before and after buf as explained above. This scheme
271 * allows maximum efficiency of sending data and protocol in a single
272 * packet while not burdening the user code with any protocol knowledge.
275 int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
276 size_t len, enum libwebsocket_write_protocol protocol)
281 int masked7 = wsi->mode == LWS_CONNMODE_WS_CLIENT;
282 unsigned char *dropmask = NULL;
283 unsigned char is_masked_bit = 0;
284 #ifndef LWS_NO_EXTENSIONS
285 struct lws_tokens eff_buf;
289 if (lws_confirm_legit_wsi(wsi)) {
290 lwsl_err("libwebsocket_write on illegitimate wsi\n");
293 if (len == 0 && protocol != LWS_WRITE_CLOSE) {
294 lwsl_warn("zero length libwebsocket_write attempt\n");
298 if (protocol == LWS_WRITE_HTTP)
301 /* websocket protocol, either binary or text */
303 if (wsi->state != WSI_STATE_ESTABLISHED)
306 #ifndef LWS_NO_EXTENSIONS
307 /* give a change to the extensions to modify payload */
308 eff_buf.token = (char *)buf;
309 eff_buf.token_len = len;
314 case LWS_WRITE_CLOSE:
318 for (n = 0; n < wsi->count_active_extensions; n++) {
319 m = wsi->active_extensions[n]->callback(
320 wsi->protocol->owning_server,
321 wsi->active_extensions[n], wsi,
322 LWS_EXT_CALLBACK_PAYLOAD_TX,
323 wsi->active_extensions_user[n], &eff_buf, 0);
329 buf = (unsigned char *)eff_buf.token;
330 len = eff_buf.token_len;
333 switch (wsi->ietf_spec_revision) {
337 dropmask = &buf[0 - pre];
338 is_masked_bit = 0x80;
341 switch (protocol & 0xf) {
343 n = LWS_WS_OPCODE_07__TEXT_FRAME;
345 case LWS_WRITE_BINARY:
346 n = LWS_WS_OPCODE_07__BINARY_FRAME;
348 case LWS_WRITE_CONTINUATION:
349 n = LWS_WS_OPCODE_07__CONTINUATION;
352 case LWS_WRITE_CLOSE:
353 n = LWS_WS_OPCODE_07__CLOSE;
356 * 06+ has a 2-byte status code in network order
357 * we can do this because we demand post-buf
360 if (wsi->close_reason) {
361 /* reason codes count as data bytes */
363 buf[0] = wsi->close_reason >> 8;
364 buf[1] = wsi->close_reason;
369 n = LWS_WS_OPCODE_07__PING;
370 wsi->pings_vs_pongs++;
373 n = LWS_WS_OPCODE_07__PONG;
376 lwsl_warn("libwebsocket_write: unknown write "
377 "opcode / protocol\n");
381 if (!(protocol & LWS_WRITE_NO_FIN))
387 buf[-pre + 1] = len | is_masked_bit;
392 buf[-pre + 1] = 126 | is_masked_bit;
393 buf[-pre + 2] = len >> 8;
398 buf[-pre + 1] = 127 | is_masked_bit;
400 buf[-pre + 2] = (len >> 56) & 0x7f;
401 buf[-pre + 3] = len >> 48;
402 buf[-pre + 4] = len >> 40;
403 buf[-pre + 5] = len >> 32;
410 buf[-pre + 6] = len >> 24;
411 buf[-pre + 7] = len >> 16;
412 buf[-pre + 8] = len >> 8;
420 * Deal with masking if we are in client -> server direction and
421 * the protocol demands it
424 if (wsi->mode == LWS_CONNMODE_WS_CLIENT) {
426 if (libwebsocket_0405_frame_mask_generate(wsi)) {
427 lwsl_err("libwebsocket_write: "
428 "frame mask generation failed\n");
433 * in v7, just mask the payload
435 for (n = 4; n < (int)len + 4; n++)
436 dropmask[n] = dropmask[n] ^ wsi->frame_masking_nonce_04[(wsi->frame_mask_index++) & 3];
439 /* copy the frame nonce into place */
441 wsi->frame_masking_nonce_04, 4);
447 lwsl_debug("send %ld: ", len + post);
448 lwsl_hexdump(&buf[-pre], len + post);
452 case LWS_WRITE_CLOSE:
453 // lwsl_hexdump(&buf[-pre], len + post);
457 if (lws_issue_raw(wsi, (unsigned char *)buf - pre,
467 * give any active extensions a chance to munge the buffer
468 * before send. We pass in a pointer to an lws_tokens struct
469 * prepared with the default buffer and content length that's in
470 * there. Rather than rewrite the default buffer, extensions
471 * that expect to grow the buffer can adapt .token to
472 * point to their own per-connection buffer in the extension
473 * user allocation. By default with no extensions or no
474 * extension callback handling, just the normal input buffer is
475 * used then so it is efficient.
477 * callback returns 1 in case it wants to spill more buffers
480 return lws_issue_raw_ext_access(wsi, buf - pre, len + pre + post);
485 * libwebsockets_serve_http_file() - Send a file back to the client using http
486 * @context: libwebsockets context
487 * @wsi: Websocket instance (available from user callback)
488 * @file: The file to issue over http
489 * @content_type: The http content type, eg, text/html
491 * This function is intended to be called from the callback in response
492 * to http requests from the client. It allows the callback to issue
493 * local files down the http link in a single step.
496 int libwebsockets_serve_http_file(struct libwebsocket_context *context,
497 struct libwebsocket *wsi, const char *file,
498 const char *content_type)
501 struct stat stat_buf;
506 strncpy(wsi->filepath, file, sizeof wsi->filepath);
507 wsi->filepath[sizeof(wsi->filepath) - 1] = '\0';
510 fd = open(wsi->filepath, O_RDONLY | _O_BINARY);
512 fd = open(wsi->filepath, O_RDONLY);
515 p += sprintf(p, "HTTP/1.0 400 Bad\x0d\x0a"
516 "Server: libwebsockets\x0d\x0a"
519 libwebsocket_write(wsi, (unsigned char *)buf, p - buf,
525 fstat(fd, &stat_buf);
526 wsi->filelen = stat_buf.st_size;
527 p += sprintf(p, "HTTP/1.0 200 OK\x0d\x0a"
528 "Server: libwebsockets\x0d\x0a"
529 "Content-Type: %s\x0d\x0a"
530 "Content-Length: %u\x0d\x0a"
531 "\x0d\x0a", content_type,
532 (unsigned int)stat_buf.st_size);
534 n = libwebsocket_write(wsi, (unsigned char *)buf, p - buf, LWS_WRITE_HTTP);
541 wsi->state = WSI_STATE_HTTP_ISSUING_FILE;
543 while (!lws_send_pipe_choked(wsi)) {
545 n = read(fd, buf, sizeof buf);
548 m = libwebsocket_write(wsi, (unsigned char *)buf, n, LWS_WRITE_HTTP);
560 if (n < sizeof(buf) || wsi->filepos == wsi->filelen) {
561 /* oh, we were able to finish here! */
562 wsi->state = WSI_STATE_HTTP;
565 if (wsi->protocol->callback(context, wsi, LWS_CALLBACK_HTTP_FILE_COMPLETION, wsi->user_space,
566 wsi->filepath, wsi->filepos)) {
567 lwsl_info("closing connecton after file_completion returned nonzero\n");
568 libwebsocket_close_and_free_session(context, wsi, LWS_CLOSE_STATUS_NOSTATUS);
575 /* we choked, no worries schedule service for the rest of it */
577 libwebsocket_callback_on_writable(context, wsi);
584 int libwebsockets_serve_http_file_fragment(struct libwebsocket_context *context,
585 struct libwebsocket *wsi)
593 fd = open(wsi->filepath, O_RDONLY | _O_BINARY);
595 fd = open(wsi->filepath, O_RDONLY);
600 lseek(fd, wsi->filepos, SEEK_SET);
602 while (!lws_send_pipe_choked(wsi)) {
603 n = read(fd, buf, sizeof buf);
605 libwebsocket_write(wsi, (unsigned char *)buf, n, LWS_WRITE_HTTP);
614 if (n < sizeof(buf) || wsi->filepos == wsi->filelen) {
615 wsi->state = WSI_STATE_HTTP;
621 libwebsocket_callback_on_writable(context, wsi);