1*9d1279ecSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*9d1279ecSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*9d1279ecSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*9d1279ecSAndrew Rist  * distributed with this work for additional information
6*9d1279ecSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*9d1279ecSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*9d1279ecSAndrew Rist  * "License"); you may not use this file except in compliance
9*9d1279ecSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*9d1279ecSAndrew Rist  *
11*9d1279ecSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*9d1279ecSAndrew Rist  *
13*9d1279ecSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*9d1279ecSAndrew Rist  * software distributed under the License is distributed on an
15*9d1279ecSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9d1279ecSAndrew Rist  * KIND, either express or implied.  See the License for the
17*9d1279ecSAndrew Rist  * specific language governing permissions and limitations
18*9d1279ecSAndrew Rist  * under the License.
19*9d1279ecSAndrew Rist  *
20*9d1279ecSAndrew Rist  *************************************************************/
21*9d1279ecSAndrew Rist 
22*9d1279ecSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_automation.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir /*************************************************************************
28cdf0e10cSrcweir  *
29cdf0e10cSrcweir  *	  ATTENTION
30cdf0e10cSrcweir  *	  This file is intended to work inside and outside the StarOffice environment.
31cdf0e10cSrcweir  *	  Only adaption of file commtypes.hxx should be necessary. Else it is a bug!
32cdf0e10cSrcweir  *
33cdf0e10cSrcweir  ************************************************************************/
34cdf0e10cSrcweir 
35cdf0e10cSrcweir #include "packethandler.hxx"
36cdf0e10cSrcweir #include <automation/commtypes.hxx>
37cdf0e10cSrcweir #include <automation/commdefines.hxx>
38cdf0e10cSrcweir #include "communiio.hxx"
39cdf0e10cSrcweir 
40cdf0e10cSrcweir /**
41cdf0e10cSrcweir Forces switch to multichannel headers even for old communication Method
42cdf0e10cSrcweir **/
43cdf0e10cSrcweir #define FORCE_MULTI_CHANNEL_HEADERS
44cdf0e10cSrcweir 
45cdf0e10cSrcweir 
PacketHandler(ITransmiter * pTransmitter_,IReceiver * pReceiver_,comm_BOOL bMC)46cdf0e10cSrcweir PacketHandler::PacketHandler( ITransmiter* pTransmitter_, IReceiver* pReceiver_, comm_BOOL bMC )
47cdf0e10cSrcweir : pTransmitter( pTransmitter_ )
48cdf0e10cSrcweir , pReceiver( pReceiver_ )
49cdf0e10cSrcweir , bMultiChannel( bMC )
50cdf0e10cSrcweir {
51cdf0e10cSrcweir }
52cdf0e10cSrcweir 
CalcCheckByte(comm_UINT32 nBytes)53cdf0e10cSrcweir unsigned char PacketHandler::CalcCheckByte( comm_UINT32 nBytes )
54cdf0e10cSrcweir {
55cdf0e10cSrcweir 	comm_UINT16 nRes = 0;
56cdf0e10cSrcweir 	nRes += HIBYTE( HIWORD( nBytes ) ) ^ 0xf0;
57cdf0e10cSrcweir 	nRes += LOBYTE( HIWORD( nBytes ) ) ^ 0x0f;
58cdf0e10cSrcweir 	nRes += HIBYTE( LOWORD( nBytes ) ) ^ 0xf0;
59cdf0e10cSrcweir 	nRes += LOBYTE( LOWORD( nBytes ) ) ^ 0x0f;
60cdf0e10cSrcweir 
61cdf0e10cSrcweir 	nRes ^= HIBYTE( nRes );
62cdf0e10cSrcweir 
63cdf0e10cSrcweir 	return LOBYTE( nRes );
64cdf0e10cSrcweir }
65cdf0e10cSrcweir 
66cdf0e10cSrcweir 
67cdf0e10cSrcweir #define READ_SOCKET( pBuffer, nLength )\
68cdf0e10cSrcweir 	if ( !bWasError )\
69cdf0e10cSrcweir 	{\
70cdf0e10cSrcweir 		bWasError |= pReceiver->ReceiveBytes( pBuffer, nLength ) != C_ERROR_NONE;\
71cdf0e10cSrcweir 	}
72cdf0e10cSrcweir 
73cdf0e10cSrcweir #define READ_SOCKET_LEN( pBuffer, nLength, nTotal )\
74cdf0e10cSrcweir 	READ_SOCKET( pBuffer, nLength );\
75cdf0e10cSrcweir 	if ( !bWasError )\
76cdf0e10cSrcweir 		{nTotal += nLength;}
77cdf0e10cSrcweir 
ReceiveData(void * & pData,comm_UINT32 & nLen)78cdf0e10cSrcweir comm_BOOL PacketHandler::ReceiveData( void* &pData, comm_UINT32 &nLen )
79cdf0e10cSrcweir {
80cdf0e10cSrcweir 	DBG_ASSERT( !pData, "pData should be NULL -> memory leak" );
81cdf0e10cSrcweir 
82cdf0e10cSrcweir 	nLen = 0;
83cdf0e10cSrcweir 	pData = NULL;
84cdf0e10cSrcweir 	comm_BOOL bWasError = sal_False;
85cdf0e10cSrcweir 	comm_BOOL bForceMultiChannelThisPacket = sal_False;
86cdf0e10cSrcweir 	if ( pReceiver )
87cdf0e10cSrcweir 	{
88cdf0e10cSrcweir 		comm_UINT32 nBytes = 0;
89cdf0e10cSrcweir 		nReceiveProtocol = CM_PROTOCOL_OLDSTYLE;
90cdf0e10cSrcweir 		nReceiveHeaderType = CH_NoHeader;
91cdf0e10cSrcweir 
92cdf0e10cSrcweir 		READ_SOCKET( &nBytes, sizeof(nBytes) )
93cdf0e10cSrcweir 		if ( bWasError )
94cdf0e10cSrcweir 			return sal_False;
95cdf0e10cSrcweir 
96cdf0e10cSrcweir 		if ( 0xFFFFFFFF == nBytes )		// Expliziter Request f�r dieses Datenpaket auf MultiChannel umzuschalten
97cdf0e10cSrcweir 		{
98cdf0e10cSrcweir 			READ_SOCKET( &nBytes, sizeof(nBytes) )
99cdf0e10cSrcweir 			if ( bWasError )
100cdf0e10cSrcweir 				return sal_False;
101cdf0e10cSrcweir 			bForceMultiChannelThisPacket = sal_True;
102cdf0e10cSrcweir 		}
103cdf0e10cSrcweir 
104cdf0e10cSrcweir 		nBytes = NETDWORD( nBytes );
105cdf0e10cSrcweir 
106cdf0e10cSrcweir 		if ( bMultiChannel || bForceMultiChannelThisPacket )
107cdf0e10cSrcweir 		{
108cdf0e10cSrcweir 			comm_ULONG nReadSoFar = 0;
109cdf0e10cSrcweir 			comm_ULONG nHeaderReadSoFar = 0;
110cdf0e10cSrcweir 
111cdf0e10cSrcweir 			// Pr�fbyte f�r L�ngenangabe
112cdf0e10cSrcweir 			unsigned char nLenCheck = 0;
113cdf0e10cSrcweir 			READ_SOCKET_LEN( &nLenCheck, 1, nReadSoFar );
114cdf0e10cSrcweir 			// Stimmt das Pr�fbyte?
115cdf0e10cSrcweir 			bWasError |= nLenCheck != CalcCheckByte( nBytes );
116cdf0e10cSrcweir 
117cdf0e10cSrcweir 
118cdf0e10cSrcweir 			comm_UINT16 nHeaderBytes;
119cdf0e10cSrcweir 			READ_SOCKET_LEN( &nHeaderBytes, 2, nReadSoFar );
120cdf0e10cSrcweir 			nHeaderBytes = NETWORD( nHeaderBytes );
121cdf0e10cSrcweir 			// reicht der Header �ber das Ende hinaus?
122cdf0e10cSrcweir 			bWasError |= !(nBytes >= nReadSoFar + nHeaderBytes);
123cdf0e10cSrcweir 
124cdf0e10cSrcweir 			READ_SOCKET_LEN( &nReceiveHeaderType, 2, nHeaderReadSoFar );
125cdf0e10cSrcweir 			nReceiveHeaderType = NETWORD( nReceiveHeaderType );
126cdf0e10cSrcweir 
127cdf0e10cSrcweir 			switch ( nReceiveHeaderType )
128cdf0e10cSrcweir 			{
129cdf0e10cSrcweir 			case CH_SimpleMultiChannel:
130cdf0e10cSrcweir 				{
131cdf0e10cSrcweir 					READ_SOCKET_LEN( &nReceiveProtocol, 2, nHeaderReadSoFar );
132cdf0e10cSrcweir 					nReceiveProtocol = NETWORD( nReceiveProtocol );
133cdf0e10cSrcweir 				}
134cdf0e10cSrcweir 				break;
135cdf0e10cSrcweir 			case CH_Handshake:
136cdf0e10cSrcweir 				{
137cdf0e10cSrcweir 				}
138cdf0e10cSrcweir 				break;
139cdf0e10cSrcweir 			default:
140cdf0e10cSrcweir 				{
141cdf0e10cSrcweir 					DBG_ERROR("Unbekannter Headertyp in der Kommunikation");
142cdf0e10cSrcweir 					bWasError = sal_True;
143cdf0e10cSrcweir 				}
144cdf0e10cSrcweir 
145cdf0e10cSrcweir 			}
146cdf0e10cSrcweir 
147cdf0e10cSrcweir 			if ( bWasError )
148cdf0e10cSrcweir 				return sal_False;
149cdf0e10cSrcweir 
150cdf0e10cSrcweir 			/// L�ngen anpassen und ggf restheader �berlesen.
151cdf0e10cSrcweir 			while ( nHeaderBytes > nHeaderReadSoFar )
152cdf0e10cSrcweir 			{
153cdf0e10cSrcweir 				unsigned char nDummy;
154cdf0e10cSrcweir 				READ_SOCKET_LEN( &nDummy, 1, nHeaderReadSoFar );
155cdf0e10cSrcweir 			}
156cdf0e10cSrcweir 
157cdf0e10cSrcweir 			nReadSoFar += nHeaderReadSoFar;
158cdf0e10cSrcweir 			nBytes -= nReadSoFar;
159cdf0e10cSrcweir 
160cdf0e10cSrcweir 		}
161cdf0e10cSrcweir 
162cdf0e10cSrcweir 		/* @@@ Notes @@@
163cdf0e10cSrcweir 		 *
164cdf0e10cSrcweir 		 * 1) a 'void*' allocated via 'new char[]' is always deallocated
165cdf0e10cSrcweir 		 * via plain 'delete()', not via array 'delete[]()'; it's just
166cdf0e10cSrcweir 		 * raw memory.
167cdf0e10cSrcweir 		 *
168cdf0e10cSrcweir 		 * 2) as the caller of this routine later-on changes ownership
169cdf0e10cSrcweir 		 * of 'pData' via 'SvMemoryStream::SetBuffer()' (in 'simplecm.cxx',
170cdf0e10cSrcweir 		 * 'SimpleCommunicationLinkViaSocket::DoReceiveDataStream()'),
171cdf0e10cSrcweir 		 * the allocator used here for 'void* pData' must match the
172cdf0e10cSrcweir 		 * deallocator used in 'SvMemoryStream::FreeMemory()', i.e.
173cdf0e10cSrcweir 		 * '::operator delete()'.
174cdf0e10cSrcweir 		 */
175cdf0e10cSrcweir 		pData = ::operator new(nBytes);
176cdf0e10cSrcweir 		READ_SOCKET( pData, nBytes )
177cdf0e10cSrcweir 		if ( bWasError )
178cdf0e10cSrcweir 		{
179cdf0e10cSrcweir 			::operator delete(pData), pData = 0;
180cdf0e10cSrcweir 			return sal_False;
181cdf0e10cSrcweir 		}
182cdf0e10cSrcweir 		nLen = nBytes;
183cdf0e10cSrcweir 	}
184cdf0e10cSrcweir 	else
185cdf0e10cSrcweir 		bWasError = sal_True;
186cdf0e10cSrcweir 
187cdf0e10cSrcweir 	return !bWasError;
188cdf0e10cSrcweir }
189cdf0e10cSrcweir 
190cdf0e10cSrcweir /*#define WRITE_SOCKET( pBuffer, nLength )\
191cdf0e10cSrcweir 	if ( !bWasError )\
192cdf0e10cSrcweir 		bWasError |= !pStreamSocket || (pStreamSocket->write( pBuffer, nLength ) != nLength)*/
193cdf0e10cSrcweir 
194cdf0e10cSrcweir #define WRITE_SOCKET( pBuffer, nLength )\
195cdf0e10cSrcweir 	if ( !bWasError )\
196cdf0e10cSrcweir 		{bWasError |= pTransmitter->TransferBytes( pBuffer, nLength ) != C_ERROR_NONE;}
197cdf0e10cSrcweir 
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 
TransferData(const void * pData,comm_UINT32 nLen,CMProtocol nProtocol)200cdf0e10cSrcweir comm_BOOL PacketHandler::TransferData( const void* pData, comm_UINT32 nLen, CMProtocol nProtocol )
201cdf0e10cSrcweir {
202cdf0e10cSrcweir 	comm_UINT32 nBuffer = nLen;
203cdf0e10cSrcweir 	comm_BOOL bWasError = sal_False;
204cdf0e10cSrcweir 
205cdf0e10cSrcweir #ifndef FORCE_MULTI_CHANNEL_HEADERS
206cdf0e10cSrcweir 	if ( bMultiChannel )
207cdf0e10cSrcweir #endif
208cdf0e10cSrcweir 		nBuffer += 1+2+2+2;	// f�r einen CH_SimpleMultiChannel
209cdf0e10cSrcweir 
210cdf0e10cSrcweir #ifdef FORCE_MULTI_CHANNEL_HEADERS
211cdf0e10cSrcweir 	if ( !bMultiChannel )
212cdf0e10cSrcweir 	{
213cdf0e10cSrcweir 		comm_UINT32 n32;
214cdf0e10cSrcweir 		n32 = 0xffffffff;	// Umschalten auf MultiChannel
215cdf0e10cSrcweir 		n32 = NETDWORD( n32 );
216cdf0e10cSrcweir 		WRITE_SOCKET( &n32, 4 );
217cdf0e10cSrcweir 	}
218cdf0e10cSrcweir #endif
219cdf0e10cSrcweir 
220cdf0e10cSrcweir 
221cdf0e10cSrcweir 	comm_UINT32 nNetworkBuffer = NETDWORD( nBuffer );
222cdf0e10cSrcweir 	WRITE_SOCKET( &nNetworkBuffer, sizeof(nNetworkBuffer) );
223cdf0e10cSrcweir 
224cdf0e10cSrcweir 
225cdf0e10cSrcweir #ifndef FORCE_MULTI_CHANNEL_HEADERS
226cdf0e10cSrcweir 	if ( bMultiChannel )
227cdf0e10cSrcweir #endif
228cdf0e10cSrcweir 	{
229cdf0e10cSrcweir 		comm_UINT16 n16;
230cdf0e10cSrcweir 		unsigned char c;
231cdf0e10cSrcweir 
232cdf0e10cSrcweir 		c = CalcCheckByte( nBuffer );
233cdf0e10cSrcweir 		WRITE_SOCKET( &c, 1 );
234cdf0e10cSrcweir 
235cdf0e10cSrcweir 		n16 = 4;	// L�nge des Headers f�r einen CH_SimpleMultiChannel
236cdf0e10cSrcweir 		n16 = NETWORD( n16 );
237cdf0e10cSrcweir 		WRITE_SOCKET( &n16, 2 );
238cdf0e10cSrcweir 
239cdf0e10cSrcweir 		n16 = CH_SimpleMultiChannel;	// Typ des Headers
240cdf0e10cSrcweir 		n16 = NETWORD( n16 );
241cdf0e10cSrcweir 		WRITE_SOCKET( &n16, 2 );
242cdf0e10cSrcweir 
243cdf0e10cSrcweir 		nProtocol = NETWORD( nProtocol );
244cdf0e10cSrcweir 		WRITE_SOCKET( &nProtocol, 2 );
245cdf0e10cSrcweir 	}
246cdf0e10cSrcweir 
247cdf0e10cSrcweir 	WRITE_SOCKET( pData, nLen );
248cdf0e10cSrcweir 	return !bWasError;
249cdf0e10cSrcweir }
250cdf0e10cSrcweir 
SendHandshake(HandshakeType aHandshakeType,const void * pData,comm_UINT32 nLen)251cdf0e10cSrcweir comm_BOOL PacketHandler::SendHandshake( HandshakeType aHandshakeType, const void* pData, comm_UINT32 nLen )
252cdf0e10cSrcweir {
253cdf0e10cSrcweir 	comm_BOOL bWasError = sal_False;
254cdf0e10cSrcweir 
255cdf0e10cSrcweir 	comm_UINT32 nBuffer = 0;
256cdf0e10cSrcweir 
257cdf0e10cSrcweir //	if ( pMyManager->IsMultiChannel() )		Wir senden immer FFFFFFFF vorweg -> immer MultiChannel (Oder GPF bei �lteren)
258cdf0e10cSrcweir 		nBuffer += 1+2+2;	// f�r einen CH_Handshake
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 	nBuffer += 2;	// f�r den Typ des Handshakes
261cdf0e10cSrcweir 
262cdf0e10cSrcweir 	switch ( aHandshakeType )
263cdf0e10cSrcweir 	{
264cdf0e10cSrcweir 		case CH_REQUEST_HandshakeAlive:
265cdf0e10cSrcweir 			nBuffer += 0;	// Keine extra Daten
266cdf0e10cSrcweir 			break;
267cdf0e10cSrcweir 		case CH_RESPONSE_HandshakeAlive:
268cdf0e10cSrcweir 			nBuffer += 0;	// Keine extra Daten
269cdf0e10cSrcweir 			break;
270cdf0e10cSrcweir 		case CH_REQUEST_ShutdownLink:
271cdf0e10cSrcweir 			nBuffer += 0;	// Keine extra Daten
272cdf0e10cSrcweir 			break;
273cdf0e10cSrcweir 		case CH_ShutdownLink:
274cdf0e10cSrcweir 			nBuffer += 0;	// Keine extra Daten
275cdf0e10cSrcweir 			break;
276cdf0e10cSrcweir 		case CH_SUPPORT_OPTIONS:
277cdf0e10cSrcweir 			nBuffer += 2 ;	// one word extradata for options
278cdf0e10cSrcweir 			break;
279cdf0e10cSrcweir 		case CH_SetApplication:
280cdf0e10cSrcweir 			nBuffer += 0 ;	// one word extradata for options
281cdf0e10cSrcweir 			break;
282cdf0e10cSrcweir 		default:
283cdf0e10cSrcweir 			DBG_ERROR("Unknown HandshakeType");
284cdf0e10cSrcweir 	}
285cdf0e10cSrcweir 
286cdf0e10cSrcweir 	if ( pData )
287cdf0e10cSrcweir 		nBuffer += nLen;	// Extra data in Buffer
288cdf0e10cSrcweir 
289cdf0e10cSrcweir 	comm_UINT32 n32;
290cdf0e10cSrcweir 	n32 = 0xffffffff;	// Umschalten auf MultiChannel
291cdf0e10cSrcweir 	n32 = NETDWORD( n32 );
292cdf0e10cSrcweir 	WRITE_SOCKET( &n32, 4 );
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 	comm_UINT32 nNetworkBuffer = NETDWORD( nBuffer );
295cdf0e10cSrcweir 	WRITE_SOCKET( &nNetworkBuffer, sizeof(nNetworkBuffer) );
296cdf0e10cSrcweir 
297cdf0e10cSrcweir 
298cdf0e10cSrcweir 	comm_UINT16 n16;
299cdf0e10cSrcweir 	unsigned char c;
300cdf0e10cSrcweir 
301cdf0e10cSrcweir 	c = CalcCheckByte( nBuffer );
302cdf0e10cSrcweir 	WRITE_SOCKET( &c, 1 );
303cdf0e10cSrcweir 
304cdf0e10cSrcweir 	n16 = 2;	// L�nge des Headers f�r einen CH_Handshake
305cdf0e10cSrcweir 	n16 = NETWORD( n16 );
306cdf0e10cSrcweir 	WRITE_SOCKET( &n16, 2 );
307cdf0e10cSrcweir 
308cdf0e10cSrcweir 	n16 = CH_Handshake;	// Typ des Headers
309cdf0e10cSrcweir 	n16 = NETWORD( n16 );
310cdf0e10cSrcweir 	WRITE_SOCKET( &n16, 2 );
311cdf0e10cSrcweir 
312cdf0e10cSrcweir 	n16 = aHandshakeType;	// Typ des Handshakes
313cdf0e10cSrcweir 	n16 = NETWORD( n16 );
314cdf0e10cSrcweir 	WRITE_SOCKET( &n16, 2 );
315cdf0e10cSrcweir 
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 	switch ( aHandshakeType )
318cdf0e10cSrcweir 	{
319cdf0e10cSrcweir 		case CH_SUPPORT_OPTIONS:
320cdf0e10cSrcweir 			n16 = OPT_USE_SHUTDOWN_PROTOCOL;
321cdf0e10cSrcweir 			n16 = NETWORD( n16 );
322cdf0e10cSrcweir 			WRITE_SOCKET( &n16, 2 );
323cdf0e10cSrcweir 			break;
324cdf0e10cSrcweir 	}
325cdf0e10cSrcweir 
326cdf0e10cSrcweir 	if ( pData )
327cdf0e10cSrcweir 		WRITE_SOCKET( pData, nLen );
328cdf0e10cSrcweir 
329cdf0e10cSrcweir 	return !bWasError;
330cdf0e10cSrcweir }
331