mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
ip tos support
This commit is contained in:
parent
8d48d8f3fb
commit
eb782bd41e
14 changed files with 285 additions and 0 deletions
|
@ -78,6 +78,18 @@ enum lws_client_connect_ssl_connection_flags {
|
|||
/**< client is a link between SS client and SS proxy */
|
||||
LCCSCF_SECSTREAM_PROXY_ONWARD = (1 << 23),
|
||||
/**< client the SS proxy's onward connection */
|
||||
|
||||
LCCSCF_IP_LOW_LATENCY = (1 << 24),
|
||||
/**< set the "low delay" bit on the IP packets of this connection */
|
||||
LCCSCF_IP_HIGH_THROUGHPUT = (1 << 25),
|
||||
/**< set the "high throughput" bit on the IP packets of this
|
||||
* connection */
|
||||
LCCSCF_IP_HIGH_RELIABILITY = (1 << 26),
|
||||
/**< set the "high reliability" bit on the IP packets of this
|
||||
* connection */
|
||||
LCCSCF_IP_LOW_COST = (1 << 27),
|
||||
/**< set the "minimize monetary cost" bit on the IP packets of this
|
||||
* connection */
|
||||
};
|
||||
|
||||
/** struct lws_client_connect_info - parameters to connect with when using
|
||||
|
@ -177,6 +189,13 @@ struct lws_client_connect_info {
|
|||
* to the client connection.
|
||||
*/
|
||||
|
||||
uint8_t priority;
|
||||
/**< 0 means normal priority... otherwise sets the IP priority on
|
||||
* packets coming from this connection, from 1 - 7. Setting 7
|
||||
* (network management priority) requires CAP_NET_ADMIN capability but
|
||||
* the others can be set by anyone.
|
||||
*/
|
||||
|
||||
#if defined(LWS_ROLE_MQTT)
|
||||
const lws_mqtt_client_connect_param_t *mqtt_cp;
|
||||
#else
|
||||
|
|
|
@ -128,6 +128,15 @@ enum {
|
|||
/**< follow redirects */
|
||||
LWSSSPOLF_HTTP_MULTIPART_IN = (1 << 17),
|
||||
/**< handle inbound multipart mime at SS level */
|
||||
|
||||
LWSSSPOLF_ATTR_LOW_LATENCY = (1 << 18),
|
||||
/**< stream requires low latency */
|
||||
LWSSSPOLF_ATTR_HIGH_THROUGHPUT = (1 << 19),
|
||||
/**< stream requires high throughput */
|
||||
LWSSSPOLF_ATTR_HIGH_RELIABILITY = (1 << 20),
|
||||
/**< stream requires high reliability */
|
||||
LWSSSPOLF_ATTR_LOW_COST = (1 << 21),
|
||||
/**< stream is not critical and should be handled as cheap as poss */
|
||||
};
|
||||
|
||||
typedef struct lws_ss_trust_store {
|
||||
|
@ -334,6 +343,8 @@ typedef struct lws_ss_policy {
|
|||
uint8_t protocol; /**< protocol index */
|
||||
uint8_t client_cert; /**< which client cert to apply
|
||||
0 = none, 1+ = cc 0+ */
|
||||
uint8_t priority; /* 0 = normal, 6 = max normal,
|
||||
* 7 = network management */
|
||||
} lws_ss_policy_t;
|
||||
|
||||
#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)
|
||||
|
|
|
@ -281,6 +281,20 @@ lws_adopt_ss_server_accept(struct lws *new_wsi)
|
|||
|
||||
h->policy = new_wsi->a.vhost->ss_handle->policy;
|
||||
|
||||
/* apply requested socket options */
|
||||
if (lws_plat_set_socket_options_ip(new_wsi->desc.sockfd,
|
||||
h->policy->priority,
|
||||
(LCCSCF_IP_LOW_LATENCY *
|
||||
!!(h->policy->flags & LWSSSPOLF_ATTR_LOW_LATENCY)) |
|
||||
(LCCSCF_IP_HIGH_THROUGHPUT *
|
||||
!!(h->policy->flags & LWSSSPOLF_ATTR_HIGH_THROUGHPUT)) |
|
||||
(LCCSCF_IP_HIGH_RELIABILITY *
|
||||
!!(h->policy->flags & LWSSSPOLF_ATTR_HIGH_RELIABILITY)) |
|
||||
(LCCSCF_IP_LOW_COST *
|
||||
!!(h->policy->flags & LWSSSPOLF_ATTR_LOW_COST))))
|
||||
lwsl_warn("%s: %s: unable to set ip options\n",
|
||||
__func__, new_wsi->lc.gutag);
|
||||
|
||||
/*
|
||||
* add us to the list of clients that came in from the server
|
||||
*/
|
||||
|
|
|
@ -154,6 +154,9 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
|
|||
|
||||
wsi->seq = i->seq;
|
||||
wsi->flags = i->ssl_connection;
|
||||
|
||||
wsi->c_pri = i->priority;
|
||||
|
||||
if (i->retry_and_idle_policy)
|
||||
wsi->retry_policy = i->retry_and_idle_policy;
|
||||
else
|
||||
|
|
|
@ -324,6 +324,12 @@ ads_known:
|
|||
goto try_next_dns_result_closesock;
|
||||
}
|
||||
|
||||
/* apply requested socket options */
|
||||
if (lws_plat_set_socket_options_ip(wsi->desc.sockfd,
|
||||
wsi->c_pri, wsi->flags))
|
||||
lwsl_warn("%s: %s: unable to set ip options\n",
|
||||
__func__, wsi->lc.gutag);
|
||||
|
||||
lwsl_debug("%s: %s: WAITING_CONNECT\n", __func__, wsi->lc.gutag);
|
||||
lwsi_set_state(wsi, LRS_WAITING_CONNECT);
|
||||
|
||||
|
|
|
@ -898,6 +898,7 @@ struct lws {
|
|||
char chunk_parser; /* enum lws_chunk_parser */
|
||||
uint8_t addrinfo_idx;
|
||||
uint8_t sys_tls_client_cert;
|
||||
uint8_t c_pri;
|
||||
#endif
|
||||
#if defined(LWS_WITH_CGI) || defined(LWS_WITH_CLIENT)
|
||||
char reason_bf; /* internal writeable callback reason bitfield */
|
||||
|
@ -1067,6 +1068,9 @@ int
|
|||
lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
|
||||
int unix_skt);
|
||||
|
||||
int
|
||||
lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags);
|
||||
|
||||
int
|
||||
lws_plat_check_connection_error(struct lws *wsi);
|
||||
|
||||
|
|
|
@ -139,6 +139,63 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt)
|
|||
return lws_plat_set_nonblocking(fd);
|
||||
}
|
||||
|
||||
static const int ip_opt_lws_flags[] = {
|
||||
LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT,
|
||||
LCCSCF_IP_HIGH_RELIABILITY, LCCSCF_IP_LOW_COST
|
||||
}, ip_opt_val[] = {
|
||||
IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY, IPTOS_MINCOST
|
||||
};
|
||||
#if !defined(LWS_WITH_NO_LOGS)
|
||||
static const char *ip_opt_names[] = {
|
||||
"LOWDELAY", "THROUGHPUT", "RELIABILITY", "MINCOST"
|
||||
};
|
||||
#endif
|
||||
|
||||
int
|
||||
lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
|
||||
{
|
||||
int optval = (int)pri, ret = 0, n;
|
||||
socklen_t optlen = sizeof(optval);
|
||||
#if !defined(LWS_WITH_NO_LOGS)
|
||||
int en;
|
||||
#endif
|
||||
|
||||
#if defined(SO_PRIORITY)
|
||||
if (pri) { /* 0 is the default already */
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY,
|
||||
(const void *)&optval, optlen) < 0) {
|
||||
#if !defined(LWS_WITH_NO_LOGS)
|
||||
en = errno;
|
||||
lwsl_warn("%s: unable to set socket pri %d: errno %d\n",
|
||||
__func__, (int)pri, en);
|
||||
#endif
|
||||
ret = 1;
|
||||
} else
|
||||
lwsl_notice("%s: set pri %u\n", __func__, pri);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (n = 0; n < 4; n++) {
|
||||
if (!(lws_flags & ip_opt_lws_flags[n]))
|
||||
continue;
|
||||
|
||||
optval = (int)ip_opt_val[n];
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_TOS, (const void *)&optval,
|
||||
optlen) < 0) {
|
||||
#if !defined(LWS_WITH_NO_LOGS)
|
||||
en = errno;
|
||||
lwsl_warn("%s: unable to set %s: errno %d\n", __func__,
|
||||
ip_opt_names[n], en);
|
||||
#endif
|
||||
ret = 1;
|
||||
} else
|
||||
lwsl_notice("%s: set ip flag %s\n", __func__,
|
||||
ip_opt_names[n]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* cast a struct sockaddr_in6 * into addr for ipv6 */
|
||||
|
||||
int
|
||||
|
|
|
@ -256,6 +256,12 @@ lws_plat_inet_pton(int af, const char *src, void *dst)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
lws_plat_set_socket_options_ip(int fd, uint8_t pri, unsigned int lws_flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(LWS_WITH_MBEDTLS)
|
||||
int
|
||||
lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len)
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#include <netinet/ip.h>
|
||||
|
||||
int
|
||||
lws_send_pipe_choked(struct lws *wsi)
|
||||
{
|
||||
|
@ -188,6 +190,69 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt)
|
|||
return lws_plat_set_nonblocking(fd);
|
||||
}
|
||||
|
||||
static const int ip_opt_lws_flags[] = {
|
||||
LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT,
|
||||
LCCSCF_IP_HIGH_RELIABILITY, LCCSCF_IP_LOW_COST
|
||||
}, ip_opt_val[] = {
|
||||
IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY, IPTOS_MINCOST
|
||||
};
|
||||
#if !defined(LWS_WITH_NO_LOGS)
|
||||
static const char *ip_opt_names[] = {
|
||||
"LOWDELAY", "THROUGHPUT", "RELIABILITY", "MINCOST"
|
||||
};
|
||||
#endif
|
||||
|
||||
int
|
||||
lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
|
||||
{
|
||||
int optval = (int)pri, ret = 0, n;
|
||||
socklen_t optlen = sizeof(optval);
|
||||
#if !defined(LWS_WITH_NO_LOGS)
|
||||
int en;
|
||||
#endif
|
||||
|
||||
#if !defined(__APPLE__) && \
|
||||
!defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && \
|
||||
!defined(__NetBSD__) && \
|
||||
!defined(__OpenBSD__) && \
|
||||
!defined(__HAIKU__)
|
||||
|
||||
/* the BSDs don't have SO_PRIORITY */
|
||||
|
||||
if (pri) { /* 0 is the default already */
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY,
|
||||
(const void *)&optval, optlen) < 0) {
|
||||
#if !defined(LWS_WITH_NO_LOGS)
|
||||
en = errno;
|
||||
lwsl_warn("%s: unable to set socket pri %d: errno %d\n",
|
||||
__func__, (int)pri, en);
|
||||
#endif
|
||||
ret = 1;
|
||||
} else
|
||||
lwsl_notice("%s: set pri %u\n", __func__, pri);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (n = 0; n < 4; n++) {
|
||||
if (!(lws_flags & ip_opt_lws_flags[n]))
|
||||
continue;
|
||||
|
||||
optval = (int)ip_opt_val[n];
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_TOS, (const void *)&optval,
|
||||
optlen) < 0) {
|
||||
#if !defined(LWS_WITH_NO_LOGS)
|
||||
en = errno;
|
||||
lwsl_warn("%s: unable to set %s: errno %d\n", __func__,
|
||||
ip_opt_names[n], en);
|
||||
#endif
|
||||
ret = 1;
|
||||
} else
|
||||
lwsl_notice("%s: set ip flag %s\n", __func__,
|
||||
ip_opt_names[n]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* cast a struct sockaddr_in6 * into addr for ipv6 */
|
||||
|
||||
|
|
|
@ -144,6 +144,19 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
|
|||
return lws_plat_set_nonblocking(fd);
|
||||
}
|
||||
|
||||
int
|
||||
lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
|
||||
{
|
||||
/*
|
||||
* Seems to require "differeniated services" but no docs
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
|
||||
* https://docs.microsoft.com/en-us/previous-versions/windows/desktop/qos/differentiated-services
|
||||
*/
|
||||
lwsl_warn("%s: not implemented on windows platform\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lws_interface_to_sa(int ipv6,
|
||||
|
|
|
@ -394,6 +394,39 @@ payload buffering (in bytes) the client will hold for this type of stream. If
|
|||
the client sends a lot of data without any flow control, this may need to
|
||||
be correspondingly large. Default is 32KB.
|
||||
|
||||
### `attr_priority`
|
||||
|
||||
A number between 0 (normal priority) and 6 (very high priority). 7 is also
|
||||
possible, but requires CAP_NET_ADMIN on Linux and is reserved for network
|
||||
administration packets. Normally default priority is fine, but under some
|
||||
conditions when transporting over IP packets, you may want to control the
|
||||
IP packet ToS priority for the streamtype by using this.
|
||||
|
||||
### `attr_low_latency`
|
||||
|
||||
This is a flag indicating that the streamtype packets should be transported
|
||||
in a way that results in lower latency where there is a choice. For IP packets,
|
||||
this sets the ToS "low delay" flag on packets from this streamtype.
|
||||
|
||||
### `attr_high_throughput`
|
||||
|
||||
This is a flag indicating that this streamtype should be expected to produce
|
||||
bulk content that requires high throughput. For IP packets,
|
||||
this sets the ToS "high throughput" flag on packets from this streamtype.
|
||||
|
||||
### `attr_high_reliability`
|
||||
|
||||
This is a flag indicating that extra efforts should be made to deliver packets
|
||||
from this streamtype where possible. For IP packets, this sets the ToS "high
|
||||
reliability" flag on packets from this streamtype.
|
||||
|
||||
### `attr_low_cost`
|
||||
|
||||
This is a flag indicating that packets from this streamtype should be routed as
|
||||
inexpensively as possible by trading off latency and reliability where there is
|
||||
a choice. For IP packets, this sets the ToS "low cost" flag on packets from
|
||||
this streamtype.
|
||||
|
||||
### `metadata`
|
||||
|
||||
This allows declaring basically dynamic symbol names to be used by the streamtype,
|
||||
|
|
|
@ -53,6 +53,11 @@ static const char * const lejp_tokens_policy[] = {
|
|||
"s[].*.allow_redirects",
|
||||
"s[].*.urgent_tx",
|
||||
"s[].*.urgent_rx",
|
||||
"s[].*.attr_priority",
|
||||
"s[].*.attr_low_latency",
|
||||
"s[].*.attr_high_throughput",
|
||||
"s[].*.attr_high_reliability",
|
||||
"s[].*.attr_low_cost",
|
||||
"s[].*.long_poll",
|
||||
"s[].*.retry",
|
||||
"s[].*.timeout_ms",
|
||||
|
@ -142,6 +147,11 @@ typedef enum {
|
|||
LSSPPT_ALLOW_REDIRECTS,
|
||||
LSSPPT_URGENT_TX,
|
||||
LSSPPT_URGENT_RX,
|
||||
LSSPPT_ATTR_PRIORITY,
|
||||
LSSPPT_ATTR_LOW_LATENCY,
|
||||
LSSPPT_ATTR_HIGH_THROUGHPUT,
|
||||
LSSPPT_ATTR_HIGH_RELIABILITY,
|
||||
LSSPPT_ATTR_LOW_COST,
|
||||
LSSPPT_LONG_POLL,
|
||||
LSSPPT_RETRYPTR,
|
||||
LSSPPT_DEFAULT_TIMEOUT_MS,
|
||||
|
@ -667,6 +677,10 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
|
|||
a->curr[LTY_POLICY].p->timeout_ms = (uint32_t)atoi(ctx->buf);
|
||||
break;
|
||||
|
||||
case LSSPPT_ATTR_PRIORITY:
|
||||
a->curr[LTY_POLICY].p->priority = (uint8_t)atoi(ctx->buf);
|
||||
break;
|
||||
|
||||
case LSSPPT_OPPORTUNISTIC:
|
||||
if (reason == LEJPCB_VAL_TRUE)
|
||||
a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_OPPORTUNISTIC;
|
||||
|
@ -708,6 +722,29 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
|
|||
LWSSSPOLF_HTTP_MULTIPART_IN;
|
||||
return 0;
|
||||
|
||||
case LSSPPT_ATTR_LOW_LATENCY:
|
||||
if (reason == LEJPCB_VAL_TRUE)
|
||||
a->curr[LTY_POLICY].p->flags |=
|
||||
LWSSSPOLF_ATTR_LOW_LATENCY;
|
||||
return 0;
|
||||
|
||||
case LSSPPT_ATTR_HIGH_THROUGHPUT:
|
||||
if (reason == LEJPCB_VAL_TRUE)
|
||||
a->curr[LTY_POLICY].p->flags |=
|
||||
LWSSSPOLF_ATTR_HIGH_THROUGHPUT;
|
||||
return 0;
|
||||
|
||||
case LSSPPT_ATTR_HIGH_RELIABILITY:
|
||||
if (reason == LEJPCB_VAL_TRUE)
|
||||
a->curr[LTY_POLICY].p->flags |=
|
||||
LWSSSPOLF_ATTR_HIGH_RELIABILITY;
|
||||
return 0;
|
||||
|
||||
case LSSPPT_ATTR_LOW_COST:
|
||||
if (reason == LEJPCB_VAL_TRUE)
|
||||
a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_ATTR_LOW_COST;
|
||||
return 0;
|
||||
|
||||
case LSSPPT_RETRYPTR:
|
||||
bot = a->heads[LTY_BACKOFF].b;
|
||||
while (bot) {
|
||||
|
|
|
@ -592,6 +592,21 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw)
|
|||
if (h->policy->flags & LWSSSPOLF_WAKE_SUSPEND__VALIDITY)
|
||||
i.ssl_connection |= LCCSCF_WAKE_SUSPEND__VALIDITY;
|
||||
|
||||
/* translate policy attributes to IP ToS flags */
|
||||
|
||||
if (h->policy->flags & LCCSCF_IP_LOW_LATENCY)
|
||||
i.ssl_connection |= LWSSSPOLF_ATTR_LOW_LATENCY;
|
||||
if (h->policy->flags & LCCSCF_IP_HIGH_THROUGHPUT)
|
||||
i.ssl_connection |= LWSSSPOLF_ATTR_HIGH_THROUGHPUT;
|
||||
if (h->policy->flags & LCCSCF_IP_HIGH_RELIABILITY)
|
||||
i.ssl_connection |= LWSSSPOLF_ATTR_HIGH_RELIABILITY;
|
||||
if (h->policy->flags & LCCSCF_IP_LOW_COST)
|
||||
i.ssl_connection |= LWSSSPOLF_ATTR_LOW_COST;
|
||||
|
||||
/* mark the connection with the streamtype priority from the policy */
|
||||
|
||||
i.priority = h->policy->priority;
|
||||
|
||||
i.ssl_connection |= LCCSCF_SECSTREAM_CLIENT;
|
||||
|
||||
if (conn_if_sspc_onw) {
|
||||
|
|
|
@ -620,6 +620,8 @@ int main(int argc, const char **argv)
|
|||
printf("\t.timeout_ms = %u,\n", pol->timeout_ms);
|
||||
if (pol->flags)
|
||||
printf("\t.flags = 0x%x,\n", pol->flags);
|
||||
if (pol->flags)
|
||||
printf("\t.priority = 0x%x,\n", (unsigned int)pol->priority);
|
||||
if (pol->port)
|
||||
printf("\t.port = %u,\n", pol->port);
|
||||
if (pol->metadata_count)
|
||||
|
|
Loading…
Add table
Reference in a new issue