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