コード例 #1
0
        private bool HandleMessage(byte[] buffer, int msgSize)
        {
            long currentTime = SystemUtils.currentTimeMillis();

            if ((buffer [2] & 1) == 0)
            {
                if (msgSize < 7)
                {
                    DebugLog("I msg too small!");
                    return(false);
                }

                if (firstIMessageReceived == false)
                {
                    firstIMessageReceived = true;
                    lastConfirmationTime  = currentTime;                    /* start timeout T2 */
                }

                int frameSendSequenceNumber = ((buffer [3] * 0x100) + (buffer [2] & 0xfe)) / 2;
                int frameRecvSequenceNumber = ((buffer [5] * 0x100) + (buffer [4] & 0xfe)) / 2;

                DebugLog("Received I frame: N(S) = " + frameSendSequenceNumber + " N(R) = " + frameRecvSequenceNumber);

                /* check the receive sequence number N(R) - connection will be closed on an unexpected value */
                if (frameSendSequenceNumber != receiveCount)
                {
                    DebugLog("Sequence error: Close connection!");
                    return(false);
                }

                if (CheckSequenceNumber(frameRecvSequenceNumber) == false)
                {
                    DebugLog("Sequence number check failed");
                    return(false);
                }

                receiveCount = (receiveCount + 1) % 32768;
                unconfirmedReceivedIMessages++;

                if (isActive)
                {
                    try {
                        ASDU asdu = new ASDU(parameters, buffer, 6, msgSize);

                        // push to handler thread for processing
                        DebugLog("Enqueue received I-message for processing");
                        receivedASDUs.Enqueue(asdu);
                    }
                    catch (ASDUParsingException e) {
                        DebugLog("ASDU parsing failed: " + e.Message);
                        return(false);
                    }
                }
                else
                {
                    // connection not activated --> skip message
                    DebugLog("Connection not activated. Skip I message");
                }
            }

            // Check for TESTFR_ACT message
            else if ((buffer [2] & 0x43) == 0x43)
            {
                DebugLog("Send TESTFR_CON");

                socketStream.Write(TESTFR_CON_MSG, 0, TESTFR_CON_MSG.Length);
            }

            // Check for STARTDT_ACT message
            else if ((buffer [2] & 0x07) == 0x07)
            {
                DebugLog("Send STARTDT_CON");

                this.isActive = true;

                this.server.Activated(this);

                socketStream.Write(STARTDT_CON_MSG, 0, TESTFR_CON_MSG.Length);
            }

            // Check for STOPDT_ACT message
            else if ((buffer [2] & 0x13) == 0x13)
            {
                DebugLog("Send STOPDT_CON");

                this.isActive = false;

                socketStream.Write(STOPDT_CON_MSG, 0, TESTFR_CON_MSG.Length);
            }

            // Check for TESTFR_CON message
            else if ((buffer [2] & 0x83) == 0x83)
            {
                DebugLog("Recv TESTFR_CON");

                outStandingTestFRConMessages = 0;
            }

            // S-message
            else if (buffer [2] == 0x01)
            {
                int seqNo = (buffer[4] + buffer[5] * 0x100) / 2;

                DebugLog("Recv S(" + seqNo + ") (own sendcounter = " + sendCount + ")");

                if (CheckSequenceNumber(seqNo) == false)
                {
                    return(false);
                }
            }
            else
            {
                DebugLog("Unknown message");
            }

            ResetT3Timeout();

            return(true);
        }
