Пример #1
0
        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;
            }
        }
Пример #2
0
        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();
            }
        }
Пример #3
0
        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);
                }
            }
        }
Пример #4
0
        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);
        }
Пример #5
0
        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;
                    }
                }
            }
        }