2 * Copyright (c) 1987-2021 by the citadel.org team
4 * This program is open source software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 3.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
14 * Uncomment this to log all communications with the Citadel server
19 #include "webserver.h"
21 long MaxRead = -1; /* should we do READ scattered or all at once? */
24 * register the timeout
26 RETSIGTYPE timeout(int signum) {
27 syslog(LOG_WARNING, "Connection timed out; unable to reach citserver\n");
28 /* no exit here, since we need to server the connection unreachable thing. exit(3); */
33 * Client side - connect to a unix domain socket
35 int connect_to_citadel(char *sockpath) {
36 struct sockaddr_un addr;
39 memset(&addr, 0, sizeof(addr));
40 addr.sun_family = AF_UNIX;
41 strncpy(addr.sun_path, sockpath, sizeof addr.sun_path);
43 s = socket(AF_UNIX, SOCK_STREAM, 0);
45 syslog(LOG_WARNING, "Can't create socket [%s]: %s\n", sockpath, strerror(errno));
49 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
50 syslog(LOG_WARNING, "Can't connect [%s]: %s\n", sockpath, strerror(errno));
59 * input string from pipe
61 int serv_getln(char *strbuf, int bufsize) {
65 StrBuf_ServGetln(WC->MigrateReadLineBuf);
66 len = StrLength(WC->MigrateReadLineBuf);
69 memcpy(strbuf, ChrPtr(WC->MigrateReadLineBuf), len);
70 FlushStrBuf(WC->MigrateReadLineBuf);
73 syslog(LOG_DEBUG, "%3d<<<%s\n", WC->serv_sock, strbuf);
79 int StrBuf_ServGetln(StrBuf *buf) {
80 const char *ErrStr = NULL;
87 rc = StrBufTCP_read_buffered_line_fast(buf,
95 syslog(LOG_INFO, "StrBuf_ServGetln(): Server connection broken: %s\n",
97 wc_backtrace(LOG_INFO);
98 if (WC->serv_sock > 0) close(WC->serv_sock);
107 if (WC->ReadPos != NULL)
108 pos = WC->ReadPos - ChrPtr(WC->ReadBuf);
109 syslog(LOG_DEBUG, "%3d<<<[%ld]%s\n", WC->serv_sock, pos, ChrPtr(buf));
115 int StrBuf_ServGetBLOBBuffered(StrBuf *buf, long BlobSize) {
119 rc = StrBufReadBLOBBuffered(buf,
128 syslog(LOG_INFO, "StrBuf_ServGetBLOBBuffered(): Server connection broken: %s\n",
130 wc_backtrace(LOG_INFO);
131 if (WC->serv_sock > 0) close(WC->serv_sock);
132 WC->serv_sock = (-1);
138 syslog(LOG_DEBUG, "%3d<<<BLOB: %d bytes\n", WC->serv_sock, StrLength(buf));
144 int StrBuf_ServGetBLOB(StrBuf *buf, long BlobSize) {
149 rc = StrBufReadBLOB(buf, &WC->serv_sock, 1, BlobSize, &ErrStr);
151 syslog(LOG_INFO, "StrBuf_ServGetBLOB(): Server connection broken: %s\n",
153 wc_backtrace(LOG_INFO);
154 if (WC->serv_sock > 0) close(WC->serv_sock);
155 WC->serv_sock = (-1);
161 syslog(LOG_DEBUG, "%3d<<<BLOB: %d bytes\n", WC->serv_sock, StrLength(buf));
168 void FlushReadBuf (void) {
173 len = StrLength(WC->ReadBuf);
174 if ((len > 0) && (WC->ReadPos != NULL) && (WC->ReadPos != StrBufNOTNULL)) {
175 pch = ChrPtr(WC->ReadBuf);
177 if (WC->ReadPos != pche) {
179 "ERROR: somebody didn't eat his soup! Remaing Chars: %ld [%s]\n",
180 (long)(pche - WC->ReadPos),
184 "--------------------------------------------------------------------------------\n"
186 "--------------------------------------------------------------------------------\n",
188 AppendImportantMessage(HKEY("Suppenkasper alert! watch your webcit logfile and get connected to your favourite opensource Crew."));
192 FlushStrBuf(WC->ReadBuf);
200 * send binary to server
201 * buf the buffer to write to citadel server
202 * nbytes how many bytes to send to citadel server
204 int serv_write(const char *buf, int nbytes) {
205 int bytes_written = 0;
209 while (bytes_written < nbytes) {
210 retval = write(WC->serv_sock, &buf[bytes_written], nbytes - bytes_written);
212 const char *ErrStr = strerror(errno);
213 syslog(LOG_INFO, "serv_write(): Server connection broken: %s\n", (ErrStr)?ErrStr:"");
214 if (WC->serv_sock > 0) close(WC->serv_sock);
215 WC->serv_sock = (-1);
220 bytes_written = bytes_written + retval;
227 * send line to server
228 * string the line to send to the citadel server
230 int serv_puts(const char *string) {
232 syslog(LOG_DEBUG, "%3d>>>%s\n", WC->serv_sock, string);
236 if (!serv_write(string, strlen(string)))
238 return serv_write("\n", 1);
242 * send line to server
243 * string the line to send to the citadel server
245 int serv_putbuf(const StrBuf *string) {
247 syslog(LOG_DEBUG, "%3d>>>%s\n", WC->serv_sock, ChrPtr(string));
251 if (!serv_write(ChrPtr(string), StrLength(string)))
253 return serv_write("\n", 1);
258 * convenience function to send stuff to the server
259 * format the formatstring
260 * ... the entities to insert into format
262 int serv_printf(const char *format,...) {
270 va_start(arg_ptr, format);
271 vsnprintf(buf, sizeof buf, format, arg_ptr);
277 rc = serv_write(buf, len);
279 syslog(LOG_DEBUG, ">>>%s", buf);
286 * Read binary data from server into memory using a series of server READ commands.
287 * returns the read content as StrBuf
289 int serv_read_binary(StrBuf *Ret, size_t total_len, StrBuf *Buf) {
290 size_t bytes_read = 0;
291 size_t this_block = 0;
299 while ((bytes_read < total_len) && (ServerRc == 6)) {
301 if (WC->serv_sock==-1) {
306 serv_printf("READ "SIZE_T_FMT"|"SIZE_T_FMT, bytes_read, total_len-bytes_read);
307 if ( (rc = StrBuf_ServGetln(Buf) > 0) && (ServerRc = GetServerStatus(Buf, NULL), ServerRc == 6) ) {
310 StrBufCutLeft(Buf, 4);
311 this_block = StrTol(Buf);
312 rc = StrBuf_ServGetBLOBBuffered(Ret, this_block);
314 syslog(LOG_INFO, "Server connection broken during download\n");
315 wc_backtrace(LOG_INFO);
316 if (WC->serv_sock > 0) close(WC->serv_sock);
317 WC->serv_sock = (-1);
326 return StrLength(Ret);
330 int client_write(StrBuf *ThisBuf) {
331 const char *ptr, *eptr;
337 ptr = ChrPtr(ThisBuf);
338 count = StrLength(ThisBuf);
341 fdflags = fcntl(WC->Hdr->http_sock, F_GETFL);
343 while ((ptr < eptr) && (WC->Hdr->http_sock != -1)) {
344 if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
346 FD_SET(WC->Hdr->http_sock, &wset);
347 if (select(WC->Hdr->http_sock + 1, NULL, &wset, NULL, NULL) == -1) {
348 syslog(LOG_INFO, "client_write: Socket select failed (%s)\n", strerror(errno));
353 if ((WC->Hdr->http_sock == -1) || ((res = write(WC->Hdr->http_sock, ptr, count)), (res == -1))) {
354 syslog(LOG_INFO, "client_write: Socket write failed (%s)\n", strerror(errno));
355 wc_backtrace(LOG_INFO);
365 int read_serv_chunk( StrBuf *Buf, size_t total_len, size_t *bytes_read) {
369 serv_printf("READ "SIZE_T_FMT"|"SIZE_T_FMT, *bytes_read, total_len-(*bytes_read));
370 if ( (rc = StrBuf_ServGetln(Buf) > 0) && (ServerRc = GetServerStatus(Buf, NULL), ServerRc == 6) ) {
371 size_t this_block = 0;
376 StrBufCutLeft(Buf, 4);
377 this_block = StrTol(Buf);
378 rc = StrBuf_ServGetBLOBBuffered(WC->WBuf, this_block);
380 syslog(LOG_INFO, "Server connection broken during download\n");
381 wc_backtrace(LOG_INFO);
382 if (WC->serv_sock > 0) close(WC->serv_sock);
383 WC->serv_sock = (-1);
393 static inline int send_http(StrBuf *Buf) {
396 return client_write_ssl(Buf);
399 return client_write(Buf);
402 * Read binary data from server into memory using a series of server READ commands.
403 * returns the read content as StrBuf
405 void serv_read_binary_to_http(StrBuf *MimeType, size_t total_len, int is_static, int detect_mime) {
407 size_t bytes_read = 0;
409 int client_con_state = 0;
412 const char *Err = NULL;
413 StrBuf *BufHeader = NULL;
418 IOBuffer WriteBuffer;
423 if (WC->Hdr->HaveRange) {
424 WC->Hdr->HaveRange++;
425 WC->Hdr->TotalBytes = total_len;
426 /* open range? or beyound file border? correct the numbers. */
427 if ((WC->Hdr->RangeTil == -1) || (WC->Hdr->RangeTil>= total_len))
428 WC->Hdr->RangeTil = total_len - 1;
429 bytes_read = WC->Hdr->RangeStart;
430 total_len = WC->Hdr->RangeTil;
433 chunked = total_len > SIZ * 10; /* TODO: disallow for HTTP / 1.0 */
436 BufHeader = NewStrBuf();
439 if ((detect_mime != 0) && (bytes_read != 0)) {
440 /* need to read first chunk to detect mime, though the client doesn't care */
441 size_t bytes_read = 0;
444 ServerRc = read_serv_chunk(
451 FreeStrBuf(&BufHeader);
455 CT = GuessMimeType(SKEY(WC->WBuf));
456 FlushStrBuf(WC->WBuf);
457 StrBufPlain(MimeType, CT, -1);
458 CheckGZipCompressionAllowed(SKEY(MimeType));
463 memset(&WriteBuffer, 0, sizeof(IOBuffer));
464 if (chunked && !DisableGzip && WC->Hdr->HR.gzip_ok) {
466 SC = StrBufNewStreamContext (eZLibEncode, &Err);
468 syslog(LOG_ERR, "Error while initializing stream context: %s", Err);
473 memset(&ReadBuffer, 0, sizeof(IOBuffer));
474 ReadBuffer.Buf = WC->WBuf;
476 WriteBuffer.Buf = NewStrBufPlain(NULL, SIZ*2);;
477 pBuf = WriteBuffer.Buf;
484 http_transmit_headers(ChrPtr(MimeType), is_static, chunked, is_gzip);
486 if (send_http(WC->HBuf) < 0) {
488 FreeStrBuf(&WriteBuffer.Buf);
489 FreeStrBuf(&BufHeader);
490 if (StrBufDestroyStreamContext(eZLibEncode, &SC, &Err) && Err) {
491 syslog(LOG_ERR, "Error while destroying stream context: %s", Err);
497 while ((bytes_read < total_len) && (ServerRc == 6) && (client_con_state == 0)) {
499 if (WC->serv_sock==-1) {
500 FlushStrBuf(WC->WBuf);
502 FreeStrBuf(&WriteBuffer.Buf);
503 FreeStrBuf(&BufHeader);
504 StrBufDestroyStreamContext(eZLibEncode, &SC, &Err);
505 if (StrBufDestroyStreamContext(eZLibEncode, &SC, &Err) && Err) {
506 syslog(LOG_ERR, "Error while destroying stream context: %s", Err);
511 ServerRc = read_serv_chunk(
522 CT = GuessMimeType(SKEY(WC->WBuf));
523 StrBufPlain(MimeType, CT, -1);
525 CheckGZipCompressionAllowed(SKEY(MimeType));
526 is_gzip = WC->Hdr->HR.gzip_ok;
528 http_transmit_headers(ChrPtr(MimeType), is_static, chunked, is_gzip);
530 client_con_state = send_http(WC->HBuf);
534 int done = (bytes_read == total_len);
535 while ((IOBufferStrLength(&ReadBuffer) > 0) && (client_con_state == 0)) {
539 rc = StrBufStreamTranscode(eZLibEncode, &WriteBuffer, &ReadBuffer, NULL, -1, SC, done, &Err);
541 if (StrLength (pBuf) > 0) {
542 StrBufPrintf(BufHeader, "%s%x\r\n",
546 client_con_state = send_http(BufHeader);
547 if (client_con_state == 0) {
548 client_con_state = send_http(pBuf);
552 } while ((rc == 1) && (StrLength(pBuf) > 0));
554 FlushStrBuf(WC->WBuf);
557 if ((chunked) && (client_con_state == 0)) {
558 StrBufPrintf(BufHeader, "%s%x\r\n",
562 client_con_state = send_http(BufHeader);
565 if (client_con_state == 0)
566 client_con_state = send_http(pBuf);
572 if (SC && StrBufDestroyStreamContext(eZLibEncode, &SC, &Err) && Err) {
573 syslog(LOG_ERR, "Error while destroying stream context: %s", Err);
575 FreeStrBuf(&WriteBuffer.Buf);
576 if ((chunked) && (client_con_state == 0)) {
577 StrBufPlain(BufHeader, HKEY("\r\n0\r\n\r\n"));
578 if (send_http(BufHeader) < 0) {
580 FreeStrBuf(&BufHeader);
584 FreeStrBuf(&BufHeader);
588 int ClientGetLine(ParsedHttpHdrs *Hdr, StrBuf *Target) {
591 const char *pch, *pchs;
592 int rlen, len, retval = 0;
596 if (StrLength(Hdr->ReadBuf) > 0) {
597 pchs = ChrPtr(Hdr->ReadBuf);
598 pch = strchr(pchs, '\n');
602 if (len > 0 && (*(pch - 1) == '\r') )
604 StrBufSub(Target, Hdr->ReadBuf, 0, len - rlen);
605 StrBufCutLeft(Hdr->ReadBuf, len + 1);
610 while (retval == 0) {
612 pchs = ChrPtr(Hdr->ReadBuf);
614 pch = strchr(pchs, '\n');
616 retval = client_read_sslbuffer(Hdr->ReadBuf, SLEEPING);
617 pchs = ChrPtr(Hdr->ReadBuf);
618 pch = strchr(pchs, '\n');
629 if ((retval > 0) && (pch != NULL)) {
632 if (len > 0 && (*(pch - 1) == '\r') )
634 StrBufSub(Target, Hdr->ReadBuf, 0, len - rlen);
635 StrBufCutLeft(Hdr->ReadBuf, len + 1);
644 return StrBufTCP_read_buffered_line_fast(Target,
655 * This is a generic function to set up a master socket for listening on
656 * a TCP port. The server shuts down if the bind fails. (IPv4/IPv6 version)
658 * ip_addr IP address to bind
659 * port_number port number to bind
660 * queue_len number of incoming connections to allow in the queue
662 int webcit_tcp_server(const char *ip_addr, int port_number, int queue_len) {
663 const char *ipv4broadcast = "0.0.0.0";
666 struct sockaddr_in6 sin6;
667 struct sockaddr_in sin4;
672 memset(&sin6, 0, sizeof(sin6));
673 memset(&sin4, 0, sizeof(sin4));
674 sin6.sin6_family = AF_INET6;
675 sin4.sin_family = AF_INET;
677 if ( (ip_addr == NULL) /* any IPv6 */
678 || (IsEmptyStr(ip_addr))
679 || (!strcmp(ip_addr, "*"))
683 sin6.sin6_addr = in6addr_any;
685 else if (!strcmp(ip_addr, "0.0.0.0")) /* any IPv4 */
688 sin4.sin_addr.s_addr = INADDR_ANY;
690 else if ((strchr(ip_addr, '.')) && (!strchr(ip_addr, ':'))) /* specific IPv4 */
693 if (inet_pton(AF_INET, ip_addr, &sin4.sin_addr) <= 0) {
694 syslog(LOG_WARNING, "Error binding to [%s] : %s\n", ip_addr, strerror(errno));
695 return (-WC_EXIT_BIND);
698 else /* specific IPv6 */
701 if (inet_pton(AF_INET6, ip_addr, &sin6.sin6_addr) <= 0) {
702 syslog(LOG_WARNING, "Error binding to [%s] : %s\n", ip_addr, strerror(errno));
703 return (-WC_EXIT_BIND);
707 if (port_number == 0) {
708 syslog(LOG_WARNING, "Cannot start: no port number specified.\n");
709 return (-WC_EXIT_BIND);
711 sin6.sin6_port = htons((u_short) port_number);
712 sin4.sin_port = htons((u_short) port_number);
714 p = getprotobyname("tcp");
716 s = socket( ((ip_version == 6) ? PF_INET6 : PF_INET), SOCK_STREAM, (p->p_proto));
718 if (IsDefault && (errno == EAFNOSUPPORT))
721 ip_addr = ipv4broadcast;
724 syslog(LOG_WARNING, "Can't create a listening socket: %s\n", strerror(errno));
725 return (-WC_EXIT_BIND);
727 /* Set some socket options that make sense. */
729 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
731 if (ip_version == 6) {
732 b = bind(s, (struct sockaddr *) &sin6, sizeof(sin6));
735 b = bind(s, (struct sockaddr *) &sin4, sizeof(sin4));
739 syslog(LOG_ERR, "Can't bind: %s\n", strerror(errno));
741 return (-WC_EXIT_BIND);
744 if (listen(s, queue_len) < 0) {
745 syslog(LOG_ERR, "Can't listen: %s\n", strerror(errno));
747 return (-WC_EXIT_BIND);
754 * Create a Unix domain socket and listen on it
755 * sockpath - file name of the unix domain socket
756 * queue_len - Number of incoming connections to allow in the queue
758 int webcit_uds_server(char *sockpath, int queue_len) {
759 struct sockaddr_un addr;
762 int actual_queue_len;
764 actual_queue_len = queue_len;
765 if (actual_queue_len < 5) actual_queue_len = 5;
767 i = unlink(sockpath);
768 if ((i != 0) && (errno != ENOENT)) {
769 syslog(LOG_WARNING, "webcit: can't unlink %s: %s\n",
770 sockpath, strerror(errno));
771 return (-WC_EXIT_BIND);
774 memset(&addr, 0, sizeof(addr));
775 addr.sun_family = AF_UNIX;
776 safestrncpy(addr.sun_path, sockpath, sizeof addr.sun_path);
778 s = socket(AF_UNIX, SOCK_STREAM, 0);
780 syslog(LOG_WARNING, "webcit: Can't create a unix domain socket: %s\n", strerror(errno));
781 return (-WC_EXIT_BIND);
784 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
785 syslog(LOG_WARNING, "webcit: Can't bind: %s\n", strerror(errno));
787 return (-WC_EXIT_BIND);
790 if (listen(s, actual_queue_len) < 0) {
791 syslog(LOG_WARNING, "webcit: Can't listen: %s\n", strerror(errno));
793 return (-WC_EXIT_BIND);
796 chmod(sockpath, 0777);
802 * Read data from the client socket.
804 * sock socket fd to read from
805 * buf buffer to read into
806 * bytes number of bytes to read
807 * timeout Number of seconds to wait before timing out
809 * Possible return values:
810 * 1 Requested number of bytes has been read.
811 * 0 Request timed out.
812 * -1 Connection is broken, or other error.
814 int client_read_to(ParsedHttpHdrs *Hdr, StrBuf *Target, int bytes, int timeout) {
823 baselen = StrLength(Target);
825 if (Hdr->Pos == NULL) {
826 Hdr->Pos = ChrPtr(Hdr->ReadBuf);
829 if (StrLength(Hdr->ReadBuf) > 0) {
830 bufremain = StrLength(Hdr->ReadBuf) - (Hdr->Pos - ChrPtr(Hdr->ReadBuf));
832 if (bytes < bufremain)
834 StrBufAppendBufPlain(Target, Hdr->Pos, bufremain, 0);
835 StrBufCutLeft(Hdr->ReadBuf, bufremain);
838 if (bytes > bufremain) {
839 while ((StrLength(Hdr->ReadBuf) + StrLength(Target) < bytes + baselen) &&
841 retval = client_read_sslbuffer(Hdr->ReadBuf, timeout);
843 StrBufAppendBuf(Target, Hdr->ReadBuf, 0); /* todo: Buf > bytes? */
847 syslog(LOG_INFO, "client_read_ssl() failed\n");
855 retval = StrBufReadBLOBBuffered(Target,
864 syslog(LOG_INFO, "client_read() failed: %s\n", Error);
865 wc_backtrace(LOG_DEBUG);
874 * Begin buffering HTTP output so we can transmit it all in one write operation later.
876 void begin_burst(void)
878 if (WC->WBuf == NULL) {
879 WC->WBuf = NewStrBufPlain(NULL, 32768);
885 * Finish buffering HTTP output. [Compress using zlib and] output with a Content-Length: header.
889 const char *ptr, *eptr;
895 if (!DisableGzip && (WC->Hdr->HR.gzip_ok))
897 if (CompressBuffer(WC->WBuf) > 0)
898 hprintf("Content-encoding: gzip\r\n");
900 syslog(LOG_ALERT, "Compression failed: %d [%s] sending uncompressed\n", errno, strerror(errno));
901 wc_backtrace(LOG_INFO);
905 if (WC->WFBuf != NULL) {
906 WildFireSerializePayload(WC->WFBuf, WC->HBuf, &WC->Hdr->nWildfireHeaders, NULL);
907 FreeStrBuf(&WC->WFBuf);
910 if (WC->Hdr->HR.prohibit_caching)
911 hprintf("Pragma: no-cache\r\nCache-Control: no-store\r\nExpires:-1\r\n");
912 hprintf("Content-length: %d\r\n\r\n", StrLength(WC->WBuf));
914 ptr = ChrPtr(WC->HBuf);
915 count = StrLength(WC->HBuf);
920 client_write_ssl(WC->HBuf);
921 client_write_ssl(WC->WBuf);
926 if (WC->Hdr->http_sock == -1) {
929 fdflags = fcntl(WC->Hdr->http_sock, F_GETFL);
931 while ((ptr < eptr) && (WC->Hdr->http_sock != -1)) {
932 if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
934 FD_SET(WC->Hdr->http_sock, &wset);
935 if (select(WC->Hdr->http_sock + 1, NULL, &wset, NULL, NULL) == -1) {
936 syslog(LOG_DEBUG, "client_write: Socket select failed (%s)\n", strerror(errno));
941 if ((WC->Hdr->http_sock == -1) ||
942 (res = write(WC->Hdr->http_sock,
945 syslog(LOG_DEBUG, "client_write: Socket write failed (%s)\n", strerror(errno));
946 wc_backtrace(LOG_INFO);
953 ptr = ChrPtr(WC->WBuf);
954 count = StrLength(WC->WBuf);
957 while ((ptr < eptr) && (WC->Hdr->http_sock != -1)) {
958 if ((fdflags & O_NONBLOCK) == O_NONBLOCK) {
960 FD_SET(WC->Hdr->http_sock, &wset);
961 if (select(WC->Hdr->http_sock + 1, NULL, &wset, NULL, NULL) == -1) {
962 syslog(LOG_INFO, "client_write: Socket select failed (%s)\n", strerror(errno));
967 if ((WC->Hdr->http_sock == -1) ||
968 (res = write(WC->Hdr->http_sock,
971 syslog(LOG_INFO, "client_write: Socket write failed (%s)\n", strerror(errno));
972 wc_backtrace(LOG_INFO);
979 return StrLength(WC->WBuf);
984 * lingering_close() a`la Apache. see
985 * http://httpd.apache.org/docs/2.0/misc/fin_wait_2.html for rationale
987 int lingering_close(int fd)
992 struct timeval tv, start;
994 gettimeofday(&start, NULL);
1000 gettimeofday(&tv, NULL);
1001 tv.tv_sec = SLEEPING - (tv.tv_sec - start.tv_sec);
1002 tv.tv_usec = start.tv_usec - tv.tv_usec;
1003 if (tv.tv_usec < 0) {
1005 tv.tv_usec += 1000000;
1009 i = select(fd + 1, &set, NULL, NULL, &tv);
1010 } while (i == -1 && errno == EINTR);
1015 i = read(fd, buf, sizeof buf);
1016 } while (i != 0 && (i != -1 || errno == EINTR));
1022 HttpNewModule_TCPSOCKETS
1023 (ParsedHttpHdrs *httpreq)
1026 httpreq->ReadBuf = NewStrBufPlain(NULL, SIZ * 4);
1030 HttpDetachModule_TCPSOCKETS
1031 (ParsedHttpHdrs *httpreq)
1034 FlushStrBuf(httpreq->ReadBuf);
1035 ReAdjustEmptyBuf(httpreq->ReadBuf, 4 * SIZ, SIZ);
1039 HttpDestroyModule_TCPSOCKETS
1040 (ParsedHttpHdrs *httpreq)
1043 FreeStrBuf(&httpreq->ReadBuf);
1048 SessionNewModule_TCPSOCKETS
1051 sess->CLineBuf = NewStrBuf();
1052 sess->MigrateReadLineBuf = NewStrBuf();
1056 SessionDestroyModule_TCPSOCKETS
1059 FreeStrBuf(&sess->CLineBuf);
1060 FreeStrBuf(&sess->ReadBuf);
1061 sess->connected = 0;
1062 sess->ReadPos = NULL;
1063 FreeStrBuf(&sess->MigrateReadLineBuf);
1064 if (sess->serv_sock > 0) {
1065 syslog(LOG_DEBUG, "Closing socket %d", sess->serv_sock);
1066 close(sess->serv_sock);
1068 sess->serv_sock = -1;