merge and broadcast addresses fix

This commit is contained in:
Matej Sekoranja
2011-01-10 17:51:30 +01:00
24 changed files with 990 additions and 483 deletions

View File

@@ -307,7 +307,6 @@
<buildTargets>
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>all</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
@@ -315,7 +314,6 @@
</target>
<target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
@@ -323,11 +321,20 @@
</target>
<target name="uninstall" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>uninstall</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
</target>
<target name="debug" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean all DEBUG=1</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
</target>
</buildTargets>
</storageModule>
</cconfiguration>

View File

@@ -24,4 +24,11 @@
# take effect.
#IOCS_APPL_TOP = </IOC/path/to/application/top>
USR_LDFLAGS += -lpthread
ifeq ($(DEBUG),1)
DEBUG_CFLAGS=-O0 -g -ggdb
endif
ifeq ($(EPICS_HOST_ARCH),linux-x86)
USR_LDFLAGS += -lpthread
endif

View File

@@ -67,6 +67,7 @@ LIBSRCS += blockingTCPConnector.cpp
LIBSRCS += blockingServerTCPTransport.cpp
LIBSRCS += blockingTCPAcceptor.cpp
LIBSRCS += channelSearchManager.cpp
LIBSRCS += abstractResponseHandler.cpp
SRC_DIRS += $(PVACCESS)/remoteClient

View File

@@ -0,0 +1,42 @@
/*
* abstractResponseHandler.cpp
*
* Created on: Jan 10, 2011
* Author: Miha Vitorovic
*/
#include "remote.h"
#include "hexDump.h"
#include <byteBuffer.h>
#include <osiSock.h>
#include <sstream>
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"<<hex<<(int)command<<", v0x"<<hex;
prologue<<(int)version<<"] received from "<<ipAddrStr;
hexDump(prologue.str(), _description,
(const int8*)payloadBuffer->getArray(),
payloadBuffer->getPosition(), payloadSize);
}
}
}
}

View File

@@ -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,

View File

@@ -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);

View File

@@ -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 '"<<ipAddrStr
<<"'.";
THROW_BASE_EXCEPTION(temp.str().c_str());
}
// use blocking channel
// socket is blocking bya default
@@ -140,7 +149,7 @@ namespace epics {
if(!transport->waitUntilVerified(3.0)) {
transport->close(true);
errlogSevPrintf(
errlogInfo,
errlogMinor,
"Connection to CA server %s failed to be validated, closing it.",
ipAddrStr);
ostringstream temp;

View File

@@ -11,7 +11,7 @@
#include "caConstants.h"
#include "transportRegistry.h"
#include "introspectionRegistry.h"
#include "serverContext.h"
#include "configuration.h"
#include <serialize.h>
#include <pvType.h>
@@ -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 <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
@@ -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 <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
@@ -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 <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
*/
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;
};
}
}

View File

@@ -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"<<hex<<(int)command<<", v0x"<<hex;
prologue<<(int)version<<"] received from "<<ipAddrStr;
hexDump(prologue.str(), _description,
(const int8*)payloadBuffer->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;

View File

@@ -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;
};
/**

View File

@@ -8,11 +8,12 @@
#ifndef SERVERCONTEXT_H_
#define SERVERCONTEXT_H_
#include "remote.h"
namespace epics {
namespace pvAccess {
class ServerContextImpl {
class ServerContextImpl : public Context {
};

View File

@@ -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<class T>
void GrowingCircularBuffer<T>::arraycopy(T* src, size_t srcPos, T* dest,
size_t destPos, size_t length) {
void GrowingCircularBuffer<T>::arraycopy(T* src, size_t srcPos,
T* dest, size_t destPos, size_t length) {
if(srcPos<destPos) // this takes care of same-buffer copy
for(int i = length-1; i>=0; i--)
dest[destPos+i] = src[srcPos+i];
@@ -111,17 +107,16 @@ namespace epics {
template<class T>
bool GrowingCircularBuffer<T>::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<class T>
@@ -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 T>
class GrowingCircularBuffer<T*> {
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 <code>true</code> 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<class T>
void GrowingCircularBuffer<T*>::arraycopy(T** src, size_t srcPos,
T** dest, size_t destPos, size_t length) {
if(srcPos<destPos) // this takes care of same-buffer copy
for(int i = length-1; i>=0; i--)
dest[destPos+i] = src[srcPos+i];
else
for(size_t i = 0; i<length; i++)
dest[destPos++] = src[srcPos++];
}
template<class T>
bool GrowingCircularBuffer<T*>::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<T*>(x);
if(++_putPointer>=_size) _putPointer = 0;
return _count==1;
}
template<class T>
T* GrowingCircularBuffer<T*>::extract() {
if(_count==0) return NULL;
_count--;
T* old = _elements[_takePointer];
if(++_takePointer>=_size) _takePointer = 0;
return old;
}
}
}
#endif /* GROWINGCIRCULARBUFFER_H_ */

