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