示例#1
0
        /// <summary>
        /// Gets an SCTP packet for a control (non-data) chunk.
        /// </summary>
        /// <param name="chunk">The control chunk to get a packet for.</param>
        /// <returns>A single control chunk SCTP packet.</returns>
        public SctpPacket GetControlPacket(SctpChunk chunk)
        {
            SctpPacket pkt = new SctpPacket(
                _sctpSourcePort,
                _sctpDestinationPort,
                _remoteVerificationTag);

            pkt.AddChunk(chunk);

            return(pkt);
        }
示例#2
0
        /// <summary>
        /// Sends a SCTP chunk to the remote party.
        /// </summary>
        /// <param name="chunk">The chunk to send.</param>
        internal void SendChunk(SctpChunk chunk)
        {
            if (!_wasAborted)
            {
                SctpPacket pkt = new SctpPacket(
                    _sctpSourcePort,
                    _sctpDestinationPort,
                    _remoteVerificationTag);

                pkt.AddChunk(chunk);

                byte[] buffer = pkt.GetBytes();

                _sctpTransport.Send(ID, buffer, 0, buffer.Length);
            }
        }
示例#3
0
        /// <summary>
        /// Creates the INIT ACK chunk and packet to send as a response to an SCTP
        /// packet containing an INIT chunk.
        /// </summary>
        /// <param name="initPacket">The received packet containing the INIT chunk.</param>
        /// <param name="remoteEP">Optional. The remote IP end point the INIT packet was
        /// received on. For transports that don't use an IP transport directly this parameter
        /// can be set to null and it will not form part of the COOKIE ECHO checks.</param>
        /// <returns>An SCTP packet with a single INIT ACK chunk.</returns>
        protected SctpPacket GetInitAck(SctpPacket initPacket, IPEndPoint remoteEP)
        {
            SctpInitChunk initChunk = initPacket.Chunks.Single(x => x.KnownType == SctpChunkType.INIT) as SctpInitChunk;

            SctpPacket initAckPacket = new SctpPacket(
                initPacket.Header.DestinationPort,
                initPacket.Header.SourcePort,
                initChunk.InitiateTag);

            var cookie = GetInitAckCookie(
                initPacket.Header.DestinationPort,
                initPacket.Header.SourcePort,
                initChunk.InitiateTag,
                initChunk.InitialTSN,
                initChunk.ARwnd,
                remoteEP != null ? remoteEP.ToString() : string.Empty,
                (int)(initChunk.CookiePreservative / 1000));

            var json       = cookie.ToJson();
            var jsonBuffer = Encoding.UTF8.GetBytes(json);

            using (HMACSHA256 hmac = new HMACSHA256(_hmacKey))
            {
                var result = hmac.ComputeHash(jsonBuffer);
                cookie.HMAC = result.HexStr();
            }

            var jsonWithHMAC       = cookie.ToJson();
            var jsonBufferWithHMAC = Encoding.UTF8.GetBytes(jsonWithHMAC);

            SctpInitChunk initAckChunk = new SctpInitChunk(
                SctpChunkType.INIT_ACK,
                cookie.Tag,
                cookie.TSN,
                cookie.ARwnd,
                SctpAssociation.DEFAULT_NUMBER_OUTBOUND_STREAMS,
                SctpAssociation.DEFAULT_NUMBER_INBOUND_STREAMS);

            initAckChunk.StateCookie = jsonBufferWithHMAC;
            initAckChunk.UnrecognizedPeerParameters = initChunk.UnrecognizedPeerParameters;

            initAckPacket.AddChunk(initAckChunk);

            return(initAckPacket);
        }
示例#4
0
        /// <summary>
        /// Send an SCTP packet with one of the error type chunks (ABORT or ERROR) to the remote peer.
        /// </summary>
        /// <param name=isAbort">Set to true to use an ABORT chunk otherwise an ERROR chunk will be used.</param>
        /// <param name="desintationPort">The SCTP destination port.</param>
        /// <param name="sourcePort">The SCTP source port.</param>
        /// <param name="initiateTag">If available the initial tag for the remote peer.</param>
        /// <param name="error">The error to send.</param>
        private void SendError(
            bool isAbort,
            ushort destinationPort,
            ushort sourcePort,
            uint initiateTag,
            ISctpErrorCause error)
        {
            SctpPacket errorPacket = new SctpPacket(
                destinationPort,
                sourcePort,
                initiateTag);

            SctpErrorChunk errorChunk = isAbort ? new SctpAbortChunk(true) : new SctpErrorChunk();

            errorChunk.AddErrorCause(error);
            errorPacket.AddChunk(errorChunk);

            var buffer = errorPacket.GetBytes();

            Send(null, buffer, 0, buffer.Length);
        }
示例#5
0
        /// <summary>
        /// Attempts to create an association with a remote party by sending an initialisation
        /// control chunk.
        /// </summary>
        private void SendInit()
        {
            if (!_wasAborted)
            {
                // A packet containing an INIT chunk MUST have a zero Verification Tag (RFC4960 Pg 15).
                SctpPacket init = new SctpPacket(_sctpSourcePort, _sctpDestinationPort, 0);

                SctpInitChunk initChunk = new SctpInitChunk(
                    SctpChunkType.INIT,
                    VerificationTag,
                    TSN,
                    ARwnd,
                    _numberOutboundStreams,
                    _numberInboundStreams);
                init.AddChunk(initChunk);

                SetState(SctpAssociationState.CookieWait);

                byte[] buffer = init.GetBytes();
                _sctpTransport.Send(ID, buffer, 0, buffer.Length);

                _t1Init = new Timer(T1InitTimerExpired, init, T1_INIT_TIMER_MILLISECONDS, T1_INIT_TIMER_MILLISECONDS);
            }
        }