Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <cassert>
6 : #include <cctype>
7 : #include <cstdio>
8 : #include <stdexcept>
9 : #include <boost/static_assert.hpp>
10 : #include <boost/algorithm/string/replace.hpp>
11 :
12 : #include <base/logging.h>
13 : #include <base/util.h>
14 : #include <base/string_util.h>
15 :
16 : #include "TXMLProtocol.h"
17 :
18 : using std::string;
19 :
20 : #ifdef TXMLPROTOCOL_DEBUG_PRETTY_PRINT
21 : static const string endl = "\n";
22 : #else
23 : static const string endl = "";
24 : #endif // !TXMLPROTOCOL_DEBUG_PRETTY_PRINT
25 :
26 : namespace contrail { namespace sandesh { namespace protocol {
27 :
28 : // Static data
29 :
30 : static const uint8_t kcXMLTagO = '<';
31 : static const uint8_t kcXMLTagC = '>';
32 : static const uint8_t kcXMLSlash = '/';
33 : static const uint8_t kcXMLSBracketC = ']';
34 :
35 : static const std::string kXMLTagO("<");
36 : static const std::string kXMLTagC(">");
37 : static const std::string kXMLSoloTagC("/>");
38 : static const std::string kXMLEndTagO("</");
39 : static const std::string kXMLSlash("/");
40 : static const std::string kXMLType("type");
41 : static const std::string kXMLIdentifier("identifier");
42 : static const std::string kXMLName("name");
43 : static const std::string kXMLKey("key");
44 : static const std::string kXMLElementTagO("<element>");
45 : static const std::string kXMLElementTagC("</element>");
46 : static const std::string kXMLValue("value");
47 : static const std::string kXMLSize("size");
48 : static const std::string kXMLBoolTrue("true");
49 : static const std::string kXMLBoolFalse("false");
50 : static const std::string kXMLCDATAO("<![CDATA[");
51 : static const std::string kXMLCDATAC("]]>");
52 :
53 : static const std::string kTypeNameBool("bool");
54 : static const std::string kTypeNameByte("byte");
55 : static const std::string kTypeNameI16("i16");
56 : static const std::string kTypeNameI32("i32");
57 : static const std::string kTypeNameI64("i64");
58 : static const std::string kTypeNameU16("u16");
59 : static const std::string kTypeNameU32("u32");
60 : static const std::string kTypeNameU64("u64");
61 : static const std::string kTypeNameIPV4("ipv4");
62 : static const std::string kTypeNameIPADDR("ipaddr");
63 : static const std::string kTypeNameDouble("double");
64 : static const std::string kTypeNameStruct("struct");
65 : static const std::string kTypeNameString("string");
66 : static const std::string kTypeNameXML("xml");
67 : static const std::string kTypeNameUUID("uuid_t");
68 : static const std::string kTypeNameMap("map");
69 : static const std::string kTypeNameList("list");
70 : static const std::string kTypeNameSet("set");
71 : static const std::string kTypeNameSandesh("sandesh");
72 : static const std::string kTypeNameUnknown("unknown");
73 :
74 : static const std::string kAttrTypeSandesh("type=\"sandesh\"");
75 : static const std::string kXMLListTagO("<list ");
76 : static const std::string kXMLListTagC("</list>" + endl);
77 : static const std::string kXMLSetTagO("<set ");
78 : static const std::string kXMLSetTagC("</set>" + endl);
79 : static const std::string kXMLMapTagO("<map ");
80 : static const std::string kXMLMapTagC("</map>" + endl);
81 :
82 341325 : const std::string& TXMLProtocol::fieldTypeName(TType type) {
83 341325 : switch (type) {
84 1987 : case T_BOOL : return kTypeNameBool ;
85 0 : case T_BYTE : return kTypeNameByte ;
86 0 : case T_I16 : return kTypeNameI16 ;
87 73682 : case T_I32 : return kTypeNameI32 ;
88 12912 : case T_I64 : return kTypeNameI64 ;
89 66 : case T_U16 : return kTypeNameU16 ;
90 3945 : case T_U32 : return kTypeNameU32 ;
91 68487 : case T_U64 : return kTypeNameU64 ;
92 0 : case T_IPV4 : return kTypeNameIPV4 ;
93 0 : case T_IPADDR : return kTypeNameIPADDR ;
94 407 : case T_DOUBLE : return kTypeNameDouble ;
95 160320 : case T_STRING : return kTypeNameString ;
96 15626 : case T_STRUCT : return kTypeNameStruct ;
97 442 : case T_MAP : return kTypeNameMap ;
98 0 : case T_SET : return kTypeNameSet ;
99 3451 : case T_LIST : return kTypeNameList ;
100 0 : case T_SANDESH: return kTypeNameSandesh;
101 0 : case T_XML : return kTypeNameXML ;
102 0 : case T_UUID : return kTypeNameUUID ;
103 0 : default: return kTypeNameUnknown;
104 : }
105 : }
106 :
107 2190 : TType TXMLProtocol::getTypeIDForTypeName(const std::string &name) {
108 2190 : TType result = T_STOP; // Sentinel value
109 2190 : if (name.length() > 1) {
110 2190 : switch (name[0]) {
111 86 : case 'b':
112 86 : switch (name[1]) {
113 86 : case 'o':
114 86 : result = T_BOOL;
115 86 : break;
116 0 : case 'y':
117 0 : result = T_BYTE;
118 0 : break;
119 : }
120 86 : break;
121 0 : case 'd':
122 0 : result = T_DOUBLE;
123 0 : break;
124 738 : case 'i':
125 738 : switch (name[1]) {
126 0 : case '1':
127 0 : result = T_I16;
128 0 : break;
129 615 : case '3':
130 615 : result = T_I32;
131 615 : break;
132 123 : case '6':
133 123 : result = T_I64;
134 123 : break;
135 0 : case 'p':
136 0 : switch (name[2]) {
137 0 : case 'a':
138 0 : result = T_IPADDR;
139 0 : break;
140 0 : case 'v':
141 0 : result = T_IPV4;
142 0 : break;
143 : }
144 0 : break;
145 : }
146 738 : break;
147 123 : case 'l':
148 123 : result = T_LIST;
149 123 : break;
150 0 : case 'm':
151 0 : result = T_MAP;
152 0 : break;
153 1132 : case 's':
154 1132 : switch (name[1]) {
155 0 : case 'a':
156 0 : result = T_SANDESH;
157 0 : break;
158 0 : case 'e':
159 0 : result = T_SET;
160 0 : break;
161 1132 : case 't':
162 1132 : switch (name[3]) {
163 1046 : case 'i':
164 1046 : result = T_STRING;
165 1046 : break;
166 86 : case 'u':
167 86 : result = T_STRUCT;
168 86 : break;
169 : }
170 1132 : break;
171 : }
172 1132 : break;
173 111 : case 'u':
174 111 : switch(name[1]) {
175 0 : case '1':
176 0 : result = T_U16;
177 0 : break;
178 111 : case '3':
179 111 : result = T_U32;
180 111 : break;
181 0 : case '6':
182 0 : result = T_U64;
183 0 : break;
184 0 : case 'u':
185 0 : result = T_UUID;
186 0 : break;
187 : }
188 111 : break;
189 0 : case 'x':
190 0 : result = T_XML;
191 0 : break;
192 : }
193 : }
194 2190 : if (result == T_STOP) {
195 0 : LOG(ERROR, __func__ << "Unrecognized type: " << name);
196 : }
197 2190 : return result;
198 : }
199 :
200 696430 : static inline void formXMLAttr(std::string &dest, const std::string& name,
201 : const std::string & value) {
202 696430 : dest += name;
203 696430 : dest += "=\"";
204 696430 : dest += value;
205 696430 : dest += "\"";
206 696430 : }
207 :
208 49826 : void TXMLProtocol::indentUp() {
209 : #if TXMLPROTOCOL_DEBUG_PRETTY_PRINT
210 : indent_str_ += string(indent_inc, ' ');
211 : #endif // !TXMLPROTOCOL_DEBUG_PRETTY_PRINT
212 49826 : }
213 :
214 64489 : void TXMLProtocol::indentDown() {
215 : #if TXMLPROTOCOL_DEBUG_PRETTY_PRINT
216 : if (indent_str_.length() < (string::size_type)indent_inc) {
217 : LOG(ERROR, __func__ << "Indent string length " <<
218 : indent_str_.length() << " less than indent length " <<
219 : (string::size_type)indent_inc);
220 : return;
221 : }
222 : indent_str_.erase(indent_str_.length() - indent_inc);
223 : #endif // !TXMLPROTOOL_DEBUG_PRETTY_PRINT
224 64489 : }
225 :
226 : // Returns the number of bytes written on success, -1 otherwise
227 651322 : int32_t TXMLProtocol::writePlain(const string& str) {
228 651322 : int ret = trans_->write((uint8_t*)str.data(), str.length());
229 651322 : if (ret) {
230 0 : return -1;
231 : }
232 651322 : return str.length();
233 : }
234 :
235 : // Returns the number of bytes written on success, -1 otherwise
236 484106 : int32_t TXMLProtocol::writeIndented(const string& str) {
237 : int ret;
238 : #if TXMLPROTOCOL_DEBUG_PRETTY_PRINT
239 : ret = trans_->write((uint8_t*)indent_str_.data(), indent_str_.length());
240 : if (ret) {
241 : return -1;
242 : }
243 : #endif // !TXMLPROTOCOL_DEBUG_PRETTY_PRINT
244 484106 : ret = trans_->write((uint8_t*)str.data(), str.length());
245 484106 : if (ret) {
246 0 : return -1;
247 : }
248 484106 : return indent_str_.length() + str.length();
249 : }
250 :
251 0 : int32_t TXMLProtocol::writeMessageBegin(const std::string& name,
252 : const TMessageType messageType,
253 : const int32_t seqid) {
254 0 : return 0;
255 : }
256 :
257 0 : int32_t TXMLProtocol::writeMessageEnd() {
258 0 : return 0;
259 : }
260 :
261 33011 : int32_t TXMLProtocol::writeStructBegin(const char* name) {
262 33011 : int32_t size = 0, ret;
263 33011 : string sname(name);
264 33011 : string xml;
265 33011 : xml.reserve(512);
266 : // Form the xml tag
267 33011 : xml += kXMLTagO;
268 33011 : xml += sname;
269 33011 : xml += kXMLTagC;
270 33011 : xml += endl;
271 : // Write to transport
272 33011 : if ((ret = writeIndented(xml)) < 0) {
273 0 : LOG(ERROR, __func__ << ": " << sname << " FAILED");
274 0 : return ret;
275 : }
276 33011 : size += ret;
277 33011 : xml_state_.push_back(sname);
278 33011 : indentUp();
279 33011 : return size;
280 33011 : }
281 :
282 33011 : int32_t TXMLProtocol::writeStructEnd() {
283 33011 : indentDown();
284 33011 : int32_t size = 0, ret;
285 33011 : string etag(xml_state_.back());
286 33011 : xml_state_.pop_back();
287 33011 : string xml;
288 33011 : xml.reserve(128);
289 : // Form the xml tag
290 33011 : xml += kXMLEndTagO;
291 33011 : xml += etag;
292 33011 : xml += kXMLTagC;
293 33011 : xml += endl;
294 : // Write to transport
295 33011 : if ((ret = writeIndented(xml)) < 0) {
296 0 : LOG(ERROR, __func__ << ": " << etag << " FAILED");
297 0 : return ret;
298 : }
299 33011 : size += ret;
300 33011 : return size;
301 33011 : }
302 :
303 12922 : int32_t TXMLProtocol::writeSandeshBegin(const char* name) {
304 12922 : int32_t size = 0, ret;
305 12922 : string sname(name);
306 12922 : string xml;
307 12922 : xml.reserve(512);
308 : // Form the xml tag
309 12922 : xml += kXMLTagO;
310 12922 : xml += sname;
311 12922 : xml += " ";
312 12922 : xml += kAttrTypeSandesh;
313 12922 : xml += kXMLTagC;
314 12922 : xml += endl;
315 : // Write to transport
316 12922 : ret = writeIndented(xml);
317 12922 : if (ret < 0) {
318 0 : LOG(ERROR, __func__ << ": " << sname << " FAILED");
319 0 : return ret;
320 : }
321 12922 : size += ret;
322 12922 : xml_state_.push_back(sname);
323 12922 : indentUp();
324 12922 : return size;
325 12922 : }
326 :
327 12922 : int32_t TXMLProtocol::writeSandeshEnd() {
328 12922 : indentDown();
329 12922 : int32_t size = 0, ret;
330 12922 : string etag(xml_state_.back());
331 12922 : xml_state_.pop_back();
332 12922 : string exml;
333 12922 : exml.reserve(128);
334 : // Form the xml tag
335 12922 : exml += kXMLEndTagO;
336 12922 : exml += etag;
337 12922 : exml += kXMLTagC;
338 12922 : exml += endl;
339 : // Write to transport
340 12922 : if ((ret = writeIndented(exml)) < 0) {
341 0 : LOG(ERROR, __func__ << ": " << etag << " FAILED");
342 0 : return ret;
343 : }
344 12922 : size += ret;
345 12922 : return size;
346 12922 : }
347 :
348 14454 : int32_t TXMLProtocol::writeContainerElementBegin() {
349 14454 : return writeIndented(kXMLElementTagO);
350 : }
351 :
352 14454 : int32_t TXMLProtocol::writeContainerElementEnd() {
353 14454 : return writeIndented(kXMLElementTagC);
354 : }
355 :
356 336990 : int32_t TXMLProtocol::writeFieldBegin(const char *name,
357 : const TType fieldType,
358 : const int16_t fieldId,
359 : const std::map<std::string, std::string> *const amap) {
360 336990 : int32_t size = 0, ret;
361 336990 : string sname(name);
362 336990 : string xml;
363 336990 : xml.reserve(512);
364 : // Form the xml tag
365 336990 : xml += kXMLTagO;
366 336990 : xml += sname;
367 336990 : xml += " ";
368 336990 : formXMLAttr(xml, kXMLType, fieldTypeName(fieldType));
369 336990 : xml += " ";
370 336990 : formXMLAttr(xml, kXMLIdentifier, integerToString(fieldId));
371 336990 : if (amap != NULL) {
372 13764 : for (std::map<string, string>::const_iterator iter = amap->begin();
373 27986 : iter != amap->end(); iter++) {
374 14222 : xml += " ";
375 14222 : formXMLAttr(xml, (*iter).first, (*iter).second);
376 : }
377 : }
378 336990 : xml += kXMLTagC;
379 : // Write to transport
380 336990 : if ((ret = writeIndented(xml)) < 0) {
381 0 : LOG(ERROR, __func__ << ": " << xml << " FAILED");
382 0 : return ret;
383 : }
384 336990 : size += ret;
385 336990 : xml_state_.push_back(sname);
386 336990 : if (fieldType == T_STRUCT) {
387 14663 : write_state_.push_back(STRUCT);
388 : #ifdef TXMLPROTOCOL_DEBUG_PRETTY_PRINT
389 : if ((ret = writePlain(endl)) < 0) {
390 : LOG(ERROR, __func__ << ": " << fieldTypeName(fieldType) << " FAILED");
391 : return ret;
392 : }
393 : size += ret;
394 : indentUp();
395 : #endif // !TXMLPROTOCOL_DEBUG_PRETTY_PRINT
396 322327 : } else if (fieldType == T_SANDESH) {
397 0 : write_state_.push_back(SNDESH);
398 : #ifdef TXMLPROTOCOL_DEBUG_PRETTY_PRINT
399 : if ((ret = writePlain(endl)) < 0) {
400 : LOG(ERROR, __func__ << ": " << fieldTypeName(fieldType) << " FAILED");
401 : return ret;
402 : }
403 : size += ret;
404 : #endif // !TXMLPROTOCOL_DEBUG_PRETTY_PRINT
405 322327 : } else if (fieldType == T_LIST) {
406 3451 : write_state_.push_back(LIST);
407 : #ifdef TXMLPROTOCOL_DEBUG_PRETTY_PRINT
408 : if ((ret = writePlain(endl)) < 0) {
409 : LOG(ERROR, __func__ << ": " << fieldTypeName(fieldType) << " FAILED");
410 : return ret;
411 : }
412 : size += ret;
413 : #endif // !TXMLPROTOCOL_DEBUG_PRETTY_PRINT
414 318876 : } else if (fieldType == T_MAP) {
415 442 : write_state_.push_back(MAP);
416 : #ifdef TXMLPROTOCOL_DEBUG_PRETTY_PRINT
417 : if ((ret = writePlain(endl)) < 0) {
418 : LOG(ERROR, __func__ << ": " << fieldTypeName(fieldType) << " FAILED");
419 : return ret;
420 : }
421 : size += ret;
422 : #endif // !TXMLPROTOCOL_DEBUG_PRETTY_PRINT
423 318434 : } else if (fieldType == T_SET) {
424 0 : write_state_.push_back(SET);
425 : #ifdef TXMLPROTOCOL_DEBUG_PRETTY_PRINT
426 : if ((ret = writePlain(endl)) < 0) {
427 : LOG(ERROR, __func__ << ": " << fieldTypeName(fieldType) << " FAILED");
428 : return ret;
429 : }
430 : size += ret;
431 : #endif // !TXMLPROTOCOL_DEBUG_PRETTY_PRINT
432 : } else {
433 318434 : write_state_.push_back(UNINIT);
434 : }
435 336990 : return size;
436 336990 : }
437 :
438 336990 : int32_t TXMLProtocol::writeFieldEnd() {
439 336990 : int32_t size = 0, ret;
440 336990 : string etag(xml_state_.back());
441 336990 : xml_state_.pop_back();
442 336990 : string exml;
443 336990 : exml.reserve(128);
444 : // Form the xml tag
445 336990 : exml += kXMLEndTagO;
446 336990 : exml += etag;
447 336990 : exml += kXMLTagC;
448 336990 : exml += endl;
449 : // Write to transport
450 336990 : write_state_t state = write_state_.back();
451 336990 : if (state != STRUCT &&
452 322327 : state != SNDESH &&
453 318876 : state != LIST &&
454 318434 : state != MAP &&
455 : state != SET) {
456 318434 : if ((ret = writePlain(exml)) < 0) {
457 0 : LOG(ERROR, __func__ << ": " << etag << " " << state <<
458 : " FAILED");
459 0 : return ret;
460 : }
461 318434 : size += ret;
462 318434 : } else {
463 18556 : if (state == STRUCT) {
464 14663 : indentDown();
465 : }
466 18556 : if ((ret = writeIndented(exml)) < 0) {
467 0 : LOG(ERROR, __func__ << ": " << etag << " " << state <<
468 : " FAILED");
469 0 : return ret;
470 : }
471 18556 : size += ret;
472 : }
473 336990 : write_state_.pop_back();
474 336990 : return size;
475 336990 : }
476 :
477 45933 : int32_t TXMLProtocol::writeFieldStop() {
478 45933 : return 0;
479 : }
480 :
481 442 : int32_t TXMLProtocol::writeMapBegin(const TType keyType,
482 : const TType valType,
483 : const uint32_t size) {
484 442 : int32_t bsize = 0, ret;
485 442 : string xml;
486 442 : xml.reserve(256);
487 : // Form the xml tag
488 442 : xml += kXMLMapTagO;
489 442 : formXMLAttr(xml, kXMLKey, fieldTypeName(keyType));
490 442 : xml += " ";
491 442 : formXMLAttr(xml, kXMLValue, fieldTypeName(valType));
492 442 : xml += " ";
493 442 : formXMLAttr(xml, kXMLSize, integerToString(size));
494 442 : xml += kXMLTagC;
495 442 : xml += endl;
496 : // Write to transport
497 442 : ret = writeIndented(xml);
498 442 : if (ret < 0) {
499 0 : LOG(ERROR, __func__ << ": Key: " << fieldTypeName(keyType) <<
500 : " Value: " << fieldTypeName(valType) << " FAILED");
501 0 : return ret;
502 : }
503 442 : bsize += ret;
504 442 : indentUp();
505 442 : return bsize;
506 442 : }
507 :
508 442 : int32_t TXMLProtocol::writeMapEnd() {
509 442 : int32_t size = 0, ret;
510 442 : indentDown();
511 442 : if ((ret = writeIndented(kXMLMapTagC)) < 0) {
512 0 : LOG(ERROR, __func__ << " FAILED");
513 0 : return ret;
514 : }
515 442 : size += ret;
516 442 : return size;
517 : }
518 :
519 3451 : int32_t TXMLProtocol::writeListBegin(const TType elemType,
520 : const uint32_t size) {
521 3451 : int32_t bsize = 0, ret;
522 3451 : string xml;
523 3451 : xml.reserve(256);
524 : // Form the xml tag
525 3451 : xml += kXMLListTagO;
526 3451 : formXMLAttr(xml, kXMLType, fieldTypeName(elemType));
527 3451 : xml += " ";
528 3451 : formXMLAttr(xml, kXMLSize, integerToString(size));
529 3451 : xml += kXMLTagC;
530 3451 : xml += endl;
531 : // Write to transport
532 3451 : ret = writeIndented(xml);
533 3451 : if (ret < 0) {
534 0 : LOG(ERROR, __func__ << ": " << fieldTypeName(elemType) <<
535 : " FAILED");
536 0 : return ret;
537 : }
538 3451 : bsize += ret;
539 3451 : indentUp();
540 3451 : return bsize;
541 3451 : }
542 :
543 3451 : int32_t TXMLProtocol::writeListEnd() {
544 3451 : int32_t size = 0, ret;
545 3451 : indentDown();
546 3451 : ret = writeIndented(kXMLListTagC);
547 3451 : if (ret < 0) {
548 0 : LOG(ERROR, __func__ << " FAILED");
549 0 : return ret;
550 : }
551 3451 : size += ret;
552 3451 : return size;
553 : }
554 :
555 0 : int32_t TXMLProtocol::writeSetBegin(const TType elemType,
556 : const uint32_t size) {
557 0 : int32_t bsize = 0, ret;
558 0 : string xml;
559 0 : xml.reserve(256);
560 : // Form the xml tag
561 0 : xml += kXMLSetTagO;
562 0 : formXMLAttr(xml, kXMLType, fieldTypeName(elemType));
563 0 : xml += " ";
564 0 : formXMLAttr(xml, kXMLSize, integerToString(size));
565 0 : xml += kXMLTagC;
566 0 : xml += endl;
567 : // Write to transport
568 0 : ret = writeIndented(xml);
569 0 : if (ret < 0) {
570 0 : LOG(ERROR, __func__ << ": " << fieldTypeName(elemType) <<
571 : " FAILED");
572 0 : return ret;
573 : }
574 0 : bsize += ret;
575 0 : indentUp();
576 0 : return bsize;
577 0 : }
578 :
579 0 : int32_t TXMLProtocol::writeSetEnd() {
580 0 : int32_t size = 0, ret;
581 0 : indentDown();
582 0 : if ((ret = writeIndented(kXMLSetTagC)) < 0) {
583 0 : LOG(ERROR, __func__ << " FAILED");
584 0 : return ret;
585 : }
586 0 : size += ret;
587 0 : return size;
588 : }
589 :
590 1987 : int32_t TXMLProtocol::writeBool(const bool value) {
591 1987 : return writePlain(value ? kXMLBoolTrue : kXMLBoolFalse);
592 : }
593 :
594 0 : int32_t TXMLProtocol::writeByte(const int8_t byte) {
595 0 : return writePlain(integerToString(byte));
596 : }
597 :
598 0 : int32_t TXMLProtocol::writeI16(const int16_t i16) {
599 0 : return writePlain(integerToString(i16));
600 : }
601 :
602 73682 : int32_t TXMLProtocol::writeI32(const int32_t i32) {
603 73682 : return writePlain(integerToString(i32));
604 : }
605 :
606 12912 : int32_t TXMLProtocol::writeI64(const int64_t i64) {
607 12912 : return writePlain(integerToString(i64));
608 : }
609 :
610 66 : int32_t TXMLProtocol::writeU16(const uint16_t u16) {
611 66 : return writePlain(integerToString(u16));
612 : }
613 :
614 3945 : int32_t TXMLProtocol::writeU32(const uint32_t u32) {
615 3945 : return writePlain(integerToString(u32));
616 : }
617 :
618 70801 : int32_t TXMLProtocol::writeU64(const uint64_t u64) {
619 70801 : return writePlain(integerToString(u64));
620 : }
621 :
622 0 : int32_t TXMLProtocol::writeIPV4(const uint32_t ip4) {
623 0 : return writePlain(integerToString(ip4));
624 : }
625 :
626 0 : int32_t TXMLProtocol::writeIPADDR(const boost::asio::ip::address& ipaddress) {
627 0 : return writePlain(ipaddress.to_string());
628 : }
629 :
630 407 : int32_t TXMLProtocol::writeDouble(const double dub) {
631 407 : return writePlain(integerToString(dub));
632 : }
633 :
634 169088 : int32_t TXMLProtocol::writeString(const string& str) {
635 : // Escape XML control characters in the string before writing
636 169088 : return writePlain(escapeXMLControlChars(str));
637 : }
638 :
639 0 : int32_t TXMLProtocol::writeBinary(const string& str) {
640 : // XXX Hex?
641 0 : return writeString(str);
642 : }
643 :
644 0 : int32_t TXMLProtocol::writeXML(const string& str) {
645 0 : std::string xmlstr;
646 0 : xmlstr.reserve(str.length() + kXMLCDATAO.length() + kXMLCDATAC.length());
647 0 : xmlstr += kXMLCDATAO;
648 0 : xmlstr += str;
649 0 : xmlstr += kXMLCDATAC;
650 0 : return writePlain(xmlstr);
651 0 : }
652 :
653 0 : int32_t TXMLProtocol::writeUUID(const boost::uuids::uuid& uuid) {
654 0 : const std::string str = boost::uuids::to_string(uuid);
655 0 : return writeString(str);
656 0 : }
657 : /**
658 : * Reading functions
659 : */
660 :
661 : // Return true if the character ch is in [-+0-9]; false otherwise
662 6105 : static bool isXMLNumeric(uint8_t ch) {
663 6105 : switch (ch) {
664 5256 : case '+':
665 : case '-':
666 : case '0':
667 : case '1':
668 : case '2':
669 : case '3':
670 : case '4':
671 : case '5':
672 : case '6':
673 : case '7':
674 : case '8':
675 : case '9':
676 5256 : return true;
677 : }
678 849 : return false;
679 : }
680 :
681 : // Read 1 character from the transport trans and verify that it is the
682 : // expected character ch. Returns 1 if does, -1 if not
683 8100 : static int32_t readSyntaxChar(TXMLProtocol::LookaheadReader &reader,
684 : uint8_t ch) {
685 8100 : uint8_t ch2 = reader.read();
686 8100 : if (ch2 != ch) {
687 0 : LOG(ERROR, __func__ << ": Expected \'" << std::string((char *)&ch, 1) <<
688 : "\'; got \'" << std::string((char *)&ch2, 1) << "\'.");
689 0 : return -1;
690 : }
691 8100 : return 1;
692 : }
693 :
694 : // Reads string from the transport trans and verify that it is the
695 : // expected string str. Returns 1 if does, -1 if not
696 0 : static int32_t readSyntaxString(TXMLProtocol::LookaheadReader &reader,
697 : const std::string str) {
698 0 : int32_t result = 0, ret;
699 0 : for (std::string::const_iterator it = str.begin(); it != str.end(); it++) {
700 0 : if ((ret = readSyntaxChar(reader, *it)) < 0) {
701 0 : return ret;
702 : }
703 0 : result += ret;
704 : }
705 0 : return result;
706 : }
707 :
708 : // Reads 1 byte and verifies that it matches ch. Returns 1 if it does,
709 : // -1 otherwise
710 8100 : int32_t TXMLProtocol::readXMLSyntaxChar(uint8_t ch) {
711 8100 : return readSyntaxChar(reader_, ch);
712 : }
713 :
714 : // Reads a XML number or string and interprets it as a double.
715 0 : int32_t TXMLProtocol::readXMLDouble(double &num) {
716 0 : LOG(ERROR, __func__ << ": Not implemented in TXMLProtocol");
717 0 : assert(false);
718 : return -1;
719 : }
720 :
721 : // Reads string and verifies that it matches str. Returns 1 if it does,
722 : // -1 otherwise
723 0 : int32_t TXMLProtocol::readXMLSyntaxString(const std::string &str) {
724 0 : return readSyntaxString(reader_, str);
725 : }
726 :
727 0 : int32_t TXMLProtocol::readXMLCDATA(std::string &str) {
728 0 : int32_t result = 0, ret;
729 0 : str.clear();
730 : // Read <![CDATA[
731 0 : if ((ret = readXMLSyntaxString(kXMLCDATAO)) < 0) {
732 0 : return ret;
733 : }
734 0 : result += ret;
735 0 : uint8_t ch = 0, ch2 = 0, ch3;
736 0 : bool ch_read = false, ch2_read = false, ch3_read = false;
737 : while (true) {
738 0 : if (!ch_read) {
739 0 : ch = reader_.peek();
740 0 : reader_.read();
741 0 : ++result;
742 0 : ch_read = true;
743 : }
744 : // Did we read ]]> ?
745 0 : if (ch == kcXMLSBracketC) {
746 0 : if (!ch2_read) {
747 0 : ch2 = reader_.peek();
748 0 : reader_.read();
749 0 : ++result;
750 0 : ch2_read = true;
751 : }
752 0 : if (ch2 == kcXMLSBracketC) {
753 0 : if (!ch3_read) {
754 0 : ch3 = reader_.peek();
755 0 : reader_.read();
756 0 : ++result;
757 0 : ch3_read = true;
758 : }
759 0 : if (ch3 == kcXMLTagC) {
760 0 : break;
761 : } else {
762 : // Consume ch
763 0 : str += ch;
764 : // Rotate ch2 and ch3 and repeat
765 0 : ch = ch2;
766 0 : ch2 = ch3;
767 0 : ch3_read = false;
768 0 : continue;
769 : }
770 : } else {
771 : // Consume ch
772 0 : str += ch;
773 : // Rotate ch2 and repeat
774 0 : ch = ch2;
775 0 : ch2_read = false;
776 0 : continue;
777 : }
778 : } else {
779 0 : str += ch;
780 0 : ch_read = false;
781 : }
782 : }
783 0 : return result;
784 : }
785 :
786 : // Reads a sequence of characters, stopping at the first occurrence of xml
787 : // tag open delimiter which signals end of field and returns the string
788 : // via str.
789 1318 : int32_t TXMLProtocol::readXMLString(std::string &str) {
790 1318 : int32_t result = 0;
791 1318 : str.clear();
792 : while (true) {
793 15691 : uint8_t ch = reader_.peek();
794 15691 : if (ch == kcXMLTagO) {
795 1318 : break;
796 : }
797 14373 : reader_.read();
798 14373 : str += ch;
799 14373 : ++result;
800 14373 : }
801 1318 : return result;
802 : }
803 :
804 : // Decodes an XML tag and returns the string without the xml open
805 : // and close delimiters via str
806 5441 : int32_t TXMLProtocol::readXMLTag(std::string &str, bool endTag) {
807 5441 : int32_t result = 0, ret;
808 : uint8_t ch;
809 5441 : str.clear();
810 5441 : if ((ret = readXMLSyntaxChar(kcXMLTagO)) < 0) {
811 0 : return ret;
812 : }
813 5441 : result += ret;
814 5441 : if (endTag) {
815 2659 : if ((ret = readXMLSyntaxChar(kcXMLSlash)) < 0) {
816 0 : return ret;
817 : }
818 2659 : result += ret;
819 : }
820 : while (true) {
821 119405 : ch = reader_.read();
822 119405 : ++result;
823 119405 : if (ch == kcXMLTagC) {
824 5441 : break;
825 : }
826 113964 : str += ch;
827 : }
828 5441 : return result;
829 : }
830 :
831 : // Reads a sequence of characters, stopping at the first one that is not
832 : // a valid numeric character.
833 849 : int32_t TXMLProtocol::readXMLNumericChars(std::string &str) {
834 849 : uint32_t result = 0;
835 849 : str.clear();
836 : while (true) {
837 6105 : uint8_t ch = reader_.peek();
838 6105 : if (!isXMLNumeric(ch)) {
839 849 : break;
840 : }
841 5256 : reader_.read();
842 5256 : str += ch;
843 5256 : ++result;
844 5256 : }
845 849 : return result;
846 : }
847 :
848 : // Reads a sequence of characters and assembles them into a number,
849 : // returning them via num
850 : template <typename NumberType>
851 849 : int32_t TXMLProtocol::readXMLInteger(NumberType &num) {
852 849 : int32_t result = 0, ret;
853 849 : std::string str;
854 849 : if ((ret = readXMLNumericChars(str)) < 0) {
855 0 : return ret;
856 : }
857 849 : result += ret;
858 849 : stringToInteger(str, num);
859 849 : return result;
860 849 : }
861 :
862 0 : int32_t TXMLProtocol::readMessageBegin(std::string& name,
863 : TMessageType& messageType,
864 : int32_t& seqid) {
865 0 : LOG(ERROR, __func__ << ": Not implemented in TXMLProtocol");
866 0 : assert(false);
867 : return -1;
868 : }
869 :
870 0 : int32_t TXMLProtocol::readMessageEnd() {
871 0 : LOG(ERROR, __func__ << ": Not implemented in TXMLProtocol");
872 0 : assert(false);
873 : return -1;
874 : }
875 :
876 246 : int32_t TXMLProtocol::readSandeshBegin(std::string& name) {
877 246 : std::string str;
878 246 : int32_t result = 0, ret;
879 246 : if ((ret = readXMLTag(str)) < 0) {
880 0 : LOG(ERROR, __func__ << ": FAILED");
881 0 : return ret;
882 : }
883 246 : result += ret;
884 246 : boost::char_separator<char> sep("=\" ");
885 246 : tokenizer tokens(str, sep);
886 : // Extract the field name
887 246 : tokenizer::iterator it = tokens.begin();
888 246 : name = *it;
889 246 : ++it;
890 492 : for (; it != tokens.end(); ++it) {
891 246 : if (*it == kXMLType) {
892 246 : ++it;
893 246 : if (kTypeNameSandesh != *it) {
894 0 : LOG(ERROR, __func__ << ": Expected " << kTypeNameSandesh <<
895 : "; got " << *it);
896 0 : return -1;
897 : }
898 : }
899 : }
900 246 : return result;
901 246 : }
902 :
903 123 : int32_t TXMLProtocol::readSandeshEnd() {
904 123 : std::string name;
905 246 : return readXMLTag(name, true);
906 123 : }
907 :
908 123 : int32_t TXMLProtocol::readStructBegin(std::string& name) {
909 123 : return readXMLTag(name);
910 : }
911 :
912 123 : int32_t TXMLProtocol::readStructEnd() {
913 123 : std::string name;
914 246 : return readXMLTag(name, true);
915 123 : }
916 :
917 223 : int32_t TXMLProtocol::readContainerElementBegin() {
918 223 : std::string name;
919 446 : return readXMLTag(name);
920 223 : }
921 :
922 223 : int32_t TXMLProtocol::readContainerElementEnd() {
923 223 : std::string name;
924 446 : return readXMLTag(name, true);
925 223 : }
926 :
927 2313 : int32_t TXMLProtocol::readFieldBegin(std::string& name,
928 : TType& fieldType,
929 : int16_t& fieldId) {
930 2313 : int32_t result = 0, ret;
931 : // Check if we hit the end of the list
932 2313 : uint8_t ch = reader_.peek2();
933 2313 : uint8_t ch1 = reader_.peek2();
934 2313 : if (ch == kcXMLTagO && ch1 == kcXMLSlash) {
935 246 : fieldType = contrail::sandesh::protocol::T_STOP;
936 246 : return result;
937 : }
938 2067 : std::string str;
939 2067 : if ((ret = readXMLTag(str)) < 0) {
940 0 : LOG(ERROR, __func__ << ": FAILED");
941 0 : return ret;
942 : }
943 2067 : result += ret;
944 2067 : boost::char_separator<char> sep("=\" ");
945 2067 : tokenizer tokens(str, sep);
946 : // Extract the field name
947 2067 : tokenizer::iterator it = tokens.begin();
948 2067 : name = *it;
949 2067 : ++it;
950 6201 : for (; it != tokens.end(); ++it) {
951 4134 : if (*it == kXMLType) {
952 2067 : ++it;
953 2067 : fieldType = getTypeIDForTypeName(*it);
954 : }
955 4134 : if (*it == kXMLIdentifier) {
956 2067 : ++it;
957 2067 : stringToInteger(*it, fieldId);
958 : }
959 : }
960 2067 : return result;
961 2067 : }
962 :
963 2067 : int32_t TXMLProtocol::readFieldEnd() {
964 2067 : string str;
965 4134 : return readXMLTag(str, true);
966 2067 : }
967 :
968 0 : int32_t TXMLProtocol::readMapBegin(TType& keyType,
969 : TType& valType,
970 : uint32_t& size) {
971 0 : int32_t result = 0, ret;
972 0 : std::string str;
973 0 : if ((ret = readXMLTag(str)) < 0) {
974 0 : LOG(ERROR, __func__ << ": FAILED");
975 0 : return ret;
976 : }
977 0 : result += ret;
978 0 : boost::char_separator<char> sep("=\" ");
979 0 : tokenizer tokens(str, sep);
980 : // Extract the field name
981 0 : tokenizer::iterator it = tokens.begin();
982 0 : if (*it != kTypeNameMap) {
983 0 : LOG(ERROR, __func__ << ": Expected \"" << kTypeNameMap <<
984 : "\"; got \"" << *it << "\"");
985 0 : return -1;
986 : }
987 0 : ++it;
988 0 : for (; it != tokens.end(); ++it) {
989 0 : if (*it == kXMLKey) {
990 0 : ++it;
991 0 : keyType = getTypeIDForTypeName(*it);
992 : }
993 0 : if (*it == kXMLValue) {
994 0 : ++it;
995 0 : valType = getTypeIDForTypeName(*it);
996 : }
997 0 : if (*it == kXMLSize) {
998 0 : ++it;
999 0 : stringToInteger(*it, size);
1000 : }
1001 : }
1002 0 : return result;
1003 0 : }
1004 :
1005 0 : int32_t TXMLProtocol::readMapEnd() {
1006 0 : std::string str;
1007 0 : return readXMLTag(str, true);
1008 0 : }
1009 :
1010 123 : int32_t TXMLProtocol::readListBegin(TType& elemType,
1011 : uint32_t& size) {
1012 123 : int32_t result = 0, ret;
1013 123 : std::string str;
1014 123 : if ((ret = readXMLTag(str)) < 0) {
1015 0 : LOG(ERROR, __func__ << ": FAILED");
1016 0 : return ret;
1017 : }
1018 123 : result += ret;
1019 123 : boost::char_separator<char> sep("=\" ");
1020 123 : tokenizer tokens(str, sep);
1021 : // Extract the field name
1022 123 : tokenizer::iterator it = tokens.begin();
1023 123 : if (*it != kTypeNameList) {
1024 0 : LOG(ERROR, __func__ << ": Expected \"" << kTypeNameList <<
1025 : "\"; got \"" << *it << "\"");
1026 0 : return -1;
1027 : }
1028 123 : ++it;
1029 369 : for (; it != tokens.end(); ++it) {
1030 246 : if (*it == kXMLType) {
1031 123 : ++it;
1032 123 : elemType = getTypeIDForTypeName(*it);
1033 : }
1034 246 : if (*it == kXMLSize) {
1035 123 : ++it;
1036 123 : stringToInteger(*it, size);
1037 : }
1038 : }
1039 123 : return result;
1040 123 : }
1041 :
1042 123 : int32_t TXMLProtocol::readListEnd() {
1043 123 : std::string str;
1044 246 : return readXMLTag(str, true);
1045 123 : }
1046 :
1047 0 : int32_t TXMLProtocol::readSetBegin(TType& elemType,
1048 : uint32_t& size) {
1049 0 : int32_t result = 0, ret;
1050 0 : std::string str;
1051 0 : if ((ret = readXMLTag(str)) < 0) {
1052 0 : LOG(ERROR, __func__ << ": FAILED");
1053 0 : return ret;
1054 : }
1055 0 : result += ret;
1056 0 : boost::char_separator<char> sep("=\" ");
1057 0 : tokenizer tokens(str, sep);
1058 : // Extract the field name
1059 0 : tokenizer::iterator it = tokens.begin();
1060 0 : if (*it != kTypeNameSet) {
1061 0 : LOG(ERROR, __func__ << ": Expected \"" << kTypeNameSet <<
1062 : "\"; got \"" << *it << "\"");
1063 0 : return -1;
1064 : }
1065 0 : ++it;
1066 0 : for (; it != tokens.end(); ++it) {
1067 0 : if (*it == kXMLType) {
1068 0 : ++it;
1069 0 : elemType = getTypeIDForTypeName(*it);
1070 : }
1071 0 : if (*it == kXMLSize) {
1072 0 : ++it;
1073 0 : stringToInteger(*it, size);
1074 : }
1075 : }
1076 0 : return result;
1077 0 : }
1078 :
1079 0 : int32_t TXMLProtocol::readSetEnd() {
1080 0 : std::string str;
1081 0 : return readXMLTag(str, true);
1082 0 : }
1083 :
1084 0 : int32_t TXMLProtocol::readI16(int16_t& i16) {
1085 0 : return readXMLInteger(i16);
1086 : }
1087 :
1088 615 : int32_t TXMLProtocol::readI32(int32_t& i32) {
1089 615 : return readXMLInteger(i32);
1090 : }
1091 :
1092 123 : int32_t TXMLProtocol::readI64(int64_t& i64) {
1093 123 : return readXMLInteger(i64);
1094 : }
1095 :
1096 0 : int32_t TXMLProtocol::readU16(uint16_t& u16) {
1097 0 : return readXMLInteger(u16);
1098 : }
1099 :
1100 111 : int32_t TXMLProtocol::readU32(uint32_t& u32) {
1101 111 : return readXMLInteger(u32);
1102 : }
1103 :
1104 0 : int32_t TXMLProtocol::readU64(uint64_t& u64) {
1105 0 : return readXMLInteger(u64);
1106 : }
1107 :
1108 0 : int32_t TXMLProtocol::readIPV4(uint32_t& ip4) {
1109 0 : return readXMLInteger(ip4);
1110 : }
1111 :
1112 0 : int32_t TXMLProtocol::readIPADDR(boost::asio::ip::address& ipaddress) {
1113 : int32_t ret;
1114 0 : std::string str;
1115 0 : if ((ret = readXMLString(str)) < 0) {
1116 0 : return ret;
1117 : }
1118 0 : boost::system::error_code ec;
1119 0 : ipaddress = boost::asio::ip::address::from_string(str, ec);
1120 0 : if (ec) {
1121 0 : return -1;
1122 : }
1123 0 : return ret;
1124 0 : }
1125 :
1126 0 : int32_t TXMLProtocol::readDouble(double& dub) {
1127 0 : return readXMLDouble(dub);
1128 : }
1129 :
1130 1232 : int32_t TXMLProtocol::readString(std::string &str) {
1131 1232 : readXMLString(str);
1132 1232 : unescapeXMLControlChars(str);
1133 1232 : return str.size();
1134 : }
1135 :
1136 86 : int32_t TXMLProtocol::readBool(bool& value) {
1137 86 : std::string str;
1138 86 : int32_t result = 0, ret;
1139 86 : if ((ret = readXMLString(str)) < 0) {
1140 0 : return ret;
1141 : }
1142 86 : result += ret;
1143 86 : if (str == kXMLBoolTrue) {
1144 86 : value = true;
1145 0 : } else if (str == kXMLBoolFalse) {
1146 0 : value = false;
1147 : } else {
1148 0 : LOG(ERROR, __func__ << ": Expected \"" << kXMLBoolTrue <<
1149 : "\" or \"" << kXMLBoolFalse << "\"; got \"" << str << "\"");
1150 : }
1151 86 : return result;
1152 86 : }
1153 :
1154 0 : int32_t TXMLProtocol::readByte(int8_t& byte) {
1155 0 : return readXMLInteger(byte);
1156 : }
1157 :
1158 0 : int32_t TXMLProtocol::readBinary(std::string &str) {
1159 0 : return readXMLString(str);
1160 : }
1161 :
1162 0 : int32_t TXMLProtocol::readXML(std::string &str) {
1163 0 : return readXMLCDATA(str);
1164 : }
1165 :
1166 0 : int32_t TXMLProtocol::readUUID(boost::uuids::uuid &uuid) {
1167 : int32_t ret;
1168 0 : std::string str;
1169 0 : if ((ret = readXMLString(str)) < 0) {
1170 0 : return ret;
1171 : }
1172 0 : std::stringstream ss;
1173 0 : ss << str;
1174 0 : ss >> uuid;
1175 0 : return ret;
1176 0 : }
1177 :
1178 : }}} // contrail::sandesh::protocol
|