X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Ftcp_sockets.c;h=b4197e5d925d7dfc5e9d70ea563e6e3e97224936;hb=144e697f9fa898814b8e6a2f53d6f74bbb931fde;hp=23bdf7bea76b777eeb73e1f3eb2e86b1a93e2b30;hpb=23fcabeb4944b5e79e80a37127ed84ec8a639ed8;p=citadel.git diff --git a/webcit/tcp_sockets.c b/webcit/tcp_sockets.c index 23bdf7bea..b4197e5d9 100644 --- a/webcit/tcp_sockets.c +++ b/webcit/tcp_sockets.c @@ -1,5 +1,21 @@ /* * $Id$ + * + * Copyright (c) 1987-2010 by the citadel.org team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* @@ -153,7 +169,7 @@ int serv_getln(char *strbuf, int bufsize) FlushStrBuf(WCC->MigrateReadLineBuf); strbuf[len] = '\0'; #ifdef SERV_TRACE - lprintf(9, "%3d>%s\n", WC->serv_sock, strbuf); + lprintf(9, "%3d<<<%s\n", WC->serv_sock, strbuf); #endif return len; } @@ -164,7 +180,8 @@ int StrBuf_ServGetln(StrBuf *buf) wcsession *WCC = WC; const char *ErrStr = NULL; int rc; - + + FlushStrBuf(buf); rc = StrBufTCP_read_buffered_line_fast(buf, WCC->ReadBuf, &WCC->ReadPos, @@ -180,6 +197,15 @@ int StrBuf_ServGetln(StrBuf *buf) WCC->connected = 0; WCC->logged_in = 0; } +#ifdef SERV_TRACE + else + { + long pos=0; + if (WCC->ReadPos != NULL) + pos = WCC->ReadPos - ChrPtr(buf); + lprintf(9, "%3d<<<[%ld]%s\n", WC->serv_sock, pos, ChrPtr(buf)); + } +#endif return rc; } @@ -206,6 +232,11 @@ int StrBuf_ServGetBLOBBuffered(StrBuf *buf, long BlobSize) WCC->connected = 0; WCC->logged_in = 0; } +#ifdef SERV_TRACE + else + lprintf(9, "%3d<<serv_sock, StrLength(buf)); +#endif + return rc; } @@ -226,6 +257,11 @@ int StrBuf_ServGetBLOB(StrBuf *buf, long BlobSize) WCC->connected = 0; WCC->logged_in = 0; } +#ifdef SERV_TRACE + else + lprintf(9, "%3d<<serv_sock, StrLength(buf)); +#endif + return rc; } @@ -268,7 +304,7 @@ void serv_puts(const char *string) { wcsession *WCC = WC; #ifdef SERV_TRACE - lprintf(9, "%3d<%s\n", WC->serv_sock, string); + lprintf(9, "%3d>>>%s\n", WC->serv_sock, string); #endif FlushStrBuf(WCC->ReadBuf); WCC->ReadPos = NULL; @@ -285,7 +321,7 @@ void serv_putbuf(const StrBuf *string) { wcsession *WCC = WC; #ifdef SERV_TRACE - lprintf(9, "%3d<%s\n", WC->serv_sock, ChrPtr(string)); + lprintf(9, "%3d>>>%s\n", WC->serv_sock, ChrPtr(string)); #endif FlushStrBuf(WCC->ReadBuf); WCC->ReadPos = NULL; @@ -319,7 +355,7 @@ void serv_printf(const char *format,...) buf[len] = '\0'; serv_write(buf, len); #ifdef SERV_TRACE - lprintf(9, "<%s", buf); + lprintf(9, ">>>%s", buf); #endif } @@ -358,23 +394,25 @@ int serv_read_binary(StrBuf *Ret, size_t total_len, StrBuf *Buf) return -1; } - pch = ChrPtr(WCC->ReadBuf); - YetRead = WCC->ReadPos - pch; - if (YetRead > 0) - { - long StillThere; - - StillThere = StrLength(WCC->ReadBuf) - - YetRead; - - StrBufPlain(Ret, - WCC->ReadPos, - StillThere); - total_len -= StillThere; - } - FlushStrBuf(WCC->ReadBuf); - WCC->ReadPos = NULL; - + if (WCC->ReadPos != NULL) { + pch = ChrPtr(WCC->ReadBuf); + + YetRead = WCC->ReadPos - pch; + if (YetRead > 0) + { + long StillThere; + + StillThere = StrLength(WCC->ReadBuf) - + YetRead; + + StrBufPlain(Ret, + WCC->ReadPos, + StillThere); + total_len -= StillThere; + } + FlushStrBuf(WCC->ReadBuf); + WCC->ReadPos = NULL; + } if (total_len > 0) { rc = StrBufReadBLOB(Ret, @@ -438,10 +476,11 @@ int serv_read_binary(StrBuf *Ret, size_t total_len, StrBuf *Buf) int ClientGetLine(ParsedHttpHdrs *Hdr, StrBuf *Target) { - const char *Error, *pch, *pchs; + const char *Error; +#ifdef HAVE_OPENSSL + const char *pch, *pchs; int rlen, len, retval = 0; -#ifdef HAVE_OPENSSL if (is_https) { int ntries = 0; if (StrLength(Hdr->ReadBuf) > 0) { @@ -499,6 +538,78 @@ int ClientGetLine(ParsedHttpHdrs *Hdr, StrBuf *Target) &Error); } +#ifdef CTDL_IPV6 + +/* + * This is a generic function to set up a master socket for listening on + * a TCP port. The server shuts down if the bind fails. (IPv4/IPv6 version) + * + * ip_addr IP address to bind + * port_number port number to bind + * queue_len number of incoming connections to allow in the queue + */ +int ig_tcp_server(char *ip_addr, int port_number, int queue_len) +{ + struct protoent *p; + struct sockaddr_in6 sin; + int s, i; + + memset(&sin, 0, sizeof(sin)); + sin.sin6_family = AF_INET6; + + if ((ip_addr == NULL) || (IsEmptyStr(ip_addr)) || (!strcmp(ip_addr, "0.0.0.0"))) { + sin.sin6_addr = in6addr_any; + } else { + char bind_to[256]; + if ((strchr(ip_addr, '.')) && (!strchr(ip_addr, ':'))) { + snprintf(bind_to, sizeof bind_to, "::ffff:%s", ip_addr); + } + else { + safestrncpy(bind_to, ip_addr, sizeof bind_to); + } + if (inet_pton(AF_INET6, bind_to, &sin.sin6_addr) <= 0) { + lprintf(1, "Error binding to [%s] : %s\n", ip_addr, strerror(errno)); + return (-WC_EXIT_BIND); + } + } + + if (port_number == 0) { + lprintf(1, "Cannot start: no port number specified.\n"); + return (-WC_EXIT_BIND); + } + sin.sin6_port = htons((u_short) port_number); + + p = getprotobyname("tcp"); + + s = socket(PF_INET6, SOCK_STREAM, (p->p_proto)); + if (s < 0) { + lprintf(1, "Can't create an IPv6 socket: %s\n", strerror(errno)); + return (-WC_EXIT_BIND); + } + /* Set some socket options that make sense. */ + i = 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); + + #ifndef __APPLE__ + fcntl(s, F_SETFL, O_NONBLOCK); /* maide: this statement is incorrect + there should be a preceding F_GETFL + and a bitwise OR with the previous + fd flags */ + #endif + + if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + lprintf(1, "Can't bind: %s\n", strerror(errno)); + return (-WC_EXIT_BIND); + } + if (listen(s, queue_len) < 0) { + lprintf(1, "Can't listen: %s\n", strerror(errno)); + return (-WC_EXIT_BIND); + } + return (s); +} + +#else /* CTDL_IPV6 */ + /* * This is a generic function to set up a master socket for listening on * a TCP port. The server shuts down if the bind fails. @@ -535,20 +646,13 @@ int ig_tcp_server(char *ip_addr, int port_number, int queue_len) s = socket(PF_INET, SOCK_STREAM, (p->p_proto)); if (s < 0) { - lprintf(1, "Can't create a socket: %s\n", strerror(errno)); + lprintf(1, "Can't create an IPv4 socket: %s\n", strerror(errno)); return (-WC_EXIT_BIND); } /* Set some socket options that make sense. */ i = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); - #ifndef __APPLE__ - fcntl(s, F_SETFL, O_NONBLOCK); /* maide: this statement is incorrect - there should be a preceding F_GETFL - and a bitwise OR with the previous - fd flags */ - #endif - if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { lprintf(1, "Can't bind: %s\n", strerror(errno)); return (-WC_EXIT_BIND); @@ -560,6 +664,7 @@ int ig_tcp_server(char *ip_addr, int port_number, int queue_len) return (s); } +#endif /* CTDL_IPV6 */ /* @@ -590,8 +695,7 @@ int ig_uds_server(char *sockpath, int queue_len) s = socket(AF_UNIX, SOCK_STREAM, 0); if (s < 0) { - lprintf(1, "webcit: Can't create a socket: %s\n", - strerror(errno)); + lprintf(1, "webcit: Can't create a unix domain socket: %s\n", strerror(errno)); return (-WC_EXIT_BIND); } @@ -683,6 +787,7 @@ int client_read_to(ParsedHttpHdrs *Hdr, StrBuf *Target, int bytes, int timeout) if (retval < 0) { lprintf(2, "client_read() failed: %s\n", Error); + wc_backtrace(); return retval; } @@ -728,6 +833,11 @@ long end_burst(void) } } + if (WCC->WFBuf != NULL) { + WildFireSerializePayload(WCC->WFBuf, WCC->HBuf, &WCC->Hdr->nWildfireHeaders, NULL); + FreeStrBuf(&WCC->WFBuf); + } + if (WCC->Hdr->HR.prohibit_caching) hprintf("Pragma: no-cache\r\nCache-Control: no-store\r\nExpires:-1\r\n"); hprintf("Content-length: %d\r\n\r\n", StrLength(WCC->WBuf));