public static RPCVariable CreateError(int faultCode, string faultString) { RPCVariable errorStruct = new RPCVariable(RPCVariableType.rpcStruct); errorStruct.StructValue.Add("faultCode", new RPCVariable(faultCode)); errorStruct.StructValue.Add("faultString", new RPCVariable(faultString)); return(errorStruct); }
public bool SetValue(RPCVariable value) { bool valueChanged = !Compare(value); if (!valueChanged) { return(false); } switch (_type) { case RPCVariableType.rpcBoolean: _booleanValue = value.BooleanValue; break; case RPCVariableType.rpcArray: _arrayValue = value.ArrayValue; break; case RPCVariableType.rpcStruct: _structValue = value.StructValue; break; case RPCVariableType.rpcInteger32: _integerValue = value.IntegerValue; break; case RPCVariableType.rpcInteger: _integerValue = value.IntegerValue; break; case RPCVariableType.rpcString: _stringValue = (value.StringValue == null) ? "" : value.StringValue; break; case RPCVariableType.rpcBase64: _stringValue = (value.StringValue == null) ? "" : value.StringValue; break; case RPCVariableType.rpcFloat: _floatValue = value.FloatValue; break; } return(true); }
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; } }
private void ProcessPacket(byte[] packet) { if (packet == null || packet.Length < 8) { return; } if ((packet[3] & 1) == 0) //Request { string methodName = ""; List <RPCVariable> parameters = _rpcDecoder.DecodeRequest(packet, ref methodName); RPCVariable response = new RPCVariable(RPCVariableType.rpcVoid); if (methodName == "") { response = RPCVariable.CreateError(-1, "Packet is not well formed: " + BitConverter.ToString(packet)); } else if (methodName == "system.listMethods") { response = new RPCVariable(RPCVariableType.rpcArray); response.ArrayValue.Add(new RPCVariable("system.multicall")); response.ArrayValue.Add(new RPCVariable("error")); response.ArrayValue.Add(new RPCVariable("event")); response.ArrayValue.Add(new RPCVariable("newDevices")); response.ArrayValue.Add(new RPCVariable("updateDevice")); response.ArrayValue.Add(new RPCVariable("deleteDevices")); response.ArrayValue.Add(new RPCVariable("newEvent")); response.ArrayValue.Add(new RPCVariable("deleteEvent")); response.ArrayValue.Add(new RPCVariable("updateEvent")); } else if (methodName == "system.multicall" && parameters.Any()) { foreach (RPCVariable method in parameters[0].ArrayValue) { if (method.Type != RPCVariableType.rpcStruct || method.StructValue.Count() != 2) { continue; } if (method.StructValue["methodName"].StringValue != "event") { continue; } List <RPCVariable> eventParams = method.StructValue["params"].ArrayValue; if (eventParams.Count() != 5 || eventParams[0].Type != RPCVariableType.rpcString || eventParams[1].Type != RPCVariableType.rpcInteger || eventParams[2].Type != RPCVariableType.rpcInteger || eventParams[3].Type != RPCVariableType.rpcString) { continue; } RPCEvent?.Invoke(this, eventParams[1].IntegerValue, eventParams[2].IntegerValue, eventParams[3].StringValue, eventParams[4], eventParams[0].StringValue); } } else if (methodName == "error" && parameters.Count() == 3 && parameters[1].Type == RPCVariableType.rpcInteger && parameters[2].Type == RPCVariableType.rpcString) { HomegearError?.Invoke(this, parameters[1].IntegerValue, parameters[2].StringValue); } else if (methodName == "newDevices") { NewDevices?.Invoke(this); } else if (methodName == "deleteDevices") { DevicesDeleted?.Invoke(this); } else if (methodName == "updateDevice") { if (parameters.Count == 4 && parameters[0].Type == RPCVariableType.rpcString && parameters[1].Type == RPCVariableType.rpcInteger && parameters[2].Type == RPCVariableType.rpcInteger && parameters[3].Type == RPCVariableType.rpcInteger) { UpdateDevice?.Invoke(this, parameters[1].IntegerValue, parameters[2].IntegerValue, parameters[3].IntegerValue); } } else if (methodName == "newEvent") { if (parameters.Count == 2 && parameters[1].Type == RPCVariableType.rpcStruct) { string id = ""; long type = -1; long peerId = 0; long channel = -1; string variable = ""; if (parameters[1].StructValue.ContainsKey("ID")) { id = parameters[1].StructValue["ID"].StringValue; } if (parameters[1].StructValue.ContainsKey("TYPE")) { type = parameters[1].StructValue["TYPE"].IntegerValue; } if (parameters[1].StructValue.ContainsKey("PEERID")) { peerId = parameters[1].StructValue["PEERID"].IntegerValue; } if (parameters[1].StructValue.ContainsKey("PEERCHANNEL")) { channel = parameters[1].StructValue["PEERCHANNEL"].IntegerValue; } if (parameters[1].StructValue.ContainsKey("VARIABLE")) { variable = parameters[1].StructValue["VARIABLE"].StringValue; } NewEvent?.Invoke(this, id, type, peerId, channel, variable); } } else if (methodName == "deleteEvent") { if (parameters.Count == 6) { EventDeleted?.Invoke(this, parameters[1].StringValue, parameters[2].IntegerValue, parameters[3].IntegerValue, parameters[4].IntegerValue, parameters[5].StringValue); } } else if (methodName == "updateEvent") { if (parameters.Count == 6) { UpdateEvent?.Invoke(this, parameters[1].StringValue, parameters[2].IntegerValue, parameters[3].IntegerValue, parameters[4].IntegerValue, parameters[5].StringValue); } } byte[] responsePacket = _rpcEncoder.EncodeResponse(response).ToArray(); SendPacket(responsePacket); } else //Response { _rpcResponse = _rpcDecoder.DecodeResponse(packet); _responseReceived.Set(); } }
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 bool Compare(RPCVariable variable) { if (Type != variable.Type) { return(false); } switch (_type) { case RPCVariableType.rpcBoolean: if (_booleanValue != variable.BooleanValue) { return(false); } break; case RPCVariableType.rpcArray: if (_arrayValue.Count != variable.ArrayValue.Count) { return(false); } else { for (int i = 0; i < _arrayValue.Count; i++) { if (!_arrayValue[i].Compare(variable.ArrayValue[i])) { return(false); } } } break; case RPCVariableType.rpcStruct: if (_structValue.Count != variable.StructValue.Count) { return(false); } else { for (int i = 0; i < _structValue.Count; i++) { if (_structValue.Keys.ElementAt(i) != variable.StructValue.Keys.ElementAt(i)) { return(false); } if (!_structValue.Values.ElementAt(i).Compare(variable.StructValue.Values.ElementAt(i))) { return(false); } } } break; case RPCVariableType.rpcInteger: if (_integerValue != variable.IntegerValue) { return(false); } break; case RPCVariableType.rpcString: if (_stringValue != variable.StringValue) { return(false); } break; case RPCVariableType.rpcBase64: if (_stringValue != variable.StringValue) { return(false); } break; case RPCVariableType.rpcFloat: if (_floatValue != variable.FloatValue) { return(false); } break; } return(true); }
private void ProcessPacket(byte[] packet) { if (packet == null) { return; } string methodName = ""; List <RPCVariable> parameters = _rpcDecoder.DecodeRequest(packet, ref methodName); RPCVariable response = new RPCVariable(RPCVariableType.rpcVoid); if (methodName == "") { response = RPCVariable.CreateError(-1, "Packet is not well formed: " + BitConverter.ToString(packet)); } else if (methodName == "system.listMethods") { response = new RPCVariable(RPCVariableType.rpcArray); response.ArrayValue.Add(new RPCVariable("system.multicall")); response.ArrayValue.Add(new RPCVariable("error")); response.ArrayValue.Add(new RPCVariable("event")); response.ArrayValue.Add(new RPCVariable("listDevices")); response.ArrayValue.Add(new RPCVariable("newDevices")); response.ArrayValue.Add(new RPCVariable("updateDevice")); response.ArrayValue.Add(new RPCVariable("deleteDevices")); response.ArrayValue.Add(new RPCVariable("newEvent")); response.ArrayValue.Add(new RPCVariable("deleteEvent")); response.ArrayValue.Add(new RPCVariable("updateEvent")); } else if (methodName == "system.multicall" && parameters.Count() > 0) { foreach (RPCVariable method in parameters[0].ArrayValue) { if (method.Type != RPCVariableType.rpcStruct || method.StructValue.Count() != 2) { continue; } if (method.StructValue["methodName"].StringValue != "event") { continue; } List <RPCVariable> eventParams = method.StructValue["params"].ArrayValue; if (eventParams.Count() != 5 || eventParams[0].Type != RPCVariableType.rpcString || eventParams[1].Type != RPCVariableType.rpcInteger || eventParams[2].Type != RPCVariableType.rpcInteger || eventParams[3].Type != RPCVariableType.rpcString) { continue; } if (RPCEvent != null) { RPCEvent(this, eventParams[1].IntegerValue, eventParams[2].IntegerValue, eventParams[3].StringValue, eventParams[4]); } } } else if (methodName == "error" && parameters.Count() == 3 && parameters[1].Type == RPCVariableType.rpcInteger && parameters[2].Type == RPCVariableType.rpcString) { if (HomegearError != null) { HomegearError(this, parameters[1].IntegerValue, parameters[2].StringValue); } } else if (methodName == "listDevices") { response = new RPCVariable(RPCVariableType.rpcArray); if (_knownDevices != null) { foreach (Int32 peerID in _knownDevices.Keys) { RPCVariable device = new RPCVariable(RPCVariableType.rpcStruct); device.StructValue.Add("ID", new RPCVariable(peerID)); response.ArrayValue.Add(device); } } } else if (methodName == "newDevices") { if (NewDevices != null) { NewDevices(this); } } else if (methodName == "deleteDevices") { if (DevicesDeleted != null) { DevicesDeleted(this); } } else if (methodName == "updateDevice") { if (parameters.Count == 4 && parameters[0].Type == RPCVariableType.rpcString && parameters[1].Type == RPCVariableType.rpcInteger && parameters[2].Type == RPCVariableType.rpcInteger && parameters[3].Type == RPCVariableType.rpcInteger) { if (UpdateDevice != null) { UpdateDevice(this, parameters[1].IntegerValue, parameters[2].IntegerValue, parameters[3].IntegerValue); } } } else if (methodName == "newEvent") { if (parameters.Count == 2 && parameters[1].Type == RPCVariableType.rpcStruct) { String id = ""; Int32 type = -1; Int32 peerID = 0; Int32 channel = -1; String variable = ""; if (parameters[1].StructValue.ContainsKey("ID")) { id = parameters[1].StructValue["ID"].StringValue; } if (parameters[1].StructValue.ContainsKey("TYPE")) { type = parameters[1].StructValue["TYPE"].IntegerValue; } if (parameters[1].StructValue.ContainsKey("PEERID")) { peerID = parameters[1].StructValue["PEERID"].IntegerValue; } if (parameters[1].StructValue.ContainsKey("PEERCHANNEL")) { channel = parameters[1].StructValue["PEERCHANNEL"].IntegerValue; } if (parameters[1].StructValue.ContainsKey("VARIABLE")) { variable = parameters[1].StructValue["VARIABLE"].StringValue; } if (NewEvent != null) { NewEvent(this, id, type, peerID, channel, variable); } } } else if (methodName == "deleteEvent") { if (parameters.Count == 6) { if (EventDeleted != null) { EventDeleted(this, parameters[1].StringValue, parameters[2].IntegerValue, parameters[3].IntegerValue, parameters[4].IntegerValue, parameters[5].StringValue); } } } else if (methodName == "updateEvent") { if (parameters.Count == 6) { if (UpdateEvent != null) { UpdateEvent(this, parameters[1].StringValue, parameters[2].IntegerValue, parameters[3].IntegerValue, parameters[4].IntegerValue, parameters[5].StringValue); } } } byte[] responsePacket = _rpcEncoder.EncodeResponse(response).ToArray(); Int32 bytesSent = 1024; Int32 bytesToSend = 0; for (int i = 0; i < responsePacket.Length; i += bytesSent) { bytesToSend = (i + 1024 >= responsePacket.Length) ? responsePacket.Length - i : 1024; if (_ssl) { _sslStream.Write(responsePacket, i, bytesToSend); _sslStream.Flush(); } else { bytesSent = _client.Client.Send(responsePacket, i, bytesToSend, SocketFlags.None); } } }
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; } } } }