1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_automation.hxx"
30 
31 
32 #define ENABLE_BYTESTRING_STREAM_OPERATORS
33 #include <tools/solar.h>
34 #include <automation/simplecm.hxx>
35 
36 #include <automation/commdefines.hxx>
37 #include "packethandler.hxx"
38 #include "tcpio.hxx"
39 
40 #if OSL_DEBUG_LEVEL > 1
41 #include <stdio.h>
42 void debug_printf( const char *chars )
43 {
44     static sal_Bool bPrint = (getenv("DEBUG") != NULL);
45     if ( bPrint )
46     {
47         printf( chars );
48         fflush( stdout );
49     }
50 }
51 #endif
52 
53 CommunicationLink::CommunicationLink( CommunicationManager *pMan )
54 : pMyManager(pMan)
55 , pServiceData(NULL)
56 , nServiceProtocol( 0 )
57 , bIsInsideCallback( sal_False )
58 , nTotalBytes( 0 )
59 , maApplication("Undefined")
60 #if OSL_DEBUG_LEVEL > 1
61 , bFlag( sal_False )
62 , nSomething( 0 )
63 #endif
64 {
65 }
66 
67 CommunicationLink::~CommunicationLink()
68 {
69 #if OSL_DEBUG_LEVEL > 1
70     if ( !bFlag )    // bFlag will be set if deletion is expected else we can set a breakpoint
71         bFlag = sal_False;
72 #endif
73 	if ( pMyManager )
74 		pMyManager->DestroyingLink( this );
75 }
76 
77 void CommunicationLink::CallInfoMsg( InfoString aMsg )
78 {
79 	if ( pMyManager )
80 		pMyManager->InfoMsg( aMsg );
81 };
82 
83 CM_InfoType CommunicationLink::GetInfoType()
84 {
85 	if ( pMyManager )
86 		return pMyManager->GetInfoType();
87 	else
88 		return CM_NO_TEXT;
89 }
90 
91 IMPL_LINK( CommunicationLink, ConnectionClosed, void*, EMPTYARG )
92 {
93 	if ( pMyManager )
94 		pMyManager->CallConnectionClosed( this );
95 	return 1;
96 }
97 
98 IMPL_LINK( CommunicationLink, DataReceived, void*, EMPTYARG )
99 {
100 	if ( pMyManager )
101 		pMyManager->CallDataReceived( this );
102 	return 1;
103 }
104 
105 sal_Bool CommunicationLink::DoTransferDataStream( SvStream *pDataStream, CMProtocol nProtocol )
106 {
107 	INFO_MSG( CByteString("S :").Append( GetCommunicationPartner( CM_FQDN ) ),
108 		CByteString("Daten Senden:").Append( GetCommunicationPartner( CM_FQDN ) ),
109 		CM_SEND, this );
110 	sal_Bool bWasError = sal_False;
111 
112 	sal_uInt32 nBuffer;
113 	nBuffer = pDataStream->SeekRel(0) +1;
114 	bWasError = pPacketHandler->TransferData( ((SvMemoryStream*)pDataStream)->GetData(), nBuffer, nProtocol ) != C_ERROR_NONE;
115 
116 	if ( bWasError )
117 	{
118 		INFO_MSG( CByteString("Send Failed:").Append( GetCommunicationPartner( CM_FQDN ) ),
119 			CByteString( "Socket wird wegen Fehlers beim Senden geschlossen: ").Append( GetCommunicationPartner( CM_FQDN ) ),
120 			CM_ERROR, this );
121 		ShutdownCommunication();
122 	}
123 	return !bWasError;
124 }
125 
126 sal_Bool CommunicationLink::TransferDataStream( SvStream *pDataStream, CMProtocol nProtocol )
127 {
128 	aLastAccess = DateTime();
129 	nTotalBytes += pDataStream->Seek( STREAM_SEEK_TO_END );
130 	return DoTransferDataStream( pDataStream, nProtocol );
131 }
132 
133 void CommunicationLink::SetApplication( const ByteString& aApp )
134 {
135 	maApplication = aApp;
136 }
137 
138 
139 SimpleCommunicationLinkViaSocket::SimpleCommunicationLinkViaSocket( CommunicationManager *pMan, vos::OStreamSocket *pSocket )
140 : CommunicationLink( pMan )
141 , aCommunicationPartner()
142 , aMyName()
143 , pStreamSocket( pSocket )
144 , pReceiveStream( NULL )
145 , bIsRequestShutdownPending( sal_False )
146 {
147 	pTCPIO = new TCPIO( pStreamSocket );
148 	pPacketHandler = new PacketHandler( (ITransmiter*) pTCPIO, pTCPIO, pMyManager->IsMultiChannel() );
149 }
150 
151 SimpleCommunicationLinkViaSocket::~SimpleCommunicationLinkViaSocket()
152 {
153 	delete pPacketHandler;
154     pPacketHandler = NULL;
155 	delete pTCPIO;
156     pTCPIO = NULL;
157 	delete pStreamSocket;
158     pStreamSocket = NULL;
159 }
160 
161 void SimpleCommunicationLinkViaSocket::SetStreamSocket( vos::OStreamSocket* pSocket )
162 {
163     if ( pTCPIO )
164         pTCPIO->SetStreamSocket( pSocket );
165     pStreamSocket = pSocket;
166 }
167 
168 sal_Bool SimpleCommunicationLinkViaSocket::StopCommunication()
169 {
170 	CommunicationLinkRef rHold(this);		// avoid deleting this link before the end of the method
171 	if ( !IsCommunicationError() )	// Meaning that the Communication is still runnung
172 	{
173 #if OSL_DEBUG_LEVEL > 1
174 		debug_printf("Sending REQUEST_ShutdownLink\n");
175 #endif
176 		SendHandshake( CH_REQUEST_ShutdownLink );
177 	}
178 	WaitForShutdown();
179 	return sal_True;
180 }
181 
182 void SimpleCommunicationLinkViaSocket::SetFinalRecieveTimeout()
183 {
184 	if ( !IsCommunicationError() )
185 	{
186         TimeValue aTime = {30, 0};   // 30 seconds
187 	    pStreamSocket->setRecvTimeout( &aTime );
188 	}
189 }
190 
191 sal_Bool SimpleCommunicationLinkViaSocket::IsCommunicationError()
192 {
193 	return !pStreamSocket;
194 }
195 
196 ByteString SimpleCommunicationLinkViaSocket::GetCommunicationPartner( CM_NameType eType )
197 {
198 	if ( pStreamSocket )
199 	{
200 		switch ( eType )
201 		{
202 			case CM_DOTTED:
203 				{
204 					rtl::OUString aDotted;
205 					vos::OSocketAddr *pPeerAdr = new vos::OSocketAddr;
206 					pStreamSocket->getPeerAddr( *pPeerAdr );
207 					((vos::OInetSocketAddr*)pPeerAdr)->getDottedAddr( aDotted );
208 					delete pPeerAdr;
209 					return ByteString( UniString(aDotted), RTL_TEXTENCODING_UTF8 );
210 				}
211 				//break;
212 			case CM_FQDN:
213 				{
214 					if ( !aCommunicationPartner.Len() )
215 					{
216 						rtl::OUString aFQDN;
217 						pStreamSocket->getPeerHost( aFQDN );
218 						aCommunicationPartner = ByteString( UniString(aFQDN), RTL_TEXTENCODING_UTF8 );
219 					}
220 					return aCommunicationPartner;
221 				}
222 				//break;
223 		}
224 	}
225 	return CByteString( "Unknown" );
226 }
227 
228 ByteString SimpleCommunicationLinkViaSocket::GetMyName( CM_NameType eType )
229 {
230 	if ( pStreamSocket )
231 	{
232 		switch ( eType )
233 		{
234 			case CM_DOTTED:
235 				{
236 					rtl::OUString aDotted;
237 					vos::OSocketAddr *pPeerAdr = new vos::OSocketAddr;
238 					pStreamSocket->getLocalAddr( *pPeerAdr );
239 					((vos::OInetSocketAddr*)pPeerAdr)->getDottedAddr( aDotted );
240 					delete pPeerAdr;
241 					return ByteString( UniString(aDotted), RTL_TEXTENCODING_UTF8 );
242 				}
243 				//break;
244 			case CM_FQDN:
245 				{
246 					if ( !aMyName.Len() )
247 					{
248 						rtl::OUString aFQDN;
249 						pStreamSocket->getLocalHost( aFQDN );
250 						aMyName = ByteString( UniString(aFQDN), RTL_TEXTENCODING_UTF8 );
251 					}
252 					return aMyName;
253 				}
254 				//break;
255 		}
256 	}
257 	return CByteString( "Error" );
258 }
259 
260 SvStream* SimpleCommunicationLinkViaSocket::GetBestCommunicationStream()
261 {
262 	SvStream* pStream = new SvMemoryStream;
263 //	pStream->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
264 	return pStream;
265 }
266 
267 #define READ_SOCKET( pBuffer, nLength )\
268 	if ( !bWasError )\
269 		{bWasError |= pTCPIO->ReceiveBytes( pBuffer, nLength ) != C_ERROR_NONE;}
270 
271 #define READ_SOCKET_LEN( pBuffer, nLength, nTotal )\
272 	READ_SOCKET( pBuffer, nLength );\
273 	if ( !bWasError )\
274 		{nTotal += nLength;}
275 
276 sal_Bool SimpleCommunicationLinkViaSocket::DoReceiveDataStream()
277 {
278 	sal_Bool bWasError = sal_False;
279 	void* pBuffer = NULL;
280 	comm_UINT32 nLen;
281 	bWasError = pPacketHandler->ReceiveData( pBuffer, nLen ) != C_ERROR_NONE;
282 	if ( !bWasError )
283 	{
284 		pReceiveStream = GetBestCommunicationStream();
285 		DBG_ASSERT( pReceiveStream->IsA() == ID_MEMORYSTREAM, "CommunicationStream is not an SvMemoryStream. Communication has to be reimplemented here!");
286 		if ( pReceiveStream->IsA() == ID_MEMORYSTREAM )
287 			((SvMemoryStream*)pReceiveStream)->SetBuffer( pBuffer, nLen, sal_True, nLen );
288 		DBG_ASSERT( pReceiveStream, "Datastream is NULL");
289 	}
290 
291 	return !bWasError;
292 }
293 
294 void SimpleCommunicationLinkViaSocket::SetApplication( const ByteString& aApp )
295 {
296 	CommunicationLink::SetApplication( aApp );
297 	SvStream* pData = GetBestCommunicationStream();
298 	*pData << aApp;
299 	SendHandshake( CH_SetApplication, pData );
300 	delete pData;
301 }
302 
303 void SimpleCommunicationLinkViaSocket::SetNewPacketAsCurrent()
304 {
305 	pServiceData = pReceiveStream;
306 	nServiceProtocol = pPacketHandler->GetReceiveProtocol();
307 	nServiceHeaderType = pPacketHandler->GetReceiveHeaderType();
308 }
309 
310 sal_Bool SimpleCommunicationLinkViaSocket::SendHandshake( HandshakeType aHandshakeType, SvStream* pData )
311 {
312 	sal_Bool bWasError;
313 
314 	if ( pData )
315 	{
316 		sal_uInt32 nBuffer;
317 		nBuffer = pData->Seek( STREAM_SEEK_TO_END );
318 		bWasError = !pPacketHandler->SendHandshake( aHandshakeType, ((SvMemoryStream*)pData)->GetData(), nBuffer );
319 	}
320 	else
321 		bWasError = !pPacketHandler->SendHandshake( aHandshakeType );
322 
323 
324 	if ( bWasError )
325 	{
326 		INFO_MSG( CByteString("Send Failed:").Append( GetCommunicationPartner( CM_FQDN ) ),
327 			CByteString( "Socket wird wegen Fehlers beim Senden geschlossen: ").Append( GetCommunicationPartner( CM_FQDN ) ),
328 			CM_ERROR, this );
329 		ShutdownCommunication();
330 	}
331 	else
332 	{	// set new status
333 		switch ( aHandshakeType )
334 		{
335 			case CH_REQUEST_HandshakeAlive:
336 				break;
337 			case CH_RESPONSE_HandshakeAlive:
338 				break;
339 			case CH_REQUEST_ShutdownLink:
340 				bIsRequestShutdownPending = sal_True;
341 				break;
342 			case CH_ShutdownLink:
343 				break;
344 			case CH_SUPPORT_OPTIONS:
345 				break;
346 			case CH_SetApplication:
347 				break;
348 			default:
349 				DBG_ERROR("Unknown HandshakeType");
350 		}
351 	}
352 	return !bWasError;
353 }
354 
355 SimpleCommunicationLinkViaSocketWithReceiveCallbacks::SimpleCommunicationLinkViaSocketWithReceiveCallbacks( CommunicationManager *pMan, vos::OStreamSocket *pSocket )
356 : SimpleCommunicationLinkViaSocket( pMan, pSocket )
357 {
358 }
359 
360 SimpleCommunicationLinkViaSocketWithReceiveCallbacks::~SimpleCommunicationLinkViaSocketWithReceiveCallbacks()
361 {
362 	if ( pMyManager && pMyManager->IsLinkValid( this ) && !bIsRequestShutdownPending )
363 		StopCommunication();
364 }
365 
366 void SimpleCommunicationLinkViaSocketWithReceiveCallbacks::WaitForShutdown()
367 {
368 	CommunicationLinkRef rHold(this);		// avoid deleting this link before the end of the method
369 	SetFinalRecieveTimeout();
370     while ( pMyManager && !IsCommunicationError() )
371 		ReceiveDataStream();
372 }
373 
374 sal_Bool SimpleCommunicationLinkViaSocketWithReceiveCallbacks::ReceiveDataStream()
375 {
376 	if ( DoReceiveDataStream() )
377 	{
378 		SetNewPacketAsCurrent();
379 		StartCallback();
380 		DataReceived();
381 		return sal_True;
382 	}
383 	else
384 	{
385 		StartCallback();
386 		ShutdownCommunication();
387 		return sal_False;
388 	}
389 }
390 
391 sal_Bool SimpleCommunicationLinkViaSocketWithReceiveCallbacks::ShutdownCommunication()
392 {
393     if ( GetStreamSocket() )
394 		GetStreamSocket()->shutdown();
395 
396 	if ( GetStreamSocket() )
397 		GetStreamSocket()->close();
398 
399     vos::OStreamSocket *pTempSocket = GetStreamSocket();
400     SetStreamSocket( NULL );
401     delete pTempSocket;
402 
403 	ConnectionClosed();
404 
405 	return sal_True;
406 }
407 
408 
409 
410 CommunicationManager::CommunicationManager( sal_Bool bUseMultiChannel )
411 : nInfoType( CM_NONE )
412 , bIsCommunicationRunning( sal_False )
413 , maApplication("Unknown")
414 , bIsMultiChannel( bUseMultiChannel )
415 {
416 }
417 
418 CommunicationManager::~CommunicationManager()
419 {
420 	xLastNewLink.Clear();
421 }
422 
423 sal_Bool CommunicationManager::StartCommunication( String aApp, String aParams )
424 {
425     (void) aApp; /* avoid warning about unused parameter */
426     (void) aParams; /* avoid warning about unused parameter */
427     return sal_False;
428 }
429 
430 sal_Bool CommunicationManager::StartCommunication( ByteString aHost, sal_uLong nPort )
431 {
432     (void) aHost; /* avoid warning about unused parameter */
433     (void) nPort; /* avoid warning about unused parameter */
434     return sal_False;
435 }
436 
437 ByteString CommunicationManager::GetMyName( CM_NameType )
438 {
439 	rtl::OUString aHostname;
440 	vos::OSocketAddr::getLocalHostname( aHostname );
441 	return ByteString( UniString(aHostname), RTL_TEXTENCODING_UTF8 );
442 }
443 
444 void CommunicationManager::CallConnectionOpened( CommunicationLink* pCL )
445 {
446 	pCL->StartCallback();		// Sollte bereits vor dem Aufruf gerufen werden
447 	pCL->aStart = DateTime();
448 	pCL->aLastAccess = pCL->aStart;
449 	bIsCommunicationRunning = sal_True;
450 	pCL->SetApplication( GetApplication() );
451 
452 	xLastNewLink = pCL;
453 
454 	INFO_MSG( CByteString("C+:").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
455 		CByteString("Verbindung aufgebaut: ").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
456 		CM_OPEN, pCL );
457 	ConnectionOpened( pCL );
458 	pCL->FinishCallback();
459 }
460 
461 void CommunicationManager::CallConnectionClosed( CommunicationLink* pCL )
462 {
463 	pCL->StartCallback();		// Sollte bereits vor dem Aufruf gerufen werden
464 	pCL->aLastAccess = DateTime();
465 
466 	INFO_MSG( CByteString("C-:").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
467 		CByteString("Verbindung abgebrochen: ").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
468 		CM_CLOSE, pCL );
469 	ConnectionClosed( pCL );
470 
471 	if ( xLastNewLink == pCL )
472 		xLastNewLink.Clear();
473 
474 	pCL->FinishCallback();
475 //	delete pCL;
476 }
477 
478 void CommunicationManager::CallDataReceived( CommunicationLink* pCL )
479 {
480 	pCL->StartCallback();		// Sollte bereits vor dem Aufruf gerufen werden
481 	pCL->aLastAccess = DateTime();
482 	CommunicationLinkRef rHold(pCL);	// H�lt den Zeiger bis zum Ende des calls
483 
484 	// should be impossible but happens for mysterious reasons
485 	if ( !pCL->pServiceData )
486 	{
487 		DBG_ERROR( "Datastream is NULL" );
488 		pCL->FinishCallback();
489 		return;
490 	}
491 
492 
493 	if ( CH_Handshake == pCL->nServiceHeaderType )
494 	{
495 		SvStream *pData = pCL->GetServiceData();
496 		sal_uInt16 nType;
497 		pData->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );	// Unfortulately it is written this way :((
498 		*pData >> nType;
499 		pData->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
500 		switch ( nType )
501 		{
502 			case CH_REQUEST_HandshakeAlive:
503 				{
504 					pCL->SendHandshake( CH_RESPONSE_HandshakeAlive );
505 				}
506 				break;
507 			case CH_REQUEST_ShutdownLink:
508 				{
509 #if OSL_DEBUG_LEVEL > 1
510 					debug_printf("Sending ShutdownLink\n");
511 #endif
512 					pCL->SendHandshake( CH_ShutdownLink );
513 				}
514 				break;
515 			case CH_ShutdownLink:
516 				{
517 #if OSL_DEBUG_LEVEL > 1
518 					debug_printf("Executing ShutdownLink\n");
519 #endif
520 					pCL->ShutdownCommunication();
521 				}
522 				break;
523 			case CH_SetApplication:
524 				{
525 					ByteString aApplication;
526 					*pData >> aApplication;
527 					pCL->CommunicationLink::SetApplication( aApplication );
528 #if OSL_DEBUG_LEVEL > 1
529 					debug_printf( "Setting Application to " );
530 					debug_printf( aApplication.GetBuffer() );
531 					debug_printf( "\n" );
532 #endif
533 				}
534 				break;
535 
536 #if OSL_DEBUG_LEVEL > 1
537 			default:
538 				{
539 					debug_printf("Unknown Handshake received\n");
540 				}
541 #endif
542 		}
543 		delete pData;
544 	}
545 	else
546 	{
547 		if ( pCL->pServiceData )
548 		{
549 			pCL->nTotalBytes += pCL->pServiceData->Seek( STREAM_SEEK_TO_END );
550 			pCL->pServiceData->Seek( STREAM_SEEK_TO_BEGIN );
551 		}
552 
553 		INFO_MSG( CByteString("D :").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
554 			CByteString("Daten Empfangen:").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
555 			CM_RECEIVE, pCL );
556 		DataReceived( pCL );
557 	}
558 	delete pCL->GetServiceData();
559 	pCL->FinishCallback();
560 }
561 
562 void CommunicationManager::CallInfoMsg( InfoString aMsg )
563 {
564 	// Hier wird es wohl kein Housekeeping geben
565 	InfoMsg( aMsg );
566 }
567 
568 void CommunicationManager::SetApplication( const ByteString& aApp, sal_Bool bRunningLinks )
569 {
570 	maApplication = aApp;
571 	if ( bRunningLinks )
572 	{
573 		sal_uInt16 i;
574 		for ( i = 0 ; i < GetCommunicationLinkCount() ; i++ )
575 			GetCommunicationLink( i )->SetApplication( aApp );
576 	}
577 }
578 
579 
580 
581 SingleCommunicationManager::SingleCommunicationManager( sal_Bool bUseMultiChannel )
582 : CommunicationManager( bUseMultiChannel )
583 {
584 	xActiveLink = NULL;
585 	pInactiveLink = NULL;
586 }
587 
588 SingleCommunicationManager::~SingleCommunicationManager()
589 {
590 	StopCommunication();
591 	if ( pInactiveLink )
592 		pInactiveLink->InvalidateManager();
593 }
594 
595 sal_Bool SingleCommunicationManager::StopCommunication()
596 {
597 	if ( xActiveLink.Is() )
598 	{
599 		sal_Bool bSuccess = xActiveLink->StopCommunication();
600 		if ( pInactiveLink )
601 			pInactiveLink->InvalidateManager();
602 		pInactiveLink = xActiveLink;
603 		xActiveLink.Clear();
604 		return bSuccess;
605 	}
606 	return sal_True;
607 }
608 
609 sal_Bool SingleCommunicationManager::IsLinkValid( CommunicationLink* pCL )
610 {
611 	return &xActiveLink == pCL;
612 }
613 
614 sal_uInt16 SingleCommunicationManager::GetCommunicationLinkCount()
615 {
616 	return IsCommunicationRunning()?1:0;
617 }
618 
619 CommunicationLinkRef SingleCommunicationManager::GetCommunicationLink( sal_uInt16 )
620 {
621 	return xActiveLink;
622 }
623 
624 void SingleCommunicationManager::CallConnectionOpened( CommunicationLink* pCL )
625 {
626 	DBG_ASSERT( !xActiveLink.Is(), "Es ist bereits ein CommunicationLink aktiv");
627 	if ( xActiveLink.Is() )
628 	{
629 		if ( pInactiveLink )
630 			pInactiveLink->InvalidateManager();
631 		pInactiveLink = xActiveLink;
632 		xActiveLink->StopCommunication();	// Den alten Link brutal abw�rgen
633 	}
634 	xActiveLink = pCL;
635 	CommunicationManager::CallConnectionOpened( pCL );
636 }
637 
638 void SingleCommunicationManager::CallConnectionClosed( CommunicationLink* pCL )
639 {
640 	CommunicationManager::CallConnectionClosed( pCL );
641 
642 	DBG_ASSERT( pCL == xActiveLink, "SingleCommunicationManager::CallConnectionClosed mit fremdem Link");
643 	if ( pInactiveLink )
644 		pInactiveLink->InvalidateManager();
645 	pInactiveLink = xActiveLink;
646 	xActiveLink.Clear();
647 	bIsCommunicationRunning = sal_False;
648 }
649 
650 void SingleCommunicationManager::DestroyingLink( CommunicationLink *pCL )
651 {
652 	pInactiveLink = NULL;
653 	pCL->InvalidateManager();
654 }
655 
656 
657 SingleCommunicationManagerClientViaSocket::SingleCommunicationManagerClientViaSocket( ByteString aHost, sal_uLong nPort, sal_Bool bUseMultiChannel )
658 : SingleCommunicationManager( bUseMultiChannel )
659 , aHostToTalk( aHost )
660 , nPortToTalk( nPort )
661 {
662 }
663 
664 
665 SingleCommunicationManagerClientViaSocket::SingleCommunicationManagerClientViaSocket( sal_Bool bUseMultiChannel )
666 : SingleCommunicationManager( bUseMultiChannel )
667 , aHostToTalk()
668 , nPortToTalk( 0 )
669 {
670 }
671 
672 
673 sal_Bool CommonSocketFunctions::DoStartCommunication( CommunicationManager *pCM, ICommunicationManagerClient *pCMC, ByteString aHost, sal_uLong nPort )
674 {
675 	vos::OInetSocketAddr Addr;
676 	vos::OConnectorSocket *pConnSocket;
677 
678 	Addr.setAddr( rtl::OUString( UniString( aHost, RTL_TEXTENCODING_UTF8 ) ) );
679 	Addr.setPort( nPort );
680 
681 	TimeValue aTV;
682 	aTV.Seconds = 10;		// Warte 10 Sekunden
683 	aTV.Nanosec = 0;
684 	do
685 	{
686 		pConnSocket = new vos::OConnectorSocket();
687 		pConnSocket->setTcpNoDelay( 1 );
688 		if ( pConnSocket->connect( Addr, &aTV ) == vos::ISocketTypes::TResult_Ok )
689 		{
690 			pConnSocket->setTcpNoDelay( 1 );
691 
692 			pCM->CallConnectionOpened( CreateCommunicationLink( pCM, pConnSocket ) );
693 			return sal_True;
694 		}
695 		else
696 			delete pConnSocket;
697 
698 	} while ( pCMC->RetryConnect() );
699 
700 	return sal_False;
701 }
702 
703