24 Commits

Author SHA1 Message Date
Andrew Johnson cb13435d15 Update version numbers for release 2020-05-28 15:43:34 -05:00
Michael Davidsaver cda2222ed5 p2p: deprecation notice 2020-05-19 17:06:28 -07:00
Michael Davidsaver 68708ff530 p2p: Fix EPICS_PVA*_AUTO_ADDR_LIST 2020-05-19 16:48:53 -07:00
Michael Davidsaver 137ecfed56 ci-scripts 2.3.2 (with appveyor) 2020-04-23 15:16:41 -07:00
Michael Davidsaver 29a6f261dc travis use ci-scripts 2019-12-20 12:06:11 -08:00
Michael Davidsaver 1d9fbbea0b don't install check_consist 2019-12-19 18:45:38 -08:00
Michael Davidsaver 536f4dd02f finalize doxygen 2019-11-03 20:08:49 -08:00
Andrew Johnson 21ae754869 Incr version and set development flag after release 2019-10-31 18:00:34 -05:00
Andrew Johnson 3024f9fb0c Clear development flag for 1.2.2 release 2019-10-31 17:58:09 -05:00
Andrew Johnson 58a2159969 Indent sub-bullets by 2 spaces for pandoc gfm 2019-10-31 17:55:59 -05:00
Michael Davidsaver c200dd22f1 doc for 1.2.2 2019-10-31 10:55:12 -07:00
Michael Davidsaver 9c6fb5c539 more WIN32 include order games 2019-09-26 13:46:26 -07:00
Freddie Akeroyd 54a882d844 MSVC is picky about vector access 2019-09-25 13:47:03 -07:00
Andrew Johnson c7a54de469 Move include of osiSock.h below db headers for Windows 2019-09-07 09:43:11 +02:00
Michael Davidsaver c2ee7c9dc4 m_data removal
Try to avoid stepping on this vxWorks landmine.
2019-09-06 14:57:03 -07:00
Ralph Lange 3e59a4b6a8 rtd-ci: add read-the-docs integration 2019-09-06 15:42:44 +02:00
Michael Davidsaver 0e0400022c vx const fixup
std::set iteration really should always be const
as mutation would invalidate the ordering.
2019-09-05 20:02:46 -07:00
Michael Davidsaver bdbf57350b replace shareLib.h with QSRV_API
and hopefully avoid at least some of the maddening
include order bugs so common with sharedLib.h.
2019-09-05 20:01:56 -07:00
Michael Davidsaver 2e58e54e1d Merge branch 'auth'
* auth:
  minor
  re-add missing enum_t
  asLib check against PeerInfo
