/src/h2o/fuzz/driver_common.cc
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2021 Fastly, Inc. |
3 | | * |
4 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
5 | | * of this software and associated documentation files (the "Software"), to |
6 | | * deal in the Software without restriction, including without limitation the |
7 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
8 | | * sell copies of the Software, and to permit persons to whom the Software is |
9 | | * furnished to do so, subject to the following conditions: |
10 | | * |
11 | | * The above copyright notice and this permission notice shall be included in |
12 | | * all copies or substantial portions of the Software. |
13 | | * |
14 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
17 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
18 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
19 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
20 | | * IN THE SOFTWARE. |
21 | | */ |
22 | | |
23 | | #define H2O_USE_EPOLL 1 |
24 | | #include "driver_common.h" |
25 | | |
26 | | #include <unistd.h> |
27 | | #include <fcntl.h> |
28 | | #include <stdio.h> |
29 | | |
30 | | /* |
31 | | * Registers a request handler with h2o |
32 | | */ |
33 | | h2o_pathconf_t *register_handler(h2o_hostconf_t *hostconf, const char *path, int (*on_req)(h2o_handler_t *, h2o_req_t *)) |
34 | 1 | { |
35 | 1 | h2o_pathconf_t *pathconf = h2o_config_register_path(hostconf, path, 0); |
36 | 1 | h2o_handler_t *handler = h2o_create_handler(pathconf, sizeof(*handler)); |
37 | 1 | handler->on_req = on_req; |
38 | 1 | return pathconf; |
39 | 1 | } |
40 | | |
41 | | /* |
42 | | * Writes the writer_thread_args at buf to fd |
43 | | */ |
44 | | void write_fully(int fd, char *buf, size_t len, int abort_on_err) |
45 | 13.2k | { |
46 | 13.2k | int done = 0; |
47 | 26.4k | while (len) { |
48 | 13.2k | int ret; |
49 | 13.2k | while ((ret = write(fd, buf + done, len)) == -1 && errno == EINTR) |
50 | 0 | ; |
51 | 13.2k | if (ret <= 0) { |
52 | 64 | if (abort_on_err) |
53 | 0 | abort(); |
54 | 64 | else |
55 | 64 | return; |
56 | 64 | } |
57 | 13.1k | done += ret; |
58 | 13.1k | len -= ret; |
59 | 13.1k | } |
60 | 13.2k | } |
61 | | |
62 | | #define OK_RESP \ |
63 | 4.85k | "HTTP/1.0 200 OK\r\n" \ |
64 | 4.85k | "Connection: Close\r\n\r\nOk" |
65 | 2.42k | #define OK_RESP_LEN (sizeof(OK_RESP) - 1) |
66 | | |
67 | | h2o_barrier_t init_barrier; |
68 | | void *upstream_thread(void *arg) |
69 | 1 | { |
70 | 1 | char *dirname = (char *)arg; |
71 | 1 | char path[PATH_MAX]; |
72 | 1 | char rbuf[1 * 1024 * 1024]; |
73 | 1 | snprintf(path, sizeof(path), "/%s/_.sock", dirname); |
74 | 1 | int sd = socket(AF_UNIX, SOCK_STREAM, 0); |
75 | 1 | if (sd < 0) { |
76 | 0 | abort(); |
77 | 0 | } |
78 | 1 | struct sockaddr_un addr; |
79 | 1 | memset(&addr, 0, sizeof(addr)); |
80 | 1 | addr.sun_family = AF_UNIX; |
81 | 1 | strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); |
82 | 1 | if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { |
83 | 0 | abort(); |
84 | 0 | } |
85 | 1 | if (listen(sd, 100) != 0) { |
86 | 0 | abort(); |
87 | 0 | } |
88 | | |
89 | 1 | h2o_barrier_wait(&init_barrier); |
90 | 2.42k | while (1) { |
91 | 2.42k | struct sockaddr_un caddr; |
92 | 2.42k | socklen_t slen = 0; |
93 | 2.42k | int cfs = accept(sd, (struct sockaddr *)&caddr, &slen); |
94 | 2.42k | if (cfs < 0) { |
95 | 0 | continue; |
96 | 0 | } |
97 | 2.42k | read(cfs, rbuf, sizeof(rbuf)); |
98 | 2.42k | write_fully(cfs, (char *)OK_RESP, OK_RESP_LEN, 0); |
99 | 2.42k | close(cfs); |
100 | 2.42k | } |
101 | 1 | } |
102 | | |
103 | | void register_proxy(h2o_hostconf_t *hostconf, const char *unix_path, h2o_access_log_filehandle_t *logfh) |
104 | 1 | { |
105 | 1 | h2o_url_t upstream; |
106 | 1 | h2o_proxy_config_vars_t proxy_config = {}; |
107 | 1 | h2o_pathconf_t *pathconf; |
108 | 1 | h2o_mem_pool_t pool; |
109 | | |
110 | 1 | h2o_mem_init_pool(&pool); |
111 | | |
112 | | /* Assuming the origin is in the same node and is not super busy, we expect 100ms should be enough for proxy timeout. |
113 | | * Having a large value would explode the total runtime of the fuzzer. */ |
114 | 1 | proxy_config.io_timeout = 100; |
115 | 1 | proxy_config.connect_timeout = proxy_config.io_timeout; |
116 | 1 | proxy_config.first_byte_timeout = proxy_config.io_timeout; |
117 | 1 | proxy_config.max_buffer_size = 1024 * 1024; |
118 | 1 | h2o_url_parse(&pool, unix_path, strlen(unix_path), &upstream); |
119 | 1 | h2o_socketpool_t *sockpool = new h2o_socketpool_t(); |
120 | 1 | h2o_socketpool_target_t *target = h2o_socketpool_create_target(&upstream, NULL); |
121 | 1 | h2o_socketpool_init_specific(sockpool, SIZE_MAX /* FIXME */, &target, 1, NULL); |
122 | 1 | h2o_socketpool_set_timeout(sockpool, 2000); |
123 | 1 | h2o_socketpool_set_ssl_ctx(sockpool, NULL); |
124 | 1 | pathconf = h2o_config_register_path(hostconf, "/reproxy-test", 0); |
125 | 1 | h2o_proxy_register_reverse_proxy(pathconf, &proxy_config, sockpool); |
126 | 1 | if (logfh != NULL) |
127 | 0 | h2o_access_log_register(pathconf, logfh); |
128 | | |
129 | 1 | h2o_mem_clear_pool(&pool); |
130 | 1 | } |