コード例 #2
0
        private void HandleConnection()
        {
            byte[] bytes = new byte[300];

            try {
                try {
                    running = true;

                    if (tlsSecInfo != null)
                    {
                        DebugLog("Setup TLS");

                        SslStream sslStream = new SslStream(socketStream, true, RemoteCertificateValidationCallback);

                        bool authenticationSuccess = false;

                        try {
                            sslStream.AuthenticateAsServer(tlsSecInfo.OwnCertificate, true, System.Security.Authentication.SslProtocols.Tls, false);

                            if (sslStream.IsAuthenticated == true)
                            {
                                socketStream          = sslStream;
                                authenticationSuccess = true;
                            }
                        }
                        catch (IOException e) {
                            if (e.GetBaseException() != null)
                            {
                                DebugLog("TLS authentication error: " + e.GetBaseException().Message);
                            }
                            else
                            {
                                DebugLog("TLS authentication error: " + e.Message);
                            }
                        }

                        if (authenticationSuccess == true)
                        {
                            socketStream = sslStream;
                        }
                        else
                        {
                            DebugLog("TLS authentication failed");
                            running = false;
                        }
                    }

                    if (running)
                    {
                        socketStream.ReadTimeout = 50;

                        callbackThread = new Thread(ProcessASDUs);
                        callbackThread.Start();

                        ResetT3Timeout();
                    }

                    while (running)
                    {
                        try {
                            // Receive the response from the remote device.
                            int bytesRec = receiveMessage(bytes);

                            if (bytesRec > 0)
                            {
                                DebugLog("RCVD: " + BitConverter.ToString(bytes, 0, bytesRec));

                                if (HandleMessage(bytes, bytesRec) == false)
                                {
                                    /* close connection on error */
                                    running = false;
                                }

                                if (unconfirmedReceivedIMessages >= parameters.W)
                                {
                                    lastConfirmationTime = SystemUtils.currentTimeMillis();

                                    unconfirmedReceivedIMessages = 0;
                                    SendSMessage();
                                }
                            }
                            else if (bytesRec == -1)
                            {
                                running = false;
                            }
                        }
                        catch (System.IO.IOException) {
                            running = false;
                        }

                        if (handleTimeouts() == false)
                        {
                            running = false;
                        }

                        if (running)
                        {
                            if (isActive)
                            {
                                SendWaitingASDUs();
                            }

                            Thread.Sleep(1);
                        }
                    }

                    isActive = false;

                    DebugLog("CLOSE CONNECTION!");

                    // Release the socket.

                    socket.Shutdown(SocketShutdown.Both);
                    socket.Close();

                    socketStream.Dispose();
                    socket.Dispose();

                    DebugLog("CONNECTION CLOSED!");
                } catch (ArgumentNullException ane) {
                    DebugLog("ArgumentNullException : " + ane.ToString());
                } catch (SocketException se) {
                    DebugLog("SocketException : " + se.ToString());
                } catch (Exception e) {
                    DebugLog("Unexpected exception : " + e.ToString());
                }
            } catch (Exception e) {
                DebugLog(e.ToString());
            }

            // unmark unconfirmed messages in server queue if k-buffer not empty
            if (oldestSentASDU != -1)
            {
                server.UnmarkAllASDUs();
            }

            server.Remove(this);

            if (callbackThreadRunning)
            {
                callbackThreadRunning = false;
                callbackThread.Join();
            }

            DebugLog("Connection thread finished");
        }
コード例 #3
0
 private void ResetT3Timeout()
 {
     nextT3Timeout = (UInt64)SystemUtils.currentTimeMillis() + (UInt64)(parameters.T3 * 1000);
 }
コード例 #4
0
        private void HandleConnection()
        {
            byte[] bytes = new byte[300];

            try {
                try {
                    running = true;

                    ResetT3Timeout();

                    while (running)
                    {
                        try {
                            // Receive the response from the remote device.
                            int bytesRec = receiveMessage(socket, bytes);

                            if (bytesRec != 0)
                            {
                                DebugLog("RCVD: " + BitConverter.ToString(bytes, 0, bytesRec));

                                if (HandleMessage(socket, bytes, bytesRec) == false)
                                {
                                    /* close connection on error */
                                    running = false;
                                }

                                if (unconfirmedReceivedIMessages >= parameters.W)
                                {
                                    lastConfirmationTime = SystemUtils.currentTimeMillis();

                                    unconfirmedReceivedIMessages = 0;
                                    SendSMessage();
                                }
                            }
                        } catch (SocketException) {
                            running = false;
                        }

                        if (handleTimeouts() == false)
                        {
                            running = false;
                        }

                        if (running)
                        {
                            if (isActive)
                            {
                                SendWaitingASDUs();
                            }

                            Thread.Sleep(1);
                        }
                    }

                    isActive = false;

                    DebugLog("CLOSE CONNECTION!");

                    // Release the socket.
                    socket.Shutdown(SocketShutdown.Both);
                    socket.Close();

                    DebugLog("CONNECTION CLOSED!");
                } catch (ArgumentNullException ane) {
                    DebugLog("ArgumentNullException : " + ane.ToString());
                } catch (SocketException se) {
                    DebugLog("SocketException : " + se.ToString());
                } catch (Exception e) {
                    DebugLog("Unexpected exception : " + e.ToString());
                }
            } catch (Exception e) {
                DebugLog(e.ToString());
            }

            callbackThreadRunning = false;

            // unmark unconfirmed messages in server queue if k-buffer not empty
            if (oldestSentASDU != -1)
            {
                server.UnmarkAllASDUs();
            }

            server.Remove(this);

            callbackThread.Join();

            DebugLog("Connection thread finished");
        }
