示例#1
0
        public int Send(Iec61850State iecs)
        {
            // Make COTP data telegramm
            int offs       = IsoTpkt.TPKT_SIZEOF;
            int maxLen     = 1 << options.tpduSize;       // max COTP len
            int maxDataLen = maxLen - COTP_HDR_DT_SIZEOF; // max DATA len

            if (iecs.sendBytes <= maxDataLen)
            {
                // Original handling, same as before / short datagram without fragmenting
                iecs.sendBuffer[offs++] = COTP_HDR_DT_SIZEOF - 1; // cotp.hdrlen wihout this field
                iecs.sendBuffer[offs++] = COTP_CODE_DT;           // code
                iecs.sendBuffer[offs++] = COTP_PACKET_COMPLETE;   // number "complete" for "short" datagrams

                iecs.sendBytes += offs;
                IsoTpkt.Send(iecs);
            }
            else
            {
                // Long data, need to fragment to TPKT + COTP fragments
                // Technique: allocate a new buffer. Keep the original data.
                // Copy original data "per partes" to the new buffer, adding TPKT and COTP headers
                // and sending the fragments via TCP.
                // Last COTP fragments must be marked 0x80, others 0x00
                // Possible optimization: for the first fragment use the original buffer (spare 1 copy operation) NOT IMPLEMENTED
                int    dLen         = iecs.sendBytes;  // Actual data length
                int    sLen         = 0;               // Actual sent data length
                byte[] originalData = iecs.sendBuffer;
                iecs.sendBuffer   = dataReserveBuffer; // Use saved / recycled buffer
                dataReserveBuffer = originalData;      // Save original buffer to reserve for future use / recycling saves allocation oper.
                const int dOffs = IsoTpkt.TPKT_SIZEOF + COTP_HDR_DT_SIZEOF;

                while (dLen > 0)
                {
                    iecs.sendBytes = Math.Min(dLen, maxDataLen);
                    Array.Copy(originalData, dOffs + sLen, iecs.sendBuffer, dOffs, iecs.sendBytes);
                    dLen -= iecs.sendBytes;
                    sLen += iecs.sendBytes;

                    offs = IsoTpkt.TPKT_SIZEOF;                                                                 // reinit offset
                    iecs.sendBuffer[offs++] = COTP_HDR_DT_SIZEOF - 1;                                           // cotp.hdrlen wihout this field
                    iecs.sendBuffer[offs++] = COTP_CODE_DT;                                                     // code
                    iecs.sendBuffer[offs++] = (byte)((dLen > 0) ? COTP_PACKET_FRAGMENT : COTP_PACKET_COMPLETE); // number "fragment" or "complete"

                    iecs.sendBytes += offs;
                    IsoTpkt.Send(iecs);
                }
            }
            return(0);
        }
示例#2
0
        private static void ReceiveCallback(IAsyncResult ar)
        {
            // Retrieve the socket from the state object.
            TcpState tcps = (TcpState)ar.AsyncState;

            try
            {
                // Complete the connection.
                if (tcps.workSocket != null)
                {
                    if (tcps.workSocket.Poll(5000, SelectMode.SelectRead) && tcps.workSocket.Available == 0)
                    {
                        //socket not connected, close it if it's still running
                        tcps.workSocket.Close();
                        tcps.workSocket = null;
                        tcps.logger.LogError("Socket disconnected (detected in ReceiveCallback)");
                        tcps.tstate = TcpProtocolState.TCP_STATE_SHUTDOWN;
                    }
                    else
                    {
                        try
                        {
                            tcps.recvBytes = tcps.workSocket.EndReceive(ar);
                            //Console.WriteLine("ReceiveCallback: Data received {0}",
                            //    tcps.recvBytes.ToString());
                        } catch (Exception e) {
                            tcps.logger.LogError(e.Message);
                        }

                        try {
                            IsoTpkt.Parse(tcps);
                        }
                        catch (Exception e)
                        {
                            tcps.logger.LogError(e.Message);
                        }
                        // Signal that the data has been received.
                        tcps.receiveDone.Set();
                    }
                }
            }
            catch (Exception e)
            {
                //   StopClient(tcps);
                //    tcps.logger.LogInfo(e.ToString());
            }
        }
