add locking callback for fds

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>
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index 8b2fec5..5562573 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -118,6 +118,10 @@
 	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;
@@ -129,6 +133,10 @@
 		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;
 }
 
@@ -138,8 +146,12 @@
 {
 	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",
@@ -150,6 +162,10 @@
 	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 */
@@ -173,6 +189,10 @@
 		    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;
 }
 
@@ -789,12 +809,21 @@
 	/* 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:
@@ -1427,6 +1456,10 @@
 		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 */
@@ -1434,6 +1467,10 @@
 		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;
 }
 
@@ -1578,6 +1615,10 @@
 
 	/* 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
@@ -1594,6 +1635,10 @@
 			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