private.h: rename to contain dir
[platform/upstream/libwebsockets.git] / lib / core-net / output.c
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010-2018 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-lib-core.h"
23
24 /*
25  * notice this returns number of bytes consumed, or -1
26  */
27 int lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len)
28 {
29         struct lws_context *context = lws_get_context(wsi);
30         struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
31         size_t real_len = len;
32         unsigned int n, m;
33
34         // lwsl_notice("%s: len %d\n", __func__, (int)len);
35         // lwsl_hexdump_level(LLL_NOTICE, buf, len);
36
37         /*
38          * Detect if we got called twice without going through the
39          * event loop to handle pending.  Since that guarantees extending any
40          * existing buflist_out it's inefficient.
41          */
42         if (0 && buf && wsi->could_have_pending) {
43                 lwsl_hexdump_level(LLL_INFO, buf, len);
44                 lwsl_info("** %p: vh: %s, prot: %s, role %s: "
45                           "Inefficient back-to-back write of %lu detected...\n",
46                           wsi, wsi->vhost ? wsi->vhost->name : "no vhost",
47                           wsi->protocol->name, wsi->role_ops->name,
48                           (unsigned long)len);
49         }
50
51         lws_stats_bump(pt, LWSSTATS_C_API_WRITE, 1);
52
53         /* just ignore sends after we cleared the truncation buffer */
54         if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE &&
55             !lws_has_buffered_out(wsi)
56 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
57             && !wsi->http.comp_ctx.may_have_more
58 #endif
59             )
60                 return (int)len;
61
62         if (buf && lws_has_buffered_out(wsi)) {
63                 lwsl_info("** %p: vh: %s, prot: %s, incr buflist_out by %lu\n",
64                           wsi, wsi->vhost ? wsi->vhost->name : "no vhost",
65                           wsi->protocol->name, (unsigned long)len);
66
67                 /*
68                  * already buflist ahead of this, add it on the tail of the
69                  * buflist, then ignore it for now and act like we're flushing
70                  * the buflist...
71                  */
72
73                 if (lws_buflist_append_segment(&wsi->buflist_out, buf, len))
74                         return -1;
75
76                 buf = NULL;
77                 len = 0;
78         }
79
80         if (wsi->buflist_out) {
81                 /* we have to drain the earliest buflist_out stuff first */
82
83                 len = lws_buflist_next_segment_len(&wsi->buflist_out, &buf);
84                 real_len = len;
85
86                 lwsl_debug("%s: draining %d\n", __func__, (int)len);
87         }
88
89         if (!len || !buf)
90                 return 0;
91
92         if (!wsi->http2_substream && !lws_socket_is_valid(wsi->desc.sockfd))
93                 lwsl_warn("** error invalid sock but expected to send\n");
94
95         /* limit sending */
96         if (wsi->protocol->tx_packet_size)
97                 n = (int)wsi->protocol->tx_packet_size;
98         else {
99                 n = (int)wsi->protocol->rx_buffer_size;
100                 if (!n)
101                         n = context->pt_serv_buf_size;
102         }
103         n += LWS_PRE + 4;
104         if (n > len)
105                 n = (int)len;
106
107         /* nope, send it on the socket directly */
108         lws_latency_pre(context, wsi);
109         m = lws_ssl_capable_write(wsi, buf, n);
110         lws_latency(context, wsi, "send lws_issue_raw", n, n == m);
111
112         lwsl_info("%s: ssl_capable_write (%d) says %d\n", __func__, n, m);
113
114         /* something got written, it can have been truncated now */
115         wsi->could_have_pending = 1;
116
117         switch (m) {
118         case LWS_SSL_CAPABLE_ERROR:
119                 /* we're going to close, let close know sends aren't possible */
120                 wsi->socket_is_permanently_unusable = 1;
121                 return -1;
122         case LWS_SSL_CAPABLE_MORE_SERVICE:
123                 /*
124                  * nothing got sent, not fatal.  Retry the whole thing later,
125                  * ie, implying treat it was a truncated send so it gets
126                  * retried
127                  */
128                 m = 0;
129                 break;
130         }
131
132         if ((int)m < 0)
133                 m = 0;
134
135         /*
136          * we were sending this from buflist_out?  Then not sending everything
137          * is a small matter of advancing ourselves only by the amount we did
138          * send in the buflist.
139          */
140         if (lws_has_buffered_out(wsi)) {
141                 if (m) {
142                         lwsl_info("%p partial adv %d (vs %ld)\n", wsi, m,
143                                         (long)real_len);
144                         lws_buflist_use_segment(&wsi->buflist_out, m);
145                 }
146
147                 if (!lws_has_buffered_out(wsi)) {
148                         lwsl_info("%s: wsi %p: buflist_out flushed\n",
149                                   __func__, wsi);
150
151                         m = (int)real_len;
152                         if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE) {
153                                 lwsl_info("*%p signalling to close now\n", wsi);
154                                 return -1; /* retry closing now */
155                         }
156
157                         if (wsi->close_when_buffered_out_drained) {
158                                 wsi->close_when_buffered_out_drained = 0;
159                                 return -1;
160                         }
161
162 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
163 #if !defined(LWS_WITHOUT_SERVER)
164                         if (wsi->http.deferred_transaction_completed) {
165                                 lwsl_notice("%s: partial completed, doing "
166                                             "deferred transaction completed\n",
167                                             __func__);
168                                 wsi->http.deferred_transaction_completed = 0;
169                                 return lws_http_transaction_completed(wsi) ?
170                                                         -1 : (int)real_len;
171                         }
172 #endif
173 #endif
174                 }
175                 /* always callback on writeable */
176                 lws_callback_on_writable(wsi);
177
178                 return m;
179         }
180
181 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
182         if (wsi->http.comp_ctx.may_have_more)
183                 lws_callback_on_writable(wsi);
184 #endif
185
186         if (m == real_len)
187                 /* what we just sent went out cleanly */
188                 return m;
189
190         /*
191          * We were not able to send everything... and we were not sending from
192          * an existing buflist_out.  So we are starting a fresh buflist_out, by
193          * buffering the unsent remainder on it.
194          * (it will get first priority next time the socket is writable).
195          */
196         lwsl_debug("%p new partial sent %d from %lu total\n", wsi, m,
197                     (unsigned long)real_len);
198
199         if (lws_buflist_append_segment(&wsi->buflist_out, buf + m,
200                                        real_len - m) < 0)
201                 return -1;
202
203         lws_stats_bump(pt, LWSSTATS_C_WRITE_PARTIALS, 1);
204         lws_stats_bump(pt, LWSSTATS_B_PARTIALS_ACCEPTED_PARTS, m);
205
206 #if !defined(LWS_WITH_ESP32) && !defined(LWS_PLAT_OPTEE)
207         if (lws_wsi_is_udp(wsi)) {
208                 /* stash original destination for fulfilling UDP partials */
209                 wsi->udp->sa_pending = wsi->udp->sa;
210                 wsi->udp->salen_pending = wsi->udp->salen;
211         }
212 #endif
213
214         /* since something buffered, force it to get another chance to send */
215         lws_callback_on_writable(wsi);
216
217         return (int)real_len;
218 }
219
220 LWS_VISIBLE int lws_write(struct lws *wsi, unsigned char *buf, size_t len,
221                           enum lws_write_protocol wp)
222 {
223         struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
224
225         lws_stats_bump(pt, LWSSTATS_C_API_LWS_WRITE, 1);
226
227         if ((int)len < 0) {
228                 lwsl_err("%s: suspicious len int %d, ulong %lu\n", __func__,
229                                 (int)len, (unsigned long)len);
230                 return -1;
231         }
232
233         lws_stats_bump(pt, LWSSTATS_B_WRITE, len);
234
235 #ifdef LWS_WITH_ACCESS_LOG
236         wsi->http.access_log.sent += len;
237 #endif
238         if (wsi->vhost)
239                 wsi->vhost->conn_stats.tx += len;
240
241         assert(wsi->role_ops);
242         if (!wsi->role_ops->write_role_protocol)
243                 return lws_issue_raw(wsi, buf, len);
244
245         return wsi->role_ops->write_role_protocol(wsi, buf, len, &wp);
246 }
247
248 LWS_VISIBLE int
249 lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len)
250 {
251         struct lws_context *context = wsi->context;
252         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
253         int n = 0;
254
255         lws_stats_bump(pt, LWSSTATS_C_API_READ, 1);
256
257         errno = 0;
258         if (lws_wsi_is_udp(wsi)) {
259 #if !defined(LWS_WITH_ESP32) && !defined(LWS_PLAT_OPTEE)
260                 wsi->udp->salen = sizeof(wsi->udp->sa);
261                 n = recvfrom(wsi->desc.sockfd, (char *)buf, len, 0,
262                              &wsi->udp->sa, &wsi->udp->salen);
263 #endif
264         } else
265                 n = recv(wsi->desc.sockfd, (char *)buf, len, 0);
266
267         if (n >= 0) {
268
269                 if (!n && wsi->unix_skt)
270                         return LWS_SSL_CAPABLE_ERROR;
271
272                 /*
273                  * See https://libwebsockets.org/
274                  * pipermail/libwebsockets/2019-March/007857.html
275                  */
276                 if (!n)
277                         return LWS_SSL_CAPABLE_ERROR;
278
279                 if (wsi->vhost)
280                         wsi->vhost->conn_stats.rx += n;
281                 lws_stats_bump(pt, LWSSTATS_B_READ, n);
282
283                 return n;
284         }
285
286         if (LWS_ERRNO == LWS_EAGAIN ||
287             LWS_ERRNO == LWS_EWOULDBLOCK ||
288             LWS_ERRNO == LWS_EINTR)
289                 return LWS_SSL_CAPABLE_MORE_SERVICE;
290
291         lwsl_info("error on reading from skt : %d\n", LWS_ERRNO);
292         return LWS_SSL_CAPABLE_ERROR;
293 }
294
295 LWS_VISIBLE int
296 lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len)
297 {
298         int n = 0;
299 #if defined(LWS_PLAT_OPTEE)
300         ssize_t send(int sockfd, const void *buf, size_t len, int flags);
301 #endif
302
303         if (lws_wsi_is_udp(wsi)) {
304 #if !defined(LWS_WITH_ESP32) && !defined(LWS_PLAT_OPTEE)
305                 if (lws_has_buffered_out(wsi))
306                         n = sendto(wsi->desc.sockfd, (const char *)buf,
307                                    len, 0, &wsi->udp->sa_pending,
308                                    wsi->udp->salen_pending);
309                 else
310                         n = sendto(wsi->desc.sockfd, (const char *)buf,
311                                    len, 0, &wsi->udp->sa, wsi->udp->salen);
312 #endif
313         } else
314                 n = send(wsi->desc.sockfd, (char *)buf, len, MSG_NOSIGNAL);
315 //      lwsl_info("%s: sent len %d result %d", __func__, len, n);
316         if (n >= 0)
317                 return n;
318
319         if (LWS_ERRNO == LWS_EAGAIN ||
320             LWS_ERRNO == LWS_EWOULDBLOCK ||
321             LWS_ERRNO == LWS_EINTR) {
322                 if (LWS_ERRNO == LWS_EWOULDBLOCK) {
323                         lws_set_blocking_send(wsi);
324                 }
325
326                 return LWS_SSL_CAPABLE_MORE_SERVICE;
327         }
328
329         lwsl_debug("ERROR writing len %d to skt fd %d err %d / errno %d\n",
330                    len, wsi->desc.sockfd, n, LWS_ERRNO);
331
332         return LWS_SSL_CAPABLE_ERROR;
333 }
334
335 LWS_VISIBLE int
336 lws_ssl_pending_no_ssl(struct lws *wsi)
337 {
338         (void)wsi;
339 #if defined(LWS_WITH_ESP32)
340         return 100;
341 #else
342         return 0;
343 #endif
344 }