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>
13#include <yarp/os/Property.h>
14#include <yarp/os/Route.h>
15#include <yarp/os/SizedWriter.h>
17
18using namespace yarp::os;
19using namespace yarp::os::impl;
20
21static 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
34static bool asJson(std::string& accum,
36 std::string* hint = nullptr);
37
38static bool asJson(std::string& accum,
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
74static bool asJson(std::string& accum,
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
167yarp::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 += ":";
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
554bool 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:64
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:24
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:44
The basic state of a connection - route, streams in use, etc.
OutputStream & os()
Shorthand for getOutputStream()
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.
InputStream & is()
Shorthand for getInputStream()
virtual void takeStreams(TwoWayStream *streams)=0
Provide streams to be used with the connection.
virtual TwoWayStream & getStreams()=0
Access the streams associated with the connection.
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:33
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:25
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:21
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:21
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:33
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:28
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:32
virtual void write(OutputStream &os)
Definition: SizedWriter.cpp:16
virtual const char * data(size_t index) const =0
virtual size_t headerLength() const =0
virtual size_t length() const =0
void add(const std::string &txt)
A stream which can be asked to perform bidirectional communication.
Definition: TwoWayStream.h:25
virtual const Contact & getLocalAddress() const =0
Get the address of the local side of the stream.
virtual OutputStream & getOutputStream()=0
Get an OutputStream to write to.
A single value (typically within a Bottle).
Definition: Value.h:43
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:95
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:46
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:84
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