Ejemplo n.º 1
0
/**
 * Load configuration.
 */
void ServerContextImpl::loadConfiguration()
{
    Configuration::shared_pointer config = getConfiguration();

    // TODO for now just a simple switch
    int32 debugLevel = config->getPropertyAsInteger(PVACCESS_DEBUG, 0);
    if (debugLevel > 0)
        SET_LOG_LEVEL(logLevelDebug);

    // TODO multiple addresses
    _ifaceAddr.ia.sin_family = AF_INET;
    _ifaceAddr.ia.sin_addr.s_addr = htonl(INADDR_ANY);
    _ifaceAddr.ia.sin_port = 0;
    config->getPropertyAsAddress("EPICS_PVAS_INTF_ADDR_LIST", &_ifaceAddr);

    _beaconAddressList = config->getPropertyAsString("EPICS_PVA_ADDR_LIST", _beaconAddressList);
    _beaconAddressList = config->getPropertyAsString("EPICS_PVAS_BEACON_ADDR_LIST", _beaconAddressList);

    _autoBeaconAddressList = config->getPropertyAsBoolean("EPICS_PVA_AUTO_ADDR_LIST", _autoBeaconAddressList);
    _autoBeaconAddressList = config->getPropertyAsBoolean("EPICS_PVAS_AUTO_BEACON_ADDR_LIST", _autoBeaconAddressList);

    _beaconPeriod = config->getPropertyAsFloat("EPICS_PVA_BEACON_PERIOD", _beaconPeriod);
    _beaconPeriod = config->getPropertyAsFloat("EPICS_PVAS_BEACON_PERIOD", _beaconPeriod);

    _serverPort = config->getPropertyAsInteger("EPICS_PVA_SERVER_PORT", _serverPort);
    _serverPort = config->getPropertyAsInteger("EPICS_PVAS_SERVER_PORT", _serverPort);
    _ifaceAddr.ia.sin_port = htons(_serverPort);

    _broadcastPort = config->getPropertyAsInteger("EPICS_PVA_BROADCAST_PORT", _broadcastPort);
    _broadcastPort = config->getPropertyAsInteger("EPICS_PVAS_BROADCAST_PORT", _broadcastPort);

    _receiveBufferSize = config->getPropertyAsInteger("EPICS_PVA_MAX_ARRAY_BYTES", _receiveBufferSize);
    _receiveBufferSize = config->getPropertyAsInteger("EPICS_PVAS_MAX_ARRAY_BYTES", _receiveBufferSize);

    _channelProviderNames = config->getPropertyAsString("EPICS_PVA_PROVIDER_NAMES", _channelProviderNames);
    _channelProviderNames = config->getPropertyAsString("EPICS_PVAS_PROVIDER_NAMES", _channelProviderNames);

    //
    // introspect network interfaces
    //

    SOCKET sock = epicsSocketCreate(AF_INET, SOCK_STREAM, 0);
    if (!sock) {
        THROW_BASE_EXCEPTION("Failed to create a socket needed to introspect network interfaces.");
    }

    if (discoverInterfaces(_ifaceList, sock, &_ifaceAddr))
    {
        THROW_BASE_EXCEPTION("Failed to introspect network interfaces.");
    }
    else if (_ifaceList.size() == 0)
    {
        THROW_BASE_EXCEPTION("No (specified) network interface(s) available.");
    }
    epicsSocketDestroy(sock);
}
Ejemplo n.º 2
0
void ServerContextImpl::run(int32 seconds)
{
    if (seconds < 0)
    {
        THROW_BASE_EXCEPTION("seconds cannot be negative.");
    }

    {
        Lock guard(_mutex);

        if (_state == NOT_INITIALIZED)
        {
            THROW_BASE_EXCEPTION("Context not initialized.");
        }
        else if (_state == DESTROYED)
        {
            THROW_BASE_EXCEPTION("Context destroyed.");
        }
        else if (_state == RUNNING)
        {
            THROW_BASE_EXCEPTION("Context is already running.");
        }
        else if (_state == SHUTDOWN)
        {
            THROW_BASE_EXCEPTION("Context was shutdown.");
        }

        _state = RUNNING;
    }

    // run...
    _beaconEmitter->start();

    //TODO review this
    if(seconds == 0)
    {
        _runEvent.wait();
    }
    else
    {
        _runEvent.wait(seconds);
    }

    {
        Lock guard(_mutex);
        _state = SHUTDOWN;
    }
}
Ejemplo n.º 3
0
void Properties::store()
{
#ifdef NO_STREAM_EXCEPTIONS
	_outfile->open(_fileName.c_str(),ifstream::trunc);
	if (_outfile->fail())
#else
	try
	{
		_outfile->open(_fileName.c_str(),ifstream::trunc);
	}
	catch (ofstream::failure& e)
#endif
	{
		string errMsg = "Error opening file: " + string(_fileName.c_str());
		THROW_BASE_EXCEPTION(errMsg.c_str());
	}


	for (std::map<std::string,std::string>::iterator propertiesIterator = _properties.begin();
			propertiesIterator != _properties.end();
			propertiesIterator++ )
	{
#ifndef NO_STREAM_EXCEPTIONS
		try
		{
#endif
			string line = string(propertiesIterator->first) + string("=") + string(propertiesIterator->second) + string("\n");
			_outfile->write(line.c_str(),line.length());
#ifdef NO_STREAM_EXCEPTIONS
			if(_outfile->fail())
#else
		}
		catch (ofstream::failure& e)
#endif
		{
			_outfile->close();
			string errMsg = "Error writing to file: " + string(_fileName.c_str());
			THROW_BASE_EXCEPTION(errMsg.c_str());
		}
	}
	_outfile->close();
}
Ejemplo n.º 4
0
void ConfigurationProviderImpl::registerConfiguration(const string &name, Configuration::shared_pointer const & configuration)
{
	Lock guard(_mutex);
	std::map<std::string,Configuration::shared_pointer>::iterator configsIter = _configs.find(name);
	if(configsIter != _configs.end())
	{
		string msg = "configuration with name " + name + " already registered";
		THROW_BASE_EXCEPTION(msg.c_str());
	}
	_configs[name] = configuration;
}
Ejemplo n.º 5
0
void ServerContextImpl::shutdown()
{
    Lock guard(_mutex);
    if(_state == DESTROYED)
    {
        THROW_BASE_EXCEPTION("Context already destroyed.");
    }

    // notify to stop running...
    _runEvent.signal();
}
Ejemplo n.º 6
0
string Properties::getProperty(const string &key)
{
	std::map<std::string,std::string>::iterator propertiesIterator = _properties.find(key);
	if(propertiesIterator != _properties.end()) //found in map
	{
		return string(propertiesIterator->second);
	}
	else
	{
		string errMsg = "Property not found in the map: " + key;
		THROW_BASE_EXCEPTION(errMsg.c_str());
	}
}
Ejemplo n.º 7
0
 std::size_t SerializeHelper::readSize(ByteBuffer* buffer,
         DeserializableControl* control) {
     control->ensureData(1);
     int8 b = buffer->getByte();
     if(b==-1)
         return -1;
     else if(b==-2) {
         control->ensureData(sizeof(int32));
         int32 s = buffer->getInt();
         if(s<0) THROW_BASE_EXCEPTION("negative size");
         return s;
     }
     else
         return (std::size_t)(b<0 ? b+256 : b);
 }
