@ -37,9 +37,11 @@ namespace epics { namespace pvDatabase {
|
|||||||
|
|
||||||
PVRecordPtr PVRecord::create(
|
PVRecordPtr PVRecord::create(
|
||||||
string const &recordName,
|
string const &recordName,
|
||||||
PVStructurePtr const & pvStructure)
|
PVStructurePtr const & pvStructure,
|
||||||
|
int asLevel,
|
||||||
|
const std::string& asGroup)
|
||||||
{
|
{
|
||||||
PVRecordPtr pvRecord(new PVRecord(recordName,pvStructure));
|
PVRecordPtr pvRecord(new PVRecord(recordName,pvStructure,asLevel,asGroup));
|
||||||
if(!pvRecord->init()) {
|
if(!pvRecord->init()) {
|
||||||
pvRecord.reset();
|
pvRecord.reset();
|
||||||
}
|
}
|
||||||
@ -49,12 +51,16 @@ PVRecordPtr PVRecord::create(
|
|||||||
|
|
||||||
PVRecord::PVRecord(
|
PVRecord::PVRecord(
|
||||||
string const & recordName,
|
string const & recordName,
|
||||||
PVStructurePtr const & pvStructure)
|
PVStructurePtr const & pvStructure,
|
||||||
|
int asLevel_,
|
||||||
|
const std::string& asGroup_)
|
||||||
: recordName(recordName),
|
: recordName(recordName),
|
||||||
pvStructure(pvStructure),
|
pvStructure(pvStructure),
|
||||||
depthGroupPut(0),
|
depthGroupPut(0),
|
||||||
traceLevel(0),
|
traceLevel(0),
|
||||||
isAddListener(false)
|
isAddListener(false),
|
||||||
|
asLevel(asLevel_),
|
||||||
|
asGroup(asGroup_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <pv/pvDatabase.h>
|
#include <pv/pvDatabase.h>
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
|
#include <asLib.h>
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
@ -58,6 +59,19 @@ class epicsShareClass ChannelProviderLocal :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(ChannelProviderLocal);
|
POINTER_DEFINITIONS(ChannelProviderLocal);
|
||||||
|
/**
|
||||||
|
* @brief Initialize access security configuration
|
||||||
|
* @param filePath AS definition file path
|
||||||
|
* @param substitutions macro substitutions
|
||||||
|
* @throws std::runtime_error in case of configuration problem
|
||||||
|
*/
|
||||||
|
static void initAs(const std::string& filePath, const std::string& substitutions="");
|
||||||
|
/**
|
||||||
|
* @brief Is access security active?
|
||||||
|
* @return true is AS is active
|
||||||
|
*/
|
||||||
|
static bool isAsActive();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructor
|
* @brief Constructor
|
||||||
*/
|
*/
|
||||||
@ -158,6 +172,7 @@ private:
|
|||||||
friend class ChannelProviderLocalRun;
|
friend class ChannelProviderLocalRun;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Channel for accessing a PVRecord.
|
* @brief Channel for accessing a PVRecord.
|
||||||
*
|
*
|
||||||
@ -341,6 +356,12 @@ public:
|
|||||||
* @param out the stream on which the message is displayed.
|
* @param out the stream on which the message is displayed.
|
||||||
*/
|
*/
|
||||||
virtual void printInfo(std::ostream& out);
|
virtual void printInfo(std::ostream& out);
|
||||||
|
/**
|
||||||
|
* @brief determines if client can write
|
||||||
|
*
|
||||||
|
* @return true if client can write
|
||||||
|
*/
|
||||||
|
virtual bool canWrite();
|
||||||
protected:
|
protected:
|
||||||
shared_pointer getPtrSelf()
|
shared_pointer getPtrSelf()
|
||||||
{
|
{
|
||||||
@ -351,6 +372,19 @@ private:
|
|||||||
ChannelProviderLocalWPtr provider;
|
ChannelProviderLocalWPtr provider;
|
||||||
PVRecordWPtr pvRecord;
|
PVRecordWPtr pvRecord;
|
||||||
epics::pvData::Mutex mutex;
|
epics::pvData::Mutex mutex;
|
||||||
|
|
||||||
|
// AS-specific variables/methods
|
||||||
|
std::vector<char> toCharArray(const std::string& s);
|
||||||
|
std::vector<char> getAsGroup(const PVRecordPtr& pvRecord);
|
||||||
|
std::vector<char> getAsUser(const epics::pvAccess::ChannelRequester::shared_pointer& requester);
|
||||||
|
std::vector<char> getAsHost(const epics::pvAccess::ChannelRequester::shared_pointer& requester);
|
||||||
|
|
||||||
|
int asLevel;
|
||||||
|
std::vector<char> asGroup;
|
||||||
|
std::vector<char> asUser;
|
||||||
|
std::vector<char> asHost;
|
||||||
|
ASMEMBERPVT asMemberPvt;
|
||||||
|
ASCLIENTPVT asClientPvt;
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
@ -59,6 +59,7 @@ class epicsShareClass PVRecord :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PVRecord);
|
POINTER_DEFINITIONS(PVRecord);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Destructor.
|
* The Destructor.
|
||||||
*/
|
*/
|
||||||
@ -112,11 +113,14 @@ public:
|
|||||||
*
|
*
|
||||||
* @param recordName The name of the record, which is also the channelName.
|
* @param recordName The name of the record, which is also the channelName.
|
||||||
* @param pvStructure The top level structure.
|
* @param pvStructure The top level structure.
|
||||||
|
* @param asLevel AS level (default: ASL0)
|
||||||
|
* @param asGroup AS group (default: DEFAULT)
|
||||||
* @return A shared pointer to the newly created record.
|
* @return A shared pointer to the newly created record.
|
||||||
*/
|
*/
|
||||||
static PVRecordPtr create(
|
static PVRecordPtr create(
|
||||||
std::string const & recordName,
|
std::string const & recordName,
|
||||||
epics::pvData::PVStructurePtr const & pvStructure);
|
epics::pvData::PVStructurePtr const & pvStructure,
|
||||||
|
int asLevel = 0, const std::string& asGroup = "DEFAULT");
|
||||||
/**
|
/**
|
||||||
* @brief Get the name of the record.
|
* @brief Get the name of the record.
|
||||||
*
|
*
|
||||||
@ -232,15 +236,30 @@ public:
|
|||||||
* @param level The level
|
* @param level The level
|
||||||
*/
|
*/
|
||||||
void setTraceLevel(int level) {traceLevel = level;}
|
void setTraceLevel(int level) {traceLevel = level;}
|
||||||
|
/**
|
||||||
|
* @brief Get the ASlevel
|
||||||
|
*
|
||||||
|
* @return The level.
|
||||||
|
*/
|
||||||
|
int getAsLevel() const {return asLevel;}
|
||||||
|
/**
|
||||||
|
* @brief Get the AS group name
|
||||||
|
*
|
||||||
|
* @return The name.
|
||||||
|
*/
|
||||||
|
std::string getAsGroup() const {return asGroup;}
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief Constructor
|
* @brief Constructor
|
||||||
* @param recordName The name of the record
|
* @param recordName The name of the record
|
||||||
* @param pvStructure The top level PVStructutre
|
* @param pvStructure The top level PVStructutre
|
||||||
|
* @param asLevel AS level (default: ASL0)
|
||||||
|
* @param asGroup AS group (default: DEFAULT)
|
||||||
*/
|
*/
|
||||||
PVRecord(
|
PVRecord(
|
||||||
std::string const & recordName,
|
std::string const & recordName,
|
||||||
epics::pvData::PVStructurePtr const & pvStructure);
|
epics::pvData::PVStructurePtr const & pvStructure,
|
||||||
|
int asLevel = 0, const std::string& asGroup = "DEFAULT");
|
||||||
/**
|
/**
|
||||||
* @brief Initializes the base class.
|
* @brief Initializes the base class.
|
||||||
*
|
*
|
||||||
@ -269,6 +288,9 @@ private:
|
|||||||
|
|
||||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||||
epics::pvData::TimeStamp timeStamp;
|
epics::pvData::TimeStamp timeStamp;
|
||||||
|
|
||||||
|
int asLevel;
|
||||||
|
std::string asGroup;
|
||||||
};
|
};
|
||||||
|
|
||||||
epicsShareFunc std::ostream& operator<<(std::ostream& o, const PVRecord& record);
|
epicsShareFunc std::ostream& operator<<(std::ostream& o, const PVRecord& record);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <epicsGuard.h>
|
#include <epicsGuard.h>
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
@ -23,6 +24,7 @@
|
|||||||
#include <pv/pvaVersionNum.h>
|
#include <pv/pvaVersionNum.h>
|
||||||
#include <pv/serverContext.h>
|
#include <pv/serverContext.h>
|
||||||
#include <pv/pvSubArrayCopy.h>
|
#include <pv/pvSubArrayCopy.h>
|
||||||
|
#include <pv/security.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
#include "pv/pvStructureCopy.h"
|
#include "pv/pvStructureCopy.h"
|
||||||
@ -517,6 +519,13 @@ void ChannelPutLocal::put(
|
|||||||
{
|
{
|
||||||
ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
|
ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
|
||||||
if(!requester) return;
|
if(!requester) return;
|
||||||
|
ChannelLocalPtr channel(channelLocal.lock());
|
||||||
|
if(!channel->canWrite()) {
|
||||||
|
Status status = Status::error("Channel put is not allowed");
|
||||||
|
requester->putDone(status,getPtrSelf());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PVRecordPtr pvr(pvRecord.lock());
|
PVRecordPtr pvr(pvRecord.lock());
|
||||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||||
try {
|
try {
|
||||||
@ -677,6 +686,12 @@ void ChannelPutGetLocal::putGet(
|
|||||||
{
|
{
|
||||||
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
|
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
|
||||||
if(!requester) return;
|
if(!requester) return;
|
||||||
|
ChannelLocalPtr channel(channelLocal.lock());
|
||||||
|
if(!channel->canWrite()) {
|
||||||
|
Status status = Status::error("Channel putGet is not allowed");
|
||||||
|
requester->putGetDone(status,getPtrSelf(),pvGetStructure,getBitSet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
PVRecordPtr pvr(pvRecord.lock());
|
PVRecordPtr pvr(pvRecord.lock());
|
||||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||||
try {
|
try {
|
||||||
@ -1225,7 +1240,13 @@ ChannelLocal::ChannelLocal(
|
|||||||
:
|
:
|
||||||
requester(requester),
|
requester(requester),
|
||||||
provider(provider),
|
provider(provider),
|
||||||
pvRecord(pvRecord)
|
pvRecord(pvRecord),
|
||||||
|
asLevel(pvRecord->getAsLevel()),
|
||||||
|
asGroup(getAsGroup(pvRecord)),
|
||||||
|
asUser(getAsUser(requester)),
|
||||||
|
asHost(getAsHost(requester)),
|
||||||
|
asMemberPvt(0),
|
||||||
|
asClientPvt(0)
|
||||||
{
|
{
|
||||||
if(pvRecord->getTraceLevel()>0) {
|
if(pvRecord->getTraceLevel()>0) {
|
||||||
cout << "ChannelLocal::ChannelLocal()"
|
cout << "ChannelLocal::ChannelLocal()"
|
||||||
@ -1233,11 +1254,86 @@ ChannelLocal::ChannelLocal(
|
|||||||
<< " requester exists " << (requester ? "true" : "false")
|
<< " requester exists " << (requester ? "true" : "false")
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
if (pvRecord->getAsGroup().empty() || asAddMember(&asMemberPvt, &asGroup[0]) != 0) {
|
||||||
|
asMemberPvt = 0;
|
||||||
|
}
|
||||||
|
if (asMemberPvt) {
|
||||||
|
asAddClient(&asClientPvt, asMemberPvt, asLevel, &asUser[0], &asHost[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> ChannelLocal::toCharArray(const std::string& s)
|
||||||
|
{
|
||||||
|
std::vector<char> v(s.begin(), s.end());
|
||||||
|
v.push_back('\0');
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> ChannelLocal::getAsGroup(const PVRecordPtr& pvRecord)
|
||||||
|
{
|
||||||
|
return toCharArray(pvRecord->getAsGroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> ChannelLocal::getAsUser(const ChannelRequester::shared_pointer& requester)
|
||||||
|
{
|
||||||
|
PeerInfo::const_shared_pointer info(requester->getPeerInfo());
|
||||||
|
std::string user;
|
||||||
|
if(info && info->identified) {
|
||||||
|
if(info->authority=="ca") {
|
||||||
|
user = info->account;
|
||||||
|
size_t first = user.find_last_of('/');
|
||||||
|
if(first != std::string::npos) {
|
||||||
|
// prevent CA accounts like "<authority>/<user>"
|
||||||
|
user = user.substr(first+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
user = info->authority + "/" + info->account;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toCharArray(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> ChannelLocal::getAsHost(const epics::pvAccess::ChannelRequester::shared_pointer& requester)
|
||||||
|
{
|
||||||
|
PeerInfo::const_shared_pointer info(requester->getPeerInfo());
|
||||||
|
std::string host;
|
||||||
|
if(info && info->identified) {
|
||||||
|
host= info->peer;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// anonymous
|
||||||
|
host = requester->getRequesterName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle form "ip:port"
|
||||||
|
size_t last = host.find_first_of(':');
|
||||||
|
if(last == std::string::npos) {
|
||||||
|
last = host.size();
|
||||||
|
}
|
||||||
|
host.resize(last);
|
||||||
|
return toCharArray(host);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChannelLocal::canWrite()
|
||||||
|
{
|
||||||
|
if(!asActive || (asClientPvt && asCheckPut(asClientPvt))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelLocal::~ChannelLocal()
|
ChannelLocal::~ChannelLocal()
|
||||||
{
|
{
|
||||||
// cout << "~ChannelLocal()" << endl;
|
// cout << "~ChannelLocal()" << endl;
|
||||||
|
if(asMemberPvt) {
|
||||||
|
asRemoveMember(&asMemberPvt);
|
||||||
|
asMemberPvt = 0;
|
||||||
|
}
|
||||||
|
if(asClientPvt) {
|
||||||
|
asRemoveClient(&asClientPvt);
|
||||||
|
asClientPvt = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelProvider::shared_pointer ChannelLocal::getProvider()
|
ChannelProvider::shared_pointer ChannelLocal::getProvider()
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
|
#include <asLib.h>
|
||||||
#include <pv/serverContext.h>
|
#include <pv/serverContext.h>
|
||||||
#include <pv/syncChannelFind.h>
|
#include <pv/syncChannelFind.h>
|
||||||
#include <pv/pvTimeStamp.h>
|
#include <pv/pvTimeStamp.h>
|
||||||
@ -176,4 +177,18 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
|
|||||||
return createChannel(channelName, channelRequester, priority);
|
return createChannel(channelName, channelRequester, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChannelProviderLocal::initAs(const std::string& filePath, const std::string& substitutions)
|
||||||
|
{
|
||||||
|
int status = asInitFile(filePath.c_str(), substitutions.c_str());
|
||||||
|
if(status) {
|
||||||
|
throw std::runtime_error("Invalid AS configuration.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChannelProviderLocal::isAsActive()
|
||||||
|
{
|
||||||
|
return asActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
Reference in New Issue
Block a user