merge the formfield patch from ooo-build
[ooovba.git] / automation / source / simplecm / simplecm.cxx
blob42d6ec5e03074bb61514b1a228bf0231e731777a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: simplecm.cxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_automation.hxx"
35 #define ENABLE_BYTESTRING_STREAM_OPERATORS
36 #include <tools/solar.h>
37 #include <automation/simplecm.hxx>
39 #include <automation/commdefines.hxx>
40 #include "packethandler.hxx"
41 #include "tcpio.hxx"
43 #if OSL_DEBUG_LEVEL > 1
44 #include <stdio.h>
45 void debug_printf( const char *chars )
47 static BOOL bPrint = (getenv("DEBUG") != NULL);
48 if ( bPrint )
50 printf( chars );
51 fflush( stdout );
54 #endif
56 CommunicationLink::CommunicationLink( CommunicationManager *pMan )
57 : pMyManager(pMan)
58 , pServiceData(NULL)
59 , nServiceProtocol( 0 )
60 , bIsInsideCallback( FALSE )
61 , nTotalBytes( 0 )
62 , maApplication("Undefined")
63 #if OSL_DEBUG_LEVEL > 1
64 , bFlag( FALSE )
65 , nSomething( 0 )
66 #endif
70 CommunicationLink::~CommunicationLink()
72 #if OSL_DEBUG_LEVEL > 1
73 if ( !bFlag ) // bFlag will be set if deletion is expected else we can set a breakpoint
74 bFlag = FALSE;
75 #endif
76 if ( pMyManager )
77 pMyManager->DestroyingLink( this );
80 void CommunicationLink::CallInfoMsg( InfoString aMsg )
82 if ( pMyManager )
83 pMyManager->InfoMsg( aMsg );
86 CM_InfoType CommunicationLink::GetInfoType()
88 if ( pMyManager )
89 return pMyManager->GetInfoType();
90 else
91 return CM_NO_TEXT;
94 IMPL_LINK( CommunicationLink, ConnectionClosed, void*, EMPTYARG )
96 if ( pMyManager )
97 pMyManager->CallConnectionClosed( this );
98 return 1;
101 IMPL_LINK( CommunicationLink, DataReceived, void*, EMPTYARG )
103 if ( pMyManager )
104 pMyManager->CallDataReceived( this );
105 return 1;
108 BOOL CommunicationLink::DoTransferDataStream( SvStream *pDataStream, CMProtocol nProtocol )
110 INFO_MSG( CByteString("S :").Append( GetCommunicationPartner( CM_FQDN ) ),
111 CByteString("Daten Senden:").Append( GetCommunicationPartner( CM_FQDN ) ),
112 CM_SEND, this );
113 BOOL bWasError = FALSE;
115 UINT32 nBuffer;
116 nBuffer = pDataStream->SeekRel(0) +1;
117 bWasError = pPacketHandler->TransferData( ((SvMemoryStream*)pDataStream)->GetData(), nBuffer, nProtocol ) != C_ERROR_NONE;
119 if ( bWasError )
121 INFO_MSG( CByteString("Send Failed:").Append( GetCommunicationPartner( CM_FQDN ) ),
122 CByteString( "Socket wird wegen Fehlers beim Senden geschlossen: ").Append( GetCommunicationPartner( CM_FQDN ) ),
123 CM_ERROR, this );
124 ShutdownCommunication();
126 return !bWasError;
129 BOOL CommunicationLink::TransferDataStream( SvStream *pDataStream, CMProtocol nProtocol )
131 aLastAccess = DateTime();
132 nTotalBytes += pDataStream->Seek( STREAM_SEEK_TO_END );
133 return DoTransferDataStream( pDataStream, nProtocol );
136 void CommunicationLink::SetApplication( const ByteString& aApp )
138 maApplication = aApp;
142 SimpleCommunicationLinkViaSocket::SimpleCommunicationLinkViaSocket( CommunicationManager *pMan, NAMESPACE_VOS(OStreamSocket) *pSocket )
143 : CommunicationLink( pMan )
144 , aCommunicationPartner()
145 , aMyName()
146 , pStreamSocket( pSocket )
147 , pReceiveStream( NULL )
148 , bIsRequestShutdownPending( FALSE )
150 pTCPIO = new TCPIO( pStreamSocket );
151 pPacketHandler = new PacketHandler( (ITransmiter*) pTCPIO, pTCPIO, pMyManager->IsMultiChannel() );
154 SimpleCommunicationLinkViaSocket::~SimpleCommunicationLinkViaSocket()
156 delete pPacketHandler;
157 pPacketHandler = NULL;
158 delete pTCPIO;
159 pTCPIO = NULL;
160 delete pStreamSocket;
161 pStreamSocket = NULL;
164 void SimpleCommunicationLinkViaSocket::SetStreamSocket( NAMESPACE_VOS(OStreamSocket)* pSocket )
166 if ( pTCPIO )
167 pTCPIO->SetStreamSocket( pSocket );
168 pStreamSocket = pSocket;
171 BOOL SimpleCommunicationLinkViaSocket::StopCommunication()
173 CommunicationLinkRef rHold(this); // avoid deleting this link before the end of the method
174 if ( !IsCommunicationError() ) // Meaning that the Communication is still runnung
176 #if OSL_DEBUG_LEVEL > 1
177 debug_printf("Sending REQUEST_ShutdownLink\n");
178 #endif
179 SendHandshake( CH_REQUEST_ShutdownLink );
181 WaitForShutdown();
182 return TRUE;
185 void SimpleCommunicationLinkViaSocket::SetFinalRecieveTimeout()
187 if ( !IsCommunicationError() )
189 TimeValue aTime = {30, 0}; // 30 seconds
190 pStreamSocket->setRecvTimeout( &aTime );
194 BOOL SimpleCommunicationLinkViaSocket::IsCommunicationError()
196 return !pStreamSocket;
199 ByteString SimpleCommunicationLinkViaSocket::GetCommunicationPartner( CM_NameType eType )
201 if ( pStreamSocket )
203 switch ( eType )
205 case CM_DOTTED:
207 rtl::OUString aDotted;
208 NAMESPACE_VOS(OSocketAddr) *pPeerAdr = new NAMESPACE_VOS(OSocketAddr);
209 pStreamSocket->getPeerAddr( *pPeerAdr );
210 ((NAMESPACE_VOS(OInetSocketAddr*))pPeerAdr)->getDottedAddr( aDotted );
211 delete pPeerAdr;
212 return ByteString( UniString(aDotted), RTL_TEXTENCODING_UTF8 );
214 //break;
215 case CM_FQDN:
217 if ( !aCommunicationPartner.Len() )
219 rtl::OUString aFQDN;
220 pStreamSocket->getPeerHost( aFQDN );
221 aCommunicationPartner = ByteString( UniString(aFQDN), RTL_TEXTENCODING_UTF8 );
223 return aCommunicationPartner;
225 //break;
228 return CByteString( "Unknown" );
231 ByteString SimpleCommunicationLinkViaSocket::GetMyName( CM_NameType eType )
233 if ( pStreamSocket )
235 switch ( eType )
237 case CM_DOTTED:
239 rtl::OUString aDotted;
240 NAMESPACE_VOS(OSocketAddr) *pPeerAdr = new NAMESPACE_VOS(OSocketAddr);
241 pStreamSocket->getLocalAddr( *pPeerAdr );
242 ((NAMESPACE_VOS(OInetSocketAddr*))pPeerAdr)->getDottedAddr( aDotted );
243 delete pPeerAdr;
244 return ByteString( UniString(aDotted), RTL_TEXTENCODING_UTF8 );
246 //break;
247 case CM_FQDN:
249 if ( !aMyName.Len() )
251 rtl::OUString aFQDN;
252 pStreamSocket->getLocalHost( aFQDN );
253 aMyName = ByteString( UniString(aFQDN), RTL_TEXTENCODING_UTF8 );
255 return aMyName;
257 //break;
260 return CByteString( "Error" );
263 SvStream* SimpleCommunicationLinkViaSocket::GetBestCommunicationStream()
265 SvStream* pStream = new SvMemoryStream;
266 // pStream->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
267 return pStream;
270 #define READ_SOCKET( pBuffer, nLength )\
271 if ( !bWasError )\
272 {bWasError |= pTCPIO->ReceiveBytes( pBuffer, nLength ) != C_ERROR_NONE;}
274 #define READ_SOCKET_LEN( pBuffer, nLength, nTotal )\
275 READ_SOCKET( pBuffer, nLength );\
276 if ( !bWasError )\
277 {nTotal += nLength;}
279 BOOL SimpleCommunicationLinkViaSocket::DoReceiveDataStream()
281 BOOL bWasError = FALSE;
282 char* pBuffer = NULL;
283 comm_UINT32 nLen;
284 bWasError = pPacketHandler->ReceiveData( (void* &)pBuffer, nLen ) != C_ERROR_NONE;
285 if ( !bWasError )
287 pReceiveStream = GetBestCommunicationStream();
288 DBG_ASSERT( pReceiveStream->IsA() == ID_MEMORYSTREAM, "CommunicationStream is not an SvMemoryStream. Communication has to be reimplemented here!");
289 if ( pReceiveStream->IsA() == ID_MEMORYSTREAM )
290 ((SvMemoryStream*)pReceiveStream)->SetBuffer( pBuffer, nLen, TRUE, nLen );
291 DBG_ASSERT( pReceiveStream, "Datastream is NULL");
294 return !bWasError;
297 void SimpleCommunicationLinkViaSocket::SetApplication( const ByteString& aApp )
299 CommunicationLink::SetApplication( aApp );
300 SvStream* pData = GetBestCommunicationStream();
301 *pData << aApp;
302 SendHandshake( CH_SetApplication, pData );
303 delete pData;
306 void SimpleCommunicationLinkViaSocket::SetNewPacketAsCurrent()
308 pServiceData = pReceiveStream;
309 nServiceProtocol = pPacketHandler->GetReceiveProtocol();
310 nServiceHeaderType = pPacketHandler->GetReceiveHeaderType();
313 BOOL SimpleCommunicationLinkViaSocket::SendHandshake( HandshakeType aHandshakeType, SvStream* pData )
315 BOOL bWasError;
317 if ( pData )
319 UINT32 nBuffer;
320 nBuffer = pData->Seek( STREAM_SEEK_TO_END );
321 bWasError = !pPacketHandler->SendHandshake( aHandshakeType, ((SvMemoryStream*)pData)->GetData(), nBuffer );
323 else
324 bWasError = !pPacketHandler->SendHandshake( aHandshakeType );
327 if ( bWasError )
329 INFO_MSG( CByteString("Send Failed:").Append( GetCommunicationPartner( CM_FQDN ) ),
330 CByteString( "Socket wird wegen Fehlers beim Senden geschlossen: ").Append( GetCommunicationPartner( CM_FQDN ) ),
331 CM_ERROR, this );
332 ShutdownCommunication();
334 else
335 { // set new status
336 switch ( aHandshakeType )
338 case CH_REQUEST_HandshakeAlive:
339 break;
340 case CH_RESPONSE_HandshakeAlive:
341 break;
342 case CH_REQUEST_ShutdownLink:
343 bIsRequestShutdownPending = TRUE;
344 break;
345 case CH_ShutdownLink:
346 break;
347 case CH_SUPPORT_OPTIONS:
348 break;
349 case CH_SetApplication:
350 break;
351 default:
352 DBG_ERROR("Unknown HandshakeType");
355 return !bWasError;
358 SimpleCommunicationLinkViaSocketWithReceiveCallbacks::SimpleCommunicationLinkViaSocketWithReceiveCallbacks( CommunicationManager *pMan, NAMESPACE_VOS(OStreamSocket) *pSocket )
359 : SimpleCommunicationLinkViaSocket( pMan, pSocket )
363 SimpleCommunicationLinkViaSocketWithReceiveCallbacks::~SimpleCommunicationLinkViaSocketWithReceiveCallbacks()
365 if ( pMyManager && pMyManager->IsLinkValid( this ) && !bIsRequestShutdownPending )
366 StopCommunication();
369 void SimpleCommunicationLinkViaSocketWithReceiveCallbacks::WaitForShutdown()
371 CommunicationLinkRef rHold(this); // avoid deleting this link before the end of the method
372 SetFinalRecieveTimeout();
373 while ( pMyManager && !IsCommunicationError() )
374 ReceiveDataStream();
377 BOOL SimpleCommunicationLinkViaSocketWithReceiveCallbacks::ReceiveDataStream()
379 if ( DoReceiveDataStream() )
381 SetNewPacketAsCurrent();
382 StartCallback();
383 DataReceived();
384 return TRUE;
386 else
388 StartCallback();
389 ShutdownCommunication();
390 return FALSE;
394 BOOL SimpleCommunicationLinkViaSocketWithReceiveCallbacks::ShutdownCommunication()
396 if ( GetStreamSocket() )
397 GetStreamSocket()->shutdown();
399 if ( GetStreamSocket() )
400 GetStreamSocket()->close();
402 NAMESPACE_VOS(OStreamSocket) *pTempSocket = GetStreamSocket();
403 SetStreamSocket( NULL );
404 delete pTempSocket;
406 ConnectionClosed();
408 return TRUE;
413 CommunicationManager::CommunicationManager( BOOL bUseMultiChannel )
414 : nInfoType( CM_NONE )
415 , bIsCommunicationRunning( FALSE )
416 , maApplication("Unknown")
417 , bIsMultiChannel( bUseMultiChannel )
421 CommunicationManager::~CommunicationManager()
423 xLastNewLink.Clear();
426 BOOL CommunicationManager::StartCommunication( String aApp, String aParams )
428 (void) aApp; /* avoid warning about unused parameter */
429 (void) aParams; /* avoid warning about unused parameter */
430 return FALSE;
433 BOOL CommunicationManager::StartCommunication( ByteString aHost, ULONG nPort )
435 (void) aHost; /* avoid warning about unused parameter */
436 (void) nPort; /* avoid warning about unused parameter */
437 return FALSE;
440 ByteString CommunicationManager::GetMyName( CM_NameType )
442 rtl::OUString aHostname;
443 NAMESPACE_VOS(OSocketAddr)::getLocalHostname( aHostname );
444 return ByteString( UniString(aHostname), RTL_TEXTENCODING_UTF8 );
447 void CommunicationManager::CallConnectionOpened( CommunicationLink* pCL )
449 pCL->StartCallback(); // Sollte bereits vor dem Aufruf gerufen werden
450 pCL->aStart = DateTime();
451 pCL->aLastAccess = pCL->aStart;
452 bIsCommunicationRunning = TRUE;
453 pCL->SetApplication( GetApplication() );
455 xLastNewLink = pCL;
457 INFO_MSG( CByteString("C+:").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
458 CByteString("Verbindung aufgebaut: ").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
459 CM_OPEN, pCL );
460 ConnectionOpened( pCL );
461 pCL->FinishCallback();
464 void CommunicationManager::CallConnectionClosed( CommunicationLink* pCL )
466 pCL->StartCallback(); // Sollte bereits vor dem Aufruf gerufen werden
467 pCL->aLastAccess = DateTime();
469 INFO_MSG( CByteString("C-:").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
470 CByteString("Verbindung abgebrochen: ").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
471 CM_CLOSE, pCL );
472 ConnectionClosed( pCL );
474 if ( xLastNewLink == pCL )
475 xLastNewLink.Clear();
477 pCL->FinishCallback();
478 // delete pCL;
481 void CommunicationManager::CallDataReceived( CommunicationLink* pCL )
483 pCL->StartCallback(); // Sollte bereits vor dem Aufruf gerufen werden
484 pCL->aLastAccess = DateTime();
485 CommunicationLinkRef rHold(pCL); // Hält den Zeiger bis zum Ende des calls
487 // should be impossible but happens for mysterious reasons
488 if ( !pCL->pServiceData )
490 DBG_ERROR( "Datastream is NULL" );
491 pCL->FinishCallback();
492 return;
496 if ( CH_Handshake == pCL->nServiceHeaderType )
498 SvStream *pData = pCL->GetServiceData();
499 USHORT nType;
500 pData->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN ); // Unfortulately it is written this way :((
501 *pData >> nType;
502 pData->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
503 switch ( nType )
505 case CH_REQUEST_HandshakeAlive:
507 pCL->SendHandshake( CH_RESPONSE_HandshakeAlive );
509 break;
510 case CH_REQUEST_ShutdownLink:
512 #if OSL_DEBUG_LEVEL > 1
513 debug_printf("Sending ShutdownLink\n");
514 #endif
515 pCL->SendHandshake( CH_ShutdownLink );
517 break;
518 case CH_ShutdownLink:
520 #if OSL_DEBUG_LEVEL > 1
521 debug_printf("Executing ShutdownLink\n");
522 #endif
523 pCL->ShutdownCommunication();
525 break;
526 case CH_SetApplication:
528 ByteString aApplication;
529 *pData >> aApplication;
530 pCL->CommunicationLink::SetApplication( aApplication );
531 #if OSL_DEBUG_LEVEL > 1
532 debug_printf( "Setting Application to " );
533 debug_printf( aApplication.GetBuffer() );
534 debug_printf( "\n" );
535 #endif
537 break;
539 #if OSL_DEBUG_LEVEL > 1
540 default:
542 debug_printf("Unknown Handshake received\n");
544 #endif
546 delete pData;
548 else
550 if ( pCL->pServiceData )
552 pCL->nTotalBytes += pCL->pServiceData->Seek( STREAM_SEEK_TO_END );
553 pCL->pServiceData->Seek( STREAM_SEEK_TO_BEGIN );
556 INFO_MSG( CByteString("D :").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
557 CByteString("Daten Empfangen:").Append( pCL->GetCommunicationPartner( CM_FQDN ) ),
558 CM_RECEIVE, pCL );
559 DataReceived( pCL );
561 delete pCL->GetServiceData();
562 pCL->FinishCallback();
565 void CommunicationManager::CallInfoMsg( InfoString aMsg )
567 // Hier wird es wohl kein Housekeeping geben
568 InfoMsg( aMsg );
571 void CommunicationManager::SetApplication( const ByteString& aApp, BOOL bRunningLinks )
573 maApplication = aApp;
574 if ( bRunningLinks )
576 USHORT i;
577 for ( i = 0 ; i < GetCommunicationLinkCount() ; i++ )
578 GetCommunicationLink( i )->SetApplication( aApp );
584 SingleCommunicationManager::SingleCommunicationManager( BOOL bUseMultiChannel )
585 : CommunicationManager( bUseMultiChannel )
587 xActiveLink = NULL;
588 pInactiveLink = NULL;
591 SingleCommunicationManager::~SingleCommunicationManager()
593 StopCommunication();
594 if ( pInactiveLink )
595 pInactiveLink->InvalidateManager();
598 BOOL SingleCommunicationManager::StopCommunication()
600 if ( xActiveLink.Is() )
602 BOOL bSuccess = xActiveLink->StopCommunication();
603 if ( pInactiveLink )
604 pInactiveLink->InvalidateManager();
605 pInactiveLink = xActiveLink;
606 xActiveLink.Clear();
607 return bSuccess;
609 return TRUE;
612 BOOL SingleCommunicationManager::IsLinkValid( CommunicationLink* pCL )
614 return &xActiveLink == pCL;
617 USHORT SingleCommunicationManager::GetCommunicationLinkCount()
619 return IsCommunicationRunning()?1:0;
622 CommunicationLinkRef SingleCommunicationManager::GetCommunicationLink( USHORT )
624 return xActiveLink;
627 void SingleCommunicationManager::CallConnectionOpened( CommunicationLink* pCL )
629 DBG_ASSERT( !xActiveLink.Is(), "Es ist bereits ein CommunicationLink aktiv");
630 if ( xActiveLink.Is() )
632 if ( pInactiveLink )
633 pInactiveLink->InvalidateManager();
634 pInactiveLink = xActiveLink;
635 xActiveLink->StopCommunication(); // Den alten Link brutal abwürgen
637 xActiveLink = pCL;
638 CommunicationManager::CallConnectionOpened( pCL );
641 void SingleCommunicationManager::CallConnectionClosed( CommunicationLink* pCL )
643 CommunicationManager::CallConnectionClosed( pCL );
645 DBG_ASSERT( pCL == xActiveLink, "SingleCommunicationManager::CallConnectionClosed mit fremdem Link");
646 if ( pInactiveLink )
647 pInactiveLink->InvalidateManager();
648 pInactiveLink = xActiveLink;
649 xActiveLink.Clear();
650 bIsCommunicationRunning = FALSE;
653 void SingleCommunicationManager::DestroyingLink( CommunicationLink *pCL )
655 pInactiveLink = NULL;
656 pCL->InvalidateManager();
660 SingleCommunicationManagerClientViaSocket::SingleCommunicationManagerClientViaSocket( ByteString aHost, ULONG nPort, BOOL bUseMultiChannel )
661 : SingleCommunicationManager( bUseMultiChannel )
662 , aHostToTalk( aHost )
663 , nPortToTalk( nPort )
668 SingleCommunicationManagerClientViaSocket::SingleCommunicationManagerClientViaSocket( BOOL bUseMultiChannel )
669 : SingleCommunicationManager( bUseMultiChannel )
670 , aHostToTalk()
671 , nPortToTalk( 0 )
676 BOOL CommonSocketFunctions::DoStartCommunication( CommunicationManager *pCM, ICommunicationManagerClient *pCMC, ByteString aHost, ULONG nPort )
678 NAMESPACE_VOS(OInetSocketAddr) Addr;
679 NAMESPACE_VOS(OConnectorSocket) *pConnSocket;
681 Addr.setAddr( rtl::OUString( UniString( aHost, RTL_TEXTENCODING_UTF8 ) ) );
682 Addr.setPort( nPort );
684 TimeValue aTV;
685 aTV.Seconds = 10; // Warte 10 Sekunden
686 aTV.Nanosec = 0;
689 pConnSocket = new NAMESPACE_VOS(OConnectorSocket)();
690 pConnSocket->setTcpNoDelay( 1 );
691 if ( pConnSocket->connect( Addr, &aTV ) == NAMESPACE_VOS(ISocketTypes::TResult_Ok) )
693 pConnSocket->setTcpNoDelay( 1 );
695 pCM->CallConnectionOpened( CreateCommunicationLink( pCM, pConnSocket ) );
696 return TRUE;
698 else
699 delete pConnSocket;
701 } while ( pCMC->RetryConnect() );
703 return FALSE;