AddUsernameAttribute() public method

public AddUsernameAttribute ( string username ) : void
username string
return void
コード例 #1
0
        /// <summary>
        /// Performs a connectivity check for a single candidate pair entry.
        /// </summary>
        /// <param name="candidatePair">The candidate pair to perform a connectivity check for.</param>
        /// <param name="setUseCandidate">If true indicates we are acting as the "controlling" ICE agent
        /// and are nominating this candidate as the chosen one.</param>
        /// <remarks>As specified in https://tools.ietf.org/html/rfc8445#section-7.2.4.</remarks>
        private void SendConnectivityCheck(ChecklistEntry candidatePair, bool setUseCandidate)
        {
            candidatePair.State           = ChecklistEntryState.InProgress;
            candidatePair.LastCheckSentAt = DateTime.Now;
            candidatePair.ChecksSent++;
            candidatePair.RequestTransactionID = Crypto.GetRandomString(STUNv2Header.TRANSACTION_ID_LENGTH);

            IPEndPoint remoteEndPoint = candidatePair.RemoteCandidate.GetEndPoint();

            logger.LogDebug($"Sending ICE connectivity check from {_rtpChannel.RTPLocalEndPoint} to {remoteEndPoint} (use candidate {setUseCandidate}).");

            STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);

            stunRequest.Header.TransactionId = Encoding.ASCII.GetBytes(candidatePair.RequestTransactionID);
            stunRequest.AddUsernameAttribute(RemoteIceUser + ":" + LocalIceUser);
            stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, BitConverter.GetBytes(candidatePair.Priority)));

            if (setUseCandidate)
            {
                stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));
            }

            byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(RemoteIcePassword, true);

            _rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, remoteEndPoint, stunReqBytes);
        }
コード例 #2
0
        public void BindingRequestWithUsernameToBytesUnitTest()
        {
            Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);

            STUNv2Message initMessage = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
            initMessage.AddUsernameAttribute("someusernamex");
            byte[] stunMessageBytes = initMessage.ToByteBuffer(null, false);

            Console.WriteLine(BitConverter.ToString(stunMessageBytes));

            Assert.IsTrue(stunMessageBytes.Length % 4 == 0);
        }
コード例 #3
0
        /// <summary>
        /// Performs a connectivity check for a single candidate pair entry.
        /// </summary>
        /// <param name="candidatePair">The candidate pair to perform a connectivity check for.</param>
        /// <remarks>As specified in https://tools.ietf.org/html/rfc8445#section-7.2.4.</remarks>
        private void DoConnectivityCheck(ChecklistEntry candidatePair)
        {
            candidatePair.State = ChecklistEntryState.InProgress;

            IPAddress  remoteAddress  = IPAddress.Parse(candidatePair.RemoteCandidate.address);
            IPEndPoint remoteEndPoint = new IPEndPoint(remoteAddress, candidatePair.RemoteCandidate.port);

            logger.LogDebug($"Sending ICE connectivity check from {_rtpChannel.RTPLocalEndPoint} to {remoteEndPoint}.");

            string localUser = LocalIceUser;

            STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);

            stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
            stunRequest.AddUsernameAttribute(RemoteIceUser + ":" + localUser);
            stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
            stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));
            byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(RemoteIcePassword, true);

            _rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, remoteEndPoint, stunReqBytes);

            //localIceCandidate.LastSTUNSendAt = DateTime.Now;
        }