Ejemplo n.º 8
0
void Properties::load()
{
	_properties.clear();

#ifdef NO_STREAM_EXCEPTIONS
	_infile->open(_fileName.c_str(),ifstream::in);
	if (_infile->fail())
#else
	try
	{
		_infile->open(_fileName.c_str(),ifstream::in);
	}
	catch (ifstream::failure& e)
#endif
	{
		string errMsg = "Error opening file: " + string(_fileName.c_str());
		THROW_BASE_EXCEPTION(errMsg.c_str());
	}

	string line;
	string property;
	string key;
#ifndef NO_STREAM_EXCEPTIONS
	try
	{
#endif
		while(!_infile->eof())
		{
			line.erase();
			std::getline(*_infile,line);

#ifdef NO_STREAM_EXCEPTIONS
			if (_infile->fail())
			{
				_infile->close();
				if(_infile->eof())
				{
					return; //end of file
				}
				string errMsg = "Error reading file: " + _fileName;
				THROW_BASE_EXCEPTION(errMsg.c_str());
			}
#endif

			//remove trailing spaces
			truncate(line);

			//empty line
			if(line.length() == 0)
			{
				continue;
			}
			// comment
			if(line[0] == '#')
			{
				continue;
			}

			//line is in format: propertyName=propertyValue
			size_t pos = line.find_first_of('=',0);
			if(pos == string::npos) //bad value (= not found)
			{
				string errMsg = "Bad property line found: " + line;
				THROW_BASE_EXCEPTION(errMsg.c_str());
			}

			key = line.substr(0,pos);
			truncate(key);
			property = line.substr(pos + 1,line.length());
			truncate(property);
			_properties[key] = property;
		}
#ifndef NO_STREAM_EXCEPTIONS
	}
	catch (ifstream::failure& e)
	{
		_infile->close();
		if(_infile->eof())
		{
			return; //end of file
		}
		string errMsg = "Error reading file: " + _fileName;
		THROW_BASE_EXCEPTION(errMsg.c_str());
	}
#endif
	_infile->close();
}
Ejemplo n.º 9
0
int BlockingTCPAcceptor::initialize() {

    char ipAddrStr[48];
    ipAddrToDottedIP(&_bindAddress.ia, ipAddrStr, sizeof(ipAddrStr));

    int tryCount = 0;
    while(tryCount<2) {
        char strBuffer[64];

        LOG(logLevelDebug, "Creating acceptor to %s.", ipAddrStr);

        _serverSocketChannel = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if(_serverSocketChannel==INVALID_SOCKET) {
            epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
            ostringstream temp;
            temp<<"Socket create error: "<<strBuffer;
            LOG(logLevelError, "%s", temp.str().c_str());
            THROW_BASE_EXCEPTION(temp.str().c_str());
        }
        else {

            //epicsSocketEnableAddressReuseDuringTimeWaitState(_serverSocketChannel);

            // try to bind
            int retval = ::bind(_serverSocketChannel, &_bindAddress.sa, sizeof(sockaddr));
            if(retval<0) {
                epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
                LOG(logLevelDebug, "Socket bind error: %s.", strBuffer);
                if(_bindAddress.ia.sin_port!=0) {
                    // failed to bind to specified bind address,
                    // try to get port dynamically, but only once
                    LOG(
                        logLevelDebug,
                        "Configured TCP port %d is unavailable, trying to assign it dynamically.",
                        ntohs(_bindAddress.ia.sin_port));
                    _bindAddress.ia.sin_port = htons(0);
                }
                else {
                    epicsSocketDestroy(_serverSocketChannel);
                    break; // exit while loop
                }
            }
            else { // if(retval<0)
                // bind succeeded

                // update bind address, if dynamically port selection was used
                if(ntohs(_bindAddress.ia.sin_port)==0) {
                    osiSocklen_t sockLen = sizeof(sockaddr);
                    // read the actual socket info
                    retval = ::getsockname(_serverSocketChannel, &_bindAddress.sa, &sockLen);
                    if(retval<0) {
                        // error obtaining port number
                        epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
                        LOG(logLevelDebug, "getsockname error: %s", strBuffer);
                    }
                    else {
                        LOG(
                            logLevelInfo,
                            "Using dynamically assigned TCP port %d.",
                            ntohs(_bindAddress.ia.sin_port));
                    }
                }

                retval = ::listen(_serverSocketChannel, 4);
                if(retval<0) {
                    epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
                    ostringstream temp;
                    temp<<"Socket listen error: "<<strBuffer;
                    LOG(logLevelError, "%s", temp.str().c_str());
                    THROW_BASE_EXCEPTION(temp.str().c_str());
                }

                _thread.start();

                // all OK, return
                return ntohs(_bindAddress.ia.sin_port);
            } // successful bind
        } // successfully obtained socket
        tryCount++;
    } // while

    ostringstream temp;
    temp<<"Failed to create acceptor to "<<ipAddrStr;
    THROW_BASE_EXCEPTION(temp.str().c_str());
}
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;
    }
}
Ejemplo n.º 11
0
void ServerContextImpl::initialize(ChannelProviderRegistry::shared_pointer const & channelProviderRegistry)
{
    Lock guard(_mutex);
    if (!channelProviderRegistry.get())
    {
        THROW_BASE_EXCEPTION("channelProviderRegistry == NULL");
    }

    if (_state == DESTROYED)
    {
        THROW_BASE_EXCEPTION("Context destroyed.");
    }
    else if (_state != NOT_INITIALIZED)
    {
        THROW_BASE_EXCEPTION("Context already initialized.");
    }

    _channelProviderRegistry = channelProviderRegistry;


    // user all providers
    if (_channelProviderNames == PVACCESS_ALL_PROVIDERS)
    {
        _channelProviderNames.resize(0); // VxWorks 5.5 omits clear()

        std::auto_ptr<ChannelProviderRegistry::stringVector_t> names = _channelProviderRegistry->getProviderNames();
        for (ChannelProviderRegistry::stringVector_t::iterator iter = names->begin(); iter != names->end(); iter++)
        {
            ChannelProvider::shared_pointer channelProvider = _channelProviderRegistry->getProvider(*iter);
            if (channelProvider)
            {
                _channelProviders.push_back(channelProvider);

                // compile a list
                if (!_channelProviderNames.empty())
                    _channelProviderNames += ' ';
                _channelProviderNames += *iter;
            }
        }
    }
    else
    {
        // split space separated names
        std::stringstream ss(_channelProviderNames);
        std::string providerName;
        while (std::getline(ss, providerName, ' '))
        {
            ChannelProvider::shared_pointer channelProvider = _channelProviderRegistry->getProvider(providerName);
            if (channelProvider)
                _channelProviders.push_back(channelProvider);
        }
    }

    //_channelProvider = _channelProviderRegistry->getProvider(_channelProviderNames);
    if (_channelProviders.size() == 0)
    {
        std::string msg = "None of the specified channel providers are available: " + _channelProviderNames + ".";
        THROW_BASE_EXCEPTION(msg.c_str());
    }

    internalInitialize();

    _state = INITIALIZED;
}