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