LCOV - code coverage report
Current view: top level - xmpp - xmpp_proto.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 236 299 78.9 %
Date: 2026-11-09 02:10:49 Functions: 22 28 78.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "xmpp/xmpp_proto.h"
       7             : #include <iostream>
       8             : #include <string>
       9             : #include <boost/algorithm/string/replace.hpp>
      10             : #include <boost/algorithm/string/predicate.hpp>
      11             : 
      12             : #include "xmpp/xmpp_connection.h"
      13             : #include "xmpp/xmpp_log.h"
      14             : #include "xmpp/xmpp_session.h"
      15             : #include "xmpp/xmpp_str.h"
      16             : 
      17             : #include "sandesh/sandesh_trace.h"
      18             : #include "sandesh/common/vns_types.h"
      19             : #include "sandesh/common/vns_constants.h"
      20             : #include "sandesh/xmpp_message_sandesh_types.h"
      21             : #include "sandesh/xmpp_trace_sandesh_types.h"
      22             : 
      23             : using namespace std;
      24             : 
      25             : unique_ptr<XmlBase> XmppProto::open_doc_(AllocXmppXmlImpl(sXMPP_STREAM_OPEN));
      26             : 
      27           0 : XmppStanza::XmppStanza() {
      28           0 : }
      29             : 
      30           0 : XmppProto::XmppProto() {
      31           0 : }
      32             : 
      33           0 : XmppProto::~XmppProto() {
      34           0 : }
      35             : 
      36       20307 : int XmppProto::EncodeStream(const XmppStreamMessage &str, string &to,
      37             :                             string &from, const string &xmlns, uint8_t *buf,
      38             :                             size_t size) {
      39       20307 :     int len = 0;
      40             : 
      41       20307 :     switch (str.strmtype) {
      42        8045 :         case (XmppStanza::XmppStreamMessage::INIT_STREAM_HEADER):
      43        8045 :             len = EncodeOpen(buf, to, from, xmlns, size);
      44        8045 :             break;
      45        7817 :         case (XmppStanza::XmppStreamMessage::INIT_STREAM_HEADER_RESP):
      46        7817 :             len = EncodeOpenResp(buf, to, from, size);
      47        7817 :             break;
      48        4445 :         case (XmppStanza::XmppStreamMessage::FEATURE_TLS):
      49        4445 :             switch (str.strmtlstype) {
      50        1512 :                 case (XmppStanza::XmppStreamMessage::TLS_FEATURE_REQUEST):
      51        1512 :                     len = EncodeFeatureTlsRequest(buf);
      52        1512 :                     break;
      53        1469 :                 case (XmppStanza::XmppStreamMessage::TLS_START):
      54        1469 :                     len = EncodeFeatureTlsStart(buf);
      55        1469 :                     break;
      56        1464 :                 case (XmppStanza::XmppStreamMessage::TLS_PROCEED):
      57        1464 :                     len = EncodeFeatureTlsProceed(buf);
      58        1464 :                     break;
      59             :             }
      60        4445 :             break;
      61           0 :         default:
      62           0 :             break;
      63             :     }
      64             : 
      65       20307 :     return len;
      66             : }
      67             : 
      68        6444 : int XmppProto::EncodeStream(const XmppStanza::XmppMessage &str, uint8_t *buf,
      69             :                             size_t size) {
      70        6444 :     int ret = 0;
      71             : 
      72        6444 :     if (str.type == XmppStanza::WHITESPACE_MESSAGE_STANZA) {
      73        6444 :         return EncodeWhitespace(buf);
      74             :     }
      75             : 
      76           0 :     return ret;
      77             : }
      78             : 
      79           0 : int XmppProto::EncodeMessage(XmlBase *dom, uint8_t *buf, size_t size) {
      80           0 :     int len = dom->WriteDoc(buf);
      81             : 
      82           0 :     return len;
      83             : }
      84             : 
      85           0 : int XmppProto::EncodePresence(uint8_t *buf, size_t size) {
      86           0 :     return 0;
      87             : }
      88             : 
      89           0 : int XmppProto::EncodeIq(const XmppStanza::XmppMessageIq *iq,
      90             :                         XmlBase *doc, uint8_t *buf, size_t size) {
      91           0 :     unique_ptr<XmlBase> send_doc_(AllocXmppXmlImpl());
      92             : 
      93             :     // create
      94           0 :     send_doc_->LoadDoc("");
      95           0 :     send_doc_->AddNode("iq", "");
      96             : 
      97           0 :     switch(iq->stype) {
      98           0 :         case XmppStanza::XmppMessageIq::GET:
      99           0 :             send_doc_->AddAttribute("type", "get");
     100           0 :             break;
     101           0 :         case XmppStanza::XmppMessageIq::SET:
     102           0 :             send_doc_->AddAttribute("type", "set");
     103           0 :             break;
     104           0 :         case XmppStanza::XmppMessageIq::RESULT:
     105           0 :             send_doc_->AddAttribute("type", "result");
     106           0 :             break;
     107           0 :         case XmppStanza::XmppMessageIq::ERROR:
     108           0 :             send_doc_->AddAttribute("type", "error");
     109           0 :             break;
     110           0 :         default:
     111           0 :             break;
     112             :     }
     113           0 :     send_doc_->AddAttribute("from", iq->from);
     114           0 :     send_doc_->AddAttribute("to", iq->to);
     115           0 :     send_doc_->AddAttribute("id", "id1");
     116             : 
     117           0 :     send_doc_->AddChildNode("pubsub", "");
     118           0 :     send_doc_->AddAttribute("xmlns", "http://jabber.org/protocol/pubsub");
     119             : 
     120           0 :     send_doc_->AppendDoc("pubsub", doc);
     121             : 
     122             :     //Returns byte encoded in the doc
     123           0 :     int len = send_doc_->WriteDoc(buf);
     124             : 
     125           0 :     return len;
     126           0 : }
     127             : 
     128        6444 : int XmppProto::EncodeWhitespace(uint8_t *buf) {
     129        6444 :     string str(sXMPP_WHITESPACE);
     130             : 
     131        6444 :     int len = str.size();
     132        6444 :     if (len > 0) {
     133        6444 :         memcpy(buf, str.data(), len);
     134             :     }
     135             : 
     136        6444 :     return len;
     137        6444 : }
     138             : 
     139        7817 : int XmppProto::EncodeOpenResp(uint8_t *buf, string &to, string &from,
     140             :                               size_t max_size) {
     141             : 
     142        7817 :     unique_ptr<XmlBase> resp_doc(XmppStanza::AllocXmppXmlImpl(sXMPP_STREAM_RESP));
     143             : 
     144        7817 :     if (resp_doc.get() == NULL) {
     145           0 :         return 0;
     146             :     }
     147             : 
     148        7817 :     SetTo(to, resp_doc.get());
     149        7817 :     SetFrom(from, resp_doc.get());
     150             : 
     151        7817 :     std::stringstream ss;
     152        7816 :     resp_doc->PrintDoc(ss);
     153        7817 :     std::string msg;
     154        7817 :     msg = ss.str();
     155        7816 :     size_t len = msg.size();
     156        7816 :     if (len > max_size) {
     157           0 :         LOG(ERROR, "\n (Open Confirm) size greater than max buffer size \n");
     158           0 :         return 0;
     159             :     } else {
     160        7816 :         boost::algorithm::ireplace_last(msg, "/", " ");
     161        7816 :         memcpy(buf, msg.c_str(), len);
     162        7816 :         return len;
     163             :     }
     164        7816 : }
     165             : 
     166        8045 : int XmppProto::EncodeOpen(uint8_t *buf, string &to, string &from,
     167             :                           const string &xmlns, size_t max_size) {
     168             : 
     169        8045 :     if (open_doc_.get() ==  NULL) {
     170           0 :         return 0;
     171             :     }
     172             : 
     173        8045 :     SetTo(to, open_doc_.get());
     174        8045 :     SetFrom(from, open_doc_.get());
     175        8045 :     SetXmlns(xmlns, open_doc_.get());
     176             : 
     177             :     //Returns byte encoded in the doc
     178        8045 :     std::stringstream ss;
     179        8045 :     open_doc_->PrintDoc(ss);
     180        8045 :     std::string msg;
     181        8045 :     msg = ss.str();
     182        8045 :     size_t len = msg.size();
     183        8045 :     if (len > max_size) {
     184           0 :         LOG(ERROR, "\n (Open Message) size greater than max buffer size \n");
     185           0 :         return 0;
     186             :     } else {
     187        8045 :         boost::algorithm::ireplace_last(msg, "/", " ");
     188        8045 :         memcpy(buf, msg.c_str(), len);
     189        8045 :         return len;
     190             :     }
     191        8045 : }
     192             : 
     193        1512 : int XmppProto::EncodeFeatureTlsRequest(uint8_t *buf) {
     194        1512 :     unique_ptr<XmlBase> resp_doc(XmppStanza::AllocXmppXmlImpl(sXMPP_STREAM_FEATURE_TLS));
     195             :     //Returns byte encoded in the doc
     196        1512 :     int len = resp_doc->WriteDoc(buf);
     197        1512 :     return len;
     198        1512 : }
     199             : 
     200        1469 : int XmppProto::EncodeFeatureTlsStart(uint8_t *buf) {
     201        1469 :     unique_ptr<XmlBase> resp_doc(XmppStanza::AllocXmppXmlImpl(sXMPP_STREAM_START_TLS));
     202             :     //Returns byte encoded in the doc
     203        1469 :     int len = resp_doc->WriteDoc(buf);
     204        1469 :     return len;
     205        1469 : }
     206             : 
     207        1464 : int XmppProto::EncodeFeatureTlsProceed(uint8_t *buf) {
     208        1464 :     unique_ptr<XmlBase> resp_doc(XmppStanza::AllocXmppXmlImpl(sXMPP_STREAM_PROCEED_TLS));
     209             :     //Returns byte encoded in the doc
     210        1464 :     int len = resp_doc->WriteDoc(buf);
     211        1464 :     return len;
     212        1464 : }
     213             : 
     214     4152424 : XmppStanza::XmppMessage *XmppProto::Decode(const XmppConnection *connection,
     215             :                                            const string &ts) {
     216     4152424 :     XmlBase *impl = XmppStanza::AllocXmppXmlImpl();
     217     4152373 :     if (impl == nullptr) {
     218           0 :         return nullptr;
     219             :     }
     220             : 
     221     4152373 :     XmppStanza::XmppMessage *msg = DecodeInternal(connection, ts, impl);
     222     4152442 :     if (!msg) {
     223           0 :         return nullptr;
     224             :     }
     225             : 
     226             :     // transfer ownership of the dom implementation
     227     4152442 :     msg->dom.reset(impl);
     228             : 
     229     4152416 :     return msg;
     230             : }
     231             : 
     232     4152375 : XmppStanza::XmppMessage *XmppProto::DecodeInternal(
     233             :         const XmppConnection *connection, const string &ts, XmlBase *impl) {
     234     4152375 :     XmppStanza::XmppMessage *ret = nullptr;
     235             : 
     236     4152375 :     string ns(sXMPP_STREAM_O);
     237     4152368 :     string ws(sXMPP_WHITESPACE);
     238     4152360 :     string iq(sXMPP_IQ_KEY);
     239             : 
     240     4152360 :     if (ts.find(sXMPP_IQ) != string::npos) {
     241       98569 :         string ts_tmp = ts;
     242             : 
     243       98570 :         if (impl->LoadDoc(ts) == -1) {
     244           0 :             XMPP_WARNING(XmppIqMessageParseFail, connection->ToUVEKey(),
     245             :                          XMPP_PEER_DIR_IN);
     246           0 :             assert(false);
     247             :             goto done;
     248             :         }
     249             : 
     250       98572 :         XmppStanza::XmppMessageIq *msg = new XmppStanza::XmppMessageIq;
     251       98569 :         impl->ReadNode(iq);
     252       98564 :         msg->to = XmppProto::GetTo(impl);
     253       98569 :         msg->from = XmppProto::GetFrom(impl);
     254       98566 :         msg->id = XmppProto::GetId(impl);
     255       98568 :         msg->iq_type = XmppProto::GetType(impl);
     256             :         // action is subscribe,publish,collection
     257       98570 :         const char *action = XmppProto::GetAction(impl, msg->iq_type);
     258       98564 :         if (action) {
     259       98548 :             msg->action = action;
     260             :         }
     261       98565 :         if (XmppProto::GetNode(impl, msg->action)) {
     262       98556 :             msg->node = XmppProto::GetNode(impl, msg->action);
     263             :         }
     264             :         //associate or dissociate collection node
     265       98569 :         if (msg->action.compare("collection") == 0) {
     266       41670 :             if (XmppProto::GetAsNode(impl)) {
     267       27304 :                 msg->as_node = XmppProto::GetAsNode(impl);
     268       27304 :                 msg->is_as_node = true;
     269       14364 :             } else if (XmppProto::GetDsNode(impl)) {
     270       14339 :                 msg->as_node = XmppProto::GetDsNode(impl);
     271       14338 :                 msg->is_as_node = false;
     272             :             }
     273             :         }
     274             : 
     275             :         //msg->dom.reset(impl);
     276             : 
     277       98568 :         ret = msg;
     278             : 
     279       98568 :         XMPP_UTDEBUG(XmppIqMessageProcess, connection->ToUVEKey(),
     280             :                      XMPP_PEER_DIR_IN, msg->node, msg->action, msg->from,
     281             :                      msg->to, msg->id, msg->iq_type);
     282       98572 :         goto done;
     283             : 
     284     4152445 :     } else if (ts.find(sXMPP_MESSAGE) != string::npos) {
     285             : 
     286     1556845 :         if (impl->LoadDoc(ts) == -1) {
     287           0 :             XMPP_WARNING(XmppChatMessageParseFail, connection->ToUVEKey(),
     288             :                          XMPP_PEER_DIR_IN);
     289           0 :             goto done;
     290             :         }
     291             :         XmppStanza::XmppMessage *msg = new XmppStanza::XmppChatMessage(
     292     1556845 :                                            STATE_NONE);
     293     1556845 :         impl->ReadNode(sXMPP_MESSAGE_KEY);
     294             : 
     295     1556845 :         msg->to = XmppProto::GetTo(impl);
     296     1556845 :         msg->from = XmppProto::GetFrom(impl);
     297     1556845 :         ret = msg;
     298             : 
     299     1556845 :         XMPP_UTDEBUG(XmppChatMessageProcess, connection->ToUVEKey(),
     300             :                      XMPP_PEER_DIR_IN, msg->type, msg->from, msg->to);
     301     1556845 :         goto done;
     302             : 
     303     2497028 :     } else if (ts.find(sXMPP_STREAM_O) != string::npos) {
     304             : 
     305             :         // ensusre stream open is at the beginning of the message
     306       15710 :         string ts_tmp = ts;
     307       15712 :         ts_tmp.erase(std::remove(ts_tmp.begin(), ts_tmp.end(), '\n'), ts_tmp.end());
     308             : 
     309       15707 :         if ((ts_tmp.compare(0, strlen(sXMPP_STREAM_START),
     310       31414 :              sXMPP_STREAM_START) != 0) &&
     311       15706 :             (ts_tmp.compare(0, strlen(sXMPP_STREAM_START_S),
     312             :              sXMPP_STREAM_START_S) != 0)) {
     313           0 :             XMPP_WARNING(XmppBadMessage, connection->ToUVEKey(),
     314             :                          XMPP_PEER_DIR_IN,
     315             :                          "Open message not at the beginning.", ts);
     316           0 :             goto done;
     317             :         }
     318             : 
     319             :         // check if the buf is xmpp open or response message
     320             :         // As end tag will be missing we need to modify the
     321             :         // string for stream open, else dom decoder will fail
     322       15708 :         boost::algorithm::replace_last(ts_tmp, ">", "/>");
     323       15709 :         if (impl->LoadDoc(ts_tmp) == -1) {
     324           0 :             XMPP_WARNING(XmppBadMessage, connection->ToUVEKey(),
     325             :                          XMPP_PEER_DIR_IN, "Open message parse failed.", ts);
     326           0 :             goto done;
     327             :         }
     328             : 
     329             :         XmppStanza::XmppStreamMessage *strm =
     330       15712 :             new XmppStanza::XmppStreamMessage();
     331       15710 :         strm->strmtype = XmppStanza::XmppStreamMessage::INIT_STREAM_HEADER;
     332       15710 :         impl->ReadNode(ns);
     333       15707 :         strm->to = XmppProto::GetTo(impl);
     334       15707 :         strm->from = XmppProto::GetFrom(impl);
     335       15708 :         strm->xmlns = XmppProto::GetXmlns(impl);
     336             : 
     337       15704 :         ret = strm;
     338             : 
     339       15704 :         XMPP_UTDEBUG(XmppRxOpenMessage, connection->ToUVEKey(),
     340             :                      XMPP_PEER_DIR_IN, strm->from, strm->to);
     341             : 
     342     2497027 :     } else if (ts.find(sXMPP_STREAM_NS_TLS) != string::npos) {
     343             : 
     344        4365 :         if (impl->LoadDoc(ts) == -1) {
     345           0 :             XMPP_WARNING(XmppBadMessage, connection->ToUVEKey(),
     346             :                          XMPP_PEER_DIR_IN, "Stream TLS parse failed.", ts);
     347           0 :             goto done;
     348             :         }
     349             : 
     350             :         // find stream:features tls required
     351        5820 :         if ((ts.find(sXMPP_STREAM_FEATURES_O) != string::npos) &&
     352        5820 :             (ts.find(sXMPP_STREAM_STARTTLS_O) != string::npos) &&
     353        1455 :             (ts.find(sXMPP_REQUIRED_O) != string::npos)) {
     354             : 
     355             :             XmppStanza::XmppStreamMessage *strm =
     356        1455 :                 new XmppStanza::XmppStreamMessage();
     357        1455 :             strm->strmtype = XmppStanza::XmppStreamMessage::FEATURE_TLS;
     358        1455 :             strm->strmtlstype = XmppStanza::XmppStreamMessage::TLS_FEATURE_REQUEST;
     359             : 
     360        1455 :             ret = strm;
     361             : 
     362        1455 :             XMPP_UTDEBUG(XmppRxStreamTlsRequired, connection->ToUVEKey(),
     363             :                          XMPP_PEER_DIR_IN);
     364             : 
     365        2910 :         } else if (ts.find(sXMPP_STREAM_STARTTLS_O) != string::npos) {
     366             :             XmppStanza::XmppStreamMessage *strm =
     367        1455 :                 new XmppStanza::XmppStreamMessage();
     368        1455 :             strm->strmtype = XmppStanza::XmppStreamMessage::FEATURE_TLS;
     369        1455 :             strm->strmtlstype = XmppStanza::XmppStreamMessage::TLS_START;
     370        1455 :             ret = strm;
     371             : 
     372        1455 :             XMPP_UTDEBUG(XmppRxStreamStartTls, connection->ToUVEKey(),
     373             :                          XMPP_PEER_DIR_IN);
     374             : 
     375        1455 :         } else if (ts.find(sXMPP_STREAM_PROCEED_O) != string::npos) {
     376             :             XmppStanza::XmppStreamMessage *strm =
     377        1455 :                 new XmppStanza::XmppStreamMessage();
     378        1455 :             strm->strmtype = XmppStanza::XmppStreamMessage::FEATURE_TLS;
     379        1455 :             strm->strmtlstype = XmppStanza::XmppStreamMessage::TLS_PROCEED;
     380             : 
     381        1455 :             ret = strm;
     382             : 
     383        1455 :             XMPP_UTDEBUG(XmppRxStreamProceed, connection->ToUVEKey(),
     384             :                          XMPP_PEER_DIR_IN);
     385             :         }
     386        4365 :         goto done;
     387             : 
     388     2476955 :     } else if (ts.find_first_of(sXMPP_VALIDWS) != string::npos) {
     389             : 
     390             :         XmppStanza::XmppMessage *msg =
     391     2476955 :             new XmppStanza::XmppMessage(WHITESPACE_MESSAGE_STANZA);
     392     2476953 :         return msg;
     393             :     } else {
     394           0 :         XMPP_WARNING(XmppBadMessage, connection->ToUVEKey(),
     395             :                      XMPP_PEER_DIR_IN, "Message not supported", ts);
     396             :     }
     397             : 
     398     1675489 : done:
     399             : 
     400     1675489 :     return ret;
     401     4152442 : }
     402             : 
     403       15861 : int XmppProto::SetTo(string &to, XmlBase *doc) {
     404       15861 :     if (!doc) return -1;
     405             : 
     406       15861 :     string ns(sXMPP_STREAM_O);
     407       15861 :     doc->ReadNode(ns);
     408       15862 :     doc->ModifyAttribute("to", to);
     409             : 
     410       15861 :     return 0;
     411       15861 : }
     412             : 
     413       15861 : int XmppProto::SetFrom(string &from, XmlBase *doc) {
     414       15861 :     if (!doc) return -1;
     415             : 
     416       15861 :     string ns(sXMPP_STREAM_O);
     417       15862 :     doc->ReadNode(ns);
     418       15862 :     return doc->ModifyAttribute("from", from);
     419       15862 : }
     420             : 
     421        8045 : int XmppProto::SetXmlns(const string &xmlns, XmlBase *doc) {
     422        8045 :     if (!doc)
     423           0 :         return -1;
     424             : 
     425        8045 :     string ns(sXMPP_STREAM_O);
     426        8045 :     doc->ReadNode(ns);
     427        8045 :     return doc->ModifyAttribute("xmlns", xmlns);
     428        8045 : }
     429             : 
     430     1671076 : const char *XmppProto::GetTo(XmlBase *doc) {
     431     1671076 :     if (!doc) return NULL;
     432             : 
     433     1671076 :     string tmp("to");
     434     1671079 :     return doc->ReadAttrib(tmp);
     435     1671088 : }
     436             : 
     437     1671096 : const char *XmppProto::GetFrom(XmlBase *doc) {
     438     1671096 :     if (!doc) return NULL;
     439             : 
     440     1671096 :     string tmp("from");
     441     1671091 :     return doc->ReadAttrib(tmp);
     442     1671097 : }
     443             : 
     444       15707 : const char *XmppProto::GetXmlns(XmlBase *doc) {
     445       15707 :     if (!doc)
     446           0 :         return NULL;
     447             : 
     448       15707 :     string tmp("xmlns");
     449       15706 :     return doc->ReadAttrib(tmp);
     450       15705 : }
     451             : 
     452       98565 : const char *XmppProto::GetId(XmlBase *doc) {
     453       98565 :     if (!doc) return NULL;
     454             : 
     455       98565 :     string tmp("id");
     456       98567 :     return doc->ReadAttrib(tmp);
     457       98570 : }
     458             : 
     459       98568 : const char *XmppProto::GetType(XmlBase *doc) {
     460       98568 :     if (!doc) return NULL;
     461             : 
     462       98568 :     string tmp("type");
     463       98569 :     return doc->ReadAttrib(tmp);
     464       98570 : }
     465             : 
     466       98569 : const char *XmppProto::GetAction(XmlBase *doc, const string &str) {
     467       98569 :     if (!doc) return NULL;
     468             : 
     469       98569 :     if (str.compare("set") == 0) {
     470       98559 :         doc->ReadNode("pubsub");
     471       98547 :         return(doc->ReadChildNodeName());
     472          15 :     } else if (str.compare("get") == 0) {
     473             :     }
     474             : 
     475          15 :     return(NULL);
     476             : }
     477             : 
     478      197117 : const char *XmppProto::GetNode(XmlBase *doc, const string &str) {
     479      197117 :     if (!doc) return NULL;
     480             : 
     481      197117 :     if (!str.empty()) {
     482      197102 :         return(doc->ReadAttrib("node"));
     483             :     }
     484             : 
     485          15 :     return(NULL);
     486             : }
     487             : 
     488       68974 : const char *XmppProto::GetAsNode(XmlBase *doc) {
     489       68974 :     if (!doc) return NULL;
     490             : 
     491       68974 :     const char *node = doc->ReadNode("associate");
     492       68972 :     if (node != NULL) {
     493       54608 :         return(doc->ReadAttrib("node"));
     494             :     }
     495             : 
     496       14364 :     return(NULL);
     497             : }
     498             : 
     499       28703 : const char *XmppProto::GetDsNode(XmlBase *doc) {
     500       28703 :     if (!doc) return NULL;
     501             : 
     502       28703 :     const char *node = doc->ReadNode("dissociate");
     503       28703 :     if (node != NULL) {
     504       28675 :         return(doc->ReadAttrib("node"));
     505             :     }
     506             : 
     507          28 :     return(NULL);
     508             : }

Generated by: LCOV version 1.14