1 /*
2 * Copyright (c) 2023, Emna Rekik
3 * Copyright (c) 2024 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include "server_internal.h"
9
10 #include <string.h>
11 #include <strings.h>
12
13 #include <zephyr/net/http/service.h>
14 #include <zephyr/net/socket.h>
15 #include <zephyr/posix/sys/eventfd.h>
16 #include <zephyr/ztest.h>
17
18 #define BUFFER_SIZE 1024
19 #define SERVER_IPV4_ADDR "127.0.0.1"
20 #define SERVER_PORT 8080
21 #define TIMEOUT_S 1
22
23 #define UPGRADE_STREAM_ID 1
24 #define TEST_STREAM_ID_1 3
25 #define TEST_STREAM_ID_2 5
26
27 #define TEST_DYNAMIC_POST_PAYLOAD "Test dynamic POST"
28 #define TEST_DYNAMIC_GET_PAYLOAD "Test dynamic GET"
29 #define TEST_STATIC_PAYLOAD "Hello, World!"
30
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
229 static uint16_t test_http_service_port = SERVER_PORT;
230 HTTP_SERVICE_DEFINE(test_http_service, SERVER_IPV4_ADDR,
231 &test_http_service_port, 1, 10, NULL);
232
233 static const char static_resource_payload[] = TEST_STATIC_PAYLOAD;
234 struct http_resource_detail_static static_resource_detail = {
235 .common = {
236 .type = HTTP_RESOURCE_TYPE_STATIC,
237 .bitmask_of_supported_http_methods = BIT(HTTP_GET),
238 },
239 .static_data = static_resource_payload,
240 .static_data_len = sizeof(static_resource_payload) - 1,
241 };
242
243 HTTP_RESOURCE_DEFINE(static_resource, test_http_service, "/",
244 &static_resource_detail);
245
246 static uint8_t dynamic_payload[32];
247 static size_t dynamic_payload_len = sizeof(dynamic_payload);
248
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)249 static int dynamic_cb(struct http_client_ctx *client, enum http_data_status status,
250 const struct http_request_ctx *request_ctx,
251 struct http_response_ctx *response_ctx, void *user_data)
252 {
253 static size_t offset;
254
255 if (status == HTTP_SERVER_DATA_ABORTED) {
256 offset = 0;
257 return 0;
258 }
259
260 switch (client->method) {
261 case HTTP_GET:
262 response_ctx->body = dynamic_payload;
263 response_ctx->body_len = dynamic_payload_len;
264 response_ctx->final_chunk = true;
265 break;
266 case HTTP_DELETE:
267 response_ctx->body = NULL;
268 response_ctx->body_len = 0;
269 response_ctx->final_chunk = true;
270 break;
271 case HTTP_POST:
272 case HTTP_PUT:
273 case HTTP_PATCH:
274 if (request_ctx->data_len + offset > sizeof(dynamic_payload)) {
275 return -ENOMEM;
276 }
277
278 if (request_ctx->data_len > 0) {
279 memcpy(dynamic_payload + offset, request_ctx->data, request_ctx->data_len);
280 offset += request_ctx->data_len;
281 }
282
283 if (status == HTTP_SERVER_DATA_FINAL) {
284 /* All data received, reset progress. */
285 dynamic_payload_len = offset;
286 offset = 0;
287 }
288
289 break;
290 default:
291 return -ENOTSUP;
292 }
293
294 return 0;
295 }
296
297 struct http_resource_detail_dynamic dynamic_detail = {
298 .common = {
299 .type = HTTP_RESOURCE_TYPE_DYNAMIC,
300 .bitmask_of_supported_http_methods =
301 BIT(HTTP_GET) | BIT(HTTP_DELETE) | BIT(HTTP_POST) |
302 BIT(HTTP_PUT) | BIT(HTTP_PATCH),
303 .content_type = "text/plain",
304 },
305 .cb = dynamic_cb,
306 .user_data = NULL,
307 };
308
309 HTTP_RESOURCE_DEFINE(dynamic_resource, test_http_service, "/dynamic",
310 &dynamic_detail);
311
312 struct test_headers_clone {
313 uint8_t buffer[CONFIG_HTTP_SERVER_CAPTURE_HEADER_BUFFER_SIZE];
314 struct http_header headers[CONFIG_HTTP_SERVER_CAPTURE_HEADER_COUNT];
315 size_t count;
316 enum http_header_status status;
317 };
318
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)319 static int dynamic_request_headers_cb(struct http_client_ctx *client, enum http_data_status status,
320 const struct http_request_ctx *request_ctx,
321 struct http_response_ctx *response_ctx, void *user_data)
322 {
323 ptrdiff_t offset;
324 struct http_header *hdrs_src;
325 struct http_header *hdrs_dst;
326 struct test_headers_clone *clone = (struct test_headers_clone *)user_data;
327
328 if (request_ctx->header_count != 0) {
329 /* Copy the captured header info to static buffer for later assertions in testcase.
330 * Don't assume that the buffer inside client context remains valid after return
331 * from the callback. Also need to update pointers within structure with an offset
332 * to point at new buffer.
333 */
334 memcpy(clone->buffer, &client->header_capture_ctx, sizeof(clone->buffer));
335
336 clone->count = request_ctx->header_count;
337 clone->status = request_ctx->headers_status;
338
339 hdrs_src = request_ctx->headers;
340 hdrs_dst = clone->headers;
341 offset = clone->buffer - client->header_capture_ctx.buffer;
342
343 for (int i = 0; i < request_ctx->header_count; i++) {
344 if (hdrs_src[i].name != NULL) {
345 hdrs_dst[i].name = hdrs_src[i].name + offset;
346 }
347
348 if (hdrs_src[i].value != NULL) {
349 hdrs_dst[i].value = hdrs_src[i].value + offset;
350 }
351 }
352 }
353
354 return 0;
355 }
356
357 /* Define two resources for testing header capture, so that we can check concurrent streams */
358 static struct test_headers_clone request_headers_clone;
359 static struct test_headers_clone request_headers_clone2;
360
361 struct http_resource_detail_dynamic dynamic_request_headers_detail = {
362 .common = {
363 .type = HTTP_RESOURCE_TYPE_DYNAMIC,
364 .bitmask_of_supported_http_methods = BIT(HTTP_GET) | BIT(HTTP_POST),
365 .content_type = "text/plain",
366 },
367 .cb = dynamic_request_headers_cb,
368 .user_data = &request_headers_clone,
369 };
370
371 struct http_resource_detail_dynamic dynamic_request_headers_detail2 = {
372 .common = {
373 .type = HTTP_RESOURCE_TYPE_DYNAMIC,
374 .bitmask_of_supported_http_methods = BIT(HTTP_GET) | BIT(HTTP_POST),
375 .content_type = "text/plain",
376 },
377 .cb = dynamic_request_headers_cb,
378 .user_data = &request_headers_clone2,
379 };
380
381 HTTP_RESOURCE_DEFINE(dynamic_request_headers_resource, test_http_service, "/header_capture",
382 &dynamic_request_headers_detail);
383
384 HTTP_RESOURCE_DEFINE(dynamic_request_headers_resource2, test_http_service, "/header_capture2",
385 &dynamic_request_headers_detail2);
386
387 HTTP_SERVER_REGISTER_HEADER_CAPTURE(capture_user_agent, "User-Agent");
388 HTTP_SERVER_REGISTER_HEADER_CAPTURE(capture_test_header, "Test-Header");
389 HTTP_SERVER_REGISTER_HEADER_CAPTURE(capture_test_header2, "Test-Header2");
390
391 enum dynamic_response_headers_variant {
392 /* No application defined response code, headers or data */
393 DYNAMIC_RESPONSE_HEADERS_VARIANT_NONE,
394
395 /* Send a 422 response code */
396 DYNAMIC_RESPONSE_HEADERS_VARIANT_422,
397
398 /* Send an extra header on top of server defaults */
399 DYNAMIC_RESPONSE_HEADERS_VARIANT_EXTRA_HEADER,
400
401 /* Override the default Content-Type header */
402 DYNAMIC_RESPONSE_HEADERS_VARIANT_OVERRIDE_HEADER,
403
404 /* Send body data combined with header data in a single callback */
405 DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_COMBINED,
406
407 /* Send body data in a separate callback to header data */
408 DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_SEPARATE,
409
410 /* Long body data split across multiple callbacks */
411 DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG,
412 };
413
414 static uint8_t dynamic_response_headers_variant;
415 static uint8_t dynamic_response_headers_buffer[sizeof(long_payload)];
416
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)417 static int dynamic_response_headers_cb(struct http_client_ctx *client, enum http_data_status status,
418 const struct http_request_ctx *request_ctx,
419 struct http_response_ctx *response_ctx, void *user_data)
420 {
421 static bool request_continuation;
422 static size_t offset;
423
424 static const struct http_header extra_headers[] = {
425 {.name = "Test-Header", .value = "test_data"},
426 };
427
428 static const struct http_header override_headers[] = {
429 {.name = "Content-Type", .value = "application/json"},
430 };
431
432 if (status != HTTP_SERVER_DATA_FINAL &&
433 dynamic_response_headers_variant != DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG) {
434 /* Long body variant is the only one which needs to take some action before final
435 * data has been received from server
436 */
437 return 0;
438 }
439
440 switch (dynamic_response_headers_variant) {
441 case DYNAMIC_RESPONSE_HEADERS_VARIANT_NONE:
442 break;
443
444 case DYNAMIC_RESPONSE_HEADERS_VARIANT_422:
445 response_ctx->status = 422;
446 response_ctx->final_chunk = true;
447 break;
448
449 case DYNAMIC_RESPONSE_HEADERS_VARIANT_EXTRA_HEADER:
450 response_ctx->headers = extra_headers;
451 response_ctx->header_count = ARRAY_SIZE(extra_headers);
452 response_ctx->final_chunk = true;
453 break;
454
455 case DYNAMIC_RESPONSE_HEADERS_VARIANT_OVERRIDE_HEADER:
456 response_ctx->headers = override_headers;
457 response_ctx->header_count = ARRAY_SIZE(extra_headers);
458 response_ctx->final_chunk = true;
459 break;
460
461 case DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_SEPARATE:
462 if (!request_continuation) {
463 /* Send headers in first callback */
464 response_ctx->headers = extra_headers;
465 response_ctx->header_count = ARRAY_SIZE(extra_headers);
466 request_continuation = true;
467 } else {
468 /* Send body in subsequent callback */
469 response_ctx->body = TEST_DYNAMIC_GET_PAYLOAD;
470 response_ctx->body_len = strlen(response_ctx->body);
471 response_ctx->final_chunk = true;
472 request_continuation = false;
473 }
474 break;
475
476 case DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_COMBINED:
477 response_ctx->headers = extra_headers;
478 response_ctx->header_count = ARRAY_SIZE(extra_headers);
479 response_ctx->body = TEST_DYNAMIC_GET_PAYLOAD;
480 response_ctx->body_len = strlen(response_ctx->body);
481 response_ctx->final_chunk = true;
482 break;
483
484 case DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG:
485 if (client->method == HTTP_GET) {
486 /* Send GET payload split across multiple callbacks */
487 size_t send_len = (offset == 0) ? strlen(TEST_LONG_PAYLOAD_CHUNK_1)
488 : strlen(TEST_LONG_PAYLOAD_CHUNK_2);
489
490 response_ctx->body = long_payload + offset;
491 response_ctx->body_len = send_len;
492 offset += send_len;
493
494 if (offset == strlen(long_payload)) {
495 offset = 0;
496 response_ctx->final_chunk = true;
497 }
498 } else if (client->method == HTTP_POST) {
499 /* Copy POST payload into buffer for later comparison */
500 zassert(offset + request_ctx->data_len <=
501 sizeof(dynamic_response_headers_buffer),
502 "POST data too long for buffer");
503 memcpy(dynamic_response_headers_buffer + offset, request_ctx->data,
504 request_ctx->data_len);
505 offset += request_ctx->data_len;
506
507 if (status == HTTP_SERVER_DATA_FINAL) {
508 offset = 0;
509 }
510 } else {
511 zassert(false, "unexpected HTTP method");
512 }
513 break;
514 }
515
516 return 0;
517 }
518
519 struct http_resource_detail_dynamic dynamic_response_headers_detail = {
520 .common = {
521 .type = HTTP_RESOURCE_TYPE_DYNAMIC,
522 .bitmask_of_supported_http_methods = BIT(HTTP_GET) | BIT(HTTP_POST),
523 .content_type = "text/plain",
524 },
525 .cb = dynamic_response_headers_cb,
526 .user_data = NULL
527 };
528
529 HTTP_RESOURCE_DEFINE(dynamic_response_headers_resource, test_http_service, "/response_headers",
530 &dynamic_response_headers_detail);
531
532 static int client_fd = -1;
533 static uint8_t buf[BUFFER_SIZE];
534
535 /* This function ensures that there's at least as much data as requested in
536 * the buffer.
537 */
test_read_data(size_t * offset,size_t need)538 static void test_read_data(size_t *offset, size_t need)
539 {
540 int ret;
541
542 while (*offset < need) {
543 ret = zsock_recv(client_fd, buf + *offset, sizeof(buf) - *offset, 0);
544 zassert_not_equal(ret, -1, "recv() failed (%d)", errno);
545 *offset += ret;
546 if (ret == 0) {
547 break;
548 }
549 };
550
551 zassert_true(*offset >= need, "Not all requested data received");
552 }
553
554 /* This function moves the remaining data in the buffer to the beginning. */
test_consume_data(size_t * offset,size_t consume)555 static void test_consume_data(size_t *offset, size_t consume)
556 {
557 zassert_true(*offset >= consume, "Cannot consume more data than received");
558 *offset -= consume;
559 memmove(buf, buf + consume, *offset);
560 }
561
expect_http1_switching_protocols(size_t * offset)562 static void expect_http1_switching_protocols(size_t *offset)
563 {
564 static const char switching_protocols[] =
565 "HTTP/1.1 101 Switching Protocols\r\n"
566 "Connection: Upgrade\r\n"
567 "Upgrade: h2c\r\n"
568 "\r\n";
569
570 test_read_data(offset, sizeof(switching_protocols) - 1);
571 zassert_mem_equal(buf, switching_protocols, sizeof(switching_protocols) - 1,
572 "Received data doesn't match expected response");
573 test_consume_data(offset, sizeof(switching_protocols) - 1);
574 }
575
test_get_frame_header(size_t * offset,struct http2_frame * frame)576 static void test_get_frame_header(size_t *offset, struct http2_frame *frame)
577 {
578 test_read_data(offset, HTTP2_FRAME_HEADER_SIZE);
579
580 frame->length = sys_get_be24(&buf[HTTP2_FRAME_LENGTH_OFFSET]);
581 frame->type = buf[HTTP2_FRAME_TYPE_OFFSET];
582 frame->flags = buf[HTTP2_FRAME_FLAGS_OFFSET];
583 frame->stream_identifier = sys_get_be32(
584 &buf[HTTP2_FRAME_STREAM_ID_OFFSET]);
585 frame->stream_identifier &= HTTP2_FRAME_STREAM_ID_MASK;
586
587 test_consume_data(offset, HTTP2_FRAME_HEADER_SIZE);
588 }
589
expect_http2_settings_frame(size_t * offset,bool ack)590 static void expect_http2_settings_frame(size_t *offset, bool ack)
591 {
592 struct http2_frame frame;
593
594 test_get_frame_header(offset, &frame);
595
596 zassert_equal(frame.type, HTTP2_SETTINGS_FRAME, "Expected settings frame");
597 zassert_equal(frame.stream_identifier, 0, "Settings frame stream ID must be 0");
598
599 if (ack) {
600 zassert_equal(frame.length, 0, "Invalid settings frame length");
601 zassert_equal(frame.flags, HTTP2_FLAG_SETTINGS_ACK,
602 "Expected settings ACK flag");
603 } else {
604 zassert_equal(frame.length % sizeof(struct http2_settings_field), 0,
605 "Invalid settings frame length");
606 zassert_equal(frame.flags, 0, "Expected no settings flags");
607
608 /* Consume settings payload */
609 test_read_data(offset, frame.length);
610 test_consume_data(offset, frame.length);
611 }
612 }
613
expect_contains_header(const uint8_t * buffer,size_t len,const struct http_header * header)614 static void expect_contains_header(const uint8_t *buffer, size_t len,
615 const struct http_header *header)
616 {
617 int ret;
618 bool found = false;
619 struct http_hpack_header_buf header_buf;
620 size_t consumed = 0;
621
622 while (consumed < len) {
623 ret = http_hpack_decode_header(buffer + consumed, len, &header_buf);
624 zassert_true(ret >= 0, "Failed to decode header");
625 zassert_true(consumed + ret <= len, "Frame length exceeded");
626
627 if (strncasecmp(header_buf.name, header->name, header_buf.name_len) == 0 &&
628 strncasecmp(header_buf.value, header->value, header_buf.value_len) == 0) {
629 found = true;
630 break;
631 }
632
633 consumed += ret;
634 }
635
636 zassert_true(found, "Header '%s: %s' not found", header->name, header->value);
637 }
638
expect_http2_headers_frame(size_t * offset,int stream_id,uint8_t flags,const struct http_header * headers,size_t headers_count)639 static void expect_http2_headers_frame(size_t *offset, int stream_id, uint8_t flags,
640 const struct http_header *headers, size_t headers_count)
641 {
642 struct http2_frame frame;
643
644 test_get_frame_header(offset, &frame);
645
646 zassert_equal(frame.type, HTTP2_HEADERS_FRAME, "Expected headers frame, got frame type %u",
647 frame.type);
648 zassert_equal(frame.stream_identifier, stream_id,
649 "Invalid headers frame stream ID");
650 zassert_equal(frame.flags, flags, "Unexpected flags received (expected %x got %x)", flags,
651 frame.flags);
652
653 /* Consume headers payload */
654 test_read_data(offset, frame.length);
655
656 for (size_t i = 0; i < headers_count; i++) {
657 expect_contains_header(buf, frame.length, &headers[i]);
658 }
659
660 test_consume_data(offset, frame.length);
661 }
662
expect_http2_data_frame(size_t * offset,int stream_id,const uint8_t * payload,size_t payload_len,uint8_t flags)663 static void expect_http2_data_frame(size_t *offset, int stream_id,
664 const uint8_t *payload, size_t payload_len,
665 uint8_t flags)
666 {
667 struct http2_frame frame;
668
669 test_get_frame_header(offset, &frame);
670
671 zassert_equal(frame.type, HTTP2_DATA_FRAME, "Expected data frame");
672 zassert_equal(frame.stream_identifier, stream_id,
673 "Invalid data frame stream ID");
674 zassert_equal(frame.flags, flags, "Unexpected flags received");
675 zassert_equal(frame.length, payload_len, "Unexpected data frame length");
676
677 /* Verify data payload */
678 test_read_data(offset, frame.length);
679 zassert_mem_equal(buf, payload, payload_len, "Unexpected data payload");
680 test_consume_data(offset, frame.length);
681 }
682
expect_http2_window_update_frame(size_t * offset,int stream_id)683 static void expect_http2_window_update_frame(size_t *offset, int stream_id)
684 {
685 struct http2_frame frame;
686
687 test_get_frame_header(offset, &frame);
688
689 zassert_equal(frame.type, HTTP2_WINDOW_UPDATE_FRAME,
690 "Expected window update frame");
691 zassert_equal(frame.stream_identifier, stream_id,
692 "Invalid window update frame stream ID (expected %d got %d)", stream_id,
693 frame.stream_identifier);
694 zassert_equal(frame.flags, 0, "Unexpected flags received");
695 zassert_equal(frame.length, sizeof(uint32_t),
696 "Unexpected window update frame length");
697
698
699 /* Consume window update payload */
700 test_read_data(offset, frame.length);
701 test_consume_data(offset, frame.length);
702 }
703
ZTEST(server_function_tests,test_http2_get_concurrent_streams)704 ZTEST(server_function_tests, test_http2_get_concurrent_streams)
705 {
706 static const uint8_t request_get_2_streams[] = {
707 TEST_HTTP2_MAGIC,
708 TEST_HTTP2_SETTINGS,
709 TEST_HTTP2_SETTINGS_ACK,
710 TEST_HTTP2_HEADERS_GET_ROOT_STREAM_1,
711 TEST_HTTP2_HEADERS_GET_INDEX_STREAM_2,
712 TEST_HTTP2_GOAWAY,
713 };
714 size_t offset = 0;
715 int ret;
716
717 ret = zsock_send(client_fd, request_get_2_streams,
718 sizeof(request_get_2_streams), 0);
719 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
720
721 memset(buf, 0, sizeof(buf));
722
723 /* Settings frame is expected twice (server settings + settings ACK) */
724 expect_http2_settings_frame(&offset, false);
725 expect_http2_settings_frame(&offset, true);
726 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1, HTTP2_FLAG_END_HEADERS, NULL, 0);
727 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, TEST_STATIC_PAYLOAD,
728 strlen(TEST_STATIC_PAYLOAD),
729 HTTP2_FLAG_END_STREAM);
730 expect_http2_headers_frame(&offset, TEST_STREAM_ID_2, HTTP2_FLAG_END_HEADERS, NULL, 0);
731 expect_http2_data_frame(&offset, TEST_STREAM_ID_2, NULL, 0,
732 HTTP2_FLAG_END_STREAM);
733 }
734
ZTEST(server_function_tests,test_http2_static_get)735 ZTEST(server_function_tests, test_http2_static_get)
736 {
737 static const uint8_t request_get_static_simple[] = {
738 TEST_HTTP2_MAGIC,
739 TEST_HTTP2_SETTINGS,
740 TEST_HTTP2_SETTINGS_ACK,
741 TEST_HTTP2_HEADERS_GET_ROOT_STREAM_1,
742 TEST_HTTP2_GOAWAY,
743 };
744 size_t offset = 0;
745 int ret;
746
747 ret = zsock_send(client_fd, request_get_static_simple,
748 sizeof(request_get_static_simple), 0);
749 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
750
751 memset(buf, 0, sizeof(buf));
752
753 expect_http2_settings_frame(&offset, false);
754 expect_http2_settings_frame(&offset, true);
755 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1, HTTP2_FLAG_END_HEADERS, NULL, 0);
756 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, TEST_STATIC_PAYLOAD,
757 strlen(TEST_STATIC_PAYLOAD),
758 HTTP2_FLAG_END_STREAM);
759 }
760
ZTEST(server_function_tests,test_http1_static_upgrade_get)761 ZTEST(server_function_tests, test_http1_static_upgrade_get)
762 {
763 static const char http1_request[] =
764 "GET / HTTP/1.1\r\n"
765 "Host: 127.0.0.1:8080\r\n"
766 "Accept: */*\r\n"
767 "Accept-Encoding: deflate, gzip, br\r\n"
768 "Connection: Upgrade, HTTP2-Settings\r\n"
769 "Upgrade: h2c\r\n"
770 "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n"
771 "\r\n";
772 size_t offset = 0;
773 int ret;
774
775 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
776 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
777
778 memset(buf, 0, sizeof(buf));
779
780 /* Verify HTTP1 switching protocols response. */
781 expect_http1_switching_protocols(&offset);
782
783 /* Verify HTTP2 frames. */
784 expect_http2_settings_frame(&offset, false);
785 expect_http2_headers_frame(&offset, UPGRADE_STREAM_ID, HTTP2_FLAG_END_HEADERS, NULL, 0);
786 expect_http2_data_frame(&offset, UPGRADE_STREAM_ID, TEST_STATIC_PAYLOAD,
787 strlen(TEST_STATIC_PAYLOAD),
788 HTTP2_FLAG_END_STREAM);
789 }
790
ZTEST(server_function_tests,test_http1_static_get)791 ZTEST(server_function_tests, test_http1_static_get)
792 {
793 static const char http1_request[] =
794 "GET / HTTP/1.1\r\n"
795 "Host: 127.0.0.1:8080\r\n"
796 "User-Agent: curl/7.68.0\r\n"
797 "Accept: */*\r\n"
798 "Accept-Encoding: deflate, gzip, br\r\n"
799 "\r\n";
800 static const char expected_response[] =
801 "HTTP/1.1 200 OK\r\n"
802 "Content-Type: text/html\r\n"
803 "Content-Length: 13\r\n"
804 "\r\n"
805 TEST_STATIC_PAYLOAD;
806 size_t offset = 0;
807 int ret;
808
809 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
810 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
811
812 memset(buf, 0, sizeof(buf));
813
814 test_read_data(&offset, sizeof(expected_response) - 1);
815 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
816 "Received data doesn't match expected response");
817 }
818
819 /* Common code to verify POST/PUT/PATCH */
common_verify_http2_dynamic_post_request(const uint8_t * request,size_t request_len)820 static void common_verify_http2_dynamic_post_request(const uint8_t *request,
821 size_t request_len)
822 {
823 size_t offset = 0;
824 int ret;
825
826 ret = zsock_send(client_fd, request, request_len, 0);
827 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
828
829 memset(buf, 0, sizeof(buf));
830
831 expect_http2_settings_frame(&offset, false);
832 expect_http2_settings_frame(&offset, true);
833 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
834 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
835
836 zassert_equal(dynamic_payload_len, strlen(TEST_DYNAMIC_POST_PAYLOAD),
837 "Wrong dynamic resource length");
838 zassert_mem_equal(dynamic_payload, TEST_DYNAMIC_POST_PAYLOAD,
839 dynamic_payload_len, "Wrong dynamic resource data");
840 }
841
ZTEST(server_function_tests,test_http2_dynamic_post)842 ZTEST(server_function_tests, test_http2_dynamic_post)
843 {
844 static const uint8_t request_post_dynamic[] = {
845 TEST_HTTP2_MAGIC,
846 TEST_HTTP2_SETTINGS,
847 TEST_HTTP2_SETTINGS_ACK,
848 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1,
849 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1,
850 TEST_HTTP2_GOAWAY,
851 };
852
853 common_verify_http2_dynamic_post_request(request_post_dynamic,
854 sizeof(request_post_dynamic));
855 }
856
857 /* Common code to verify POST/PUT/PATCH */
common_verify_http1_dynamic_upgrade_post(const uint8_t * method)858 static void common_verify_http1_dynamic_upgrade_post(const uint8_t *method)
859 {
860 static const char http1_request[] =
861 " /dynamic HTTP/1.1\r\n"
862 "Host: 127.0.0.1:8080\r\n"
863 "User-Agent: curl/7.68.0\r\n"
864 "Accept: */*\r\n"
865 "Content-Length: 17\r\n"
866 "Connection: Upgrade, HTTP2-Settings\r\n"
867 "Upgrade: h2c\r\n"
868 "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n"
869 "\r\n"
870 TEST_DYNAMIC_POST_PAYLOAD;
871 size_t offset = 0;
872 int ret;
873
874 ret = zsock_send(client_fd, method, strlen(method), 0);
875 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
876
877 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
878 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
879
880 memset(buf, 0, sizeof(buf));
881
882 /* Verify HTTP1 switching protocols response. */
883 expect_http1_switching_protocols(&offset);
884
885 /* Verify HTTP2 frames. */
886 expect_http2_settings_frame(&offset, false);
887 expect_http2_headers_frame(&offset, UPGRADE_STREAM_ID,
888 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
889
890 zassert_equal(dynamic_payload_len, strlen(TEST_DYNAMIC_POST_PAYLOAD),
891 "Wrong dynamic resource length");
892 zassert_mem_equal(dynamic_payload, TEST_DYNAMIC_POST_PAYLOAD,
893 dynamic_payload_len, "Wrong dynamic resource data");
894 }
895
ZTEST(server_function_tests,test_http1_dynamic_upgrade_post)896 ZTEST(server_function_tests, test_http1_dynamic_upgrade_post)
897 {
898 common_verify_http1_dynamic_upgrade_post("POST");
899 }
900
901 /* Common code to verify POST/PUT/PATCH */
common_verify_http1_dynamic_post(const uint8_t * method)902 static void common_verify_http1_dynamic_post(const uint8_t *method)
903 {
904 static const char http1_request[] =
905 " /dynamic HTTP/1.1\r\n"
906 "Host: 127.0.0.1:8080\r\n"
907 "User-Agent: curl/7.68.0\r\n"
908 "Accept: */*\r\n"
909 "Content-Length: 17\r\n"
910 "\r\n"
911 TEST_DYNAMIC_POST_PAYLOAD;
912 static const char expected_response[] = "HTTP/1.1 200\r\n"
913 "Transfer-Encoding: chunked\r\n"
914 "Content-Type: text/plain\r\n"
915 "\r\n"
916 "0\r\n\r\n";
917 size_t offset = 0;
918 int ret;
919
920 ret = zsock_send(client_fd, method, strlen(method), 0);
921 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
922
923 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
924 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
925
926 memset(buf, 0, sizeof(buf));
927
928 test_read_data(&offset, sizeof(expected_response) - 1);
929 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
930 "Received data doesn't match expected response");
931
932 zassert_equal(dynamic_payload_len, strlen(TEST_DYNAMIC_POST_PAYLOAD),
933 "Wrong dynamic resource length");
934 zassert_mem_equal(dynamic_payload, TEST_DYNAMIC_POST_PAYLOAD,
935 dynamic_payload_len, "Wrong dynamic resource data");
936 }
937
ZTEST(server_function_tests,test_http1_dynamic_post)938 ZTEST(server_function_tests, test_http1_dynamic_post)
939 {
940 common_verify_http1_dynamic_post("POST");
941 }
942
common_verify_http2_dynamic_get_request(const uint8_t * request,size_t request_len)943 static void common_verify_http2_dynamic_get_request(const uint8_t *request,
944 size_t request_len)
945 {
946 size_t offset = 0;
947 int ret;
948
949 dynamic_payload_len = strlen(TEST_DYNAMIC_GET_PAYLOAD);
950 memcpy(dynamic_payload, TEST_DYNAMIC_GET_PAYLOAD, dynamic_payload_len);
951
952 ret = zsock_send(client_fd, request, request_len, 0);
953 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
954
955 memset(buf, 0, sizeof(buf));
956
957 expect_http2_settings_frame(&offset, false);
958 expect_http2_settings_frame(&offset, true);
959 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1, HTTP2_FLAG_END_HEADERS, NULL, 0);
960 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, TEST_DYNAMIC_GET_PAYLOAD,
961 strlen(TEST_DYNAMIC_GET_PAYLOAD), HTTP2_FLAG_END_STREAM);
962 }
963
ZTEST(server_function_tests,test_http2_dynamic_get)964 ZTEST(server_function_tests, test_http2_dynamic_get)
965 {
966 static const uint8_t request_get_dynamic[] = {
967 TEST_HTTP2_MAGIC,
968 TEST_HTTP2_SETTINGS,
969 TEST_HTTP2_SETTINGS_ACK,
970 TEST_HTTP2_HEADERS_GET_DYNAMIC_STREAM_1,
971 TEST_HTTP2_GOAWAY,
972 };
973
974 common_verify_http2_dynamic_get_request(request_get_dynamic,
975 sizeof(request_get_dynamic));
976 }
977
ZTEST(server_function_tests,test_http1_dynamic_upgrade_get)978 ZTEST(server_function_tests, test_http1_dynamic_upgrade_get)
979 {
980 static const char http1_request[] =
981 "GET /dynamic HTTP/1.1\r\n"
982 "Host: 127.0.0.1:8080\r\n"
983 "User-Agent: curl/7.68.0\r\n"
984 "Accept: */*\r\n"
985 "Accept-Encoding: deflate, gzip, br\r\n"
986 "Connection: Upgrade, HTTP2-Settings\r\n"
987 "Upgrade: h2c\r\n"
988 "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n"
989 "\r\n";
990 size_t offset = 0;
991 int ret;
992
993 dynamic_payload_len = strlen(TEST_DYNAMIC_GET_PAYLOAD);
994 memcpy(dynamic_payload, TEST_DYNAMIC_GET_PAYLOAD, dynamic_payload_len);
995
996 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
997 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
998
999 memset(buf, 0, sizeof(buf));
1000
1001 /* Verify HTTP1 switching protocols response. */
1002 expect_http1_switching_protocols(&offset);
1003
1004 /* Verify HTTP2 frames. */
1005 expect_http2_settings_frame(&offset, false);
1006 expect_http2_headers_frame(&offset, UPGRADE_STREAM_ID, HTTP2_FLAG_END_HEADERS, NULL, 0);
1007 expect_http2_data_frame(&offset, UPGRADE_STREAM_ID, TEST_DYNAMIC_GET_PAYLOAD,
1008 strlen(TEST_DYNAMIC_GET_PAYLOAD), HTTP2_FLAG_END_STREAM);
1009 }
1010
ZTEST(server_function_tests,test_http1_dynamic_get)1011 ZTEST(server_function_tests, test_http1_dynamic_get)
1012 {
1013 static const char http1_request[] =
1014 "GET /dynamic HTTP/1.1\r\n"
1015 "Host: 127.0.0.1:8080\r\n"
1016 "User-Agent: curl/7.68.0\r\n"
1017 "Accept: */*\r\n"
1018 "Accept-Encoding: deflate, gzip, br\r\n"
1019 "\r\n";
1020 static const char expected_response[] = "HTTP/1.1 200\r\n"
1021 "Transfer-Encoding: chunked\r\n"
1022 "Content-Type: text/plain\r\n"
1023 "\r\n"
1024 "10\r\n" TEST_DYNAMIC_GET_PAYLOAD "\r\n"
1025 "0\r\n\r\n";
1026 size_t offset = 0;
1027 int ret;
1028
1029 dynamic_payload_len = strlen(TEST_DYNAMIC_GET_PAYLOAD);
1030 memcpy(dynamic_payload, TEST_DYNAMIC_GET_PAYLOAD, dynamic_payload_len);
1031
1032 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
1033 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1034
1035 memset(buf, 0, sizeof(buf));
1036
1037 test_read_data(&offset, sizeof(expected_response) - 1);
1038 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
1039 "Received data doesn't match expected response");
1040 }
1041
ZTEST(server_function_tests,test_http2_dynamic_put)1042 ZTEST(server_function_tests, test_http2_dynamic_put)
1043 {
1044 static const uint8_t request_put_dynamic[] = {
1045 TEST_HTTP2_MAGIC,
1046 TEST_HTTP2_SETTINGS,
1047 TEST_HTTP2_SETTINGS_ACK,
1048 TEST_HTTP2_HEADERS_PUT_DYNAMIC_STREAM_1,
1049 TEST_HTTP2_DATA_PUT_DYNAMIC_STREAM_1,
1050 TEST_HTTP2_GOAWAY,
1051 };
1052
1053 common_verify_http2_dynamic_post_request(request_put_dynamic,
1054 sizeof(request_put_dynamic));
1055 }
1056
ZTEST(server_function_tests,test_http1_dynamic_upgrade_put)1057 ZTEST(server_function_tests, test_http1_dynamic_upgrade_put)
1058 {
1059 common_verify_http1_dynamic_upgrade_post("PUT");
1060 }
1061
ZTEST(server_function_tests,test_http1_dynamic_put)1062 ZTEST(server_function_tests, test_http1_dynamic_put)
1063 {
1064 common_verify_http1_dynamic_post("PUT");
1065 }
1066
ZTEST(server_function_tests,test_http2_dynamic_patch)1067 ZTEST(server_function_tests, test_http2_dynamic_patch)
1068 {
1069 static const uint8_t request_patch_dynamic[] = {
1070 TEST_HTTP2_MAGIC,
1071 TEST_HTTP2_SETTINGS,
1072 TEST_HTTP2_SETTINGS_ACK,
1073 TEST_HTTP2_HEADERS_PATCH_DYNAMIC_STREAM_1,
1074 TEST_HTTP2_DATA_PATCH_DYNAMIC_STREAM_1,
1075 TEST_HTTP2_GOAWAY,
1076 };
1077
1078 common_verify_http2_dynamic_post_request(request_patch_dynamic,
1079 sizeof(request_patch_dynamic));
1080 }
1081
ZTEST(server_function_tests,test_http1_dynamic_upgrade_patch)1082 ZTEST(server_function_tests, test_http1_dynamic_upgrade_patch)
1083 {
1084 common_verify_http1_dynamic_upgrade_post("PATCH");
1085 }
1086
ZTEST(server_function_tests,test_http1_dynamic_patch)1087 ZTEST(server_function_tests, test_http1_dynamic_patch)
1088 {
1089 common_verify_http1_dynamic_post("PATCH");
1090 }
1091
ZTEST(server_function_tests,test_http2_dynamic_delete)1092 ZTEST(server_function_tests, test_http2_dynamic_delete)
1093 {
1094 static const uint8_t request_delete_dynamic[] = {
1095 TEST_HTTP2_MAGIC,
1096 TEST_HTTP2_SETTINGS,
1097 TEST_HTTP2_SETTINGS_ACK,
1098 TEST_HTTP2_HEADERS_DELETE_DYNAMIC_STREAM_1,
1099 TEST_HTTP2_GOAWAY,
1100 };
1101 size_t offset = 0;
1102 int ret;
1103
1104 ret = zsock_send(client_fd, request_delete_dynamic,
1105 sizeof(request_delete_dynamic), 0);
1106 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1107
1108 memset(buf, 0, sizeof(buf));
1109
1110 expect_http2_settings_frame(&offset, false);
1111 expect_http2_settings_frame(&offset, true);
1112 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
1113 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM,
1114 NULL, 0);
1115 }
1116
ZTEST(server_function_tests,test_http1_dynamic_upgrade_delete)1117 ZTEST(server_function_tests, test_http1_dynamic_upgrade_delete)
1118 {
1119 static const char http1_request[] =
1120 "DELETE /dynamic HTTP/1.1\r\n"
1121 "Host: 127.0.0.1:8080\r\n"
1122 "User-Agent: curl/7.68.0\r\n"
1123 "Connection: Upgrade, HTTP2-Settings\r\n"
1124 "Upgrade: h2c\r\n"
1125 "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n"
1126 "\r\n";
1127 size_t offset = 0;
1128 int ret;
1129
1130 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
1131 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1132
1133 memset(buf, 0, sizeof(buf));
1134
1135 /* Verify HTTP1 switching protocols response. */
1136 expect_http1_switching_protocols(&offset);
1137
1138 /* Verify HTTP2 frames. */
1139 expect_http2_settings_frame(&offset, false);
1140 expect_http2_headers_frame(&offset, UPGRADE_STREAM_ID,
1141 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM,
1142 NULL, 0);
1143 }
1144
ZTEST(server_function_tests,test_http1_dynamic_delete)1145 ZTEST(server_function_tests, test_http1_dynamic_delete)
1146 {
1147 static const char http1_request[] =
1148 "DELETE /dynamic HTTP/1.1\r\n"
1149 "Host: 127.0.0.1:8080\r\n"
1150 "User-Agent: curl/7.68.0\r\n"
1151 "\r\n";
1152 static const char expected_response[] = "HTTP/1.1 200\r\n"
1153 "Transfer-Encoding: chunked\r\n"
1154 "Content-Type: text/plain\r\n"
1155 "\r\n"
1156 "0\r\n\r\n";
1157 size_t offset = 0;
1158 int ret;
1159
1160 ret = zsock_send(client_fd, http1_request, strlen(http1_request), 0);
1161 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1162
1163 memset(buf, 0, sizeof(buf));
1164
1165 test_read_data(&offset, sizeof(expected_response) - 1);
1166 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
1167 "Received data doesn't match expected response");
1168 }
1169
ZTEST(server_function_tests,test_http1_connection_close)1170 ZTEST(server_function_tests, test_http1_connection_close)
1171 {
1172 static const char http1_request_1[] =
1173 "GET / HTTP/1.1\r\n"
1174 "Host: 127.0.0.1:8080\r\n"
1175 "User-Agent: curl/7.68.0\r\n"
1176 "Accept: */*\r\n"
1177 "Accept-Encoding: deflate, gzip, br\r\n"
1178 "\r\n";
1179 static const char http1_request_2[] =
1180 "GET / HTTP/1.1\r\n"
1181 "Host: 127.0.0.1:8080\r\n"
1182 "User-Agent: curl/7.68.0\r\n"
1183 "Accept: */*\r\n"
1184 "Accept-Encoding: deflate, gzip, br\r\n"
1185 "Connection: close\r\n"
1186 "\r\n";
1187 static const char expected_response[] =
1188 "HTTP/1.1 200 OK\r\n"
1189 "Content-Type: text/html\r\n"
1190 "Content-Length: 13\r\n"
1191 "\r\n"
1192 TEST_STATIC_PAYLOAD;
1193 size_t offset = 0;
1194 int ret;
1195
1196 ret = zsock_send(client_fd, http1_request_1, strlen(http1_request_1), 0);
1197 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1198
1199 memset(buf, 0, sizeof(buf));
1200
1201 test_read_data(&offset, sizeof(expected_response) - 1);
1202 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
1203 "Received data doesn't match expected response");
1204 test_consume_data(&offset, sizeof(expected_response) - 1);
1205
1206 /* With no connection: close, the server shall serve another request on
1207 * the same connection.
1208 */
1209 ret = zsock_send(client_fd, http1_request_2, strlen(http1_request_2), 0);
1210 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1211
1212 memset(buf, 0, sizeof(buf));
1213
1214 test_read_data(&offset, sizeof(expected_response) - 1);
1215 zassert_mem_equal(buf, expected_response, sizeof(expected_response) - 1,
1216 "Received data doesn't match expected response");
1217 test_consume_data(&offset, sizeof(expected_response) - 1);
1218
1219 /* Second request included connection: close, so we should expect the
1220 * connection to be closed now.
1221 */
1222 ret = zsock_recv(client_fd, buf, sizeof(buf), 0);
1223 zassert_equal(ret, 0, "Connection should've been closed");
1224 }
1225
ZTEST(server_function_tests,test_http2_post_data_with_padding)1226 ZTEST(server_function_tests, test_http2_post_data_with_padding)
1227 {
1228 static const uint8_t request_post_dynamic[] = {
1229 TEST_HTTP2_MAGIC,
1230 TEST_HTTP2_SETTINGS,
1231 TEST_HTTP2_SETTINGS_ACK,
1232 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1,
1233 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1_PADDED,
1234 TEST_HTTP2_GOAWAY,
1235 };
1236
1237 common_verify_http2_dynamic_post_request(request_post_dynamic,
1238 sizeof(request_post_dynamic));
1239 }
1240
ZTEST(server_function_tests,test_http2_post_headers_with_priority)1241 ZTEST(server_function_tests, test_http2_post_headers_with_priority)
1242 {
1243 static const uint8_t request_post_dynamic[] = {
1244 TEST_HTTP2_MAGIC,
1245 TEST_HTTP2_SETTINGS,
1246 TEST_HTTP2_SETTINGS_ACK,
1247 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1_PRIORITY,
1248 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1_PADDED,
1249 TEST_HTTP2_GOAWAY,
1250 };
1251
1252 common_verify_http2_dynamic_post_request(request_post_dynamic,
1253 sizeof(request_post_dynamic));
1254 }
1255
ZTEST(server_function_tests,test_http2_post_headers_with_priority_and_padding)1256 ZTEST(server_function_tests, test_http2_post_headers_with_priority_and_padding)
1257 {
1258 static const uint8_t request_post_dynamic[] = {
1259 TEST_HTTP2_MAGIC,
1260 TEST_HTTP2_SETTINGS,
1261 TEST_HTTP2_SETTINGS_ACK,
1262 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1_PRIORITY_PADDED,
1263 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1_PADDED,
1264 TEST_HTTP2_GOAWAY,
1265 };
1266
1267 common_verify_http2_dynamic_post_request(request_post_dynamic,
1268 sizeof(request_post_dynamic));
1269 }
1270
ZTEST(server_function_tests,test_http2_post_headers_with_continuation)1271 ZTEST(server_function_tests, test_http2_post_headers_with_continuation)
1272 {
1273 static const uint8_t request_post_dynamic[] = {
1274 TEST_HTTP2_MAGIC,
1275 TEST_HTTP2_SETTINGS,
1276 TEST_HTTP2_SETTINGS_ACK,
1277 TEST_HTTP2_PARTIAL_HEADERS_POST_DYNAMIC_STREAM_1,
1278 TEST_HTTP2_CONTINUATION_POST_DYNAMIC_STREAM_1,
1279 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1,
1280 TEST_HTTP2_GOAWAY,
1281 };
1282
1283 common_verify_http2_dynamic_post_request(request_post_dynamic,
1284 sizeof(request_post_dynamic));
1285 }
1286
ZTEST(server_function_tests,test_http2_post_missing_continuation)1287 ZTEST(server_function_tests, test_http2_post_missing_continuation)
1288 {
1289 static const uint8_t request_post_dynamic[] = {
1290 TEST_HTTP2_MAGIC,
1291 TEST_HTTP2_SETTINGS,
1292 TEST_HTTP2_SETTINGS_ACK,
1293 TEST_HTTP2_PARTIAL_HEADERS_POST_DYNAMIC_STREAM_1,
1294 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1,
1295 TEST_HTTP2_GOAWAY,
1296 };
1297 size_t offset = 0;
1298 int ret;
1299
1300 memset(buf, 0, sizeof(buf));
1301
1302 ret = zsock_send(client_fd, request_post_dynamic,
1303 sizeof(request_post_dynamic), 0);
1304 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1305
1306 /* Expect settings, but processing headers (and lack of continuation
1307 * frame) should break the stream, and trigger disconnect.
1308 */
1309 expect_http2_settings_frame(&offset, false);
1310 expect_http2_settings_frame(&offset, true);
1311
1312 ret = zsock_recv(client_fd, buf, sizeof(buf), 0);
1313 zassert_equal(ret, 0, "Connection should've been closed");
1314 }
1315
ZTEST(server_function_tests,test_http2_post_trailing_headers)1316 ZTEST(server_function_tests, test_http2_post_trailing_headers)
1317 {
1318 static const uint8_t request_post_dynamic[] = {
1319 TEST_HTTP2_MAGIC,
1320 TEST_HTTP2_SETTINGS,
1321 TEST_HTTP2_SETTINGS_ACK,
1322 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1,
1323 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1_NO_END_STREAM,
1324 TEST_HTTP2_TRAILING_HEADER_STREAM_1,
1325 TEST_HTTP2_GOAWAY,
1326 };
1327 size_t offset = 0;
1328 int ret;
1329
1330 ret = zsock_send(client_fd, request_post_dynamic,
1331 sizeof(request_post_dynamic), 0);
1332 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1333
1334 memset(buf, 0, sizeof(buf));
1335
1336 expect_http2_settings_frame(&offset, false);
1337 expect_http2_settings_frame(&offset, true);
1338 /* In this case order is reversed, data frame had not END_STREAM flag.
1339 * Because of this, reply will only be sent after processing the final
1340 * trailing headers frame, but this will be preceded by window update
1341 * after processing the data frame.
1342 */
1343 expect_http2_window_update_frame(&offset, TEST_STREAM_ID_1);
1344 expect_http2_window_update_frame(&offset, 0);
1345 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
1346 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
1347
1348 zassert_equal(dynamic_payload_len, strlen(TEST_DYNAMIC_POST_PAYLOAD),
1349 "Wrong dynamic resource length");
1350 zassert_mem_equal(dynamic_payload, TEST_DYNAMIC_POST_PAYLOAD,
1351 dynamic_payload_len, "Wrong dynamic resource data");
1352 }
1353
ZTEST(server_function_tests,test_http2_get_headers_with_padding)1354 ZTEST(server_function_tests, test_http2_get_headers_with_padding)
1355 {
1356 static const uint8_t request_get_dynamic[] = {
1357 TEST_HTTP2_MAGIC,
1358 TEST_HTTP2_SETTINGS,
1359 TEST_HTTP2_SETTINGS_ACK,
1360 TEST_HTTP2_HEADERS_GET_DYNAMIC_STREAM_1_PADDED,
1361 TEST_HTTP2_GOAWAY,
1362 };
1363
1364 common_verify_http2_dynamic_get_request(request_get_dynamic,
1365 sizeof(request_get_dynamic));
1366 }
1367
ZTEST(server_function_tests,test_http2_rst_stream)1368 ZTEST(server_function_tests, test_http2_rst_stream)
1369 {
1370 static const uint8_t request_rst_stream[] = {
1371 TEST_HTTP2_MAGIC,
1372 TEST_HTTP2_SETTINGS,
1373 TEST_HTTP2_SETTINGS_ACK,
1374 TEST_HTTP2_HEADERS_POST_DYNAMIC_STREAM_1,
1375 TEST_HTTP2_RST_STREAM_STREAM_1,
1376 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1,
1377 TEST_HTTP2_GOAWAY,
1378 };
1379
1380 size_t offset = 0;
1381 int ret;
1382
1383 memset(buf, 0, sizeof(buf));
1384
1385 ret = zsock_send(client_fd, request_rst_stream,
1386 sizeof(request_rst_stream), 0);
1387 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1388
1389 /* Expect settings, but processing RST_STREAM should close the stream,
1390 * so DATA frame should trigger connection error (closed stream) and
1391 * disconnect.
1392 */
1393 expect_http2_settings_frame(&offset, false);
1394 expect_http2_settings_frame(&offset, true);
1395
1396 ret = zsock_recv(client_fd, buf, sizeof(buf), 0);
1397 zassert_equal(ret, 0, "Connection should've been closed");
1398 }
1399
1400 static const char http1_header_capture_common_response[] = "HTTP/1.1 200\r\n"
1401 "Transfer-Encoding: chunked\r\n"
1402 "Content-Type: text/plain\r\n"
1403 "\r\n"
1404 "0\r\n\r\n";
1405
test_http1_header_capture_common(const char * request)1406 static void test_http1_header_capture_common(const char *request)
1407 {
1408 size_t offset = 0;
1409 int ret;
1410
1411 ret = zsock_send(client_fd, request, strlen(request), 0);
1412 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1413
1414 test_read_data(&offset, sizeof(http1_header_capture_common_response) - 1);
1415 }
1416
ZTEST(server_function_tests,test_http1_header_capture)1417 ZTEST(server_function_tests, test_http1_header_capture)
1418 {
1419 static const char request[] = "GET /header_capture HTTP/1.1\r\n"
1420 "User-Agent: curl/7.68.0\r\n"
1421 "Test-Header: test_value\r\n"
1422 "Accept: */*\r\n"
1423 "Accept-Encoding: deflate, gzip, br\r\n"
1424 "\r\n";
1425 struct http_header *hdrs = request_headers_clone.headers;
1426 int ret;
1427
1428 test_http1_header_capture_common(request);
1429
1430 zassert_equal(request_headers_clone.count, 2,
1431 "Didn't capture the expected number of headers");
1432 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_OK,
1433 "Header capture status was not OK");
1434
1435 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1436 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1437 zassert_not_equal(hdrs[1].name, NULL, "Second header name is NULL");
1438 zassert_not_equal(hdrs[1].value, NULL, "Second header value is NULL");
1439
1440 ret = strcmp(hdrs[0].name, "User-Agent");
1441 zassert_equal(0, ret, "Header strings did not match");
1442 ret = strcmp(hdrs[0].value, "curl/7.68.0");
1443 zassert_equal(0, ret, "Header strings did not match");
1444 ret = strcmp(hdrs[1].name, "Test-Header");
1445 zassert_equal(0, ret, "Header strings did not match");
1446 ret = strcmp(hdrs[1].value, "test_value");
1447 zassert_equal(0, ret, "Header strings did not match");
1448 }
1449
ZTEST(server_function_tests,test_http1_header_too_long)1450 ZTEST(server_function_tests, test_http1_header_too_long)
1451 {
1452 static const char request[] =
1453 "GET /header_capture HTTP/1.1\r\n"
1454 "User-Agent: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n"
1455 "Test-Header: test_value\r\n"
1456 "Accept: */*\r\n"
1457 "Accept-Encoding: deflate, gzip, br\r\n"
1458 "\r\n";
1459 struct http_header *hdrs = request_headers_clone.headers;
1460 int ret;
1461
1462 test_http1_header_capture_common(request);
1463
1464 zassert_equal(request_headers_clone.count, 1,
1465 "Didn't capture the expected number of headers");
1466 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_DROPPED,
1467 "Header capture status was OK, but should not have been");
1468
1469 /* First header too long should not stop second header being captured into first slot */
1470 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1471 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1472
1473 ret = strcmp(hdrs[0].name, "Test-Header");
1474 zassert_equal(0, ret, "Header strings did not match");
1475 ret = strcmp(hdrs[0].value, "test_value");
1476 zassert_equal(0, ret, "Header strings did not match");
1477 }
1478
ZTEST(server_function_tests,test_http1_header_too_many)1479 ZTEST(server_function_tests, test_http1_header_too_many)
1480 {
1481 static const char request[] = "GET /header_capture HTTP/1.1\r\n"
1482 "User-Agent: curl/7.68.0\r\n"
1483 "Test-Header: test_value\r\n"
1484 "Test-Header2: test_value2\r\n"
1485 "Accept: */*\r\n"
1486 "Accept-Encoding: deflate, gzip, br\r\n"
1487 "\r\n";
1488 struct http_header *hdrs = request_headers_clone.headers;
1489 int ret;
1490
1491 test_http1_header_capture_common(request);
1492
1493 zassert_equal(request_headers_clone.count, 2,
1494 "Didn't capture the expected number of headers");
1495 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_DROPPED,
1496 "Header capture status OK, but should not have been");
1497
1498 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1499 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1500 zassert_not_equal(hdrs[1].name, NULL, "Second header name is NULL");
1501 zassert_not_equal(hdrs[1].value, NULL, "Second header value is NULL");
1502
1503 ret = strcmp(hdrs[0].name, "User-Agent");
1504 zassert_equal(0, ret, "Header strings did not match");
1505 ret = strcmp(hdrs[0].value, "curl/7.68.0");
1506 zassert_equal(0, ret, "Header strings did not match");
1507 ret = strcmp(hdrs[1].name, "Test-Header");
1508 zassert_equal(0, ret, "Header strings did not match");
1509 ret = strcmp(hdrs[1].value, "test_value");
1510 zassert_equal(0, ret, "Header strings did not match");
1511 }
1512
common_verify_http2_get_header_capture_request(const uint8_t * request,size_t request_len)1513 static void common_verify_http2_get_header_capture_request(const uint8_t *request,
1514 size_t request_len)
1515 {
1516 size_t offset = 0;
1517 int ret;
1518
1519 dynamic_payload_len = strlen(TEST_DYNAMIC_GET_PAYLOAD);
1520 memcpy(dynamic_payload, TEST_DYNAMIC_GET_PAYLOAD, dynamic_payload_len);
1521
1522 ret = zsock_send(client_fd, request, request_len, 0);
1523 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1524
1525 memset(buf, 0, sizeof(buf));
1526
1527 expect_http2_settings_frame(&offset, false);
1528 expect_http2_settings_frame(&offset, true);
1529 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
1530 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
1531 }
1532
ZTEST(server_function_tests,test_http2_header_capture)1533 ZTEST(server_function_tests, test_http2_header_capture)
1534 {
1535 static const uint8_t request[] = {
1536 TEST_HTTP2_MAGIC,
1537 TEST_HTTP2_SETTINGS,
1538 TEST_HTTP2_SETTINGS_ACK,
1539 TEST_HTTP2_HEADERS_GET_HEADER_CAPTURE1_STREAM_1,
1540 TEST_HTTP2_GOAWAY,
1541 };
1542 struct http_header *hdrs = request_headers_clone.headers;
1543 int ret;
1544
1545 common_verify_http2_get_header_capture_request(request, sizeof(request));
1546
1547 zassert_equal(request_headers_clone.count, 2,
1548 "Didn't capture the expected number of headers");
1549 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_OK,
1550 "Header capture status was not OK");
1551
1552 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1553 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1554 zassert_not_equal(hdrs[1].name, NULL, "Second header name is NULL");
1555 zassert_not_equal(hdrs[1].value, NULL, "Second header value is NULL");
1556
1557 ret = strcmp(hdrs[0].name, "User-Agent");
1558 zassert_equal(0, ret, "Header strings did not match");
1559 ret = strcmp(hdrs[0].value, "curl/7.81.0");
1560 zassert_equal(0, ret, "Header strings did not match");
1561 ret = strcmp(hdrs[1].name, "Test-Header");
1562 zassert_equal(0, ret, "Header strings did not match");
1563 ret = strcmp(hdrs[1].value, "test_value");
1564 zassert_equal(0, ret, "Header strings did not match");
1565 }
1566
ZTEST(server_function_tests,test_http2_header_too_long)1567 ZTEST(server_function_tests, test_http2_header_too_long)
1568 {
1569 static const uint8_t request[] = {
1570 TEST_HTTP2_MAGIC,
1571 TEST_HTTP2_SETTINGS,
1572 TEST_HTTP2_SETTINGS_ACK,
1573 TEST_HTTP2_HEADERS_GET_HEADER_CAPTURE2_STREAM_1,
1574 TEST_HTTP2_GOAWAY,
1575 };
1576 struct http_header *hdrs = request_headers_clone.headers;
1577 int ret;
1578
1579 common_verify_http2_get_header_capture_request(request, sizeof(request));
1580
1581 zassert_equal(request_headers_clone.count, 1,
1582 "Didn't capture the expected number of headers");
1583 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_DROPPED,
1584 "Header capture status was OK, but should not have been");
1585
1586 /* First header too long should not stop second header being captured into first slot */
1587 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1588 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1589
1590 ret = strcmp(hdrs[0].name, "Test-Header");
1591 zassert_equal(0, ret, "Header strings did not match");
1592 ret = strcmp(hdrs[0].value, "test_value");
1593 zassert_equal(0, ret, "Header strings did not match");
1594 }
1595
ZTEST(server_function_tests,test_http2_header_too_many)1596 ZTEST(server_function_tests, test_http2_header_too_many)
1597 {
1598 static const uint8_t request[] = {
1599 TEST_HTTP2_MAGIC,
1600 TEST_HTTP2_SETTINGS,
1601 TEST_HTTP2_SETTINGS_ACK,
1602 TEST_HTTP2_HEADERS_GET_HEADER_CAPTURE3_STREAM_1,
1603 TEST_HTTP2_GOAWAY,
1604 };
1605 struct http_header *hdrs = request_headers_clone.headers;
1606 int ret;
1607
1608 common_verify_http2_get_header_capture_request(request, sizeof(request));
1609
1610 zassert_equal(request_headers_clone.count, 2,
1611 "Didn't capture the expected number of headers");
1612 zassert_equal(request_headers_clone.status, HTTP_HEADER_STATUS_DROPPED,
1613 "Header capture status OK, but should not have been");
1614
1615 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1616 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1617 zassert_not_equal(hdrs[1].name, NULL, "Second header name is NULL");
1618 zassert_not_equal(hdrs[1].value, NULL, "Second header value is NULL");
1619
1620 ret = strcmp(hdrs[0].name, "User-Agent");
1621 zassert_equal(0, ret, "Header strings did not match");
1622 ret = strcmp(hdrs[0].value, "curl/7.81.0");
1623 zassert_equal(0, ret, "Header strings did not match");
1624 ret = strcmp(hdrs[1].name, "Test-Header");
1625 zassert_equal(0, ret, "Header strings did not match");
1626 ret = strcmp(hdrs[1].value, "test_value");
1627 zassert_equal(0, ret, "Header strings did not match");
1628 }
1629
ZTEST(server_function_tests,test_http2_header_concurrent)1630 ZTEST(server_function_tests, test_http2_header_concurrent)
1631 {
1632 /* Two POST requests which are concurrent, ie. headers1, headers2, data1, data2 */
1633 static const uint8_t request[] = {
1634 TEST_HTTP2_MAGIC,
1635 TEST_HTTP2_SETTINGS,
1636 TEST_HTTP2_SETTINGS_ACK,
1637 TEST_HTTP2_HEADERS_POST_HEADER_CAPTURE_WITH_TESTHEADER_STREAM_1,
1638 TEST_HTTP2_HEADERS_POST_HEADER_CAPTURE2_NO_TESTHEADER_STREAM_2,
1639 TEST_HTTP2_DATA_POST_HEADER_CAPTURE_STREAM_1,
1640 TEST_HTTP2_DATA_POST_HEADER_CAPTURE_STREAM_2,
1641 TEST_HTTP2_GOAWAY,
1642 };
1643
1644 struct http_header *hdrs = request_headers_clone.headers;
1645 struct http_header *hdrs2 = request_headers_clone2.headers;
1646 int ret;
1647 size_t offset = 0;
1648
1649 ret = zsock_send(client_fd, request, sizeof(request), 0);
1650 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1651
1652 /* Wait for response on both resources before checking captured headers */
1653 expect_http2_settings_frame(&offset, false);
1654 expect_http2_settings_frame(&offset, true);
1655 expect_http2_headers_frame(&offset, TEST_STREAM_ID_1,
1656 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
1657 expect_http2_window_update_frame(&offset, TEST_STREAM_ID_1);
1658 expect_http2_window_update_frame(&offset, 0);
1659 expect_http2_headers_frame(&offset, TEST_STREAM_ID_2,
1660 HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM, NULL, 0);
1661
1662 /* Headers captured on /header_capture path should have two headers including the
1663 * Test-Header
1664 */
1665 zassert_equal(request_headers_clone.count, 2,
1666 "Didn't capture the expected number of headers");
1667
1668 zassert_not_equal(hdrs[0].name, NULL, "First header name is NULL");
1669 zassert_not_equal(hdrs[0].value, NULL, "First header value is NULL");
1670 zassert_not_equal(hdrs[1].name, NULL, "Second header name is NULL");
1671 zassert_not_equal(hdrs[1].value, NULL, "Second header value is NULL");
1672
1673 ret = strcmp(hdrs[0].name, "User-Agent");
1674 zassert_equal(0, ret, "Header strings did not match");
1675 ret = strcmp(hdrs[0].value, "curl/7.81.0");
1676 zassert_equal(0, ret, "Header strings did not match");
1677 ret = strcmp(hdrs[1].name, "Test-Header");
1678 zassert_equal(0, ret, "Header strings did not match");
1679 ret = strcmp(hdrs[1].value, "test_value");
1680 zassert_equal(0, ret, "Header strings did not match");
1681
1682 /* Headers captured on the /header_capture2 path should have only one header, not including
1683 * the Test-Header
1684 */
1685 zassert_equal(request_headers_clone2.count, 1,
1686 "Didn't capture the expected number of headers");
1687
1688 zassert_not_equal(hdrs2[0].name, NULL, "First header name is NULL");
1689 zassert_not_equal(hdrs2[0].value, NULL, "First header value is NULL");
1690
1691 ret = strcmp(hdrs2[0].name, "User-Agent");
1692 zassert_equal(0, ret, "Header strings did not match");
1693 ret = strcmp(hdrs2[0].value, "curl/7.81.0");
1694 zassert_equal(0, ret, "Header strings did not match");
1695 }
1696
test_http1_dynamic_response_headers(const char * request,const char * expected_response)1697 static void test_http1_dynamic_response_headers(const char *request, const char *expected_response)
1698 {
1699 int ret;
1700 size_t offset = 0;
1701
1702 ret = zsock_send(client_fd, request, strlen(request), 0);
1703 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1704
1705 test_read_data(&offset, strlen(expected_response));
1706 zassert_mem_equal(buf, expected_response, strlen(expected_response));
1707 }
1708
test_http1_dynamic_response_headers_default(const char * expected_response,bool post)1709 static void test_http1_dynamic_response_headers_default(const char *expected_response, bool post)
1710 {
1711 static const char http1_get_response_headers_request[] =
1712 "GET /response_headers HTTP/1.1\r\n"
1713 "Accept: */*\r\n"
1714 "\r\n";
1715 static const char http1_post_response_headers_request[] =
1716 "POST /response_headers HTTP/1.1\r\n"
1717 "Accept: */*\r\n"
1718 "Content-Length: 17\r\n"
1719 "\r\n" TEST_DYNAMIC_POST_PAYLOAD;
1720 const char *request =
1721 post ? http1_post_response_headers_request : http1_get_response_headers_request;
1722
1723 test_http1_dynamic_response_headers(request, expected_response);
1724 }
1725
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)1726 static void test_http2_dynamic_response_headers(const uint8_t *request, size_t request_len,
1727 const struct http_header *expected_headers,
1728 size_t expected_headers_count, bool end_stream,
1729 size_t *offset)
1730 {
1731 int ret;
1732 const uint8_t expected_flags = end_stream ? HTTP2_FLAG_END_HEADERS | HTTP2_FLAG_END_STREAM
1733 : HTTP2_FLAG_END_HEADERS;
1734
1735 ret = zsock_send(client_fd, request, request_len, 0);
1736 zassert_not_equal(ret, -1, "send() failed (%d)", errno);
1737
1738 expect_http2_settings_frame(offset, false);
1739 expect_http2_settings_frame(offset, true);
1740 expect_http2_headers_frame(offset, TEST_STREAM_ID_1, expected_flags, expected_headers,
1741 expected_headers_count);
1742 }
1743
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)1744 static void test_http2_dynamic_response_headers_default(const struct http_header *expected_headers,
1745 size_t expected_headers_count, bool post,
1746 bool end_stream, size_t *offset)
1747 {
1748 const uint8_t http2_get_response_headers_request[] = {
1749 TEST_HTTP2_MAGIC,
1750 TEST_HTTP2_SETTINGS,
1751 TEST_HTTP2_SETTINGS_ACK,
1752 TEST_HTTP2_HEADERS_GET_RESPONSE_HEADERS_STREAM_1,
1753 TEST_HTTP2_GOAWAY,
1754 };
1755 const uint8_t http2_post_response_headers_request[] = {
1756 TEST_HTTP2_MAGIC,
1757 TEST_HTTP2_SETTINGS,
1758 TEST_HTTP2_SETTINGS_ACK,
1759 TEST_HTTP2_HEADERS_POST_RESPONSE_HEADERS_STREAM_1,
1760 TEST_HTTP2_DATA_POST_DYNAMIC_STREAM_1,
1761 TEST_HTTP2_GOAWAY,
1762 };
1763 const uint8_t *request =
1764 post ? http2_post_response_headers_request : http2_get_response_headers_request;
1765 size_t request_len = post ? sizeof(http2_post_response_headers_request)
1766 : sizeof(http2_get_response_headers_request);
1767
1768 test_http2_dynamic_response_headers(request, request_len, expected_headers,
1769 expected_headers_count, end_stream, offset);
1770 }
1771
test_http1_dynamic_response_header_none(bool post)1772 static void test_http1_dynamic_response_header_none(bool post)
1773 {
1774 static const char response[] = "HTTP/1.1 200\r\n"
1775 "Transfer-Encoding: chunked\r\n"
1776 "Content-Type: text/plain\r\n"
1777 "\r\n"
1778 "0\r\n\r\n";
1779
1780 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_NONE;
1781
1782 test_http1_dynamic_response_headers_default(response, post);
1783 }
1784
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_none)1785 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_none)
1786 {
1787 test_http1_dynamic_response_header_none(false);
1788 }
1789
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_none)1790 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_none)
1791 {
1792 test_http1_dynamic_response_header_none(true);
1793 }
1794
test_http2_dynamic_response_header_none(bool post)1795 static void test_http2_dynamic_response_header_none(bool post)
1796 {
1797 size_t offset = 0;
1798 const struct http_header expected_headers[] = {
1799 {.name = ":status", .value = "200"},
1800 {.name = "content-type", .value = "text/plain"},
1801 };
1802
1803 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_NONE;
1804
1805 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
1806 post, true, &offset);
1807 }
1808
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_none)1809 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_none)
1810 {
1811 test_http2_dynamic_response_header_none(false);
1812 }
1813
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_none)1814 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_none)
1815 {
1816 test_http2_dynamic_response_header_none(true);
1817 }
1818
test_http1_dynamic_response_header_422(bool post)1819 static void test_http1_dynamic_response_header_422(bool post)
1820 {
1821 static const char response[] = "HTTP/1.1 422\r\n"
1822 "Transfer-Encoding: chunked\r\n"
1823 "Content-Type: text/plain\r\n"
1824 "\r\n"
1825 "0\r\n\r\n";
1826
1827 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_422;
1828
1829 test_http1_dynamic_response_headers_default(response, post);
1830 }
1831
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_422)1832 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_422)
1833 {
1834 test_http1_dynamic_response_header_422(false);
1835 }
1836
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_422)1837 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_422)
1838 {
1839 test_http1_dynamic_response_header_422(true);
1840 }
1841
test_http2_dynamic_response_header_422(bool post)1842 static void test_http2_dynamic_response_header_422(bool post)
1843 {
1844 size_t offset = 0;
1845 const struct http_header expected_headers[] = {
1846 {.name = ":status", .value = "422"},
1847 {.name = "content-type", .value = "text/plain"},
1848 };
1849
1850 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_422;
1851
1852 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
1853 post, true, &offset);
1854 }
1855
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_422)1856 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_422)
1857 {
1858 test_http2_dynamic_response_header_422(false);
1859 }
1860
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_422)1861 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_422)
1862 {
1863 test_http2_dynamic_response_header_422(true);
1864 }
1865
test_http1_dynamic_response_header_extra(bool post)1866 static void test_http1_dynamic_response_header_extra(bool post)
1867 {
1868 static const char response[] = "HTTP/1.1 200\r\n"
1869 "Transfer-Encoding: chunked\r\n"
1870 "Test-Header: test_data\r\n"
1871 "Content-Type: text/plain\r\n"
1872 "\r\n"
1873 "0\r\n\r\n";
1874
1875 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_EXTRA_HEADER;
1876
1877 test_http1_dynamic_response_headers_default(response, post);
1878 }
1879
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_extra)1880 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_extra)
1881 {
1882 test_http1_dynamic_response_header_extra(false);
1883 }
1884
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_extra)1885 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_extra)
1886 {
1887 test_http1_dynamic_response_header_extra(true);
1888 }
1889
test_http2_dynamic_response_header_extra(bool post)1890 static void test_http2_dynamic_response_header_extra(bool post)
1891 {
1892 size_t offset = 0;
1893 const struct http_header expected_headers[] = {
1894 {.name = ":status", .value = "200"},
1895 {.name = "content-type", .value = "text/plain"},
1896 {.name = "test-header", .value = "test_data"},
1897 };
1898
1899 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_EXTRA_HEADER;
1900
1901 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
1902 post, true, &offset);
1903 }
1904
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_extra)1905 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_extra)
1906 {
1907 test_http2_dynamic_response_header_extra(false);
1908 }
1909
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_extra)1910 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_extra)
1911 {
1912 test_http2_dynamic_response_header_extra(true);
1913 }
1914
test_http1_dynamic_response_header_override(bool post)1915 static void test_http1_dynamic_response_header_override(bool post)
1916 {
1917 static const char response[] = "HTTP/1.1 200\r\n"
1918 "Transfer-Encoding: chunked\r\n"
1919 "Content-Type: application/json\r\n"
1920 "\r\n"
1921 "0\r\n\r\n";
1922
1923 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_OVERRIDE_HEADER;
1924
1925 test_http1_dynamic_response_headers_default(response, post);
1926 }
1927
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_override)1928 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_override)
1929 {
1930 test_http1_dynamic_response_header_override(false);
1931 }
1932
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_override)1933 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_override)
1934 {
1935 test_http1_dynamic_response_header_override(true);
1936 }
1937
test_http2_dynamic_response_header_override(bool post)1938 static void test_http2_dynamic_response_header_override(bool post)
1939 {
1940 size_t offset = 0;
1941 const struct http_header expected_headers[] = {
1942 {.name = ":status", .value = "200"},
1943 {.name = "content-type", .value = "application/json"},
1944 };
1945
1946 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_OVERRIDE_HEADER;
1947
1948 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
1949 post, true, &offset);
1950 }
1951
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_override)1952 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_override)
1953 {
1954 test_http2_dynamic_response_header_override(false);
1955 }
1956
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_override)1957 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_override)
1958 {
1959 test_http2_dynamic_response_header_override(true);
1960 }
1961
test_http1_dynamic_response_header_separate(bool post)1962 static void test_http1_dynamic_response_header_separate(bool post)
1963 {
1964 static const char response[] = "HTTP/1.1 200\r\n"
1965 "Transfer-Encoding: chunked\r\n"
1966 "Test-Header: test_data\r\n"
1967 "Content-Type: text/plain\r\n"
1968 "\r\n"
1969 "10\r\n" TEST_DYNAMIC_GET_PAYLOAD "\r\n"
1970 "0\r\n\r\n";
1971
1972 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_SEPARATE;
1973
1974 test_http1_dynamic_response_headers_default(response, post);
1975 }
1976
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_separate)1977 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_separate)
1978 {
1979 test_http1_dynamic_response_header_separate(false);
1980 }
1981
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_separate)1982 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_separate)
1983 {
1984 test_http1_dynamic_response_header_separate(true);
1985 }
1986
test_http2_dynamic_response_header_separate(bool post)1987 static void test_http2_dynamic_response_header_separate(bool post)
1988 {
1989 size_t offset = 0;
1990 const struct http_header expected_headers[] = {
1991 {.name = ":status", .value = "200"},
1992 {.name = "test-header", .value = "test_data"},
1993 {.name = "content-type", .value = "text/plain"},
1994 };
1995
1996 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_SEPARATE;
1997
1998 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
1999 post, false, &offset);
2000 }
2001
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_separate)2002 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_separate)
2003 {
2004 test_http2_dynamic_response_header_separate(false);
2005 }
2006
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_separate)2007 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_separate)
2008 {
2009 test_http2_dynamic_response_header_separate(true);
2010 }
2011
test_http1_dynamic_response_header_combined(bool post)2012 static void test_http1_dynamic_response_header_combined(bool post)
2013 {
2014 static const char response[] = "HTTP/1.1 200\r\n"
2015 "Transfer-Encoding: chunked\r\n"
2016 "Test-Header: test_data\r\n"
2017 "Content-Type: text/plain\r\n"
2018 "\r\n"
2019 "10\r\n" TEST_DYNAMIC_GET_PAYLOAD "\r\n"
2020 "0\r\n\r\n";
2021
2022 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_COMBINED;
2023
2024 test_http1_dynamic_response_headers_default(response, post);
2025 }
2026
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_combined)2027 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_combined)
2028 {
2029 test_http1_dynamic_response_header_combined(false);
2030 }
2031
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_combined)2032 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_combined)
2033 {
2034 test_http1_dynamic_response_header_combined(true);
2035 }
2036
test_http2_dynamic_response_header_combined(bool post)2037 static void test_http2_dynamic_response_header_combined(bool post)
2038 {
2039 size_t offset = 0;
2040 const struct http_header expected_headers[] = {
2041 {.name = ":status", .value = "200"},
2042 {.name = "test-header", .value = "test_data"},
2043 {.name = "content-type", .value = "text/plain"},
2044 };
2045
2046 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_COMBINED;
2047
2048 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
2049 post, false, &offset);
2050 }
2051
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_combined)2052 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_combined)
2053 {
2054 test_http2_dynamic_response_header_combined(false);
2055 }
2056
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_combined)2057 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_combined)
2058 {
2059 test_http2_dynamic_response_header_combined(true);
2060 }
2061
ZTEST(server_function_tests,test_http1_dynamic_get_response_header_long)2062 ZTEST(server_function_tests, test_http1_dynamic_get_response_header_long)
2063 {
2064 static const char response[] = "HTTP/1.1 200\r\n"
2065 "Transfer-Encoding: chunked\r\n"
2066 "Content-Type: text/plain\r\n"
2067 "\r\n"
2068 "130\r\n" TEST_LONG_PAYLOAD_CHUNK_1 "\r\n"
2069 "d0\r\n" TEST_LONG_PAYLOAD_CHUNK_2 "\r\n"
2070 "0\r\n\r\n";
2071
2072 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG;
2073
2074 test_http1_dynamic_response_headers_default(response, false);
2075 }
2076
ZTEST(server_function_tests,test_http1_dynamic_post_response_header_long)2077 ZTEST(server_function_tests, test_http1_dynamic_post_response_header_long)
2078 {
2079 static const char request[] = "POST /response_headers HTTP/1.1\r\n"
2080 "Accept: */*\r\n"
2081 "Content-Length: 512\r\n"
2082 "\r\n" TEST_LONG_PAYLOAD_CHUNK_1 TEST_LONG_PAYLOAD_CHUNK_2;
2083 static const char response[] = "HTTP/1.1 200\r\n"
2084 "Transfer-Encoding: chunked\r\n"
2085 "Content-Type: text/plain\r\n"
2086 "\r\n"
2087 "0\r\n\r\n";
2088
2089 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG;
2090
2091 test_http1_dynamic_response_headers(request, response);
2092 zassert_mem_equal(dynamic_response_headers_buffer, long_payload, strlen(long_payload));
2093 }
2094
ZTEST(server_function_tests,test_http2_dynamic_get_response_header_long)2095 ZTEST(server_function_tests, test_http2_dynamic_get_response_header_long)
2096 {
2097 size_t offset = 0;
2098 const struct http_header expected_headers[] = {
2099 {.name = ":status", .value = "200"},
2100 {.name = "content-type", .value = "text/plain"},
2101 };
2102
2103 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG;
2104
2105 test_http2_dynamic_response_headers_default(expected_headers, ARRAY_SIZE(expected_headers),
2106 false, false, &offset);
2107 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, TEST_LONG_PAYLOAD_CHUNK_1,
2108 strlen(TEST_LONG_PAYLOAD_CHUNK_1), 0);
2109 expect_http2_data_frame(&offset, TEST_STREAM_ID_1, TEST_LONG_PAYLOAD_CHUNK_2,
2110 strlen(TEST_LONG_PAYLOAD_CHUNK_2), HTTP2_FLAG_END_STREAM);
2111 }
2112
ZTEST(server_function_tests,test_http2_dynamic_post_response_header_long)2113 ZTEST(server_function_tests, test_http2_dynamic_post_response_header_long)
2114 {
2115 size_t offset = 0;
2116 size_t req_offset = 0;
2117
2118 const struct http_header expected_headers[] = {
2119 {.name = ":status", .value = "200"},
2120 {.name = "content-type", .value = "text/plain"},
2121 };
2122
2123 const uint8_t request_part1[] = {
2124 TEST_HTTP2_MAGIC,
2125 TEST_HTTP2_SETTINGS,
2126 TEST_HTTP2_SETTINGS_ACK,
2127 TEST_HTTP2_HEADERS_POST_RESPONSE_HEADERS_STREAM_1,
2128 /* Data frame header */
2129 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, TEST_STREAM_ID_1,
2130 };
2131
2132 const uint8_t request_part3[] = {
2133 TEST_HTTP2_GOAWAY,
2134 };
2135
2136 static uint8_t
2137 request[sizeof(request_part1) + (sizeof(long_payload) - 1) + sizeof(request_part3)];
2138
2139 BUILD_ASSERT(sizeof(long_payload) - 1 == 0x200, "Length field in data frame header must "
2140 "match length of long_payload");
2141
2142 memcpy(request + req_offset, request_part1, sizeof(request_part1));
2143 req_offset += sizeof(request_part1);
2144 memcpy(request + req_offset, long_payload, sizeof(long_payload) - 1);
2145 req_offset += sizeof(long_payload) - 1;
2146 memcpy(request + req_offset, request_part3, sizeof(request_part3));
2147 req_offset += sizeof(request_part3);
2148
2149 dynamic_response_headers_variant = DYNAMIC_RESPONSE_HEADERS_VARIANT_BODY_LONG;
2150
2151 test_http2_dynamic_response_headers(request, req_offset, expected_headers,
2152 ARRAY_SIZE(expected_headers), true, &offset);
2153 zassert_mem_equal(dynamic_response_headers_buffer, long_payload, strlen(long_payload));
2154 }
2155
ZTEST(server_function_tests_no_init,test_http_server_start_stop)2156 ZTEST(server_function_tests_no_init, test_http_server_start_stop)
2157 {
2158 struct sockaddr_in sa = { 0 };
2159 int ret;
2160
2161 sa.sin_family = AF_INET;
2162 sa.sin_port = htons(SERVER_PORT);
2163
2164 ret = zsock_inet_pton(AF_INET, SERVER_IPV4_ADDR, &sa.sin_addr.s_addr);
2165 zassert_equal(1, ret, "inet_pton() failed to convert %s", SERVER_IPV4_ADDR);
2166
2167 zassert_ok(http_server_start(), "Failed to start the server");
2168 zassert_not_ok(http_server_start(), "Server start should report na error.");
2169
2170 zassert_ok(http_server_stop(), "Failed to stop the server");
2171 zassert_not_ok(http_server_stop(), "Server stop should report na error.");
2172
2173 zassert_ok(http_server_start(), "Failed to start the server");
2174
2175 /* Server should be listening now. */
2176 ret = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2177 zassert_not_equal(ret, -1, "failed to create client socket (%d)", errno);
2178 client_fd = ret;
2179
2180 zassert_ok(zsock_connect(client_fd, (struct sockaddr *)&sa, sizeof(sa)),
2181 "failed to connect to the server (%d)", errno);
2182 zassert_ok(zsock_close(client_fd), "close() failed on the client fd (%d)", errno);
2183 client_fd = -1;
2184
2185 /* Check if the server can be restarted again after client connected. */
2186 zassert_ok(http_server_stop(), "Failed to stop the server");
2187 zassert_ok(http_server_start(), "Failed to start the server");
2188
2189 /* Let the server thread run. */
2190 k_msleep(CONFIG_HTTP_SERVER_RESTART_DELAY + 10);
2191
2192 ret = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2193 zassert_not_equal(ret, -1, "failed to create client socket (%d)", errno);
2194 client_fd = ret;
2195
2196 zassert_ok(zsock_connect(client_fd, (struct sockaddr *)&sa, sizeof(sa)),
2197 "failed to connect to the server (%d)", errno);
2198 zassert_ok(zsock_close(client_fd), "close() failed on the client fd (%d)", errno);
2199 client_fd = -1;
2200
2201 zassert_ok(http_server_stop(), "Failed to stop the server");
2202 }
2203
ZTEST(server_function_tests_no_init,test_get_frame_type_name)2204 ZTEST(server_function_tests_no_init, test_get_frame_type_name)
2205 {
2206 zassert_str_equal(get_frame_type_name(HTTP2_DATA_FRAME), "DATA",
2207 "Unexpected frame type");
2208 zassert_str_equal(get_frame_type_name(HTTP2_HEADERS_FRAME),
2209 "HEADERS", "Unexpected frame type");
2210 zassert_str_equal(get_frame_type_name(HTTP2_PRIORITY_FRAME),
2211 "PRIORITY", "Unexpected frame type");
2212 zassert_str_equal(get_frame_type_name(HTTP2_RST_STREAM_FRAME),
2213 "RST_STREAM", "Unexpected frame type");
2214 zassert_str_equal(get_frame_type_name(HTTP2_SETTINGS_FRAME),
2215 "SETTINGS", "Unexpected frame type");
2216 zassert_str_equal(get_frame_type_name(HTTP2_PUSH_PROMISE_FRAME),
2217 "PUSH_PROMISE", "Unexpected frame type");
2218 zassert_str_equal(get_frame_type_name(HTTP2_PING_FRAME), "PING",
2219 "Unexpected frame type");
2220 zassert_str_equal(get_frame_type_name(HTTP2_GOAWAY_FRAME),
2221 "GOAWAY", "Unexpected frame type");
2222 zassert_str_equal(get_frame_type_name(HTTP2_WINDOW_UPDATE_FRAME),
2223 "WINDOW_UPDATE", "Unexpected frame type");
2224 zassert_str_equal(get_frame_type_name(HTTP2_CONTINUATION_FRAME),
2225 "CONTINUATION", "Unexpected frame type");
2226 }
2227
ZTEST(server_function_tests_no_init,test_parse_http_frames)2228 ZTEST(server_function_tests_no_init, test_parse_http_frames)
2229 {
2230 static struct http_client_ctx ctx_client1;
2231 static struct http_client_ctx ctx_client2;
2232 struct http2_frame *frame;
2233
2234 unsigned char buffer1[] = {
2235 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00,
2236 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00,
2237 0x04, 0x00, 0x00, 0xff, 0xff, 0x00
2238 };
2239 unsigned char buffer2[] = {
2240 0x00, 0x00, 0x21, 0x01, 0x05, 0x00, 0x00, 0x00,
2241 0x01, 0x82, 0x84, 0x86, 0x41, 0x8a, 0x0b, 0xe2,
2242 0x5c, 0x0b, 0x89, 0x70, 0xdc, 0x78, 0x0f, 0x03,
2243 0x53, 0x03, 0x2a, 0x2f, 0x2a, 0x90, 0x7a, 0x8a,
2244 0xaa, 0x69, 0xd2, 0x9a, 0xc4, 0xc0, 0x57, 0x68,
2245 0x0b, 0x83
2246 };
2247
2248 memcpy(ctx_client1.buffer, buffer1, sizeof(buffer1));
2249 memcpy(ctx_client2.buffer, buffer2, sizeof(buffer2));
2250
2251 ctx_client1.cursor = ctx_client1.buffer;
2252 ctx_client1.data_len = ARRAY_SIZE(buffer1);
2253
2254 ctx_client2.cursor = ctx_client2.buffer;
2255 ctx_client2.data_len = ARRAY_SIZE(buffer2);
2256
2257 /* Test: Buffer with the first frame */
2258 int parser1 = parse_http_frame_header(&ctx_client1, ctx_client1.cursor,
2259 ctx_client1.data_len);
2260
2261 zassert_equal(parser1, 0, "Failed to parse the first frame");
2262
2263 frame = &ctx_client1.current_frame;
2264
2265 /* Validate frame details for the 1st frame */
2266 zassert_equal(frame->length, 0x0C, "Expected length for the 1st frame doesn't match");
2267 zassert_equal(frame->type, 0x04, "Expected type for the 1st frame doesn't match");
2268 zassert_equal(frame->flags, 0x00, "Expected flags for the 1st frame doesn't match");
2269 zassert_equal(frame->stream_identifier, 0x00,
2270 "Expected stream_identifier for the 1st frame doesn't match");
2271
2272 /* Test: Buffer with the second frame */
2273 int parser2 = parse_http_frame_header(&ctx_client2, ctx_client2.cursor,
2274 ctx_client2.data_len);
2275
2276 zassert_equal(parser2, 0, "Failed to parse the second frame");
2277
2278 frame = &ctx_client2.current_frame;
2279
2280 /* Validate frame details for the 2nd frame */
2281 zassert_equal(frame->length, 0x21, "Expected length for the 2nd frame doesn't match");
2282 zassert_equal(frame->type, 0x01, "Expected type for the 2nd frame doesn't match");
2283 zassert_equal(frame->flags, 0x05, "Expected flags for the 2nd frame doesn't match");
2284 zassert_equal(frame->stream_identifier, 0x01,
2285 "Expected stream_identifier for the 2nd frame doesn't match");
2286 }
2287
http_server_tests_before(void * fixture)2288 static void http_server_tests_before(void *fixture)
2289 {
2290 struct sockaddr_in sa;
2291 struct timeval optval = {
2292 .tv_sec = TIMEOUT_S,
2293 .tv_usec = 0,
2294 };
2295 int ret;
2296
2297 ARG_UNUSED(fixture);
2298
2299 memset(dynamic_payload, 0, sizeof(dynamic_payload));
2300 memset(dynamic_response_headers_buffer, 0, sizeof(dynamic_response_headers_buffer));
2301 memset(&request_headers_clone, 0, sizeof(request_headers_clone));
2302 memset(&request_headers_clone2, 0, sizeof(request_headers_clone2));
2303 dynamic_payload_len = 0;
2304
2305 ret = http_server_start();
2306 if (ret < 0) {
2307 printk("Failed to start the server\n");
2308 return;
2309 }
2310
2311 ret = zsock_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2312 if (ret < 0) {
2313 printk("Failed to create client socket (%d)\n", errno);
2314 return;
2315 }
2316 client_fd = ret;
2317
2318 ret = zsock_setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &optval,
2319 sizeof(optval));
2320 if (ret < 0) {
2321 printk("Failed to set timeout (%d)\n", errno);
2322 return;
2323 }
2324
2325 sa.sin_family = AF_INET;
2326 sa.sin_port = htons(SERVER_PORT);
2327
2328 ret = zsock_inet_pton(AF_INET, SERVER_IPV4_ADDR, &sa.sin_addr.s_addr);
2329 if (ret != 1) {
2330 printk("inet_pton() failed to convert %s\n", SERVER_IPV4_ADDR);
2331 return;
2332 }
2333
2334 ret = zsock_connect(client_fd, (struct sockaddr *)&sa, sizeof(sa));
2335 if (ret < 0) {
2336 printk("Failed to connect (%d)\n", errno);
2337 }
2338 }
2339
http_server_tests_after(void * fixture)2340 static void http_server_tests_after(void *fixture)
2341 {
2342 ARG_UNUSED(fixture);
2343
2344 if (client_fd >= 0) {
2345 (void)zsock_close(client_fd);
2346 client_fd = -1;
2347 }
2348
2349 (void)http_server_stop();
2350 }
2351
2352 ZTEST_SUITE(server_function_tests, NULL, NULL, http_server_tests_before,
2353 http_server_tests_after, NULL);
2354 ZTEST_SUITE(server_function_tests_no_init, NULL, NULL, NULL,
2355 http_server_tests_after, NULL);
2356