YARP
Yet Another Robot Platform
XmlRpcStream.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 "XmlRpcStream.h"
7 #include "XmlRpcValue.h"
8 #include "XmlRpcLogComponent.h"
9 
10 #include <yarp/os/Bottle.h>
11 #include <yarp/os/Value.h>
12 
13 using namespace yarp::os;
14 using YarpXmlRpc::XmlRpcValue;
15 
16 Value toValue(XmlRpcValue& v, bool outer)
17 {
18  int t = v.getType();
19  switch (t) {
20  case XmlRpcValue::TypeInt:
21  return Value((int)v);
22  break;
23  case XmlRpcValue::TypeDouble:
24  return Value((double)v);
25  break;
26  case XmlRpcValue::TypeString:
27  {
28  std::string s = (std::string)v;
29  if (s.length()==0 || s[0]!='[') {
30  return Value(s);
31  } else {
32  Value v;
33  v.fromString(s.c_str());
34  return v;
35  }
36  }
37  break;
38  case XmlRpcValue::TypeArray:
39  {
40  Value vbot;
41  Bottle *bot = vbot.asList();
42  for (int i=0; i<v.size(); i++) {
43  XmlRpcValue& v2 = v[i];
44  if (v2.getType()!=XmlRpcValue::TypeInvalid) {
45  Value v = toValue(v2,false);
46  if (i==0) {
47  std::string tag = v.asString();
48  if (tag=="list"||tag=="dict") {
49  if (!outer) {
50  bot->addString("list");
51  }
52  }
53  }
54  bot->add(v);
55  }
56  }
57  return vbot;
58  }
59  break;
60  case XmlRpcValue::TypeStruct:
61  {
62  Value vbot;
63  Bottle *bot = vbot.asList();
64  XmlRpcValue::ValueStruct& vals = v;
65  bot->addString("dict");
66  for (auto& val : vals) {
67  XmlRpcValue& v2 = val.second;
68  Bottle& sub = bot->addList();
69  sub.addString(val.first.c_str());
70  if (v2.getType()!=XmlRpcValue::TypeInvalid) {
71  sub.add(toValue(v2,false));
72  }
73  }
74  return vbot;
75  }
76  break;
77  case XmlRpcValue::TypeInvalid:
78  return Value::getNullValue();
79  break;
80  }
81  yCTrace(XMLRPCCARRIER, "Skipping %d", t);
82  return Value("(type not supported yet out of laziness)");
83 }
84 
86 {
87  yCTrace(XMLRPCCARRIER, "XMLRPC READ");
88  yarp::conf::ssize_t result = sis.read(b);
89  if (result>0) {
90  yCTrace(XMLRPCCARRIER, "RETURNING %zd bytes", result);
91  return result;
92  }
93  yCTrace(XMLRPCCARRIER, "No string");
94  if (result==0) {
95  yCTrace(XMLRPCCARRIER, "Reading...");
96  bool ok = false;
97  if (sender) {
98  client.reset();
99  } else {
100  server.reset();
101  }
102  if (firstRound) {
103  if (sender) {
104  client.read("POST /RP");
105  } else {
106  server.read("POST /RP");
107  }
108  firstRound = false;
109  }
110  char buf[1000];
111  Bytes bytes(buf,sizeof(buf));
112  while (!ok) {
113  int result2 = delegate->getInputStream().partialRead(bytes);
114  if (result2<=0) {
115  return result2;
116  }
117  std::string s(buf,result2);
118  yCTrace(XMLRPCCARRIER, "Giving %s to parser", s.c_str());
119  if (sender) {
120  ok = client.read(s);
121  } else {
122  ok = server.read(s);
123  }
124  if (ok) {
125  yCTrace(XMLRPCCARRIER, "got a block!");
126  XmlRpcValue xresult;
127  std::string prefix;
128  std::string cprefix;
129  if (sender) {
130  client.parseResponse(xresult);
131  } else {
132  cprefix = server.parseRequest(xresult);
133  bool isAdmin = false;
134  if (interpretRos) {
135  if (cprefix=="publisherUpdate") {
136  isAdmin = true;
137  }
138  if (cprefix=="requestTopic") {
139  isAdmin = true;
140  }
141  if (cprefix=="getPid") {
142  isAdmin = true;
143  }
144  if (cprefix=="getBusInfo") {
145  isAdmin = true;
146  }
147  }
148  prefix = isAdmin?"a\n":"d\n";
149  prefix += cprefix;
150  prefix += " ";
151  }
152  yCTrace(XMLRPCCARRIER, "xmlrpc block is %s", xresult.toXml().c_str());
153  Value v = toValue(xresult,true);
154  if (!v.isNull()) {
155  sis.reset(prefix + v.toString() + "\n");
156  } else {
157  sis.reset(prefix + "\n");
158  }
159  yCTrace(XMLRPCCARRIER, "String version is %s", sis.toString().c_str());
160  result = sis.read(b);
161  break;
162  }
163  }
164  }
165  yCTrace(XMLRPCCARRIER, "RETURNING %zd bytes", result);
166  return (result>0)?result:-1;
167 }
168 
169 
171 {
172  delegate->getOutputStream().write(b);
173 }
float t
const yarp::os::LogComponent & XMLRPCCARRIER()
Value toValue(XmlRpcValue &v, bool outer)
void write(const yarp::os::Bytes &b) override
Write a block of bytes to the stream.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
void add(const Value &value)
Add a Value to the bottle, at the end of the list.
Definition: Bottle.cpp:336
Bottle & addList()
Places an empty nested list in the bottle, at the end of the list.
Definition: Bottle.cpp:182
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:170
A simple abstraction for a block of bytes.
Definition: Bytes.h:25
virtual int read()
Read and return a single byte.
Definition: InputStream.cpp:20
A single value (typically within a Bottle).
Definition: Value.h:45
static Value & getNullValue()
Return an invalid, "null" Value.
Definition: Value.cpp:466
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:240
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Value.cpp:356
bool isNull() const override
Checks if the object is invalid.
Definition: Value.cpp:380
void fromString(const char *str)
Set value to correspond to a textual representation.
Definition: Value.cpp:351
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
#define yCTrace(component,...)
Definition: LogComponent.h:85
::ssize_t ssize_t
Definition: numeric.h:86
An interface to the operating system, including Port based communication.