source: source/ariba/Node.cpp@ 12061

Last change on this file since 12061 was 12060, checked in by hock@…, 11 years ago

Reintegrate branch: 20130111-hock-message_classes

improvements:

  • new message classes (reboost, zero-copy)
  • "fast path" for direct links (skip overlay layer)
  • link-properties accessible from the application
  • SystemQueue can call boost::bind functions
  • protlib compatibility removed (32bit overhead saved in every message)
  • addressing2
  • AddressDiscovery discoveres only addresses on which we're actually listening
  • ariba serialization usage reduced (sill used in OverlayMsg)
  • Node::connect, easier and cleaner interface to start-up ariba from the application
  • ariba configs via JSON, XML, etc (boost::property_tree)
  • keep-alive overhead greatly reduced
  • (relayed) overlay links can actually be closed now
  • lost messages are detected in most cases
  • notification to the application when link is transformed into direct-link
  • overlay routing: send message to second best hop if it would be dropped otherwise
  • SequenceNumbers (only mechanisms, so for: upward compatibility)
  • various small fixes


regressions:

  • bluetooth is not yet working again
  • bootstrap modules deactivated
  • liblog4xx is not working (use cout-logging)

This patch brings great performance and stability improvements at cost of backward compatibility.
Also bluetooth and the bootstrap modules have not been ported to the new interfaces, yet.