View File

@@ -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; i<maxNodes; i++) {
if (!(*p->ifr_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; i<maxNodes; i++) {
if(!(*pifreq->ifr_name)) break;
if(i>0) {
size_t n = pifreq->ifr_addr.sa_len+sizeof(pifreq->ifr_name);
if(n<sizeof(ifreq))
pifreq++;
else
pifreq = (struct ifreq *)((char *)pifreq+n);
}
/*
* If its not an internet interface then dont use it
*/
if(p->ifr_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) {

View File

@@ -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.

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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;

View File

@@ -8,6 +8,7 @@
#include "blockingTCP.h"
#include "remote.h"
#include "logger.h"
#include "configuration.h"
#include <iostream>
@@ -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;
}

View File

@@ -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;

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -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."<<endl;
ArrayFIFO<int> 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."<<endl;
int testVals[] = {0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20};
ArrayFIFO<int*> fifoInt;
assert(fifoInt.size()==0);
assert(fifoInt.isEmpty());
cout<<"Testing clear."<<endl;
fifoInt.push(&testVals[3]);
assert(fifoInt.size()==1);
fifoInt.clear();
assert(fifoInt.isEmpty());
cout<<"Testing push/pop."<<endl;
fifoInt.push(&testVals[5]);
fifoInt.push(&testVals[6]);
fifoInt.push(&testVals[7]);
assert(fifoInt.size()==3);
assert(fifoInt.pop()==&testVals[7]);
assert(fifoInt.size()==2);
assert(fifoInt.pop()==&testVals[6]);
assert(fifoInt.size()==1);
assert(fifoInt.pop()==&testVals[5]);
assert(fifoInt.size()==0);
cout<<"Testing FIFO ops (first/last)."<<endl;
fifoInt.addFirst(&testVals[1]);
fifoInt.addFirst(&testVals[2]);
fifoInt.addFirst(&testVals[3]);
fifoInt.addFirst(&testVals[4]);
fifoInt.addFirst(&testVals[5]);
assert(fifoInt.size()==5);
assert(fifoInt.pollLast()==&testVals[1]);
assert(fifoInt.pollLast()==&testVals[2]);
assert(fifoInt.pollLast()==&testVals[3]);
assert(fifoInt.pollLast()==&testVals[4]);
assert(fifoInt.pollLast()==&testVals[5]);
assert(fifoInt.isEmpty());
cout<<"Testing FIFO ops (last/first)."<<endl;
fifoInt.addLast(&testVals[7]);
fifoInt.addLast(&testVals[8]);
fifoInt.addLast(&testVals[9]);
fifoInt.addLast(&testVals[10]);
fifoInt.addLast(&testVals[11]);
assert(fifoInt.size()==5);
assert(fifoInt.pollFirst()==&testVals[7]);
assert(fifoInt.pollFirst()==&testVals[8]);
assert(fifoInt.pollFirst()==&testVals[9]);
assert(fifoInt.pollFirst()==&testVals[10]);
assert(fifoInt.pollFirst()==&testVals[11]);
assert(fifoInt.isEmpty());
cout<<"Testing remove, peek."<<endl;
fifoInt.addFirst(&testVals[1]);
fifoInt.addFirst(&testVals[2]);
fifoInt.addFirst(&testVals[3]);
fifoInt.addFirst(&testVals[4]);
fifoInt.addFirst(&testVals[5]);
fifoInt.addFirst(&testVals[6]);
fifoInt.addFirst(&testVals[7]);
// - - - - - - - - - - - -
fifoInt.addFirst(&testVals[8]);
fifoInt.addFirst(&testVals[9]);
fifoInt.addFirst(&testVals[10]);
assert(fifoInt.peekFirst()==&testVals[10]);
assert(fifoInt.peekLast()==&testVals[1]);
assert(fifoInt.size()==10);
assert(fifoInt.remove(&testVals[9]));
assert(fifoInt.size()==9);
assert(!fifoInt.remove(&testVals[15]));
assert(fifoInt.size()==9);
assert(fifoInt.pollLast()==&testVals[1]);
assert(fifoInt.pollLast()==&testVals[2]);
assert(fifoInt.pollLast()==&testVals[3]);
assert(fifoInt.pollLast()==&testVals[4]);
assert(fifoInt.pollLast()==&testVals[5]);
assert(fifoInt.pollLast()==&testVals[6]);
assert(fifoInt.pollLast()==&testVals[7]);
assert(fifoInt.pollLast()==&testVals[8]);
// - - - - - - - - - - - -
assert(fifoInt.pollLast()==&testVals[10]);
assert(fifoInt.isEmpty());
cout<<"Testing increase buffer."<<endl;
fifoInt.addLast(&testVals[2]);
fifoInt.addLast(&testVals[3]);
fifoInt.addLast(&testVals[4]);
fifoInt.addLast(&testVals[5]);
fifoInt.addLast(&testVals[6]);
fifoInt.addLast(&testVals[7]);
fifoInt.addLast(&testVals[8]);
fifoInt.addLast(&testVals[9]);
fifoInt.addLast(&testVals[10]);
fifoInt.addLast(&testVals[11]);
fifoInt.addLast(&testVals[12]);
fifoInt.addLast(&testVals[13]);
fifoInt.addLast(&testVals[14]);
fifoInt.addLast(&testVals[15]);
fifoInt.addLast(&testVals[16]);
fifoInt.addLast(&testVals[17]);
fifoInt.addLast(&testVals[18]);
fifoInt.addLast(&testVals[19]);
assert(fifoInt.size()==18);
fifoInt.debugState();
fifoInt.clear();
assert(fifoInt.isEmpty());
cout<<"\nPASSED!\n";
}
int main(int argc, char *argv[]) {
testSimpleType();
cout<<endl;
testPointerType();
return 0;
}

View File

@@ -16,19 +16,19 @@ using std::endl;
const size_t CAPACITY = 10;
int main(int argc, char *argv[]) {
void testSimpleType() {
GrowingCircularBuffer<int> cb(CAPACITY);
cout<<"Testing circular buffer."<<endl;
cout<<"Testing circular buffer simple type."<<endl;
assert(cb.capacity()==CAPACITY);
assert(cb.size()==0);
// insert, get test
bool first = cb.insert(1);
assert(first);
assert(cb.size()==1);
assert(cb.extract()==1);
assert(first);
assert(cb.size()==0);
for(size_t i = 0; i<2*CAPACITY; i++) {
@@ -45,6 +45,45 @@ int main(int argc, char *argv[]) {
assert(cb.size()==0);
cout<<"\nPASSED!\n";
return 0;
}
void testPointerType() {
GrowingCircularBuffer<int*> 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."<<endl;
assert(cb.capacity()==CAPACITY);
assert(cb.size()==0);
// insert, get test
bool first = cb.insert(&testVals[1]);
assert(first);
assert(cb.size()==1);
assert(cb.extract()==&testVals[1]);
assert(cb.size()==0);
for(size_t i = 0; i<2*CAPACITY; i++) {
first = cb.insert(&testVals[i]);
assert(cb.size()==i+1);
assert((cb.size() == 1)==first);
}
assert(cb.size()==2*CAPACITY);
for(size_t i = 0; i<2*CAPACITY; i++) {
assert(cb.extract()==&testVals[i]);
assert(cb.size()==2*CAPACITY-i-1);
}
assert(cb.size()==0);
cout<<"\nPASSED!\n";
}
int main(int argc, char *argv[]) {
testSimpleType();
cout<<endl;
testPointerType();
return 0;
}

View File

@@ -6,6 +6,7 @@
*/
#include "inetAddressUtil.h"
#include "logger.h"
#include <byteBuffer.h>
#include <pvType.h>
@@ -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: "<<broadcasts->size()<<endl;
for(size_t i = 0; i<broadcasts->size(); i++) {
cout<<"Broadcast address: ";
cout<<inetAddressToString(broadcasts->at(i), false)<<endl;
cout<<inetAddressToString(broadcasts->at(i))<<endl;
}
delete broadcasts;