Files
pvAccess/pvAccessApp/utils/inetAddressUtil.cpp
miha_vitorovic 8339c338de blockingServerTCPTransport.cpp:
- using enum to specify command.

BlockingTCPAcceptor.cpp:
- added 'destroy()' to dtor
- added parentheses to expressions

blockingTCPCinnector.cpp:
- fixed log message

blockingTCPTransport.cpp:
- added _socketAddress allocation
- fixed waiting for timeout in 'waitUntilVerified'
- fixed how many bytes are copied from the buffer

responseHandlers.cpp:
- added 'ConnectionValidationHandler' implementation
- added 'ConnectionValidationHandler' to 'ServerResponseHandler'

responseHandlers.h:
- added 'ConnectionValidationHandler' declaration

inetAddressUtil.cpp:
- fixed all issues with sockaddr_in byte-order
- removed function 'processAddressForList', using EPICSv3 'aToIPAddr' instead

inetAddressUtilsTest.cpp:
- fixed the tests in accordance with the correct function implementation

testBlockingUDPClnt.cpp:
- deleting transport at the end of the test

testBlockingTCPSrv.cpp, testBlockingTCPClnt.cpp:
- added tests (work in progress).

Makefile:
- added blockingTCP tests
2011-01-06 14:58:32 +01:00

219 lines
7.6 KiB
C++

/*
* inetAddressUtil.cpp
*
* Created on: Nov 12, 2010
* Author: Miha Vitorovic
*/
/* pvAccess */
#include "inetAddressUtil.h"
/* pvData */
#include <byteBuffer.h>
/* EPICSv3 */
#include <osiSock.h>
#include <ellLib.h>
#include <epicsAssert.h>
#include <epicsException.h>
/* standard */
#include <vector>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <sys/socket.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 = htonl(addr);
ret->ia.sin_port = 0;
return ret;
}
int32 ipv4AddressToInt(const osiSockAddr& addr) {
return (int32)ntohl(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;
}
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));
osiSockAddr* addr = new osiSockAddr;
aToIPAddr(address.c_str(), defaultPort, &addr->ia);
iav->push_back(addr);
subStart = list.find_first_not_of(" \t\r\n\v", subEnd);
}
if(subStart!=String::npos&&list.length()>0) {
osiSockAddr* addr = new osiSockAddr;
aToIPAddr(list.substr(subStart).c_str(), defaultPort, &addr->ia);
iav->push_back(addr);
}
if(appendList!=NULL) {
for(size_t i = 0; i<appendList->size(); i++)
iav->push_back(appendList->at(i));
}
return iav;
}
const String inetAddressToString(const osiSockAddr *addr,
bool displayHex) {
stringstream saddr;
int ipa = ntohl(addr->ia.sin_addr.s_addr);
saddr<<((int)(ipa>>24)&0xFF)<<'.';
saddr<<((int)(ipa>>16)&0xFF)<<'.';
saddr<<((int)(ipa>>8)&0xFF)<<'.';
saddr<<((int)ipa&0xFF);
if(addr->ia.sin_port>0) saddr<<":"<<ntohs(addr->ia.sin_port);
if(displayHex) saddr<<" ("<<hex
<<ntohl(addr->ia.sin_addr.s_addr)<<")";
return saddr.str();
}
}
}