1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26
27 /*
28 * notice this returns number of bytes consumed, or -1
29 */
30 int
lws_issue_raw(struct lws * wsi,unsigned char * buf,size_t len)31 lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len)
32 {
33 struct lws_context *context = lws_get_context(wsi);
34 size_t real_len = len;
35 unsigned int n, m;
36
37 /*
38 * If you're looking to dump data being sent down the tls tunnel, see
39 * lws_ssl_capable_write() in lib/tls/mbedtls/mbedtls-ssl.c or
40 * lib/tls/openssl/openssl-ssl.c.
41 *
42 * There's also a corresponding lws_ssl_capable_read() in those files
43 * where you can enable a dump of decrypted data as soon as it was
44 * read.
45 */
46
47 /*
48 * Detect if we got called twice without going through the
49 * event loop to handle pending. Since that guarantees extending any
50 * existing buflist_out it's inefficient.
51 */
52 if (0 && buf && wsi->could_have_pending) {
53 lwsl_hexdump_level(LLL_INFO, buf, len);
54 lwsl_info("** %s: vh: %s, prot: %s, role %s: "
55 "Inefficient back-to-back write of %lu detected...\n",
56 lws_wsi_tag(wsi), lws_vh_tag(wsi->a.vhost),
57 wsi->a.protocol->name, wsi->role_ops->name,
58 (unsigned long)len);
59 }
60
61 /* just ignore sends after we cleared the truncation buffer */
62 if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE &&
63 !lws_has_buffered_out(wsi)
64 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
65 && !wsi->http.comp_ctx.may_have_more
66 #endif
67 )
68 return (int)len;
69
70 if (buf && lws_has_buffered_out(wsi)) {
71 lwsl_info("** %s: vh: %s, prot: %s, incr buflist_out by %lu\n",
72 lws_wsi_tag(wsi), lws_vh_tag(wsi->a.vhost),
73 wsi->a.protocol->name, (unsigned long)len);
74
75 /*
76 * already buflist ahead of this, add it on the tail of the
77 * buflist, then ignore it for now and act like we're flushing
78 * the buflist...
79 */
80
81 if (lws_buflist_append_segment(&wsi->buflist_out, buf, len))
82 return -1;
83
84 buf = NULL;
85 len = 0;
86 }
87
88 if (wsi->buflist_out) {
89 /* we have to drain the earliest buflist_out stuff first */
90
91 len = lws_buflist_next_segment_len(&wsi->buflist_out, &buf);
92 real_len = len;
93
94 lwsl_debug("%s: draining %d\n", __func__, (int)len);
95 }
96
97 if (!len || !buf)
98 return 0;
99
100 if (!wsi->mux_substream && !lws_socket_is_valid(wsi->desc.sockfd))
101 lwsl_err("%s: %s invalid sock\n", __func__, lws_wsi_tag(wsi));
102
103 /* limit sending */
104 if (wsi->a.protocol->tx_packet_size)
105 n = (unsigned int)wsi->a.protocol->tx_packet_size;
106 else {
107 n = (unsigned int)wsi->a.protocol->rx_buffer_size;
108 if (!n)
109 n = context->pt_serv_buf_size;
110 }
111 n += LWS_PRE + 4;
112 if (n > len)
113 n = (unsigned int)len;
114
115 /* nope, send it on the socket directly */
116
117 if (lws_fi(&wsi->fic, "sendfail"))
118 m = (unsigned int)LWS_SSL_CAPABLE_ERROR;
119 else
120 m = (unsigned int)lws_ssl_capable_write(wsi, buf, n);
121
122 lwsl_info("%s: ssl_capable_write (%d) says %d\n", __func__, n, m);
123
124 /* something got written, it can have been truncated now */
125 wsi->could_have_pending = 1;
126
127 switch ((int)m) {
128 case LWS_SSL_CAPABLE_ERROR:
129 /* we're going to close, let close know sends aren't possible */
130 wsi->socket_is_permanently_unusable = 1;
131 return -1;
132 case LWS_SSL_CAPABLE_MORE_SERVICE:
133 /*
134 * nothing got sent, not fatal. Retry the whole thing later,
135 * ie, implying treat it was a truncated send so it gets
136 * retried
137 */
138 m = 0;
139 break;
140 }
141
142 if ((int)m < 0)
143 m = 0;
144
145 /*
146 * we were sending this from buflist_out? Then not sending everything
147 * is a small matter of advancing ourselves only by the amount we did
148 * send in the buflist.
149 */
150 if (lws_has_buffered_out(wsi)) {
151 if (m) {
152 lwsl_info("%s partial adv %d (vs %ld)\n",
153 lws_wsi_tag(wsi), m, (long)real_len);
154 lws_buflist_use_segment(&wsi->buflist_out, m);
155 }
156
157 if (!lws_has_buffered_out(wsi)) {
158 lwsl_info("%s: %s: buflist_out flushed\n",
159 __func__, lws_wsi_tag(wsi));
160
161 m = (unsigned int)real_len;
162 if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE) {
163 lwsl_info("*%s signalling to close now\n",
164 lws_wsi_tag(wsi));
165 return -1; /* retry closing now */
166 }
167
168 if (wsi->close_when_buffered_out_drained) {
169 wsi->close_when_buffered_out_drained = 0;
170 return -1;
171 }
172
173 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
174 #if defined(LWS_WITH_SERVER)
175 if (wsi->http.deferred_transaction_completed) {
176 lwsl_notice("%s: partial completed, doing "
177 "deferred transaction completed\n",
178 __func__);
179 wsi->http.deferred_transaction_completed = 0;
180 return lws_http_transaction_completed(wsi) ?
181 -1 : (int)real_len;
182 }
183 #endif
184 #endif
185 #if defined(LWS_ROLE_WS)
186 /* Since buflist_out flushed, we're not inside a frame any more */
187 if (wsi->ws)
188 wsi->ws->inside_frame = 0;
189 #endif
190 }
191 /* always callback on writeable */
192 lws_callback_on_writable(wsi);
193
194 return (int)m;
195 }
196
197 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
198 if (wsi->http.comp_ctx.may_have_more)
199 lws_callback_on_writable(wsi);
200 #endif
201
202 if (m == real_len)
203 /* what we just sent went out cleanly */
204 return (int)m;
205
206 /*
207 * We were not able to send everything... and we were not sending from
208 * an existing buflist_out. So we are starting a fresh buflist_out, by
209 * buffering the unsent remainder on it.
210 * (it will get first priority next time the socket is writable).
211 */
212 lwsl_debug("%s new partial sent %d from %lu total\n", lws_wsi_tag(wsi),
213 m, (unsigned long)real_len);
214
215 if (lws_buflist_append_segment(&wsi->buflist_out, buf + m,
216 real_len - m) < 0)
217 return -1;
218
219 #if defined(LWS_WITH_UDP)
220 if (lws_wsi_is_udp(wsi))
221 /* stash original destination for fulfilling UDP partials */
222 wsi->udp->sa46_pending = wsi->udp->sa46;
223 #endif
224
225 /* since something buffered, force it to get another chance to send */
226 lws_callback_on_writable(wsi);
227
228 return (int)real_len;
229 }
230
231 int
lws_write(struct lws * wsi,unsigned char * buf,size_t len,enum lws_write_protocol wp)232 lws_write(struct lws *wsi, unsigned char *buf, size_t len,
233 enum lws_write_protocol wp)
234 {
235 int m;
236
237 if ((int)len < 0) {
238 lwsl_err("%s: suspicious len int %d, ulong %lu\n", __func__,
239 (int)len, (unsigned long)len);
240 return -1;
241 }
242
243 #ifdef LWS_WITH_ACCESS_LOG
244 wsi->http.access_log.sent += len;
245 #endif
246
247 assert(wsi->role_ops);
248
249 if (!lws_rops_fidx(wsi->role_ops, LWS_ROPS_write_role_protocol))
250 m = lws_issue_raw(wsi, buf, len);
251 else
252 m = lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_write_role_protocol).
253 write_role_protocol(wsi, buf, len, &wp);
254
255 #if defined(LWS_WITH_SYS_METRICS)
256 if (wsi->a.vhost)
257 lws_metric_event(wsi->a.vhost->mt_traffic_tx, (char)
258 (m < 0 ? METRES_NOGO : METRES_GO), len);
259 #endif
260
261 return m;
262 }
263
264 int
lws_ssl_capable_read_no_ssl(struct lws * wsi,unsigned char * buf,size_t len)265 lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, size_t len)
266 {
267 int n = 0, en;
268
269 errno = 0;
270 #if defined(LWS_WITH_UDP)
271 if (lws_wsi_is_udp(wsi)) {
272 socklen_t slt = sizeof(wsi->udp->sa46);
273
274 n = (int)recvfrom(wsi->desc.sockfd, (char *)buf,
275 #if defined(WIN32)
276 (int)
277 #endif
278 len, 0,
279 sa46_sockaddr(&wsi->udp->sa46), &slt);
280 } else
281 #endif
282 n = (int)recv(wsi->desc.sockfd, (char *)buf,
283 #if defined(WIN32)
284 (int)
285 #endif
286 len, 0);
287 en = LWS_ERRNO;
288 if (n >= 0) {
289
290 if (!n && wsi->unix_skt)
291 goto do_err;
292
293 /*
294 * See https://libwebsockets.org/
295 * pipermail/libwebsockets/2019-March/007857.html
296 */
297 if (!n && !wsi->unix_skt)
298 goto do_err;
299
300 #if defined(LWS_WITH_SYS_METRICS) && defined(LWS_WITH_SERVER)
301 if (wsi->a.vhost)
302 lws_metric_event(wsi->a.vhost->mt_traffic_rx,
303 METRES_GO /* rx */, (unsigned int)n);
304 #endif
305
306 return n;
307 }
308
309 if (en == LWS_EAGAIN ||
310 en == LWS_EWOULDBLOCK ||
311 en == LWS_EINTR)
312 return LWS_SSL_CAPABLE_MORE_SERVICE;
313
314 do_err:
315 #if defined(LWS_WITH_SYS_METRICS) && defined(LWS_WITH_SERVER)
316 if (wsi->a.vhost)
317 lws_metric_event(wsi->a.vhost->mt_traffic_rx, METRES_NOGO, 0u);
318 #endif
319
320 lwsl_info("%s: error on reading from skt : %d, errno %d\n",
321 __func__, n, en);
322
323 return LWS_SSL_CAPABLE_ERROR;
324 }
325
326 int
lws_ssl_capable_write_no_ssl(struct lws * wsi,unsigned char * buf,size_t len)327 lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, size_t len)
328 {
329 int n = 0;
330 #if defined(LWS_PLAT_OPTEE)
331 ssize_t send(int sockfd, const void *buf, size_t len, int flags);
332 #endif
333
334 #if defined(LWS_WITH_UDP)
335 if (lws_wsi_is_udp(wsi)) {
336
337 if (lws_fi(&wsi->fic, "udp_tx_loss")) {
338 /* pretend it was sent */
339 n = (int)(ssize_t)len;
340 goto post_send;
341 }
342
343 if (lws_has_buffered_out(wsi))
344 n = (int)sendto(wsi->desc.sockfd, (const char *)buf,
345 #if defined(WIN32)
346 (int)
347 #endif
348 len, 0, sa46_sockaddr(&wsi->udp->sa46_pending),
349 sa46_socklen(&wsi->udp->sa46_pending));
350 else
351 n = (int)sendto(wsi->desc.sockfd, (const char *)buf,
352 #if defined(WIN32)
353 (int)
354 #endif
355 len, 0, sa46_sockaddr(&wsi->udp->sa46),
356 sa46_socklen(&wsi->udp->sa46));
357 } else
358 #endif
359 if (wsi->role_ops->file_handle)
360 n = (int)write((int)(lws_intptr_t)wsi->desc.filefd, buf,
361 #if defined(WIN32)
362 (int)
363 #endif
364 len);
365 else
366 n = (int)send(wsi->desc.sockfd, (char *)buf,
367 #if defined(WIN32)
368 (int)
369 #endif
370 len, MSG_NOSIGNAL);
371 // lwsl_info("%s: sent len %d result %d", __func__, len, n);
372
373 #if defined(LWS_WITH_UDP)
374 post_send:
375 #endif
376 if (n >= 0)
377 return n;
378
379 if (LWS_ERRNO == LWS_EAGAIN ||
380 LWS_ERRNO == LWS_EWOULDBLOCK ||
381 LWS_ERRNO == LWS_EINTR) {
382 if (LWS_ERRNO == LWS_EWOULDBLOCK) {
383 lws_set_blocking_send(wsi);
384 }
385
386 return LWS_SSL_CAPABLE_MORE_SERVICE;
387 }
388
389 lwsl_debug("ERROR writing len %d to skt fd %d err %d / errno %d\n",
390 (int)(ssize_t)len, wsi->desc.sockfd, n, LWS_ERRNO);
391
392 return LWS_SSL_CAPABLE_ERROR;
393 }
394
395 int
lws_ssl_pending_no_ssl(struct lws * wsi)396 lws_ssl_pending_no_ssl(struct lws *wsi)
397 {
398 (void)wsi;
399 #if defined(LWS_PLAT_FREERTOS)
400 return 100;
401 #else
402 return 0;
403 #endif
404 }
405