2019-08-31 19:22:23 -07:00
Michael Davidsaver ddfd746c62 minor 2019-08-31 19:18:56 -07:00
Michael Davidsaver e41269230c re-add missing enum_t 2019-08-13 20:08:40 -07:00
Michael Davidsaver c3b6fc08b8 re-add missing enum_t 2019-08-13 20:07:26 -07:00
Andrew Johnson d70a2ff8c3 Update version number to 1.2.2 DEVELOPMENT 2019-08-13 11:08:34 -05:00
Michael Davidsaver d7314eaef4 asLib check against PeerInfo
Check Put permissions
2019-05-16 18:19:38 -07:00
42 changed files with 3208 additions and 298 deletions
+102
View File
@@ -0,0 +1,102 @@
# .appveyor.yml for use with EPICS Base ci-scripts
# (see: https://github.com/epics-base/ci-scripts)
# This is YAML - indentation levels are crucial
cache:
- C:\Users\appveyor\.tools
#---------------------------------#
# additional packages #
#---------------------------------#
install:
# for the sequencer
- cinst re2c
- cmd: git submodule update --init --recursive
#---------------------------------#
# repository cloning #
#---------------------------------#
init:
# Set autocrlf to make batch files work
- git config --global core.autocrlf true
clone_depth: 50
# Skipping commits affecting only specific files
skip_commits:
files:
- 'documentation/*'
- '**/*.md'
# Build Configurations: dll/static, regular/debug
configuration:
- dynamic
- static
- dynamic-debug
- static-debug
# Environment variables: compiler toolchain, base version, setup file, ...
environment:
# common / default variables for all jobs
SETUP_PATH: .ci-local:.ci
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
CMP: vs2019
BASE: 7.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
CMP: mingw
BASE: 7.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
CMP: vs2017
BASE: 7.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
CMP: vs2019
BASE: 3.15
# Platform: processor architecture
platform:
- x64
#---------------------------------#
# building & testing #
#---------------------------------#
build_script:
- cmd: python .ci/appveyor/do.py prepare
- cmd: python .ci/appveyor/do.py build
test_script:
- cmd: python .ci/appveyor/do.py test
on_finish:
- ps: Get-ChildItem *.tap -Recurse -Force | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
- cmd: python .ci/appveyor/do.py build test-results -s
#---------------------------------#
# debugging #
#---------------------------------#
## if you want to connect by remote desktop to a failed build, uncomment these lines
## note that you will need to connect within the usual build timeout limit (60 minutes)
## so you may want to adjust the build matrix above to just build the one of interest
#on_failure:
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
#---------------------------------#
# notifications #
#---------------------------------#
notifications:
- provider: Email
to:
- me@example.com
on_build_success: false
- provider: GitHubPullRequest
Submodule
+1
Submodule .ci added at ecb7e43660
+14
View File
@@ -0,0 +1,14 @@
# EPICS Base
BASE_DIRNAME=base
BASE_REPONAME=epics-base
BASE_REPOOWNER=epics-base
BASE_VARNAME=EPICS_BASE
BASE_RECURSIVE=NO
MODULES=PVDATA PVACCESS
PVDATA_REPONAME=pvDataCPP
PVDATA_REPOOWNER=epics-base
PVACCESS_REPONAME=pvAccessCPP
PVACCESS_REPOOWNER=epics-base
-10
View File
@@ -1,10 +0,0 @@
#!/bin/sh
set -e -x
make -j2 $EXTRA
if [ "$TEST" != "NO" ]
then
make tapfiles
make -s test-results
fi
-112
View File
@@ -1,112 +0,0 @@
#!/bin/sh
set -e -x
CURDIR="$PWD"
cat << EOF > $CURDIR/configure/RELEASE.local
EPICS_BASE=$HOME/.source/epics-base
EOF
install -d "$HOME/.source"
cd "$HOME/.source"
add_gh_flat() {
MODULE=$1
REPOOWNER=$2
REPONAME=$3
BRANCH=$4
MODULE_UC=$(echo $MODULE | tr 'a-z' 'A-Z')
( git clone --quiet --depth 5 --branch $BRANCH https://github.com/$REPOOWNER/$REPONAME.git $MODULE && \
cd $MODULE && git log -n1 )
cat < $CURDIR/configure/RELEASE.local > $MODULE/configure/RELEASE.local
cat << EOF >> $CURDIR/configure/RELEASE.local
${MODULE_UC}=$HOME/.source/$MODULE
EOF
}
# not recursive
git clone --quiet --depth 5 --branch "$BRBASE" https://github.com/${REPOBASE:-epics-base}/epics-base.git epics-base
(cd epics-base && git log -n1 )
add_gh_flat pvData ${REPOPVD:-epics-base} pvDataCPP ${BRPVD:-master}
add_gh_flat pvAccess ${REPOPVA:-epics-base} pvAccessCPP ${BRPVA:-master}
if [ -e $CURDIR/configure/RELEASE.local ]
then
cat $CURDIR/configure/RELEASE.local
fi
EPICS_HOST_ARCH=`sh epics-base/startup/EpicsHostArch`
# requires wine and g++-mingw-w64-i686
if [ "$WINE" = "32" ]
then
echo "Cross mingw32"
sed -i -e '/CMPLR_PREFIX/d' epics-base/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
cat << EOF >> epics-base/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
CMPLR_PREFIX=i686-w64-mingw32-
EOF
cat << EOF >> epics-base/configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw
EOF
fi
if [ "$STATIC" = "YES" ]
then
echo "Build static libraries/executables"
cat << EOF >> epics-base/configure/CONFIG_SITE
SHARED_LIBRARIES=NO
STATIC_BUILD=YES
EOF
fi
case "$CMPLR" in
clang)
echo "Host compiler is clang"
cat << EOF >> epics-base/configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH
GNU = NO
CMPLR_CLASS = clang
CC = clang
CCC = clang++
EOF
# hack
sed -i -e 's/CMPLR_CLASS = gcc/CMPLR_CLASS = clang/' epics-base/configure/CONFIG.gnuCommon
clang --version
;;
*)
echo "Host compiler is default"
gcc --version
;;
esac
cat <<EOF >> epics-base/configure/CONFIG_SITE
USR_CPPFLAGS += $USR_CPPFLAGS
USR_CFLAGS += $USR_CFLAGS
USR_CXXFLAGS += $USR_CXXFLAGS
EOF
# set RTEMS to eg. "4.9" or "4.10"
# requires qemu, bison, flex, texinfo, install-info
if [ -n "$RTEMS" ]
then
echo "Cross RTEMS${RTEMS} for pc386"
curl -L "https://github.com/mdavidsaver/rsb/releases/download/20171203-${RTEMS}/i386-rtems${RTEMS}-trusty-20171203-${RTEMS}.tar.bz2" \
| tar -C / -xmj
sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' epics-base/configure/os/CONFIG_SITE.Common.RTEMS
cat << EOF >> epics-base/configure/os/CONFIG_SITE.Common.RTEMS
RTEMS_VERSION=$RTEMS
RTEMS_BASE=$HOME/.rtems
EOF
cat << EOF >> epics-base/configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386-qemu
EOF
fi
make -j2 -C epics-base $EXTRA
make -j2 -C pvData $EXTRA
make -j2 -C pvAccess $EXTRA
find epics-base/include
find epics-base/lib
+3
View File
@@ -0,0 +1,3 @@
[submodule ".ci"]
path = .ci
url = https://github.com/epics-base/ci-scripts
+17
View File
@@ -0,0 +1,17 @@
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Build documentation in the documentation/ directory with Sphinx
sphinx:
configuration: documentation/conf.py
# Build documentation with MkDocs
#mkdocs:
# configuration: mkdocs.yml
# Optionally build your docs in additional formats such as PDF and ePub
formats: all
+97 -19
View File
@@ -1,30 +1,108 @@
sudo: false
dist: trusty
language: c++
compiler:
- gcc
# .travis.yml for use with EPICS Base ci-scripts
# (see: https://github.com/epics-base/ci-scripts)
# This is YAML - indentation levels are crucial
language: cpp
compiler: gcc
dist: bionic
cache:
directories:
- $HOME/.cache
env:
global:
- SETUP_PATH=.ci-local:.ci
addons:
apt:
packages:
# for all EPICS builds
- libreadline6-dev
- libncurses5-dev
- perl
# for clang compiler
- clang
# for mingw builds (32bit and 64bit)
- g++-mingw-w64-i686
- g++-mingw-w64-x86-64
# for RTEMS cross builds
- qemu-system-x86
install:
- ./.ci/travis-prepare.sh
- ./.ci/travis/prepare.sh
script:
- ./.ci/travis-build.sh
env:
- BRBASE=7.0
- BRBASE=7.0 CMPLR=clang
- BRBASE=7.0 EXTRA="CMD_CXXFLAGS=-std=c++98"
- BRBASE=7.0 EXTRA="CMD_CXXFLAGS=-std=c++11"
- BRBASE=7.0 CMPLR=clang EXTRA="CMD_CXXFLAGS=-std=c++11"
- BRBASE=7.0 WINE=32 TEST=NO STATIC=YES
- BRBASE=7.0 WINE=32 TEST=NO STATIC=NO
- BRBASE=7.0 RTEMS=4.10 TEST=NO
- BRBASE=7.0 RTEMS=4.9 TEST=NO
- BRBASE=3.16
- BRBASE=3.15
- ./.ci/travis/build.sh
# If you need to do more during install and build,
# add a local directory to your module and do e.g.
# - ./.ci-local/travis/install-extras.sh
# Define build jobs
# Well-known variables to use
# SET source setup file
# EXTRA content will be added to make command line
# STATIC set to YES for static build (default: NO)
# TEST set to NO to skip running the tests (default: YES)
# VV set to make build scripts verbose (default: unset)
# Usually from setup files, but may be specified or overridden
# on a job line
# MODULES list of dependency modules
# BASE branch or release tag name of the EPICS Base to use
# <MODULE> branch or release tag for a specific module
# ... see README for setup file syntax description
jobs:
include:
# Different configurations of default gcc and clang
- env: BASE=7.0
- env: BASE=7.0
compiler: clang
- env: BASE=7.0 EXTRA="CMD_CXXFLAGS=-std=c++11"
- env: BASE=7.0 EXTRA="CMD_CXXFLAGS=-std=c++11"
compiler: clang
# Trusty: compiler versions very close to RHEL 7
- env: BASE=7.0
dist: trusty
- env: BASE=7.0 EXTRA="CMD_CXXFLAGS=-std=c++11"
dist: trusty
- env: BASE=3.15 EXTRA="CMD_CXXFLAGS=-std=c++11"
dist: trusty
# Cross-compilations to Windows using MinGW and WINE
- env: BASE=7.0 WINE=32 TEST=NO STATIC=YES
compiler: mingw
- env: BASE=7.0 WINE=64 TEST=NO STATIC=NO
compiler: mingw
# Other gcc versions (added as an extra package)
- env: BASE=7.0
compiler: gcc-6
addons: { apt: { packages: ["g++-6"], sources: ["ubuntu-toolchain-r-test"] } }
- env: BASE=7.0
compiler: gcc-7
addons: { apt: { packages: ["g++-7"], sources: ["ubuntu-toolchain-r-test"] } }
# MacOS build
- env: BASE=7.0
os: osx
compiler: clang
addons: { homebrew: { packages: ["re2c"], update: true } }
+2497
View File
File diff suppressed because it is too large Load Diff
+8 -2
View File
@@ -1,9 +1,15 @@
# Module (source) version
EPICS_QSRV_MAJOR_VERSION = 1
EPICS_QSRV_MINOR_VERSION = 2
EPICS_QSRV_MAINTENANCE_VERSION = 1
EPICS_QSRV_DEVELOPMENT_FLAG = 0
EPICS_QSRV_MAINTENANCE_VERSION = 3
# ABI version
EPICS_QSRV_ABI_MAJOR_VERSION = 1
EPICS_QSRV_ABI_MINOR_VERSION = 1
# Development flag, set to zero for release versions
EPICS_QSRV_DEVELOPMENT_FLAG = 0
# Immediately after a release the MAINTENANCE_VERSION
# will be incremented and the DEVELOPMENT_FLAG set to 1
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = pva2pva
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 1.2.1
PROJECT_NUMBER = 1.2.3
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
+7
View File
@@ -0,0 +1,7 @@
.wy-side-nav-search {
background-color: #18334B;
}
.wy-side-nav-search input[type="text"] {
border-color: #18334b;
}
+78
View File
@@ -0,0 +1,78 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'EPICS Documentation'
copyright = '2019, EPICS Controls.'
author = 'EPICS'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.intersphinx',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# Intersphinx links to subprojects
intersphinx_mapping = {
'how-tos': ('https://docs.epics-controls.org/projects/how-tos/en/latest', None),
}
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_css_files = [
'css/custom.css',
]
master_doc = 'index'
html_theme_options = {
'logo_only': True,
}
html_logo = "images/EPICS_white_logo_v02.png"
html_extra_path = ['../html']
# -- Run Doxygen ------------------------------------------------------------
import subprocess
subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True)
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

