libcyberradio  22.01.24
DataPort.cpp
1 /***************************************************************************
2  * \file DataPort.cpp
3  * \brief Defines the basic 10GigE data port interface for an
4  * NDR-class radio.
5  * \author DA
6  * \author NH
7  * \author MN
8  * \copyright (c) 2017 CyberRadio Solutions, Inc. All rights reserved.
9  *
10  ***************************************************************************/
11 
12 #include "LibCyberRadio/Driver/DataPort.h"
13 #include "LibCyberRadio/Driver/RadioHandler.h"
14 #include "LibCyberRadio/Common/Pythonesque.h"
15 #include <boost/lexical_cast.hpp>
16 #include <sstream>
17 
18 
19 namespace LibCyberRadio
20 {
21 
22  namespace Driver
23  {
24 
25  DataPort::DataPort(const std::string& name,
26  int index,
27  RadioHandler* parent,
28  bool debug,
29  const std::string& sourceIP,
30  int numDataPortDipEntries,
31  int dataPortDipEntryIndexBase) :
32  Configurable(name, debug),
33  _index(index),
34  _parent(parent),
35  _sourceIP(sourceIP),
36  _numDipEntries(numDataPortDipEntries),
37  _dipEntryIndexBase(dataPortDipEntryIndexBase),
38  _errorsEnabled(true),
39  _flowControlEnabled(true)
40  {
42  }
43 
45  {
46  }
47 
48  DataPort::DataPort(const DataPort& other) :
49  Configurable(other),
50  _index(other._index),
51  _parent(other._parent),
52  _sourceIP(other._sourceIP),
53  _numDipEntries(other._numDipEntries),
54  _macAddresses(other._macAddresses),
55  _ipAddresses(other._ipAddresses),
56  _sourcePorts(other._sourcePorts),
57  _destPorts(other._destPorts),
58  _dipEntryIndexBase(other._dipEntryIndexBase),
59  _errorsEnabled(other._errorsEnabled),
60  _flowControlEnabled(other._flowControlEnabled)
61  {
62  }
63 
65  {
67  if ( this != &other )
68  {
69  _index = other._index;
70  _parent = other._parent;
71  _sourceIP = other._sourceIP;
72  _numDipEntries = other._numDipEntries;
73  _macAddresses = other._macAddresses;
74  _ipAddresses = other._ipAddresses;
75  _sourcePorts = other._sourcePorts;
76  _destPorts = other._destPorts;
77  _dipEntryIndexBase = other._dipEntryIndexBase;
78  _errorsEnabled = other._errorsEnabled;
79  _flowControlEnabled = other._flowControlEnabled;
80  }
81  return *this;
82  }
83 
85  {
86  this->debug("[DataPort::setConfiguration] Called\n");
87  // Call the base-class version to modify the configuration dictionary
88  bool ret = Configurable::setConfiguration(cfg);
89  // Use the keys provided in the *incoming* dictionary to determine
90  // what needs to be changed.
91  if ( cfg.hasKey("sourceIP") && _config.hasKey("sourceIP") )
92  {
93  ret &= setSourceIP(cfg["sourceIP"]);
94  }
95  if ( cfg.hasKey("errors") && _config.hasKey("errors") )
96  {
97  ret &= enableErrors( cfg["errors"].asBool() );
98  }
99  if ( cfg.hasKey("flowControl") && _config.hasKey("flowControl") )
100  {
101  ret &= enableFlowControl( cfg["flowControl"].asBool() );
102  }
103  this->debug("[DataPort::setConfiguration] Returning\n");
104  return ret;
105  }
106 
108  {
109  this->debug("[DataPort::queryConfiguration] Called\n");
110  // Query source and destination information
111  if ( _config.hasKey("sourceIP") )
112  executeSourceIPQuery(_index, _sourceIP);
113  if ( _config.hasKey("errors") )
114  executeErrorEnabledQuery(_index, _errorsEnabled);
115  if ( _config.hasKey("flowControl") )
116  executeFlowControlEnabledQuery(_index, _flowControlEnabled);
117  for (int dipIndex = _dipEntryIndexBase;
118  dipIndex < _dipEntryIndexBase + _numDipEntries;
119  dipIndex++)
120  {
121  executeDestIPQuery(_index, dipIndex,
122  _macAddresses[dipIndex],
123  _ipAddresses[dipIndex],
124  _sourcePorts[dipIndex],
125  _destPorts[dipIndex]);
126  }
128  this->debug("[DataPort::queryConfiguration] Returning\n");
129  }
130 
132  {
133  return _numDipEntries;
134  }
135 
137  {
138  BasicIntList ret;
139  for (int dipIndex = _dipEntryIndexBase;
140  dipIndex < _dipEntryIndexBase + _numDipEntries;
141  dipIndex++)
142  {
143  ret.push_back(dipIndex);
144  }
145  return ret;
146  }
147 
148  std::string DataPort::getSourceIP() const
149  {
150  return _sourceIP;
151  }
152 
153  bool DataPort::setSourceIP(const std::string& ipAddr)
154  {
155  bool ret = false;
156  if ( _config.hasKey("sourceIP") )
157  {
158  std::string adjSourceIP = ipAddr;
159  ret = executeSourceIPCommand(_index, adjSourceIP);
160  if ( ret )
161  {
162  _sourceIP = adjSourceIP;
164  }
165  }
166  return ret;
167  }
168 
169  std::string DataPort::getDestMACAddress(int dipIndex) const
170  {
171  std::string ret;
172  if ( _macAddresses.find(dipIndex) != _macAddresses.end() )
173  ret = _macAddresses.at(dipIndex);
174  return ret;
175  }
176 
177  std::string DataPort::getDestIPAddress(int dipIndex) const
178  {
179  std::string ret;
180  if ( _ipAddresses.find(dipIndex) != _ipAddresses.end() )
181  ret = _ipAddresses.at(dipIndex);
182  return ret;
183  }
184 
185  unsigned int DataPort::getDestSourcePort(int dipIndex) const
186  {
187  int ret = 0;
188  if ( _sourcePorts.find(dipIndex) != _sourcePorts.end() )
189  ret = _sourcePorts.at(dipIndex);
190  return ret;
191  }
192 
193  unsigned int DataPort::getDestDestPort(int dipIndex) const
194  {
195  int ret = 0;
196  if ( _destPorts.find(dipIndex) != _destPorts.end() )
197  ret = _destPorts.at(dipIndex);
198  return ret;
199  }
200 
201  bool DataPort::setDestInfo(int dipIndex,
202  const std::string& ipAddr,
203  const std::string& macAddr,
204  unsigned int sourcePort,
205  unsigned int destPort)
206  {
207  std::string adjIp = ipAddr;
208  std::string adjMac = macAddr;
209  unsigned int adjSrc = sourcePort;
210  unsigned int adjDst = destPort;
211  bool ret = executeDestIPCommand(_index, dipIndex, adjIp, adjMac,
212  adjSrc, adjDst);
213  if ( ret )
214  {
215  _macAddresses[dipIndex] = adjMac;
216  _ipAddresses[dipIndex] = adjIp;
217  _sourcePorts[dipIndex] = adjSrc;
218  _destPorts[dipIndex] = adjDst;
219  //updateConfigurationDict();
220  }
221  return ret;
222  }
223 
224  bool DataPort::setDestMACAddress(int dipIndex, const std::string& macAddr)
225  {
226  return setDestInfo(dipIndex,
227  _ipAddresses[dipIndex],
228  macAddr,
229  _sourcePorts[dipIndex],
230  _destPorts[dipIndex]);
231  }
232 
233  bool DataPort::setDestIPAddress(int dipIndex, const std::string& ipAddr)
234  {
235  return setDestInfo(dipIndex,
236  ipAddr,
237  _macAddresses[dipIndex],
238  _sourcePorts[dipIndex],
239  _destPorts[dipIndex]);
240  }
241 
242  bool DataPort::setDestSourcePort(int dipIndex, unsigned int sourcePort)
243  {
244  return setDestInfo(dipIndex,
245  _ipAddresses[dipIndex],
246  _macAddresses[dipIndex],
247  sourcePort,
248  _destPorts[dipIndex]);
249  }
250 
251  bool DataPort::setDestDestPort(int dipIndex, unsigned int destPort)
252  {
253  return setDestInfo(dipIndex,
254  _ipAddresses[dipIndex],
255  _macAddresses[dipIndex],
256  _sourcePorts[dipIndex],
257  destPort);
258  }
259 
260  bool DataPort::enableErrors(bool enabled)
261  {
262  bool ret = false;
263  if ( _config.hasKey("errors") )
264  {
265  bool adjEn = enabled;
266  if ( executeErrorEnabledCommand(_index, adjEn) )
267  {
268  _errorsEnabled = enabled;
270  ret = true;
271  }
272  }
273  return ret;
274  }
275 
277  {
278  return enableErrors(false);
279  }
280 
281  bool DataPort::enableFlowControl(bool enabled)
282  {
283  bool ret = false;
284  if ( _config.hasKey("errors") )
285  {
286  bool adjEn = enabled;
287  if ( executeFlowControlEnabledCommand(_index, adjEn) )
288  {
289  _flowControlEnabled = enabled;
291  ret = true;
292  }
293  }
294  return ret;
295  }
296 
298  {
299  return enableFlowControl(false);
300  }
301 
303  {
304  _config.clear();
305  //this->debug("[DataPort::initConfigurationDict] Called\n");
306  _config["sourceIP"] = _sourceIP;
307  _config["errors"] = _errorsEnabled;
308  _config["flowControl"] = _flowControlEnabled;
309  //this->debug("[DataPort::initConfigurationDict] Returning\n");
310  }
311 
313  {
314  this->debug("[DataPort::updateConfigurationDict] Called\n");
315  if ( _config.hasKey("sourceIP") )
316  setConfigurationValue("sourceIP", _sourceIP);
317  if ( _config.hasKey("errors") )
318  setConfigurationValueToBool("errors", _errorsEnabled);
319  if ( _config.hasKey("flowControl") )
320  setConfigurationValueToBool("flowControl", _flowControlEnabled);
321  this->debug("[DataPort::updateConfigurationDict] Returning\n");
322  }
323 
324  // Default implementation uses the NDR308 pattern
325  bool DataPort::executeSourceIPQuery(int index, std::string& sourceIP)
326  {
327  bool ret = false;
328  if ( (_parent != NULL) && (_parent->isConnected()) )
329  {
330  std::ostringstream oss;
331  oss << "SIP? " << index << "\n";
332  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
333  if ( _parent->getLastCommandErrorInfo() == "" )
334  {
336  Pythonesque::Replace(rsp.front(), "SIP ", ""),
337  ", ");
338  // vec[0] = Index
339  // vec[1] = Source IP address
340  sourceIP = vec[1];
341  ret = true;
342  }
343  }
344  return ret;
345  }
346 
347  // Default implementation uses the NDR308 pattern
348  bool DataPort::executeSourceIPCommand(int index, std::string& sourceIP)
349  {
350  bool ret = false;
351  if ( (_parent != NULL) && (_parent->isConnected()) )
352  {
353  std::ostringstream oss;
354  oss << "SIP " << index
355  << ", " << sourceIP
356  << "\n";
357  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
358  if ( _parent->getLastCommandErrorInfo() == "" )
359  {
360  ret = true;
361  }
362  }
363  return ret;
364  }
365 
366  // Default implementation uses the NDR308 pattern
368  int dipIndex,
369  std::string& ipAddr,
370  std::string& macAddr,
371  unsigned int& sourcePort,
372  unsigned int& destPort)
373  {
374  bool ret = false;
375  ipAddr = "";
376  macAddr = "";
377  sourcePort = 0;
378  destPort = 0;
379  if ( (_parent != NULL) && (_parent->isConnected()) &&
380  ( _macAddresses.find(dipIndex) != _macAddresses.end()) )
381  {
382  std::ostringstream oss;
383  oss << "DIP? " << index << ", " << dipIndex << "\n";
384  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
385  if ( _parent->getLastCommandErrorInfo() == "" )
386  {
387  if ( Pythonesque::Startswith(rsp.front(), "DIP") )
388  {
390  Pythonesque::Replace(rsp.front(), "DIP ", ""),
391  ", ");
392  // vec[0] = Index
393  // vec[1] = Destination index
394  // vec[2] = IP address (with lots of leading spaces)
395  //this->debug("[DataPort::executeDestIPQuery] IP addr string=\"%s\"\n", vec[2].c_str());
396  ipAddr = Pythonesque::Strip(vec[2]);
397  //this->debug("[DataPort::executeDestIPQuery] -- converted=\"%s\"\n", ipAddr.c_str());
398  // vec[3] = MAC address
399  //this->debug("[DataPort::executeDestIPQuery] MAC addr string=\"%s\"\n", vec[3].c_str());
400  macAddr = Pythonesque::Strip(vec[3]);
401  //this->debug("[DataPort::executeDestIPQuery] -- converted=\"%s\"\n", macAddr.c_str());
402  // vec[4] = UDP port
403  //this->debug("[DataPort::executeDestIPQuery] Source UDP port string=\"%s\"\n", vec[4].c_str());
404  sourcePort = boost::lexical_cast<unsigned int>(Pythonesque::Strip(vec[4]));
405  //this->debug("[DataPort::executeDestIPQuery] -- converted=%u\n", udpPort);
406  // vec[5] = Stream ID
407  //this->debug("[DataPort::executeDestIPQuery] Destination UDP string=\"%s\"\n", vec[5].c_str());
408  destPort = boost::lexical_cast<unsigned int>(Pythonesque::Strip(vec[5]));
409  //this->debug("[DataPort::executeDestIPQuery] -- converted=%u\n", streamId);
410  ret = true;
411  }
412  }
413  }
414  return ret;
415  }
416 
417  // Default implementation uses the NDR308 pattern
419  int dipIndex,
420  std::string& ipAddr,
421  std::string& macAddr,
422  unsigned int& sourcePort,
423  unsigned int& destPort)
424  {
425  bool ret = false;
426  if ( (_parent != NULL) && (_parent->isConnected()) )
427  {
428  std::ostringstream oss;
429  oss << "DIP " << index
430  << ", " << dipIndex
431  << ", " << ipAddr
432  << ", " << macAddr
433  << ", " << sourcePort
434  << ", " << destPort
435  << "\n";
436  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
437  if ( _parent->getLastCommandErrorInfo() == "" )
438  {
439  ret = true;
440  }
441  }
442  return ret;
443  }
444 
445  // Default implementation uses the NDR308 pattern
446  bool DataPort::executeErrorEnabledQuery(int index, bool& enabled)
447  {
448  bool ret = false;
449  if ( (_parent != NULL) && (_parent->isConnected()) )
450  {
451  std::ostringstream oss;
452  oss << "TGBED? " << index << "\n";
453  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
454  if ( _parent->getLastCommandErrorInfo() == "" )
455  {
457  Pythonesque::Replace(rsp.front(), "TGBED ", ""),
458  ", ");
459  // vec[0] = Index
460  // vec[1] = Disabled indicator (1 = disabled, 0 = enabled)
461  int ind = boost::lexical_cast<int>(vec[1]);
462  enabled = (ind == 0);
463  ret = true;
464  }
465  }
466  return ret;
467  }
468 
469  // Default implementation uses the NDR308 pattern
470  bool DataPort::executeErrorEnabledCommand(int index, bool& enabled)
471  {
472  bool ret = false;
473  if ( (_parent != NULL) && (_parent->isConnected()) )
474  {
475  std::ostringstream oss;
476  oss << "TGBED " << index
477  << ", " << (enabled ? 0 : 1)
478  << "\n";
479  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
480  if ( _parent->getLastCommandErrorInfo() == "" )
481  {
482  ret = true;
483  }
484  }
485  return ret;
486  }
487 
488  // Default implementation uses the NDR308 pattern
489  bool DataPort::executeFlowControlEnabledQuery(int index, bool& enabled)
490  {
491  bool ret = false;
492  if ( (_parent != NULL) && (_parent->isConnected()) )
493  {
494  std::ostringstream oss;
495  oss << "TGFC? " << index << "\n";
496  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
497  if ( _parent->getLastCommandErrorInfo() == "" )
498  {
500  Pythonesque::Replace(rsp.front(), "TGFC ", ""),
501  ", ");
502  // vec[0] = Index
503  // vec[1] = Enabled indicator (1 = enabled, 0 = disabled)
504  int ind = boost::lexical_cast<int>(vec[1]);
505  enabled = (ind == 1);
506  ret = true;
507  }
508  }
509  return ret;
510  }
511 
512  // Default implementation uses the NDR308 pattern
513  bool DataPort::executeFlowControlEnabledCommand(int index, bool& enabled)
514  {
515  bool ret = false;
516  if ( (_parent != NULL) && (_parent->isConnected()) )
517  {
518  std::ostringstream oss;
519  oss << "TGFC " << index
520  << ", " << (enabled ? 1 : 0)
521  << "\n";
522  BasicStringList rsp = _parent->sendCommand(oss.str(), 2.0);
523  if ( _parent->getLastCommandErrorInfo() == "" )
524  {
525  ret = true;
526  }
527  }
528  return ret;
529  }
530 
531 
532  } /* namespace Driver */
533 
534 } /* namespace LibCyberRadio */
535 
virtual bool setDestSourcePort(int dipIndex, unsigned int sourcePort)
Sets the source UDP port number for a given entry in the destination IP table.
Definition: DataPort.cpp:242
virtual bool setSourceIP(const std::string &ipAddr)
Sets the source IP address.
Definition: DataPort.cpp:153
virtual bool setDestInfo(int dipIndex, const std::string &ipAddr, const std::string &macAddr, unsigned int sourcePort, unsigned int destPort)
Sets the destination table information for a given entry in the DIP table.
Definition: DataPort.cpp:201
static std::string Strip(const std::string &str, const std::string &chars=" \\\)
Strips both leading and trailing whitespace from the given string.
Definition: Pythonesque.cpp:57
virtual bool hasKey(const std::string &key) const
Determines if the dictionary has the given key.
virtual bool executeFlowControlEnabledQuery(int index, bool &enabled)
Executes the flow control enabled query.
Definition: DataPort.cpp:489
virtual bool setConfigurationValueToBool(const std::string &key, const bool value)
Sets a named configuration value to a Boolean.
virtual unsigned int getDestSourcePort(int dipIndex) const
Gets the source UDP port number for a given entry in the destination IP table.
Definition: DataPort.cpp:185
virtual bool executeErrorEnabledCommand(int index, bool &enabled)
Executes the error enabled command.
Definition: DataPort.cpp:470
virtual std::string getDestIPAddress(int dipIndex) const
Gets the IP address for a given entry in the destination IP table.
Definition: DataPort.cpp:177
virtual BasicIntList getDestEntryIndexRange() const
Gets the list of destination IP table entry indices.
Definition: DataPort.cpp:136
virtual bool isConnected() const
Gets whether or not the handler is connected.
static std::string Replace(const std::string &str, const std::string &oldstr, const std::string &newstr, int count=INT_MAX)
Replaces occurrences of one substring with another within the given string.
Definition: Pythonesque.cpp:62
virtual bool enableFlowControl(bool enabled=true)
Enables flow control on the data port.
Definition: DataPort.cpp:281
virtual bool disableFlowControl()
Disables flow control on the data port.
Definition: DataPort.cpp:297
virtual void updateConfigurationDict()
Updates the configuration dictionary from object settings.
Definition: DataPort.cpp:312
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this object.
Definition: DataPort.cpp:84
virtual bool setDestMACAddress(int dipIndex, const std::string &macAddr)
Sets the MAC address for a given entry in the destination IP table.
Definition: DataPort.cpp:224
virtual bool disableErrors()
Disables errors on the data port.
Definition: DataPort.cpp:276
10GigE data port class.
Definition: DataPort.h:45
virtual std::string getSourceIP() const
Gets the source IP address.
Definition: DataPort.cpp:148
virtual bool enableErrors(bool enabled=true)
Enables errors on the data port.
Definition: DataPort.cpp:260
static BasicStringList Split(const std::string &str, const std::string &sep, int maxsplit=INT_MAX)
Splits the given string into a list of string tokens.
Definition: Pythonesque.cpp:77
virtual unsigned int getDestDestPort(int dipIndex) const
Gets the destination UDP port number for a given entry in the destination IP table.
Definition: DataPort.cpp:193
virtual bool executeSourceIPQuery(int index, std::string &ipAddr)
Executes the source IP query command.
Definition: DataPort.cpp:325
Generic radio handler class.
Definition: RadioHandler.h:54
virtual int debug(const char *format,...)
Outputs debug information.
Definition: Debuggable.cpp:95
BASIC_LIST_CONTAINER< std::string > BasicStringList
Type representing a list of strings.
Definition: BasicList.h:25
static bool Startswith(const std::string &str, const std::string &prefix, int start=0, int end=INT_MAX)
Determines if the given string starts with the specified prefix.
virtual bool executeSourceIPCommand(int index, std::string &ipAddr)
Executes the source IP set command.
Definition: DataPort.cpp:348
Defines functionality for LibCyberRadio applications.
Definition: App.h:23
A configuration dictionary.
Definition: Configurable.h:51
DataPort(const std::string &name="DATAPORT", int index=0, RadioHandler *parent=NULL, bool debug=false, const std::string &sourceIP="0.0.0.0", int numDataPortDipEntries=0, int dataPortDipEntryIndexBase=0)
Constructs a DataPort object.
Definition: DataPort.cpp:25
virtual std::string getLastCommandErrorInfo() const
Gets the error message from the last command attempted.
virtual ~DataPort()
Destroys a DataPort object.
Definition: DataPort.cpp:44
virtual bool executeFlowControlEnabledCommand(int index, bool &enabled)
Executes the flow control enabled command.
Definition: DataPort.cpp:513
virtual bool executeErrorEnabledQuery(int index, bool &enabled)
Executes the error enabled query.
Definition: DataPort.cpp:446
virtual Configurable & operator=(const Configurable &other)
Assignment operator for Configurable objects.
virtual DataPort & operator=(const DataPort &other)
Assignment operator for DataPort objects.
Definition: DataPort.cpp:64
virtual bool setDestDestPort(int dipIndex, unsigned int destPort)
Sets the destination UDP port number for a given entry in the destination IP table.
Definition: DataPort.cpp:251
virtual bool setConfiguration(ConfigurationDict &cfg)
Sets the configuration dictionary for this object.
virtual BasicStringList sendCommand(const std::string &cmdString, double timeout=-1)
Sends a command to the radio.
Base configurable object class.
Definition: Configurable.h:79
BASIC_LIST_CONTAINER< int > BasicIntList
Type representing a list of integers.
Definition: BasicList.h:27
virtual bool executeDestIPQuery(int index, int dipIndex, std::string &ipAddr, std::string &macAddr, unsigned int &sourcePort, unsigned int &destPort)
Executes the destination IP query command.
Definition: DataPort.cpp:367
virtual bool setDestIPAddress(int dipIndex, const std::string &ipAddr)
Sets the IP address for a given entry in the destination IP table.
Definition: DataPort.cpp:233
virtual void initConfigurationDict()
Initializes the configuration dictionary, defining the allowed keys.
Definition: DataPort.cpp:302
virtual int getNumDestEntries() const
Gets the number of destination IP table entries.
Definition: DataPort.cpp:131
virtual bool setConfigurationValue(const std::string &key, const std::string &value)
Sets a named configuration value to a string.
virtual bool executeDestIPCommand(int index, int dipIndex, std::string &ipAddr, std::string &macAddr, unsigned int &sourcePort, unsigned int &destPort)
Executes the destination IP set command.
Definition: DataPort.cpp:418
virtual void queryConfiguration()
Tells the object to create its configuration dictionary.
Definition: DataPort.cpp:107
virtual std::string getDestMACAddress(int dipIndex) const
Gets the MAC address for a given entry in the destination IP table.
Definition: DataPort.cpp:169