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

source: ntlp/branches/20081127-merge-mobility-mk3/src/ntlp_statemodule_api.cpp @ 4147

Last change on this file since 4147 was 4147, checked in by bless, 8 years ago
  • merged in changes from current trunk, reverted changes from r3121 and r3185, compiles at least
  • Property svn:keywords set to Id HeadURL Rev
File size: 30.7 KB
Line 
1/// ----------------------------------------*- mode: C++; -*--
2/// @file ntlp_statemodule_api.cpp
3/// GIST state module - implements API interactions for GIST
4/// ----------------------------------------------------------
5/// $Id: ntlp_statemodule_api.cpp 4147 2009-07-21 16:02:36Z bless $
6/// $HeadURL: ntlp/branches/20081127-merge-mobility-mk3/src/ntlp_statemodule_api.cpp $
7// ===========================================================
8//                     
9// Copyright (C) 2005-2007, all rights reserved by
10// - Institute of Telematics, Universitaet Karlsruhe (TH)
11//
12// More information and contact:
13// https://projekte.tm.uka.de/trac/NSIS
14//                     
15// This program is free software; you can redistribute it and/or modify
16// it under the terms of the GNU General Public License as published by
17// the Free Software Foundation; version 2 of the License
18//
19// This program is distributed in the hope that it will be useful,
20// but WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22// GNU General Public License for more details.
23//
24// You should have received a copy of the GNU General Public License along
25// with this program; if not, write to the Free Software Foundation, Inc.,
26// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27//
28// ===========================================================
29/** @ingroup statemodule
30 * Statemodule
31 *
32 * This module implements API functions for GIST
33 *
34 * Messages from network are processed and routing state is managed.
35 *
36 */
37#include "ntlp_statemodule.h"
38#include <sstream>
39
40#include "gist_conf.h"
41
42namespace ntlp {
43
44/** @deftogroup gistapi GIST application programming interface interactions
45 *  @ingroup statemodule
46 *  @ingroup ntlp
47 * @{
48 */
49
50using namespace protlib;
51
52
53/**
54 * process API messages from NSLP modules or from APIWrapper module
55 * @param apimsg -- the messge to process
56 */
57void 
58Statemodule::process_api_msg(APIMsg* apimsg) 
59{
60  // Putting Message Source and NSLPID into nslptable
61  param.nslptable.save_address(apimsg->get_nslpid(), apimsg->get_source());
62
63  EVLog(param.name, color[blue] << "API call received: " << color[off] 
64        << apimsg->get_subtype_name() << " msg#" << apimsg->get_id() << " from NSLPID " << apimsg->get_nslpid() 
65      << " at API interface address " << param.nslptable.get_address(apimsg->get_nslpid()));
66
67   
68  // ===============================================
69  // Start Processing
70  // ===============================================
71 
72
73  switch (apimsg->get_subtype()) 
74  {
75    case APIMsg::Register: 
76    { // ================
77      EVLog(param.name, "NSLP registered with NSLPID " << apimsg->get_nslpid() << " at address " << apimsg->get_source());
78     
79      uint16 rao = apimsg->get_rao();
80     
81      param.rt.add_rao(apimsg->get_nslpid(), rao);
82      EVLog(param.name, "Registered RAO value " << rao << " for this NSLPID");
83     
84      bool found = false;
85      for (unsigned int i = 0; i < param.raovec.size(); i++) {
86        if (param.raovec[i] == rao) found = true;
87      }
88       
89      if (!found) param.raovec.push_back(apimsg->get_rao());
90       
91      ostringstream os;
92     
93      for (unsigned int i = 0; i < param.raovec.size(); i++) {
94        os << "|" << param.raovec[i];
95      }
96     
97      EVLog(param.name, "Now intercepting the following RAOs: " << os.str().c_str());
98     
99      break;
100    }
101
102
103    case APIMsg::SendMessage: 
104    { // ===================
105      tg_send_message(apimsg);
106      break;
107    }
108
109    case APIMsg::RecvMessageAnswer: 
110    { // =========================
111      tg_recv_message_answer(apimsg);
112      break;
113    }
114
115
116    case APIMsg::InvalidateRoutingState: 
117    { // ==============================
118      DLog(param.name, "InvalidateRoutingState received, carrying out the instructions");
119     
120      if (apimsg->get_status_change()==APIMsg::bad) 
121      {
122        DLog(param.name, "We are requested to put state to BAD, this means we put it to state DEAD");
123        param.rt.invalidate_routing_state(apimsg->get_mri()->copy(), apimsg->get_nslpid(), apimsg->get_status_change(), apimsg->get_urgency());
124      }
125       
126      if (apimsg->get_status_change()==APIMsg::tentative) 
127      {
128        DLog(param.name, "We are requested to put state to TENTATIVE, this means we put it to state REFRESH and carry out a Refresh, even if we are not requested via 'urgency' flag");
129        param.rt.invalidate_routing_state(apimsg->get_mri()->copy(), apimsg->get_nslpid(), apimsg->get_status_change(), apimsg->get_urgency());
130       
131      }
132
133      if ((apimsg->get_status_change()!=APIMsg::bad) && (apimsg->get_status_change()!=APIMsg::tentative)) {
134        WLog(param.name, "It is not foreseen that NSLP may set Routing State to something other than BAD or TENTATIVE - doing nothing");
135      }
136      break;
137    }
138     
139
140    case APIMsg::SetStateLifetime: 
141    { // =========================
142      DLog(param.name, "SetStateLifetime received, carrying out the instructions");
143     
144      param.rt.set_state_lifetime(apimsg->get_mri()->copy(), apimsg->get_nslpid(), apimsg->get_state_lifetime());
145      break;
146    }
147
148    default: 
149      {
150        ERRCLog(param.name, "API call unimplemented"); 
151      }
152    } // end switch
153   
154    delete apimsg;
155
156} // end process_api_message
157
158
159/**
160 * Deliver received data to NSLP instance
161 * @param peer -- the peer from which we received the data
162 * @param own_addr -- the IP address of the interface we received the data on
163 * @param pdu -- the pdu containing the data (may NOT be NULL)
164 * @param r_key -- the routing key (may be NULL)
165 * @param r_entry -- the routing entry itself (may be NULL)
166 */
167void
168Statemodule::deliver(const appladdress* peer, const appladdress* own_addr, const known_ntlp_pdu* pdu, const routingkey* r_key, const routingentry* r_entry) 
169{
170  APIMsg* msg = new APIMsg;
171
172  assert (pdu != NULL);
173
174  nslpdata* mydata = pdu->get_nslpdata();
175 
176  assert( pdu->get_mri() != NULL );
177  mri* mymr=pdu->get_mri()->copy();
178   
179  // get SII-Handle from PDU (from NLI info is present), if unavailable (GIST Data Message or Message in C-Mode) take it from entry
180
181  // check NLI information
182  nli* nlinfo=  pdu->get_nli();
183
184  uint32 sii_handle = nlinfo ? param.rt.get_sii_handle(nlinfo) : 0;
185
186  tx_attr_t myattr;
187   
188  if (r_entry) {
189    myattr.secure=r_entry->secure;
190    myattr.reliable=!(r_entry->dmode);
191
192    if (!sii_handle)
193    {
194      sii_handle= r_entry->sii_handle;
195    }
196  } else {
197    // Initial Query/Initial Confirm, D-Mode, unsecure
198    myattr.secure=false;
199    myattr.reliable=false;
200  }
201
202  /*
203   * Check if this GIST node is the final hop for this flow. This is the
204   * case if either
205   *     1. this is a downstream message and we are the destination hop, or
206   *     2. this is an upstream message and we are the source hop
207   *
208   * We have to compare the relevant address with each of our own addresses,
209   * given in the configuration.
210   */
211  if ( mymr->get_downstream() )
212    myattr.final_hop = is_local_address(mymr->get_destaddress());
213  else
214    myattr.final_hop = is_local_address(mymr->get_sourceaddress());
215
216  DLog("statemodule", "GIST node is the final hop: " << myattr.final_hop);
217
218  nslpdata* senddata = NULL;
219
220  if (mydata) senddata = new nslpdata(*mydata);
221
222  uint8 ip_distance = 0;
223  uint8 ip_ttl = 0;
224
225  if (nlinfo) 
226  {
227    ip_ttl = nlinfo->get_ip_ttl();
228  } 
229  else 
230  {
231    if (r_entry) {
232      if (r_entry->nl) ip_ttl = r_entry->nl->get_ip_ttl();
233    }
234  }
235
236  if (nlinfo && peer->get_ip_ttl()) 
237  {
238    ip_distance = ip_ttl - peer->get_ip_ttl();
239  } 
240  else 
241  {
242    if (r_entry && peer->get_ip_ttl()) {
243      ip_distance = r_entry->nl->get_ip_ttl() - peer->get_ip_ttl();
244    }
245  }
246
247  msg->set_recvmessage(senddata, own_addr->copy(), pdu->get_nslpid(), new sessionid(*(pdu->get_sessionid())), mymr, false, sii_handle, myattr, ip_ttl, ip_distance, pdu->get_hops(), r_entry ? r_entry->get_incoming_if() : 0 );
248   
249  msg->send_to(param.nslptable.get_address(pdu->get_nslpid()));
250
251  DLog(param.name, "Message passed to NSLP instance at address "
252       << param.nslptable.get_address(pdu->get_nslpid()));
253}
254
255
256
257
258/**
259 * Deliver received data to NSLP instance and set adjacency check flag
260 * @param peer -- the peer from which we received the data
261 * @param own_addr -- the IP address of the interface we received the data on
262 * @param pdu -- the pdu containing the data (may NOT be NULL)
263 * @param r_entry -- the routing entry itself
264 */
265void
266Statemodule::deliver_adjacency_flag(const appladdress* peer, const appladdress* own_addr, const known_ntlp_pdu* pdu, const routingentry* r_entry) 
267{
268  APIMsg* msg = new APIMsg;
269
270  nslpdata* mydata = pdu->get_nslpdata();
271
272 
273  if( pdu->get_mri() == NULL )
274  {
275          // at this stage it is not possible that an MRI in the PDU is missing since it should have
276          // been checked twice, i.e., during parsing and in ntlp_statemodule_main
277          ERRCLog("statemodule","deliver_adjacency_flag(): PDU contains no MRI, which is required though. This should not happen and is an internal error.");
278          return;
279  }
280 
281  nattraversal* nattravobj= pdu->get_nattraversal(); 
282  mri* pdumri= pdu->get_mri()->copy();
283  // use MRI from NTO if present
284  mri* ntomri= nattravobj ? nattravobj->get_embedded_mri()->copy() : 0;
285       
286  tx_attr_t myattr;
287       
288  if (r_entry) {
289    myattr.secure=r_entry->secure;
290    myattr.reliable=!(r_entry->dmode);
291  } else {
292    // Initial Query/Initial Confirm, D-Mode, unsecure
293    myattr.secure=false;
294    myattr.reliable=false;
295  }
296
297  // check for final hop, same as in Statemodule::deliver()
298  // this must be done using the outer flow destination address
299  if ( pdumri->get_downstream() )
300    myattr.final_hop = is_local_address(pdumri->get_destaddress());
301  else
302    myattr.final_hop = is_local_address(pdumri->get_sourceaddress());
303
304  DLog("statemodule", "GIST node is the final hop: " << myattr.final_hop);
305
306  nslpdata* senddata = NULL;
307
308  if (mydata) senddata = new nslpdata(*mydata);
309
310  uint8 ip_distance = 0;
311  // if we can do distance calculation, DO IT!
312  if (peer->get_ip_ttl()) {
313    if (pdu->get_nli()) {
314      ip_distance = pdu->get_nli()->get_ip_ttl() - peer->get_ip_ttl();
315    }
316  }
317
318  // TODO: for MA setup only
319  msg->set_recvmessage(senddata, own_addr->copy(), 
320                       pdu->get_nslpid(), 
321                       pdu->get_sessionid()->copy(), 
322                       ntomri ? ntomri : pdumri,  // use MRI from NAT traversal object if present
323                       true, 0, myattr, 
324                       pdu->get_nli()->get_ip_ttl(), 
325                       ip_distance, 
326                       pdu->get_hops(), 
327                       r_entry ? r_entry->get_incoming_if() : 0 );
328   
329  msg->send_to(param.nslptable.get_address(pdu->get_nslpid()));
330
331  DLog(param.name, "Message passed to NSLP instance at address "<< param.nslptable.get_address(pdu->get_nslpid()));
332}
333
334
335/**
336 * Notify NSLP via NetworkNotification about Changes, store state in r_entry (esentially, give MRI, SII-Handle and state)
337 * @param r_key -- the routing key (may NOT be NULL)
338 * @param r_entry -- the routing entry itself (may NOT be NULL)
339 * @param status -- the Status to report to NSLP
340 * @param force -- force notification, even if the same status was rported before (used on rerouting events)
341 */
342void 
343Statemodule::networknotification(const routingkey* r_key, routingentry* r_entry, APIMsg::error_t status, bool force) {
344  if ((r_entry->rtstate!=status) || force) 
345  {
346    // save the change
347    r_entry->rtstate = status;
348       
349    mri* mymri = r_key->mr->copy();
350    APIMsg* msg = new APIMsg;
351       
352    sessionid* mysid = r_key->sid->copy();
353   
354    msg->set_source(message::qaddr_coordination);
355       
356    msg->set_networknotification(r_key->nslpid, mysid, mymri, status, r_entry->sii_handle);
357       
358    msg->send_to(param.nslptable.get_address(r_key->nslpid));
359       
360    EVLog(param.name, color[yellow] << "NetworkNotification passed to NSLP instance at address "<< param.nslptable.get_address(r_key->nslpid) << ": " << msg->get_error_str(status) << color[off]);
361  } else {
362    DLog(param.name, color[yellow] << "Routing State unchanged, no need to notify NSLP" << color[off]);
363  }
364}
365
366
367/**
368 * Notify NSLP via MessageStatus about Message Failures
369 * @param r_key -- the routing key (may NOT be NULL)
370 * @param r_entry -- the routing entry itself (may NOT be NULL)
371 * @param nslpmsghandle -- the Msg Handle of the message referred to
372 * @param status -- the status to report
373 */
374void 
375Statemodule::messagestatus(const routingkey* r_key, routingentry* r_entry, msghandle_t nslpmsghandle, APIMsg::error_t status) {
376 
377  APIMsg* msg = new APIMsg;
378
379  msg->set_source(message::qaddr_coordination);
380   
381  tx_attr_t txattr;
382  txattr.secure=r_entry->secure;
383  txattr.reliable=!r_entry->dmode;
384  txattr.final_hop = false; // meaningless in this context
385
386  sessionid *sid = NULL;
387  if ( r_key->sid != NULL )
388    sid = r_key->sid->copy(); // ApiMsg's destructor will delete it
389
390  msg->set_messagestatus(r_key->nslpid, sid, nslpmsghandle, txattr, status);
391
392  msg->send_to(param.nslptable.get_address(r_key->nslpid));
393   
394  EVLog(param.name, color[yellow] << "MessageStatus passed to NSLP instance at address "<< param.nslptable.get_address(r_key->nslpid) << ": " << msg->get_error_str(status) << color[yellow]);
395
396}
397
398
399/**
400 * SendMessage API Call processing, set up state or send via existing state a GIST Data
401 * @param apimsg -- the API message from caller containing all data we need
402 */
403void 
404Statemodule::tg_send_message(APIMsg* apimsg) 
405{
406  assert(apimsg != NULL);
407
408  if (!apimsg->get_mri()) 
409  {
410    ERRCLog(param.name, "SendMessage Call without given MRI");
411    return;
412  }
413
414  bool explicit_routed = false;
415
416  if (apimsg->get_sii_handle()) 
417  {
418    DLog("param.name", "Got an explicit routing request, using entry derived from SII-Handle");
419    explicit_routed = true;
420  }
421
422  transfer_t transtype;
423 
424  // if MRI contains IPv4 and IPv6 mix, we bail out and inform via LOG entry. This is the NSLP's fault and an error
425  hostaddress src = apimsg->get_mri()->get_sourceaddress();
426  hostaddress dst = apimsg->get_mri()->get_destaddress();
427
428  if (src.is_ipv6() != dst.is_ipv6()) 
429  {
430    ERRCLog(param.name, "MRI of API call contains mixed IPv4/IPv6 addresses, dropping");
431    delete apimsg;
432    return;
433  }
434   
435  // print some info
436  DLog(param.name, color[yellow] << "IP TTL: " << apimsg->get_ip_ttl() << " GHC: " << apimsg->get_ghc() << color[off]);
437   
438  // 1st step: Look for Routing State
439   
440  routingentry* r_entry=NULL;
441   
442  // create a new routingkey, this will in the end given to timermessage, a copy is stored in routingtable
443  routingkey* r_key=new routingkey();
444   
445  r_key->mr=(apimsg->get_mri())->copy();
446  r_key->sid=new sessionid(*(apimsg->get_sessionid()));
447  r_key->nslpid=apimsg->get_nslpid();
448   
449  //DLog(param.name, "Routing map key created from API Message for NSLPID " << r_key->nslpid);
450   
451  //r_key->mr->print(cout, 0, 0);
452  //r_key->sid->print(cout, 0, 0);
453   
454   
455  //=======================================================
456  // look up routing state and print a status dump of routing table
457  //=======================================================
458  param.rt.status();
459 
460  // try to do explicit routing and return
461  if (explicit_routed) 
462  {
463    DLog(param.name, "Explicit Routing requested");
464       
465    send_data_explicit(apimsg);
466       
467//    delete apimsg;
468    return;
469  } 
470     
471  DLog(param.name, "No explicit routing, try to look up the normal way");
472  // look up routing state in routing map. If there is none, r_entry remains NULL
473  r_entry=param.rt.lookup(r_key);
474
475  // 2nd step: Consider which type of transmit is needed for the message
476   
477  // look for nslp data payload size, decide initially between C- and D-Mode
478  if (!apimsg->get_data()) 
479  {
480    ERRCLog(param.name, "No Data Payload in SendMessage. We will not process this further");
481    delete apimsg;
482    if (r_entry)
483      param.rt.unlock(r_key);
484    return;
485  }
486
487  // look for GIST Hop Count
488  // Sec. 4.3.3.: GIST MUST reject messages for which the signalling application
489  // has specified a value of zero.
490  if (apimsg->get_ghc() == 0)
491  {
492    ERRCLog(param.name, "Not allowed to send messages with GIST Hop Count = 0. We will not process this further.");
493    delete apimsg;
494    if (r_entry)
495      param.rt.unlock(r_key);
496    return;
497  }
498
499  // check whether fragmentation is required
500  transtype= (apimsg->get_data()->get_size() > MAX_NSLP_PAYLOAD) ? tx_cmode : tx_dmode;
501   
502  // look if we were asked to transfer reliable -> C-Mode instead of DMode
503  if (apimsg->get_tx_attr().reliable) transtype=tx_cmode;
504   
505  // look if we were asked to transfer secure -> Secure C-Mode
506  if (apimsg->get_tx_attr().secure) transtype=tx_cmode_sec;
507   
508  // if we have no routing state we must change our attitude and consider transfer change based on that
509  if (!r_entry) 
510  {
511    // if we can transfer the data in D-Mode, we can transfer queryencapsulated, else we have to queue
512    // the data and set up C-Mode (sec/unsec) prior to be able to send it.
513    if (transtype==tx_dmode) 
514    { 
515      // Here we can send QueryEncapsulated and set up our local state in "awaiting response", as we use only D-Mode
516      DLog(param.name, "No Routing State - Sending Payload Query Encapsulated (in a QUERY), creating local routing state in 'qn_awaiting_response' mode");
517           
518      // create new routingentry (as a querier)
519      r_entry= new routingentry(false);
520      if (param.addresses.addr_is(src, AddressList::HomeAddr_P)) {
521        r_entry->set_local_src(src);
522      } else {
523        uint32_t pref = IPV6_PREFER_SRC_COA;
524        hostaddress *laddr = param.addresses.get_src_addr(dst, &pref);
525        cout << "SELECTING ADDRESS: " << src << ", " << *laddr << param.addresses.addr_is(*laddr, AddressList::HAAddr_P) << param.addresses.addr_is(src, AddressList::HAAddr_P) << endl;
526        if (param.addresses.addr_is(*laddr, AddressList::HAAddr_P))
527          laddr = param.addresses.get_first(AddressList::AltHAAddr_P, src.is_ipv4());
528        cout << *laddr << endl;
529        r_entry->set_local_src(*laddr);
530      }
531
532      apimsg->set_local_addr(r_entry->local_src->copy());
533
534      // set it to qn_awaiting_response
535      r_entry->state=qn_awaiting_response;
536     
537      // save IP TTL for Query Repetitions (NSLP gives us the IP TTL value)
538      r_entry->ip_ttl = apimsg->get_ip_ttl();
539     
540      // save GIST Hop count for Query Repetitions (NSLP gives us the hop count value)
541      r_entry->ghc=apimsg->get_ghc();
542     
543      // set D-Mode unsecure (we set it here, so we remember it when processing response)
544      r_entry->dmode=true;
545      r_entry->secure=false;
546     
547      // set local default RS_Validity Time
548      r_entry->rs_validity_time= gconf.getpar<uint32>(gistconf_rs_validity_time);
549     
550      // initiate sending the Query
551      send_query(apimsg,r_key,r_entry);
552
553      // start NoResponse timer
554      starttimer(r_key, r_entry, noresponse, 0, r_entry->reset_retry_timeout());
555           
556      // add routing state
557      param.rt.add(r_key, r_entry);
558    } 
559    else 
560    { // Routing State Setup with Message Association
561      DLog(param.name, "No Routing State - 'Reliable' or 'Secure' requested, queueing data, initiating C-Mode setup, creating local routing state in 'qn_awaiting_response' mode");
562           
563      // create new routingentry (as querier)
564      r_entry= new routingentry(false);
565      if (param.addresses.addr_is(src, AddressList::HomeAddr_P)) {
566        r_entry->set_local_src(src);
567      } else {
568        uint32_t pref = IPV6_PREFER_SRC_COA;
569        hostaddress *laddr = param.addresses.get_src_addr(dst, &pref);
570        r_entry->set_local_src(*laddr);
571      }
572
573      apimsg->set_local_addr(r_entry->local_src->copy());
574   
575      // set it to qn_awaiting_response
576      r_entry->state=qn_awaiting_response;
577           
578      // set C-Mode (we set it here, so we remember it when processing response)
579      r_entry->dmode= false;
580           
581      // save IP TTL for Query Repetitions (NSLP gives us the IP TTL value)
582      r_entry->ip_ttl = apimsg->get_ip_ttl();
583
584      // set security option in local state, so we choose a secure protocol if needed when processing response
585      r_entry->secure= (transtype==tx_cmode) ? false : true;
586
587      // set local Default RS_Validity Time
588      r_entry->rs_validity_time= gconf.getpar<uint32>(gistconf_rs_validity_time);;
589           
590      // send a Query requesting handshake, this will NOT transfer data payload!
591      send_query_handshake(apimsg, r_key, r_entry);
592               
593      // start NoResponse timer
594      starttimer(r_key, r_entry, noresponse, 0, r_entry->reset_retry_timeout());
595           
596      // Here we enqueue the data
597      enqueuedata(r_key, r_entry, apimsg->get_data(), apimsg->get_timeout(), apimsg->get_nslpmsghandle());
598           
599      // add routing state
600      param.rt.add(r_key, r_entry);
601    }
602  } // endif no routing state exists
603  else 
604  { // routing state exists already
605    // save GIST Hop count for Query Repetitions (NSLP gives us the hop count value)
606    r_entry->ghc=apimsg->get_ghc();
607       
608    // save IP TTL for any Messages sent on behalf of this SendMessage
609    r_entry->ip_ttl = apimsg->get_ip_ttl();
610
611    apimsg->set_local_addr(r_entry->local_src->copy());
612       
613    switch (r_entry->state) 
614    {
615      // there is a handshake in progress, we must queue the data
616      case rn_awaiting_confirm:
617      case qn_awaiting_response: 
618        {
619       
620          ERRCLog(param.name, "Routing State available - Handshake in progress, queueing data");
621          enqueuedata(r_key, r_entry, apimsg->get_data(), apimsg->get_timeout(), apimsg->get_nslpmsghandle());
622          break;
623        }
624
625        // Routing State is established. However we must decide if it suits our transfer requirements   
626      case qn_awaiting_refresh:
627      case rn_awaiting_refresh:
628      case rn_established:
629      case qn_established: 
630        {
631          // if it is set up in D-Mode
632          if (r_entry->dmode) 
633          {
634            // if transfer type is dmode -> OK, send in D-MODE
635            if (transtype==tx_dmode) 
636            {
637              DLog(param.name, "Routing State set up in D-Mode, this suits, we send data Message in D-Mode");
638              send_data_dmode(apimsg->get_data(), r_key, r_entry, apimsg->get_nslpid());
639            }
640                   
641            // if transfer type is something else -> New Handshake required
642            if (transtype!=tx_dmode) 
643            {
644              DLog(param.name, "Routing State set up in D-Mode, however, we need to use C-Mode, so we enqueue the data and prepare a new handshake.");
645                       
646              if (r_entry->state==qn_established) 
647              {
648                DLog(param.name, color[red] << "Upgrading to C-Mode from Querier side" << color[off]);
649                           
650                if (apimsg->get_data()) 
651                {
652                  enqueuedata(r_key, r_entry, apimsg->get_data(), apimsg->get_timeout(), apimsg->get_nslpmsghandle());
653                  DLog(param.name, color[red] << "Enqueued data payload" << color[off]);       
654                }
655                           
656                r_entry->state=qn_awaiting_response;
657                r_entry->dmode= false;  // was !(apimsg->get_tx_attr().reliable); unreliabe but secure currently not supported
658                r_entry->secure= (apimsg->get_tx_attr().secure);
659
660                // start NoResponse timer
661                starttimer(r_key, r_entry, noresponse, 0, r_entry->reset_retry_timeout());
662                           
663              } // if state established
664            }
665          } // endif D-Mode
666          else 
667          { // C-Mode desired
668
669            // if transfer type is dmode -> Transfer in C-Mode instead
670            if (transtype==tx_dmode) 
671            {
672              DLog(param.name, "Routing State set up in C-Mode, we use it however it was not required.");
673              send_data_cmode(apimsg->get_data(), r_key, r_entry, apimsg->get_nslpmsghandle());
674            }
675                   
676            // if transfer type is cmode -> OK, send in C-Mode
677            if (transtype==tx_cmode) 
678            {
679              DLog(param.name, "Routing State set up in C-Mode, we use it as it was required.");
680              send_data_cmode(apimsg->get_data(), r_key, r_entry, apimsg->get_nslpmsghandle());
681            }
682                   
683            // if set up cmode with security and transfer type is cmode_sec -> OK, send in C-Mode
684            if (r_entry->secure && (transtype==tx_cmode_sec)) 
685            {
686              DLog(param.name, "Routing State set up in C-Mode with security, we use it.");
687              send_data_cmode(apimsg->get_data(), r_key, r_entry, apimsg->get_nslpmsghandle());
688            }
689                   
690            // if set up cmode without security and transfer type is cmode_sec -> Bad, queue and re-initiate
691            if (!r_entry->secure && (transtype==tx_cmode_sec)) 
692            {
693              DLog(param.name, "Routing State currently in C-Mode without security, queueing data and initiating secure C-Mode setup.");
694                   
695              if (apimsg->get_data()) 
696              {
697                enqueuedata(r_key, r_entry, apimsg->get_data(), apimsg->get_timeout(), apimsg->get_nslpmsghandle());
698                DLog(param.name, color[red] << "Enqueued data payload" << color[off]); 
699              }
700                           
701              r_entry->state=qn_awaiting_response;
702
703              r_entry->dmode= false; // unreliable but secure currently not supported
704              r_entry->secure= (apimsg->get_tx_attr().secure);
705
706              // start NoResponse timer
707              starttimer(r_key, r_entry, noresponse, 0, r_entry->reset_retry_timeout());
708                       
709            } // endif set up cmode without security and transfer type is cmode_sec
710          } // endif C-Mode desired
711          break;
712        } // end case
713               
714      case dead: 
715        {
716          DLog(param.name, "Encountered Request to send data for DEAD Routing State, this is possible via explicit routing, only D-Mode possible");
717               
718          send_data_dmode(apimsg->get_data(), r_key, r_entry, apimsg->get_nslpid());
719          break;
720        }
721               
722      default: 
723        { 
724          ERRCLog(param.name, "Routing State available - Invalid State " << r_entry->state);
725          break;
726        }               
727    } // end switch
728  } // end else routing state exists already
729  param.rt.unlock(r_key);
730}
731
732
733/**
734 * RecvMessageAnswer API Call: set up state backwards or relay the received message on behalf of NSLP
735 * @param apimsg -- the API message from caller containing all data we need
736 */
737void 
738Statemodule::tg_recv_message_answer(APIMsg* apimsg) 
739{
740  assert(apimsg != NULL);
741   
742  // Here we initiate backwards routing state (install state and send response)
743  // or we relay the message (not yet implemented)
744   
745  // 1st step: Look for Routing State
746   
747  routingentry* r_entry=NULL;
748   
749  // create a new routinkey
750  routingkey* r_key= new routingkey();
751  r_key->mr=  (apimsg->get_mri())->copy();
752  r_key->sid= new sessionid(*(apimsg->get_sessionid()));
753  r_key->nslpid= apimsg->get_nslpid();
754   
755  //=======================================================
756  // look up routing state and print a status dump of routing table
757  //=======================================================
758   
759  // we communicated via uninverted MRI with API client!
760  // but status is saved with inverted MRI!
761  r_key->mr->invertDirection();
762   
763  r_entry=param.rt.lookup(r_key);
764   
765  if (!r_entry) 
766  {
767    ERRCLog(param.name, "Cannot find routing state for RecvMessageAnswer. Ignoring API call.");
768    // apimsg will be deleted in calling method anyway
769    return;
770  }
771
772  // do something in case of Routing State in rn_querynslp
773  if (r_entry->state == rn_querynslp) 
774  {
775    DLog(param.name, "State in RN_QUERYNSLP");
776       
777    // take the saved PDU, remove it from entry
778    known_ntlp_pdu* reqpdu = r_entry->tmppdu;
779    r_entry->tmppdu=NULL;
780       
781    if (!reqpdu) 
782      ERRCLog(param.name, "There should be a saved PDU but there isn't!");
783       
784    // take the saved Peer
785    appladdress* peer = r_entry->tmppeer;
786    r_entry->tmppeer=NULL;
787       
788    if (!peer) 
789      ERRCLog(param.name, "There should be a saved Peer address but there isn't!");
790       
791    // decide what to do
792    if (apimsg->get_directive() == APIMsg::directive_establish) 
793    {
794      // save data payload in entry, for repetitions of responses
795      if (apimsg->get_data()) 
796        r_entry->mod_data=new nslpdata(*apimsg->get_data());
797           
798      //##############################################################
799      // State setup
800      //##############################################################
801           
802      DLog(param.name, "Dispatching GIST Response");
803      send_response(reqpdu, r_key, r_entry, peer);
804           
805      // do we enforce late state installation?
806      if ( gconf.getpar<bool>(gistconf_latestate) )
807      {
808        DLog(param.name, "Late state installation configured, no state is saved");                 
809        param.rt.destroy_entry(r_key);
810
811        r_key= 0;
812        //param.rt.delete_entry(r_key);
813      } 
814      else 
815      {
816        DLog(param.name, "Immediate state installation configured, set up state");
817               
818        r_entry->rs_validity_time = gconf.getpar<uint32>(gistconf_rs_validity_time);
819       
820        // put in state "rn_established"
821        if ( gconf.getpar<bool>(gistconf_confirmrequired) == false ) 
822        {
823          DLog(param.name, "No full handshake is configured, state set up");
824                   
825          // install Routing State
826          if (!r_entry->dmode) 
827          {
828            // install Routing State
829            param.rt.add_ma(new nli(*r_entry->nl), *peer, r_entry->ma_hold_time, true);
830          }
831          networknotification(r_key, r_entry, APIMsg::route_changed_status_good, false);
832                   
833          r_entry->state= rn_established;
834          // Start Expire_RNode timer!
835          starttimer(r_key, r_entry, expire_rnode, 0, r_entry->rs_validity_time);
836                   
837          // set retry timeout back to default
838          r_entry->reset_retry_timeout();
839                   
840          // check and restart downstream Refresh_QNode timer if necessary
841          check_refresh_timer(r_key);
842        } 
843        else 
844        {
845          DLog(param.name, "Full handshake is configured, waiting for GIST Confirm");
846          r_entry->state=rn_awaiting_confirm;
847                   
848          starttimer(r_key, r_entry, noconfirm, 0, r_entry->reset_retry_timeout());
849        }
850      } //end if param.latestate (else)
851    } 
852    else 
853    {
854      //************************************************************
855      // Relay on NSLP's order
856      //************************************************************
857           
858      EVLog(param.name, "NSLP told us to relay only");
859           
860      nslpdata* mydata=apimsg->get_data();
861      if (mydata) 
862      {
863        DLog(param.name, "NSLP provided data for relaying");
864        reqpdu->set_data(mydata->copy());
865      }
866           
867      mri* mymri=reqpdu->get_mri();
868      nli* mynli=reqpdu->get_nli();
869           
870      // this cannot happen, if everything is all right
871      assert(mymri != NULL);
872      assert(mynli != NULL);
873           
874      appladdress* peer = mymri->determine_dest_address();
875      DLog(param.name, "Constructed target address for relaying");
876           
877      if (SignalingNTLP::is_local_addr(peer)) 
878      {
879        ERRCLog(param.name, "NSLP told us to relay, but we are the end");
880        ERRCLog(param.name, "Sending Error Message is redundant, as we would send it to ourself.");
881        // apimsg will be deleted in calling method anyway
882       
883        if (r_entry)
884          param.rt.unlock(r_key);
885        delete apimsg;
886        return;
887      }
888
889      peer->set_ip_ttl(mynli->get_ip_ttl());
890      DLog(param.name, "Set IP TTL of target address to the one in the original NLI");
891           
892      peer->set_rao(param.rt.get_rao(r_key->nslpid));
893      DLog(param.name, "Set RAO value to the one of the NSLP (we know it for sure)");
894           
895      uint16 outgoinginterface = mymri->get_local_if();
896           
897      if (!outgoinginterface) 
898      {
899        DLog(param.name, "Lookup of outgoing interface failed (this would certainly also affect the flow's routing). TP modules may use any interface.");
900      } 
901      else 
902      {
903        peer->set_if_index(outgoinginterface);
904        DLog(param.name, "Set request for outgoing interface index " << outgoinginterface << " for GIST Query");
905      }
906
907
908      // send it to signaling
909      SignalingMsgNTLP* sigmsg = new SignalingMsgNTLP;
910      sigmsg->set_local_addr(r_entry->local_src->copy());
911      sigmsg->set_req(peer, reqpdu);
912      sigmsg->send_or_delete();
913     
914      param.rt.destroy_entry(r_key);
915
916      DLog(param.name, "Message sent to signaling for Relaying");
917      if (r_key) delete r_key;
918      r_key= 0;
919    }
920  } // end if state==rn_querynslp
921   
922  if (r_key) param.rt.unlock(r_key);
923}
924
925//@}
926
927} // end namespace ntlp
Note: See TracBrowser for help on using the repository browser.