Diff for /libwww/Library/src/HTTCP.c between versions 2.39.2.2 and 2.39.2.3

version 2.39.2.2, 1995/05/16 20:11:50 version 2.39.2.3, 1995/05/17 19:16:43
Line 1038  PUBLIC int HTDoConnect ARGS5(HTNetInfo * Line 1038  PUBLIC int HTDoConnect ARGS5(HTNetInfo *
     /* If we are trying to connect to a multi-homed host then loop here until      /* If we are trying to connect to a multi-homed host then loop here until
        success or we have tried all IP-addresses */         success or we have tried all IP-addresses */
     do {      do {
                         if (net->sockfd==INVSOC) {          if (net->sockfd==INVSOC) {
                             int hosts;              int hosts;
                             if ((hosts = HTParseInet(&net->sock_addr, host, use_cur)) < 0) {              if ((hosts = HTParseInet(&net->sock_addr, host, use_cur)) < 0) {
                                 if (PROT_TRACE)                  if (PROT_TRACE)
                                     fprintf(TDEST, "HTDoConnect. Can't locate remote host `%s\'\n", host);                      fprintf(TDEST, "HTDoConnect. Can't locate remote host `%s\'\n", host);
                                 HTErrorAdd(net->request, ERR_FATAL, NO, HTERR_NO_REMOTE_HOST,                  HTErrorAdd(net->request, ERR_FATAL, NO, HTERR_NO_REMOTE_HOST,
                                            (void *) host, strlen(host), "HTDoConnect");                             (void *) host, strlen(host), "HTDoConnect");
                                 break;                  break;
                             }              }
                             if (!net->addressCount && hosts > 1)              if (!net->addressCount && hosts > 1)
                                         net->addressCount = hosts;                  net->addressCount = hosts;
 #ifdef DECNET  #ifdef DECNET
                             if ((net->sockfd=socket(AF_DECnet, SOCK_STREAM, 0))==INVSOC)              if ((net->sockfd=socket(AF_DECnet, SOCK_STREAM, 0))==INVSOC)
 #else  #else
                             if ((net->sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVSOC)              if ((net->sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVSOC)
 #endif  #endif
                             {              {
                                         HTErrorSysAdd(net->request, ERR_FATAL, socerrno, NO, "socket");                  HTErrorSysAdd(net->request, ERR_FATAL, socerrno, NO, "socket");
                                         break;                  break;
                             }              }
                             if (addr)              if (addr)
                                         *addr = ntohl(net->sock_addr.sin_addr.s_addr);                  *addr = ntohl(net->sock_addr.sin_addr.s_addr);
                             if (PROT_TRACE)              if (PROT_TRACE)
                                         fprintf(TDEST, "HTDoConnect. Created socket number %d\n",                  fprintf(TDEST, "HTDoConnect. Created socket number %d\n",
                                                 net->sockfd);                          net->sockfd);
   
                             /* If non-blocking protocol then change socket status              /* If non-blocking protocol then change socket status
                             ** I use FCNTL so that I can ask the status before I set it.               ** I use FCNTL so that I can ask the status before I set it.
                             ** See W. Richard Stevens (Advan. Prog. in UNIX environment, p.364)               ** See W. Richard Stevens (Advan. Prog. in UNIX environment, p.364)
                             ** Be CAREFULL with the old `O_NDELAY' - it will not work as read()               ** Be CAREFULL with the old `O_NDELAY' - it will not work as read()
                             ** returns 0 when blocking and NOT -1. FNDELAY is ONLY for BSD and               ** returns 0 when blocking and NOT -1. FNDELAY is ONLY for BSD and
                             ** does NOT work on SVR4 systems. O_NONBLOCK is POSIX.               ** does NOT work on SVR4 systems. O_NONBLOCK is POSIX.
                             */               */
                             if (!HTProtocolBlocking(net->request)) {              if (!HTProtocolBlocking(net->request)) {
 #ifdef _WINDOWS   #ifdef _WINDOWS 
                                 {               /* begin windows scope  */                  {               /* begin windows scope  */
                                     HTRequest * rq = net->request;                      HTRequest * rq = net->request;
                                     long levents = FD_READ | FD_WRITE | FD_ACCEPT |                       long levents = FD_READ | FD_WRITE | FD_ACCEPT | 
                                         FD_CONNECT | FD_CLOSE ;                          FD_CONNECT | FD_CLOSE ;
                                     int rv = 0 ;                      int rv = 0 ;
                                                                           
 #ifndef _WIN32            #ifndef _WIN32          
                                     if (net->request->hwnd == 0) {                      if (net->request->hwnd == 0) {
                                                                                   
                                     }                      }
 #endif   #endif 
                     /* N.B WSAAsyncSelect() turns on non-blocking I/O */                      /* N.B WSAAsyncSelect() turns on non-blocking I/O */
   
                                     if (net->request->hwnd != 0) {                      if (net->request->hwnd != 0) {
                                         rv = WSAAsyncSelect( net->sockfd, rq->hwnd,                           rv = WSAAsyncSelect( net->sockfd, rq->hwnd, 
                                                             rq->winMsg, levents);                                              rq->winMsg, levents);
                                         if (rv == SOCKET_ERROR) {                          if (rv == SOCKET_ERROR) {
                                             status = -1 ;                              status = -1 ;
                                             if (PROT_TRACE)                               if (PROT_TRACE) 
                                                 fprintf(TDEST,                                   fprintf(TDEST, 
                                                         "HTDoConnect: WSAAsyncSelect() fails: %d\n",                                           "HTDoConnect: WSAAsyncSelect() fails: %d\n", 
                                                         WSAGetLastError());                                          WSAGetLastError());
                                         } /* error returns */                          } /* error returns */
                                     }                      } else {
                                     else {                          int enable = 1 ;
                                         int enable = 1 ;                          status = IOCTL(net->sockfd, FIONBIO, &enable);
                                         status = IOCTL(net->sockfd, FIONBIO, &enable);                      }
                                     }                  } /* end scope */
                                 } /* end scope */  
 #else   #else 
 #if defined(VMS)  #if defined(VMS)
                                 {                  {
                                     int enable = 1;                      int enable = 1;
                                     status = IOCTL(net->sockfd, FIONBIO, &enable);                      status = IOCTL(net->sockfd, FIONBIO, &enable);
                                 }                  }
 #else  #else
                                 if((status = FCNTL(net->sockfd, F_GETFL, 0)) != -1) {                  if((status = FCNTL(net->sockfd, F_GETFL, 0)) != -1) {
                                     status |= O_NONBLOCK;                           /* POSIX */                      status |= O_NONBLOCK; /* POSIX */
                                     status = FCNTL(net->sockfd, F_SETFL, status);                      status = FCNTL(net->sockfd, F_SETFL, status);
                                 }                  }
 #endif /* VMS */  #endif /* VMS */
 #endif /* WINDOW */  #endif /* WINDOW */
                                 if (status == -1) {                  if (status == -1) {
                                     if (PROT_TRACE)                      if (PROT_TRACE)
                                                 fprintf(TDEST, "HTDoConnect. Can NOT make socket non-blocking\n");                          fprintf(TDEST, "HTDoConnect. Can NOT make socket non-blocking\n");
                                 } else if (PROT_TRACE)                  } else if (PROT_TRACE)
                                     fprintf(TDEST, "HTDoConnect. Using NON_BLOCKING I/O\n");                      fprintf(TDEST, "HTDoConnect. Using NON_BLOCKING I/O\n");
                             }              }
                           
                             /* If multi-homed host then start timer on connection */              /* If multi-homed host then start timer on connection */
                             if (net->addressCount >= 1)              if (net->addressCount >= 1)
                                         net->connecttime = time(NULL);                  net->connecttime = time(NULL);
                 } /* IF socket is invalid */          } /* IF socket is invalid */
           
                 /* Check for interrupt */          /* Check for interrupt */
           if (HTThreadIntr(net->sockfd)) {
                 if (HTThreadIntr(net->sockfd)) {                /* connect call was interrupted */              if (NETCLOSE(net->sockfd) < 0)
                     if (NETCLOSE(net->sockfd) < 0)                  HTErrorSysAdd(net->request, ERR_FATAL, socerrno,NO,"NETCLOSE");
                                 HTErrorSysAdd(net->request, ERR_FATAL, socerrno,NO,"NETCLOSE");              HTThreadState(net->sockfd, THD_CLOSE);
                     HTThreadState(net->sockfd, THD_CLOSE);              net->sockfd = INVSOC;
                     net->sockfd = INVSOC;              free(p1);
                     free(p1);              return HT_INTERRUPTED;
                     return HT_INTERRUPTED;          }
                 }          
           /* Do a connect */
                 /* Do a connect */          status = connect(net->sockfd, (struct sockaddr *) &net->sock_addr,
                            sizeof(net->sock_addr));
                 status = connect(net->sockfd, (struct sockaddr *) &net->sock_addr,          /*
                                  sizeof(net->sock_addr));           * According to the Sun man page for connect:
                 /*           *     EINPROGRESS         The socket is non-blocking and the  con-
                  * According to the Sun man page for connect:           *                         nection cannot be completed immediately.
                  *     EINPROGRESS         The socket is non-blocking and the  con-           *                         It is possible to select(2) for  comple-
                  *                         nection cannot be completed immediately.           *                         tion  by  selecting the socket for writ-
                  *                         It is possible to select(2) for  comple-           *                         ing.
                  *                         tion  by  selecting the socket for writ-           * According to the Motorola SVR4 man page for connect:
                  *                         ing.           *     EAGAIN              The socket is non-blocking and the  con-
                  * According to the Motorola SVR4 man page for connect:           *                         nection cannot be completed immediately.
                  *     EAGAIN              The socket is non-blocking and the  con-           *                         It is possible to select for  completion
                  *                         nection cannot be completed immediately.           *                         by  selecting  the  socket  for writing.
                  *                         It is possible to select for  completion           *                         However, this is only  possible  if  the
                  *                         by  selecting  the  socket  for writing.           *                         socket  STREAMS  module  is  the topmost
                  *                         However, this is only  possible  if  the           *                         module on  the  protocol  stack  with  a
                  *                         socket  STREAMS  module  is  the topmost           *                         write  service  procedure.  This will be
                  *                         module on  the  protocol  stack  with  a           *                         the normal case.
                  *                         write  service  procedure.  This will be           */
                  *                         the normal case.          
                  */  
   
 #ifdef EAGAIN  #ifdef EAGAIN
                 if ((status < 0) && ((socerrno==EINPROGRESS) || (socerrno==EAGAIN)))          if ((status < 0) && ((socerrno==EINPROGRESS) || (socerrno==EAGAIN)))
 #else   #else 
 #ifdef WSAEWOULDBLOCK      /* WinSock API */  #ifdef WSAEWOULDBLOCK      /* WinSock API */
                 if ((status == SOCKET_ERROR) && (socerrno == WSAEWOULDBLOCK))          if ((status == SOCKET_ERROR) && (socerrno == WSAEWOULDBLOCK))
 #else  #else
                 if ((status < 0) && (socerrno == EINPROGRESS))          if ((status < 0) && (socerrno == EINPROGRESS))
 #endif /* WSAEWOULDBLOCK */  #endif /* WSAEWOULDBLOCK */
 #endif /* EAGAIN */  #endif /* EAGAIN */
                 {          {
                     if (PROT_TRACE)              if (PROT_TRACE)
                                 fprintf(TDEST, "HTDoConnect. WOULD BLOCK `%s'\n", host);                  fprintf(TDEST, "HTDoConnect. WOULD BLOCK `%s'\n", host);
                     HTThreadState(net->sockfd, THD_SET_WRITE);              HTThreadState(net->sockfd, THD_SET_WRITE);
               free(p1);
               return HT_WOULD_BLOCK;
           }
           
           /* We have 4 situations: single OK, Pb and multi OK, pb */
           if (net->addressCount >= 1) {
               net->connecttime = time((long *)0) - net->connecttime;
               if (status < 0) {                                    /* multi PB */
                   if (socerrno == EISCONN) { /* connect multi after would block*/
                       HTThreadState(net->sockfd, THD_CLR_WRITE);
                       HTTCPAddrWeights(host, net->connecttime);
                     free(p1);                      free(p1);
                     return HT_WOULD_BLOCK;                      net->addressCount = 0;
                       if (PROT_TRACE)
                           fprintf(TDEST, "HTDoConnect: Socket %ld already connected\n", net->sockfd) ;
                       return 0;
                 }                  }
   
                 if (net->addressCount >= 1) {                  HTErrorSysAdd(net->request, ERR_NON_FATAL, socerrno, NO,
                     net->connecttime = time((long *)0) - net->connecttime;                                "connect");
                     if (status < 0) {  
                                 if (socerrno == EISCONN) {  /* connect multi after would block */                  /* I have added EINVAL `invalid argument' as this is what I 
                                     HTThreadState(net->sockfd, THD_CLR_WRITE);                     get back from a non-blocking connect where I should 
                                     HTTCPAddrWeights(host, net->connecttime);                     get `connection refused' on SVR4 */
                                     free(p1);  
                                     net->addressCount = 0;  
                                         if (PROT_TRACE)  
                                                 fprintf(TDEST, "HTDoConnect: Socket %ld already connected\n", net->sockfd) ;  
                                     return 0;  
                         }  
   
                         HTErrorSysAdd(net->request, ERR_NON_FATAL, socerrno, NO,  
                                       "connect");  
   
                         /* I have added EINVAL `invalid argument' as this is what I   
                            get back from a non-blocking connect where I should   
                            get `connection refused' on SVR4 */  
   
                         if (socerrno==ECONNREFUSED || socerrno==ETIMEDOUT ||                  if (socerrno==ECONNREFUSED || socerrno==ETIMEDOUT ||
                             socerrno==ENETUNREACH || socerrno==EHOSTUNREACH ||                      socerrno==ENETUNREACH || socerrno==EHOSTUNREACH ||
 #ifdef __srv4__  #ifdef __srv4__
                             socerrno==EHOSTDOWN || socerrno==EINVAL)                      socerrno==EHOSTDOWN || socerrno==EINVAL)
 #else  #else
                             socerrno==EHOSTDOWN)                      socerrno==EHOSTDOWN)
 #endif  #endif
                             net->connecttime += TCP_DELAY;                      net->connecttime += TCP_DELAY;
                         else                  else
                             net->connecttime += TCP_PENALTY;                      net->connecttime += TCP_PENALTY;
   
                         if (NETCLOSE(net->sockfd) < 0)                  if (NETCLOSE(net->sockfd) < 0)
                             HTErrorSysAdd(net->request, ERR_FATAL, socerrno, NO,                           HTErrorSysAdd(net->request, ERR_FATAL, socerrno, NO, 
                                           "NETCLOSE");                                        "NETCLOSE");
                         HTThreadState(net->sockfd, THD_CLOSE);                  HTThreadState(net->sockfd, THD_CLOSE);
                         net->sockfd = INVSOC;                  net->sockfd = INVSOC;
                         HTTCPAddrWeights(host, net->connecttime);                  HTTCPAddrWeights(host, net->connecttime);
                     } else {                               /* Connect on multi-homed */              } else {                                             /* multi OK */
                                 HTTCPAddrWeights(host, net->connecttime);                  HTTCPAddrWeights(host, net->connecttime);
                                 free(p1);                  free(p1);
                                 net->addressCount = 0;                  net->addressCount = 0;
                                 return 0;                  return 0;
                     }              }
                 } else if (status < 0) {          } else if (status < 0) {                                /* single PB */
                     if (socerrno==EISCONN) {     /* Connect single after would block */              if (socerrno==EISCONN) {     /* Connect single after would block */
                                 HTThreadState(net->sockfd, THD_CLR_WRITE);                  HTThreadState(net->sockfd, THD_CLR_WRITE);
                                 net->addressCount = 0;                  net->addressCount = 0;
                                 free(p1);                  free(p1);
                                 return 0;                  return 0;
                     } else {              } else {
                                 HTErrorSysAdd(net->request, ERR_FATAL, socerrno, NO,                  HTErrorSysAdd(net->request, ERR_FATAL, socerrno, NO,
                                               "connect");                            "connect");
                                 HTTCPCacheRemoveHost(host);                  HTTCPCacheRemoveHost(host);
                                 if (NETCLOSE(net->sockfd) < 0)                  if (NETCLOSE(net->sockfd) < 0)
                                     HTErrorSysAdd(net->request, ERR_FATAL, socerrno, NO,                      HTErrorSysAdd(net->request, ERR_FATAL, socerrno, NO,
                                                   "NETCLOSE");                                    "NETCLOSE");
                                 HTThreadState(net->sockfd, THD_CLOSE);                  HTThreadState(net->sockfd, THD_CLOSE);
                                 break;                  break;
                     }              }
                 } else {                                  /* Connect on single homed */          } else {                                                /* single OK */
                     free(p1);              free(p1);
                     net->addressCount = 0;              net->addressCount = 0;
                     return 0;              return 0;
                 }          }
     } while (--net->addressCount);      } while (--net->addressCount);                       /* End of mega loop */
   
     if (PROT_TRACE)      if (PROT_TRACE)
                 fprintf(TDEST, "HTDoConnect. Connect failed\n");          fprintf(TDEST, "HTDoConnect. Connect failed\n");
     free (p1);      free (p1);
     net->addressCount = 0;      net->addressCount = 0;
     net->sockfd = INVSOC;      net->sockfd = INVSOC;

Removed from v.2.39.2.2  
changed lines
  Added in v.2.39.2.3


Webmaster