diff --git a/include/opendht/peer_discovery.h b/include/opendht/peer_discovery.h index 862f9c5fbacd36b125de87cd85238c3ae3731444..6f607741e795959d85f06d169d2ca11eaaec1f0c 100644 --- a/include/opendht/peer_discovery.h +++ b/include/opendht/peer_discovery.h @@ -23,7 +23,7 @@ #include <string.h> #include <stdio.h> -#include <unistd.h> +#include <unistd.h> #include <thread> #include <mutex> @@ -39,7 +39,7 @@ public: PeerDiscovery(sa_family_t domain, in_port_t port); ~PeerDiscovery(); - + /** * startDiscovery - Keep Listening data from the sender until node is joinned or stop is called */ @@ -63,13 +63,11 @@ public: /** * Join the threads */ - void join(){ - - if(running_listen.joinable()){ running_listen.join(); }; - if(running_send.joinable()){ running_send.join(); }; - + void join() { + if(running_listen.joinable()) running_listen.join(); + if(running_send.joinable()) running_send.join(); } - + private: std::mutex mtx_; std::condition_variable cv_; @@ -82,13 +80,13 @@ private: SockAddr sockAddrSend_; std::array<uint8_t,dht::InfoHash::size() + sizeof(in_port_t)> data_send_; - //Thread export to be joined + //Thread export to be joined std::thread running_listen; std::thread running_send; dht::InfoHash nodeId_; /** - * Multicast Socket Initialization, accept IPV4, IPV6 + * Multicast Socket Initialization, accept IPV4, IPV6 */ static int initialize_socket(sa_family_t domain); @@ -134,11 +132,6 @@ private: return (uint32_t)lit_int[0] << 0 | (uint32_t)lit_int[1] << 8; } - -#ifdef _WIN32 - WSADATA wsaData; -#endif - }; } diff --git a/include/opendht/sockaddr.h b/include/opendht/sockaddr.h index 684c4a03d03b913dc991f91af3cdd9cbd9110450..c622573aa58f698aafa0dcf40c7867ab5cce7d1b 100644 --- a/include/opendht/sockaddr.h +++ b/include/opendht/sockaddr.h @@ -91,8 +91,6 @@ public: static std::vector<SockAddr> resolve(const std::string& host, const std::string& service = {}); - static SockAddr parse(sa_family_t family, const char* address); - bool operator<(const SockAddr& o) const { if (len != o.len) return len < o.len; @@ -193,6 +191,12 @@ public: } } + /** + * Set the address part of the socket address from a numeric IP address (string representation). + * Family must be already set. Throws in case of parse failue. + */ + void setAddress(const char* address); + /** * Returns the accessible byte length at the pointer returned by #get(). * If zero, #get() returns null. diff --git a/src/peer_discovery.cpp b/src/peer_discovery.cpp index b4885a2205fce3e3067dc1b1a37ea1184c9d1ea5..984b7dbbfeb33fccc53cf35363506fa07177aeae 100644 --- a/src/peer_discovery.cpp +++ b/src/peer_discovery.cpp @@ -29,7 +29,7 @@ namespace dht { constexpr char MULTICAST_ADDRESS_IPV4[10] = "224.0.0.1"; -constexpr char MULTICAST_ADDRESS_IPV6[8] = "ff02::1"; +constexpr char MULTICAST_ADDRESS_IPV6[8] = "ff05::2"; // Site-local multicast #ifdef _WIN32 @@ -66,12 +66,10 @@ PeerDiscovery::PeerDiscovery(sa_family_t domain, in_port_t port) int PeerDiscovery::initialize_socket(sa_family_t domain) { - #ifdef _WIN32 - // Initialize Windows Socket API with given VERSION. + WSADATA wsaData; if (WSAStartup(0x0101, &wsaData)) { - perror("WSAStartup"); - throw std::runtime_error(std::string("Socket Creation Error_initialize_socket ") + strerror(errno)); + throw std::runtime_error(std::string("Can't initialize Winsock2 ") + strerror(errno)); } #endif @@ -85,7 +83,7 @@ PeerDiscovery::initialize_socket(sa_family_t domain) void PeerDiscovery::listener_setup() -{ +{ SockAddr sockAddrListen_; sockAddrListen_.setFamily(domain_); sockAddrListen_.setPort(port_); @@ -107,58 +105,52 @@ PeerDiscovery::socketJoinMulticast(int sockfd, sa_family_t family) { switch (family) { - case AF_INET:{ - - ip_mreq config_ipv4; - - //This option can be used to set the interface for sending outbound - //multicast datagrams from the sockets application. - config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY); - if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &config_ipv4.imr_interface, sizeof( struct in_addr )) < 0 ) { - throw std::runtime_error(std::string("Bound Network Interface IPV4 Error: ") + strerror(errno)); - } - - //The IP_MULTICAST_TTL socket option allows the application to primarily - //limit the lifetime of the packet in the Internet and prevent it from circulating indefinitely - unsigned char ttl4 = 20; - if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl4, sizeof( ttl4 )) < 0 ) { - throw std::runtime_error(std::string(" TTL Sockopt Error: ") + strerror(errno)); - } - - // config the listener to be interested in joining in the multicast group - config_ipv4.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDRESS_IPV4); - config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY); - if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&config_ipv4, sizeof(config_ipv4)) < 0){ - throw std::runtime_error(std::string(" Member Addition IPV4 Error: ") + strerror(errno)); - } - - break; + case AF_INET:{ + ip_mreq config_ipv4; + + //This option can be used to set the interface for sending outbound + //multicast datagrams from the sockets application. + config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY); + if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &config_ipv4.imr_interface, sizeof( struct in_addr )) < 0 ) { + throw std::runtime_error(std::string("Bound Network Interface IPV4 Error: ") + strerror(errno)); } - - case AF_INET6:{ - - ipv6_mreq config_ipv6; - unsigned int outif = 0; - if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &outif, sizeof( outif )) < 0 ) { - throw std::runtime_error(std::string("Bound Network Interface IPV6 Error: ") + strerror(errno)); - } + //The IP_MULTICAST_TTL socket option allows the application to primarily + //limit the lifetime of the packet in the Internet and prevent it from circulating indefinitely + unsigned char ttl4 = 20; + if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl4, sizeof( ttl4 )) < 0 ) { + throw std::runtime_error(std::string(" TTL Sockopt Error: ") + strerror(errno)); + } - unsigned int ttl6 = 20; - if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl6, sizeof( ttl6 )) < 0 ) { - throw std::runtime_error(std::string("Hop Count Set Error: ") + strerror(errno)); - } + // config the listener to be interested in joining in the multicast group + config_ipv4.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDRESS_IPV4); + config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY); + if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&config_ipv4, sizeof(config_ipv4)) < 0){ + throw std::runtime_error(std::string(" Member Addition IPV4 Error: ") + strerror(errno)); + } + break; + } + case AF_INET6: { + ipv6_mreq config_ipv6; - config_ipv6.ipv6mr_interface = 0; - inet_pton(AF_INET6, MULTICAST_ADDRESS_IPV6, &config_ipv6.ipv6mr_multiaddr); - if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &config_ipv6, sizeof(config_ipv6)) < 0){ - throw std::runtime_error(std::string("Member Addition IPV6 Error: ") + strerror(errno)); - } + unsigned int outif = 0; + if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &outif, sizeof( outif )) < 0 ) { + throw std::runtime_error(std::string("Bound Network Interface IPV6 Error: ") + strerror(errno)); + } - break; + unsigned int ttl6 = 20; + if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl6, sizeof( ttl6 )) < 0 ) { + throw std::runtime_error(std::string("Hop Count Set Error: ") + strerror(errno)); } - } + config_ipv6.ipv6mr_interface = 0; + inet_pton(AF_INET6, MULTICAST_ADDRESS_IPV6, &config_ipv6.ipv6mr_multiaddr); + if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &config_ipv6, sizeof(config_ipv6)) < 0){ + throw std::runtime_error(std::string("Member Addition IPV6 Error: ") + strerror(errno)); + } + break; + } + } } void @@ -205,7 +197,8 @@ PeerDiscovery::sender_setup(const dht::InfoHash& nodeId, in_port_t port_to_send) { nodeId_ = nodeId; //Set up for Sender - sockAddrSend_ = SockAddr::parse(domain_, domain_ == AF_INET ? MULTICAST_ADDRESS_IPV4 : MULTICAST_ADDRESS_IPV6); + sockAddrSend_.setFamily(domain_); + sockAddrSend_.setAddress(domain_ == AF_INET ? MULTICAST_ADDRESS_IPV4 : MULTICAST_ADDRESS_IPV6); sockAddrSend_.setPort(port_); //Setup for send data @@ -277,10 +270,10 @@ PeerDiscovery::listener_thread(PeerDiscoveredCallback callback) size_t data_receive_size = data_receive.size(); auto from = recvFrom(data_receive.data(), data_receive_size); - //Data_receive_size as a value-result member will hlep to filter packs - if(data_receive_size != data_receive.size()){ + //Data_receive_size as a value-result member will hlep to filter packs + if(data_receive_size != data_receive.size()){ perror("Data Received Unmatch"); - continue; + continue; } std::array<uint8_t,dht::InfoHash::size()> data_infohash; @@ -330,7 +323,6 @@ PeerDiscovery::stop() } cv_.notify_one(); if (stop_writefd_ != -1) { - if (write(stop_writefd_, "\0", 1) == -1) { perror("write"); } diff --git a/src/utils.cpp b/src/utils.cpp index d5c55049ba88ab831232b09353e55d911cfb3501..144bc48bd86a8a30abe741a1507d515c794b5a26 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -73,19 +73,23 @@ SockAddr::resolve(const std::string& host, const std::string& service) return ips; } - -SockAddr -SockAddr::parse(sa_family_t family, const char* address) +void +SockAddr::setAddress(const char* address) { - SockAddr addr; - addr.setFamily(family); - if (inet_pton(family, address, family == AF_INET ? (void*)&addr.getIPv4().sin_addr.s_addr : (void*)&addr.getIPv6().sin6_addr) <= 0){ - throw std::runtime_error("SockAddr::parse inet_pton"); + auto family = getFamily(); + void* addr = nullptr; + switch (family) { + case AF_INET: + addr = &getIPv4().sin_addr; + break; + case AF_INET6: + addr = &getIPv6().sin6_addr; + break; } - return addr; + if (not addr or inet_pton(family, address, addr) <= 0) + throw std::runtime_error("Can't parse IP address"); } - std::string print_addr(const sockaddr* sa, socklen_t slen) {