Blame


1 014c66b6 2023-06-25 op /*
2 014c66b6 2023-06-25 op * Copyright (c) 2022 Omar Polo <op@omarpolo.com>
3 014c66b6 2023-06-25 op *
4 014c66b6 2023-06-25 op * Permission to use, copy, modify, and distribute this software for any
5 014c66b6 2023-06-25 op * purpose with or without fee is hereby granted, provided that the above
6 014c66b6 2023-06-25 op * copyright notice and this permission notice appear in all copies.
7 014c66b6 2023-06-25 op *
8 014c66b6 2023-06-25 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 014c66b6 2023-06-25 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 014c66b6 2023-06-25 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 014c66b6 2023-06-25 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 014c66b6 2023-06-25 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 014c66b6 2023-06-25 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 014c66b6 2023-06-25 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 014c66b6 2023-06-25 op */
16 014c66b6 2023-06-25 op
17 014c66b6 2023-06-25 op #include <sys/queue.h>
18 014c66b6 2023-06-25 op #include <sys/tree.h>
19 014c66b6 2023-06-25 op #include <sys/socket.h>
20 014c66b6 2023-06-25 op
21 014c66b6 2023-06-25 op #include <netinet/in.h>
22 014c66b6 2023-06-25 op #include <arpa/inet.h>
23 014c66b6 2023-06-25 op
24 014c66b6 2023-06-25 op #include <errno.h>
25 014c66b6 2023-06-25 op #include <event.h>
26 014c66b6 2023-06-25 op #include <limits.h>
27 014c66b6 2023-06-25 op #include <stdarg.h>
28 014c66b6 2023-06-25 op #include <stdio.h>
29 014c66b6 2023-06-25 op #include <stdlib.h>
30 014c66b6 2023-06-25 op #include <stdint.h>
31 014c66b6 2023-06-25 op #include <string.h>
32 014c66b6 2023-06-25 op #include <unistd.h>
33 014c66b6 2023-06-25 op
34 014c66b6 2023-06-25 op #include "log.h"
35 014c66b6 2023-06-25 op #include "pkg.h"
36 4218a914 2024-01-08 op
37 4218a914 2024-01-08 op #if template
38 014c66b6 2023-06-25 op #include "tmpl.h"
39 4218a914 2024-01-08 op #endif
40 014c66b6 2023-06-25 op
41 014c66b6 2023-06-25 op #define MIN(a, b) ((a) < (b) ? (a) : (b))
42 014c66b6 2023-06-25 op
43 014c66b6 2023-06-25 op struct fcgi_header {
44 014c66b6 2023-06-25 op unsigned char version;
45 014c66b6 2023-06-25 op unsigned char type;
46 014c66b6 2023-06-25 op unsigned char req_id1;
47 014c66b6 2023-06-25 op unsigned char req_id0;
48 014c66b6 2023-06-25 op unsigned char content_len1;
49 014c66b6 2023-06-25 op unsigned char content_len0;
50 014c66b6 2023-06-25 op unsigned char padding;
51 014c66b6 2023-06-25 op unsigned char reserved;
52 014c66b6 2023-06-25 op } __attribute__((packed));
53 014c66b6 2023-06-25 op
54 014c66b6 2023-06-25 op /*
55 014c66b6 2023-06-25 op * number of bytes in a FCGI_HEADER. Future version of the protocol
56 014c66b6 2023-06-25 op * will not reduce this number.
57 014c66b6 2023-06-25 op */
58 014c66b6 2023-06-25 op #define FCGI_HEADER_LEN 8
59 014c66b6 2023-06-25 op
60 014c66b6 2023-06-25 op /*
61 014c66b6 2023-06-25 op * values for the version component
62 014c66b6 2023-06-25 op */
63 014c66b6 2023-06-25 op #define FCGI_VERSION_1 1
64 014c66b6 2023-06-25 op
65 014c66b6 2023-06-25 op /*
66 014c66b6 2023-06-25 op * values for the type component
67 014c66b6 2023-06-25 op */
68 014c66b6 2023-06-25 op #define FCGI_BEGIN_REQUEST 1
69 014c66b6 2023-06-25 op #define FCGI_ABORT_REQUEST 2
70 014c66b6 2023-06-25 op #define FCGI_END_REQUEST 3
71 014c66b6 2023-06-25 op #define FCGI_PARAMS 4
72 014c66b6 2023-06-25 op #define FCGI_STDIN 5
73 014c66b6 2023-06-25 op #define FCGI_STDOUT 6
74 014c66b6 2023-06-25 op #define FCGI_STDERR 7
75 014c66b6 2023-06-25 op #define FCGI_DATA 8
76 014c66b6 2023-06-25 op #define FCGI_GET_VALUES 9
77 014c66b6 2023-06-25 op #define FCGI_GET_VALUES_RESULT 10
78 014c66b6 2023-06-25 op #define FCGI_UNKNOWN_TYPE 11
79 014c66b6 2023-06-25 op #define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)
80 014c66b6 2023-06-25 op
81 014c66b6 2023-06-25 op struct fcgi_begin_req {
82 014c66b6 2023-06-25 op unsigned char role1;
83 014c66b6 2023-06-25 op unsigned char role0;
84 014c66b6 2023-06-25 op unsigned char flags;
85 014c66b6 2023-06-25 op unsigned char reserved[5];
86 014c66b6 2023-06-25 op };
87 014c66b6 2023-06-25 op
88 014c66b6 2023-06-25 op struct fcgi_begin_req_record {
89 014c66b6 2023-06-25 op struct fcgi_header header;
90 014c66b6 2023-06-25 op struct fcgi_begin_req body;
91 014c66b6 2023-06-25 op };
92 014c66b6 2023-06-25 op
93 014c66b6 2023-06-25 op /*
94 014c66b6 2023-06-25 op * mask for flags;
95 014c66b6 2023-06-25 op */
96 014c66b6 2023-06-25 op #define FCGI_KEEP_CONN 1
97 014c66b6 2023-06-25 op
98 014c66b6 2023-06-25 op /*
99 014c66b6 2023-06-25 op * values for the role
100 014c66b6 2023-06-25 op */
101 014c66b6 2023-06-25 op #define FCGI_RESPONDER 1
102 014c66b6 2023-06-25 op #define FCGI_AUTHORIZER 2
103 014c66b6 2023-06-25 op #define FCGI_FILTER 3
104 014c66b6 2023-06-25 op
105 014c66b6 2023-06-25 op struct fcgi_end_req_body {
106 014c66b6 2023-06-25 op unsigned char app_status3;
107 014c66b6 2023-06-25 op unsigned char app_status2;
108 014c66b6 2023-06-25 op unsigned char app_status1;
109 014c66b6 2023-06-25 op unsigned char app_status0;
110 014c66b6 2023-06-25 op unsigned char proto_status;
111 014c66b6 2023-06-25 op unsigned char reserved[3];
112 014c66b6 2023-06-25 op };
113 014c66b6 2023-06-25 op
114 014c66b6 2023-06-25 op /*
115 014c66b6 2023-06-25 op * values for proto_status
116 014c66b6 2023-06-25 op */
117 014c66b6 2023-06-25 op #define FCGI_REQUEST_COMPLETE 0
118 014c66b6 2023-06-25 op #define FCGI_CANT_MPX_CONN 1
119 014c66b6 2023-06-25 op #define FCGI_OVERLOADED 2
120 014c66b6 2023-06-25 op #define FCGI_UNKNOWN_ROLE 3
121 014c66b6 2023-06-25 op
122 014c66b6 2023-06-25 op /*
123 014c66b6 2023-06-25 op * Variable names for FCGI_GET_VALUES / FCGI_GET_VALUES_RESULT
124 014c66b6 2023-06-25 op * records.
125 014c66b6 2023-06-25 op */
126 014c66b6 2023-06-25 op #define FCGI_MAX_CONNS "FCGI_MAX_CONNS"
127 014c66b6 2023-06-25 op #define FCGI_MAX_REQS "FCGI_MAX_REQS"
128 014c66b6 2023-06-25 op #define FCGI_MPXS_CONNS "FCGI_MPXS_CONNS"
129 014c66b6 2023-06-25 op
130 014c66b6 2023-06-25 op #define CAT(f0, f1) ((f0) + ((f1) << 8))
131 014c66b6 2023-06-25 op
132 014c66b6 2023-06-25 op enum {
133 014c66b6 2023-06-25 op FCGI_RECORD_HEADER,
134 014c66b6 2023-06-25 op FCGI_RECORD_BODY,
135 014c66b6 2023-06-25 op };
136 014c66b6 2023-06-25 op
137 014c66b6 2023-06-25 op volatile int fcgi_inflight;
138 014c66b6 2023-06-25 op int32_t fcgi_id;
139 014c66b6 2023-06-25 op
140 014c66b6 2023-06-25 op int accept_reserve(int, struct sockaddr *, socklen_t *, int,
141 014c66b6 2023-06-25 op volatile int *);
142 014c66b6 2023-06-25 op
143 014c66b6 2023-06-25 op static int
144 014c66b6 2023-06-25 op fcgi_send_end_req(struct fcgi *fcgi, int id, int as, int ps)
145 014c66b6 2023-06-25 op {
146 014c66b6 2023-06-25 op struct bufferevent *bev = fcgi->fcg_bev;
147 014c66b6 2023-06-25 op struct fcgi_header hdr;
148 014c66b6 2023-06-25 op struct fcgi_end_req_body end;
149 014c66b6 2023-06-25 op
150 014c66b6 2023-06-25 op memset(&hdr, 0, sizeof(hdr));
151 014c66b6 2023-06-25 op memset(&end, 0, sizeof(end));
152 014c66b6 2023-06-25 op
153 014c66b6 2023-06-25 op hdr.version = FCGI_VERSION_1;
154 014c66b6 2023-06-25 op hdr.type = FCGI_END_REQUEST;
155 014c66b6 2023-06-25 op hdr.req_id0 = (id & 0xFF);
156 014c66b6 2023-06-25 op hdr.req_id1 = (id >> 8);
157 014c66b6 2023-06-25 op hdr.content_len0 = sizeof(end);
158 014c66b6 2023-06-25 op
159 014c66b6 2023-06-25 op end.app_status0 = (unsigned char)as;
160 014c66b6 2023-06-25 op end.proto_status = (unsigned char)ps;
161 014c66b6 2023-06-25 op
162 014c66b6 2023-06-25 op if (bufferevent_write(bev, &hdr, sizeof(hdr)) == -1)
163 014c66b6 2023-06-25 op return (-1);
164 014c66b6 2023-06-25 op if (bufferevent_write(bev, &end, sizeof(end)) == -1)
165 014c66b6 2023-06-25 op return (-1);
166 014c66b6 2023-06-25 op return (0);
167 014c66b6 2023-06-25 op }
168 014c66b6 2023-06-25 op
169 014c66b6 2023-06-25 op static int
170 014c66b6 2023-06-25 op end_request(struct client *clt, int status, int proto_status)
171 014c66b6 2023-06-25 op {
172 014c66b6 2023-06-25 op struct fcgi *fcgi = clt->clt_fcgi;
173 014c66b6 2023-06-25 op int r;
174 014c66b6 2023-06-25 op
175 014c66b6 2023-06-25 op if (clt_flush(clt) == -1)
176 014c66b6 2023-06-25 op return (-1);
177 014c66b6 2023-06-25 op
178 014c66b6 2023-06-25 op r = fcgi_send_end_req(fcgi, clt->clt_id, status,
179 014c66b6 2023-06-25 op proto_status);
180 014c66b6 2023-06-25 op if (r == -1) {
181 014c66b6 2023-06-25 op fcgi_error(fcgi->fcg_bev, EV_WRITE, fcgi);
182 014c66b6 2023-06-25 op return (-1);
183 014c66b6 2023-06-25 op }
184 014c66b6 2023-06-25 op
185 014c66b6 2023-06-25 op SPLAY_REMOVE(client_tree, &fcgi->fcg_clients, clt);
186 014c66b6 2023-06-25 op server_client_free(clt);
187 014c66b6 2023-06-25 op
188 014c66b6 2023-06-25 op if (!fcgi->fcg_keep_conn)
189 014c66b6 2023-06-25 op fcgi->fcg_done = 1;
190 014c66b6 2023-06-25 op
191 014c66b6 2023-06-25 op return (0);
192 014c66b6 2023-06-25 op }
193 014c66b6 2023-06-25 op
194 014c66b6 2023-06-25 op int
195 014c66b6 2023-06-25 op fcgi_end_request(struct client *clt, int status)
196 014c66b6 2023-06-25 op {
197 014c66b6 2023-06-25 op return (end_request(clt, status, FCGI_REQUEST_COMPLETE));
198 014c66b6 2023-06-25 op }
199 014c66b6 2023-06-25 op
200 014c66b6 2023-06-25 op int
201 014c66b6 2023-06-25 op fcgi_abort_request(struct client *clt)
202 014c66b6 2023-06-25 op {
203 014c66b6 2023-06-25 op return (end_request(clt, 1, FCGI_OVERLOADED));
204 014c66b6 2023-06-25 op }
205 014c66b6 2023-06-25 op
206 014c66b6 2023-06-25 op static void
207 014c66b6 2023-06-25 op fcgi_inflight_dec(const char *why)
208 014c66b6 2023-06-25 op {
209 014c66b6 2023-06-25 op fcgi_inflight--;
210 014c66b6 2023-06-25 op log_debug("%s: fcgi inflight decremented, now %d, %s",
211 014c66b6 2023-06-25 op __func__, fcgi_inflight, why);
212 014c66b6 2023-06-25 op }
213 014c66b6 2023-06-25 op
214 014c66b6 2023-06-25 op void
215 014c66b6 2023-06-25 op fcgi_accept(int fd, short event, void *arg)
216 014c66b6 2023-06-25 op {
217 014c66b6 2023-06-25 op struct env *env = arg;
218 014c66b6 2023-06-25 op struct fcgi *fcgi = NULL;
219 014c66b6 2023-06-25 op socklen_t slen;
220 014c66b6 2023-06-25 op struct sockaddr_storage ss;
221 014c66b6 2023-06-25 op int s = -1;
222 014c66b6 2023-06-25 op
223 014c66b6 2023-06-25 op event_add(&env->env_pausev, NULL);
224 014c66b6 2023-06-25 op if ((event & EV_TIMEOUT))
225 014c66b6 2023-06-25 op return;
226 014c66b6 2023-06-25 op
227 014c66b6 2023-06-25 op slen = sizeof(ss);
228 014c66b6 2023-06-25 op if ((s = accept_reserve(env->env_sockfd, (struct sockaddr *)&ss,
229 014c66b6 2023-06-25 op &slen, FD_RESERVE, &fcgi_inflight)) == -1) {
230 014c66b6 2023-06-25 op /*
231 014c66b6 2023-06-25 op * Pause accept if we are out of file descriptors, or
232 014c66b6 2023-06-25 op * libevent will haunt us here too.
233 014c66b6 2023-06-25 op */
234 014c66b6 2023-06-25 op if (errno == ENFILE || errno == EMFILE) {
235 014c66b6 2023-06-25 op struct timeval evtpause = { 1, 0 };
236 014c66b6 2023-06-25 op
237 014c66b6 2023-06-25 op event_del(&env->env_sockev);
238 014c66b6 2023-06-25 op evtimer_add(&env->env_pausev, &evtpause);
239 014c66b6 2023-06-25 op log_debug("%s: deferring connections", __func__);
240 014c66b6 2023-06-25 op }
241 014c66b6 2023-06-25 op return;
242 014c66b6 2023-06-25 op }
243 014c66b6 2023-06-25 op
244 014c66b6 2023-06-25 op if ((fcgi = calloc(1, sizeof(*fcgi))) == NULL)
245 014c66b6 2023-06-25 op goto err;
246 014c66b6 2023-06-25 op
247 014c66b6 2023-06-25 op fcgi->fcg_id = ++fcgi_id;
248 014c66b6 2023-06-25 op fcgi->fcg_s = s;
249 014c66b6 2023-06-25 op fcgi->fcg_env = env;
250 014c66b6 2023-06-25 op fcgi->fcg_want = FCGI_RECORD_HEADER;
251 014c66b6 2023-06-25 op fcgi->fcg_toread = sizeof(struct fcgi_header);
252 014c66b6 2023-06-25 op SPLAY_INIT(&fcgi->fcg_clients);
253 014c66b6 2023-06-25 op
254 014c66b6 2023-06-25 op /* assume it's enabled until we get a FCGI_BEGIN_REQUEST */
255 014c66b6 2023-06-25 op fcgi->fcg_keep_conn = 1;
256 014c66b6 2023-06-25 op
257 014c66b6 2023-06-25 op fcgi->fcg_bev = bufferevent_new(fcgi->fcg_s, fcgi_read, fcgi_write,
258 014c66b6 2023-06-25 op fcgi_error, fcgi);
259 014c66b6 2023-06-25 op if (fcgi->fcg_bev == NULL)
260 014c66b6 2023-06-25 op goto err;
261 014c66b6 2023-06-25 op
262 014c66b6 2023-06-25 op bufferevent_enable(fcgi->fcg_bev, EV_READ | EV_WRITE);
263 014c66b6 2023-06-25 op return;
264 014c66b6 2023-06-25 op
265 014c66b6 2023-06-25 op err:
266 014c66b6 2023-06-25 op if (s != -1) {
267 014c66b6 2023-06-25 op close(s);
268 014c66b6 2023-06-25 op free(fcgi);
269 014c66b6 2023-06-25 op fcgi_inflight_dec(__func__);
270 014c66b6 2023-06-25 op }
271 014c66b6 2023-06-25 op }
272 014c66b6 2023-06-25 op
273 014c66b6 2023-06-25 op static int
274 014c66b6 2023-06-25 op parse_len(struct fcgi *fcgi, struct evbuffer *src)
275 014c66b6 2023-06-25 op {
276 014c66b6 2023-06-25 op unsigned char c, x[3];
277 014c66b6 2023-06-25 op
278 014c66b6 2023-06-25 op fcgi->fcg_toread--;
279 014c66b6 2023-06-25 op evbuffer_remove(src, &c, 1);
280 014c66b6 2023-06-25 op if (c >> 7 == 0)
281 014c66b6 2023-06-25 op return (c);
282 014c66b6 2023-06-25 op
283 014c66b6 2023-06-25 op if (fcgi->fcg_toread < 3)
284 014c66b6 2023-06-25 op return (-1);
285 014c66b6 2023-06-25 op
286 014c66b6 2023-06-25 op fcgi->fcg_toread -= 3;
287 014c66b6 2023-06-25 op evbuffer_remove(src, x, sizeof(x));
288 014c66b6 2023-06-25 op return (((c & 0x7F) << 24) | (x[0] << 16) | (x[1] << 8) | x[2]);
289 014c66b6 2023-06-25 op }
290 014c66b6 2023-06-25 op
291 014c66b6 2023-06-25 op static int
292 014c66b6 2023-06-25 op fcgi_parse_params(struct fcgi *fcgi, struct evbuffer *src, struct client *clt)
293 014c66b6 2023-06-25 op {
294 014c66b6 2023-06-25 op char pname[32];
295 014c66b6 2023-06-25 op char server[HOST_NAME_MAX + 1];
296 014c66b6 2023-06-25 op char path[PATH_MAX];
297 014c66b6 2023-06-25 op char query[GEMINI_MAXLEN];
298 014c66b6 2023-06-25 op char method[8];
299 014c66b6 2023-06-25 op int nlen, vlen;
300 014c66b6 2023-06-25 op
301 014c66b6 2023-06-25 op while (fcgi->fcg_toread > 0) {
302 014c66b6 2023-06-25 op if ((nlen = parse_len(fcgi, src)) < 0 ||
303 014c66b6 2023-06-25 op (vlen = parse_len(fcgi, src)) < 0)
304 014c66b6 2023-06-25 op return (-1);
305 014c66b6 2023-06-25 op
306 014c66b6 2023-06-25 op if (fcgi->fcg_toread < nlen + vlen)
307 014c66b6 2023-06-25 op return (-1);
308 014c66b6 2023-06-25 op
309 014c66b6 2023-06-25 op if ((size_t)nlen > sizeof(pname) - 1) {
310 014c66b6 2023-06-25 op /* ignore this parameter */
311 014c66b6 2023-06-25 op fcgi->fcg_toread -= nlen - vlen;
312 014c66b6 2023-06-25 op evbuffer_drain(src, nlen + vlen);
313 014c66b6 2023-06-25 op continue;
314 014c66b6 2023-06-25 op }
315 014c66b6 2023-06-25 op
316 014c66b6 2023-06-25 op fcgi->fcg_toread -= nlen;
317 014c66b6 2023-06-25 op evbuffer_remove(src, &pname, nlen);
318 014c66b6 2023-06-25 op pname[nlen] = '\0';
319 014c66b6 2023-06-25 op
320 014c66b6 2023-06-25 op if (!strcmp(pname, "SERVER_NAME") &&
321 014c66b6 2023-06-25 op (size_t)vlen < sizeof(server)) {
322 014c66b6 2023-06-25 op fcgi->fcg_toread -= vlen;
323 014c66b6 2023-06-25 op evbuffer_remove(src, &server, vlen);
324 014c66b6 2023-06-25 op server[vlen] = '\0';
325 014c66b6 2023-06-25 op
326 014c66b6 2023-06-25 op free(clt->clt_server_name);
327 014c66b6 2023-06-25 op if ((clt->clt_server_name = strdup(server)) == NULL)
328 014c66b6 2023-06-25 op return (-1);
329 014c66b6 2023-06-25 op DPRINTF("clt %d: server_name: %s", clt->clt_id,
330 014c66b6 2023-06-25 op clt->clt_server_name);
331 014c66b6 2023-06-25 op continue;
332 014c66b6 2023-06-25 op }
333 014c66b6 2023-06-25 op
334 014c66b6 2023-06-25 op if (!strcmp(pname, "SCRIPT_NAME") &&
335 014c66b6 2023-06-25 op (size_t)vlen < sizeof(path)) {
336 014c66b6 2023-06-25 op fcgi->fcg_toread -= vlen;
337 014c66b6 2023-06-25 op evbuffer_remove(src, &path, vlen);
338 014c66b6 2023-06-25 op path[vlen] = '\0';
339 014c66b6 2023-06-25 op
340 014c66b6 2023-06-25 op free(clt->clt_script_name);
341 dd58c961 2023-08-08 op clt->clt_script_name = strdup(path);
342 014c66b6 2023-06-25 op if (clt->clt_script_name == NULL)
343 014c66b6 2023-06-25 op return (-1);
344 014c66b6 2023-06-25 op
345 014c66b6 2023-06-25 op DPRINTF("clt %d: script_name: %s", clt->clt_id,
346 014c66b6 2023-06-25 op clt->clt_script_name);
347 014c66b6 2023-06-25 op continue;
348 014c66b6 2023-06-25 op }
349 014c66b6 2023-06-25 op
350 505e5764 2023-08-08 op if (!strcmp(pname, "PATH_INFO") &&
351 014c66b6 2023-06-25 op (size_t)vlen < sizeof(path)) {
352 014c66b6 2023-06-25 op fcgi->fcg_toread -= vlen;
353 014c66b6 2023-06-25 op evbuffer_remove(src, &path, vlen);
354 014c66b6 2023-06-25 op path[vlen] = '\0';
355 014c66b6 2023-06-25 op
356 014c66b6 2023-06-25 op free(clt->clt_path_info);
357 dd58c961 2023-08-08 op clt->clt_path_info = strdup(path);
358 014c66b6 2023-06-25 op if (clt->clt_path_info == NULL)
359 014c66b6 2023-06-25 op return (-1);
360 014c66b6 2023-06-25 op
361 014c66b6 2023-06-25 op DPRINTF("clt %d: path_info: %s", clt->clt_id,
362 014c66b6 2023-06-25 op clt->clt_path_info);
363 014c66b6 2023-06-25 op continue;
364 014c66b6 2023-06-25 op }
365 014c66b6 2023-06-25 op
366 014c66b6 2023-06-25 op if (!strcmp(pname, "QUERY_STRING") &&
367 014c66b6 2023-06-25 op (size_t)vlen < sizeof(query) &&
368 014c66b6 2023-06-25 op vlen > 0) {
369 014c66b6 2023-06-25 op fcgi->fcg_toread -= vlen;
370 014c66b6 2023-06-25 op evbuffer_remove(src, &query, vlen);
371 014c66b6 2023-06-25 op query[vlen] = '\0';
372 014c66b6 2023-06-25 op
373 014c66b6 2023-06-25 op free(clt->clt_query);
374 014c66b6 2023-06-25 op if ((clt->clt_query = strdup(query)) == NULL)
375 014c66b6 2023-06-25 op return (-1);
376 014c66b6 2023-06-25 op
377 014c66b6 2023-06-25 op DPRINTF("clt %d: query: %s", clt->clt_id,
378 014c66b6 2023-06-25 op clt->clt_query);
379 014c66b6 2023-06-25 op continue;
380 014c66b6 2023-06-25 op }
381 014c66b6 2023-06-25 op
382 014c66b6 2023-06-25 op if (!strcmp(pname, "REQUEST_METHOD") &&
383 014c66b6 2023-06-25 op (size_t)vlen < sizeof(method)) {
384 014c66b6 2023-06-25 op fcgi->fcg_toread -= vlen;
385 014c66b6 2023-06-25 op evbuffer_remove(src, &method, vlen);
386 014c66b6 2023-06-25 op method[vlen] = '\0';
387 014c66b6 2023-06-25 op
388 014c66b6 2023-06-25 op if (!strcasecmp(method, "GET"))
389 014c66b6 2023-06-25 op clt->clt_method = METHOD_GET;
390 014c66b6 2023-06-25 op if (!strcasecmp(method, "POST"))
391 014c66b6 2023-06-25 op clt->clt_method = METHOD_POST;
392 014c66b6 2023-06-25 op
393 014c66b6 2023-06-25 op continue;
394 014c66b6 2023-06-25 op }
395 014c66b6 2023-06-25 op
396 014c66b6 2023-06-25 op fcgi->fcg_toread -= vlen;
397 014c66b6 2023-06-25 op evbuffer_drain(src, vlen);
398 014c66b6 2023-06-25 op }
399 014c66b6 2023-06-25 op
400 014c66b6 2023-06-25 op return (0);
401 014c66b6 2023-06-25 op }
402 014c66b6 2023-06-25 op
403 014c66b6 2023-06-25 op void
404 014c66b6 2023-06-25 op fcgi_read(struct bufferevent *bev, void *d)
405 014c66b6 2023-06-25 op {
406 014c66b6 2023-06-25 op struct fcgi *fcgi = d;
407 014c66b6 2023-06-25 op struct env *env = fcgi->fcg_env;
408 014c66b6 2023-06-25 op struct evbuffer *src = EVBUFFER_INPUT(bev);
409 014c66b6 2023-06-25 op struct fcgi_header hdr;
410 014c66b6 2023-06-25 op struct fcgi_begin_req breq;
411 014c66b6 2023-06-25 op struct client *clt, q;
412 014c66b6 2023-06-25 op int role;
413 014c66b6 2023-06-25 op
414 014c66b6 2023-06-25 op memset(&q, 0, sizeof(q));
415 014c66b6 2023-06-25 op
416 014c66b6 2023-06-25 op for (;;) {
417 014c66b6 2023-06-25 op if (EVBUFFER_LENGTH(src) < (size_t)fcgi->fcg_toread)
418 014c66b6 2023-06-25 op return;
419 014c66b6 2023-06-25 op
420 014c66b6 2023-06-25 op if (fcgi->fcg_want == FCGI_RECORD_HEADER) {
421 014c66b6 2023-06-25 op fcgi->fcg_want = FCGI_RECORD_BODY;
422 014c66b6 2023-06-25 op bufferevent_read(bev, &hdr, sizeof(hdr));
423 014c66b6 2023-06-25 op
424 014c66b6 2023-06-25 op DPRINTF("header: v=%d t=%d id=%d len=%d p=%d",
425 014c66b6 2023-06-25 op hdr.version, hdr.type,
426 014c66b6 2023-06-25 op CAT(hdr.req_id0, hdr.req_id1),
427 014c66b6 2023-06-25 op CAT(hdr.content_len0, hdr.content_len1),
428 014c66b6 2023-06-25 op hdr.padding);
429 014c66b6 2023-06-25 op
430 014c66b6 2023-06-25 op if (hdr.version != FCGI_VERSION_1) {
431 014c66b6 2023-06-25 op log_warnx("unknown fastcgi version: %d",
432 014c66b6 2023-06-25 op hdr.version);
433 014c66b6 2023-06-25 op fcgi_error(bev, EV_READ, d);
434 014c66b6 2023-06-25 op return;
435 014c66b6 2023-06-25 op }
436 014c66b6 2023-06-25 op
437 014c66b6 2023-06-25 op fcgi->fcg_toread = CAT(hdr.content_len0,
438 014c66b6 2023-06-25 op hdr.content_len1);
439 014c66b6 2023-06-25 op if (fcgi->fcg_toread < 0) {
440 014c66b6 2023-06-25 op log_warnx("invalid record length: %d",
441 014c66b6 2023-06-25 op fcgi->fcg_toread);
442 014c66b6 2023-06-25 op fcgi_error(bev, EV_READ, d);
443 014c66b6 2023-06-25 op return;
444 014c66b6 2023-06-25 op }
445 014c66b6 2023-06-25 op
446 014c66b6 2023-06-25 op fcgi->fcg_padding = hdr.padding;
447 014c66b6 2023-06-25 op if (fcgi->fcg_padding < 0) {
448 014c66b6 2023-06-25 op log_warnx("invalid padding: %d",
449 014c66b6 2023-06-25 op fcgi->fcg_padding);
450 014c66b6 2023-06-25 op fcgi_error(bev, EV_READ, d);
451 014c66b6 2023-06-25 op return;
452 014c66b6 2023-06-25 op }
453 014c66b6 2023-06-25 op
454 014c66b6 2023-06-25 op fcgi->fcg_type = hdr.type;
455 014c66b6 2023-06-25 op fcgi->fcg_rec_id = CAT(hdr.req_id0, hdr.req_id1);
456 014c66b6 2023-06-25 op continue;
457 014c66b6 2023-06-25 op }
458 014c66b6 2023-06-25 op
459 014c66b6 2023-06-25 op q.clt_id = fcgi->fcg_rec_id;
460 014c66b6 2023-06-25 op clt = SPLAY_FIND(client_tree, &fcgi->fcg_clients, &q);
461 014c66b6 2023-06-25 op
462 014c66b6 2023-06-25 op switch (fcgi->fcg_type) {
463 014c66b6 2023-06-25 op case FCGI_BEGIN_REQUEST:
464 014c66b6 2023-06-25 op if (sizeof(breq) != fcgi->fcg_toread) {
465 014c66b6 2023-06-25 op log_warnx("unexpected size for "
466 014c66b6 2023-06-25 op "FCGI_BEGIN_REQUEST");
467 014c66b6 2023-06-25 op fcgi_error(bev, EV_READ, d);
468 014c66b6 2023-06-25 op return;
469 014c66b6 2023-06-25 op }
470 014c66b6 2023-06-25 op
471 014c66b6 2023-06-25 op evbuffer_remove(src, &breq, sizeof(breq));
472 014c66b6 2023-06-25 op
473 014c66b6 2023-06-25 op role = CAT(breq.role0, breq.role1);
474 014c66b6 2023-06-25 op if (role != FCGI_RESPONDER) {
475 014c66b6 2023-06-25 op log_warnx("unknown fastcgi role: %d",
476 014c66b6 2023-06-25 op role);
477 014c66b6 2023-06-25 op if (fcgi_send_end_req(fcgi, fcgi->fcg_rec_id,
478 014c66b6 2023-06-25 op 1, FCGI_UNKNOWN_ROLE) == -1) {
479 014c66b6 2023-06-25 op fcgi_error(bev, EV_READ, d);
480 014c66b6 2023-06-25 op return;
481 014c66b6 2023-06-25 op }
482 014c66b6 2023-06-25 op break;
483 014c66b6 2023-06-25 op }
484 014c66b6 2023-06-25 op
485 014c66b6 2023-06-25 op if (!fcgi->fcg_keep_conn) {
486 014c66b6 2023-06-25 op log_warnx("trying to reuse the fastcgi "
487 014c66b6 2023-06-25 op "socket without marking it as so.");
488 014c66b6 2023-06-25 op fcgi_error(bev, EV_READ, d);
489 014c66b6 2023-06-25 op return;
490 014c66b6 2023-06-25 op }
491 014c66b6 2023-06-25 op fcgi->fcg_keep_conn = breq.flags & FCGI_KEEP_CONN;
492 014c66b6 2023-06-25 op
493 014c66b6 2023-06-25 op if (clt != NULL) {
494 014c66b6 2023-06-25 op log_warnx("ignoring attemp to re-use an "
495 014c66b6 2023-06-25 op "active request id (%d)",
496 014c66b6 2023-06-25 op fcgi->fcg_rec_id);
497 014c66b6 2023-06-25 op break;
498 014c66b6 2023-06-25 op }
499 014c66b6 2023-06-25 op
500 014c66b6 2023-06-25 op if ((clt = calloc(1, sizeof(*clt))) == NULL) {
501 014c66b6 2023-06-25 op log_warnx("calloc");
502 014c66b6 2023-06-25 op break;
503 014c66b6 2023-06-25 op }
504 014c66b6 2023-06-25 op
505 014c66b6 2023-06-25 op #if template
506 014c66b6 2023-06-25 op clt->clt_tp = template(clt, clt_tp_puts, clt_tp_putc);
507 014c66b6 2023-06-25 op if (clt->clt_tp == NULL) {
508 014c66b6 2023-06-25 op free(clt);
509 014c66b6 2023-06-25 op log_warn("template");
510 014c66b6 2023-06-25 op break;
511 014c66b6 2023-06-25 op }
512 014c66b6 2023-06-25 op #endif
513 014c66b6 2023-06-25 op
514 014c66b6 2023-06-25 op clt->clt_id = fcgi->fcg_rec_id;
515 014c66b6 2023-06-25 op clt->clt_fd = -1;
516 014c66b6 2023-06-25 op clt->clt_fcgi = fcgi;
517 014c66b6 2023-06-25 op SPLAY_INSERT(client_tree, &fcgi->fcg_clients, clt);
518 014c66b6 2023-06-25 op break;
519 014c66b6 2023-06-25 op case FCGI_PARAMS:
520 014c66b6 2023-06-25 op if (clt == NULL) {
521 014c66b6 2023-06-25 op log_warnx("got FCGI_PARAMS for inactive id "
522 014c66b6 2023-06-25 op "(%d)", fcgi->fcg_rec_id);
523 014c66b6 2023-06-25 op evbuffer_drain(src, fcgi->fcg_toread);
524 014c66b6 2023-06-25 op break;
525 014c66b6 2023-06-25 op }
526 014c66b6 2023-06-25 op if (fcgi->fcg_toread == 0) {
527 014c66b6 2023-06-25 op evbuffer_drain(src, fcgi->fcg_toread);
528 014c66b6 2023-06-25 op if (server_handle(env, clt) == -1)
529 014c66b6 2023-06-25 op return;
530 014c66b6 2023-06-25 op break;
531 014c66b6 2023-06-25 op }
532 014c66b6 2023-06-25 op if (fcgi_parse_params(fcgi, src, clt) == -1) {
533 014c66b6 2023-06-25 op log_warnx("fcgi_parse_params failed");
534 014c66b6 2023-06-25 op fcgi_error(bev, EV_READ, d);
535 014c66b6 2023-06-25 op return;
536 014c66b6 2023-06-25 op }
537 014c66b6 2023-06-25 op break;
538 014c66b6 2023-06-25 op case FCGI_STDIN:
539 014c66b6 2023-06-25 op /* not interested in reading stdin */
540 014c66b6 2023-06-25 op evbuffer_drain(src, fcgi->fcg_toread);
541 014c66b6 2023-06-25 op break;
542 014c66b6 2023-06-25 op case FCGI_ABORT_REQUEST:
543 014c66b6 2023-06-25 op if (clt == NULL) {
544 014c66b6 2023-06-25 op log_warnx("got FCGI_ABORT_REQUEST for inactive"
545 014c66b6 2023-06-25 op " id (%d)", fcgi->fcg_rec_id);
546 014c66b6 2023-06-25 op evbuffer_drain(src, fcgi->fcg_toread);
547 014c66b6 2023-06-25 op break;
548 014c66b6 2023-06-25 op }
549 014c66b6 2023-06-25 op if (fcgi_end_request(clt, 1) == -1) {
550 014c66b6 2023-06-25 op /* calls fcgi_error on failure */
551 014c66b6 2023-06-25 op return;
552 014c66b6 2023-06-25 op }
553 014c66b6 2023-06-25 op break;
554 014c66b6 2023-06-25 op default:
555 014c66b6 2023-06-25 op log_warnx("unknown fastcgi record type %d",
556 014c66b6 2023-06-25 op fcgi->fcg_type);
557 014c66b6 2023-06-25 op evbuffer_drain(src, fcgi->fcg_toread);
558 014c66b6 2023-06-25 op break;
559 014c66b6 2023-06-25 op }
560 014c66b6 2023-06-25 op
561 014c66b6 2023-06-25 op /* Prepare for the next record. */
562 014c66b6 2023-06-25 op evbuffer_drain(src, fcgi->fcg_padding);
563 014c66b6 2023-06-25 op fcgi->fcg_want = FCGI_RECORD_HEADER;
564 014c66b6 2023-06-25 op fcgi->fcg_toread = sizeof(struct fcgi_header);
565 014c66b6 2023-06-25 op }
566 014c66b6 2023-06-25 op }
567 014c66b6 2023-06-25 op
568 014c66b6 2023-06-25 op void
569 014c66b6 2023-06-25 op fcgi_write(struct bufferevent *bev, void *d)
570 014c66b6 2023-06-25 op {
571 014c66b6 2023-06-25 op struct fcgi *fcgi = d;
572 014c66b6 2023-06-25 op struct evbuffer *out = EVBUFFER_OUTPUT(bev);
573 014c66b6 2023-06-25 op
574 014c66b6 2023-06-25 op if (fcgi->fcg_done && EVBUFFER_LENGTH(out) == 0)
575 014c66b6 2023-06-25 op fcgi_error(bev, EVBUFFER_EOF, fcgi);
576 014c66b6 2023-06-25 op }
577 014c66b6 2023-06-25 op
578 014c66b6 2023-06-25 op void
579 014c66b6 2023-06-25 op fcgi_error(struct bufferevent *bev, short event, void *d)
580 014c66b6 2023-06-25 op {
581 014c66b6 2023-06-25 op struct fcgi *fcgi = d;
582 014c66b6 2023-06-25 op struct env *env = fcgi->fcg_env;
583 014c66b6 2023-06-25 op struct client *clt;
584 014c66b6 2023-06-25 op
585 014c66b6 2023-06-25 op log_debug("fcgi failure, shutting down connection (ev: %x)",
586 014c66b6 2023-06-25 op event);
587 014c66b6 2023-06-25 op fcgi_inflight_dec(__func__);
588 014c66b6 2023-06-25 op
589 014c66b6 2023-06-25 op while ((clt = SPLAY_MIN(client_tree, &fcgi->fcg_clients)) != NULL) {
590 014c66b6 2023-06-25 op SPLAY_REMOVE(client_tree, &fcgi->fcg_clients, clt);
591 014c66b6 2023-06-25 op server_client_free(clt);
592 014c66b6 2023-06-25 op }
593 014c66b6 2023-06-25 op
594 014c66b6 2023-06-25 op SPLAY_REMOVE(fcgi_tree, &env->env_fcgi_socks, fcgi);
595 014c66b6 2023-06-25 op fcgi_free(fcgi);
596 014c66b6 2023-06-25 op
597 014c66b6 2023-06-25 op return;
598 014c66b6 2023-06-25 op }
599 014c66b6 2023-06-25 op
600 014c66b6 2023-06-25 op void
601 014c66b6 2023-06-25 op fcgi_free(struct fcgi *fcgi)
602 014c66b6 2023-06-25 op {
603 014c66b6 2023-06-25 op close(fcgi->fcg_s);
604 014c66b6 2023-06-25 op bufferevent_free(fcgi->fcg_bev);
605 014c66b6 2023-06-25 op free(fcgi);
606 014c66b6 2023-06-25 op }
607 014c66b6 2023-06-25 op
608 014c66b6 2023-06-25 op int
609 014c66b6 2023-06-25 op clt_flush(struct client *clt)
610 014c66b6 2023-06-25 op {
611 014c66b6 2023-06-25 op struct fcgi *fcgi = clt->clt_fcgi;
612 014c66b6 2023-06-25 op struct bufferevent *bev = fcgi->fcg_bev;
613 014c66b6 2023-06-25 op struct fcgi_header hdr;
614 014c66b6 2023-06-25 op
615 014c66b6 2023-06-25 op if (clt->clt_buflen == 0)
616 014c66b6 2023-06-25 op return (0);
617 014c66b6 2023-06-25 op
618 014c66b6 2023-06-25 op memset(&hdr, 0, sizeof(hdr));
619 014c66b6 2023-06-25 op hdr.version = FCGI_VERSION_1;
620 014c66b6 2023-06-25 op hdr.type = FCGI_STDOUT;
621 014c66b6 2023-06-25 op hdr.req_id0 = (clt->clt_id & 0xFF);
622 014c66b6 2023-06-25 op hdr.req_id1 = (clt->clt_id >> 8);
623 014c66b6 2023-06-25 op hdr.content_len0 = (clt->clt_buflen & 0xFF);
624 014c66b6 2023-06-25 op hdr.content_len1 = (clt->clt_buflen >> 8);
625 014c66b6 2023-06-25 op
626 014c66b6 2023-06-25 op if (bufferevent_write(bev, &hdr, sizeof(hdr)) == -1 ||
627 014c66b6 2023-06-25 op bufferevent_write(bev, clt->clt_buf, clt->clt_buflen) == -1) {
628 014c66b6 2023-06-25 op fcgi_error(bev, EV_WRITE, fcgi);
629 014c66b6 2023-06-25 op return (-1);
630 014c66b6 2023-06-25 op }
631 014c66b6 2023-06-25 op
632 014c66b6 2023-06-25 op clt->clt_buflen = 0;
633 014c66b6 2023-06-25 op
634 014c66b6 2023-06-25 op return (0);
635 014c66b6 2023-06-25 op }
636 014c66b6 2023-06-25 op
637 014c66b6 2023-06-25 op int
638 014c66b6 2023-06-25 op clt_write(struct client *clt, const uint8_t *buf, size_t len)
639 014c66b6 2023-06-25 op {
640 014c66b6 2023-06-25 op size_t left, copy;
641 014c66b6 2023-06-25 op
642 014c66b6 2023-06-25 op while (len > 0) {
643 014c66b6 2023-06-25 op left = sizeof(clt->clt_buf) - clt->clt_buflen;
644 014c66b6 2023-06-25 op if (left == 0) {
645 014c66b6 2023-06-25 op if (clt_flush(clt) == -1)
646 014c66b6 2023-06-25 op return (-1);
647 014c66b6 2023-06-25 op left = sizeof(clt->clt_buf);
648 014c66b6 2023-06-25 op }
649 014c66b6 2023-06-25 op
650 014c66b6 2023-06-25 op copy = MIN(left, len);
651 014c66b6 2023-06-25 op
652 014c66b6 2023-06-25 op memcpy(&clt->clt_buf[clt->clt_buflen], buf, copy);
653 014c66b6 2023-06-25 op clt->clt_buflen += copy;
654 014c66b6 2023-06-25 op buf += copy;
655 014c66b6 2023-06-25 op len -= copy;
656 014c66b6 2023-06-25 op }
657 014c66b6 2023-06-25 op
658 014c66b6 2023-06-25 op return (0);
659 014c66b6 2023-06-25 op }
660 014c66b6 2023-06-25 op
661 014c66b6 2023-06-25 op int
662 014c66b6 2023-06-25 op clt_putc(struct client *clt, char ch)
663 014c66b6 2023-06-25 op {
664 014c66b6 2023-06-25 op return (clt_write(clt, &ch, 1));
665 014c66b6 2023-06-25 op }
666 014c66b6 2023-06-25 op
667 014c66b6 2023-06-25 op int
668 014c66b6 2023-06-25 op clt_puts(struct client *clt, const char *str)
669 014c66b6 2023-06-25 op {
670 014c66b6 2023-06-25 op return (clt_write(clt, str, strlen(str)));
671 014c66b6 2023-06-25 op }
672 014c66b6 2023-06-25 op
673 014c66b6 2023-06-25 op int
674 014c66b6 2023-06-25 op clt_write_bufferevent(struct client *clt, struct bufferevent *bev)
675 014c66b6 2023-06-25 op {
676 014c66b6 2023-06-25 op struct evbuffer *src = EVBUFFER_INPUT(bev);
677 014c66b6 2023-06-25 op size_t len, left, copy;
678 014c66b6 2023-06-25 op
679 014c66b6 2023-06-25 op len = EVBUFFER_LENGTH(src);
680 014c66b6 2023-06-25 op while (len > 0) {
681 014c66b6 2023-06-25 op left = sizeof(clt->clt_buf) - clt->clt_buflen;
682 014c66b6 2023-06-25 op if (left == 0) {
683 014c66b6 2023-06-25 op if (clt_flush(clt) == -1)
684 014c66b6 2023-06-25 op return (-1);
685 014c66b6 2023-06-25 op left = sizeof(clt->clt_buf);
686 014c66b6 2023-06-25 op }
687 014c66b6 2023-06-25 op
688 014c66b6 2023-06-25 op copy = bufferevent_read(bev, &clt->clt_buf[clt->clt_buflen],
689 014c66b6 2023-06-25 op MIN(left, len));
690 014c66b6 2023-06-25 op clt->clt_buflen += copy;
691 014c66b6 2023-06-25 op
692 014c66b6 2023-06-25 op len = EVBUFFER_LENGTH(src);
693 014c66b6 2023-06-25 op }
694 014c66b6 2023-06-25 op
695 014c66b6 2023-06-25 op return (0);
696 014c66b6 2023-06-25 op }
697 014c66b6 2023-06-25 op
698 014c66b6 2023-06-25 op int
699 014c66b6 2023-06-25 op clt_printf(struct client *clt, const char *fmt, ...)
700 014c66b6 2023-06-25 op {
701 014c66b6 2023-06-25 op struct fcgi *fcgi = clt->clt_fcgi;
702 014c66b6 2023-06-25 op struct bufferevent *bev = fcgi->fcg_bev;
703 014c66b6 2023-06-25 op char *str;
704 014c66b6 2023-06-25 op va_list ap;
705 014c66b6 2023-06-25 op int r;
706 014c66b6 2023-06-25 op
707 014c66b6 2023-06-25 op va_start(ap, fmt);
708 014c66b6 2023-06-25 op r = vasprintf(&str, fmt, ap);
709 014c66b6 2023-06-25 op va_end(ap);
710 014c66b6 2023-06-25 op if (r == -1) {
711 014c66b6 2023-06-25 op fcgi_error(bev, EV_WRITE, fcgi);
712 014c66b6 2023-06-25 op return (-1);
713 014c66b6 2023-06-25 op }
714 014c66b6 2023-06-25 op
715 014c66b6 2023-06-25 op r = clt_write(clt, str, r);
716 014c66b6 2023-06-25 op free(str);
717 014c66b6 2023-06-25 op return (r);
718 014c66b6 2023-06-25 op }
719 014c66b6 2023-06-25 op
720 014c66b6 2023-06-25 op #if template
721 014c66b6 2023-06-25 op int
722 014c66b6 2023-06-25 op clt_tp_puts(struct template *tp, const char *str)
723 014c66b6 2023-06-25 op {
724 014c66b6 2023-06-25 op struct client *clt = tp->tp_arg;
725 014c66b6 2023-06-25 op
726 014c66b6 2023-06-25 op if (clt_puts(clt, str) == -1)
727 014c66b6 2023-06-25 op return (-1);
728 014c66b6 2023-06-25 op
729 014c66b6 2023-06-25 op return (0);
730 014c66b6 2023-06-25 op }
731 014c66b6 2023-06-25 op
732 014c66b6 2023-06-25 op int
733 014c66b6 2023-06-25 op clt_tp_putc(struct template *tp, int c)
734 014c66b6 2023-06-25 op {
735 014c66b6 2023-06-25 op struct client *clt = tp->tp_arg;
736 014c66b6 2023-06-25 op
737 014c66b6 2023-06-25 op if (clt_putc(clt, c) == -1)
738 014c66b6 2023-06-25 op return (-1);
739 014c66b6 2023-06-25 op
740 014c66b6 2023-06-25 op return (0);
741 014c66b6 2023-06-25 op }
742 014c66b6 2023-06-25 op #endif
743 014c66b6 2023-06-25 op
744 014c66b6 2023-06-25 op int
745 014c66b6 2023-06-25 op fcgi_cmp(struct fcgi *a, struct fcgi *b)
746 014c66b6 2023-06-25 op {
747 014c66b6 2023-06-25 op return ((int)a->fcg_id - b->fcg_id);
748 014c66b6 2023-06-25 op }
749 014c66b6 2023-06-25 op
750 014c66b6 2023-06-25 op int
751 014c66b6 2023-06-25 op fcgi_client_cmp(struct client *a, struct client *b)
752 014c66b6 2023-06-25 op {
753 014c66b6 2023-06-25 op return ((int)a->clt_id - b->clt_id);
754 014c66b6 2023-06-25 op }
755 014c66b6 2023-06-25 op
756 014c66b6 2023-06-25 op int
757 014c66b6 2023-06-25 op accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
758 014c66b6 2023-06-25 op int reserve, volatile int *counter)
759 014c66b6 2023-06-25 op {
760 014c66b6 2023-06-25 op int ret;
761 014c66b6 2023-06-25 op
762 014c66b6 2023-06-25 op if (getdtablecount() + reserve + *counter >= getdtablesize()) {
763 014c66b6 2023-06-25 op errno = EMFILE;
764 014c66b6 2023-06-25 op return (-1);
765 014c66b6 2023-06-25 op }
766 014c66b6 2023-06-25 op
767 014c66b6 2023-06-25 op if ((ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK)) > -1) {
768 014c66b6 2023-06-25 op (*counter)++;
769 014c66b6 2023-06-25 op log_debug("%s: inflight incremented, now %d", __func__,
770 014c66b6 2023-06-25 op *counter);
771 014c66b6 2023-06-25 op }
772 014c66b6 2023-06-25 op
773 014c66b6 2023-06-25 op return (ret);
774 014c66b6 2023-06-25 op }
775 014c66b6 2023-06-25 op
776 014c66b6 2023-06-25 op SPLAY_GENERATE(fcgi_tree, fcgi, fcg_nodes, fcgi_cmp);
777 014c66b6 2023-06-25 op SPLAY_GENERATE(client_tree, client, clt_nodes, fcgi_client_cmp);