Пример #1
0
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;
}
Пример #2
0
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);
}
Пример #3
0
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;
    }
}
Пример #4
0
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();

}
Пример #5
0
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;
    }
}