Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
            }
        }
Exemplo n.º 4
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;
            }
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 7
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;
                    }
                }
            }
        }