source: source/ariba/communication/BaseCommunication.cpp@ 5616

Last change on this file since 5616 was 5616, checked in by mies, 15 years ago
File size: 21.4 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 ARIBA PROJECT 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 "BaseCommunication.h"
40
41#ifdef UNDERLAY_OMNET
42 #include "ariba/communication/modules/transport/omnet/AribaOmnetModule.h"
43 #include "ariba/communication/modules/network/omnet/OmnetNetworkProtocol.h"
44 #include "ariba/utility/system/StartupWrapper.h"
45
46 using ariba::communication::AribaOmnetModule;
47 using ariba::communication::OmnetNetworkProtocol;
48 using ariba::utility::StartupWrapper;
49#endif
50
51namespace ariba {
52namespace communication {
53
54#include "networkinfo/AddressDiscovery.hpp"
55
56use_logging_cpp(BaseCommunication);
57
58/// adds an endpoint to the list
59void BaseCommunication::add_endpoint( const address_v* endpoint ) {
60 BOOST_FOREACH( endpoint_reference& ref, remote_endpoints ) {
61 if (*ref.endpoint == *endpoint) {
62 ref.count++;
63 return;
64 }
65 }
66 endpoint_reference ref;
67 ref.endpoint = endpoint->clone();
68 ref.count = 0;
69 remote_endpoints.push_back(ref);
70}
71
72/// removes an endpoint from the list
73void BaseCommunication::remove_endpoint( const address_v* endpoint ) {
74 for (vector<endpoint_reference>::iterator i = remote_endpoints.begin();
75 i != remote_endpoints.end(); i++) {
76 if (*i->endpoint == *endpoint) {
77 i->count--;
78 if (i->count==0) {
79 logging_info("No more links to " << i->endpoint->to_string() << ": terminating transports!");
80 transport->terminate(i->endpoint);
81 delete i->endpoint;
82 remote_endpoints.erase(i);
83 }
84 return;
85 }
86 }
87}
88
89BaseCommunication::BaseCommunication() {
90 this->transport = NULL;
91 this->started = false;
92}
93
94BaseCommunication::~BaseCommunication(){
95}
96
97void BaseCommunication::start() {
98 logging_info( "Starting up ..." );
99 currentSeqnum = 0;
100
101 // creating transports
102 logging_info( "Creating transports ..." );
103
104#ifdef UNDERLAY_OMNET
105 AribaOmnetModule* module = StartupWrapper::getCurrentModule();
106 module->setServerPort( listenport );
107
108 transport = module;
109 network = new OmnetNetworkProtocol( module );
110#else
111 transport = new transport_peer( localDescriptor.getEndpoints() );
112#endif
113
114 logging_info( "Searching for local locators ..." );
115 discover_endpoints(localDescriptor.getEndpoints());
116 logging_info( "Done. Local endpoints = " << localDescriptor.toString() );
117
118 transport->register_listener( this );
119 transport->start();
120
121#ifndef UNDERLAY_OMNET
122 // bind to the network change detection
123 networkMonitor.registerNotification( this );
124#endif
125
126 // base comm startup done
127 started = true;
128 logging_info( "Started up." );
129}
130
131void BaseCommunication::stop() {
132 logging_info( "Stopping transports ..." );
133
134 transport->stop();
135 delete transport;
136 started = false;
137
138 logging_info( "Stopped." );
139}
140
141bool BaseCommunication::isStarted(){
142 return started;
143}
144
145/// Sets the endpoints
146void BaseCommunication::setEndpoints( string& _endpoints ) {
147 localDescriptor.getEndpoints().assign(_endpoints);
148 logging_info("Setting local end-points: "
149 << localDescriptor.getEndpoints().to_string());
150}
151
152const LinkID BaseCommunication::establishLink(
153 const EndpointDescriptor& descriptor,
154 const LinkID& link_id,
155 const QoSParameterSet& qos,
156 const SecurityParameterSet& sec) {
157
158 // copy link id
159 LinkID linkid = link_id;
160
161 // debug
162 logging_debug( "Request to establish link" );
163
164 // create link identifier
165 if (linkid.isUnspecified()) linkid = LinkID::create();
166
167 // create link descriptor
168 logging_debug( "Creating new descriptor entry with local link id=" << linkid.toString() );
169 LinkDescriptor* ld = new LinkDescriptor();
170 ld->localLink = linkid;
171 addLink( ld );
172
173 // send a message to request new link to remote
174 logging_debug( "Send messages with request to open link to " << descriptor.toString() );
175 AribaBaseMsg baseMsg( AribaBaseMsg::typeLinkRequest, linkid );
176 baseMsg.getLocalDescriptor() = localDescriptor;
177
178 // serialize and send message
179 send( &baseMsg, descriptor );
180
181 return linkid;
182}
183
184void BaseCommunication::dropLink(const LinkID link) {
185
186 logging_debug( "Starting to drop link " + link.toString() );
187
188 // see if we have the link
189 LinkDescriptor& ld = queryLocalLink( link );
190 if( ld.isUnspecified() ) {
191 logging_error( "Don't know the link you want to drop "+ link.toString() );
192 return;
193 }
194
195 // tell the registered listeners
196 BOOST_FOREACH( CommunicationEvents* i, eventListener ) {
197 i->onLinkDown( link, ld.localLocator, ld.remoteLocator );
198 }
199
200 // create message to drop the link
201 logging_debug( "Sending out link close request. for us, the link is closed now" );
202 AribaBaseMsg msg( AribaBaseMsg::typeLinkClose, ld.localLink, ld.remoteLink );
203
204 // send message to drop the link
205 send( &msg, ld );
206
207 // remove from map
208 removeLink(link);
209}
210
211seqnum_t BaseCommunication::sendMessage( const LinkID lid, const Message* message) {
212
213 logging_debug( "Sending out message to link " << lid.toString() );
214
215 // query local link info
216 LinkDescriptor& ld = queryLocalLink(lid);
217 if( ld.isUnspecified() ){
218 logging_error( "Don't know the link with id " << lid.toString() );
219 return -1;
220 }
221
222 // link not up-> error
223 if( !ld.up ) {
224 logging_error("Can not send on link " << lid.toString() << ": link not up");
225 return -1;
226 }
227
228 // create message
229 AribaBaseMsg msg( AribaBaseMsg::typeData, ld.localLink, ld.remoteLink );
230
231 // encapsulate the payload message
232 msg.encapsulate( const_cast<Message*>(message) );
233
234 // send message
235 send( &msg, ld );
236
237 // return sequence number
238 return ++currentSeqnum;
239}
240
241const EndpointDescriptor& BaseCommunication::getEndpointDescriptor(const LinkID link) const {
242 if( link == LinkID::UNSPECIFIED){
243 return localDescriptor;
244 } else {
245 LinkDescriptor& linkDesc = queryLocalLink(link);
246 if (linkDesc.isUnspecified()) return EndpointDescriptor::UNSPECIFIED;
247 return linkDesc.remoteEndpoint;
248 }
249}
250
251void BaseCommunication::registerEventListener(CommunicationEvents* _events){
252 if( eventListener.find( _events ) == eventListener.end() )
253 eventListener.insert( _events );
254}
255
256void BaseCommunication::unregisterEventListener(CommunicationEvents* _events){
257 EventListenerSet::iterator i = eventListener.find( _events );
258 if( i != eventListener.end() )
259 eventListener.erase( i );
260}
261
262SystemEventType TransportEvent("Transport");
263SystemEventType MessageDispatchEvent("MessageDispatchEvent", TransportEvent );
264
265class DispatchMsg {
266public:
267 address_v* local;
268 address_v* remote;
269 Message* message;
270};
271
272/// called when a system event is emitted by system queue
273void BaseCommunication::handleSystemEvent(const SystemEvent& event) {
274
275 // dispatch received messages
276 if ( event.getType() == MessageDispatchEvent ){
277 logging_debug( "Forwarding message receiver" );
278 DispatchMsg* dmsg = event.getData<DispatchMsg>();
279 Message* msg = dmsg->message;
280 receiveMessage(msg, dmsg->local, dmsg->remote);
281 msg->dropPayload();
282 delete dmsg;
283 delete msg;
284 }
285}
286
287/// called when a message is received from transport_peer
288void BaseCommunication::receive_message(transport_protocol* transport,
289 const address_vf local, const address_vf remote, const uint8_t* data,
290 size_t size) {
291
292// logging_debug( "Dispatching message" );
293
294 // convert data
295 Data data_( const_cast<uint8_t*>(data), size * 8 );
296 DispatchMsg* dmsg = new DispatchMsg();
297
298 Message* msg = new Message(data_);
299 dmsg->local = local->clone();
300 dmsg->remote = remote->clone();
301 dmsg->message = msg;
302
303 SystemQueue::instance().scheduleEvent(
304 SystemEvent( this, MessageDispatchEvent, dmsg )
305 );
306}
307
308/// handles a message from the underlay transport
309void BaseCommunication::receiveMessage(const Message* message,
310 const address_v* local, const address_v* remote ){
311
312 /// decapsulate message
313 AribaBaseMsg* msg = ((Message*)message)->decapsulate<AribaBaseMsg>();
314 logging_debug( "Receiving message of type " << msg->getTypeString() );
315
316 // handle message
317 switch (msg->getType()) {
318
319 // ---------------------------------------------------------------------
320 // data message
321 // ---------------------------------------------------------------------
322 case AribaBaseMsg::typeData: {
323 logging_debug( "Received data message, forwarding to overlay" );
324 if( messageReceiver != NULL ) {
325 messageReceiver->receiveMessage(
326 msg, msg->getRemoteLink(), NodeID::UNSPECIFIED
327 );
328 }
329 break;
330 }
331
332 // ---------------------------------------------------------------------
333 // handle link request from remote
334 // ---------------------------------------------------------------------
335 case AribaBaseMsg::typeLinkRequest: {
336 logging_debug( "Received link open request" );
337
338 /// only answer the first request
339 if (!queryRemoteLink(msg->getLocalLink()).isUnspecified()) {
340 logging_debug("Link request already received. Ignore!");
341 break;
342 }
343
344 /// create link ids
345 LinkID localLink = LinkID::create();
346 LinkID remoteLink = msg->getLocalLink();
347 logging_debug( "local=" << local->to_string()
348 << " remote=" << remote->to_string()
349 );
350
351 // check if link creation is allowed by ALL listeners
352 bool allowlink = true;
353 BOOST_FOREACH( CommunicationEvents* i, eventListener ){
354 allowlink &= i->onLinkRequest( localLink, local, remote );
355 }
356
357 // not allowed-> warn
358 if( !allowlink ){
359 logging_warn( "Overlay denied creation of link" );
360 return;
361 }
362
363 // create descriptor
364 LinkDescriptor* ld = new LinkDescriptor();
365 ld->localLink = localLink;
366 ld->remoteLink = remoteLink;
367 ld->localLocator = local->clone();
368 ld->remoteLocator = remote->clone();
369 ld->remoteEndpoint = msg->getLocalDescriptor();
370 add_endpoint(ld->remoteLocator);
371
372 // add layer 1-3 addresses
373 ld->remoteEndpoint.getEndpoints().add(
374 ld->remoteLocator, endpoint_set::Layer1_3);
375 localDescriptor.getEndpoints().add(
376 local, endpoint_set::Layer1_3
377 );
378
379 // link is now up-> add it
380 ld->up = true;
381 addLink(ld);
382
383 // link is up!
384 logging_debug( "Link (initiated from remote) is up with "
385 << "local(id=" << ld->localLink.toString() << ","
386 << "locator=" << ld->localLocator->to_string() << ") "
387 << "remote(id=" << ld->remoteLink.toString() << ", "
388 << "locator=" << ld->remoteLocator->to_string() << ")"
389 );
390
391 // sending link request reply
392 logging_debug( "Sending link request reply with ids "
393 << "local=" << localLink.toString() << ", "
394 << "remote=" << remoteLink.toString() );
395 AribaBaseMsg reply( AribaBaseMsg::typeLinkReply, localLink, remoteLink );
396 reply.getLocalDescriptor() = localDescriptor;
397 reply.getRemoteDescriptor() = ld->remoteEndpoint;
398
399 send( &reply, *ld );
400
401 // inform listeners about new open link
402 BOOST_FOREACH( CommunicationEvents* i, eventListener ) {
403 i->onLinkUp( localLink, ld->localLocator, ld->remoteLocator);
404 }
405
406 // done
407 break;
408 }
409
410 // ---------------------------------------------------------------------
411 // handle link request reply
412 // ---------------------------------------------------------------------
413 case AribaBaseMsg::typeLinkReply: {
414 logging_debug( "Received link open reply for a link we initiated" );
415
416 // this is a reply to a link open request, so we have already
417 // a link mapping and can now set the remote link to valid
418 LinkDescriptor& ld = queryLocalLink( msg->getRemoteLink() );
419
420 // no link found-> warn!
421 if (ld.isUnspecified()) {
422 logging_warn("Failed to find local link " << msg->getRemoteLink().toString());
423 return;
424 }
425
426 // set remote locator and link id
427 ld.remoteLink = msg->getLocalLink();
428 ld.remoteLocator = remote->clone();
429 localDescriptor.getEndpoints().add(
430 msg->getRemoteDescriptor().getEndpoints(),
431 endpoint_set::Layer1_3
432 );
433 ld.up = true;
434 add_endpoint(ld->remoteLocator);
435
436 logging_debug( "Link is now up with local id "
437 << ld.localLink.toString() << " and remote id "
438 << ld.remoteLink.toString() );
439
440
441 // inform lisneters about link up event
442 BOOST_FOREACH( CommunicationEvents* i, eventListener ){
443 i->onLinkUp( ld.localLink, ld.localLocator, ld.remoteLocator );
444 }
445
446 // done
447 break;
448 }
449
450 // ---------------------------------------------------------------------
451 // handle link close requests
452 // ---------------------------------------------------------------------
453 case AribaBaseMsg::typeLinkClose: {
454 // get remote link
455 const LinkID& localLink = msg->getRemoteLink();
456 logging_debug( "Received link close request for link " << localLink.toString() );
457
458 // searching for link, not found-> warn
459 LinkDescriptor& linkDesc = queryLocalLink( localLink );
460 if (linkDesc.isUnspecified()) {
461 logging_warn("Failed to find local link " << localLink.toString());
462 return;
463 }
464
465 // inform listeners
466 BOOST_FOREACH( CommunicationEvents* i, eventListener ){
467 i->onLinkDown( linkDesc.localLink,
468 linkDesc.localLocator, linkDesc.remoteLocator );
469 }
470
471 // remove the link descriptor
472 removeLink( localLink );
473
474 // done
475 break;
476 }
477
478 // ---------------------------------------------------------------------
479 // handle link locator changes
480 // ---------------------------------------------------------------------
481 case AribaBaseMsg::typeLinkUpdate: {
482 const LinkID& localLink = msg->getRemoteLink();
483 logging_debug( "Received link update for link "
484 << localLink.toString() );
485
486 // find the link description
487 LinkDescriptor& linkDesc = queryLocalLink( localLink );
488 if (linkDesc.isUnspecified()) {
489 logging_warn("Failed to update local link "
490 << localLink.toString());
491 return;
492 }
493
494 // update the remote locator
495 const address_v* oldremote = linkDesc.remoteLocator;
496 linkDesc.remoteLocator = remote->clone();
497
498 // inform the listeners (local link has _not_ changed!)
499 BOOST_FOREACH( CommunicationEvents* i, eventListener ){
500 i->onLinkChanged(
501 linkDesc.localLink, // linkid
502 linkDesc.localLocator, // old local
503 linkDesc.localLocator, // new local
504 oldremote, // old remote
505 linkDesc.remoteLocator // new remote
506 );
507 }
508
509 // done
510 break;
511 }
512 }
513}
514
515/// add a newly allocated link to the set of links
516void BaseCommunication::addLink( LinkDescriptor* link ) {
517 linkSet.push_back( link );
518}
519
520/// remove a link from set
521void BaseCommunication::removeLink( const LinkID& localLink ) {
522 for(LinkSet::iterator i=linkSet.begin(); i != linkSet.end(); i++){
523 if( (*i)->localLink != localLink) continue;
524 remove_endpoint((*i)->remoteLocator);
525 delete *i;
526 linkSet.erase( i );
527 break;
528 }
529}
530
531/// query a descriptor by local link id
532BaseCommunication::LinkDescriptor& BaseCommunication::queryLocalLink( const LinkID& link ) const {
533 for (int i=0; i<linkSet.size();i++)
534 if (linkSet[i]->localLink == link) return (LinkDescriptor&)*linkSet[i];
535
536 LinkDescriptor ret;
537 ret.unspecified = true;
538 return ret;
539}
540
541/// query a descriptor by remote link id
542BaseCommunication::LinkDescriptor& BaseCommunication::queryRemoteLink( const LinkID& link ) const {
543 for (int i=0; i<linkSet.size();i++)
544 if (linkSet[i]->remoteLink == link) return (LinkDescriptor&)*linkSet[i];
545
546 LinkDescriptor ret;
547 ret.unspecified = true;
548 return ret;
549}
550
551LinkIDs BaseCommunication::getLocalLinks( const address_v* addr ) const {
552 LinkIDs ids;
553 for (int i=0; i<linkSet.size(); i++){
554 if( addr == NULL ){
555 ids.push_back( linkSet[i]->localLink );
556 } else {
557 if ( *linkSet[i]->remoteLocator == *addr )
558 ids.push_back( linkSet[i]->localLink );
559 }
560 }
561 return ids;
562}
563
564void BaseCommunication::onNetworkChange(const NetworkChangeInterface::NetworkChangeInfo& info){
565
566#ifdef UNDERLAY_OMNET
567
568 // we have no mobility support for simulations
569 return
570
571#endif // UNDERLAY_OMNET
572
573/*- disabled!
574
575 // we only care about address changes, not about interface changes
576 // as address changes are triggered by interface changes, we are safe here
577 if( info.type != NetworkChangeInterface::EventTypeAddressNew &&
578 info.type != NetworkChangeInterface::EventTypeAddressDelete ) return;
579
580 logging_info( "base communication is handling network address changes" );
581
582 // get all now available addresses
583 NetworkInformation networkInformation;
584 AddressInformation addressInformation;
585
586 NetworkInterfaceList interfaces = networkInformation.getInterfaces();
587 AddressList addresses;
588
589 for( NetworkInterfaceList::iterator i = interfaces.begin(); i != interfaces.end(); i++ ){
590 AddressList newaddr = addressInformation.getAddresses(*i);
591 addresses.insert( addresses.end(), newaddr.begin(), newaddr.end() );
592 }
593
594 //
595 // get current locators for the local endpoint
596 // TODO: this code is dublicate of the ctor code!!! cleanup!
597 //
598
599 NetworkProtocol::NetworkLocatorSet locators = network->getAddresses();
600 NetworkProtocol::NetworkLocatorSet::iterator i = locators.begin();
601 NetworkProtocol::NetworkLocatorSet::iterator iend = locators.end();
602
603 //
604 // remember the old local endpoint, in case it changes
605 //
606
607 EndpointDescriptor oldLocalDescriptor( localDescriptor );
608
609 //
610 // look for local locators that we can use in communication
611 //
612 // choose the first locator that is not localhost
613 //
614
615 bool foundLocator = false;
616 bool changedLocator = false;
617
618 for( ; i != iend; i++){
619 logging_debug( "local locator found " << (*i)->toString() );
620 IPv4Locator* ipv4locator = dynamic_cast<IPv4Locator*>(*i);
621
622 if( *ipv4locator != IPv4Locator::LOCALHOST &&
623 *ipv4locator != IPv4Locator::ANY &&
624 *ipv4locator != IPv4Locator::BROADCAST ){
625
626 ipv4locator->setPort( listenport );
627 changedLocator = *localDescriptor.locator != *ipv4locator;
628 localDescriptor.locator = ipv4locator;
629 logging_info( "binding to addr = " << ipv4locator->toString() );
630 foundLocator = true;
631 break;
632 }
633 } // for( ; i != iend; i++)
634
635 //
636 // if we found no locator, bind to localhost
637 //
638
639 if( !foundLocator ){
640 changedLocator = *localDescriptor.locator != IPv4Locator::LOCALHOST;
641 localDescriptor.locator = new IPv4Locator( IPv4Locator::LOCALHOST );
642 ((IPv4Locator*)(localDescriptor.locator))->setPort( listenport );
643 logging_info( "found no good local lcoator, binding to addr = " <<
644 localDescriptor.locator->toString() );
645 }
646
647 //
648 // if we have connections that have no more longer endpoints
649 // close these. they will be automatically built up again.
650 // also update the local locator in the linkset mapping
651 //
652
653 if( changedLocator ){
654
655 logging_debug( "local endp locator has changed to " << localDescriptor.toString() <<
656 ", resettings connections that end at old locator " <<
657 oldLocalDescriptor.toString());
658
659 LinkSet::iterator i = linkSet.begin();
660 LinkSet::iterator iend = linkSet.end();
661
662 for( ; i != iend; i++ ){
663
664 logging_debug( "checking connection for locator change: " <<
665 " local " << (*i).localLocator->toString() <<
666 " old " << oldLocalDescriptor.locator->toString() );
667
668 if( *((*i).localLocator) == *(oldLocalDescriptor.locator) ){
669
670 logging_debug("terminating connection to " << (*i).remoteLocator->toString() );
671 transport->terminate( oldLocalDescriptor.locator, (*i).remoteLocator );
672
673 (*i).localLocator = localDescriptor.locator;
674 }
675 } // for( ; i != iend; i++ )
676
677 // wait 500ms to give the sockets time to shut down
678 usleep( 500000 );
679
680 } else {
681
682 logging_debug( "locator has not changed, not resetting connections" );
683
684 }
685
686 //
687 // handle the connections that have no longer any
688 // valid locator. send update messages with the new
689 // locator, so the remote node updates its locator/link mapping
690 //
691
692 LinkSet::iterator iAffected = linkSet.begin();
693 LinkSet::iterator endAffected = linkSet.end();
694
695 for( ; iAffected != endAffected; iAffected++ ){
696 LinkDescriptor descr = *iAffected;
697 logging_debug( "sending out link locator update to " << descr.remoteLocator->toString() );
698
699 AribaBaseMsg updateMsg( descr.remoteLocator,
700 AribaBaseMsg::LINK_STATE_UPDATE,
701 descr.localLink, descr.remoteLink );
702
703 transport->sendMessage( &updateMsg );
704 }
705*/
706}
707
708/// sends a message to all end-points in the end-point descriptor
709void BaseCommunication::send(Message* message, const EndpointDescriptor& endpoint) {
710 Data data = data_serialize( message, DEFAULT_V );
711 transport->send( endpoint.getEndpoints(), data.getBuffer(), data.getLength() / 8);
712}
713
714/// sends a message to the remote locator inside the link descriptor
715void BaseCommunication::send(Message* message, const LinkDescriptor& desc) {
716 Data data = data_serialize( message, DEFAULT_V );
717 transport->send( desc.remoteLocator, data.getBuffer(), data.getLength() / 8);
718}
719
720}} // namespace ariba, communication
Note: See TracBrowser for help on using the repository browser.