diff --git a/pvAccessApp/remote/blockingUDP.h b/pvAccessApp/remote/blockingUDP.h index 43b1b6f..d0b7990 100644 --- a/pvAccessApp/remote/blockingUDP.h +++ b/pvAccessApp/remote/blockingUDP.h @@ -17,7 +17,7 @@ #include #include #include -#include +#include /* EPICSv3 */ #include @@ -33,7 +33,6 @@ namespace epics { public: BlockingUDPTransport(ResponseHandler* responseHandler, SOCKET channel, osiSockAddr& bindAddress, - InetAddrVector* sendAddresses, short remoteTransportRevision); virtual ~BlockingUDPTransport(); @@ -43,7 +42,7 @@ namespace epics { } virtual const osiSockAddr* getRemoteAddress() const { - return _socketAddress; + return &_bindAddress; } virtual const String getType() const { @@ -97,7 +96,7 @@ namespace epics { virtual void close(bool forced); virtual void ensureData(int size) { - // TODO Auto-generated method stub + // noop } virtual void startMessage(int8 command, int ensureCapacity); @@ -108,13 +107,12 @@ namespace epics { } virtual void setRecipient(const osiSockAddr& sendTo) { - if(_sendTo!=NULL) delete _sendTo; - _sendTo = new osiSockAddr; - memcpy(_sendTo, &sendTo, sizeof(osiSockAddr)); + _sendToEnabled = true; + _sendTo = sendTo; } virtual void flushSerializeBuffer() { - // TODO Auto-generated method stub + // noop } virtual void ensureBuffer(int size) { @@ -126,7 +124,15 @@ namespace epics { * @param addresses list of ignored addresses. */ void setIgnoredAddresses(InetAddrVector* addresses) { - _ignoredAddresses = addresses; + if (addresses) + { + if (!_ignoredAddresses) _ignoredAddresses = new InetAddrVector; + *_ignoredAddresses = *addresses; + } + else + { + if (_ignoredAddresses) { delete _ignoredAddresses; _ignoredAddresses = 0; } + } } /** @@ -154,7 +160,7 @@ namespace epics { * @return bind address. */ const osiSockAddr* getBindAddress() const { - return _bindAddress; + return &_bindAddress; } /** @@ -162,11 +168,19 @@ namespace epics { * @param addresses list of send addresses, non-null. */ void setBroadcastAddresses(InetAddrVector* addresses) { - _sendAddresses = addresses; + if (addresses) + { + if (!_sendAddresses) _sendAddresses = new InetAddrVector; + *_sendAddresses = *addresses; + } + else + { + if (_sendAddresses) { delete _sendAddresses; _sendAddresses = 0; } + } } virtual IntrospectionRegistry* getIntrospectionRegistry() { - THROW_BASE_EXCEPTION("not supported by UDP transport"); + return 0; } protected: @@ -184,6 +198,8 @@ namespace epics { bool processBuffer(osiSockAddr& fromAddress, epics::pvData::ByteBuffer* receiveBuffer); + void close(bool forced, bool waitForThreadToComplete); + // Context only used for logging in this class /** @@ -191,15 +207,10 @@ namespace epics { */ SOCKET _channel; - /** - * Cached socket address. - */ - osiSockAddr* _socketAddress; - /** * Bind address. */ - osiSockAddr* _bindAddress; + osiSockAddr _bindAddress; /** * Send addresses. @@ -211,8 +222,12 @@ namespace epics { */ InetAddrVector* _ignoredAddresses; - osiSockAddr* _sendTo; - + /** + * Send address. + */ + osiSockAddr _sendTo; + bool _sendToEnabled; + /** * Receive buffer. */ @@ -228,15 +243,12 @@ namespace epics { */ int _lastMessageStartPosition; - /** - * Read buffer - */ - char* _readBuffer; - /** * Used for process sync. */ - Mutex* _mutex; + Mutex _mutex; + Mutex _sendMutex; + Event _shutdownEvent; /** * Thread ID @@ -245,18 +257,19 @@ namespace epics { }; - class BlockingUDPConnector : public Connector, - public epics::pvData::NoDefaultMethods { + class BlockingUDPConnector : + public Connector, + private epics::pvData::NoDefaultMethods { public: - BlockingUDPConnector(bool reuseSocket, - InetAddrVector* sendAddresses, bool broadcast) : - _sendAddresses(sendAddresses), _reuseSocket(reuseSocket), - _broadcast(broadcast) { + BlockingUDPConnector( + bool reuseSocket, + bool broadcast) : + _reuseSocket(reuseSocket), + _broadcast(broadcast) { } virtual ~BlockingUDPConnector() { - // TODO: delete _sendAddresses here? } /** @@ -268,11 +281,6 @@ namespace epics { private: - /** - * Send address. - */ - InetAddrVector* _sendAddresses; - /** * Reuse socket flag. */ diff --git a/pvAccessApp/remote/blockingUDPConnector.cpp b/pvAccessApp/remote/blockingUDPConnector.cpp index 00225bc..6f66853 100644 --- a/pvAccessApp/remote/blockingUDPConnector.cpp +++ b/pvAccessApp/remote/blockingUDPConnector.cpp @@ -9,9 +9,6 @@ #include "blockingUDP.h" #include "remote.h" -/* pvData */ -#include - /* EPICSv3 */ #include #include @@ -26,6 +23,7 @@ namespace epics { Transport* BlockingUDPConnector::connect(TransportClient* client, ResponseHandler* responseHandler, osiSockAddr& bindAddress, short transportRevision, int16 priority) { + errlogSevPrintf(errlogInfo, "Creating datagram socket to: %s", inetAddressToString(&bindAddress).c_str()); @@ -33,40 +31,32 @@ namespace epics { if(socket==INVALID_SOCKET) { char errStr[64]; epicsSocketConvertErrnoToString(errStr, sizeof(errStr)); - errlogSevPrintf(errlogMajor, "Error creating socket: %s", - errStr); + errlogSevPrintf(errlogMajor, "Error creating socket: %s", errStr); + return 0; } int optval = _broadcast ? 1 : 0; - int retval = ::setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &optval, - sizeof(optval)); - if(retval<0) errlogSevPrintf(errlogMajor, - "Error setting SO_BROADCAST: %s", strerror(errno)); - - // set the socket options + int retval = ::setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)); + if(retval<0) + { + errlogSevPrintf(errlogMajor, "Error setting SO_BROADCAST: %s", strerror(errno)); + epicsSocketDestroy (socket); + return 0; + } + + // set SO_REUSEADDR or SO_REUSEPORT, OS dependant if (_reuseSocket) epicsSocketEnableAddressUseForDatagramFanout(socket); -/* - optval = _reuseSocket ? 1 : 0; - // or SO_REUSEADDR, OS dependant - retval = ::setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &optval, - sizeof(optval)); - if(retval<0) errlogSevPrintf(errlogMajor, - "Error setting SO_REUSEADDR: %s", strerror(errno)); -*/ - retval = ::bind(socket, (sockaddr*)&(bindAddress.sa), - sizeof(sockaddr)); + retval = ::bind(socket, (sockaddr*)&(bindAddress.sa), sizeof(sockaddr)); if(retval<0) { - errlogSevPrintf(errlogMajor, "Error binding socket: %s", - strerror(errno)); - THROW_BASE_EXCEPTION(strerror(errno)); + errlogSevPrintf(errlogMajor, "Error binding socket: %s", strerror(errno)); + epicsSocketDestroy (socket); + return 0; } // sockets are blocking by default - - return new BlockingUDPTransport(responseHandler, socket, - bindAddress, _sendAddresses, transportRevision); + return new BlockingUDPTransport(responseHandler, socket, bindAddress, transportRevision); } } diff --git a/pvAccessApp/remote/blockingUDPTransport.cpp b/pvAccessApp/remote/blockingUDPTransport.cpp index 7e5cba5..08a00db 100644 --- a/pvAccessApp/remote/blockingUDPTransport.cpp +++ b/pvAccessApp/remote/blockingUDPTransport.cpp @@ -33,83 +33,85 @@ namespace epics { BlockingUDPTransport::BlockingUDPTransport( ResponseHandler* responseHandler, SOCKET channel, - osiSockAddr& bindAddress, InetAddrVector* sendAddresses, + osiSockAddr& bindAddress, short remoteTransportRevision) : _closed(false), _responseHandler(responseHandler), _channel(channel), - _sendAddresses(sendAddresses), - _ignoredAddresses(NULL), - _sendTo(NULL), - _receiveBuffer(new ByteBuffer(MAX_UDP_RECV, - EPICS_ENDIAN_BIG)), + _bindAddress(bindAddress), + _sendAddresses(0), + _ignoredAddresses(0), + _sendToEnabled(false), + _receiveBuffer(new ByteBuffer(MAX_UDP_RECV, EPICS_ENDIAN_BIG)), _sendBuffer(new ByteBuffer(MAX_UDP_RECV, EPICS_ENDIAN_BIG)), - _lastMessageStartPosition(0), _readBuffer( - new char[MAX_UDP_RECV]), _mutex(new Mutex()), - _threadId(NULL) { - _socketAddress = new osiSockAddr; - memcpy(_socketAddress, &bindAddress, sizeof(osiSockAddr)); - _bindAddress = _socketAddress; - + _lastMessageStartPosition(0), + _threadId(0) + { } BlockingUDPTransport::~BlockingUDPTransport() { close(true); // close the socket and stop the thread. - if(_sendTo!=NULL) delete _sendTo; - delete _socketAddress; - // _bindAddress equals _socketAddress + + if (_sendAddresses) delete _sendAddresses; + if (_ignoredAddresses) delete _ignoredAddresses; delete _receiveBuffer; delete _sendBuffer; - delete[] _readBuffer; - delete _mutex; } void BlockingUDPTransport::start() { - String threadName = "UDP-receive "+inetAddressToString( - _socketAddress); + String threadName = "UDP-receive "+inetAddressToString(&_bindAddress); - errlogSevPrintf(errlogInfo, "Starting thread: %s", - threadName.c_str()); + errlogSevPrintf(errlogInfo, "Starting thread: %s",threadName.c_str()); _threadId = epicsThreadCreate(threadName.c_str(), - epicsThreadPriorityMedium, epicsThreadGetStackSize( - epicsThreadStackMedium), + epicsThreadPriorityMedium, + epicsThreadGetStackSize(epicsThreadStackMedium), BlockingUDPTransport::threadRunner, this); } void BlockingUDPTransport::close(bool forced) { - if(_closed) return; - _closed = true; + close(forced, true); + } - if(_bindAddress!=NULL) errlogSevPrintf(errlogInfo, + void BlockingUDPTransport::close(bool forced, bool waitForThreadToComplete) { + { + Lock guard(&_mutex); + if(_closed) return; + _closed = true; + + errlogSevPrintf(errlogInfo, "UDP socket %s closed.", - inetAddressToString(_bindAddress).c_str()); - - epicsSocketDestroy(_channel); + inetAddressToString(&_bindAddress).c_str()); + + epicsSocketDestroy(_channel); + } + + // wait for send thread to exit cleanly + if (waitForThreadToComplete) + _shutdownEvent.wait(3.0); } void BlockingUDPTransport::enqueueSendRequest(TransportSender* sender) { - Lock lock(_mutex); + Lock lock(&_sendMutex); - _sendTo = NULL; + _sendToEnabled = false; _sendBuffer->clear(); sender->lock(); try { sender->send(_sendBuffer, this); sender->unlock(); endMessage(); - if(_sendTo==NULL) + if(!_sendToEnabled) send(_sendBuffer); else - send(_sendBuffer, *_sendTo); + send(_sendBuffer, _sendTo); } catch(...) { sender->unlock(); } } - void BlockingUDPTransport::startMessage(int8 command, - int ensureCapacity) { + void BlockingUDPTransport::startMessage(int8 command, int ensureCapacity) { _lastMessageStartPosition = _sendBuffer->getPosition(); _sendBuffer->putShort(CA_MAGIC_AND_VERSION); _sendBuffer->putByte(0); // data @@ -118,21 +120,29 @@ namespace epics { } void BlockingUDPTransport::endMessage() { - _sendBuffer->putInt(_lastMessageStartPosition+(sizeof(int16)+2), - _sendBuffer->getPosition()-_lastMessageStartPosition - -CA_MESSAGE_HEADER_SIZE); - + _sendBuffer->putInt( + _lastMessageStartPosition+(sizeof(int16)+2), + _sendBuffer->getPosition()-_lastMessageStartPosition-CA_MESSAGE_HEADER_SIZE); } void BlockingUDPTransport::processRead() { // This function is always called from only one thread - this // object's own thread. + char _readBuffer[MAX_UDP_RECV]; osiSockAddr fromAddress; try { + bool closed; while(!_closed) { + + _mutex.lock(); + closed = _closed; + _mutex.unlock(); + if (closed) + break; + // we poll to prevent blocking indefinitely // data ready to be read @@ -147,18 +157,23 @@ namespace epics { if(bytesRead>0) { // successfully got datagram bool ignore = false; - if(_ignoredAddresses!=NULL) for(size_t i = 0; i - <_ignoredAddresses->size(); i++) + if(_ignoredAddresses!=0) + { + for(size_t i = 0; i <_ignoredAddresses->size(); i++) if(_ignoredAddresses->at(i)->ia.sin_addr.s_addr ==fromAddress.ia.sin_addr.s_addr) { ignore = true; break; } - + } + if(!ignore) { - _receiveBuffer->put(_readBuffer, 0, bytesRead - <_receiveBuffer->getRemaining() ? bytesRead - : _receiveBuffer->getRemaining()); + // TODO do not copy.... wrap the buffer!!! + _receiveBuffer->put(_readBuffer, 0, + bytesRead <_receiveBuffer->getRemaining() ? + bytesRead : + _receiveBuffer->getRemaining() + ); _receiveBuffer->flip(); @@ -166,22 +181,26 @@ namespace epics { } } else { - // 0 == socket close - + // 0 == socket remotely closed // log a 'recvfrom' error - if(bytesRead==-1) errlogSevPrintf(errlogMajor, + if(!_closed && bytesRead==-1) errlogSevPrintf(errlogMajor, "Socket recv error: %s", strerror(errno)); + + close(true, false); + break; } } } catch(...) { // TODO: catch all exceptions, and act accordingly - close(true); + close(true, false); } char threadName[40]; epicsThreadGetName(_threadId, threadName, 40); errlogSevPrintf(errlogInfo, "Thread '%s' exiting", threadName); + + _shutdownEvent.signal(); } bool BlockingUDPTransport::processBuffer(osiSockAddr& fromAddress, @@ -240,7 +259,7 @@ namespace epics { } bool BlockingUDPTransport::send(ByteBuffer* buffer) { - if(_sendAddresses==NULL) return false; + if(!_sendAddresses) return false; for(size_t i = 0; i<_sendAddresses->size(); i++) { buffer->flip(); @@ -262,7 +281,7 @@ namespace epics { // that is the buffer size used by the platform for input on // this DatagramSocket. - int sockBufSize; + int sockBufSize = -1; socklen_t intLen = sizeof(int); int retval = getsockopt(_channel, SOL_SOCKET, SO_RCVBUF, diff --git a/testApp/remote/testBeaconEmitter.cpp b/testApp/remote/testBeaconEmitter.cpp index 9e98d85..4c6cdaa 100644 --- a/testApp/remote/testBeaconEmitter.cpp +++ b/testApp/remote/testBeaconEmitter.cpp @@ -56,36 +56,26 @@ void testBeaconEmitter() { ContextImpl ctx; DummyResponseHandler drh(&ctx); -/* SOCKET mysocket; - if ((mysocket = socket (AF_INET, SOCK_DGRAM, 0)) == -1) - { - assert(false); - } - InetAddrVector* broadcastAddresses = getBroadcastAddresses(mysocket);*/ + SOCKET socket = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0); + auto_ptr broadcastAddresses(getBroadcastAddresses(socket, 5067)); + epicsSocketDestroy (socket); - InetAddrVector* broadcastAddresses = new InetAddrVector; - osiSockAddr* addr = new osiSockAddr; - addr->ia.sin_family = AF_INET; - addr->ia.sin_port = htons(5067); - if(inet_aton("255.255.255.255",&addr->ia.sin_addr)==0) - { - assert(false); - } - broadcastAddresses->push_back(addr); - BlockingUDPConnector connector(true, broadcastAddresses, true); + BlockingUDPConnector connector(true, true); osiSockAddr bindAddr; bindAddr.ia.sin_family = AF_INET; bindAddr.ia.sin_port = htons(5066); bindAddr.ia.sin_addr.s_addr = htonl(INADDR_ANY); - Transport* transport = connector.connect(NULL, &drh, bindAddr, 1, 50); + + BlockingUDPTransport* transport = (BlockingUDPTransport*)connector.connect(NULL, &drh, bindAddr, 1, 50); + transport->setBroadcastAddresses(broadcastAddresses.get()); cout<<"Sending beacons"<getRemoteAddress()); beaconEmitter.start(); - while(1) sleep(1); + epicsThreadSleep (60.0); delete transport; } diff --git a/testApp/remote/testBeaconHandler.cpp b/testApp/remote/testBeaconHandler.cpp index 0e5ec28..c72194d 100644 --- a/testApp/remote/testBeaconHandler.cpp +++ b/testApp/remote/testBeaconHandler.cpp @@ -57,15 +57,15 @@ public: transport->ensureData((2*sizeof(int16)+2*sizeof(int32)+128)/sizeof(int8)); - const int32 sequentalID = payloadBuffer->getShort() & 0x0000FFFF; - const TimeStamp startupTimestamp(payloadBuffer->getInt() & 0x00000000FFFFFFFFL,(int32)(payloadBuffer->getInt() & 0x00000000FFFFFFFFL)); + /*const int32 sequentalID = */ payloadBuffer->getShort(); + const TimeStamp startupTimestamp(payloadBuffer->getInt(),payloadBuffer->getInt()); // 128-bit IPv6 address osiSockAddr address; decodeFromIPv6Address(payloadBuffer, &address); // get port - const int32 port = payloadBuffer->getShort() & 0xFFFF; + const int32 port = payloadBuffer->getShort(); address.ia.sin_port = ntohs(port); // accept given address if explicitly specified by sender @@ -130,7 +130,7 @@ void testBeaconHandler() { ContextImpl ctx; BeaconResponseHandler brh(&ctx); - BlockingUDPConnector connector(false, NULL, true); + BlockingUDPConnector connector(false, true); osiSockAddr bindAddr; bindAddr.ia.sin_family = AF_INET; @@ -139,7 +139,7 @@ void testBeaconHandler() Transport* transport = connector.connect(NULL, &brh, bindAddr, 1, 50); (static_cast(transport))->start(); - while(1) sleep(1); + epicsThreadSleep (60.0); delete transport; } diff --git a/testApp/remote/testBlockingUDPClnt.cpp b/testApp/remote/testBlockingUDPClnt.cpp index 2117906..d34ae35 100644 --- a/testApp/remote/testBlockingUDPClnt.cpp +++ b/testApp/remote/testBlockingUDPClnt.cpp @@ -5,17 +5,19 @@ * Author: Miha Vitorovic */ -#include "remote.h" -#include "blockingUDP.h" -#include "logger.h" -#include "inetAddressUtil.h" +#include +#include +#include +#include + +//#include #include #include #include -#define SRV_IP "192.168.71.132" +#define SRV_IP "127.0.0.1" using namespace epics::pvAccess; using namespace epics::pvData; @@ -28,19 +30,16 @@ static osiSockAddr sendTo; class ContextImpl : public Context { public: - ContextImpl() : - _tr(new TransportRegistry()), _timer(new Timer("server thread", - lowPriority)), _conf(new SystemConfigurationImpl()) { - } + ContextImpl() + {} + virtual ~ContextImpl() { - delete _tr; - delete _timer; } virtual Timer* getTimer() { - return _timer; + return 0; } virtual TransportRegistry* getTransportRegistry() { - return _tr; + return 0; } virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; @@ -49,13 +48,8 @@ public: return 0; } virtual Configuration* getConfiguration() { - return _conf; + return 0; } - -private: - TransportRegistry* _tr; - Timer* _timer; - Configuration* _conf; }; class DummyResponseHandler : public ResponseHandler { @@ -97,7 +91,7 @@ private: }; void testBlockingUDPSender() { - BlockingUDPConnector connector(false, NULL, true); + BlockingUDPConnector connector(false, true); ContextImpl ctx; DummyTransportSender dts; @@ -130,8 +124,11 @@ void testBlockingUDPSender() { } int main(int argc, char *argv[]) { - createFileLogger("testBlockingUDPClnt.log"); +// createFileLogger("testBlockingUDPClnt.log"); testBlockingUDPSender(); + +// std::cout << "-----------------------------------------------------------------------" << std::endl; +// getShowConstructDestruct()->constuctDestructTotals(stdout); return (0); } diff --git a/testApp/remote/testBlockingUDPSrv.cpp b/testApp/remote/testBlockingUDPSrv.cpp index 5308428..a8c3aa4 100644 --- a/testApp/remote/testBlockingUDPSrv.cpp +++ b/testApp/remote/testBlockingUDPSrv.cpp @@ -23,19 +23,15 @@ using std::dec; class ContextImpl : public Context { public: - ContextImpl() : - _tr(new TransportRegistry()), _timer(new Timer("server thread", - lowPriority)), _conf(new SystemConfigurationImpl()) { - } + ContextImpl() {} + virtual ~ContextImpl() { - delete _tr; - delete _timer; } virtual Timer* getTimer() { - return _timer; + return 0; } virtual TransportRegistry* getTransportRegistry() { - return _tr; + return 0; } virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; @@ -44,13 +40,8 @@ public: return 0; } virtual Configuration* getConfiguration() { - return _conf; + return 0; } - -private: - TransportRegistry* _tr; - Timer* _timer; - Configuration* _conf; }; class DummyResponseHandler : public ResponseHandler { @@ -102,7 +93,7 @@ void DummyResponseHandler::handleResponse(osiSockAddr* responseFrom, } void testBlockingUDPConnector() { - BlockingUDPConnector connector(false, NULL, true); + BlockingUDPConnector connector(false, true); ContextImpl ctx; DummyResponseHandler drh(&ctx); @@ -127,7 +118,7 @@ void testBlockingUDPConnector() { } int main(int argc, char *argv[]) { - createFileLogger("testBlockingUDPSrv.log"); +// createFileLogger("testBlockingUDPSrv.log"); testBlockingUDPConnector(); return (0); diff --git a/testApp/remote/testRemoteClientImpl.cpp b/testApp/remote/testRemoteClientImpl.cpp index a317037..2e00223 100644 --- a/testApp/remote/testRemoteClientImpl.cpp +++ b/testApp/remote/testRemoteClientImpl.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include ƒ #include #include @@ -2309,6 +2309,7 @@ class TestChannelImpl : public ChannelImpl { // setup UDP transport initializeUDPTransport(); + // TODO what if initialization failed!!! // setup search manager m_channelSearchManager = new ChannelSearchManager(this); @@ -2317,73 +2318,63 @@ class TestChannelImpl : public ChannelImpl { /** * Initialized UDP transport (broadcast socket and repeater connection). */ - void initializeUDPTransport() { - // setup UDP transport - try + bool initializeUDPTransport() { + + // quary broadcast addresses of all IFs + SOCKET socket = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0); + auto_ptr broadcastAddresses(getBroadcastAddresses(socket, m_broadcastPort)); + epicsSocketDestroy (socket); + + // set broadcast address list + if (!m_addressList.empty()) { - // where to bind (listen) address - osiSockAddr listenLocalAddress; - listenLocalAddress.ia.sin_family = AF_INET; - listenLocalAddress.ia.sin_port = htons(m_broadcastPort); - listenLocalAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY); + // if auto is true, add it to specified list + InetAddrVector* appendList = 0; + if (m_autoAddressList) + appendList = broadcastAddresses.get(); - // where to send address - SOCKET socket = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0); - InetAddrVector* broadcastAddresses = getBroadcastAddresses(socket, m_broadcastPort); - cout<<"Broadcast addresses: "<size()<size(); i++) { - cout<<"Broadcast address: "; - cout<at(i))<connect( - 0, new ClientResponseHandler(this), - listenLocalAddress, CA_MINOR_PROTOCOL_REVISION, - CA_DEFAULT_PRIORITY); - - - BlockingUDPConnector* searchConnector = new BlockingUDPConnector(false, broadcastAddresses, true); - - // undefined address - osiSockAddr undefinedAddress; - undefinedAddress.ia.sin_family = AF_INET; - undefinedAddress.ia.sin_port = htons(0); - undefinedAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY); - - m_searchTransport = (BlockingUDPTransport*)searchConnector->connect( - 0, new ClientResponseHandler(this), - undefinedAddress, CA_MINOR_PROTOCOL_REVISION, - CA_DEFAULT_PRIORITY); - - // set broadcast address list - if (!m_addressList.empty()) - { - // if auto is true, add it to specified list - InetAddrVector* appendList = 0; - if (m_autoAddressList) - appendList = m_broadcastTransport->getSendAddresses(); - - InetAddrVector* list = getSocketAddressList(m_addressList, m_broadcastPort, appendList); - // TODO delete !!!! - if (list && list->size()) { - m_broadcastTransport->setBroadcastAddresses(list); - m_searchTransport->setBroadcastAddresses(list); - } + auto_ptr list(getSocketAddressList(m_addressList, m_broadcastPort, appendList)); + if (list.get() && list->size()) { + // delete old list and take ownership of a new one + broadcastAddresses = list; } - - m_broadcastTransport->start(); - m_searchTransport->start(); - - } - catch (...) - { - // TODO } + + // where to bind (listen) address + osiSockAddr listenLocalAddress; + listenLocalAddress.ia.sin_family = AF_INET; + listenLocalAddress.ia.sin_port = htons(m_broadcastPort); + listenLocalAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY); + + BlockingUDPConnector* broadcastConnector = new BlockingUDPConnector(true, true); + m_broadcastTransport = (BlockingUDPTransport*)broadcastConnector->connect( + 0, new ClientResponseHandler(this), + listenLocalAddress, CA_MINOR_PROTOCOL_REVISION, + CA_DEFAULT_PRIORITY); + if (!m_broadcastTransport) + return false; + m_broadcastTransport->setBroadcastAddresses(broadcastAddresses.get()); + + // undefined address + osiSockAddr undefinedAddress; + undefinedAddress.ia.sin_family = AF_INET; + undefinedAddress.ia.sin_port = htons(0); + undefinedAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY); + + BlockingUDPConnector* searchConnector = new BlockingUDPConnector(false, true); + m_searchTransport = (BlockingUDPTransport*)searchConnector->connect( + 0, new ClientResponseHandler(this), + undefinedAddress, CA_MINOR_PROTOCOL_REVISION, + CA_DEFAULT_PRIORITY); + if (!m_searchTransport) + return false; + m_searchTransport->setBroadcastAddresses(broadcastAddresses.get()); + + // become active + m_broadcastTransport->start(); + m_searchTransport->start(); + + return true; } void internalDestroy() { @@ -3077,10 +3068,11 @@ int main(int argc,char *argv[]) ChannelRequesterImpl channelRequester; Channel* channel = context->getProvider()->createChannel("structureArrayTest", &channelRequester); + + epicsThreadSleep ( 1.0 ); + channel->printInfo(); - - epicsThreadSleep ( 3.0 ); - +/* GetFieldRequesterImpl getFieldRequesterImpl; channel->getField(&getFieldRequesterImpl, ""); epicsThreadSleep ( 1.0 ); @@ -3112,7 +3104,7 @@ int main(int argc,char *argv[]) //TODOchannelPut->destroy(); // TODO delete pvRequest - +*/ /* MonitorRequesterImpl monitorRequesterImpl; Monitor* monitor = channel->createMonitor(&monitorRequesterImpl, 0); @@ -3130,7 +3122,7 @@ int main(int argc,char *argv[]) monitor->destroy(); */ - epicsThreadSleep ( 20.0 ); + epicsThreadSleep ( 3.0 ); channel->destroy(); context->destroy();