Multiprotocol connect
authorArch Librarian <arch@canonical.com>
Mon, 20 Sep 2004 16:53:53 +0000 (16:53 +0000)
committerArch Librarian <arch@canonical.com>
Mon, 20 Sep 2004 16:53:53 +0000 (16:53 +0000)
Author: jgg
Date: 1999-05-29 03:25:03 GMT
Multiprotocol connect

methods/connect.cc [new file with mode: 0644]
methods/connect.h [new file with mode: 0644]
methods/ftp.cc
methods/http.cc
methods/makefile

diff --git a/methods/connect.cc b/methods/connect.cc
new file mode 100644 (file)
index 0000000..a7ef8c6
--- /dev/null
@@ -0,0 +1,143 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                                                         /*{{{*/
+// $Id: connect.cc,v 1.1 1999/05/29 03:25:03 jgg Exp $
+/* ######################################################################
+
+   Connect - Replacement connect call
+   
+   ##################################################################### */
+                                                                       /*}}}*/
+// Include Files                                                       /*{{{*/
+#include "connect.h"
+#include <apt-pkg/error.h>
+#include <apt-pkg/fileutl.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+
+// Internet stuff
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "rfc2553emu.h"
+                                                                       /*}}}*/
+
+static string LastHost;
+static int LastPort = 0;
+static struct addrinfo *LastHostAddr = 0;
+static struct addrinfo *LastUsed = 0;
+
+// DoConnect - Attempt a connect operation                             /*{{{*/
+// ---------------------------------------------------------------------
+/* This helper function attempts a connection to a single address. */
+static bool DoConnect(struct addrinfo *Addr,string Host,
+                     unsigned long TimeOut,int &Fd,pkgAcqMethod *Owner)
+{
+   // Show a status indicator
+   char Name[NI_MAXHOST];
+   Name[0] = 0;
+   getnameinfo(Addr->ai_addr,Addr->ai_addrlen,
+              Name,sizeof(Name),0,0,NI_NUMERICHOST);
+   Owner->Status("Connecting to %s (%s)",Host.c_str(),Name);
+   
+   // Get a socket
+   if ((Fd = socket(Addr->ai_family,Addr->ai_socktype,
+                   Addr->ai_protocol)) < 0)
+      return _error->Errno("socket","Could not create a socket");
+   
+   SetNonBlock(Fd,true);
+   if (connect(Fd,Addr->ai_addr,Addr->ai_addrlen) < 0 &&
+       errno != EINPROGRESS)
+      return _error->Errno("connect","Cannot initiate the connection "
+                          "to %s (%s).",Host.c_str(),Name);
+   
+   /* This implements a timeout for connect by opening the connection
+      nonblocking */
+   if (WaitFd(Fd,true,TimeOut) == false)
+      return _error->Error("Could not connect to %s (%s), "
+                          "connection timed out",Host.c_str(),Name);
+   
+   // Check the socket for an error condition
+   unsigned int Err;
+   unsigned int Len = sizeof(Err);
+   if (getsockopt(Fd,SOL_SOCKET,SO_ERROR,&Err,&Len) != 0)
+      return _error->Errno("getsockopt","Failed");
+   
+   if (Err != 0)
+      return _error->Error("Could not connect to %s (%s).",Host.c_str(),Name);
+
+   return true;
+}
+                                                                       /*}}}*/
+// Connect - Connect to a server                                               /*{{{*/
+// ---------------------------------------------------------------------
+/* Performs a connection to the server */
+bool Connect(string Host,int Port,const char *Service,int &Fd,
+            unsigned long TimeOut,pkgAcqMethod *Owner)
+{
+   if (_error->PendingError() == true)
+      return false;
+   
+   /* We used a cached address record.. Yes this is against the spec but
+      the way we have setup our rotating dns suggests that this is more
+      sensible */
+   if (LastHost != Host || LastPort != Port)
+   {
+      Owner->Status("Connecting to %s",Host.c_str());
+
+      // Lookup the host
+      char S[300];
+      if (Port != 0)
+        snprintf(S,sizeof(S),"%u",Port);
+      else
+        snprintf(S,sizeof(S),"%s",Service);
+
+      // Free the old address structure
+      if (LastHostAddr != 0)
+      {
+        freeaddrinfo(LastHostAddr);
+        LastHostAddr = 0;
+      }
+      
+      // We only understand SOCK_STREAM sockets.
+      struct addrinfo Hints;
+      memset(&Hints,0,sizeof(Hints));
+      Hints.ai_socktype = SOCK_STREAM;
+      
+      // Resolve both the host and service simultaneously
+      if (getaddrinfo(Host.c_str(),S,&Hints,&LastHostAddr) != 0 ||
+         LastHostAddr == 0)
+        return _error->Error("Could not resolve '%s'",Host.c_str());
+
+      LastHost = Host;
+      LastPort = Port;
+      LastUsed = 0;
+   }
+
+   // Get the printable IP address
+   struct addrinfo *CurHost = LastHostAddr;
+   if (LastUsed != 0)
+       CurHost = LastUsed;
+   
+   while (CurHost != 0)
+   {
+      if (DoConnect(CurHost,Host,TimeOut,Fd,Owner) == true)
+      {
+        LastUsed = CurHost;
+        return true;
+      }      
+      close(Fd);
+      Fd = -1;
+      
+      CurHost = CurHost->ai_next;
+      LastUsed = 0;
+      if (CurHost != 0)
+        _error->Discard();
+   }
+   
+   return false;
+}
+                                                                       /*}}}*/
diff --git a/methods/connect.h b/methods/connect.h
new file mode 100644 (file)
index 0000000..3af4992
--- /dev/null
@@ -0,0 +1,19 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                                                         /*{{{*/
+// $Id: connect.h,v 1.1 1999/05/29 03:25:03 jgg Exp $
+/* ######################################################################
+
+   Connect - Replacement connect call
+   
+   ##################################################################### */
+                                                                       /*}}}*/
+#ifndef CONNECT_H
+#define CONNECT_H
+
+#include <string>
+#include <apt-pkg/acquire-method.h>
+
+bool Connect(string To,int Port,const char *Service,int &Fd,
+            unsigned long TimeOut,pkgAcqMethod *Owner);
+
+#endif
index efc50c2..7bd0a3e 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: ftp.cc,v 1.12 1999/05/28 07:04:45 jgg Exp $
+// $Id: ftp.cc,v 1.13 1999/05/29 03:25:03 jgg Exp $
 /* ######################################################################
 
    HTTP Aquire Method - This is the FTP aquire method for APT.
@@ -36,6 +36,7 @@
 #include <netdb.h>
 
 #include "rfc2553emu.h"
+#include "connect.h"
 #include "ftp.h"
                                                                        /*}}}*/
 