File size: 13.2 KB
Line 
1// [License]
2// The Ariba-Underlay Copyright
3//
4// Copyright (c) 2008-2009, Institute of Telematics, UniversitÀt Karlsruhe (TH)
5//
6// Institute of Telematics
7// UniversitÀt Karlsruhe (TH)
8// Zirkel 2, 76128 Karlsruhe
9// Germany
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
22// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OF TELEMATICS OR
25// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33// The views and conclusions contained in the software and documentation
34// are those of the authors and should not be interpreted as representing
35// official policies, either expressed or implied, of the Institute of
36// Telematics.
37// [License]
38
39#include "Node.h"
40
41#include <boost/foreach.hpp>
42
43#include "ariba/overlay/BaseOverlay.h"
44#include "ariba/communication/BaseCommunication.h"
45
46#include "ariba/utility/types/OverlayParameterSet.h"
47#include "ariba/communication/EndpointDescriptor.h"
48
49#include <boost/property_tree/exceptions.hpp>
50
51using namespace std;
52using ariba::communication::EndpointDescriptor;
53using boost::property_tree::ptree;
54
55namespace ariba {
56
57//Node::Node(AribaModule& ariba_mod, const Name& node_name) :
58// name(node_name), ariba_mod(ariba_mod) {
59// base_overlay = new BaseOverlay();
60//}
61
62Node::Node() :
63 name(Name::UNSPECIFIED),
64 base_communication(NULL),
65 base_overlay(NULL)
66{
67 base_communication = new BaseCommunication();
68 base_overlay = new BaseOverlay();
69}
70
71Node::~Node() {
72 delete base_overlay;
73 base_overlay = NULL;
74
75 delete base_communication;
76 base_communication = NULL;
77}
78
79void Node::connect(const ptree& config)
80{
81 using namespace boost::property_tree;
82 using namespace addressing2;
83
84 assert( ! base_communication->isStarted() );
85 assert( ! base_overlay->isStarted() );
86
87 // XXX needed since »empty_ptree<ptree>()« is not working
88 // ---> see: http://stackoverflow.com/questions/5003549/where-is-boost-property-treeempty-ptree
89 static const ptree empty_pt;
90
91 // SpovNet ID
92 Name spovnet_name(config.get<string>("spovnet_name"));
93 spovnetId = spovnet_name.toSpoVNetId();
94
95 // Node ID
96 try
97 {
98 name = config.get<string>("node_name");
99 }
100 catch ( ptree_bad_path& e )
101 {
102 name = Name::UNSPECIFIED;
103 }
104 nodeId = generateNodeId(name);
105
106
107
108 /* Base Communication */
109 EndpointSetPtr listen_on;
110 try
111 {
112 listen_on = endpoint_set::create_EndpointSet(
113 config.get_child("listen_on"));
114 }
115 catch ( ptree_bad_path& e )
116 {
117 /* no endpoints specified, using default: »[::]:41322+« */
118
119 ptree default_listen_on;
120 default_listen_on.put("endp.category", "TCPIP");
121 default_listen_on.put("endp.addr", "::");
122 default_listen_on.put("endp.port", 0); // defaults to 41322 (or higher)
123
124 listen_on = endpoint_set::create_EndpointSet(default_listen_on);
125// logging_warn("No endpoints specified in config. ---> Using default.");
126 cout << "No endpoints specified in config. ---> Using default." << endl;
127 }
128 base_communication->start(listen_on);
129
130 // TODO maybe notify the upper layer whether we have any active endpoints
131
132
133 /* Base Overlay */
134 base_overlay->start( base_communication, nodeId );
135
136 base_overlay->createSpoVNet( spovnetId );
137 base_overlay->joinSpoVNet( spovnetId );
138
139
140
141 /* Bootstrap */
142 const ptree& bootstrap_pt = config.get_child("bootstrap", empty_pt);
143
144 // Static Bootstrap
145 try
146 {
147 // read endpoint_set from config
148 EndpointSetPtr ep_set = endpoint_set::create_EndpointSet(
149 bootstrap_pt.get_child("direct"));
150
151 EndpointDescriptor ep = EndpointDescriptor::UNSPECIFIED();
152 ep.replace_endpoint_set(ep_set);
153
154 // try to connect
155 base_overlay->joinSpoVNet( spovnetId, ep);
156 }
157 catch ( ptree_bad_path& e )
158 {
159// logging_info("No direct bootstrap info in config.");
160 cout << "No direct bootstrap info in config." << endl;
161 }
162
163
164 /* Bootstrap modules */
165 vector<pair<BootstrapManager::BootstrapType,string> > internalmodules;
166
167 // Bootstrap: Broadcast
168 if ( bootstrap_pt.get("broadcast", false) )
169 {
170 internalmodules.push_back(make_pair(
171 BootstrapManager::BootstrapTypePeriodicBroadcast,""));
172 }
173
174 // Bootstrap: MDNS
175 if ( bootstrap_pt.get("mdns", false) )
176 {
177 internalmodules.push_back(make_pair(
178 BootstrapManager::BootstrapTypeMulticastDns,""));
179 }
180
181 // Bootstrap: SDP
182 if ( bootstrap_pt.get("sdp", false) )
183 {
184 internalmodules.push_back(make_pair(
185 BootstrapManager::BootstrapTypeBluetoothSdp,""));
186 }
187
188 // start automatic overlay bootstrapping modules
189 base_overlay->startBootstrapModules(internalmodules);
190}
191
192//void Node::join(const Name& vnetname) {
193// spovnetId = vnetname.toSpoVNetId();
194// nodeId = generateNodeId(name);
195//
196// // start base comm if not started
197// if( !ariba_mod.base_comm->isStarted() )
198// ariba_mod.base_comm->start();
199//
200// // start base overlay if not started
201// // join against ourselfs
202// if( !base_overlay->isStarted() )
203// base_overlay->start( *ariba_mod.base_comm, nodeId );
204// base_overlay->joinSpoVNet( spovnetId );
205//
206// // join against static bootstrap points and
207// // start automatic bootstrapping modules
208// vector<AribaModule::BootstrapMechanism> mechanisms
209// = ariba_mod.getBootstrapMechanisms(vnetname);
210//
211// vector<pair<BootstrapManager::BootstrapType,string> > internalmodules;
212//
213// BOOST_FOREACH(AribaModule::BootstrapMechanism m, mechanisms){
214// switch(m){
215// case AribaModule::BootstrapMechanismStatic:
216// {
217// const communication::EndpointDescriptor* ep =
218// ariba_mod.getBootstrapNode(vnetname, m);
219// if( ep != NULL && ep->isUnspecified() == false )
220// base_overlay->joinSpoVNet( spovnetId, *ep);
221// break;
222// }
223// case AribaModule::BootstrapMechanismBroadcast:
224// internalmodules.push_back(make_pair(
225// BootstrapManager::BootstrapTypePeriodicBroadcast,
226// ariba_mod.getBootstrapInfo(vnetname, m)));
227// break;
228// case AribaModule::BootstrapMechanismMulticastDNS:
229// internalmodules.push_back(make_pair(
230// BootstrapManager::BootstrapTypeMulticastDns,
231// ariba_mod.getBootstrapInfo(vnetname, m)));
232// break;
233// case AribaModule::BootstrapMechanismSDP:
234// internalmodules.push_back(make_pair(
235// BootstrapManager::BootstrapTypeBluetoothSdp,
236// ariba_mod.getBootstrapInfo(vnetname, m)));
237// break;
238// default:
239// break;
240// }
241// }
242//
243// // start automatic overlay bootstrapping modules
244// base_overlay->startBootstrapModules(internalmodules);
245//
246// // done
247//}
248//
249//void Node::initiate(const Name& vnetname, const SpoVNetProperties& parm) {
250// utility::OverlayParameterSet ovrpset;
251// ovrpset.setOverlayStructure(
252// (utility::OverlayParameterSet::_OverlayStructure)
253// parm.getBaseOverlayType()
254// );
255//
256// spovnetId = vnetname.toSpoVNetId();
257// nodeId = generateNodeId(name);
258//
259// // start base comm if not started
260// if( !ariba_mod.base_comm->isStarted() )
261// ariba_mod.base_comm->start();
262//
263// // start base overlay if not started
264// if( !base_overlay->isStarted() )
265// base_overlay->start( *ariba_mod.base_comm, nodeId );
266//
267// base_overlay->createSpoVNet( spovnetId, ovrpset );
268//}
269
270void Node::leave() {
271 base_overlay->stopBootstrapModules();
272 base_overlay->leaveSpoVNet();
273 base_communication->stop(); // XXX before »base_overlay->stop()« ??
274 base_overlay->stop();
275}
276
277const SpoVNetProperties& Node::getSpoVNetProperties() const {
278 return SpoVNetProperties::DEFAULT;
279}
280
281const SpoVNetID& Node::getSpoVNetId() const {
282 return spovnetId;
283}
284
285const NodeID& Node::getNodeId(const LinkID& lid) const {
286 if( lid == LinkID::UNSPECIFIED ) return nodeId;
287 else return base_overlay->getNodeID( lid );
288}
289
290NodeID Node::generateNodeId(const Name& name) const {
291 if (name == Name::UNSPECIFIED) return Name::random().toNodeId();
292 else return name.toNodeId();
293}
294
295vector<NodeID> Node::getNeighborNodes() const {
296 return base_overlay->getOverlayNeighbors();
297}
298
299LinkID Node::establishLink(const NodeID& nid, const ServiceID& sid) {
300 return base_overlay->establishLink(nid, sid);
301}
302
303void Node::dropLink(const LinkID& lnk) {
304 base_overlay->dropLink(lnk);
305}
306
307bool Node::isLinkDirect(const ariba::LinkID& lnk) const
308{
309 return base_overlay->isLinkDirect(lnk);
310}
311
312int Node::getHopCount(const ariba::LinkID& lnk) const
313{
314 return base_overlay->getHopCount(lnk);
315}
316
317
318
319
320/* +++++ Message sending +++++ */
321void Node::check_send_priority(uint8_t priority)
322{
323 if ( priority < send_priority::HIGHEST || priority > send_priority::LOWEST )
324 throw std::invalid_argument("Illegal priority");
325}
326
327
328// +++ new interface +++
329const SequenceNumber& Node::sendMessage(reboost::message_t msg, const LinkID& lnk, uint8_t priority)
330{
331 // check priority
332 check_send_priority(priority);
333
334 // * call base overlay *
335 return base_overlay->sendMessage(msg, lnk, priority);
336}
337
338// +++ legacy interface +++
339seqnum_t Node::sendMessage(const DataMessage& msg, const LinkID& lnk)
340{
341 reboost::message_t message = ((Message*) msg)->wrap_up_for_sending();
342
343 try
344 {
345 base_overlay->sendMessage(message, lnk, send_priority::NORMAL);
346 return 0;
347 }
348 catch ( ariba::overlay::message_not_sent& e )
349 {
350 logging_warn("Message could not be sent. Dropped.");
351 return -1;
352 }
353}
354
355
356// +++ new interface +++
357const SequenceNumber& Node::sendMessage(reboost::message_t msg, const NodeID& nid,
358 const ServiceID& sid, uint8_t priority, const LinkProperties& req) {
359
360 // check priority
361 check_send_priority(priority);
362
363 // * call base overlay *
364 return base_overlay->sendMessage(msg, nid, priority, sid);
365}
366
367// +++ legacy interface +++
368seqnum_t Node::sendMessage(const DataMessage& msg, const NodeID& nid,
369 const ServiceID& sid, const LinkProperties& req) {
370
371// reboost::message_t message = ((Message*) msg)->wrap_up_for_sending();
372 reboost::message_t message;
373 message.push_back( ((Message*) msg)->serialize_into_shared_buffer() );
374
375 try
376 {
377 sendMessage(message, nid, sid, send_priority::NORMAL, req);
378 return 0;
379 }
380 catch ( ariba::overlay::message_not_sent& e )
381 {
382 logging_warn("Message could not be sent. Dropped.");
383 return -1;
384 }
385}
386
387
388// +++ new interface +++
389NodeID Node::sendMessageCloserToNodeID(reboost::message_t msg, const NodeID& nid, const ServiceID& sid,
390 uint8_t priority, const LinkProperties& req) {
391
392 // check priority
393 check_send_priority(priority);
394
395 // * call base overlay *
396 return base_overlay->sendMessageCloserToNodeID(msg, nid, priority, sid);
397}
398
399// +++ legacy interface +++
400NodeID Node::sendMessageCloserToNodeID(const DataMessage& msg, const NodeID& nid, const ServiceID& sid,
401 const LinkProperties& req) {
402
403 reboost::message_t message = ((Message*) msg)->wrap_up_for_sending();
404
405 return sendMessageCloserToNodeID(message, nid, sid, send_priority::NORMAL, req);
406}
407
408
409// +++ new interface +++
410void Node::sendBroadcastMessage(reboost::message_t msg, const ServiceID& sid, uint8_t priority) {
411
412 // check priority
413 check_send_priority(priority);
414
415 // * call base overlay *
416 return base_overlay->broadcastMessage(msg, sid, priority);
417}
418
419// +++ legacy interface +++
420void Node::sendBroadcastMessage(const DataMessage& msg, const ServiceID& sid) {
421 reboost::message_t message = ((Message*) msg)->wrap_up_for_sending();
422
423 return sendBroadcastMessage(message, sid);
424}
425
426
427/* +++++ [Message sending] +++++ */
428
429
430
431
432bool Node::bind(NodeListener* listener) {
433 return base_overlay->bind(listener);
434}
435
436bool Node::unbind(NodeListener* listener) {
437 return base_overlay->unbind(listener);
438}
439
440bool Node::bind(CommunicationListener* listener, const ServiceID& sid) {
441 // bind the listener
442 bool ret = base_overlay->bind(listener, sid);
443
444// // now that we have a listener, we can ask if sniffing is ok
445// if( ariba_mod.sideport_sniffer != NULL ){
446// base_overlay->registerSidePort(ariba_mod.sideport_sniffer);
447// }
448
449 return ret;
450}
451
452bool Node::unbind(CommunicationListener* listener, const ServiceID& sid) {
453 return base_overlay->unbind(listener, sid);
454}
455
456// @see Module.h
457string Node::getName() const {
458 return name.toString();
459}
460
461} // namespace ariba
Note: See TracBrowser for help on using the repository browser.