14 #define epicsExportSharedSymbols 29 const Version ServerContextImpl::VERSION(
"pvAccess Server",
"cpp",
30 EPICS_PVA_MAJOR_VERSION, EPICS_PVA_MINOR_VERSION, EPICS_PVA_MAINTENANCE_VERSION, EPICS_PVA_DEVELOPMENT_FLAG);
32 size_t ServerContextImpl::num_instances;
34 ServerContextImpl::ServerContextImpl():
37 _autoBeaconAddressList(
true),
47 _beaconServerStatusProvider(),
67 catch(std::exception& e)
69 std::cerr<<
"Error in: ServerContextImpl::~ServerContextImpl: "<<e.what()<<
"\n";
84 void ServerContextImpl::generateGUID()
98 if (configuration.get() == 0)
101 configuration = configurationProvider->getConfiguration(
"pvAccess-server");
102 if (configuration.get() == 0)
104 configuration = configurationProvider->getConfiguration(
"system");
107 return configuration;
113 void ServerContextImpl::loadConfiguration()
115 Configuration::const_shared_pointer config = configuration;
123 memset(&_ifaceAddr, 0,
sizeof(_ifaceAddr));
124 _ifaceAddr.
ia.sin_family = AF_INET;
125 _ifaceAddr.
ia.sin_addr.s_addr = htonl(INADDR_ANY);
126 _ifaceAddr.
ia.sin_port = 0;
127 if(!config->getPropertyAsAddress(
"EPICS_PVAS_INTF_ADDR_LIST", &_ifaceAddr) && config->hasProperty(
"EPICS_PVAS_INTF_ADDR_LIST"))
128 THROW_EXCEPTION2(std::runtime_error,
"EPICS_PVAS_INTF_ADDR_LIST contains invalid IP or non-existant hostname");
130 _beaconAddressList = config->getPropertyAsString(
"EPICS_PVA_ADDR_LIST", _beaconAddressList);
131 _beaconAddressList = config->getPropertyAsString(
"EPICS_PVAS_BEACON_ADDR_LIST", _beaconAddressList);
133 _autoBeaconAddressList = config->getPropertyAsBoolean(
"EPICS_PVA_AUTO_ADDR_LIST", _autoBeaconAddressList);
134 _autoBeaconAddressList = config->getPropertyAsBoolean(
"EPICS_PVAS_AUTO_BEACON_ADDR_LIST", _autoBeaconAddressList);
136 _beaconPeriod = config->getPropertyAsFloat(
"EPICS_PVA_BEACON_PERIOD", _beaconPeriod);
137 _beaconPeriod = config->getPropertyAsFloat(
"EPICS_PVAS_BEACON_PERIOD", _beaconPeriod);
139 _serverPort = config->getPropertyAsInteger(
"EPICS_PVA_SERVER_PORT", _serverPort);
140 _serverPort = config->getPropertyAsInteger(
"EPICS_PVAS_SERVER_PORT", _serverPort);
141 _ifaceAddr.
ia.sin_port = htons(_serverPort);
143 _broadcastPort = config->getPropertyAsInteger(
"EPICS_PVA_BROADCAST_PORT", _broadcastPort);
144 _broadcastPort = config->getPropertyAsInteger(
"EPICS_PVAS_BROADCAST_PORT", _broadcastPort);
146 _receiveBufferSize = config->getPropertyAsInteger(
"EPICS_PVA_MAX_ARRAY_BYTES", _receiveBufferSize);
147 _receiveBufferSize = config->getPropertyAsInteger(
"EPICS_PVAS_MAX_ARRAY_BYTES", _receiveBufferSize);
149 if(_channelProviders.empty()) {
158 std::set<std::string> names;
159 reg->getProviderNames(names);
160 for (std::set<std::string>::const_iterator iter = names.begin(); iter != names.end(); iter++)
162 ChannelProvider::shared_pointer channelProvider = reg->getProvider(*iter);
163 if (channelProvider) {
164 _channelProviders.push_back(channelProvider);
172 std::stringstream ss(providers);
173 std::string providerName;
174 while (std::getline(ss, providerName,
' '))
176 ChannelProvider::shared_pointer channelProvider(reg->getProvider(providerName));
177 if (channelProvider) {
178 _channelProviders.push_back(channelProvider);
180 LOG(
logLevelWarn,
"Requested provider '%s' not found", providerName.c_str());
186 if(_channelProviders.empty())
187 LOG(
logLevelError,
"ServerContext configured with no Providers will do nothing!\n");
204 else if (_ifaceList.size() == 0)
211 Configuration::shared_pointer
216 std::ostringstream providerName;
217 for(
size_t i=0;
i<_channelProviders.size();
i++) {
220 providerName<<_channelProviders[
i]->getProviderName();
223 #define SET(K, V) B.add(K, V); 228 buf[
sizeof(buf)-1] =
'\0';
229 SET(
"EPICS_PVAS_INTF_ADDR_LIST", buf);
232 SET(
"EPICS_PVAS_BEACON_ADDR_LIST", _beaconAddressList);
233 SET(
"EPICS_PVA_ADDR_LIST", _beaconAddressList);
235 SET(
"EPICS_PVAS_AUTO_BEACON_ADDR_LIST",
236 _autoBeaconAddressList ?
"YES" :
"NO");
237 SET(
"EPICS_PVA_AUTO_ADDR_LIST",
238 _autoBeaconAddressList ?
"YES" :
"NO");
252 SET(
"EPICS_PVAS_PROVIDER_NAMES", providerName.str());
262 return config->hasProperty(
"EPICS_PVAS_PROVIDER_NAMES");
276 _acceptor.reset(
new BlockingTCPAcceptor(thisServerContext, _responseHandler, _ifaceAddr, _receiveBufferSize));
277 _serverPort = ntohs(_acceptor->getBindAddress()->ia.sin_port);
281 _broadcastPort, _autoBeaconAddressList, _beaconAddressList, _ignoreAddressList);
283 _beaconEmitter.reset(
new BeaconEmitter(
"tcp", _broadcastTransport, thisServerContext));
285 _beaconEmitter->start();
297 _runEvent.
wait(seconds);
301 #define LEAK_CHECK(PTR, NAME) if((PTR) && !(PTR).unique()) { std::cerr<<"Leaking ServerContext " NAME " use_count="<<(PTR).use_count()<<"\n"<<show_referrers(PTR, false);} 312 for (BlockingUDPTransportVector::const_iterator iter = _udpTransports.begin();
313 iter != _udpTransports.end(); iter++)
315 const BlockingUDPTransport::shared_pointer& transport = *iter;
320 if(transport!=_broadcastTransport)
323 _udpTransports.clear();
328 _beaconEmitter->destroy();
330 _beaconEmitter.reset();
334 if (_broadcastTransport)
336 _broadcastTransport->close();
337 LEAK_CHECK(_broadcastTransport,
"_broadcastTransport")
338 _broadcastTransport.reset();
344 _acceptor->destroy();
350 _transportRegistry.
clear();
358 LEAK_CHECK(_responseHandler,
"_responseHandler")
359 _responseHandler.reset();
374 <<
"Active configuration (w/ defaults)\n";
377 #define SHOW(ENV) str << #ENV " = "<<conf->getPropertyAsString(#ENV, std::string())<<"\n"; 378 SHOW(EPICS_PVAS_INTF_ADDR_LIST)
379 SHOW(EPICS_PVAS_BEACON_ADDR_LIST)
380 SHOW(EPICS_PVAS_AUTO_BEACON_ADDR_LIST)
381 SHOW(EPICS_PVAS_BEACON_PERIOD)
382 SHOW(EPICS_PVAS_BROADCAST_PORT)
383 SHOW(EPICS_PVAS_SERVER_PORT)
384 SHOW(EPICS_PVAS_PROVIDER_NAMES)
391 _transportRegistry.
toArray(transports);
394 for(TransportRegistry::transportVector_t::const_iterator it(transports.begin()), end(transports.end());
397 const Transport::shared_pointer& transport(*it);
399 str<<
" "<<transport->getType()<<
"://"<<transport->getRemoteName()
400 <<
" "<<(transport->isClosed()?
"closed!":
"");
405 str<<
" ver="<<unsigned(casTransport->
getRevision())
406 <<
" "<<(casTransport ? casTransport->
getChannelCount() : size_t(-1))<<
" channels";
408 PeerInfo::const_shared_pointer peer;
414 str<<
" user: "<<peer->authority<<
"/"<<peer->account;
415 if(!peer->realm.empty())
416 str<<
"@"<<peer->realm;
417 if(lvl>=2 && !peer->roles.empty()) {
420 for(PeerInfo::roles_t::const_iterator it(peer->roles.begin()), end(peer->roles.end()); it!=end; ++it, ++n) {
426 if(lvl>=3 && peer->aux) {
427 str<<
" aux. auth.:\n";
436 if(!casTransport || lvl<2)
440 typedef std::vector<ServerChannel::shared_pointer> channels_t;
444 for(channels_t::const_iterator it(channels.begin()), end(channels.end()); it!=end; ++it)
446 const ServerChannel *channel(static_cast<const ServerChannel*>(it->get()));
447 const Channel::shared_pointer& providerChan(channel->
getChannel());
451 str<<
" "<<providerChan->getChannelName()
452 <<(providerChan->isConnected()?
"":
" closed");
455 providerChan->printInfo(str);
465 _beaconServerStatusProvider = beaconServerStatusProvider;
470 return _beaconPeriod;
475 return _receiveBufferSize;
485 return _broadcastPort;
490 return _beaconServerStatusProvider;
497 return const_cast<osiSockAddr*
>(_acceptor->getBindAddress());
504 return _broadcastTransport;
509 return _channelProviders;
519 return &_transportRegistry;
525 return Channel::shared_pointer();
531 return Transport::shared_pointer();
544 ServerContext::shared_pointer
startPVAServer(std::string
const & providerNames,
int timeToRun,
bool runInSeparateThread,
bool printInfo)
548 .add(
"EPICS_PVAS_PROVIDER_NAMES", providerNames)
555 if(!runInSeparateThread) {
558 }
else if(timeToRun!=0) {
559 LOG(
logLevelWarn,
"startPVAServer() timeToRun!=0 only supported when runInSeparateThread==false\n");
566 struct shutdown_dtor {
571 if(!wrapped.unique())
572 LOG(
logLevelWarn,
"ServerContextImpl::shutdown() doesn't break all internal ref. loops. use_count=%u\n", (
unsigned)wrapped.use_count());
581 ret->configuration = conf._conf;
582 ret->_channelProviders = conf._providers;
584 if (!ret->configuration)
587 ret->configuration = configurationProvider->getConfiguration(
"pvAccess-server");
588 if (!ret->configuration)
590 ret->configuration = configurationProvider->getConfiguration(
"system");
593 if(!ret->configuration) {
597 ret->loadConfiguration();
TransportRegistry * getTransportRegistry() OVERRIDE FINAL
LIBCOM_API void epicsStdCall epicsSocketDestroy(SOCKET s)
Configuration::shared_pointer build()
void printInfo(int lvl=0)
const Channel::shared_pointer & getChannel() const
static ChannelProviderRegistry::shared_pointer servers()
static ConfigurationProvider::shared_pointer getProvider()
LIBCOM_API void epicsStdCall epicsSignalInstallSigPipeIgnore(void)
#define THROW_EXCEPTION2(TYPE, MSG)
EPICS_ALWAYS_INLINE void putInt(int32 value)
void shutdown() OVERRIDE FINAL
Channel::shared_pointer getChannel(pvAccessID id) OVERRIDE FINAL
const osiSockAddr * getServerInetAddress()
#define SET_LOG_LEVEL(level)
shared_ptr< T > static_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
virtual Configuration::shared_pointer getCurrentConfig() OVERRIDE FINAL
epics::pvData::Timer::shared_pointer getTimer() OVERRIDE FINAL
size_t getChannelCount() const
epics::pvData::int32 getBroadcastPort() OVERRIDE FINAL
epicsShareExtern const std::string PVACCESS_DEBUG
epicsShareExtern const std::string PVACCESS_DEFAULT_PROVIDER
TODO only here because of the Lockable.
epics::pvData::int32 getServerPort() OVERRIDE FINAL
A lock for multithreading.
Transport::shared_pointer getSearchTransport() OVERRIDE FINAL
epicsTimeStamp & getStartTime() OVERRIDE FINAL
BeaconServerStatusProvider::shared_pointer getBeaconServerStatusProvider()
epics::pvData::Mutex _mutex
const BlockingUDPTransport::shared_pointer & getBroadcastTransport()
void toArray(transportVector_t &transportArray, const osiSockAddr *dest=0)
epics::pvData::Mutex _mutex
const epics::pvData::int32 PVA_SERVER_PORT
Support for delayed or periodic callback execution.
virtual const std::vector< ChannelProvider::shared_pointer > & getChannelProviders() OVERRIDE FINAL
static size_t num_instances
int32 getNanoseconds() const
ConfigurationProvider::shared_pointer configurationProvider
LIBCOM_API SOCKET epicsStdCall epicsSocketCreate(int domain, int type, int protocol)
const Version & getVersion() OVERRIDE FINAL
#define LOG(level, format,...)
epics::pvData::int32 getReceiveBufferSize()
void getChannels(std::vector< std::tr1::shared_ptr< ServerChannel > > &channels) const
epics::pvData::int8 getRevision() const
static const Version VERSION
#define LEAK_CHECK(PTR, NAME)
int epicsStdCall epicsTimeGetCurrent(epicsTimeStamp *pDest)
Get current time into *pDest.
ConfigurationBuilder & push_map()
const epics::pvData::int32 PVA_BROADCAST_PORT
This class implements a Bytebuffer that is like the java.nio.ByteBuffer.
std::vector< Transport::shared_pointer > transportVector_t
const std::string getVersionString() const
LIBCOM_API void epicsStdCall epicsSignalInstallSigAlarmIgnore(void)
const ServerGUID & getGUID() OVERRIDE FINAL
void setBeaconServerStatusProvider(BeaconServerStatusProvider::shared_pointer const &beaconServerStatusProvider) OVERRIDE FINAL
void initializeUDPTransports(bool serverFlag, BlockingUDPTransportVector &udpTransports, const IfaceNodeVector &ifaceList, const ResponseHandler::shared_pointer &responseHandler, BlockingUDPTransport::shared_pointer &sendTransport, int32 &listenPort, bool autoAddressList, const std::string &addressList, const std::string &ignoreAddressList)
ServerContextImpl::shared_pointer wrapped
virtual void newServerDetected() OVERRIDE FINAL
bool isChannelProviderNamePreconfigured()
epicsShareFunc ServerContext::shared_pointer startPVAServer(std::string const &providerNames=PVACCESS_ALL_PROVIDERS, int timeToRun=0, bool runInSeparateThread=false, bool printInfo=false)
ConfigurationBuilder & push_env()
#define THROW_BASE_EXCEPTION(msg)
EPICS time stamp, for use from C code.
PeerInfo::const_shared_pointer _peerInfo
friend class ServerContext
void run(epics::pvData::uint32 seconds) OVERRIDE FINAL
Options for a server insatnce.
static ServerContext::shared_pointer create(const Config &conf=Config())
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
virtual ~ServerContextImpl()
std::tr1::shared_ptr< BeaconServerStatusProvider > shared_pointer
OS-independent routines for ignoring Posix signals.
epicsShareExtern const std::string PVACCESS_ALL_PROVIDERS
void printInfo(std::ostream &str, int lvl) OVERRIDE FINAL
int64 getSecondsPastEpoch() const
const epics::pvData::int32 MAX_TCP_RECV
EPICS_ALWAYS_INLINE void putLong(int64 value)
int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *pMatchAddr)
std::tr1::shared_ptr< ServerContextImpl > shared_pointer
Configuration::const_shared_pointer getConfiguration() OVERRIDE FINAL
Methods for manipulating timeStamp.
unsigned epicsStdCall ipAddrToDottedIP(const struct sockaddr_in *paddr, char *pBuf, unsigned bufSize)