/// <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); } }
public RTCPSession(uint ssrc, RTPChannel rtpChannel, ProtectRtpPacket srtcpProtect) { Ssrc = ssrc; m_rtpChannel = rtpChannel; m_srtcpProtect = srtcpProtect; CreatedAt = DateTime.Now; Cname = Guid.NewGuid().ToString(); }
/// <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); }
public RTCPSession(uint ssrc, RTPChannel rtpChannel, bool isMultiplexed) { Ssrc = ssrc; m_rtpChannel = rtpChannel; m_isMultiplexed = isMultiplexed; CreatedAt = DateTime.Now; Cname = Guid.NewGuid().ToString(); }
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; }
/// <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(); }
/// <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); } }
/// <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; }
/// <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(); }
/// <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); }
/// <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; }
/// <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); }
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 += () => { }; } }
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()); }
/// <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) } } } }; }