linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #04408
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2593: Listen to both ipv4&6
------------------------------------------------------------
revno: 2593
committer: Jacek Sieka <arnetheduck@xxxxxxxxx>
branch nick: dcplusplus
timestamp: Fri 2011-08-19 20:07:56 +0200
message:
Listen to both ipv4&6
modified:
dcpp/ConnectionManager.cpp
dcpp/SearchManager.cpp
dcpp/Socket.cpp
dcpp/Socket.h
--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk
Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/ConnectionManager.cpp'
--- dcpp/ConnectionManager.cpp 2011-08-11 13:02:19 +0000
+++ dcpp/ConnectionManager.cpp 2011-08-19 18:07:56 +0000
@@ -213,7 +213,7 @@
ConnectionManager::Server::Server(bool secure_, uint16_t aPort, const string& ip) : port(0), secure(secure_), die(false) {
sock.setLocalIp4(ip);
- port = sock.listen(Util::toString(aPort), AF_INET);
+ port = sock.listen(Util::toString(aPort));
start();
}
@@ -237,7 +237,7 @@
while(!die) {
try {
sock.disconnect();
- port = sock.listen(Util::toString(port), AF_INET);
+ port = sock.listen(Util::toString(port));
if(failed) {
LogManager::getInstance()->message(_("Connectivity restored"));
=== modified file 'dcpp/SearchManager.cpp'
--- dcpp/SearchManager.cpp 2011-08-04 09:57:32 +0000
+++ dcpp/SearchManager.cpp 2011-08-19 18:07:56 +0000
@@ -93,7 +93,7 @@
try {
socket.reset(new Socket(Socket::TYPE_UDP));
socket->setLocalIp4(SETTING(BIND_ADDRESS));
- port = socket->listen(Util::toString(SETTING(UDP_PORT)), AF_INET);
+ port = socket->listen(Util::toString(SETTING(UDP_PORT)));
socket->setBlocking(true);
start();
} catch(...) {
@@ -140,7 +140,7 @@
while(!stop) {
try {
socket->disconnect();
- port = socket->listen(Util::toString(SETTING(UDP_PORT)), AF_INET);
+ port = socket->listen(Util::toString(SETTING(UDP_PORT)));
socket->setBlocking(true);
if(failed) {
LogManager::getInstance()->message(_("Search enabled again"));
=== modified file 'dcpp/Socket.cpp'
--- dcpp/Socket.cpp 2011-08-11 13:02:19 +0000
+++ dcpp/Socket.cpp 2011-08-19 18:07:56 +0000
@@ -134,6 +134,21 @@
return false;
}
+inline int readable(socket_t sock0, socket_t sock1) {
+ fd_set rfd;
+ struct timeval tv = { 0 };
+
+ FD_ZERO(&rfd);
+ FD_SET(sock0, &rfd);
+ FD_SET(sock1, &rfd);
+
+ if(::select(std::max(sock0, sock1) + 1, &rfd, NULL, NULL, &tv) > 0) {
+ return FD_ISSET(sock0, &rfd) ? sock0 : sock1;
+ }
+
+ return sock0;
+}
+
}
Socket::addr Socket::udpAddr;
@@ -243,7 +258,9 @@
addr sock_addr = { { 0 } };
socklen_t sz = sizeof(sock_addr);
- auto sock = setSock(check([&] { return ::accept(listeningSocket.getSock(), &sock_addr.sa, &sz); }), sock_addr.sa.sa_family);
+ auto sock = setSock(check([&] {
+ return ::accept(readable(listeningSocket.sock4, listeningSocket.sock6), &sock_addr.sa, &sz);
+ }), sock_addr.sa.sa_family);
#ifdef _WIN32
// Make sure we disable any inherited windows message things for this socket.
@@ -253,21 +270,54 @@
setIp(resolveName(&sock_addr.sa, sz));
}
-uint16_t Socket::listen(const string& port, int af) {
+uint16_t Socket::listen(const string& port) {
disconnect();
- auto &localIp = af == AF_INET ? getLocalIp4() : getLocalIp6();
-
- auto ai = resolveAddr(localIp, port, af, AI_PASSIVE | AI_ADDRCONFIG);
-
- create(*ai); // TODO What if more than one is returned?
- check([&] { return ::bind(getSock(), ai->ai_addr, ai->ai_addrlen); });
-
- if(type == TYPE_TCP) {
- check([&] { return ::listen(getSock(), 20); });
- }
-
- return getLocalPort();
+ //auto &localIp = af == AF_INET ? getLocalIp4() : getLocalIp6();
+
+ auto ai = resolveAddr(/*localIp*/ "", port, AF_UNSPEC, AI_PASSIVE | AI_ADDRCONFIG);
+
+ uint16_t p = 0;
+
+ // For server sockets we create both ipv4 and ipv6 if possible
+ // We use the same port for both sockets to deal with the fact that
+ // there's no way in ADC to have different ports for v4 and v6 TCP sockets
+ for(auto a = ai.get(); a; a = a->ai_next) {
+ if(!sock4.valid() && a->ai_family == AF_INET) {
+ create(*a);
+ if(p != 0) {
+ ((sockaddr_in*)a->ai_addr)->sin_port = p;
+ }
+
+ check([&] { return ::bind(sock4, a->ai_addr, a->ai_addrlen); });
+ check([&] { return ::getsockname(sock4, a->ai_addr, (socklen_t*)&a->ai_addrlen); });
+ p = ((sockaddr_in*)a->ai_addr)->sin_port;
+
+ if(type == TYPE_TCP) {
+ check([&] { return ::listen(sock4, 20); });
+ }
+ }
+
+ if(!sock6.valid() && a->ai_family == AF_INET6) {
+ create(*a);
+ if(p != 0) {
+ ((sockaddr_in6*)a->ai_addr)->sin6_port = p;
+ }
+
+ check([&] { return ::bind(sock6, a->ai_addr, a->ai_addrlen); });
+ check([&] { return ::getsockname(sock6, a->ai_addr, (socklen_t*)&a->ai_addrlen); });
+ p = ((sockaddr_in6*)a->ai_addr)->sin6_port;
+
+ if(type == TYPE_TCP) {
+ check([&] { return ::listen(sock6, 20); });
+ }
+ }
+ }
+
+ if(p == 0) {
+ throw SocketException(_("Could not open port for listening"));
+ }
+ return ntohs(p);
}
void Socket::connect(const string& aAddr, const string& aPort, const string& localPort) {
@@ -456,7 +506,7 @@
socklen_t addr_length = sizeof(remote_addr);
auto len = check([&] {
- return ::recvfrom(getSock(), (char*)aBuffer, aBufLen, 0, &remote_addr.sa, &addr_length);
+ return ::recvfrom(readable(sock4, sock6), (char*)aBuffer, aBufLen, 0, &remote_addr.sa, &addr_length);
}, true);
if(len > 0) {
@@ -527,6 +577,9 @@
throw SocketException(EADDRNOTAVAIL);
}
+ if(!sock4.valid() || !sock6.valid()) {
+
+ }
auto buf = (const uint8_t*)aBuffer;
int sent;
@@ -563,10 +616,15 @@
connStr.insert(connStr.end(), buf, buf + aLen);
- sent = check([&] { return ::sendto(getSock(), (const char*)&connStr[0], (int)connStr.size(), 0, &udpAddr.sa, udpAddrLen); });
+ sent = check([&] { return ::sendto(udpAddr.sa.sa_family == AF_INET ? sock4 : sock6,
+ (const char*)&connStr[0], (int)connStr.size(), 0, &udpAddr.sa, udpAddrLen); });
} else {
auto ai = resolveAddr(aAddr, aPort);
- sent = check([&] { return ::sendto(getSock(), (const char*)aBuffer, (int)aLen, 0, ai->ai_addr, ai->ai_addrlen); });
+ if((ai->ai_family == AF_INET && !sock4.valid()) || (ai->ai_family == AF_INET6 && !sock6.valid())) {
+ create(*ai);
+ }
+ sent = check([&] { return ::sendto(ai->ai_family == AF_INET ? sock4 : sock6,
+ (const char*)aBuffer, (int)aLen, 0, ai->ai_addr, ai->ai_addrlen); });
}
stats.totalUp += sent;
@@ -639,31 +697,49 @@
return 0;
}
- auto sock = getSock();
check([&] () -> int {
+ int nfds = -1;
+
if(waitFor & WAIT_READ) {
dcassert(!(waitFor & WAIT_CONNECT));
rfdp = &rfd;
FD_ZERO(rfdp);
- FD_SET(sock, rfdp);
+ if(sock4.valid()) {
+ FD_SET(sock4, &rfd);
+ nfds = std::max((int)sock4, nfds);
+ }
+
+ if(sock6.valid()) {
+ FD_SET(sock6, &rfd);
+ nfds = std::max((int)sock6, nfds);
+ }
}
if(waitFor & WAIT_WRITE) {
dcassert(!(waitFor & WAIT_CONNECT));
wfdp = &wfd;
FD_ZERO(wfdp);
- FD_SET(sock, wfdp);
+ if(sock4.valid()) {
+ FD_SET(sock4, &wfd);
+ nfds = std::max((int)sock4, nfds);
+ }
+
+ if(sock6.valid()) {
+ FD_SET(sock6, &wfd);
+ nfds = std::max((int)sock6, nfds);
+ }
}
- return ::select((int)(sock+1), rfdp, wfdp, NULL, &tv);
+ return ::select(nfds + 1, rfdp, wfdp, NULL, &tv);
});
waitFor = WAIT_NONE;
- if(rfdp && FD_ISSET(sock, rfdp)) {
+ if(rfdp && ((sock4.valid() && FD_ISSET(sock4, rfdp)) || (sock6.valid() && FD_ISSET(sock6, rfdp)))) {
waitFor |= WAIT_READ;
}
- if(wfdp && FD_ISSET(sock, wfdp)) {
+
+ if(wfdp && ((sock4.valid() && FD_ISSET(sock4, wfdp)) || (sock6.valid() && FD_ISSET(sock6, wfdp)))) {
waitFor |= WAIT_WRITE;
}
=== modified file 'dcpp/Socket.h'
--- dcpp/Socket.h 2011-08-11 13:02:19 +0000
+++ dcpp/Socket.h 2011-08-19 18:07:56 +0000
@@ -172,7 +172,7 @@
uint16_t getLocalPort() noexcept;
/** Binds a socket to a certain local port and possibly IP. */
- virtual uint16_t listen(const string& port, int af);
+ virtual uint16_t listen(const string& port);
virtual void accept(const Socket& listeningSocket);
int getSocketOptInt(int option);