📄 pana_udp_transport.h
字号:
#endiftemplate<int PF>class PANA_EXPORT PANA_Socket : public PANA_IO{ public: virtual ACE_INT32 open(std::string &iface, ACE_INET_Addr &listenAddr) { m_AdapterInfo.Ifname() = iface; m_BindAddr = listenAddr; return m_Socket.open(SOCK_DGRAM, PF, IPPROTO_UDP, 0); } virtual ACE_INT32 recv(void *buf, size_t n, ACE_UINT32 &srcPort, PANA_DeviceIdContainer &srcDevices) { ACE_Handle_Set handle_set; handle_set.reset(); handle_set.set_bit(m_Socket.get_handle()); // Check the status of the current socket to make sure there's data // to recv (or time out). ACE_Time_Value tm(5, 0); int selectWidth;#if defined (ACE_WIN64) || defined(ACE_WIN32) // This arg is ignored on Windows and causes pointer truncation // warnings on 64-bit compiles. selectWidth = 0;#else selectWidth = (int)m_Socket.get_handle () + 1;#endif /* ACE_WIN64 */ switch (ACE_OS::select (selectWidth, handle_set, 0, 0, &tm)) { case -1: return -1; case 0: errno = ETIME; return -1; default: break; } // Read the data ACE_INET_Addr srcAddr; sockaddr *saddr = (sockaddr *) srcAddr.get_addr (); ACE_INT32 addrLen = srcAddr.get_size (); ACE_INT32 pktLen = ACE_OS::recvfrom(m_Socket.get_handle(), (char*)buf, n, 0, saddr, &addrLen); if (pktLen > 0) { srcAddr.set_size(addrLen); srcPort = srcAddr.get_port_number(); PANA_DUMP_RXADDR(srcAddr); PANA_DeviceId *ip = PANA_DeviceIdConverter::CreateFromAddr(srcAddr); srcDevices.push_back(ip); } return (pktLen); } virtual ACE_INT32 send(void *buf, size_t n, ACE_UINT32 destPort, PANA_DeviceIdContainer &destDevices) { PANA_DeviceId *id = PANA_DeviceIdConverter:: GetIpOnlyAddress(destDevices, (PF == PF_INET6)); if (id) { ACE_INET_Addr addr; PANA_DeviceIdConverter::FormatToAddr(*id, addr); addr.set_port_number(destPort); PANA_DUMP_TXADDR(addr); return (ACE_OS::sendto(m_Socket.get_handle(), (char*)buf, n, 0, (sockaddr*)addr.get_addr(), addr.get_size())); } return (-1); } virtual ACE_INT32 get_local_addr(PANA_DeviceIdContainer &localDevices) { return m_AdapterInfo.get_local_addr(localDevices); } virtual void close() { m_Socket.close(); } protected: ACE_SOCK_IO m_Socket; ACE_INET_Addr m_BindAddr; PANA_IfAdapterInfo m_AdapterInfo;};template<int PF> class PANA_EXPORT PANA_BoundedSocket : public PANA_Socket<PF>{ public: virtual ACE_INT32 open(std::string &iface, ACE_INET_Addr &listenAddr) { if (PANA_Socket<PF>::open(iface, listenAddr) >= 0) { if (ACE_OS::bind(PANA_Socket<PF>::m_Socket.get_handle(), (sockaddr*)listenAddr.get_addr(), listenAddr.get_size()) == 0) { return 0; } ACE_DEBUG((LM_ERROR, "(%P|%t) UDP bind failure\n")); PANA_Socket<PF>::close(); } return -1; }}; #if defined(ACE_HAS_IPV6)template<bool BIND, bool MCAST, bool JOIN>class PANA_EXPORT PANA_UdpIPv6 : public PANA_Socket<PF_INET6>{ public: virtual ACE_INT32 open(std::string &iface, ACE_INET_Addr &listenAddr) { m_AdapterInfo.Ifname() = iface; m_BindAddr = listenAddr; struct addrinfo hints, *res, *ressave; memset(&hints, 0, sizeof(struct addrinfo)); /* AI_PASSIVE flag: the resulting address is used to bind to a socket for accepting incoming connections. So, when the hostname==NULL, getaddrinfo function will return one entry per allowed protocol family containing the unspecified address for that family. */ hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; char service[32]; ACE_OS::sprintf(service, "%d", listenAddr.get_port_number()); if (getaddrinfo(NULL, service, &hints, &res) != 0) { ACE_DEBUG((LM_ERROR, "(%P|%t) Address info failure\n")); return -1; } ressave=res; /* Try open socket with each address getaddrinfo returned, until getting a valid listening socket. */ try { while (res) { if (m_Socket.open(res->ai_socktype, res->ai_family, res->ai_protocol, 0) < 0) { res = res->ai_next; continue; } if (BIND && ACE_OS::bind(m_Socket.get_handle(), res->ai_addr, (int)res->ai_addrlen) < 0) { ACE_DEBUG((LM_ERROR, "(%P|%t) UDP bind failure\n")); throw (1); } sockaddr_in6 *in6 = (sockaddr_in6*)listenAddr.get_addr(); if (MCAST && IN6_IS_ADDR_MULTICAST(&in6->sin6_addr) && McastSetup(listenAddr) < 0) { throw (1); } freeaddrinfo(ressave); return 0; } } catch (...) { } close(); freeaddrinfo(ressave); return -1; } virtual ACE_INT32 send(void *buf, size_t n, ACE_UINT32 destPort, PANA_DeviceIdContainer &destDevices) { PANA_DeviceId *id = PANA_DeviceIdConverter:: GetIpOnlyAddress(destDevices, true); if (id) { sockaddr_in6 daddr; ACE_OS::memset(&daddr, 0, sizeof(daddr)); daddr.sin6_family = AF_INET6; daddr.sin6_port = ACE_HTONS(destPort); ACE_OS::memcpy(&daddr.sin6_addr, id->value.data(), id->value.size());#if defined(ACE_WIN32) if (IN6_IS_ADDR_LINKLOCAL(&daddr.sin6_addr)) {#else if (IN6_IS_ADDR_LINKLOCAL(&daddr.sin6_addr) || IN6_IS_ADDR_MULTICAST(&daddr.sin6_addr)) {#endif daddr.sin6_scope_id = m_AdapterInfo.get_adapter_index ( m_AdapterInfo.Ifname().data()); if (daddr.sin6_scope_id == 0) { ACE_DEBUG((LM_ERROR, "(%P|%t) IF index failed to resolve: %s\n", m_AdapterInfo.Ifname().data())); return -1; } }#if defined(PANA_UDP_ADDR_DEBUG) ACE_INET_Addr aceAddr; PANA_DeviceIdConverter::FormatToAddr(*id, aceAddr); PANA_DUMP_TXADDR(aceAddr);#endif return (ACE_OS::sendto(m_Socket.get_handle(), (char*)buf, n, 0, (sockaddr*)&daddr, sizeof(sockaddr_in6))); } return (-1); } private: int McastSetup(ACE_INET_Addr &mcastAddr) { int hops = 8; if (m_Socket.set_option(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) < 0) { ACE_DEBUG((LM_ERROR, "(%P|%t) Multicast hops option failed\n")); return -1; } int ifindex = m_AdapterInfo.get_adapter_index (m_AdapterInfo.Ifname().data()); if (ifindex == 0) { ACE_DEBUG((LM_ERROR, "(%P|%t) Invalid ifname: %s\n", m_AdapterInfo.Ifname().data())); return -1; } if (m_Socket.set_option(IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0) { ACE_DEBUG((LM_ERROR, "(%P|%t) Multicast IF option failed\n")); return -1; } if (JOIN) { struct ipv6_mreq mreq; sockaddr_in6 *sin = (sockaddr_in6*)mcastAddr.get_addr(); ACE_OS::memcpy(&mreq.ipv6mr_multiaddr, &sin->sin6_addr, sizeof(in6_addr)); mreq.ipv6mr_interface = ifindex; if (m_Socket.set_option(IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq, sizeof(mreq)) < 0) { ACE_DEBUG((LM_ERROR, "(%P|%t) Multicast join failed: %s\n", strerror(errno))); return -1; } } return (0); }};typedef PANA_UdpIPv6<false, true, true> PANA_McastSender;typedef PANA_UdpIPv6<true, true, true> PANA_McastListener;#if defined(ACE_WIN32)typedef PANA_UdpIPv6<false, true, false> PANA_UdpBoundedSender;#elsetypedef PANA_UdpIPv6<false, true, true> PANA_UdpBoundedSender;#endif#elseclass PANA_EXPORT PANA_McastSender : public PANA_BoundedSocket<PF_INET>{ public: virtual ACE_INT32 open(std::string &iface, ACE_INET_Addr &listenAddr) { if (PANA_Socket<PF_INET>::open(iface, listenAddr) >= 0) { return McastIFSetup(); } return -1; } private: int McastIFSetup() { PANA_DeviceIdContainer localDevices; m_AdapterInfo.get_local_addr(localDevices); PANA_DeviceId *id = PANA_DeviceIdConverter:: GetIpOnlyAddress(localDevices); if (id) { ACE_INET_Addr ifAddr; PANA_DeviceIdConverter::FormatToAddr(*id, ifAddr); ip_mreq mcastAddr; mcastAddr.imr_interface.s_addr = htonl(ifAddr.get_ip_address()); if (m_Socket.set_option(IPPROTO_IP, IP_MULTICAST_IF, &mcastAddr.imr_interface.s_addr, sizeof (struct in_addr)) >= 0) { return 0; } } ACE_DEBUG((LM_ERROR, "(%P|%t) Multicast IF option failed\n")); close(); return -1; }};class PANA_EXPORT PANA_McastListener : public PANA_BoundedSocket<PF_INET>{ public: virtual ACE_INT32 open(std::string &iface, ACE_INET_Addr &mcastAddr) { ACE_INET_Addr listenAddr(mcastAddr.get_port_number()); if (PANA_BoundedSocket<PF_INET>::open(iface, listenAddr) >= 0) { struct ip_mreq mreq; memset(&mreq, 0, sizeof(mreq)); PANA_DeviceIdContainer localDevices; m_AdapterInfo.get_local_addr(localDevices); PANA_DeviceId *id = PANA_DeviceIdConverter:: GetIpOnlyAddress(localDevices); if (id) { ACE_INET_Addr ifAddr; PANA_DeviceIdConverter::FormatToAddr(*id, ifAddr); mreq.imr_interface.s_addr = htonl(ifAddr.get_ip_address()); } else { mreq.imr_interface.s_addr = ACE_HTONS(INADDR_ANY); } mreq.imr_multiaddr.s_addr = htonl(mcastAddr.get_ip_address()); if (m_Socket.set_option(IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) >= 0) { return (0); } printf("Error: %s\n", strerror(errno)); ACE_DEBUG((LM_ERROR, "(%P|%t) Multicast add membership failed\n")); close(); } return -1; }};typedef PANA_McastSender PANA_UdpBoundedSender;#endif // ACE_HAS_IPV6#endif /* __PANA_UDP_TRANSPORT_H__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -