blob: e18a09a03ac005c048308d0c6d358120cdbd86d0 [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
Andy Greenfc7c5e42013-02-23 10:50:10 +080089/*
Andy Green1f4267b2013-10-17 08:09:19 +080090 * notice this returns number of bytes consumed, or -1
Andy Greenfc7c5e42013-02-23 10:50:10 +080091 */
92
Andy Greenb429d482013-01-16 12:21:29 +080093int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)
94{
Andy Greene000a702013-01-29 12:37:35 +080095 struct libwebsocket_context *context = wsi->protocol->owning_server;
Andy Greenb429d482013-01-16 12:21:29 +080096 int n;
mroszko793e7c02013-12-10 21:15:00 +080097 size_t real_len = len;
98
Andy Green3182ece2013-01-20 17:08:31 +080099#ifndef LWS_NO_EXTENSIONS
Andy Greenb429d482013-01-16 12:21:29 +0800100 int m;
Andy Green2764eba2013-12-09 14:16:17 +0800101
Andy Greene254d952014-03-23 11:41:15 +0800102 if (wsi->truncated_send_len && (buf < wsi->truncated_send_malloc ||
Andy Green27e770b2014-03-23 11:21:51 +0800103 buf > (wsi->truncated_send_malloc +
104 wsi->truncated_send_len +
105 wsi->truncated_send_offset))) {
106 lwsl_err("****** %x Sending new, pending truncated ...\n", wsi);
Andy Green2764eba2013-12-09 14:16:17 +0800107 assert(0);
108 }
Andy Greenb429d482013-01-16 12:21:29 +0800109
110 /*
111 * one of the extensions is carrying our data itself? Like mux?
112 */
113
114 for (n = 0; n < wsi->count_active_extensions; n++) {
115 /*
116 * there can only be active extensions after handshake completed
117 * so we can rely on protocol being set already in here
118 */
119 m = wsi->active_extensions[n]->callback(
120 wsi->protocol->owning_server,
121 wsi->active_extensions[n], wsi,
122 LWS_EXT_CALLBACK_PACKET_TX_DO_SEND,
123 wsi->active_extensions_user[n], &buf, len);
124 if (m < 0) {
125 lwsl_ext("Extension reports fatal error\n");
126 return -1;
127 }
128 if (m) /* handled */ {
129/* lwsl_ext("ext sent it\n"); */
Andy Green1f4267b2013-10-17 08:09:19 +0800130 n = m;
131 goto handle_truncated_send;
Andy Greenb429d482013-01-16 12:21:29 +0800132 }
133 }
Andy Green3182ece2013-01-20 17:08:31 +0800134#endif
Andy Green1f4267b2013-10-17 08:09:19 +0800135 if (wsi->sock < 0)
136 lwsl_warn("** error invalid sock but expected to send\n");
Andy Greenb429d482013-01-16 12:21:29 +0800137
138 /*
139 * nope, send it on the socket directly
140 */
141
142#if 0
143 lwsl_debug(" TX: ");
Andy Green0303db42013-01-17 14:46:43 +0800144 lws_hexdump(buf, len);
Andy Greenb429d482013-01-16 12:21:29 +0800145#endif
146
Andy Green2764eba2013-12-09 14:16:17 +0800147#if 0
148 /* test partial send support by forcing multiple sends on everything */
149 len = len / 2;
150 if (!len)
151 len = 1;
152#endif
153
Andy Greene000a702013-01-29 12:37:35 +0800154 lws_latency_pre(context, wsi);
Andy Greenb429d482013-01-16 12:21:29 +0800155#ifdef LWS_OPENSSL_SUPPORT
156 if (wsi->ssl) {
157 n = SSL_write(wsi->ssl, buf, len);
Andy Greene000a702013-01-29 12:37:35 +0800158 lws_latency(context, wsi, "SSL_write lws_issue_raw", n, n >= 0);
Andy Greenb429d482013-01-16 12:21:29 +0800159 if (n < 0) {
Patrick Gansterer2dbd8372014-02-28 12:37:52 +0100160 if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EINTR) {
Andy Green2764eba2013-12-09 14:16:17 +0800161 n = 0;
162 goto handle_truncated_send;
163 }
Andy Greenb429d482013-01-16 12:21:29 +0800164 lwsl_debug("ERROR writing to socket\n");
165 return -1;
166 }
167 } else {
168#endif
169 n = send(wsi->sock, buf, len, MSG_NOSIGNAL);
Andy Greene000a702013-01-29 12:37:35 +0800170 lws_latency(context, wsi, "send lws_issue_raw", n, n == len);
Andy Greenfc7c5e42013-02-23 10:50:10 +0800171 if (n < 0) {
Patrick Gansterer2dbd8372014-02-28 12:37:52 +0100172 if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EINTR) {
Andy Green2764eba2013-12-09 14:16:17 +0800173 n = 0;
174 goto handle_truncated_send;
175 }
Andy Greenb5b23192013-02-11 17:13:32 +0800176 lwsl_debug("ERROR writing len %d to skt %d\n", len, n);
Andy Greenb429d482013-01-16 12:21:29 +0800177 return -1;
178 }
179#ifdef LWS_OPENSSL_SUPPORT
180 }
181#endif
Andy Green1f4267b2013-10-17 08:09:19 +0800182
183handle_truncated_send:
184
185 /*
186 * already handling a truncated send?
187 */
Andy Greene254d952014-03-23 11:41:15 +0800188 if (wsi->truncated_send_len) {
Andy Green27e770b2014-03-23 11:21:51 +0800189 lwsl_info("***** %x partial send moved on by %d (vs %d)\n",
190 wsi, n, real_len);
Andy Green2764eba2013-12-09 14:16:17 +0800191 wsi->truncated_send_offset += n;
192 wsi->truncated_send_len -= n;
Andy Green1f4267b2013-10-17 08:09:19 +0800193
Andy Green2764eba2013-12-09 14:16:17 +0800194 if (!wsi->truncated_send_len) {
195 lwsl_info("***** %x partial send completed\n", wsi);
Andy Greene254d952014-03-23 11:41:15 +0800196 /* done with it, but don't free it */
Andy Green2764eba2013-12-09 14:16:17 +0800197 n = real_len;
Andy Green1f4267b2013-10-17 08:09:19 +0800198 } else
199 libwebsocket_callback_on_writable(
200 wsi->protocol->owning_server, wsi);
201
202 return n;
203 }
204
Andy Green2764eba2013-12-09 14:16:17 +0800205 if (n < real_len) {
Andy Green0c0bf4a2013-10-18 19:23:06 +0800206 if (wsi->u.ws.clean_buffer)
Andy Green1f4267b2013-10-17 08:09:19 +0800207 /*
208 * This buffer unaffected by extension rewriting.
209 * It means the user code is expected to deal with
210 * partial sends. (lws knows the header was already
211 * sent, so on next send will just resume sending
212 * payload)
213 */
Andy Green0c0bf4a2013-10-18 19:23:06 +0800214 return n;
Andy Green1f4267b2013-10-17 08:09:19 +0800215
216 /*
217 * Newly truncated send. Buffer the remainder (it will get
218 * first priority next time the socket is writable)
219 */
Andy Green27e770b2014-03-23 11:21:51 +0800220 lwsl_info("***** %x new partial sent %d from %d total\n",
221 wsi, n, real_len);
Andy Green1f4267b2013-10-17 08:09:19 +0800222
Andy Greene254d952014-03-23 11:41:15 +0800223 /*
224 * - if we still have a suitable malloc lying around, use it
225 * - or, if too small, reallocate it
226 * - or, if no buffer, create it
227 */
228 if (!wsi->truncated_send_malloc ||
229 real_len - n > wsi->truncated_send_allocation) {
230 if (wsi->truncated_send_malloc)
231 free(wsi->truncated_send_malloc);
Andy Green1f4267b2013-10-17 08:09:19 +0800232
Andy Greene254d952014-03-23 11:41:15 +0800233 wsi->truncated_send_allocation = real_len - n;
234 wsi->truncated_send_malloc = malloc(real_len - n);
235 if (!wsi->truncated_send_malloc) {
236 lwsl_err(
237 "truncated send: unable to malloc %d\n",
238 real_len - n);
239 return -1;
240 }
241 }
Andy Green2764eba2013-12-09 14:16:17 +0800242 wsi->truncated_send_offset = 0;
243 wsi->truncated_send_len = real_len - n;
244 memcpy(wsi->truncated_send_malloc, buf + n, real_len - n);
Andy Green1f4267b2013-10-17 08:09:19 +0800245
246 libwebsocket_callback_on_writable(
247 wsi->protocol->owning_server, wsi);
248
Andy Green2764eba2013-12-09 14:16:17 +0800249 return real_len;
Andy Green1f4267b2013-10-17 08:09:19 +0800250 }
251
Andy Greenfc7c5e42013-02-23 10:50:10 +0800252 return n;
Andy Greenb429d482013-01-16 12:21:29 +0800253}
254
Andy Green3182ece2013-01-20 17:08:31 +0800255#ifdef LWS_NO_EXTENSIONS
256int
257lws_issue_raw_ext_access(struct libwebsocket *wsi,
258 unsigned char *buf, size_t len)
259{
260 return lws_issue_raw(wsi, buf, len);
261}
262#else
Andy Greenb429d482013-01-16 12:21:29 +0800263int
264lws_issue_raw_ext_access(struct libwebsocket *wsi,
265 unsigned char *buf, size_t len)
266{
267 int ret;
268 struct lws_tokens eff_buf;
269 int m;
270 int n;
271
272 eff_buf.token = (char *)buf;
273 eff_buf.token_len = len;
274
275 /*
276 * while we have original buf to spill ourselves, or extensions report
277 * more in their pipeline
278 */
279
280 ret = 1;
281 while (ret == 1) {
282
283 /* default to nobody has more to spill */
284
285 ret = 0;
286
287 /* show every extension the new incoming data */
288
289 for (n = 0; n < wsi->count_active_extensions; n++) {
290 m = wsi->active_extensions[n]->callback(
291 wsi->protocol->owning_server,
292 wsi->active_extensions[n], wsi,
293 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
294 wsi->active_extensions_user[n], &eff_buf, 0);
295 if (m < 0) {
296 lwsl_ext("Extension: fatal error\n");
297 return -1;
298 }
299 if (m)
300 /*
301 * at least one extension told us he has more
302 * to spill, so we will go around again after
303 */
304 ret = 1;
305 }
306
Andy Green1f4267b2013-10-17 08:09:19 +0800307 if ((char *)buf != eff_buf.token)
Andy Green27e770b2014-03-23 11:21:51 +0800308 /*
309 * extension recreated it:
310 * need to buffer this if not all sent
311 */
312 wsi->u.ws.clean_buffer = 0;
Andy Green1f4267b2013-10-17 08:09:19 +0800313
Andy Greenb429d482013-01-16 12:21:29 +0800314 /* assuming they left us something to send, send it */
315
Andy Greenfc7c5e42013-02-23 10:50:10 +0800316 if (eff_buf.token_len) {
317 n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
318 eff_buf.token_len);
319 if (n < 0)
Andy Greenb429d482013-01-16 12:21:29 +0800320 return -1;
Andy Greenfc7c5e42013-02-23 10:50:10 +0800321
Andy Green1f4267b2013-10-17 08:09:19 +0800322 /* always either sent it all or privately buffered */
Andy Greenfc7c5e42013-02-23 10:50:10 +0800323 }
Andy Greenb429d482013-01-16 12:21:29 +0800324
325 lwsl_parser("written %d bytes to client\n", eff_buf.token_len);
326
Andy Green1f4267b2013-10-17 08:09:19 +0800327 /* no extension has more to spill? Then we can go */
Andy Greenb429d482013-01-16 12:21:29 +0800328
329 if (!ret)
330 break;
331
332 /* we used up what we had */
333
334 eff_buf.token = NULL;
335 eff_buf.token_len = 0;
336
337 /*
338 * Did that leave the pipe choked?
Andy Green1f4267b2013-10-17 08:09:19 +0800339 * Or we had to hold on to some of it?
Andy Greenb429d482013-01-16 12:21:29 +0800340 */
341
Andy Green1f4267b2013-10-17 08:09:19 +0800342 if (!lws_send_pipe_choked(wsi) &&
Andy Greene254d952014-03-23 11:41:15 +0800343 !wsi->truncated_send_len)
Andy Green1f4267b2013-10-17 08:09:19 +0800344 /* no we could add more, lets's do that */
Andy Greenb429d482013-01-16 12:21:29 +0800345 continue;
346
347 lwsl_debug("choked\n");
348
349 /*
350 * Yes, he's choked. Don't spill the rest now get a callback
351 * when he is ready to send and take care of it there
352 */
353 libwebsocket_callback_on_writable(
354 wsi->protocol->owning_server, wsi);
355 wsi->extension_data_pending = 1;
356 ret = 0;
357 }
358
Andy Greenfc7c5e42013-02-23 10:50:10 +0800359 return len;
Andy Greenb429d482013-01-16 12:21:29 +0800360}
Andy Green3182ece2013-01-20 17:08:31 +0800361#endif
Andy Greenb429d482013-01-16 12:21:29 +0800362
363/**
364 * libwebsocket_write() - Apply protocol then write data to client
365 * @wsi: Websocket instance (available from user callback)
366 * @buf: The data to send. For data being sent on a websocket
367 * connection (ie, not default http), this buffer MUST have
368 * LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
369 * and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
370 * in the buffer after (buf + len). This is so the protocol
371 * header and trailer data can be added in-situ.
372 * @len: Count of the data bytes in the payload starting from buf
373 * @protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one
374 * of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
375 * data on a websockets connection. Remember to allow the extra
376 * bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
377 * are used.
378 *
379 * This function provides the way to issue data back to the client
380 * for both http and websocket protocols.
381 *
382 * In the case of sending using websocket protocol, be sure to allocate
383 * valid storage before and after buf as explained above. This scheme
384 * allows maximum efficiency of sending data and protocol in a single
385 * packet while not burdening the user code with any protocol knowledge.
Andy Greenfc7c5e42013-02-23 10:50:10 +0800386 *
387 * Return may be -1 for a fatal error needing connection close, or a
388 * positive number reflecting the amount of bytes actually sent. This
389 * can be less than the requested number of bytes due to OS memory
390 * pressure at any given time.
Andy Greenb429d482013-01-16 12:21:29 +0800391 */
392
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800393LWS_VISIBLE int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
Andy Greenb429d482013-01-16 12:21:29 +0800394 size_t len, enum libwebsocket_write_protocol protocol)
395{
396 int n;
397 int pre = 0;
398 int post = 0;
Andy Green5738c0e2013-01-21 09:53:35 +0800399 int masked7 = wsi->mode == LWS_CONNMODE_WS_CLIENT;
Andy Greenb429d482013-01-16 12:21:29 +0800400 unsigned char *dropmask = NULL;
401 unsigned char is_masked_bit = 0;
Andy Greenfc7c5e42013-02-23 10:50:10 +0800402 size_t orig_len = len;
Andy Green3182ece2013-01-20 17:08:31 +0800403#ifndef LWS_NO_EXTENSIONS
Andy Greenb429d482013-01-16 12:21:29 +0800404 struct lws_tokens eff_buf;
405 int m;
Andy Green3182ece2013-01-20 17:08:31 +0800406#endif
Andy Greenb429d482013-01-16 12:21:29 +0800407
Andy Green1f4267b2013-10-17 08:09:19 +0800408 if (len == 0 && protocol != LWS_WRITE_CLOSE &&
409 protocol != LWS_WRITE_PING && protocol != LWS_WRITE_PONG) {
Andy Greenb429d482013-01-16 12:21:29 +0800410 lwsl_warn("zero length libwebsocket_write attempt\n");
411 return 0;
412 }
413
414 if (protocol == LWS_WRITE_HTTP)
415 goto send_raw;
416
417 /* websocket protocol, either binary or text */
418
419 if (wsi->state != WSI_STATE_ESTABLISHED)
420 return -1;
421
Andy Green1f4267b2013-10-17 08:09:19 +0800422 /* if we are continuing a frame that already had its header done */
423
424 if (wsi->u.ws.inside_frame)
425 goto do_more_inside_frame;
426
427 /* if he wants all partials buffered, never have a clean_buffer */
428 wsi->u.ws.clean_buffer = !wsi->protocol->no_buffer_all_partial_tx;
429
Andy Green3182ece2013-01-20 17:08:31 +0800430#ifndef LWS_NO_EXTENSIONS
Andy Green1f4267b2013-10-17 08:09:19 +0800431 /*
432 * give a chance to the extensions to modify payload
433 * pre-TX mangling is not allowed to truncate
434 */
Andy Greenb429d482013-01-16 12:21:29 +0800435 eff_buf.token = (char *)buf;
436 eff_buf.token_len = len;
437
Andy Green0303db42013-01-17 14:46:43 +0800438 switch (protocol) {
439 case LWS_WRITE_PING:
440 case LWS_WRITE_PONG:
441 case LWS_WRITE_CLOSE:
442 break;
443 default:
Andy Greenf7248f82013-01-16 14:35:12 +0800444
445 for (n = 0; n < wsi->count_active_extensions; n++) {
446 m = wsi->active_extensions[n]->callback(
447 wsi->protocol->owning_server,
448 wsi->active_extensions[n], wsi,
449 LWS_EXT_CALLBACK_PAYLOAD_TX,
450 wsi->active_extensions_user[n], &eff_buf, 0);
451 if (m < 0)
452 return -1;
453 }
Andy Greenb429d482013-01-16 12:21:29 +0800454 }
455
Andy Green1f4267b2013-10-17 08:09:19 +0800456 /*
457 * an extension did something we need to keep... for example, if
458 * compression extension, it has already updated its state according
459 * to this being issued
460 */
461 if ((char *)buf != eff_buf.token)
Andy Green27e770b2014-03-23 11:21:51 +0800462 /*
463 * extension recreated it:
464 * need to buffer this if not all sent
465 */
466 wsi->u.ws.clean_buffer = 0;
Andy Green1f4267b2013-10-17 08:09:19 +0800467
Andy Greenb429d482013-01-16 12:21:29 +0800468 buf = (unsigned char *)eff_buf.token;
469 len = eff_buf.token_len;
Andy Green3182ece2013-01-20 17:08:31 +0800470#endif
Andy Greenb429d482013-01-16 12:21:29 +0800471
472 switch (wsi->ietf_spec_revision) {
Andy Greenb429d482013-01-16 12:21:29 +0800473 case 13:
Andy Green1f4267b2013-10-17 08:09:19 +0800474
Andy Greenb429d482013-01-16 12:21:29 +0800475 if (masked7) {
476 pre += 4;
477 dropmask = &buf[0 - pre];
478 is_masked_bit = 0x80;
479 }
Andy Green5738c0e2013-01-21 09:53:35 +0800480
Andy Greenb429d482013-01-16 12:21:29 +0800481 switch (protocol & 0xf) {
482 case LWS_WRITE_TEXT:
Andy Green5738c0e2013-01-21 09:53:35 +0800483 n = LWS_WS_OPCODE_07__TEXT_FRAME;
Andy Greenb429d482013-01-16 12:21:29 +0800484 break;
485 case LWS_WRITE_BINARY:
Andy Green5738c0e2013-01-21 09:53:35 +0800486 n = LWS_WS_OPCODE_07__BINARY_FRAME;
Andy Greenb429d482013-01-16 12:21:29 +0800487 break;
488 case LWS_WRITE_CONTINUATION:
Andy Green5738c0e2013-01-21 09:53:35 +0800489 n = LWS_WS_OPCODE_07__CONTINUATION;
Andy Greenb429d482013-01-16 12:21:29 +0800490 break;
491
492 case LWS_WRITE_CLOSE:
Andy Green5738c0e2013-01-21 09:53:35 +0800493 n = LWS_WS_OPCODE_07__CLOSE;
Andy Greenb429d482013-01-16 12:21:29 +0800494
495 /*
Andy Green5738c0e2013-01-21 09:53:35 +0800496 * 06+ has a 2-byte status code in network order
497 * we can do this because we demand post-buf
Andy Greenb429d482013-01-16 12:21:29 +0800498 */
499
Andy Green623a98d2013-01-21 11:04:23 +0800500 if (wsi->u.ws.close_reason) {
Andy Green5738c0e2013-01-21 09:53:35 +0800501 /* reason codes count as data bytes */
502 buf -= 2;
Andy Green623a98d2013-01-21 11:04:23 +0800503 buf[0] = wsi->u.ws.close_reason >> 8;
504 buf[1] = wsi->u.ws.close_reason;
Andy Green5738c0e2013-01-21 09:53:35 +0800505 len += 2;
Andy Greenb429d482013-01-16 12:21:29 +0800506 }
507 break;
508 case LWS_WRITE_PING:
Andy Green5738c0e2013-01-21 09:53:35 +0800509 n = LWS_WS_OPCODE_07__PING;
Andy Greenb429d482013-01-16 12:21:29 +0800510 break;
511 case LWS_WRITE_PONG:
Andy Green5738c0e2013-01-21 09:53:35 +0800512 n = LWS_WS_OPCODE_07__PONG;
Andy Greenb429d482013-01-16 12:21:29 +0800513 break;
514 default:
Andy Greenb5b23192013-02-11 17:13:32 +0800515 lwsl_warn("lws_write: unknown write opc / protocol\n");
Andy Greenb429d482013-01-16 12:21:29 +0800516 return -1;
517 }
518
519 if (!(protocol & LWS_WRITE_NO_FIN))
520 n |= 1 << 7;
521
522 if (len < 126) {
523 pre += 2;
524 buf[-pre] = n;
525 buf[-pre + 1] = len | is_masked_bit;
526 } else {
527 if (len < 65536) {
528 pre += 4;
529 buf[-pre] = n;
530 buf[-pre + 1] = 126 | is_masked_bit;
531 buf[-pre + 2] = len >> 8;
532 buf[-pre + 3] = len;
533 } else {
534 pre += 10;
535 buf[-pre] = n;
536 buf[-pre + 1] = 127 | is_masked_bit;
537#if defined __LP64__
538 buf[-pre + 2] = (len >> 56) & 0x7f;
539 buf[-pre + 3] = len >> 48;
540 buf[-pre + 4] = len >> 40;
541 buf[-pre + 5] = len >> 32;
542#else
543 buf[-pre + 2] = 0;
544 buf[-pre + 3] = 0;
545 buf[-pre + 4] = 0;
546 buf[-pre + 5] = 0;
547#endif
548 buf[-pre + 6] = len >> 24;
549 buf[-pre + 7] = len >> 16;
550 buf[-pre + 8] = len >> 8;
551 buf[-pre + 9] = len;
552 }
553 }
554 break;
555 }
556
Andy Green1f4267b2013-10-17 08:09:19 +0800557do_more_inside_frame:
558
Andy Greenb429d482013-01-16 12:21:29 +0800559 /*
560 * Deal with masking if we are in client -> server direction and
561 * the protocol demands it
562 */
563
Andy Green5738c0e2013-01-21 09:53:35 +0800564 if (wsi->mode == LWS_CONNMODE_WS_CLIENT) {
Andy Greenb429d482013-01-16 12:21:29 +0800565
Andy Green1f4267b2013-10-17 08:09:19 +0800566 if (!wsi->u.ws.inside_frame)
567 if (libwebsocket_0405_frame_mask_generate(wsi)) {
Andy Green27e770b2014-03-23 11:21:51 +0800568 lwsl_err("frame mask generation failed\n");
Andy Green1f4267b2013-10-17 08:09:19 +0800569 return -1;
570 }
Andy Greenb429d482013-01-16 12:21:29 +0800571
Andy Green5738c0e2013-01-21 09:53:35 +0800572 /*
573 * in v7, just mask the payload
574 */
Nikolay Dimitrova8268e72013-12-21 10:22:17 +0800575 if (dropmask) { /* never set if already inside frame */
576 for (n = 4; n < (int)len + 4; n++)
577 dropmask[n] = dropmask[n] ^
Andy Greenb5b23192013-02-11 17:13:32 +0800578 wsi->u.ws.frame_masking_nonce_04[
579 (wsi->u.ws.frame_mask_index++) & 3];
Andy Green5738c0e2013-01-21 09:53:35 +0800580
Andy Green5738c0e2013-01-21 09:53:35 +0800581 /* copy the frame nonce into place */
Andy Green1f4267b2013-10-17 08:09:19 +0800582 memcpy(dropmask, wsi->u.ws.frame_masking_nonce_04, 4);
Nikolay Dimitrova8268e72013-12-21 10:22:17 +0800583 }
Andy Greenb429d482013-01-16 12:21:29 +0800584 }
585
586send_raw:
587
588#if 0
Andy Green8ea19552014-02-15 16:00:37 +0800589 lwsl_debug("send %ld: ", len + pre + post);
590 lwsl_hexdump(&buf[-pre], len + pre + post);
Andy Greenb429d482013-01-16 12:21:29 +0800591#endif
592
Andy Green0303db42013-01-17 14:46:43 +0800593 switch (protocol) {
594 case LWS_WRITE_CLOSE:
Andy Greenb5b23192013-02-11 17:13:32 +0800595/* lwsl_hexdump(&buf[-pre], len + post); */
Andy Green0303db42013-01-17 14:46:43 +0800596 case LWS_WRITE_HTTP:
597 case LWS_WRITE_PONG:
598 case LWS_WRITE_PING:
Andy Greenfc7c5e42013-02-23 10:50:10 +0800599 return lws_issue_raw(wsi, (unsigned char *)buf - pre,
600 len + pre + post);
Andy Green0303db42013-01-17 14:46:43 +0800601 default:
602 break;
Andy Greenb429d482013-01-16 12:21:29 +0800603 }
604
Andy Green1f4267b2013-10-17 08:09:19 +0800605 wsi->u.ws.inside_frame = 1;
606
Andy Greenb429d482013-01-16 12:21:29 +0800607 /*
608 * give any active extensions a chance to munge the buffer
609 * before send. We pass in a pointer to an lws_tokens struct
610 * prepared with the default buffer and content length that's in
611 * there. Rather than rewrite the default buffer, extensions
612 * that expect to grow the buffer can adapt .token to
613 * point to their own per-connection buffer in the extension
614 * user allocation. By default with no extensions or no
615 * extension callback handling, just the normal input buffer is
616 * used then so it is efficient.
617 *
618 * callback returns 1 in case it wants to spill more buffers
Andy Green1f4267b2013-10-17 08:09:19 +0800619 *
620 * This takes care of holding the buffer if send is incomplete, ie,
621 * if wsi->u.ws.clean_buffer is 0 (meaning an extension meddled with
622 * the buffer). If wsi->u.ws.clean_buffer is 1, it will instead
623 * return to the user code how much OF THE USER BUFFER was consumed.
Andy Greenb429d482013-01-16 12:21:29 +0800624 */
625
Andy Greenfc7c5e42013-02-23 10:50:10 +0800626 n = lws_issue_raw_ext_access(wsi, buf - pre, len + pre + post);
627 if (n < 0)
628 return n;
629
Andy Green1f4267b2013-10-17 08:09:19 +0800630 if (n == len + pre + post) {
631 /* everything in the buffer was handled (or rebuffered...) */
632 wsi->u.ws.inside_frame = 0;
633 return orig_len;
634 }
635
636 /*
637 * it is how many bytes of user buffer got sent... may be < orig_len
638 * in which case callback when writable has already been arranged
639 * and user code can call libwebsocket_write() again with the rest
640 * later.
641 */
642
643 return n - (pre + post);
Andy Greenb429d482013-01-16 12:21:29 +0800644}
645
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800646LWS_VISIBLE int libwebsockets_serve_http_file_fragment(
Andy Greenb5b23192013-02-11 17:13:32 +0800647 struct libwebsocket_context *context, struct libwebsocket *wsi)
Andy Greenb8b247d2013-01-22 07:20:08 +0800648{
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100649#if defined(WIN32) || defined(_WIN32)
650 DWORD n;
651#else
652 int n;
653#endif
654 int m;
Andy Greenb8b247d2013-01-22 07:20:08 +0800655
656 while (!lws_send_pipe_choked(wsi)) {
Andy Green2764eba2013-12-09 14:16:17 +0800657
Andy Greene254d952014-03-23 11:41:15 +0800658 if (wsi->truncated_send_len) {
Andy Green2764eba2013-12-09 14:16:17 +0800659 lws_issue_raw(wsi, wsi->truncated_send_malloc +
660 wsi->truncated_send_offset,
Andy Green27e770b2014-03-23 11:21:51 +0800661 wsi->truncated_send_len);
Andy Green2764eba2013-12-09 14:16:17 +0800662 continue;
663 }
664
665 if (wsi->u.http.filepos == wsi->u.http.filelen)
666 goto all_sent;
667
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100668#if defined(WIN32) || defined(_WIN32)
669 if (!ReadFile(wsi->u.http.fd, context->service_buffer,
Andy Green27e770b2014-03-23 11:21:51 +0800670 sizeof(context->service_buffer), &n, NULL))
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100671 return -1; /* caller will close */
672#else
Andy Greenb5b23192013-02-11 17:13:32 +0800673 n = read(wsi->u.http.fd, context->service_buffer,
674 sizeof(context->service_buffer));
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100675
676 if (n < 0)
677 return -1; /* caller will close */
678#endif
679 if (n) {
Andy Greenfc7c5e42013-02-23 10:50:10 +0800680 m = libwebsocket_write(wsi, context->service_buffer, n,
Andy Greenb5b23192013-02-11 17:13:32 +0800681 LWS_WRITE_HTTP);
Andy Greenfc7c5e42013-02-23 10:50:10 +0800682 if (m < 0)
683 return -1;
684
David Gauchard6c582282013-06-29 10:24:16 +0800685 wsi->u.http.filepos += m;
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100686 if (m != n) {
Andy Greenfc7c5e42013-02-23 10:50:10 +0800687 /* adjust for what was not sent */
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100688#if defined(WIN32) || defined(_WIN32)
Andy Green27e770b2014-03-23 11:21:51 +0800689 SetFilePointer(wsi->u.http.fd, m - n,
690 NULL, FILE_CURRENT);
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100691#else
Andy Greenfc7c5e42013-02-23 10:50:10 +0800692 lseek(wsi->u.http.fd, m - n, SEEK_CUR);
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100693#endif
694 }
Andy Greenb8b247d2013-01-22 07:20:08 +0800695 }
Andy Green2764eba2013-12-09 14:16:17 +0800696all_sent:
Andy Greene254d952014-03-23 11:41:15 +0800697 if (!wsi->truncated_send_len &&
Andy Green2764eba2013-12-09 14:16:17 +0800698 wsi->u.http.filepos == wsi->u.http.filelen) {
Andy Greenb8b247d2013-01-22 07:20:08 +0800699 wsi->state = WSI_STATE_HTTP;
700
701 if (wsi->protocol->callback)
David Gauchard6c582282013-06-29 10:24:16 +0800702 /* ignore callback returned value */
703 user_callback_handle_rxflow(
Andy Greenb5b23192013-02-11 17:13:32 +0800704 wsi->protocol->callback, context, wsi,
705 LWS_CALLBACK_HTTP_FILE_COMPLETION,
706 wsi->user_space, NULL, 0);
David Gauchard6c582282013-06-29 10:24:16 +0800707 return 1; /* >0 indicates completed */
Andy Greenb8b247d2013-01-22 07:20:08 +0800708 }
709 }
710
Andy Green2764eba2013-12-09 14:16:17 +0800711 lwsl_info("choked before able to send whole file (post)\n");
Andy Greenb8b247d2013-01-22 07:20:08 +0800712 libwebsocket_callback_on_writable(context, wsi);
713
David Gauchard6c582282013-06-29 10:24:16 +0800714 return 0; /* indicates further processing must be done */
Andy Greenb8b247d2013-01-22 07:20:08 +0800715}