コード例 #4
0
        /// <summary>
        /// Periodically send a STUN binding request to check connectivity.
        /// </summary>
        /// <param name="stateInfo">Not used.</param>
        private void SendStunConnectivityChecks(Object stateInfo)
        {
            try
            {
                //logger.LogDebug($"Send STUN connectivity checks, local candidates {LocalIceCandidates.Count()}, remote candidates {_remoteIceCandidates.Count()}.");

                // If one of the ICE candidates has the remote RTP socket set then the negotiation is complete and the STUN checks are to keep the connection alive.
                if (RemoteIceUser != null && RemoteIcePassword != null)
                {
                    if (IsConnected)
                    {
                        // Remote RTP endpoint gets set when the DTLS negotiation is finished.
                        if (RemoteEndPoint != null)
                        {
                            //logger.LogDebug("Sending STUN connectivity check to client " + iceCandidate.RemoteRtpEndPoint + ".");

                            string localUser = LocalIceUser;

                            STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                            stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                            stunRequest.AddUsernameAttribute(RemoteIceUser + ":" + localUser);
                            stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                            stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));   // Must send this to get DTLS started.
                            byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(RemoteIcePassword, true);

                            _rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, RemoteEndPoint, stunReqBytes);

                            _lastStunSentAt = DateTime.Now;
                        }

                        if (_lastCommunicationAt != DateTime.MinValue)
                        {
                            var secondsSinceLastResponse = DateTime.Now.Subtract(_lastCommunicationAt).TotalSeconds;

                            if (secondsSinceLastResponse > ICE_CONNECTED_NO_COMMUNICATIONS_TIMEOUT_SECONDS)
                            {
                                logger.LogWarning($"No packets have been received from {RemoteEndPoint} within the last {secondsSinceLastResponse:#} seconds, closing session.");
                                Close("Inactivity timeout.");
                            }
                        }
                    }
                    else
                    {
                        if (_remoteIceCandidates.Count() > 0)
                        {
                            foreach (var localIceCandidate in LocalIceCandidates.Where(x => x.IsStunLocalExchangeComplete == false && x.StunConnectionRequestAttempts < MAXIMUM_STUN_CONNECTION_ATTEMPTS))
                            {
                                localIceCandidate.StunConnectionRequestAttempts++;

                                // ToDo: Include srflx and relay addresses.

                                // Only supporting UDP candidates at this stage.
                                foreach (var remoteIceCandidate in RemoteIceCandidates.Where(x => x.Transport.ToLower() == "udp" && x.NetworkAddress.NotNullOrBlank() && x.HasConnectionError == false))
                                {
                                    try
                                    {
                                        IPAddress remoteAddress = IPAddress.Parse(remoteIceCandidate.NetworkAddress);

                                        logger.LogDebug($"Sending authenticated STUN binding request {localIceCandidate.StunConnectionRequestAttempts} from {_rtpChannel.RTPLocalEndPoint} to WebRTC peer at {remoteIceCandidate.NetworkAddress}:{remoteIceCandidate.Port}.");

                                        string localUser = LocalIceUser;

                                        STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                                        stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                                        stunRequest.AddUsernameAttribute(RemoteIceUser + ":" + localUser);
                                        stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                                        stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));
                                        byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(RemoteIcePassword, true);

                                        _rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, new IPEndPoint(IPAddress.Parse(remoteIceCandidate.NetworkAddress), remoteIceCandidate.Port), stunReqBytes);

                                        localIceCandidate.LastSTUNSendAt = DateTime.Now;
                                    }
                                    catch (System.Net.Sockets.SocketException sockExcp)
                                    {
                                        logger.LogWarning($"SocketException sending STUN request to {remoteIceCandidate.NetworkAddress}:{remoteIceCandidate.Port}, removing candidate. {sockExcp.Message}");
                                        remoteIceCandidate.HasConnectionError = true;
                                    }
                                }
                            }
                        }
                    }
                }

                if (!IsClosed)
                {
                    var interval = GetNextStunCheckInterval(STUN_CHECK_BASE_PERIOD_MILLISECONDS);

                    if (m_stunChecksTimer == null)
                    {
                        m_stunChecksTimer = new Timer(SendStunConnectivityChecks, null, interval, interval);
                    }
                    else
                    {
                        m_stunChecksTimer.Change(interval, interval);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SendStunConnectivityCheck. " + excp);
                //m_stunChecksTimer?.Dispose();
            }
        }
