Exemple #1
0
        /// <summary>
        /// Does the actual sending of an RTP packet using the specified data nad header values.
        /// </summary>
        /// <param name="rtpChannel">The RTP channel to send from.</param>
        /// <param name="dstRtpSocket">Destination to send to.</param>
        /// <param name="data">The RTP packet payload.</param>
        /// <param name="timestamp">The RTP header timestamp.</param>
        /// <param name="markerBit">The RTP header marker bit.</param>
        /// <param name="payloadType">The RTP header payload type.</param>
        private void SendRtpPacket(RTPChannel rtpChannel, IPEndPoint dstRtpSocket, byte[] data, uint timestamp, int markerBit, int payloadType)
        {
            int srtpProtectionLength = (SrtpProtect != null) ? SRTP_AUTH_KEY_LENGTH : 0;

            RTPPacket rtpPacket = new RTPPacket(data.Length + srtpProtectionLength);

            rtpPacket.Header.SyncSource     = Ssrc;
            rtpPacket.Header.SequenceNumber = SeqNum;
            rtpPacket.Header.Timestamp      = timestamp;
            rtpPacket.Header.MarkerBit      = markerBit;
            rtpPacket.Header.PayloadType    = payloadType;

            Buffer.BlockCopy(data, 0, rtpPacket.Payload, 0, data.Length);

            OnRtpPacketSent?.Invoke(rtpPacket);

            var rtpBuffer = rtpPacket.GetBytes();

            int rtperr = SrtpProtect == null ? 0 : SrtpProtect(rtpBuffer, rtpBuffer.Length - srtpProtectionLength);

            if (rtperr != 0)
            {
                logger.LogError("SendDtmfEvent SRTP packet protection failed, result " + rtperr + ".");
            }
            else
            {
                rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, dstRtpSocket, rtpBuffer);
            }
        }
Exemple #2
0
 public RTCPSession(uint ssrc, RTPChannel rtpChannel, ProtectRtpPacket srtcpProtect)
 {
     Ssrc           = ssrc;
     m_rtpChannel   = rtpChannel;
     m_srtcpProtect = srtcpProtect;
     CreatedAt      = DateTime.Now;
     Cname          = Guid.NewGuid().ToString();
 }
Exemple #3
0
        /// <summary>
        /// Creates a new instance of an ICE session.
        /// </summary>
        /// <param name="rtpChannel">The RTP channel is the object managing the socket
        /// doing the media sending and receiving. Its the same socket the ICE session
        /// will need to initiate all the connectivity checks on.</param>
        /// <param name="component">The component (RTP or RTCP) the channel is being used for. Note
        /// for cases where RTP and RTCP are multiplexed the component is set to RTP.</param>
        public IceSession(RTPChannel rtpChannel, RTCIceComponent component)
        {
            _rtpChannel = rtpChannel;
            Component   = component;

            LocalIceUser     = Crypto.GetRandomString(ICE_UFRAG_LENGTH);
            LocalIcePassword = Crypto.GetRandomString(ICE_PASSWORD_LENGTH);
        }
Exemple #4
0
 public RTCPSession(uint ssrc, RTPChannel rtpChannel, bool isMultiplexed)
 {
     Ssrc            = ssrc;
     m_rtpChannel    = rtpChannel;
     m_isMultiplexed = isMultiplexed;
     CreatedAt       = DateTime.Now;
     Cname           = Guid.NewGuid().ToString();
 }
Exemple #5
0
        public WebRtcSession(string dtlsFingerprint, List <IPAddress> offerAddresses)
        {
            _dtlsCertificateFingerprint = dtlsFingerprint;

            SessionID = Guid.NewGuid().ToString();

            _rtpSession     = new RTPSession((int)SDPMediaFormatsEnum.PCMU, AddressFamily.InterNetwork, true);
            _videoSessionID = _rtpSession.AddStream(VP8_PAYLOAD_TYPE_ID, null);
            _rtpChannel     = _rtpSession.RtpChannel;
            _rtpChannel.OnRTPDataReceived += OnRTPDataReceived;
            _rtpSession.OnRtpClosed       += Close;

            _offerAddresses = offerAddresses;
        }
