예제 #1
0
        /// <summary>
        /// Sends the request to the server.
        /// </summary>
        protected void SendRequest(DataPacket request)
        {
            request.Encode();
            netStream.Write(request.Buffer, 0, request.BufferLength);

            if (CommLog != null)
            {
                CommLog.WriteAction(FunctionID.GetName(request.FunctionID));
                CommLog.WriteAction(BuildWritingText(request.Buffer, 0, request.BufferLength));
            }
        }
예제 #2
0
        /// <summary>
        /// Sends the request to the server.
        /// </summary>
        protected void SendRequest(DataPacket request)
        {
            try
            {
                request.Encode();
                netStream.Write(request.Buffer, 0, request.BufferLength);

                if (CommLog != null)
                {
                    CommLog.WriteAction(FunctionID.GetName(request.FunctionID));
                    CommLog.WriteAction(BuildWritingText(request.Buffer, 0, request.BufferLength));
                }
            }
            catch (IOException)
            {
                ClientState = ClientState.Error;
                throw;
            }
        }
예제 #3
0
        /// <summary>
        /// Disconnects from the server.
        /// </summary>
        protected void Disconnect()
        {
            if (tcpClient != null)
            {
                CommLog?.WriteAction("Disconnect");

                if (netStream != null)
                {
                    ClearNetStream(netStream, inBuf); // to disconnect correctly
                    netStream.Close();
                    netStream = null;
                }

                tcpClient.Close();
                tcpClient = null;

                ClientState = ClientState.Disconnected;
                SessionID   = 0;
                ServerName  = "";
            }
        }
예제 #4
0
        /// <summary>
        /// Connects and authenticates with the server.
        /// </summary>
        protected void Connect()
        {
            // create connection
            tcpClient = new TcpClient
            {
                SendTimeout    = ConnectionOptions.Timeout,
                ReceiveTimeout = ConnectionOptions.Timeout
            };

            // connect
            CommLog?.WriteAction("Connect to " + ConnectionOptions.Host);

            if (IPAddress.TryParse(ConnectionOptions.Host, out IPAddress address))
            {
                tcpClient.Connect(address, ConnectionOptions.Port);
            }
            else
            {
                tcpClient.Connect(ConnectionOptions.Host, ConnectionOptions.Port);
            }

            netStream   = tcpClient.GetStream();
            ClientState = ClientState.Connected;
        }
예제 #5
0
        /// <summary>
        /// Receives a response from the server.
        /// </summary>
        protected DataPacket ReceiveResponse(DataPacket request)
        {
            DataPacket response    = null;
            bool       formatError = true;
            string     errDescr    = "";
            int        bytesToRead = HeaderLength + 2;
            int        bytesRead;

            try
            {
                bytesRead = netStream.Read(inBuf, 0, bytesToRead);
                CommLog?.WriteAction(BuildReadingText(inBuf, 0, bytesToRead, bytesRead));
            }
            catch (IOException)
            {
                ClientState = ClientState.Error;
                throw;
            }

            if (bytesRead == bytesToRead)
            {
                response = new DataPacket
                {
                    TransactionID = BitConverter.ToUInt16(inBuf, 0),
                    DataLength    = BitConverter.ToInt32(inBuf, 2),
                    SessionID     = BitConverter.ToInt64(inBuf, 6),
                    FunctionID    = BitConverter.ToUInt16(inBuf, 14),
                    Buffer        = inBuf
                };

                if (response.DataLength + 6 > inBuf.Length)
                {
                    errDescr = Locale.IsRussian ?
                               "длина данных слишком велика" :
                               "data length is too big";
                }
                else if (response.TransactionID != request.TransactionID)
                {
                    errDescr = Locale.IsRussian ?
                               "неверный идентификатор транзакции" :
                               "incorrect transaction ID";
                }
                else if (response.SessionID != SessionID && SessionID != 0)
                {
                    errDescr = Locale.IsRussian ?
                               "неверный идентификатор сессии" :
                               "incorrect session ID";
                }
                else if ((response.FunctionID & 0x7FFF) != request.FunctionID)
                {
                    errDescr = Locale.IsRussian ?
                               "неверный идентификатор функции" :
                               "incorrect function ID";
                }
                else
                {
                    // read the rest of the data
                    bytesToRead = response.DataLength - 10;
                    bytesRead   = ReadData(netStream, tcpClient.ReceiveTimeout, inBuf, HeaderLength + 2, bytesToRead);
                    CommLog?.WriteAction(BuildReadingText(inBuf, HeaderLength + 2, bytesToRead, bytesRead));

                    if (bytesRead == bytesToRead)
                    {
                        formatError = false;
                        responseDT  = DateTime.UtcNow;

                        // handle error response
                        if ((response.FunctionID & 0x8000) > 0)
                        {
                            ErrorCode errorCode = (ErrorCode)inBuf[ArgumentIndex];
                            CommLog?.WriteError(errorCode.ToString());
                            throw new ProtocolException(errorCode);
                        }
                    }
                    else
                    {
                        errDescr = Locale.IsRussian ?
                                   "не удалось прочитать все данные" :
                                   "unable to read all data";
                    }
                }
            }
            else
            {
                errDescr = Locale.IsRussian ?
                           "не удалось прочитать заголовок пакета данных" :
                           "unable to read data packet header";
            }

            if (formatError)
            {
                throw new ScadaException(Locale.IsRussian ?
                                         "Некорректный формат данных, полученных от сервера: {0}" :
                                         "Incorrect format of data received from the server: {0}", errDescr);
            }

            return(response);
        }
