/// <summary> /// Creates a new RTP session. The synchronisation source and sequence number are initialised to /// pseudo random values. /// </summary> /// <param name="formatTypeID">The format type ID for the media. It's what gets set in the payload /// type ID field in the RTP header. A default media announcement will be created.</param> /// <param name="srtpProtect">Optional secure DTLS context for encrypting RTP packets.</param> /// <param name="srtcpProtect">Optional secure DTLS context for encrypting RTCP packets.</param> /// <param name="rtpEventSupport">True if RTP event sending and receiving should be supported.</param> /// <param name="addrFamily">Determines whether the RTP channel will use an IPv4 or IPv6 socket.</param> public RTPSession(int formatTypeID, ProtectRtpPacket srtpProtect, ProtectRtpPacket srtcpProtect, bool rtpEventSupport, AddressFamily addrFamily) { MediaFormat = new SDPMediaFormat(formatTypeID); MediaAnnouncement = new SDPMediaAnnouncement { Media = SDPMediaTypesEnum.audio, MediaFormats = new List <SDPMediaFormat> { MediaFormat }, MediaStreamStatus = MediaStreamStatusEnum.SendRecv }; if (rtpEventSupport) { int clockRate = MediaFormat.GetClockRate(); SDPMediaFormat rtpEventFormat = new SDPMediaFormat(DTMF_EVENT_PAYLOAD_ID); rtpEventFormat.SetFormatAttribute($"{TELEPHONE_EVENT_ATTRIBUTE}/{clockRate}"); rtpEventFormat.SetFormatParameterAttribute("0-16"); MediaAnnouncement.MediaFormats.Add(rtpEventFormat); } m_rtpEventSupport = rtpEventSupport; FormatTypeID = formatTypeID; SrtpProtect = srtpProtect; Initialise(addrFamily, srtcpProtect); }
public RTCPSession(uint ssrc, RTPChannel rtpChannel, ProtectRtpPacket srtcpProtect) { Ssrc = ssrc; m_rtpChannel = rtpChannel; m_srtcpProtect = srtcpProtect; CreatedAt = DateTime.Now; Cname = Guid.NewGuid().ToString(); }
public RTPSession(int payloadType, ProtectRtpPacket srtpProtect, ProtectRtpPacket srtcpProtect) { PayloadType = payloadType; SrtpProtect = srtpProtect; SrtcpProtect = srtcpProtect; Ssrc = Convert.ToUInt32(Crypto.GetRandomInt(0, Int32.MaxValue)); SeqNum = Convert.ToUInt16(Crypto.GetRandomInt(0, UInt16.MaxValue)); }
public override void SetSecurityContext( ProtectRtpPacket protectRtp, ProtectRtpPacket unprotectRtp, ProtectRtpPacket protectRtcp, ProtectRtpPacket unprotectRtcp) { base.SetSecurityContext(protectRtp, unprotectRtp, protectRtcp, unprotectRtcp); if (iceConnectionState == RTCIceConnectionState.connected && connectionState != RTCPeerConnectionState.connected) { // This is the case where the DTLS handshake completed before the ICE connection checks. connectionState = RTCPeerConnectionState.connected; onconnectionstatechange?.Invoke(RTCPeerConnectionState.connected); } }
/// <summary> /// Sets the Secure RTP (SRTP) delegates and marks this session as ready for communications. /// </summary> /// <param name="protectRtp">SRTP encrypt RTP packet delegate.</param> /// <param name="unprotectRtp">SRTP decrypt RTP packet delegate.</param> /// <param name="protectRtcp">SRTP encrypt RTCP packet delegate.</param> /// <param name="unprotectRtcp">SRTP decrypt RTCP packet delegate.</param> public void SetSecurityContext( ProtectRtpPacket protectRtp, ProtectRtpPacket unprotectRtp, ProtectRtpPacket protectRtcp, ProtectRtpPacket unprotectRtcp) { m_srtpProtect = protectRtp; m_srtpUnprotect = unprotectRtp; m_srtcpControlProtect = protectRtcp; m_srtcpControlUnprotect = unprotectRtcp; IsSecureContextReady = true; // Start the reporting sessions. m_audioRtcpSession?.Start(); m_videoRtcpSession?.Start(); logger.LogDebug("Secure context successfully set on RTPSession."); }
/// <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> /// Hands the socket handle to the DTLS context and waits for the handshake to complete. /// </summary> /// <param name="rtpSocket">The RTP socket being used for the WebRTC session.</param> private static int DoDtlsHandshake(WebRtcSession webRtcSession, Socket rtpSocket, out ProtectRtpPacket protectRtp, out ProtectRtpPacket protectRtcp) { logger.LogDebug("DoDtlsHandshake started."); protectRtp = null; protectRtcp = null; if (!File.Exists(DTLS_CERTIFICATE_PATH)) { throw new ApplicationException($"The DTLS certificate file could not be found at {DTLS_CERTIFICATE_PATH}."); } else if (!File.Exists(DTLS_KEY_PATH)) { throw new ApplicationException($"The DTLS key file could not be found at {DTLS_KEY_PATH}."); } var dtls = new Dtls(DTLS_CERTIFICATE_PATH, DTLS_KEY_PATH); webRtcSession.OnClose += (reason) => dtls.Shutdown(); int res = dtls.DoHandshake((ulong)rtpSocket.Handle); logger.LogDebug("DtlsContext initialisation result=" + res); if (dtls.GetState() == (int)DtlsState.OK) { logger.LogDebug("DTLS negotiation complete."); var srtpContext = new Srtp(dtls, false); protectRtp = srtpContext.ProtectRTP; protectRtcp = srtpContext.ProtectRTCP; } return(res); }