/// <summary>
        /// Gets a cookie to send in an INIT ACK chunk. This SCTP
        /// transport for a WebRTC peer connection needs to use the same
        /// local tag and TSN in every chunk as only a single association
        /// is ever maintained.
        /// </summary>
        protected override SctpTransportCookie GetInitAckCookie(
            ushort sourcePort,
            ushort destinationPort,
            uint remoteTag,
            uint remoteTSN,
            uint remoteARwnd,
            string remoteEndPoint,
            int lifeTimeExtension = 0)
        {
            var cookie = new SctpTransportCookie
            {
                SourcePort      = sourcePort,
                DestinationPort = destinationPort,
                RemoteTag       = remoteTag,
                RemoteTSN       = remoteTSN,
                RemoteARwnd     = remoteARwnd,
                RemoteEndPoint  = remoteEndPoint,
                Tag             = RTCSctpAssociation.VerificationTag,
                TSN             = RTCSctpAssociation.TSN,
                ARwnd           = SctpAssociation.DEFAULT_ADVERTISED_RECEIVE_WINDOW,
                CreatedAt       = DateTime.Now.ToString("o"),
                Lifetime        = DEFAULT_COOKIE_LIFETIME_SECONDS + lifeTimeExtension,
                HMAC            = string.Empty
            };

            return(cookie);
        }
Exemple #2
0
        /// <summary>
        /// Create a new SCTP association instance from the cookie that was previously
        /// sent to the remote party in an INIT ACK chunk.
        /// </summary>
        public SctpAssociation(
            SctpTransport sctpTransport,
            SctpTransportCookie cookie,
            int localTransportPort)
        {
            _sctpTransport = sctpTransport;
            ID             = $"{cookie.SourcePort}:{cookie.DestinationPort}:{localTransportPort}";
            State          = SctpAssociationState.Closed;

            GotCookie(cookie);
        }
Exemple #3
0
        /// <summary>
        /// Initialises the association state based on the echoed cookie (the cookie that we sent
        /// to the remote party and was then echoed back to us). An association can only be initialised
        /// from a cookie prior to it being used and prior to it ever having entered the established state.
        /// </summary>
        /// <param name="cookie">The echoed cookie that was returned from the remote party.</param>
        public void GotCookie(SctpTransportCookie cookie)
        {
            // The CookieEchoed state is allowed, even though a cookie should be creating a brand
            // new association rather than one that has already sent an INIT, in order to deal with
            // a race condition where both SCTP end points attempt to establish the association at
            // the same time using the same ports.
            if (_wasAborted || _wasShutdown)
            {
                logger.LogWarning($"SCTP association cannot initialise with a cookie after an abort or shutdown.");
            }
            else if (!(State == SctpAssociationState.Closed || State == SctpAssociationState.CookieEchoed))
            {
                throw new ApplicationException($"SCTP association cannot initialise with a cookie in state {State}.");
            }
            else
            {
                _sctpSourcePort      = cookie.SourcePort;
                _sctpDestinationPort = cookie.DestinationPort;
                VerificationTag      = cookie.Tag;
                ARwnd       = cookie.ARwnd;
                Destination = !string.IsNullOrEmpty(cookie.RemoteEndPoint) ?
                              IPSocket.Parse(cookie.RemoteEndPoint) : null;

                if (_dataReceiver == null)
                {
                    _dataReceiver = new SctpDataReceiver(ARwnd, _defaultMTU, cookie.RemoteTSN);
                }

                if (_dataSender == null)
                {
                    _dataSender = new SctpDataSender(ID, this.SendChunk, _defaultMTU, cookie.TSN, cookie.RemoteARwnd);
                }

                InitRemoteProperties(cookie.RemoteTag, cookie.RemoteTSN, cookie.RemoteARwnd);

                var cookieAckChunk = new SctpChunk(SctpChunkType.COOKIE_ACK);
                SendChunk(cookieAckChunk);

                SetState(SctpAssociationState.Established);
                _dataSender.StartSending();
                CancelTimers();
            }
        }