Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_network_ws_limits.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
36
37#include "nilorea/n_log.h"
38#include "nilorea/n_network.h"
39#include "nilorea/n_str.h"
40
41#include <string.h>
42
44#define WS_LIMITS_PORT "27431"
45
52static int send_hostile_header(NETWORK* peer, uint64_t len) {
53 unsigned char hdr[10];
54 size_t i;
55 hdr[0] = 0x81; /* FIN + text */
56 hdr[1] = 0x7F; /* 64-bit extended length, not masked */
57 for (i = 0; i < 8; i++)
58 hdr[2 + i] = (unsigned char)((len >> (56 - 8 * i)) & 0xFF);
59 if (send_data(peer, (char*)hdr, (uint32_t)sizeof(hdr)) != (ssize_t)sizeof(hdr))
60 return -1;
61 return 0;
62}
63
70static int check_refused(const char* label, uint64_t len) {
71 NETWORK* server = NULL;
72 NETWORK* peer = NULL;
73 NETWORK* client = NULL;
74 N_WS_CONN conn;
75 N_WS_MESSAGE msg;
76 int rc;
77 int failed = 1;
78
79 memset(&conn, 0, sizeof(conn));
80 memset(&msg, 0, sizeof(msg));
81
82 if (netw_make_listening(&server, "127.0.0.1", (char*)WS_LIMITS_PORT, 1, NETWORK_IPV4) == FALSE) {
83 n_log(LOG_ERR, "FAIL(%s): could not listen on " WS_LIMITS_PORT, label);
84 return 1;
85 }
86 if (netw_connect_to(&client, "127.0.0.1", (char*)WS_LIMITS_PORT, NETWORK_IPV4, 2000) == FALSE) {
87 n_log(LOG_ERR, "FAIL(%s): could not connect to the listener", label);
89 return 1;
90 }
92 if (!peer) {
93 n_log(LOG_ERR, "FAIL(%s): listener did not accept", label);
94 netw_close(&client);
96 return 1;
97 }
98
99 if (send_hostile_header(peer, len) != 0) {
100 n_log(LOG_ERR, "FAIL(%s): could not send the frame header", label);
101 goto cleanup;
102 }
103
104 conn.netw = client;
105 conn.connected = 1;
106 rc = n_ws_recv(&conn, &msg);
107 if (rc == 0) {
108 n_log(LOG_ERR, "FAIL(%s): n_ws_recv ACCEPTED a declared payload of %llu bytes", label, (unsigned long long)len);
109 if (msg.payload)
110 free_nstr(&msg.payload);
111 } else {
112 n_log(LOG_INFO, "PASS(%s): n_ws_recv refused a declared payload of %llu bytes", label, (unsigned long long)len);
113 failed = 0;
114 }
115
116cleanup:
117 netw_close(&peer);
118 netw_close(&client);
120 return failed;
121}
122
123int main(void) {
124 int errors = 0;
125
127 n_log(LOG_INFO, "n_ws_recv frame-length bound: N_WS_MAX_PAYLOAD is %zu bytes", (size_t)N_WS_MAX_PAYLOAD);
128
129 /* the wrapping case: length + 1 for the terminator becomes 0, so the
130 allocation would come back a single byte and the payload read would run
131 off the end of it */
132 errors += check_refused("terminator wrap", (uint64_t)SIZE_MAX - 1);
133 /* the memory-exhaustion case: representable, but far past anything a real
134 peer sends */
135 errors += check_refused("over the cap", (uint64_t)N_WS_MAX_PAYLOAD + 1);
136
137 if (errors > 0) {
138 n_log(LOG_ERR, "ex_network_ws_limits: %d test(s) failed", errors);
139 exit(1);
140 }
141 n_log(LOG_INFO, "ex_network_ws_limits: all checks passed");
142 exit(0);
143}
int main(void)
Definition ex_atlas.c:117
NETWORK * server
#define WS_LIMITS_PORT
Port the local listener binds for this test.
static int send_hostile_header(NETWORK *peer, uint64_t len)
Send a raw WebSocket frame header naming a payload length of len.
static int check_refused(const char *label, uint64_t len)
Drive one hostile length through n_ws_recv and report the outcome.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:113
#define LOG_ERR
error conditions
Definition n_log.h:100
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
Definition n_log.c:123
#define LOG_INFO
informational
Definition n_log.h:106
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:203
NETWORK * netw
underlying network connection
Definition n_network.h:1073
int connected
1 if handshake completed
Definition n_network.h:1074
N_STR * payload
message payload
Definition n_network.h:1067
#define N_WS_MAX_PAYLOAD
Largest WebSocket payload n_ws_recv() will accept from a peer, in bytes.
Definition n_network.h:1062
int netw_make_listening(NETWORK **netw, char *addr, char *port, int nbpending, int ip_version)
Make a NETWORK be a Listening network.
Definition n_network.c:3493
#define NETWORK_IPV4
Flag to force IPV4.
Definition n_network.h:50
ssize_t send_data(void *netw, char *buf, uint32_t n)
send data onto the socket
Definition n_network.c:4824
NETWORK * netw_accept_from(NETWORK *from)
make a normal blocking 'accept' .
Definition n_network.c:4178
int netw_close(NETWORK **netw)
Closing a specified Network, destroy queues, free the structure.
Definition n_network.c:3258
int n_ws_recv(N_WS_CONN *conn, N_WS_MESSAGE *msg_out)
Receive one WebSocket frame.
Definition n_network.c:7157
int netw_connect_to(NETWORK **netw, char *host, char *port, int ip_version, int connect_timeout_ms)
Connect a NETWORK with a bounded connection-establishment time.
Definition n_network.c:2803
WebSocket connection.
Definition n_network.h:1072
WebSocket message.
Definition n_network.h:1065
Structure of a NETWORK.
Definition n_network.h:375
Generic log system.
Network Engine.
N_STR and string function declaration.