1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: packethandler.cxx,v $
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"
34 /*************************************************************************
37 * This file is intended to work inside and outside the StarOffice environment.
38 * Only adaption of file commtypes.hxx should be necessary. Else it is a bug!
40 ************************************************************************/
42 #include "packethandler.hxx"
43 #include <automation/commtypes.hxx>
44 #include <automation/commdefines.hxx>
45 #include "communiio.hxx"
48 Forces switch to multichannel headers even for old communication Method
50 #define FORCE_MULTI_CHANNEL_HEADERS
53 PacketHandler::PacketHandler( ITransmiter
* pTransmitter_
, IReceiver
* pReceiver_
, comm_BOOL bMC
)
54 : pTransmitter( pTransmitter_
)
55 , pReceiver( pReceiver_
)
56 , bMultiChannel( bMC
)
60 unsigned char PacketHandler::CalcCheckByte( comm_UINT32 nBytes
)
63 nRes
+= HIBYTE( HIWORD( nBytes
) ) ^ 0xf0;
64 nRes
+= LOBYTE( HIWORD( nBytes
) ) ^ 0x0f;
65 nRes
+= HIBYTE( LOWORD( nBytes
) ) ^ 0xf0;
66 nRes
+= LOBYTE( LOWORD( nBytes
) ) ^ 0x0f;
68 nRes
^= HIBYTE( nRes
);
70 return LOBYTE( nRes
);
74 #define READ_SOCKET( pBuffer, nLength )\
77 bWasError |= pReceiver->ReceiveBytes( pBuffer, nLength ) != C_ERROR_NONE;\
80 #define READ_SOCKET_LEN( pBuffer, nLength, nTotal )\
81 READ_SOCKET( pBuffer, nLength );\
85 comm_BOOL
PacketHandler::ReceiveData( void* &pData
, comm_UINT32
&nLen
)
87 DBG_ASSERT( !pData
, "pData should be NULL -> memory leak" );
91 comm_BOOL bWasError
= FALSE
;
92 comm_BOOL bForceMultiChannelThisPacket
= FALSE
;
95 comm_UINT32 nBytes
= 0;
96 nReceiveProtocol
= CM_PROTOCOL_OLDSTYLE
;
97 nReceiveHeaderType
= CH_NoHeader
;
99 READ_SOCKET( &nBytes
, sizeof(nBytes
) )
103 if ( 0xFFFFFFFF == nBytes
) // Expliziter Request für dieses Datenpaket auf MultiChannel umzuschalten
105 READ_SOCKET( &nBytes
, sizeof(nBytes
) )
108 bForceMultiChannelThisPacket
= TRUE
;
111 nBytes
= NETDWORD( nBytes
);
113 if ( bMultiChannel
|| bForceMultiChannelThisPacket
)
115 comm_ULONG nReadSoFar
= 0;
116 comm_ULONG nHeaderReadSoFar
= 0;
118 // Prüfbyte für Längenangabe
119 unsigned char nLenCheck
= 0;
120 READ_SOCKET_LEN( &nLenCheck
, 1, nReadSoFar
);
121 // Stimmt das Prüfbyte?
122 bWasError
|= nLenCheck
!= CalcCheckByte( nBytes
);
125 comm_UINT16 nHeaderBytes
;
126 READ_SOCKET_LEN( &nHeaderBytes
, 2, nReadSoFar
);
127 nHeaderBytes
= NETWORD( nHeaderBytes
);
128 // reicht der Header über das Ende hinaus?
129 bWasError
|= !(nBytes
>= nReadSoFar
+ nHeaderBytes
);
131 READ_SOCKET_LEN( &nReceiveHeaderType
, 2, nHeaderReadSoFar
);
132 nReceiveHeaderType
= NETWORD( nReceiveHeaderType
);
134 switch ( nReceiveHeaderType
)
136 case CH_SimpleMultiChannel
:
138 READ_SOCKET_LEN( &nReceiveProtocol
, 2, nHeaderReadSoFar
);
139 nReceiveProtocol
= NETWORD( nReceiveProtocol
);
148 DBG_ERROR("Unbekannter Headertyp in der Kommunikation");
157 /// Längen anpassen und ggf restheader überlesen.
158 while ( nHeaderBytes
> nHeaderReadSoFar
)
160 unsigned char nDummy
;
161 READ_SOCKET_LEN( &nDummy
, 1, nHeaderReadSoFar
);
164 nReadSoFar
+= nHeaderReadSoFar
;
165 nBytes
-= nReadSoFar
;
171 * 1) a 'void*' allocated via 'new char[]' is always deallocated
172 * via plain 'delete()', not via array 'delete[]()'; it's just
175 * 2) as the caller of this routine later-on changes ownership
176 * of 'pData' via 'SvMemoryStream::SetBuffer()' (in 'simplecm.cxx',
177 * 'SimpleCommunicationLinkViaSocket::DoReceiveDataStream()'),
178 * the allocator used here for 'void* pData' must match the
179 * deallocator used in 'SvMemoryStream::FreeMemory()', i.e.
180 * '::operator delete()'.
182 pData
= ::operator new(nBytes
);
183 READ_SOCKET( pData
, nBytes
)
186 ::operator delete(pData
), pData
= 0;
197 /*#define WRITE_SOCKET( pBuffer, nLength )\
199 bWasError |= !pStreamSocket || (pStreamSocket->write( pBuffer, nLength ) != nLength)*/
201 #define WRITE_SOCKET( pBuffer, nLength )\
203 {bWasError |= pTransmitter->TransferBytes( pBuffer, nLength ) != C_ERROR_NONE;}
207 comm_BOOL
PacketHandler::TransferData( const void* pData
, comm_UINT32 nLen
, CMProtocol nProtocol
)
209 comm_UINT32 nBuffer
= nLen
;
210 comm_BOOL bWasError
= FALSE
;
212 #ifndef FORCE_MULTI_CHANNEL_HEADERS
215 nBuffer
+= 1+2+2+2; // für einen CH_SimpleMultiChannel
217 #ifdef FORCE_MULTI_CHANNEL_HEADERS
218 if ( !bMultiChannel
)
221 n32
= 0xffffffff; // Umschalten auf MultiChannel
222 n32
= NETDWORD( n32
);
223 WRITE_SOCKET( &n32
, 4 );
228 comm_UINT32 nNetworkBuffer
= NETDWORD( nBuffer
);
229 WRITE_SOCKET( &nNetworkBuffer
, sizeof(nNetworkBuffer
) );
232 #ifndef FORCE_MULTI_CHANNEL_HEADERS
239 c
= CalcCheckByte( nBuffer
);
240 WRITE_SOCKET( &c
, 1 );
242 n16
= 4; // Länge des Headers für einen CH_SimpleMultiChannel
243 n16
= NETWORD( n16
);
244 WRITE_SOCKET( &n16
, 2 );
246 n16
= CH_SimpleMultiChannel
; // Typ des Headers
247 n16
= NETWORD( n16
);
248 WRITE_SOCKET( &n16
, 2 );
250 nProtocol
= NETWORD( nProtocol
);
251 WRITE_SOCKET( &nProtocol
, 2 );
254 WRITE_SOCKET( pData
, nLen
);
258 comm_BOOL
PacketHandler::SendHandshake( HandshakeType aHandshakeType
, const void* pData
, comm_UINT32 nLen
)
260 comm_BOOL bWasError
= FALSE
;
262 comm_UINT32 nBuffer
= 0;
264 // if ( pMyManager->IsMultiChannel() ) Wir senden immer FFFFFFFF vorweg -> immer MultiChannel (Oder GPF bei älteren)
265 nBuffer
+= 1+2+2; // für einen CH_Handshake
267 nBuffer
+= 2; // für den Typ des Handshakes
269 switch ( aHandshakeType
)
271 case CH_REQUEST_HandshakeAlive
:
272 nBuffer
+= 0; // Keine extra Daten
274 case CH_RESPONSE_HandshakeAlive
:
275 nBuffer
+= 0; // Keine extra Daten
277 case CH_REQUEST_ShutdownLink
:
278 nBuffer
+= 0; // Keine extra Daten
280 case CH_ShutdownLink
:
281 nBuffer
+= 0; // Keine extra Daten
283 case CH_SUPPORT_OPTIONS
:
284 nBuffer
+= 2 ; // one word extradata for options
286 case CH_SetApplication
:
287 nBuffer
+= 0 ; // one word extradata for options
290 DBG_ERROR("Unknown HandshakeType");
294 nBuffer
+= nLen
; // Extra data in Buffer
297 n32
= 0xffffffff; // Umschalten auf MultiChannel
298 n32
= NETDWORD( n32
);
299 WRITE_SOCKET( &n32
, 4 );
301 comm_UINT32 nNetworkBuffer
= NETDWORD( nBuffer
);
302 WRITE_SOCKET( &nNetworkBuffer
, sizeof(nNetworkBuffer
) );
308 c
= CalcCheckByte( nBuffer
);
309 WRITE_SOCKET( &c
, 1 );
311 n16
= 2; // Länge des Headers für einen CH_Handshake
312 n16
= NETWORD( n16
);
313 WRITE_SOCKET( &n16
, 2 );
315 n16
= CH_Handshake
; // Typ des Headers
316 n16
= NETWORD( n16
);
317 WRITE_SOCKET( &n16
, 2 );
319 n16
= aHandshakeType
; // Typ des Handshakes
320 n16
= NETWORD( n16
);
321 WRITE_SOCKET( &n16
, 2 );
324 switch ( aHandshakeType
)
326 case CH_SUPPORT_OPTIONS
:
327 n16
= OPT_USE_SHUTDOWN_PROTOCOL
;
328 n16
= NETWORD( n16
);
329 WRITE_SOCKET( &n16
, 2 );
334 WRITE_SOCKET( pData
, nLen
);