blob: a835ec3914c36cc1c4398a37f451e89c3f67649e [file] [log] [blame]
Andy Greenb429d482013-01-16 12:21:29 +08001/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010-2013 Andy Green <andy@warmcat.com>
5 *
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
102 if (wsi->truncated_send_malloc &&
103 (buf < wsi->truncated_send_malloc ||
104 buf > (wsi->truncated_send_malloc + wsi->truncated_send_len + wsi->truncated_send_offset))) {
105 lwsl_err("****** %x Sending something else while pending truncated ...\n", wsi);
106 assert(0);
107 }
Andy Greenb429d482013-01-16 12:21:29 +0800108
109 /*
110 * one of the extensions is carrying our data itself? Like mux?
111 */
112
113 for (n = 0; n < wsi->count_active_extensions; n++) {
114 /*
115 * there can only be active extensions after handshake completed
116 * so we can rely on protocol being set already in here
117 */
118 m = wsi->active_extensions[n]->callback(
119 wsi->protocol->owning_server,
120 wsi->active_extensions[n], wsi,
121 LWS_EXT_CALLBACK_PACKET_TX_DO_SEND,
122 wsi->active_extensions_user[n], &buf, len);
123 if (m < 0) {
124 lwsl_ext("Extension reports fatal error\n");
125 return -1;
126 }
127 if (m) /* handled */ {
128/* lwsl_ext("ext sent it\n"); */
Andy Green1f4267b2013-10-17 08:09:19 +0800129 n = m;
130 goto handle_truncated_send;
Andy Greenb429d482013-01-16 12:21:29 +0800131 }
132 }
Andy Green3182ece2013-01-20 17:08:31 +0800133#endif
Andy Green1f4267b2013-10-17 08:09:19 +0800134 if (wsi->sock < 0)
135 lwsl_warn("** error invalid sock but expected to send\n");
Andy Greenb429d482013-01-16 12:21:29 +0800136
137 /*
138 * nope, send it on the socket directly
139 */
140
141#if 0
142 lwsl_debug(" TX: ");
Andy Green0303db42013-01-17 14:46:43 +0800143 lws_hexdump(buf, len);
Andy Greenb429d482013-01-16 12:21:29 +0800144#endif
145
Andy Green2764eba2013-12-09 14:16:17 +0800146#if 0
147 /* test partial send support by forcing multiple sends on everything */
148 len = len / 2;
149 if (!len)
150 len = 1;
151#endif
152
Andy Greene000a702013-01-29 12:37:35 +0800153 lws_latency_pre(context, wsi);
Andy Greenb429d482013-01-16 12:21:29 +0800154#ifdef LWS_OPENSSL_SUPPORT
155 if (wsi->ssl) {
156 n = SSL_write(wsi->ssl, buf, len);
Andy Greene000a702013-01-29 12:37:35 +0800157 lws_latency(context, wsi, "SSL_write lws_issue_raw", n, n >= 0);
Andy Greenb429d482013-01-16 12:21:29 +0800158 if (n < 0) {
Patrick Gansterer2dbd8372014-02-28 12:37:52 +0100159 if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EINTR) {
Andy Green2764eba2013-12-09 14:16:17 +0800160 n = 0;
161 goto handle_truncated_send;
162 }
Andy Greenb429d482013-01-16 12:21:29 +0800163 lwsl_debug("ERROR writing to socket\n");
164 return -1;
165 }
166 } else {
167#endif
168 n = send(wsi->sock, buf, len, MSG_NOSIGNAL);
Andy Greene000a702013-01-29 12:37:35 +0800169 lws_latency(context, wsi, "send lws_issue_raw", n, n == len);
Andy Greenfc7c5e42013-02-23 10:50:10 +0800170 if (n < 0) {
Patrick Gansterer2dbd8372014-02-28 12:37:52 +0100171 if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EINTR) {
Andy Green2764eba2013-12-09 14:16:17 +0800172 n = 0;
173 goto handle_truncated_send;
174 }
Andy Greenb5b23192013-02-11 17:13:32 +0800175 lwsl_debug("ERROR writing len %d to skt %d\n", len, n);
Andy Greenb429d482013-01-16 12:21:29 +0800176 return -1;
177 }
178#ifdef LWS_OPENSSL_SUPPORT
179 }
180#endif
Andy Green1f4267b2013-10-17 08:09:19 +0800181
182handle_truncated_send:
183
184 /*
185 * already handling a truncated send?
186 */
Andy Green2764eba2013-12-09 14:16:17 +0800187 if (wsi->truncated_send_malloc) {
188 lwsl_info("***** %x partial send moved on by %d (vs %d)\n", wsi, n, real_len);
189 wsi->truncated_send_offset += n;
190 wsi->truncated_send_len -= n;
Andy Green1f4267b2013-10-17 08:09:19 +0800191
Andy Green2764eba2013-12-09 14:16:17 +0800192 if (!wsi->truncated_send_len) {
193 lwsl_info("***** %x partial send completed\n", wsi);
Andy Green1f4267b2013-10-17 08:09:19 +0800194 /* done with it */
Andy Green2764eba2013-12-09 14:16:17 +0800195 free(wsi->truncated_send_malloc);
196 wsi->truncated_send_malloc = NULL;
197 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 Green2764eba2013-12-09 14:16:17 +0800220 lwsl_info("***** %x new partial sent %d from %d total\n", wsi, n, real_len);
Andy Green1f4267b2013-10-17 08:09:19 +0800221
Andy Green2764eba2013-12-09 14:16:17 +0800222 wsi->truncated_send_malloc = malloc(real_len - n);
223 if (!wsi->truncated_send_malloc) {
Andy Green1f4267b2013-10-17 08:09:19 +0800224 lwsl_err("truncated send: unable to malloc %d\n",
Andy Green2764eba2013-12-09 14:16:17 +0800225 real_len - n);
Andy Green1f4267b2013-10-17 08:09:19 +0800226 return -1;
227 }
228
Andy Green2764eba2013-12-09 14:16:17 +0800229 wsi->truncated_send_offset = 0;
230 wsi->truncated_send_len = real_len - n;
231 memcpy(wsi->truncated_send_malloc, buf + n, real_len - n);
Andy Green1f4267b2013-10-17 08:09:19 +0800232
233 libwebsocket_callback_on_writable(
234 wsi->protocol->owning_server, wsi);
235
Andy Green2764eba2013-12-09 14:16:17 +0800236 return real_len;
Andy Green1f4267b2013-10-17 08:09:19 +0800237 }
238
Andy Greenfc7c5e42013-02-23 10:50:10 +0800239 return n;
Andy Greenb429d482013-01-16 12:21:29 +0800240}
241
Andy Green3182ece2013-01-20 17:08:31 +0800242#ifdef LWS_NO_EXTENSIONS
243int
244lws_issue_raw_ext_access(struct libwebsocket *wsi,
245 unsigned char *buf, size_t len)
246{
247 return lws_issue_raw(wsi, buf, len);
248}
249#else
Andy Greenb429d482013-01-16 12:21:29 +0800250int
251lws_issue_raw_ext_access(struct libwebsocket *wsi,
252 unsigned char *buf, size_t len)
253{
254 int ret;
255 struct lws_tokens eff_buf;
256 int m;
257 int n;
258
259 eff_buf.token = (char *)buf;
260 eff_buf.token_len = len;
261
262 /*
263 * while we have original buf to spill ourselves, or extensions report
264 * more in their pipeline
265 */
266
267 ret = 1;
268 while (ret == 1) {
269
270 /* default to nobody has more to spill */
271
272 ret = 0;
273
274 /* show every extension the new incoming data */
275
276 for (n = 0; n < wsi->count_active_extensions; n++) {
277 m = wsi->active_extensions[n]->callback(
278 wsi->protocol->owning_server,
279 wsi->active_extensions[n], wsi,
280 LWS_EXT_CALLBACK_PACKET_TX_PRESEND,
281 wsi->active_extensions_user[n], &eff_buf, 0);
282 if (m < 0) {
283 lwsl_ext("Extension: fatal error\n");
284 return -1;
285 }
286 if (m)
287 /*
288 * at least one extension told us he has more
289 * to spill, so we will go around again after
290 */
291 ret = 1;
292 }
293
Andy Green1f4267b2013-10-17 08:09:19 +0800294 if ((char *)buf != eff_buf.token)
295 wsi->u.ws.clean_buffer = 0; /* extension recreated it: we need to buffer this if not all sent */
296
Andy Greenb429d482013-01-16 12:21:29 +0800297 /* assuming they left us something to send, send it */
298
Andy Greenfc7c5e42013-02-23 10:50:10 +0800299 if (eff_buf.token_len) {
300 n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
301 eff_buf.token_len);
302 if (n < 0)
Andy Greenb429d482013-01-16 12:21:29 +0800303 return -1;
Andy Greenfc7c5e42013-02-23 10:50:10 +0800304
Andy Green1f4267b2013-10-17 08:09:19 +0800305 /* always either sent it all or privately buffered */
Andy Greenfc7c5e42013-02-23 10:50:10 +0800306 }
Andy Greenb429d482013-01-16 12:21:29 +0800307
308 lwsl_parser("written %d bytes to client\n", eff_buf.token_len);
309
Andy Green1f4267b2013-10-17 08:09:19 +0800310 /* no extension has more to spill? Then we can go */
Andy Greenb429d482013-01-16 12:21:29 +0800311
312 if (!ret)
313 break;
314
315 /* we used up what we had */
316
317 eff_buf.token = NULL;
318 eff_buf.token_len = 0;
319
320 /*
321 * Did that leave the pipe choked?
Andy Green1f4267b2013-10-17 08:09:19 +0800322 * Or we had to hold on to some of it?
Andy Greenb429d482013-01-16 12:21:29 +0800323 */
324
Andy Green1f4267b2013-10-17 08:09:19 +0800325 if (!lws_send_pipe_choked(wsi) &&
Andy Green2764eba2013-12-09 14:16:17 +0800326 !wsi->truncated_send_malloc)
Andy Green1f4267b2013-10-17 08:09:19 +0800327 /* no we could add more, lets's do that */
Andy Greenb429d482013-01-16 12:21:29 +0800328 continue;
329
330 lwsl_debug("choked\n");
331
332 /*
333 * Yes, he's choked. Don't spill the rest now get a callback
334 * when he is ready to send and take care of it there
335 */
336 libwebsocket_callback_on_writable(
337 wsi->protocol->owning_server, wsi);
338 wsi->extension_data_pending = 1;
339 ret = 0;
340 }
341
Andy Greenfc7c5e42013-02-23 10:50:10 +0800342 return len;
Andy Greenb429d482013-01-16 12:21:29 +0800343}
Andy Green3182ece2013-01-20 17:08:31 +0800344#endif
Andy Greenb429d482013-01-16 12:21:29 +0800345
346/**
347 * libwebsocket_write() - Apply protocol then write data to client
348 * @wsi: Websocket instance (available from user callback)
349 * @buf: The data to send. For data being sent on a websocket
350 * connection (ie, not default http), this buffer MUST have
351 * LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
352 * and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
353 * in the buffer after (buf + len). This is so the protocol
354 * header and trailer data can be added in-situ.
355 * @len: Count of the data bytes in the payload starting from buf
356 * @protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one
357 * of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
358 * data on a websockets connection. Remember to allow the extra
359 * bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
360 * are used.
361 *
362 * This function provides the way to issue data back to the client
363 * for both http and websocket protocols.
364 *
365 * In the case of sending using websocket protocol, be sure to allocate
366 * valid storage before and after buf as explained above. This scheme
367 * allows maximum efficiency of sending data and protocol in a single
368 * packet while not burdening the user code with any protocol knowledge.
Andy Greenfc7c5e42013-02-23 10:50:10 +0800369 *
370 * Return may be -1 for a fatal error needing connection close, or a
371 * positive number reflecting the amount of bytes actually sent. This
372 * can be less than the requested number of bytes due to OS memory
373 * pressure at any given time.
Andy Greenb429d482013-01-16 12:21:29 +0800374 */
375
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800376LWS_VISIBLE int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
Andy Greenb429d482013-01-16 12:21:29 +0800377 size_t len, enum libwebsocket_write_protocol protocol)
378{
379 int n;
380 int pre = 0;
381 int post = 0;
Andy Green5738c0e2013-01-21 09:53:35 +0800382 int masked7 = wsi->mode == LWS_CONNMODE_WS_CLIENT;
Andy Greenb429d482013-01-16 12:21:29 +0800383 unsigned char *dropmask = NULL;
384 unsigned char is_masked_bit = 0;
Andy Greenfc7c5e42013-02-23 10:50:10 +0800385 size_t orig_len = len;
Andy Green3182ece2013-01-20 17:08:31 +0800386#ifndef LWS_NO_EXTENSIONS
Andy Greenb429d482013-01-16 12:21:29 +0800387 struct lws_tokens eff_buf;
388 int m;
Andy Green3182ece2013-01-20 17:08:31 +0800389#endif
Andy Greenb429d482013-01-16 12:21:29 +0800390
Andy Green1f4267b2013-10-17 08:09:19 +0800391 if (len == 0 && protocol != LWS_WRITE_CLOSE &&
392 protocol != LWS_WRITE_PING && protocol != LWS_WRITE_PONG) {
Andy Greenb429d482013-01-16 12:21:29 +0800393 lwsl_warn("zero length libwebsocket_write attempt\n");
394 return 0;
395 }
396
397 if (protocol == LWS_WRITE_HTTP)
398 goto send_raw;
399
400 /* websocket protocol, either binary or text */
401
402 if (wsi->state != WSI_STATE_ESTABLISHED)
403 return -1;
404
Andy Green1f4267b2013-10-17 08:09:19 +0800405 /* if we are continuing a frame that already had its header done */
406
407 if (wsi->u.ws.inside_frame)
408 goto do_more_inside_frame;
409
410 /* if he wants all partials buffered, never have a clean_buffer */
411 wsi->u.ws.clean_buffer = !wsi->protocol->no_buffer_all_partial_tx;
412
Andy Green3182ece2013-01-20 17:08:31 +0800413#ifndef LWS_NO_EXTENSIONS
Andy Green1f4267b2013-10-17 08:09:19 +0800414 /*
415 * give a chance to the extensions to modify payload
416 * pre-TX mangling is not allowed to truncate
417 */
Andy Greenb429d482013-01-16 12:21:29 +0800418 eff_buf.token = (char *)buf;
419 eff_buf.token_len = len;
420
Andy Green0303db42013-01-17 14:46:43 +0800421 switch (protocol) {
422 case LWS_WRITE_PING:
423 case LWS_WRITE_PONG:
424 case LWS_WRITE_CLOSE:
425 break;
426 default:
Andy Greenf7248f82013-01-16 14:35:12 +0800427
428 for (n = 0; n < wsi->count_active_extensions; n++) {
429 m = wsi->active_extensions[n]->callback(
430 wsi->protocol->owning_server,
431 wsi->active_extensions[n], wsi,
432 LWS_EXT_CALLBACK_PAYLOAD_TX,
433 wsi->active_extensions_user[n], &eff_buf, 0);
434 if (m < 0)
435 return -1;
436 }
Andy Greenb429d482013-01-16 12:21:29 +0800437 }
438
Andy Green1f4267b2013-10-17 08:09:19 +0800439 /*
440 * an extension did something we need to keep... for example, if
441 * compression extension, it has already updated its state according
442 * to this being issued
443 */
444 if ((char *)buf != eff_buf.token)
445 wsi->u.ws.clean_buffer = 0; /* we need to buffer this if not all sent */
446
Andy Greenb429d482013-01-16 12:21:29 +0800447 buf = (unsigned char *)eff_buf.token;
448 len = eff_buf.token_len;
Andy Green3182ece2013-01-20 17:08:31 +0800449#endif
Andy Greenb429d482013-01-16 12:21:29 +0800450
451 switch (wsi->ietf_spec_revision) {
Andy Greenb429d482013-01-16 12:21:29 +0800452 case 13:
Andy Green1f4267b2013-10-17 08:09:19 +0800453
Andy Greenb429d482013-01-16 12:21:29 +0800454 if (masked7) {
455 pre += 4;
456 dropmask = &buf[0 - pre];
457 is_masked_bit = 0x80;
458 }
Andy Green5738c0e2013-01-21 09:53:35 +0800459
Andy Greenb429d482013-01-16 12:21:29 +0800460 switch (protocol & 0xf) {
461 case LWS_WRITE_TEXT:
Andy Green5738c0e2013-01-21 09:53:35 +0800462 n = LWS_WS_OPCODE_07__TEXT_FRAME;
Andy Greenb429d482013-01-16 12:21:29 +0800463 break;
464 case LWS_WRITE_BINARY:
Andy Green5738c0e2013-01-21 09:53:35 +0800465 n = LWS_WS_OPCODE_07__BINARY_FRAME;
Andy Greenb429d482013-01-16 12:21:29 +0800466 break;
467 case LWS_WRITE_CONTINUATION:
Andy Green5738c0e2013-01-21 09:53:35 +0800468 n = LWS_WS_OPCODE_07__CONTINUATION;
Andy Greenb429d482013-01-16 12:21:29 +0800469 break;
470
471 case LWS_WRITE_CLOSE:
Andy Green5738c0e2013-01-21 09:53:35 +0800472 n = LWS_WS_OPCODE_07__CLOSE;
Andy Greenb429d482013-01-16 12:21:29 +0800473
474 /*
Andy Green5738c0e2013-01-21 09:53:35 +0800475 * 06+ has a 2-byte status code in network order
476 * we can do this because we demand post-buf
Andy Greenb429d482013-01-16 12:21:29 +0800477 */
478
Andy Green623a98d2013-01-21 11:04:23 +0800479 if (wsi->u.ws.close_reason) {
Andy Green5738c0e2013-01-21 09:53:35 +0800480 /* reason codes count as data bytes */
481 buf -= 2;
Andy Green623a98d2013-01-21 11:04:23 +0800482 buf[0] = wsi->u.ws.close_reason >> 8;
483 buf[1] = wsi->u.ws.close_reason;
Andy Green5738c0e2013-01-21 09:53:35 +0800484 len += 2;
Andy Greenb429d482013-01-16 12:21:29 +0800485 }
486 break;
487 case LWS_WRITE_PING:
Andy Green5738c0e2013-01-21 09:53:35 +0800488 n = LWS_WS_OPCODE_07__PING;
Andy Greenb429d482013-01-16 12:21:29 +0800489 break;
490 case LWS_WRITE_PONG:
Andy Green5738c0e2013-01-21 09:53:35 +0800491 n = LWS_WS_OPCODE_07__PONG;
Andy Greenb429d482013-01-16 12:21:29 +0800492 break;
493 default:
Andy Greenb5b23192013-02-11 17:13:32 +0800494 lwsl_warn("lws_write: unknown write opc / protocol\n");
Andy Greenb429d482013-01-16 12:21:29 +0800495 return -1;
496 }
497
498 if (!(protocol & LWS_WRITE_NO_FIN))
499 n |= 1 << 7;
500
501 if (len < 126) {
502 pre += 2;
503 buf[-pre] = n;
504 buf[-pre + 1] = len | is_masked_bit;
505 } else {
506 if (len < 65536) {
507 pre += 4;
508 buf[-pre] = n;
509 buf[-pre + 1] = 126 | is_masked_bit;
510 buf[-pre + 2] = len >> 8;
511 buf[-pre + 3] = len;
512 } else {
513 pre += 10;
514 buf[-pre] = n;
515 buf[-pre + 1] = 127 | is_masked_bit;
516#if defined __LP64__
517 buf[-pre + 2] = (len >> 56) & 0x7f;
518 buf[-pre + 3] = len >> 48;
519 buf[-pre + 4] = len >> 40;
520 buf[-pre + 5] = len >> 32;
521#else
522 buf[-pre + 2] = 0;
523 buf[-pre + 3] = 0;
524 buf[-pre + 4] = 0;
525 buf[-pre + 5] = 0;
526#endif
527 buf[-pre + 6] = len >> 24;
528 buf[-pre + 7] = len >> 16;
529 buf[-pre + 8] = len >> 8;
530 buf[-pre + 9] = len;
531 }
532 }
533 break;
534 }
535
Andy Green1f4267b2013-10-17 08:09:19 +0800536do_more_inside_frame:
537
Andy Greenb429d482013-01-16 12:21:29 +0800538 /*
539 * Deal with masking if we are in client -> server direction and
540 * the protocol demands it
541 */
542
Andy Green5738c0e2013-01-21 09:53:35 +0800543 if (wsi->mode == LWS_CONNMODE_WS_CLIENT) {
Andy Greenb429d482013-01-16 12:21:29 +0800544
Andy Green1f4267b2013-10-17 08:09:19 +0800545 if (!wsi->u.ws.inside_frame)
546 if (libwebsocket_0405_frame_mask_generate(wsi)) {
547 lwsl_err("lws_write: frame mask generation failed\n");
548 return -1;
549 }
Andy Greenb429d482013-01-16 12:21:29 +0800550
Andy Green5738c0e2013-01-21 09:53:35 +0800551 /*
552 * in v7, just mask the payload
553 */
Nikolay Dimitrova8268e72013-12-21 10:22:17 +0800554 if (dropmask) { /* never set if already inside frame */
555 for (n = 4; n < (int)len + 4; n++)
556 dropmask[n] = dropmask[n] ^
Andy Greenb5b23192013-02-11 17:13:32 +0800557 wsi->u.ws.frame_masking_nonce_04[
558 (wsi->u.ws.frame_mask_index++) & 3];
Andy Green5738c0e2013-01-21 09:53:35 +0800559
Andy Green5738c0e2013-01-21 09:53:35 +0800560 /* copy the frame nonce into place */
Andy Green1f4267b2013-10-17 08:09:19 +0800561 memcpy(dropmask, wsi->u.ws.frame_masking_nonce_04, 4);
Nikolay Dimitrova8268e72013-12-21 10:22:17 +0800562 }
Andy Greenb429d482013-01-16 12:21:29 +0800563 }
564
565send_raw:
566
567#if 0
Andy Green8ea19552014-02-15 16:00:37 +0800568 lwsl_debug("send %ld: ", len + pre + post);
569 lwsl_hexdump(&buf[-pre], len + pre + post);
Andy Greenb429d482013-01-16 12:21:29 +0800570#endif
571
Andy Green0303db42013-01-17 14:46:43 +0800572 switch (protocol) {
573 case LWS_WRITE_CLOSE:
Andy Greenb5b23192013-02-11 17:13:32 +0800574/* lwsl_hexdump(&buf[-pre], len + post); */
Andy Green0303db42013-01-17 14:46:43 +0800575 case LWS_WRITE_HTTP:
576 case LWS_WRITE_PONG:
577 case LWS_WRITE_PING:
Andy Greenfc7c5e42013-02-23 10:50:10 +0800578 return lws_issue_raw(wsi, (unsigned char *)buf - pre,
579 len + pre + post);
Andy Green0303db42013-01-17 14:46:43 +0800580 default:
581 break;
Andy Greenb429d482013-01-16 12:21:29 +0800582 }
583
Andy Green1f4267b2013-10-17 08:09:19 +0800584 wsi->u.ws.inside_frame = 1;
585
Andy Greenb429d482013-01-16 12:21:29 +0800586 /*
587 * give any active extensions a chance to munge the buffer
588 * before send. We pass in a pointer to an lws_tokens struct
589 * prepared with the default buffer and content length that's in
590 * there. Rather than rewrite the default buffer, extensions
591 * that expect to grow the buffer can adapt .token to
592 * point to their own per-connection buffer in the extension
593 * user allocation. By default with no extensions or no
594 * extension callback handling, just the normal input buffer is
595 * used then so it is efficient.
596 *
597 * callback returns 1 in case it wants to spill more buffers
Andy Green1f4267b2013-10-17 08:09:19 +0800598 *
599 * This takes care of holding the buffer if send is incomplete, ie,
600 * if wsi->u.ws.clean_buffer is 0 (meaning an extension meddled with
601 * the buffer). If wsi->u.ws.clean_buffer is 1, it will instead
602 * return to the user code how much OF THE USER BUFFER was consumed.
Andy Greenb429d482013-01-16 12:21:29 +0800603 */
604
Andy Greenfc7c5e42013-02-23 10:50:10 +0800605 n = lws_issue_raw_ext_access(wsi, buf - pre, len + pre + post);
606 if (n < 0)
607 return n;
608
Andy Green1f4267b2013-10-17 08:09:19 +0800609 if (n == len + pre + post) {
610 /* everything in the buffer was handled (or rebuffered...) */
611 wsi->u.ws.inside_frame = 0;
612 return orig_len;
613 }
614
615 /*
616 * it is how many bytes of user buffer got sent... may be < orig_len
617 * in which case callback when writable has already been arranged
618 * and user code can call libwebsocket_write() again with the rest
619 * later.
620 */
621
622 return n - (pre + post);
Andy Greenb429d482013-01-16 12:21:29 +0800623}
624
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800625LWS_VISIBLE int libwebsockets_serve_http_file_fragment(
Andy Greenb5b23192013-02-11 17:13:32 +0800626 struct libwebsocket_context *context, struct libwebsocket *wsi)
Andy Greenb8b247d2013-01-22 07:20:08 +0800627{
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100628#if defined(WIN32) || defined(_WIN32)
629 DWORD n;
630#else
631 int n;
632#endif
633 int m;
Andy Greenb8b247d2013-01-22 07:20:08 +0800634
635 while (!lws_send_pipe_choked(wsi)) {
Andy Green2764eba2013-12-09 14:16:17 +0800636
637 if (wsi->truncated_send_malloc) {
638 lws_issue_raw(wsi, wsi->truncated_send_malloc +
639 wsi->truncated_send_offset,
640 wsi->truncated_send_len);
641 continue;
642 }
643
644 if (wsi->u.http.filepos == wsi->u.http.filelen)
645 goto all_sent;
646
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100647#if defined(WIN32) || defined(_WIN32)
648 if (!ReadFile(wsi->u.http.fd, context->service_buffer,
649 sizeof(context->service_buffer), &n, NULL))
650 return -1; /* caller will close */
651#else
Andy Greenb5b23192013-02-11 17:13:32 +0800652 n = read(wsi->u.http.fd, context->service_buffer,
653 sizeof(context->service_buffer));
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100654
655 if (n < 0)
656 return -1; /* caller will close */
657#endif
658 if (n) {
Andy Greenfc7c5e42013-02-23 10:50:10 +0800659 m = libwebsocket_write(wsi, context->service_buffer, n,
Andy Greenb5b23192013-02-11 17:13:32 +0800660 LWS_WRITE_HTTP);
Andy Greenfc7c5e42013-02-23 10:50:10 +0800661 if (m < 0)
662 return -1;
663
David Gauchard6c582282013-06-29 10:24:16 +0800664 wsi->u.http.filepos += m;
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100665 if (m != n) {
Andy Greenfc7c5e42013-02-23 10:50:10 +0800666 /* adjust for what was not sent */
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100667#if defined(WIN32) || defined(_WIN32)
668 SetFilePointer(wsi->u.http.fd, m - n, NULL, FILE_CURRENT);
669#else
Andy Greenfc7c5e42013-02-23 10:50:10 +0800670 lseek(wsi->u.http.fd, m - n, SEEK_CUR);
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100671#endif
672 }
Andy Greenb8b247d2013-01-22 07:20:08 +0800673 }
Andy Green2764eba2013-12-09 14:16:17 +0800674all_sent:
675 if (!wsi->truncated_send_malloc &&
676 wsi->u.http.filepos == wsi->u.http.filelen) {
Andy Greenb8b247d2013-01-22 07:20:08 +0800677 wsi->state = WSI_STATE_HTTP;
678
679 if (wsi->protocol->callback)
David Gauchard6c582282013-06-29 10:24:16 +0800680 /* ignore callback returned value */
681 user_callback_handle_rxflow(
Andy Greenb5b23192013-02-11 17:13:32 +0800682 wsi->protocol->callback, context, wsi,
683 LWS_CALLBACK_HTTP_FILE_COMPLETION,
684 wsi->user_space, NULL, 0);
David Gauchard6c582282013-06-29 10:24:16 +0800685 return 1; /* >0 indicates completed */
Andy Greenb8b247d2013-01-22 07:20:08 +0800686 }
687 }
688
Andy Green2764eba2013-12-09 14:16:17 +0800689 lwsl_info("choked before able to send whole file (post)\n");
Andy Greenb8b247d2013-01-22 07:20:08 +0800690 libwebsocket_callback_on_writable(context, wsi);
691
David Gauchard6c582282013-06-29 10:24:16 +0800692 return 0; /* indicates further processing must be done */
Andy Greenb8b247d2013-01-22 07:20:08 +0800693}