void TransportRegistry::put(Transport::shared_pointer const & transport) { Lock guard(_mutex); //const string type = transport.getType(); const int16 priority = transport->getPriority(); const osiSockAddr* address = transport->getRemoteAddress(); transportsMap_t::iterator transportsIter = _transports.find(address); prioritiesMapSharedPtr_t priorities; if(transportsIter == _transports.end()) { priorities.reset(new prioritiesMap_t()); _transports[address] = priorities; _transportCount++; } else { priorities = transportsIter->second; prioritiesMap_t::iterator prioritiesIter = priorities->find(priority); if(prioritiesIter == priorities->end()) //only increase transportCount if not replacing { _transportCount++; } } (*priorities)[priority] = transport; }
void AuthNZHandler::handleResponse(osiSockAddr* responseFrom, Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command, size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer) { AbstractResponseHandler::handleResponse(responseFrom, transport, version, command, payloadSize, payloadBuffer); epics::pvData::PVField::shared_pointer data = SerializationHelper::deserializeFull(payloadBuffer, transport.get()); transport->authNZMessage(data); }
bool BlockingTCPAcceptor::validateConnection(Transport::shared_pointer const & transport, const char* address) { try { return transport->verify(5000); } catch(...) { LOG(logLevelDebug, "Validation of %s failed.", address); return false; } }
void ServerContextImpl::destroyAllTransports() { // not initialized yet if (!_transportRegistry.get()) { return; } std::auto_ptr<TransportRegistry::transportVector_t> transports = _transportRegistry->toArray(); if (transports.get() == 0) return; int size = (int)transports->size(); if (size == 0) return; LOG(logLevelInfo, "Server context still has %d transport(s) active and closing...", size); for (int i = 0; i < size; i++) { Transport::shared_pointer transport = (*transports)[i]; try { transport->close(); } catch (std::exception &e) { // do all exception safe, log in case of an error LOG(logLevelError, "Unhandled exception caught from client code at %s:%d: %s", __FILE__, __LINE__, e.what()); } catch (...) { // do all exception safe, log in case of an error LOG(logLevelError, "Unhandled exception caught from client code at %s:%d.", __FILE__, __LINE__); } } // now clear all (release) _transportRegistry->clear(); }
Transport::shared_pointer TransportRegistry::remove(Transport::shared_pointer const & transport) { Lock guard(_mutex); const int16 priority = transport->getPriority(); const osiSockAddr* address = transport->getRemoteAddress(); Transport::shared_pointer retTransport; transportsMap_t::iterator transportsIter = _transports.find(address); if(transportsIter != _transports.end()) { prioritiesMapSharedPtr_t priorities = transportsIter->second; prioritiesMap_t::iterator prioritiesIter = priorities->find(priority); if(prioritiesIter != priorities->end()) { retTransport = prioritiesIter->second; priorities->erase(prioritiesIter); _transportCount--; if(priorities->size() == 0) { _transports.erase(transportsIter); } } } return retTransport; }
void ResponseHandler::handleResponse(osiSockAddr* responseFrom, Transport::shared_pointer const & transport, int8 version, int8 command, size_t payloadSize, ByteBuffer* payloadBuffer) { if(_debugLevel >= 3) { // TODO make a constant of sth (0 - off, 1 - debug, 2 - more/trace, 3 - messages) 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<<" on "<<transport->getRemoteName(); hexDump(prologue.str(), _description, (const int8*)payloadBuffer->getArray(), payloadBuffer->getPosition(), static_cast<int>(payloadSize)); } }
Transport::shared_pointer BlockingTCPConnector::connect(std::tr1::shared_ptr<ClientChannelImpl> const & client, ResponseHandler::shared_pointer const & responseHandler, osiSockAddr& address, int8 transportRevision, int16 priority) { SOCKET socket = INVALID_SOCKET; char ipAddrStr[64]; ipAddrToDottedIP(&address.ia, ipAddrStr, sizeof(ipAddrStr)); Context::shared_pointer context = _context.lock(); TransportRegistry::Reservation rsvp(context->getTransportRegistry(), address, priority); // we are now blocking any connect() to this destination (address and prio) // concurrent connect() to other destination is allowed. // This prevents us from opening duplicate connections. Transport::shared_pointer transport = context->getTransportRegistry()->get(address, priority); if(transport.get()) { LOG(logLevelDebug, "Reusing existing connection to PVA server: %s.", ipAddrStr); if (transport->acquire(client)) return transport; } try { LOG(logLevelDebug, "Connecting to PVA server: %s.", ipAddrStr); socket = tryConnect(address, 3); LOG(logLevelDebug, "Socket connected to PVA server: %s.", ipAddrStr); // enable TCP_NODELAY (disable Nagle's algorithm) int optval = 1; // true int retval = ::setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(int)); if(retval<0) { char errStr[64]; epicsSocketConvertErrnoToString(errStr, sizeof(errStr)); LOG(logLevelWarn, "Error setting TCP_NODELAY: %s.", errStr); } // enable TCP_KEEPALIVE retval = ::setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(int)); if(retval<0) { char errStr[64]; epicsSocketConvertErrnoToString(errStr, sizeof(errStr)); LOG(logLevelWarn, "Error setting SO_KEEPALIVE: %s.", errStr); } // TODO tune buffer sizes?! Win32 defaults are 8k, which is OK // create transport // TODO introduce factory // get TCP send buffer size osiSocklen_t intLen = sizeof(int); int _socketSendBufferSize; retval = getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&_socketSendBufferSize, &intLen); if(retval<0) { char strBuffer[64]; epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer)); LOG(logLevelDebug, "Error getting SO_SNDBUF: %s.", strBuffer); } // create() also adds to context connection pool _context->getTransportRegistry() transport = detail::BlockingClientTCPTransportCodec::create( context, socket, responseHandler, _receiveBufferSize, _socketSendBufferSize, client, transportRevision, _heartbeatInterval, priority); // verify if(!transport->verify(5000)) { LOG( logLevelDebug, "Connection to PVA server %s failed to be validated, closing it.", ipAddrStr); std::ostringstream temp; temp<<"Failed to verify TCP connection to '"<<ipAddrStr<<"'."; THROW_BASE_EXCEPTION(temp.str().c_str()); } LOG(logLevelDebug, "Connected to PVA server: %s.", ipAddrStr); return transport; } catch(std::exception&) { if(transport.get()) transport->close(); else if(socket!=INVALID_SOCKET) epicsSocketDestroy(socket); throw; } }