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