YARP
Yet Another Robot Platform
HttpCarrier.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
8 
9 #include <yarp/os/Bottle.h>
11 #include <yarp/os/DummyConnector.h>
12 #include <yarp/os/ManagedBytes.h>
13 #include <yarp/os/Property.h>
14 #include <yarp/os/Route.h>
15 #include <yarp/os/SizedWriter.h>
17 
18 using namespace yarp::os;
19 using namespace yarp::os::impl;
20 
21 static std::string quoteFree(const std::string& src)
22 {
23  std::string result;
24  for (char ch : src) {
25  if (ch == '"') {
26  result += "&quot;";
27  } else {
28  result += ch;
29  }
30  }
31  return result;
32 }
33 
34 static bool asJson(std::string& accum,
35  yarp::os::Bottle* bot,
36  std::string* hint = nullptr);
37 
38 static bool asJson(std::string& accum,
39  yarp::os::Value& v)
40 {
41  if (v.isInt32() || v.isFloat64()) {
42  accum += v.toString();
43  return true;
44  }
45  if (v.isString() || v.isVocab32()) {
46  std::string x = v.toString();
47  accum += "\"";
48  for (char ch : x) {
49  if (ch == '\n') {
50  accum += '\\';
51  accum += 'n';
52  } else if (ch == '\r') {
53  accum += '\\';
54  accum += 'r';
55  } else if (ch == '\0') {
56  accum += '\\';
57  accum += '0';
58  } else {
59  if (ch == '\\' || ch == '\"') {
60  accum += '\\';
61  }
62  accum += ch;
63  }
64  }
65  accum += "\"";
66  }
67  if (v.isList()) {
68  yarp::os::Bottle* bot = v.asList();
69  return asJson(accum, bot);
70  }
71  return false;
72 }
73 
74 static bool asJson(std::string& accum,
75  yarp::os::Bottle* bot,
76  std::string* hint)
77 {
78  if (bot == nullptr) {
79  return false;
80  }
81  bool struc = false;
82  bool struc_set = false;
83  int offset = 0;
84  int offset2 = 0;
85  std::string tag = bot->get(0).asString();
86  if (hint != nullptr) {
87  if ((*hint) == "list") {
88  struc = false;
89  struc_set = true;
90  } else if ((*hint) == "dict") {
91  struc = true;
92  struc_set = true;
93  }
94  }
95  if (!struc_set) {
96  if (tag == "list") {
97  struc = false;
98  offset = 1;
99  } else if (tag == "dict") {
100  struc = true;
101  offset = 1;
102  } else {
103  // auto-detect
104  struc = (bot->size() > 1);
105  if (bot->size() > 0) {
106  yarp::os::Value& v0 = bot->get(0);
107  if (!v0.isList()) {
108  offset2 = 1;
109  offset = 1;
110  }
111  }
112  for (size_t i = offset2; i < bot->size(); i++) {
113  yarp::os::Value& vi = bot->get(i);
114  if (!vi.isList()) {
115  struc = false;
116  break;
117  }
118  if (vi.asList()->size() != 2) {
119  struc = false;
120  break;
121  }
122  }
123  }
124  }
125  if (struc) {
126  // { ... }
127  accum += "{";
128  bool need_comma = false;
129  if (offset2 != 0) {
130  accum += "\"type\": ";
131  asJson(accum, bot->get(0));
132  need_comma = true;
133  }
134  for (size_t i = offset; i < bot->size(); i++) {
135  yarp::os::Bottle* boti = bot->get(i).asList();
136  if (boti == nullptr) {
137  continue;
138  }
139  if (need_comma) {
140  accum += ", ";
141  }
142  asJson(accum, boti->get(0));
143  accum += ": ";
144  asJson(accum, boti->get(1));
145  need_comma = true;
146  }
147  accum += "}";
148  return true;
149  }
150 
151  // [ ... ]
152  accum += "[";
153  if (offset2 != 0) {
154  offset--;
155  }
156  for (int i = offset; (size_t)i < bot->size(); i++) {
157  if (i > offset) {
158  accum += ", ";
159  }
160  asJson(accum, bot->get(i));
161  }
162  accum += "]";
163  return true;
164 }
165 
166 
167 yarp::os::impl::HttpTwoWayStream::HttpTwoWayStream(TwoWayStream* delegate, const char* txt, const char* prefix, yarp::os::Property& prop, bool writer) :
168  delegate(delegate)
169 {
170  this->isWriter = writer;
171  data = false;
172  filterData = false;
173  chunked = false;
174  if (writer) {
175  Bottle b;
176  b.addString(txt);
177  sis.add(b.toString());
178  sis.add("\n");
179  return;
180  }
181  std::string s(txt);
182  std::string sData;
183  Property& p = prop;
184  //p.fromQuery(txt);
185  format = p.check("format", Value("html")).asString();
186  outer = p.check("outer", Value("auto")).asString();
187  bool admin = p.check("admin");
188  bool req = p.check("req");
189  if (p.check("cmd")) {
190  s = p.check("cmd", Value("")).asString();
191  } else if (p.check("data") || req) {
192  if (req) {
193  s = p.check("req", Value("")).asString();
194  if (!p.check("format")) {
195  format = "json";
196  p.put("format", "json");
197  }
198  } else {
199  s = p.check("data", Value("")).asString();
200  }
201  s += " ";
202  std::string sFixed;
203  std::string var;
204  bool arg = false;
205  for (unsigned int i = 0; i < s.length(); i++) {
206  char ch = s[i];
207  if (arg) {
208  if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '_')) {
209  var += ch;
210  } else {
211  arg = false;
212  sFixed += p.check(var, Value("")).toString();
213  if (i != s.length() - 1) {
214  sFixed += ch; // omit padding
215  }
216  var = "";
217  }
218  } else {
219  if (ch == '$') {
220  arg = true;
221  } else {
222  if (i != s.length() - 1) {
223  sFixed += ch; // omit padding
224  }
225  }
226  }
227  }
228 
229  sData = sFixed;
230  if (admin) {
231  s = std::string("a\n") + sFixed;
232  } else {
233  s = std::string("d\n") + sFixed;
234  }
235  }
236 
237 
238  std::string from = prefix;
239  from += "<input type=text name=data value=\"";
240  from += quoteFree(sData);
241 
242  from += "\"><input type=submit value=\"send data\"></form></p>\n";
243  from += "<pre>\n";
244 
245  bool classic = false;
246  // support old-style messages
247  if (s.length() <= 1) {
248  classic = true;
249  }
250  if (s.length() > 1) {
251  if (s[0] == '?' || s[1] == '?') {
252  classic = true;
253  }
254  if (s[0] == 'd' && s[1] == '\n') {
255  classic = true;
256  }
257  }
258  if (s.length() >= 4) {
259  if (s[0] == 'f' && s[1] == 'o' && s[2] == 'r' && s[3] == 'm') {
260  classic = true;
261  }
262  if (s[0] == 'd' && s[1] == 'a' && s[2] == 't' && s[3] == 'a') {
263  classic = true;
264  }
265  if (s[0] == 'f' && s[1] == 'a' && s[2] == 'v' && s[3] == 'i') {
266  // kill favicon.ico, sorry
267  classic = true;
268  }
269  }
270  if (req) {
271  classic = false;
272  }
273 
274  if (classic) {
275  std::string header = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n";
276  chunked = false;
277  if (s[0] == 'r') {
278  header += "Transfer-Encoding: chunked\r\n";
279  chunked = true;
280  }
281  header += "\r\n";
282  int N = 2 * 1024;
283  std::string body = from;
284  if (chunked) {
285  body += "Reading data from port...\n";
286  header += yarp::conf::numeric::to_hex_string((int)(body.length() + N));
287  header += "\r\n";
288  }
289 
290  Bytes b1((char*)header.c_str(), header.length());
291  delegate->getOutputStream().write(b1);
292 
293  if (chunked) {
294  // chrome etc won't render until enough chars are received.
295  for (int i = 0; i < N; i++) {
296  delegate->getOutputStream().write(' ');
297  }
298  }
299 
300  Bytes b2((char*)body.c_str(), body.length());
301  delegate->getOutputStream().write(b2);
302  delegate->getOutputStream().write('\r');
303  delegate->getOutputStream().write('\n');
304  delegate->getOutputStream().flush();
305 
306  if (s.empty()) {
307  s = "*";
308  }
309  if (chunked) {
310  filterData = true;
311  }
312  for (char& ch : s) {
313  if (ch == ',') {
314  ch = '\n';
315  }
316  if (ch == '+') {
317  ch = ' ';
318  }
319  }
320  if (chunked) {
321  sis.add("r\n");
322  } else {
323  sis.add(s);
324  sis.add("\nq\n");
325  }
326 
327  } else {
328  chunked = true;
329  if (!req) {
330  if (admin) {
331  sis.add("a\n");
332  } else {
333  sis.add("d\n");
334  }
335  for (int i = 0; i < (int)s.length(); i++) {
336  if (s[i] == '/') {
337  s[i] = ' ';
338  }
339  if (s[i] == '?') {
340  s = s.substr(0, i);
341  break;
342  }
343  }
344  }
345  sis.add(s);
346  sis.add(" ");
347  sis.add(p.toString());
348  sis.add("\n");
349  }
350 }
351 
353 {
354  if (delegate != nullptr) {
355  delete delegate;
356  delegate = nullptr;
357  }
358 }
359 
361 {
362  return sis;
363 }
364 
366 {
367  return *this;
368 }
369 
371 {
372  return delegate->getLocalAddress();
373 }
374 
376 {
377  return delegate->getRemoteAddress();
378 }
379 
381 {
382  return true; //delegate->isOk();
383 }
384 
386 {
387  delegate->reset();
388 }
389 
391 { // throws
392  if (chunked || isWriter) {
393  delegate->getOutputStream().write(b);
394  } else {
395  for (size_t i = 0; i < b.length(); i++) {
396  apply(b.get()[i]);
397  }
398  }
399 }
400 
402 {
403  if (ch == '\r') {
404  return;
405  }
406  if (ch == '\n') {
407  proc = "";
409  if (addr.isValid()) {
410  if (addr.getCarrier() == "tcp" && (addr.getRegName().find("/quit") == std::string::npos)) {
411  proc += "<a href=\"http://";
412  proc += addr.getHost();
413  proc += ":";
414  proc += yarp::conf::numeric::to_string(addr.getPort());
415  proc += "\">";
416  proc += addr.getRegName();
417  proc += "</A> ";
418  size_t len = addr.getRegName().length();
419  size_t target = 30;
420  if (len < target) {
421  for (size_t i = 0; i < target - len; i++) {
422  proc += " ";
423  }
424  }
425  proc += "(";
426  proc += addr.toString();
427  proc += ")";
428  proc += "\n";
429  } else {
430  // Don't show non tcp connections
431  //proc += part;
432  //proc += "\n";
433  }
434  } else {
435  if ((part[0] == '\"' && part[1] == '[') || (part[0] == '+')) {
436  // translate this to a form
437  if (part[0] == '+') {
438  part[0] = ' ';
439  }
440  std::string org = part;
441  part = "<p><form method=post action='/form'>";
442  size_t i = 0;
443  for (i = 0; i < org.length(); i++) {
444  if (org[i] == '"') {
445  org[i] = ' ';
446  }
447  }
448  part += "<input type=hidden name=data value=\"";
449  part += org;
450  part += "\">";
451  part += org;
452  org += " ";
453  bool arg = false;
454  std::string var;
455  for (i = 0; i < org.length(); i++) {
456  char ch = org[i];
457  if (arg) {
458  if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '_')) {
459  var += ch;
460  } else {
461  arg = false;
462  part += "\n ";
463  part += var;
464  part += " ";
465  part += "<input type=text name=";
466  part += var;
467  part += " size=5 value=\"\">";
468  var = "";
469  }
470  }
471  if (ch == '$') {
472  arg = true;
473  }
474  }
475  part += "<input type=submit value=\"go\">";
476  part += "</form></p>";
477  }
478  proc += part;
479  proc += "\n";
480  }
481  if (data || !filterData) {
482  Bytes tmp((char*)proc.c_str(), proc.length());
483  delegate->getOutputStream().write(tmp);
484  delegate->getOutputStream().flush();
485  }
486  data = false;
487  if (proc[0] == 'd' || proc[0] == 'D') {
488  data = true;
489  }
490  part = "";
491  } else {
492  part += ch;
493  }
494 }
495 
497 {
498  apply('\n');
499  apply('\n');
500  delegate->close();
501 }
502 
504 {
505  delegate->beginPacket();
506 }
507 
509 {
510  delegate->endPacket();
511 }
512 
514 {
515  sis.add("r\n");
516 }
517 
519 {
520  sis.add("q\n");
521 }
522 
524 {
525  return format == "json";
526 }
527 
529 {
530  return &outer;
531 }
532 
533 
535  url(""),
536  input(""),
537  urlDone(false),
538  expectPost(false),
539  contentLength(0),
540  stream(nullptr)
541 {
542 }
543 
545 {
546  return new HttpCarrier();
547 }
548 
550 {
551  return "http";
552 }
553 
554 bool yarp::os::impl::HttpCarrier::checkHeader(const Bytes& header, const char* prefix)
555 {
556  if (header.length() == 8) {
557  std::string target = prefix;
558  for (unsigned int i = 0; i < target.length(); i++) {
559  if (!(target[i] == header.get()[i])) {
560  return false;
561  }
562  }
563  return true;
564  }
565  return false;
566 }
567 
569 {
570  bool ok = checkHeader(header, "GET /");
571  if (!ok) {
572  // http carrier accepts POST /form but not general posts
573  // (leave that to xmlrpc carrier)
574  ok = checkHeader(header, "POST /fo");
575  } else {
576  // make sure it isn't a MJPEG stream get or a websocket request
577  ok = !checkHeader(header, "GET /?ac") && !checkHeader(header, "GET /?ws");
578  }
579  return ok;
580 }
581 
583 {
584  if (header.length() == 8) {
585  bool adding = false;
586  for (unsigned int j = 0; j < 8; j++) {
587  char ch = header.get()[j];
588  if (adding) {
589  if (ch != ' ') {
590  url += ch;
591  } else {
592  urlDone = true;
593  break;
594  }
595  }
596  if (ch == '/') {
597  adding = true;
598  }
599  }
600  }
601 }
602 
604 {
605  if (header.length() == 8) {
606  std::string target = "GET / HT";
607  for (int i = 0; i < 8; i++) {
608  header.get()[i] = target[i];
609  }
610  }
611 }
612 
614 {
615  return false;
616 }
617 
619 {
620  return true;
621 }
622 
623 
625 {
626  return true;
627 }
628 
630 {
631  std::string target = "GET / HTTP/1.0\r\n";
632  std::string path = proto.getRoute().getToName();
633  if (path.size() >= 2) {
634  target = "GET " + path + " HTTP/1.0\r\n";
635  }
636  Contact host = proto.getRoute().getToContact();
637  if (!host.getHost().empty()) {
638  target += "Host: ";
639  target += host.getHost();
640  target += "\r\n";
641  }
642  target += "\r\n";
643  Bytes b((char*)target.c_str(), target.length());
644  proto.os().write(b);
645  return true;
646 }
647 
649 {
650  Route route = proto.getRoute();
651  route.setFromName("web");
652  proto.setRoute(route);
653  std::string remainder = proto.is().readLine();
654  if (!urlDone) {
655  for (char i : remainder) {
656  if (i != ' ') {
657  url += i;
658  } else {
659  break;
660  }
661  }
662  }
663 
664  bool done = false;
665  expectPost = false;
666  contentLength = 0;
667  while (!done) {
668  std::string result = proto.is().readLine();
669  if (result.empty()) {
670  done = true;
671  } else {
672  //printf(">>> %s\n", result.c_str());
673  Bottle b;
674  b.fromString(result);
675  if (b.get(0).asString() == "Content-Length:") {
676  //printf("]]] got length %d\n", b.get(1).asInt32());
677  contentLength = b.get(1).asInt32();
678  }
679  if (b.get(0).asString() == "Content-Type:") {
680  //printf("]]] got type %s\n", b.get(1).asString());
681  if (b.get(1).asString() == "application/x-www-form-urlencoded") {
682  expectPost = true;
683  }
684  }
685  }
686  }
687 
688  if (expectPost) {
689  //printf("[[[this is a post message of length %d]]]\n", contentLength);
690  ManagedBytes blk(contentLength + 1);
691  Bytes start(blk.get(), contentLength);
692  proto.is().readFull(start);
693  blk.get()[contentLength] = '\0';
694  //printf("message: %s\n", blk.get());
695  input = blk.get();
696  } else {
697  //printf("message: %s\n", url.c_str());
698  input = url;
699  }
700  prop.fromQuery(input.c_str());
701  prop.put("REQUEST_URI", url);
702  //printf("Property %s\n", prop.toString().c_str());
703 
705  Contact me = proto.getStreams().getLocalAddress();
706 
707  std::string from = "<html><head><link href=\"http://";
708  from += home.getHost();
709  from += ":";
710  from += yarp::conf::numeric::to_string(home.getPort());
711  from += R"(/web/main.css" rel="stylesheet" type="text/css"/></head><body bgcolor='#ffffcc'><h1>yarp port )";
712  from += proto.getRoute().getToName();
713  from += "</h1>\n";
714 
715  from += "<p>(<a href=\"http://";
716  from += home.getHost();
717  from += ":";
718  from += yarp::conf::numeric::to_string(home.getPort());
719  from += "/data=list\">All ports</a>)&nbsp;&nbsp;\n";
720 
721  from += "(<a href=\"http://";
722  from += me.getHost();
723  from += ":";
725  from += "/\">connections</a>)&nbsp;&nbsp;\n";
726 
727  from += "(<a href=\"http://";
728  from += me.getHost();
729  from += ":";
731  from += "/data=help\">help</a>)&nbsp;&nbsp;\n";
732 
733  from += "(<a href=\"http://";
734  from += me.getHost();
735  from += ":";
737  from += "/r\">read</a>)&nbsp;&nbsp;\n";
738 
739  from += "</p>\n";
740  from += "<p>\n";
741  from += R"(<form method="post" action="http://)";
742  from += me.getHost();
743  from += ":";
745  from += "/form\">";
746 
747  prefix = from;
748 
749 
750  //Bytes b2((char*)from.c_str(), from.length());
751  //proto.os().write(b2);
752  //proto.os().flush();
753  // Message gets finished by the stream
754 
755  return proto.os().isOk();
756 }
757 
759 {
760  input = "";
761  yarp::conf::ssize_t len = 1;
762  while (len > 0) {
763  char buf[2];
764  Bytes b((char*)&buf[0], 1);
765  len = proto.is().read(b);
766  if (len > 0) {
767  buf[len] = '\0';
768  input += std::string(buf, len);
769  }
770  }
771  stream = new HttpTwoWayStream(proto.giveStreams(),
772  input.c_str(),
773  prefix.c_str(),
774  prop,
775  true);
776  proto.takeStreams(stream);
777  return true;
778 }
779 
780 
782 {
783  YARP_UNUSED(proto);
784  YARP_UNUSED(writer);
785  // no index
786  return true;
787 }
788 
790 {
791  YARP_UNUSED(proto);
792  // no index
793  return true;
794 }
795 
797 {
798  YARP_UNUSED(proto);
799  // no acknowledgement
800  return true;
801 }
802 
804 {
805  YARP_UNUSED(proto);
806  // no acknowledgement
807  return true;
808 }
809 
811 {
812  stream = new HttpTwoWayStream(proto.giveStreams(),
813  input.c_str(),
814  prefix.c_str(),
815  prop,
816  false);
817  proto.takeStreams(stream);
818  return true;
819 }
820 
822 {
823  DummyConnector con;
824  con.setTextMode(true);
825  for (size_t i = writer.headerLength(); i < writer.length(); i++) {
826  con.getWriter().appendBlock(writer.data(i), writer.length(i));
827  }
828  Bottle b;
829  b.read(con.getReader());
830 
831  std::string body = b.find("web").toString();
832  if (body.length() != 0) {
833  std::string header;
834  header += yarp::conf::numeric::to_hex_string((int)body.length());
835  header += "\r\n";
836 
837  Bytes b2((char*)header.c_str(), header.length());
838  proto.os().write(b2);
839 
840  Bytes b3((char*)body.c_str(), body.length());
841  proto.os().write(b3);
842 
843  proto.os().write('\r');
844  proto.os().write('\n');
845 
846  } else {
847  std::string txt = b.toString() + "\r\n";
848  std::string header;
849  header += yarp::conf::numeric::to_hex_string((int)txt.length());
850  header += "\r\n";
851  Bytes b2((char*)header.c_str(), header.length());
852  proto.os().write(b2);
853  Bytes b3((char*)txt.c_str(), txt.length());
854  proto.os().write(b3);
855  proto.os().write('\r');
856  proto.os().write('\n');
857  }
858  proto.os().flush();
859  return proto.os().isOk();
860 }
861 
863 {
864  DummyConnector con;
865  con.setTextMode(true);
866  for (size_t i = writer.headerLength(); i < writer.length(); i++) {
867  con.getWriter().appendBlock(writer.data(i), writer.length(i));
868  }
869  Bottle b;
870  b.read(con.getReader());
871 
872  std::string mime = b.check("mime", Value("text/html")).asString();
873 
874  std::string body;
875 
876  bool using_json = false;
877  if (stream != nullptr) {
878  if (stream->useJson()) {
879  mime = "text/json";
880  asJson(body, &b, stream->typeHint());
881  using_json = true;
882  }
883  }
884 
885  if (b.check("web") && !using_json) {
886  body = b.find("web").toString();
887  }
888 
889  if (b.check("stream") && !using_json) {
890  std::string header("HTTP/1.1 200 OK\r\nContent-Type: ");
891  header += mime;
892  header += "\r\n";
893  header += "Transfer-Encoding: chunked\r\n";
894  header += "\r\n";
895  int N = 2 * 1024;
896  header += yarp::conf::numeric::to_hex_string((int)body.length() + N);
897  header += "\r\n";
898 
899  Bytes b2((char*)header.c_str(), header.length());
900  proto.os().write(b2);
901 
902  // chrome etc won't render until enough chars are received.
903  for (int i = 0; i < N; i++) {
904  proto.os().write(' ');
905  }
906 
907  Bytes b3((char*)body.c_str(), body.length());
908  proto.os().write(b3);
909 
910  proto.os().write('\r');
911  proto.os().write('\n');
912 
913 
914  if (stream != nullptr) {
915  stream->flip();
916  }
917  return true;
918  }
919 
920  if (stream != nullptr) {
921  stream->finish();
922  }
923 
924  // Could check response codes, mime types here.
925 
926  if (body.length() != 0 || using_json) {
927  std::string mime = b.check("mime", Value(using_json ? "application/json" : "text/html")).asString();
928  std::string header("HTTP/1.1 200 OK\nContent-Type: ");
929  header += mime;
930  header += "\n";
931  header += "Access-Control-Allow-Origin: *\n";
932  header += "\n";
933  Bytes b2((char*)header.c_str(), header.length());
934  proto.os().write(b2);
935 
936  //body = b.toString();
937  Bytes b3((char*)body.c_str(), body.length());
938  proto.os().write(b3);
939  } else {
940  writer.write(proto.os());
941  }
942  proto.os().flush();
943  return proto.os().isOk();
944 }
static bool asJson(std::string &accum, yarp::os::Bottle *bot, std::string *hint=nullptr)
Definition: HttpCarrier.cpp:74
static std::string quoteFree(const std::string &src)
Definition: HttpCarrier.cpp:21
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
void fromString(const std::string &text)
Initializes bottle from a string.
Definition: Bottle.cpp:204
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:251
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition: Bottle.cpp:240
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Definition: Bottle.cpp:277
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:170
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:211
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Definition: Bottle.cpp:287
A simple abstraction for a block of bytes.
Definition: Bytes.h:25
size_t length() const
Definition: Bytes.cpp:22
const char * get() const
Definition: Bytes.cpp:27
A base class for connection types (tcp, mcast, shmem, ...) which are called carriers in YARP.
Definition: Carrier.h:45
The basic state of a connection - route, streams in use, etc.
virtual TwoWayStream & getStreams()=0
Access the streams associated with the connection.
virtual const Route & getRoute() const =0
Get the route associated with this connection.
virtual TwoWayStream * giveStreams()=0
Take ownership of the streams associated with the connection.
virtual void takeStreams(TwoWayStream *streams)=0
Provide streams to be used with the connection.
InputStream & is()
Shorthand for getInputStream()
OutputStream & os()
Shorthand for getOutputStream()
virtual void setRoute(const Route &route)=0
Set the route associated with this connection.
virtual void appendBlock(const char *data, size_t len)=0
Send a block of data to the network connection.
Represents how to reach a part of a YARP network.
Definition: Contact.h:36
bool isValid() const
Checks if a Contact is tagged as valid.
Definition: Contact.cpp:298
std::string getRegName() const
Get the name associated with this Contact.
Definition: Contact.cpp:217
std::string toString() const
Get a textual representation of the Contact.
Definition: Contact.cpp:303
int getPort() const
Get the port number associated with this Contact for socket communication.
Definition: Contact.cpp:239
std::string getCarrier() const
Get the carrier associated with this Contact for socket communication.
Definition: Contact.cpp:250
std::string getHost() const
Get the host name associated with this Contact for socket communication.
Definition: Contact.cpp:228
A dummy connection to test yarp::os::Portable implementations.
ConnectionWriter & getWriter()
Get the dummy ConnectionWriter loaded with whatever was written the ConnectionWriter since it was las...
void setTextMode(bool textmode)
Set the textMode of the dummy connection.
ConnectionReader & getReader(ConnectionWriter *replyWriter=nullptr)
Get the dummy ConnectionReader loaded with whatever was written the ConnectionWriter since it was las...
Simple specification of the minimum functions needed from input streams.
Definition: InputStream.h:26
virtual int read()
Read and return a single byte.
Definition: InputStream.cpp:20
yarp::conf::ssize_t readFull(Bytes &b)
Keep reading until buffer is full.
Definition: InputStream.cpp:96
std::string readLine(const char terminal='\n', bool *success=nullptr)
Read a block of text terminated with a specific marker (or EOF).
Definition: InputStream.cpp:54
An abstraction for a block of bytes, with optional responsibility for allocating/destroying that bloc...
Definition: ManagedBytes.h:22
const char * get() const
static Contact getNameServerContact()
Get the contact information for the port associated with the nameserver (usually "/root",...
Definition: Network.cpp:1360
Simple specification of the minimum functions needed from output streams.
Definition: OutputStream.h:22
virtual void flush()
Make sure all pending write operations are finished.
virtual bool isOk() const =0
Check if the stream is ok or in an error state.
virtual void write(char ch)
Write a single byte to the stream.
A class for storing options and configuration information.
Definition: Property.h:34
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Property.cpp:1069
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition: Property.cpp:1015
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Definition: Property.cpp:1041
Information about a connection between two ports.
Definition: Route.h:29
const std::string & getToName() const
Get the destination of the route.
Definition: Route.cpp:103
void setFromName(const std::string &fromName)
Set the source of the route.
Definition: Route.cpp:98
const Contact & getToContact() const
Get the destination contact of the route, if available.
Definition: Route.cpp:113
Minimal requirements for an efficient Writer.
Definition: SizedWriter.h:33
virtual void write(OutputStream &os)
Definition: SizedWriter.cpp:16
virtual size_t headerLength() const =0
virtual size_t length() const =0
virtual const char * data(size_t index) const =0
void add(const std::string &txt)
A stream which can be asked to perform bidirectional communication.
Definition: TwoWayStream.h:26
virtual OutputStream & getOutputStream()=0
Get an OutputStream to write to.
virtual const Contact & getLocalAddress() const =0
Get the address of the local side of the stream.
A single value (typically within a Bottle).
Definition: Value.h:45
virtual bool isString() const
Checks if value is a string.
Definition: Value.cpp:156
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:204
virtual bool isList() const
Checks if value is a list.
Definition: Value.cpp:162
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:240
virtual bool isFloat64() const
Checks if value is a 64-bit floating point number.
Definition: Value.cpp:150
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Value.cpp:356
virtual bool isInt32() const
Checks if value is a 32-bit integer.
Definition: Value.cpp:132
virtual bool isVocab32() const
Checks if value is a vocabulary identifier.
Definition: Value.cpp:174
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
Communicating via http.
Definition: HttpCarrier.h:97
Carrier * create() const override
Factory method.
void getHeader(Bytes &header) const override
Provide 8 bytes describing this connection sufficiently to allow the other side of a connection to se...
std::string getName() const override
Get the name of this connection type ("tcp", "mcast", "shmem", ...)
bool isTextMode() const override
Check if carrier is textual in nature.
bool respondToHeader(ConnectionState &proto) override
Respond to the header.
bool expectReplyToHeader(ConnectionState &proto) override
Process reply to header, if one is expected for this carrier.
bool reply(ConnectionState &proto, SizedWriter &writer) override
bool sendAck(ConnectionState &proto) override
Send an acknowledgement, if needed for this carrier.
bool sendHeader(ConnectionState &proto) override
Write a header appropriate to the carrier to the connection, followed by any carrier-specific data.
bool expectAck(ConnectionState &proto) override
Receive an acknowledgement, if expected for this carrier.
bool checkHeader(const Bytes &header, const char *prefix)
bool requireAck() const override
Check if carrier has flow control, requiring sent messages to be acknowledged by recipient.
bool supportReply() const override
This flag is used by YARP to determine whether the connection can carry RPC traffic,...
bool write(ConnectionState &proto, SizedWriter &writer) override
Write a message.
bool expectSenderSpecifier(ConnectionState &proto) override
Expect the name of the sending port.
bool expectIndex(ConnectionState &proto) override
Expect a message header, if there is one for this carrier.
void setParameters(const Bytes &header) override
Configure this carrier based on the first 8 bytes of the connection.
bool sendIndex(ConnectionState &proto, SizedWriter &writer) override
Minimal http connection support.
Definition: HttpCarrier.h:48
bool isOk() const override
Check if the stream is ok or in an error state.
OutputStream & getOutputStream() override
Get an OutputStream to write to.
void beginPacket() override
Mark the beginning of a logical packet.
HttpTwoWayStream(TwoWayStream *delegate, const char *txt, const char *prefix, yarp::os::Property &prop, bool writer)
void endPacket() override
Mark the end of a logical packet (see beginPacket).
const Contact & getLocalAddress() const override
Get the address of the local side of the stream.
InputStream & getInputStream() override
Get an InputStream to read from.
virtual void apply(char ch)
void reset() override
Reset the stream.
const Contact & getRemoteAddress() const override
Get the address of the remote side of the stream.
void write(const Bytes &b) override
Write a block of bytes to the stream.
void close() override
Terminate the stream.
static Contact extractAddress(const std::string &txt)
Extract an address from its text representation.
Definition: NameClient.cpp:270
std::string home()
Returns the home directory for current user.
Definition: dirs.h:86
std::string to_hex_string(IntegerType i)
Definition: numeric.h:321
std::string to_string(IntegerType x)
Definition: numeric.h:115
::ssize_t ssize_t
Definition: numeric.h:86
The components from which ports and connections are built.
An interface to the operating system, including Port based communication.
#define YARP_UNUSED(var)
Definition: api.h:162