From 0db4a9a3425fec0ea01c85c2c035f110c60059f3 Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Wed, 2 Mar 2016 12:37:58 +0100 Subject: [PATCH] udp transport initialization refactoring (deduplication) --- src/remote/blockingUDP.h | 14 ++ src/remote/blockingUDPTransport.cpp | 304 ++++++++++++++++++++++--- src/remoteClient/clientContextImpl.cpp | 211 +---------------- src/server/serverContext.cpp | 228 +------------------ src/server/serverContext.h | 1 - testApp/remote/channelAccessIFTest.cpp | 1 + 6 files changed, 305 insertions(+), 454 deletions(-) diff --git a/src/remote/blockingUDP.h b/src/remote/blockingUDP.h index e0b2c5b..c7791bf 100644 --- a/src/remote/blockingUDP.h +++ b/src/remote/blockingUDP.h @@ -491,6 +491,20 @@ namespace epics { }; + typedef std::vector BlockingUDPTransportVector; + + epicsShareExtern void initializeUDPTransports( + bool serverFlag, + BlockingUDPTransportVector& udpTransports, + const IfaceNodeVector& ifaceList, + const ResponseHandler::shared_pointer& responseHandler, + BlockingUDPTransport::shared_pointer& sendTransport, + epics::pvData::int32& listenPort, + bool autoAddressList, + const std::string& addressList, + const std::string& ignoreAddressList); + + } } diff --git a/src/remote/blockingUDPTransport.cpp b/src/remote/blockingUDPTransport.cpp index 6ce492e..c2012eb 100644 --- a/src/remote/blockingUDPTransport.cpp +++ b/src/remote/blockingUDPTransport.cpp @@ -357,36 +357,40 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so // CMD_ORIGIN_TAG filtering // NOTE: from design point of view this is not a right place to process application message here - if (unlikely((command == CMD_ORIGIN_TAG) && _tappedNIF)) + if (unlikely(command == CMD_ORIGIN_TAG)) { - // 128-bit IPv6 address - osiSockAddr originNIFAddress; - if (decodeAsIPv6Address(receiveBuffer, &originNIFAddress)) + // enabled? + if (_tappedNIF) { - originNIFAddress.ia.sin_family = AF_INET; - - /* - LOG(logLevelDebug, "Got CMD_ORIGIN_TAG message form %s tagged as %s.", - inetAddressToString(fromAddress, true).c_str(), - inetAddressToString(originNIFAddress, false).c_str()); - */ - - // filter - if (originNIFAddress.ia.sin_addr.s_addr != htonl(INADDR_ANY)) + // 128-bit IPv6 address + osiSockAddr originNIFAddress; + if (decodeAsIPv6Address(receiveBuffer, &originNIFAddress)) { - bool accept = false; - for(size_t i = 0; i < _tappedNIF->size(); i++) - { - if((*_tappedNIF)[i].ia.sin_addr.s_addr == originNIFAddress.ia.sin_addr.s_addr) - { - accept = true; - break; - } - } + originNIFAddress.ia.sin_family = AF_INET; - // ignore messages from non-tapped NIFs - if (!accept) - return false; + /* + LOG(logLevelDebug, "Got CMD_ORIGIN_TAG message form %s tagged as %s.", + inetAddressToString(fromAddress, true).c_str(), + inetAddressToString(originNIFAddress, false).c_str()); + */ + + // filter + if (originNIFAddress.ia.sin_addr.s_addr != htonl(INADDR_ANY)) + { + bool accept = false; + for(size_t i = 0; i < _tappedNIF->size(); i++) + { + if((*_tappedNIF)[i].ia.sin_addr.s_addr == originNIFAddress.ia.sin_addr.s_addr) + { + accept = true; + break; + } + } + + // ignore messages from non-tapped NIFs + if (!accept) + return false; + } } } } @@ -408,6 +412,12 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so bool BlockingUDPTransport::send(const char* buffer, size_t length, const osiSockAddr& address) { + if (IS_LOGGABLE(logLevelDebug)) + { + LOG(logLevelDebug, "Sending %d bytes to %s.", + length, inetAddressToString(address).c_str()); + } + int retval = sendto(_channel, buffer, length, 0, &(address.sa), sizeof(sockaddr)); if(unlikely(retval<0)) @@ -425,6 +435,13 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so bool BlockingUDPTransport::send(ByteBuffer* buffer, const osiSockAddr& address) { buffer->flip(); + + if (IS_LOGGABLE(logLevelDebug)) + { + LOG(logLevelDebug, "Sending %d bytes to %s.", + buffer->getRemaining(), inetAddressToString(address).c_str()); + } + int retval = sendto(_channel, buffer->getArray(), buffer->getLimit(), 0, &(address.sa), sizeof(sockaddr)); if(unlikely(retval<0)) @@ -552,6 +569,241 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so } + void initializeUDPTransports(bool serverFlag, + BlockingUDPTransportVector& udpTransports, + const IfaceNodeVector& ifaceList, + const ResponseHandler::shared_pointer& responseHandler, + BlockingUDPTransport::shared_pointer& sendTransport, + int32& listenPort, + bool autoAddressList, + const std::string& addressList, + const std::string& ignoreAddressList) + { + TransportClient::shared_pointer nullTransportClient; + auto_ptr connector(new BlockingUDPConnector(serverFlag, true, true)); + + // TODO configurable local NIF, address + osiSockAddr loAddr; + getLoopbackNIF(loAddr, "", 0); + + // TODO configurable local multicast address + std::string mcastAddress("224.0.0.128"); + + osiSockAddr group; + aToIPAddr(mcastAddress.c_str(), listenPort, &group.ia); + + // + // set ignore address list + // + auto_ptr ignoreAddressVector; + if (!ignoreAddressList.empty()) + ignoreAddressVector.reset(getSocketAddressList(ignoreAddressList, 0, 0)); + + // + // Setup UDP trasport(s) (per interface) + // + + InetAddrVector tappedNIF; + + for (IfaceNodeVector::const_iterator iter = ifaceList.begin(); iter != ifaceList.end(); iter++) + { + ifaceNode node = *iter; + + LOG(logLevelDebug, "Setting up UDP for interface %s, broadcast %s.", + inetAddressToString(node.ifaceAddr, false).c_str(), + inetAddressToString(node.ifaceBCast, false).c_str()); + try + { + // where to bind (listen) address + osiSockAddr listenLocalAddress; + listenLocalAddress.ia.sin_family = AF_INET; + listenLocalAddress.ia.sin_port = htons(listenPort); + listenLocalAddress.ia.sin_addr.s_addr = node.ifaceAddr.ia.sin_addr.s_addr; + + BlockingUDPTransport::shared_pointer transport = static_pointer_cast(connector->connect( + nullTransportClient, responseHandler, + listenLocalAddress, PVA_PROTOCOL_REVISION, + PVA_DEFAULT_PRIORITY)); + listenLocalAddress = *transport->getRemoteAddress(); + // to allow automatic assignment of listen port (for testing) + if (listenPort == 0) + { + listenPort = ntohs(listenLocalAddress.ia.sin_port); + aToIPAddr(mcastAddress.c_str(), listenPort, &group.ia); + + LOG(logLevelDebug, "Dynamic listen UDP port set to %d.", listenPort); + } + + if (ignoreAddressVector.get() && ignoreAddressVector->size()) + transport->setIgnoredAddresses(ignoreAddressVector.get()); + + tappedNIF.push_back(listenLocalAddress); + + + BlockingUDPTransport::shared_pointer transport2; + + if(node.ifaceBCast.ia.sin_family == AF_UNSPEC || + node.ifaceBCast.ia.sin_addr.s_addr == listenLocalAddress.ia.sin_addr.s_addr) { + LOG(logLevelWarn, "Unable to find broadcast address of interface %s.", inetAddressToString(node.ifaceAddr, false).c_str()); + } + #if !defined(_WIN32) + else + { + /* An oddness of BSD sockets (not winsock) is that binding to + * INADDR_ANY will receive unicast and broadcast, but binding to + * a specific interface address receives only unicast. The trick + * is to bind a second socket to the interface broadcast address, + * which will then receive only broadcasts. + */ + + osiSockAddr bcastAddress; + bcastAddress.ia.sin_family = AF_INET; + bcastAddress.ia.sin_port = htons(listenPort); + bcastAddress.ia.sin_addr.s_addr = node.ifaceBCast.ia.sin_addr.s_addr; + + transport2 = static_pointer_cast(connector->connect( + nullTransportClient, responseHandler, + bcastAddress, PVA_PROTOCOL_REVISION, + PVA_DEFAULT_PRIORITY)); + /* The other wrinkle is that nothing should be sent from this second + * socket. So replies are made through the unicast socket. + */ + transport2->setReplyTransport(transport); + + if (ignoreAddressVector.get() && ignoreAddressVector->size()) + transport2->setIgnoredAddresses(ignoreAddressVector.get()); + + tappedNIF.push_back(bcastAddress); + } + #endif + + transport->setMutlicastNIF(loAddr, true); + transport->setLocalMulticastAddress(group); + + transport->start(); + udpTransports.push_back(transport); + + if (transport2) + { + transport2->start(); + udpTransports.push_back(transport2); + } + } + catch (std::exception& e) + { + THROW_BASE_EXCEPTION_CAUSE("Failed to initialize UDP transport.", e); + } + catch (...) + { + THROW_BASE_EXCEPTION("Failed to initialize UDP transport."); + } + } + + + // + // Create UDP transport for sending (to all network interfaces) + // + + osiSockAddr anyAddress; + anyAddress.ia.sin_family = AF_INET; + anyAddress.ia.sin_port = htons(0); + anyAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY); + + sendTransport = static_pointer_cast(connector->connect( + nullTransportClient, responseHandler, + anyAddress, PVA_PROTOCOL_REVISION, + PVA_DEFAULT_PRIORITY)); + + // TODO current implementation shares the port (aka beacon and search port) + int32 sendPort = listenPort; + + // + // compile auto address list - where to send packets + // + + InetAddrVector autoBCastAddr; + for (IfaceNodeVector::const_iterator iter = ifaceList.begin(); iter != ifaceList.end(); iter++) + { + ifaceNode node = *iter; + + if (node.ifaceBCast.ia.sin_family != AF_UNSPEC) + { + node.ifaceBCast.ia.sin_port = htons(sendPort); + autoBCastAddr.push_back(node.ifaceBCast); + } + } + + // + // set send address list + // + + if (!addressList.empty()) + { + // if auto is true, add it to specified list + if (!autoAddressList) + autoBCastAddr.clear(); + + auto_ptr list(getSocketAddressList(addressList, sendPort, &autoBCastAddr)); + if (list.get() && list->size()) + { + sendTransport->setSendAddresses(list.get()); + } + /* + else + { + // fallback + // set default (auto) address list + sendTransport->setSendAddresses(&autoBCastAddr); + } + */ + } + else if (autoAddressList) + { + // set default (auto) address list + sendTransport->setSendAddresses(&autoBCastAddr); + } + + + sendTransport->start(); + udpTransports.push_back(sendTransport); + + // debug output of broadcast addresses + InetAddrVector* blist = sendTransport->getSendAddresses(); + if (!blist || !blist->size()) + LOG(logLevelError, + "No broadcast addresses found or specified - empty address list!"); + else + for (size_t i = 0; i < blist->size(); i++) + LOG(logLevelDebug, + "Broadcast address #%d: %s.", i, inetAddressToString((*blist)[i]).c_str()); + + // + // Setup local multicasting + // + + BlockingUDPTransport::shared_pointer localMulticastTransport; + try + { + // NOTE: multicast receiver socket must be "bound" to INADDR_ANY or multicast address + localMulticastTransport = static_pointer_cast(connector->connect( + nullTransportClient, responseHandler, + group, PVA_PROTOCOL_REVISION, + PVA_DEFAULT_PRIORITY)); + localMulticastTransport->setTappedNIF(&tappedNIF); + localMulticastTransport->join(group, loAddr); + localMulticastTransport->start(); + udpTransports.push_back(localMulticastTransport); + + LOG(logLevelDebug, "Local multicast enabled on %s/%s.", + inetAddressToString(loAddr, false).c_str(), + inetAddressToString(group).c_str()); + } + catch (std::exception& ex) + { + LOG(logLevelDebug, "Failed to initialize local multicast, funcionality disabled. Reason: %s.", ex.what()); + } + } + } } diff --git a/src/remoteClient/clientContextImpl.cpp b/src/remoteClient/clientContextImpl.cpp index 6f64393..3db0f6b 100644 --- a/src/remoteClient/clientContextImpl.cpp +++ b/src/remoteClient/clientContextImpl.cpp @@ -4478,222 +4478,20 @@ namespace epics { SOCKET socket = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0); if (socket == INVALID_SOCKET) { - LOG(logLevelError, "Failed to initialize broadcast UDP transport."); + LOG(logLevelError, "Failed to create a socket to introspect network interfaces."); return false; } IfaceNodeVector ifaceList; if (discoverInterfaces(ifaceList, socket, 0) || ifaceList.size() == 0) { - LOG(logLevelError, "Failed to initialize broadcast UDP transport, no interfaces available."); + LOG(logLevelError, "Failed to introspect interfaces or no network interfaces available."); return false; } - epicsSocketDestroy (socket); - - - //ClientContextImpl::shared_pointer thisPointer = shared_from_this(); - TransportClient::shared_pointer nullTransportClient; - auto_ptr broadcastConnector(new BlockingUDPConnector(false, true, true)); - - osiSockAddr anyAddress; - anyAddress.ia.sin_family = AF_INET; - anyAddress.ia.sin_port = htons(0); - anyAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY); - - m_searchTransport = static_pointer_cast(broadcastConnector->connect( - nullTransportClient, m_responseHandler, - anyAddress, PVA_PROTOCOL_REVISION, - PVA_DEFAULT_PRIORITY)); - if (!m_searchTransport.get()) - return false; - - - - - InetAddrVector autoBCastAddr; - for (IfaceNodeVector::const_iterator iter = ifaceList.begin(); iter != ifaceList.end(); iter++) - { - ifaceNode node = *iter; - - if (node.ifaceBCast.ia.sin_family != AF_UNSPEC) - { - node.ifaceBCast.ia.sin_port = htons(m_broadcastPort); - autoBCastAddr.push_back(node.ifaceBCast); - } - } - - // - // set beacon (broadcast) address list - // - - - if (!m_addressList.empty()) - { - // if auto is true, add it to specified list - if (!m_autoAddressList) - autoBCastAddr.clear(); - - auto_ptr list(getSocketAddressList(m_addressList, m_broadcastPort, &autoBCastAddr)); - if (list.get() && list->size()) - { - m_searchTransport->setSendAddresses(list.get()); - } - /* - else - { - // fallback - // set default (auto) address list - m_searchTransport->setSendAddresses(&autoBCastAddr); - } - */ - } - else if (m_autoAddressList) - { - // set default (auto) address list - m_searchTransport->setSendAddresses(&autoBCastAddr); - } - - m_searchTransport->start(); - - // debug output for broadcast addresses - InetAddrVector* blist = m_searchTransport->getSendAddresses(); - if (!blist || !blist->size()) - LOG(logLevelError, - "No broadcast addresses found or specified - empty PV search address list!"); - else - for (size_t i = 0; i < blist->size(); i++) - LOG(logLevelDebug, - "Broadcast address #%d: %s.", i, inetAddressToString((*blist)[i]).c_str()); - - - // TODO configurable local NIF, address - osiSockAddr loAddr; - getLoopbackNIF(loAddr, "", 0); - - // - // Setup local multicasting - // - - osiSockAddr group; - // TODO configurable local multicast address - aToIPAddr("224.0.0.128", m_broadcastPort, &group.ia); - - BlockingUDPTransport::shared_pointer localMulticastTransport; - - if (true) - { - try - { - // NOTE: multicast receiver socket must be "bound" to INADDR_ANY or multicast address - localMulticastTransport = static_pointer_cast(broadcastConnector->connect( - nullTransportClient, m_responseHandler, - group, PVA_PROTOCOL_REVISION, - PVA_DEFAULT_PRIORITY)); - localMulticastTransport->join(group, loAddr); - - if (localMulticastTransport) - { - localMulticastTransport->start(); - m_udpTransports.push_back(localMulticastTransport); - } - - LOG(logLevelDebug, "Local multicast enabled on %s/%s.", - inetAddressToString(loAddr, false).c_str(), - inetAddressToString(group).c_str()); - } - catch (std::exception& ex) - { - LOG(logLevelDebug, "Failed to initialize local multicast, funcionality disabled. Reason: %s.", ex.what()); - } - } - else - { - LOG(logLevelDebug, "Failed to detect a loopback network interface, local multicast disabled."); - } - - - - - - - for (IfaceNodeVector::const_iterator iter = ifaceList.begin(); iter != ifaceList.end(); iter++) - { - ifaceNode node = *iter; - - LOG(logLevelDebug, "Setting up UDP for interface %s, broadcast %s.", - inetAddressToString(node.ifaceAddr, false).c_str(), - inetAddressToString(node.ifaceBCast, false).c_str()); - try - { - // where to bind (listen) address - // TODO opt copy - osiSockAddr listenLocalAddress; - listenLocalAddress.ia.sin_family = AF_INET; - listenLocalAddress.ia.sin_port = htons(m_broadcastPort); - listenLocalAddress.ia.sin_addr.s_addr = node.ifaceAddr.ia.sin_addr.s_addr; - - BlockingUDPTransport::shared_pointer transport = static_pointer_cast(broadcastConnector->connect( - nullTransportClient, m_responseHandler, - listenLocalAddress, PVA_PROTOCOL_REVISION, - PVA_DEFAULT_PRIORITY)); - listenLocalAddress = *transport->getRemoteAddress(); - - BlockingUDPTransport::shared_pointer transport2; - - if(node.ifaceBCast.ia.sin_family == AF_UNSPEC || - node.ifaceBCast.ia.sin_addr.s_addr == listenLocalAddress.ia.sin_addr.s_addr) { - LOG(logLevelWarn, "Unable to find broadcast address of interface %s.", inetAddressToString(node.ifaceBCast, false).c_str()); - } - #if !defined(_WIN32) - else - { - /* An oddness of BSD sockets (not winsock) is that binding to - * INADDR_ANY will receive unicast and broadcast, but binding to - * a specific interface address receives only unicast. The trick - * is to bind a second socket to the interface broadcast address, - * which will then receive only broadcasts. - */ - - // TODO opt copy - osiSockAddr bcastAddress; - bcastAddress.ia.sin_family = AF_INET; - bcastAddress.ia.sin_port = htons(m_broadcastPort); - bcastAddress.ia.sin_addr.s_addr = node.ifaceBCast.ia.sin_addr.s_addr; - - transport2 = static_pointer_cast(broadcastConnector->connect( - nullTransportClient, m_responseHandler, - bcastAddress, PVA_PROTOCOL_REVISION, - PVA_DEFAULT_PRIORITY)); - /* The other wrinkle is that nothing should be sent from this second - * socket. So replies are made through the unicast socket. - */ - transport2->setReplyTransport(transport); - } - #endif - - transport->setMutlicastNIF(loAddr, true); - transport->setLocalMulticastAddress(group); - - transport->start(); - m_udpTransports.push_back(transport); - - if (transport2) - { - transport2->start(); - m_udpTransports.push_back(transport2); - } - } - catch (std::exception& e) - { - THROW_BASE_EXCEPTION_CAUSE("Failed to initialize broadcast UDP transport", e); - } - catch (...) - { - THROW_BASE_EXCEPTION("Failed to initialize broadcast UDP transport"); - } - } + initializeUDPTransports(false, m_udpTransports, ifaceList, m_responseHandler, m_searchTransport, + m_broadcastPort, m_autoAddressList, m_addressList, std::string()); return true; } @@ -5112,7 +4910,6 @@ namespace epics { /** * UDP transports needed to receive channel searches. */ - typedef std::vector BlockingUDPTransportVector; BlockingUDPTransportVector m_udpTransports; /** diff --git a/src/server/serverContext.cpp b/src/server/serverContext.cpp index 6f4059f..1698f0a 100644 --- a/src/server/serverContext.cpp +++ b/src/server/serverContext.cpp @@ -172,13 +172,15 @@ void ServerContextImpl::loadConfiguration() SOCKET sock = epicsSocketCreate(AF_INET, SOCK_STREAM, 0); if (!sock) { THROW_BASE_EXCEPTION("Failed to create a socket needed to introspect network interfaces."); - return; } - if (discoverInterfaces(_ifaceList, sock, &_ifaceAddr) || _ifaceList.size() == 0) + if (discoverInterfaces(_ifaceList, sock, &_ifaceAddr)) { - THROW_BASE_EXCEPTION("Failed to introspect network interfaces or no network interfaces available."); - return; + THROW_BASE_EXCEPTION("Failed to introspect network interfaces."); + } + else if (_ifaceList.size() == 0) + { + THROW_BASE_EXCEPTION("No (specified) network interface(s) available."); } epicsSocketDestroy(sock); } @@ -276,222 +278,8 @@ void ServerContextImpl::internalInitialize() void ServerContextImpl::initializeBroadcastTransport() { - TransportClient::shared_pointer nullTransportClient; - auto_ptr broadcastConnector(new BlockingUDPConnector(true, true, true)); - - // TODO configurable local NIF, address - osiSockAddr loAddr; - getLoopbackNIF(loAddr, "", 0); - - // TODO configurable local multicast address - osiSockAddr group; - aToIPAddr("224.0.0.128", _broadcastPort, &group.ia); - - // - // set ignore address list - // - auto_ptr ignoreAddressList; - if (!_ignoreAddressList.empty()) - ignoreAddressList.reset(getSocketAddressList(_ignoreAddressList, 0, 0)); - - // - // Setup UDP trasport(s) (per interface) - // - - InetAddrVector tappedNIF; - - for (IfaceNodeVector::const_iterator iter = _ifaceList.begin(); iter != _ifaceList.end(); iter++) - { - ifaceNode node = *iter; - - LOG(logLevelDebug, "Setting up UDP for interface %s, broadcast %s.", - inetAddressToString(node.ifaceAddr, false).c_str(), - inetAddressToString(node.ifaceBCast, false).c_str()); - try - { - // where to bind (listen) address - osiSockAddr listenLocalAddress; - listenLocalAddress.ia.sin_family = AF_INET; - listenLocalAddress.ia.sin_port = htons(_broadcastPort); - listenLocalAddress.ia.sin_addr.s_addr = node.ifaceAddr.ia.sin_addr.s_addr; - - BlockingUDPTransport::shared_pointer transport = static_pointer_cast(broadcastConnector->connect( - nullTransportClient, _responseHandler, - listenLocalAddress, PVA_PROTOCOL_REVISION, - PVA_DEFAULT_PRIORITY)); - listenLocalAddress = *transport->getRemoteAddress(); - // to allow automatic assignment of broadcast port (for testing) - if (_broadcastPort == 0) - { - _broadcastPort = ntohs(listenLocalAddress.ia.sin_port); - aToIPAddr("224.0.0.128", _broadcastPort, &group.ia); - - LOG(logLevelDebug, "Dynamic broadcast UDP port set to %d.", _broadcastPort); - } - - if (ignoreAddressList.get() && ignoreAddressList->size()) - transport->setIgnoredAddresses(ignoreAddressList.get()); - - tappedNIF.push_back(listenLocalAddress); - - - BlockingUDPTransport::shared_pointer transport2; - - if(node.ifaceBCast.ia.sin_family == AF_UNSPEC || - node.ifaceBCast.ia.sin_addr.s_addr == listenLocalAddress.ia.sin_addr.s_addr) { - LOG(logLevelWarn, "Unable to find broadcast address of interface %s.", inetAddressToString(node.ifaceBCast, false).c_str()); - } - #if !defined(_WIN32) - else - { - /* An oddness of BSD sockets (not winsock) is that binding to - * INADDR_ANY will receive unicast and broadcast, but binding to - * a specific interface address receives only unicast. The trick - * is to bind a second socket to the interface broadcast address, - * which will then receive only broadcasts. - */ - - osiSockAddr bcastAddress; - bcastAddress.ia.sin_family = AF_INET; - bcastAddress.ia.sin_port = htons(_broadcastPort); - bcastAddress.ia.sin_addr.s_addr = node.ifaceBCast.ia.sin_addr.s_addr; - - transport2 = static_pointer_cast(broadcastConnector->connect( - nullTransportClient, _responseHandler, - bcastAddress, PVA_PROTOCOL_REVISION, - PVA_DEFAULT_PRIORITY)); - /* The other wrinkle is that nothing should be sent from this second - * socket. So replies are made through the unicast socket. - */ - transport2->setReplyTransport(transport); - - if (ignoreAddressList.get() && ignoreAddressList->size()) - transport2->setIgnoredAddresses(ignoreAddressList.get()); - - tappedNIF.push_back(bcastAddress); - } - #endif - - transport->setMutlicastNIF(loAddr, true); - transport->setLocalMulticastAddress(group); - - transport->start(); - _udpTransports.push_back(transport); - - if (transport2) - { - transport2->start(); - _udpTransports.push_back(transport2); - } - } - catch (std::exception& e) - { - THROW_BASE_EXCEPTION_CAUSE("Failed to initialize broadcast UDP transport", e); - } - catch (...) - { - THROW_BASE_EXCEPTION("Failed to initialize broadcast UDP transport"); - } - } - - - // - // Create UDP transport for sending (to all network interfaces) - // - - osiSockAddr anyAddress; - anyAddress.ia.sin_family = AF_INET; - anyAddress.ia.sin_port = htons(0); - anyAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY); - - _broadcastTransport = static_pointer_cast(broadcastConnector->connect( - nullTransportClient, _responseHandler, - anyAddress, PVA_PROTOCOL_REVISION, - PVA_DEFAULT_PRIORITY)); - - // - // compile auto address list - where to send beacons - // - - InetAddrVector autoBCastAddr; - for (IfaceNodeVector::const_iterator iter = _ifaceList.begin(); iter != _ifaceList.end(); iter++) - { - ifaceNode node = *iter; - - if (node.ifaceBCast.ia.sin_family != AF_UNSPEC) - { - node.ifaceBCast.ia.sin_port = htons(_broadcastPort); - autoBCastAddr.push_back(node.ifaceBCast); - } - } - - // - // set beacon (broadcast) address list - // - - if (!_beaconAddressList.empty()) - { - // if auto is true, add it to specified list - if (!_autoBeaconAddressList) - autoBCastAddr.clear(); - - auto_ptr list(getSocketAddressList(_beaconAddressList, _broadcastPort, &autoBCastAddr)); - if (list.get() && list->size()) - { - _broadcastTransport->setSendAddresses(list.get()); - } - /* - else - { - // fallback - // set default (auto) address list - _broadcastTransport->setSendAddresses(&autoBCastAddr); - } - */ - } - else if (_autoBeaconAddressList) - { - // set default (auto) address list - _broadcastTransport->setSendAddresses(&autoBCastAddr); - } - - - // debug output of broadcast addresses - InetAddrVector* blist = _broadcastTransport->getSendAddresses(); - if (!blist || !blist->size()) - LOG(logLevelError, - "No broadcast addresses found or specified - empty beacon address list!"); - else - for (size_t i = 0; i < blist->size(); i++) - LOG(logLevelDebug, - "Beacon broadcast address #%d: %s.", i, inetAddressToString((*blist)[i]).c_str()); - - // - // Setup local multicasting - // - - BlockingUDPTransport::shared_pointer localMulticastTransport; - try - { - // NOTE: multicast receiver socket must be "bound" to INADDR_ANY or multicast address - localMulticastTransport = static_pointer_cast(broadcastConnector->connect( - nullTransportClient, _responseHandler, - group, PVA_PROTOCOL_REVISION, - PVA_DEFAULT_PRIORITY)); - localMulticastTransport->setTappedNIF(&tappedNIF); - localMulticastTransport->join(group, loAddr); - localMulticastTransport->start(); - _udpTransports.push_back(localMulticastTransport); - - LOG(logLevelDebug, "Local multicast enabled on %s/%s.", - inetAddressToString(loAddr, false).c_str(), - inetAddressToString(group).c_str()); - } - catch (std::exception& ex) - { - LOG(logLevelDebug, "Failed to initialize local multicast, funcionality disabled. Reason: %s.", ex.what()); - } - + initializeUDPTransports(true, _udpTransports, _ifaceList, _responseHandler, _broadcastTransport, + _broadcastPort, _autoBeaconAddressList, _beaconAddressList, _ignoreAddressList); } void ServerContextImpl::run(int32 seconds) diff --git a/src/server/serverContext.h b/src/server/serverContext.h index e75f42b..675d0ab 100644 --- a/src/server/serverContext.h +++ b/src/server/serverContext.h @@ -354,7 +354,6 @@ private: /** * UDP transports needed to receive channel searches. */ - typedef std::vector BlockingUDPTransportVector; BlockingUDPTransportVector _udpTransports; /** diff --git a/testApp/remote/channelAccessIFTest.cpp b/testApp/remote/channelAccessIFTest.cpp index 05a25ba..5e480b8 100755 --- a/testApp/remote/channelAccessIFTest.cpp +++ b/testApp/remote/channelAccessIFTest.cpp @@ -59,6 +59,7 @@ int ChannelAccessIFTest::runAllTest() { testPlan(153+EXTRA_STRESS_TESTS); Configuration::shared_pointer base_config(ConfigurationBuilder() + //.add("EPICS_PVA_DEBUG", "3") .add("EPICS_PVAS_INTF_ADDR_LIST", "127.0.0.1") .add("EPICS_PVA_ADDR_LIST", "127.0.0.1") .add("EPICS_PVA_AUTO_ADDR_LIST","0")