Exemple #6
0
        /// <summary>
        /// Initialises the RTP session state and starts the RTP channel UDP sockets.
        /// </summary>
        /// <param name="addrFamily">Whether the RTP channel should use IPv4 or IPv6.</param>
        /// <param name="isRtcpMultiplexed">If true RTCP reports will be multiplexed with RTP on a single channel.
        /// If false (standard mode) then a separate socket is used to send and receive RTCP reports.</param>
        private void InitialiseRtpChannel(AddressFamily addrFamily, bool isRtcpMultiplexed)
        {
            var channelAddress = (addrFamily == AddressFamily.InterNetworkV6) ? IPAddress.IPv6Any : IPAddress.Any;

            RtpChannel = new RTPChannel(channelAddress, !isRtcpMultiplexed);

            RtpChannel.OnRTPDataReceived += RtpPacketReceived;
            RtpChannel.OnClosed          += OnRTPChannelClosed;

            RtcpSession          = new RTCPSession(m_sessionStreams.First().Ssrc, RtpChannel, isRtcpMultiplexed);
            OnRtpPacketReceived += RtcpSession.RtpPacketReceived;
            RtpChannel.OnControlDataReceived += RtcpSession.ControlDataReceived;
            OnRtpPacketSent += RtcpSession.RtpPacketSent;

            // Start the RTP and Control socket receivers and the RTCP session.
            RtpChannel.Start();
            RtcpSession.Start();
        }
Exemple #7
0
        /// <summary>
        /// Does the actual sending of an RTP packet using the specified data and header values.
        /// </summary>
        /// <param name="rtpChannel">The RTP channel to send from.</param>
        /// <param name="dstRtpSocket">Destination to send to.</param>
        /// <param name="data">The RTP packet payload.</param>
        /// <param name="timestamp">The RTP header timestamp.</param>
        /// <param name="markerBit">The RTP header marker bit.</param>
        /// <param name="payloadType">The RTP header payload type.</param>
        private void SendRtpPacket(RTPChannel rtpChannel, IPEndPoint dstRtpSocket, byte[] data, uint timestamp, int markerBit, int payloadType, uint ssrc, ushort seqNum, RTCPSession rtcpSession)
        {
            if (IsSecure && !IsSecureContextReady)
            {
                logger.LogWarning("SendRtpPacket cannot be called on a secure session before calling SetSecurityContext.");
            }
            else
            {
                int srtpProtectionLength = (m_srtpProtect != null) ? SRTP_MAX_PREFIX_LENGTH : 0;

                RTPPacket rtpPacket = new RTPPacket(data.Length + srtpProtectionLength);
                rtpPacket.Header.SyncSource     = ssrc;
                rtpPacket.Header.SequenceNumber = seqNum;
                rtpPacket.Header.Timestamp      = timestamp;
                rtpPacket.Header.MarkerBit      = markerBit;
                rtpPacket.Header.PayloadType    = payloadType;

                Buffer.BlockCopy(data, 0, rtpPacket.Payload, 0, data.Length);

                var rtpBuffer = rtpPacket.GetBytes();

                if (m_srtpProtect == null)
                {
                    rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, dstRtpSocket, rtpBuffer);
                }
                else
                {
                    int outBufLen = 0;
                    int rtperr    = m_srtpProtect(rtpBuffer, rtpBuffer.Length - srtpProtectionLength, out outBufLen);
                    if (rtperr != 0)
                    {
                        logger.LogError("SendRTPPacket protection failed, result " + rtperr + ".");
                    }
                    else
                    {
                        rtpChannel.SendAsync(RTPChannelSocketsEnum.RTP, dstRtpSocket, rtpBuffer.Take(outBufLen).ToArray());
                    }
                }
                m_lastRtpTimestamp = timestamp;

                rtcpSession?.RecordRtpPacketSend(rtpPacket);
            }
        }
