v1.7.9
[platform/upstream/libwebsockets.git] / lib / lws-plat-mbed3.cpp
1 #include "private-libwebsockets.h"
2 #include "core-util/CriticalSectionLock.h"
3
4 extern "C" void *mbed3_create_tcp_stream_socket(void)
5 {
6         lws_conn_listener *srv = new lws_conn_listener;
7
8         //lwsl_notice("%s: %p\r\n", __func__, (void *)srv);
9
10         return (void *)srv;
11 }
12
13 /* this is called by compatible_close() */
14 extern "C" void mbed3_delete_tcp_stream_socket(void *sock)
15 {
16         lws_conn *conn = (lws_conn *)sock;
17
18         conn->ts->close();
19
20         lwsl_notice("%s: wsi %p: conn %p\r\n", __func__, (void *)conn->wsi, sock);
21         delete conn;
22 }
23
24 void lws_conn::serialized_writeable(struct lws *_wsi)
25 {
26         struct lws *wsi = (struct lws *)_wsi;
27         struct lws_pollfd pollfd;
28         lws_conn *conn = (lws_conn *)wsi->sock;
29
30         conn->awaiting_on_writeable = 0;
31
32         pollfd.fd = wsi->sock;
33         pollfd.events = POLLOUT;
34         pollfd.revents = POLLOUT;
35
36         lwsl_debug("%s: wsi %p\r\n", __func__, (void *)wsi);
37
38         lws_service_fd(lws_get_context(wsi), &pollfd);
39 }
40
41 extern "C" void mbed3_tcp_stream_bind(void *sock, int port, struct lws *wsi)
42 {
43         lws_conn_listener *srv = (lws_conn_listener *)sock;
44
45         lwsl_debug("%s\r\n", __func__);
46         /* associate us with the listening wsi */
47         ((lws_conn *)srv)->set_wsi(wsi);
48
49         mbed::util::FunctionPointer1<void, uint16_t> fp(srv, &lws_conn_listener::start);
50         minar::Scheduler::postCallback(fp.bind(port));
51 }
52
53 extern "C" void mbed3_tcp_stream_accept(void *sock, struct lws *wsi)
54 {
55         lws_conn *conn = (lws_conn *)sock;
56
57         lwsl_debug("%s\r\n", __func__);
58         conn->set_wsi(wsi);
59 }
60
61 extern "C" LWS_VISIBLE int
62 lws_plat_change_pollfd(struct lws_context *context,
63                       struct lws *wsi, struct lws_pollfd *pfd)
64 {
65         lws_conn *conn = (lws_conn *)wsi->sock;
66
67         (void)context;
68         if (pfd->events & POLLOUT) {
69                 conn->awaiting_on_writeable = 1;
70                 if (conn->writeable) {
71                         mbed::util::FunctionPointer1<void, struct lws *> book(conn, &lws_conn::serialized_writeable);
72                         minar::Scheduler::postCallback(book.bind(wsi));
73                         lwsl_debug("%s: wsi %p (booked callback)\r\n", __func__, (void *)wsi);
74                 } else {
75
76                         lwsl_debug("%s: wsi %p (set awaiting_on_writeable)\r\n", __func__, (void *)wsi);
77                 }
78         } else
79                 conn->awaiting_on_writeable = 0;
80
81         return 0;
82 }
83
84 extern "C" LWS_VISIBLE int
85 lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len)
86 {
87         socket_error_t err;
88         size_t _len = len;
89
90         lwsl_debug("%s\r\n", __func__);
91
92         err = ((lws_conn *)wsi->sock)->ts->recv((char *)buf, &_len);
93         if (err == SOCKET_ERROR_NONE) {
94                 lwsl_info("%s: got %d bytes\n", __func__, _len);
95                 return _len;
96         }
97 #if LWS_POSIX
98         if (LWS_ERRNO == LWS_EAGAIN ||
99             LWS_ERRNO == LWS_EWOULDBLOCK ||
100             LWS_ERRNO == LWS_EINTR)
101 #else
102         if (err == SOCKET_ERROR_WOULD_BLOCK)
103 #endif
104                 return LWS_SSL_CAPABLE_MORE_SERVICE;
105
106         lwsl_warn("error on reading from skt: %d\n", err);
107         return LWS_SSL_CAPABLE_ERROR;
108 }
109
110 extern "C" LWS_VISIBLE int
111 lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len)
112 {
113         socket_error_t err;
114         lws_conn *conn = (lws_conn *)wsi->sock;
115
116         lwsl_debug("%s: wsi %p: write %d (from %p)\n", __func__, (void *)wsi, len, (void *)buf);
117
118         lwsl_debug("%s: wsi %p: clear writeable\n", __func__, (void *)wsi);
119         conn->writeable = 0;
120
121         err = conn->ts->send((char *)buf, len);
122         if (err == SOCKET_ERROR_NONE)
123                 return len;
124
125 #if LWS_POSIX
126         if (LWS_ERRNO == LWS_EAGAIN ||
127             LWS_ERRNO == LWS_EWOULDBLOCK ||
128             LWS_ERRNO == LWS_EINTR) {
129                 if (LWS_ERRNO == LWS_EWOULDBLOCK)
130                         lws_set_blocking_send(wsi);
131 #else
132         if (err == SOCKET_ERROR_WOULD_BLOCK)
133                 return LWS_SSL_CAPABLE_MORE_SERVICE;
134 #endif
135
136         lwsl_warn("%s: wsi %p: ERROR %d writing len %d to skt\n", __func__, (void *)wsi, err, len);
137         return LWS_SSL_CAPABLE_ERROR;
138 }
139
140 /*
141  * Set the listening socket to listen.
142  */
143
144 void lws_conn_listener::start(const uint16_t port)
145 {
146         socket_error_t err = srv.open(SOCKET_AF_INET4);
147
148         if (srv.error_check(err))
149                 return;
150         err = srv.bind("0.0.0.0", port);
151         if (srv.error_check(err))
152                 return;
153         err = srv.start_listening(TCPListener::IncomingHandler_t(this,
154                                         &lws_conn_listener::onIncoming));
155         srv.error_check(err);
156 }
157
158 void lws_conn::onRX(Socket *s)
159 {
160         struct lws_pollfd pollfd;
161
162         (void)s;
163
164         pollfd.fd = this;
165         pollfd.events = POLLIN;
166         pollfd.revents = POLLIN;
167
168         lwsl_debug("%s: lws %p\n", __func__, wsi);
169
170         lws_service_fd(lws_get_context(wsi), &pollfd);
171 }
172
173 /*
174  * this gets called from the OS when the TCPListener gets a connection that
175  * needs accept()-ing.  LWS needs to run the associated flow.
176  */
177
178 void lws_conn_listener::onIncoming(TCPListener *tl, void *impl)
179 {
180         mbed::util::CriticalSectionLock lock;
181         lws_conn *conn;
182
183         if (!impl) {
184                 onError(tl, SOCKET_ERROR_NULL_PTR);
185                 return;
186         }
187
188         conn = new(lws_conn);
189         if (!conn) {
190                 lwsl_err("OOM\n");
191                 return;
192         }
193         conn->ts = srv.accept(impl);
194         if (!conn->ts)
195                 return;
196
197         conn->ts->setNagle(0);
198
199         /*
200          * we use the listen socket wsi to get started, but a new wsi is
201          * created.  mbed3_tcp_stream_accept() is also called from
202          * here to bind the conn and new wsi together
203          */
204         lws_server_socket_service(lws_get_context(wsi),
205                                   wsi, (struct pollfd *)conn);
206
207         conn->ts->setOnError(TCPStream::ErrorHandler_t(conn, &lws_conn::onError));
208         conn->ts->setOnDisconnect(TCPStream::DisconnectHandler_t(conn,
209                             &lws_conn::onDisconnect));
210         conn->ts->setOnSent(Socket::SentHandler_t(conn, &lws_conn::onSent));
211         conn->ts->setOnReadable(TCPStream::ReadableHandler_t(conn, &lws_conn::onRX));
212
213         conn->onRX((Socket *)conn->ts);
214
215         lwsl_debug("%s: exit\n", __func__);
216 }
217
218 extern "C" LWS_VISIBLE struct lws *
219 wsi_from_fd(const struct lws_context *context, lws_sockfd_type fd)
220 {
221         lws_conn *conn = (lws_conn *)fd;
222         (void)context;
223
224         return conn->wsi;
225 }
226
227 extern "C" LWS_VISIBLE void
228 lws_plat_insert_socket_into_fds(struct lws_context *context,
229                                                        struct lws *wsi)
230 {
231         (void)wsi;
232         lws_libev_io(wsi, LWS_EV_START | LWS_EV_READ);
233         context->pt[0].fds[context->pt[0].fds_count++].revents = 0;
234 }
235
236 extern "C" LWS_VISIBLE void
237 lws_plat_delete_socket_from_fds(struct lws_context *context,
238                                                 struct lws *wsi, int m)
239 {
240         (void)context;
241         (void)wsi;
242         (void)m;
243 }
244
245 void lws_conn_listener::onDisconnect(TCPStream *s)
246 {
247         lwsl_info("%s\r\n", __func__);
248         (void)s;
249         //if (s)
250         //delete this;
251 }
252
253 extern "C" LWS_VISIBLE int
254 lws_plat_service(struct lws_context *context, int timeout_ms)
255 {
256         (void)context;
257         (void)timeout_ms;
258
259         return 0;
260 }
261
262 void lws_conn::onSent(Socket *s, uint16_t len)
263 {
264         struct lws_pollfd pollfd;
265
266         (void)s;
267         (void)len;
268
269         if (!awaiting_on_writeable) {
270                 lwsl_debug("%s: wsi %p (setting writable=1)\r\n",
271                            __func__, (void *)wsi);
272                 writeable = 1;
273                 return;
274         }
275
276         writeable = 1;
277
278         pollfd.fd = wsi->sock;
279         pollfd.events = POLLOUT;
280         pollfd.revents = POLLOUT;
281
282         lwsl_debug("%s: wsi %p (servicing now)\r\n", __func__, (void *)wsi);
283
284         lws_service_fd(lws_get_context(wsi), &pollfd);
285 }
286
287 void lws_conn_listener::onError(Socket *s, socket_error_t err)
288 {
289         (void) s;
290         lwsl_notice("Socket Error: %s (%d)\r\n", socket_strerror(err), err);
291         if (ts)
292                 ts->close();
293 }
294
295 void lws_conn::onDisconnect(TCPStream *s)
296 {
297         lwsl_notice("%s:\r\n", __func__);
298         (void)s;
299         lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
300 }
301
302
303 void lws_conn::onError(Socket *s, socket_error_t err)
304 {
305         (void) s;
306         lwsl_notice("Socket Error: %s (%d)\r\n", socket_strerror(err), err);
307         s->close();
308 }