1 /*
2 * Copyright (c) 2023, Emna Rekik
3 * Copyright (c) 2024 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include "server_internal.h"
9
10 #include <string.h>
11 #include <strings.h>
12
13 #include <zephyr/net/http/service.h>
14 #include <zephyr/net/socket.h>
15 #include <zephyr/posix/sys/eventfd.h>
16 #include <zephyr/ztest.h>
17
18 #define BUFFER_SIZE 1024
19 #define SERVER_IPV4_ADDR "127.0.0.1"
20 #define SERVER_PORT 8080
21 #define TIMEOUT_S 1
22
23 #define UPGRADE_STREAM_ID 1
24 #define TEST_STREAM_ID_1 3
25 #define TEST_STREAM_ID_2 5
26
27 #define TEST_DYNAMIC_POST_PAYLOAD "Test dynamic POST"
28 #define TEST_DYNAMIC_GET_PAYLOAD "Test dynamic GET"
29 #define TEST_STATIC_PAYLOAD "Hello, World!"
30 #define TEST_STATIC_FS_PAYLOAD "Hello, World from static file!"
31
32 /* Random base64 encoded data */
33 #define TEST_LONG_PAYLOAD_CHUNK_1 \
34 "Z3479c2x8gXgzvDpvt4YuQePsvmsur1J1U+lLKzkyGCQgtWEysRjnO63iZvN/Zaag5YlliAkcaWi" \
35 "Alb8zI4SxK+JB3kfpkcAA6c8m2PfkP6D5+Vrcy9O6ituR8gb0tm8o9CwTeUhf8H6q2kB5BO1ZZxm" \
36 "G9c3VO9BLLTC8LMG8isyzB1wT+EB8YTv4YaNc9mXJmXNt3pycZ4Thg20rPfhZsvleIeUYZZQJArx" \
37 "ufSBYR4v6mAEm/qdFqIwe9k6dtJEfR5guFoAWbR4jMrJreshyvByrZSy+aP1S93Fvob9hNn6ouSc"
38 #define TEST_LONG_PAYLOAD_CHUNK_2 \
39 "a0UIx0JKhFKvnM23kcavlMzwD+MerSiPUDYKSjtnjhhZmW3GonTpUWMEuDGZNkbrAZ3fbuWRbHi0" \
40 "1GufXYWGw/Jk6H6GV5WWWF9a71dng6gsH21zD1dqYIo46hofi4mfJ8Spo9a4Ch04ARNFSMhuLwYv" \
41 "eOprXUybMUiBVlTansXL2mdH2BgCPu4u65kIyAxcQpiXNGSJ3EjEIGIa"
42
43 static const char long_payload[] = TEST_LONG_PAYLOAD_CHUNK_1 TEST_LONG_PAYLOAD_CHUNK_2;
44 BUILD_ASSERT(sizeof(long_payload) - 1 > CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE,
45 "long_payload should be longer than client buffer to test payload being sent to "
46 "application across multiple calls to dynamic resource callback");
47
48 /* Individual HTTP2 frames, used to compose requests.
49 *
50 * Headers and data frames can be composed based on a "real" request by copying the frame from a
51 * wireshark capture (Copy --> ...as a hex stream) and formatting into a C array initializer using
52 * xxd:
53 *
54 * echo "<frame_as_hex_stream>" | xxd -r -p | xxd -i
55 *
56 * For example:
57 * $ echo "01234567" | xxd -r -p | xxd -i
58 * 0x01, 0x23, 0x45, 0x67
59 */
60 #define TEST_HTTP2_MAGIC \
61 0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x32, \
62 0x2e, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a
63 #define TEST_HTTP2_SETTINGS \
64 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, \
65 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x04, 0x00, 0x00, 0xff, 0xff
66 #define TEST_HTTP2_SETTINGS_ACK \
67 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00
68 #define TEST_HTTP2_GOAWAY \
69 0x00, 0x00, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, \
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
71 #define TEST_HTTP2_HEADERS_GET_ROOT_STREAM_1 \
72 0x00, 0x00, 0x21, 0x01, 0x05, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
73 0x82, 0x84, 0x86, 0x41, 0x8a, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xdc, \
74 0x78, 0x0f, 0x03, 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x90, 0x7a, 0x8a, 0xaa, \
75 0x69, 0xd2, 0x9a, 0xc4, 0xc0, 0x57, 0x68, 0x0b, 0x83
76 #define TEST_HTTP2_HEADERS_GET_INDEX_STREAM_2 \
77 0x00, 0x00, 0x21, 0x01, 0x05, 0x00, 0x00, 0x00, TEST_STREAM_ID_2, \
78 0x82, 0x85, 0x86, 0x41, 0x8a, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xdc, \
79 0x78, 0x0f, 0x03, 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x90, 0x7a, 0x8a, 0xaa, \
80 0x69, 0xd2, 0x9a, 0xc4, 0xc0, 0x57, 0x68, 0x0b, 0x83
81 #define TEST_HTTP2_HEADERS_GET_DYNAMIC_STREAM_1 \
82 0x00, 0x00, 0x2b, 0x01, 0x05, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
83 0x82, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, 0x04, \
84 0x86, 0x62, 0x4f, 0x55, 0x0e, 0x93, 0x13, 0x7a, 0x88, 0x25, 0xb6, 0x50, \
85 0xc3, 0xcb, 0xbc, 0xb8, 0x3f, 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x5f, 0x87, \
86 0x49, 0x7c, 0xa5, 0x8a, 0xe8, 0x19, 0xaa
87 #define TEST_HTTP2_HEADERS_GET_DYNAMIC_STREAM_1_PADDED \
88 0x00, 0x00, 0x3d, 0x01, 0x0d, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, 0x11,\
89 0x82, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, 0x04, \
90 0x86, 0x62, 0x4f, 0x55, 0x0e, 0x93, 0x13, 0x7a, 0x88, 0x25, 0xb6, 0x50, \
91 0xc3, 0xcb, 0xbc, 0xb8, 0x3f, 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x5f, 0x87, \
92 0x49, 0x7c, 0xa5, 0x8a, 0xe8, 0x19, 0xaa, \
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
94 0x00, 0x00, 0x00, 0x00, 0x00
95 #define TEST_HTTP2_HEADERS_GET_HEADER_CAPTURE1_STREAM_1 \
96 0x00, 0x00, 0x39, 0x01, 0x05, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
97 0x82, 0x04, 0x8b, 0x62, 0x72, 0x8e, 0x42, 0xd9, 0x11, 0x07, 0x5a, 0x6d, \
98 0xb0, 0xbf, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, \
99 0x7a, 0x88, 0x25, 0xb6, 0x50, 0xc3, 0xab, 0xbc, 0x15, 0xc1, 0x53, 0x03, \
100 0x2a, 0x2f, 0x2a, 0x40, 0x88, 0x49, 0x50, 0x95, 0xa7, 0x28, 0xe4, 0x2d, \
101 0x9f, 0x87, 0x49, 0x50, 0x98, 0xbb, 0x8e, 0x8b, 0x4b
102 #define TEST_HTTP2_HEADERS_GET_HEADER_CAPTURE2_STREAM_1 \
103 0x00, 0x00, 0x5a, 0x01, 0x05, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
104 0x82, 0x04, 0x8b, 0x62, 0x72, 0x8e, 0x42, 0xd9, 0x11, 0x07, 0x5a, 0x6d, \
105 0xb0, 0xbf, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, \
106 0x7a, 0xa9, 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xc6, 0x31, 0x8c, 0x63, \
107 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xc6, \
108 0x31, 0x8c, 0x63, 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x18, 0xc6, 0x31, 0x8c, \
109 0x63, 0x18, 0xc6, 0x31, 0x8c, 0x63, 0x1f, 0x53, 0x03, 0x2a, 0x2f, 0x2a, \
110 0x40, 0x88, 0x49, 0x50, 0x95, 0xa7, 0x28, 0xe4, 0x2d, 0x9f, 0x87, 0x49, \
111 0x50, 0x98, 0xbb, 0x8e, 0x8b, 0x4b
112 #define TEST_HTTP2_HEADERS_GET_HEADER_CAPTURE3_STREAM_1 \
113 0x00, 0x00, 0x4c, 0x01, 0x05, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
114 0x82, 0x04, 0x8b, 0x62, 0x72, 0x8e, 0x42, 0xd9, 0x11, 0x07, 0x5a, 0x6d, \
115 0xb0, 0xbf, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, \
116 0x7a, 0x88, 0x25, 0xb6, 0x50, 0xc3, 0xab, 0xbc, 0x15, 0xc1, 0x53, 0x03, \
117 0x2a, 0x2f, 0x2a, 0x40, 0x88, 0x49, 0x50, 0x95, 0xa7, 0x28, 0xe4, 0x2d, \
118 0x9f, 0x87, 0x49, 0x50, 0x98, 0xbb, 0x8e, 0x8b, 0x4b, 0x40, 0x88, 0x49, \
119 0x50, 0x95, 0xa7, 0x28, 0xe4, 0x2d, 0x82, 0x88, 0x49, 0x50, 0x98, 0xbb, \
120 0x8e, 0x8b, 0x4a, 0x2f
121 #define TEST_HTTP2_HEADERS_POST_HEADER_CAPTURE_WITH_TESTHEADER_STREAM_1 \
122 0x00, 0x00, 0x4b, 0x01, 0x04, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
123 0x83, 0x04, 0x8b, 0x62, 0x72, 0x8e, 0x42, 0xd9, 0x11, 0x07, 0x5a, 0x6d, \
124 0xb0, 0xbf, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, \
125 0x7a, 0x88, 0x25, 0xb6, 0x50, 0xc3, 0xab, 0xbc, 0x15, 0xc1, 0x53, 0x03, \
126 0x2a, 0x2f, 0x2a, 0x40, 0x88, 0x49, 0x50, 0x95, 0xa7, 0x28, 0xe4, 0x2d, \
127 0x9f, 0x87, 0x49, 0x50, 0x98, 0xbb, 0x8e, 0x8b, 0x4b, 0x5f, 0x8b, 0x1d, \
128 0x75, 0xd0, 0x62, 0x0d, 0x26, 0x3d, 0x4c, 0x74, 0x41, 0xea, 0x0f, 0x0d, \
129 0x02, 0x31, 0x30
130 #define TEST_HTTP2_HEADERS_POST_HEADER_CAPTURE2_NO_TESTHEADER_STREAM_2 \
131 0x00, 0x00, 0x39, 0x01, 0x04, 0x00, 0x00, 0x00, TEST_STREAM_ID_2, \
132 0x83, 0x04, 0x8b, 0x62, 0x72, 0x8e, 0x42, 0xd9, 0x11, 0x07, 0x5a, 0x6d, \
133 0xb0, 0xa2, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, \
134 0x7a, 0x88, 0x25, 0xb6, 0x50, 0xc3, 0xab, 0xbc, 0x15, 0xc1, 0x53, 0x03, \
135 0x2a, 0x2f, 0x2a, 0x5f, 0x8b, 0x1d, 0x75, 0xd0, 0x62, 0x0d, 0x26, 0x3d, \
136 0x4c, 0x74, 0x41, 0xea, 0x0f, 0x0d, 0x02, 0x31, 0x30
137 #define TEST_HTTP2_HEADERS_GET_RESPONSE_HEADERS_STREAM_1 \
138 0x00, 0x00, 0x28, 0x01, 0x05, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
139 0x82, 0x04, 0x8c, 0x62, 0xc2, 0xa2, 0xb3, 0xd4, 0x82, 0xc5, 0x39, 0x47, \
140 0x21, 0x6c, 0x47, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, \
141 0xff, 0x7a, 0x88, 0x25, 0xb6, 0x50, 0xc3, 0xab, 0xbc, 0x15, 0xc1, 0x53, \
142 0x03, 0x2a, 0x2f, 0x2a
143 #define TEST_HTTP2_HEADERS_POST_RESPONSE_HEADERS_STREAM_1 \
144 0x00, 0x00, 0x28, 0x01, 0x04, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
145 0x83, 0x04, 0x8c, 0x62, 0xc2, 0xa2, 0xb3, 0xd4, 0x82, 0xc5, 0x39, 0x47, \
146 0x21, 0x6c, 0x47, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, \
147 0xff, 0x7a, 0x88, 0x25, 0xb6, 0x50, 0xc3, 0xab, 0xbc, 0x15, 0xc1, 0x53, \
148 0x03, 0x2a, 0x2f, 0x2a
149 #define TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1 \
150 0x00, 0x00, 0x30, 0x01, 0x04, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
151 0x83, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, 0x04, \
152 0x86, 0x62, 0x4f, 0x55, 0x0e, 0x93, 0x13, 0x7a, 0x88, 0x25, 0xb6, 0x50, \
153 0xc3, 0xcb, 0xbc, 0xb8, 0x3f, 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x5f, 0x87, \
154 0x49, 0x7c, 0xa5, 0x8a, 0xe8, 0x19, 0xaa, 0x0f, 0x0d, 0x02, 0x31, 0x37
155 #define TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1_PRIORITY \
156 0x00, 0x00, 0x35, 0x01, 0x24, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
157 0x00, 0x00, 0x00, 0x00, 0x64, \
158 0x83, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, 0x04, \
159 0x86, 0x62, 0x4f, 0x55, 0x0e, 0x93, 0x13, 0x7a, 0x88, 0x25, 0xb6, 0x50, \
160 0xc3, 0xcb, 0xbc, 0xb8, 0x3f, 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x5f, 0x87, \
161 0x49, 0x7c, 0xa5, 0x8a, 0xe8, 0x19, 0xaa, 0x0f, 0x0d, 0x02, 0x31, 0x37
162 #define TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1_PRIORITY_PADDED \
163 0x00, 0x00, 0x40, 0x01, 0x2c, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
164 0x0a, 0x00, 0x00, 0x00, 0x00, 0xc8,\
165 0x83, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, 0x04, \
166 0x86, 0x62, 0x4f, 0x55, 0x0e, 0x93, 0x13, 0x7a, 0x88, 0x25, 0xb6, 0x50, \
167 0xc3, 0xcb, 0xbc, 0xb8, 0x3f, 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x5f, 0x87, \
168 0x49, 0x7c, 0xa5, 0x8a, 0xe8, 0x19, 0xaa, 0x0f, 0x0d, 0x02, 0x31, 0x37, \
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
170 #define TEST_HTTP2_PARTIAL_HEADERS_POST_DYNAMIC_STREAM_1 \
171 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
172 0x83, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, 0x04, \
173 0x86, 0x62, 0x4f, 0x55, 0x0e, 0x93, 0x13, 0x7a, 0x88, 0x25, 0xb6, 0x50, \
174 0xc3, 0xcb, 0xbc, 0xb8, 0x3f, 0x53, 0x03, 0x2a
175 #define TEST_HTTP2_CONTINUATION_POST_DYNAMIC_STREAM_1 \
176 0x00, 0x00, 0x10, 0x09, 0x04, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
177 0x2f, 0x2a, 0x5f, 0x87, 0x49, 0x7c, 0xa5, 0x8a, 0xe8, 0x19, 0xaa, 0x0f, \
178 0x0d, 0x02, 0x31, 0x37
179 #define TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1 \
180 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
181 0x54, 0x65, 0x73, 0x74, 0x20, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, \
182 0x20, 0x50, 0x4f, 0x53, 0x54
183 #define TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1_PADDED \
184 0x00, 0x00, 0x34, 0x00, 0x09, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, 0x22, \
185 0x54, 0x65, 0x73, 0x74, 0x20, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, \
186 0x20, 0x50, 0x4f, 0x53, 0x54, \
187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
190 #define TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1_NO_END_STREAM \
191 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
192 0x54, 0x65, 0x73, 0x74, 0x20, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, \
193 0x20, 0x50, 0x4f, 0x53, 0x54
194 #define TEST_HTTP2_DATA_POST_HEADER_CAPTURE_STREAM_1 \
195 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
196 0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x31, 0x7d
197 #define TEST_HTTP2_DATA_POST_HEADER_CAPTURE_STREAM_2 \
198 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, TEST_STREAM_ID_2, \
199 0x7b, 0x22, 0x74, 0x65, 0x73, 0x74, 0x22, 0x3a, 0x31, 0x7d
200 #define TEST_HTTP2_TRAILING_HEADER_STREAM_1 \
201 0x00, 0x00, 0x0c, 0x01, 0x05, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
202 0x40, 0x84, 0x92, 0xda, 0x69, 0xf5, 0x85, 0x9c, 0xa3, 0x90, 0xb6, 0x7f
203 #define TEST_HTTP2_RST_STREAM_STREAM_1 \
204 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
205 0xaa, 0xaa, 0xaa, 0xaa
206 #define TEST_HTTP2_HEADERS_PUT_DYNAMIC_STREAM_1 \
207 0x00, 0x00, 0x34, 0x01, 0x04, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
208 0x42, 0x03, 0x50, 0x55, 0x54, 0x86, 0x41, 0x87, 0x0b, 0xe2, 0x5c, 0x0b, \
209 0x89, 0x70, 0xff, 0x04, 0x86, 0x62, 0x4f, 0x55, 0x0e, 0x93, 0x13, 0x7a, \
210 0x88, 0x25, 0xb6, 0x50, 0xc3, 0xcb, 0xbc, 0xb8, 0x3f, 0x53, 0x03, 0x2a, \
211 0x2f, 0x2a, 0x5f, 0x87, 0x49, 0x7c, 0xa5, 0x8a, 0xe8, 0x19, 0xaa, 0x0f, \
212 0x0d, 0x02, 0x31, 0x37
213 #define TEST_HTTP2_HEADERS_PATCH_DYNAMIC_STREAM_1 \
214 0x00, 0x00, 0x36, 0x01, 0x04, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
215 0x42, 0x05, 0x50, 0x41, 0x54, 0x43, 0x48, 0x86, 0x41, 0x87, 0x0b, 0xe2, \
216 0x5c, 0x0b, 0x89, 0x70, 0xff, 0x04, 0x86, 0x62, 0x4f, 0x55, 0x0e, 0x93, \
217 0x13, 0x7a, 0x88, 0x25, 0xb6, 0x50, 0xc3, 0xcb, 0xbc, 0xb8, 0x3f, 0x53, \
218 0x03, 0x2a, 0x2f, 0x2a, 0x5f, 0x87, 0x49, 0x7c, 0xa5, 0x8a, 0xe8, 0x19, \
219 0xaa, 0x0f, 0x0d, 0x02, 0x31, 0x37
220 #define TEST_HTTP2_DATA_PUT_DYNAMIC_STREAM_1 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1
221 #define TEST_HTTP2_DATA_PATCH_DYNAMIC_STREAM_1 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1
222 #define TEST_HTTP2_HEADERS_DELETE_DYNAMIC_STREAM_1 \
223 0x00, 0x00, 0x32, 0x01, 0x05, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
224 0x42, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x86, 0x41, 0x87, 0x0b, \
225 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xff, 0x04, 0x86, 0x62, 0x4f, 0x55, 0x0e, \
226 0x93, 0x13, 0x7a, 0x88, 0x25, 0xb6, 0x50, 0xc3, 0xcb, 0xbc, 0xb8, 0x3f, \
227 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x5f, 0x87, 0x49, 0x7c, 0xa5, 0x8a, 0xe8, \
228 0x19, 0xaa
229 #define TEST_HTTP2_HEADERS_POST_ROOT_STREAM_1 \
230 0x00, 0x00, 0x21, 0x01, 0x05, 0x00, 0x00, 0x00, TEST_STREAM_ID_1, \
231 0x83, 0x84, 0x86, 0x41, 0x8a, 0x0b, 0xe2, 0x5c, 0x0b, 0x89, 0x70, 0xdc, \
232 0x78, 0x0f, 0x03, 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x90, 0x7a, 0x8a, 0xaa, \
233 0x69, 0xd2, 0x9a, 0xc4, 0xc0, 0x57, 0x68, 0x0b, 0x83
234 #define TEST_HTTP2_DATA_POST_ROOT_STREAM_1 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1
235
236 static uint16_t test_http_service_port = SERVER_PORT;
237 HTTP_SERVICE_DEFINE(test_http_service, SERVER_IPV4_ADDR,
238 &test_http_service_port, 1, 10, NULL, NULL);
239
240 static const char static_resource_payload[] = TEST_STATIC_PAYLOAD;
241 struct http_resource_detail_static static_resource_detail = {
242 .common = {
243 .type = HTTP_RESOURCE_TYPE_STATIC,
244 .bitmask_of_supported_http_methods = BIT(HTTP_GET),
245 },
246 .static_data = static_resource_payload,
247 .static_data_len = sizeof(static_resource_payload) - 1,
248 };
249
250 HTTP_RESOURCE_DEFINE(static_resource, test_http_service, "/",
251 &static_resource_detail);
252
253 static uint8_t dynamic_payload[32];
254 static size_t dynamic_payload_len = sizeof(dynamic_payload);
255 static bool dynamic_error;
256
dynamic_cb(struct http_client_ctx * client,enum http_data_status status,const struct http_request_ctx * request_ctx,struct http_response_ctx * response_ctx,void * user_data)257 static int dynamic_cb(struct http_client_ctx *client, enum http_data_status status,
258 const struct http_request_ctx *request_ctx,
259 struct http_response_ctx *response_ctx, void *user_data)
260 {
261 static size_t offset;
262
263 if (status == HTTP_SERVER_DATA_ABORTED) {
264 offset = 0;
265 return 0;
266 }
267
268 if (dynamic_error) {
269 return -ENOMEM;
270 }
271
272 switch (client->method) {
273 case HTTP_GET:
274 response_ctx->body = dynamic_payload;
275 response_ctx->body_len = dynamic_payload_len;
276 response_ctx->final_chunk = true;
277 break;
278 case HTTP_DELETE:
279 response_ctx->body = NULL;
280 response_ctx->body_len = 0;
281 response_ctx->final_chunk = true;
282 break;
283 case HTTP_POST:
284 case HTTP_PUT:
285 case HTTP_PATCH:
286 if (request_ctx->data_len + offset > sizeof(dynamic_payload)) {
287 return -ENOMEM;
288 }
289
290 if (request_ctx->data_len > 0) {
291 memcpy(dynamic_payload + offset, request_ctx->data, request_ctx->data_len);
292 offset += request_ctx->data_len;
293 }
294
295 if (status == HTTP_SERVER_DATA_FINAL) {
296 /* All data received, reset progress. */
297 dynamic_payload_len = offset;
298 offset = 0;
299 }
300
301 break;
302 default:
303 return -ENOTSUP;
304 }
305
306 return 0;
307 }
308
309 struct http_resource_detail_dynamic dynamic_detail = {
310 .common = {
311 .type = HTTP_RESOURCE_TYPE_DYNAMIC,
312 .bitmask_of_supported_http_methods =
313 BIT(HTTP_GET) | BIT(HTTP_DELETE) | BIT(HTTP_POST) |
314 BIT(HTTP_PUT) | BIT(HTTP_PATCH),
315 .content_type = "text/plain",
316 },
317 .cb = dynamic_cb,
318 .user_data = NULL,
319 };
320
321 HTTP_RESOURCE_DEFINE(dynamic_resource, test_http_service, "/dynamic",
322 &dynamic_detail);
323
324 struct test_headers_clone {
325 uint8_t buffer[CONFIG_HTTP_SERVER_CAPTURE_HEADER_BUFFER_SIZE];
326 struct http_header headers[CONFIG_HTTP_SERVER_CAPTURE_HEADER_COUNT];
327 size_t count;
328 enum http_header_status status;
329 };
330
dynamic_request_headers_cb(struct http_client_ctx * client,enum http_data_status status,const struct http_request_ctx * request_ctx,struct http_response_ctx * response_ctx,void * user_data)331 static int dynamic_request_headers_cb(struct http_client_ctx *client, enum http_data_status status,
332 const struct http_request_ctx *request_ctx,
333 struct http_response_ctx *response_ctx, void *user_data)
334 {
335 ptrdiff_t offset;
336 struct http_header *hdrs_src;
337 struct http_header *hdrs_dst;
338 struct test_headers_clone *clone = (struct test_headers_clone *)user_data;
339
340 if (request_ctx->header_count != 0) {
341 /* Copy the captured header info to static buffer for later assertions in testcase.
342 * Don't assume that the buffer inside client context remains valid after return
343 * from the callback. Also need to update pointers within structure with an offset
344 * to point at new buffer.
345 */
346 memcpy(clone->buffer, &client->header_capture_ctx, sizeof(clone->buffer));
347
348 clone->count = request_ctx->header_count;
349 clone->status = request_ctx->headers_status;
350
351 hdrs_src = request_ctx->headers;
352 hdrs_dst = clone->headers;
353 offset = clone->buffer - client->header_capture_ctx.buffer;
354
355 for (int i = 0; i < request_ctx->header_count; i++) {
356 if (hdrs_src[i].name != NULL) {
357 hdrs_dst[i].name = hdrs_src[i].name + offset;
358 }
359
360 if (hdrs_src[i].value != NULL) {
361 hdrs_dst[i].value = hdrs_src[i].value + offset;
362 }
363 }
364 }
365
366 return 0;
367 }
368
369 /* Define two resources for testing header capture, so that we can check concurrent streams */
370 static struct test_headers_clone request_headers_clone;
371 static struct test_headers_clone request_headers_clone2;
372
373 struct http_resource_detail_dynamic dynamic_request_headers_detail = {
374 .common = {
375 .type = HTTP_RESOURCE_TYPE_DYNAMIC,
376 .bitmask_of_supported_http_methods = BIT(HTTP_GET) | BIT(HTTP_POST),
377 .content_type = "text/plain",
378 },
379 .cb = dynamic_request_headers_cb,
380 .user_data = &request_headers_clone,
381 };
382
383 struct http_resource_detail_dynamic dynamic_request_headers_detail2 = {
384 .common = {
385 .type = HTTP_RESOURCE_TYPE_DYNAMIC,
386 .bitmask_of_supported_http_methods = BIT(HTTP_GET) | BIT(HTTP_POST),
387 .content_type = "text/plain",
388 },
389 .cb = dynamic_request_headers_cb,
390 .user_data = &request_headers_clone2,
391 };
392
393 HTTP_RESOURCE_DEFINE(dynamic_request_headers_resource, test_http_service, "/header_capture",
394 &dynamic_request_headers_detail);
395
396 HTTP_RESOURCE_DEFINE(dynamic_request_headers_resource2, test_http_service, "/header_capture2",
397 &dynamic_request_headers_detail2);
398
399 HTTP_SERVER_REGISTER_HEADER_CAPTURE(capture_user_agent, "User-Agent");
400 HTTP_SERVER_REGISTER_HEADER_CAPTURE(capture_test_header, "Test-Header");
401 HTTP_SERVER_REGISTER_HEADER_CAPTURE(capture_test_header2, "Test-Header2");
402
403 enum dynamic_response_headers_variant {
404 /* No application defined response code, headers or data */
405 DYNAMIC_RESPONSE_HEADERS_VARIANT_NONE,
406
407 /* Send a 422 response code */
408 DYNAMIC_RESPONSE_HEADERS_VARIANT_422,
409
410 /* Send an extra header on top of server defaults */
411 DYNAMIC_RESPONSE_HEADERS_VARIANT_EXTRA_HEADER,
412
413 /* Override the default Content-Type header */
414 DYNAMIC_RESPONSE_HEADERS_VARIANT_OVERRIDE_HEADER,
415
416 /* Send body data combined with header data in a single callback */
417 DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_COMBINED,
418
419 /* Send body data in a separate callback to header data */
420 DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_SEPARATE,
421
422 /* Long body data split across multiple callbacks */
423 DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG,
424 };
425
426 static uint8_t dynamic_response_headers_variant;
427 static uint8_t dynamic_response_headers_buffer[sizeof(long_payload)];
428
dynamic_response_headers_cb(struct http_client_ctx * client,enum http_data_status status,const struct http_request_ctx * request_ctx,struct http_response_ctx * response_ctx,void * user_data)429 static int dynamic_response_headers_cb(struct http_client_ctx *client, enum http_data_status status,
430 const struct http_request_ctx *request_ctx,
431 struct http_response_ctx *response_ctx, void *user_data)
432 {
433 static bool request_continuation;
434 static size_t offset;
435
436 static const struct http_header extra_headers[] = {
437 {.name = "Test-Header", .value = "test_data"},
438 };
439
440 static const struct http_header override_headers[] = {
441 {.name = "Content-Type", .value = "application/json"},
442 };
443
444 if (status != HTTP_SERVER_DATA_FINAL &&
445 dynamic_response_headers_variant != DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG) {
446 /* Long body variant is the only one which needs to take some action before final
447 * data has been received from server
448 */
449 return 0;
450 }
451
452 switch (dynamic_response_headers_variant) {
453 case DYNAMIC_RESPONSE_HEADERS_VARIANT_NONE:
454 break;
455
456 case DYNAMIC_RESPONSE_HEADERS_VARIANT_422:
457 response_ctx->status = 422;
458 response_ctx->final_chunk = true;
459 break;
460
461 case DYNAMIC_RESPONSE_HEADERS_VARIANT_EXTRA_HEADER:
462 response_ctx->headers = extra_headers;
463 response_ctx->header_count = ARRAY_SIZE(extra_headers);
464 response_ctx->final_chunk = true;
465 break;
466
467 case DYNAMIC_RESPONSE_HEADERS_VARIANT_OVERRIDE_HEADER:
468 response_ctx->headers = override_headers;
469 response_ctx->header_count = ARRAY_SIZE(extra_headers);
470 response_ctx->final_chunk = true;
471 break;
472
473 case DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_SEPARATE:
474 if (!request_continuation) {
475 /* Send headers in first callback */
476 response_ctx->headers = extra_headers;
477 response_ctx->header_count = ARRAY_SIZE(extra_headers);
478 request_continuation = true;
479 } else {
480 /* Send body in subsequent callback */
481 response_ctx->body = TEST_DYNAMIC_GET_PAYLOAD;
482 response_ctx->body_len = strlen(response_ctx->body);
483 response_ctx->final_chunk = true;
484 request_continuation = false;
485 }
486 break;
487
488 case DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_COMBINED:
489 response_ctx->headers = extra_headers;
490 response_ctx->header_count = ARRAY_SIZE(extra_headers);
491 response_ctx->body = TEST_DYNAMIC_GET_PAYLOAD;
492 response_ctx->body_len = strlen(response_ctx->body);
493 response_ctx->final_chunk = true;
494 break;
495
496 case DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG:
497 if (client->method == HTTP_GET) {
498 /* Send GET payload split across multiple callbacks */
499 size_t send_len = (offset == 0) ? strlen(TEST_LONG_PAYLOAD_CHUNK_1)
500 : strlen(TEST_LONG_PAYLOAD_CHUNK_2);
501
502 response_ctx->body = long_payload + offset;
503 response_ctx->body_len = send_len;
504 offset += send_len;
505
506 if (offset == strlen(long_payload)) {
507 offset = 0;
508 response_ctx->final_chunk = true;
509 }
510 } else if (client->method == HTTP_POST) {
511 /* Copy POST payload into buffer for later comparison */
512 zassert(offset + request_ctx->data_len <=
513 sizeof(dynamic_response_headers_buffer),
514 "POST data too long for buffer");
515 memcpy(dynamic_response_headers_buffer + offset, request_ctx->data,
516 request_ctx->data_len);
517 offset += request_ctx->data_len;
518
519 if (status == HTTP_SERVER_DATA_FINAL) {
520 offset = 0;
521 }
522 } else {
523 zassert(false, "unexpected HTTP method");
524 }
525 break;
526 }
527
528 return 0;
529 }
530
531 struct http_resource_detail_dynamic dynamic_response_headers_detail = {
532 .common = {
533 .type = HTTP_RESOURCE_TYPE_DYNAMIC,
534 .bitmask_of_supported_http_methods = BIT(HTTP_GET) | BIT(HTTP_POST),
535 .content_type = "text/plain",
536 },
537 .cb = dynamic_response_headers_cb,
538 .user_data = NULL
539 };
540
541 HTTP_RESOURCE_DEFINE(dynamic_response_headers_resource, test_http_service, "/response_headers",
542 &dynamic_response_headers_detail);
543
544 static int client_fd = -1;
545 static uint8_t buf[BUFFER_SIZE];
546
547 /* This function ensures that there's at least as much data as requested in
548 * the buffer.
549 */
test_read_data(size_t * offset,size_t need)550 static void test_read_data(size_t *offset, size_t need)
551 {
552 int ret;
553
554 while (*offset < need) {
555 ret = zsock_recv(client_fd, buf + *offset, sizeof(buf) - *offset, 0);
556 zassert_not_equal(ret, -1, "recv() failed (%d)", errno);
557 *offset += ret;
558 if (ret == 0) {
559 break;
560 }
561 };
562
563 zassert_true(*offset >= need, "Not all requested data received");
564 }
565
566 /* This function moves the remaining data in the buffer to the beginning. */
test_consume_data(size_t * offset,size_t consume)567 static void test_consume_data(size_t *offset, size_t consume)
568 {
569 zassert_true(*offset >= consume, "Cannot consume more data than received");
570 *offset -= consume;
571 memmove(buf, buf + consume, *offset);
572 }
573
expect_http1_switching_protocols(size_t * offset)574 static void expect_http1_switching_protocols(size_t *offset)
575 {
576 static const char switching_protocols[] =
577 "HTTP/1.1 101 Switching Protocols\r\n"
578 "Connection: Upgrade\r\n"
579 "Upgrade: h2c\r\n"
580 "\r\n";
581
582 test_read_data(offset, sizeof(switching_protocols) - 1);
583 zassert_mem_equal(buf, switching_protocols, sizeof(switching_protocols) - 1,
584 "Received data doesn't match expected response");
585 test_consume_data(offset, sizeof(switching_protocols) - 1);
586 }
587
test_get_frame_header(size_t * offset,struct http2_frame * frame)588 static void test_get_frame_header(size_t *offset, struct http2_frame *frame)
589 {
590 test_read_data(offset, HTTP2_FRAME_HEADER_SIZE);
591
592 frame->length = sys_get_be24(&buf[HTTP2_FRAME_LENGTH_OFFSET]);
593 frame->type = buf[HTTP2_FRAME_TYPE_OFFSET];
594 frame->flags = buf[HTTP2_FRAME_FLAGS_OFFSET];
595 frame->stream_identifier = sys_get_be32(
596 &buf[HTTP2_FRAME_STREAM_ID_OFFSET]);
597 frame->stream_identifier &= HTTP2_FRAME_STREAM_ID_MASK;
598
599 test_consume_data(offset, HTTP2_FRAME_HEADER_SIZE);
600 }
601
expect_http2_settings_frame(size_t * offset,bool ack)602 static void expect_http2_settings_frame(size_t *offset, bool ack)
603 {
604 struct http2_frame frame;
605
606 test_get_frame_header(offset, &frame);
607
608 zassert_equal(frame.type, HTTP2_SETTINGS_FRAME, "Expected settings frame");
609 zassert_equal(frame.stream_identifier, 0, "Settings frame stream ID must be 0");
610
611 if (ack) {
612 zassert_equal(frame.length, 0, "Invalid settings frame length");
613 zassert_equal(frame.flags, HTTP2_FLAG_SETTINGS_ACK,
614 "Expected settings ACK flag");
615 } else {
616 zassert_equal(frame.length % sizeof(struct http2_settings_field), 0,
617 "Invalid settings frame length");
618 zassert_equal(frame.flags, 0, "Expected no settings flags");
619
620 /* Consume settings payload */
621 test_read_data(offset, frame.length);
622 test_consume_data(offset, frame.length);
623 }
624 }
625
expect_contains_header(const uint8_t * buffer,size_t len,const struct http_header * header)626 static void expect_contains_header(const uint8_t *buffer, size_t len,
627 const struct http_header *header)
628 {
629 int ret;
630 bool found = false;
631 struct http_hpack_header_buf header_buf;
632 size_t consumed = 0;
633
634 while (consumed < len) {
635 ret = http_hpack_decode_header(buffer + consumed, len, &header_buf);
636 zassert_true(ret >= 0, "Failed to decode header");
637 zassert_true(consumed + ret <= len, "Frame length exceeded");
638
639 if (strncasecmp(header_buf.name, header->name, header_buf.name_len) == 0 &&
640 strncasecmp(header_buf.value, header->value, header_buf.value_len) == 0) {
641 found = true;
642 break;
643 }
644
645 consumed += ret;
646 }
647
648 zassert_true(found, "Header '%s: %s' not found", header->name, header->value);
649 }
650
expect_http2_headers_frame(size_t * offset,int stream_id,uint8_t flags,const struct http_header * headers,size_t headers_count)651 static void expect_http2_headers_frame(size_t *offset, int stream_id, uint8_t flags,
652 const struct http_header *headers, size_t headers_count)
653 {
654 struct http2_frame frame;
655
656 test_get_frame_header(offset, &frame);
657
658 zassert_equal(frame.type, HTTP2_HEADERS_FRAME, "Expected headers frame, got frame type %u",
659 frame.type);
660 zassert_equal(frame.stream_identifier, stream_id,
661 "Invalid headers frame stream ID");
662 zassert_equal(frame.flags, flags, "Unexpected flags received (expected %x got %x)", flags,
663 frame.flags);
664
665 /* Consume headers payload */
666 test_read_data(offset, frame.length);
667
668 for (size_t i = 0; i < headers_count; i++) {
669 expect_contains_header(buf, frame.length, &headers[i]);
670 }
671
672 test_consume_data(offset, frame.length);
673 }
674
675 /* "payload" may be NULL to skip data frame content validation. */
expect_http2_data_frame(size_t * offset,int stream_id,const uint8_t * payload,size_t payload_len,uint8_t flags)676 static void expect_http2_data_frame(size_t *offset, int stream_id,
677 const uint8_t *payload, size_t payload_len,
678 uint8_t flags)
679 {
680 struct http2_frame frame;
681
682 test_get_frame_header(offset, &frame);
683
684 zassert_equal(frame.type, HTTP2_DATA_FRAME, "Expected data frame");
685 zassert_equal(frame.stream_identifier, stream_id,
686 "Invalid data frame stream ID");
687 zassert_equal(frame.flags, flags, "Unexpected flags received");
688 if (payload != NULL) {
689 zassert_equal(frame.length, payload_len,
690 "Unexpected data frame length");
691 }
692
693 /* Verify data payload */
694 test_read_data(offset, frame.length);
695 if (payload != NULL) {
696 zassert_mem_equal(buf, payload, payload_len,
697 "Unexpected data payload");
698 }
699 test_consume_data(offset, frame.length);
700 }
701
expect_http2_window_update_frame(size_t * offset,int stream_id)702 static void expect_http2_window_update_frame(size_t *offset, int stream_id)
703 {
704 struct http2_frame frame;
705
706 test_get_frame_header(offset, &frame);
707
708 zassert_equal(frame.type, HTTP2_WINDOW_UPDATE_FRAME,
709 "Expected window update frame");
710 zassert_equal(frame.stream_identifier, stream_id,
711 "Invalid window update frame stream ID (expected %d got %d)", stream_id,
712 frame.stream_identifier);
713 zassert_equal(frame.flags, 0, "Unexpected flags received");
714 zassert_equal(frame.length, sizeof(uint32_t),
715 "Unexpected window update frame length");
716
717
718 /* Consume window update payload */
719 test_read_data(offset, frame.length);
720 test_consume_data(offset, frame.length);
721 }
722
ZTEST(server_function_tests,test_http2_get_concurrent_streams)723 ZTEST(server_function_tests, test_http2_get_concurrent_streams)
724 {
725 static const uint8_t request_get_2_streams[] = {
726 TEST_HTTP2_MAGIC,
727 TEST_HTTP2_SETTINGS,
728 TEST_HTTP2_SETTINGS_ACK,
729 TEST_HTTP2_HEADERS_GET_ROOT_STREAM_1,
730 TEST_HTTP2_HEADERS_GET_INDEX_STREAM_2,
731 TEST_HTTP2_GOAWAY,
732 };
733 size_t offset = 0;
734 int ret;
735
736 ret = zsock_send(client_fd, request_get_2_streams,
737 sizeof(request_get_2_streams), 0);
738 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
739
740 memset(buf, 0, sizeof(buf));
741
742 /* Settings frame is expected twice (server settings + settings ACK) */
743 expect_http2_settings_frame(&offset, false);
744 expect_http2_settings_frame(&offset, true);
745 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1, HTTP2_FLAG_END_HEADERS, NULL, 0);
746 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, TEST_STATIC_PAYLOAD,
747 strlen(TEST_STATIC_PAYLOAD),
748 HTTP2_FLAG_END_STREAM);
749 expect_http2_headers_frame(&offset, TEST_STREAM_ID_2, HTTP2_FLAG_END_HEADERS, NULL, 0);
750 expect_http2_data_frame(&offset, TEST_STREAM_ID_2, NULL, 0,
751 HTTP2_FLAG_END_STREAM);
752 }
753
ZTEST(server_function_tests,test_http2_static_get)754 ZTEST(server_function_tests, test_http2_static_get)
755 {
756 static const uint8_t request_get_static_simple[] = {
757 TEST_HTTP2_MAGIC,
758 TEST_HTTP2_SETTINGS,
759 TEST_HTTP2_SETTINGS_ACK,
760 TEST_HTTP2_HEADERS_GET_ROOT_STREAM_1,
761 TEST_HTTP2_GOAWAY,
762 };
763 size_t offset = 0;
764 int ret;
765
766 ret = zsock_send(client_fd, request_get_static_simple,
767 sizeof(request_get_static_simple), 0);
768 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
769
770 memset(buf, 0, sizeof(buf));
771
772 expect_http2_settings_frame(&offset, false);
773 expect_http2_settings_frame(&offset, true);
774 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1, HTTP2_FLAG_END_HEADERS, NULL, 0);
775 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, TEST_STATIC_PAYLOAD,
776 strlen(TEST_STATIC_PAYLOAD),
777 HTTP2_FLAG_END_STREAM);
778 }
779
ZTEST(server_function_tests,test_http1_static_upgrade_get)780 ZTEST(server_function_tests, test_http1_static_upgrade_get)
781 {
782 static const char http1_request[] =
783 "GET / HTTP/1.1\r\n"
784 "Host: 127.0.0.1:8080\r\n"
785 "Accept: */*\r\n"
786 "Accept-Encoding: deflate, gzip, br\r\n"
787 "Connection: Upgrade, HTTP2-Settings\r\n"
788 "Upgrade: h2c\r\n"
789 "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n"
790 "\r\n";
791 size_t offset = 0;
792 int ret;
793
794 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
795 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
796
797 memset(buf, 0, sizeof(buf));
798
799 /* Verify HTTP1 switching protocols response. */
800 expect_http1_switching_protocols(&offset);
801
802 /* Verify HTTP2 frames. */
803 expect_http2_settings_frame(&offset, false);
804 expect_http2_headers_frame(&offset, UPGRADE_STREAM_ID, HTTP2_FLAG_END_HEADERS, NULL, 0);
805 expect_http2_data_frame(&offset, UPGRADE_STREAM_ID, TEST_STATIC_PAYLOAD,
806 strlen(TEST_STATIC_PAYLOAD),
807 HTTP2_FLAG_END_STREAM);
808 }
809
ZTEST(server_function_tests,test_http1_static_get)810 ZTEST(server_function_tests, test_http1_static_get)
811 {
812 static const char http1_request[] =
813 "GET / HTTP/1.1\r\n"
814 "Host: 127.0.0.1:8080\r\n"
815 "User-Agent: curl/7.68.0\r\n"
816 "Accept: */*\r\n"
817 "Accept-Encoding: deflate, gzip, br\r\n"
818 "\r\n";
819 static const char expected_response[] =
820 "HTTP/1.1 200 OK\r\n"
821 "Content-Type: text/html\r\n"
822 "Content-Length: 13\r\n"
823 "\r\n"
824 TEST_STATIC_PAYLOAD;
825 size_t offset = 0;
826 int ret;
827
828 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
829 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
830
831 memset(buf, 0, sizeof(buf));
832
833 test_read_data(&offset, sizeof(expected_response) - 1);
834 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
835 "Received data doesn't match expected response");
836 }
837
838 /* Common code to verify POST/PUT/PATCH */
common_verify_http2_dynamic_post_request(const uint8_t * request,size_t request_len)839 static void common_verify_http2_dynamic_post_request(const uint8_t *request,
840 size_t request_len)
841 {
842 size_t offset = 0;
843 int ret;
844
845 ret = zsock_send(client_fd, request, request_len, 0);
846 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
847
848 memset(buf, 0, sizeof(buf));
849
850 expect_http2_settings_frame(&offset, false);
851 expect_http2_settings_frame(&offset, true);
852 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
853 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
854
855 zassert_equal(dynamic_payload_len, strlen(TEST_DYNAMIC_POST_PAYLOAD),
856 "Wrong dynamic resource length");
857 zassert_mem_equal(dynamic_payload, TEST_DYNAMIC_POST_PAYLOAD,
858 dynamic_payload_len, "Wrong dynamic resource data");
859 }
860
ZTEST(server_function_tests,test_http2_dynamic_post)861 ZTEST(server_function_tests, test_http2_dynamic_post)
862 {
863 static const uint8_t request_post_dynamic[] = {
864 TEST_HTTP2_MAGIC,
865 TEST_HTTP2_SETTINGS,
866 TEST_HTTP2_SETTINGS_ACK,
867 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1,
868 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1,
869 TEST_HTTP2_GOAWAY,
870 };
871
872 common_verify_http2_dynamic_post_request(request_post_dynamic,
873 sizeof(request_post_dynamic));
874 }
875
876 /* Common code to verify POST/PUT/PATCH */
common_verify_http1_dynamic_upgrade_post(const uint8_t * method)877 static void common_verify_http1_dynamic_upgrade_post(const uint8_t *method)
878 {
879 static const char http1_request[] =
880 " /dynamic HTTP/1.1\r\n"
881 "Host: 127.0.0.1:8080\r\n"
882 "User-Agent: curl/7.68.0\r\n"
883 "Accept: */*\r\n"
884 "Content-Length: 17\r\n"
885 "Connection: Upgrade, HTTP2-Settings\r\n"
886 "Upgrade: h2c\r\n"
887 "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n"
888 "\r\n"
889 TEST_DYNAMIC_POST_PAYLOAD;
890 size_t offset = 0;
891 int ret;
892
893 ret = zsock_send(client_fd, method, strlen(method), 0);
894 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
895
896 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
897 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
898
899 memset(buf, 0, sizeof(buf));
900
901 /* Verify HTTP1 switching protocols response. */
902 expect_http1_switching_protocols(&offset);
903
904 /* Verify HTTP2 frames. */
905 expect_http2_settings_frame(&offset, false);
906 expect_http2_headers_frame(&offset, UPGRADE_STREAM_ID,
907 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
908
909 zassert_equal(dynamic_payload_len, strlen(TEST_DYNAMIC_POST_PAYLOAD),
910 "Wrong dynamic resource length");
911 zassert_mem_equal(dynamic_payload, TEST_DYNAMIC_POST_PAYLOAD,
912 dynamic_payload_len, "Wrong dynamic resource data");
913 }
914
ZTEST(server_function_tests,test_http1_dynamic_upgrade_post)915 ZTEST(server_function_tests, test_http1_dynamic_upgrade_post)
916 {
917 common_verify_http1_dynamic_upgrade_post("POST");
918 }
919
920 /* Common code to verify POST/PUT/PATCH */
common_verify_http1_dynamic_post(const uint8_t * method)921 static void common_verify_http1_dynamic_post(const uint8_t *method)
922 {
923 static const char http1_request[] =
924 " /dynamic HTTP/1.1\r\n"
925 "Host: 127.0.0.1:8080\r\n"
926 "User-Agent: curl/7.68.0\r\n"
927 "Accept: */*\r\n"
928 "Content-Length: 17\r\n"
929 "\r\n"
930 TEST_DYNAMIC_POST_PAYLOAD;
931 static const char expected_response[] = "HTTP/1.1 200\r\n"
932 "Transfer-Encoding: chunked\r\n"
933 "Content-Type: text/plain\r\n"
934 "\r\n"
935 "0\r\n\r\n";
936 size_t offset = 0;
937 int ret;
938
939 ret = zsock_send(client_fd, method, strlen(method), 0);
940 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
941
942 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
943 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
944
945 memset(buf, 0, sizeof(buf));
946
947 test_read_data(&offset, sizeof(expected_response) - 1);
948 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
949 "Received data doesn't match expected response");
950
951 zassert_equal(dynamic_payload_len, strlen(TEST_DYNAMIC_POST_PAYLOAD),
952 "Wrong dynamic resource length");
953 zassert_mem_equal(dynamic_payload, TEST_DYNAMIC_POST_PAYLOAD,
954 dynamic_payload_len, "Wrong dynamic resource data");
955 }
956
ZTEST(server_function_tests,test_http1_dynamic_post)957 ZTEST(server_function_tests, test_http1_dynamic_post)
958 {
959 common_verify_http1_dynamic_post("POST");
960 }
961
common_verify_http2_dynamic_get_request(const uint8_t * request,size_t request_len)962 static void common_verify_http2_dynamic_get_request(const uint8_t *request,
963 size_t request_len)
964 {
965 size_t offset = 0;
966 int ret;
967
968 dynamic_payload_len = strlen(TEST_DYNAMIC_GET_PAYLOAD);
969 memcpy(dynamic_payload, TEST_DYNAMIC_GET_PAYLOAD, dynamic_payload_len);
970
971 ret = zsock_send(client_fd, request, request_len, 0);
972 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
973
974 memset(buf, 0, sizeof(buf));
975
976 expect_http2_settings_frame(&offset, false);
977 expect_http2_settings_frame(&offset, true);
978 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1, HTTP2_FLAG_END_HEADERS, NULL, 0);
979 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, TEST_DYNAMIC_GET_PAYLOAD,
980 strlen(TEST_DYNAMIC_GET_PAYLOAD), HTTP2_FLAG_END_STREAM);
981 }
982
ZTEST(server_function_tests,test_http2_dynamic_get)983 ZTEST(server_function_tests, test_http2_dynamic_get)
984 {
985 static const uint8_t request_get_dynamic[] = {
986 TEST_HTTP2_MAGIC,
987 TEST_HTTP2_SETTINGS,
988 TEST_HTTP2_SETTINGS_ACK,
989 TEST_HTTP2_HEADERS_GET_DYNAMIC_STREAM_1,
990 TEST_HTTP2_GOAWAY,
991 };
992
993 common_verify_http2_dynamic_get_request(request_get_dynamic,
994 sizeof(request_get_dynamic));
995 }
996
ZTEST(server_function_tests,test_http1_dynamic_upgrade_get)997 ZTEST(server_function_tests, test_http1_dynamic_upgrade_get)
998 {
999 static const char http1_request[] =
1000 "GET /dynamic HTTP/1.1\r\n"
1001 "Host: 127.0.0.1:8080\r\n"
1002 "User-Agent: curl/7.68.0\r\n"
1003 "Accept: */*\r\n"
1004 "Accept-Encoding: deflate, gzip, br\r\n"
1005 "Connection: Upgrade, HTTP2-Settings\r\n"
1006 "Upgrade: h2c\r\n"
1007 "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n"
1008 "\r\n";
1009 size_t offset = 0;
1010 int ret;
1011
1012 dynamic_payload_len = strlen(TEST_DYNAMIC_GET_PAYLOAD);
1013 memcpy(dynamic_payload, TEST_DYNAMIC_GET_PAYLOAD, dynamic_payload_len);
1014
1015 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
1016 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1017
1018 memset(buf, 0, sizeof(buf));
1019
1020 /* Verify HTTP1 switching protocols response. */
1021 expect_http1_switching_protocols(&offset);
1022
1023 /* Verify HTTP2 frames. */
1024 expect_http2_settings_frame(&offset, false);
1025 expect_http2_headers_frame(&offset, UPGRADE_STREAM_ID, HTTP2_FLAG_END_HEADERS, NULL, 0);
1026 expect_http2_data_frame(&offset, UPGRADE_STREAM_ID, TEST_DYNAMIC_GET_PAYLOAD,
1027 strlen(TEST_DYNAMIC_GET_PAYLOAD), HTTP2_FLAG_END_STREAM);
1028 }
1029
ZTEST(server_function_tests,test_http1_dynamic_get)1030 ZTEST(server_function_tests, test_http1_dynamic_get)
1031 {
1032 static const char http1_request[] =
1033 "GET /dynamic HTTP/1.1\r\n"
1034 "Host: 127.0.0.1:8080\r\n"
1035 "User-Agent: curl/7.68.0\r\n"
1036 "Accept: */*\r\n"
1037 "Accept-Encoding: deflate, gzip, br\r\n"
1038 "\r\n";
1039 static const char expected_response[] = "HTTP/1.1 200\r\n"
1040 "Transfer-Encoding: chunked\r\n"
1041 "Content-Type: text/plain\r\n"
1042 "\r\n"
1043 "10\r\n" TEST_DYNAMIC_GET_PAYLOAD "\r\n"
1044 "0\r\n\r\n";
1045 size_t offset = 0;
1046 int ret;
1047
1048 dynamic_payload_len = strlen(TEST_DYNAMIC_GET_PAYLOAD);
1049 memcpy(dynamic_payload, TEST_DYNAMIC_GET_PAYLOAD, dynamic_payload_len);
1050
1051 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
1052 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1053
1054 memset(buf, 0, sizeof(buf));
1055
1056 test_read_data(&offset, sizeof(expected_response) - 1);
1057 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
1058 "Received data doesn't match expected response");
1059 }
1060
ZTEST(server_function_tests,test_http2_dynamic_put)1061 ZTEST(server_function_tests, test_http2_dynamic_put)
1062 {
1063 static const uint8_t request_put_dynamic[] = {
1064 TEST_HTTP2_MAGIC,
1065 TEST_HTTP2_SETTINGS,
1066 TEST_HTTP2_SETTINGS_ACK,
1067 TEST_HTTP2_HEADERS_PUT_DYNAMIC_STREAM_1,
1068 TEST_HTTP2_DATA_PUT_DYNAMIC_STREAM_1,
1069 TEST_HTTP2_GOAWAY,
1070 };
1071
1072 common_verify_http2_dynamic_post_request(request_put_dynamic,
1073 sizeof(request_put_dynamic));
1074 }
1075
ZTEST(server_function_tests,test_http1_dynamic_upgrade_put)1076 ZTEST(server_function_tests, test_http1_dynamic_upgrade_put)
1077 {
1078 common_verify_http1_dynamic_upgrade_post("PUT");
1079 }
1080
ZTEST(server_function_tests,test_http1_dynamic_put)1081 ZTEST(server_function_tests, test_http1_dynamic_put)
1082 {
1083 common_verify_http1_dynamic_post("PUT");
1084 }
1085
ZTEST(server_function_tests,test_http2_dynamic_patch)1086 ZTEST(server_function_tests, test_http2_dynamic_patch)
1087 {
1088 static const uint8_t request_patch_dynamic[] = {
1089 TEST_HTTP2_MAGIC,
1090 TEST_HTTP2_SETTINGS,
1091 TEST_HTTP2_SETTINGS_ACK,
1092 TEST_HTTP2_HEADERS_PATCH_DYNAMIC_STREAM_1,
1093 TEST_HTTP2_DATA_PATCH_DYNAMIC_STREAM_1,
1094 TEST_HTTP2_GOAWAY,
1095 };
1096
1097 common_verify_http2_dynamic_post_request(request_patch_dynamic,
1098 sizeof(request_patch_dynamic));
1099 }
1100
ZTEST(server_function_tests,test_http1_dynamic_upgrade_patch)1101 ZTEST(server_function_tests, test_http1_dynamic_upgrade_patch)
1102 {
1103 common_verify_http1_dynamic_upgrade_post("PATCH");
1104 }
1105
ZTEST(server_function_tests,test_http1_dynamic_patch)1106 ZTEST(server_function_tests, test_http1_dynamic_patch)
1107 {
1108 common_verify_http1_dynamic_post("PATCH");
1109 }
1110
ZTEST(server_function_tests,test_http2_dynamic_delete)1111 ZTEST(server_function_tests, test_http2_dynamic_delete)
1112 {
1113 static const uint8_t request_delete_dynamic[] = {
1114 TEST_HTTP2_MAGIC,
1115 TEST_HTTP2_SETTINGS,
1116 TEST_HTTP2_SETTINGS_ACK,
1117 TEST_HTTP2_HEADERS_DELETE_DYNAMIC_STREAM_1,
1118 TEST_HTTP2_GOAWAY,
1119 };
1120 size_t offset = 0;
1121 int ret;
1122
1123 ret = zsock_send(client_fd, request_delete_dynamic,
1124 sizeof(request_delete_dynamic), 0);
1125 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1126
1127 memset(buf, 0, sizeof(buf));
1128
1129 expect_http2_settings_frame(&offset, false);
1130 expect_http2_settings_frame(&offset, true);
1131 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
1132 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM,
1133 NULL, 0);
1134 }
1135
ZTEST(server_function_tests,test_http1_dynamic_upgrade_delete)1136 ZTEST(server_function_tests, test_http1_dynamic_upgrade_delete)
1137 {
1138 static const char http1_request[] =
1139 "DELETE /dynamic HTTP/1.1\r\n"
1140 "Host: 127.0.0.1:8080\r\n"
1141 "User-Agent: curl/7.68.0\r\n"
1142 "Connection: Upgrade, HTTP2-Settings\r\n"
1143 "Upgrade: h2c\r\n"
1144 "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n"
1145 "\r\n";
1146 size_t offset = 0;
1147 int ret;
1148
1149 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
1150 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1151
1152 memset(buf, 0, sizeof(buf));
1153
1154 /* Verify HTTP1 switching protocols response. */
1155 expect_http1_switching_protocols(&offset);
1156
1157 /* Verify HTTP2 frames. */
1158 expect_http2_settings_frame(&offset, false);
1159 expect_http2_headers_frame(&offset, UPGRADE_STREAM_ID,
1160 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM,
1161 NULL, 0);
1162 }
1163
ZTEST(server_function_tests,test_http1_dynamic_delete)1164 ZTEST(server_function_tests, test_http1_dynamic_delete)
1165 {
1166 static const char http1_request[] =
1167 "DELETE /dynamic HTTP/1.1\r\n"
1168 "Host: 127.0.0.1:8080\r\n"
1169 "User-Agent: curl/7.68.0\r\n"
1170 "\r\n";
1171 static const char expected_response[] = "HTTP/1.1 200\r\n"
1172 "Transfer-Encoding: chunked\r\n"
1173 "Content-Type: text/plain\r\n"
1174 "\r\n"
1175 "0\r\n\r\n";
1176 size_t offset = 0;
1177 int ret;
1178
1179 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
1180 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1181
1182 memset(buf, 0, sizeof(buf));
1183
1184 test_read_data(&offset, sizeof(expected_response) - 1);
1185 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
1186 "Received data doesn't match expected response");
1187 }
1188
ZTEST(server_function_tests,test_http1_connection_close)1189 ZTEST(server_function_tests, test_http1_connection_close)
1190 {
1191 static const char http1_request_1[] =
1192 "GET / HTTP/1.1\r\n"
1193 "Host: 127.0.0.1:8080\r\n"
1194 "User-Agent: curl/7.68.0\r\n"
1195 "Accept: */*\r\n"
1196 "Accept-Encoding: deflate, gzip, br\r\n"
1197 "\r\n";
1198 static const char http1_request_2[] =
1199 "GET / HTTP/1.1\r\n"
1200 "Host: 127.0.0.1:8080\r\n"
1201 "User-Agent: curl/7.68.0\r\n"
1202 "Accept: */*\r\n"
1203 "Accept-Encoding: deflate, gzip, br\r\n"
1204 "Connection: close\r\n"
1205 "\r\n";
1206 static const char expected_response[] =
1207 "HTTP/1.1 200 OK\r\n"
1208 "Content-Type: text/html\r\n"
1209 "Content-Length: 13\r\n"
1210 "\r\n"
1211 TEST_STATIC_PAYLOAD;
1212 size_t offset = 0;
1213 int ret;
1214
1215 ret = zsock_send(client_fd, http1_request_1, strlen(http1_request_1), 0);
1216 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1217
1218 memset(buf, 0, sizeof(buf));
1219
1220 test_read_data(&offset, sizeof(expected_response) - 1);
1221 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
1222 "Received data doesn't match expected response");
1223 test_consume_data(&offset, sizeof(expected_response) - 1);
1224
1225 /* With no connection: close, the server shall serve another request on
1226 * the same connection.
1227 */
1228 ret = zsock_send(client_fd, http1_request_2, strlen(http1_request_2), 0);
1229 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1230
1231 memset(buf, 0, sizeof(buf));
1232
1233 test_read_data(&offset, sizeof(expected_response) - 1);
1234 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
1235 "Received data doesn't match expected response");
1236 test_consume_data(&offset, sizeof(expected_response) - 1);
1237
1238 /* Second request included connection: close, so we should expect the
1239 * connection to be closed now.
1240 */
1241 ret = zsock_recv(client_fd, buf, sizeof(buf), 0);
1242 zassert_equal(ret, 0, "Connection should've been closed");
1243 }
1244
ZTEST(server_function_tests,test_http2_post_data_with_padding)1245 ZTEST(server_function_tests, test_http2_post_data_with_padding)
1246 {
1247 static const uint8_t request_post_dynamic[] = {
1248 TEST_HTTP2_MAGIC,
1249 TEST_HTTP2_SETTINGS,
1250 TEST_HTTP2_SETTINGS_ACK,
1251 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1,
1252 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1_PADDED,
1253 TEST_HTTP2_GOAWAY,
1254 };
1255
1256 common_verify_http2_dynamic_post_request(request_post_dynamic,
1257 sizeof(request_post_dynamic));
1258 }
1259
ZTEST(server_function_tests,test_http2_post_headers_with_priority)1260 ZTEST(server_function_tests, test_http2_post_headers_with_priority)
1261 {
1262 static const uint8_t request_post_dynamic[] = {
1263 TEST_HTTP2_MAGIC,
1264 TEST_HTTP2_SETTINGS,
1265 TEST_HTTP2_SETTINGS_ACK,
1266 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1_PRIORITY,
1267 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1_PADDED,
1268 TEST_HTTP2_GOAWAY,
1269 };
1270
1271 common_verify_http2_dynamic_post_request(request_post_dynamic,
1272 sizeof(request_post_dynamic));
1273 }
1274
ZTEST(server_function_tests,test_http2_post_headers_with_priority_and_padding)1275 ZTEST(server_function_tests, test_http2_post_headers_with_priority_and_padding)
1276 {
1277 static const uint8_t request_post_dynamic[] = {
1278 TEST_HTTP2_MAGIC,
1279 TEST_HTTP2_SETTINGS,
1280 TEST_HTTP2_SETTINGS_ACK,
1281 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1_PRIORITY_PADDED,
1282 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1_PADDED,
1283 TEST_HTTP2_GOAWAY,
1284 };
1285
1286 common_verify_http2_dynamic_post_request(request_post_dynamic,
1287 sizeof(request_post_dynamic));
1288 }
1289
ZTEST(server_function_tests,test_http2_post_headers_with_continuation)1290 ZTEST(server_function_tests, test_http2_post_headers_with_continuation)
1291 {
1292 static const uint8_t request_post_dynamic[] = {
1293 TEST_HTTP2_MAGIC,
1294 TEST_HTTP2_SETTINGS,
1295 TEST_HTTP2_SETTINGS_ACK,
1296 TEST_HTTP2_PARTIAL_HEADERS_POST_DYNAMIC_STREAM_1,
1297 TEST_HTTP2_CONTINUATION_POST_DYNAMIC_STREAM_1,
1298 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1,
1299 TEST_HTTP2_GOAWAY,
1300 };
1301
1302 common_verify_http2_dynamic_post_request(request_post_dynamic,
1303 sizeof(request_post_dynamic));
1304 }
1305
ZTEST(server_function_tests,test_http2_post_missing_continuation)1306 ZTEST(server_function_tests, test_http2_post_missing_continuation)
1307 {
1308 static const uint8_t request_post_dynamic[] = {
1309 TEST_HTTP2_MAGIC,
1310 TEST_HTTP2_SETTINGS,
1311 TEST_HTTP2_SETTINGS_ACK,
1312 TEST_HTTP2_PARTIAL_HEADERS_POST_DYNAMIC_STREAM_1,
1313 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1,
1314 TEST_HTTP2_GOAWAY,
1315 };
1316 size_t offset = 0;
1317 int ret;
1318
1319 memset(buf, 0, sizeof(buf));
1320
1321 ret = zsock_send(client_fd, request_post_dynamic,
1322 sizeof(request_post_dynamic), 0);
1323 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1324
1325 /* Expect settings, but processing headers (and lack of continuation
1326 * frame) should break the stream, and trigger disconnect.
1327 */
1328 expect_http2_settings_frame(&offset, false);
1329 expect_http2_settings_frame(&offset, true);
1330
1331 ret = zsock_recv(client_fd, buf, sizeof(buf), 0);
1332 zassert_equal(ret, 0, "Connection should've been closed");
1333 }
1334
ZTEST(server_function_tests,test_http2_post_trailing_headers)1335 ZTEST(server_function_tests, test_http2_post_trailing_headers)
1336 {
1337 static const uint8_t request_post_dynamic[] = {
1338 TEST_HTTP2_MAGIC,
1339 TEST_HTTP2_SETTINGS,
1340 TEST_HTTP2_SETTINGS_ACK,
1341 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1,
1342 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1_NO_END_STREAM,
1343 TEST_HTTP2_TRAILING_HEADER_STREAM_1,
1344 TEST_HTTP2_GOAWAY,
1345 };
1346 size_t offset = 0;
1347 int ret;
1348
1349 ret = zsock_send(client_fd, request_post_dynamic,
1350 sizeof(request_post_dynamic), 0);
1351 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1352
1353 memset(buf, 0, sizeof(buf));
1354
1355 expect_http2_settings_frame(&offset, false);
1356 expect_http2_settings_frame(&offset, true);
1357 /* In this case order is reversed, data frame had not END_STREAM flag.
1358 * Because of this, reply will only be sent after processing the final
1359 * trailing headers frame, but this will be preceded by window update
1360 * after processing the data frame.
1361 */
1362 expect_http2_window_update_frame(&offset, TEST_STREAM_ID_1);
1363 expect_http2_window_update_frame(&offset, 0);
1364 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
1365 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
1366
1367 zassert_equal(dynamic_payload_len, strlen(TEST_DYNAMIC_POST_PAYLOAD),
1368 "Wrong dynamic resource length");
1369 zassert_mem_equal(dynamic_payload, TEST_DYNAMIC_POST_PAYLOAD,
1370 dynamic_payload_len, "Wrong dynamic resource data");
1371 }
1372
ZTEST(server_function_tests,test_http2_get_headers_with_padding)1373 ZTEST(server_function_tests, test_http2_get_headers_with_padding)
1374 {
1375 static const uint8_t request_get_dynamic[] = {
1376 TEST_HTTP2_MAGIC,
1377 TEST_HTTP2_SETTINGS,
1378 TEST_HTTP2_SETTINGS_ACK,
1379 TEST_HTTP2_HEADERS_GET_DYNAMIC_STREAM_1_PADDED,
1380 TEST_HTTP2_GOAWAY,
1381 };
1382
1383 common_verify_http2_dynamic_get_request(request_get_dynamic,
1384 sizeof(request_get_dynamic));
1385 }
1386
ZTEST(server_function_tests,test_http2_rst_stream)1387 ZTEST(server_function_tests, test_http2_rst_stream)
1388 {
1389 static const uint8_t request_rst_stream[] = {
1390 TEST_HTTP2_MAGIC,
1391 TEST_HTTP2_SETTINGS,
1392 TEST_HTTP2_SETTINGS_ACK,
1393 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1,
1394 TEST_HTTP2_RST_STREAM_STREAM_1,
1395 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1,
1396 TEST_HTTP2_GOAWAY,
1397 };
1398
1399 size_t offset = 0;
1400 int ret;
1401
1402 memset(buf, 0, sizeof(buf));
1403
1404 ret = zsock_send(client_fd, request_rst_stream,
1405 sizeof(request_rst_stream), 0);
1406 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1407
1408 /* Expect settings, but processing RST_STREAM should close the stream,
1409 * so DATA frame should trigger connection error (closed stream) and
1410 * disconnect.
1411 */
1412 expect_http2_settings_frame(&offset, false);
1413 expect_http2_settings_frame(&offset, true);
1414
1415 ret = zsock_recv(client_fd, buf, sizeof(buf), 0);
1416 zassert_equal(ret, 0, "Connection should've been closed");
1417 }
1418
1419 static const char http1_header_capture_common_response[] = "HTTP/1.1 200\r\n"
1420 "Transfer-Encoding: chunked\r\n"
1421 "Content-Type: text/plain\r\n"
1422 "\r\n"
1423 "0\r\n\r\n";
1424
test_http1_header_capture_common(const char * request)1425 static void test_http1_header_capture_common(const char *request)
1426 {
1427 size_t offset = 0;
1428 int ret;
1429
1430 ret = zsock_send(client_fd, request, strlen(request), 0);
1431 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1432
1433 test_read_data(&offset, sizeof(http1_header_capture_common_response) - 1);
1434 }
1435
ZTEST(server_function_tests,test_http1_header_capture)1436 ZTEST(server_function_tests, test_http1_header_capture)
1437 {
1438 static const char request[] = "GET /header_capture HTTP/1.1\r\n"
1439 "User-Agent: curl/7.68.0\r\n"
1440 "Test-Header: test_value\r\n"
1441 "Accept: */*\r\n"
1442 "Accept-Encoding: deflate, gzip, br\r\n"
1443 "\r\n";
1444 struct http_header *hdrs = request_headers_clone.headers;
1445 int ret;
1446
1447 test_http1_header_capture_common(request);
1448
1449 zassert_equal(request_headers_clone.count, 2,
1450 "Didn't capture the expected number of headers");
1451 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_OK,
1452 "Header capture status was not OK");
1453
1454 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1455 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1456 zassert_not_equal(hdrs[1].name, NULL, "Second header name is NULL");
1457 zassert_not_equal(hdrs[1].value, NULL, "Second header value is NULL");
1458
1459 ret = strcmp(hdrs[0].name, "User-Agent");
1460 zassert_equal(0, ret, "Header strings did not match");
1461 ret = strcmp(hdrs[0].value, "curl/7.68.0");
1462 zassert_equal(0, ret, "Header strings did not match");
1463 ret = strcmp(hdrs[1].name, "Test-Header");
1464 zassert_equal(0, ret, "Header strings did not match");
1465 ret = strcmp(hdrs[1].value, "test_value");
1466 zassert_equal(0, ret, "Header strings did not match");
1467 }
1468
ZTEST(server_function_tests,test_http1_header_too_long)1469 ZTEST(server_function_tests, test_http1_header_too_long)
1470 {
1471 static const char request[] =
1472 "GET /header_capture HTTP/1.1\r\n"
1473 "User-Agent: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n"
1474 "Test-Header: test_value\r\n"
1475 "Accept: */*\r\n"
1476 "Accept-Encoding: deflate, gzip, br\r\n"
1477 "\r\n";
1478 struct http_header *hdrs = request_headers_clone.headers;
1479 int ret;
1480
1481 test_http1_header_capture_common(request);
1482
1483 zassert_equal(request_headers_clone.count, 1,
1484 "Didn't capture the expected number of headers");
1485 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_DROPPED,
1486 "Header capture status was OK, but should not have been");
1487
1488 /* First header too long should not stop second header being captured into first slot */
1489 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1490 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1491
1492 ret = strcmp(hdrs[0].name, "Test-Header");
1493 zassert_equal(0, ret, "Header strings did not match");
1494 ret = strcmp(hdrs[0].value, "test_value");
1495 zassert_equal(0, ret, "Header strings did not match");
1496 }
1497
ZTEST(server_function_tests,test_http1_header_too_many)1498 ZTEST(server_function_tests, test_http1_header_too_many)
1499 {
1500 static const char request[] = "GET /header_capture HTTP/1.1\r\n"
1501 "User-Agent: curl/7.68.0\r\n"
1502 "Test-Header: test_value\r\n"
1503 "Test-Header2: test_value2\r\n"
1504 "Accept: */*\r\n"
1505 "Accept-Encoding: deflate, gzip, br\r\n"
1506 "\r\n";
1507 struct http_header *hdrs = request_headers_clone.headers;
1508 int ret;
1509
1510 test_http1_header_capture_common(request);
1511
1512 zassert_equal(request_headers_clone.count, 2,
1513 "Didn't capture the expected number of headers");
1514 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_DROPPED,
1515 "Header capture status OK, but should not have been");
1516
1517 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1518 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1519 zassert_not_equal(hdrs[1].name, NULL, "Second header name is NULL");
1520 zassert_not_equal(hdrs[1].value, NULL, "Second header value is NULL");
1521
1522 ret = strcmp(hdrs[0].name, "User-Agent");
1523 zassert_equal(0, ret, "Header strings did not match");
1524 ret = strcmp(hdrs[0].value, "curl/7.68.0");
1525 zassert_equal(0, ret, "Header strings did not match");
1526 ret = strcmp(hdrs[1].name, "Test-Header");
1527 zassert_equal(0, ret, "Header strings did not match");
1528 ret = strcmp(hdrs[1].value, "test_value");
1529 zassert_equal(0, ret, "Header strings did not match");
1530 }
1531
common_verify_http2_get_header_capture_request(const uint8_t * request,size_t request_len)1532 static void common_verify_http2_get_header_capture_request(const uint8_t *request,
1533 size_t request_len)
1534 {
1535 size_t offset = 0;
1536 int ret;
1537
1538 dynamic_payload_len = strlen(TEST_DYNAMIC_GET_PAYLOAD);
1539 memcpy(dynamic_payload, TEST_DYNAMIC_GET_PAYLOAD, dynamic_payload_len);
1540
1541 ret = zsock_send(client_fd, request, request_len, 0);
1542 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1543
1544 memset(buf, 0, sizeof(buf));
1545
1546 expect_http2_settings_frame(&offset, false);
1547 expect_http2_settings_frame(&offset, true);
1548 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
1549 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
1550 }
1551
ZTEST(server_function_tests,test_http2_header_capture)1552 ZTEST(server_function_tests, test_http2_header_capture)
1553 {
1554 static const uint8_t request[] = {
1555 TEST_HTTP2_MAGIC,
1556 TEST_HTTP2_SETTINGS,
1557 TEST_HTTP2_SETTINGS_ACK,
1558 TEST_HTTP2_HEADERS_GET_HEADER_CAPTURE1_STREAM_1,
1559 TEST_HTTP2_GOAWAY,
1560 };
1561 struct http_header *hdrs = request_headers_clone.headers;
1562 int ret;
1563
1564 common_verify_http2_get_header_capture_request(request, sizeof(request));
1565
1566 zassert_equal(request_headers_clone.count, 2,
1567 "Didn't capture the expected number of headers");
1568 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_OK,
1569 "Header capture status was not OK");
1570
1571 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1572 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1573 zassert_not_equal(hdrs[1].name, NULL, "Second header name is NULL");
1574 zassert_not_equal(hdrs[1].value, NULL, "Second header value is NULL");
1575
1576 ret = strcmp(hdrs[0].name, "User-Agent");
1577 zassert_equal(0, ret, "Header strings did not match");
1578 ret = strcmp(hdrs[0].value, "curl/7.81.0");
1579 zassert_equal(0, ret, "Header strings did not match");
1580 ret = strcmp(hdrs[1].name, "Test-Header");
1581 zassert_equal(0, ret, "Header strings did not match");
1582 ret = strcmp(hdrs[1].value, "test_value");
1583 zassert_equal(0, ret, "Header strings did not match");
1584 }
1585
ZTEST(server_function_tests,test_http2_header_too_long)1586 ZTEST(server_function_tests, test_http2_header_too_long)
1587 {
1588 static const uint8_t request[] = {
1589 TEST_HTTP2_MAGIC,
1590 TEST_HTTP2_SETTINGS,
1591 TEST_HTTP2_SETTINGS_ACK,
1592 TEST_HTTP2_HEADERS_GET_HEADER_CAPTURE2_STREAM_1,
1593 TEST_HTTP2_GOAWAY,
1594 };
1595 struct http_header *hdrs = request_headers_clone.headers;
1596 int ret;
1597
1598 common_verify_http2_get_header_capture_request(request, sizeof(request));
1599
1600 zassert_equal(request_headers_clone.count, 1,
1601 "Didn't capture the expected number of headers");
1602 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_DROPPED,
1603 "Header capture status was OK, but should not have been");
1604
1605 /* First header too long should not stop second header being captured into first slot */
1606 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1607 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1608
1609 ret = strcmp(hdrs[0].name, "Test-Header");
1610 zassert_equal(0, ret, "Header strings did not match");
1611 ret = strcmp(hdrs[0].value, "test_value");
1612 zassert_equal(0, ret, "Header strings did not match");
1613 }
1614
ZTEST(server_function_tests,test_http2_header_too_many)1615 ZTEST(server_function_tests, test_http2_header_too_many)
1616 {
1617 static const uint8_t request[] = {
1618 TEST_HTTP2_MAGIC,
1619 TEST_HTTP2_SETTINGS,
1620 TEST_HTTP2_SETTINGS_ACK,
1621 TEST_HTTP2_HEADERS_GET_HEADER_CAPTURE3_STREAM_1,
1622 TEST_HTTP2_GOAWAY,
1623 };
1624 struct http_header *hdrs = request_headers_clone.headers;
1625 int ret;
1626
1627 common_verify_http2_get_header_capture_request(request, sizeof(request));
1628
1629 zassert_equal(request_headers_clone.count, 2,
1630 "Didn't capture the expected number of headers");
1631 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_DROPPED,
1632 "Header capture status OK, but should not have been");
1633
1634 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1635 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1636 zassert_not_equal(hdrs[1].name, NULL, "Second header name is NULL");
1637 zassert_not_equal(hdrs[1].value, NULL, "Second header value is NULL");
1638
1639 ret = strcmp(hdrs[0].name, "User-Agent");
1640 zassert_equal(0, ret, "Header strings did not match");
1641 ret = strcmp(hdrs[0].value, "curl/7.81.0");
1642 zassert_equal(0, ret, "Header strings did not match");
1643 ret = strcmp(hdrs[1].name, "Test-Header");
1644 zassert_equal(0, ret, "Header strings did not match");
1645 ret = strcmp(hdrs[1].value, "test_value");
1646 zassert_equal(0, ret, "Header strings did not match");
1647 }
1648
ZTEST(server_function_tests,test_http2_header_concurrent)1649 ZTEST(server_function_tests, test_http2_header_concurrent)
1650 {
1651 /* Two POST requests which are concurrent, ie. headers1, headers2, data1, data2 */
1652 static const uint8_t request[] = {
1653 TEST_HTTP2_MAGIC,
1654 TEST_HTTP2_SETTINGS,
1655 TEST_HTTP2_SETTINGS_ACK,
1656 TEST_HTTP2_HEADERS_POST_HEADER_CAPTURE_WITH_TESTHEADER_STREAM_1,
1657 TEST_HTTP2_HEADERS_POST_HEADER_CAPTURE2_NO_TESTHEADER_STREAM_2,
1658 TEST_HTTP2_DATA_POST_HEADER_CAPTURE_STREAM_1,
1659 TEST_HTTP2_DATA_POST_HEADER_CAPTURE_STREAM_2,
1660 TEST_HTTP2_GOAWAY,
1661 };
1662
1663 struct http_header *hdrs = request_headers_clone.headers;
1664 struct http_header *hdrs2 = request_headers_clone2.headers;
1665 int ret;
1666 size_t offset = 0;
1667
1668 ret = zsock_send(client_fd, request, sizeof(request), 0);
1669 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1670
1671 /* Wait for response on both resources before checking captured headers */
1672 expect_http2_settings_frame(&offset, false);
1673 expect_http2_settings_frame(&offset, true);
1674 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
1675 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
1676 expect_http2_window_update_frame(&offset, TEST_STREAM_ID_1);
1677 expect_http2_window_update_frame(&offset, 0);
1678 expect_http2_headers_frame(&offset, TEST_STREAM_ID_2,
1679 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
1680
1681 /* Headers captured on /header_capture path should have two headers including the
1682 * Test-Header
1683 */
1684 zassert_equal(request_headers_clone.count, 2,
1685 "Didn't capture the expected number of headers");
1686
1687 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1688 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1689 zassert_not_equal(hdrs[1].name, NULL, "Second header name is NULL");
1690 zassert_not_equal(hdrs[1].value, NULL, "Second header value is NULL");
1691
1692 ret = strcmp(hdrs[0].name, "User-Agent");
1693 zassert_equal(0, ret, "Header strings did not match");
1694 ret = strcmp(hdrs[0].value, "curl/7.81.0");
1695 zassert_equal(0, ret, "Header strings did not match");
1696 ret = strcmp(hdrs[1].name, "Test-Header");
1697 zassert_equal(0, ret, "Header strings did not match");
1698 ret = strcmp(hdrs[1].value, "test_value");
1699 zassert_equal(0, ret, "Header strings did not match");
1700
1701 /* Headers captured on the /header_capture2 path should have only one header, not including
1702 * the Test-Header
1703 */
1704 zassert_equal(request_headers_clone2.count, 1,
1705 "Didn't capture the expected number of headers");
1706
1707 zassert_not_equal(hdrs2[0].name, NULL, "First header name is NULL");
1708 zassert_not_equal(hdrs2[0].value, NULL, "First header value is NULL");
1709
1710 ret = strcmp(hdrs2[0].name, "User-Agent");
1711 zassert_equal(0, ret, "Header strings did not match");
1712 ret = strcmp(hdrs2[0].value, "curl/7.81.0");
1713 zassert_equal(0, ret, "Header strings did not match");
1714 }
1715
test_http1_dynamic_response_headers(const char * request,const char * expected_response)1716 static void test_http1_dynamic_response_headers(const char *request, const char *expected_response)
1717 {
1718 int ret;
1719 size_t offset = 0;
1720
1721 ret = zsock_send(client_fd, request, strlen(request), 0);
1722 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1723
1724 test_read_data(&offset, strlen(expected_response));
1725 zassert_mem_equal(buf, expected_response, strlen(expected_response));
1726 }
1727
test_http1_dynamic_response_headers_default(const char * expected_response,bool post)1728 static void test_http1_dynamic_response_headers_default(const char *expected_response, bool post)
1729 {
1730 static const char http1_get_response_headers_request[] =
1731 "GET /response_headers HTTP/1.1\r\n"
1732 "Accept: */*\r\n"
1733 "\r\n";
1734 static const char http1_post_response_headers_request[] =
1735 "POST /response_headers HTTP/1.1\r\n"
1736 "Accept: */*\r\n"
1737 "Content-Length: 17\r\n"
1738 "\r\n" TEST_DYNAMIC_POST_PAYLOAD;
1739 const char *request =
1740 post ? http1_post_response_headers_request : http1_get_response_headers_request;
1741
1742 test_http1_dynamic_response_headers(request, expected_response);
1743 }
1744
test_http2_dynamic_response_headers(const uint8_t * request,size_t request_len,const struct http_header * expected_headers,size_t expected_headers_count,bool end_stream,size_t * offset)1745 static void test_http2_dynamic_response_headers(const uint8_t *request, size_t request_len,
1746 const struct http_header *expected_headers,
1747 size_t expected_headers_count, bool end_stream,
1748 size_t *offset)
1749 {
1750 int ret;
1751 const uint8_t expected_flags = end_stream ? HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM
1752 : HTTP2_FLAG_END_HEADERS;
1753
1754 ret = zsock_send(client_fd, request, request_len, 0);
1755 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1756
1757 expect_http2_settings_frame(offset, false);
1758 expect_http2_settings_frame(offset, true);
1759 expect_http2_headers_frame(offset, TEST_STREAM_ID_1, expected_flags, expected_headers,
1760 expected_headers_count);
1761 }
1762
test_http2_dynamic_response_headers_default(const struct http_header * expected_headers,size_t expected_headers_count,bool post,bool end_stream,size_t * offset)1763 static void test_http2_dynamic_response_headers_default(const struct http_header *expected_headers,
1764 size_t expected_headers_count, bool post,
1765 bool end_stream, size_t *offset)
1766 {
1767 const uint8_t http2_get_response_headers_request[] = {
1768 TEST_HTTP2_MAGIC,
1769 TEST_HTTP2_SETTINGS,
1770 TEST_HTTP2_SETTINGS_ACK,
1771 TEST_HTTP2_HEADERS_GET_RESPONSE_HEADERS_STREAM_1,
1772 TEST_HTTP2_GOAWAY,
1773 };
1774 const uint8_t http2_post_response_headers_request[] = {
1775 TEST_HTTP2_MAGIC,
1776 TEST_HTTP2_SETTINGS,
1777 TEST_HTTP2_SETTINGS_ACK,
1778 TEST_HTTP2_HEADERS_POST_RESPONSE_HEADERS_STREAM_1,
1779 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1,
1780 TEST_HTTP2_GOAWAY,
1781 };
1782 const uint8_t *request =
1783 post ? http2_post_response_headers_request : http2_get_response_headers_request;
1784 size_t request_len = post ? sizeof(http2_post_response_headers_request)
1785 : sizeof(http2_get_response_headers_request);
1786
1787 test_http2_dynamic_response_headers(request, request_len, expected_headers,
1788 expected_headers_count, end_stream, offset);
1789 }
1790
test_http1_dynamic_response_header_none(bool post)1791 static void test_http1_dynamic_response_header_none(bool post)
1792 {
1793 static const char response[] = "HTTP/1.1 200\r\n"
1794 "Transfer-Encoding: chunked\r\n"
1795 "Content-Type: text/plain\r\n"
1796 "\r\n"
1797 "0\r\n\r\n";
1798
1799 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_NONE;
1800
1801 test_http1_dynamic_response_headers_default(response, post);
1802 }
1803
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_none)1804 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_none)
1805 {
1806 test_http1_dynamic_response_header_none(false);
1807 }
1808
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_none)1809 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_none)
1810 {
1811 test_http1_dynamic_response_header_none(true);
1812 }
1813
test_http2_dynamic_response_header_none(bool post)1814 static void test_http2_dynamic_response_header_none(bool post)
1815 {
1816 size_t offset = 0;
1817 const struct http_header expected_headers[] = {
1818 {.name = ":status", .value = "200"},
1819 {.name = "content-type", .value = "text/plain"},
1820 };
1821
1822 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_NONE;
1823
1824 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
1825 post, true, &offset);
1826 }
1827
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_none)1828 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_none)
1829 {
1830 test_http2_dynamic_response_header_none(false);
1831 }
1832
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_none)1833 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_none)
1834 {
1835 test_http2_dynamic_response_header_none(true);
1836 }
1837
test_http1_dynamic_response_header_422(bool post)1838 static void test_http1_dynamic_response_header_422(bool post)
1839 {
1840 static const char response[] = "HTTP/1.1 422\r\n"
1841 "Transfer-Encoding: chunked\r\n"
1842 "Content-Type: text/plain\r\n"
1843 "\r\n"
1844 "0\r\n\r\n";
1845
1846 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_422;
1847
1848 test_http1_dynamic_response_headers_default(response, post);
1849 }
1850
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_422)1851 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_422)
1852 {
1853 test_http1_dynamic_response_header_422(false);
1854 }
1855
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_422)1856 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_422)
1857 {
1858 test_http1_dynamic_response_header_422(true);
1859 }
1860
test_http2_dynamic_response_header_422(bool post)1861 static void test_http2_dynamic_response_header_422(bool post)
1862 {
1863 size_t offset = 0;
1864 const struct http_header expected_headers[] = {
1865 {.name = ":status", .value = "422"},
1866 {.name = "content-type", .value = "text/plain"},
1867 };
1868
1869 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_422;
1870
1871 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
1872 post, true, &offset);
1873 }
1874
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_422)1875 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_422)
1876 {
1877 test_http2_dynamic_response_header_422(false);
1878 }
1879
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_422)1880 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_422)
1881 {
1882 test_http2_dynamic_response_header_422(true);
1883 }
1884
test_http1_dynamic_response_header_extra(bool post)1885 static void test_http1_dynamic_response_header_extra(bool post)
1886 {
1887 static const char response[] = "HTTP/1.1 200\r\n"
1888 "Transfer-Encoding: chunked\r\n"
1889 "Test-Header: test_data\r\n"
1890 "Content-Type: text/plain\r\n"
1891 "\r\n"
1892 "0\r\n\r\n";
1893
1894 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_EXTRA_HEADER;
1895
1896 test_http1_dynamic_response_headers_default(response, post);
1897 }
1898
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_extra)1899 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_extra)
1900 {
1901 test_http1_dynamic_response_header_extra(false);
1902 }
1903
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_extra)1904 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_extra)
1905 {
1906 test_http1_dynamic_response_header_extra(true);
1907 }
1908
test_http2_dynamic_response_header_extra(bool post)1909 static void test_http2_dynamic_response_header_extra(bool post)
1910 {
1911 size_t offset = 0;
1912 const struct http_header expected_headers[] = {
1913 {.name = ":status", .value = "200"},
1914 {.name = "content-type", .value = "text/plain"},
1915 {.name = "test-header", .value = "test_data"},
1916 };
1917
1918 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_EXTRA_HEADER;
1919
1920 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
1921 post, true, &offset);
1922 }
1923
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_extra)1924 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_extra)
1925 {
1926 test_http2_dynamic_response_header_extra(false);
1927 }
1928
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_extra)1929 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_extra)
1930 {
1931 test_http2_dynamic_response_header_extra(true);
1932 }
1933
test_http1_dynamic_response_header_override(bool post)1934 static void test_http1_dynamic_response_header_override(bool post)
1935 {
1936 static const char response[] = "HTTP/1.1 200\r\n"
1937 "Transfer-Encoding: chunked\r\n"
1938 "Content-Type: application/json\r\n"
1939 "\r\n"
1940 "0\r\n\r\n";
1941
1942 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_OVERRIDE_HEADER;
1943
1944 test_http1_dynamic_response_headers_default(response, post);
1945 }
1946
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_override)1947 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_override)
1948 {
1949 test_http1_dynamic_response_header_override(false);
1950 }
1951
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_override)1952 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_override)
1953 {
1954 test_http1_dynamic_response_header_override(true);
1955 }
1956
test_http2_dynamic_response_header_override(bool post)1957 static void test_http2_dynamic_response_header_override(bool post)
1958 {
1959 size_t offset = 0;
1960 const struct http_header expected_headers[] = {
1961 {.name = ":status", .value = "200"},
1962 {.name = "content-type", .value = "application/json"},
1963 };
1964
1965 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_OVERRIDE_HEADER;
1966
1967 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
1968 post, true, &offset);
1969 }
1970
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_override)1971 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_override)
1972 {
1973 test_http2_dynamic_response_header_override(false);
1974 }
1975
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_override)1976 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_override)
1977 {
1978 test_http2_dynamic_response_header_override(true);
1979 }
1980
test_http1_dynamic_response_header_separate(bool post)1981 static void test_http1_dynamic_response_header_separate(bool post)
1982 {
1983 static const char response[] = "HTTP/1.1 200\r\n"
1984 "Transfer-Encoding: chunked\r\n"
1985 "Test-Header: test_data\r\n"
1986 "Content-Type: text/plain\r\n"
1987 "\r\n"
1988 "10\r\n" TEST_DYNAMIC_GET_PAYLOAD "\r\n"
1989 "0\r\n\r\n";
1990
1991 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_SEPARATE;
1992
1993 test_http1_dynamic_response_headers_default(response, post);
1994 }
1995
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_separate)1996 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_separate)
1997 {
1998 test_http1_dynamic_response_header_separate(false);
1999 }
2000
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_separate)2001 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_separate)
2002 {
2003 test_http1_dynamic_response_header_separate(true);
2004 }
2005
test_http2_dynamic_response_header_separate(bool post)2006 static void test_http2_dynamic_response_header_separate(bool post)
2007 {
2008 size_t offset = 0;
2009 const struct http_header expected_headers[] = {
2010 {.name = ":status", .value = "200"},
2011 {.name = "test-header", .value = "test_data"},
2012 {.name = "content-type", .value = "text/plain"},
2013 };
2014
2015 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_SEPARATE;
2016
2017 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
2018 post, false, &offset);
2019 }
2020
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_separate)2021 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_separate)
2022 {
2023 test_http2_dynamic_response_header_separate(false);
2024 }
2025
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_separate)2026 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_separate)
2027 {
2028 test_http2_dynamic_response_header_separate(true);
2029 }
2030
test_http1_dynamic_response_header_combined(bool post)2031 static void test_http1_dynamic_response_header_combined(bool post)
2032 {
2033 static const char response[] = "HTTP/1.1 200\r\n"
2034 "Transfer-Encoding: chunked\r\n"
2035 "Test-Header: test_data\r\n"
2036 "Content-Type: text/plain\r\n"
2037 "\r\n"
2038 "10\r\n" TEST_DYNAMIC_GET_PAYLOAD "\r\n"
2039 "0\r\n\r\n";
2040
2041 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_COMBINED;
2042
2043 test_http1_dynamic_response_headers_default(response, post);
2044 }
2045
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_combined)2046 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_combined)
2047 {
2048 test_http1_dynamic_response_header_combined(false);
2049 }
2050
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_combined)2051 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_combined)
2052 {
2053 test_http1_dynamic_response_header_combined(true);
2054 }
2055
test_http2_dynamic_response_header_combined(bool post)2056 static void test_http2_dynamic_response_header_combined(bool post)
2057 {
2058 size_t offset = 0;
2059 const struct http_header expected_headers[] = {
2060 {.name = ":status", .value = "200"},
2061 {.name = "test-header", .value = "test_data"},
2062 {.name = "content-type", .value = "text/plain"},
2063 };
2064
2065 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_COMBINED;
2066
2067 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
2068 post, false, &offset);
2069 }
2070
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_combined)2071 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_combined)
2072 {
2073 test_http2_dynamic_response_header_combined(false);
2074 }
2075
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_combined)2076 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_combined)
2077 {
2078 test_http2_dynamic_response_header_combined(true);
2079 }
2080
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_long)2081 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_long)
2082 {
2083 static const char response[] = "HTTP/1.1 200\r\n"
2084 "Transfer-Encoding: chunked\r\n"
2085 "Content-Type: text/plain\r\n"
2086 "\r\n"
2087 "130\r\n" TEST_LONG_PAYLOAD_CHUNK_1 "\r\n"
2088 "d0\r\n" TEST_LONG_PAYLOAD_CHUNK_2 "\r\n"
2089 "0\r\n\r\n";
2090
2091 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG;
2092
2093 test_http1_dynamic_response_headers_default(response, false);
2094 }
2095
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_long)2096 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_long)
2097 {
2098 static const char request[] = "POST /response_headers HTTP/1.1\r\n"
2099 "Accept: */*\r\n"
2100 "Content-Length: 512\r\n"
2101 "\r\n" TEST_LONG_PAYLOAD_CHUNK_1 TEST_LONG_PAYLOAD_CHUNK_2;
2102 static const char response[] = "HTTP/1.1 200\r\n"
2103 "Transfer-Encoding: chunked\r\n"
2104 "Content-Type: text/plain\r\n"
2105 "\r\n"
2106 "0\r\n\r\n";
2107
2108 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG;
2109
2110 test_http1_dynamic_response_headers(request, response);
2111 zassert_mem_equal(dynamic_response_headers_buffer, long_payload, strlen(long_payload));
2112 }
2113
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_long)2114 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_long)
2115 {
2116 size_t offset = 0;
2117 const struct http_header expected_headers[] = {
2118 {.name = ":status", .value = "200"},
2119 {.name = "content-type", .value = "text/plain"},
2120 };
2121
2122 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG;
2123
2124 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
2125 false, false, &offset);
2126 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, TEST_LONG_PAYLOAD_CHUNK_1,
2127 strlen(TEST_LONG_PAYLOAD_CHUNK_1), 0);
2128 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, TEST_LONG_PAYLOAD_CHUNK_2,
2129 strlen(TEST_LONG_PAYLOAD_CHUNK_2), HTTP2_FLAG_END_STREAM);
2130 }
2131
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_long)2132 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_long)
2133 {
2134 size_t offset = 0;
2135 size_t req_offset = 0;
2136
2137 const struct http_header expected_headers[] = {
2138 {.name = ":status", .value = "200"},
2139 {.name = "content-type", .value = "text/plain"},
2140 };
2141
2142 const uint8_t request_part1[] = {
2143 TEST_HTTP2_MAGIC,
2144 TEST_HTTP2_SETTINGS,
2145 TEST_HTTP2_SETTINGS_ACK,
2146 TEST_HTTP2_HEADERS_POST_RESPONSE_HEADERS_STREAM_1,
2147 /* Data frame header */
2148 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, TEST_STREAM_ID_1,
2149 };
2150
2151 const uint8_t request_part3[] = {
2152 TEST_HTTP2_GOAWAY,
2153 };
2154
2155 static uint8_t
2156 request[sizeof(request_part1) + (sizeof(long_payload) - 1) + sizeof(request_part3)];
2157
2158 BUILD_ASSERT(sizeof(long_payload) - 1 == 0x200, "Length field in data frame header must "
2159 "match length of long_payload");
2160
2161 memcpy(request + req_offset, request_part1, sizeof(request_part1));
2162 req_offset += sizeof(request_part1);
2163 memcpy(request + req_offset, long_payload, sizeof(long_payload) - 1);
2164 req_offset += sizeof(long_payload) - 1;
2165 memcpy(request + req_offset, request_part3, sizeof(request_part3));
2166 req_offset += sizeof(request_part3);
2167
2168 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG;
2169
2170 test_http2_dynamic_response_headers(request, req_offset, expected_headers,
2171 ARRAY_SIZE(expected_headers), true, &offset);
2172 zassert_mem_equal(dynamic_response_headers_buffer, long_payload, strlen(long_payload));
2173 }
2174
ZTEST(server_function_tests,test_http1_409_method_not_allowed)2175 ZTEST(server_function_tests, test_http1_409_method_not_allowed)
2176 {
2177 static const char http1_request[] =
2178 "POST / HTTP/1.1\r\n"
2179 "Host: 127.0.0.1:8080\r\n"
2180 "Content-Type: text/html\r\n"
2181 "Content-Length: 13\r\n\r\n"
2182 TEST_STATIC_PAYLOAD;
2183 static const char expected_response[] =
2184 "HTTP/1.1 405 Method Not Allowed\r\n";
2185 size_t offset = 0;
2186 int ret;
2187
2188 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
2189 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
2190
2191 memset(buf, 0, sizeof(buf));
2192
2193 test_read_data(&offset, sizeof(expected_response) - 1);
2194 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
2195 "Received data doesn't match expected response");
2196 }
2197
ZTEST(server_function_tests,test_http1_upgrade_409_method_not_allowed)2198 ZTEST(server_function_tests, test_http1_upgrade_409_method_not_allowed)
2199 {
2200 static const char http1_request[] =
2201 "POST / HTTP/1.1\r\n"
2202 "Host: 127.0.0.1:8080\r\n"
2203 "Content-Type: text/html\r\n"
2204 "Content-Length: 13\r\n"
2205 "Connection: Upgrade, HTTP2-Settings\r\n"
2206 "Upgrade: h2c\r\n"
2207 "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n\r\n"
2208 TEST_STATIC_PAYLOAD;
2209 const struct http_header expected_headers[] = {
2210 {.name = ":status", .value = "405"}
2211 };
2212 size_t offset = 0;
2213 int ret;
2214
2215 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
2216 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
2217
2218 memset(buf, 0, sizeof(buf));
2219
2220 /* Verify HTTP1 switching protocols response. */
2221 expect_http1_switching_protocols(&offset);
2222
2223 /* Verify HTTP2 frames. */
2224 expect_http2_settings_frame(&offset, false);
2225 expect_http2_headers_frame(&offset, UPGRADE_STREAM_ID,
2226 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM,
2227 expected_headers, 1);
2228 }
2229
ZTEST(server_function_tests,test_http2_409_method_not_allowed)2230 ZTEST(server_function_tests, test_http2_409_method_not_allowed)
2231 {
2232 static const uint8_t request_post_static[] = {
2233 TEST_HTTP2_MAGIC,
2234 TEST_HTTP2_SETTINGS,
2235 TEST_HTTP2_SETTINGS_ACK,
2236 TEST_HTTP2_HEADERS_POST_ROOT_STREAM_1,
2237 TEST_HTTP2_DATA_POST_ROOT_STREAM_1,
2238 TEST_HTTP2_GOAWAY,
2239 };
2240 const struct http_header expected_headers[] = {
2241 {.name = ":status", .value = "405"}
2242 };
2243 size_t offset = 0;
2244 int ret;
2245
2246 ret = zsock_send(client_fd, request_post_static,
2247 sizeof(request_post_static), 0);
2248 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
2249
2250 memset(buf, 0, sizeof(buf));
2251
2252 expect_http2_settings_frame(&offset, false);
2253 expect_http2_settings_frame(&offset, true);
2254 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
2255 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM,
2256 expected_headers, 1);
2257 }
2258
ZTEST(server_function_tests,test_http1_500_internal_server_error)2259 ZTEST(server_function_tests, test_http1_500_internal_server_error)
2260 {
2261 static const char http1_request[] =
2262 "GET /dynamic HTTP/1.1\r\n"
2263 "Host: 127.0.0.1:8080\r\n"
2264 "User-Agent: curl/7.68.0\r\n"
2265 "Accept: */*\r\n"
2266 "Accept-Encoding: deflate, gzip, br\r\n"
2267 "\r\n";
2268 static const char expected_response[] =
2269 "HTTP/1.1 500 Internal Server Error\r\n";
2270 size_t offset = 0;
2271 int ret;
2272
2273 dynamic_error = true;
2274
2275 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
2276 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
2277
2278 memset(buf, 0, sizeof(buf));
2279
2280 test_read_data(&offset, sizeof(expected_response) - 1);
2281 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
2282 "Received data doesn't match expected response");
2283 }
2284
ZTEST(server_function_tests,test_http1_upgrade_500_internal_server_error)2285 ZTEST(server_function_tests, test_http1_upgrade_500_internal_server_error)
2286 {
2287 static const char http1_request[] =
2288 "GET /dynamic HTTP/1.1\r\n"
2289 "Host: 127.0.0.1:8080\r\n"
2290 "User-Agent: curl/7.68.0\r\n"
2291 "Accept: */*\r\n"
2292 "Accept-Encoding: deflate, gzip, br\r\n"
2293 "Connection: Upgrade, HTTP2-Settings\r\n"
2294 "Upgrade: h2c\r\n"
2295 "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n"
2296 "\r\n";
2297 const struct http_header expected_headers[] = {
2298 {.name = ":status", .value = "500"}
2299 };
2300 size_t offset = 0;
2301 int ret;
2302
2303 dynamic_error = true;
2304
2305 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
2306 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
2307
2308 memset(buf, 0, sizeof(buf));
2309
2310 /* Verify HTTP1 switching protocols response. */
2311 expect_http1_switching_protocols(&offset);
2312
2313 /* Verify HTTP2 frames. */
2314 expect_http2_settings_frame(&offset, false);
2315 expect_http2_headers_frame(&offset, UPGRADE_STREAM_ID,
2316 HTTP2_FLAG_END_HEADERS,
2317 expected_headers, 1);
2318 /* Expect data frame with reason but don't check the content as it may
2319 * depend on libc being used (i. e. string returned by strerror()).
2320 */
2321 expect_http2_data_frame(&offset, UPGRADE_STREAM_ID, NULL, 0,
2322 HTTP2_FLAG_END_STREAM);
2323 }
2324
ZTEST(server_function_tests,test_http2_500_internal_server_error)2325 ZTEST(server_function_tests, test_http2_500_internal_server_error)
2326 {
2327 static const uint8_t request_get_dynamic[] = {
2328 TEST_HTTP2_MAGIC,
2329 TEST_HTTP2_SETTINGS,
2330 TEST_HTTP2_SETTINGS_ACK,
2331 TEST_HTTP2_HEADERS_GET_DYNAMIC_STREAM_1,
2332 TEST_HTTP2_GOAWAY,
2333 };
2334 const struct http_header expected_headers[] = {
2335 {.name = ":status", .value = "500"}
2336 };
2337 size_t offset = 0;
2338 int ret;
2339
2340 dynamic_error = true;
2341
2342 ret = zsock_send(client_fd, request_get_dynamic,
2343 sizeof(request_get_dynamic), 0);
2344 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
2345
2346 memset(buf, 0, sizeof(buf));
2347
2348 expect_http2_settings_frame(&offset, false);
2349 expect_http2_settings_frame(&offset, true);
2350 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
2351 HTTP2_FLAG_END_HEADERS,
2352 expected_headers, 1);
2353 /* Expect data frame with reason but don't check the content as it may
2354 * depend on libc being used (i. e. string returned by strerror()).
2355 */
2356 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, NULL, 0,
2357 HTTP2_FLAG_END_STREAM);
2358 }
2359
ZTEST(server_function_tests_no_init,test_http_server_start_stop)2360 ZTEST(server_function_tests_no_init, test_http_server_start_stop)
2361 {
2362 struct sockaddr_in sa = { 0 };
2363 int ret;
2364
2365 sa.sin_family = AF_INET;
2366 sa.sin_port = htons(SERVER_PORT);
2367
2368 ret = zsock_inet_pton(AF_INET, SERVER_IPV4_ADDR, &sa.sin_addr.s_addr);
2369 zassert_equal(1, ret, "inet_pton() failed to convert %s", SERVER_IPV4_ADDR);
2370
2371 zassert_ok(http_server_start(), "Failed to start the server");
2372 zassert_not_ok(http_server_start(), "Server start should report na error.");
2373
2374 zassert_ok(http_server_stop(), "Failed to stop the server");
2375 zassert_not_ok(http_server_stop(), "Server stop should report na error.");
2376
2377 zassert_ok(http_server_start(), "Failed to start the server");
2378
2379 /* Server should be listening now. */
2380 ret = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2381 zassert_not_equal(ret, -1, "failed to create client socket (%d)", errno);
2382 client_fd = ret;
2383
2384 zassert_ok(zsock_connect(client_fd, (struct sockaddr *)&sa, sizeof(sa)),
2385 "failed to connect to the server (%d)", errno);
2386 zassert_ok(zsock_close(client_fd), "close() failed on the client fd (%d)", errno);
2387 client_fd = -1;
2388
2389 /* Check if the server can be restarted again after client connected. */
2390 zassert_ok(http_server_stop(), "Failed to stop the server");
2391 zassert_ok(http_server_start(), "Failed to start the server");
2392
2393 /* Let the server thread run. */
2394 k_msleep(CONFIG_HTTP_SERVER_RESTART_DELAY + 10);
2395
2396 ret = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2397 zassert_not_equal(ret, -1, "failed to create client socket (%d)", errno);
2398 client_fd = ret;
2399
2400 zassert_ok(zsock_connect(client_fd, (struct sockaddr *)&sa, sizeof(sa)),
2401 "failed to connect to the server (%d)", errno);
2402 zassert_ok(zsock_close(client_fd), "close() failed on the client fd (%d)", errno);
2403 client_fd = -1;
2404
2405 zassert_ok(http_server_stop(), "Failed to stop the server");
2406 }
2407
ZTEST(server_function_tests_no_init,test_get_frame_type_name)2408 ZTEST(server_function_tests_no_init, test_get_frame_type_name)
2409 {
2410 zassert_str_equal(get_frame_type_name(HTTP2_DATA_FRAME), "DATA",
2411 "Unexpected frame type");
2412 zassert_str_equal(get_frame_type_name(HTTP2_HEADERS_FRAME),
2413 "HEADERS", "Unexpected frame type");
2414 zassert_str_equal(get_frame_type_name(HTTP2_PRIORITY_FRAME),
2415 "PRIORITY", "Unexpected frame type");
2416 zassert_str_equal(get_frame_type_name(HTTP2_RST_STREAM_FRAME),
2417 "RST_STREAM", "Unexpected frame type");
2418 zassert_str_equal(get_frame_type_name(HTTP2_SETTINGS_FRAME),
2419 "SETTINGS", "Unexpected frame type");
2420 zassert_str_equal(get_frame_type_name(HTTP2_PUSH_PROMISE_FRAME),
2421 "PUSH_PROMISE", "Unexpected frame type");
2422 zassert_str_equal(get_frame_type_name(HTTP2_PING_FRAME), "PING",
2423 "Unexpected frame type");
2424 zassert_str_equal(get_frame_type_name(HTTP2_GOAWAY_FRAME),
2425 "GOAWAY", "Unexpected frame type");
2426 zassert_str_equal(get_frame_type_name(HTTP2_WINDOW_UPDATE_FRAME),
2427 "WINDOW_UPDATE", "Unexpected frame type");
2428 zassert_str_equal(get_frame_type_name(HTTP2_CONTINUATION_FRAME),
2429 "CONTINUATION", "Unexpected frame type");
2430 }
2431
ZTEST(server_function_tests_no_init,test_parse_http_frames)2432 ZTEST(server_function_tests_no_init, test_parse_http_frames)
2433 {
2434 static struct http_client_ctx ctx_client1;
2435 static struct http_client_ctx ctx_client2;
2436 struct http2_frame *frame;
2437
2438 unsigned char buffer1[] = {
2439 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00,
2440 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00,
2441 0x04, 0x00, 0x00, 0xff, 0xff, 0x00
2442 };
2443 unsigned char buffer2[] = {
2444 0x00, 0x00, 0x21, 0x01, 0x05, 0x00, 0x00, 0x00,
2445 0x01, 0x82, 0x84, 0x86, 0x41, 0x8a, 0x0b, 0xe2,
2446 0x5c, 0x0b, 0x89, 0x70, 0xdc, 0x78, 0x0f, 0x03,
2447 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x90, 0x7a, 0x8a,
2448 0xaa, 0x69, 0xd2, 0x9a, 0xc4, 0xc0, 0x57, 0x68,
2449 0x0b, 0x83
2450 };
2451
2452 memcpy(ctx_client1.buffer, buffer1, sizeof(buffer1));
2453 memcpy(ctx_client2.buffer, buffer2, sizeof(buffer2));
2454
2455 ctx_client1.cursor = ctx_client1.buffer;
2456 ctx_client1.data_len = ARRAY_SIZE(buffer1);
2457
2458 ctx_client2.cursor = ctx_client2.buffer;
2459 ctx_client2.data_len = ARRAY_SIZE(buffer2);
2460
2461 /* Test: Buffer with the first frame */
2462 int parser1 = parse_http_frame_header(&ctx_client1, ctx_client1.cursor,
2463 ctx_client1.data_len);
2464
2465 zassert_equal(parser1, 0, "Failed to parse the first frame");
2466
2467 frame = &ctx_client1.current_frame;
2468
2469 /* Validate frame details for the 1st frame */
2470 zassert_equal(frame->length, 0x0C, "Expected length for the 1st frame doesn't match");
2471 zassert_equal(frame->type, 0x04, "Expected type for the 1st frame doesn't match");
2472 zassert_equal(frame->flags, 0x00, "Expected flags for the 1st frame doesn't match");
2473 zassert_equal(frame->stream_identifier, 0x00,
2474 "Expected stream_identifier for the 1st frame doesn't match");
2475
2476 /* Test: Buffer with the second frame */
2477 int parser2 = parse_http_frame_header(&ctx_client2, ctx_client2.cursor,
2478 ctx_client2.data_len);
2479
2480 zassert_equal(parser2, 0, "Failed to parse the second frame");
2481
2482 frame = &ctx_client2.current_frame;
2483
2484 /* Validate frame details for the 2nd frame */
2485 zassert_equal(frame->length, 0x21, "Expected length for the 2nd frame doesn't match");
2486 zassert_equal(frame->type, 0x01, "Expected type for the 2nd frame doesn't match");
2487 zassert_equal(frame->flags, 0x05, "Expected flags for the 2nd frame doesn't match");
2488 zassert_equal(frame->stream_identifier, 0x01,
2489 "Expected stream_identifier for the 2nd frame doesn't match");
2490 }
2491
2492 #if DT_HAS_COMPAT_STATUS_OKAY(zephyr_ram_disk)
2493
2494 #include <zephyr/fs/fs.h>
2495 #include <zephyr/fs/littlefs.h>
2496
2497 FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage);
2498
2499 #define TEST_PARTITION storage_partition
2500 #define TEST_PARTITION_ID FIXED_PARTITION_ID(TEST_PARTITION)
2501
2502 #define LFS_MNTP "/littlefs"
2503 #define TEST_FILE "static_file.html"
2504 #define TEST_DIR "/files"
2505 #define TEST_DIR_PATH LFS_MNTP TEST_DIR
2506
2507 static struct http_resource_detail_static_fs static_file_resource_detail = {
2508 .common = {
2509 .type = HTTP_RESOURCE_TYPE_STATIC_FS,
2510 .bitmask_of_supported_http_methods = BIT(HTTP_GET),
2511 .content_type = "text/html",
2512 },
2513 .fs_path = TEST_DIR_PATH,
2514 };
2515
2516 HTTP_RESOURCE_DEFINE(static_file_resource, test_http_service, "/static_file.html",
2517 &static_file_resource_detail);
2518
2519 struct fs_mount_t littlefs_mnt = {
2520 .type = FS_LITTLEFS,
2521 .fs_data = &storage,
2522 .storage_dev = (void *)TEST_PARTITION_ID,
2523 .mnt_point = LFS_MNTP,
2524 };
2525
test_clear_flash(void)2526 void test_clear_flash(void)
2527 {
2528 int rc;
2529 const struct flash_area *fap;
2530
2531 rc = flash_area_open(TEST_PARTITION_ID, &fap);
2532 zassert_equal(rc, 0, "Opening flash area for erase [%d]\n", rc);
2533
2534 rc = flash_area_flatten(fap, 0, fap->fa_size);
2535 zassert_equal(rc, 0, "Erasing flash area [%d]\n", rc);
2536 }
2537
test_mount(void)2538 static int test_mount(void)
2539 {
2540 int ret;
2541
2542 ret = fs_mount(&littlefs_mnt);
2543 if (ret < 0) {
2544 TC_PRINT("Error mounting fs [%d]\n", ret);
2545 return TC_FAIL;
2546 }
2547
2548 return TC_PASS;
2549 }
2550
test_unmount(void)2551 static int test_unmount(void)
2552 {
2553 int ret;
2554
2555 ret = fs_unmount(&littlefs_mnt);
2556 if (ret < 0 && ret != -EINVAL) {
2557 TC_PRINT("Error unmounting fs [%d]\n", ret);
2558 return TC_FAIL;
2559 }
2560
2561 return TC_PASS;
2562 }
2563
2564 #ifndef PATH_MAX
2565 #define PATH_MAX 64
2566 #endif
2567
check_file_dir_exists(const char * fpath)2568 int check_file_dir_exists(const char *fpath)
2569 {
2570 int res;
2571 struct fs_dirent entry;
2572
2573 res = fs_stat(fpath, &entry);
2574
2575 return !res;
2576 }
2577
test_file_write(struct fs_file_t * filep,const char * test_str)2578 int test_file_write(struct fs_file_t *filep, const char *test_str)
2579 {
2580 ssize_t brw;
2581 int res;
2582
2583 TC_PRINT("\nWrite tests:\n");
2584
2585 /* Verify fs_seek() */
2586 res = fs_seek(filep, 0, FS_SEEK_SET);
2587 if (res) {
2588 TC_PRINT("fs_seek failed [%d]\n", res);
2589 fs_close(filep);
2590 return res;
2591 }
2592
2593 TC_PRINT("Data written:\"%s\"\n\n", test_str);
2594
2595 /* Verify fs_write() */
2596 brw = fs_write(filep, (char *)test_str, strlen(test_str));
2597 if (brw < 0) {
2598 TC_PRINT("Failed writing to file [%zd]\n", brw);
2599 fs_close(filep);
2600 return brw;
2601 }
2602
2603 if (brw < strlen(test_str)) {
2604 TC_PRINT("Unable to complete write. Volume full.\n");
2605 TC_PRINT("Number of bytes written: [%zd]\n", brw);
2606 fs_close(filep);
2607 return TC_FAIL;
2608 }
2609
2610 TC_PRINT("Data successfully written!\n");
2611
2612 return res;
2613 }
2614
test_mkdir(const char * dir_path,const char * file)2615 int test_mkdir(const char *dir_path, const char *file)
2616 {
2617 int res;
2618 struct fs_file_t filep;
2619 char file_path[PATH_MAX] = { 0 };
2620
2621 fs_file_t_init(&filep);
2622 res = sprintf(file_path, "%s/%s", dir_path, file);
2623 __ASSERT_NO_MSG(res < sizeof(file_path));
2624
2625 if (check_file_dir_exists(dir_path)) {
2626 TC_PRINT("Dir %s exists\n", dir_path);
2627 return TC_FAIL;
2628 }
2629
2630 TC_PRINT("Creating new dir %s\n", dir_path);
2631
2632 /* Verify fs_mkdir() */
2633 res = fs_mkdir(dir_path);
2634 if (res) {
2635 TC_PRINT("Error creating dir[%d]\n", res);
2636 return res;
2637 }
2638
2639 res = fs_open(&filep, file_path, FS_O_CREATE | FS_O_RDWR);
2640 if (res) {
2641 TC_PRINT("Failed opening file [%d]\n", res);
2642 return res;
2643 }
2644
2645 TC_PRINT("Testing write to file %s\n", file_path);
2646 res = test_file_write(&filep, TEST_STATIC_FS_PAYLOAD);
2647 if (res) {
2648 fs_close(&filep);
2649 return res;
2650 }
2651
2652 res = fs_close(&filep);
2653 if (res) {
2654 TC_PRINT("Error closing file [%d]\n", res);
2655 return res;
2656 }
2657
2658 TC_PRINT("Created dir %s!\n", dir_path);
2659
2660 return res;
2661 }
2662
setup_fs(const char * file_ending)2663 static int setup_fs(const char *file_ending)
2664 {
2665 char filename_buf[sizeof(TEST_FILE)+5] = TEST_FILE;
2666
2667 strcat(filename_buf, file_ending);
2668 test_clear_flash();
2669
2670 zassert_equal(test_unmount(), TC_PASS, "Failed to unmount fs");
2671 zassert_equal(test_mount(), TC_PASS, "Failed to mount fs");
2672
2673 return test_mkdir(TEST_DIR_PATH, filename_buf);
2674 }
2675
ZTEST(server_function_tests,test_http1_static_fs)2676 ZTEST(server_function_tests, test_http1_static_fs)
2677 {
2678 static const char http1_request[] =
2679 "GET /static_file.html HTTP/1.1\r\n"
2680 "Host: 127.0.0.1:8080\r\n"
2681 "User-Agent: curl/7.68.0\r\n"
2682 "Accept: */*\r\n"
2683 "\r\n";
2684 static const char expected_response[] =
2685 "HTTP/1.1 200 OK\r\n"
2686 "Content-Length: 30\r\n"
2687 "Content-Type: text/html\r\n"
2688 "\r\n"
2689 TEST_STATIC_FS_PAYLOAD;
2690 size_t offset = 0;
2691 int ret;
2692
2693 ret = setup_fs("");
2694 zassert_equal(ret, TC_PASS, "Failed to mount fs");
2695
2696 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
2697 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
2698
2699 memset(buf, 0, sizeof(buf));
2700
2701 test_read_data(&offset, sizeof(expected_response) - 1);
2702 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
2703 "Received data doesn't match expected response");
2704 }
2705
ZTEST(server_function_tests,test_http1_static_fs_compression)2706 ZTEST(server_function_tests, test_http1_static_fs_compression)
2707 {
2708 #define HTTP1_COMPRESSION_REQUEST \
2709 "GET /static_file.html HTTP/1.1\r\n" \
2710 "Host: 127.0.0.1:8080\r\n" \
2711 "User-Agent: curl/7.68.0\r\n" \
2712 "Accept: */*\r\n" \
2713 "Accept-Encoding: %s\r\n" \
2714 "\r\n"
2715 #define HTTP1_COMPRESSION_RESPONSE \
2716 "HTTP/1.1 200 OK\r\n" \
2717 "Content-Length: 30\r\n" \
2718 "Content-Type: text/html\r\n" \
2719 "Content-Encoding: %s\r\n" \
2720 "\r\n" TEST_STATIC_FS_PAYLOAD
2721
2722 static const char mixed_compression_str[] = "gzip, deflate, br";
2723 static char http1_request[sizeof(HTTP1_COMPRESSION_REQUEST) +
2724 ARRAY_SIZE(mixed_compression_str)] = {0};
2725 static char expected_response[sizeof(HTTP1_COMPRESSION_RESPONSE) +
2726 HTTP_COMPRESSION_MAX_STRING_LEN] = {0};
2727 static const char *const file_ending_map[] = {[HTTP_GZIP] = ".gz",
2728 [HTTP_COMPRESS] = ".lzw",
2729 [HTTP_DEFLATE] = ".zz",
2730 [HTTP_BR] = ".br",
2731 [HTTP_ZSTD] = ".zst"};
2732 size_t offset;
2733 int ret;
2734 int expected_response_size;
2735
2736 for (enum http_compression i = 0; compression_value_is_valid(i); ++i) {
2737 offset = 0;
2738
2739 if (i == HTTP_NONE) {
2740 continue;
2741 }
2742 TC_PRINT("Testing %s compression...\n", http_compression_text(i));
2743 zassert(i < ARRAY_SIZE(file_ending_map) && &file_ending_map[i] != NULL,
2744 "No file ending defined for compression");
2745
2746 sprintf(http1_request, HTTP1_COMPRESSION_REQUEST, http_compression_text(i));
2747 expected_response_size = sprintf(expected_response, HTTP1_COMPRESSION_RESPONSE,
2748 http_compression_text(i));
2749
2750 ret = setup_fs(file_ending_map[i]);
2751 zassert_equal(ret, TC_PASS, "Failed to mount fs");
2752
2753 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
2754 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
2755
2756 memset(buf, 0, sizeof(buf));
2757
2758 test_read_data(&offset, expected_response_size);
2759 zassert_mem_equal(buf, expected_response, expected_response_size,
2760 "Received data doesn't match expected response");
2761 }
2762
2763 offset = 0;
2764 TC_PRINT("Testing mixed compression...\n");
2765 sprintf(http1_request, HTTP1_COMPRESSION_REQUEST, mixed_compression_str);
2766 expected_response_size = sprintf(expected_response, HTTP1_COMPRESSION_RESPONSE,
2767 http_compression_text(HTTP_BR));
2768 ret = setup_fs(file_ending_map[HTTP_BR]);
2769 zassert_equal(ret, TC_PASS, "Failed to mount fs");
2770
2771 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
2772 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
2773
2774 memset(buf, 0, sizeof(buf));
2775
2776 test_read_data(&offset, expected_response_size);
2777 zassert_mem_equal(buf, expected_response, expected_response_size,
2778 "Received data doesn't match expected response");
2779 }
2780 #endif /* DT_HAS_COMPAT_STATUS_OKAY(zephyr_ram_disk) */
2781
http_server_tests_before(void * fixture)2782 static void http_server_tests_before(void *fixture)
2783 {
2784 struct sockaddr_in sa;
2785 struct timeval optval = {
2786 .tv_sec = TIMEOUT_S,
2787 .tv_usec = 0,
2788 };
2789 int ret;
2790
2791 ARG_UNUSED(fixture);
2792
2793 memset(dynamic_payload, 0, sizeof(dynamic_payload));
2794 memset(dynamic_response_headers_buffer, 0, sizeof(dynamic_response_headers_buffer));
2795 memset(&request_headers_clone, 0, sizeof(request_headers_clone));
2796 memset(&request_headers_clone2, 0, sizeof(request_headers_clone2));
2797 dynamic_payload_len = 0;
2798 dynamic_error = false;
2799
2800 ret = http_server_start();
2801 if (ret < 0) {
2802 printk("Failed to start the server\n");
2803 return;
2804 }
2805
2806 ret = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2807 if (ret < 0) {
2808 printk("Failed to create client socket (%d)\n", errno);
2809 return;
2810 }
2811 client_fd = ret;
2812
2813 ret = zsock_setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &optval,
2814 sizeof(optval));
2815 if (ret < 0) {
2816 printk("Failed to set timeout (%d)\n", errno);
2817 return;
2818 }
2819
2820 sa.sin_family = AF_INET;
2821 sa.sin_port = htons(SERVER_PORT);
2822
2823 ret = zsock_inet_pton(AF_INET, SERVER_IPV4_ADDR, &sa.sin_addr.s_addr);
2824 if (ret != 1) {
2825 printk("inet_pton() failed to convert %s\n", SERVER_IPV4_ADDR);
2826 return;
2827 }
2828
2829 ret = zsock_connect(client_fd, (struct sockaddr *)&sa, sizeof(sa));
2830 if (ret < 0) {
2831 printk("Failed to connect (%d)\n", errno);
2832 }
2833 }
2834
http_server_tests_after(void * fixture)2835 static void http_server_tests_after(void *fixture)
2836 {
2837 ARG_UNUSED(fixture);
2838
2839 if (client_fd >= 0) {
2840 (void)zsock_close(client_fd);
2841 client_fd = -1;
2842 }
2843
2844 (void)http_server_stop();
2845
2846 k_yield();
2847 }
2848
2849 ZTEST_SUITE(server_function_tests, NULL, NULL, http_server_tests_before,
2850 http_server_tests_after, NULL);
2851 ZTEST_SUITE(server_function_tests_no_init, NULL, NULL, NULL,
2852 http_server_tests_after, NULL);
2853