diff --git a/pvAccessCPP.files b/pvAccessCPP.files index 04ecb7c..19574db 100644 --- a/pvAccessCPP.files +++ b/pvAccessCPP.files @@ -237,3 +237,308 @@ testApp/utils/testInetAddressUtils.cpp testApp/utils/transportRegistryTest.cpp src/remote/security.h src/remote/security.cpp +include/pv/baseChannelRequester.h +include/pv/beaconEmitter.h +include/pv/beaconHandler.h +include/pv/beaconServerStatusProvider.h +include/pv/blockingTCP.h +include/pv/blockingUDP.h +include/pv/caChannel.h +include/pv/caProvider.h +include/pv/channelSearchManager.h +include/pv/clientContextImpl.h +include/pv/clientFactory.h +include/pv/codec.h +include/pv/configuration.h +include/pv/hexDump.h +include/pv/inetAddressUtil.h +include/pv/introspectionRegistry.h +include/pv/likely.h +include/pv/logger.h +include/pv/namedLockPattern.h +include/pv/pvAccess.h +include/pv/pvAccessMB.h +include/pv/pvaConstants.h +include/pv/pvaVersion.h +include/pv/referenceCountingLock.h +include/pv/remote.h +include/pv/responseHandlers.h +include/pv/rpcClient.h +include/pv/rpcServer.h +include/pv/rpcService.h +include/pv/security.h +include/pv/serializationHelper.h +include/pv/serverChannelImpl.h +include/pv/serverContext.h +include/pv/simpleChannelSearchManagerImpl.h +include/pv/syncChannelFind.h +include/pv/transportRegistry.h +include/pv/wildcard.h +pvtoolsSrc/eget.cpp +pvtoolsSrc/pvget.cpp +pvtoolsSrc/pvinfo.cpp +pvtoolsSrc/pvput.cpp +pvtoolsSrc/pvutils.cpp +pvtoolsSrc/pvutils.h +src/ca/caChannel.cpp +src/ca/caChannel.h +src/ca/caProvider.cpp +src/ca/caProvider.h +src/client/pvAccess.cpp +src/client/pvAccess.h +src/factory/ChannelAccessFactory.cpp +src/mb/pvAccessMB.cpp +src/mb/pvAccessMB.h +src/pva/clientFactory.cpp +src/pva/clientFactory.h +src/pva/pvaConstants.h +src/pva/pvaVersion.cpp +src/pva/pvaVersion.h +src/remote/abstractResponseHandler.cpp +src/remote/beaconHandler.cpp +src/remote/beaconHandler.h +src/remote/blockingTCP.h +src/remote/blockingTCPAcceptor.cpp +src/remote/blockingTCPConnector.cpp +src/remote/blockingUDP.h +src/remote/blockingUDPConnector.cpp +src/remote/blockingUDPTransport.cpp +src/remote/channelSearchManager.h +src/remote/codec.cpp +src/remote/codec.h +src/remote/remote.h +src/remote/security.cpp +src/remote/security.h +src/remote/serializationHelper.cpp +src/remote/serializationHelper.h +src/remote/simpleChannelSearchManagerImpl.cpp +src/remote/simpleChannelSearchManagerImpl.h +src/remote/transportRegistry.cpp +src/remote/transportRegistry.h +src/remoteClient/clientContextImpl.cpp +src/remoteClient/clientContextImpl.h +src/rpcClient/rpcClient.cpp +src/rpcClient/rpcClient.h +src/rpcService/rpcServer.cpp +src/rpcService/rpcServer.h +src/rpcService/rpcService.cpp +src/rpcService/rpcService.h +src/server/baseChannelRequester.cpp +src/server/baseChannelRequester.h +src/server/beaconEmitter.cpp +src/server/beaconEmitter.h +src/server/beaconServerStatusProvider.cpp +src/server/beaconServerStatusProvider.h +src/server/responseHandlers.cpp +src/server/responseHandlers.h +src/server/serverChannelImpl.cpp +src/server/serverChannelImpl.h +src/server/serverContext.cpp +src/server/serverContext.h +src/utils/configuration.cpp +src/utils/configuration.h +src/utils/hexDump.cpp +src/utils/hexDump.h +src/utils/inetAddressUtil.cpp +src/utils/inetAddressUtil.h +src/utils/introspectionRegistry.cpp +src/utils/introspectionRegistry.h +src/utils/likely.h +src/utils/logger.cpp +src/utils/logger.h +src/utils/namedLockPattern.h +src/utils/referenceCountingLock.cpp +src/utils/referenceCountingLock.h +src/utils/wildcard.cpp +src/utils/wildcard.h +src/v3ioc/PVAClientRegister.cpp +src/v3ioc/PVAServerRegister.cpp +src/v3ioc/syncChannelFind.h +testApp/client/MockClientImpl.cpp +testApp/client/testChannelAccessFactory.cpp +testApp/client/testMockClient.cpp +testApp/client/testStartStop.cpp +testApp/remote/channelAccessIFTest.cpp +testApp/remote/channelAccessIFTest.h +testApp/remote/epicsv4Grayscale.h +testApp/remote/rpcClientExample.cpp +testApp/remote/rpcServiceExample.cpp +testApp/remote/syncTestRequesters.h +testApp/remote/testADCSim.cpp +testApp/remote/testBeaconEmitter.cpp +testApp/remote/testBeaconHandler.cpp +testApp/remote/testBlockingTCPClnt.cpp +testApp/remote/testBlockingTCPSrv.cpp +testApp/remote/testBlockingUDPClnt.cpp +testApp/remote/testBlockingUDPSrv.cpp +testApp/remote/testChannelAccess.cpp +testApp/remote/testChannelConnect.cpp +testApp/remote/testChannelSearchManager.cpp +testApp/remote/testCodec.cpp +testApp/remote/testGetPerformance.cpp +testApp/remote/testMonitorPerformance.cpp +testApp/remote/testNTImage.cpp +testApp/remote/testRemoteClientImpl.cpp +testApp/remote/testServer.cpp +testApp/remote/testServerContext.cpp +testApp/utils/configurationTest.cpp +testApp/utils/introspectionRegistryTest.cpp +testApp/utils/loggerTest.cpp +testApp/utils/namedLockPatternTest.cpp +testApp/utils/testAtomicBoolean.cpp +testApp/utils/testHexDump.cpp +testApp/utils/testInetAddressUtils.cpp +testApp/utils/transportRegistryTest.cpp +include/pv/baseChannelRequester.h +include/pv/beaconEmitter.h +include/pv/beaconHandler.h +include/pv/beaconServerStatusProvider.h +include/pv/blockingTCP.h +include/pv/blockingUDP.h +include/pv/caChannel.h +include/pv/caProvider.h +include/pv/channelSearchManager.h +include/pv/clientContextImpl.h +include/pv/clientFactory.h +include/pv/codec.h +include/pv/configuration.h +include/pv/hexDump.h +include/pv/inetAddressUtil.h +include/pv/introspectionRegistry.h +include/pv/likely.h +include/pv/logger.h +include/pv/namedLockPattern.h +include/pv/pvAccess.h +include/pv/pvAccessMB.h +include/pv/pvaConstants.h +include/pv/pvaVersion.h +include/pv/referenceCountingLock.h +include/pv/remote.h +include/pv/responseHandlers.h +include/pv/rpcClient.h +include/pv/rpcServer.h +include/pv/rpcService.h +include/pv/security.h +include/pv/serializationHelper.h +include/pv/serverChannelImpl.h +include/pv/serverContext.h +include/pv/simpleChannelSearchManagerImpl.h +include/pv/syncChannelFind.h +include/pv/transportRegistry.h +include/pv/wildcard.h +pvtoolsSrc/eget.cpp +pvtoolsSrc/pvget.cpp +pvtoolsSrc/pvinfo.cpp +pvtoolsSrc/pvput.cpp +pvtoolsSrc/pvutils.cpp +pvtoolsSrc/pvutils.h +src/ca/caChannel.cpp +src/ca/caChannel.h +src/ca/caProvider.cpp +src/ca/caProvider.h +src/client/pvAccess.cpp +src/client/pvAccess.h +src/factory/ChannelAccessFactory.cpp +src/mb/pvAccessMB.cpp +src/mb/pvAccessMB.h +src/pva/clientFactory.cpp +src/pva/clientFactory.h +src/pva/pvaConstants.h +src/pva/pvaVersion.cpp +src/pva/pvaVersion.h +src/remote/abstractResponseHandler.cpp +src/remote/beaconHandler.cpp +src/remote/beaconHandler.h +src/remote/blockingTCP.h +src/remote/blockingTCPAcceptor.cpp +src/remote/blockingTCPConnector.cpp +src/remote/blockingUDP.h +src/remote/blockingUDPConnector.cpp +src/remote/blockingUDPTransport.cpp +src/remote/channelSearchManager.h +src/remote/codec.cpp +src/remote/codec.h +src/remote/remote.h +src/remote/security.cpp +src/remote/security.h +src/remote/serializationHelper.cpp +src/remote/serializationHelper.h +src/remote/simpleChannelSearchManagerImpl.cpp +src/remote/simpleChannelSearchManagerImpl.h +src/remote/transportRegistry.cpp +src/remote/transportRegistry.h +src/remoteClient/clientContextImpl.cpp +src/remoteClient/clientContextImpl.h +src/rpcClient/rpcClient.cpp +src/rpcClient/rpcClient.h +src/rpcService/rpcServer.cpp +src/rpcService/rpcServer.h +src/rpcService/rpcService.cpp +src/rpcService/rpcService.h +src/server/baseChannelRequester.cpp +src/server/baseChannelRequester.h +src/server/beaconEmitter.cpp +src/server/beaconEmitter.h +src/server/beaconServerStatusProvider.cpp +src/server/beaconServerStatusProvider.h +src/server/responseHandlers.cpp +src/server/responseHandlers.h +src/server/serverChannelImpl.cpp +src/server/serverChannelImpl.h +src/server/serverContext.cpp +src/server/serverContext.h +src/utils/configuration.cpp +src/utils/configuration.h +src/utils/hexDump.cpp +src/utils/hexDump.h +src/utils/inetAddressUtil.cpp +src/utils/inetAddressUtil.h +src/utils/introspectionRegistry.cpp +src/utils/introspectionRegistry.h +src/utils/likely.h +src/utils/logger.cpp +src/utils/logger.h +src/utils/namedLockPattern.h +src/utils/referenceCountingLock.cpp +src/utils/referenceCountingLock.h +src/utils/wildcard.cpp +src/utils/wildcard.h +src/v3ioc/PVAClientRegister.cpp +src/v3ioc/PVAServerRegister.cpp +src/v3ioc/syncChannelFind.h +testApp/client/MockClientImpl.cpp +testApp/client/testChannelAccessFactory.cpp +testApp/client/testMockClient.cpp +testApp/client/testStartStop.cpp +testApp/remote/channelAccessIFTest.cpp +testApp/remote/channelAccessIFTest.h +testApp/remote/epicsv4Grayscale.h +testApp/remote/rpcClientExample.cpp +testApp/remote/rpcServiceExample.cpp +testApp/remote/rpcWildServiceExample.cpp +testApp/remote/syncTestRequesters.h +testApp/remote/testADCSim.cpp +testApp/remote/testBeaconEmitter.cpp +testApp/remote/testBeaconHandler.cpp +testApp/remote/testBlockingTCPClnt.cpp +testApp/remote/testBlockingTCPSrv.cpp +testApp/remote/testBlockingUDPClnt.cpp +testApp/remote/testBlockingUDPSrv.cpp +testApp/remote/testChannelAccess.cpp +testApp/remote/testChannelConnect.cpp +testApp/remote/testChannelSearchManager.cpp +testApp/remote/testCodec.cpp +testApp/remote/testGetPerformance.cpp +testApp/remote/testMonitorPerformance.cpp +testApp/remote/testNTImage.cpp +testApp/remote/testRemoteClientImpl.cpp +testApp/remote/testServer.cpp +testApp/remote/testServerContext.cpp +testApp/utils/configurationTest.cpp +testApp/utils/introspectionRegistryTest.cpp +testApp/utils/loggerTest.cpp +testApp/utils/namedLockPatternTest.cpp +testApp/utils/testAtomicBoolean.cpp +testApp/utils/testHexDump.cpp +testApp/utils/testInetAddressUtils.cpp +testApp/utils/transportRegistryTest.cpp diff --git a/src/rpcService/rpcServer.cpp b/src/rpcService/rpcServer.cpp index f74d0ae..d356ab7 100644 --- a/src/rpcService/rpcServer.cpp +++ b/src/rpcService/rpcServer.cpp @@ -5,9 +5,12 @@ */ #include +#include +#include #define epicsExportSharedSymbols #include +#include using namespace epics::pvData; using std::string; @@ -362,14 +365,15 @@ public: virtual void cancel() {} virtual void destroy() {} - + virtual ChannelFind::shared_pointer channelFind(std::string const & channelName, ChannelFindRequester::shared_pointer const & channelFindRequester) { bool found; { Lock guard(m_mutex); - found = (m_services.find(channelName) != m_services.end()); + found = (m_services.find(channelName) != m_services.end()) || + findWildService(channelName); } ChannelFind::shared_pointer thisPtr(shared_from_this()); channelFindRequester->channelFindResult(Status::Ok, thisPtr, found); @@ -403,13 +407,21 @@ public: ChannelRequester::shared_pointer const & channelRequester, short /*priority*/) { + RPCService::shared_pointer service; + RPCServiceMap::const_iterator iter; { Lock guard(m_mutex); iter = m_services.find(channelName); } - - if (iter == m_services.end()) + if (iter != m_services.end()) + service = iter->second; + + // check for wild services + if (!service) + service = findWildService(channelName); + + if (!service) { Channel::shared_pointer nullChannel; channelRequester->channelCreated(noSuchChannelStatus, nullChannel); @@ -422,7 +434,7 @@ public: shared_from_this(), channelName, channelRequester, - iter->second)); + service)); Channel::shared_pointer rpcChannel = tp; channelRequester->channelCreated(Status::Ok, rpcChannel); return rpcChannel; @@ -442,17 +454,58 @@ public: { Lock guard(m_mutex); m_services[serviceName] = service; + + if (isWildcardPattern(serviceName)) + m_wildServices.push_back(std::make_pair(serviceName, service)); } void unregisterService(std::string const & serviceName) { Lock guard(m_mutex); m_services.erase(serviceName); + + if (isWildcardPattern(serviceName)) + { + for (RPCWildServiceList::iterator iter = m_wildServices.begin(); + iter != m_wildServices.end(); + iter++) + if (iter->first == serviceName) + { + m_wildServices.erase(iter); + break; + } + } } private: + // assumes sync on services + RPCService::shared_pointer findWildService(string const & wildcard) + { + if (!m_wildServices.empty()) + for (RPCWildServiceList::iterator iter = m_wildServices.begin(); + iter != m_wildServices.end(); + iter++) + if (Wildcard::wildcardfit(iter->first.c_str(), wildcard.c_str())) + return iter->second; + + return RPCService::shared_pointer(); + } + + // (too) simple check + bool isWildcardPattern(string const & pattern) + { + return + (pattern.find('*') != string::npos || + pattern.find('?') != string::npos || + (pattern.find('[') != string::npos && pattern.find(']') != string::npos)); + } + typedef std::map RPCServiceMap; RPCServiceMap m_services; + + typedef std::vector > RPCWildServiceList; + RPCWildServiceList m_wildServices; + epics::pvData::Mutex m_mutex; }; diff --git a/src/utils/Makefile b/src/utils/Makefile index a5d0ac9..f7e163c 100644 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -10,6 +10,7 @@ INC += namedLockPattern.h INC += referenceCountingLock.h INC += configuration.h INC += likely.h +INC += wildcard.h LIBSRCS += hexDump.cpp LIBSRCS += inetAddressUtil.cpp @@ -17,3 +18,4 @@ LIBSRCS += logger.cpp LIBSRCS += introspectionRegistry.cpp LIBSRCS += configuration.cpp LIBSRCS += referenceCountingLock.cpp +LIBSRCS += wildcard.cpp diff --git a/src/utils/wildcard.cpp b/src/utils/wildcard.cpp new file mode 100644 index 0000000..fe4c66a --- /dev/null +++ b/src/utils/wildcard.cpp @@ -0,0 +1,168 @@ +/******************************************************************* + * This implementation was adpoted from: + * + * Copyright (C) 1996, 1997, 1998, 1999, 2000 Florian Schintke + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307 USA + * + * F.Schintke, the author of the original code, has authorized to + * distribute these files under LGPL License. + * + * ---------------------- + * Implementation of the UN*X wildcards + * Supported wild-characters: '*', '?'; sets: [a-z], '!' negation + * Examples: + * '[a-g]l*i?n' matches 'florian' + * '[!abc]*e' matches 'smile' + * '[-z] matches 'a' + * + */ + +#define epicsExportSharedSymbols +#include + +using namespace epics::pvAccess; + +int +Wildcard::wildcardfit (const char *wildcard, const char *test) +{ + int fit = 1; + + for (; ('\000' != *wildcard) && (1 == fit) && ('\000' != *test); wildcard++) + { + switch (*wildcard) + { + case '[': + wildcard++; /* leave out the opening square bracket */ + fit = set (&wildcard, &test); + /* we don't need to decrement the wildcard as in case */ + /* of asterisk because the closing ] is still there */ + break; + case '?': + test++; + break; + case '*': + fit = asterisk (&wildcard, &test); + /* the asterisk was skipped by asterisk() but the loop will */ + /* increment by itself. So we have to decrement */ + wildcard--; + break; + default: + fit = (int) (*wildcard == *test); + test++; + } + } + while ((*wildcard == '*') && (1 == fit)) + /* here the teststring is empty otherwise you cannot */ + /* leave the previous loop */ + wildcard++; + return (int) ((1 == fit) && ('\0' == *test) && ('\0' == *wildcard)); +} + +int +Wildcard::set (const char **wildcard, const char **test) +{ + int fit = 0; + int negation = 0; + int at_beginning = 1; + + if ('!' == **wildcard) + { + negation = 1; + (*wildcard)++; + } + while ((']' != **wildcard) || (1 == at_beginning)) + { + if (0 == fit) + { + if (('-' == **wildcard) + && ((*(*wildcard - 1)) < (*(*wildcard + 1))) + && (']' != *(*wildcard + 1)) + && (0 == at_beginning)) + { + if (((**test) >= (*(*wildcard - 1))) + && ((**test) <= (*(*wildcard + 1)))) + { + fit = 1; + (*wildcard)++; + } + } + else if ((**wildcard) == (**test)) + { + fit = 1; + } + } + (*wildcard)++; + at_beginning = 0; + } + if (1 == negation) + /* change from zero to one and vice versa */ + fit = 1 - fit; + if (1 == fit) + (*test)++; + + return (fit); +} + +int +Wildcard::asterisk (const char **wildcard, const char **test) +{ + /* Warning: uses multiple returns */ + int fit = 1; + + /* erase the leading asterisk */ + (*wildcard)++; + while (('\000' != (**test)) + && (('?' == **wildcard) + || ('*' == **wildcard))) + { + if ('?' == **wildcard) + (*test)++; + (*wildcard)++; + } + /* Now it could be that test is empty and wildcard contains */ + /* aterisks. Then we delete them to get a proper state */ + while ('*' == (**wildcard)) + (*wildcard)++; + + if (('\0' == (**test)) && ('\0' != (**wildcard))) + return (fit = 0); + if (('\0' == (**test)) && ('\0' == (**wildcard))) + return (fit = 1); + else + { + /* Neither test nor wildcard are empty! */ + /* the first character of wildcard isn't in [*?] */ + if (0 == wildcardfit(*wildcard, (*test))) + { + do + { + (*test)++; + /* skip as much characters as possible in the teststring */ + /* stop if a character match occurs */ + while (((**wildcard) != (**test)) + && ('[' != (**wildcard)) + && ('\0' != (**test))) + (*test)++; + } + while ((('\0' != **test))? + (0 == wildcardfit (*wildcard, (*test))) + : (0 != (fit = 0))); + } + if (('\0' == **test) && ('\0' == **wildcard)) + fit = 1; + return (fit); + } +} diff --git a/src/utils/wildcard.h b/src/utils/wildcard.h new file mode 100644 index 0000000..bc68bf8 --- /dev/null +++ b/src/utils/wildcard.h @@ -0,0 +1,83 @@ +/******************************************************************* + * This implementation was adpoted from: + * + * Copyright (C) 1996, 1997, 1998, 1999, 2000 Florian Schintke + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307 USA + * + * F.Schintke, the author of the original code, has authorized to + * distribute these files under LGPL License. + * + * ---------------------- + * Implementation of the UN*X wildcards + * Supported wild-characters: '*', '?'; sets: [a-z], '!' negation + * Examples: + * '[a-g]l*i?n' matches 'florian' + * '[!abc]*e' matches 'smile' + * '[-z] matches 'a' + * + */ + +#ifndef WILDCARD_H +#define WILDCARD_H + +#include + +namespace epics { namespace pvAccess { + +/** + * Class which implements UNIX style wildcards and tests to see + * if strings match the wildcard. + */ +class epicsShareClass Wildcard +{ + + public: + + /** + * This function implements the UN*X wildcards. + * @param wildcard Wildcard to be used. + * @param test Value which we want to see if it matches the wildcard. + * @return 0 if wildcard does not match *test. 1 - if wildcard + * matches test. + */ + static int wildcardfit (const char *wildcard, const char *test); + + private: + /** + * Scans a set of characters and returns 0 if the set mismatches at this + * position in the teststring and 1 if it is matching + * wildcard is set to the closing ] and test is unmodified if mismatched + * and otherwise the char pointer is pointing to the next character + * @param wildcard UNIX style wildcard to be used + * @param test String we will test against the wildcard. + * @return 0 if the set mismatches. 1 otherwise. + */ + static int set (const char **wildcard, const char **test); + + /** + * Scans an asterisk. + * @param wildcard UNIX style wildcard to be used + * @param test String we will test against the wildcard. + * @return ??? + */ + static int asterisk (const char **wildcard, const char **test); +}; + +} } + + +#endif + diff --git a/testApp/remote/Makefile b/testApp/remote/Makefile index 5e2e524..44645c7 100644 --- a/testApp/remote/Makefile +++ b/testApp/remote/Makefile @@ -68,6 +68,10 @@ PROD_HOST += rpcServiceExample rpcServiceExample_SRCS += rpcServiceExample.cpp rpcServiceExample_LIBS += pvAccess pvData pvMB Com +PROD_HOST += rpcWildServiceExample +rpcWildServiceExample_SRCS += rpcWildServiceExample.cpp +rpcWildServiceExample_LIBS += pvAccess pvData pvMB Com + PROD_HOST += rpcClientExample rpcClientExample_SRCS += rpcClientExample.cpp rpcClientExample_LIBS += pvAccess pvData pvMB Com diff --git a/testApp/remote/rpcWildServiceExample.cpp b/testApp/remote/rpcWildServiceExample.cpp new file mode 100644 index 0000000..ef029fb --- /dev/null +++ b/testApp/remote/rpcWildServiceExample.cpp @@ -0,0 +1,48 @@ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * pvAccessCPP is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ + +#include +#include + +using namespace epics::pvData; +using namespace epics::pvAccess; + +static Structure::const_shared_pointer resultStructure = + getFieldCreate()->createFieldBuilder()-> + add("channelName", pvString)-> + createStructure(); + +class WildServiceImpl : + public RPCService +{ + PVStructure::shared_pointer request(PVStructure::shared_pointer const & pvArguments) + throw (RPCRequestException) + { + // requires NTURI as argument + if (pvArguments->getStructure()->getID() != "uri:ev4:nt/2012/pwd:NTURI") + throw RPCRequestException(Status::STATUSTYPE_ERROR, "RPC argument must be a NTURI normative type"); + + std::string channelName = pvArguments->getSubField("path")->get(); + + // create return structure and set data + PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(resultStructure); + result->getSubField("channelName")->put(channelName); + return result; + } +}; + +int main() +{ + RPCServer server; + + server.registerService("wild*", RPCService::shared_pointer(new WildServiceImpl())); + // you can register as many services as you want here ... + + server.printInfo(); + server.run(); + + return 0; +}