コード例 #5
0
ファイル: RTSPSession.cs プロジェクト: Dawn2Yuan/sipsorcery
        private void RTPReceive()
        {
            try
            {
                Thread.CurrentThread.Name = "rtspsess-rtprecv";

                byte[] buffer = new byte[2048];

                while (!_closed)
                {
                    try
                    {
                        EndPoint remoteEP = (EndPoint)new IPEndPoint(IPAddress.Any, 0);

                        //int bytesRead = _rtpSocket.Receive(buffer);
                        int bytesRead = _rtpSocket.ReceiveFrom(buffer, ref remoteEP);

                        IPEndPoint remoteIPEndPoint = remoteEP as IPEndPoint;

                        //logger.Debug("RTPReceive from " + remoteEP + ".");

                        //if (((IPEndPoint)remoteEP).Address.ToString() != _remoteEndPoint.Address.ToString())
                        //{
                        //    var oldEndPoint = _remoteEndPoint;
                        //    _remoteEndPoint = remoteEP as IPEndPoint;
                        //    logger.Warn("RtspSession " + _sessionID + " switched to new remote endpoint at " + _remoteEndPoint + " (old end point " + oldEndPoint + ").");
                        //}

                        if (bytesRead > 0)
                        {
                            _rtpLastActivityAt = DateTime.Now;

                            if (bytesRead > RTPHeader.MIN_HEADER_LEN)
                            {
                                if ((buffer[0] >= 20) && (buffer[0] <= 64))
                                {
                                    // DTLS.
                                    if(OnDtlsReceive != null)
                                    {
                                        try
                                        {
                                            OnDtlsReceive(buffer, bytesRead, SendRTPRaw);
                                        }
                                        catch(Exception dtlsExcp)
                                        {
                                            logger.Error("Exception RTSPSession.RTPReceive DTLS. " + dtlsExcp);
                                        }
                                    }
                                    else
                                    {
                                        logger.Warn("RTSPSession.RTPReceive received a DTLS packet from " + _remoteEndPoint + "but bo DTLS handler has been set.");
                                    }
                                }
                                else if ((buffer[0] == 0) || (buffer[0] == 1))
                                {
                                    // STUN.
                                    if (_iceState != null)
                                    {
                                        try
                                        {
                                            STUNv2Message stunMessage = STUNv2Message.ParseSTUNMessage(buffer, bytesRead);

                                            //logger.Debug("STUN message received from Receiver Client @ " + stunMessage.Header.MessageType + ".");

                                            if (stunMessage.Header.MessageType == STUNv2MessageTypesEnum.BindingRequest)
                                            {
                                                //logger.Debug("Sending STUN response to Receiver Client @ " + remoteEndPoint + ".");

                                                STUNv2Message stunResponse = new STUNv2Message(STUNv2MessageTypesEnum.BindingSuccessResponse);
                                                stunResponse.Header.TransactionId = stunMessage.Header.TransactionId;
                                                stunResponse.AddXORMappedAddressAttribute(remoteIPEndPoint.Address, remoteIPEndPoint.Port);
                                                byte[] stunRespBytes = stunResponse.ToByteBuffer(_iceState.SenderPassword, true);
                                                _rtpSocket.SendTo(stunRespBytes, remoteIPEndPoint);

                                                //logger.Debug("Sending Binding request to Receiver Client @ " + remoteEndPoint + ".");

                                                STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                                                stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                                                stunRequest.AddUsernameAttribute(_iceState.ReceiverUser + ":" + _iceState.SenderUser);
                                                stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                                                stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));   // Must send this to get DTLS started.
                                                byte[] stunReqBytes = stunRequest.ToByteBuffer(_iceState.ReceiverPassword, true);
                                                _rtpSocket.SendTo(stunReqBytes, remoteIPEndPoint);

                                                _iceState.LastSTUNMessageReceivedAt = DateTime.Now;
                                            }
                                            else if (stunMessage.Header.MessageType == STUNv2MessageTypesEnum.BindingSuccessResponse)
                                            {
                                                if (!_iceState.IsSTUNExchangeComplete)
                                                {
                                                    _iceState.IsSTUNExchangeComplete = true;
                                                    logger.Debug("WebRTC client STUN exchange complete for " + remoteIPEndPoint.ToString() + " and ICE ufrag " + _iceState.ReceiverUser + ".");

                                                    _remoteEndPoint = remoteIPEndPoint;
                                                }
                                            }
                                            else if (stunMessage.Header.MessageType == STUNv2MessageTypesEnum.BindingErrorResponse)
                                            {
                                                //logger.Warn("A STUN binding error response was received from " + remoteIPEndPoint + ".");
                                            }
                                            else
                                            {
                                                //logger.Warn("An unrecognised STUN request was received from " + remoteIPEndPoint + ".");
                                            }
                                        }
                                        catch (SocketException sockExcp)
                                        {
                                            logger.Debug("RTPSession.RTPReceive STUN processing (" + remoteIPEndPoint + "). " + sockExcp.Message);
                                            continue;
                                        }
                                        catch (Exception stunExcp)
                                        {
                                            logger.Warn("Exception RTPSession.RTPReceive STUN processing (" + remoteIPEndPoint + "). " + stunExcp);
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        //logger.Warn("A STUN reponse was received on RTP socket from " + remoteIPEndPoint + " but no ICE state was set.");
                                    }
                                }
                                else if ((buffer[0] >= 128) && (buffer[0] <= 191))
                                {
                                    if (buffer[1] == 0xC8 /* RTCP SR */ || buffer[1] == 0xC9 /* RTCP RR */)
                                    {
                                        // RTCP packet.
                                    }
                                    else
                                    {
                                        // RTP Packet.

                                        RTPPacket rtpPacket = new RTPPacket(buffer.Take(bytesRead).ToArray());

                                        //System.Diagnostics.Debug.WriteLine("RTPReceive ssrc " + rtpPacket.Header.SyncSource + ", seq num " + rtpPacket.Header.SequenceNumber + ", timestamp " + rtpPacket.Header.Timestamp + ", marker " + rtpPacket.Header.MarkerBit + ".");
                                        //logger.Debug("RTPReceive remote " + remoteIPEndPoint + ", ssrc " + rtpPacket.Header.SyncSource + ", seq num " + rtpPacket.Header.SequenceNumber + ", timestamp " + rtpPacket.Header.Timestamp + ", bytes " + bytesRead + ", marker " + rtpPacket.Header.MarkerBit + ".");

                                        lock (_packets)
                                        {
                                            if (_packets.Count > RTP_PACKETS_MAX_QUEUE_LENGTH)
                                            {
                                                System.Diagnostics.Debug.WriteLine("RTSPSession.RTPReceive packets queue full, clearing.");
                                                logger.Warn("RTSPSession.RTPReceive packets queue full, clearing.");

                                                _packets.Clear();

                                                if (OnRTPQueueFull != null)
                                                {
                                                    OnRTPQueueFull();
                                                }
                                            }
                                            else
                                            {
                                                _packets.Enqueue(rtpPacket);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                logger.Warn("RTSPSession.RTPReceive an unrecognised packet was received for session ID " + SessionID + " and " + remoteIPEndPoint + ".");
                            }
                        }
                        else
                        {
                            logger.Warn("Zero bytes read from RTSPSession RTP socket for session ID " + SessionID + " and " + remoteIPEndPoint + ".");
                            break;
                        }
                    }
                    catch (SocketException sockExcp)
                    {
                        if (!_closed)
                        {
                            _rtpSocketError = sockExcp.SocketErrorCode;

                            if (_rtpSocketError == SocketError.Interrupted)
                            {
                                // If the receive has been interrupted it means the socket has been closed most likely as a result of an RTSP TEARDOWN request.
                                if (OnRTPSocketDisconnected != null)
                                {
                                    OnRTPSocketDisconnected(_sessionID);
                                }
                                break;
                            }
                            else
                            {
                                throw;
                            }
                        }
                    }
                    catch (Exception excp)
                    {
                        if (!_closed)
                        {
                            logger.Error("Exception RTSPSession.RTPReceive receiving. " + excp);
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                if (!_closed)
                {
                    logger.Error("Exception RTSPSession.RTPReceive. " + excp);

                    if (OnRTPSocketDisconnected != null)
                    {
                        OnRTPSocketDisconnected(_sessionID);
                    }
                }
            }
        }
コード例 #6
0
        private void SendStunConnectivityChecks()
        {
            try
            {
                while (!IsClosed)
                {
                    try
                    {
                        // If one of the ICE candidates has the remote RTP socket set then the negotiation is complete and the STUN checks are to keep the connection alive.
                        if (LocalIceCandidates.Any(x => x.IsConnected == true))
                        {
                            var iceCandidate = LocalIceCandidates.First(x => x.IsConnected == true);

                            // Remote RTP endpoint gets set when the DTLS negotiation is finished.
                            if (iceCandidate.RemoteRtpEndPoint != null)
                            {
                                //logger.Debug("Sending STUN connectivity check to client " + iceCandidate.RemoteRtpEndPoint + ".");

                                STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                                stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                                stunRequest.AddUsernameAttribute(RemoteIceUser + ":" + LocalIceUser);
                                stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                                stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));   // Must send this to get DTLS started.
                                byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(RemoteIcePassword, true);

                                iceCandidate.LocalRtpSocket.SendTo(stunReqBytes, iceCandidate.RemoteRtpEndPoint);

                                iceCandidate.LastSTUNSendAt = DateTime.Now;
                            }

                            var secondsSinceLastResponse = DateTime.Now.Subtract(iceCandidate.LastCommunicationAt).TotalSeconds;

                            if (secondsSinceLastResponse > ICE_TIMEOUT_SECONDS)
                            {
                                logger.Warn("No STUN response was received on a connected ICE connection for " + secondsSinceLastResponse + "s, closing connection.");

                                iceCandidate.IsDisconnected = true;

                                if (LocalIceCandidates.Any(x => x.IsConnected == true) == false)
                                {
                                    // If there are no connected local candidates left close the peer.
                                    Close();
                                    break;
                                }
                            }
                        }
                        else
                        {
                            if (_remoteIceCandidates.Count() > 0)
                            {
                                foreach (var localIceCandidate in LocalIceCandidates.Where(x => x.IsStunLocalExchangeComplete == false && x.StunConnectionRequestAttempts < MAXIMUM_STUN_CONNECTION_ATTEMPTS))
                                {
                                    localIceCandidate.StunConnectionRequestAttempts++;

                                    // ToDo: Include srflx and relay addresses.

                                    foreach (var remoteIceCandidate in RemoteIceCandidates.Where(x => x.Transport != "tcp" && x.NetworkAddress.NotNullOrBlank()))   // Only supporting UDP candidates at this stage.
                                    {
                                        IPAddress remoteAddress = IPAddress.Parse(remoteIceCandidate.NetworkAddress);

                                        logger.Debug("Sending authenticated STUN binding request " + localIceCandidate.StunConnectionRequestAttempts + " from " + localIceCandidate.LocalRtpSocket.LocalEndPoint + " to WebRTC peer at " + remoteIceCandidate.NetworkAddress + ":" + remoteIceCandidate.Port + ".");

                                        STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                                        stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                                        stunRequest.AddUsernameAttribute(RemoteIceUser + ":" + LocalIceUser);
                                        stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                                        stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));   // Must send this to get DTLS started.
                                        byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(RemoteIcePassword, true);

                                        localIceCandidate.LocalRtpSocket.SendTo(stunReqBytes, new IPEndPoint(IPAddress.Parse(remoteIceCandidate.NetworkAddress), remoteIceCandidate.Port));

                                        localIceCandidate.LastSTUNSendAt = DateTime.Now;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception excp)
                    {
                        logger.Error("Exception SendStunConnectivityCheck ConnectivityCheck. " + excp);
                    }

                    if (!IsClosed)
                    {
                        Thread.Sleep(ESTABLISHED_STUN_BINDING_PERIOD_MILLISECONDS);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SendStunConnectivityCheck. " + excp);
            }
        }
コード例 #7
0
ファイル: RTPChannel.cs プロジェクト: Dawn2Yuan/sipsorcery
        private void RTPReceive()
        {
            try
            {
                Thread.CurrentThread.Name = "rtpchanrecv-" + _rtpPort;

                byte[] buffer = new byte[2048];

                while (!_isClosed)
                {
                    try
                    {
                        int bytesRead = _rtpSocket.Receive(buffer);

                        if (bytesRead > 0)
                        {
                            _rtpSocket.SendTo(buffer, bytesRead, SocketFlags.None, _wiresharkEP);

                            _rtpLastActivityAt = DateTime.Now;

                            if (bytesRead > RTPHeader.MIN_HEADER_LEN)
                            {
                                if ((buffer[0] & 0x80) == 0)
                                {
                                    #region STUN Packet.

                                    if (_iceState != null)
                                    {
                                        try
                                        {
                                            STUNv2Message stunMessage = STUNv2Message.ParseSTUNMessage(buffer, bytesRead);

                                            //logger.Debug("STUN message received from Receiver Client @ " + stunMessage.Header.MessageType + ".");

                                            if (stunMessage.Header.MessageType == STUNv2MessageTypesEnum.BindingRequest)
                                            {
                                                //logger.Debug("Sending STUN response to Receiver Client @ " + remoteEndPoint + ".");

                                                STUNv2Message stunResponse = new STUNv2Message(STUNv2MessageTypesEnum.BindingSuccessResponse);
                                                stunResponse.Header.TransactionId = stunMessage.Header.TransactionId;
                                                stunResponse.AddXORMappedAddressAttribute(_remoteEndPoint.Address, _remoteEndPoint.Port);
                                                byte[] stunRespBytes = stunResponse.ToByteBuffer(_iceState.SenderPassword, true);
                                                _rtpSocket.SendTo(stunRespBytes, _remoteEndPoint);

                                                //logger.Debug("Sending Binding request to Receiver Client @ " + remoteEndPoint + ".");

                                                STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                                                stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                                                stunRequest.AddUsernameAttribute(_iceState.ReceiverUser + ":" + _iceState.SenderUser);
                                                stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                                                byte[] stunReqBytes = stunRequest.ToByteBuffer(_iceState.ReceiverPassword, true);
                                                _rtpSocket.SendTo(stunReqBytes, _remoteEndPoint);

                                                _iceState.LastSTUNMessageReceivedAt = DateTime.Now;
                                            }
                                            else if (stunMessage.Header.MessageType == STUNv2MessageTypesEnum.BindingSuccessResponse)
                                            {
                                                if (!_iceState.IsSTUNExchangeComplete)
                                                {
                                                    _iceState.IsSTUNExchangeComplete = true;
                                                    logger.Debug("WebRTC client STUN exchange complete for " + _remoteEndPoint.ToString() + ".");
                                                }
                                            }
                                            else if (stunMessage.Header.MessageType == STUNv2MessageTypesEnum.BindingErrorResponse)
                                            {
                                                logger.Warn("A STUN binding error response was received from " + _remoteEndPoint + ".");
                                            }
                                            else
                                            {
                                                logger.Warn("An unrecognised STUN request was received from " + _remoteEndPoint + ".");
                                            }
                                        }
                                        catch (SocketException sockExcp)
                                        {
                                            logger.Debug("RTPChannel.RTPReceive STUN processing (" + _remoteEndPoint + "). " + sockExcp.Message);
                                            continue;
                                        }
                                        catch (Exception stunExcp)
                                        {
                                            logger.Warn("Exception RTPChannel.RTPReceive STUN processing (" + _remoteEndPoint + "). " + stunExcp);
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        logger.Warn("A STUN reponse was received on RTP socket from " + _remoteEndPoint + " but no ICE state was set.");
                                    }

                                    #endregion
                                }
                                else
                                {
                                    RTPPacket rtpPacket = new RTPPacket(buffer.Take(bytesRead).ToArray());

                                    //System.Diagnostics.Debug.WriteLine("RTPReceive ssrc " + rtpPacket.Header.SyncSource + ", seq num " + rtpPacket.Header.SequenceNumber + ", timestamp " + rtpPacket.Header.Timestamp + ", marker " + rtpPacket.Header.MarkerBit + ".");

                                    lock (_packets)
                                    {
                                        if (_packets.Count > RTP_PACKETS_MAX_QUEUE_LENGTH)
                                        {
                                            System.Diagnostics.Debug.WriteLine("RTPChannel.RTPReceive packets queue full, clearing.");
                                            logger.Warn("RTPChannel.RTPReceive packets queue full, clearing.");

                                            _packets.Clear();

                                            if (OnRTPQueueFull != null)
                                            {
                                                OnRTPQueueFull();
                                            }
                                        }
                                        else
                                        {
                                            _packets.Enqueue(rtpPacket);
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            logger.Warn("Zero bytes read from RTPChannel RTP socket connected to " + _remoteEndPoint + ".");
                            //break;
                        }
                    }
                    catch (SocketException sockExcp)
                    {
                        if (!_isClosed)
                        {
                            _rtpSocketError = sockExcp.SocketErrorCode;

                            if (_rtpSocketError == SocketError.Interrupted)
                            {
                                // If the receive has been interrupted it means the socket has been closed.
                                if (OnRTPSocketDisconnected != null)
                                {
                                    OnRTPSocketDisconnected();
                                }
                                break;
                            }
                            else
                            {
                                throw;
                            }
                        }
                    }
                    catch (Exception excp)
                    {
                        if (!_isClosed)
                        {
                            logger.Error("Exception RTPChannel.RTPReceive receiving. " + excp);
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                if (!_isClosed)
                {
                    logger.Error("Exception RTPChannel.RTPReceive. " + excp);

                    if (OnRTPSocketDisconnected != null)
                    {
                        OnRTPSocketDisconnected();
                    }
                }
            }
        }
コード例 #8
0
ファイル: IceSession.cs プロジェクト: lordrak007/sipsorcery
        private void SendStunConnectivityChecks(Object stateInfo)
        {
            try
            {
                lock (_stunChecksTimer)
                {
                    //logger.LogDebug($"Send STUN connectivity checks, local candidates {_candidates?.Count()}, remote candidates {_remoteCandidates?.Count()}.");

                    // If one of the ICE candidates has the remote RTP socket set then the negotiation is complete and the STUN checks are to keep the connection alive.
                    if (RemoteIceUser != null && RemoteIcePassword != null)
                    {
                        if (ConnectionState == RTCIceConnectionState.connected)
                        {
                            // Remote RTP endpoint gets set when the DTLS negotiation is finished.
                            if (_connectedRemoteEndPoint != null)
                            {
                                //logger.LogDebug("Sending STUN connectivity check to client " + iceCandidate.RemoteRtpEndPoint + ".");

                                string localUser = LocalIceUser;

                                STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                                stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                                stunRequest.AddUsernameAttribute(RemoteIceUser + ":" + localUser);
                                stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                                stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));   // Must send this to get DTLS started.
                                byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(RemoteIcePassword, true);

                                _rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, _connectedRemoteEndPoint, stunReqBytes);

                                //_lastStunSentAt = DateTime.Now;
                            }
                        }
                        else
                        {
                            if (_remoteCandidates.Count() > 0 && _candidates != null)
                            {
                                foreach (var localIceCandidate in _candidates.Where(x => x.IsStunLocalExchangeComplete == false && x.StunConnectionRequestAttempts < MAXIMUM_STUN_CONNECTION_ATTEMPTS))
                                {
                                    localIceCandidate.StunConnectionRequestAttempts++;

                                    // ToDo: Include srflx and relay addresses.

                                    // Only supporting UDP candidates at this stage.
                                    foreach (var remoteIceCandidate in _remoteCandidates.Where(x => x.protocol == RTCIceProtocol.udp &&
                                                                                               x.address.NotNullOrBlank() && x.HasConnectionError == false))
                                    {
                                        try
                                        {
                                            IPAddress remoteAddress = IPAddress.Parse(remoteIceCandidate.address);

                                            logger.LogDebug($"Sending authenticated STUN binding request {localIceCandidate.StunConnectionRequestAttempts} from {_rtpChannel.RTPLocalEndPoint} to WebRTC peer at {remoteIceCandidate.address}:{remoteIceCandidate.port}.");

                                            string localUser = LocalIceUser;

                                            STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                                            stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                                            stunRequest.AddUsernameAttribute(RemoteIceUser + ":" + localUser);
                                            stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                                            stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));
                                            byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(RemoteIcePassword, true);

                                            _rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, new IPEndPoint(IPAddress.Parse(remoteIceCandidate.address), remoteIceCandidate.port), stunReqBytes);

                                            localIceCandidate.LastSTUNSendAt = DateTime.Now;
                                        }
                                        catch (System.Net.Sockets.SocketException sockExcp)
                                        {
                                            logger.LogWarning($"SocketException sending STUN request to {remoteIceCandidate.address}:{remoteIceCandidate.port}, removing candidate. {sockExcp.Message}");
                                            remoteIceCandidate.HasConnectionError = true;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    //if (!_closed)
                    //{
                    //    var interval = GetNextStunCheckInterval(STUN_CHECK_BASE_PERIOD_MILLISECONDS);

                    //    if (m_stunChecksTimer == null)
                    //    {
                    //        m_stunChecksTimer = new Timer(SendStunConnectivityChecks, null, interval, interval);
                    //    }
                    //    else
                    //    {
                    //        m_stunChecksTimer.Change(interval, interval);
                    //    }
                    //}
                }
            }
            catch (Exception excp)
            {
                logger.LogError("Exception SendStunConnectivityCheck. " + excp);
                //m_stunChecksTimer?.Dispose();
            }
        }
コード例 #9
0
ファイル: WebRtcPeer.cs プロジェクト: sipsorcery/sipsorcery
        private void SendStunConnectivityChecks()
        {
            try
            {
                while (!IsClosed)
                {
                    try
                    {
                        // If one of the ICE candidates has the remote RTP socket set then the negotiation is complete and the STUN checks are to keep the connection alive.
                        if (LocalIceCandidates.Any(x => x.IsConnected == true))
                        {
                            var iceCandidate = LocalIceCandidates.First(x => x.IsConnected == true);

                            // Remote RTP endpoint gets set when the DTLS negotiation is finished.
                            if (iceCandidate.RemoteRtpEndPoint != null)
                            {
                                //logger.Debug("Sending STUN connectivity check to client " + iceCandidate.RemoteRtpEndPoint + ".");

                                STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                                stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                                stunRequest.AddUsernameAttribute(RemoteIceUser + ":" + LocalIceUser);
                                stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                                stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));   // Must send this to get DTLS started.
                                byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(RemoteIcePassword, true);

                                iceCandidate.LocalRtpSocket.SendTo(stunReqBytes, iceCandidate.RemoteRtpEndPoint);

                                iceCandidate.LastSTUNSendAt = DateTime.Now;
                            }

                            var secondsSinceLastResponse = DateTime.Now.Subtract(iceCandidate.LastCommunicationAt).TotalSeconds;

                            if (secondsSinceLastResponse > ICE_TIMEOUT_SECONDS)
                            {
                                logger.Warn("No STUN response was received on a connected ICE connection for " + secondsSinceLastResponse + "s, closing connection.");

                                iceCandidate.IsDisconnected = true;

                                if (LocalIceCandidates.Any(x => x.IsConnected == true) == false)
                                {
                                    // If there are no connected local candidates left close the peer.
                                    Close();
                                    break;
                                }
                            }
                        }
                        else
                        {
                            if (_remoteIceCandidates.Count() > 0)
                            {
                                foreach (var localIceCandidate in LocalIceCandidates.Where(x => x.IsStunLocalExchangeComplete == false && x.StunConnectionRequestAttempts < MAXIMUM_STUN_CONNECTION_ATTEMPTS))
                                {
                                    localIceCandidate.StunConnectionRequestAttempts++;

                                    // ToDo: Include srflx and relay addresses.

                                    foreach (var remoteIceCandidate in RemoteIceCandidates.Where(x => x.Transport != "tcp" && x.NetworkAddress.NotNullOrBlank()))   // Only supporting UDP candidates at this stage.
                                    {
                                        IPAddress remoteAddress = IPAddress.Parse(remoteIceCandidate.NetworkAddress);

                                        logger.Debug("Sending authenticated STUN binding request " + localIceCandidate.StunConnectionRequestAttempts + " from " + localIceCandidate.LocalRtpSocket.LocalEndPoint + " to WebRTC peer at " + remoteIceCandidate.NetworkAddress + ":" + remoteIceCandidate.Port + ".");

                                        STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                                        stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                                        stunRequest.AddUsernameAttribute(RemoteIceUser + ":" + LocalIceUser);
                                        stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                                        stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));   // Must send this to get DTLS started.
                                        byte[] stunReqBytes = stunRequest.ToByteBufferStringKey(RemoteIcePassword, true);

                                        localIceCandidate.LocalRtpSocket.SendTo(stunReqBytes, new IPEndPoint(IPAddress.Parse(remoteIceCandidate.NetworkAddress), remoteIceCandidate.Port));

                                        localIceCandidate.LastSTUNSendAt = DateTime.Now;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception excp)
                    {
                        logger.Error("Exception SendStunConnectivityCheck ConnectivityCheck. " + excp);
                    }

                    if (!IsClosed)
                    {
                        Thread.Sleep(ESTABLISHED_STUN_BINDING_PERIOD_MILLISECONDS);
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SendStunConnectivityCheck. " + excp);
            }
        }
コード例 #10
0
ファイル: Program.cs プロジェクト: Dawn2Yuan/sipsorcery
        private static void SendStunConnectivityChecks(UdpClient localSocket)
        {
            try
            {
                while (!m_exit)
                {
                    try
                    {
                        foreach (var client in _webRTCClients.Where(x => x.SocketAddress != null))
                        {
                            //logger.Debug("Sending STUN connectivity check to client " + client.SocketAddress + ".");

                            STUNv2Message stunRequest = new STUNv2Message(STUNv2MessageTypesEnum.BindingRequest);
                            stunRequest.Header.TransactionId = Guid.NewGuid().ToByteArray().Take(12).ToArray();
                            stunRequest.AddUsernameAttribute(client.ICEUser + ":" + client.LocalICEUser);
                            stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.Priority, new byte[] { 0x6e, 0x7f, 0x1e, 0xff }));
                            stunRequest.Attributes.Add(new STUNv2Attribute(STUNv2AttributeTypesEnum.UseCandidate, null));   // Must send this to get DTLS started.
                            byte[] stunReqBytes = stunRequest.ToByteBuffer(client.ICEPassword, true);
                            localSocket.Send(stunReqBytes, stunReqBytes.Length, client.SocketAddress);

                            client.LastSTUNSendAt = DateTime.Now;

                            //if(client.IsDtlsNegotiationComplete)
                            //{
                            //    // Send RTCP report.
                            //    RTCPPacket rtcp = new RTCPPacket(client.SSRC, 0, 0, 0, 0);
                            //    RTCPReport rtcpResport = new RTCPReport(Guid.NewGuid(), 0, client.SocketAddress);
                            //    var rtcpBuffer = rtcp.GetBytes(rtcpResport.GetBytes());
                            //    var rtcpProtectedBuffer = new byte[rtcpBuffer.Length + SRTP_AUTH_KEY_LENGTH];
                            //    Buffer.BlockCopy(rtcpBuffer, 0, rtcpProtectedBuffer, 0, rtcpBuffer.Length);
                            //    int rtperr = client.SrtpContext.ProtectRTP(rtcpBuffer, rtcpBuffer.Length - SRTP_AUTH_KEY_LENGTH);

                            //    if (rtperr != 0)
                            //    {
                            //        logger.Debug("RTCP packet protect result " + rtperr + ".");
                            //    }
                            //    else
                            //    {
                            //        localSocket.Send(rtcpProtectedBuffer, rtcpProtectedBuffer.Length, client.SocketAddress);
                            //    }
                            //}
                        }
                    }
                    catch (Exception excp)
                    {
                        logger.Error("Exception SendStunConnectivityCheck ConnectivityCheck. " + excp);
                    }

                    Thread.Sleep(2000);

                    lock (_webRTCClients)
                    {
                        var expiredClients = (from cli in _webRTCClients where cli.STUNExchangeComplete && cli.IsDtlsNegotiationComplete && DateTime.Now.Subtract(cli.LastSTUNReceiveAt).TotalSeconds > EXPIRE_CLIENT_SECONDS select cli).ToList();
                        for (int index = 0; index < expiredClients.Count(); index++)
                        {
                            var expiredClient = expiredClients[index];
                            logger.Debug("Removed expired client " + expiredClient.SocketAddress + ".");
                            _webRTCClients.TryTake(out expiredClient);
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception SendStunConnectivityCheck. " + excp);
            }
        }