@@ -81,9 +82,6 @@ void FTPConn::Close()
 // ---------------------------------------------------------------------
 /* Connect to the server using a non-blocking connection and perform a 
    login. */
-string LastHost;
-int LastPort = 0;
-struct addrinfo *LastHostAddr = 0;
 bool FTPConn::Open(pkgAcqMethod *Owner)
 {
    // Use the already open connection if possible.
@@ -125,70 +123,14 @@ bool FTPConn::Open(pkgAcqMethod *Owner)
         Port = Proxy.Port;
       Host = Proxy.Host;
    }
-   
-   /* We used a cached address record.. Yes this is against the spec but
-      the way we have setup our rotating dns suggests that this is more
-      sensible */
-   if (LastHost != Host || LastPort != Port)
-   {
-      Owner->Status("Connecting to %s",Host.c_str());
-
-      // Lookup the host
-      char S[30] = "ftp";
-      if (Port != 0)
-        snprintf(S,sizeof(S),"%u",Port);
-
-      // Free the old address structure
-      if (LastHostAddr != 0)
-      {
-        freeaddrinfo(LastHostAddr);
-        LastHostAddr = 0;
-      }
-      
-      // We only understand SOCK_STREAM sockets.
-      struct addrinfo Hints;
-      memset(&Hints,0,sizeof(Hints));
-      Hints.ai_socktype = SOCK_STREAM;
-      
-      // Resolve both the host and service simultaneously
-      if (getaddrinfo(Host.c_str(),S,&Hints,&LastHostAddr) != 0 ||
-         LastHostAddr == 0)
-        return _error->Error("Could not resolve '%s'",Host.c_str());
 
-      LastHost = Host;
-      LastPort = Port;
-   }
-
-   // Get the printable IP address
-   char Name[NI_MAXHOST];
-   Name[0] = 0;
-   getnameinfo(LastHostAddr->ai_addr,LastHostAddr->ai_addrlen,
-              Name,sizeof(Name),0,0,NI_NUMERICHOST);
-   Owner->Status("Connecting to %s (%s)",Host.c_str(),Name);
+   // Connect to the remote server
+   if (Connect(Host,Port,"ftp",ServerFd,TimeOut,Owner) == false)
+      return false;
+   socklen_t Len = sizeof(Peer);
+   if (getpeername(ServerFd,(sockaddr *)&Peer,&Len) != 0)
+      return _error->Errno("getpeername","Unable to determine the peer name");
    
-   // Get a socket
-   if ((ServerFd = socket(LastHostAddr->ai_family,LastHostAddr->ai_socktype,
-                         LastHostAddr->ai_protocol)) < 0)
-      return _error->Errno("socket","Could not create a socket");
-   SetNonBlock(ServerFd,true);
-   if (connect(ServerFd,LastHostAddr->ai_addr,LastHostAddr->ai_addrlen) < 0 &&
-       errno != EINPROGRESS)
-      return _error->Errno("connect","Cannot initiate the connection "
-                          "to %s (%s).",Host.c_str(),Name);
-   Peer = *((struct sockaddr_in *)LastHostAddr->ai_addr);
-      
-   /* This implements a timeout for connect by opening the connection
-      nonblocking */
-   if (WaitFd(ServerFd,true,TimeOut) == false)
-      return _error->Error("Could not connect to %s (%s), "
-                          "connection timed out",Host.c_str(),Name);
-   unsigned int Err;
-   unsigned int Len = sizeof(Err);
-   if (getsockopt(ServerFd,SOL_SOCKET,SO_ERROR,&Err,&Len) != 0)
-      return _error->Errno("getsockopt","Failed");
-   if (Err != 0)
-      return _error->Error("Could not connect to %s (%s).",Host.c_str(),Name);
-
    Owner->Status("Logging in");
    return Login();
 }