Exemple #8
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="dtlsFingerprint">The fingerprint of our DTLS certificate (we always act as the DTLS server).
        /// It gets placed in the SDP offer sent to the remote party.</param>
        /// <param name="offerAddresses">Optional. A list of the IP addresses used as local ICE candidates.
        /// If null then all local IP addresses get used.</param>
        /// <param name="turnServerEndPoint">Optional. A parameter that can be used include a TURN
        /// server in this session's ICE candidate gathering.</param>
        public WebRtcSession(
            AddressFamily addrFamily,
            string dtlsFingerprint,
            List <IPAddress> offerAddresses,
            IPEndPoint turnServerEndPoint)
        {
            _dtlsCertificateFingerprint = dtlsFingerprint;
            _offerAddresses             = offerAddresses;
            _turnServerEndPoint         = turnServerEndPoint;

            SessionID = Guid.NewGuid().ToString();

            RtpSession = new RTPSession(addrFamily, true, true);

            _rtpChannel = RtpSession.RtpChannel;
            _rtpChannel.OnRTPDataReceived += OnRTPDataReceived;
            RtpSession.OnRtpClosed        += Close;
            RtpSession.OnRtcpBye          += Close;
        }
Exemple #9
0
        /// <summary>
        /// Initialises the RTP session state and starts the RTP channel UDP sockets.
        /// </summary>
        private void Initialise(AddressFamily addrFamily, ProtectRtpPacket srtcpProtect)
        {
            Ssrc   = Convert.ToUInt32(Crypto.GetRandomInt(0, Int32.MaxValue));
            SeqNum = Convert.ToUInt16(Crypto.GetRandomInt(0, UInt16.MaxValue));

            RtpChannel = new RTPChannel((addrFamily == AddressFamily.InterNetworkV6) ? IPAddress.IPv6Any : IPAddress.Any, true);

            MediaAnnouncement.Port        = RtpChannel.RTPPort;
            RtpChannel.OnRTPDataReceived += RtpPacketReceived;
            RtpChannel.OnClosed          += OnRTPChannelClosed;

            RtcpSession          = new RTCPSession(Ssrc, RtpChannel, srtcpProtect);
            OnRtpPacketReceived += RtcpSession.RtpPacketReceived;
            RtpChannel.OnControlDataReceived += RtcpSession.ControlDataReceived;
            OnRtpPacketSent += RtcpSession.RtpPacketSent;

            // Start the RTP and Control socket receivers and the RTCP session.
            RtpChannel.Start();
            RtcpSession.Start();
        }
Exemple #10
0
        /// <summary>
        /// Creates a new RTP session. The synchronisation source and sequence number are initialised to
        /// pseudo random values.
        /// </summary>
        /// <param name="mediaType">The default media type for this RTP session. If media multiplexing
        /// is being used additional streams can be added by calling AddStream.</param>
        /// <param name="payloadTypeID">The payload type ID for this RTP stream. It's what gets set in the payload
        /// type ID field in the RTP header.</param>
        /// <param name="addrFamily">Determines whether the RTP channel will use an IPv4 or IPv6 socket.</param>
        /// <param name="isRtcpMultiplexed">If true RTCP reports will be multiplexed with RTP on a single channel.
        /// If false (standard mode) then a separate socket is used to send and receive RTCP reports.</param>
        /// <param name="isSecure">If true indicated this session is using SRTP to encrypt and authorise
        /// RTP and RTCP packets. No communications or reporting will commence until the
        /// is explicitly set as complete.</param>
        public RTPSession(
            SDPMediaTypesEnum mediaType,
            int payloadTypeID,
            AddressFamily addrFamily,
            bool isRtcpMultiplexed,
            bool isSecure)
        {
            m_isRtcpMultiplexed = isRtcpMultiplexed;
            IsSecure            = isSecure;

            var channelAddress = (addrFamily == AddressFamily.InterNetworkV6) ? IPAddress.IPv6Any : IPAddress.Any;

            RtpChannel = new RTPChannel(channelAddress, !isRtcpMultiplexed);

            RtpChannel.OnRTPDataReceived     += OnReceive;
            RtpChannel.OnControlDataReceived += OnReceive; // RTCP packets could come on RTP or control socket.
            RtpChannel.OnClosed += OnRTPChannelClosed;

            // Start the RTP, and if required the Control, socket receivers and the RTCP session.
            RtpChannel.Start();

            AddStream(mediaType, payloadTypeID, null);
        }
