diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2009-12-07 15:04:33 +0000 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2009-12-07 15:04:33 +0000 |
| commit | cc4a14a1bcfadba7b7540b911bf659f7844d58fc (patch) | |
| tree | 323381f19326c7ae19b0ea98059210bb4e5b7b29 /src/SocketCore.cc | |
| parent | 8cd1d845f27adb00f3169a3f314410c4e409202c (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.cc | 73 |
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()); } } |
