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

Last change on this file since 3993 was 3712, checked in by Christoph Mayer, 16 years ago

-autolink message buffer von basecomm nach baseoverlay und komplette logik hochgezogen damit mit neuem overlay routing zurecht kommt, damit ist letzer fehler raus

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