port from pvAccessCPP-md

This commit is contained in:
Matej Sekoranja
2011-05-12 12:47:55 +02:00
parent a077d7d084
commit c36ba5264d
68 changed files with 4762 additions and 5612 deletions
+63 -63
View File
@@ -20,105 +20,102 @@
namespace epics {
namespace pvAccess {
BlockingTCPConnector::BlockingTCPConnector(Context* context,
int receiveBufferSize, float beaconInterval) :
_context(context), _namedLocker(new NamedLockPattern<
const osiSockAddr*, comp_osiSockAddrPtr> ()),
_receiveBufferSize(receiveBufferSize), _beaconInterval(
beaconInterval) {
BlockingTCPConnector::BlockingTCPConnector(
Context::shared_pointer& context,
int receiveBufferSize,
float beaconInterval) :
_context(context),
_namedLocker(),
_receiveBufferSize(receiveBufferSize),
_beaconInterval(beaconInterval)
{
}
BlockingTCPConnector::~BlockingTCPConnector() {
delete _namedLocker;
}
SOCKET BlockingTCPConnector::tryConnect(osiSockAddr& address, int tries) {
for(int tryCount = 0; tryCount<tries; tryCount++) {
// sleep for a while
if(tryCount>0) epicsThreadSleep(0.1);
char strBuffer[64];
ipAddrToDottedIP(&address.ia, strBuffer, sizeof(strBuffer));
char strBuffer[64];
ipAddrToDottedIP(&address.ia, strBuffer, sizeof(strBuffer));
for(int tryCount = 0; tryCount<tries; tryCount++) {
errlogSevPrintf(errlogInfo,
"Opening socket to CA server %s, attempt %d.",
strBuffer, tryCount+1);
SOCKET socket = epicsSocketCreate(AF_INET, SOCK_STREAM,
IPPROTO_TCP);
if(socket==INVALID_SOCKET) {
epicsSocketConvertErrnoToString(strBuffer,
sizeof(strBuffer));
errlogSevPrintf(errlogMinor, "Socket create error: %s",
strBuffer);
SOCKET socket = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socket == INVALID_SOCKET)
{
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
errlogSevPrintf(errlogMinor, "Socket create error: %s", strBuffer);
return INVALID_SOCKET;
}
else {
if(::connect(socket, &address.sa, sizeof(sockaddr))==0)
if(::connect(socket, &address.sa, sizeof(sockaddr))==0) {
return socket;
}
else {
epicsSocketConvertErrnoToString(strBuffer,
sizeof(strBuffer));
errlogSevPrintf(errlogMinor,
"Socket connect error: %s", strBuffer);
epicsSocketDestroy (socket);
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
errlogSevPrintf(errlogMinor, "Socket connect error: %s", strBuffer);
}
}
}
return INVALID_SOCKET;
}
Transport* BlockingTCPConnector::connect(TransportClient* client,
ResponseHandler* responseHandler, osiSockAddr& address,
Transport::shared_pointer BlockingTCPConnector::connect(TransportClient::shared_pointer& client,
auto_ptr<ResponseHandler>& responseHandler, osiSockAddr& address,
short transportRevision, int16 priority) {
SOCKET socket = INVALID_SOCKET;
char ipAddrStr[64];
ipAddrToDottedIP(&address.ia, ipAddrStr, sizeof(ipAddrStr));
Context::shared_pointer context = _context.lock();
// first try to check cache w/o named lock...
BlockingClientTCPTransport
* transport =
(BlockingClientTCPTransport*)(_context->getTransportRegistry()->get(
"TCP", &address, priority));
if(transport!=NULL) {
Transport::shared_pointer tt = context->getTransportRegistry()->get("TCP", &address, priority);
BlockingClientTCPTransport::shared_pointer transport = std::tr1::static_pointer_cast<BlockingClientTCPTransport>(tt);
if(transport.get()) {
errlogSevPrintf(errlogInfo,
"Reusing existing connection to CA server: %s",
ipAddrStr);
if(transport->acquire(client)) return transport;
if (transport->acquire(client))
return transport;
}
bool lockAcquired = _namedLocker->acquireSynchronizationObject(
&address, LOCK_TIMEOUT);
bool lockAcquired = _namedLocker.acquireSynchronizationObject(&address, LOCK_TIMEOUT);
if(lockAcquired) {
try {
// ... transport created during waiting in lock
transport
= (BlockingClientTCPTransport*)(_context->getTransportRegistry()->get(
"TCP", &address, priority));
if(transport!=NULL) {
tt = context->getTransportRegistry()->get("TCP", &address, priority);
transport = std::tr1::static_pointer_cast<BlockingClientTCPTransport>(tt);
if(transport.get()) {
errlogSevPrintf(errlogInfo,
"Reusing existing connection to CA server: %s",
ipAddrStr);
if(transport->acquire(client)) return transport;
"Reusing existing connection to CA server: %s",
ipAddrStr);
if (transport->acquire(client))
return transport;
}
errlogSevPrintf(errlogInfo, "Connecting to CA server: %s",
ipAddrStr);
errlogSevPrintf(errlogInfo, "Connecting to CA server: %s", ipAddrStr);
socket = tryConnect(address, 3);
// verify
if(socket==INVALID_SOCKET) {
errlogSevPrintf(errlogMajor,
"Connection to CA server %s failed.", ipAddrStr);
ostringstream temp;
temp<<"Failed to verify TCP connection to '"<<ipAddrStr
<<"'.";
temp<<"Failed to verify TCP connection to '"<<ipAddrStr<<"'.";
THROW_BASE_EXCEPTION(temp.str().c_str());
}
// use blocking channel
// socket is blocking bya default
//socket.configureBlocking(true);
errlogSevPrintf(errlogInfo, "Socket connected to CA server: %s.", ipAddrStr);
// enable TCP_NODELAY (disable Nagle's algorithm)
int optval = 1; // true
@@ -134,14 +131,11 @@ namespace epics {
"Error setting SO_KEEPALIVE: %s", strerror(errno));
// TODO tune buffer sizes?! Win32 defaults are 8k, which is OK
//socket.socket().setReceiveBufferSize();
//socket.socket().setSendBufferSize();
// create transport
transport = new BlockingClientTCPTransport(_context,
socket, responseHandler, _receiveBufferSize,
client, transportRevision, _beaconInterval,
priority);
transport = BlockingClientTCPTransport::create(
context, socket, responseHandler, _receiveBufferSize,
client, transportRevision, _beaconInterval, priority);
// verify
if(!transport->waitUntilVerified(3.0)) {
@@ -150,25 +144,31 @@ namespace epics {
"Connection to CA server %s failed to be validated, closing it.",
ipAddrStr);
ostringstream temp;
temp<<"Failed to verify TCP connection to '"<<ipAddrStr
<<"'.";
temp<<"Failed to verify TCP connection to '"<<ipAddrStr<<"'.";
THROW_BASE_EXCEPTION(temp.str().c_str());
}
// TODO send security token
errlogSevPrintf(errlogInfo, "Connected to CA server: %s",
ipAddrStr);
errlogSevPrintf(errlogInfo, "Connected to CA server: %s", ipAddrStr);
_namedLocker.releaseSynchronizationObject(&address);
return transport;
} catch(...) {
if(transport!=NULL)
} catch(std::exception& ex) {
// TODO
printf("ex %s\n", ex.what());
if(transport.get())
transport->close(true);
else if(socket!=INVALID_SOCKET) epicsSocketDestroy(socket);
_namedLocker->releaseSynchronizationObject(&address);
_namedLocker.releaseSynchronizationObject(&address);
throw;
} catch(...) {
if(transport.get())
transport->close(true);
else if(socket!=INVALID_SOCKET) epicsSocketDestroy(socket);
_namedLocker.releaseSynchronizationObject(&address);
throw;
}
_namedLocker->releaseSynchronizationObject(&address);
}
else {
ostringstream temp;