]>
git.saurik.com Git - apt.git/blob - methods/connect.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: connect.cc,v 1.4 1999/11/19 05:01:54 jgg Exp $
4 /* ######################################################################
6 Connect - Replacement connect call
8 ##################################################################### */
10 // Include Files /*{{{*/
12 #include <apt-pkg/error.h>
13 #include <apt-pkg/fileutl.h>
20 #include <netinet/in.h>
21 #include <sys/socket.h>
22 #include <arpa/inet.h>
25 #include "rfc2553emu.h"
28 static string LastHost
;
29 static int LastPort
= 0;
30 static struct addrinfo
*LastHostAddr
= 0;
31 static struct addrinfo
*LastUsed
= 0;
33 // DoConnect - Attempt a connect operation /*{{{*/
34 // ---------------------------------------------------------------------
35 /* This helper function attempts a connection to a single address. */
36 static bool DoConnect(struct addrinfo
*Addr
,string Host
,
37 unsigned long TimeOut
,int &Fd
,pkgAcqMethod
*Owner
)
39 // Show a status indicator
40 char Name
[NI_MAXHOST
];
42 getnameinfo(Addr
->ai_addr
,Addr
->ai_addrlen
,
43 Name
,sizeof(Name
),0,0,NI_NUMERICHOST
);
44 Owner
->Status("Connecting to %s (%s)",Host
.c_str(),Name
);
47 if ((Fd
= socket(Addr
->ai_family
,Addr
->ai_socktype
,
48 Addr
->ai_protocol
)) < 0)
49 return _error
->Errno("socket","Could not create a socket");
52 if (connect(Fd
,Addr
->ai_addr
,Addr
->ai_addrlen
) < 0 &&
54 return _error
->Errno("connect","Cannot initiate the connection "
55 "to %s (%s).",Host
.c_str(),Name
);
57 /* This implements a timeout for connect by opening the connection
59 if (WaitFd(Fd
,true,TimeOut
) == false)
60 return _error
->Error("Could not connect to %s (%s), "
61 "connection timed out",Host
.c_str(),Name
);
63 // Check the socket for an error condition
65 unsigned int Len
= sizeof(Err
);
66 if (getsockopt(Fd
,SOL_SOCKET
,SO_ERROR
,&Err
,&Len
) != 0)
67 return _error
->Errno("getsockopt","Failed");
70 return _error
->Error("Could not connect to %s (%s).",Host
.c_str(),Name
);
75 // Connect - Connect to a server /*{{{*/
76 // ---------------------------------------------------------------------
77 /* Performs a connection to the server */
78 bool Connect(string Host
,int Port
,const char *Service
,int DefPort
,int &Fd
,
79 unsigned long TimeOut
,pkgAcqMethod
*Owner
)
81 if (_error
->PendingError() == true)
84 /* We used a cached address record.. Yes this is against the spec but
85 the way we have setup our rotating dns suggests that this is more
87 if (LastHost
!= Host
|| LastPort
!= Port
)
89 Owner
->Status("Connecting to %s",Host
.c_str());
94 snprintf(S
,sizeof(S
),"%u",Port
);
96 snprintf(S
,sizeof(S
),"%s",Service
);
98 // Free the old address structure
99 if (LastHostAddr
!= 0)
101 freeaddrinfo(LastHostAddr
);
105 // We only understand SOCK_STREAM sockets.
106 struct addrinfo Hints
;
107 memset(&Hints
,0,sizeof(Hints
));
108 Hints
.ai_socktype
= SOCK_STREAM
;
109 Hints
.ai_protocol
= IPPROTO_TCP
; // Right?
111 // Resolve both the host and service simultaneously
115 if ((Res
= getaddrinfo(Host
.c_str(),S
,&Hints
,&LastHostAddr
)) != 0 ||
118 if (Res
== EAI_NONAME
|| Res
== EAI_SERVICE
)
122 snprintf(S
,sizeof(S
),"%u",DefPort
);
126 return _error
->Error("Could not resolve '%s'",Host
.c_str());
129 return _error
->Error("Something wicked happend resolving '%s/%s'",
135 if (LastHostAddr
->ai_family
== AF_UNIX
)
136 return _error
->Error("getaddrinfo returned a unix domain socket\n");
143 // Get the printable IP address
144 struct addrinfo
*CurHost
= LastHostAddr
;
150 if (DoConnect(CurHost
,Host
,TimeOut
,Fd
,Owner
) == true)
158 CurHost
= CurHost
->ai_next
;