- Added inetAddressUtil.
- Fixed Makefiles to use a single pvData library.
This commit is contained in:
@@ -8,8 +8,8 @@ LIBSRCS += ChannelAccessFactory.cpp
|
||||
|
||||
LIBRARY=pvAccessClient
|
||||
|
||||
pvAccessClient_LIBS += pvMisc
|
||||
pvMisc_DIR = $(PVDATA_HOME)/lib/$(EPICS_HOST_ARCH)
|
||||
pvAccessClient_LIBS += pvData
|
||||
pvData_DIR = $(PVDATA_HOME)/lib/$(EPICS_HOST_ARCH)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
|
||||
@@ -4,19 +4,24 @@ include $(TOP)/configure/CONFIG
|
||||
|
||||
PROD_HOST += hexDumpTest
|
||||
hexDumpTest_SRCS += hexDumpTest.cpp
|
||||
hexDumpTest_LIBS += pvAccUtils
|
||||
hexDumpTest_LIBS += pvAccessUtils
|
||||
|
||||
PROD_HOST += wildcharMatcherTest
|
||||
wildcharMatcherTest_SRCS += wildcharMatcherTest.cpp
|
||||
wildcharMatcherTest_LIBS += pvAccUtils Com
|
||||
wildcharMatcherTest_LIBS += pvAccessUtils Com
|
||||
|
||||
PROD_HOST += arrayFIFOTest
|
||||
arrayFIFOTest_SRCS += arrayFIFOTest.cpp
|
||||
arrayFIFOTest_LIBS += pvAccUtils Com
|
||||
arrayFIFOTest_LIBS += pvAccessUtils Com
|
||||
|
||||
PROD_HOST += growingCircularBufferTest
|
||||
growingCircularBufferTest_SRCS += growingCircularBufferTest.cpp
|
||||
growingCircularBufferTest_LIBS += pvAccUtils Com
|
||||
growingCircularBufferTest_LIBS += pvAccessUtils Com
|
||||
|
||||
|
||||
PROD_HOST += inetAddressUtilsTest
|
||||
inetAddressUtilsTest_SRCS += inetAddressUtilsTest.cpp
|
||||
inetAddressUtilsTest_LIBS += pvAccessUtils Com
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
|
||||
138
pvAccessApp/testUtils/inetAddressUtilsTest.cpp
Normal file
138
pvAccessApp/testUtils/inetAddressUtilsTest.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* inetAddressUtilsTest.cpp
|
||||
*
|
||||
* Created on: Dec 8, 2010
|
||||
* Author: user
|
||||
*/
|
||||
|
||||
#include "inetAddressUtil.h"
|
||||
|
||||
#include <byteBuffer.h>
|
||||
#include <pvType.h>
|
||||
#include <epicsAssert.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
using namespace epics::pvAccess;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::stringstream;
|
||||
using std::hex;
|
||||
|
||||
String inetAddressToString(osiSockAddr *addr) {
|
||||
stringstream saddr;
|
||||
|
||||
saddr<<(int)((addr->ia.sin_addr.s_addr)>>24)<<'.';
|
||||
saddr<<((int)((addr->ia.sin_addr.s_addr)>>16)&0xFF)<<'.';
|
||||
saddr<<((int)((addr->ia.sin_addr.s_addr)>>8)&0xFF)<<'.';
|
||||
saddr<<((int)(addr->ia.sin_addr.s_addr)&0xFF);
|
||||
if(addr->ia.sin_port>0) saddr<<":"<<addr->ia.sin_port;
|
||||
saddr<<" ("<<hex<<((uint32_t)(addr->ia.sin_addr.s_addr))<<")";
|
||||
|
||||
return saddr.str();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
InetAddrVector *vec;
|
||||
InetAddrVector *vec1;
|
||||
|
||||
cout<<"Testing \"getSocketAddressList\""<<endl;
|
||||
vec = getSocketAddressList("127.0.0.1 10.10.12.11:1234 192.168.3.4", 555);
|
||||
|
||||
assert(vec->size()==3);
|
||||
|
||||
osiSockAddr* addr;
|
||||
addr = vec->at(0);
|
||||
assert(addr->ia.sin_family==AF_INET);
|
||||
assert(addr->ia.sin_port==555);
|
||||
assert(addr->ia.sin_addr.s_addr==(uint32_t)0x7F000001);
|
||||
cout<<'\t'<<inetAddressToString(addr)<<endl;
|
||||
|
||||
addr = vec->at(1);
|
||||
assert(addr->ia.sin_family==AF_INET);
|
||||
assert(addr->ia.sin_port==1234);
|
||||
assert(addr->ia.sin_addr.s_addr==(uint32_t)0x0A0A0C0B);
|
||||
cout<<'\t'<<inetAddressToString(addr)<<endl;
|
||||
|
||||
addr = vec->at(2);
|
||||
assert(addr->ia.sin_family==AF_INET);
|
||||
assert(addr->ia.sin_port==555);
|
||||
assert(addr->ia.sin_addr.s_addr==(uint32_t)0xC0A80304);
|
||||
cout<<'\t'<<inetAddressToString(addr)<<endl;
|
||||
|
||||
cout<<"\nPASSED!\n";
|
||||
|
||||
cout<<"Testing \"getSocketAddressList\" with append"<<endl;
|
||||
|
||||
vec1 = getSocketAddressList("172.16.55.160", 6789, vec);
|
||||
assert(vec1->size()==4);
|
||||
|
||||
addr = vec1->at(0);
|
||||
assert(addr->ia.sin_family==AF_INET);
|
||||
assert(addr->ia.sin_port==6789);
|
||||
assert(addr->ia.sin_addr.s_addr==(uint32_t)0xAC1037A0);
|
||||
cout<<'\t'<<inetAddressToString(addr)<<endl;
|
||||
|
||||
addr = vec1->at(1);
|
||||
assert(addr->ia.sin_family==AF_INET);
|
||||
assert(addr->ia.sin_port==555);
|
||||
assert(addr->ia.sin_addr.s_addr==(uint32_t)0x7F000001);
|
||||
cout<<'\t'<<inetAddressToString(addr)<<endl;
|
||||
|
||||
addr = vec1->at(2);
|
||||
assert(addr->ia.sin_family==AF_INET);
|
||||
assert(addr->ia.sin_port==1234);
|
||||
assert(addr->ia.sin_addr.s_addr==(uint32_t)0x0A0A0C0B);
|
||||
cout<<'\t'<<inetAddressToString(addr)<<endl;
|
||||
|
||||
addr = vec1->at(3);
|
||||
assert(addr->ia.sin_family==AF_INET);
|
||||
assert(addr->ia.sin_port==555);
|
||||
assert(addr->ia.sin_addr.s_addr==(uint32_t)0xC0A80304);
|
||||
cout<<'\t'<<inetAddressToString(addr)<<endl;
|
||||
|
||||
cout<<"\nPASSED!\n";
|
||||
|
||||
cout<<"Testing \"ipv4AddressToInt\""<<endl;
|
||||
assert(ipv4AddressToInt(*(vec->at(0)))==(int32)0x7F000001);
|
||||
assert(ipv4AddressToInt(*(vec->at(1)))==(int32)0x0A0A0C0B);
|
||||
assert(ipv4AddressToInt(*(vec->at(2)))==(int32)0xC0A80304);
|
||||
cout<<"\nPASSED!\n";
|
||||
|
||||
delete vec;
|
||||
delete vec1;
|
||||
|
||||
cout<<"Testing \"intToIPv4Address\""<<endl;
|
||||
addr = intToIPv4Address(0x7F000001);
|
||||
assert(addr->ia.sin_family==AF_INET);
|
||||
cout<<'\t'<<inetAddressToString(addr)<<endl;
|
||||
delete addr;
|
||||
|
||||
addr = intToIPv4Address(0x0A0A0C0B);
|
||||
assert(addr->ia.sin_family==AF_INET);
|
||||
cout<<'\t'<<inetAddressToString(addr)<<endl;
|
||||
|
||||
cout<<"\nPASSED!\n";
|
||||
|
||||
cout<<"Testing \"encodeAsIPv6Address\""<<endl;
|
||||
|
||||
ByteBuffer* buff = new ByteBuffer();
|
||||
|
||||
char src[] = { (char)0, (char)0, (char)0, (char)0, (char)0, (char)0,
|
||||
(char)0, (char)0, (char)0, (char)0, (char)0xFF, (char)0xFF,
|
||||
(char)0x0A, (char)0x0A, (char)0x0C, (char)0x0B };
|
||||
|
||||
|
||||
encodeAsIPv6Address(buff, addr);
|
||||
assert(strncmp(buff->getArray(),src,16)==0);
|
||||
cout<<"\nPASSED!\n";
|
||||
|
||||
// TODO add test for 'getBroadcastAddresses'
|
||||
|
||||
delete addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,13 +6,17 @@ INC += hexDump.h
|
||||
INC += wildcharMatcher.h
|
||||
INC += arrayFIFO.h
|
||||
INC += growingCircularBuffer.h
|
||||
INC += inetAddressUtil.h
|
||||
|
||||
LIBSRCS += hexDump.cpp
|
||||
LIBSRCS += wildcharMatcher.cpp
|
||||
LIBSRCS += inetAddressUtil.cpp
|
||||
|
||||
LIBRARY = pvAccUtils
|
||||
LIBRARY = pvAccessUtils
|
||||
pvAccessUtils_LIBS += Com
|
||||
pvAccessUtils_LIBS += pvData
|
||||
|
||||
#pvAccUtils_LIBS += Com
|
||||
pvData_DIR = $(PVDATA_HOME)/lib/$(EPICS_HOST_ARCH)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
|
||||
208
pvAccessApp/utils/inetAddressUtil.cpp
Normal file
208
pvAccessApp/utils/inetAddressUtil.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* inetAddressUtil.cpp
|
||||
*
|
||||
* Created on: Nov 12, 2010
|
||||
* Author: Miha Vitorovic
|
||||
*/
|
||||
|
||||
#include "inetAddressUtil.h"
|
||||
|
||||
#include <vector>
|
||||
#include <osiSock.h>
|
||||
#include <ellLib.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <epicsAssert.h>
|
||||
#include <byteBuffer.h>
|
||||
#include <epicsException.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
/* copied from EPICS v3 ca/iocinf.cpp
|
||||
* removeDuplicateAddresses ()
|
||||
*/
|
||||
void removeDuplicateAddresses(ELLLIST *pDestList, ELLLIST *pSrcList,
|
||||
int silent) {
|
||||
ELLNODE *pRawNode;
|
||||
|
||||
while((pRawNode = ellGet(pSrcList))) {
|
||||
STATIC_ASSERT(offsetof(osiSockAddrNode, node)==0);
|
||||
osiSockAddrNode *pNode =
|
||||
reinterpret_cast<osiSockAddrNode *> (pRawNode);
|
||||
osiSockAddrNode *pTmpNode;
|
||||
|
||||
if(pNode->addr.sa.sa_family==AF_INET) {
|
||||
|
||||
pTmpNode = (osiSockAddrNode *)ellFirst (pDestList); // X aCC 749
|
||||
while(pTmpNode) {
|
||||
if(pTmpNode->addr.sa.sa_family==AF_INET) {
|
||||
if(pNode->addr.ia.sin_addr.s_addr
|
||||
==pTmpNode->addr.ia.sin_addr.s_addr
|
||||
&&pNode->addr.ia.sin_port
|
||||
==pTmpNode->addr.ia.sin_port) {
|
||||
if(!silent) {
|
||||
char buf[64];
|
||||
ipAddrToDottedIP(&pNode->addr.ia, buf,
|
||||
sizeof(buf));
|
||||
fprintf(
|
||||
stderr,
|
||||
"Warning: Duplicate EPICS CA Address list entry \"%s\" discarded\n",
|
||||
buf);
|
||||
}
|
||||
free(pNode);
|
||||
pNode = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pTmpNode = (osiSockAddrNode *)ellNext (&pTmpNode->node); // X aCC 749
|
||||
}
|
||||
if(pNode) {
|
||||
ellAdd(pDestList, &pNode->node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ellAdd(pDestList, &pNode->node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InetAddrVector* getBroadcastAddresses(SOCKET sock) {
|
||||
ELLLIST bcastList;
|
||||
ELLLIST tmpList;
|
||||
osiSockAddr addr;
|
||||
|
||||
ellInit ( &bcastList ); // X aCC 392
|
||||
ellInit ( &tmpList ); // X aCC 392
|
||||
|
||||
addr.ia.sin_family = AF_UNSPEC;
|
||||
osiSockDiscoverBroadcastAddresses(&bcastList, sock, &addr);
|
||||
removeDuplicateAddresses(&tmpList, &bcastList, 1);
|
||||
// forcePort ( &bcastList, port ); // if needed copy from ca/iocinf.cpp
|
||||
|
||||
int size = ellCount(&bcastList );
|
||||
InetAddrVector* retVector = new InetAddrVector(size);
|
||||
|
||||
ELLNODE *pRawNode;
|
||||
|
||||
while((pRawNode = ellGet(&tmpList))) {
|
||||
osiSockAddrNode *pNode =
|
||||
reinterpret_cast<osiSockAddrNode *> (pRawNode);
|
||||
osiSockAddr* posa = new osiSockAddr;
|
||||
memcpy(posa, &(pNode->addr), sizeof(osiSockAddr));
|
||||
retVector->push_back(posa);
|
||||
free(pNode); // using free because it is allocated by calloc
|
||||
}
|
||||
|
||||
return retVector;
|
||||
}
|
||||
|
||||
void encodeAsIPv6Address(ByteBuffer* buffer, const osiSockAddr* address) {
|
||||
// IPv4 compatible IPv6 address
|
||||
// first 80-bit are 0
|
||||
buffer->putLong(0);
|
||||
buffer->putShort(0);
|
||||
// next 16-bits are 1
|
||||
buffer->putShort(0xFFFF);
|
||||
// following IPv4 address in big-endian (network) byte order
|
||||
in_addr_t ipv4Addr = 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) {
|
||||
osiSockAddr* ret = new osiSockAddr;
|
||||
ret->ia.sin_family = AF_INET;
|
||||
ret->ia.sin_addr.s_addr = (in_addr_t)addr;
|
||||
ret->ia.sin_port = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32 ipv4AddressToInt(const osiSockAddr& addr) {
|
||||
return (int32)(addr.ia.sin_addr.s_addr);
|
||||
}
|
||||
|
||||
int32 parseInetAddress(const String addr) {
|
||||
int32 retAddr;
|
||||
|
||||
size_t dot = addr.find('.');
|
||||
if(dot==String::npos) THROW_BASE_EXCEPTION("Not an IPv4 address.");
|
||||
int byte = atoi(addr.substr(0, dot).c_str());
|
||||
if(byte<0||byte>255) THROW_BASE_EXCEPTION("Not an IPv4 address.");
|
||||
retAddr = byte;
|
||||
|
||||
int num = dot+1;
|
||||
dot = addr.find('.', num);
|
||||
if(dot==String::npos) THROW_BASE_EXCEPTION("Not an IPv4 address.");
|
||||
byte = atoi(addr.substr(num, dot-num).c_str());
|
||||
if(byte<0||byte>255) THROW_BASE_EXCEPTION("Not an IPv4 address.");
|
||||
retAddr <<= 8;
|
||||
retAddr |= byte;
|
||||
|
||||
num = dot+1;
|
||||
dot = addr.find('.', num);
|
||||
if(dot==String::npos) THROW_BASE_EXCEPTION("Not an IPv4 address.");
|
||||
byte = atoi(addr.substr(num, dot-num).c_str());
|
||||
if(byte<0||byte>255) THROW_BASE_EXCEPTION("Not an IPv4 address.");
|
||||
retAddr <<= 8;
|
||||
retAddr |= byte;
|
||||
|
||||
num = dot+1;
|
||||
byte = atoi(addr.substr(num).c_str());
|
||||
if(byte<0||byte>255) THROW_BASE_EXCEPTION("Not an IPv4 address.");
|
||||
retAddr <<= 8;
|
||||
retAddr |= byte;
|
||||
|
||||
return retAddr;
|
||||
}
|
||||
|
||||
osiSockAddr* processAddressForList(String address, int defaultPort) {
|
||||
// check port
|
||||
int port = defaultPort;
|
||||
size_t pos = address.find(':');
|
||||
if(pos!=String::npos) {
|
||||
port = atoi(address.substr(pos+1).c_str());
|
||||
address = address.substr(0, pos);
|
||||
}
|
||||
|
||||
// add parsed address
|
||||
osiSockAddr* addr = new osiSockAddr;
|
||||
addr->ia.sin_family = AF_INET;
|
||||
addr->ia.sin_port = port;
|
||||
addr->ia.sin_addr.s_addr = parseInetAddress(address);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
InetAddrVector* getSocketAddressList(String list, int defaultPort,
|
||||
const InetAddrVector* appendList) {
|
||||
InetAddrVector* iav = new InetAddrVector();
|
||||
|
||||
// parse string
|
||||
size_t subStart = 0;
|
||||
size_t subEnd;
|
||||
while((subEnd = list.find(' ', subStart))!=String::npos) {
|
||||
String address = list.substr(subStart, (subEnd-subStart));
|
||||
|
||||
iav->push_back(processAddressForList(address, defaultPort));
|
||||
subStart = list.find_first_not_of(" \t\r\n\v", subEnd);
|
||||
}
|
||||
|
||||
if(subStart!=String::npos&&list.length()>0) iav->push_back(
|
||||
processAddressForList(list.substr(subStart), defaultPort));
|
||||
|
||||
if(appendList!=NULL) {
|
||||
for(size_t i = 0; i<appendList->size(); i++)
|
||||
iav->push_back(appendList->at(i));
|
||||
}
|
||||
return iav;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
87
pvAccessApp/utils/inetAddressUtil.h
Normal file
87
pvAccessApp/utils/inetAddressUtil.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* inetAddressUtil.h
|
||||
*
|
||||
* Created on: Nov 12, 2010
|
||||
* Author: Miha Vitorovic
|
||||
*/
|
||||
|
||||
#ifndef INETADDRESSUTIL_H_
|
||||
#define INETADDRESSUTIL_H_
|
||||
|
||||
/* uporabim lahko:
|
||||
* EPICSv3 osiSock.h kjer je definiran osiSockDiscoverBroadcastAddresses
|
||||
*
|
||||
* Kako se ga uporablja je v
|
||||
* epics/base/src/ca/iocinf.cpp funkcija configureChannelAccessAddressList
|
||||
*
|
||||
* razišči kako se to priredi za IPv6
|
||||
*
|
||||
*/
|
||||
|
||||
#include <pvType.h>
|
||||
#include <byteBuffer.h>
|
||||
#include <osiSock.h>
|
||||
#include <vector>
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
typedef std::vector<osiSockAddr*> InetAddrVector;
|
||||
|
||||
/**
|
||||
* returns a vector containing all the IPv4 broadcast addresses
|
||||
* on this machine. IPv6 doesn't have a local broadcast address.
|
||||
*
|
||||
* TODO Check implementation/rewrite this
|
||||
*/
|
||||
InetAddrVector* getBroadcastAddresses(SOCKET sock);
|
||||
|
||||
/**
|
||||
* Encode IPv4 address as IPv6 address.
|
||||
* @param buffer byte-buffer where to put encoded data.
|
||||
* @param address address to encode.
|
||||
*/
|
||||
void
|
||||
encodeAsIPv6Address(ByteBuffer* buffer,
|
||||
const osiSockAddr* address);
|
||||
|
||||
/**
|
||||
* Convert an integer into an IPv4 INET address.
|
||||
* @param addr integer representation of a given address.
|
||||
* @return IPv4 INET address.
|
||||
*/
|
||||
osiSockAddr* intToIPv4Address(int32 addr);
|
||||
|
||||
/**
|
||||
* Convert an IPv4 INET address to an integer.
|
||||
* @param addr IPv4 INET address.
|
||||
* @return integer representation of a given address.
|
||||
*/
|
||||
int32 ipv4AddressToInt(const osiSockAddr& addr);
|
||||
|
||||
/**
|
||||
* Parse space delimited addresss[:port] string and return array of <code>InetSocketAddress</code>.
|
||||
* @param list space delimited addresss[:port] string.
|
||||
* @param defaultPort port take if not specified.
|
||||
* @param appendList list to be appended.
|
||||
* @return array of <code>InetSocketAddress</code>.
|
||||
*/
|
||||
InetAddrVector* getSocketAddressList(String list, int defaultPort,
|
||||
const InetAddrVector* appendList);
|
||||
|
||||
/**
|
||||
* Parse space delimited addresss[:port] string and return array of <code>InetSocketAddress</code>.
|
||||
* @param list space delimited addresss[:port] string.
|
||||
* @param defaultPort port take if not specified.
|
||||
* @return array of <code>InetSocketAddress</code>.
|
||||
*/
|
||||
InetAddrVector* getSocketAddressList(String list, int defaultPort) {
|
||||
return getSocketAddressList(list, defaultPort, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* INETADDRESSUTIL_H_ */
|
||||
Reference in New Issue
Block a user