diff --git a/.cproject b/.cproject index e91f269..0e0c996 100644 --- a/.cproject +++ b/.cproject @@ -307,7 +307,6 @@ make - all true true @@ -315,7 +314,6 @@ make - clean true true @@ -323,11 +321,20 @@ make + uninstall true true false + + make + + clean all DEBUG=1 + true + true + false + diff --git a/configure/CONFIG_SITE b/configure/CONFIG_SITE index 287667b..7f70b02 100644 --- a/configure/CONFIG_SITE +++ b/configure/CONFIG_SITE @@ -24,4 +24,11 @@ # take effect. #IOCS_APPL_TOP = -USR_LDFLAGS += -lpthread +ifeq ($(DEBUG),1) + DEBUG_CFLAGS=-O0 -g -ggdb +endif + +ifeq ($(EPICS_HOST_ARCH),linux-x86) + USR_LDFLAGS += -lpthread +endif + diff --git a/pvAccessApp/Makefile b/pvAccessApp/Makefile index 687ee94..ce364c2 100644 --- a/pvAccessApp/Makefile +++ b/pvAccessApp/Makefile @@ -67,6 +67,7 @@ LIBSRCS += blockingTCPConnector.cpp LIBSRCS += blockingServerTCPTransport.cpp LIBSRCS += blockingTCPAcceptor.cpp LIBSRCS += channelSearchManager.cpp +LIBSRCS += abstractResponseHandler.cpp SRC_DIRS += $(PVACCESS)/remoteClient diff --git a/pvAccessApp/remote/abstractResponseHandler.cpp b/pvAccessApp/remote/abstractResponseHandler.cpp new file mode 100644 index 0000000..2d5f0b3 --- /dev/null +++ b/pvAccessApp/remote/abstractResponseHandler.cpp @@ -0,0 +1,42 @@ +/* + * abstractResponseHandler.cpp + * + * Created on: Jan 10, 2011 + * Author: Miha Vitorovic + */ + +#include "remote.h" +#include "hexDump.h" + +#include + +#include + +#include + +using std::ostringstream; +using std::hex; + +using namespace epics::pvData; + +namespace epics { + namespace pvAccess { + + void AbstractResponseHandler::handleResponse(osiSockAddr* responseFrom, + Transport* transport, int8 version, int8 command, + int payloadSize, ByteBuffer* payloadBuffer) { + if(_debug) { + char ipAddrStr[48]; + ipAddrToDottedIP(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr)); + + ostringstream prologue; + prologue<<"Message [0x"<getArray(), + payloadBuffer->getPosition(), payloadSize); + } + } + } +} diff --git a/pvAccessApp/remote/blockingServerTCPTransport.cpp b/pvAccessApp/remote/blockingServerTCPTransport.cpp index 9048920..042a2b8 100644 --- a/pvAccessApp/remote/blockingServerTCPTransport.cpp +++ b/pvAccessApp/remote/blockingServerTCPTransport.cpp @@ -52,7 +52,7 @@ namespace epics { if(_channels->size()==0) return; char ipAddrStr[64]; - ipAddrToA(&_socketAddress->ia, ipAddrStr, sizeof(ipAddrStr)); + ipAddrToDottedIP(&_socketAddress->ia, ipAddrStr, sizeof(ipAddrStr)); errlogSevPrintf( errlogInfo, diff --git a/pvAccessApp/remote/blockingTCPAcceptor.cpp b/pvAccessApp/remote/blockingTCPAcceptor.cpp index c5bfcb7..10c5f21 100644 --- a/pvAccessApp/remote/blockingTCPAcceptor.cpp +++ b/pvAccessApp/remote/blockingTCPAcceptor.cpp @@ -51,7 +51,7 @@ namespace epics { char strBuffer[64]; char ipAddrStr[48]; - ipAddrToA(&_bindAddress->ia, ipAddrStr, sizeof(ipAddrStr)); + ipAddrToDottedIP(&_bindAddress->ia, ipAddrStr, sizeof(ipAddrStr)); int tryCount = 0; while(tryCount<2) { @@ -150,7 +150,7 @@ namespace epics { void BlockingTCPAcceptor::handleEvents() { // rise level if port is assigned dynamically char ipAddrStr[48]; - ipAddrToA(&_bindAddress->ia, ipAddrStr, sizeof(ipAddrStr)); + ipAddrToDottedIP(&_bindAddress->ia, ipAddrStr, sizeof(ipAddrStr)); errlogSevPrintf(errlogInfo, "Accepting connections at %s.", ipAddrStr); @@ -183,7 +183,8 @@ namespace epics { _serverSocketChannel, &address.sa, &len); if(newClient!=INVALID_SOCKET) { // accept succeeded - ipAddrToA(&address.ia, ipAddrStr, sizeof(ipAddrStr)); + ipAddrToDottedIP(&address.ia, ipAddrStr, + sizeof(ipAddrStr)); errlogSevPrintf(errlogInfo, "Accepted connection from CA client: %s", ipAddrStr); @@ -273,7 +274,8 @@ namespace epics { if(_serverSocketChannel!=INVALID_SOCKET) { char ipAddrStr[48]; - ipAddrToA(&_bindAddress->ia, ipAddrStr, sizeof(ipAddrStr)); + ipAddrToDottedIP(&_bindAddress->ia, ipAddrStr, + sizeof(ipAddrStr)); errlogSevPrintf(errlogInfo, "Stopped accepting connections at %s.", ipAddrStr); diff --git a/pvAccessApp/remote/blockingTCPConnector.cpp b/pvAccessApp/remote/blockingTCPConnector.cpp index 1bd09d4..5c3b021 100644 --- a/pvAccessApp/remote/blockingTCPConnector.cpp +++ b/pvAccessApp/remote/blockingTCPConnector.cpp @@ -106,8 +106,17 @@ namespace epics { ipAddrStr); socket = tryConnect(address, 3); - if (socket == INVALID_SOCKET) - return 0; + // verify + if(socket==INVALID_SOCKET) { + errlogSevPrintf( + errlogMajor, + "Connection to CA server %s failed.", + ipAddrStr); + ostringstream temp; + temp<<"Failed to verify TCP connection to '"<waitUntilVerified(3.0)) { transport->close(true); errlogSevPrintf( - errlogInfo, + errlogMinor, "Connection to CA server %s failed to be validated, closing it.", ipAddrStr); ostringstream temp; diff --git a/pvAccessApp/remote/remote.h b/pvAccessApp/remote/remote.h index f5129d1..8a8aaea 100644 --- a/pvAccessApp/remote/remote.h +++ b/pvAccessApp/remote/remote.h @@ -11,7 +11,7 @@ #include "caConstants.h" #include "transportRegistry.h" #include "introspectionRegistry.h" -#include "serverContext.h" +#include "configuration.h" #include #include @@ -32,42 +32,42 @@ namespace epics { }; enum QoS { - /** - * Default behavior. - */ - DEFAULT = 0x00, - /** - * Require reply (acknowledgment for reliable operation). - */ - REPLY_REQUIRED = 0x01, - /** - * Best-effort option (no reply). - */ - BESY_EFFORT = 0x02, - /** - * Process option. - */ - PROCESS = 0x04, - /** - * Initialize option. - */ - INIT = 0x08, - /** - * Destroy option. - */ - DESTROY = 0x10, - /** - * Share data option. - */ - SHARE = 0x20, - /** - * Get. - */ - GET = 0x40, - /** - * Get-put. - */ - GET_PUT =0x80 + /** + * Default behavior. + */ + DEFAULT = 0x00, + /** + * Require reply (acknowledgment for reliable operation). + */ + REPLY_REQUIRED = 0x01, + /** + * Best-effort option (no reply). + */ + BESY_EFFORT = 0x02, + /** + * Process option. + */ + PROCESS = 0x04, + /** + * Initialize option. + */ + INIT = 0x08, + /** + * Destroy option. + */ + DESTROY = 0x10, + /** + * Share data option. + */ + SHARE = 0x20, + /** + * Get. + */ + GET = 0x40, + /** + * Get-put. + */ + GET_PUT = 0x80 }; typedef int32 pvAccessID; @@ -253,6 +253,35 @@ namespace epics { }; + class Channel; + + /** + * Not public IF, used by Transports, etc. + */ + class Context { + public: + virtual ~Context() { + } + /** + * Get timer. + * @return timer. + */ + virtual Timer* getTimer() = 0; + + /** + * Get transport (virtual circuit) registry. + * @return transport (virtual circuit) registry. + */ + virtual TransportRegistry* getTransportRegistry() = 0; + + virtual Channel* getChannel(pvAccessID id) = 0; + + virtual Transport* getSearchTransport() = 0; + + virtual Configuration* getConfiguration() = 0; + + }; + /** * Interface defining response handler. * @author Matej Sekoranja @@ -260,6 +289,10 @@ namespace epics { */ class ResponseHandler { public: + ResponseHandler(Context* context) : + _context(context) { + } + virtual ~ResponseHandler() { } @@ -277,6 +310,9 @@ namespace epics { handleResponse(osiSockAddr* responseFrom, Transport* transport, int8 version, int8 command, int payloadSize, epics::pvData::ByteBuffer* payloadBuffer) =0; + + protected: + Context* _context; }; /** @@ -289,9 +325,10 @@ namespace epics { /** * @param description */ - AbstractResponseHandler(String description) : - _description(description), _debug(true) { - //debug = System.getProperties().containsKey(CAConstants.CAJ_DEBUG); + AbstractResponseHandler(Context* context, String description) : + ResponseHandler(context), _description(description), _debug( + _context->getConfiguration()->getPropertyAsBoolean( + "PVACCESS_DEBUG", false)) { } virtual ~AbstractResponseHandler() { @@ -373,33 +410,6 @@ namespace epics { }; - class Channel; - - /** - * Not public IF, used by Transports, etc. - */ - class Context { - public: - virtual ~Context() { - } - /** - * Get timer. - * @return timer. - */ - virtual Timer* getTimer() =0; - - /** - * Get transport (virtual circuit) registry. - * @return transport (virtual circuit) registry. - */ - virtual TransportRegistry* getTransportRegistry() =0; - - virtual Channel* getChannel(pvAccessID id) = 0; - - virtual Transport* getSearchTransport() = 0; - - }; - /** * Interface defining reference counting transport IF. * @author Matej Sekoranja @@ -474,7 +484,8 @@ namespace epics { * @param sid preallocated channel SID. * @param channel channel to register. */ - virtual void registerChannel(pvAccessID sid, ServerChannel* channel) =0; + virtual void + registerChannel(pvAccessID sid, ServerChannel* channel) =0; /** * Unregister a new channel (and deallocates its handle). @@ -495,44 +506,44 @@ namespace epics { */ virtual int getChannelCount() =0; }; - + /** * A request that expects an response. - * Responses identified by its I/O ID. + * Responses identified by its I/O ID. * This interface needs to be extended (to provide method called on response). * @author Matej Sekoranja */ class ResponseRequest { - public: - - /** - * Get I/O ID. - * @return ioid - */ - virtual pvAccessID getIOID() = 0; - - /** - * Timeout notification. - */ - virtual void timeout() = 0; - - /** - * Cancel response request (always to be called to complete/destroy). - */ - virtual void cancel() = 0; - - /** - * Report status to clients (e.g. disconnected). - * @param status to report. - */ - virtual void reportStatus(epics::pvData::Status* status) = 0; - - /** - * Get request requester. - * @return request requester. - */ - virtual epics::pvData::Requester* getRequester() = 0; - }; + public: + + /** + * Get I/O ID. + * @return ioid + */ + virtual pvAccessID getIOID() = 0; + + /** + * Timeout notification. + */ + virtual void timeout() = 0; + + /** + * Cancel response request (always to be called to complete/destroy). + */ + virtual void cancel() = 0; + + /** + * Report status to clients (e.g. disconnected). + * @param status to report. + */ + virtual void reportStatus(epics::pvData::Status* status) = 0; + + /** + * Get request requester. + * @return request requester. + */ + virtual epics::pvData::Requester* getRequester() = 0; + }; } } diff --git a/pvAccessApp/server/responseHandlers.cpp b/pvAccessApp/server/responseHandlers.cpp index f191c32..fe57284 100644 --- a/pvAccessApp/server/responseHandlers.cpp +++ b/pvAccessApp/server/responseHandlers.cpp @@ -24,23 +24,6 @@ using namespace epics::pvData; namespace epics { namespace pvAccess { - void AbstractResponseHandler::handleResponse(osiSockAddr* responseFrom, - Transport* transport, int8 version, int8 command, - int payloadSize, ByteBuffer* payloadBuffer) { - if(_debug) { - char ipAddrStr[48]; - ipAddrToDottedIP(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr)); - - ostringstream prologue; - prologue<<"Message [0x"<getArray(), - payloadBuffer->getPosition(), payloadSize); - } - } - void BadResponse::handleResponse(osiSockAddr* responseFrom, Transport* transport, int8 version, int8 command, int payloadSize, ByteBuffer* payloadBuffer) { @@ -57,15 +40,15 @@ namespace epics { } ServerResponseHandler::ServerResponseHandler(ServerContextImpl* context) : - _context(context) { + ResponseHandler(context) { BadResponse* badResponse = new BadResponse(context); _handlerTable = new ResponseHandler*[HANDLER_TABLE_LENGTH]; // TODO add real handlers, as they are developed - _handlerTable[0] = new NoopResponse(_context, "Beacon"); - _handlerTable[1] = new ConnectionValidationHandler(_context); - _handlerTable[2] = new EchoHandler(_context); + _handlerTable[0] = new NoopResponse(context, "Beacon"); + _handlerTable[1] = new ConnectionValidationHandler(context); + _handlerTable[2] = new EchoHandler(context); _handlerTable[3] = badResponse; _handlerTable[4] = badResponse; _handlerTable[5] = badResponse; diff --git a/pvAccessApp/server/responseHandlers.h b/pvAccessApp/server/responseHandlers.h index afbcdba..7aeab36 100644 --- a/pvAccessApp/server/responseHandlers.h +++ b/pvAccessApp/server/responseHandlers.h @@ -8,6 +8,7 @@ #ifndef RESPONSEHANDLERS_H_ #define RESPONSEHANDLERS_H_ +#include "serverContext.h" #include "remote.h" namespace epics { @@ -25,13 +26,11 @@ namespace epics { */ AbstractServerResponseHandler(ServerContextImpl* context, String description) : - AbstractResponseHandler(description), _context(context) { + AbstractResponseHandler(context, description) { } virtual ~AbstractServerResponseHandler() { } - protected: - ServerContextImpl* _context; }; /** @@ -77,11 +76,6 @@ namespace epics { */ ResponseHandler** _handlerTable; - /** - * Context instance. - */ - ServerContextImpl* _context; - }; /** diff --git a/pvAccessApp/server/serverContext.h b/pvAccessApp/server/serverContext.h index d535616..c01d52e 100644 --- a/pvAccessApp/server/serverContext.h +++ b/pvAccessApp/server/serverContext.h @@ -8,11 +8,12 @@ #ifndef SERVERCONTEXT_H_ #define SERVERCONTEXT_H_ +#include "remote.h" + namespace epics { namespace pvAccess { - - class ServerContextImpl { + class ServerContextImpl : public Context { }; diff --git a/pvAccessApp/utils/growingCircularBuffer.h b/pvAccessApp/utils/growingCircularBuffer.h index 6a993a1..63bb242 100644 --- a/pvAccessApp/utils/growingCircularBuffer.h +++ b/pvAccessApp/utils/growingCircularBuffer.h @@ -28,8 +28,8 @@ namespace epics { * Create a GrowingCircularBuffer with the given capacity. **/ GrowingCircularBuffer(size_t capacity = 16) : - _elements(new T[capacity]), _takePointer(0), _putPointer(0), _count(0), _size(capacity) - { + _elements(new T[capacity]), _takePointer(0), _putPointer(0), + _count(0), _size(capacity) { } ~GrowingCircularBuffer() { @@ -94,13 +94,9 @@ namespace epics { size_t length); }; - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * g++ requires template definition inside a header file. - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - template - void GrowingCircularBuffer::arraycopy(T* src, size_t srcPos, T* dest, - size_t destPos, size_t length) { + void GrowingCircularBuffer::arraycopy(T* src, size_t srcPos, + T* dest, size_t destPos, size_t length) { if(srcPos=0; i--) dest[destPos+i] = src[srcPos+i]; @@ -111,17 +107,16 @@ namespace epics { template bool GrowingCircularBuffer::insert(const T x) { - if (_count == _size) - { + if(_count==_size) { // we are full, grow by factor 2 - T* newElements = new T[_size * 2]; + T* newElements = new T[_size*2]; // invariant: _takePointer < _size - size_t split = _size - _takePointer; - if (split > 0) - arraycopy(_elements, _takePointer, newElements, 0, split); - if (_takePointer != 0) - arraycopy(_elements, 0, newElements, split, _putPointer); + size_t split = _size-_takePointer; + if(split>0) arraycopy(_elements, _takePointer, newElements, 0, + split); + if(_takePointer!=0) arraycopy(_elements, 0, newElements, split, + _putPointer); _takePointer = 0; _putPointer = _size; @@ -132,8 +127,8 @@ namespace epics { _count++; _elements[_putPointer] = x; - if (++_putPointer >= _size) _putPointer = 0; - return _count == 1; + if(++_putPointer>=_size) _putPointer = 0; + return _count==1; } template @@ -146,6 +141,141 @@ namespace epics { return old; } + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Template specialization for pointers. + * Implementation of circular FIFO unbouded buffer. + * Instance is not thread safe. + * @author Miha Vitorovic + */ + template + class GrowingCircularBuffer { + public: + + /** + * Create a GrowingCircularBuffer with the given capacity. + **/ + GrowingCircularBuffer(size_t capacity = 16) : + _elements(new T*[capacity]), _takePointer(0), _putPointer(0), + _count(0), _size(capacity) { + } + + ~GrowingCircularBuffer() { + delete[] _elements; + } + + /** + * Get number of elements in the buffer. + * @return number of elements in the buffer. + */ + inline size_t size() { + return _count; + } + + /** + * Get current buffer capacity. + * @return buffer current capacity. + */ + inline size_t capacity() { + return _size; + } + + /** + * Insert a new element in to the buffer. + * If buffer full the buffer is doubled. + * + * @param x element to insert. + * @return true if first element. + */ + bool insert(const T* x); + + /** + * Extract the oldest element from the buffer. + * @return the oldest element from the buffer. + */ + T* extract(); + + private: + /** + * Array (circular buffer) of elements. + */ + T** _elements; + + /** + * Take (read) pointer. + */ + size_t _takePointer; + + /** + * Put (write) pointer. + */ + size_t _putPointer; + + /** + * Number of elements in the buffer. + */ + size_t _count; + + size_t _size; + + void arraycopy(T** src, size_t srcPos, T** dest, size_t destPos, + size_t length); + }; + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * g++ requires template definition inside a header file. + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + template + void GrowingCircularBuffer::arraycopy(T** src, size_t srcPos, + T** dest, size_t destPos, size_t length) { + if(srcPos=0; i--) + dest[destPos+i] = src[srcPos+i]; + else + for(size_t i = 0; i + bool GrowingCircularBuffer::insert(const T* x) { + if(_count==_size) { + // we are full, grow by factor 2 + T** newElements = new T*[_size*2]; + + // invariant: _takePointer < _size + size_t split = _size-_takePointer; + if(split>0) arraycopy(_elements, _takePointer, newElements, 0, + split); + if(_takePointer!=0) arraycopy(_elements, 0, newElements, split, + _putPointer); + + _takePointer = 0; + _putPointer = _size; + _size *= 2; + delete[] _elements; + _elements = newElements; + } + _count++; + + _elements[_putPointer] = const_cast(x); + if(++_putPointer>=_size) _putPointer = 0; + return _count==1; + } + + template + T* GrowingCircularBuffer::extract() { + if(_count==0) return NULL; + + _count--; + T* old = _elements[_takePointer]; + if(++_takePointer>=_size) _takePointer = 0; + return old; + } + } } #endif /* GROWINGCIRCULARBUFFER_H_ */ diff --git a/pvAccessApp/utils/inetAddressUtil.cpp b/pvAccessApp/utils/inetAddressUtil.cpp index e9ab30f..18e1d18 100644 --- a/pvAccessApp/utils/inetAddressUtil.cpp +++ b/pvAccessApp/utils/inetAddressUtil.cpp @@ -32,14 +32,25 @@ using namespace epics::pvData; namespace epics { namespace pvAccess { + void addDefaultBroadcastAddress(InetAddrVector* v, in_port_t p) { + osiSockAddr* pNewNode = new osiSockAddr; + pNewNode->ia.sin_family = AF_INET; + pNewNode->ia.sin_addr.s_addr = htonl(INADDR_BROADCAST); + pNewNode->ia.sin_port = htons(p); + v->push_back(pNewNode); + } + /* port of osiSockDiscoverBroadcastAddresses() in * epics/base/src/libCom/osi/os/default/osdNetIntf.c */ - InetAddrVector* getBroadcastAddresses(SOCKET sock) { + InetAddrVector* getBroadcastAddresses(SOCKET sock, + in_port_t defaultPort) { static const unsigned nelem = 100; int status; struct ifconf ifconf; struct ifreq* pIfreqList; + struct ifreq* pifreq; + struct ifreq ifrBuff; osiSockAddr* pNewNode; InetAddrVector* retVector = new InetAddrVector(); @@ -54,68 +65,72 @@ namespace epics { if(!pIfreqList) { errlogSevPrintf(errlogMajor, "getBroadcastAddresses(): no memory to complete request"); + addDefaultBroadcastAddress(retVector, defaultPort); return retVector; } // get number of interfaces ifconf.ifc_len = nelem*sizeof(ifreq); ifconf.ifc_req = pIfreqList; - memset(ifconf.ifc_req,0,ifconf.ifc_len); + memset(ifconf.ifc_req, 0, ifconf.ifc_len); status = ioctl(sock, SIOCGIFCONF, &ifconf); if(status<0||ifconf.ifc_len==0) { - errlogSevPrintf( - errlogMinor, + errlogSevPrintf(errlogMinor, "getBroadcastAddresses(): unable to fetch network interface configuration"); delete[] pIfreqList; + addDefaultBroadcastAddress(retVector, defaultPort); return retVector; } - struct ifreq* p = pIfreqList; int maxNodes = ifconf.ifc_len/sizeof(ifreq); - for(int i = 0; iifr_name)) break; - //printf("[%i] plen %d name %s\n", i,p->ifr_addr.sa_len, p->ifr_name); - - - size_t n = p->ifr_addr.sa_len + sizeof(p->ifr_name); - if (n < sizeof(*p)) - p++; - else - p = (struct ifreq *)((char *)p + n); + //errlogPrintf("Found %d interfaces\n", maxNodes); + pifreq = pIfreqList; + + for(int i = 0; iifr_name)) break; + + if(i>0) { + size_t n = pifreq->ifr_addr.sa_len+sizeof(pifreq->ifr_name); + if(nifr_addr.sa_family!=AF_INET) continue; + if(pifreq->ifr_addr.sa_family!=AF_INET) continue; - struct ifreq ifrflags; - strncpy(ifrflags.ifr_name, p->ifr_name, - sizeof(ifrflags.ifr_name)); - status = ioctl(sock, SIOCGIFFLAGS, (char*)&ifrflags); + strncpy(ifrBuff.ifr_name, pifreq->ifr_name, + sizeof(ifrBuff.ifr_name)); + status = ioctl(sock, SIOCGIFFLAGS, &ifrBuff); if(status) { errlogSevPrintf( errlogMinor, "getBroadcastAddresses(): net intf flags fetch for \"%s\" failed", - p->ifr_name); + pifreq->ifr_name); continue; } /* * dont bother with interfaces that have been disabled */ - if(!(ifrflags.ifr_flags&IFF_UP)) continue; + if(!(ifrBuff.ifr_flags&IFF_UP)) continue; /* * dont use the loop back interface */ - if(ifrflags.ifr_flags&IFF_LOOPBACK) continue; + if(ifrBuff.ifr_flags&IFF_LOOPBACK) continue; pNewNode = new osiSockAddr; if(pNewNode==NULL) { errlogSevPrintf(errlogMajor, "getBroadcastAddresses(): no memory available for configuration"); delete[] pIfreqList; + if(retVector->size()==0) addDefaultBroadcastAddress( + retVector, defaultPort); return retVector; } @@ -129,46 +144,45 @@ namespace epics { * Otherwise CA will not query through the * interface. */ - if(ifrflags.ifr_flags&IFF_BROADCAST) { - struct ifreq ifrflags; - strncpy(ifrflags.ifr_name, p->ifr_name, - sizeof(ifrflags.ifr_name)); - status = ioctl(sock, SIOCGIFBRDADDR, (char*)&ifrflags); + if(ifrBuff.ifr_flags&IFF_BROADCAST) { + strncpy(ifrBuff.ifr_name, pifreq->ifr_name, + sizeof(ifrBuff.ifr_name)); + status = ioctl(sock, SIOCGIFBRDADDR, &ifrBuff); if(status) { errlogSevPrintf( errlogMinor, "getBroadcastAddresses(): net intf \"%s\": bcast addr fetch fail", - p->ifr_name); + pifreq->ifr_name); delete pNewNode; continue; } - pNewNode->sa = ifrflags.ifr_broadaddr; + pNewNode->sa = ifrBuff.ifr_broadaddr; } #ifdef IFF_POINTOPOINT - else if(ifrflags.ifr_flags&IFF_POINTOPOINT) { - struct ifreq ifrflags; - strncpy(ifrflags.ifr_name, p->ifr_name, - sizeof(ifrflags.ifr_name)); - status = ioctl(sock, SIOCGIFDSTADDR, (char*)&ifrflags); + else if(ifrBuff.ifr_flags&IFF_POINTOPOINT) { + strncpy(ifrBuff.ifr_name, pifreq->ifr_name, + sizeof(ifrBuff.ifr_name)); + status = ioctl(sock, SIOCGIFDSTADDR, &ifrBuff); if(status) { errlogSevPrintf( errlogMinor, "getBroadcastAddresses(): net intf \"%s\": pt to pt addr fetch fail", - p->ifr_name); + pifreq->ifr_name); delete pNewNode; continue; } - pNewNode->sa = ifrflags.ifr_dstaddr; + pNewNode->sa = ifrBuff.ifr_dstaddr; } #endif else { errlogSevPrintf( errlogMinor, "getBroadcastAddresses(): net intf \"%s\": not point to point or bcast?", - p->ifr_name); + pifreq->ifr_name); delete pNewNode; continue; } + pNewNode->ia.sin_port = htons(defaultPort); retVector->push_back(pNewNode); } @@ -185,16 +199,12 @@ namespace epics { buffer->putShort(0); // next 16-bits are 1 buffer->putShort(0xFFFF); - buffer->putInt(ntohl(address->ia.sin_addr.s_addr)); - - /* // following IPv4 address in big-endian (network) byte order in_addr_t ipv4Addr = ntohl(address->ia.sin_addr.s_addr); buffer->putByte((int8)((ipv4Addr>>24)&0xFF)); buffer->putByte((int8)((ipv4Addr>>16)&0xFF)); buffer->putByte((int8)((ipv4Addr>>8)&0xFF)); buffer->putByte((int8)(ipv4Addr&0xFF)); - */ } osiSockAddr* intToIPv4Address(int32 addr) { diff --git a/pvAccessApp/utils/inetAddressUtil.h b/pvAccessApp/utils/inetAddressUtil.h index ee7f381..e8ee082 100644 --- a/pvAccessApp/utils/inetAddressUtil.h +++ b/pvAccessApp/utils/inetAddressUtil.h @@ -33,8 +33,12 @@ namespace epics { /** * returns a vector containing all the IPv4 broadcast addresses * on this machine. IPv6 doesn't have a local broadcast address. - */ - InetAddrVector* getBroadcastAddresses(SOCKET sock); + * Conversion of the defaultPort to network byte order performed by + * the function. + * TODO: Windows implementation of the function. + */ + InetAddrVector* getBroadcastAddresses(SOCKET sock, + in_port_t defaultPort); /** * Encode IPv4 address as IPv6 address. diff --git a/testApp/remote/testBeaconEmitter.cpp b/testApp/remote/testBeaconEmitter.cpp index 0d3c904..c1a3026 100644 --- a/testApp/remote/testBeaconEmitter.cpp +++ b/testApp/remote/testBeaconEmitter.cpp @@ -18,6 +18,8 @@ using namespace epics::pvData; class DummyResponseHandler : public ResponseHandler { public: + DummyResponseHandler(Context* ctx) : ResponseHandler(ctx) {} + virtual void handleResponse(osiSockAddr* responseFrom, Transport* transport, int8 version, int8 command, int payloadSize, ByteBuffer* payloadBuffer) @@ -27,9 +29,33 @@ public: }; +class ContextImpl : public Context { +public: + ContextImpl() : + _tr(new TransportRegistry()), _timer(new Timer("server thread", + lowPriority)), _conf(new SystemConfigurationImpl()) { + } + virtual ~ContextImpl() { + delete _tr; + delete _timer; + } + virtual Timer* getTimer() { return _timer; } + virtual TransportRegistry* getTransportRegistry() { return _tr; } + virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; } + virtual Transport* getSearchTransport() { return 0; } + virtual Configuration* getConfiguration() { return _conf; } + +private: + TransportRegistry* _tr; + Timer* _timer; + Configuration* _conf; +}; + + void testBeaconEmitter() { - DummyResponseHandler drh; + ContextImpl ctx; + DummyResponseHandler drh(&ctx); /* SOCKET mysocket; if ((mysocket = socket (AF_INET, SOCK_DGRAM, 0)) == -1) { diff --git a/testApp/remote/testBeaconHandler.cpp b/testApp/remote/testBeaconHandler.cpp index 0ac231c..6690ab4 100644 --- a/testApp/remote/testBeaconHandler.cpp +++ b/testApp/remote/testBeaconHandler.cpp @@ -37,7 +37,7 @@ void decodeFromIPv6Address(ByteBuffer* buffer, osiSockAddr* address) class BeaconResponseHandler : public ResponseHandler { public: - BeaconResponseHandler() + BeaconResponseHandler(Context* ctx) : ResponseHandler(ctx) { _pvDataCreate = getPVDataCreate(); } @@ -103,9 +103,33 @@ private: }; +class ContextImpl : public Context { +public: + ContextImpl() : + _tr(new TransportRegistry()), _timer(new Timer("server thread", + lowPriority)), _conf(new SystemConfigurationImpl()) { + } + virtual ~ContextImpl() { + delete _tr; + delete _timer; + } + virtual Timer* getTimer() { return _timer; } + virtual TransportRegistry* getTransportRegistry() { return _tr; } + virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; } + virtual Transport* getSearchTransport() { return 0; } + virtual Configuration* getConfiguration() { return _conf; } + +private: + TransportRegistry* _tr; + Timer* _timer; + Configuration* _conf; +}; + + void testBeaconHandler() { - BeaconResponseHandler brh; + ContextImpl ctx; + BeaconResponseHandler brh(&ctx); BlockingUDPConnector connector(false, NULL, true); osiSockAddr bindAddr; diff --git a/testApp/remote/testBlockingTCPClnt.cpp b/testApp/remote/testBlockingTCPClnt.cpp index a3bde97..d845c1b 100644 --- a/testApp/remote/testBlockingTCPClnt.cpp +++ b/testApp/remote/testBlockingTCPClnt.cpp @@ -29,28 +29,30 @@ using std::sscanf; class ContextImpl : public Context { public: ContextImpl() : - _tr(new TransportRegistry()), _timer(new Timer("client thread", - lowPriority)) { + _tr(new TransportRegistry()), _timer(new Timer("server thread", + lowPriority)), _conf(new SystemConfigurationImpl()) { } virtual ~ContextImpl() { delete _tr; delete _timer; } - virtual Timer* getTimer() { - return _timer; - } - virtual TransportRegistry* getTransportRegistry() { - return _tr; - } - virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; } - virtual Transport* getSearchTransport() { return 0; } + virtual Timer* getTimer() { return _timer; } + virtual TransportRegistry* getTransportRegistry() { return _tr; } + virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; } + virtual Transport* getSearchTransport() { return 0; } + virtual Configuration* getConfiguration() { return _conf; } + private: TransportRegistry* _tr; Timer* _timer; + Configuration* _conf; }; class DummyResponseHandler : public ResponseHandler { public: + DummyResponseHandler(Context* ctx) : ResponseHandler(ctx) { + } + virtual void handleResponse(osiSockAddr* responseFrom, Transport* transport, int8 version, int8 command, int payloadSize, ByteBuffer* payloadBuffer) { @@ -110,7 +112,7 @@ void testBlockingTCPSender() { DummyTransportClient dtc; DummyTransportSender dts; - DummyResponseHandler drh; + DummyResponseHandler drh(&ctx); osiSockAddr srvAddr; diff --git a/testApp/remote/testBlockingTCPSrv.cpp b/testApp/remote/testBlockingTCPSrv.cpp index 6ab54f6..c7ced35 100644 --- a/testApp/remote/testBlockingTCPSrv.cpp +++ b/testApp/remote/testBlockingTCPSrv.cpp @@ -8,6 +8,7 @@ #include "blockingTCP.h" #include "remote.h" #include "logger.h" +#include "configuration.h" #include @@ -21,7 +22,8 @@ class ContextImpl : public Context { public: ContextImpl() : _tr(new TransportRegistry()), - _timer(new Timer("server thread", lowPriority)) {} + _timer(new Timer("server thread", lowPriority)), + _conf(new SystemConfigurationImpl()) {} virtual ~ContextImpl() { delete _tr; delete _timer; @@ -30,10 +32,12 @@ public: virtual TransportRegistry* getTransportRegistry() { return _tr; } virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; } virtual Transport* getSearchTransport() { return 0; } - + virtual Configuration* getConfiguration() { return _conf; } + private: TransportRegistry* _tr; Timer* _timer; + Configuration* _conf; }; void testServerConnections() { @@ -43,7 +47,7 @@ void testServerConnections() { 1024); cout<<"Press any key to stop the server..."; - char c = cin.peek(); + cin.peek(); delete srv; } diff --git a/testApp/remote/testBlockingUDPClnt.cpp b/testApp/remote/testBlockingUDPClnt.cpp index 06443aa..3e124d9 100644 --- a/testApp/remote/testBlockingUDPClnt.cpp +++ b/testApp/remote/testBlockingUDPClnt.cpp @@ -26,8 +26,44 @@ using std::sscanf; static osiSockAddr sendTo; +class ContextImpl : public Context { +public: + ContextImpl() : + _tr(new TransportRegistry()), _timer(new Timer("server thread", + lowPriority)), _conf(new SystemConfigurationImpl()) { + } + virtual ~ContextImpl() { + delete _tr; + delete _timer; + } + virtual Timer* getTimer() { + return _timer; + } + virtual TransportRegistry* getTransportRegistry() { + return _tr; + } + virtual Channel* getChannel(epics::pvAccess::pvAccessID) { + return 0; + } + virtual Transport* getSearchTransport() { + return 0; + } + virtual Configuration* getConfiguration() { + return _conf; + } + +private: + TransportRegistry* _tr; + Timer* _timer; + Configuration* _conf; +}; + class DummyResponseHandler : public ResponseHandler { public: + DummyResponseHandler(Context* ctx) : + ResponseHandler(ctx) { + } + virtual void handleResponse(osiSockAddr* responseFrom, Transport* transport, int8 version, int8 command, int payloadSize, ByteBuffer* payloadBuffer) { @@ -69,9 +105,10 @@ private: void testBlockingUDPSender() { BlockingUDPConnector connector(false, NULL, true); + ContextImpl ctx; DummyTransportSender dts; - DummyResponseHandler drh; + DummyResponseHandler drh(&ctx); osiSockAddr bindAddr; diff --git a/testApp/remote/testBlockingUDPSrv.cpp b/testApp/remote/testBlockingUDPSrv.cpp index 6b713bb..16612ac 100644 --- a/testApp/remote/testBlockingUDPSrv.cpp +++ b/testApp/remote/testBlockingUDPSrv.cpp @@ -21,10 +21,42 @@ using std::endl; using std::hex; using std::dec; +class ContextImpl : public Context { +public: + ContextImpl() : + _tr(new TransportRegistry()), _timer(new Timer("server thread", + lowPriority)), _conf(new SystemConfigurationImpl()) { + } + virtual ~ContextImpl() { + delete _tr; + delete _timer; + } + virtual Timer* getTimer() { + return _timer; + } + virtual TransportRegistry* getTransportRegistry() { + return _tr; + } + virtual Channel* getChannel(epics::pvAccess::pvAccessID) { + return 0; + } + virtual Transport* getSearchTransport() { + return 0; + } + virtual Configuration* getConfiguration() { + return _conf; + } + +private: + TransportRegistry* _tr; + Timer* _timer; + Configuration* _conf; +}; + class DummyResponseHandler : public ResponseHandler { public: - DummyResponseHandler() : - packets(0) { + DummyResponseHandler(Context* context) : + ResponseHandler(context), packets(0) { } int getPackets() { @@ -71,8 +103,9 @@ void DummyResponseHandler::handleResponse(osiSockAddr* responseFrom, void testBlockingUDPConnector() { BlockingUDPConnector connector(false, NULL, true); + ContextImpl ctx; - DummyResponseHandler drh; + DummyResponseHandler drh(&ctx); osiSockAddr bindAddr; diff --git a/testApp/remote/testRemoteClientImpl.cpp b/testApp/remote/testRemoteClientImpl.cpp index de251df..5f8c362 100644 --- a/testApp/remote/testRemoteClientImpl.cpp +++ b/testApp/remote/testRemoteClientImpl.cpp @@ -21,6 +21,7 @@ #include #include #include +#include using namespace epics::pvData; using namespace epics::pvAccess; @@ -35,7 +36,7 @@ class ChannelImplProcess : public ChannelProcess ChannelProcessRequester* m_channelProcessRequester; PVStructure* m_pvStructure; PVScalar* m_valueField; - + private: ~ChannelImplProcess() { @@ -54,29 +55,29 @@ class ChannelImplProcess : public ChannelProcess Status* noValueFieldStatus = getStatusCreate()->createStatus(STATUSTYPE_ERROR, "no 'value' field"); m_channelProcessRequester->channelProcessConnect(noValueFieldStatus, this); delete noValueFieldStatus; - + // NOTE client must destroy this instance... // do not access any fields and return ASAP return; } - + if (field->getField()->getType() != scalar) { Status* notAScalarStatus = getStatusCreate()->createStatus(STATUSTYPE_ERROR, "'value' field not scalar type"); m_channelProcessRequester->channelProcessConnect(notAScalarStatus, this); delete notAScalarStatus; - + // NOTE client must destroy this instance…. // do not access any fields and return ASAP return; } - + m_valueField = static_cast(field); - - // TODO pvRequest + + // TODO pvRequest m_channelProcessRequester->channelProcessConnect(getStatusCreate()->getStatusOK(), this); } - + virtual void process(bool lastRequest) { switch (m_valueField->getScalar()->getScalarType()) @@ -148,19 +149,19 @@ class ChannelImplProcess : public ChannelProcess default: // noop break; - - } + + } m_channelProcessRequester->processDone(getStatusCreate()->getStatusOK()); - + if (lastRequest) destroy(); } - + virtual void destroy() { delete this; } - + }; @@ -177,7 +178,7 @@ class ChannelImplGet : public ChannelGet PVStructure* m_pvStructure; BitSet* m_bitSet; volatile bool m_first; - + private: ~ChannelImplGet() { @@ -191,10 +192,10 @@ class ChannelImplGet : public ChannelGet { PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockChannelGet); - // TODO pvRequest + // TODO pvRequest m_channelGetRequester->channelGetConnect(getStatusCreate()->getStatusOK(), this, m_pvStructure, m_bitSet); } - + virtual void get(bool lastRequest) { m_channelGetRequester->getDone(getStatusCreate()->getStatusOK()); @@ -203,17 +204,17 @@ class ChannelImplGet : public ChannelGet m_first = false; m_bitSet->set(0); // TODO } - + if (lastRequest) destroy(); } - + virtual void destroy() { delete m_bitSet; delete this; } - + }; @@ -232,7 +233,7 @@ class ChannelImplPut : public ChannelPut PVStructure* m_pvStructure; BitSet* m_bitSet; volatile bool m_first; - + private: ~ChannelImplPut() { @@ -246,17 +247,17 @@ class ChannelImplPut : public ChannelPut { PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockChannelPut); - // TODO pvRequest + // TODO pvRequest m_channelPutRequester->channelPutConnect(getStatusCreate()->getStatusOK(), this, m_pvStructure, m_bitSet); } - + virtual void put(bool lastRequest) { m_channelPutRequester->putDone(getStatusCreate()->getStatusOK()); if (lastRequest) destroy(); } - + virtual void get() { m_channelPutRequester->getDone(getStatusCreate()->getStatusOK()); @@ -267,7 +268,7 @@ class ChannelImplPut : public ChannelPut delete m_bitSet; delete this; } - + }; @@ -288,7 +289,7 @@ class MockMonitor : public Monitor, public MonitorElement volatile bool m_first; Mutex* m_lock; volatile int m_count; - + private: ~MockMonitor() { @@ -307,16 +308,16 @@ class MockMonitor : public Monitor, public MonitorElement PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockMonitor); m_changedBitSet->set(0); - - // TODO pvRequest + + // TODO pvRequest m_monitorRequester->monitorConnect(getStatusCreate()->getStatusOK(), this, const_cast(m_pvStructure->getStructure())); } - + virtual Status* start() { // fist monitor m_monitorRequester->monitorEvent(this); - + // client needs to delete status, so passing shared OK instance is not right thing to do return getStatusCreate()->createStatus(STATUSTYPE_OK, "Monitor started."); } @@ -347,24 +348,24 @@ class MockMonitor : public Monitor, public MonitorElement if (m_count) m_count--; } - + virtual void destroy() { delete stop(); - + delete m_lock; delete m_overrunBitSet; delete m_changedBitSet; delete this; } - + // ============ MonitorElement ============ - + virtual PVStructure* getPVStructure() { return m_pvStructure; } - + virtual BitSet* getChangedBitSet() { return m_changedBitSet; @@ -374,8 +375,8 @@ class MockMonitor : public Monitor, public MonitorElement { return m_overrunBitSet; } - - + + }; @@ -395,7 +396,8 @@ typedef std::map IOIDResponseRequestMap; /** * @param context */ - DebugResponse() + DebugResponse(Context* ctx) : + ResponseHandler(ctx) { } @@ -409,7 +411,6 @@ typedef std::map IOIDResponseRequestMap; char ipAddrStr[48]; ipAddrToDottedIP(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr)); - ostringstream prologue; prologue<<"Message [0x"< IOIDResponseRequestMap; hexDump(prologue.str(), "received", (const int8*)payloadBuffer->getArray(), payloadBuffer->getPosition(), payloadSize); - + } }; @@ -426,7 +427,7 @@ typedef std::map IOIDResponseRequestMap; private: ClientContextImpl* m_context; public: - SearchResponseHandler(ClientContextImpl* context) : m_context(context) + SearchResponseHandler(ClientContextImpl* context) : ResponseHandler(context), m_context(context) { } @@ -492,30 +493,30 @@ typedef std::map IOIDResponseRequestMap; */ class ClientResponseHandler : public ResponseHandler, private epics::pvData::NoDefaultMethods { private: - + /** * Table of response handlers for each command ID. */ ResponseHandler** m_handlerTable; - /** - * Context instance. + /* + * Context instance is part of the response handler now */ - ClientContextImpl* m_context; - + //ClientContextImpl* m_context; + public: - + ~ClientResponseHandler() { delete[] m_handlerTable; } - + /** * @param context */ - ClientResponseHandler(ClientContextImpl* context) : m_context(context) { - static ResponseHandler* badResponse = new DebugResponse(); + ClientResponseHandler(ClientContextImpl* context) : ResponseHandler((Context*)context) { + static ResponseHandler* badResponse = new DebugResponse((Context*)context); static ResponseHandler* dataResponse = 0; //new DataResponseHandler(context); - + #define HANDLER_COUNT 28 m_handlerTable = new ResponseHandler*[HANDLER_COUNT]; m_handlerTable[ 0] = badResponse; // TODO new BeaconHandler(context), /* 0 */ @@ -564,7 +565,7 @@ class ClientResponseHandler : public ResponseHandler, private epics::pvData::NoD hexDump(buf, (const int8*)(payloadBuffer->getArray()), payloadBuffer->getPosition(), payloadSize); return; } - + // delegate m_handlerTable[c]->handleResponse(responseFrom, transport, version, command, payloadSize, payloadBuffer); } @@ -587,7 +588,7 @@ class ClientResponseHandler : public ResponseHandler, private epics::pvData::NoD }; - + @@ -617,7 +618,7 @@ enum ContextState { */ CONTEXT_DESTROYED }; - + class TestClientContextImpl : public ClientContextImpl { @@ -633,7 +634,7 @@ class TestClientContextImpl : public ClientContextImpl */ class TestChannelImpl : public ChannelImpl { private: - + /** * Context. */ @@ -643,12 +644,12 @@ class TestChannelImpl : public ChannelImpl { * Client channel ID. */ pvAccessID m_channelID; - + /** * Channel name. */ String m_name; - + /** * Channel requester. */ @@ -658,48 +659,48 @@ class TestChannelImpl : public ChannelImpl { * Process priority. */ short m_priority; - + /** * List of fixed addresses, if name resolution will be used. */ InetAddrVector* m_addresses; - + /** * Connection status. */ ConnectionState m_connectionState; - + /** - * List of all channel's pending requests (keys are subscription IDs). + * List of all channel's pending requests (keys are subscription IDs). */ IOIDResponseRequestMap m_responseRequests; - + /** - * Allow reconnection flag. + * Allow reconnection flag. */ bool m_allowCreation; - + /** * Reference counting. - * NOTE: synced on m_channelMutex. + * NOTE: synced on m_channelMutex. */ int m_references; - + /* ****************** */ - /* CA protocol fields */ + /* CA protocol fields */ /* ****************** */ - + /** * Server transport. */ Transport* m_transport; - + /** * Server channel ID. */ pvAccessID m_serverChannelID; - + /** * Context sync. mutex. */ @@ -707,20 +708,20 @@ class TestChannelImpl : public ChannelImpl { /** * Flag indicting what message to send. - */ + */ bool m_issueCreateMessage; - + // TODO mock PVStructure* m_pvStructure; - + private: ~TestChannelImpl() { PVDATA_REFCOUNT_MONITOR_DESTRUCT(channel); } - + public: - + /** * Constructor. * @param context @@ -749,15 +750,14 @@ class TestChannelImpl : public ChannelImpl { m_issueCreateMessage(true) { PVDATA_REFCOUNT_MONITOR_CONSTRUCT(channel); - + // register before issuing search request m_context->registerChannel(this); - + // connect connect(); - } - + virtual void destroy() { if (m_addresses) delete m_addresses; @@ -769,13 +769,13 @@ class TestChannelImpl : public ChannelImpl { { return getChannelName(); }; - - virtual void message(String message,MessageType messageType) + + virtual void message(String message,MessageType messageType) { - std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; } - virtual ChannelProvider* getProvider() + virtual ChannelProvider* getProvider() { return m_context->getProvider(); } @@ -852,14 +852,14 @@ class TestChannelImpl : public ChannelImpl { throw std::runtime_error("Channel destroyed."); else if (m_connectionState == CONNECTED) disconnect(false, true); - } - + } + /** * Create a channel, i.e. submit create channel request to the server. * This method is called after search is complete. * @param transport */ - void createChannel(Transport* transport) + void createChannel(Transport* transport) { Lock guard(&m_channelMutex); @@ -867,12 +867,12 @@ class TestChannelImpl : public ChannelImpl { if (!m_allowCreation) return; m_allowCreation = false; - + // check existing transport if (m_transport && m_transport != transport) { disconnectPendingIO(false); - + ReferenceCountingTransport* rct = dynamic_cast(m_transport); if (rct) rct->release(this); } @@ -882,11 +882,11 @@ class TestChannelImpl : public ChannelImpl { // this happens when server is slower (processing search requests) than client generating it return; } - + m_transport = transport; m_transport->enqueueSendRequest(this); } - + virtual void cancel() { // noop } @@ -912,7 +912,7 @@ class TestChannelImpl : public ChannelImpl { * sid might not be valid, this depends on protocol revision. * @param sid */ - void connectionCompleted(pvAccessID sid/*, rights*/) + void connectionCompleted(pvAccessID sid/*, rights*/) { Lock guard(&m_channelMutex); @@ -929,16 +929,16 @@ class TestChannelImpl : public ChannelImpl { // user might create monitors in listeners, so this has to be done before this can happen // however, it would not be nice if events would come before connection event is fired - // but this cannot happen since transport (TCP) is serving in this thread + // but this cannot happen since transport (TCP) is serving in this thread resubscribeSubscriptions(); setConnectionState(CONNECTED); allOK = true; } catch (...) { // noop - // TODO at least log something?? + // TODO at least log something?? } - + if (!allOK) { // end connection request @@ -953,10 +953,10 @@ class TestChannelImpl : public ChannelImpl { Lock guard(&m_channelMutex); if (m_connectionState == DESTROYED) throw std::runtime_error("Channel already destroyed."); - + // do destruction via context m_context->destroyChannel(this, force); - + } /** @@ -983,7 +983,7 @@ class TestChannelImpl : public ChannelImpl { m_references--; if (m_references > 0 && !force) return; - + // stop searching... m_context->getChannelSearchManager()->unregisterChannel(this); cancel(); @@ -1003,7 +1003,7 @@ class TestChannelImpl : public ChannelImpl { } setConnectionState(DESTROYED); - + // unregister m_context->unregisterChannel(this); } @@ -1015,10 +1015,10 @@ class TestChannelImpl : public ChannelImpl { */ void disconnect(bool initiateSearch, bool remoteDestroy) { Lock guard(&m_channelMutex); - + if (m_connectionState != CONNECTED && !m_transport) return; - + if (!initiateSearch) { // stop searching... m_context->getChannelSearchManager()->unregisterChannel(this); @@ -1035,12 +1035,12 @@ class TestChannelImpl : public ChannelImpl { m_issueCreateMessage = false; m_transport->enqueueSendRequest(this); } - + ReferenceCountingTransport* rct = dynamic_cast(m_transport); if (rct) rct->release(this); m_transport = 0; } - + if (initiateSearch) this->initiateSearch(); @@ -1054,7 +1054,7 @@ class TestChannelImpl : public ChannelImpl { Lock guard(&m_channelMutex); m_allowCreation = true; - + if (!m_addresses) m_context->getChannelSearchManager()->registerChannel(this); /* TODO @@ -1079,7 +1079,7 @@ class TestChannelImpl : public ChannelImpl { return; } } - + transport = m_context->getTransport(this, serverAddress, minorRevision, m_priority); if (!transport) { @@ -1104,7 +1104,7 @@ class TestChannelImpl : public ChannelImpl { if (m_connectionState == DISCONNECTED) { updateSubscriptions(); - + // reconnect using existing IDs, data connectionCompleted(m_serverChannelID/*, accessRights*/); } @@ -1117,7 +1117,7 @@ class TestChannelImpl : public ChannelImpl { // NOTE: 2 types of disconnected state - distinguish them setConnectionState(DISCONNECTED); - // ... CA notifies also w/ no access rights callback, although access right are not changed + // ... CA notifies also w/ no access rights callback, although access right are not changed } } @@ -1131,7 +1131,7 @@ class TestChannelImpl : public ChannelImpl { if (m_connectionState != connectionState) { m_connectionState = connectionState; - + //bool connectionStatusToReport = (connectionState == CONNECTED); //if (connectionStatusToReport != lastReportedConnectionState) { @@ -1146,16 +1146,16 @@ class TestChannelImpl : public ChannelImpl { // noop } - + virtual void send(ByteBuffer* buffer, TransportSendControl* control) { m_channelMutex.lock(); bool issueCreateMessage = m_issueCreateMessage; m_channelMutex.unlock(); - + if (issueCreateMessage) { control->startMessage((int8)7, 2+4); - + // count buffer->putShort((int16)1); // array of CIDs and names @@ -1194,9 +1194,9 @@ class TestChannelImpl : public ChannelImpl { { // TODO } - + /** - * Resubscribe subscriptions. + * Resubscribe subscriptions. */ // TODO to be called from non-transport thread !!!!!! void resubscribeSubscriptions() @@ -1205,7 +1205,7 @@ class TestChannelImpl : public ChannelImpl { } /** - * Update subscriptions. + * Update subscriptions. */ // TODO to be called from non-transport thread !!!!!! void updateSubscriptions() @@ -1246,7 +1246,7 @@ class TestChannelImpl : public ChannelImpl { // TODO return 0; } - + virtual ChannelRPC* createChannelRPC(ChannelRPCRequester *channelRPCRequester, epics::pvData::PVStructure *pvRequest) { @@ -1268,20 +1268,20 @@ class TestChannelImpl : public ChannelImpl { // TODO return 0; } - - - + + + virtual void printInfo() { String info; printInfo(&info); std::cout << info.c_str() << std::endl; } - + virtual void printInfo(epics::pvData::StringBuilder out) { //Lock lock(&m_channelMutex); //std::ostringstream ostr; //static String emptyString; - + out->append( "CHANNEL : "); out->append(m_name); out->append("\nSTATE : "); out->append(ConnectionStateNames[m_connectionState]); if (m_connectionState == CONNECTED) @@ -1292,72 +1292,72 @@ class TestChannelImpl : public ChannelImpl { out->append("\n"); } }; - + class ChannelProviderImpl; - + class ChannelImplFind : public ChannelFind { public: ChannelImplFind(ChannelProvider* provider) : m_provider(provider) { } - + virtual void destroy() { // one instance for all, do not delete at all } - + virtual ChannelProvider* getChannelProvider() { return m_provider; }; - + virtual void cancelChannelFind() { throw std::runtime_error("not supported"); } - + private: - + // only to be destroyed by it friend class ChannelProviderImpl; virtual ~ChannelImplFind() {} - - ChannelProvider* m_provider; + + ChannelProvider* m_provider; }; - + class ChannelProviderImpl : public ChannelProvider { public: - + ChannelProviderImpl(ClientContextImpl* context) : m_context(context) { } - + virtual epics::pvData::String getProviderName() { return "ChannelProviderImpl"; } - + virtual void destroy() { delete this; } - + virtual ChannelFind* channelFind( epics::pvData::String channelName, ChannelFindRequester *channelFindRequester) { m_context->checkChannelName(channelName); - + if (!channelFindRequester) throw std::runtime_error("null requester"); - + std::auto_ptr errorStatus(getStatusCreate()->createStatus(STATUSTYPE_ERROR, "not implemented", 0)); channelFindRequester->channelFindResult(errorStatus.get(), 0, false); return 0; } - + virtual Channel* createChannel( epics::pvData::String channelName, ChannelRequester *channelRequester, @@ -1365,7 +1365,7 @@ class TestChannelImpl : public ChannelImpl { { return createChannel(channelName, channelRequester, priority, emptyString); } - + virtual Channel* createChannel( epics::pvData::String channelName, ChannelRequester *channelRequester, @@ -1377,19 +1377,18 @@ class TestChannelImpl : public ChannelImpl { if (channel) channelRequester->channelCreated(getStatusCreate()->getStatusOK(), channel); return channel; - + // NOTE it's up to internal code to respond w/ error to requester and return 0 in case of errors } - + private: ~ChannelProviderImpl() {}; - + /* TODO static*/ String emptyString; ClientContextImpl* m_context; }; public: - TestClientContextImpl() : m_addressList(""), m_autoAddressList(true), m_connectionTimeout(30.0f), m_beaconPeriod(15.0f), m_broadcastPort(CA_BROADCAST_PORT), m_receiveBufferSize(MAX_TCP_RECV), m_timer(0), @@ -1397,11 +1396,15 @@ class TestChannelImpl : public ChannelImpl { m_namedLocker(0), m_lastCID(0), m_lastIOID(0), m_channelSearchManager(0), m_version(new Version("CA Client", "cpp", 0, 0, 0, 1)), m_provider(new ChannelProviderImpl(this)), - m_contextState(CONTEXT_NOT_INITIALIZED) + m_contextState(CONTEXT_NOT_INITIALIZED), m_configuration(new SystemConfigurationImpl()) { loadConfiguration(); } - + + virtual Configuration* getConfiguration() { + return m_configuration; + } + virtual Version* getVersion() { return m_version; } @@ -1431,28 +1434,28 @@ class TestChannelImpl : public ChannelImpl { virtual void initialize() { Lock lock(&m_contextMutex); - + if (m_contextState == CONTEXT_DESTROYED) throw std::runtime_error("Context destroyed."); else if (m_contextState == CONTEXT_INITIALIZED) throw std::runtime_error("Context already initialized."); - + internalInitialize(); m_contextState = CONTEXT_INITIALIZED; } - + virtual void printInfo() { String info; printInfo(&info); std::cout << info.c_str() << std::endl; } - + virtual void printInfo(epics::pvData::StringBuilder out) { Lock lock(&m_contextMutex); std::ostringstream ostr; static String emptyString; - + out->append( "CLASS : ::epics::pvAccess::ClientContextImpl"); out->append("\nVERSION : "); out->append(m_version->getVersionString()); out->append("\nADDR_LIST : "); ostr << m_addressList; out->append(ostr.str()); ostr.str(emptyString); @@ -1478,7 +1481,7 @@ class TestChannelImpl : public ChannelImpl { } out->append("\n"); } - + virtual void destroy() { m_contextMutex.lock(); @@ -1488,21 +1491,21 @@ class TestChannelImpl : public ChannelImpl { m_contextMutex.unlock(); throw std::runtime_error("Context already destroyed."); } - - // go into destroyed state ASAP + + // go into destroyed state ASAP m_contextState = CONTEXT_DESTROYED; internalDestroy(); } - + virtual void dispose() { destroy(); - } - + } + private: ~TestClientContextImpl() {}; - + void loadConfiguration() { // TODO /* @@ -1516,19 +1519,19 @@ class TestChannelImpl : public ChannelImpl { } void internalInitialize() { - + m_timer = new Timer("pvAccess-client timer", lowPriority); m_connector = new BlockingTCPConnector(this, m_receiveBufferSize, m_beaconPeriod); m_transportRegistry = new TransportRegistry(); m_namedLocker = new NamedLockPattern(); - + // setup UDP transport initializeUDPTransport(); // setup search manager m_channelSearchManager = new ChannelSearchManager(this); } - + /** * Initialized UDP transport (broadcast socket and repeater connection). */ @@ -1541,13 +1544,12 @@ class TestChannelImpl : public ChannelImpl { listenLocalAddress.ia.sin_family = AF_INET; listenLocalAddress.ia.sin_port = htons(m_broadcastPort); listenLocalAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY); - + // where to send address SOCKET socket = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0); - InetAddrVector* broadcastAddresses = getBroadcastAddresses(socket); + InetAddrVector* broadcastAddresses = getBroadcastAddresses(socket, m_broadcastPort); cout<<"Broadcast addresses: "<size()<size(); i++) { - broadcastAddresses->at(i)->ia.sin_port = htons(m_broadcastPort); 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, @@ -1582,7 +1584,7 @@ class TestChannelImpl : public ChannelImpl { InetAddrVector* appendList = 0; if (m_autoAddressList) appendList = m_broadcastTransport->getSendAddresses(); - + InetAddrVector* list = getSocketAddressList(m_addressList, m_broadcastPort, appendList); // TODO delete !!!! if (list && list->size()) { @@ -1600,40 +1602,41 @@ class TestChannelImpl : public ChannelImpl { // TODO } } - + void internalDestroy() { - + // stop searching if (m_channelSearchManager) delete m_channelSearchManager; //->destroy(); - + // stop timer - if (m_timer) + if (m_timer) delete m_timer; // // cleanup // - + // this will also close all CA transports destroyAllChannels(); - + // TODO destroy !!! if (m_broadcastTransport) delete m_broadcastTransport; //->destroy(true); if (m_searchTransport) delete m_searchTransport; //->destroy(true); - + if (m_namedLocker) delete m_namedLocker; if (m_transportRegistry) delete m_transportRegistry; if (m_connector) delete m_connector; + if (m_configuration) delete m_configuration; m_provider->destroy(); delete m_version; m_contextMutex.unlock(); delete this; } - + void destroyAllChannels() { // TODO } @@ -1688,18 +1691,18 @@ class TestChannelImpl : public ChannelImpl { ChannelImpl* getChannel(pvAccessID channelID) { Lock guard(&m_cidMapMutex); - CIDChannelMap::iterator it = m_channelsByCID.find(channelID); + CIDChannelMap::iterator it = m_channelsByCID.find(channelID); return (it == m_channelsByCID.end() ? 0 : it->second); } /** * Generate Client channel ID (CID). - * @return Client channel ID (CID). + * @return Client channel ID (CID). */ pvAccessID generateCID() { Lock guard(&m_cidMapMutex); - + // search first free (theoretically possible loop of death) while (m_channelsByCID.find(++m_lastCID) != m_channelsByCID.end()); // reserve CID @@ -1716,7 +1719,7 @@ class TestChannelImpl : public ChannelImpl { m_channelsByCID.erase(cid); } - + /** * Get, or create if necessary, transport of given server address. * @param serverAddress required transport address @@ -1736,7 +1739,7 @@ class TestChannelImpl : public ChannelImpl { return 0; } } - + /** * Internal create channel. */ @@ -1747,16 +1750,16 @@ class TestChannelImpl : public ChannelImpl { checkState(); checkChannelName(name); - + if (requester == 0) throw std::runtime_error("null requester"); - + if (priority < ChannelProvider::PRIORITY_MIN || priority > ChannelProvider::PRIORITY_MAX) throw std::range_error("priority out of bounds"); bool lockAcquired = true; // TODO namedLocker->acquireSynchronizationObject(name, LOCK_TIMEOUT); if (lockAcquired) - { + { try { pvAccessID cid = generateCID(); @@ -1766,10 +1769,10 @@ class TestChannelImpl : public ChannelImpl { // TODO return 0; } - // TODO namedLocker.releaseSynchronizationObject(name); + // TODO namedLocker.releaseSynchronizationObject(name); } else - { + { // TODO is this OK? throw std::runtime_error("Failed to obtain synchronization lock for '" + name + "', possible deadlock."); } @@ -1783,23 +1786,23 @@ class TestChannelImpl : public ChannelImpl { * @throws IllegalStateException */ void destroyChannel(ChannelImpl* channel, bool force) { - + String name = channel->getChannelName(); bool lockAcquired = true; //namedLocker->acquireSynchronizationObject(name, LOCK_TIMEOUT); if (lockAcquired) - { + { try - { + { channel->destroyChannel(force); } catch(...) { // TODO } - // TODO namedLocker->releaseSynchronizationObject(channel.getChannelName()); + // TODO namedLocker->releaseSynchronizationObject(channel.getChannelName()); } else - { - // TODO is this OK? + { + // TODO is this OK? throw std::runtime_error("Failed to obtain synchronization lock for '" + name + "', possible deadlock."); } } @@ -1811,15 +1814,15 @@ class TestChannelImpl : public ChannelImpl { ChannelSearchManager* getChannelSearchManager() { return m_channelSearchManager; } - + /** * A space-separated list of broadcast address for process variable name resolution. * Each address must be of the form: ip.number:port or host.name:port */ String m_addressList; - + /** - * Define whether or not the network interfaces should be discovered at runtime. + * Define whether or not the network interfaces should be discovered at runtime. */ bool m_autoAddressList; @@ -1830,22 +1833,22 @@ class TestChannelImpl : public ChannelImpl { * the server is no longer present on the network and disconnect. */ float m_connectionTimeout; - + /** * Period in second between two beacon signals. */ float m_beaconPeriod; - + /** * Broadcast (beacon, search) port number to listen to. */ int m_broadcastPort; - + /** * Receive buffer size (max size of payload). */ int m_receiveBufferSize; - + /** * Timer. */ @@ -1855,7 +1858,7 @@ class TestChannelImpl : public ChannelImpl { * Broadcast transport needed to listen for broadcasts. */ BlockingUDPTransport* m_broadcastTransport; - + /** * UDP transport needed for channel searches. */ @@ -1868,7 +1871,7 @@ class TestChannelImpl : public ChannelImpl { /** * CA transport (virtual circuit) registry. - * This registry contains all active transports - connections to CA servers. + * This registry contains all active transports - connections to CA servers. */ TransportRegistry* m_transportRegistry; @@ -1895,7 +1898,7 @@ class TestChannelImpl : public ChannelImpl { Mutex m_cidMapMutex; /** - * Last CID cache. + * Last CID cache. */ pvAccessID m_lastCID; @@ -1907,7 +1910,7 @@ class TestChannelImpl : public ChannelImpl { IOIDResponseRequestMap m_pendingResponseRequests; /** - * Last IOID cache. + * Last IOID cache. */ pvAccessID m_lastIOID; @@ -1923,7 +1926,7 @@ class TestChannelImpl : public ChannelImpl { // TODO consider std::unordered_map // typedef std::map AddressBeaconHandlerMap; // AddressBeaconHandlerMap m_beaconHandlers; - + /** * Version. */ @@ -1933,18 +1936,20 @@ class TestChannelImpl : public ChannelImpl { * Provider implementation. */ ChannelProviderImpl* m_provider; - + /** * Context state. */ ContextState m_contextState; - + /** * Context sync. mutex. */ Mutex m_contextMutex; friend class ChannelProviderImpl; + + Configuration* m_configuration; }; @@ -1953,7 +1958,7 @@ class ChannelFindRequesterImpl : public ChannelFindRequester virtual void channelFindResult(epics::pvData::Status *status,ChannelFind *channelFind,bool wasFound) { std::cout << "[ChannelFindRequesterImpl] channelFindResult(" - << status->toString() << ", ..., " << wasFound << ")" << std::endl; + << status->toString() << ", ..., " << wasFound << ")" << std::endl; } }; @@ -1963,10 +1968,10 @@ class ChannelRequesterImpl : public ChannelRequester { return "ChannelRequesterImpl"; }; - - virtual void message(String message,MessageType messageType) + + virtual void message(String message,MessageType messageType) { - std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; } virtual void channelCreated(epics::pvData::Status* status, Channel *channel) @@ -1974,7 +1979,7 @@ class ChannelRequesterImpl : public ChannelRequester std::cout << "channelCreated(" << status->toString() << ", " << (channel ? channel->getChannelName() : "(null)") << ")" << std::endl; } - + virtual void channelStateChange(Channel *c, ConnectionState connectionState) { std::cout << "channelStateChange(" << c->getChannelName() << ", " << ConnectionStateNames[connectionState] << ")" << std::endl; @@ -1987,10 +1992,10 @@ class GetFieldRequesterImpl : public GetFieldRequester { return "GetFieldRequesterImpl"; }; - - virtual void message(String message,MessageType messageType) + + virtual void message(String message,MessageType messageType) { - std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; } virtual void getDone(epics::pvData::Status *status,epics::pvData::FieldConstPtr field) @@ -2013,22 +2018,22 @@ class ChannelGetRequesterImpl : public ChannelGetRequester ChannelGet *m_channelGet; epics::pvData::PVStructure *m_pvStructure; epics::pvData::BitSet *m_bitSet; - + virtual String getRequesterName() { return "ChannelGetRequesterImpl"; }; - - virtual void message(String message,MessageType messageType) + + virtual void message(String message,MessageType messageType) { - std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; } virtual void channelGetConnect(epics::pvData::Status *status,ChannelGet *channelGet, epics::pvData::PVStructure *pvStructure,epics::pvData::BitSet *bitSet) { std::cout << "channelGetConnect(" << status->toString() << ")" << std::endl; - + // TODO sync m_channelGet = channelGet; m_pvStructure = pvStructure; @@ -2050,22 +2055,22 @@ class ChannelPutRequesterImpl : public ChannelPutRequester ChannelPut *m_channelPut; epics::pvData::PVStructure *m_pvStructure; epics::pvData::BitSet *m_bitSet; - + virtual String getRequesterName() { return "ChannelPutRequesterImpl"; }; - - virtual void message(String message,MessageType messageType) + + virtual void message(String message,MessageType messageType) { - std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; } virtual void channelPutConnect(epics::pvData::Status *status,ChannelPut *channelPut, epics::pvData::PVStructure *pvStructure,epics::pvData::BitSet *bitSet) { std::cout << "channelPutConnect(" << status->toString() << ")" << std::endl; - + // TODO sync m_channelPut = channelPut; m_pvStructure = pvStructure; @@ -2091,20 +2096,20 @@ class ChannelPutRequesterImpl : public ChannelPutRequester } }; - - + + class MonitorRequesterImpl : public MonitorRequester { virtual String getRequesterName() { return "MonitorRequesterImpl"; }; - - virtual void message(String message,MessageType messageType) + + virtual void message(String message,MessageType messageType) { - std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; } - + virtual void monitorConnect(Status* status, Monitor* monitor, Structure* structure) { std::cout << "monitorConnect(" << status->toString() << ")" << std::endl; @@ -2115,13 +2120,13 @@ class MonitorRequesterImpl : public MonitorRequester std::cout << str << std::endl; } } - + virtual void monitorEvent(Monitor* monitor) { std::cout << "monitorEvent" << std::endl; MonitorElement* element = monitor->poll(); - + String str("changed/overrun "); element->getChangedBitSet()->toString(&str); str += '/'; @@ -2129,35 +2134,35 @@ class MonitorRequesterImpl : public MonitorRequester str += '\n'; element->getPVStructure()->toString(&str); std::cout << str << std::endl; - + monitor->release(element); } - + virtual void unlisten(Monitor* monitor) { std::cout << "unlisten" << std::endl; } -}; +}; class ChannelProcessRequesterImpl : public ChannelProcessRequester { ChannelProcess *m_channelProcess; - + virtual String getRequesterName() { return "ProcessRequesterImpl"; }; - - virtual void message(String message,MessageType messageType) + + virtual void message(String message,MessageType messageType) { - std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; } virtual void channelProcessConnect(epics::pvData::Status *status,ChannelProcess *channelProcess) { std::cout << "channelProcessConnect(" << status->toString() << ")" << std::endl; - + // TODO sync m_channelProcess = channelProcess; } @@ -2174,33 +2179,33 @@ int main(int argc,char *argv[]) TestClientContextImpl* context = new TestClientContextImpl(); context->printInfo(); - context->initialize(); + context->initialize(); context->printInfo(); - + epicsThreadSleep ( 1.0 ); - + //ChannelFindRequesterImpl findRequester; //context->getProvider()->channelFind("something", &findRequester); - + ChannelRequesterImpl channelRequester; Channel* channel = context->getProvider()->createChannel("structureArrayTest", &channelRequester); channel->printInfo(); /* GetFieldRequesterImpl getFieldRequesterImpl; channel->getField(&getFieldRequesterImpl, "timeStamp.secondsPastEpoch"); - + ChannelGetRequesterImpl channelGetRequesterImpl; ChannelGet* channelGet = channel->createChannelGet(&channelGetRequesterImpl, 0); channelGet->get(false); channelGet->destroy(); - + ChannelPutRequesterImpl channelPutRequesterImpl; ChannelPut* channelPut = channel->createChannelPut(&channelPutRequesterImpl, 0); channelPut->get(); channelPut->put(false); channelPut->destroy(); - - + + MonitorRequesterImpl monitorRequesterImpl; Monitor* monitor = channel->createMonitor(&monitorRequesterImpl, 0); @@ -2213,20 +2218,20 @@ int main(int argc,char *argv[]) ChannelProcess* channelProcess = channel->createChannelProcess(&channelProcessRequester, 0); channelProcess->process(false); channelProcess->destroy(); - + status = monitor->stop(); std::cout << "monitor->stop() = " << status->toString() << std::endl; delete status; - - + + monitor->destroy(); */ epicsThreadSleep ( 100.0 ); channel->destroy(); - + context->destroy(); - + std::cout << "-----------------------------------------------------------------------" << std::endl; getShowConstructDestruct()->constuctDestructTotals(stdout); return(0); diff --git a/testApp/utils/arrayFIFOTest.cpp b/testApp/utils/arrayFIFOTest.cpp index 61cbfc7..966d2c1 100644 --- a/testApp/utils/arrayFIFOTest.cpp +++ b/testApp/utils/arrayFIFOTest.cpp @@ -15,7 +15,9 @@ using namespace epics::pvAccess; using std::cout; using std::endl; -int main(int argc, char *argv[]) { +void testSimpleType() { + cout<<"\nTests for simple type template."< fifoInt; assert(fifoInt.size()==0); @@ -133,5 +135,137 @@ int main(int argc, char *argv[]) { assert(fifoInt.isEmpty()); cout<<"\nPASSED!\n"; +} + +void testPointerType() { + cout<<"\nTests for pointer type template."< fifoInt; + + assert(fifoInt.size()==0); + assert(fifoInt.isEmpty()); + + cout<<"Testing clear."< cb(CAPACITY); - cout<<"Testing circular buffer."< cb(CAPACITY); + int testVals[] = {0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20}; + + cout<<"Testing circular buffer pointer type."< #include @@ -23,6 +24,7 @@ using std::stringstream; using std::hex; int main(int argc, char *argv[]) { + createFileLogger("inetAddresUtils.log"); InetAddrVector *vec; InetAddrVector *vec1; @@ -126,12 +128,12 @@ int main(int argc, char *argv[]) { assert(strncmp(buff->getArray(), src, 16)==0); cout<<"\nPASSED!\n"; - SOCKET socket = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0); - InetAddrVector* broadcasts = getBroadcastAddresses(socket); + SOCKET socket = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP); + InetAddrVector* broadcasts = getBroadcastAddresses(socket,6678); cout<<"Broadcast addresses: "<size()<size(); i++) { cout<<"Broadcast address: "; - cout<at(i), false)<at(i))<