예제 #6
0
        /// <summary>
        /// Restores a connection with the server.
        /// </summary>
        protected void RestoreConnection()
        {
            DateTime utcNow        = DateTime.UtcNow;
            bool     connectNeeded = false;

            if (ClientState == ClientState.LoggedIn)
            {
                if (utcNow - responseDT > PingPeriod)
                {
                    try
                    {
                        // check connection
                        DataPacket request = CreateRequest(FunctionID.GetStatus, 10);
                        SendRequest(request);
                        ReceiveResponse(request);
                    }
                    catch
                    {
                        connectNeeded = true;
                    }
                }
            }
            else if (utcNow - connAttemptDT > ReconnectPeriod)
            {
                connectNeeded = true;
            }

            try
            {
                if (connectNeeded)
                {
                    connAttemptDT = utcNow;
                    Disconnect();
                    Connect();

                    GetSessionInfo(out long sessionID, out string serverName);
                    SessionID  = sessionID;
                    ServerName = serverName;

                    Login(ConnectionOptions.Username, ConnectionOptions.Password,
                          out bool loggedIn, out int userID, out int roleID, out string errMsg);
                    UserID = userID;
                    RoleID = roleID;

                    if (loggedIn)
                    {
                        ClientState = ClientState.LoggedIn;
                        CommLog?.WriteAction("User is logged in");
                    }
                    else
                    {
                        throw new ScadaException(errMsg);
                    }
                }
                else if (ClientState == ClientState.LoggedIn)
                {
                    ClearNetStream(netStream, inBuf);
                }
                else
                {
                    throw new ScadaException(Locale.IsRussian ?
                                             "Клиент не вошёл в систему. Попробуйте позже." :
                                             "Client is not logged in. Try again later.");
                }
            }
            catch
            {
                ClientState = ClientState.Error;
                throw;
            }
        }
예제 #7
0
        /// <summary>
        /// Restores a connection with the server.
        /// </summary>
        protected void RestoreConnection()
        {
            DateTime utcNow        = DateTime.UtcNow;
            bool     connectNeeded = false;

            if (ClientState == ClientState.LoggedIn)
            {
                if (utcNow - responseDT > PingPeriod)
                {
                    try
                    {
                        // check connection
                        DataPacket request = CreateRequest(FunctionID.GetStatus, 10);
                        SendRequest(request);
                        ReceiveResponse(request);
                    }
                    catch
                    {
                        connectNeeded = true;
                    }
                }
            }
            else if (utcNow - connAttemptDT > ReconnectPeriod)
            {
                connectNeeded = true;
            }

            try
            {
                if (connectNeeded)
                {
                    connAttemptDT = utcNow;
                    Disconnect();
                    Connect();

                    GetSessionInfo(out long sessionID, out ushort protocolVersion, out string serverName);
                    SessionID  = sessionID;
                    ServerName = serverName;

                    if (protocolVersion != ProtocolVersion)
                    {
                        throw new ScadaException(Locale.IsRussian ?
                                                 "Несовместимая версия протокола." :
                                                 "Incompatible protocol version.");
                    }

                    Login(out bool loggedIn, out _, out _, out string errorMessage);

                    if (loggedIn)
                    {
                        ClientState = ClientState.LoggedIn;
                        CommLog?.WriteAction("User is logged in");
                    }
                    else
                    {
                        throw new ScadaException(errorMessage);
                    }
                }
                else if (ClientState == ClientState.LoggedIn)
                {
                    ClearNetStream(netStream, inBuf);
                }
                else
                {
                    throw new ScadaException(Locale.IsRussian ?
                                             "Клиент не вошёл в систему. Попробуйте позже." :
                                             "Client is not logged in. Try again later.");
                }
            }
            catch
            {
                ClientState = ClientState.Error;
                throw;
            }
        }