Exemple #11
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="dtlsFingerprint">The fingerprint of our DTLS certificate (we always act as the DTLS server).
        /// It gets placed in the SDP offer sent to the remote party.</param>
        /// <param name="supportedAudioFormats">List of audio codecs that we support. Can be null or empty if
        /// the session is not supporting audio.</param>
        /// <param name="supportedVideoFormats">List of video codecs that we support. Can be null or empty if
        /// the session is not supporting video.</param>
        /// <param name="offerAddresses">Optional. A list of the IP addresses used as local ICE candidates.
        /// If null then all local IP addresses get used.</param>
        public WebRtcSession(
            string dtlsFingerprint,
            List <SDPMediaFormat> supportedAudioFormats,
            List <SDPMediaFormat> supportedVideoFormats,
            List <IPAddress> offerAddresses)
        {
            if (supportedAudioFormats == null && supportedVideoFormats == null)
            {
                throw new ApplicationException("At least one of the audio or video supported formats must be specified.");
            }

            _dtlsCertificateFingerprint = dtlsFingerprint;
            _supportedAudioFormats      = supportedAudioFormats;
            _supportedVideoFormats      = supportedVideoFormats;

            SessionID = Guid.NewGuid().ToString();

            if (_supportedAudioFormats != null && supportedAudioFormats.Count > 0)
            {
                RtpSession = new RTPSession(SDPMediaTypesEnum.audio, (int)supportedAudioFormats.First().FormatCodec, AddressFamily.InterNetwork, true, true);
            }
            else if (_supportedVideoFormats != null && supportedVideoFormats.Count > 0)
            {
                RtpSession = new RTPSession(SDPMediaTypesEnum.video, (int)supportedVideoFormats.First().FormatCodec, AddressFamily.InterNetwork, true, true);
            }

            if (RtpSession == null)
            {
                throw new ApplicationException("No supported audio or video types were provided.");
            }

            _rtpChannel = RtpSession.RtpChannel;
            _rtpChannel.OnRTPDataReceived += OnRTPDataReceived;
            RtpSession.OnRtpClosed        += Close;

            _offerAddresses = offerAddresses;
        }
Exemple #12
0
        /// <summary>
        /// Creates a new instance of an ICE session.
        /// </summary>
        /// <param name="rtpChannel">The RTP channel is the object managing the socket
        /// doing the media sending and receiving. Its the same socket the ICE session
        /// will need to initiate all the connectivity checks on.</param>
        /// <param name="component">The component (RTP or RTCP) the channel is being used for. Note
        /// for cases where RTP and RTCP are multiplexed the component is set to RTP.</param>
        public IceSession(RTPChannel rtpChannel, RTCIceComponent component)
        {
            if (rtpChannel == null)
            {
                throw new ArgumentNullException("rtpChannel");
            }

            _rtpChannel = rtpChannel;
            Component   = component;

            LocalIceUser     = Crypto.GetRandomString(ICE_UFRAG_LENGTH);
            LocalIcePassword = Crypto.GetRandomString(ICE_PASSWORD_LENGTH);

            _localChecklistCandidate = new RTCIceCandidate(new RTCIceCandidateInit {
                sdpMid = "0", sdpMLineIndex = 0, usernameFragment = LocalIceUser
            });
            _localChecklistCandidate.SetAddressProperties(
                RTCIceProtocol.udp,
                _rtpChannel.RTPLocalEndPoint.Address,
                (ushort)_rtpChannel.RTPLocalEndPoint.Port,
                RTCIceCandidateType.host,
                null,
                0);
        }
Exemple #13
0
        public RTPManager(bool includeAudio, bool includeVideo)
        {
            if (includeAudio)
            {
                // Create a UDP socket to use for sending and receiving RTP audio packets.
                _rtpAudioChannel = new RTPChannel();
                _rtpAudioChannel.SetFrameType(FrameTypesEnum.Audio);
                _rtpAudioChannel.ReservePorts(DEFAULT_START_RTP_PORT, DEFAULT_END_RTP_PORT);
                _rtpAudioChannel.OnFrameReady += AudioFrameReady;
            }

            if (includeVideo)
            {
                _rtpVideoChannel = new RTPChannel();
                _rtpVideoChannel.SetFrameType(FrameTypesEnum.VP8);
                _rtpVideoChannel.ReservePorts(DEFAULT_START_RTP_PORT, DEFAULT_END_RTP_PORT);
                _rtpVideoChannel.OnFrameReady += VideoFrameReady;
                _rtpVideoChannel.OnRTPSocketDisconnected += () => { };
            }
        }