コード例 #5
0
        /// <summary>
        /// 信息检查,按说每收到一条信息都要来这里检查。。。
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="buffer"></param>
        /// <param name="msgSize"></param>
        /// <returns></returns>
        private bool checkMessage(Socket socket, byte[] buffer, int msgSize)
        {
            //这里检测I帧和U帧,不知道为什么不检测S帧,难道是S帧已经处理过了?
            //update:似乎他这里只需要发送S帧,不主动监测S帧。。。
            if ((buffer[2] & 1) == 0)
            { /* I format frame */
                if (debugOutput)
                {
                    Console.WriteLine("Received I frame");
                }

                if (msgSize < 7)
                {
                    if (debugOutput)
                    {
                        Console.WriteLine("I msg too small!");
                    }

                    return(false);
                }

                receiveCount++;
                unconfirmedMessages++;

                long currentTime = SystemUtils.currentTimeMillis();

                if ((unconfirmedMessages > parameters.W) || checkConfirmTimeout(currentTime))
                {
                    //未确认消息超过W,或者t2超时,则发送S帧
                    lastConfirmationTime = currentTime;

                    unconfirmedMessages = 0;
                    sendSMessage();
                }

                //新建一个ASDU,准备解析
                ASDU asdu = new ASDU(parameters, buffer, msgSize);

                //解析ASDU
                if (asduReceivedHandler != null)
                {
                    asduReceivedHandler(asduReceivedHandlerParameter, asdu);
                }
            }
            else if ((buffer[2] & 0x03) == 0x03)
            {     /* U format frame */
                if (buffer[2] == 0x43)
                { // Check for TESTFR_ACT message
                    //收到了测试命令,回复测试确认
                    socket.Send(TESTFR_CON_MSG);
                }
                else if (buffer[2] == 0x07)
                { /* STARTDT ACT */
                    //收到了开启命令,回复开启命令确认
                    socket.Send(STARTDT_CON_MSG);
                }
                else if (buffer[2] == 0x0b)
                { /* STARTDT_CON */
                    //收到了开启确认,处理[已连接]事件
                    if (connectionHandler != null)
                    {
                        connectionHandler(connectionHandlerParameter, ConnectionEvent.STARTDT_CON_RECEIVED);
                    }
                }
                else if (buffer[2] == 0x23)
                { /* STOPDT_CON */
                    //收到了停止确认,处理[已断开]事件
                    if (connectionHandler != null)
                    {
                        connectionHandler(connectionHandlerParameter, ConnectionEvent.STOPDT_CON_RECEIVED);
                    }
                }
            }

            return(true);
        }
