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