blob: 9c98cae6f71bb741bdb54d36bd1cd53898390b46 [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;
Andy Greenb429d482013-01-16 12:21:29 +080098 int m;
Andy Green03cf1dd2014-04-01 14:20:44 +080099
100 if (!len)
101 return 0;
Andy Green2764eba2013-12-09 14:16:17 +0800102
Andy Greene254d952014-03-23 11:41:15 +0800103 if (wsi->truncated_send_len && (buf < wsi->truncated_send_malloc ||
Andy Green27e770b2014-03-23 11:21:51 +0800104 buf > (wsi->truncated_send_malloc +
105 wsi->truncated_send_len +
106 wsi->truncated_send_offset))) {
107 lwsl_err("****** %x Sending new, pending truncated ...\n", wsi);
Andy Green2764eba2013-12-09 14:16:17 +0800108 assert(0);
109 }
Andy Greenb429d482013-01-16 12:21:29 +0800110
Andy Green2c24ec02014-04-02 19:45:42 +0800111 m = lws_ext_callback_for_each_active(wsi,
112 LWS_EXT_CALLBACK_PACKET_TX_DO_SEND, &buf, len);
113 if (m < 0)
114 return -1;
115 if (m) /* handled */ {
116 n = m;
117 goto handle_truncated_send;
Andy Greenb429d482013-01-16 12:21:29 +0800118 }
Andy Green1f4267b2013-10-17 08:09:19 +0800119 if (wsi->sock < 0)
120 lwsl_warn("** error invalid sock but expected to send\n");
Andy Greenb429d482013-01-16 12:21:29 +0800121
122 /*
123 * nope, send it on the socket directly
124 */
Andy Greene000a702013-01-29 12:37:35 +0800125 lws_latency_pre(context, wsi);
Andy Green28b12ad2014-03-23 12:02:52 +0800126
Andy Green02138122014-04-06 06:26:35 +0100127 n = lws_ssl_capable_write(wsi, buf, len);
128 lws_latency(context, wsi, "send lws_issue_raw", n, n == len);
129 switch (n) {
130 case LWS_SSL_CAPABLE_ERROR:
131 return -1;
132 case LWS_SSL_CAPABLE_MORE_SERVICE:
133 n = 0;
134 goto handle_truncated_send;
Andy Greenb429d482013-01-16 12:21:29 +0800135 }
Andy Green1f4267b2013-10-17 08:09:19 +0800136
137handle_truncated_send:
Andy Green1f4267b2013-10-17 08:09:19 +0800138 /*
139 * already handling a truncated send?
140 */
Andy Greene254d952014-03-23 11:41:15 +0800141 if (wsi->truncated_send_len) {
Andy Green27e770b2014-03-23 11:21:51 +0800142 lwsl_info("***** %x partial send moved on by %d (vs %d)\n",
143 wsi, n, real_len);
Andy Green2764eba2013-12-09 14:16:17 +0800144 wsi->truncated_send_offset += n;
145 wsi->truncated_send_len -= n;
Andy Green1f4267b2013-10-17 08:09:19 +0800146
Andy Green2764eba2013-12-09 14:16:17 +0800147 if (!wsi->truncated_send_len) {
148 lwsl_info("***** %x partial send completed\n", wsi);
Andy Greene254d952014-03-23 11:41:15 +0800149 /* done with it, but don't free it */
Andy Green2764eba2013-12-09 14:16:17 +0800150 n = real_len;
Andy Green1f4267b2013-10-17 08:09:19 +0800151 } else
152 libwebsocket_callback_on_writable(
153 wsi->protocol->owning_server, wsi);
154
155 return n;
156 }
157
Andy Green2764eba2013-12-09 14:16:17 +0800158 if (n < real_len) {
Andy Green5bc002e2014-04-01 09:59:23 +0800159 if (n && wsi->u.ws.clean_buffer)
Andy Green1f4267b2013-10-17 08:09:19 +0800160 /*
161 * This buffer unaffected by extension rewriting.
162 * It means the user code is expected to deal with
163 * partial sends. (lws knows the header was already
164 * sent, so on next send will just resume sending
165 * payload)
166 */
Andy Green0c0bf4a2013-10-18 19:23:06 +0800167 return n;
Andy Green1f4267b2013-10-17 08:09:19 +0800168
169 /*
170 * Newly truncated send. Buffer the remainder (it will get
171 * first priority next time the socket is writable)
172 */
Andy Green27e770b2014-03-23 11:21:51 +0800173 lwsl_info("***** %x new partial sent %d from %d total\n",
174 wsi, n, real_len);
Andy Green1f4267b2013-10-17 08:09:19 +0800175
Andy Greene254d952014-03-23 11:41:15 +0800176 /*
177 * - if we still have a suitable malloc lying around, use it
178 * - or, if too small, reallocate it
179 * - or, if no buffer, create it
180 */
181 if (!wsi->truncated_send_malloc ||
182 real_len - n > wsi->truncated_send_allocation) {
183 if (wsi->truncated_send_malloc)
184 free(wsi->truncated_send_malloc);
Andy Green1f4267b2013-10-17 08:09:19 +0800185
Andy Greene254d952014-03-23 11:41:15 +0800186 wsi->truncated_send_allocation = real_len - n;
187 wsi->truncated_send_malloc = malloc(real_len - n);
188 if (!wsi->truncated_send_malloc) {
189 lwsl_err(
190 "truncated send: unable to malloc %d\n",
191 real_len - n);
192 return -1;
193 }
194 }
Andy Green2764eba2013-12-09 14:16:17 +0800195 wsi->truncated_send_offset = 0;
196 wsi->truncated_send_len = real_len - n;
197 memcpy(wsi->truncated_send_malloc, buf + n, real_len - n);
Andy Green1f4267b2013-10-17 08:09:19 +0800198
199 libwebsocket_callback_on_writable(
200 wsi->protocol->owning_server, wsi);
201
Andy Green2764eba2013-12-09 14:16:17 +0800202 return real_len;
Andy Green1f4267b2013-10-17 08:09:19 +0800203 }
204
Andy Greenfc7c5e42013-02-23 10:50:10 +0800205 return n;
Andy Greenb429d482013-01-16 12:21:29 +0800206}
207
Andy Greenb429d482013-01-16 12:21:29 +0800208/**
209 * libwebsocket_write() - Apply protocol then write data to client
210 * @wsi: Websocket instance (available from user callback)
211 * @buf: The data to send. For data being sent on a websocket
212 * connection (ie, not default http), this buffer MUST have
213 * LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE the pointer
214 * and an additional LWS_SEND_BUFFER_POST_PADDING bytes valid
215 * in the buffer after (buf + len). This is so the protocol
216 * header and trailer data can be added in-situ.
217 * @len: Count of the data bytes in the payload starting from buf
218 * @protocol: Use LWS_WRITE_HTTP to reply to an http connection, and one
219 * of LWS_WRITE_BINARY or LWS_WRITE_TEXT to send appropriate
220 * data on a websockets connection. Remember to allow the extra
221 * bytes before and after buf if LWS_WRITE_BINARY or LWS_WRITE_TEXT
222 * are used.
223 *
224 * This function provides the way to issue data back to the client
225 * for both http and websocket protocols.
226 *
227 * In the case of sending using websocket protocol, be sure to allocate
228 * valid storage before and after buf as explained above. This scheme
229 * allows maximum efficiency of sending data and protocol in a single
230 * packet while not burdening the user code with any protocol knowledge.
Andy Greenfc7c5e42013-02-23 10:50:10 +0800231 *
232 * Return may be -1 for a fatal error needing connection close, or a
233 * positive number reflecting the amount of bytes actually sent. This
234 * can be less than the requested number of bytes due to OS memory
235 * pressure at any given time.
Andy Greenb429d482013-01-16 12:21:29 +0800236 */
237
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800238LWS_VISIBLE int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf,
Andy Greenb429d482013-01-16 12:21:29 +0800239 size_t len, enum libwebsocket_write_protocol protocol)
240{
241 int n;
242 int pre = 0;
243 int post = 0;
Andy Green5738c0e2013-01-21 09:53:35 +0800244 int masked7 = wsi->mode == LWS_CONNMODE_WS_CLIENT;
Andy Greenb429d482013-01-16 12:21:29 +0800245 unsigned char *dropmask = NULL;
246 unsigned char is_masked_bit = 0;
Andy Greenfc7c5e42013-02-23 10:50:10 +0800247 size_t orig_len = len;
Andy Greenb429d482013-01-16 12:21:29 +0800248 struct lws_tokens eff_buf;
Andy Greenb429d482013-01-16 12:21:29 +0800249
Andy Green1f4267b2013-10-17 08:09:19 +0800250 if (len == 0 && protocol != LWS_WRITE_CLOSE &&
251 protocol != LWS_WRITE_PING && protocol != LWS_WRITE_PONG) {
Andy Greenb429d482013-01-16 12:21:29 +0800252 lwsl_warn("zero length libwebsocket_write attempt\n");
253 return 0;
254 }
255
256 if (protocol == LWS_WRITE_HTTP)
257 goto send_raw;
258
259 /* websocket protocol, either binary or text */
260
261 if (wsi->state != WSI_STATE_ESTABLISHED)
262 return -1;
263
Andy Green1f4267b2013-10-17 08:09:19 +0800264 /* if we are continuing a frame that already had its header done */
265
266 if (wsi->u.ws.inside_frame)
267 goto do_more_inside_frame;
268
269 /* if he wants all partials buffered, never have a clean_buffer */
270 wsi->u.ws.clean_buffer = !wsi->protocol->no_buffer_all_partial_tx;
271
Andy Green1f4267b2013-10-17 08:09:19 +0800272 /*
273 * give a chance to the extensions to modify payload
274 * pre-TX mangling is not allowed to truncate
275 */
Andy Greenb429d482013-01-16 12:21:29 +0800276 eff_buf.token = (char *)buf;
277 eff_buf.token_len = len;
278
Andy Green0303db42013-01-17 14:46:43 +0800279 switch (protocol) {
280 case LWS_WRITE_PING:
281 case LWS_WRITE_PONG:
282 case LWS_WRITE_CLOSE:
283 break;
284 default:
Andy Green2c24ec02014-04-02 19:45:42 +0800285 if (lws_ext_callback_for_each_active(wsi,
286 LWS_EXT_CALLBACK_PAYLOAD_TX, &eff_buf, 0) < 0)
287 return -1;
Andy Greenb429d482013-01-16 12:21:29 +0800288 }
289
Andy Green1f4267b2013-10-17 08:09:19 +0800290 /*
291 * an extension did something we need to keep... for example, if
292 * compression extension, it has already updated its state according
293 * to this being issued
294 */
295 if ((char *)buf != eff_buf.token)
Andy Green27e770b2014-03-23 11:21:51 +0800296 /*
297 * extension recreated it:
298 * need to buffer this if not all sent
299 */
300 wsi->u.ws.clean_buffer = 0;
Andy Green1f4267b2013-10-17 08:09:19 +0800301
Andy Greenb429d482013-01-16 12:21:29 +0800302 buf = (unsigned char *)eff_buf.token;
303 len = eff_buf.token_len;
304
305 switch (wsi->ietf_spec_revision) {
Andy Greenb429d482013-01-16 12:21:29 +0800306 case 13:
Andy Green1f4267b2013-10-17 08:09:19 +0800307
Andy Greenb429d482013-01-16 12:21:29 +0800308 if (masked7) {
309 pre += 4;
310 dropmask = &buf[0 - pre];
311 is_masked_bit = 0x80;
312 }
Andy Green5738c0e2013-01-21 09:53:35 +0800313
Andy Greenb429d482013-01-16 12:21:29 +0800314 switch (protocol & 0xf) {
315 case LWS_WRITE_TEXT:
Andy Green5738c0e2013-01-21 09:53:35 +0800316 n = LWS_WS_OPCODE_07__TEXT_FRAME;
Andy Greenb429d482013-01-16 12:21:29 +0800317 break;
318 case LWS_WRITE_BINARY:
Andy Green5738c0e2013-01-21 09:53:35 +0800319 n = LWS_WS_OPCODE_07__BINARY_FRAME;
Andy Greenb429d482013-01-16 12:21:29 +0800320 break;
321 case LWS_WRITE_CONTINUATION:
Andy Green5738c0e2013-01-21 09:53:35 +0800322 n = LWS_WS_OPCODE_07__CONTINUATION;
Andy Greenb429d482013-01-16 12:21:29 +0800323 break;
324
325 case LWS_WRITE_CLOSE:
Andy Green5738c0e2013-01-21 09:53:35 +0800326 n = LWS_WS_OPCODE_07__CLOSE;
Andy Greenb429d482013-01-16 12:21:29 +0800327
328 /*
Andy Green5738c0e2013-01-21 09:53:35 +0800329 * 06+ has a 2-byte status code in network order
330 * we can do this because we demand post-buf
Andy Greenb429d482013-01-16 12:21:29 +0800331 */
332
Andy Green623a98d2013-01-21 11:04:23 +0800333 if (wsi->u.ws.close_reason) {
Andy Green5738c0e2013-01-21 09:53:35 +0800334 /* reason codes count as data bytes */
335 buf -= 2;
Andy Green623a98d2013-01-21 11:04:23 +0800336 buf[0] = wsi->u.ws.close_reason >> 8;
337 buf[1] = wsi->u.ws.close_reason;
Andy Green5738c0e2013-01-21 09:53:35 +0800338 len += 2;
Andy Greenb429d482013-01-16 12:21:29 +0800339 }
340 break;
341 case LWS_WRITE_PING:
Andy Green5738c0e2013-01-21 09:53:35 +0800342 n = LWS_WS_OPCODE_07__PING;
Andy Greenb429d482013-01-16 12:21:29 +0800343 break;
344 case LWS_WRITE_PONG:
Andy Green5738c0e2013-01-21 09:53:35 +0800345 n = LWS_WS_OPCODE_07__PONG;
Andy Greenb429d482013-01-16 12:21:29 +0800346 break;
347 default:
Andy Greenb5b23192013-02-11 17:13:32 +0800348 lwsl_warn("lws_write: unknown write opc / protocol\n");
Andy Greenb429d482013-01-16 12:21:29 +0800349 return -1;
350 }
351
352 if (!(protocol & LWS_WRITE_NO_FIN))
353 n |= 1 << 7;
354
355 if (len < 126) {
356 pre += 2;
357 buf[-pre] = n;
358 buf[-pre + 1] = len | is_masked_bit;
359 } else {
360 if (len < 65536) {
361 pre += 4;
362 buf[-pre] = n;
363 buf[-pre + 1] = 126 | is_masked_bit;
364 buf[-pre + 2] = len >> 8;
365 buf[-pre + 3] = len;
366 } else {
367 pre += 10;
368 buf[-pre] = n;
369 buf[-pre + 1] = 127 | is_masked_bit;
370#if defined __LP64__
371 buf[-pre + 2] = (len >> 56) & 0x7f;
372 buf[-pre + 3] = len >> 48;
373 buf[-pre + 4] = len >> 40;
374 buf[-pre + 5] = len >> 32;
375#else
376 buf[-pre + 2] = 0;
377 buf[-pre + 3] = 0;
378 buf[-pre + 4] = 0;
379 buf[-pre + 5] = 0;
380#endif
381 buf[-pre + 6] = len >> 24;
382 buf[-pre + 7] = len >> 16;
383 buf[-pre + 8] = len >> 8;
384 buf[-pre + 9] = len;
385 }
386 }
387 break;
388 }
389
Andy Green1f4267b2013-10-17 08:09:19 +0800390do_more_inside_frame:
391
Andy Greenb429d482013-01-16 12:21:29 +0800392 /*
393 * Deal with masking if we are in client -> server direction and
394 * the protocol demands it
395 */
396
Andy Green5738c0e2013-01-21 09:53:35 +0800397 if (wsi->mode == LWS_CONNMODE_WS_CLIENT) {
Andy Greenb429d482013-01-16 12:21:29 +0800398
Andy Green1f4267b2013-10-17 08:09:19 +0800399 if (!wsi->u.ws.inside_frame)
400 if (libwebsocket_0405_frame_mask_generate(wsi)) {
Andy Green27e770b2014-03-23 11:21:51 +0800401 lwsl_err("frame mask generation failed\n");
Andy Green1f4267b2013-10-17 08:09:19 +0800402 return -1;
403 }
Andy Greenb429d482013-01-16 12:21:29 +0800404
Andy Green5738c0e2013-01-21 09:53:35 +0800405 /*
406 * in v7, just mask the payload
407 */
Nikolay Dimitrova8268e72013-12-21 10:22:17 +0800408 if (dropmask) { /* never set if already inside frame */
409 for (n = 4; n < (int)len + 4; n++)
410 dropmask[n] = dropmask[n] ^
Andy Greenb5b23192013-02-11 17:13:32 +0800411 wsi->u.ws.frame_masking_nonce_04[
412 (wsi->u.ws.frame_mask_index++) & 3];
Andy Green5738c0e2013-01-21 09:53:35 +0800413
Andy Green5738c0e2013-01-21 09:53:35 +0800414 /* copy the frame nonce into place */
Andy Green1f4267b2013-10-17 08:09:19 +0800415 memcpy(dropmask, wsi->u.ws.frame_masking_nonce_04, 4);
Nikolay Dimitrova8268e72013-12-21 10:22:17 +0800416 }
Andy Greenb429d482013-01-16 12:21:29 +0800417 }
418
419send_raw:
Andy Green0303db42013-01-17 14:46:43 +0800420 switch (protocol) {
421 case LWS_WRITE_CLOSE:
Andy Greenb5b23192013-02-11 17:13:32 +0800422/* lwsl_hexdump(&buf[-pre], len + post); */
Andy Green0303db42013-01-17 14:46:43 +0800423 case LWS_WRITE_HTTP:
424 case LWS_WRITE_PONG:
425 case LWS_WRITE_PING:
Andy Greenfc7c5e42013-02-23 10:50:10 +0800426 return lws_issue_raw(wsi, (unsigned char *)buf - pre,
427 len + pre + post);
Andy Green0303db42013-01-17 14:46:43 +0800428 default:
429 break;
Andy Greenb429d482013-01-16 12:21:29 +0800430 }
431
Andy Green1f4267b2013-10-17 08:09:19 +0800432 wsi->u.ws.inside_frame = 1;
433
Andy Greenb429d482013-01-16 12:21:29 +0800434 /*
435 * give any active extensions a chance to munge the buffer
436 * before send. We pass in a pointer to an lws_tokens struct
437 * prepared with the default buffer and content length that's in
438 * there. Rather than rewrite the default buffer, extensions
439 * that expect to grow the buffer can adapt .token to
440 * point to their own per-connection buffer in the extension
441 * user allocation. By default with no extensions or no
442 * extension callback handling, just the normal input buffer is
443 * used then so it is efficient.
444 *
445 * callback returns 1 in case it wants to spill more buffers
Andy Green1f4267b2013-10-17 08:09:19 +0800446 *
447 * This takes care of holding the buffer if send is incomplete, ie,
448 * if wsi->u.ws.clean_buffer is 0 (meaning an extension meddled with
449 * the buffer). If wsi->u.ws.clean_buffer is 1, it will instead
450 * return to the user code how much OF THE USER BUFFER was consumed.
Andy Greenb429d482013-01-16 12:21:29 +0800451 */
452
Andy Greenfc7c5e42013-02-23 10:50:10 +0800453 n = lws_issue_raw_ext_access(wsi, buf - pre, len + pre + post);
Andy Green03cf1dd2014-04-01 14:20:44 +0800454 if (n <= 0)
Andy Greenfc7c5e42013-02-23 10:50:10 +0800455 return n;
456
Andy Green1f4267b2013-10-17 08:09:19 +0800457 if (n == len + pre + post) {
458 /* everything in the buffer was handled (or rebuffered...) */
459 wsi->u.ws.inside_frame = 0;
460 return orig_len;
461 }
462
463 /*
464 * it is how many bytes of user buffer got sent... may be < orig_len
465 * in which case callback when writable has already been arranged
466 * and user code can call libwebsocket_write() again with the rest
467 * later.
468 */
469
470 return n - (pre + post);
Andy Greenb429d482013-01-16 12:21:29 +0800471}
472
Peter Pentchev9a4fef72013-03-30 09:52:21 +0800473LWS_VISIBLE int libwebsockets_serve_http_file_fragment(
Andy Greenb5b23192013-02-11 17:13:32 +0800474 struct libwebsocket_context *context, struct libwebsocket *wsi)
Andy Greenb8b247d2013-01-22 07:20:08 +0800475{
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100476 int n;
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100477 int m;
Andy Greenb8b247d2013-01-22 07:20:08 +0800478
479 while (!lws_send_pipe_choked(wsi)) {
Andy Green2764eba2013-12-09 14:16:17 +0800480
Andy Greene254d952014-03-23 11:41:15 +0800481 if (wsi->truncated_send_len) {
Andy Green2764eba2013-12-09 14:16:17 +0800482 lws_issue_raw(wsi, wsi->truncated_send_malloc +
483 wsi->truncated_send_offset,
Andy Green27e770b2014-03-23 11:21:51 +0800484 wsi->truncated_send_len);
Andy Green2764eba2013-12-09 14:16:17 +0800485 continue;
486 }
487
488 if (wsi->u.http.filepos == wsi->u.http.filelen)
489 goto all_sent;
490
Andy Green158e8042014-04-02 14:25:10 +0800491 compatible_file_read(n, wsi->u.http.fd, context->service_buffer,
Andy Greenb5b23192013-02-11 17:13:32 +0800492 sizeof(context->service_buffer));
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100493 if (n < 0)
494 return -1; /* caller will close */
Patrick Gansterer81338aa2014-02-27 03:21:50 +0100495 if (n) {
Andy Greenfc7c5e42013-02-23 10:50:10 +0800496 m = libwebsocket_write(wsi, context->service_buffer, n,
Andy Greenb5b23192013-02-11 17:13:32 +0800497 LWS_WRITE_HTTP);
Andy Greenfc7c5e42013-02-23 10:50:10 +0800498 if (m < 0)
499 return -1;
500
David Gauchard6c582282013-06-29 10:24:16 +0800501 wsi->u.http.filepos += m;
Andy Green158e8042014-04-02 14:25:10 +0800502 if (m != n)
Andy Greenfc7c5e42013-02-23 10:50:10 +0800503 /* adjust for what was not sent */
Andy Green158e8042014-04-02 14:25:10 +0800504 compatible_file_seek_cur(wsi->u.http.fd, m - n);
Andy Greenb8b247d2013-01-22 07:20:08 +0800505 }
Andy Green2764eba2013-12-09 14:16:17 +0800506all_sent:
Andy Greene254d952014-03-23 11:41:15 +0800507 if (!wsi->truncated_send_len &&
Andy Green2764eba2013-12-09 14:16:17 +0800508 wsi->u.http.filepos == wsi->u.http.filelen) {
Andy Greenb8b247d2013-01-22 07:20:08 +0800509 wsi->state = WSI_STATE_HTTP;
510
511 if (wsi->protocol->callback)
David Gauchard6c582282013-06-29 10:24:16 +0800512 /* ignore callback returned value */
513 user_callback_handle_rxflow(
Andy Greenb5b23192013-02-11 17:13:32 +0800514 wsi->protocol->callback, context, wsi,
515 LWS_CALLBACK_HTTP_FILE_COMPLETION,
516 wsi->user_space, NULL, 0);
David Gauchard6c582282013-06-29 10:24:16 +0800517 return 1; /* >0 indicates completed */
Andy Greenb8b247d2013-01-22 07:20:08 +0800518 }
519 }
520
Andy Green2764eba2013-12-09 14:16:17 +0800521 lwsl_info("choked before able to send whole file (post)\n");
Andy Greenb8b247d2013-01-22 07:20:08 +0800522 libwebsocket_callback_on_writable(context, wsi);
523
David Gauchard6c582282013-06-29 10:24:16 +0800524 return 0; /* indicates further processing must be done */
Andy Greenb8b247d2013-01-22 07:20:08 +0800525}
Andy Green02138122014-04-06 06:26:35 +0100526
527LWS_VISIBLE int
528lws_ssl_capable_read_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len)
529{
530 int n;
531
532 n = recv(wsi->sock, buf, len, 0);
533 if (n < 0) {
534 lwsl_warn("error on reading from skt\n");
535 return LWS_SSL_CAPABLE_ERROR;
536 }
537
538 return n;
539}
540
541LWS_VISIBLE int
542lws_ssl_capable_write_no_ssl(struct libwebsocket *wsi, unsigned char *buf, int len)
543{
544 int n;
545
Andy Green485abc12014-04-06 12:41:20 +0100546 n = send(wsi->sock, buf, len, 0);
Andy Green02138122014-04-06 06:26:35 +0100547 if (n < 0) {
548 if (LWS_ERRNO == LWS_EAGAIN ||
549 LWS_ERRNO == LWS_EWOULDBLOCK ||
550 LWS_ERRNO == LWS_EINTR) {
551 if (LWS_ERRNO == LWS_EWOULDBLOCK)
552 lws_set_blocking_send(wsi);
553 return LWS_SSL_CAPABLE_MORE_SERVICE;
554 }
555 lwsl_debug("ERROR writing len %d to skt %d\n", len, n);
556 return LWS_SSL_CAPABLE_ERROR;
557 }
558
559 return n;
560}