]> code.citadel.org Git - citadel.git/blobdiff - webcit/tcp_sockets.c
When trying to bind default broadcast (ipv6) fails, retry with broadcast ipv4.
[citadel.git] / webcit / tcp_sockets.c
index 9952fd9ab081057539640bec98177487fbb39de0..137df9abfc76c3d2a6330116745cb5a8fbe36977 100644 (file)
@@ -1,19 +1,13 @@
 /*
- * Copyright (c) 1987-2011 by the citadel.org team
+ * Copyright (c) 1987-2012 by the citadel.org team
  *
  * This program is open source 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.
- *
+ * it under the terms of the GNU General Public License, version 3.
+ * 
  * 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
  */
 
 /*
@@ -21,7 +15,6 @@
 #define SERV_TRACE 1
  */
 
-
 #include "webcit.h"
 #include "webserver.h"
 
@@ -172,6 +165,9 @@ int StrBuf_ServGetln(StrBuf *buf)
        const char *ErrStr = NULL;
        int rc;
        
+       if (!WCC->connected)
+               return -1;
+
        FlushStrBuf(buf);
        rc = StrBufTCP_read_buffered_line_fast(buf, 
                                               WCC->ReadBuf, 
@@ -400,13 +396,14 @@ int serv_read_binary(StrBuf *Ret, size_t total_len, StrBuf *Buf)
        wcsession *WCC = WC;
        size_t bytes_read = 0;
        size_t this_block = 0;
-       int rc;
+       int rc = 6;
+       int ServerRc = 6;
 
        if (Ret == NULL) {
                return -1;
        }
 
-       while (bytes_read < total_len) {
+       while ((bytes_read < total_len) && (ServerRc == 6)) {
 
                if (WCC->serv_sock==-1) {
                        FlushStrBuf(Ret); 
@@ -414,7 +411,8 @@ int serv_read_binary(StrBuf *Ret, size_t total_len, StrBuf *Buf)
                }
 
                serv_printf("READ "SIZE_T_FMT"|"SIZE_T_FMT, bytes_read, total_len-bytes_read);
-               if ( (rc = StrBuf_ServGetln(Buf) > 0) && (GetServerStatus(Buf, NULL) == 6) ) 
+               if ( (rc = StrBuf_ServGetln(Buf) > 0) &&
+                    (ServerRc = GetServerStatus(Buf, NULL), ServerRc == 6) ) 
                {
                        if (rc < 0)
                                return rc;
@@ -514,14 +512,17 @@ int ClientGetLine(ParsedHttpHdrs *Hdr, StrBuf *Target)
  * port_number port number to bind
  * queue_len   number of incoming connections to allow in the queue
  */
-int webcit_tcp_server(char *ip_addr, int port_number, int queue_len)
+int webcit_tcp_server(const char *ip_addr, int port_number, int queue_len)
 {
+       const char *ipv4broadcast = "0.0.0.0";
+       int IsDefault = 0;
        struct protoent *p;
        struct sockaddr_in6 sin6;
        struct sockaddr_in sin4;
        int s, i, b;
        int ip_version = 6;
 
+retry:
        memset(&sin6, 0, sizeof(sin6));
        memset(&sin4, 0, sizeof(sin4));
        sin6.sin6_family = AF_INET6;
@@ -531,6 +532,7 @@ int webcit_tcp_server(char *ip_addr, int port_number, int queue_len)
                || (IsEmptyStr(ip_addr))
                || (!strcmp(ip_addr, "*"))
        ) {
+               IsDefault = 1;
                ip_version = 6;
                sin6.sin6_addr = in6addr_any;
        }
@@ -567,7 +569,13 @@ int webcit_tcp_server(char *ip_addr, int port_number, int queue_len)
 
        s = socket( ((ip_version == 6) ? PF_INET6 : PF_INET), SOCK_STREAM, (p->p_proto));
        if (s < 0) {
-               syslog(1, "Can't create a listening socket: %s\n", strerror(errno));
+               if (IsDefault && (errno == EAFNOSUPPORT))
+               {
+                       s = 0;
+                       ip_addr = ipv4broadcast;
+                       goto retry;
+               }
+               syslog(LOG_WARNING, "Can't create a listening socket: %s\n", strerror(errno));
                return (-WC_EXIT_BIND);
        }
        /* Set some socket options that make sense. */