index 4e659cc..f014193 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: http.cc,v 1.33 1999/05/28 07:04:45 jgg Exp $
+// $Id: http.cc,v 1.34 1999/05/29 03:25:03 jgg Exp $
 /* ######################################################################
 
    HTTP Aquire Method - This is the HTTP aquire method for APT.
 #include <errno.h>
 
 // Internet stuff
-/*#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netdb.h>*/
+#include <netdb.h>
 
+#include "connect.h"
 #include "rfc2553emu.h"
 #include "http.h"
 
@@ -306,67 +304,9 @@ bool ServerState::Open()
       Host = Proxy.Host;
    }
    
-   /* We used a cached address record.. Yes this is against the spec but
-      the way we have setup our rotating dns suggests that this is more
-      sensible */
-   if (LastHost != Host || LastPort != Port)
-   {
-      Owner->Status("Connecting to %s",Host.c_str());
-
-      // Lookup the host
-      char S[30] = "http";
-      if (Port != 0)
-        snprintf(S,sizeof(S),"%u",Port);
-
-      // Free the old address structure
-      if (LastHostAddr != 0)
-      {
-        freeaddrinfo(LastHostAddr);
-        LastHostAddr = 0;
-      }
-      
-      // We only understand SOCK_STREAM sockets.
-      struct addrinfo Hints;
-      memset(&Hints,0,sizeof(Hints));
-      Hints.ai_socktype = SOCK_STREAM;
-      
-      // Resolve both the host and service simultaneously
-      if (getaddrinfo(Host.c_str(),S,&Hints,&LastHostAddr) != 0 ||
-         LastHostAddr == 0)
-        return _error->Error("Could not resolve '%s'",Host.c_str());
-
-      LastHost = Host;
-      LastPort = Port;
-   }
-
-   // Get the printable IP address
-   char Name[NI_MAXHOST];
-   Name[0] = 0;
-   getnameinfo(LastHostAddr->ai_addr,LastHostAddr->ai_addrlen,
-              Name,sizeof(Name),0,0,NI_NUMERICHOST);
-   Owner->Status("Connecting to %s (%s)",Host.c_str(),Name);
-   
-   // Get a socket
-   if ((ServerFd = socket(LastHostAddr->ai_family,LastHostAddr->ai_socktype,
-                         LastHostAddr->ai_protocol)) < 0)
-      return _error->Errno("socket","Could not create a socket");
-   SetNonBlock(ServerFd,true);
-   if (connect(ServerFd,LastHostAddr->ai_addr,LastHostAddr->ai_addrlen) < 0 &&
-       errno != EINPROGRESS)
-      return _error->Errno("connect","Cannot initiate the connection "
-                          "to %s (%s).",Host.c_str(),Name);
-
-   /* This implements a timeout for connect by opening the connection
-      nonblocking */
-   if (WaitFd(ServerFd,true,TimeOut) == false)
-      return _error->Error("Could not connect to %s (%s), "
-                          "connection timed out",Host.c_str(),Name);
-   unsigned int Err;
-   unsigned int Len = sizeof(Err);
-   if (getsockopt(ServerFd,SOL_SOCKET,SO_ERROR,&Err,&Len) != 0)
-      return _error->Errno("getsockopt","Failed");
-   if (Err != 0)
-      return _error->Error("Could not connect to %s (%s).",Host.c_str(),Name);
+   // Connect to the remote server
+   if (Connect(Host,Port,"http",ServerFd,TimeOut,Owner) == false)
+      return false;
    
    return true;
 }
index 4345307..32ec346 100644 (file)
@@ -36,14 +36,14 @@ include $(PROGRAM_H)
 
 # The http method
 PROGRAM=http
-SLIBS = -lapt-pkg 
+SLIBS = -lapt-pkg
 LIB_MAKES = apt-pkg/makefile
-SOURCE = http.cc rfc2553emu.cc
+SOURCE = http.cc rfc2553emu.cc connect.cc
 include $(PROGRAM_H)
 
 # The ftp method
 PROGRAM=ftp
-SLIBS = -lapt-pkg 
+SLIBS = -lapt-pkg
 LIB_MAKES = apt-pkg/makefile
-SOURCE = ftp.cc rfc2553emu.cc
+SOURCE = ftp.cc rfc2553emu.cc connect.cc
 include $(PROGRAM_H)