コード例 #6
0
ファイル: Connection.cs プロジェクト: yanvasilij/lib60870
        private bool checkMessage(Socket socket, byte[] buffer, int msgSize)
        {
            long currentTime = SystemUtils.currentTimeMillis();

            if ((buffer [2] & 1) == 0)               /* I format frame */

            {
                if (firstIMessageReceived == false)
                {
                    firstIMessageReceived = true;
                    lastConfirmationTime  = currentTime;                    /* start timeout T2 */
                }

                if (msgSize < 7)
                {
                    DebugLog("I msg too small!");
                    return(false);
                }

                int frameSendSequenceNumber = ((buffer [3] * 0x100) + (buffer [2] & 0xfe)) / 2;
                int frameRecvSequenceNumber = ((buffer [5] * 0x100) + (buffer [4] & 0xfe)) / 2;

                DebugLog("Received I frame: N(S) = " + frameSendSequenceNumber + " N(R) = " + frameRecvSequenceNumber);

                /* check the receive sequence number N(R) - connection will be closed on an unexpected value */
                if (frameSendSequenceNumber != receiveSequenceNumber)
                {
                    DebugLog("Sequence error: Close connection!");
                    return(false);
                }

                if (CheckSequenceNumber(frameRecvSequenceNumber) == false)
                {
                    return(false);
                }

                receiveSequenceNumber = (receiveSequenceNumber + 1) % 32768;
                unconfirmedReceivedIMessages++;

                try {
                    ASDU asdu = new ASDU(parameters, buffer, 6, msgSize);

                    if (asduReceivedHandler != null)
                    {
                        asduReceivedHandler(asduReceivedHandlerParameter, asdu);
                    }
                }
                catch (ASDUParsingException e) {
                    DebugLog("ASDU parsing failed: " + e.Message);
                    return(false);
                }
            }
            else if ((buffer [2] & 0x03) == 0x01)                 /* S format frame */
            {
                int seqNo = (buffer[4] + buffer[5] * 0x100) / 2;

                DebugLog("Recv S(" + seqNo + ") (own sendcounter = " + sendSequenceNumber + ")");

                if (CheckSequenceNumber(seqNo) == false)
                {
                    return(false);
                }
            }
            else if ((buffer [2] & 0x03) == 0x03)                 /* U format frame */

            {
                uMessageTimeout = 0;

                if (buffer [2] == 0x43)                   // Check for TESTFR_ACT message
                {
                    statistics.RcvdTestFrActCounter++;
                    DebugLog("RCVD TESTFR_ACT");
                    DebugLog("SEND TESTFR_CON");
                    socket.Send(TESTFR_CON_MSG);
                    statistics.SentMsgCounter++;
                }
                else if (buffer [2] == 0x83)                     /* TESTFR_CON */
                {
                    DebugLog("RCVD TESTFR_CON");
                    statistics.RcvdTestFrConCounter++;
                    outStandingTestFRConMessages = 0;
                }
                else if (buffer [2] == 0x07)                     /* STARTDT ACT */
                {
                    DebugLog("RCVD STARTDT_ACT");
                    socket.Send(STARTDT_CON_MSG);
                    statistics.SentMsgCounter++;
                }
                else if (buffer [2] == 0x0b)                     /* STARTDT_CON */
                {
                    DebugLog("RCVD STARTDT_CON");

                    if (connectionHandler != null)
                    {
                        connectionHandler(connectionHandlerParameter, ConnectionEvent.STARTDT_CON_RECEIVED);
                    }
                }
                else if (buffer [2] == 0x23)                     /* STOPDT_CON */
                {
                    DebugLog("RCVD STOPDT_CON");

                    if (connectionHandler != null)
                    {
                        connectionHandler(connectionHandlerParameter, ConnectionEvent.STOPDT_CON_RECEIVED);
                    }
                }
            }
            else
            {
                DebugLog("Unknown message type");
                return(false);
            }

            ResetT3Timeout();

            return(true);
        }
