diff --git a/src/Makefile b/src/Makefile index da65c0e..046139f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -61,6 +61,7 @@ LIB_SRCS += serverconn.cpp LIB_SRCS += serverchan.cpp LIB_SRCS += serverintrospect.cpp LIB_SRCS += serverget.cpp +LIB_SRCS += serversource.cpp LIB_LIBS += Com diff --git a/src/pvxs/server.h b/src/pvxs/server.h index 4aa1431..4e5872e 100644 --- a/src/pvxs/server.h +++ b/src/pvxs/server.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -228,6 +229,13 @@ struct PVXS_API Source { * Callee with either do nothing, or std::move() the ChannelControl and call ChannelControl::setHandler() */ virtual void onCreate(std::unique_ptr&& op) =0; + + struct List { + std::shared_ptr> names; + bool dynamic; + }; + + virtual List onList(); }; }} // namespace pvxs::server diff --git a/src/server.cpp b/src/server.cpp index 14d9244..60fd854 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -390,6 +390,12 @@ Server::Pvt::Pvt(Config&& conf) effective.auto_beacon = false; }); + + // Add magic "server" PV + { + auto L = sourcesLock.lockWriter(); + sources[std::make_pair(-1, "server")] = std::make_shared(this); + } } Server::Pvt::~Pvt() @@ -597,6 +603,10 @@ void Server::Pvt::doBeaconsS(evutil_socket_t fd, short evt, void *raw) Source::~Source() {} +Source::List Source::onList() { + return Source::List{}; +} + OpBase::~OpBase() {} ChannelControl::~ChannelControl() {} diff --git a/src/serverconn.h b/src/serverconn.h index 6b1d8c9..54957de 100644 --- a/src/serverconn.h +++ b/src/serverconn.h @@ -167,6 +167,22 @@ struct ServIface static void onConnS(struct evconnlistener *listener, evutil_socket_t sock, struct sockaddr *peer, int socklen, void *raw); }; + +//! Home of the magic "server" PV used by "pvinfo" +struct ServerSource : public server::Source +{ + const std::string name; + server::Server::Pvt* const serv; + + const Value info; + + ServerSource(server::Server::Pvt* serv); + + virtual void onSearch(Search &op) override final; + + virtual void onCreate(std::unique_ptr &&op) override final; +}; + } // namespace impl namespace server { diff --git a/src/serversource.cpp b/src/serversource.cpp new file mode 100644 index 0000000..ab7890e --- /dev/null +++ b/src/serversource.cpp @@ -0,0 +1,99 @@ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * pvxs is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ + +#include +#include +#include "serverconn.h" + +namespace pvxs { +namespace impl { + +DEFINE_LOGGER(srvsrc, "server.src"); + +ServerSource::ServerSource(server::Server::Pvt* serv) + :name("server") + ,serv(serv) + ,info(TypeDef(TypeCode::Struct, { + Member(TypeCode::String, "implLang"), + Member(TypeCode::String, "version"), + }).create()) +{} + +void ServerSource::onSearch(Search &op) +{ + // nothing. our "server" PV is not advertised +} + +void ServerSource::onCreate(std::unique_ptr &&op) +{ + if(op->name()!=name) + return; + + auto handle = std::move(op); // claim + + handle->onRPC([this](std::unique_ptr&& eop, Value&& raw) { + log_printf(srvsrc, PLVL_DEBUG, "Client %s calls %s\n", eop->peerName().c_str(), + std::string(SB()<reply(ret); + } + + auto op = args["op"].as(); + + if(op=="channels") { + + std::set names; + { + auto L(serv->sourcesLock.lockReader()); + + for(auto& pair : serv->sources) { + auto list = pair.second->onList(); + if(list.names) { + for(auto& name : *list.names) { + names.insert(name); + } + } + } + } + + shared_array lnames(names.size()); + size_t i=0; + for(auto& name : names) { + lnames[i++] = name; + } + + auto ret = nt::NTScalar{TypeCode::StringA}.create(); + ret["value"] = lnames.freeze().castTo(); + + eop->reply(ret); + return; + + } else if(op=="info") { + auto ret = info.cloneEmpty(); + + ret["implLang"] = "cpp"; + ret["version"] = version_str(); + + eop->reply(ret); + return; + } + + eop->error("Not implemented"); + }); +} + + +} // namespace impl +} // namespace pvxs diff --git a/test/dummyserv.cpp b/test/dummyserv.cpp index 20e968b..473a322 100644 --- a/test/dummyserv.cpp +++ b/test/dummyserv.cpp @@ -59,6 +59,14 @@ public: } } } + + virtual List onList() override final + { + auto names(std::make_shared>()); + names->insert(name); + return List{names}; + } + virtual void onCreate(std::unique_ptr&& raw) override final { if(raw->name()!=name)