/src/fluent-bit/lib/monkey/mk_server/mk_header.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* Monkey HTTP Server |
4 | | * ================== |
5 | | * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> |
6 | | * |
7 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
8 | | * you may not use this file except in compliance with the License. |
9 | | * You may obtain a copy of the License at |
10 | | * |
11 | | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | | * |
13 | | * Unless required by applicable law or agreed to in writing, software |
14 | | * distributed under the License is distributed on an "AS IS" BASIS, |
15 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | | * See the License for the specific language governing permissions and |
17 | | * limitations under the License. |
18 | | */ |
19 | | |
20 | | #include <monkey/monkey.h> |
21 | | #include <monkey/mk_server.h> |
22 | | #include <monkey/mk_header.h> |
23 | | #include <monkey/mk_core.h> |
24 | | #include <monkey/mk_http_status.h> |
25 | | #include <monkey/mk_config.h> |
26 | | #include <monkey/mk_socket.h> |
27 | | #include <monkey/mk_utils.h> |
28 | | #include <monkey/mk_clock.h> |
29 | | #include <monkey/mk_cache.h> |
30 | | #include <monkey/mk_http.h> |
31 | | #include <monkey/mk_vhost.h> |
32 | | #include <monkey/mk_tls.h> |
33 | | |
34 | | #define MK_HEADER_SHORT_DATE "Date: " |
35 | | #define MK_HEADER_SHORT_LOCATION "Location: " |
36 | | #define MK_HEADER_SHORT_CT "Content-Type: " |
37 | | #define MK_HEADER_ACCEPT_RANGES "Accept-Ranges: bytes" MK_CRLF |
38 | | #define MK_HEADER_ALLOWED_METHODS "Allow: " |
39 | | #define MK_HEADER_CONN_KA "Connection: Keep-Alive" MK_CRLF |
40 | | #define MK_HEADER_CONN_CLOSE "Connection: Close" MK_CRLF |
41 | | #define MK_HEADER_CONN_UPGRADE "Connection: Upgrade" MK_CRLF |
42 | | #define MK_HEADER_CONTENT_LENGTH "Content-Length: " |
43 | | #define MK_HEADER_CONTENT_ENCODING "Content-Encoding: " |
44 | | #define MK_HEADER_TE_CHUNKED "Transfer-Encoding: chunked" MK_CRLF |
45 | | #define MK_HEADER_LAST_MODIFIED "Last-Modified: " |
46 | | #define MK_HEADER_UPGRADE_H2C "Upgrade: h2c" MK_CRLF |
47 | | |
48 | | const mk_ptr_t mk_header_short_date = mk_ptr_init(MK_HEADER_SHORT_DATE); |
49 | | const mk_ptr_t mk_header_short_location = mk_ptr_init(MK_HEADER_SHORT_LOCATION); |
50 | | const mk_ptr_t mk_header_short_ct = mk_ptr_init(MK_HEADER_SHORT_CT); |
51 | | const mk_ptr_t mk_header_allow = mk_ptr_init(MK_HEADER_ALLOWED_METHODS); |
52 | | |
53 | | const mk_ptr_t mk_header_conn_ka = mk_ptr_init(MK_HEADER_CONN_KA); |
54 | | const mk_ptr_t mk_header_conn_close = mk_ptr_init(MK_HEADER_CONN_CLOSE); |
55 | | const mk_ptr_t mk_header_conn_upgrade = mk_ptr_init(MK_HEADER_CONN_UPGRADE); |
56 | | const mk_ptr_t mk_header_content_length = mk_ptr_init(MK_HEADER_CONTENT_LENGTH); |
57 | | const mk_ptr_t mk_header_content_encoding = mk_ptr_init(MK_HEADER_CONTENT_ENCODING); |
58 | | const mk_ptr_t mk_header_accept_ranges = mk_ptr_init(MK_HEADER_ACCEPT_RANGES); |
59 | | const mk_ptr_t mk_header_te_chunked = mk_ptr_init(MK_HEADER_TE_CHUNKED); |
60 | | const mk_ptr_t mk_header_last_modified = mk_ptr_init(MK_HEADER_LAST_MODIFIED); |
61 | | const mk_ptr_t mk_header_upgrade_h2c = mk_ptr_init(MK_HEADER_UPGRADE_H2C); |
62 | | |
63 | | #define status_entry(num, str) {num, sizeof(str) - 1, str} |
64 | | |
65 | | static const struct header_status_response status_response[] = { |
66 | | |
67 | | /* |
68 | | * The most used first: |
69 | | * |
70 | | * - HTTP/1.1 200 OK |
71 | | * - HTTP/1.1 404 Not Found |
72 | | */ |
73 | | status_entry(MK_HTTP_OK, MK_RH_HTTP_OK), |
74 | | status_entry(MK_CLIENT_NOT_FOUND, MK_RH_CLIENT_NOT_FOUND), |
75 | | |
76 | | /* Informational */ |
77 | | status_entry(MK_INFO_CONTINUE, MK_RH_INFO_CONTINUE), |
78 | | status_entry(MK_INFO_SWITCH_PROTOCOL, MK_RH_INFO_SWITCH_PROTOCOL), |
79 | | |
80 | | /* Successful */ |
81 | | status_entry(MK_HTTP_CREATED, MK_RH_HTTP_CREATED), |
82 | | status_entry(MK_HTTP_ACCEPTED, MK_RH_HTTP_ACCEPTED), |
83 | | status_entry(MK_HTTP_NON_AUTH_INFO, MK_RH_HTTP_NON_AUTH_INFO), |
84 | | status_entry(MK_HTTP_NOCONTENT, MK_RH_HTTP_NOCONTENT), |
85 | | status_entry(MK_HTTP_RESET, MK_RH_HTTP_RESET), |
86 | | status_entry(MK_HTTP_PARTIAL, MK_RH_HTTP_PARTIAL), |
87 | | |
88 | | /* Redirections */ |
89 | | status_entry(MK_REDIR_MULTIPLE, MK_RH_REDIR_MULTIPLE), |
90 | | status_entry(MK_REDIR_MOVED, MK_RH_REDIR_MOVED), |
91 | | status_entry(MK_REDIR_MOVED_T, MK_RH_REDIR_MOVED_T), |
92 | | status_entry(MK_REDIR_SEE_OTHER, MK_RH_REDIR_SEE_OTHER), |
93 | | status_entry(MK_NOT_MODIFIED, MK_RH_NOT_MODIFIED), |
94 | | status_entry(MK_REDIR_USE_PROXY, MK_RH_REDIR_USE_PROXY), |
95 | | |
96 | | /* Client side errors */ |
97 | | status_entry(MK_CLIENT_BAD_REQUEST, MK_RH_CLIENT_BAD_REQUEST), |
98 | | status_entry(MK_CLIENT_UNAUTH, MK_RH_CLIENT_UNAUTH), |
99 | | status_entry(MK_CLIENT_PAYMENT_REQ, MK_RH_CLIENT_PAYMENT_REQ), |
100 | | status_entry(MK_CLIENT_FORBIDDEN, MK_RH_CLIENT_FORBIDDEN), |
101 | | status_entry(MK_CLIENT_METHOD_NOT_ALLOWED, MK_RH_CLIENT_METHOD_NOT_ALLOWED), |
102 | | status_entry(MK_CLIENT_NOT_ACCEPTABLE, MK_RH_CLIENT_NOT_ACCEPTABLE), |
103 | | status_entry(MK_CLIENT_PROXY_AUTH, MK_RH_CLIENT_PROXY_AUTH), |
104 | | status_entry(MK_CLIENT_REQUEST_TIMEOUT, MK_RH_CLIENT_REQUEST_TIMEOUT), |
105 | | status_entry(MK_CLIENT_CONFLICT, MK_RH_CLIENT_CONFLICT), |
106 | | status_entry(MK_CLIENT_GONE, MK_RH_CLIENT_GONE), |
107 | | status_entry(MK_CLIENT_LENGTH_REQUIRED, MK_RH_CLIENT_LENGTH_REQUIRED), |
108 | | status_entry(MK_CLIENT_PRECOND_FAILED, MK_RH_CLIENT_PRECOND_FAILED), |
109 | | status_entry(MK_CLIENT_REQUEST_ENTITY_TOO_LARGE, |
110 | | MK_RH_CLIENT_REQUEST_ENTITY_TOO_LARGE), |
111 | | status_entry(MK_CLIENT_REQUEST_URI_TOO_LONG, |
112 | | MK_RH_CLIENT_REQUEST_URI_TOO_LONG), |
113 | | status_entry(MK_CLIENT_UNSUPPORTED_MEDIA, MK_RH_CLIENT_UNSUPPORTED_MEDIA), |
114 | | status_entry(MK_CLIENT_REQUESTED_RANGE_NOT_SATISF, |
115 | | MK_RH_CLIENT_REQUESTED_RANGE_NOT_SATISF), |
116 | | |
117 | | /* Server side errors */ |
118 | | status_entry(MK_SERVER_INTERNAL_ERROR, MK_RH_SERVER_INTERNAL_ERROR), |
119 | | status_entry(MK_SERVER_NOT_IMPLEMENTED, MK_RH_SERVER_NOT_IMPLEMENTED), |
120 | | status_entry(MK_SERVER_BAD_GATEWAY, MK_RH_SERVER_BAD_GATEWAY), |
121 | | status_entry(MK_SERVER_SERVICE_UNAV, MK_RH_SERVER_SERVICE_UNAV), |
122 | | status_entry(MK_SERVER_GATEWAY_TIMEOUT, MK_RH_SERVER_GATEWAY_TIMEOUT), |
123 | | status_entry(MK_SERVER_HTTP_VERSION_UNSUP, MK_RH_SERVER_HTTP_VERSION_UNSUP) |
124 | | }; |
125 | | |
126 | | static const int status_response_len = |
127 | | (sizeof(status_response)/(sizeof(status_response[0]))); |
128 | | |
129 | | static void mk_header_cb_finished(struct mk_stream_input *in) |
130 | 0 | { |
131 | 0 | struct mk_iov *iov = in->buffer; |
132 | |
|
133 | 0 | mk_iov_free_marked(iov); |
134 | |
|
135 | | #if defined(__APPLE__) |
136 | | /* |
137 | | * Disable TCP_CORK right away, according to: |
138 | | * |
139 | | * --- |
140 | | * commit 81e8b869d70f9da93ddfbfb17ec7f12ce3c28fc6 |
141 | | * Author: Sonny Karlsson <ksonny@lotrax.org> |
142 | | * Date: Sat Oct 18 12:11:49 2014 +0200 |
143 | | * |
144 | | * http: Remove cork before first call to sendfile(). |
145 | | * |
146 | | * This removes a large delay on Mac OS X when headers and file content |
147 | | * does not fill a single frame. |
148 | | * Deactivating TCP_NOPUSH does not cause pending frames to be sent until |
149 | | * the next write operation. |
150 | | * --- |
151 | | */ |
152 | | |
153 | | mk_server_cork_flag(in->stream->channel->fd, TCP_CORK_OFF); |
154 | | #endif |
155 | 0 | } |
156 | | |
157 | | static void cb_stream_iov_extended_free(struct mk_stream_input *in) |
158 | 0 | { |
159 | 0 | struct mk_iov *iov; |
160 | |
|
161 | 0 | iov = in->buffer; |
162 | 0 | mk_iov_free(iov); |
163 | 0 | } |
164 | | |
165 | | /* Send response headers */ |
166 | | int mk_header_prepare(struct mk_http_session *cs, struct mk_http_request *sr, |
167 | | struct mk_server *server) |
168 | 0 | { |
169 | 0 | int i = 0; |
170 | 0 | unsigned long len = 0; |
171 | 0 | char *buffer = 0; |
172 | 0 | mk_ptr_t response; |
173 | 0 | struct response_headers *sh; |
174 | 0 | struct mk_iov *iov; |
175 | |
|
176 | 0 | sh = &sr->headers; |
177 | 0 | iov = &sh->headers_iov; |
178 | | |
179 | | /* HTTP Status Code */ |
180 | 0 | if (sh->status == MK_CUSTOM_STATUS) { |
181 | 0 | response.data = sh->custom_status.data; |
182 | 0 | response.len = sh->custom_status.len; |
183 | 0 | } |
184 | 0 | else { |
185 | 0 | for (i = 0; i < status_response_len; i++) { |
186 | 0 | if (status_response[i].status == sh->status) { |
187 | 0 | response.data = status_response[i].response; |
188 | 0 | response.len = status_response[i].length; |
189 | 0 | break; |
190 | 0 | } |
191 | 0 | } |
192 | 0 | } |
193 | | |
194 | | /* Invalid status set */ |
195 | 0 | mk_bug(i == status_response_len); |
196 | | |
197 | 0 | mk_iov_add(iov, response.data, response.len, MK_FALSE); |
198 | | |
199 | | /* |
200 | | * Preset headers (mk_clock.c): |
201 | | * |
202 | | * - Server |
203 | | * - Date |
204 | | */ |
205 | 0 | mk_iov_add(iov, |
206 | 0 | server->clock_context->headers_preset.data, |
207 | 0 | server->clock_context->headers_preset.len, |
208 | 0 | MK_FALSE); |
209 | | |
210 | | /* Last-Modified */ |
211 | 0 | if (sh->last_modified > 0) { |
212 | 0 | mk_ptr_t *lm = MK_TLS_GET(mk_tls_cache_header_lm); |
213 | 0 | lm->len = mk_utils_utime2gmt(&lm->data, sh->last_modified); |
214 | |
|
215 | 0 | mk_iov_add(iov, |
216 | 0 | mk_header_last_modified.data, |
217 | 0 | mk_header_last_modified.len, |
218 | 0 | MK_FALSE); |
219 | 0 | mk_iov_add(iov, |
220 | 0 | lm->data, |
221 | 0 | lm->len, |
222 | 0 | MK_FALSE); |
223 | 0 | } |
224 | | |
225 | | /* Connection */ |
226 | 0 | if (sh->connection == 0) { |
227 | 0 | if (cs->close_now == MK_FALSE) { |
228 | 0 | if (sr->connection.len > 0) { |
229 | 0 | if (sr->protocol != MK_HTTP_PROTOCOL_11) { |
230 | 0 | mk_iov_add(iov, |
231 | 0 | mk_header_conn_ka.data, |
232 | 0 | mk_header_conn_ka.len, |
233 | 0 | MK_FALSE); |
234 | 0 | } |
235 | 0 | } |
236 | 0 | } |
237 | 0 | else { |
238 | 0 | mk_iov_add(iov, |
239 | 0 | mk_header_conn_close.data, |
240 | 0 | mk_header_conn_close.len, |
241 | 0 | MK_FALSE); |
242 | 0 | } |
243 | 0 | } |
244 | 0 | else if (sh->connection == MK_HEADER_CONN_UPGRADED) { |
245 | 0 | mk_iov_add(iov, |
246 | 0 | mk_header_conn_upgrade.data, |
247 | 0 | mk_header_conn_upgrade.len, |
248 | 0 | MK_FALSE); |
249 | 0 | } |
250 | | |
251 | | /* Location */ |
252 | 0 | if (sh->location != NULL) { |
253 | 0 | mk_iov_add(iov, |
254 | 0 | mk_header_short_location.data, |
255 | 0 | mk_header_short_location.len, |
256 | 0 | MK_FALSE); |
257 | |
|
258 | 0 | mk_iov_add(iov, |
259 | 0 | sh->location, |
260 | 0 | strlen(sh->location), |
261 | 0 | MK_TRUE); |
262 | 0 | } |
263 | | |
264 | | /* allowed methods */ |
265 | 0 | if (sh->allow_methods.len > 0) { |
266 | 0 | mk_iov_add(iov, |
267 | 0 | mk_header_allow.data, |
268 | 0 | mk_header_allow.len, |
269 | 0 | MK_FALSE); |
270 | 0 | mk_iov_add(iov, |
271 | 0 | sh->allow_methods.data, |
272 | 0 | sh->allow_methods.len, |
273 | 0 | MK_FALSE); |
274 | 0 | } |
275 | | |
276 | | /* Content type */ |
277 | 0 | if (sh->content_type.len > 0) { |
278 | 0 | mk_iov_add(iov, |
279 | 0 | sh->content_type.data, |
280 | 0 | sh->content_type.len, |
281 | 0 | MK_FALSE); |
282 | 0 | } |
283 | | |
284 | | /* |
285 | | * Transfer Encoding: the transfer encoding header is just sent when |
286 | | * the response has some content defined by the HTTP status response |
287 | | */ |
288 | 0 | switch (sh->transfer_encoding) { |
289 | 0 | case MK_HEADER_TE_TYPE_CHUNKED: |
290 | 0 | mk_iov_add(iov, |
291 | 0 | mk_header_te_chunked.data, |
292 | 0 | mk_header_te_chunked.len, |
293 | 0 | MK_FALSE); |
294 | 0 | break; |
295 | 0 | } |
296 | | |
297 | | /* E-Tag */ |
298 | 0 | if (sh->etag_len > 0) { |
299 | 0 | mk_iov_add(iov, sh->etag_buf, sh->etag_len, MK_FALSE); |
300 | 0 | } |
301 | | |
302 | | /* Content-Encoding */ |
303 | 0 | if (sh->content_encoding.len > 0) { |
304 | 0 | mk_iov_add(iov, mk_header_content_encoding.data, |
305 | 0 | mk_header_content_encoding.len, |
306 | 0 | MK_FALSE); |
307 | 0 | mk_iov_add(iov, sh->content_encoding.data, |
308 | 0 | sh->content_encoding.len, |
309 | 0 | MK_FALSE); |
310 | 0 | } |
311 | | |
312 | | /* Content-Length */ |
313 | 0 | if (sh->content_length >= 0 && sh->transfer_encoding != 0) { |
314 | | /* Map content length to MK_POINTER */ |
315 | 0 | mk_ptr_t *cl = MK_TLS_GET(mk_tls_cache_header_cl); |
316 | 0 | mk_string_itop(sh->content_length, cl); |
317 | | |
318 | | /* Set headers */ |
319 | 0 | mk_iov_add(iov, |
320 | 0 | mk_header_content_length.data, |
321 | 0 | mk_header_content_length.len, |
322 | 0 | MK_FALSE); |
323 | 0 | mk_iov_add(iov, |
324 | 0 | cl->data, |
325 | 0 | cl->len, |
326 | 0 | MK_FALSE); |
327 | 0 | } |
328 | |
|
329 | 0 | if ((sh->content_length != 0 && (sh->ranges[0] >= 0 || sh->ranges[1] >= 0)) && |
330 | 0 | server->resume == MK_TRUE) { |
331 | 0 | buffer = 0; |
332 | | |
333 | | /* yyy- */ |
334 | 0 | if (sh->ranges[0] >= 0 && sh->ranges[1] == -1) { |
335 | 0 | mk_string_build(&buffer, |
336 | 0 | &len, |
337 | 0 | "%s bytes %d-%ld/%ld\r\n", |
338 | 0 | RH_CONTENT_RANGE, |
339 | 0 | sh->ranges[0], |
340 | 0 | (sh->real_length - 1), sh->real_length); |
341 | 0 | mk_iov_add(iov, buffer, len, MK_TRUE); |
342 | 0 | } |
343 | | |
344 | | /* yyy-xxx */ |
345 | 0 | if (sh->ranges[0] >= 0 && sh->ranges[1] >= 0) { |
346 | 0 | mk_string_build(&buffer, |
347 | 0 | &len, |
348 | 0 | "%s bytes %d-%d/%ld\r\n", |
349 | 0 | RH_CONTENT_RANGE, |
350 | 0 | sh->ranges[0], sh->ranges[1], sh->real_length); |
351 | |
|
352 | 0 | mk_iov_add(iov, buffer, len, MK_TRUE); |
353 | 0 | } |
354 | | |
355 | | /* -xxx */ |
356 | 0 | if (sh->ranges[0] == -1 && sh->ranges[1] > 0) { |
357 | 0 | mk_string_build(&buffer, |
358 | 0 | &len, |
359 | 0 | "%s bytes %ld-%ld/%ld\r\n", |
360 | 0 | RH_CONTENT_RANGE, |
361 | 0 | (sh->real_length - sh->ranges[1]), |
362 | 0 | (sh->real_length - 1), sh->real_length); |
363 | 0 | mk_iov_add(iov, buffer, len, MK_TRUE); |
364 | 0 | } |
365 | 0 | } |
366 | |
|
367 | 0 | if (sh->upgrade == MK_HEADER_UPGRADED_H2C) { |
368 | 0 | mk_iov_add(iov, mk_header_upgrade_h2c.data, mk_header_upgrade_h2c.len, |
369 | 0 | MK_FALSE); |
370 | 0 | } |
371 | | |
372 | |
|
373 | 0 | if (sh->cgi == SH_NOCGI || sh->breakline == MK_HEADER_BREAKLINE) { |
374 | 0 | if (!sr->headers._extra_rows) { |
375 | 0 | mk_iov_add(iov, mk_iov_crlf.data, mk_iov_crlf.len, |
376 | 0 | MK_FALSE); |
377 | 0 | } |
378 | 0 | else { |
379 | 0 | mk_iov_add(sr->headers._extra_rows, mk_iov_crlf.data, |
380 | 0 | mk_iov_crlf.len, MK_FALSE); |
381 | 0 | } |
382 | 0 | } |
383 | | |
384 | | /* |
385 | | * Configure the Stream to dispatch the headers |
386 | | */ |
387 | | |
388 | | /* Set the IOV input stream */ |
389 | 0 | sr->in_headers.buffer = iov; |
390 | 0 | sr->in_headers.bytes_total = iov->total_len; |
391 | 0 | sr->in_headers.cb_finished = mk_header_cb_finished; |
392 | |
|
393 | 0 | if (sr->headers._extra_rows) { |
394 | | /* Our main sr->stream contains the main headers (header_iov) |
395 | | * and 'may' have already some linked data. If we have some |
396 | | * extra headers rows we need to link this IOV right after |
397 | | * the main header_iov. |
398 | | */ |
399 | 0 | struct mk_stream_input *in = &sr->in_headers_extra; |
400 | 0 | in->type = MK_STREAM_IOV; |
401 | 0 | in->dynamic = MK_FALSE; |
402 | 0 | in->cb_consumed = NULL; |
403 | 0 | in->cb_finished = cb_stream_iov_extended_free; |
404 | 0 | in->stream = &sr->stream; |
405 | 0 | in->buffer = sr->headers._extra_rows; |
406 | 0 | in->bytes_total = sr->headers._extra_rows->total_len; |
407 | |
|
408 | 0 | mk_list_add_after(&sr->in_headers_extra._head, |
409 | 0 | &sr->in_headers._head, |
410 | 0 | &sr->stream.inputs); |
411 | 0 | } |
412 | |
|
413 | 0 | sh->sent = MK_TRUE; |
414 | |
|
415 | 0 | return 0; |
416 | 0 | } |
417 | | |
418 | | void mk_header_set_http_status(struct mk_http_request *sr, int status) |
419 | 0 | { |
420 | 0 | mk_bug(!sr); |
421 | 0 | sr->headers.status = status; |
422 | |
|
423 | 0 | MK_TRACE("Set HTTP status = %i", status); |
424 | 0 | } |
425 | | |
426 | | void mk_header_response_reset(struct response_headers *header) |
427 | 0 | { |
428 | 0 | struct mk_iov *iov; |
429 | |
|
430 | 0 | header->status = -1; |
431 | 0 | header->sent = MK_FALSE; |
432 | 0 | header->ranges[0] = -1; |
433 | 0 | header->ranges[1] = -1; |
434 | 0 | header->content_length = -1; |
435 | 0 | header->connection = 0; |
436 | 0 | header->transfer_encoding = -1; |
437 | 0 | header->last_modified = -1; |
438 | 0 | header->upgrade = -1; |
439 | 0 | header->cgi = SH_NOCGI; |
440 | 0 | mk_ptr_reset(&header->content_type); |
441 | 0 | mk_ptr_reset(&header->content_encoding); |
442 | 0 | header->location = NULL; |
443 | 0 | header->_extra_rows = NULL; |
444 | 0 | header->allow_methods.len = 0; |
445 | | |
446 | | /* Initialize headers IOV */ |
447 | 0 | iov = &header->headers_iov; |
448 | 0 | iov->io = (struct iovec *) &header->__iov_io; |
449 | 0 | iov->buf_to_free = (void *) &header->__iov_buf; |
450 | 0 | mk_iov_init(&header->headers_iov, MK_HEADER_IOV, 0); |
451 | 0 | } |