コード例 #7
0
ファイル: Connection.cs プロジェクト: yanvasilij/lib60870
        private void HandleConnection()
        {
            byte[] bytes = new byte[300];

            try {
                try {
                    connecting = true;

                    try {
                        // Connect to a remote device.
                        ConnectSocketWithTimeout();

                        DebugLog("Socket connected to " + socket.RemoteEndPoint.ToString());

                        if (autostart)
                        {
                            socket.Send(STARTDT_ACT_MSG);
                            statistics.SentMsgCounter++;
                        }

                        running     = true;
                        socketError = false;
                        connecting  = false;

                        if (connectionHandler != null)
                        {
                            connectionHandler(connectionHandlerParameter, ConnectionEvent.OPENED);
                        }
                    } catch (SocketException se) {
                        DebugLog("SocketException: " + se.ToString());

                        running       = false;
                        socketError   = true;
                        lastException = se;
                    }

                    if (running)
                    {
                        bool loopRunning = running;

                        while (loopRunning)
                        {
                            bool suspendThread = true;

                            try {
                                // Receive a message from from the remote device.
                                int bytesRec = receiveMessage(socket, bytes);

                                if (bytesRec > 0)
                                {
                                    DebugLog("RCVD: " + BitConverter.ToString(bytes, 0, bytesRec));

                                    statistics.RcvdMsgCounter++;

                                    bool handleMessage = true;

                                    if (rawMessageHandler != null)
                                    {
                                        handleMessage = rawMessageHandler(rawMessageHandlerParameter, bytes, bytesRec);
                                    }

                                    if (handleMessage)
                                    {
                                        if (checkMessage(socket, bytes, bytesRec) == false)
                                        {
                                            /* close connection on error */
                                            loopRunning = false;
                                        }
                                    }

                                    if (unconfirmedReceivedIMessages >= parameters.W)
                                    {
                                        lastConfirmationTime = SystemUtils.currentTimeMillis();

                                        unconfirmedReceivedIMessages = 0;
                                        SendSMessage();
                                    }

                                    suspendThread = false;
                                }
                                else if (bytesRec == -1)
                                {
                                    loopRunning = false;
                                }


                                if (handleTimeouts() == false)
                                {
                                    loopRunning = false;
                                }

                                if (isConnected() == false)
                                {
                                    loopRunning = false;
                                }

                                if (useSendMessageQueue)
                                {
                                    if (SendNextWaitingASDU() == true)
                                    {
                                        suspendThread = false;
                                    }
                                }

                                if (suspendThread)
                                {
                                    Thread.Sleep(10);
                                }
                            }
                            catch (SocketException) {
                                loopRunning = false;
                            }
                        }

                        DebugLog("CLOSE CONNECTION!");

                        // Release the socket.
                        try {
                            socket.Shutdown(SocketShutdown.Both);
                        }
                        catch (SocketException) {
                        }

                        socket.Close();

                        if (connectionHandler != null)
                        {
                            connectionHandler(connectionHandlerParameter, ConnectionEvent.CLOSED);
                        }
                    }
                } catch (ArgumentNullException ane) {
                    connecting = false;
                    DebugLog("ArgumentNullException: " + ane.ToString());
                } catch (SocketException se) {
                    DebugLog("SocketException: " + se.ToString());
                } catch (Exception e) {
                    DebugLog("Unexpected exception: " + e.ToString());
                }
            } catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            running    = false;
            connecting = false;
        }
コード例 #8
0
        private bool handleTimeouts()
        {
            UInt64 currentTime = (UInt64)SystemUtils.currentTimeMillis();

            if (currentTime > nextT3Timeout)
            {
                if (outStandingTestFRConMessages > 2)
                {
                    DebugLog("Timeout for TESTFR_CON message");

                    // close connection
                    return(false);
                }
                else
                {
                    socket.Send(TESTFR_ACT_MSG);
                    statistics.SentMsgCounter++;
                    DebugLog("U message T3 timeout");
                    uMessageTimeout = (UInt64)currentTime + (UInt64)(parameters.T1 * 1000);
                    outStandingTestFRConMessages++;
                    ResetT3Timeout();
                    if (sentMessageHandler != null)
                    {
                        sentMessageHandler(sentMessageHandlerParameter, TESTFR_ACT_MSG, 6);
                    }
                }
            }

            if (unconfirmedReceivedIMessages > 0)
            {
                if (checkConfirmTimeout((long)currentTime))
                {
                    lastConfirmationTime         = (long)currentTime;
                    unconfirmedReceivedIMessages = 0;

                    SendSMessage();                      /* send confirmation message */
                }
            }

            if (uMessageTimeout != 0)
            {
                if (currentTime > uMessageTimeout)
                {
                    DebugLog("U message T1 timeout");
                    throw new SocketException(10060);
                }
            }

            /* check if counterpart confirmed I messages */
            lock (sentASDUs) {
                if (oldestSentASDU != -1)
                {
                    if (((long)currentTime - sentASDUs [oldestSentASDU].sentTime) >= (parameters.T1 * 1000))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }