"Fossies" - the Fresh Open Source Software Archive 
Member "Pound-3.0.2/src/backend.c" (28 Nov 2021, 22578 Bytes) of package /linux/www/Pound-3.0.2.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "backend.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
3.0.1_vs_3.0.2.
1 /*
2 * Pound - the reverse-proxy load-balancer
3 * Copyright (C) 2002-2020 Apsis GmbH
4 *
5 * This file is part of Pound.
6 *
7 * Pound is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Pound is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/> .
19 *
20 * Contact information:
21 * Apsis GmbH
22 * P.O.Box
23 * 8707 Uetikon am See
24 * Switzerland
25 * EMail: roseg@apsis.ch
26 */
27
28 #include "pound.h"
29
30 #define EOF_LISTENER(S) {\
31 char *m;\
32 int f;\
33 \
34 nn_send((S), "", 0, 0);\
35 f = 100;\
36 nn_setsockopt(S, NN_SOL_SOCKET, NN_RCVTIMEO, &f, sizeof(f));\
37 if(nn_recv((S), &m, NN_MSG, 0) >= 0)\
38 nn_freemsg(m);\
39 nn_close(S);\
40 }
41
42 static int
43 backend_1(BACKEND *be, int s_listener, FILE *f_be, char *client_addr)
44 {
45 char buf[MAXBUF + 1], request[MAXBUF + 1], *msg;
46 int no_content, is_chunked, reply_code, n;
47 long content_length, total;
48 regmatch_t match[2];
49
50 logmsg(1, "%lX start backend_1 %s:%d", pthread_self(), __FILE__, __LINE__);
51 no_content = is_chunked = 0;
52 content_length = total = 0L;
53 /* receive the request from the listener and keep it for logging */
54 if(nn_recv(s_listener, &msg, NN_MSG, 0) <= 0) {
55 logmsg(2, "%lX can't get request %s:%d", pthread_self(), __FILE__, __LINE__);
56 EOF_LISTENER(s_listener);
57 return -1;
58 }
59 strcpy(request, msg);
60 nn_freemsg(msg);
61 no_content = !strncasecmp("HEAD", request, 4);
62 fputs(request, f_be);
63 for(n = 0; n < MAXBUF && request[n]; n++)
64 if(request[n] == '\r' || request[n] == '\n') {
65 request[n] = '\0';
66 break;
67 }
68 logmsg(4, "%lX request:%s %s:%d", pthread_self(), request, __FILE__, __LINE__);
69
70 /* receive the other headers from the listener and pass them to the back-end */
71 while(nn_recv(s_listener, &msg, NN_MSG, 0) > 0) {
72 logmsg(4, "%lX header:%s %s:%d", pthread_self(), msg, __FILE__, __LINE__);
73 fputs(msg, f_be);
74 nn_freemsg(msg);
75 }
76 nn_freemsg(msg);
77 logmsg(2, "%lX end request %s:%d", pthread_self(), __FILE__, __LINE__);
78
79 fflush(f_be);
80
81 total = 0L;
82 if(fgets(buf, MAXBUF - 1, f_be) == NULL) {
83 logmsg(2, "%lX no reply from backend %s:%d", pthread_self(), __FILE__, __LINE__);
84 close(fileno(f_be));
85 fclose(f_be);
86 EOF_LISTENER(s_listener);
87 return -1;
88 }
89 nn_send(s_listener, buf, strlen(buf), 0);
90 logmsg(4, "%lX reply %s %s:%d", pthread_self(), buf, __FILE__, __LINE__);
91
92 for(;;) {
93 if(regexec(&rex_Response, buf, 2, match, REG_ICASE))
94 continue;
95 sscanf(buf + match[1].rm_so, "%d", &reply_code);
96 if(reply_code >= 200)
97 break;
98 /* a 1xx reply - pass and skip */
99 while(fgets(buf, MAXBUF - 1, f_be) != NULL) {
100 logmsg(4, "%lX 100 pass through %s:%d", pthread_self(), buf, __FILE__, __LINE__);
101 nn_send(s_listener, buf, strlen(buf), 0);
102 if(buf[0] == '\r' || buf[0] == '\n')
103 break;
104 }
105 if(fgets(buf, MAXBUF, f_be) == NULL) {
106 close(fileno(f_be));
107 fclose(f_be);
108 EOF_LISTENER(s_listener);
109 time_stamp(buf);
110 logmsg(0, "%s - - [%s] \"%s\" premature EOF", client_addr, buf, request);
111 return -1;
112 }
113 logmsg(4, "%lX %s %s:%d", pthread_self(), buf, __FILE__, __LINE__);
114 nn_send(s_listener, buf, strlen(buf), 0);
115 }
116
117 total += strlen(buf);
118 /*
119 * receive the reply headers
120 *
121 * WARNING: we do not check here for malicious combinations, as we assume our servers to be OK!
122 */
123 if(be->add_header) {
124 nn_send(s_listener, be->add_header, strlen(be->add_header), 0);
125 logmsg(4, "%lX add header %s %s:%d", pthread_self(), be->add_header, __FILE__, __LINE__);
126 nn_send(s_listener, "\r\n", 2, 0);
127 total += strlen(be->add_header) + 2;
128 }
129 while(fgets(buf, MAXBUF, f_be) != NULL) {
130 logmsg(4, "%lX header %s %s:%d", pthread_self, buf, __FILE__, __LINE__);
131 nn_send(s_listener, buf, strlen(buf), 0);
132 total += strlen(buf);
133 if(buf[0] == '\r' || buf[0] == '\n')
134 break;
135 if(!no_content) {
136 if(!regexec(&rex_Chunked, buf, 0, NULL, REG_ICASE))
137 is_chunked = 1;
138 else if(!regexec(&rex_ContentLength, buf, 2, match, REG_ICASE))
139 sscanf(buf + match[1].rm_so, "%ld", &content_length);
140 }
141 }
142
143 logmsg(3, "%lX no_content %d, is_chunked %d, content_length %d %s:%d", pthread_self, no_content, is_chunked, content_length, __FILE__, __LINE__);
144
145 if(!no_content) {
146 if(is_chunked) {
147 for(;;) {
148 if(fgets(buf, MAXBUF, f_be) == NULL)
149 break;
150 nn_send(s_listener, buf, strlen(buf), 0);
151 total += strlen(buf);
152 sscanf(buf, "%lx", &content_length);
153 logmsg(4, "%lX chunk %d %s:%d", pthread_self(), content_length, __FILE__, __LINE__);
154 if(content_length == 0L)
155 break;
156 while(content_length > 0L) {
157 if((n = fread(buf, sizeof(char), content_length > MAXBUF? MAXBUF: content_length, f_be)) > 0) {
158 logmsg(4, "%lX read %d %s:%d", pthread_self(), n, __FILE__, __LINE__);
159 nn_send(s_listener, buf, n, 0);
160 content_length -= n;
161 total += n;
162 } else {
163 content_length = -1L;
164 logmsg(4, "%lX read return %d %s:%d", pthread_self(), n, __FILE__, __LINE__);
165 }
166
167 }
168 /* CR/LF separator */
169 fgets(buf, MAXBUF, f_be);
170 }
171
172 /* possibly some more headers */
173 while(fgets(buf, MAXBUF, f_be) != NULL) {
174 nn_send(s_listener, buf, strlen(buf), 0);
175 logmsg(4, "%lX additional header %s %s:%d", pthread_self(), buf, __FILE__, __LINE__);
176 total += strlen(buf);
177 if(buf[0] == '\r' || buf[0] == '\n')
178 break;
179 }
180 } else while(content_length > 0L) {
181 memset(buf, '\0', MAXBUF + 1);
182 if((n = fread(buf, sizeof(char), content_length > MAXBUF? MAXBUF: content_length, f_be)) > 0) {
183 logmsg(4, "%lX read %d %s:%d", pthread_self(), n, __FILE__, __LINE__);
184 nn_send(s_listener, buf, n, 0);
185 content_length -= n;
186 total += n;
187 } else {
188 logmsg(4, "%lX read return %d %s:%d", pthread_self(), n, __FILE__, __LINE__);
189 content_length = -1L;
190 }
191 }
192 }
193
194 EOF_LISTENER(s_listener);
195 time_stamp(buf);
196 logmsg(0, "%s - - [%s] \"%s\" %d %ld", client_addr, buf, request, reply_code, total);
197 return fileno(f_be);
198 }
199
200 static int
201 backend_2(BACKEND *be, int s_listener, FILE *f_be, char *client_addr)
202 {
203 struct hpack_headerblock *headers, *r_headers;
204 struct hpack_header *h;
205 struct hpack_table *tab;
206 int TABSIZE, FRAMESIZE, n, no_content, is_chunked, reply_code;
207 long content_length, total;
208 size_t h_len;
209 char buf[MAXBUF], *method, *path, *authority, *cp, *tp, *ttp, request[MAXBUF];
210 unsigned char *msg, *content;
211 regmatch_t match[2];
212
213 logmsg(1, "%lX start backend_2 %s:%d", pthread_self(), __FILE__, __LINE__);
214 if(nn_recv(s_listener, &msg, NN_MSG, 0) != sizeof(int)) {
215 logmsg(2, "%lX can't get FRAMESIZE %s:%d", pthread_self(), __FILE__, __LINE__);
216 EOF_LISTENER(s_listener);
217 return -1;
218 }
219 memcpy(&FRAMESIZE, msg, sizeof(int));
220 nn_freemsg(msg);
221 if(nn_recv(s_listener, &msg, NN_MSG, 0) != sizeof(int)) {
222 logmsg(2, "%lX can't get TABSIZE %s:%d", pthread_self(), __FILE__, __LINE__);
223 EOF_LISTENER(s_listener);
224 return -1;
225 }
226 memcpy(&TABSIZE, msg, sizeof(int));
227 nn_freemsg(msg);
228 if(nn_recv(s_listener, &msg, NN_MSG, 0) != sizeof(struct hpack_headerblock *)) {
229 logmsg(2, "%lX can't get headers %s:%d", pthread_self(), __FILE__, __LINE__);
230 EOF_LISTENER(s_listener);
231 return -1;
232 }
233 memcpy(&headers, msg, sizeof(struct hpack_headerblock *));
234 nn_freemsg(msg);
235 logmsg(3, "%lX FRAMESIZE %d, TABSIZE %d %s:%d", pthread_self(), FRAMESIZE, TABSIZE, __FILE__, __LINE__);
236
237 method = path = authority = NULL;
238 TAILQ_FOREACH(h, headers, hdr_entry) {
239 if(!strcmp(h->hdr_name, ":method"))
240 method = h->hdr_value;
241 else if(!strcmp(h->hdr_name, ":authority"))
242 authority = h->hdr_value;
243 else if(!strcmp(h->hdr_name, ":path"))
244 path = h->hdr_value;
245 }
246 if(method == NULL || path == NULL || authority == NULL) {
247 logmsg(2, "%lX can't find method/path/authority %s:%d", pthread_self(), __FILE__, __LINE__);
248 EOF_LISTENER(s_listener);
249 return -1;
250 }
251 is_chunked = 0;
252 snprintf(request, MAXBUF, "%s %s HTTP/1.1", method, path);
253 fprintf(f_be, "%s\r\n", request);
254 logmsg(4, "%lX %s %s HTTP/1.1 %s:%d", pthread_self(), method, path, __FILE__, __LINE__);
255 fprintf(f_be, "host: %s\r\n", authority);
256 logmsg(4, "%lX host: %s %s:%d", pthread_self(), authority, __FILE__, __LINE__);
257 TAILQ_FOREACH(h, headers, hdr_entry) {
258 if(!strcasecmp(h->hdr_name, ":method") || !strcasecmp(h->hdr_name, ":authority") || !strcasecmp(h->hdr_name, ":path") || !strcasecmp(h->hdr_name, ":scheme"))
259 continue;
260 if(!strcmp(h->hdr_name, "te") || !strcasecmp(h->hdr_name, "transfer-encoding")) {
261 fprintf(f_be, "%s: %s, chunked\r\n", h->hdr_name, h->hdr_value);
262 logmsg(4, "%lX %s: %s, chunked %s:%d", pthread_self(), h->hdr_name, h->hdr_value, __FILE__, __LINE__);
263 is_chunked = 1;
264 } if(!strcasecmp(h->hdr_name, "upgrade") || !strcasecmp(h->hdr_name, "upgrade-insecure-requests")) {
265 logmsg(4, "%lX %s: skipped %s:%d", pthread_self(), h->hdr_name, __FILE__, __LINE__);
266 } else {
267 fprintf(f_be, "%s: %s\r\n", h->hdr_name, h->hdr_value);
268 logmsg(4, "%lX %s: %s %s:%d", pthread_self(), h->hdr_name, h->hdr_value, __FILE__, __LINE__);
269 }
270 }
271 if(!is_chunked) {
272 fprintf(f_be, "te: chunked\r\n");
273 logmsg(4, "%lX te: chunked %s:%d", pthread_self(), __FILE__, __LINE__);
274 }
275 fprintf(f_be, "\r\n");
276 logmsg(4, "%lX ---end of headers--- %s:%d", pthread_self(), __FILE__, __LINE__);
277
278 while((n = nn_recv(s_listener, &msg, NN_MSG, 0)) > 0) {
279 logmsg(4, "%lX chunk %d %s:%d", pthread_self(), n, __FILE__, __LINE__);
280 fprintf(f_be, "%X\r\n", n);
281 fwrite(msg, 1, n, f_be);
282 fwrite("\r\n", 1, 2, f_be);
283 nn_freemsg(msg);
284 }
285 fprintf(f_be, "0\r\n");
286 logmsg(4, "%lX ---end of content--- %s:%d", pthread_self(), __FILE__, __LINE__);
287 if(nn_recv(s_listener, &msg, NN_MSG, 0) == sizeof(struct hpack_headerblock *)) {
288 memcpy(&headers, msg, sizeof(struct hpack_headerblock *));
289 TAILQ_FOREACH(h, headers, hdr_entry) {
290 if(!strcasecmp(h->hdr_name, ":method") || !strcasecmp(h->hdr_name, ":authority") || !strcasecmp(h->hdr_name, ":path") || !strcasecmp(h->hdr_name, ":scheme"))
291 continue;
292 fprintf(f_be, "%s: %s\r\n", h->hdr_name, h->hdr_value);
293 logmsg(4, "%lX trailing header %s: %s %s:%d", pthread_self(), h->hdr_name, h->hdr_value, __FILE__, __LINE__);
294 }
295 } else {
296 logmsg(2, "%lX no trailing headers %s:%d", pthread_self(), __FILE__, __LINE__);
297 }
298 nn_freemsg(msg);
299 fprintf(f_be, "\r\n");
300 logmsg(4, "%lX ---end of trailing headers --- %s:%d", pthread_self(), __FILE__, __LINE__);
301
302 no_content = !strncasecmp("HEAD", method, 4);
303 total = 0L;
304 r_headers = hpack_headerblock_new();
305 tab = hpack_table_new(TABSIZE);
306
307 for(;;) {
308 do {
309 if(fgets(buf, MAXBUF - 1, f_be) == NULL) {
310 logmsg(2, "%lX no reply from backend %s:%d", pthread_self(), __FILE__, __LINE__);
311 hpack_headerblock_free(r_headers);
312 hpack_table_free(tab);
313 close(fileno(f_be));
314 fclose(f_be);
315 EOF_LISTENER(s_listener);
316 return -1;
317 } else
318 logmsg(4, "%lX read %s %s:%d", pthread_self(), buf, __FILE__, __LINE__);
319 } while(regexec(&rex_Response, buf, 2, match, REG_ICASE));
320 sscanf(buf + match[1].rm_so, "%d", &reply_code);
321 logmsg(4, "%lX reply code %d %s:%d", pthread_self(), reply_code, __FILE__, __LINE__);
322 if(reply_code >= 200) {
323 sprintf(buf, "%d", reply_code);
324 hpack_header_add(r_headers, ":status", buf, HPACK_INDEX);
325 logmsg(4, "%lX reply header :status %s %s:%d", pthread_self(), buf, __FILE__, __LINE__);
326 total += strlen(":status") + strlen(buf);
327 break;
328 }
329 }
330
331 if(be->add_header) {
332 strncpy(buf, be->add_header, MAXBUF);
333 cp = strtok_r(buf, ":", &tp);
334 if((ttp = strtok_r(NULL, "\r", &tp)) != NULL)
335 while(*ttp == ' ')
336 ttp++;
337 else
338 ttp = "";
339 hpack_header_add(r_headers, cp, ttp, HPACK_INDEX);
340 logmsg(4, "%lX add header %s %s:%d", pthread_self(), be->add_header, __FILE__, __LINE__);
341 total += strlen(cp) + strlen(ttp);
342 }
343
344 is_chunked = 0;
345 content_length = 0L;
346 while(fgets(buf, MAXBUF, f_be) != NULL) {
347 if(buf[0] == '\r' || buf[0] == '\n')
348 break;
349 if(!no_content) {
350 if(!regexec(&rex_Chunked, buf, 0, NULL, REG_ICASE))
351 is_chunked = 1;
352 else if(!regexec(&rex_ContentLength, buf, 2, match, REG_ICASE))
353 sscanf(buf + match[1].rm_so, "%ld", &content_length);
354 }
355 cp = strtok_r(buf, ":", &tp);
356 if(!strcasecmp(cp, "connection") || !strcasecmp(cp, "keep-alive") || !strcasecmp(cp, "proxy-connection") || !strcasecmp(cp, "transfer-encoding")
357 || !strcasecmp(cp, "te") || !strcasecmp(cp, "content-length") || !strcasecmp(cp, "upgrade")) {
358 logmsg(4, "%lX header %s skipped %s:%d", pthread_self(), buf, __FILE__, __LINE__);
359 continue;
360 }
361 if((ttp = strtok_r(NULL, "\r", &tp)) != NULL)
362 while(*ttp == ' ')
363 ttp++;
364 else
365 ttp = "";
366 hpack_header_add(r_headers, cp, ttp, HPACK_INDEX);
367 logmsg(4, "%lX header %s => %s: %s %s:%d", pthread_self(), buf, cp, ttp, __FILE__, __LINE__);
368 total += strlen(cp) + strlen(ttp);
369 }
370 if((content = hpack_encode(r_headers, &h_len, tab)) == NULL) {
371 logmsg(4, "%lX failed encode %s:%d", pthread_self(), __FILE__, __LINE__);
372 hpack_headerblock_free(r_headers);
373 hpack_table_free(tab);
374 close(fileno(f_be));
375 fclose(f_be);
376 EOF_LISTENER(s_listener);
377 return -1;
378 }
379 for(n = 0; h_len > 0; ) {
380 nn_send(s_listener, content + n, h_len > FRAMESIZE? FRAMESIZE: h_len, 0);
381 n += (h_len > FRAMESIZE? FRAMESIZE: h_len);
382 h_len -= (h_len > FRAMESIZE? FRAMESIZE: h_len);
383 }
384 free(content);
385 hpack_headerblock_free(r_headers);
386
387 /* end of headers */
388 nn_send(s_listener, "", 0, 0);
389 logmsg(3, "%lX no_content %d, is_chunked %d, content_length %d %s:%d", pthread_self(), no_content, is_chunked, content_length, __FILE__, __LINE__);
390
391 if(!no_content) {
392 if((content = malloc(FRAMESIZE)) == NULL) {
393 logmsg(4, "%lX out of memory for content %s:%d", pthread_self(), __FILE__, __LINE__);
394 hpack_table_free(tab);
395 close(fileno(f_be));
396 fclose(f_be);
397 EOF_LISTENER(s_listener);
398 return -1;
399 }
400
401 if(is_chunked) {
402 for(;;) {
403 if(fgets(buf, MAXBUF, f_be) == NULL)
404 break;
405 sscanf(buf, "%lx", &content_length);
406 logmsg(4, "%lX chunk %d (%s) %s:%d", pthread_self(), content_length, buf, __FILE__, __LINE__);
407 if(content_length == 0L)
408 break;
409 while(content_length > 0L) {
410 if((n = fread(content, sizeof(char), content_length > FRAMESIZE? FRAMESIZE: content_length, f_be)) > 0) {
411 logmsg(4, "%lX read %d %s:%d", pthread_self(), n, __FILE__, __LINE__);
412 nn_send(s_listener, content, n, 0);
413 content_length -= n;
414 total += n;
415 } else {
416 content_length = -1L;
417 logmsg(4, "%lX read return %d %s:%d", pthread_self(), n, __FILE__, __LINE__);
418 }
419
420 }
421 /* CR/LF separator */
422 fgets(buf, MAXBUF, f_be);
423 }
424 } else while(content_length > 0L) {
425 if((n = fread(content, sizeof(char), content_length > FRAMESIZE? FRAMESIZE: content_length, f_be)) > 0) {
426 logmsg(4, "%lX read %d %s:%d", pthread_self(), n, __FILE__, __LINE__);
427 nn_send(s_listener, content, n, 0);
428 content_length -= n;
429 total += n;
430 } else {
431 logmsg(4, "%lX read return %d %s:%d", pthread_self(), n, __FILE__, __LINE__);
432 content_length = -1L;
433 }
434 }
435
436 free(content);
437 }
438 /* end of data */
439 nn_send(s_listener, "", 0, 0);
440 logmsg(4, "%lX sent end-of-content %s:%d", pthread_self(), __FILE__, __LINE__);
441
442 EOF_LISTENER(s_listener);
443 time_stamp(buf);
444 logmsg(0, "%s - - [%s] \"%s\" %d %ld", client_addr, buf, request, reply_code, total);
445 return fileno(f_be);
446 }
447
448 void *
449 thr_backend(void *arg)
450 {
451 BACKEND *be;
452 int s_listener, s_be, res, flags, http_ver;
453 char *msg, client_addr[NI_MAXHOST], *cp, *saveptr;
454 struct pollfd be_poll;
455 struct linger s_linger;
456 struct timeval s_time;
457 FILE *f_be;
458 regmatch_t match[2];
459
460 be = (BACKEND *)arg;
461 sem_post(&sem_start);
462 s_be = -1;
463 for(;;) {
464 msg = NULL;
465
466 if(nn_recv(be->sock, &msg, NN_MSG, 0) <= 0) {
467 logmsg(0, "Backend: can't receive from queue socket");
468 continue;
469 }
470 if((s_listener = nn_socket(AF_SP, NN_PAIR)) < 0) {
471 logmsg(0, "Backend: can't create direct socket");
472 continue;
473 }
474 if(nn_connect(s_listener, msg) < 0) {
475 logmsg(0, "Backend: can't connect to direct socket");
476 continue;
477 }
478 nn_freemsg(msg);
479
480 /* prepare the back-end socket */
481 if(s_be >= 0) {
482 be_poll.fd = s_be;
483 be_poll.events = POLLIN;
484 if(poll(&be_poll, 1, 1) == 1) {
485 /* only EOF can be read! */
486 close(s_be);
487 s_be = -1;
488 }
489 }
490 if(s_be < 0) {
491 /* open the socket to the backend */
492 if((s_be = socket(be->addr->ai_family, SOCK_STREAM, 0)) < 0) {
493 logmsg(0, "Backend: can't create socket");
494 s_be = -1;
495 EOF_LISTENER(s_listener);
496 continue;
497 }
498
499 /* wait at most 'timeout' seconds for the connection */
500 flags = fcntl(s_be, F_GETFL, &flags);
501 fcntl(s_be, F_SETFL, flags | O_NONBLOCK);
502 if(connect(s_be, be->addr->ai_addr, be->addr->ai_addrlen)) {
503 if(errno != EINPROGRESS) {
504 logmsg(0, "Backend: can't connect socket");
505 close(s_be);
506 s_be = -1;
507 EOF_LISTENER(s_listener);
508 continue;
509 }
510 be_poll.fd = s_be;
511 be_poll.events = POLLOUT;
512 if(poll(&be_poll, 1, be->timeout * 1000) != 1) {
513 logmsg(0, "Backend: can't connect");
514 close(s_be);
515 be->is_dead = 1;
516 s_be = -1;
517 EOF_LISTENER(s_listener);
518 continue;
519 }
520 }
521 fcntl(s_be, F_SETFL, flags);
522 s_linger.l_onoff = 1;
523 s_linger.l_linger = 0;
524 setsockopt(s_be, SOL_SOCKET, SO_LINGER, &s_linger, sizeof(s_linger));
525 s_time.tv_sec = be->timeout;
526 s_time.tv_usec = 0;
527 setsockopt(s_be, SOL_SOCKET, SO_RCVTIMEO, &s_time, sizeof(s_time));
528 setsockopt(s_be, SOL_SOCKET, SO_SNDTIMEO, &s_time, sizeof(s_time));
529 f_be = fdopen(s_be, "r+");
530 }
531
532 /* received the protocol information from the listener */
533 if(nn_recv(s_listener, &msg, NN_MSG, 0) != sizeof(int)) {
534 logmsg(2, "%lX can't get protocol version %s:%d", pthread_self(), __FILE__, __LINE__);
535 EOF_LISTENER(s_listener);
536 continue;
537 }
538 memcpy(&http_ver, msg, sizeof(int));
539 nn_freemsg(msg);
540 logmsg(4, "%lX http_ver %d %s:%d", pthread_self(), http_ver, __FILE__, __LINE__);
541
542 /* receive the client address from the listener and keep it for logging */
543 if(nn_recv(s_listener, &msg, NN_MSG, 0) <= 0) {
544 logmsg(2, "thr_backend: can't get client address %s:%d", pthread_self(), __FILE__, __LINE__);
545 EOF_LISTENER(s_listener);
546 continue;
547 }
548 strcpy(client_addr, msg);
549 nn_freemsg(msg);
550 logmsg(4, "%lX client_addr:%s %s:%d", pthread_self(), client_addr, __FILE__, __LINE__);
551
552 /* receive the reply from the back-end and pass it to the listener in the appropriate protocol */
553 if(http_ver == 2)
554 s_be = backend_2(be, s_listener, f_be, client_addr);
555 else
556 s_be = backend_1(be, s_listener, f_be, client_addr);
557 }
558 }