1
0
Fork 0
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:
Bud Davis 2015-01-30 10:13:01 +08:00 committed by Andy Green
parent 413b3a6c55
commit 229bfec948
6 changed files with 114 additions and 20 deletions

View file

@ -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);

View file

@ -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)

View file

@ -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);
}

View file

@ -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)

View file

@ -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);

View file

@ -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;