示例#3
0
        public int SendInit(Iec61850State iecs)
        {
            //Reset dstref
            Reset(iecs.cp);

            // Make COTP init telegramm
            int offs  = IsoTpkt.TPKT_SIZEOF;
            int optof = COTP_HDR_IDX_OPTION;

            iecs.sendBuffer[offs + COTP_HDR_IDX_HDRLEN] = (byte)(COTP_HDR_CR_SIZEOF + options.getSize());

            iecs.sendBuffer[offs + COTP_HDR_IDX_CODE] = COTP_CODE_CR;
            Array.Copy(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(m_COTP_dstref)), 0, iecs.sendBuffer, offs + COTP_HDR_IDX_DSTREF, 2);
            Array.Copy(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(m_COTP_srcref)), 0, iecs.sendBuffer, offs + COTP_HDR_IDX_SRCREF, 2);
            iecs.sendBuffer[offs + optof++] = m_COTP_option;

            // Parameters
            iecs.sendBuffer[offs + optof++] = COTP_PCODE_TSIZ;
            iecs.sendBuffer[offs + optof++] = 1;
            iecs.sendBuffer[offs + optof++] = options.tpduSize;
            if (options.tSelDst.size > 0)
            {
                iecs.sendBuffer[offs + optof++] = COTP_PCODE_DSAP;
                iecs.sendBuffer[offs + optof++] = options.tSelDst.size;
                byte[] bt = options.tSelDst.GetBytes();
                Array.Copy(bt, 0, iecs.sendBuffer, offs + optof, options.tSelDst.size);
                optof += options.tSelDst.size;
            }

            if (options.tSelSrc.size > 0)
            {
                iecs.sendBuffer[offs + optof++] = COTP_PCODE_SSAP;
                iecs.sendBuffer[offs + optof++] = options.tSelSrc.size;
                Array.Copy(options.tSelSrc.GetBytes(), 0, iecs.sendBuffer, offs + optof, options.tSelSrc.size);
            }

            iecs.sendBytes = offs + COTP_HDR_CR_SIZEOF + 1 + options.getSize();

            IsoTpkt.Send(iecs);
            return(0);
        }
示例#4
0
        int fastSend(Iec61850State iecs)
        {
            // Make COTP data telegramm directly
            int offs = IsoTpkt.TPKT_SIZEOF;

            // MMS already encoded in iecs.msMMSout
            iecs.sendBytes = (int)iecs.msMMSout.Length;

            iecs.sendBuffer[offs++] = 0x02;                                                                                                 // cotp.hdrlen
            iecs.sendBuffer[offs++] = IsoCotp.COTP_CODE_DT;                                                                                 // code
            iecs.sendBuffer[offs++] = 0x80;                                                                                                 // number "complete"
            iecs.sendBuffer[offs++] = 0x01;                                                                                                 // giveTokensPDU.type
            iecs.sendBuffer[offs++] = 0x00;                                                                                                 // giveTokensPDU.hdrlen
            iecs.sendBuffer[offs++] = 0x01;                                                                                                 // dataTransferPDU.type
            iecs.sendBuffer[offs++] = 0x00;                                                                                                 // dataTransferPDU.hdrlen

            iecs.sendBuffer[offs++] = 0x61;                                                                                                 // pres.dtpdu_tag
            iecs.sendBuffer[offs++] = 0x82;                                                                                                 // pres.dtpdu_len_code
            Array.Copy(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)(iecs.sendBytes + 15 - 4))), 0, iecs.sendBuffer, offs, 2); // pres.dtpdu_len
            offs += 2;
            iecs.sendBuffer[offs++] = 0x30;                                                                                                 // pres.sequ_tag
            iecs.sendBuffer[offs++] = 0x82;                                                                                                 // pres.sequ_len_code
            Array.Copy(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)(iecs.sendBytes + 15 - 8))), 0, iecs.sendBuffer, offs, 2); // pres.sequ_len
            offs += 2;
            iecs.sendBuffer[offs++] = 0x02;                                                                                                 // pres.context_tag
            iecs.sendBuffer[offs++] = 0x01;                                                                                                 // pres.context_len
            iecs.sendBuffer[offs++] = 0x03;                                                                                                 // pres.context_val
            iecs.sendBuffer[offs++] = 0xa0;                                                                                                 // pres.data_tag
            iecs.sendBuffer[offs++] = 0x82;                                                                                                 // pres.data_len_code
            Array.Copy(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)(iecs.sendBytes))), 0, iecs.sendBuffer, offs, 2);          // pres.sequ_len
            offs += 2;

            iecs.msMMSout.Seek(0, SeekOrigin.Begin);
            iecs.msMMSout.Read(iecs.sendBuffer, offs, iecs.sendBytes);

            iecs.sendBytes += offs;
            IsoTpkt.Send(iecs);
            return(0);
        }