Exemple #14
0
        private WaveFormat _waveFormat = new WaveFormat(8000, 16, 1); // The format that both the input and output audio streams will use, i.e. PCMU.

        #endregion Fields

        #region Constructors

        public AudioChannel()
        {
            // Set up the device that will play the audio from the RTP received from the remote end of the call.
            m_waveOut = new WaveOut();
            m_waveProvider = new BufferedWaveProvider(_waveFormat);
            m_waveOut.Init(m_waveProvider);
            m_waveOut.Play();

            // Set up the input device that will provide audio samples that can be encoded, packaged into RTP and sent to
            // the remote end of the call.
            m_waveInEvent = new WaveInEvent();
            m_waveInEvent.BufferMilliseconds = 20;
            m_waveInEvent.NumberOfBuffers = 1;
            m_waveInEvent.DeviceNumber = 0;
            m_waveInEvent.DataAvailable += RTPChannelSampleAvailable;
            m_waveInEvent.WaveFormat = _waveFormat;

            // Create a UDP socket to use for sending and receiving RTP packets.
            int port = FreePort.FindNextAvailableUDPPort(DEFAULT_START_RTP_PORT);
            _rtpEndPoint = new IPEndPoint(_defaultLocalAddress, port);
            m_rtpChannel = new RTPChannel(_rtpEndPoint);
            m_rtpChannel.OnFrameReady += RTPChannelSampleReceived;

            _audioLogger.Debug("RTP channel endpoint " + _rtpEndPoint.ToString());
        }
Exemple #15
0
        /// <param name="rtpListenAddress">The local IP address to establish the RTP listener socket on.</param>
        /// <param name="sdpAdvertiseAddress">The public IP address to put into the SDP sent back to the caller.</param>
        /// <param name="request">The INVITE request that instigated the RTP diagnostics job.</param>
        public RTPDiagnosticsJob(IPAddress rtpListenAddress, IPAddress sdpAdvertiseAddress, SIPServerUserAgent uas, SIPRequest request)
        {
            m_request = request;
            m_remoteSDP = SDP.ParseSDPDescription(request.Body);
            RemoteRTPEndPoint = new IPEndPoint(IPAddress.Parse(m_remoteSDP.Connection.ConnectionAddress), m_remoteSDP.Media[0].Port);
            UAS = uas;
            //m_rawSourceStream = new RawSourceWaveStream(m_outStream, WaveFormat.CreateMuLawFormat(8000, 1));
            //m_waveFileWriter = new WaveFileWriter("out.wav", new WaveFormat(8000, 16, 1));
            m_waveFileWriter = new WaveFileWriter("out.wav", new WaveFormat(8000, 16, 1));
            //m_outPCMStream = WaveFormatConversionStream.CreatePcmStream(m_rawSourceStream);
            //m_rawRTPPayloadWriter = new StreamWriter("out.rtp");
            //m_rawRTPPayloadReader = new StreamReader("in.rtp");
            //IPEndPoint rtpListenEndPoint = null;
            IPEndPoint rtpListenEndPoint = null;
            NetServices.CreateRandomUDPListener(rtpListenAddress, RTP_PORTRANGE_START, RTP_PORTRANGE_END, m_inUsePorts, out rtpListenEndPoint);
            RTPListenEndPoint = rtpListenEndPoint;
            m_inUsePorts.Add(rtpListenEndPoint.Port);
            //RTPListenEndPoint = new IPEndPoint(rtpListenAddress, RTP_PORTRANGE_START);
            m_rtpChannel = new RTPChannel(RTPListenEndPoint);
            m_rtpChannel.SampleReceived += SampleReceived;
            ThreadPool.QueueUserWorkItem(delegate { GetAudioSamples(); });

            LocalSDP = new SDP()
            {
                SessionId = Crypto.GetRandomString(6),
                Address = sdpAdvertiseAddress.ToString(),
                SessionName = "sipsorcery",
                Timing = "0 0",
                Connection = new SDPConnectionInformation(sdpAdvertiseAddress.ToString()),
                Media = new List<SDPMediaAnnouncement>()
                {
                    new SDPMediaAnnouncement()
                    {
                        Media = SDPMediaTypesEnum.audio,
                        Port = RTPListenEndPoint.Port,
                        MediaFormats = new List<SDPMediaFormat>() { new SDPMediaFormat((int)SDPMediaFormatsEnum.PCMU) }
                    }
                }
            };
        }