1 #include "private-libwebsockets.h"
2 #include "core-util/CriticalSectionLock.h"
4 extern "C" void *mbed3_create_tcp_stream_socket(void)
6 lws_conn_listener *srv = new lws_conn_listener;
8 //lwsl_notice("%s: %p\r\n", __func__, (void *)srv);
13 /* this is called by compatible_close() */
14 extern "C" void mbed3_delete_tcp_stream_socket(void *sock)
16 lws_conn *conn = (lws_conn *)sock;
20 lwsl_notice("%s: wsi %p: conn %p\r\n", __func__, (void *)conn->wsi, sock);
24 void lws_conn::serialized_writeable(struct lws *_wsi)
26 struct lws *wsi = (struct lws *)_wsi;
27 struct lws_pollfd pollfd;
28 lws_conn *conn = (lws_conn *)wsi->sock;
30 conn->awaiting_on_writeable = 0;
32 pollfd.fd = wsi->sock;
33 pollfd.events = POLLOUT;
34 pollfd.revents = POLLOUT;
36 lwsl_debug("%s: wsi %p\r\n", __func__, (void *)wsi);
38 lws_service_fd(lws_get_context(wsi), &pollfd);
41 extern "C" void mbed3_tcp_stream_bind(void *sock, int port, struct lws *wsi)
43 lws_conn_listener *srv = (lws_conn_listener *)sock;
45 lwsl_debug("%s\r\n", __func__);
46 /* associate us with the listening wsi */
47 ((lws_conn *)srv)->set_wsi(wsi);
49 mbed::util::FunctionPointer1<void, uint16_t> fp(srv, &lws_conn_listener::start);
50 minar::Scheduler::postCallback(fp.bind(port));
53 extern "C" void mbed3_tcp_stream_accept(void *sock, struct lws *wsi)
55 lws_conn *conn = (lws_conn *)sock;
57 lwsl_debug("%s\r\n", __func__);
61 extern "C" LWS_VISIBLE int
62 lws_plat_change_pollfd(struct lws_context *context,
63 struct lws *wsi, struct lws_pollfd *pfd)
65 lws_conn *conn = (lws_conn *)wsi->sock;
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);
76 lwsl_debug("%s: wsi %p (set awaiting_on_writeable)\r\n", __func__, (void *)wsi);
79 conn->awaiting_on_writeable = 0;
84 extern "C" LWS_VISIBLE int
85 lws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, int len)
90 lwsl_debug("%s\r\n", __func__);
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);
98 if (LWS_ERRNO == LWS_EAGAIN ||
99 LWS_ERRNO == LWS_EWOULDBLOCK ||
100 LWS_ERRNO == LWS_EINTR)
102 if (err == SOCKET_ERROR_WOULD_BLOCK)
104 return LWS_SSL_CAPABLE_MORE_SERVICE;
106 lwsl_warn("error on reading from skt: %d\n", err);
107 return LWS_SSL_CAPABLE_ERROR;
110 extern "C" LWS_VISIBLE int
111 lws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, int len)
114 lws_conn *conn = (lws_conn *)wsi->sock;
116 lwsl_debug("%s: wsi %p: write %d (from %p)\n", __func__, (void *)wsi, len, (void *)buf);
118 lwsl_debug("%s: wsi %p: clear writeable\n", __func__, (void *)wsi);
121 err = conn->ts->send((char *)buf, len);
122 if (err == SOCKET_ERROR_NONE)
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);
132 if (err == SOCKET_ERROR_WOULD_BLOCK)
133 return LWS_SSL_CAPABLE_MORE_SERVICE;
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;
141 * Set the listening socket to listen.
144 void lws_conn_listener::start(const uint16_t port)
146 socket_error_t err = srv.open(SOCKET_AF_INET4);
148 if (srv.error_check(err))
150 err = srv.bind("0.0.0.0", port);
151 if (srv.error_check(err))
153 err = srv.start_listening(TCPListener::IncomingHandler_t(this,
154 &lws_conn_listener::onIncoming));
155 srv.error_check(err);
158 void lws_conn::onRX(Socket *s)
160 struct lws_pollfd pollfd;
165 pollfd.events = POLLIN;
166 pollfd.revents = POLLIN;
168 lwsl_debug("%s: lws %p\n", __func__, wsi);
170 lws_service_fd(lws_get_context(wsi), &pollfd);
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.
178 void lws_conn_listener::onIncoming(TCPListener *tl, void *impl)
180 mbed::util::CriticalSectionLock lock;
184 onError(tl, SOCKET_ERROR_NULL_PTR);
188 conn = new(lws_conn);
193 conn->ts = srv.accept(impl);
197 conn->ts->setNagle(0);
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
204 lws_server_socket_service(lws_get_context(wsi),
205 wsi, (struct pollfd *)conn);
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));
213 conn->onRX((Socket *)conn->ts);
215 lwsl_debug("%s: exit\n", __func__);
218 extern "C" LWS_VISIBLE struct lws *
219 wsi_from_fd(const struct lws_context *context, lws_sockfd_type fd)
221 lws_conn *conn = (lws_conn *)fd;
227 extern "C" LWS_VISIBLE void
228 lws_plat_insert_socket_into_fds(struct lws_context *context,
232 lws_libev_io(wsi, LWS_EV_START | LWS_EV_READ);
233 context->pt[0].fds[context->pt[0].fds_count++].revents = 0;
236 extern "C" LWS_VISIBLE void
237 lws_plat_delete_socket_from_fds(struct lws_context *context,
238 struct lws *wsi, int m)
245 void lws_conn_listener::onDisconnect(TCPStream *s)
247 lwsl_info("%s\r\n", __func__);
253 extern "C" LWS_VISIBLE int
254 lws_plat_service(struct lws_context *context, int timeout_ms)
262 void lws_conn::onSent(Socket *s, uint16_t len)
264 struct lws_pollfd pollfd;
269 if (!awaiting_on_writeable) {
270 lwsl_debug("%s: wsi %p (setting writable=1)\r\n",
271 __func__, (void *)wsi);
278 pollfd.fd = wsi->sock;
279 pollfd.events = POLLOUT;
280 pollfd.revents = POLLOUT;
282 lwsl_debug("%s: wsi %p (servicing now)\r\n", __func__, (void *)wsi);
284 lws_service_fd(lws_get_context(wsi), &pollfd);
287 void lws_conn_listener::onError(Socket *s, socket_error_t err)
290 lwsl_notice("Socket Error: %s (%d)\r\n", socket_strerror(err), err);
295 void lws_conn::onDisconnect(TCPStream *s)
297 lwsl_notice("%s:\r\n", __func__);
299 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS);
303 void lws_conn::onError(Socket *s, socket_error_t err)
306 lwsl_notice("Socket Error: %s (%d)\r\n", socket_strerror(err), err);