+16
View File
@@ -0,0 +1,16 @@
pva2pva (QSRV / pvAccess Gateway)
=================================
.. toctree::
:hidden:
EPICS Website <https://epics-controls.org>
EPICS Documentation Home <https://docs.epics-controls.org>
.. toctree::
:maxdepth: 1
:caption: pva2pva
Reference Manual and API Documentation <https://docs.epics-controls.org/projects/pva2pva/en/latest/doxygen>
Source Code Repository on GitHub <https://github.com/epics-base/pva2pva>
+2 -1
View File
@@ -11,7 +11,8 @@ runs inside an EPICS IOC process and allows clients
to make requests to access the Process Variables (PVs)
within.
Documentation of @ref qsrv_config including @ref qsrv_group_def
Documentation of @ref qsrv_config including @ref qsrv_group_def ,
@ref qsrv_aslib
and @ref qsrv_link configuration.
- @ref release_notes
+27 -2
View File
@@ -162,6 +162,33 @@ record(ai, "...") {
}
@endcode
@subsection qsrv_aslib Access Security
QSRV will enforce an optional access control policy file (.acf) loaded by the usual means (cf. asSetFilename() ).
This policy is applied to both Single and Group PVs. With Group PVs, restrictions are not defined for the group,
but rather for the individual member records. The same policy will be applied regardess of how a record
is accessed (individually, or through a group).
Policy application differs from CA (RSRV) in several ways:
* Client hostname is always the numeric IP address. HAG() entries must either contained numeric IP addresses,
or that asCheckClientIP=1 flag must be set to translate hostnames into IPs on ACF file load (effects CA server as well).
This prevents clients from trivially forging "hostname".
* In additional to client usernames. UAG definitions may contained items beginning with "role/" which are matched
against the list of groups of which the client username is a member. Username to group lookup is done internally
to QSRV, and depends on IOC host authentication configuration. Note that this is still based on the client provided
username string.
@code
UAG(special) {
someone, "role/op"
}
@endcode
The "special" UAG will match CA or PVA clients with the username "someone".
It will also match a PVA client if the client provided username is a member
of the "op" group (supported on POSIX targets and Windows).
@subsection qsrv_link PVAccess Links
When built against Base >= 3.16.1, support is enabled for PVAccess links,
@@ -170,8 +197,6 @@ for PVA links is quite different.
@note The "dbjlr" and "dbpvar" IOC shell command provide information about PVA links in a running IOC.
@warning The PVA Link syntax shown below is provisional and subject to change.
A simple configuration using defaults is
@code
+26 -14
View File
@@ -2,39 +2,51 @@
@page release_notes Release Notes
Release 1.2.3 (May 2020)
========================
- P2P gateway deprecated in favor of https://mdavidsaver.github.io/p4p/gw.html
Release 1.2.2 (Nov 2019)
========================
- Changes
- Enforce Access Security policy.
- NTEnum .value field add missing "enum_t" type ID string.
Release 1.2.1 (July 2019)
=========================
- Fixes
- Fix unittest: testpvalink. No functional change.
- Fix unittest: testpvalink. No functional change.
Release 1.2.0 (Mar 2019)
========================
- Incompatible changes
- The field 'display.format' is replaced with 'display.form' and 'display.precision'.
https://github.com/epics-base/pva2pva/issues/19
- The field 'display.format' is replaced with 'display.form' and 'display.precision'.
https://github.com/epics-base/pva2pva/issues/19
- Additions
- Use @code info(Q:form, "...") @endcode to set 'display.form'. See @ref qsrv_form
- Use @code info(Q:form, "...") @endcode to set 'display.form'. See @ref qsrv_form
- Fixes
- Correct handling of 64-bit integer fields.
- Install a copy of softIocExit.db for standalone builds
- Correct handling of 64-bit integer fields.
- Install a copy of softIocExit.db for standalone builds
Release 1.1.0 (Nov 2018)
==========================
- Incompatible changes
- Requires pvDataCPP >= 7.1.0
- Requires pvAccessCPP >= 6.1.0
- Requires pvDataCPP >= 7.1.0
- Requires pvAccessCPP >= 6.1.0
- Removals
- Drop the broken ioccircle and ioccircle2 examples.
- Drop the broken ioccircle and ioccircle2 examples.
- Fixes
- Fix QSRV monitor locking causing crash
- Fix Windows DLL import/export errors
- Correctly handle empty "scalar" case of NELM=1, NORD=0.
- Fix QSRV monitor locking causing crash
- Fix Windows DLL import/export errors
- Correctly handle empty "scalar" case of NELM=1, NORD=0.
- Additions
- QSRV implement channelList() (aka. 'pvlist') with list of record and group names.
- @ref qsrv_link type (requires Base >= 3.16.1)
- QSRV implement channelList() (aka. 'pvlist') with list of record and group names.
- @ref qsrv_link type (requires Base >= 3.16.1)
Release 1.0.0 (Dec 2017)
========================
+13 -2
View File
@@ -139,7 +139,7 @@ GWServerChannelProvider::shared_pointer configure_client(ServerConfig& arg, cons
pva::Configuration::shared_pointer C(pva::ConfigurationBuilder()
.add("EPICS_PVA_ADDR_LIST", conf->getSubFieldT<pvd::PVString>("addrlist")->get())
.add("EPICS_PVA_AUTO_ADDR_LIST", conf->getSubFieldT<pvd::PVBoolean>("autoaddrlist")->get())
.add("EPICS_PVA_AUTO_ADDR_LIST", conf->getSubFieldT<pvd::PVScalar>("autoaddrlist")->getAs<std::string>())
.add("EPICS_PVA_SERVER_PORT", conf->getSubFieldT<pvd::PVScalar>("serverport")->getAs<pvd::uint16>())
.add("EPICS_PVA_BROADCAST_PORT", conf->getSubFieldT<pvd::PVScalar>("bcastport")->getAs<pvd::uint16>())
.add("EPICS_PVA_DEBUG", arg.debug>=5 ? 5 : 0)
@@ -163,7 +163,7 @@ pva::ServerContext::shared_pointer configure_server(ServerConfig& arg, const pvd
pva::Configuration::shared_pointer C(pva::ConfigurationBuilder()
.add("EPICS_PVAS_INTF_ADDR_LIST", conf->getSubFieldT<pvd::PVString>("interface")->get())
.add("EPICS_PVAS_BEACON_ADDR_LIST", conf->getSubFieldT<pvd::PVString>("addrlist")->get())
.add("EPICS_PVAS_AUTO_BEACON_ADDR_LIST", conf->getSubFieldT<pvd::PVBoolean>("autoaddrlist")->get())
.add("EPICS_PVAS_AUTO_BEACON_ADDR_LIST", conf->getSubFieldT<pvd::PVScalar>("autoaddrlist")->getAs<std::string>())
.add("EPICS_PVAS_SERVER_PORT", conf->getSubFieldT<pvd::PVScalar>("serverport")->getAs<pvd::uint16>())
.add("EPICS_PVAS_BROADCAST_PORT", conf->getSubFieldT<pvd::PVScalar>("bcastport")->getAs<pvd::uint16>())
.add("EPICS_PVA_DEBUG", arg.debug>=5 ? 5 : 0)
@@ -258,6 +258,17 @@ int main(int argc, char *argv[])
theserver = &arg;
getargs(arg, argc, argv);
if(arg.debug>0)
std::cout<<"Notice: This p2p gateway prototype has been superceded by the p4p.gw gateway\n"
" which has exciting new features including granular access control,\n"
" and status PVs including bandwidth usage reports.\n"
" p2p is considered deprecated by its author, and will receive\n"
" minimal maintainance effort going forward.\n"
" Users are encouraged to migrate to p4p.gw.\n"
"\n"
" https://mdavidsaver.github.io/p4p/gw.html\n"
"\n";
pva::pvAccessLogLevel lvl;
if(arg.debug<0)
lvl = pva::logLevelError;
+25 -25
View File
@@ -75,7 +75,7 @@ private:
mutex_type mutex;
store_t store;
};
std::tr1::shared_ptr<data> m_data;
std::tr1::shared_ptr<data> _data;
struct dtor {
std::tr1::weak_ptr<data> container;
@@ -110,7 +110,7 @@ private:
};
public:
//! Construct a new empty set
weak_value_map() :m_data(new data) {}
weak_value_map() :_data(new data) {}
private:
//! Not copyable
@@ -122,22 +122,22 @@ public:
//! exchange the two sets.
//! @warning Not thread safe (exchanges mutexes as well)
void swap(weak_value_map& O) {
m_data.swap(O.m_data);
_data.swap(O._data);
}
//! Remove all (weak) entries from the set
//! @note Thread safe
void clear() {
guard_type G(m_data->mutex);
return m_data->store.clear();
guard_type G(_data->mutex);
return _data->store.clear();
}
//! Test if set is empty at this moment
//! @note Thread safe
//! @warning see size()
bool empty() const {
guard_type G(m_data->mutex);
return m_data->store.empty();
guard_type G(_data->mutex);
return _data->store.empty();
}
//! number of entries in the set at this moment
@@ -145,8 +145,8 @@ public:
//! @warning May be momentarily inaccurate (larger) due to dead refs.
//! which have not yet been removed.
size_t size() const {
guard_type G(m_data->mutex);
return m_data->store.size();
guard_type G(_data->mutex);
return _data->store.size();
}
//! proxy class for lookup of non-const
@@ -167,8 +167,8 @@ public:
{
if(!v.unique())
throw std::invalid_argument("Only unique() references may be inserted");
value_pointer chainptr(v.get(), dtor(M.m_data, k, v));
M.m_data->store[k] = chainptr;
value_pointer chainptr(v.get(), dtor(M._data, k, v));
M._data->store[k] = chainptr;
v.swap(chainptr);
return v;
}
@@ -215,9 +215,9 @@ public:
value_pointer find(const K& k) const
{
value_pointer ret;
guard_type G(m_data->mutex);
typename store_t::const_iterator it(m_data->store.find(k));
if(it!=m_data->store.end()) {
guard_type G(_data->mutex);
typename store_t::const_iterator it(_data->store.find(k));
if(it!=_data->store.end()) {
// may be nullptr if we race destruction
// as ref. count falls to zero before we can remove it
ret = it->second.lock();
@@ -230,9 +230,9 @@ public:
value_pointer insert(const K& k, value_pointer& v)
{
value_pointer ret;
guard_type G(m_data->mutex);
typename store_t::const_iterator it = m_data->store.find(k);
if(it!=m_data->store.end())
guard_type G(_data->mutex);
typename store_t::const_iterator it = _data->store.find(k);
if(it!=_data->store.end())
ret = it->second.lock();
(*this)[k] = v;
return ret;
@@ -243,9 +243,9 @@ public:
lock_map_type lock_map() const
{
lock_map_type ret;
guard_type G(m_data->mutex);
for(typename store_t::const_iterator it = m_data->store.begin(),
end = m_data->store.end(); it!=end; ++it)
guard_type G(_data->mutex);
for(typename store_t::const_iterator it = _data->store.begin(),
end = _data->store.end(); it!=end; ++it)
{
value_pointer P(it->second.lock);
if(P) ret[it->first] = P;
@@ -259,10 +259,10 @@ public:
lock_vector_type lock_vector() const
{
lock_vector_type ret;
guard_type G(m_data->mutex);
ret.reserve(m_data->store.size());
for(typename store_t::const_iterator it = m_data->store.begin(),
end = m_data->store.end(); it!=end; ++it)
guard_type G(_data->mutex);
ret.reserve(_data->store.size());
for(typename store_t::const_iterator it = _data->store.begin(),
end = _data->store.end(); it!=end; ++it)
{
value_pointer P(it->second.lock());
if(P) ret.push_back(std::make_pair(it->first, P));
@@ -274,7 +274,7 @@ public:
//! for use with batch operations.
//! @warning Use caution when swap()ing while holding this lock!
inline epicsMutex& mutex() const {
return m_data->mutex;
return _data->mutex;
}
};
+25 -25
View File
@@ -94,7 +94,7 @@ private:
mutex_type mutex;
store_t store;
};
std::tr1::shared_ptr<data> m_data;
std::tr1::shared_ptr<data> _data;
//! Destroyer for a chained shared_ptr
//! which holds the unique() real strong
@@ -131,7 +131,7 @@ private:
};
public:
//! Construct a new empty set
weak_set() :m_data(new data) {}
weak_set() :_data(new data) {}
private:
//! Not copyable
@@ -143,22 +143,22 @@ public:
//! exchange the two sets.
//! @warning Not thread safe (exchanges mutexes as well)
void swap(weak_set& O) {
m_data.swap(O.m_data);
_data.swap(O._data);
}
//! Remove all (weak) entries from the set
//! @note Thread safe
void clear() {
guard_type G(m_data->mutex);
return m_data->store.clear();
guard_type G(_data->mutex);
return _data->store.clear();
}
//! Test if set is empty
//! @note Thread safe
//! @warning see size()
bool empty() const {
guard_type G(m_data->mutex);
return m_data->store.empty();
guard_type G(_data->mutex);
return _data->store.empty();
}
//! number of entries in the set at this moment
@@ -166,8 +166,8 @@ public:
//! @warning May be momentarily inaccurate (larger) due to dead refs.
//! which have not yet been removed.
size_t size() const {
guard_type G(m_data->mutex);
return m_data->store.size();
guard_type G(_data->mutex);
return _data->store.size();
}
//! Insert a new entry into the set
@@ -178,8 +178,8 @@ public:
//! Remove any (weak) ref to this object from the set
//! @returns the number of objects removed (0 or 1)
size_t erase(value_pointer& v) {
guard_type G(m_data->mutex);
return m_data->store.erase(v);
guard_type G(_data->mutex);
return _data->store.erase(v);
}
//! Return a set of strong references to all entries
@@ -197,7 +197,7 @@ public:
//! for use with batch operations.
//! @warning Use caution when swap()ing while holding this lock!
inline epicsMutex& mutex() const {
return m_data->mutex;
return _data->mutex;
}
//! an iterator-ish object which also locks the set during iteration
@@ -205,7 +205,7 @@ public:
weak_set& set;
epicsGuard<epicsMutex> guard;
typename store_t::iterator it, end;
XIterator(weak_set& S) :set(S), guard(S.mutex()), it(S.m_data->store.begin()), end(S.m_data->store.end()) {}
XIterator(weak_set& S) :set(S), guard(S.mutex()), it(S._data->store.begin()), end(S._data->store.end()) {}
//! yield the next live entry
value_pointer next() {
value_pointer ret;
@@ -229,14 +229,14 @@ void weak_set<T>::insert(value_pointer &v)
if(!v.unique())
throw std::invalid_argument("Only unique() references may be inserted");
guard_type G(m_data->mutex);
typename store_t::const_iterator it = m_data->store.find(v);
if(it==m_data->store.end()) { // new object
guard_type G(_data->mutex);
typename store_t::const_iterator it = _data->store.find(v);
if(it==_data->store.end()) { // new object
// wrapped strong ref. which removes from our map
value_pointer chainptr(v.get(), dtor(m_data, v));
value_pointer chainptr(v.get(), dtor(_data, v));
m_data->store.insert(chainptr);
_data->store.insert(chainptr);
v.swap(chainptr); // we only keep the chained pointer
} else {
@@ -253,9 +253,9 @@ typename weak_set<T>::set_type
weak_set<T>::lock_set() const
{
set_type ret;
guard_type G(m_data->mutex);
for(typename store_t::const_iterator it=m_data->store.begin(),
end=m_data->store.end(); it!=end; ++it)
guard_type G(_data->mutex);
for(typename store_t::const_iterator it=_data->store.begin(),
end=_data->store.end(); it!=end; ++it)
{
value_pointer P(it->lock());
if(P) ret.insert(P);
@@ -275,10 +275,10 @@ weak_set<T>::lock_vector() const
template<typename T>
void weak_set<T>::lock_vector(vector_type& ret) const
{
guard_type G(m_data->mutex);
ret.reserve(m_data->store.size());
for(typename store_t::const_iterator it=m_data->store.begin(),
end=m_data->store.end(); it!=end; ++it)
guard_type G(_data->mutex);
ret.reserve(_data->store.size());
for(typename store_t::const_iterator it=_data->store.begin(),
end=_data->store.end(); it!=end; ++it)
{
value_pointer P(it->lock());
if(P) ret.push_back(P);
+1
View File
@@ -16,6 +16,7 @@ LIBRARY += qsrv
SHRLIB_VERSION ?= $(EPICS_QSRV_ABI_MAJOR_VERSION).$(EPICS_QSRV_ABI_MINOR_VERSION)
USR_CPPFLAGS += -DQSRV_API_BUILDING
USR_CPPFLAGS += -I$(TOP)/common -I$(TOP)/p2pApp
INC += pv/qsrv.h
-1
View File
@@ -14,7 +14,6 @@
#include <pv/configuration.h>
#include <pv/json.h>
#define epicsExportSharedSymbols
#include "pdbgroup.h"
namespace {
-1
View File
@@ -13,7 +13,6 @@
#include <pv/pvData.h>
#include <pv/anyscalar.h>
#define epicsExportSharedSymbols
#include "pvif.h"
namespace pvd = epics::pvData;
-1
View File
@@ -19,7 +19,6 @@
#include <pv/pvAccess.h>
#include <pv/configuration.h>
#define epicsExportSharedSymbols
#include "helper.h"
#include "pdbsingle.h"
#include "pvif.h"
+2 -2
View File
@@ -30,7 +30,7 @@ struct PDBPV
virtual void show(int lvl) {}
};
struct epicsShareClass PDBProvider : public epics::pvAccess::ChannelProvider,
struct QSRV_API PDBProvider : public epics::pvAccess::ChannelProvider,
public epics::pvAccess::ChannelFind,
public std::tr1::enable_shared_from_this<PDBProvider>
{
@@ -67,7 +67,7 @@ struct epicsShareClass PDBProvider : public epics::pvAccess::ChannelProvider,
static size_t num_instances;
};
epicsShareFunc
QSRV_API
void QSRVRegistrar_counters();
#endif // PDB_H
+12 -2
View File
@@ -13,7 +13,6 @@
#include <pv/configuration.h>
#include <pv/epicsException.h>
#define epicsExportSharedSymbols
#include "helper.h"
#include "pdbgroup.h"
#include "pdb.h"
@@ -139,6 +138,15 @@ PDBGroupPV::connect(const std::tr1::shared_ptr<PDBProvider>& prov,
const pva::ChannelRequester::shared_pointer& req)
{
PDBGroupChannel::shared_pointer ret(new PDBGroupChannel(shared_from_this(), prov, req));
ret->cred.update(req);
ret->aspvt.resize(members.size());
for(size_t i=0, N=members.size(); i<N; i++)
{
ret->aspvt[i].add(members[i].chan, ret->cred);
}
return ret;
}
@@ -368,7 +376,9 @@ void PDBGroupPut::put(pvd::PVStructure::shared_pointer const & value,
DBScanLocker L(dbChannelRecord(info.chan));
ret |= putpvif[i]->get(*changed, info.allowProc ? doProc : PVIF::ProcInhibit);
ret |= putpvif[i]->get(*changed,
info.allowProc ? doProc : PVIF::ProcInhibit,
channel->aspvt[i].canWrite());
}
}
+8 -5
View File
@@ -19,9 +19,9 @@
#include <shareLib.h>
struct epicsShareClass GroupConfig
struct QSRV_API GroupConfig
{
struct epicsShareClass Field {
struct QSRV_API Field {
std::string type, channel, trigger, id;
int putorder;
@@ -36,7 +36,7 @@ struct epicsShareClass GroupConfig
}
};
struct epicsShareClass Group {
struct QSRV_API Group {
typedef std::map<std::string, Field> fields_t;
fields_t fields;
bool atomic, atomic_set;
@@ -70,7 +70,7 @@ struct PDBGroupMonitor;
void pdb_group_event(void *user_arg, struct dbChannel *chan,
int eventsRemaining, struct db_field_log *pfl);
struct epicsShareClass PDBGroupPV : public PDBPV
struct QSRV_API PDBGroupPV : public PDBPV
{
POINTER_DEFINITIONS(PDBGroupPV);
weak_pointer weakself;
@@ -133,12 +133,15 @@ struct epicsShareClass PDBGroupPV : public PDBPV
virtual void show(int lvl) OVERRIDE;
};
struct epicsShareClass PDBGroupChannel : public BaseChannel,
struct QSRV_API PDBGroupChannel : public BaseChannel,
public std::tr1::enable_shared_from_this<PDBGroupChannel>
{
POINTER_DEFINITIONS(PDBGroupChannel);
PDBGroupPV::shared_pointer pv;
std::vector<ASCLIENT> aspvt;
// storage referenced from aspvt
ASCred cred;
static size_t num_instances;
+21 -4
View File
@@ -5,15 +5,16 @@
#include <dbAccess.h>
#include <dbChannel.h>
#include <dbStaticLib.h>
#include <epicsAtomic.h>
#include <errlog.h>
#include <dbNotify.h>
#include <osiSock.h>
#include <epicsAtomic.h>
#include <pv/epicsException.h>
#include <pv/pvAccess.h>
#include <pv/security.h>
#include <pv/configuration.h>
#define epicsExportSharedSymbols
#include "helper.h"
#include "pdbsingle.h"
#include "pdb.h"
@@ -128,6 +129,11 @@ PDBSinglePV::connect(const std::tr1::shared_ptr<PDBProvider>& prov,
const pva::ChannelRequester::shared_pointer& req)
{
PDBSingleChannel::shared_pointer ret(new PDBSingleChannel(shared_from_this(), req));
ret->cred.update(req);
ret->aspvt.add(chan, ret->cred);
return ret;
}
@@ -200,7 +206,15 @@ PDBSingleChannel::~PDBSingleChannel()
void PDBSingleChannel::printInfo(std::ostream& out)
{
out<<"PDBSingleChannel";
if(aspvt.canWrite())
out << "RW ";
else
out << "RO ";
out<<(&cred.user[0])<<'@'<<(&cred.host[0]);
for(size_t i=0, N=cred.groups.size(); i<N; i++) {
out<<", "<<(&cred.groups[i][0]);
}
out<<"\n";
}
pva::ChannelPut::shared_pointer
@@ -337,7 +351,10 @@ void PDBSinglePut::put(pvd::PVStructure::shared_pointer const & value,
dbFldDes *fld = dbChannelFldDes(chan);
pvd::Status ret;
if(dbChannelFieldType(chan)>=DBF_INLINK && dbChannelFieldType(chan)<=DBF_FWDLINK) {
if(!channel->aspvt.canWrite()) {
ret = pvd::Status::error("Put not permitted");
} else if(dbChannelFieldType(chan)>=DBF_INLINK && dbChannelFieldType(chan)<=DBF_FWDLINK) {
try{
std::string lval(value->getSubFieldT<pvd::PVScalar>("value")->getAs<std::string>());
long status = dbChannelPutField(chan, DBF_STRING, lval.c_str(), 1);
+5 -1
View File
@@ -5,6 +5,7 @@
#include <dbAccess.h>
#include <dbNotify.h>
#include <asLib.h>
#include <dbEvent.h>
@@ -19,7 +20,7 @@
struct PDBSingleMonitor;
struct epicsShareClass PDBSinglePV : public PDBPV
struct QSRV_API PDBSinglePV : public PDBPV
{
POINTER_DEFINITIONS(PDBSinglePV);
weak_pointer weakself;
@@ -78,6 +79,9 @@ struct PDBSingleChannel : public BaseChannel,
POINTER_DEFINITIONS(PDBSingleChannel);
PDBSinglePV::shared_pointer pv;
// storage referenced from aspvt
ASCred cred;
ASCLIENT aspvt;
static size_t num_instances;
+28 -6
View File
@@ -2,7 +2,6 @@
#define PV_QSRV_H
#include <epicsVersion.h>
#include <shareLib.h>
#ifndef VERSION_INT
# define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P))
@@ -15,6 +14,29 @@
#define QSRV_ABI_VERSION_INT VERSION_INT(EPICS_QSRV_ABI_MAJOR_VERSION, EPICS_QSRV_ABI_MINOR_VERSION, 0, 0)
#if defined(QSRV_API_BUILDING) && defined(epicsExportSharedSymbols)
# error Use QSRV_API or shareLib.h not both
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
# if defined(QSRV_API_BUILDING) && defined(EPICS_BUILD_DLL)
/* building library as dll */
# define QSRV_API __declspec(dllexport)
# elif !defined(QSRV_API_BUILDING) && defined(EPICS_CALL_DLL)
/* calling library in dll form */
# define QSRV_API __declspec(dllimport)
# endif
#elif __GNUC__ >= 4
# define QSRV_API __attribute__ ((visibility("default")))
#endif
#ifndef QSRV_API
# define QSRV_API
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -22,12 +44,12 @@ extern "C" {
struct link; /* aka. DBLINK from link.h */
/** returns QSRV_VERSION_INT captured at compilation time */
epicsShareExtern unsigned qsrvVersion(void);
QSRV_API unsigned qsrvVersion(void);
/** returns QSRV_ABI_VERSION_INT captured at compilation time */
epicsShareExtern unsigned qsrvABIVersion(void);
QSRV_API unsigned qsrvABIVersion(void);
epicsShareFunc void testqsrvWaitForLinkEvent(struct link *plink);
QSRV_API void testqsrvWaitForLinkEvent(struct link *plink);
/** Call before testIocShutdownOk()
@code
@@ -41,7 +63,7 @@ epicsShareFunc void testqsrvWaitForLinkEvent(struct link *plink);
testdbCleanup();
@endcode
*/
epicsShareExtern void testqsrvShutdownOk(void);
QSRV_API void testqsrvShutdownOk(void);
/** Call after testIocShutdownOk() and before testdbCleanup()
@code
@@ -55,7 +77,7 @@ epicsShareExtern void testqsrvShutdownOk(void);
testdbCleanup();
@endcode
*/
epicsShareExtern void testqsrvCleanup(void);
QSRV_API void testqsrvCleanup(void);
#ifdef __cplusplus
}
+1 -2
View File
@@ -26,13 +26,12 @@
#include <pv/reftrack.h>
#include <pva/client.h>
#include <epicsExport.h> /* defines epicsExportSharedSymbols */
#include "pv/qsrv.h"
#include "helper.h"
#include "pvif.h"
#include "pvalink.h"
#include <epicsExport.h> /* defines epicsExportSharedSymbols */
int pvaLinkDebug;
int pvaLinkIsolate;
+3 -13
View File
@@ -4,11 +4,6 @@
#include <set>
#include <map>
#ifdef epicsExportSharedSymbols
# define pvalinkEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#define EPICS_DBCA_PRIVATE_API
#include <epicsGuard.h>
#include <dbAccess.h>
@@ -44,19 +39,14 @@
#include <pv/sharedPtr.h>
#ifdef pvalinkEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvalinkEpicsExportSharedSymbols
#endif
#include "helper.h"
#include "pvif.h"
#include "tpool.h"
extern "C" {
epicsShareExtern int pvaLinkDebug;
epicsShareExtern int pvaLinkIsolate;
epicsShareExtern int pvaLinkNWorkers;
QSRV_API extern int pvaLinkDebug;
QSRV_API extern int pvaLinkIsolate;
QSRV_API extern int pvaLinkNWorkers;
}
#if 0
-3
View File
@@ -3,9 +3,6 @@
#include <pv/reftrack.h>
#define epicsExportSharedSymbols
#include <shareLib.h>
#include "pvalink.h"
int pvaLinkNWorkers = 1;
-3
View File
@@ -2,9 +2,6 @@
#include <epicsStdio.h> // redirects stdout/stderr
#define epicsExportSharedSymbols
#include <shareLib.h>
#include "pvalink.h"
namespace pvalink {
-3
View File
@@ -1,9 +1,6 @@
#include <pv/reftrack.h>
#include <alarm.h>
#define epicsExportSharedSymbols
#include <shareLib.h>
#include "pvalink.h"
namespace pvalink {
-3
View File
@@ -6,9 +6,6 @@
#include <pv/current_function.h>
#define epicsExportSharedSymbols
#include <shareLib.h>
#include "pvalink.h"
+132 -20
View File
@@ -12,14 +12,16 @@
#include <errSymTbl.h>
#include <epicsVersion.h>
#include <errlog.h>
#include <osiSock.h>
#include <pv/status.h>
#include <pv/bitSet.h>
#include <pv/pvData.h>
#include <pv/anyscalar.h>
#include <pv/reftrack.h>
#include <pv/pvAccess.h>
#include <pv/security.h>
#define epicsExportSharedSymbols
#include "sb.h"
#include "pvif.h"
@@ -34,6 +36,7 @@
#endif
namespace pvd = epics::pvData;
namespace pva = epics::pvAccess;
DBCH::DBCH(dbChannel *ch) :chan(ch)
{
@@ -66,6 +69,97 @@ void DBCH::swap(DBCH& o)
std::swap(chan, o.chan);
}
void ASCred::update(const pva::ChannelRequester::shared_pointer& req)
{
pva::PeerInfo::const_shared_pointer info(req->getPeerInfo());
std::string usertemp, hosttemp;
if(info && info->identified) {
hosttemp = info->peer;
if(info->authority=="ca") {
usertemp = info->account;
size_t sep = usertemp.find_last_of('/');
if(sep != std::string::npos) {
// prevent CA auth from claiming to be eg. "krb/someone.special"
usertemp = usertemp.substr(sep+1);
}
} else {
usertemp = info->authority + "/" + info->account;
}
const char role[] = "role/";
groups.resize(info->roles.size());
size_t idx = 0u;
for(pva::PeerInfo::roles_t::const_iterator it(info->roles.begin()), end(info->roles.end()); it!=end; ++it, idx++) {
groups[idx].resize((*it).size()+sizeof(role)); // sizeof(role) includes trailing nil
std::copy(role,
role+sizeof(role)-1,
groups[idx].begin());
std::copy(it->begin(),
it->end(),
groups[idx].begin()+sizeof(role)-1);
groups[idx][groups[idx].size()-1] = '\0';
}
} else {
// legacy and anonymous
hosttemp = req->getRequesterName();
}
// remote names have the form "IP:port"
size_t sep = hosttemp.find_first_of(':');
if(sep == std::string::npos) {
sep = hosttemp.size();
}
hosttemp.resize(sep);
host.resize(hosttemp.size()+1);
std::copy(hosttemp.begin(),
hosttemp.end(),
host.begin());
host[hosttemp.size()] = '\0';
user.resize(usertemp.size()+1);
std::copy(usertemp.begin(),
usertemp.end(),
user.begin());
user[usertemp.size()] = '\0';
}
ASCLIENT::~ASCLIENT()
{
asRemoveClient(&aspvt);
for(size_t i=0, N=grppvt.size(); i<N; i++) {
asRemoveClient(&grppvt[i]);
}
}
void ASCLIENT::add(dbChannel* chan, ASCred& cred)
{
asRemoveClient(&aspvt);
/* asAddClient() fails secure to no-permission */
(void)asAddClient(&aspvt, dbChannelRecord(chan)->asp, dbChannelFldDes(chan)->as_level, &cred.user[0], &cred.host[0]);
grppvt.resize(cred.groups.size(), 0);
for(size_t i=0, N=grppvt.size(); i<N; i++) {
asRemoveClient(&grppvt[i]);
(void)asAddClient(&grppvt[i], dbChannelRecord(chan)->asp, dbChannelFldDes(chan)->as_level, &cred.groups[i][0], &cred.host[0]);
}
}
bool ASCLIENT::canWrite() {
if(!asActive || (aspvt && asCheckPut(aspvt)))
return true;
for(size_t i=0, N=grppvt.size(); i<N; i++) {
if(grppvt[i] && asCheckPut(grppvt[i]))
return true;
}
return false;
}
PVIF::PVIF(dbChannel *ch)
:chan(ch)
{}
@@ -602,15 +696,21 @@ struct PVIFScalarNumeric : public PVIF
}
}
virtual pvd::Status get(const epics::pvData::BitSet& mask, proc_t proc) OVERRIDE FINAL
virtual pvd::Status get(const epics::pvData::BitSet& mask, proc_t proc, bool permit) OVERRIDE FINAL
{
pvd::Status ret;
bool newval = mask.logical_and(pvmeta.maskVALUEPut);
if(newval) {
getValue(pvmeta.chan, pvmeta.value.get());
if(permit)
getValue(pvmeta.chan, pvmeta.value.get());
else
ret = pvd::Status::error("Put not permitted");
}
if(newval || proc==PVIF::ProcForce) {
ret = PVIF::get(mask, proc);
if(permit)
ret = PVIF::get(mask, proc);
else
ret = pvd::Status::error("Process not permitted");
}
return ret;
}
@@ -682,6 +782,7 @@ ScalarBuilder::dtype(dbChannel *channel)
if(dbr==DBR_ENUM)
builder = builder->setId("epics:nt/NTEnum:1.0")
->addNestedStructure("value")
->setId("enum_t")
->add("index", pvd::pvInt)
->addArray("choices", pvd::pvString)
->endNested();
@@ -795,7 +896,7 @@ struct PVIFPlain : public PVIF
virtual ~PVIFPlain() {}
virtual void put(epics::pvData::BitSet& mask, unsigned dbe, db_field_log *pfl)
virtual void put(epics::pvData::BitSet& mask, unsigned dbe, db_field_log *pfl) OVERRIDE FINAL
{
if(dbe&DBE_VALUE) {
putValue(channel, field.get(), pfl);
@@ -803,20 +904,26 @@ struct PVIFPlain : public PVIF
}
}
virtual pvd::Status get(const epics::pvData::BitSet& mask, proc_t proc)
virtual pvd::Status get(const epics::pvData::BitSet& mask, proc_t proc, bool permit) OVERRIDE FINAL
{
pvd::Status ret;
bool newval = mask.get(fieldOffset);
if(newval) {
getValue(channel, field.get());
if(permit)
getValue(channel, field.get());
else
ret = pvd::Status::error("Put not permitted");
}
if(newval || proc==PVIF::ProcForce) {
ret = PVIF::get(mask, proc);
if(permit)
ret = PVIF::get(mask, proc);
else
ret = pvd::Status::error("Process not permitted");
}
return ret;
}
virtual unsigned dbe(const epics::pvData::BitSet& mask)
virtual unsigned dbe(const epics::pvData::BitSet& mask) OVERRIDE FINAL
{
// TODO: figure out how to handle various intermidiate compressed
// bitSet and enclosing.
@@ -940,7 +1047,7 @@ struct PVIFMeta : public PVIF
virtual ~PVIFMeta() {}
virtual void put(epics::pvData::BitSet& mask, unsigned dbe, db_field_log *pfl)
virtual void put(epics::pvData::BitSet& mask, unsigned dbe, db_field_log *pfl) OVERRIDE FINAL
{
mask |= meta.maskALWAYS;
if(dbe&DBE_ALARM)
@@ -949,13 +1056,15 @@ struct PVIFMeta : public PVIF
putTime(meta, dbe, pfl);
}
virtual pvd::Status get(const epics::pvData::BitSet& mask, proc_t proc)
virtual pvd::Status get(const epics::pvData::BitSet& mask, proc_t proc, bool permit) OVERRIDE FINAL
{
// can't put time/alarm
if(mask.logical_and(meta.maskALARM))
return pvd::Status::warn("Put to meta field ignored");
return pvd::Status::Ok;
}
virtual unsigned dbe(const epics::pvData::BitSet& mask)
virtual unsigned dbe(const epics::pvData::BitSet& mask) OVERRIDE FINAL
{
if(mask.logical_and(meta.maskALARM))
return DBE_ALARM;
@@ -1010,18 +1119,18 @@ struct PVIFProc : public PVIF
{
PVIFProc(dbChannel *channel) :PVIF(channel) {}
virtual void put(epics::pvData::BitSet& mask, unsigned dbe, db_field_log *pfl)
virtual void put(epics::pvData::BitSet& mask, unsigned dbe, db_field_log *pfl) OVERRIDE FINAL
{
// nothing to get
}
virtual pvd::Status get(const epics::pvData::BitSet& mask, proc_t proc)
virtual pvd::Status get(const epics::pvData::BitSet& mask, proc_t proc, bool permit) OVERRIDE FINAL
{
// always process
return PVIF::get(mask, PVIF::ProcForce);
// always process (if permitted)
return PVIF::get(mask, PVIF::ProcForce, permit);
}
virtual unsigned dbe(const epics::pvData::BitSet& mask)
virtual unsigned dbe(const epics::pvData::BitSet& mask) OVERRIDE FINAL
{
return 0;
}
@@ -1036,7 +1145,7 @@ struct ProcBuilder : public PVIFBuilder
virtual epics::pvData::FieldBuilderPtr dtype(epics::pvData::FieldBuilderPtr& builder,
const std::string& fld,
dbChannel *channel)
dbChannel *channel) OVERRIDE FINAL
{
// invisible
return builder;
@@ -1054,7 +1163,7 @@ struct ProcBuilder : public PVIFBuilder
}//namespace
pvd::Status PVIF::get(const epics::pvData::BitSet& mask, proc_t proc)
pvd::Status PVIF::get(const epics::pvData::BitSet& mask, proc_t proc, bool permit)
{
dbCommon *precord = dbChannelRecord(chan);
@@ -1066,7 +1175,10 @@ pvd::Status PVIF::get(const epics::pvData::BitSet& mask, proc_t proc)
pvd::Status ret;
if (tryproc) {
if (precord->pact) {
if (!permit) {
return pvd::Status::error("Process not permitted");
} else if (precord->pact) {
if (precord->tpro)
printf("%s: Active %s\n",
epicsThreadGetNameSelf(), precord->name);
+35 -11
View File
@@ -3,6 +3,7 @@
#include <map>
#include <asLib.h>
#include <dbAccess.h>
#include <dbChannel.h>
#include <dbStaticLib.h>
@@ -15,7 +16,7 @@
#include <pv/pvData.h>
#include <pv/anyscalar.h>
#include <shareLib.h>
#include <pv/qsrv.h>
#ifndef VERSION_INT
# define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P))
@@ -29,14 +30,20 @@
# define USE_MULTILOCK
#endif
namespace epics {
namespace pvAccess {
class ChannelRequester;
}
}
short PVD2DBR(epics::pvData::ScalarType pvt);
// copy from PVField (.value sub-field) to DBF buffer
epicsShareExtern
QSRV_API
long copyPVD2DBF(const epics::pvData::PVField::const_shared_pointer& in,
void *outbuf, short outdbf, long *outnReq);
// copy from DBF buffer to PVField (.value sub-field)
epicsShareExtern
QSRV_API
long copyDBF2PVD(const epics::pvData::shared_vector<const void>& buf,
const epics::pvData::PVField::shared_pointer& out,
epics::pvData::BitSet &changed,
@@ -62,7 +69,7 @@ union dbrbuf {
char dbf_STRING[MAX_STRING_SIZE];
};
struct epicsShareClass DBCH {
struct QSRV_API DBCH {
dbChannel *chan;
DBCH() :chan(0) {}
explicit DBCH(dbChannel *ch); // calls dbChannelOpen()
@@ -81,6 +88,23 @@ private:
void prepare();
};
struct ASCred {
// string storage must be safely mutable. cf. asAddClient()
std::vector<char> user, host;
std::vector<std::vector<char> > groups;
void update(const std::tr1::shared_ptr<epics::pvAccess::ChannelRequester>& request);
};
struct ASCLIENT {
ASCLIENTPVT aspvt;
std::vector<ASCLIENTPVT> grppvt;
ASCLIENT() :aspvt(0) {}
~ASCLIENT();
// ASCred storage must remain valid
void add(dbChannel* chan, ASCred& cred);
bool canWrite();
};
struct pdbRecordInfo {
DBENTRY ent;
pdbRecordInfo(const char *name)
@@ -254,7 +278,7 @@ struct DBManyLock
dbLocker *plock;
DBManyLock() :plock(NULL) {}
DBManyLock(const std::vector<dbCommon*>& recs, unsigned flags=0)
:plock(dbLockerAlloc((dbCommon**)&recs[0], recs.size(), flags))
:plock(dbLockerAlloc( (recs.size() > 0 ? (dbCommon**)&recs[0] : NULL), recs.size(), flags))
{
if(!plock) throw std::invalid_argument("Failed to create locker");
}
@@ -285,7 +309,7 @@ struct DBManyLocker
};
#endif
struct epicsShareClass FieldName
struct QSRV_API FieldName
{
struct Component {
std::string name;
@@ -328,7 +352,7 @@ private:
FieldName& operator=(const FieldName&);
};
struct epicsShareClass PVIF {
struct QSRV_API PVIF {
PVIF(dbChannel *ch);
virtual ~PVIF() {}
@@ -343,9 +367,9 @@ struct epicsShareClass PVIF {
//! Copy from PDB record to pvalue (call dbChannelGet())
//! caller must lock record
virtual void put(epics::pvData::BitSet& mask, unsigned dbe, db_field_log *pfl) =0;
//! Copy from pvalue to PDB record (call dbChannelPut())
//! May copy from pvalue to PDB record (call dbChannelPut())
//! caller must lock record
virtual epics::pvData::Status get(const epics::pvData::BitSet& mask, proc_t proc=ProcInhibit) =0;
virtual epics::pvData::Status get(const epics::pvData::BitSet& mask, proc_t proc=ProcInhibit, bool permit=true) =0;
//! Calculate DBE mask from changed bitset
virtual unsigned dbe(const epics::pvData::BitSet& mask) =0;
@@ -354,7 +378,7 @@ private:
PVIF& operator=(const PVIF&);
};
struct epicsShareClass PVIFBuilder {
struct QSRV_API PVIFBuilder {
virtual ~PVIFBuilder() {}
@@ -378,7 +402,7 @@ private:
PVIFBuilder& operator=(const PVIFBuilder&);
};
struct epicsShareClass ScalarBuilder : public PVIFBuilder
struct QSRV_API ScalarBuilder : public PVIFBuilder
{
virtual ~ScalarBuilder() {}
-2
View File
@@ -18,8 +18,6 @@
#include <pv/serverContext.h>
#include <pv/iocshelper.h>
#define epicsExportSharedSymbols
#include "pv/qsrv.h"
#include "pvahelper.h"
#include "pvif.h"
-1
View File
@@ -9,7 +9,6 @@
#include <pv/sharedPtr.h>
#define epicsExportSharedSymbols
#include "helper.h"
#include "tpool.h"
+1 -1
View File
@@ -44,7 +44,7 @@ testpdb_SRCS += p2pTestIoc_registerRecordDeviceDriver.cpp
testpdb_LIBS += qsrv
TESTS += testpdb
PROD_HOST += check_consist
TESTPROD_HOST += check_consist
check_consist_SRCS += check_consist.cpp
ifdef BASE_3_16