Blame


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