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 46 PacketHandler::PacketHandler( ITransmiter* pTransmitter_, IReceiver* pReceiver_, comm_BOOL bMC ) 47 : pTransmitter( pTransmitter_ ) 48 , pReceiver( pReceiver_ ) 49 , bMultiChannel( bMC ) 50 { 51 } 52 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 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 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 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