private.h: rename to contain dir
[platform/upstream/libwebsockets.git] / lib / roles / raw-skt / ops-raw-skt.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 static int
25 rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi,
26                            struct lws_pollfd *pollfd)
27 {
28         struct lws_tokens ebuf;
29         int n, buffered;
30
31         /* pending truncated sends have uber priority */
32
33         if (lws_has_buffered_out(wsi)) {
34                 if (!(pollfd->revents & LWS_POLLOUT))
35                         return LWS_HPI_RET_HANDLED;
36
37                 /* drain the output buflist */
38                 if (lws_issue_raw(wsi, NULL, 0) < 0)
39                         goto fail;
40                 /*
41                  * we can't afford to allow input processing to send
42                  * something new, so spin around he event loop until
43                  * he doesn't have any partials
44                  */
45                 return LWS_HPI_RET_HANDLED;
46         }
47
48
49 #if !defined(LWS_NO_SERVER)
50         if (!lwsi_role_client(wsi) &&  lwsi_state(wsi) != LRS_ESTABLISHED) {
51
52                 lwsl_debug("%s: %p: wsistate 0x%x\n", __func__, wsi,
53                            wsi->wsistate);
54
55                 if (lwsi_state(wsi) != LRS_SSL_INIT)
56                         if (lws_server_socket_service_ssl(wsi,
57                                                           LWS_SOCK_INVALID))
58                                 return LWS_HPI_RET_PLEASE_CLOSE_ME;
59
60                 return LWS_HPI_RET_HANDLED;
61         }
62 #endif
63
64         if ((pollfd->revents & pollfd->events & LWS_POLLIN) &&
65             /* any tunnel has to have been established... */
66             lwsi_state(wsi) != LRS_SSL_ACK_PENDING &&
67             !(wsi->favoured_pollin &&
68               (pollfd->revents & pollfd->events & LWS_POLLOUT))) {
69
70                 buffered = lws_buflist_aware_read(pt, wsi, &ebuf);
71                 switch (ebuf.len) {
72                 case 0:
73                         lwsl_info("%s: read 0 len\n", __func__);
74                         wsi->seen_zero_length_recv = 1;
75                         if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
76                                 goto fail;
77
78                         /*
79                          * we need to go to fail here, since it's the only
80                          * chance we get to understand that the socket has
81                          * closed
82                          */
83                         // goto try_pollout;
84                         goto fail;
85
86                 case LWS_SSL_CAPABLE_ERROR:
87                         goto fail;
88                 case LWS_SSL_CAPABLE_MORE_SERVICE:
89                         goto try_pollout;
90                 }
91
92                 n = user_callback_handle_rxflow(wsi->protocol->callback,
93                                                 wsi, LWS_CALLBACK_RAW_RX,
94                                                 wsi->user_space, ebuf.token,
95                                                 ebuf.len);
96                 if (n < 0) {
97                         lwsl_info("LWS_CALLBACK_RAW_RX_fail\n");
98                         goto fail;
99                 }
100
101                 if (lws_buflist_aware_consume(wsi, &ebuf, ebuf.len, buffered))
102                         return LWS_HPI_RET_PLEASE_CLOSE_ME;
103         } else
104                 if (wsi->favoured_pollin &&
105                     (pollfd->revents & pollfd->events & LWS_POLLOUT))
106                         /* we balanced the last favouring of pollin */
107                         wsi->favoured_pollin = 0;
108
109 try_pollout:
110
111         if (!(pollfd->revents & LWS_POLLOUT))
112                 return LWS_HPI_RET_HANDLED;
113
114 #if !defined(LWS_WITHOUT_CLIENT)
115         if (lwsi_state(wsi) == LRS_WAITING_CONNECT)
116                 lws_client_connect_3(wsi, NULL, 0);
117 #endif
118
119         /* one shot */
120         if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
121                 lwsl_notice("%s a\n", __func__);
122                 goto fail;
123         }
124
125         /* clear back-to-back write detection */
126         wsi->could_have_pending = 0;
127
128         lws_stats_bump(pt, LWSSTATS_C_WRITEABLE_CB, 1);
129 #if defined(LWS_WITH_STATS)
130         if (wsi->active_writable_req_us) {
131                 uint64_t ul = lws_now_usecs() -
132                                 wsi->active_writable_req_us;
133
134                 lws_stats_bump(pt, LWSSTATS_US_WRITABLE_DELAY_AVG, ul);
135                 lws_stats_max(pt,
136                           LWSSTATS_US_WORST_WRITABLE_DELAY, ul);
137                 wsi->active_writable_req_us = 0;
138         }
139 #endif
140         n = user_callback_handle_rxflow(wsi->protocol->callback,
141                         wsi, LWS_CALLBACK_RAW_WRITEABLE,
142                         wsi->user_space, NULL, 0);
143         if (n < 0) {
144                 lwsl_info("writeable_fail\n");
145                 goto fail;
146         }
147
148         return LWS_HPI_RET_HANDLED;
149
150 fail:
151         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "raw svc fail");
152
153         return LWS_HPI_RET_WSI_ALREADY_DIED;
154 }
155
156 #if !defined(LWS_NO_SERVER)
157 static int
158 rops_adoption_bind_raw_skt(struct lws *wsi, int type, const char *vh_prot_name)
159 {
160         /* no http but socket... must be raw skt */
161         if ((type & LWS_ADOPT_HTTP) || !(type & LWS_ADOPT_SOCKET) ||
162             (type & _LWS_ADOPT_FINISH))
163                 return 0; /* no match */
164
165 #if !defined(LWS_WITH_ESP32) && !defined(LWS_PLAT_OPTEE)
166         if (type & LWS_ADOPT_FLAG_UDP)
167                 /*
168                  * these can be >128 bytes, so just alloc for UDP
169                  */
170                 wsi->udp = lws_malloc(sizeof(*wsi->udp), "udp struct");
171 #endif
172
173         lws_role_transition(wsi, 0, (type & LWS_ADOPT_ALLOW_SSL) ? LRS_SSL_INIT :
174                                 LRS_ESTABLISHED, &role_ops_raw_skt);
175
176         if (vh_prot_name)
177                 lws_bind_protocol(wsi, wsi->protocol, __func__);
178         else
179                 /* this is the only time he will transition */
180                 lws_bind_protocol(wsi,
181                         &wsi->vhost->protocols[wsi->vhost->raw_protocol_index],
182                         __func__);
183
184         return 1; /* bound */
185 }
186 #endif
187
188 #if !defined(LWS_NO_CLIENT)
189 static int
190 rops_client_bind_raw_skt(struct lws *wsi,
191                          const struct lws_client_connect_info *i)
192 {
193         if (!i) {
194
195                 /* finalize */
196
197                 if (!wsi->user_space && wsi->stash->method)
198                         if (lws_ensure_user_space(wsi))
199                                 return 1;
200
201                 return 0;
202         }
203
204         /* we are a fallback if nothing else matched */
205
206         lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
207                             &role_ops_raw_skt);
208
209         return 1; /* matched */
210 }
211 #endif
212
213 struct lws_role_ops role_ops_raw_skt = {
214         /* role name */                 "raw-skt",
215         /* alpn id */                   NULL,
216         /* check_upgrades */            NULL,
217         /* init_context */              NULL,
218         /* init_vhost */                NULL,
219         /* destroy_vhost */             NULL,
220         /* periodic_checks */           NULL,
221         /* service_flag_pending */      NULL,
222         /* handle_POLLIN */             rops_handle_POLLIN_raw_skt,
223         /* handle_POLLOUT */            NULL,
224         /* perform_user_POLLOUT */      NULL,
225         /* callback_on_writable */      NULL,
226         /* tx_credit */                 NULL,
227         /* write_role_protocol */       NULL,
228         /* encapsulation_parent */      NULL,
229         /* alpn_negotiated */           NULL,
230         /* close_via_role_protocol */   NULL,
231         /* close_role */                NULL,
232         /* close_kill_connection */     NULL,
233         /* destroy_role */              NULL,
234 #if !defined(LWS_NO_SERVER)
235         /* adoption_bind */             rops_adoption_bind_raw_skt,
236 #else
237                                         NULL,
238 #endif
239 #if !defined(LWS_NO_CLIENT)
240         /* client_bind */               rops_client_bind_raw_skt,
241 #else
242                                         NULL,
243 #endif
244         /* adoption_cb clnt, srv */     { LWS_CALLBACK_RAW_CONNECTED,
245                                           LWS_CALLBACK_RAW_ADOPT },
246         /* rx_cb clnt, srv */           { LWS_CALLBACK_RAW_RX,
247                                           LWS_CALLBACK_RAW_RX },
248         /* writeable cb clnt, srv */    { LWS_CALLBACK_RAW_WRITEABLE,
249                                           LWS_CALLBACK_RAW_WRITEABLE},
250         /* close cb clnt, srv */        { LWS_CALLBACK_RAW_CLOSE,
251                                           LWS_CALLBACK_RAW_CLOSE },
252         /* protocol_bind cb c, srv */   { LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL,
253                                           LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL },
254         /* protocol_unbind cb c, srv */ { LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL,
255                                           LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL },
256         /* file_handle */               0,
257 };