summaryrefslogtreecommitdiff
path: root/src/SocketCore.cc
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2009-12-07 15:04:33 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2009-12-07 15:04:33 +0000
commitcc4a14a1bcfadba7b7540b911bf659f7844d58fc (patch)
tree323381f19326c7ae19b0ea98059210bb4e5b7b29 /src/SocketCore.cc
parent8cd1d845f27adb00f3169a3f314410c4e409202c (diff)
2009-12-08 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed the bug that aria2 listens wrong port if --interface option is used. * src/SocketCore.cc
Diffstat (limited to 'src/SocketCore.cc')
-rw-r--r--src/SocketCore.cc73
1 files changed, 45 insertions, 28 deletions
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index 8dcece60..83d5c068 100644
--- a/src/SocketCore.cc
+++ b/src/SocketCore.cc
@@ -187,41 +187,58 @@ static sock_t bindInternal(int family, int socktype, int protocol,
return fd;
}
+static sock_t bindTo
+(const char* host, uint16_t port, int family, int sockType,
+ int getaddrinfoFlags, std::string& error)
+{
+ struct addrinfo hints;
+ struct addrinfo* res;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = sockType;
+ hints.ai_flags = getaddrinfoFlags;
+ hints.ai_protocol = 0;
+ int s = getaddrinfo(host, uitos(port).c_str(), &hints, &res);
+ if(s) {
+ error = gai_strerror(s);
+ return -1;
+ }
+ auto_delete<struct addrinfo*> resDeleter(res, freeaddrinfo);
+ struct addrinfo* rp;
+ for(rp = res; rp; rp = rp->ai_next) {
+ sock_t fd = bindInternal(rp->ai_family, rp->ai_socktype, rp->ai_protocol,
+ rp->ai_addr, rp->ai_addrlen);
+ if(fd != (sock_t)-1) {
+ return fd;
+ }
+ }
+ error = strerror(errno);
+ return -1;
+}
+
void SocketCore::bind(uint16_t port, int flags)
{
closeConnection();
-
- if(flags == 0 || _bindAddrs.empty()) {
- struct addrinfo hints;
- struct addrinfo* res;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = _protocolFamily;
- hints.ai_socktype = _sockType;
- hints.ai_flags = flags;
- hints.ai_protocol = 0;
- int s;
- s = getaddrinfo(0, uitos(port).c_str(), &hints, &res);
- if(s) {
- throw DL_ABORT_EX(StringFormat(EX_SOCKET_BIND, gai_strerror(s)).str());
- }
- struct addrinfo* rp;
- for(rp = res; rp; rp = rp->ai_next) {
- sock_t fd = bindInternal(rp->ai_family, rp->ai_socktype, rp->ai_protocol,
- rp->ai_addr, rp->ai_addrlen);
- if(fd == (sock_t) -1) {
- continue;
- }
+ std::string error;
+ if(!(flags&AI_PASSIVE) || _bindAddrs.empty()) {
+ sock_t fd = bindTo(0, port, _protocolFamily, _sockType, flags, error);
+ if(fd != (sock_t) -1) {
sockfd = fd;
- break;
}
- freeaddrinfo(res);
} else {
for(std::vector<std::pair<struct sockaddr_storage, socklen_t> >::
const_iterator i = _bindAddrs.begin(); i != _bindAddrs.end(); ++i) {
- sock_t fd = bindInternal
- ((*i).first.ss_family, _sockType, 0,
- reinterpret_cast<const struct sockaddr*>
- (&(*i).first), (*i).second);
+ char host[NI_MAXHOST];
+ int s;
+ s = getnameinfo(reinterpret_cast<const struct sockaddr*>(&(*i).first),
+ (*i).second,
+ host, NI_MAXHOST, 0, NI_MAXSERV,
+ NI_NUMERICHOST);
+ if(s) {
+ error = gai_strerror(s);
+ continue;
+ }
+ sock_t fd = bindTo(host, port, _protocolFamily, _sockType, flags, error);
if(fd != (sock_t)-1) {
sockfd = fd;
break;
@@ -229,7 +246,7 @@ void SocketCore::bind(uint16_t port, int flags)
}
}
if(sockfd == (sock_t) -1) {
- throw DL_ABORT_EX(StringFormat(EX_SOCKET_BIND, strerror(errno)).str());
+ throw DL_ABORT_EX(StringFormat(EX_SOCKET_BIND, error.c_str()).str());
}
}