{
struct libwebsocket_context *context = NULL;
char *p;
-
+#ifdef _WIN32
+ int i;
+#endif
int pid_daemon = get_daemonize_pid();
lwsl_notice("Initial logging level %d\n", log_level);
return NULL;
}
+#ifdef _WIN32
+ for (i = 0; i < FD_HASHTABLE_MODULUS; i++) {
+ context->fd_hashtable[i].wsi = lws_zalloc(sizeof(struct libwebsocket*) * context->max_fds);
+ }
+#else
context->lws_lookup = lws_zalloc(sizeof(struct libwebsocket *) * context->max_fds);
if (context->lws_lookup == NULL) {
lwsl_err(
lws_free(context);
return NULL;
}
+#endif
if (lws_plat_init_fd_tables(context)) {
+#ifndef _WIN32
lws_free(context->lws_lookup);
+#endif
lws_free(context->fds);
lws_free(context);
return NULL;
for (n = 0; n < context->fds_count; n++) {
struct libwebsocket *wsi =
- context->lws_lookup[context->fds[n].fd];
+ wsi_from_fd(context, context->fds[n].fd);
if (!wsi)
continue;
libwebsocket_close_and_free_session(context,
lws_ssl_context_destroy(context);
lws_free(context->fds);
+#ifndef _WIN32
lws_free(context->lws_lookup);
-
+#endif
lws_plat_context_late_destroy(context);
lws_free(context);
"LATENCY",
};
-
void
libwebsocket_close_and_free_session(struct libwebsocket_context *context,
struct libwebsocket *wsi, enum lws_close_status reason)
struct libwebsocket *wsi;
for (n = 0; n < context->fds_count; n++) {
- wsi = context->lws_lookup[context->fds[n].fd];
+ wsi = wsi_from_fd(context, context->fds[n].fd);
if (!wsi)
continue;
if (wsi->protocol == protocol)
struct libwebsocket *wsi;
for (n = 0; n < context->fds_count; n++) {
- wsi = context->lws_lookup[context->fds[n].fd];
+ wsi = wsi_from_fd(context, context->fds[n].fd);
if (!wsi)
continue;
if (wsi->protocol == protocol)
}
#endif
+/* file descriptor hash management */
+
+struct libwebsocket *
+wsi_from_fd(struct libwebsocket_context *context, int fd)
+{
+ int h = LWS_FD_HASH(fd);
+ int n = 0;
+
+ for (n = 0; n < context->fd_hashtable[h].length; n++)
+ if (context->fd_hashtable[h].wsi[n]->sock == fd)
+ return context->fd_hashtable[h].wsi[n];
+
+ return NULL;
+}
+
+int
+insert_wsi(struct libwebsocket_context *context, struct libwebsocket *wsi)
+{
+ int h = LWS_FD_HASH(wsi->sock);
+
+ if (context->fd_hashtable[h].length == (getdtablesize() - 1)) {
+ lwsl_err("hash table overflow\n");
+ return 1;
+ }
+
+ context->fd_hashtable[h].wsi[context->fd_hashtable[h].length++] = wsi;
+
+ return 0;
+}
+
+int
+delete_from_fd(struct libwebsocket_context *context, int fd)
+{
+ int h = LWS_FD_HASH(fd);
+ int n = 0;
+
+ for (n = 0; n < context->fd_hashtable[h].length; n++)
+ if (context->fd_hashtable[h].wsi[n]->sock == fd) {
+ while (n < context->fd_hashtable[h].length) {
+ context->fd_hashtable[h].wsi[n] =
+ context->fd_hashtable[h].wsi[n + 1];
+ n++;
+ }
+ context->fd_hashtable[h].length--;
+
+ return 0;
+ }
+
+ lwsl_err("Failed to find fd %d requested for "
+ "delete in hashtable\n", fd);
+ return 1;
+}
+
LWS_VISIBLE int libwebsockets_get_random(struct libwebsocket_context *context,
void *buf, int len)
{
continue;
if (pfd->events & LWS_POLLOUT) {
- if (context->lws_lookup[pfd->fd]->sock_send_blocking)
+ if (wsi_from_fd(context,pfd->fd)->sock_send_blocking)
continue;
pfd->revents = LWS_POLLOUT;
n = libwebsocket_service_fd(context, pfd);
pfd->revents = networkevents.lNetworkEvents;
if (pfd->revents & LWS_POLLOUT)
- context->lws_lookup[pfd->fd]->sock_send_blocking = FALSE;
+ wsi_from_fd(context,pfd->fd)->sock_send_blocking = FALSE;
return libwebsocket_service_fd(context, pfd);
}
return 1;
}
+#ifndef _WIN32
if (wsi->sock >= context->max_fds) {
lwsl_err("Socket fd %d is too high (%d)\n",
wsi->sock, context->max_fds);
return 1;
}
+#endif
assert(wsi);
assert(wsi->sock >= 0);
LWS_CALLBACK_LOCK_POLL,
wsi->user_space, (void *) &pa, 0);
- context->lws_lookup[wsi->sock] = wsi;
+ insert_wsi(context, wsi);
wsi->position_in_fds_table = context->fds_count;
context->fds[context->fds_count].fd = wsi->sock;
context->fds[context->fds_count].events = LWS_POLLIN;
* (still same fd pointing to same wsi)
*/
/* end guy's "position in fds table" changed */
- context->lws_lookup[context->fds[context->fds_count].fd]->
- position_in_fds_table = m;
+ wsi_from_fd(context,context->fds[context->fds_count].fd)->
+ position_in_fds_table = m;
/* deletion guy's lws_lookup entry needs nuking */
- context->lws_lookup[wsi->sock] = NULL;
+ delete_from_fd(context,wsi->sock);
/* removed wsi has no position any more */
wsi->position_in_fds_table = -1;
struct libwebsocket *wsi;
for (n = 0; n < context->fds_count; n++) {
- wsi = context->lws_lookup[context->fds[n].fd];
+ wsi = wsi_from_fd(context,context->fds[n].fd);
if (!wsi)
continue;
if (wsi->protocol == protocol)
#define MSG_NOSIGNAL SO_NOSIGPIPE
#endif
+#ifdef _WIN32
+#ifndef FD_HASHTABLE_MODULUS
+#define FD_HASHTABLE_MODULUS 32
+#endif
+#endif
+
#ifndef LWS_MAX_HEADER_LEN
#define LWS_MAX_HEADER_LEN 1024
#endif
};
#endif /* LWS_USE_LIBEV */
+#ifdef _WIN32
+#define LWS_FD_HASH(fd) ((fd ^ (fd >> 8) ^ (fd >> 16)) % FD_HASHTABLE_MODULUS)
+struct libwebsocket_fd_hashtable {
+ struct libwebsocket **wsi;
+ int length;
+};
+#endif
+
struct libwebsocket_context {
#ifdef _WIN32
WSAEVENT *events;
#endif
struct libwebsocket_pollfd *fds;
- struct libwebsocket **lws_lookup; /* fd to wsi */
+#ifdef _WIN32
+/* different implementation between unix and windows */
+ struct libwebsocket_fd_hashtable fd_hashtable[FD_HASHTABLE_MODULUS];
+#else
+ struct libwebsocket **lws_lookup; /* fd to wsi */
+#endif
int fds_count;
#ifdef LWS_USE_LIBEV
struct ev_loop* io_loop;
char pending_timeout; /* enum pending_timeout */
time_t pending_timeout_limit;
-
int sock;
int position_in_fds_table;
#ifdef LWS_LATENCY
LWS_EXTERN int
lws_b64_selftest(void);
+#ifdef _WIN32
LWS_EXTERN struct libwebsocket *
wsi_from_fd(struct libwebsocket_context *context, int fd);
+LWS_EXTERN int
+insert_wsi(struct libwebsocket_context *context, struct libwebsocket *wsi);
+
+LWS_EXTERN int
+delete_from_fd(struct libwebsocket_context *context, int fd);
+#else
+#define wsi_from_fd(A,B) A->lws_lookup[B]
+#define insert_wsi(A,B) A->lws_lookup[B->sock]=B
+#define delete_from_fd(A,B) A->lws_lookup[B]=0
+#endif
+
LWS_EXTERN int
insert_wsi_socket_into_fds(struct libwebsocket_context *context,
struct libwebsocket *wsi);
struct lws_tokens eff_buf;
if (context->listen_service_fd)
- listen_socket_fds_index = context->lws_lookup[
- context->listen_service_fd]->position_in_fds_table;
+ listen_socket_fds_index = wsi_from_fd(context,context->listen_service_fd)->position_in_fds_table;
- /*
+ /*
* you can call us with pollfd = NULL to just allow the once-per-second
* global timeout checks; if less than a second since the last check
* it returns immediately then.
for (n = 0; n < context->fds_count; n++) {
m = context->fds[n].fd;
- wsi = context->lws_lookup[m];
+ wsi = wsi_from_fd(context,m);
if (!wsi)
continue;
return 0;
/* no, here to service a socket descriptor */
- wsi = context->lws_lookup[pollfd->fd];
+ wsi = wsi_from_fd(context,pollfd->fd);
if (wsi == NULL)
/* not lws connection ... leave revents alone and return */
return 0;