mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
win32 use hashtable for fd management
At least some win32 uses an opaque pointer for fd that is not an ordinal like it is in unix. Resurrect the old hashtable management for that platform to use instead, and introduce a helper to get the wsi from the fd "somehow". Signed-off-by: Bud Davis <bdavis9659@gmail.com>
This commit is contained in:
parent
413b3a6c55
commit
229bfec948
6 changed files with 114 additions and 20 deletions
|
@ -76,7 +76,9 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
{
|
||||
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);
|
||||
|
@ -145,6 +147,11 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
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(
|
||||
|
@ -154,9 +161,12 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
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;
|
||||
|
@ -292,7 +302,7 @@ libwebsocket_context_destroy(struct libwebsocket_context *context)
|
|||
|
||||
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,
|
||||
|
@ -329,8 +339,9 @@ libwebsocket_context_destroy(struct libwebsocket_context *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);
|
||||
|
|
|
@ -37,7 +37,6 @@ static const char * const log_level_names[] = {
|
|||
"LATENCY",
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
libwebsocket_close_and_free_session(struct libwebsocket_context *context,
|
||||
struct libwebsocket *wsi, enum lws_close_status reason)
|
||||
|
@ -451,7 +450,7 @@ libwebsocket_callback_all_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)
|
||||
|
@ -584,7 +583,7 @@ libwebsocket_rx_flow_allow_all_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)
|
||||
|
|
|
@ -33,6 +33,59 @@ time_t time(time_t *t)
|
|||
}
|
||||
#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)
|
||||
{
|
||||
|
@ -104,7 +157,7 @@ lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
|
|||
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);
|
||||
|
@ -143,7 +196,7 @@ lws_plat_service(struct libwebsocket_context *context, int timeout_ms)
|
|||
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);
|
||||
}
|
||||
|
|
12
lib/pollfd.c
12
lib/pollfd.c
|
@ -32,11 +32,13 @@ insert_wsi_socket_into_fds(struct libwebsocket_context *context,
|
|||
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);
|
||||
|
@ -48,7 +50,7 @@ insert_wsi_socket_into_fds(struct libwebsocket_context *context,
|
|||
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;
|
||||
|
@ -108,10 +110,10 @@ remove_wsi_socket_from_fds(struct libwebsocket_context *context,
|
|||
* (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;
|
||||
|
||||
|
@ -282,7 +284,7 @@ libwebsocket_callback_on_writable_all_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)
|
||||
|
|
|
@ -249,6 +249,12 @@ typedef unsigned __int64 u_int64_t;
|
|||
#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
|
||||
|
@ -412,12 +418,25 @@ struct lws_signal_watcher {
|
|||
};
|
||||
#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;
|
||||
|
@ -808,7 +827,6 @@ struct libwebsocket {
|
|||
|
||||
char pending_timeout; /* enum pending_timeout */
|
||||
time_t pending_timeout_limit;
|
||||
|
||||
int sock;
|
||||
int position_in_fds_table;
|
||||
#ifdef LWS_LATENCY
|
||||
|
@ -895,9 +913,21 @@ lws_http_action(struct libwebsocket_context *context, struct libwebsocket *wsi);
|
|||
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);
|
||||
|
|
|
@ -348,10 +348,9 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
|
|||
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.
|
||||
|
@ -372,7 +371,7 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
|
|||
|
||||
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;
|
||||
|
||||
|
@ -397,7 +396,7 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
|
|||
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;
|
||||
|
|
Loading…
Add table
Reference in a new issue