This adds two new callbacks in protocols[0] that are optional for allowing limited thread
access to libwebsockets, LWS_CALLBACK_LOCK_POLL and LWS_CALLBACK_UNLOCK_POLL.
If you use them, they protect internal and external poll list changes, but if you want to use
external thread access to libwebsocket_callback_on_writable() you have to implement your
locking here even if you don't use external poll support.
If you will use another thread for this, take a lot of care about managing your list of
live wsi by doing it from ESTABLISHED and CLOSED callbacks (with your own locking).
Signed-off-by: Andy Green <andy.green@linaro.org>
it explicitly.
+Two new callbacks are added in protocols[0] that are optional for allowing
+limited thread access to libwebsockets, LWS_CALLBACK_LOCK_POLL and
+LWS_CALLBACK_UNLOCK_POLL.
+
+If you use them, they protect internal and external poll list changes, but if
+you want to use external thread access to libwebsocket_callback_on_writable()
+you have to implement your locking here even if you don't use external
+poll support.
+
+If you will use another thread for this, take a lot of care about managing
+your list of live wsi by doing it from ESTABLISHED and CLOSED callbacks
+(with your own locking).
+
+
+
User api changes
----------------
* happening at a time when there's no real connection yet
*/
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
pollfd->events &= ~POLLOUT;
/* external POLL support via protocol 0 */
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
/* we can retry this... just cook the SSL BIO the first time */
if (wsi->use_ssl && !wsi->ssl) {
lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n",
wsi, wsi->sock, context->fds_count);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
context->lws_lookup[wsi->sock] = wsi;
wsi->position_in_fds_table = context->fds_count;
context->fds[context->fds_count].fd = wsi->sock;
LWS_CALLBACK_ADD_POLL_FD,
wsi->user_space, (void *)(long)wsi->sock, POLLIN);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
return 0;
}
{
int m;
- if (!--context->fds_count)
+ if (!--context->fds_count) {
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
goto do_ext;
+ }
if (wsi->sock > context->max_fds) {
lwsl_err("Socket fd %d too high (%d)\n",
lwsl_info("remove_wsi_socket_from_fds: wsi=%p, sock=%d, fds pos=%d\n",
wsi, wsi->sock, wsi->position_in_fds_table);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
m = wsi->position_in_fds_table; /* replace the contents for this */
/* have the last guy take up the vacant slot */
LWS_CALLBACK_DEL_POLL_FD, wsi->user_space,
(void *)(long)wsi->sock, 0);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
return 0;
}
/* one shot */
if (pollfd) {
+
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
pollfd->events &= ~POLLOUT;
/* external POLL support via protocol 0 */
context->protocols[0].callback(context, wsi,
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
+
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
}
#ifndef LWS_NO_EXTENSIONS
notify_action:
return -1;
}
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
context->fds[wsi->position_in_fds_table].events |= POLLOUT;
/* external POLL support via protocol 0 */
LWS_CALLBACK_SET_MODE_POLL_FD,
wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
return 1;
}
/* adjust the pollfd for this wsi */
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
if (wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW)
context->fds[wsi->position_in_fds_table].events |= POLLIN;
else
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
wsi->user_space, (void *)(long)wsi->sock, POLLIN);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
return 1;
}
#endif
LWS_CALLBACK_DEL_POLL_FD,
LWS_CALLBACK_SET_MODE_POLL_FD,
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
+ LWS_CALLBACK_LOCK_POLL,
+ LWS_CALLBACK_UNLOCK_POLL,
};
#ifndef LWS_NO_EXTENSIONS
break;
/* one shot */
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
pollfd->events &= ~POLLOUT;
+ /* external POLL support via protocol 0 */
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_CLEAR_MODE_POLL_FD,
+ wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
+
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
+
if (wsi->state != WSI_STATE_HTTP_ISSUING_FILE) {
n = user_callback_handle_rxflow(
wsi->protocol->callback,
case LWS_CONNMODE_SSL_ACK_PENDING:
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
pollfd->events &= ~POLLOUT;
/* external POLL support via protocol 0 */
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
lws_latency_pre(context, wsi);
n = recv(wsi->sock, context->service_buffer,
m, ERR_error_string(m, NULL));
if (m == SSL_ERROR_WANT_READ) {
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
context->fds[
wsi->position_in_fds_table].events |= POLLIN;
LWS_CALLBACK_SET_MODE_POLL_FD,
wsi->user_space,
(void *)(long)wsi->sock, POLLIN);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
lwsl_info("SSL_ERROR_WANT_READ\n");
break;
}
if (m == SSL_ERROR_WANT_WRITE) {
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
context->fds[
wsi->position_in_fds_table].events |= POLLOUT;
/* external POLL support via protocol 0 */
LWS_CALLBACK_SET_MODE_POLL_FD,
wsi->user_space,
(void *)(long)wsi->sock, POLLOUT);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
break;
}
lwsl_debug("SSL_accept failed skt %u: %s\n",
* protocol 0 callback
*/
+ case LWS_CALLBACK_LOCK_POLL:
+ /*
+ * lock mutex to protect pollfd state
+ * called before any other POLL related callback
+ */
+ break;
+
+ case LWS_CALLBACK_UNLOCK_POLL:
+ /*
+ * unlock mutex to protect pollfd state when
+ * called after any other POLL related callback
+ */
+ break;
+
case LWS_CALLBACK_ADD_POLL_FD:
if (count_pollfds >= max_poll_elements) {