NSIS-ka
A free C++ implementation of NSIS protocols

root/ntlp/trunk/src/signalingmodule_ntlp.cpp @ 2361

Revision 2361, 36.7 KB (checked in by bless, 6 years ago)

- changed debugging output to use to_string() method for sessionid

  • Property svn:keywords set to HeadURL URL Id Rev LastChangedRevision Date
Line 
1// ----------------------------------------*- mode: C++; -*--
2// signalingmsg_ntlp.cpp - The NTLP Signaling module
3// ----------------------------------------------------------
4// $Id$
5// $HeadURL$
6// ==========================================================
7//                     
8// (C)opyright, all rights reserved by
9// - Institute of Telematics, University of Karlsruhe (TH)
10// ==========================================================
11
12/** @ingroup Signaling Module
13 * @file
14 * Signaling Module
15 *
16 * This module receives and sends messages and calls the serializatio/deserialization routines
17 * of NTLP Protocol class.
18 *
19 * Also Error checking and relaying on messages is done in this module.
20 *
21 */
22#include <signalingmodule_ntlp.h>
23#include "queuemanager.h"
24#include "logfile.h"
25#include "ntlpproto.h"
26#include <net/if.h>
27#include <cerrno>
28
29
30namespace ntlp {
31
32 using namespace protlib;
33
34 const unsigned int max_mtu_size= 576;
35
36
37/**
38 * SignalingNTLPParam constructor, take over parameters for Signaling Module
39 * @param pm -- The Protocol map containing pointers to all TP Modules in use
40 * @param localnliv4 -- A NLI describing the peer, contains the IPv4 address which is to be sent to peers for contacting this peer
41 * @param localnliv6 -- A NLI describing the peer, contains the IPv6 address which is to be sent to peers for contacting this peer
42 * @param nslptable -- The table holding the addresses of registered NSLP clients
43 * @param well_known_port -- The UDP Well-Known Port of GIST
44 * @param sleep_time -- Thread sleep time
45 * @param see, sre -- No idea. Something obsolete from GIST
46 * @param find_next_signaling_peer, dest_addr -- Something obsolete from GIST
47 * @note -- This will create a time period in [factor - ((1-factor)/2) * value .. factor + ((1-factor)/2) * value]
48 */
49SignalingNTLPParam::SignalingNTLPParam(protocol_map_t pm,
50                                       nli& localnliv4,
51                                       nli& localnliv6,
52                                       //const appladdress& deforig,
53                                       NSLPtable& nslptable,
54                                       uint16 well_known_port,
55                                       uint32 sleep_time,
56                                       bool see, bool sre,
57                                       appladdress* (*find_next_signaling_peer) (const hostaddress& dest_addr)
58                                       )
59  : ThreadParam(sleep_time,"GIST Signaling"),
60    protomap(pm),
61    localnliv4(localnliv4),
62    localnliv6(localnliv6),
63    //default_originator(deforig),
64    source(message::qaddr_signaling),
65    send_error_expedited(see),
66    send_reply_expedited(sre),
67    find_next_signaling_peer(find_next_signaling_peer),
68    nslptable(nslptable),
69    well_known_port(well_known_port)
70{
71} // end constructor
72 
73
74
75/// Return a handle to a TP module handling the given protocol ID
76TP*
77SignalingNTLPParam::get_tp(protocol_t id) const 
78{
79  protocol_map_const_it_t mit = protomap.find(id);
80  if (mit==protomap.end()) return NULL;
81  else return mit->second;
82} // end get_tp
83
84
85SignalingMsgNTLP::SignalingMsgNTLP(bool conf)
86        : message(type_signaling),
87        subtype(ignore), err(SignalingNTLP::error_ok),
88        pdu(NULL), peer(NULL), ownaddr(NULL), encap_pdu(NULL), ref_id(0), confirm(conf) {}
89
90
91SignalingMsgNTLP::~SignalingMsgNTLP() {
92        if (pdu) delete pdu;
93        if (peer) delete peer;
94        if (ownaddr) delete ownaddr;
95        if (encap_pdu) delete encap_pdu;
96} // end destructor
97
98
99/* A request from the coordinator to send a signaling message
100 */
101void 
102SignalingMsgNTLP::set_req(const appladdress* peeraddr, known_ntlp_pdu* p, gp_id_t refid, uint16 oiface) {
103        set_source(qaddr_coordination);
104        subtype = SigReq;
105        err = SignalingNTLP::error_ok;
106        pdu = p;
107        peer = peeraddr;
108        ownaddr = NULL;
109        encap_pdu = NULL;
110        ref_id = refid;
111        oif = oiface;
112} // end set_req
113
114
115/* An indication to the coordinator that a signaling message arrived
116 */
117void 
118SignalingMsgNTLP::set_ind(gp_id_t id, const appladdress* peeraddr, const appladdress* own_addr, known_ntlp_pdu* p,
119                gp_id_t rid, known_ntlp_pdu* epdu) {
120        set_source(qaddr_signaling);
121        set_id(id);
122        subtype = SigInd;
123        err = SignalingNTLP::error_ok;
124        pdu = p;
125        peer = peeraddr;
126        ownaddr = own_addr;
127        encap_pdu = epdu;
128        ref_id = rid;
129} // end set_ind
130
131
132/* A confirmation to the coordinator that a signaling message was processed/sent
133 */
134void 
135SignalingMsgNTLP::set_cnf(gp_id_t id, known_ntlp_pdu* p, known_ntlp_pdu* epdu) {
136        set_source(qaddr_signaling);
137        set_id(id);
138        subtype = SigCnf;
139        err = SignalingNTLP::error_ok;
140        pdu = p;
141        peer = NULL;
142        ownaddr = NULL;
143        encap_pdu = epdu;
144        ref_id = 0;
145} // end set_cnf
146
147
148/* A response from the coordinator that has to be sent back as a signaling message
149 */
150void 
151SignalingMsgNTLP::set_rsp(gp_id_t id, known_ntlp_pdu* p, bool setencap) {
152        set_source(qaddr_coordination);
153        set_id(id);
154        subtype = SigRsp;
155        err = SignalingNTLP::error_ok;
156        pdu = p;
157        peer = NULL;
158        ownaddr = NULL;
159        encap_pdu = NULL;
160        if (setencap) ref_id = id;
161        else ref_id = 0;
162} // end set_rsp
163
164
165/** Set up  a cancel message. If reply is set true, send error or
166 * confirmation.
167 */
168void 
169SignalingMsgNTLP::set_cancel(gp_id_t id, bool reply)
170{
171  set_source(qaddr_coordination);
172  set_id(id);
173  subtype = SigCancel;
174  err = SignalingNTLP::error_ok;
175  pdu = NULL;
176  peer = NULL;
177  ownaddr = NULL;
178  encap_pdu = NULL;
179  ref_id = 0;
180  confirm = reply;
181} // end set_cancel
182
183
184/* Terminate (i.e., shut down) a signaling association/connection
185 */
186void 
187SignalingMsgNTLP::set_trm(const appladdress* peeraddr)
188{
189  set_source(qaddr_coordination);
190  subtype = SigTrm;
191  err = SignalingNTLP::error_ok;
192  pdu = NULL;
193  peer = peeraddr;
194  ownaddr = NULL;
195  encap_pdu = NULL;
196  ref_id = 0;
197  confirm = false;
198} // end set_ind
199
200
201void 
202SignalingMsgNTLP::clear_pointers()
203{
204  pdu = NULL;
205  peer = NULL;
206  ownaddr = NULL;
207  encap_pdu = NULL;
208} // end clear_pointers
209
210
211bool 
212SignalingMsgNTLP::send(bool exp)
213{
214  qaddr_t s = get_source();
215  if (s==qaddr_signaling) return send_to(qaddr_coordination,exp);
216  else if (s!=qaddr_unknown) return send_to(qaddr_signaling,exp);
217  else return false;
218} // end send
219
220
221bool SignalingMsgNTLP::set_confirm(bool conf)
222{
223  register bool o = confirm;
224  confirm = conf;
225  return o;
226} // end set_confirm
227
228
229const char* const SignalingMsgNTLP::subtypename[] =
230{
231  "ignore",
232  "SigReq",
233  "SigInd",
234  "SigCnf",
235  "SigRsp",
236  "SigTrm",
237  "SigCancel"
238}; // end subtypename
239
240//@}
241
242
243const char* const SignalingNTLP::errstr[] =
244{
245  "success",
246  "Message sent to peer.",
247  "No address or wrong address.",
248  "Peer unreachable.",
249  "Internal transport protocol error",
250  "No transport protocol found for peer address.",
251  "Wrong PDU type.",
252  "Malformed PDU or PDU state invalid, cannot serialize.",
253  "No matching request found.",
254  "PDU too big for maximum payload size.",
255  "Bad message reference or reference already in use.",
256  "Internal GIST protocol error.",
257  "Internal signaling module error.",
258  "Bad SignalingMsg, wrong subtype for receiver."
259}; // end errstr
260
261
262const char*
263SignalingNTLP::get_error_string(error_t e)
264{
265  return errstr[e];
266}
267
268/**
269 * Initialize Thread base class and GIST protocol.
270 * @param p -- Parameter for Module
271 */
272SignalingNTLP::SignalingNTLP(const SignalingNTLPParam& p)
273  : Thread(p),
274    param(p),
275    gistproto(p.default_originator, p.localnliv4, p.localnliv6, p.well_known_port)
276{
277  // register queue
278 
279  QueueManager::instance()->register_queue(get_fqueue(),p.source);
280  Log(DEBUG_LOG,LOG_NORMAL, param.name, "Created SignalingModule object");
281       
282} // end constructor
283
284
285SignalingNTLP::~SignalingNTLP()
286{
287  Log(DEBUG_LOG,LOG_NORMAL, param.name, "Destroying SignalingModule object");
288  QueueManager::instance()->unregister_queue(param.source);
289} // end destructor
290
291
292/**
293 * Main Loop
294 * @param nr -- Number of thread
295 */
296void 
297SignalingNTLP::main_loop(uint32 nr)
298{
299  Log(DEBUG_LOG,LOG_NORMAL, param.name, "Starting thread #" << nr);
300
301  // process queue of internal messages
302  process_queue();
303
304  Log(DEBUG_LOG,LOG_NORMAL, param.name, "Thread #" << nr << " stopped");
305} // end main_loop
306
307
308
309/**
310 * process queue of internal messages for the signaling module
311 * (usually message::qaddr_signaling)
312 */
313void 
314SignalingNTLP::process_queue()
315{
316  uint32 wait = param.sleep_time*1000; // max. waiting time at internal msg queue
317  message* msg = NULL;
318  SignalingMsgNTLP* sigmsg = NULL;
319  TPMsg* tpmsg = NULL;
320
321  // get queue (param.source is usually message::qaddr_signaling)
322  FastQueue* fq = QueueManager::instance()->get_queue(param.source);
323  if (!fq)
324  {
325    Log(ERROR_LOG,LOG_ALERT, param.name, "Cannot find input msg queue");
326   
327    return;
328  } // end if not fq
329
330 
331  /// wait for messages if in state running
332  while (get_state()==STATE_RUN)
333  {
334    // dequeue message from internal message queue
335    msg= fq->dequeue_timedwait(wait);
336    if (msg)
337    {
338      Log(DEBUG_LOG,LOG_NORMAL, param.name, "Received incoming message #" << msg->get_id() << " on Queue");
339      switch( msg->get_type() )
340      {
341        // message from transport
342        case message::type_transport:
343          {
344           
345            tpmsg = dynamic_cast<TPMsg*>(msg);
346            if (tpmsg)
347            {
348              // process incoming message from TP module (network)
349              process_tp_msg(tpmsg);
350              Log(DEBUG_LOG,LOG_NORMAL, param.name, "Received incoming message #" << msg->get_id() << " from TP Module");
351            }
352            else 
353            {
354              Log(ERROR_LOG,LOG_ALERT, param.name, "Cannot cast message from source " << msg->get_qaddr_name() << " of type " << msg->get_type_name() << " to TPMsg");
355             
356              delete msg;
357            } // end if tpmsg
358          } break;
359         
360          // message from coordinator
361        case message::type_signaling:
362          {
363            sigmsg = dynamic_cast<SignalingMsgNTLP*>(msg);
364            if (sigmsg)
365            {
366              // process message from coordinator to TP
367              // (outgoing message to network)
368              process_sig_msg(sigmsg);
369            }
370            else 
371            {
372              Log(ERROR_LOG,LOG_ALERT, param.name, "Cannot cast message from source " << msg->get_qaddr_name() << " of type " << msg->get_type_name() << " to SignalingMsgNTLP");
373              delete msg;
374            } // end if sigmsg
375          } break;
376         
377          default:
378            {
379              Log(ERROR_LOG,LOG_NORMAL, param.name, "Received a message from " << msg->get_qaddr_name() << " of type " << msg->get_type_name() << " that cannot be processed here");
380             
381              delete msg;
382            }
383      } // end switch
384    } // end if msg
385  } // end while running
386} // end process_queue
387
388
389
390/** process incoming message from TP module
391  * (incoming signaling message from network)
392  * @param tpmsg Internal TPMsg from TP module
393  */
394void 
395SignalingNTLP::process_tp_msg(TPMsg* tpmsg)
396{
397  SignalingMsgNTLP* sigmsg = NULL;
398  NTLP::error_t gisterror;
399  gp_id_t result_id = 0;
400  known_ntlp_pdu* result_pdu = NULL;
401  gp_id_t refid = 0;
402  known_ntlp_pdu* encappdu = NULL;
403
404
405  assert(tpmsg!=NULL);
406
407  Log(DEBUG_LOG,LOG_NORMAL,param.name,"process_tp_msg() - received message #"<< tpmsg->get_id() <<" from TP");
408
409  // remember netmsg and peer from TPmsg
410  NetMsg* netmsg= tpmsg->get_message();
411  // peer may be updated by process_response()
412  appladdress* peer= 0;
413  if (tpmsg->get_peeraddress())
414  { // this will copy the peer address
415    peer= dynamic_cast<appladdress*>(tpmsg->get_peeraddress()->copy());
416  }
417  else
418  {
419    // peer address not set, create empty address
420    peer= new appladdress();
421  }
422
423  const appladdress* ownaddr= dynamic_cast<appladdress*>(tpmsg->get_ownaddress()->copy());
424  if (ownaddr == 0)
425  {
426    Log(ERROR_LOG,LOG_NORMAL,param.name,"process_tp_msg() - ownaddr not set");
427  }
428
429  //Log(DEBUG_LOG,LOG_NORMAL,param.name,"process_tp_msg() - before get_error()");
430
431  // If an incoming tpmsg contains an error it is deleted.
432  if (tpmsg->get_error())
433  {
434    Log(ERROR_LOG,LOG_NORMAL, param.name, "Received error " << tpmsg->get_error()->getstr()
435                                          << " from " << tpmsg->get_qaddr_name() << " peer " ); //<< peer->to_string());
436  }
437  else 
438  {
439    //Log(DEBUG_LOG,LOG_NORMAL,param.name,"process_tp_msg() - before deleting peer address");
440    if (tpmsg->get_peeraddress())
441      delete tpmsg->get_peeraddress();
442    //Log(DEBUG_LOG,LOG_NORMAL,param.name,"process_tp_msg() - before clear_pointers()");
443    // don't need TPMsg any longer, clear pointers
444    tpmsg->clear_pointers();
445
446    // Log(DEBUG_LOG,LOG_NORMAL,param.name,"process_tp_msg() - before assertions");
447    if (peer==0 || ownaddr==0 || netmsg==0)
448      Log(ERROR_LOG,LOG_NORMAL,param.name,"process_tp_msg() - precondition for peer, ownaddr, or netmsg failed");
449
450    //assert(peer!=NULL);
451    //assert(ownaddr!=NULL);
452    //assert(netmsg!=NULL);
453
454    //#define DEBUG_HARD
455    //#ifdef DEBUG_HARD
456    Log(DEBUG_LOG,LOG_NORMAL,param.name,"process_tp_msg() - received PDU now parsing...") ;
457    //#endif
458
459    // process NetMsg by GIST (generates C++ objects from byte stream)
460    gisterror = gistproto.process_tp_recv_msg(*netmsg,*peer,result_id,result_pdu,refid,encappdu);
461
462    Log(DEBUG_LOG,LOG_NORMAL,param.name,"process_tp_msg() - parsed PDU ");
463
464    // now result_id, result_pdu and optionally refid, encappdu are returned
465    // check for result/error during decoding
466    switch (gisterror)
467    {
468      case NTLP::error_ok_in_auth  :
469      case NTLP::error_ok_out_auth :
470        Log(ERROR_LOG,LOG_NORMAL, param.name, "Authentication is not supported yet, deleting PDU");
471       
472        if (peer) delete peer;
473        if (result_pdu) delete result_pdu;
474        if (encappdu) delete encappdu;
475      break;
476
477      // everything ok
478      case NTLP::error_ok :
479      { 
480        sigmsg = new SignalingMsgNTLP;
481
482        assert(result_pdu!=NULL);
483        assert(sigmsg!=NULL);
484
485        // if we received with hops == 0, the sender has probably gone mad, but we throw error at him
486        if (!result_pdu->get_hops())
487        {
488          ERRCLog(param.name, "We received an invalid message with hop limit == 0");
489          senderror(result_pdu, peer, GIST_Error::error_gist_hop_limit_exceeded);
490          delete sigmsg;
491          return;
492        }
493
494        // Decrement the GIST Hop Counter
495        result_pdu->dec_hops();
496
497        // Implement the relaying if no suitable NSLPID is available on the machine
498        uint32 nslpid = result_pdu->get_nslpid();
499
500        if ((nslpid==0) || (param.nslptable.get_address(nslpid) != message::qaddr_unknown))
501        {
502          if (nslpid)
503          {
504            DLog(param.name, color[blue] << "Accepted incoming message, it is addressed to NSLP ID " 
505                << result_pdu->get_nslpid() << " at API interface " << param.nslptable.get_address(result_pdu->get_nslpid()));
506          }
507          else 
508          {
509            DLog(param.name, color[blue] << "Accepted incoming message, it is marked as being not addressed to a specific NSLP at all (maybe GIST MA Hello or GIST Error)");
510          }
511
512          // if this is an incoming response the
513          // service primitive is a confirmation
514          // otherwise (incoming request) it is an indication
515          // if (result_pdu->is_response())  // incoming response -> cnf
516          // sigmsg->set_cnf(result_id,result_pdu,result_pdu);
517          // else // incoming request -> ind
518          sigmsg->set_ind(result_id,peer->copy(),ownaddr->copy(),result_pdu,refid,encappdu);
519             
520          Log(DEBUG_LOG,LOG_NORMAL,param.name,"Passing " << color[red] <<  result_pdu->get_ie_name() << color[off]
521                                               << " msg#" << sigmsg->get_id() << " to coordination");
522             
523          // send this to the coordinator
524          peer = NULL;
525          result_pdu = NULL;
526          encappdu = NULL;
527          if (!sigmsg->send_to(message::qaddr_coordination,false))
528          {
529            Log(ERROR_LOG,LOG_NORMAL, param.name, "Cannot send a message to " << message::get_qaddr_name(message::qaddr_coordination));
530           
531            delete sigmsg;
532          } // end if not sent
533        }
534        else 
535        { // RELAY message!
536
537          //******************** Relay ONLY, if it is a GIST Query Else throw gist_error_unknown_nslpid ***********
538          if ((!result_pdu->is_query()) && (!(result_pdu->is_data() && (peer->get_protocol()==prot_query_encap)))) 
539          {
540           
541            ERRCLog(param.name, "Will not relay other messages than GIST Query or Query Encapsulated GIST Data!");
542            senderror(result_pdu, peer, GIST_Error::error_gist_unknown_nslpid);
543           
544            delete sigmsg;
545            return;
546          }
547
548          //******************** Relay ONLY, if it is addressed to someone else, not to US! ***********************
549          if (is_local_addr(result_pdu->get_mri()->route_next_hop()))
550          {
551            ERRCLog(param.name, "Will NOT relay this message, it is directly addressed to us, the NSLP is unknown -> Spooling Error Message");
552
553            senderror(result_pdu, peer, GIST_Error::error_gist_endnode_found);
554           
555            delete sigmsg;
556            return;
557          }
558
559          //******************** Relay ONLY, if the serialized PDU length is not exceeding 576 byte **************
560
561          // 576 - 8 byte UDP header (?) -> 568byte for PDU
562          if (result_pdu->get_serialized_size(IE::protocol_v1) > max_mtu_size-8)
563          {
564            ERRCLog(param.name, "Will NOT relay this message, it is too large for our MTU limit of " 
565                << max_mtu_size << " bytes");
566
567            senderror(result_pdu, peer, GIST_Error::error_gist_message_too_large);
568
569            delete sigmsg;
570            return;
571          }
572
573          //******************************************************************************************************
574          DLog(param.name, color[blue] << "Incoming Message for which there is no registered NSLP available, relaying message" << color[off]);
575
576          // We only relay, if there are any hops left
577          if (result_pdu->get_hops()>0)
578          {
579            // We must decrement IP TTL on relaying, first grab it
580            uint8 ip_ttl = peer->get_ip_ttl();
581
582            if (!ip_ttl)
583              DLog(param.name, "Got no IP TTL information for this message, which is to relay. TPqueryEncap not working properly? - Message cannot be stopped here based on IP TTL!?!?!");
584
585            // construct target address
586            appladdress* target = result_pdu->get_mri()->route_next_hop();
587            target->set_port(param.well_known_port);
588            target->set_protocol(prot_query_encap);
589            target->set_rao(peer->get_rao());
590           
591                  //decrement IP TTL
592                  if (ip_ttl) {
593                      target->set_ip_ttl(ip_ttl-1);
594                     
595                      if (ip_ttl-1 == 0) {
596                          ERRCLog(param.name, "Discarded the Message to relay, because we had IP TTL information, decremented it as defined in GIST and it is now ZERO.");
597                          delete sigmsg;
598                          return;
599                      }
600                  }
601                 
602                  // here we also call the MRI outgoing interface lookup routine to provide us with a outgoing interface index
603                  sigmsg->set_req(target, result_pdu, 0, result_pdu->get_mri()->get_local_if());
604                  sigmsg->send_or_delete();
605                 
606              } else {
607                  DLog(param.name, "Hop limit exceeded. Discarding Message which does not fit to any local NSLP");
608
609                  senderror(result_pdu, peer, GIST_Error::error_gist_hop_limit_exceeded);
610
611                  delete sigmsg;
612
613              }
614             
615          }       
616      } // end case error_ok
617      break;
618     
619     
620      // parsing resulted in error, send back error PDU
621      case NTLP::error_send_error_pdu :
622      {
623        assert(result_pdu!=NULL);
624        if (netmsg) delete netmsg;
625        netmsg = NULL;
626        Log(INFO_LOG,LOG_NORMAL, param.name, "Trying to send error PDU " << endl << color[magenta] <<  result_pdu->to_string() << color[off] << " to peer " << *peer);
627       
628        gisterror = gistproto.process_outgoing(*result_pdu,*peer,result_id,0,netmsg);
629        if (gisterror==NTLP::error_ok)
630        {
631          // send the returned NetMsg
632          assert(netmsg!=NULL);
633          // netmsg should not be accessed after this call because it may have been already deleted
634          peer->convert_to_ipv6();
635          send_tp(netmsg,*(peer->copy()));
636        } // end if OK
637        if (peer) delete peer;
638        if (result_pdu) delete result_pdu;
639        if (encappdu) delete encappdu;
640        return;
641      }
642      break;
643
644      // parsing resulted in error, do not send back error PDU, only log error
645      case NTLP::error_log_incpduerror_only:
646      {
647        if (netmsg) delete netmsg;
648        netmsg = NULL;
649        Log(ERROR_LOG,LOG_NORMAL, param.name, "Error on incoming PDU, but not sending back error PDU");
650       
651        if (peer) delete peer;
652        if (result_pdu) delete result_pdu;
653        if (encappdu) delete encappdu;
654        return;
655      }
656      break;
657       
658      default:
659      {
660        Log(ERROR_LOG,LOG_NORMAL, param.name, "Received a GIST error that cannot be handled. Deleting NetMsg");
661       
662        if (peer) delete peer;
663        if (result_pdu) delete result_pdu;
664        if (encappdu) delete encappdu;
665      }
666      break;
667    } // end switch gisterror
668
669    // NetMsg is no longer needed
670    if (netmsg)
671      delete netmsg;
672  } // end if get_error
673
674  //Log(DEBUG_LOG,LOG_NORMAL,param.name,"process_tp_msg() - before delete");
675
676  // because pointers are cleared, objects peer and netmsg
677  // are not deleted by calling tpmsg destructor now
678  delete tpmsg;
679
680  //Log(DEBUG_LOG,LOG_NORMAL,param.name,"process_tp_msg() - done.");
681} // end process_tp_msg
682
683
684/**
685 * process message from State Module
686 * (outgoing signaling message, sent subsequently to TP module)
687 */
688void 
689SignalingNTLP::process_sig_msg(SignalingMsgNTLP* sigmsg)
690{
691  NTLP::error_t gisterror = NTLP::error_ok;
692  appladdress peer;
693  known_ntlp_pdu* pdu = NULL;
694  NetMsg* netmsg = NULL;
695  error_t sendres = error_ok;
696
697  assert(sigmsg!=NULL);
698  if (sigmsg->get_error()!=SignalingNTLP::error_ok)
699  {
700    Log(ERROR_LOG,LOG_NORMAL, param.name,
701        "Received SignalingMsg with error " << sigmsg->get_error_string() << ", deleting");
702   
703    delete sigmsg;
704  } // end if error
705
706  switch ( sigmsg->get_subtype() )
707  {
708    case SignalingMsgNTLP::ignore:
709      delete sigmsg;
710      break;
711
712    case SignalingMsgNTLP::SigCancel:
713      {
714        bool revres = gistproto.revoke(sigmsg->get_id());
715        if (sigmsg->get_confirm())
716        {
717          if (revres)
718            send_back_sig_error(error_ok,sigmsg);
719          else 
720            send_back_sig_error(error_no_request_found,sigmsg);
721        }
722        else 
723          delete sigmsg;
724      } break;
725
726    case SignalingMsgNTLP::SigReq:
727      {
728        // look for PDU and peer address
729        if (sigmsg->get_peer() && sigmsg->get_pdu())
730        {
731          // extract data from sigmsg
732          peer = *sigmsg->get_peer();
733          pdu = sigmsg->get_pdu();
734
735          // add basic header if necessary
736          if (sigmsg->get_oif())
737          {
738              DLog(param.name, color[blue] << "We were indicated to request usage of interface " << sigmsg->get_oif() << color[off]);
739          }
740
741          // Log output
742          if (pdu->get_sessionid())
743          {
744            DLog(param.name, "Sending <" << pdu->get_ie_name() << "> sid: " << pdu->get_sessionid()->to_string() << " to " << peer);
745          }
746          else
747          {
748            DLog(param.name, "Sending <" << pdu->get_ie_name() << "> sid: N/A to " << peer);
749          }
750
751          EVLog(param.name, color[magenta] << "Sending (msg#"<< sigmsg->get_id() << "):" << endl << *pdu << color[off]);
752
753          // create GIST message
754          gisterror = gistproto.process_outgoing(*pdu,peer,sigmsg->get_id(),sigmsg->get_ref_id(),netmsg);
755          if (gisterror==NTLP::error_ok)
756          {
757            // send the returned NetMsg
758            assert(netmsg!=NULL);
759            // netmsg should not be accessed after this call because it may have been already deleted
760            peer.convert_to_ipv6();
761            sendres = send_tp(netmsg,peer, sigmsg->get_oif());
762            if (sendres==error_ok)
763            {
764              if (sigmsg->get_confirm())
765                send_back_confirmation(sigmsg);
766              else 
767                delete sigmsg;
768            }
769            else 
770            {
771              // inform GIST
772              gistproto.revoke(sigmsg->get_id());
773              send_back_sig_error(sendres,sigmsg);
774            } // end if senderror
775          }
776          //send_back_gist_error(gisterror,sigmsg);
777        }
778        else 
779          send_back_sig_error(error_bad_sigmsg,sigmsg);
780      }
781      break;
782     
783    case SignalingMsgNTLP::SigRsp:
784      { // send response PDU from coordinator to peer
785        // look for PDU
786        if (sigmsg->get_pdu())
787        {
788          pdu = sigmsg->get_pdu();
789          peer = *(sigmsg->get_peer());
790
791          // Log output
792          if (pdu->get_sessionid())
793          {
794            DLog(param.name, "Sending <" << pdu->get_ie_name() << "> " << *pdu->get_sessionid() << " to " << peer << " (SigRSP)");
795          }
796          else
797          {
798            DLog(param.name, "Sending <" << pdu->get_ie_name() << "> <sessionid>: N/A to " << peer << " (SigRSP)");
799          }
800
801          EVLog(param.name, color[magenta] << "Sending (msg#"<< sigmsg->get_id() << "):" << endl << *pdu << color[off]);
802
803          // GIST must serialize this PDU now
804          gisterror = gistproto.process_response(sigmsg->get_id(),*pdu,sigmsg->get_ref_id(),netmsg,peer);
805          if (gisterror==NTLP::error_ok)
806          {
807            // send the returned NetMSg
808            assert(netmsg!=NULL);
809            // netmsg should not be accessed after this call because it may have been already deleted
810            peer.convert_to_ipv6();
811            sendres = send_tp(netmsg,peer);
812            if (sendres==error_ok)
813            {
814              // SignalingMsg with PDU and address is no longer needed
815                if (sigmsg->get_confirm()) {
816               
817
818                  //==================================================================
819
820                  //    !!! Confirmation to message sender temporarily deactivated !!!
821
822                  //==================================================================
823
824 
825                //send_back_confirmation(sigmsg);
826                }             
827                else 
828                    delete sigmsg;
829            }
830            else 
831            {
832              send_back_sig_error(sendres,sigmsg);
833            } // end if senderror
834          }
835     
836        }
837        else 
838          send_back_sig_error(error_bad_sigmsg,sigmsg);
839      } // end process sig response
840      break;
841
842    case SignalingMsgNTLP::SigTrm:
843      {
844        // terminate a signaling connection
845        error_t res= error_ok;
846        if (sigmsg->get_peer())
847          peer= *sigmsg->get_peer();
848
849        TP* tp = param.get_tp(peer.get_protocol());
850        if (tp) {
851          // terminate
852          try {
853            Log(EVENT_LOG,LOG_NORMAL,param.name,"Terminating connection/association " << peer);
854                        tp->terminate(peer);
855          } catch(TPError& e)
856          {
857            switch (e.err) {
858              case TPError::ERROR_BAD_ADDRESS: res = error_bad_address; break;
859              case TPError::ERROR_BAD_NETMSG: res = error_internal; break;
860              case TPError::ERROR_UNREACHABLE: res = error_unreachable; break;
861              case TPError::ERROR_PAYLOAD: res = error_max_payload; break;
862              default: res = error_tp_internal; break;
863            }
864          } catch(...) {
865            res = error_tp_internal;
866          } // end try-catch
867        }
868        else
869        {
870          Log(ERROR_LOG,LOG_NORMAL,param.name,"Protocol #" << (int) peer.get_protocol() << " (" << peer.get_protocol_name() << ") not found");
871        }
872       
873        if (sigmsg->get_confirm())
874        {
875          sigmsg->set_error(res);
876          if (!sigmsg->send_back(param.source,param.send_error_expedited)) delete sigmsg;
877        }
878      }
879      break;
880
881     
882    default:
883      {
884        Log(ERROR_LOG,LOG_NORMAL, param.name, "Received SignalingMsg of wrong subtype, trying to send error");
885       
886        sigmsg->set_error(error_bad_sigmsg);
887        if (!sigmsg->send_back(param.source,param.send_error_expedited)) delete sigmsg;
888      }
889      break;
890
891
892  } // end switch get_subtype
893} // end process_sig_msg
894
895void 
896SignalingNTLP::send_back_sig_error(error_t err, SignalingMsgNTLP* msg)
897{
898  assert(msg!=NULL);
899  msg->set_error(err);
900  Log(ERROR_LOG,LOG_NORMAL, param.name, "An error occured, trying to send error [" << msg->get_error_string() << "] to " << msg->get_qaddr_name());
901       
902  if (!msg->send_back(param.source,param.send_error_expedited)) delete msg;
903} // end send_back_sig_error
904
905void 
906SignalingNTLP::send_back_confirmation(SignalingMsgNTLP* msg)
907{
908  assert(msg!=NULL);
909  msg->set_error(error_msg_sent);
910  if (!msg->send_back(param.source,param.send_error_expedited))
911  {
912    Log(ERROR_LOG,LOG_NORMAL, param.name, "Cannot send message-sent confirmation to " << msg->get_qaddr_name());
913               
914    delete msg;
915  } // end if not sent
916} // end send_back_confirmation
917
918SignalingNTLP::error_t
919SignalingNTLP::send_tp(NetMsg* msg, const appladdress& addr, uint16 oif)
920{
921  error_t res = error_ok;
922  TP* tp = param.get_tp(addr.get_protocol());
923  if (tp)
924  {
925    // send message
926    try 
927    {
928       Log(EVENT_LOG,LOG_NORMAL,param.name,"Sending msg to Protocol #" << (int) addr.get_protocol()
929                                           << " (" << addr.get_protocol_name() << ") Dest:" << addr.get_ip_str());
930
931      if (oif) DLog(param.name, "send_tp: Request to use specific interface received, index: " << oif);
932
933
934      // the following call should only return after the message has been sent (synchronous call)
935      // or the TP must ensure that it works on copies of both parameters since they might get freed
936      // soon after this method returns...
937      tp->send(msg,addr);
938    }
939    catch(TPError& e)
940    {
941      switch (e.err)
942      {
943        case TPError::ERROR_BAD_ADDRESS: res = error_bad_address; break;
944        case TPError::ERROR_BAD_NETMSG: res = error_internal; break;
945        case TPError::ERROR_UNREACHABLE: res = error_unreachable; break;
946        case TPError::ERROR_PAYLOAD: res = error_max_payload; break;
947        default: res = error_tp_internal; break;
948      }
949    }
950    catch(...)
951    {
952      res = error_tp_internal;
953    } // end try-catch
954  }
955  else
956  {
957    Log(ERROR_LOG,LOG_NORMAL,param.name,"Protocol #" << (int) addr.get_protocol() << " (" << addr.get_protocol_name() << ") not found");
958    res = error_no_tp;
959  }
960  return res;
961} // end send_tp
962
963
964void 
965SignalingNTLP::senderror(const known_ntlp_pdu* pdu, const appladdress* peer, GIST_Error::gist_error_code_t error)
966{
967  DLog(param.name, "Error Message Sender called");
968
969  errorobject* errobj = NULL;
970
971  bool dgram = (peer->get_protocol() == prot_query_encap) || (peer->get_protocol() == tsdb::get_udp_id());
972  bool qe = (peer->get_protocol() == prot_query_encap);
973           
974  mri* mr = NULL;
975  sessionid* sid = NULL;
976
977  switch (error)
978  {
979    case GIST_Error::error_gist_no_routing_state:
980           
981      if (pdu->get_mri()) mr = pdu->get_mri()->copy();
982      if (pdu->get_sessionid()) sid = pdu->get_sessionid()->copy();
983           
984      errobj = new errorobject(mr, sid, errorobject::ProtocolError, errorobject::err_NoRoutingState, 0, pdu->get_version(), pdu->get_hops(), pdu->get_length(), pdu->get_nslpid(), pdu->get_type(), pdu->get_flags(), dgram, qe, NULL, 0);
985      break;
986
987    case GIST_Error::error_gist_endnode_found:
988      if (pdu->get_mri()) mr = pdu->get_mri()->copy();
989      if (pdu->get_sessionid()) sid = pdu->get_sessionid()->copy();
990     
991      errobj = new errorobject(mr, sid, errorobject::PermanentFailure, errorobject::err_EndpointFound, 0, pdu->get_version(), pdu->get_hops(), pdu->get_length(), pdu->get_nslpid(), pdu->get_type(), pdu->get_flags(), dgram, qe, NULL, 0);
992      break;
993
994    case GIST_Error::error_gist_unknown_nslpid:
995      if (pdu->get_mri()) mr = pdu->get_mri()->copy();
996      if (pdu->get_sessionid()) sid = pdu->get_sessionid()->copy();
997     
998      errobj = new errorobject(mr, sid, errorobject::PermanentFailure, errorobject::err_UnknownNSLPID, 0, pdu->get_version(), pdu->get_hops(), pdu->get_length(), pdu->get_nslpid(), pdu->get_type(), pdu->get_flags(), dgram, qe, NULL, 0);
999      break;
1000     
1001     
1002    case GIST_Error::error_gist_message_too_large:
1003      if (pdu->get_mri()) mr = pdu->get_mri()->copy();
1004      if (pdu->get_sessionid()) sid = pdu->get_sessionid()->copy();
1005     
1006      errobj = new errorobject(mr, sid, errorobject::PermanentFailure, errorobject::err_MessageTooLarge, 0, pdu->get_version(), pdu->get_hops(), pdu->get_length(), pdu->get_nslpid(), pdu->get_type(), pdu->get_flags(), dgram, qe, NULL, 0, max_mtu_size);
1007      break;
1008     
1009     
1010    case GIST_Error::error_gist_hop_limit_exceeded:
1011      if (pdu->get_mri()) mr = pdu->get_mri()->copy();
1012      if (pdu->get_sessionid()) sid = pdu->get_sessionid()->copy();
1013     
1014      errobj = new errorobject(mr, sid, errorobject::PermanentFailure, errorobject::err_HopLimitExceeded, 0, pdu->get_version(), pdu->get_hops(), pdu->get_length(), pdu->get_nslpid(), pdu->get_type(), pdu->get_flags(), dgram, qe, NULL, 0, max_mtu_size);
1015      break;
1016     
1017    default:
1018      DLog(param.name, "Yet unhandled Error thrown (code: " << error << "), will not send Error Message");
1019      break;
1020     
1021  } // end switch
1022 
1023  uint8 ip_version = (mr!=0) ? mr->get_ip_version() : 4;
1024   
1025  nli* mynl = NULL;
1026
1027  if (ip_version == 4)
1028  {
1029    mynl = param.localnliv4.copy();
1030  }
1031  else 
1032  {
1033    mynl = param.localnliv6.copy();
1034  }
1035
1036  ntlp::error* errpdu = new ntlp::error(mynl, errobj);
1037
1038  errpdu->set_hops(1);
1039
1040  // calculate the address
1041  appladdress* target = NULL;
1042
1043  // IP source is NOT the last GIST hop
1044  if (!pdu->get_S())
1045  {
1046    if (pdu->get_nli())
1047    { // if IP Source is NOT last GIST hop, sending to GIST denoted by NLI
1048      DLog(param.name, "IP Source is NOT last GIST hop, sending to GIST denoted by NLI");
1049      target = new appladdress(*(pdu->get_nli()->get_if_address()), "udp", param.well_known_port);
1050    }
1051    else 
1052    {
1053      ERRCLog(param.name, "No valid target address for Error Message found. Dropping errormessage: " << pdu);   
1054    }   
1055  }
1056  else 
1057  {
1058    DLog(param.name, "IP Source IS last GIST hop, sending to it.");
1059    target = new appladdress(*peer);
1060    if (target->get_protocol()==prot_query_encap) target->set_protocol(tsdb::get_udp_id());
1061    if (target->get_protocol()==tsdb::get_udp_id()) target->set_port(param.well_known_port);
1062  }
1063 
1064  SignalingMsgNTLP* sigmsg = new SignalingMsgNTLP;
1065  sigmsg->set_req(target, errpdu);
1066  sigmsg->send_or_delete();
1067}
1068
1069
1070bool 
1071SignalingNTLP::is_local_addr(const hostaddress* addr)
1072{
1073
1074  DLog("GIST Signaling", "Checking if " << addr->get_ip_str() << " is a local one");
1075
1076  // First: Copy the address, convert it to IPv6 (it will make NO difference)
1077
1078  hostaddress* myaddr=addr->copy();
1079  myaddr->convert_to_ipv6();
1080 
1081  char* ifname= new char[IF_NAMESIZE];
1082 
1083  //so we can decide via "is_mapped_ip" if its v4 or v6, v4 in_addr can be derived from it too!!
1084   
1085  if (!myaddr->is_mapped_ip())
1086  {
1087    // Now do the RTNetlink Magic
1088       
1089    // sockaddr_in6?
1090    struct in6_addr dstaddr;
1091   
1092    // Netlink Message header plus RTNetlink Message Header plus 1024byte data
1093    struct {
1094      struct nlmsghdr n;
1095      struct rtmsg r;
1096      char data[1024];
1097    } req;
1098   
1099    // Struct rtattr
1100    struct rtattr *attr;
1101   
1102    // int outgoinginterface
1103    uint16 outgoinginterface = 0;
1104   
1105    // OPEN an RTNETLINK SOCKET
1106    int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1107    if (sock < 0)
1108    {
1109      Log(ERROR_LOG, LOG_NORMAL, "GIST Signaling", "Error Opening Netlink Socket: " << strerror(errno));
1110    }
1111       
1112    myaddr->get_ip(dstaddr);
1113       
1114    memset(&req, 0, sizeof(req));
1115    req.n.nlmsg_len =
1116      NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.r))) +
1117      RTA_LENGTH(sizeof(dstaddr));
1118    req.n.nlmsg_flags = NLM_F_REQUEST;
1119    req.n.nlmsg_type = RTM_GETROUTE;
1120    req.r.rtm_family = AF_INET6;
1121    req.r.rtm_dst_len = 128;
1122    req.r.rtm_src_len = 0;
1123   
1124    attr = reinterpret_cast<rtattr*>(reinterpret_cast<char *>(&req) + NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.r))));
1125    attr->rta_type = RTA_DST;
1126    attr->rta_len = RTA_LENGTH(sizeof(dstaddr));
1127   
1128    memcpy(RTA_DATA(attr), &dstaddr, sizeof(dstaddr));
1129   
1130    /* Send the message */
1131    if (send(sock, &req, req.n.nlmsg_len, 0) < 0)
1132    {
1133      Log(ERROR_LOG, LOG_NORMAL, "GIST Signaling", "Error sending netlink message: " << strerror(errno));
1134      close(sock);
1135    }
1136       
1137    char* returnbuf = new char[NL_BUFSIZE];
1138       
1139    readnl(sock, returnbuf);
1140       
1141    nlmsghdr* nlhdrp = reinterpret_cast<struct nlmsghdr *>(returnbuf);
1142       
1143    rtmsg* rtmsg = static_cast<struct rtmsg*>(NLMSG_DATA(nlhdrp));
1144       
1145    // Iterate through data area serachin
1146       
1147    rtattr* attrp = RTM_RTA(rtmsg);
1148    uint32 attrlen = RTM_PAYLOAD(nlhdrp);
1149       
1150    for( ; RTA_OK(attrp, attrlen); attrp = RTA_NEXT(attrp, attrlen) )
1151    {
1152      if ((attrp->rta_type) == RTA_OIF)
1153      {
1154        if_indextoname(*(int *)RTA_DATA(attrp), ifname);
1155               
1156        Log(EVENT_LOG, LOG_NORMAL, "mri_pathcoupled""Kernel decided the outgoing interface index would be " << *(int *)RTA_DATA(attrp) << ", interface Name " << ifname);
1157               
1158        outgoinginterface=*(int *)RTA_DATA(attrp);
1159      }
1160    } // end for 
1161  }
1162  else 
1163  {
1164    // IPv4!
1165
1166    // Now do the RTNetlink Magic
1167   
1168    // sockaddr_in
1169    struct in_addr dstaddr;
1170       
1171    // Netlink Message header plus RTNetlink Message Header plus 1024byte data
1172    struct {
1173      struct nlmsghdr n;
1174      struct rtmsg r;
1175      char data[1024];
1176    } req;
1177   
1178    // Struct rtattr
1179    struct rtattr *attr;
1180       
1181    // int outgoinginterface
1182    uint16 outgoinginterface = 0;
1183       
1184    // OPEN a RTNETLINK SOCKET
1185       
1186    int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1187    if (sock < 0)
1188    {
1189      Log(ERROR_LOG, LOG_NORMAL, "GIST Signaling", "Error Opening Netlink Socket: " << strerror(errno));
1190    }
1191       
1192    myaddr->get_ip(dstaddr);
1193       
1194    memset(&req, 0, sizeof(req));
1195    req.n.nlmsg_len =
1196      NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.r))) +
1197      RTA_LENGTH(sizeof(dstaddr));
1198    req.n.nlmsg_flags = NLM_F_REQUEST;
1199    req.n.nlmsg_type = RTM_GETROUTE;
1200    req.r.rtm_family = AF_INET;
1201    req.r.rtm_dst_len = 32;
1202    req.r.rtm_src_len = 0;
1203       
1204    attr = reinterpret_cast<rtattr*>(reinterpret_cast<char *>(&req) + NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.r))));
1205    attr->rta_type = RTA_DST;
1206    attr->rta_len = RTA_LENGTH(sizeof(dstaddr));
1207   
1208    memcpy(RTA_DATA(attr), &dstaddr, sizeof(dstaddr));
1209   
1210   
1211    /*Send the message*/
1212   
1213    if (send(sock, &req, req.n.nlmsg_len, 0) < 0) {
1214      Log(ERROR_LOG, LOG_NORMAL, "GIST Signaling", "Error while sending to Netlink Socket: " << strerror(errno));
1215      close(sock);
1216    }
1217       
1218    char* returnbuf = new char[NL_BUFSIZE];
1219       
1220    readnl(sock, returnbuf);
1221       
1222    nlmsghdr* nlhdrp = reinterpret_cast<struct nlmsghdr *>(returnbuf);
1223       
1224    rtmsg* rtmsg = static_cast<struct rtmsg*>(NLMSG_DATA(nlhdrp));
1225       
1226    // Iterate through data area
1227       
1228    rtattr* attrp = RTM_RTA(rtmsg);
1229    uint32 attrlen = RTM_PAYLOAD(nlhdrp);
1230       
1231    for( ; RTA_OK(attrp, attrlen); attrp = RTA_NEXT(attrp, attrlen) )
1232    {
1233      if ((attrp->rta_type) == RTA_OIF)
1234      {
1235        if_indextoname(*(static_cast<int *>(RTA_DATA(attrp))), ifname);
1236               
1237        Log(EVENT_LOG, LOG_NORMAL, "mri_pathcoupled""Kernel decided the outgoing interface index would be " << *(int *)RTA_DATA(attrp) << ", interface Name " << ifname);
1238               
1239        outgoinginterface=*(static_cast<int *>(RTA_DATA(attrp)));
1240      }
1241    } // end for
1242
1243    close(sock);
1244   
1245  }
1246   
1247  if (!strncmp(ifname, "lo", 2)) {
1248    DLog("Signaling", "This address is a local one - should not be used for relaying");
1249    return true; 
1250  }
1251
1252  return false;
1253}
1254
1255
1256//@}
1257
1258}//end namespace protlib
Note: See TracBrowser for help on using the browser.