private uint EncodeHeader(List <byte> packet, RPCHeader header) { uint oldPacketSize = (uint)packet.Count(); int parameterCount = 0; if (header.Authorization.Length > 0) { parameterCount++; _encoder.EncodeString(packet, "Authorization"); _encoder.EncodeString(packet, header.Authorization); } else { return(0); } List <byte> parameterCountBytes = new List <byte>(4); parameterCountBytes.Add((byte)((parameterCount >> 24) & 0xFF)); parameterCountBytes.Add((byte)((parameterCount >> 16) & 0xFF)); parameterCountBytes.Add((byte)((parameterCount >> 8) & 0xFF)); parameterCountBytes.Add((byte)(parameterCount & 0xFF)); packet.InsertRange((int)oldPacketSize, parameterCountBytes); uint headerSize = (uint)packet.Count() - oldPacketSize; List <byte> sizeBytes = new List <byte>(4); sizeBytes.Add((byte)((headerSize >> 24) & 0xFF)); sizeBytes.Add((byte)((headerSize >> 16) & 0xFF)); sizeBytes.Add((byte)((headerSize >> 8) & 0xFF)); sizeBytes.Add((byte)(headerSize & 0xFF)); packet.InsertRange((int)oldPacketSize, sizeBytes); return(headerSize); }
public RPCHeader DecodeHeader(byte[] packet) { RPCHeader header = new RPCHeader(); if (packet.Length < 12 || (packet[3] & 0x40) == 0) { return(header); } uint position = 4; int headerSize = 0; headerSize = _decoder.DecodeInteger(packet, ref position); if (headerSize < 4) { return(header); } int parameterCount = _decoder.DecodeInteger(packet, ref position); for (int i = 0; i < parameterCount; i++) { string field = _decoder.DecodeString(packet, ref position).ToLower(); string value = _decoder.DecodeString(packet, ref position); if (field == "authorization") { header.Authorization = value; } } return(header); }
public void InsertHeader(List <byte> packet, RPCHeader header) { if (packet.Count() < 4) { return; } List <byte> headerData = new List <byte>(); uint headerSize = EncodeHeader(headerData, header); if (headerSize > 0) { packet[3] |= 0x40; packet.InsertRange(4, headerData); } }
public RPCVariable CallMethod(string name, List <RPCVariable> parameters) { try { lock (_callMethodLock) { for (int j = 0; j < _maxTries; j++) { for (int i = 0; i < 3; i++) { try { if (_client == null || !_client.Connected) { Connect(); } if (Ssl && _sslStream == null) { Connect(); } break; } catch (HomegearRpcClientSSLException ex) { throw ex; } catch (HomegearRpcClientException ex) { if (i == 2) { throw ex; } } if (_stopThread) { break; } Thread.Sleep(1000); if (_stopThread) { break; } } _responseReceived.Reset(); _rpcResponse = null; Encoding.RPCHeader header = null; if (Ssl && _authString != null && _authString.Length > 0) { header = new Encoding.RPCHeader(); header.Authorization = Marshal.PtrToStringAuto(Marshal.SecureStringToBSTR(_authString)); } byte[] requestPacket = _rpcEncoder.EncodeRequest(name, parameters, header).ToArray(); try { SendPacket(requestPacket); } catch (System.IO.IOException ex) { Disconnect(); if (j == _maxTries - 1) { throw new HomegearRpcClientException( "Error calling rpc method " + name + " on server " + _hostname + " and port " + _port.ToString() + ": " + ex.Message); } continue; } catch (SocketException ex) { Disconnect(); if (j == _maxTries - 1) { throw new HomegearRpcClientException( "Error calling rpc method " + name + " on server " + _hostname + " and port " + _port.ToString() + ": " + ex.Message); } continue; } if (_responseReceived.WaitOne(15000) && _rpcResponse != null) { break; } } if (_rpcResponse == null) { return(RPCVariable.CreateError(-32501, "No response received.")); } if (_rpcResponse.ErrorStruct && _rpcResponse.StructValue["faultCode"].IntegerValue == -32603) { _client.Close(); //Unauthorized } return(_rpcResponse); } } catch (Exception ex) { throw ex; } }
public RPCVariable CallMethod(String name, List <RPCVariable> parameters) { RPCVariable result = null; _sendMutex.WaitOne(); try { for (int j = 0; j < _maxTries; j++) { for (int i = 0; i < 3; i++) { try { if (_client == null || !_client.Connected) { Connect(); } if (_ssl && _sslStream == null) { Connect(); } break; } catch (HomegearRPCClientSSLException ex) { throw ex; } catch (HomegearRPCClientException ex) { if (i == 2) { throw ex; } } Thread.Sleep(1000); } Encoding.RPCHeader header = null; if (_ssl && _authString != null && _authString.Length > 0) { header = new Encoding.RPCHeader(); header.Authorization = Marshal.PtrToStringAuto(Marshal.SecureStringToBSTR(_authString)); } byte[] requestPacket = _rpcEncoder.EncodeRequest(name, parameters, header).ToArray(); try { Int32 bytesSent = 1024; Int32 bytesToSend = 0; for (int i = 0; i < requestPacket.Length; i += bytesSent) { bytesToSend = (i + 1024 >= requestPacket.Length) ? requestPacket.Length - i : 1024; if (_ssl) { _sslStream.Write(requestPacket, i, bytesToSend); _sslStream.Flush(); } else { bytesSent = _client.Client.Send(requestPacket, i, bytesToSend, SocketFlags.None); } } } catch (System.IO.IOException ex) { Disconnect(); if (j == _maxTries - 1) { throw new HomegearRPCClientException("Error calling rpc method " + name + " on server " + _hostname + " and port " + _port.ToString() + ": " + ex.Message); } continue; } catch (SocketException ex) { Disconnect(); if (j == _maxTries - 1) { throw new HomegearRPCClientException("Error calling rpc method " + name + " on server " + _hostname + " and port " + _port.ToString() + ": " + ex.Message); } continue; } try { byte[] packet = null; int bytesReceived = 0; byte[] buffer = new byte[1024]; uint dataSize = 0; uint packetLength = 0; do { if (_ssl) { bytesReceived = _sslStream.Read(buffer, 0, buffer.Length); } else { bytesReceived = _client.Client.Receive(buffer); } if (dataSize == 0) { if ((buffer[3] & 1) == 0) { throw new HomegearRPCClientException("RPC client received binary request as response from server " + _hostname + " on port " + _port.ToString() + "."); } if (bytesReceived < 8) { throw new HomegearRPCClientException("RPC client received binary response smaller than 8 bytes from server " + _hostname + " on port " + _port.ToString() + "."); } dataSize = (uint)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + buffer[7]); if (dataSize == 0) { throw new HomegearRPCClientException("RPC client received empty response from server " + _hostname + " on port " + _port.ToString() + "."); } if (dataSize > 104857600) { throw new HomegearRPCClientException("RPC client received response larger than 100 MiB from server " + _hostname + " on port " + _port.ToString() + "."); } packetLength = (uint)bytesReceived - 8; packet = new byte[dataSize + 8]; Array.Copy(buffer, packet, bytesReceived); } else { if (packetLength + bytesReceived > dataSize) { throw new HomegearRPCClientException("RPC client received response larger than the expected size from server " + _hostname + " on port " + _port.ToString() + "."); } Array.Copy(buffer, 0, packet, packetLength + 8, bytesReceived); packetLength += (uint)bytesReceived; } if (packetLength == dataSize) { break; } } while (bytesReceived != 0); if (packet != null) { result = _rpcDecoder.DecodeResponse(packet); } break; } catch (System.IO.IOException ex) { Disconnect(); if (j == _maxTries - 1) { throw new HomegearRPCClientException("IOException thrown calling rpc method " + name + " on server " + _hostname + " and port " + _port.ToString() + ": " + ex.Message); } } catch (SocketException ex) { Disconnect(); if (j == _maxTries - 1) { throw new HomegearRPCClientException("SocketException thrown on calling rpc method " + name + " on server " + _hostname + " and port " + _port.ToString() + ": " + ex.Message); } } catch (Exception ex) { Disconnect(); if (j == _maxTries - 1) { throw new HomegearRPCClientException("Exception thrown on calling rpc method " + name + " on server " + _hostname + " and port " + _port.ToString() + ": " + ex.Message); } } } if (result.ErrorStruct && result.StructValue["faultCode"].IntegerValue == -32603) { _client.Close(); } } catch (Exception ex) { throw ex; } finally { _sendMutex.ReleaseMutex(); } if (result == null) { result = RPCVariable.CreateError(-32500, "Response was empty."); } return(result); }
public List <byte> EncodeRequest(string methodName, List <RPCVariable> parameters, RPCHeader header = null) { //The "Bin", the type byte after that and the length itself are not part of the length List <byte> packet = new List <byte>(); packet.InsertRange(0, _packetStartRequest); uint headerSize = 0; if (header != null) { headerSize = EncodeHeader(packet, header) + 4; if (headerSize > 0) { packet[3] |= 0x40; } } _encoder.EncodeString(packet, methodName); if (parameters == null) { _encoder.EncodeInteger(packet, 0); } else { _encoder.EncodeInteger(packet, parameters.Count()); } if (parameters != null) { foreach (RPCVariable parameter in parameters) { EncodeVariable(packet, parameter); } } int dataSize = (int)(packet.Count() - 4 - headerSize); List <byte> sizeBytes = new List <byte>(4); sizeBytes.Add((byte)((dataSize >> 24) & 0xFF)); sizeBytes.Add((byte)((dataSize >> 16) & 0xFF)); sizeBytes.Add((byte)((dataSize >> 8) & 0xFF)); sizeBytes.Add((byte)(dataSize & 0xFF)); packet.InsertRange((int)headerSize + 4, sizeBytes); return(packet); }
private void ReadClient() { byte[] buffer = new byte[2048]; int bytesReceived = 0; uint dataSize = 0; uint headerSize = 0; uint packetLength = 0; byte[] packet = null; while (!_stopServer) { try { if (_client == null || !_client.Connected) { break; } if (_ssl) { bytesReceived = _sslStream.Read(buffer, 0, buffer.Length); } else { bytesReceived = _client.Client.Receive(buffer); } if (bytesReceived == 0) { continue; } UInt32 bufferPos = 0; while (bufferPos == 0 || bufferPos + dataSize + 8 < bytesReceived) { if (buffer[bufferPos] == 'B' && buffer[bufferPos + 1] == 'i' && buffer[bufferPos + 2] == 'n') { if ((buffer[bufferPos + 3] & 1) == 1) { continue; //Response received } if (bytesReceived < 8) { continue; } if ((buffer[bufferPos + 3] & 0x40) == 0x40) { headerSize = (uint)((buffer[bufferPos + 4] << 24) + (buffer[bufferPos + 5] << 16) + (buffer[bufferPos + 6] << 8) + buffer[bufferPos + 7]); if (bytesReceived < bufferPos + headerSize + 12) { continue; } dataSize = (uint)((buffer[bufferPos + 8 + headerSize] << 24) + (buffer[bufferPos + 9 + headerSize] << 16) + (buffer[bufferPos + 10 + headerSize] << 8) + buffer[bufferPos + 11 + headerSize]) + headerSize + 4; } else { headerSize = 0; dataSize = (uint)((buffer[bufferPos + 4] << 24) + (buffer[bufferPos + 5] << 16) + (buffer[bufferPos + 6] << 8) + buffer[bufferPos + 7]); } if (dataSize == 0) { continue; } if (dataSize > 104857600) { continue; } if (headerSize > 1024) { continue; } packetLength = (uint)bytesReceived - 8; if (packetLength > dataSize) { packetLength = dataSize; } packet = new byte[dataSize + 8]; Array.Copy(buffer, bufferPos, packet, 0, ((dataSize + 8) > bytesReceived) ? bytesReceived : (Int32)dataSize + 8); if (_authString != null && _authString.Length > 0) { Encoding.RPCHeader header = _rpcDecoder.DecodeHeader(packet); if (header.Authorization != Marshal.PtrToStringAuto(Marshal.SecureStringToBSTR(_authString))) { packet = null; List <byte> responsePacket = _rpcEncoder.EncodeResponse(RPCVariable.CreateError(-32603, "Unauthorized")); if (_ssl) { _sslStream.Write(responsePacket.ToArray()); _sslStream.Flush(); } else { _client.Client.Send(responsePacket.ToArray()); } continue; } } } else if (packet != null) { if (packetLength + bytesReceived > dataSize) { System.Diagnostics.Debug.WriteLine("RPC server received response larger than the expected size from Homegear."); bytesReceived = (int)(dataSize - packetLength); } Array.Copy(buffer, 0, packet, packetLength + 8, bytesReceived); packetLength += (uint)bytesReceived; } if (packet != null && packetLength == dataSize) { ProcessPacket(packet); packet = null; } bufferPos = dataSize + 8; } } catch (TimeoutException) { continue; } catch (SocketException ex) { if (ex.SocketErrorCode == SocketError.TimedOut) { continue; } else { System.Diagnostics.Debug.WriteLine(ex.Message); break; } } catch (IOException ex) { if (ex.HResult == -2146232800) { continue; } else { System.Diagnostics.Debug.WriteLine(ex.Message); break; } } } }