Blame


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