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