diff options
Diffstat (limited to 'automation/source/simplecm')
-rw-r--r-- | automation/source/simplecm/communiio.hxx | 65 | ||||
-rw-r--r-- | automation/source/simplecm/makefile.mk | 46 | ||||
-rw-r--r-- | automation/source/simplecm/packethandler.cxx | 334 | ||||
-rw-r--r-- | automation/source/simplecm/packethandler.hxx | 69 | ||||
-rw-r--r-- | automation/source/simplecm/simplecm.cxx | 702 | ||||
-rw-r--r-- | automation/source/simplecm/tcpio.cxx | 71 | ||||
-rw-r--r-- | automation/source/simplecm/tcpio.hxx | 61 |
7 files changed, 1348 insertions, 0 deletions
diff --git a/automation/source/simplecm/communiio.hxx b/automation/source/simplecm/communiio.hxx new file mode 100644 index 000000000000..5431c9d49621 --- /dev/null +++ b/automation/source/simplecm/communiio.hxx @@ -0,0 +1,65 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/************************************************************************* + * + * ATTENTION + * This file is intended to work inside and outside the StarOffice environment. + * Only adaption of file commtypes.hxx should be necessary. Else it is a bug! + * + ************************************************************************/ + +#include <automation/commtypes.hxx> + +#define C_ERROR_NONE 0x0001 +#define C_ERROR_PERMANENT 0x0002 +#define C_ERROR_RETRY 0x0003 +#define C_ERROR_TIMEOUT 0x0004 + +class ITransmiter +{ +protected: + comm_ULONG nLastSent; +public: + ITransmiter() :nLastSent( 0 ){} + virtual ~ITransmiter() {} + virtual comm_USHORT TransferBytes( const void* pBuffer, comm_UINT32 nLen ) = 0; + + comm_ULONG GetLastSent() { return nLastSent; } +}; + +class IReceiver +{ +protected: + comm_ULONG nLastReceived; +public: + IReceiver() :nLastReceived( 0 ){} + virtual ~IReceiver() {;} + virtual comm_USHORT ReceiveBytes( void* pBuffer, comm_UINT32 nLen ) = 0; + + comm_ULONG GetLastReceived() { return nLastReceived; } +}; diff --git a/automation/source/simplecm/makefile.mk b/automation/source/simplecm/makefile.mk new file mode 100644 index 000000000000..b6318ab4fd46 --- /dev/null +++ b/automation/source/simplecm/makefile.mk @@ -0,0 +1,46 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=automation +TARGET=simplecm + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/tcpio.obj \ + $(SLO)$/packethandler.obj \ + $(SLO)$/simplecm.obj \ + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/automation/source/simplecm/packethandler.cxx b/automation/source/simplecm/packethandler.cxx new file mode 100644 index 000000000000..91f787fbff2f --- /dev/null +++ b/automation/source/simplecm/packethandler.cxx @@ -0,0 +1,334 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_automation.hxx" + +/************************************************************************* + * + * ATTENTION + * This file is intended to work inside and outside the StarOffice environment. + * Only adaption of file commtypes.hxx should be necessary. Else it is a bug! + * + ************************************************************************/ + +#include "packethandler.hxx" +#include <automation/commtypes.hxx> +#include <automation/commdefines.hxx> +#include "communiio.hxx" + +/** +Forces switch to multichannel headers even for old communication Method +**/ +#define FORCE_MULTI_CHANNEL_HEADERS + + +PacketHandler::PacketHandler( ITransmiter* pTransmitter_, IReceiver* pReceiver_, comm_BOOL bMC ) +: pTransmitter( pTransmitter_ ) +, pReceiver( pReceiver_ ) +, bMultiChannel( bMC ) +{ +} + +unsigned char PacketHandler::CalcCheckByte( comm_UINT32 nBytes ) +{ + comm_UINT16 nRes = 0; + nRes += HIBYTE( HIWORD( nBytes ) ) ^ 0xf0; + nRes += LOBYTE( HIWORD( nBytes ) ) ^ 0x0f; + nRes += HIBYTE( LOWORD( nBytes ) ) ^ 0xf0; + nRes += LOBYTE( LOWORD( nBytes ) ) ^ 0x0f; + + nRes ^= HIBYTE( nRes ); + + return LOBYTE( nRes ); +} + + +#define READ_SOCKET( pBuffer, nLength )\ + if ( !bWasError )\ + {\ + bWasError |= pReceiver->ReceiveBytes( pBuffer, nLength ) != C_ERROR_NONE;\ + } + +#define READ_SOCKET_LEN( pBuffer, nLength, nTotal )\ + READ_SOCKET( pBuffer, nLength );\ + if ( !bWasError )\ + {nTotal += nLength;} + +comm_BOOL PacketHandler::ReceiveData( void* &pData, comm_UINT32 &nLen ) +{ + DBG_ASSERT( !pData, "pData should be NULL -> memory leak" ); + + nLen = 0; + pData = NULL; + comm_BOOL bWasError = FALSE; + comm_BOOL bForceMultiChannelThisPacket = FALSE; + if ( pReceiver ) + { + comm_UINT32 nBytes = 0; + nReceiveProtocol = CM_PROTOCOL_OLDSTYLE; + nReceiveHeaderType = CH_NoHeader; + + READ_SOCKET( &nBytes, sizeof(nBytes) ) + if ( bWasError ) + return FALSE; + + if ( 0xFFFFFFFF == nBytes ) // Expliziter Request für dieses Datenpaket auf MultiChannel umzuschalten + { + READ_SOCKET( &nBytes, sizeof(nBytes) ) + if ( bWasError ) + return FALSE; + bForceMultiChannelThisPacket = TRUE; + } + + nBytes = NETDWORD( nBytes ); + + if ( bMultiChannel || bForceMultiChannelThisPacket ) + { + comm_ULONG nReadSoFar = 0; + comm_ULONG nHeaderReadSoFar = 0; + + // Prüfbyte für Längenangabe + unsigned char nLenCheck = 0; + READ_SOCKET_LEN( &nLenCheck, 1, nReadSoFar ); + // Stimmt das Prüfbyte? + bWasError |= nLenCheck != CalcCheckByte( nBytes ); + + + comm_UINT16 nHeaderBytes; + READ_SOCKET_LEN( &nHeaderBytes, 2, nReadSoFar ); + nHeaderBytes = NETWORD( nHeaderBytes ); + // reicht der Header über das Ende hinaus? + bWasError |= !(nBytes >= nReadSoFar + nHeaderBytes); + + READ_SOCKET_LEN( &nReceiveHeaderType, 2, nHeaderReadSoFar ); + nReceiveHeaderType = NETWORD( nReceiveHeaderType ); + + switch ( nReceiveHeaderType ) + { + case CH_SimpleMultiChannel: + { + READ_SOCKET_LEN( &nReceiveProtocol, 2, nHeaderReadSoFar ); + nReceiveProtocol = NETWORD( nReceiveProtocol ); + } + break; + case CH_Handshake: + { + } + break; + default: + { + DBG_ERROR("Unbekannter Headertyp in der Kommunikation"); + bWasError = TRUE; + } + + } + + if ( bWasError ) + return FALSE; + + /// Längen anpassen und ggf restheader überlesen. + while ( nHeaderBytes > nHeaderReadSoFar ) + { + unsigned char nDummy; + READ_SOCKET_LEN( &nDummy, 1, nHeaderReadSoFar ); + } + + nReadSoFar += nHeaderReadSoFar; + nBytes -= nReadSoFar; + + } + + /* @@@ Notes @@@ + * + * 1) a 'void*' allocated via 'new char[]' is always deallocated + * via plain 'delete()', not via array 'delete[]()'; it's just + * raw memory. + * + * 2) as the caller of this routine later-on changes ownership + * of 'pData' via 'SvMemoryStream::SetBuffer()' (in 'simplecm.cxx', + * 'SimpleCommunicationLinkViaSocket::DoReceiveDataStream()'), + * the allocator used here for 'void* pData' must match the + * deallocator used in 'SvMemoryStream::FreeMemory()', i.e. + * '::operator delete()'. + */ + pData = ::operator new(nBytes); + READ_SOCKET( pData, nBytes ) + if ( bWasError ) + { + ::operator delete(pData), pData = 0; + return FALSE; + } + nLen = nBytes; + } + else + bWasError = TRUE; + + return !bWasError; +} + +/*#define WRITE_SOCKET( pBuffer, nLength )\ + if ( !bWasError )\ + bWasError |= !pStreamSocket || (pStreamSocket->write( pBuffer, nLength ) != nLength)*/ + +#define WRITE_SOCKET( pBuffer, nLength )\ + if ( !bWasError )\ + {bWasError |= pTransmitter->TransferBytes( pBuffer, nLength ) != C_ERROR_NONE;} + + + +comm_BOOL PacketHandler::TransferData( const void* pData, comm_UINT32 nLen, CMProtocol nProtocol ) +{ + comm_UINT32 nBuffer = nLen; + comm_BOOL bWasError = FALSE; + +#ifndef FORCE_MULTI_CHANNEL_HEADERS + if ( bMultiChannel ) +#endif + nBuffer += 1+2+2+2; // für einen CH_SimpleMultiChannel + +#ifdef FORCE_MULTI_CHANNEL_HEADERS + if ( !bMultiChannel ) + { + comm_UINT32 n32; + n32 = 0xffffffff; // Umschalten auf MultiChannel + n32 = NETDWORD( n32 ); + WRITE_SOCKET( &n32, 4 ); + } +#endif + + + comm_UINT32 nNetworkBuffer = NETDWORD( nBuffer ); + WRITE_SOCKET( &nNetworkBuffer, sizeof(nNetworkBuffer) ); + + +#ifndef FORCE_MULTI_CHANNEL_HEADERS + if ( bMultiChannel ) +#endif + { + comm_UINT16 n16; + unsigned char c; + + c = CalcCheckByte( nBuffer ); + WRITE_SOCKET( &c, 1 ); + + n16 = 4; // Länge des Headers für einen CH_SimpleMultiChannel + n16 = NETWORD( n16 ); + WRITE_SOCKET( &n16, 2 ); + + n16 = CH_SimpleMultiChannel; // Typ des Headers + n16 = NETWORD( n16 ); + WRITE_SOCKET( &n16, 2 ); + + nProtocol = NETWORD( nProtocol ); + WRITE_SOCKET( &nProtocol, 2 ); + } + + WRITE_SOCKET( pData, nLen ); + return !bWasError; +} + +comm_BOOL PacketHandler::SendHandshake( HandshakeType aHandshakeType, const void* pData, comm_UINT32 nLen ) +{ + comm_BOOL bWasError = FALSE; + + comm_UINT32 nBuffer = 0; + +// if ( pMyManager->IsMultiChannel() ) Wir senden immer FFFFFFFF vorweg -> immer MultiChannel (Oder GPF bei älteren) + nBuffer += 1+2+2; // für einen CH_Handshake + + nBuffer += 2; // für den Typ des Handshakes + + switch ( aHandshakeType ) + { + case CH_REQUEST_HandshakeAlive: + nBuffer += 0; // Keine extra Daten + break; + case CH_RESPONSE_HandshakeAlive: + nBuffer += 0; // Keine extra Daten + break; + case CH_REQUEST_ShutdownLink: + nBuffer += 0; // Keine extra Daten + break; + case CH_ShutdownLink: + nBuffer += 0; // Keine extra Daten + break; + case CH_SUPPORT_OPTIONS: + nBuffer += 2 ; // one word extradata for options + break; + case CH_SetApplication: + nBuffer += 0 ; // one word extradata for options + break; + default: + DBG_ERROR("Unknown HandshakeType"); + } + + if ( pData ) + nBuffer += nLen; // Extra data in Buffer + + comm_UINT32 n32; + n32 = 0xffffffff; // Umschalten auf MultiChannel + n32 = NETDWORD( n32 ); + WRITE_SOCKET( &n32, 4 ); + + comm_UINT32 nNetworkBuffer = NETDWORD( nBuffer ); + WRITE_SOCKET( &nNetworkBuffer, sizeof(nNetworkBuffer) ); + + + comm_UINT16 n16; + unsigned char c; + + c = CalcCheckByte( nBuffer ); + WRITE_SOCKET( &c, 1 ); + + n16 = 2; // Länge des Headers für einen CH_Handshake + n16 = NETWORD( n16 ); + WRITE_SOCKET( &n16, 2 ); + + n16 = CH_Handshake; // Typ des Headers + n16 = NETWORD( n16 ); + WRITE_SOCKET( &n16, 2 ); + + n16 = aHandshakeType; // Typ des Handshakes + n16 = NETWORD( n16 ); + WRITE_SOCKET( &n16, 2 ); + + + switch ( aHandshakeType ) + { + case CH_SUPPORT_OPTIONS: + n16 = OPT_USE_SHUTDOWN_PROTOCOL; + n16 = NETWORD( n16 ); + WRITE_SOCKET( &n16, 2 ); + break; + } + + if ( pData ) + WRITE_SOCKET( pData, nLen ); + + return !bWasError; +} diff --git a/automation/source/simplecm/packethandler.hxx b/automation/source/simplecm/packethandler.hxx new file mode 100644 index 000000000000..ce0c22c100c9 --- /dev/null +++ b/automation/source/simplecm/packethandler.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/************************************************************************* + * + * ATTENTION + * This file is intended to work inside and outside the StarOffice environment. + * Only adaption of file commtypes.hxx should be necessary. Else it is a bug! + * + ************************************************************************/ + +#ifndef _TOOLS_PACKETHANDLER_HXX_ +#define _TOOLS_PACKETHANDLER_HXX_ + +#include <automation/commtypes.hxx> +#include <automation/commdefines.hxx> + +class ITransmiter; +class IReceiver; + +class PacketHandler +{ +private: + unsigned char CalcCheckByte( comm_UINT32 nBytes ); + ITransmiter* pTransmitter; + IReceiver* pReceiver; + + comm_BOOL bMultiChannel; + +protected: + comm_UINT16 nReceiveProtocol; + comm_UINT16 nReceiveHeaderType; + +public: + PacketHandler( ITransmiter* pTransmitter_, IReceiver* pReceiver_, comm_BOOL bMC = FALSE ); + + comm_UINT16 GetReceiveProtocol() { return nReceiveProtocol; } + comm_UINT16 GetReceiveHeaderType() { return nReceiveHeaderType; } + + comm_BOOL ReceiveData( void* &pData, comm_UINT32 &nLen ); /// Recieve DataPacket from Socket + virtual comm_BOOL SendHandshake( HandshakeType aHandshakeType, const void* pData = NULL, comm_UINT32 nLen = 0 ); + virtual comm_BOOL TransferData( const void* pData, comm_UINT32 nLen, CMProtocol nProtocol = CM_PROTOCOL_OLDSTYLE ); +}; + +#endif diff --git a/automation/source/simplecm/simplecm.cxx b/automation/source/simplecm/simplecm.cxx new file mode 100644 index 000000000000..92642e8cd7c5 --- /dev/null +++ b/automation/source/simplecm/simplecm.cxx @@ -0,0 +1,702 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_automation.hxx" + + +#define ENABLE_BYTESTRING_STREAM_OPERATORS +#include <tools/solar.h> +#include <automation/simplecm.hxx> + +#include <automation/commdefines.hxx> +#include "packethandler.hxx" +#include "tcpio.hxx" + +#if OSL_DEBUG_LEVEL > 1 +#include <stdio.h> +void debug_printf( const char *chars ) +{ + static BOOL bPrint = (getenv("DEBUG") != NULL); + if ( bPrint ) + { + printf( chars ); + fflush( stdout ); + } +} +#endif + +CommunicationLink::CommunicationLink( CommunicationManager *pMan ) +: pMyManager(pMan) +, pServiceData(NULL) +, nServiceProtocol( 0 ) +, bIsInsideCallback( FALSE ) +, nTotalBytes( 0 ) +, maApplication("Undefined") +#if OSL_DEBUG_LEVEL > 1 +, bFlag( FALSE ) +, nSomething( 0 ) +#endif +{ +} + +CommunicationLink::~CommunicationLink() +{ +#if OSL_DEBUG_LEVEL > 1 + if ( !bFlag ) // bFlag will be set if deletion is expected else we can set a breakpoint + bFlag = FALSE; +#endif + if ( pMyManager ) + pMyManager->DestroyingLink( this ); +} + +void CommunicationLink::CallInfoMsg( InfoString aMsg ) +{ + if ( pMyManager ) + pMyManager->InfoMsg( aMsg ); +}; + +CM_InfoType CommunicationLink::GetInfoType() +{ + if ( pMyManager ) + return pMyManager->GetInfoType(); + else + return CM_NO_TEXT; +} + +IMPL_LINK( CommunicationLink, ConnectionClosed, void*, EMPTYARG ) +{ + if ( pMyManager ) + pMyManager->CallConnectionClosed( this ); + return 1; +} + +IMPL_LINK( CommunicationLink, DataReceived, void*, EMPTYARG ) +{ + if ( pMyManager ) + pMyManager->CallDataReceived( this ); + return 1; +} + +BOOL CommunicationLink::DoTransferDataStream( SvStream *pDataStream, CMProtocol nProtocol ) +{ + INFO_MSG( CByteString("S :").Append( GetCommunicationPartner( CM_FQDN ) ), + CByteString("Daten Senden:").Append( GetCommunicationPartner( CM_FQDN ) ), + CM_SEND, this ); + BOOL bWasError = FALSE; + + UINT32 nBuffer; + nBuffer = pDataStream->SeekRel(0) +1; + bWasError = pPacketHandler->TransferData( ((SvMemoryStream*)pDataStream)->GetData(), nBuffer, nProtocol ) != C_ERROR_NONE; + + if ( bWasError ) + { + INFO_MSG( CByteString("Send Failed:").Append( GetCommunicationPartner( CM_FQDN ) ), + CByteString( "Socket wird wegen Fehlers beim Senden geschlossen: ").Append( GetCommunicationPartner( CM_FQDN ) ), + CM_ERROR, this ); + ShutdownCommunication(); + } + return !bWasError; +} + +BOOL CommunicationLink::TransferDataStream( SvStream *pDataStream, CMProtocol nProtocol ) +{ + aLastAccess = DateTime(); + nTotalBytes += pDataStream->Seek( STREAM_SEEK_TO_END ); + return DoTransferDataStream( pDataStream, nProtocol ); +} + +void CommunicationLink::SetApplication( const ByteString& aApp ) +{ + maApplication = aApp; +} + + +SimpleCommunicationLinkViaSocket::SimpleCommunicationLinkViaSocket( CommunicationManager *pMan, NAMESPACE_VOS(OStreamSocket) *pSocket ) +: CommunicationLink( pMan ) +, aCommunicationPartner() +, aMyName() +, pStreamSocket( pSocket ) +, pReceiveStream( NULL ) +, bIsRequestShutdownPending( FALSE ) +{ + pTCPIO = new TCPIO( pStreamSocket ); + pPacketHandler = new PacketHandler( (ITransmiter*) pTCPIO, pTCPIO, pMyManager->IsMultiChannel() ); +} + +SimpleCommunicationLinkViaSocket::~SimpleCommunicationLinkViaSocket() +{ + delete pPacketHandler; + pPacketHandler = NULL; + delete pTCPIO; + pTCPIO = NULL; + delete pStreamSocket; + pStreamSocket = NULL; +} + +void SimpleCommunicationLinkViaSocket::SetStreamSocket( NAMESPACE_VOS(OStreamSocket)* pSocket ) +{ + if ( pTCPIO ) + pTCPIO->SetStreamSocket( pSocket ); + pStreamSocket = pSocket; +} + +BOOL SimpleCommunicationLinkViaSocket::StopCommunication() +{ + CommunicationLinkRef rHold(this); // avoid deleting this link before the end of the method + if ( !IsCommunicationError() ) // Meaning that the Communication is still runnung + { +#if OSL_DEBUG_LEVEL > 1 + debug_printf("Sending REQUEST_ShutdownLink\n"); +#endif + SendHandshake( CH_REQUEST_ShutdownLink ); + } + WaitForShutdown(); + return TRUE; +} + +void SimpleCommunicationLinkViaSocket::SetFinalRecieveTimeout() +{ + if ( !IsCommunicationError() ) + { + TimeValue aTime = {30, 0}; // 30 seconds + pStreamSocket->setRecvTimeout( &aTime ); + } +} + +BOOL SimpleCommunicationLinkViaSocket::IsCommunicationError() +{ + return !pStreamSocket; +} + +ByteString SimpleCommunicationLinkViaSocket::GetCommunicationPartner( CM_NameType eType ) +{ + if ( pStreamSocket ) + { + switch ( eType ) + { + case CM_DOTTED: + { + rtl::OUString aDotted; + NAMESPACE_VOS(OSocketAddr) *pPeerAdr = new NAMESPACE_VOS(OSocketAddr); + pStreamSocket->getPeerAddr( *pPeerAdr ); + ((NAMESPACE_VOS(OInetSocketAddr*))pPeerAdr)->getDottedAddr( aDotted ); + delete pPeerAdr; + return ByteString( UniString(aDotted), RTL_TEXTENCODING_UTF8 ); + } + //break; + case CM_FQDN: + { + if ( !aCommunicationPartner.Len() ) + { + rtl::OUString aFQDN; + pStreamSocket->getPeerHost( aFQDN ); + aCommunicationPartner = ByteString( UniString(aFQDN), RTL_TEXTENCODING_UTF8 ); + } + return aCommunicationPartner; + } + //break; + } + } + return CByteString( "Unknown" ); +} + +ByteString SimpleCommunicationLinkViaSocket::GetMyName( CM_NameType eType ) +{ + if ( pStreamSocket ) + { + switch ( eType ) + { + case CM_DOTTED: + { + rtl::OUString aDotted; + NAMESPACE_VOS(OSocketAddr) *pPeerAdr = new NAMESPACE_VOS(OSocketAddr); + pStreamSocket->getLocalAddr( *pPeerAdr ); + ((NAMESPACE_VOS(OInetSocketAddr*))pPeerAdr)->getDottedAddr( aDotted ); + delete pPeerAdr; + return ByteString( UniString(aDotted), RTL_TEXTENCODING_UTF8 ); + } + //break; + case CM_FQDN: + { + if ( !aMyName.Len() ) + { + rtl::OUString aFQDN; + pStreamSocket->getLocalHost( aFQDN ); + aMyName = ByteString( UniString(aFQDN), RTL_TEXTENCODING_UTF8 ); + } + return aMyName; + } + //break; + } + } + return CByteString( "Error" ); +} + +SvStream* SimpleCommunicationLinkViaSocket::GetBestCommunicationStream() +{ + SvStream* pStream = new SvMemoryStream; +// pStream->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN ); + return pStream; +} + +#define READ_SOCKET( pBuffer, nLength )\ + if ( !bWasError )\ + {bWasError |= pTCPIO->ReceiveBytes( pBuffer, nLength ) != C_ERROR_NONE;} + +#define READ_SOCKET_LEN( pBuffer, nLength, nTotal )\ + READ_SOCKET( pBuffer, nLength );\ + if ( !bWasError )\ + {nTotal += nLength;} + +BOOL SimpleCommunicationLinkViaSocket::DoReceiveDataStream() +{ + BOOL bWasError = FALSE; + void* pBuffer = NULL; + comm_UINT32 nLen; + bWasError = pPacketHandler->ReceiveData( pBuffer, nLen ) != C_ERROR_NONE; + if ( !bWasError ) + { + pReceiveStream = GetBestCommunicationStream(); + DBG_ASSERT( pReceiveStream->IsA() == ID_MEMORYSTREAM, "CommunicationStream is not an SvMemoryStream. Communication has to be reimplemented here!"); + if ( pReceiveStream->IsA() == ID_MEMORYSTREAM ) + ((SvMemoryStream*)pReceiveStream)->SetBuffer( pBuffer, nLen, TRUE, nLen ); + DBG_ASSERT( pReceiveStream, "Datastream is NULL"); + } + + return !bWasError; +} + +void SimpleCommunicationLinkViaSocket::SetApplication( const ByteString& aApp ) +{ + CommunicationLink::SetApplication( aApp ); + SvStream* pData = GetBestCommunicationStream(); + *pData << aApp; + SendHandshake( CH_SetApplication, pData ); + delete pData; +} + +void SimpleCommunicationLinkViaSocket::SetNewPacketAsCurrent() +{ + pServiceData = pReceiveStream; + nServiceProtocol = pPacketHandler->GetReceiveProtocol(); + nServiceHeaderType = pPacketHandler->GetReceiveHeaderType(); +} + +BOOL SimpleCommunicationLinkViaSocket::SendHandshake( HandshakeType aHandshakeType, SvStream* pData ) +{ + BOOL bWasError; + + if ( pData ) + { + UINT32 nBuffer; + nBuffer = pData->Seek( STREAM_SEEK_TO_END ); + bWasError = !pPacketHandler->SendHandshake( aHandshakeType, ((SvMemoryStream*)pData)->GetData(), nBuffer ); + } + else + bWasError = !pPacketHandler->SendHandshake( aHandshakeType ); + + + if ( bWasError ) + { + INFO_MSG( CByteString("Send Failed:").Append( GetCommunicationPartner( CM_FQDN ) ), + CByteString( "Socket wird wegen Fehlers beim Senden geschlossen: ").Append( GetCommunicationPartner( CM_FQDN ) ), + CM_ERROR, this ); + ShutdownCommunication(); + } + else + { // set new status + switch ( aHandshakeType ) + { + case CH_REQUEST_HandshakeAlive: + break; + case CH_RESPONSE_HandshakeAlive: + break; + case CH_REQUEST_ShutdownLink: + bIsRequestShutdownPending = TRUE; + break; + case CH_ShutdownLink: + break; + case CH_SUPPORT_OPTIONS: + break; + case CH_SetApplication: + break; + default: + DBG_ERROR("Unknown HandshakeType"); + } + } + return !bWasError; +} + +SimpleCommunicationLinkViaSocketWithReceiveCallbacks::SimpleCommunicationLinkViaSocketWithReceiveCallbacks( CommunicationManager *pMan, NAMESPACE_VOS(OStreamSocket) *pSocket ) +: SimpleCommunicationLinkViaSocket( pMan, pSocket ) +{ +} + +SimpleCommunicationLinkViaSocketWithReceiveCallbacks::~SimpleCommunicationLinkViaSocketWithReceiveCallbacks() +{ + if ( pMyManager && pMyManager->IsLinkValid( this ) && !bIsRequestShutdownPending ) + StopCommunication(); +} + +void SimpleCommunicationLinkViaSocketWithReceiveCallbacks::WaitForShutdown() +{ + CommunicationLinkRef rHold(this); // avoid deleting this link before the end of the method + SetFinalRecieveTimeout(); + while ( pMyManager && !IsCommunicationError() ) + ReceiveDataStream(); +} + +BOOL SimpleCommunicationLinkViaSocketWithReceiveCallbacks::ReceiveDataStream() +{ + if ( DoReceiveDataStream() ) + { + SetNewPacketAsCurrent(); + StartCallback(); + DataReceived(); + return TRUE; + } + else + { + StartCallback(); + ShutdownCommunication(); + return FALSE; + } +} + +BOOL SimpleCommunicationLinkViaSocketWithReceiveCallbacks::ShutdownCommunication() +{ + if ( GetStreamSocket() ) + GetStreamSocket()->shutdown(); + + if ( GetStreamSocket() ) + GetStreamSocket()->close(); + + NAMESPACE_VOS(OStreamSocket) *pTempSocket = GetStreamSocket(); + SetStreamSocket( NULL ); + delete pTempSocket; + + ConnectionClosed(); + + return TRUE; +} + + + +CommunicationManager::CommunicationManager( BOOL bUseMultiChannel ) +: nInfoType( CM_NONE ) +, bIsCommunicationRunning( FALSE ) +, maApplication("Unknown") +, bIsMultiChannel( bUseMultiChannel ) +{ +} + +CommunicationManager::~CommunicationManager() +{ + xLastNewLink.Clear(); +} + +BOOL CommunicationManager::StartCommunication( String aApp, String aParams ) +{ + (void) aApp; /* avoid warning about unused parameter */ + (void) aParams; /* avoid warning about unused parameter */ + return FALSE; +} + +BOOL CommunicationManager::StartCommunication( ByteString aHost, ULONG nPort ) +{ + (void) aHost; /* avoid warning about unused parameter */ + (void) nPort; /* avoid warning about unused parameter */ + return FALSE; +} + +ByteString CommunicationManager::GetMyName( CM_NameType ) +{ + rtl::OUString aHostname; + NAMESPACE_VOS(OSocketAddr)::getLocalHostname( aHostname ); + return ByteString( UniString(aHostname), RTL_TEXTENCODING_UTF8 ); +} + +void CommunicationManager::CallConnectionOpened( CommunicationLink* pCL ) +{ + pCL->StartCallback(); // Sollte bereits vor dem Aufruf gerufen werden + pCL->aStart = DateTime(); + pCL->aLastAccess = pCL->aStart; + bIsCommunicationRunning = TRUE; + pCL->SetApplication( GetApplication() ); + + xLastNewLink = pCL; + + INFO_MSG( CByteString("C+:").Append( pCL->GetCommunicationPartner( CM_FQDN ) ), + CByteString("Verbindung aufgebaut: ").Append( pCL->GetCommunicationPartner( CM_FQDN ) ), + CM_OPEN, pCL ); + ConnectionOpened( pCL ); + pCL->FinishCallback(); +} + +void CommunicationManager::CallConnectionClosed( CommunicationLink* pCL ) +{ + pCL->StartCallback(); // Sollte bereits vor dem Aufruf gerufen werden + pCL->aLastAccess = DateTime(); + + INFO_MSG( CByteString("C-:").Append( pCL->GetCommunicationPartner( CM_FQDN ) ), + CByteString("Verbindung abgebrochen: ").Append( pCL->GetCommunicationPartner( CM_FQDN ) ), + CM_CLOSE, pCL ); + ConnectionClosed( pCL ); + + if ( xLastNewLink == pCL ) + xLastNewLink.Clear(); + + pCL->FinishCallback(); +// delete pCL; +} + +void CommunicationManager::CallDataReceived( CommunicationLink* pCL ) +{ + pCL->StartCallback(); // Sollte bereits vor dem Aufruf gerufen werden + pCL->aLastAccess = DateTime(); + CommunicationLinkRef rHold(pCL); // Hält den Zeiger bis zum Ende des calls + + // should be impossible but happens for mysterious reasons + if ( !pCL->pServiceData ) + { + DBG_ERROR( "Datastream is NULL" ); + pCL->FinishCallback(); + return; + } + + + if ( CH_Handshake == pCL->nServiceHeaderType ) + { + SvStream *pData = pCL->GetServiceData(); + USHORT nType; + pData->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN ); // Unfortulately it is written this way :(( + *pData >> nType; + pData->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); + switch ( nType ) + { + case CH_REQUEST_HandshakeAlive: + { + pCL->SendHandshake( CH_RESPONSE_HandshakeAlive ); + } + break; + case CH_REQUEST_ShutdownLink: + { +#if OSL_DEBUG_LEVEL > 1 + debug_printf("Sending ShutdownLink\n"); +#endif + pCL->SendHandshake( CH_ShutdownLink ); + } + break; + case CH_ShutdownLink: + { +#if OSL_DEBUG_LEVEL > 1 + debug_printf("Executing ShutdownLink\n"); +#endif + pCL->ShutdownCommunication(); + } + break; + case CH_SetApplication: + { + ByteString aApplication; + *pData >> aApplication; + pCL->CommunicationLink::SetApplication( aApplication ); +#if OSL_DEBUG_LEVEL > 1 + debug_printf( "Setting Application to " ); + debug_printf( aApplication.GetBuffer() ); + debug_printf( "\n" ); +#endif + } + break; + +#if OSL_DEBUG_LEVEL > 1 + default: + { + debug_printf("Unknown Handshake received\n"); + } +#endif + } + delete pData; + } + else + { + if ( pCL->pServiceData ) + { + pCL->nTotalBytes += pCL->pServiceData->Seek( STREAM_SEEK_TO_END ); + pCL->pServiceData->Seek( STREAM_SEEK_TO_BEGIN ); + } + + INFO_MSG( CByteString("D :").Append( pCL->GetCommunicationPartner( CM_FQDN ) ), + CByteString("Daten Empfangen:").Append( pCL->GetCommunicationPartner( CM_FQDN ) ), + CM_RECEIVE, pCL ); + DataReceived( pCL ); + } + delete pCL->GetServiceData(); + pCL->FinishCallback(); +} + +void CommunicationManager::CallInfoMsg( InfoString aMsg ) +{ + // Hier wird es wohl kein Housekeeping geben + InfoMsg( aMsg ); +} + +void CommunicationManager::SetApplication( const ByteString& aApp, BOOL bRunningLinks ) +{ + maApplication = aApp; + if ( bRunningLinks ) + { + USHORT i; + for ( i = 0 ; i < GetCommunicationLinkCount() ; i++ ) + GetCommunicationLink( i )->SetApplication( aApp ); + } +} + + + +SingleCommunicationManager::SingleCommunicationManager( BOOL bUseMultiChannel ) +: CommunicationManager( bUseMultiChannel ) +{ + xActiveLink = NULL; + pInactiveLink = NULL; +} + +SingleCommunicationManager::~SingleCommunicationManager() +{ + StopCommunication(); + if ( pInactiveLink ) + pInactiveLink->InvalidateManager(); +} + +BOOL SingleCommunicationManager::StopCommunication() +{ + if ( xActiveLink.Is() ) + { + BOOL bSuccess = xActiveLink->StopCommunication(); + if ( pInactiveLink ) + pInactiveLink->InvalidateManager(); + pInactiveLink = xActiveLink; + xActiveLink.Clear(); + return bSuccess; + } + return TRUE; +} + +BOOL SingleCommunicationManager::IsLinkValid( CommunicationLink* pCL ) +{ + return &xActiveLink == pCL; +} + +USHORT SingleCommunicationManager::GetCommunicationLinkCount() +{ + return IsCommunicationRunning()?1:0; +} + +CommunicationLinkRef SingleCommunicationManager::GetCommunicationLink( USHORT ) +{ + return xActiveLink; +} + +void SingleCommunicationManager::CallConnectionOpened( CommunicationLink* pCL ) +{ + DBG_ASSERT( !xActiveLink.Is(), "Es ist bereits ein CommunicationLink aktiv"); + if ( xActiveLink.Is() ) + { + if ( pInactiveLink ) + pInactiveLink->InvalidateManager(); + pInactiveLink = xActiveLink; + xActiveLink->StopCommunication(); // Den alten Link brutal abwürgen + } + xActiveLink = pCL; + CommunicationManager::CallConnectionOpened( pCL ); +} + +void SingleCommunicationManager::CallConnectionClosed( CommunicationLink* pCL ) +{ + CommunicationManager::CallConnectionClosed( pCL ); + + DBG_ASSERT( pCL == xActiveLink, "SingleCommunicationManager::CallConnectionClosed mit fremdem Link"); + if ( pInactiveLink ) + pInactiveLink->InvalidateManager(); + pInactiveLink = xActiveLink; + xActiveLink.Clear(); + bIsCommunicationRunning = FALSE; +} + +void SingleCommunicationManager::DestroyingLink( CommunicationLink *pCL ) +{ + pInactiveLink = NULL; + pCL->InvalidateManager(); +} + + +SingleCommunicationManagerClientViaSocket::SingleCommunicationManagerClientViaSocket( ByteString aHost, ULONG nPort, BOOL bUseMultiChannel ) +: SingleCommunicationManager( bUseMultiChannel ) +, aHostToTalk( aHost ) +, nPortToTalk( nPort ) +{ +} + + +SingleCommunicationManagerClientViaSocket::SingleCommunicationManagerClientViaSocket( BOOL bUseMultiChannel ) +: SingleCommunicationManager( bUseMultiChannel ) +, aHostToTalk() +, nPortToTalk( 0 ) +{ +} + + +BOOL CommonSocketFunctions::DoStartCommunication( CommunicationManager *pCM, ICommunicationManagerClient *pCMC, ByteString aHost, ULONG nPort ) +{ + NAMESPACE_VOS(OInetSocketAddr) Addr; + NAMESPACE_VOS(OConnectorSocket) *pConnSocket; + + Addr.setAddr( rtl::OUString( UniString( aHost, RTL_TEXTENCODING_UTF8 ) ) ); + Addr.setPort( nPort ); + + TimeValue aTV; + aTV.Seconds = 10; // Warte 10 Sekunden + aTV.Nanosec = 0; + do + { + pConnSocket = new NAMESPACE_VOS(OConnectorSocket)(); + pConnSocket->setTcpNoDelay( 1 ); + if ( pConnSocket->connect( Addr, &aTV ) == NAMESPACE_VOS(ISocketTypes::TResult_Ok) ) + { + pConnSocket->setTcpNoDelay( 1 ); + + pCM->CallConnectionOpened( CreateCommunicationLink( pCM, pConnSocket ) ); + return TRUE; + } + else + delete pConnSocket; + + } while ( pCMC->RetryConnect() ); + + return FALSE; +} + diff --git a/automation/source/simplecm/tcpio.cxx b/automation/source/simplecm/tcpio.cxx new file mode 100644 index 000000000000..5498e3a69774 --- /dev/null +++ b/automation/source/simplecm/tcpio.cxx @@ -0,0 +1,71 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_automation.hxx" + +#include "tcpio.hxx" + +/// implement ITransmiter +comm_USHORT TCPIO::TransferBytes( const void* pBuffer, comm_UINT32 nLen ) +{ + vos::OGuard aGuard( aMSocketWriteAccess ); + if ( !pStreamSocket ) + { + nLastSent = 0; + return C_ERROR_PERMANENT; + } + nLastSent = pStreamSocket->write( pBuffer, nLen ); + if ( nLastSent == nLen ) + return C_ERROR_NONE; + return C_ERROR_PERMANENT; +} + + +/// implement IReceiver +comm_USHORT TCPIO::ReceiveBytes( void* pBuffer, comm_UINT32 nLen ) +{ + vos::OGuard aGuard( aMSocketReadAccess ); + if ( !pStreamSocket ) + { + nLastReceived = 0; + return C_ERROR_PERMANENT; + } + nLastReceived = pStreamSocket->read( pBuffer, nLen ); + if ( nLastReceived == nLen ) + return C_ERROR_NONE; + return C_ERROR_PERMANENT; +} + + +// helper +void TCPIO::SetStreamSocket( NAMESPACE_VOS(OStreamSocket) *pSocket ) +{ + vos::OGuard aRGuard( aMSocketReadAccess ); + vos::OGuard aWGuard( aMSocketWriteAccess ); + pStreamSocket = pSocket; +} diff --git a/automation/source/simplecm/tcpio.hxx b/automation/source/simplecm/tcpio.hxx new file mode 100644 index 000000000000..626f164ba0f5 --- /dev/null +++ b/automation/source/simplecm/tcpio.hxx @@ -0,0 +1,61 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef TCPIO_HXX +#define TCPIO_HXX + +#include <vos/socket.hxx> +#include <vos/mutex.hxx> + +#include "communiio.hxx" + +class TCPIO : public ITransmiter, public IReceiver +{ +private: + NAMESPACE_VOS(OStreamSocket) *pStreamSocket; + vos::OMutex aMSocketReadAccess; + vos::OMutex aMSocketWriteAccess; + +public: + + /// + TCPIO( NAMESPACE_VOS(OStreamSocket) *pSocket ):pStreamSocket( pSocket ){} + virtual ~TCPIO(){} + + + /// implement ITransmiter + virtual comm_USHORT TransferBytes( const void* pBuffer, comm_UINT32 nLen ); + + /// implement IReceiver + virtual comm_USHORT ReceiveBytes( void* pBuffer, comm_UINT32 nLen ); + + // helper + void SetStreamSocket( NAMESPACE_VOS(OStreamSocket) *pSocket ); + +}; + +#endif |