1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

PEER_LIMITS: modernize to sa46 and add notification cb

There are a bunch of sa46-aware lws apis for formatting, etc sa46
in ./include/libwebsockets/lws-network-helper.h
This commit is contained in:
Andy Green 2020-05-24 19:44:46 +01:00
parent 4f3e012cdd
commit 90c7e789eb
6 changed files with 56 additions and 36 deletions

View file

@ -237,6 +237,10 @@ struct lws_ss_plugin;
typedef int (*lws_context_ready_cb_t)(struct lws_context *context);
typedef int (*lws_peer_limits_notify_t)(struct lws_context *ctx,
lws_sockfd_type sockfd,
lws_sockaddr46 *sa46);
/** struct lws_context_creation_info - parameters to create context and /or vhost with
*
* This is also used to create vhosts.... if LWS_SERVER_OPTION_EXPLICIT_VHOSTS
@ -738,6 +742,15 @@ struct lws_context_creation_info {
/**< 0 = inherit the initial ulimit for files / sockets from the startup
* environment. Nonzero = try to set the limit for this process.
*/
#if defined(LWS_WITH_PEER_LIMITS)
lws_peer_limits_notify_t pl_notify_cb;
/**< CONTEXT: NULL, or a callback to receive notifications each time a
* connection is being dropped because of peer limits.
*
* The callback provides the context, and an lws_sockaddr46 with the
* peer address and port.
*/
#endif
/* Add new things just above here ---^
* This is part of the ABI, don't needlessly break compatibility

View file

@ -338,11 +338,16 @@ lws_adopt_descriptor_vhost_via_info(const lws_adopt_desc_t *info)
if (peer && info->vh->context->ip_limit_wsi &&
peer->count_wsi >= info->vh->context->ip_limit_wsi) {
lwsl_notice("Peer reached wsi limit %d\n",
lwsl_info("Peer reached wsi limit %d\n",
info->vh->context->ip_limit_wsi);
lws_stats_bump(&info->vh->context->pt[0],
LWSSTATS_C_PEER_LIMIT_WSI_DENIED,
1);
if (info->vh->context->pl_notify_cb)
info->vh->context->pl_notify_cb(
info->vh->context,
info->fd.sockfd,
&peer->sa46);
compatible_close(info->fd.sockfd);
return NULL;
}

View file

@ -187,10 +187,11 @@ struct lws_peer {
struct lws_peer *next;
struct lws_peer *peer_wait_list;
lws_sockaddr46 sa46;
time_t time_created;
time_t time_closed_all;
uint8_t addr[32];
uint32_t hash;
uint32_t count_wsi;
uint32_t total_wsi;
@ -198,8 +199,6 @@ struct lws_peer {
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
struct lws_peer_role_http http;
#endif
uint8_t af;
};
#endif

View file

@ -661,6 +661,7 @@ lws_create_context(const struct lws_context_creation_info *info)
context->ip_limit_ah = info->ip_limit_ah;
context->ip_limit_wsi = info->ip_limit_wsi;
context->pl_notify_cb = info->pl_notify_cb;
#endif
lwsl_info(" mem: context: %5lu B (%ld ctx + (%ld thr x %d))\n",

View file

@ -432,9 +432,10 @@ struct lws_context {
#endif
#if defined(LWS_WITH_PEER_LIMITS)
struct lws_peer **pl_hash_table;
struct lws_peer *peer_wait_list;
time_t next_cull;
struct lws_peer **pl_hash_table;
struct lws_peer *peer_wait_list;
lws_peer_limits_notify_t pl_notify_cb;
time_t next_cull;
#endif
const lws_system_ops_t *system_ops;

View file

@ -1,7 +1,7 @@
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@ -60,42 +60,32 @@ struct lws_peer *
lws_get_or_create_peer(struct lws_vhost *vhost, lws_sockfd_type sockfd)
{
struct lws_context *context = vhost->context;
socklen_t rlen = 0;
void *q;
uint8_t *q8;
struct lws_peer *peer;
lws_sockaddr46 sa46;
socklen_t rlen = 0;
uint32_t hash = 0;
int n, af = AF_INET;
struct sockaddr_storage addr;
uint8_t *q8;
void *q;
int n;
if (vhost->options & LWS_SERVER_OPTION_UNIX_SOCK)
return NULL;
#ifdef LWS_WITH_IPV6
if (LWS_IPV6_ENABLED(vhost)) {
af = AF_INET6;
}
#endif
rlen = sizeof(addr);
if (getpeername(sockfd, (struct sockaddr*)&addr, &rlen))
rlen = sizeof(sa46);
if (getpeername(sockfd, (struct sockaddr*)&sa46, &rlen))
/* eg, udp doesn't have to have a peer */
return NULL;
#ifdef LWS_WITH_IPV6
if (af == AF_INET)
if (sa46.sa4.sin_family == AF_INET6) {
q = &sa46.sa6.sin6_addr;
rlen = sizeof(sa46.sa6.sin6_addr);
} else
#endif
{
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
q = &s->sin_addr;
rlen = sizeof(s->sin_addr);
q = &sa46.sa4.sin_addr;
rlen = sizeof(sa46.sa4.sin_addr);
}
#ifdef LWS_WITH_IPV6
else {
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
q = &s->sin6_addr;
rlen = sizeof(s->sin6_addr);
}
#endif
q8 = q;
for (n = 0; n < (int)rlen; n++)
@ -107,9 +97,21 @@ lws_get_or_create_peer(struct lws_vhost *vhost, lws_sockfd_type sockfd)
lws_start_foreach_ll(struct lws_peer *, peerx,
context->pl_hash_table[hash]) {
if (peerx->af == af && !memcmp(q, peerx->addr, rlen)) {
lws_context_unlock(context); /* === */
return peerx;
if (peerx->sa46.sa4.sin_family == sa46.sa4.sin_family) {
#if defined(LWS_WITH_IPV6)
if (sa46.sa4.sin_family == AF_INET6 &&
!memcmp(q, &peerx->sa46.sa6.sin6_addr, rlen))
goto hit;
#endif
if (sa46.sa4.sin_family == AF_INET &&
!memcmp(q, &peerx->sa46.sa4.sin_addr, rlen)) {
#if defined(LWS_WITH_IPV6)
hit:
#endif
lws_context_unlock(context); /* === */
return peerx;
}
}
} lws_end_foreach_ll(peerx, next);
@ -125,9 +127,8 @@ lws_get_or_create_peer(struct lws_vhost *vhost, lws_sockfd_type sockfd)
context->count_peers++;
peer->next = context->pl_hash_table[hash];
peer->hash = hash;
peer->af = af;
peer->sa46 = sa46;
context->pl_hash_table[hash] = peer;
memcpy(peer->addr, q, rlen);
time(&peer->time_created);
/*
* On creation, the peer has no wsi attached, so is created on the