YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
PortMonitor.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include <yarp/os/Log.h>
7#include <string>
10#include <yarp/os/Route.h>
11#include <yarp/os/Contactable.h>
12#include <yarp/os/LogStream.h>
13#include <yarp/os/Network.h>
14
15#include "PortMonitor.h"
16#include "MonitorLogComponent.h"
17
18
19
20using namespace yarp::os;
21
22
27// Read connection settings.
29{
31
32 portName = proto.getRoute().getToName();
33 sourceName = proto.getRoute().getFromName();
34 group = getPeers().add(portName,this);
35 if (!group) {
36 yCError(PORTMONITORCARRIER) << "Cannot find group";
37 return false;
38 }
39
40 Property options;
41 options.fromString(proto.getSenderSpecifier());
42 options.put("source", sourceName);
43 options.put("destination", portName);
44 options.put("sender_side",
45 (proto.getContactable()->getName() == sourceName) ? 1 : 0);
46 options.put("receiver_side",
47 (proto.getContactable()->getName() == portName) ? 1 : 0);
48 options.put("carrier", proto.getRoute().getCarrierName());
49 return configureFromProperty(options);
50}
51
53{
55
56 delete binder;
57 binder = nullptr;
58
59 std::string script = options.check("type", Value("lua")).asString();
60 std::string filename = options.check("file", Value("modifier")).asString();
61 std::string constraint = options.check("constraint", Value("")).asString();
62 // context is used to find the script files
63 std::string context = options.check("context", Value("")).asString();
64
65 // check which monitor should be used
66 if((binder = MonitorBinding::create(script.c_str())) == nullptr)
67 {
68 yCError(PORTMONITORCARRIER, R"(Currently only 'lua' script and 'dll' object is supported by portmonitor)");
69 return false;
70 }
71
72 // set the acceptance constraint
73 binder->setAcceptConstraint(constraint.c_str());
74
75 std::string strFile = filename;
76
77 if(script != "dll")
78 {
80 rf.setDefaultContext(context);
81 rf.configure(0, nullptr);
82 strFile = rf.findFile(filename);
83 if(strFile.empty()) {
84 strFile = rf.findFile(filename+".lua");
85 }
86 }
87
88 // provide some useful information for the monitor object
89 // which can be accessed in the create() callback.
91 info.clear();
92 info.put("filename", strFile);
93 info.put("type", script);
94 info.put("source", options.find("source").asString());
95 info.put("destination", options.find("destination").asString());
96 info.put("sender_side", options.find("sender_side").asInt32());
97 info.put("receiver_side",options.find("receiver_side").asInt32());
98 info.put("carrier", options.find("carrier").asString());
99
101 bReady = binder->load(info);
103 return bReady;
104}
105
107{
109
110 if(!bReady) {
111 return;
112 }
114 binder->setParams(params);
116}
117
119{
121
122 if(!bReady) {
123 return;
124 }
126 binder->getParams(params);
128}
129
130
132{
134
135 if(!bReady) {
136 return reader;
137 }
138
139 // When we are here,
140 // the incoming data should be accessed using localReader.
141 // The reader passed to this function is infact empty.
142 // first check if we need to call the update callback
143 if(!binder->hasUpdate()) {
144 localReader->setParentConnectionReader(&reader);
145 return *localReader;
146 }
147
149 yarp::os::Things thing;
150 thing.setConnectionReader(*localReader);
151 yarp::os::Things& result = binder->updateData(thing);
153 con.reset();
154 if(result.write(con.getWriter())) {
155 auto& cReader = con.getReader(reader.getWriter());
156 cReader.setParentConnectionReader(&reader);
157 if (result.getPortReader() != nullptr) {
158 cReader.getWriter()->setReplyHandler(*result.getPortReader());
159 }
160 return cReader;
161 }
162 return *localReader;
163}
164
166{
168
169 if(!bReady) {
170 return false;
171 }
172
173 bool result = false;
174 localReader = &reader;
175 // If no accept callback avoid calling the binder
176 if(binder->hasAccept())
177 {
179 Things thing;
180 // set the reference connection reader
181 thing.setConnectionReader(reader);
182 result = binder->acceptData(thing);
184 if(!result) {
185 return false;
186 }
187
188 // When data is read here using the reader passed to this functions,
189 // then it won't be available for modifyIncomingData(). Thus, we write
190 // it to a dummy connection and pass it to the modifyOutgoingData() using
191 // localReader.
192 // localReader points to a connection reader which contains
193 // either the original or modified data.
194 if(thing.hasBeenRead()) {
195 con.reset();
196 if(thing.write(con.getWriter())) {
197 localReader = &con.getReader(reader.getWriter());
198 }
199 }
200 }
201
202 if(group!=nullptr) {
203 getPeers().lock();
204 result = group->acceptIncomingData(this);
205 getPeers().unlock();
206 }
207 return result;
208}
209
210
212{
214
215 if(!bReady) {
216 return writer;
217 }
218
219 // If no update callback avoid calling it
220 if(!binder->hasUpdate()) {
221 return writer;
222 }
223
225 thing.reset();
226 thing.setPortWriter(const_cast<yarp::os::PortWriter*>(&writer));
227 yarp::os::Things& result = binder->updateData(thing);
229 return *result.getPortWriter();
230}
231
233{
235
236 if(!bReady) {
237 return false;
238 }
239
240 // If no accept callback avoid calling it
241 if(!binder->hasAccept()) {
242 return true;
243 }
244
246 yarp::os::Things thing;
247 thing.setPortWriter(const_cast<yarp::os::PortWriter*>(&writer));
248 bool result = binder->acceptData(thing);
250 return result;
251}
252
254{
256
257 if(!bReady) {
258 return reader;
259 }
260
261 // If no updateReply callback avoid calling it
262 if(!binder->hasUpdateReply()) {
263 return reader;
264 }
265
267 thing.reset();
268 thing.setPortReader(&reader);
269 yarp::os::Things& result = binder->updateReply(thing);
271 return *result.getPortReader();
272}
273
278ElectionOf<PortMonitorGroup> *PortMonitor::peers = nullptr;
279
280// Make a singleton manager for finding peer carriers.
281ElectionOf<PortMonitorGroup>& PortMonitor::getPeers()
282{
284
286 if (peers==nullptr) {
290 } else {
292 }
293 return *peers;
294}
295
296// Decide whether data should be accepted, for real.
298{
300
301 //bool accept = true;
302 for (auto& it : peerSet)
303 {
304 PortMonitor *peer = it.first;
305 if(peer != source)
306 {
307 peer->lock();
308 // TODO: check whether we should return false if
309 // the peer monitor object is not ready!
310 if(peer->getBinder()) {
311 peer->getBinder()->peerTrigged();
312 }
313 peer->unlock();
314 }
315 }
316 return source->getBinder()->canAccept();
317}
const yarp::os::LogComponent & PORTMONITORCARRIER()
virtual bool hasAccept()=0
virtual bool hasUpdate()=0
virtual bool hasUpdateReply()=0
virtual bool acceptData(yarp::os::Things &thing)=0
static MonitorBinding * create(const char *script_type)
factory method
virtual bool canAccept()=0
virtual bool getParams(yarp::os::Property &params)=0
virtual yarp::os::Things & updateData(yarp::os::Things &thing)=0
virtual yarp::os::Things & updateReply(yarp::os::Things &thing)=0
virtual bool setParams(const yarp::os::Property &params)=0
virtual bool peerTrigged()=0
virtual bool load(const yarp::os::Property &options)=0
virtual bool setAcceptConstraint(const char *constraint)=0
virtual bool acceptIncomingData(PortMonitor *source)
Allow to monitor and modify port data from Lua script Under development.
Definition PortMonitor.h:52
MonitorBinding * getBinder()
void lock() const
void getCarrierParams(yarp::os::Property &params) const override
Get carrier configuration and deliver it by port administrative commands.
yarp::os::ConnectionReader & modifyIncomingData(yarp::os::ConnectionReader &reader) override
Modify incoming payload data, if appropriate.
void unlock() const
const yarp::os::PortWriter & modifyOutgoingData(const yarp::os::PortWriter &writer) override
Modify outgoing payload data, if appropriate.
yarp::os::PortReader & modifyReply(yarp::os::PortReader &reader) override
Modify reply payload data, if appropriate.
void setCarrierParams(const yarp::os::Property &params) override
Configure carrier from port administrative commands.
bool configureFromProperty(yarp::os::Property &options) override
bool acceptIncomingData(yarp::os::ConnectionReader &reader) override
Determine whether incoming data should be accepted.
std::string sourceName
bool acceptOutgoingData(const yarp::os::PortWriter &writer) override
Determine whether outgoing data should be accepted.
std::string portName
bool configure(yarp::os::ConnectionState &proto) override
Class PortMonitor.
A mini-server for performing network communication in the background.
std::string getName() const override
Get name of port.
An interface for reading from a network connection.
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
virtual void setParentConnectionReader(ConnectionReader *parentConnectionReader)
Set ConnectionReader to be used for reading the envelope.
The basic state of a connection - route, streams in use, etc.
virtual const Route & getRoute() const =0
Get the route associated with this connection.
virtual std::string getSenderSpecifier() const =0
Extract a name for the sender, if the connection type supports that.
virtual Contactable * getContactable() const =0
Get the port associated with the connection.
ConnectionWriter & getWriter()
Get the dummy ConnectionWriter loaded with whatever was written the ConnectionWriter since it was las...
ConnectionReader & getReader(ConnectionWriter *replyWriter=nullptr)
Get the dummy ConnectionReader loaded with whatever was written the ConnectionWriter since it was las...
void reset()
Reset and clear the current ConnectionWriter.
static void unlock()
Call post() on a global mutual-exclusion semaphore allocated by YARP.
Definition Network.cpp:1423
static void lock()
Call wait() on a global mutual-exclusion semaphore allocated by YARP.
Definition Network.cpp:1418
Interface implemented by all objects that can read themselves from the network, such as Bottle object...
Definition PortReader.h:24
Interface implemented by all objects that can write themselves to the network, such as Bottle objects...
Definition PortWriter.h:23
A class for storing options and configuration information.
Definition Property.h:33
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition Property.cpp:987
bool check(const std::string &key) const override
Check if there exists a property of the given name.
void clear()
Remove all associations.
Helper class for finding config files and other external resources.
bool setDefaultContext(const std::string &contextName)
Sets the context for the current ResourceFinder object.
bool configure(int argc, char *argv[], bool skipFirstArgument=true)
Sets up the ResourceFinder.
std::string findFile(const std::string &name)
Find the full path to a file.
Base class for generic things.
Definition Things.h:18
bool setConnectionReader(yarp::os::ConnectionReader &reader)
set a reference to a ConnectionReader
Definition Things.cpp:46
yarp::os::PortWriter * getPortWriter()
Definition Things.cpp:31
yarp::os::PortReader * getPortReader()
Definition Things.cpp:41
bool write(yarp::os::ConnectionWriter &connection)
Definition Things.cpp:54
void setPortReader(yarp::os::PortReader *reader)
Set the reference to a PortReader object.
Definition Things.cpp:36
void setPortWriter(yarp::os::PortWriter *writer)
Set the reference to a PortWriter object.
Definition Things.cpp:26
bool hasBeenRead()
Definition Things.cpp:75
A single value (typically within a Bottle).
Definition Value.h:43
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition Value.cpp:204
virtual std::string asString() const
Get string value.
Definition Value.cpp:234
#define yCError(component,...)
#define yCAssert(component, x)
#define yCTrace(component,...)
An interface to the operating system, including Port based communication.