public async Task <RTCSessionDescriptionInit> GotOffer(RTCSessionDescriptionInit offer) { _logger.LogDebug($"SDP offer received."); _logger.LogTrace($"Offer SDP:\n{offer.sdp}"); var pc = new RTCPeerConnection(); if (_publicIPv4 != null) { var rtpPort = pc.GetRtpChannel().RTPPort; var publicIPv4Candidate = new RTCIceCandidate(RTCIceProtocol.udp, _publicIPv4, (ushort)rtpPort, RTCIceCandidateType.host); pc.addLocalIceCandidate(publicIPv4Candidate); } if (_publicIPv6 != null) { var rtpPort = pc.GetRtpChannel().RTPPort; var publicIPv6Candidate = new RTCIceCandidate(RTCIceProtocol.udp, _publicIPv6, (ushort)rtpPort, RTCIceCandidateType.host); pc.addLocalIceCandidate(publicIPv6Candidate); } MediaStreamTrack audioTrack = new MediaStreamTrack(SDPMediaTypesEnum.audio, false, new List <SDPAudioVideoMediaFormat> { new SDPAudioVideoMediaFormat(SDPWellKnownMediaFormatsEnum.PCMU) }, MediaStreamStatusEnum.SendRecv); pc.addTrack(audioTrack); MediaStreamTrack videoTrack = new MediaStreamTrack(new VideoFormat(VideoCodecsEnum.VP8, VP8_PAYLOAD_ID), MediaStreamStatusEnum.SendRecv); pc.addTrack(videoTrack); pc.OnRtpPacketReceived += (IPEndPoint rep, SDPMediaTypesEnum media, RTPPacket rtpPkt) => { pc.SendRtpRaw(media, rtpPkt.Payload, rtpPkt.Header.Timestamp, rtpPkt.Header.MarkerBit, rtpPkt.Header.PayloadType); //_logger.LogDebug($"RTP {media} pkt received, SSRC {rtpPkt.Header.SyncSource}, SeqNum {rtpPkt.Header.SequenceNumber}."); }; //peerConnection.OnReceiveReport += RtpSession_OnReceiveReport; //peerConnection.OnSendReport += RtpSession_OnSendReport; pc.OnTimeout += (mediaType) => _logger.LogWarning($"Timeout for {mediaType}."); pc.onconnectionstatechange += (state) => { _logger.LogDebug($"Peer connection state changed to {state}."); if (state == RTCPeerConnectionState.failed) { pc.Close("ice failure"); } }; var setResult = pc.setRemoteDescription(offer); if (setResult == SetDescriptionResultEnum.OK) { var offerSdp = pc.createOffer(null); await pc.setLocalDescription(offerSdp); var answer = pc.createAnswer(null); await pc.setLocalDescription(answer); _logger.LogTrace($"Answer SDP:\n{answer.sdp}"); return(answer); } else { return(null); } }
public async Task <RTCSessionDescriptionInit> GotOffer(RTCSessionDescriptionInit offer) { logger.LogTrace($"SDP offer received."); logger.LogTrace(offer.sdp); var pc = new RTCPeerConnection(); if (_presetIceAddresses != null) { foreach (var addr in _presetIceAddresses) { var rtpPort = pc.GetRtpChannel().RTPPort; var publicIPv4Candidate = new RTCIceCandidate(RTCIceProtocol.udp, addr, (ushort)rtpPort, RTCIceCandidateType.host); pc.addLocalIceCandidate(publicIPv4Candidate); } } MediaStreamTrack audioTrack = new MediaStreamTrack(SDPWellKnownMediaFormatsEnum.PCMU); pc.addTrack(audioTrack); MediaStreamTrack videoTrack = new MediaStreamTrack(new VideoFormat(VideoCodecsEnum.VP8, VP8_PAYLOAD_ID)); pc.addTrack(videoTrack); pc.OnRtpPacketReceived += (IPEndPoint rep, SDPMediaTypesEnum media, RTPPacket rtpPkt) => { pc.SendRtpRaw(media, rtpPkt.Payload, rtpPkt.Header.Timestamp, rtpPkt.Header.MarkerBit, rtpPkt.Header.PayloadType); }; pc.OnTimeout += (mediaType) => logger.LogWarning($"Timeout for {mediaType}."); pc.oniceconnectionstatechange += (state) => logger.LogInformation($"ICE connection state changed to {state}."); pc.onsignalingstatechange += () => logger.LogInformation($"Signaling state changed to {pc.signalingState}."); pc.onconnectionstatechange += (state) => { logger.LogInformation($"Peer connection state changed to {state}."); if (state == RTCPeerConnectionState.failed) { pc.Close("ice failure"); } }; var setResult = pc.setRemoteDescription(offer); if (setResult == SetDescriptionResultEnum.OK) { var offerSdp = pc.createOffer(null); await pc.setLocalDescription(offerSdp); var answer = pc.createAnswer(null); logger.LogTrace($"SDP answer created."); logger.LogTrace(answer.sdp); return(answer); } else { logger.LogWarning($"Failed to set remote description {setResult}."); return(null); } }