blob: 692456616f3862732f7f9a733f5ae084f12bba01 [file] [log] [blame]
Andy Greenb429d482013-01-16 12:21:29 +08001/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
Andy Green27e770b2014-03-23 11:21:51 +08004 * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
Andy Greenb429d482013-01-16 12:21:29 +08005 *
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.
10 *
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.
15 *
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,
19 * MA 02110-1301 USA
20 */
21
22#include "private-libwebsockets.h"
23
Andy Greenb429d482013-01-16 12:21:29 +080024static int
25libwebsocket_0405_frame_mask_generate(struct libwebsocket *wsi)
26{
Andy Greenb429d482013-01-16 12:21:29 +080027 int n;
28
29 /* fetch the per-frame nonce */
30
31 n = libwebsockets_get_random(wsi->protocol->owning_server,
Andy Greenb5b23192013-02-11 17:13:32 +080032 wsi->u.ws.frame_masking_nonce_04, 4);
Andy Greenb429d482013-01-16 12:21:29 +080033 if (n != 4) {
34 lwsl_parser("Unable to read from random device %s %d\n",
35 SYSTEM_RANDOM_FILEPATH, n);
36 return 1;
37 }
38
39 /* start masking from first byte of masking key buffer */
Andy Green623a98d2013-01-21 11:04:23 +080040 wsi->u.ws.frame_mask_index = 0;
Andy Greenb429d482013-01-16 12:21:29 +080041
Andy Greenb429d482013-01-16 12:21:29 +080042 return 0;
43}
44
Andy Greencf3590e2013-01-16 14:35:27 +080045#ifdef _DEBUG
Andy Greenb429d482013-01-16 12:21:29 +080046
Peter Pentchev9a4fef72013-03-30 09:52:21 +080047LWS_VISIBLE void lwsl_hexdump(void *vbuf, size_t len)
Andy Greenb429d482013-01-16 12:21:29 +080048{
49 int n;
50 int m;
51 int start;
Andy Greencf3590e2013-01-16 14:35:27 +080052 unsigned char *buf = (unsigned char *)vbuf;
53 char line[80];
54 char *p;
Andy Greenb429d482013-01-16 12:21:29 +080055
56 lwsl_parser("\n");
57
58 for (n = 0; n < len;) {
59 start = n;
Andy Greencf3590e2013-01-16 14:35:27 +080060 p = line;
Andy Greenb429d482013-01-16 12:21:29 +080061
Andy Greencf3590e2013-01-16 14:35:27 +080062 p += sprintf(p, "%04X: ", start);
Andy Greenb429d482013-01-16 12:21:29 +080063
64 for (m = 0; m < 16 && n < len; m++)
Andy Greencf3590e2013-01-16 14:35:27 +080065 p += sprintf(p, "%02X ", buf[n++]);
Andy Greenb429d482013-01-16 12:21:29 +080066 while (m++ < 16)
Andy Greencf3590e2013-01-16 14:35:27 +080067 p += sprintf(p, " ");
Andy Greenb429d482013-01-16 12:21:29 +080068
Andy Greencf3590e2013-01-16 14:35:27 +080069 p += sprintf(p, " ");
Andy Greenb429d482013-01-16 12:21:29 +080070
71 for (m = 0; m < 16 && (start + m) < len; m++) {
Andy Green3182ece2013-01-20 17:08:31 +080072 if (buf[start + m] >= ' ' && buf[start + m] < 127)
Andy Greencf3590e2013-01-16 14:35:27 +080073 *p++ = buf[start + m];
Andy Greenb429d482013-01-16 12:21:29 +080074 else
Andy Greencf3590e2013-01-16 14:35:27 +080075 *p++ = '.';
Andy Greenb429d482013-01-16 12:21:29 +080076 }
77 while (m++ < 16)
Andy Greencf3590e2013-01-16 14:35:27 +080078 *p++ = ' ';
Andy Greenb429d482013-01-16 12:21:29 +080079
Andy Greencf3590e2013-01-16 14:35:27 +080080 *p++ = '\n';
81 *p = '\0';
Andy Green3182ece2013-01-20 17:08:31 +080082 lwsl_debug("%s", line);
Andy Greenb429d482013-01-16 12:21:29 +080083 }
84 lwsl_debug("\n");
85}
86
Andy Greencf3590e2013-01-16 14:35:27 +080087#endif
88
Patrick Gansterer0fc37b62014-03-28 15:44:56 +010089static void lws_set_blocking_send(struct libwebsocket *wsi)
90{
91#ifdef _WIN32
92 wsi->sock_send_blocking = TRUE;
93#endif
94}
95
Andy Greenfc7c5e42013-02-23 10:50:10 +080096/*
Andy Green1f4267b2013-10-17 08:09:19 +080097 * notice this returns number of bytes consumed, or -1
Andy Greenfc7c5e42013-02-23 10:50:10 +080098 */
99
Andy Greenb429d482013-01-16 12:21:29 +0800100int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)
101{
Andy Greene000a702013-01-29 12:37:35 +0800102 struct libwebsocket_context *context = wsi->protocol->owning_server;
Andy Greenb429d482013-01-16 12:21:29 +0800103 int n;
mroszko793e7c02013-12-10 21:15:00 +0800104 size_t real_len = len;
105
Andy Green3182ece2013-01-20 17:08:31 +0800106#ifndef LWS_NO_EXTENSIONS
Andy Greenb429d482013-01-16 12:21:29 +0800107 int m;
Andy Green2764eba2013-12-09 14:16:17 +0800108
Andy Greene254d952014-03-23 11:41:15 +0800109 if (wsi->truncated_send_len && (buf < wsi->truncated_send_malloc ||
Andy Green27e770b2014-03-23 11:21:51 +0800110 buf > (wsi->truncated_send_malloc +
111 wsi->truncated_send_len +
112 wsi->truncated_send_offset))) {
113 lwsl_err("****** %x Sending new, pending truncated ...\n", wsi);
Andy Green2764eba2013-12-09 14:16:17 +0800114 assert(0);
115 }
Andy Greenb429d482013-01-16 12:21:29 +0800116
117 /*
118 * one of the extensions is carrying our data itself? Like mux?
119 */
120
121 for (n = 0; n < wsi->count_active_extensions; n++) {
122 /*
123 * there can only be active extensions after handshake completed
124 * so we can rely on protocol being set already in here
125 */
126 m = wsi->active_extensions[n]->callback(
127 wsi->protocol->owning_server,
128 wsi->active_extensions[n], wsi,
129 LWS_EXT_CALLBACK_PACKET_TX_DO_SEND,
130 wsi->active_extensions_user[n], &buf, len);
131 if (m < 0) {
132 lwsl_ext("Extension reports fatal error\n");
133 return -1;
134 }
135 if (m) /* handled */ {
136/* lwsl_ext("ext sent it\n"); */
Andy Green1f4267b2013-10-17 08:09:19 +0800137 n = m;
138 goto handle_truncated_send;
Andy Greenb429d482013-01-16 12:21:29 +0800139 }
140 }
Andy Green3182ece2013-01-20 17:08:31 +0800141#endif
Andy Green1f4267b2013-10-17 08:09:19 +0800142 if (wsi->sock < 0)
143 lwsl_warn("** error invalid sock but expected to send\n");
Andy Greenb429d482013-01-16 12:21:29 +0800144
145 /*
146 * nope, send it on the socket directly
147 */
148
149#if 0
150 lwsl_debug(" TX: ");
Andy Green0303db42013-01-17 14:46:43 +0800151 lws_hexdump(buf, len);
Andy Greenb429d482013-01-16 12:21:29 +0800152#endif
153
Andy Green2764eba2013-12-09 14:16:17 +0800154#if 0
155 /* test partial send support by forcing multiple sends on everything */
156 len = len / 2;
157 if (!len)
158 len = 1;
159#endif
160
Andy Greene000a702013-01-29 12:37:35 +0800161 lws_latency_pre(context, wsi);
Andy Greenb429d482013-01-16 12:21:29 +0800162#ifdef LWS_OPENSSL_SUPPORT
163 if (wsi->ssl) {
164 n = SSL_write(wsi->ssl, buf, len);
Andy Greene000a702013-01-29 12:37:35 +0800165 lws_latency(context, wsi, "SSL_write lws_issue_raw", n, n >= 0);
Andy Greenb429d482013-01-16 12:21:29 +0800166 if (n < 0) {
Andy Green28b12ad2014-03-23 12:02:52 +0800167 n = SSL_get_error(wsi->ssl, n);
168 if (n == SSL_ERROR_WANT_READ ||
169 n == SSL_ERROR_WANT_WRITE) {
Patrick Gansterer0fc37b62014-03-28 15:44:56 +0100170 if (n == SSL_ERROR_WANT_WRITE)
171 lws_set_blocking_send(wsi);
Andy Green2764eba2013-12-09 14:16:17 +0800172 n = 0;
173 goto handle_truncated_send;
Andy Green28b12ad2014-03-23 12:02:52 +0800174
Andy Green2764eba2013-12-09 14:16:17 +0800175 }
Andy Greenb429d482013-01-16 12:21:29 +0800176 lwsl_debug("ERROR writing to socket\n");
177 return -1;
178 }
179 } else {
180#endif
181 n = send(wsi->sock, buf, len, MSG_NOSIGNAL);
Andy Greene000a702013-01-29 12:37:35 +0800182 lws_latency(context, wsi, "send lws_issue_raw", n, n == len);
Andy Greenfc7c5e42013-02-23 10:50:10 +0800183 if (n < 0) {
Patrick Gansterer0fc37b62014-03-28 15:44:56 +0100184 if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK
185 || LWS_ERRNO == LWS_EINTR) {
186 if (LWS_ERRNO == LWS_EWOULDBLOCK)
187 lws_set_blocking_send(wsi);
Andy Green2764eba2013-12-09 14:16:17 +0800188 n = 0;
189 goto handle_truncated_send;
190 }
Andy Greenb5b23192013-02-11 17:13:32 +0800191 lwsl_debug("ERROR writing len %d to skt %d\n", len, n);
Andy Greenb429d482013-01-16 12:21:29 +0800192 return -1;
193 }
194#ifdef LWS_OPENSSL_SUPPORT
195 }
196#endif
Andy Green1f4267b2013-10-17 08:09:19 +0800197
198handle_truncated_send:
199
200 /*
201 * already handling a truncated send?
202 */
Andy Greene254d952014-03-23 11:41:15 +0800203 if (wsi->truncated_send_len) {
Andy Green27e770b2014-03-23 11:21:51 +0800204 lwsl_info("***** %x partial send moved on by %d (vs %d)\n",
205 wsi, n, real_len);
Andy Green2764eba2013-12-09 14:16:17 +0800206 wsi->truncated_send_offset += n;
207 wsi->truncated_send_len -= n;
Andy Green1f4267b2013-10-17 08:09:19 +0800208
Andy Green2764eba2013-12-09 14:16:17 +0800209 if (!wsi->truncated_send_len) {
210 lwsl_info("***** %x partial send completed\n", wsi);
Andy Greene254d952014-03-23 11:41:15 +0800211 /* done with it, but don't free it */
Andy Green2764eba2013-12-09 14:16:17 +0800212 n = real_len;
Andy Green1f4267b2013-10-17 08:09:19 +0800213 } else
214 libwebsocket_callback_on_writable(
215 wsi->protocol->owning_server, wsi);
216
217 return n;
218 }
219
Andy Green2764eba2013-12-09 14:16:17 +0800220 if (n < real_len) {
Andy Green0c0bf4a2013-10-18 19:23:06 +0800221 if (wsi->u.ws.clean_buffer)
Andy Green1f4267b2013-10-17 08:09:19 +0800222 /*
223 * This buffer unaffected by extension rewriting.
224 * It means the user code is expected to deal with
225 * partial sends. (lws knows the header was already
226 * sent, so on next send will just resume sending
227 * payload)
228 */
Andy Green0c0bf4a2013-10-18 19:23:06 +0800229 return n;
Andy Green1f4267b2013-10-17 08:09:19 +0800230
231 /*
232 * Newly truncated send. Buffer the remainder (it will get
233 * first priority next time the socket is writable)
234 */
Andy Green27e770b2014-03-23 11:21:51 +0800235 lwsl_info("***** %x new partial sent %d from %d total\n",
236 wsi, n, real_len);
Andy Green1f4267b2013-10-17 08:09:19 +0800237
Andy Greene254d952014-03-23 11:41:15 +0800238 /*
239 * - if we still have a suitable malloc lying around, use it
240 * - or, if too small, reallocate it
241 * - or, if no buffer, create it
242 */
243 if (!wsi->truncated_send_malloc ||
244 real_len - n > wsi->truncated_send_allocation) {
245 if (wsi->truncated_send_malloc)
246 free(wsi->truncated_send_malloc);
Andy Green1f4267b2013-10-17 08:09:19 +0800247
Andy Greene254d952014-03-23 11:41:15 +0800248 wsi->truncated_send_allocation = real_len - n;
249 wsi->truncated_send_malloc = malloc(real_len - n);
250 if (!wsi->truncated_send_malloc) {
251 lwsl_err(
252 "truncated send: unable to malloc %d\n",
253 real_len - n);
254 return -1;
255 }
256 }
Andy Green2764eba2013-12-09 14:16:17 +0800257 wsi->truncated_send_offset = 0;
258 wsi->truncated_send_len = real_len - n;
259 memcpy(wsi->truncated_send_malloc, buf + n, real_len - n);
Andy Green1f4267b2013-10-17 08:09:19 +0800260
261 libwebsocket_callback_on_writable(
262 wsi->protocol->owning_server, wsi);
263
Andy Green2764eba2013-12-09 14:16:17 +0800264 return real_len;
Andy Green1f4267b2013-10-17 08:09:19 +0800265 }
266
Andy Greenfc7c5e42013-02-23 10:50:10 +0800267 return n;
Andy Greenb429d482013-01-16 12:21:29 +0800268}
269
Andy Green3182ece2013-01-20 17:08:31 +0800270#ifdef LWS_NO_EXTENSIONS
271int
272lws_issue_raw_ext_access(struct libwebsocket *wsi,
273 unsigned char *buf, size_t len)
274{
275 return lws_issue_raw(wsi, buf, len);
276}
277#else
Andy Greenb429d482013-01-16 12:21:29 +0800278int
279lws_issue_raw_ext_access(struct libwebsocket *wsi,
280 unsigned char *buf, size_t len)
281{
282 int ret;
283 struct lws_tokens eff_buf;
284 int m;
285 int n;
286
287 eff_buf.token = (char *)buf;
288 eff_buf.token_len = len;
289
290 /*
291 * while we have original buf to spill ourselves, or extensions report
292 * more in their pipeline
293 */
294
295 ret = 1;
296 while (ret == 1) {
297
298 /* default to nobody has more to spill */
299
300 ret = 0;
301
302 /* show every extension the new incoming data */
303
304 for (n = 0; n < wsi->count_active_extensions; n++) {
305 m = wsi->active_extensions[n]->callback(
306 wsi->protocol->owning_server,
307 wsi->active_extensions[n], wsi,
308 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
309 wsi->active_extensions_user[n], &eff_buf, 0);
310 if (m < 0) {
311 lwsl_ext("Extension: fatal error\n");
312 return -1;
313 }
314 if (m)
315 /*
316 * at least one extension told us he has more
317 * to spill, so we will go around again after
318 */
319 ret = 1;
320 }
321
Andy Green1f4267b2013-10-17 08:09:19 +0800322 if ((char *)buf != eff_buf.token)
Andy Green27e770b2014-03-23 11:21:51 +0800323 /*
324 * extension recreated it:
325 * need to buffer this if not all sent
326 */
327 wsi->u.ws.clean_buffer = 0;
Andy Green1f4267b2013-10-17 08:09:19 +0800328
Andy Greenb429d482013-01-16 12:21:29 +0800329 /* assuming they left us something to send, send it */
330
Andy Greenfc7c5e42013-02-23 10:50:10 +0800331 if (eff_buf.token_len) {
332 n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
333 eff_buf.token_len);
334 if (n < 0)
Andy Greenb429d482013-01-16 12:21:29 +0800335 return -1;
Andy Greenfc7c5e42013-02-23 10:50:10 +0800336
Andy Green1f4267b2013-10-17 08:09:19 +0800337 /* always either sent it all or privately buffered */
Andy Greenfc7c5e42013-02-23 10:50:10 +0800338 }
Andy Greenb429d482013-01-16 12:21:29 +0800339
340 lwsl_parser("written %d bytes to client\n", eff_buf.token_len);
341
Andy Green1f4267b2013-10-17 08:09:19 +0800342 /* no extension has more to spill? Then we can go */
Andy Greenb429d482013-01-16 12:21:29 +0800343
344 if (!ret)
345 break;
346
347 /* we used up what we had */
348
349 eff_buf.token = NULL;
350 eff_buf.token_len = 0;
351
352 /*
353 * Did that leave the pipe choked?
Andy Green1f4267b2013-10-17 08:09:19 +0800354 * Or we had to hold on to some of it?
Andy Greenb429d482013-01-16 12:21:29 +0800355 */
356
Andy Green1f4267b2013-10-17 08:09:19 +0800357 if (!lws_send_pipe_choked(wsi) &&
Andy Greene254d952014-03-23 11:41:15 +0800358 !wsi->truncated_send_len)
Andy Green1f4267b2013-10-17 08:09:19 +0800359 /* no we could add more, lets's do that */
Andy Greenb429d482013-01-16 12:21:29 +0800360 continue;
361
362 lwsl_debug("choked\n");
363
364 /*
365 * Yes, he's choked. Don't spill the rest now get a callback
366 * when he is ready to send and take care of it there
367 */
368 libwebsocket_callback_on_writable(
369 wsi->protocol->owning_server, wsi);
370 wsi->extension_data_pending = 1;
371 ret = 0;
372 }
373
Andy Greenfc7c5e42013-02-23 10:50:10 +0800374 return len;
Andy Greenb429d482013-01-16 12:21:29 +0800375}
Andy Green3182ece2013-01-20 17:08:31 +0800376#endif
Andy Greenb429d482013-01-16 12:21:29 +0800377
378/**
379 * libwebsocket_write() - Apply protocol then write data to client
380 * @wsi: Websocket instance (available from user callback)
381 * @buf: The data to send. For data being sent on a websocket
382 * connection (ie, not default http), this buffer MUST have
383 * LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
384 * and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
385 * in the buffer after (buf + len). This is so the protocol
386 * header and trailer data can be added in-situ.
387 * @len: Count of the data bytes in the payload starting from buf
388 * @protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one
389 * of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
390 * data on a websockets connection. Remember to allow the extra
391 * bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
392 * are used.
393 *
394 * This function provides the way to issue data back to the client
395 * for both http and websocket protocols.
396 *
397 * In the case of sending using websocket protocol, be sure to allocate
398 * valid storage before and after buf as explained above. This scheme
399 * allows maximum efficiency of sending data and protocol in a single
400 * packet while not burdening the user code with any protocol knowledge.
Andy Greenfc7c5e42013-02-23 10:50:10 +0800401 *
402 * Return may be -1 for a fatal error needing connection close, or a
403 * positive number reflecting the amount of bytes actually sent. This
404 * can be less than the requested number of bytes due to OS memory
405 * pressure at any given time.
Andy Greenb429d482013-01-16 12:21:29 +0800406 */
407
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800408LWS_VISIBLE int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
Andy Greenb429d482013-01-16 12:21:29 +0800409 size_t len, enum libwebsocket_write_protocol protocol)
410{
411 int n;
412 int pre = 0;
413 int post = 0;
Andy Green5738c0e2013-01-21 09:53:35 +0800414 int masked7 = wsi->mode == LWS_CONNMODE_WS_CLIENT;
Andy Greenb429d482013-01-16 12:21:29 +0800415 unsigned char *dropmask = NULL;
416 unsigned char is_masked_bit = 0;
Andy Greenfc7c5e42013-02-23 10:50:10 +0800417 size_t orig_len = len;
Andy Green3182ece2013-01-20 17:08:31 +0800418#ifndef LWS_NO_EXTENSIONS
Andy Greenb429d482013-01-16 12:21:29 +0800419 struct lws_tokens eff_buf;
420 int m;
Andy Green3182ece2013-01-20 17:08:31 +0800421#endif
Andy Greenb429d482013-01-16 12:21:29 +0800422
Andy Green1f4267b2013-10-17 08:09:19 +0800423 if (len == 0 && protocol != LWS_WRITE_CLOSE &&
424 protocol != LWS_WRITE_PING && protocol != LWS_WRITE_PONG) {
Andy Greenb429d482013-01-16 12:21:29 +0800425 lwsl_warn("zero length libwebsocket_write attempt\n");
426 return 0;
427 }
428
429 if (protocol == LWS_WRITE_HTTP)
430 goto send_raw;
431
432 /* websocket protocol, either binary or text */
433
434 if (wsi->state != WSI_STATE_ESTABLISHED)
435 return -1;
436
Andy Green1f4267b2013-10-17 08:09:19 +0800437 /* if we are continuing a frame that already had its header done */
438
439 if (wsi->u.ws.inside_frame)
440 goto do_more_inside_frame;
441
442 /* if he wants all partials buffered, never have a clean_buffer */
443 wsi->u.ws.clean_buffer = !wsi->protocol->no_buffer_all_partial_tx;
444
Andy Green3182ece2013-01-20 17:08:31 +0800445#ifndef LWS_NO_EXTENSIONS
Andy Green1f4267b2013-10-17 08:09:19 +0800446 /*
447 * give a chance to the extensions to modify payload
448 * pre-TX mangling is not allowed to truncate
449 */
Andy Greenb429d482013-01-16 12:21:29 +0800450 eff_buf.token = (char *)buf;
451 eff_buf.token_len = len;
452
Andy Green0303db42013-01-17 14:46:43 +0800453 switch (protocol) {
454 case LWS_WRITE_PING:
455 case LWS_WRITE_PONG:
456 case LWS_WRITE_CLOSE:
457 break;
458 default:
Andy Greenf7248f82013-01-16 14:35:12 +0800459
460 for (n = 0; n < wsi->count_active_extensions; n++) {
461 m = wsi->active_extensions[n]->callback(
462 wsi->protocol->owning_server,
463 wsi->active_extensions[n], wsi,
464 LWS_EXT_CALLBACK_PAYLOAD_TX,
465 wsi->active_extensions_user[n], &eff_buf, 0);
466 if (m < 0)
467 return -1;
468 }
Andy Greenb429d482013-01-16 12:21:29 +0800469 }
470
Andy Green1f4267b2013-10-17 08:09:19 +0800471 /*
472 * an extension did something we need to keep... for example, if
473 * compression extension, it has already updated its state according
474 * to this being issued
475 */
476 if ((char *)buf != eff_buf.token)
Andy Green27e770b2014-03-23 11:21:51 +0800477 /*
478 * extension recreated it:
479 * need to buffer this if not all sent
480 */
481 wsi->u.ws.clean_buffer = 0;
Andy Green1f4267b2013-10-17 08:09:19 +0800482
Andy Greenb429d482013-01-16 12:21:29 +0800483 buf = (unsigned char *)eff_buf.token;
484 len = eff_buf.token_len;
Andy Green3182ece2013-01-20 17:08:31 +0800485#endif
Andy Greenb429d482013-01-16 12:21:29 +0800486
487 switch (wsi->ietf_spec_revision) {
Andy Greenb429d482013-01-16 12:21:29 +0800488 case 13:
Andy Green1f4267b2013-10-17 08:09:19 +0800489
Andy Greenb429d482013-01-16 12:21:29 +0800490 if (masked7) {
491 pre += 4;
492 dropmask = &buf[0 - pre];
493 is_masked_bit = 0x80;
494 }
Andy Green5738c0e2013-01-21 09:53:35 +0800495
Andy Greenb429d482013-01-16 12:21:29 +0800496 switch (protocol & 0xf) {
497 case LWS_WRITE_TEXT:
Andy Green5738c0e2013-01-21 09:53:35 +0800498 n = LWS_WS_OPCODE_07__TEXT_FRAME;
Andy Greenb429d482013-01-16 12:21:29 +0800499 break;
500 case LWS_WRITE_BINARY:
Andy Green5738c0e2013-01-21 09:53:35 +0800501 n = LWS_WS_OPCODE_07__BINARY_FRAME;
Andy Greenb429d482013-01-16 12:21:29 +0800502 break;
503 case LWS_WRITE_CONTINUATION:
Andy Green5738c0e2013-01-21 09:53:35 +0800504 n = LWS_WS_OPCODE_07__CONTINUATION;
Andy Greenb429d482013-01-16 12:21:29 +0800505 break;
506
507 case LWS_WRITE_CLOSE:
Andy Green5738c0e2013-01-21 09:53:35 +0800508 n = LWS_WS_OPCODE_07__CLOSE;
Andy Greenb429d482013-01-16 12:21:29 +0800509
510 /*
Andy Green5738c0e2013-01-21 09:53:35 +0800511 * 06+ has a 2-byte status code in network order
512 * we can do this because we demand post-buf
Andy Greenb429d482013-01-16 12:21:29 +0800513 */
514
Andy Green623a98d2013-01-21 11:04:23 +0800515 if (wsi->u.ws.close_reason) {
Andy Green5738c0e2013-01-21 09:53:35 +0800516 /* reason codes count as data bytes */
517 buf -= 2;
Andy Green623a98d2013-01-21 11:04:23 +0800518 buf[0] = wsi->u.ws.close_reason >> 8;
519 buf[1] = wsi->u.ws.close_reason;
Andy Green5738c0e2013-01-21 09:53:35 +0800520 len += 2;
Andy Greenb429d482013-01-16 12:21:29 +0800521 }
522 break;
523 case LWS_WRITE_PING:
Andy Green5738c0e2013-01-21 09:53:35 +0800524 n = LWS_WS_OPCODE_07__PING;
Andy Greenb429d482013-01-16 12:21:29 +0800525 break;
526 case LWS_WRITE_PONG:
Andy Green5738c0e2013-01-21 09:53:35 +0800527 n = LWS_WS_OPCODE_07__PONG;
Andy Greenb429d482013-01-16 12:21:29 +0800528 break;
529 default:
Andy Greenb5b23192013-02-11 17:13:32 +0800530 lwsl_warn("lws_write: unknown write opc / protocol\n");
Andy Greenb429d482013-01-16 12:21:29 +0800531 return -1;
532 }
533
534 if (!(protocol & LWS_WRITE_NO_FIN))
535 n |= 1 << 7;
536
537 if (len < 126) {
538 pre += 2;
539 buf[-pre] = n;
540 buf[-pre + 1] = len | is_masked_bit;
541 } else {
542 if (len < 65536) {
543 pre += 4;
544 buf[-pre] = n;
545 buf[-pre + 1] = 126 | is_masked_bit;
546 buf[-pre + 2] = len >> 8;
547 buf[-pre + 3] = len;
548 } else {
549 pre += 10;
550 buf[-pre] = n;
551 buf[-pre + 1] = 127 | is_masked_bit;
552#if defined __LP64__
553 buf[-pre + 2] = (len >> 56) & 0x7f;
554 buf[-pre + 3] = len >> 48;
555 buf[-pre + 4] = len >> 40;
556 buf[-pre + 5] = len >> 32;
557#else
558 buf[-pre + 2] = 0;
559 buf[-pre + 3] = 0;
560 buf[-pre + 4] = 0;
561 buf[-pre + 5] = 0;
562#endif
563 buf[-pre + 6] = len >> 24;
564 buf[-pre + 7] = len >> 16;
565 buf[-pre + 8] = len >> 8;
566 buf[-pre + 9] = len;
567 }
568 }
569 break;
570 }
571
Andy Green1f4267b2013-10-17 08:09:19 +0800572do_more_inside_frame:
573
Andy Greenb429d482013-01-16 12:21:29 +0800574 /*
575 * Deal with masking if we are in client -> server direction and
576 * the protocol demands it
577 */
578
Andy Green5738c0e2013-01-21 09:53:35 +0800579 if (wsi->mode == LWS_CONNMODE_WS_CLIENT) {
Andy Greenb429d482013-01-16 12:21:29 +0800580
Andy Green1f4267b2013-10-17 08:09:19 +0800581 if (!wsi->u.ws.inside_frame)
582 if (libwebsocket_0405_frame_mask_generate(wsi)) {
Andy Green27e770b2014-03-23 11:21:51 +0800583 lwsl_err("frame mask generation failed\n");
Andy Green1f4267b2013-10-17 08:09:19 +0800584 return -1;
585 }
Andy Greenb429d482013-01-16 12:21:29 +0800586
Andy Green5738c0e2013-01-21 09:53:35 +0800587 /*
588 * in v7, just mask the payload
589 */
Nikolay Dimitrova8268e72013-12-21 10:22:17 +0800590 if (dropmask) { /* never set if already inside frame */
591 for (n = 4; n < (int)len + 4; n++)
592 dropmask[n] = dropmask[n] ^
Andy Greenb5b23192013-02-11 17:13:32 +0800593 wsi->u.ws.frame_masking_nonce_04[
594 (wsi->u.ws.frame_mask_index++) & 3];
Andy Green5738c0e2013-01-21 09:53:35 +0800595
Andy Green5738c0e2013-01-21 09:53:35 +0800596 /* copy the frame nonce into place */
Andy Green1f4267b2013-10-17 08:09:19 +0800597 memcpy(dropmask, wsi->u.ws.frame_masking_nonce_04, 4);
Nikolay Dimitrova8268e72013-12-21 10:22:17 +0800598 }
Andy Greenb429d482013-01-16 12:21:29 +0800599 }
600
601send_raw:
602
603#if 0
Andy Green8ea19552014-02-15 16:00:37 +0800604 lwsl_debug("send %ld: ", len + pre + post);
605 lwsl_hexdump(&buf[-pre], len + pre + post);
Andy Greenb429d482013-01-16 12:21:29 +0800606#endif
607
Andy Green0303db42013-01-17 14:46:43 +0800608 switch (protocol) {
609 case LWS_WRITE_CLOSE:
Andy Greenb5b23192013-02-11 17:13:32 +0800610/* lwsl_hexdump(&buf[-pre], len + post); */
Andy Green0303db42013-01-17 14:46:43 +0800611 case LWS_WRITE_HTTP:
612 case LWS_WRITE_PONG:
613 case LWS_WRITE_PING:
Andy Greenfc7c5e42013-02-23 10:50:10 +0800614 return lws_issue_raw(wsi, (unsigned char *)buf - pre,
615 len + pre + post);
Andy Green0303db42013-01-17 14:46:43 +0800616 default:
617 break;
Andy Greenb429d482013-01-16 12:21:29 +0800618 }
619
Andy Green1f4267b2013-10-17 08:09:19 +0800620 wsi->u.ws.inside_frame = 1;
621
Andy Greenb429d482013-01-16 12:21:29 +0800622 /*
623 * give any active extensions a chance to munge the buffer
624 * before send. We pass in a pointer to an lws_tokens struct
625 * prepared with the default buffer and content length that's in
626 * there. Rather than rewrite the default buffer, extensions
627 * that expect to grow the buffer can adapt .token to
628 * point to their own per-connection buffer in the extension
629 * user allocation. By default with no extensions or no
630 * extension callback handling, just the normal input buffer is
631 * used then so it is efficient.
632 *
633 * callback returns 1 in case it wants to spill more buffers
Andy Green1f4267b2013-10-17 08:09:19 +0800634 *
635 * This takes care of holding the buffer if send is incomplete, ie,
636 * if wsi->u.ws.clean_buffer is 0 (meaning an extension meddled with
637 * the buffer). If wsi->u.ws.clean_buffer is 1, it will instead
638 * return to the user code how much OF THE USER BUFFER was consumed.
Andy Greenb429d482013-01-16 12:21:29 +0800639 */
640
Andy Greenfc7c5e42013-02-23 10:50:10 +0800641 n = lws_issue_raw_ext_access(wsi, buf - pre, len + pre + post);
642 if (n < 0)
643 return n;
644
Andy Green1f4267b2013-10-17 08:09:19 +0800645 if (n == len + pre + post) {
646 /* everything in the buffer was handled (or rebuffered...) */
647 wsi->u.ws.inside_frame = 0;
648 return orig_len;
649 }
650
651 /*
652 * it is how many bytes of user buffer got sent... may be < orig_len
653 * in which case callback when writable has already been arranged
654 * and user code can call libwebsocket_write() again with the rest
655 * later.
656 */
657
658 return n - (pre + post);
Andy Greenb429d482013-01-16 12:21:29 +0800659}
660
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800661LWS_VISIBLE int libwebsockets_serve_http_file_fragment(
Andy Greenb5b23192013-02-11 17:13:32 +0800662 struct libwebsocket_context *context, struct libwebsocket *wsi)
Andy Greenb8b247d2013-01-22 07:20:08 +0800663{
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100664#if defined(WIN32) || defined(_WIN32)
665 DWORD n;
666#else
667 int n;
668#endif
669 int m;
Andy Greenb8b247d2013-01-22 07:20:08 +0800670
671 while (!lws_send_pipe_choked(wsi)) {
Andy Green2764eba2013-12-09 14:16:17 +0800672
Andy Greene254d952014-03-23 11:41:15 +0800673 if (wsi->truncated_send_len) {
Andy Green2764eba2013-12-09 14:16:17 +0800674 lws_issue_raw(wsi, wsi->truncated_send_malloc +
675 wsi->truncated_send_offset,
Andy Green27e770b2014-03-23 11:21:51 +0800676 wsi->truncated_send_len);
Andy Green2764eba2013-12-09 14:16:17 +0800677 continue;
678 }
679
680 if (wsi->u.http.filepos == wsi->u.http.filelen)
681 goto all_sent;
682
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100683#if defined(WIN32) || defined(_WIN32)
684 if (!ReadFile(wsi->u.http.fd, context->service_buffer,
Andy Green27e770b2014-03-23 11:21:51 +0800685 sizeof(context->service_buffer), &n, NULL))
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100686 return -1; /* caller will close */
687#else
Andy Greenb5b23192013-02-11 17:13:32 +0800688 n = read(wsi->u.http.fd, context->service_buffer,
689 sizeof(context->service_buffer));
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100690
691 if (n < 0)
692 return -1; /* caller will close */
693#endif
694 if (n) {
Andy Greenfc7c5e42013-02-23 10:50:10 +0800695 m = libwebsocket_write(wsi, context->service_buffer, n,
Andy Greenb5b23192013-02-11 17:13:32 +0800696 LWS_WRITE_HTTP);
Andy Greenfc7c5e42013-02-23 10:50:10 +0800697 if (m < 0)
698 return -1;
699
David Gauchard6c582282013-06-29 10:24:16 +0800700 wsi->u.http.filepos += m;
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100701 if (m != n) {
Andy Greenfc7c5e42013-02-23 10:50:10 +0800702 /* adjust for what was not sent */
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100703#if defined(WIN32) || defined(_WIN32)
Andy Green27e770b2014-03-23 11:21:51 +0800704 SetFilePointer(wsi->u.http.fd, m - n,
705 NULL, FILE_CURRENT);
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100706#else
Andy Greenfc7c5e42013-02-23 10:50:10 +0800707 lseek(wsi->u.http.fd, m - n, SEEK_CUR);
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100708#endif
709 }
Andy Greenb8b247d2013-01-22 07:20:08 +0800710 }
Andy Green2764eba2013-12-09 14:16:17 +0800711all_sent:
Andy Greene254d952014-03-23 11:41:15 +0800712 if (!wsi->truncated_send_len &&
Andy Green2764eba2013-12-09 14:16:17 +0800713 wsi->u.http.filepos == wsi->u.http.filelen) {
Andy Greenb8b247d2013-01-22 07:20:08 +0800714 wsi->state = WSI_STATE_HTTP;
715
716 if (wsi->protocol->callback)
David Gauchard6c582282013-06-29 10:24:16 +0800717 /* ignore callback returned value */
718 user_callback_handle_rxflow(
Andy Greenb5b23192013-02-11 17:13:32 +0800719 wsi->protocol->callback, context, wsi,
720 LWS_CALLBACK_HTTP_FILE_COMPLETION,
721 wsi->user_space, NULL, 0);
David Gauchard6c582282013-06-29 10:24:16 +0800722 return 1; /* >0 indicates completed */
Andy Greenb8b247d2013-01-22 07:20:08 +0800723 }
724 }
725
Andy Green2764eba2013-12-09 14:16:17 +0800726 lwsl_info("choked before able to send whole file (post)\n");
Andy Greenb8b247d2013-01-22 07:20:08 +0800727 libwebsocket_callback_on_writable(context, wsi);
728
David Gauchard6c582282013-06-29 10:24:16 +0800729 return 0; /* indicates further processing must be done */
Andy Greenb8b247d2013-01-22 07:20:08 +0800730}