xref: /AOO41X/main/automation/source/simplecm/packethandler.cxx (revision 9d1279ece119b840266617e54d20d4d5fa7aea95)
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;
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