// =============================== // Public Method // =============================== /// <summary> /// IceServerのリストをRTCIceServerのリストに変換する /// </summary> /// <returns></returns> #if NETFX_CORE public Task <List <RTCIceServer> > ConvertIceServersToRTCIceServers() { var task = Task.Run(() => { List <RTCIceServer> result = new List <RTCIceServer>(); foreach (IceServer iceServer in IceServers) { string url = "stun:"; if (iceServer.Type == IceServer.ServerType.TURN) { url = "turn:"; } RTCIceServer server = null; url += iceServer.Host; server = new RTCIceServer { Url = url }; if (iceServer.Credential != null) { server.Credential = iceServer.Credential; } if (iceServer.Username != null) { server.Username = iceServer.Username; } result.Add(server); } return(result); }); return(task); }
void AddServer(string url, string username = null, string password = null) { // Store the ICE server as a stringified JSON object in option.value. GameObject option = Instantiate(optionElement, optionParent); Text optionText = option.GetComponentInChildren <Text>(); Button optionButton = option.GetComponentInChildren <Button>(); RTCIceServer iceServer = new RTCIceServer { urls = new[] { url }, username = usernameInputField.text, credential = passwordInputField.text }; optionText.text = url; if (!string.IsNullOrEmpty(username) || !string.IsNullOrEmpty(password)) { optionText.text += $"[{username}:{password}]"; } optionButton.onClick.AddListener(() => OnSelectServer(option)); iceServers.Add(option, iceServer); urlInputField.text = string.Empty; usernameInputField.text = string.Empty; passwordInputField.text = string.Empty; }
public static Webrtc.PeerConnection.IceServer ToNative(this RTCIceServer iceServer) => Webrtc.PeerConnection.IceServer.InvokeBuilder(iceServer.Urls.ToList()) //.SetTlsCertPolicy(iceServer.CredentialType?.ToNative() ?? //Webrtc.PeerConnection.TlsCertPolicy.TlsCertPolicySecure) //.If(iceServer.Username != null, builder => builder.SetUsername(iceServer.Username)) //.If(iceServer.Credential != null, builder => builder.SetPassword(iceServer.Credential)) .CreateIceServer();
public static Webrtc.RTCIceServer ToNative(this RTCIceServer iceServer) => new Webrtc.RTCIceServer ( urlStrings: iceServer.Urls, username: iceServer.Username, credential: iceServer.Credential, tlsCertPolicy: iceServer.CredentialType?.ToNative() ?? Webrtc.RTCTlsCertPolicy.Secure );
//ピアの作成をする void CreatePeer() { //ローカル RTCConfiguration pc_config = new RTCConfiguration(); var server = new RTCIceServer(); server.urls = new string[] { "stun:stun.webrtc.ecl.ntt.com:3478" }; pc_config.iceServers = new RTCIceServer[] { server }; localConnection = new RTCPeerConnection(ref pc_config); //データチャネルの作成 RTCDataChannelInit conf = new RTCDataChannelInit(true); localDataChannel = localConnection.CreateDataChannel("send", ref conf); localDataChannel.OnOpen = new DelegateOnOpen(() => { Debug.Log("データチャネル:localOpen"); }); localDataChannel.OnClose = new DelegateOnClose(() => { Debug.Log("データチャネル:localClose"); }); //メディアストリームの追加(現在のバージョンだとメディアストリームは1つまでらしい) if (_rtcType == RTCTYPE.OFFER) { _videoStream = _streamCamera.CaptureStream(800, 450); } localConnection.OnDataChannel = new DelegateOnDataChannel(x => { Debug.Log("ondatachannel"); remoteDataChannel = x; remoteDataChannel.OnMessage = onDataChannelMessage; }); localConnection.OnTrack = new DelegateOnTrack(x => { x.Track; //PlayVideo(x.Track); }); localConnection.OnIceConnectionChange = new DelegateOnIceConnectionChange(state => { OnIceConnectionChange(localConnection, state); }); //ICEの登録 localConnection.OnIceCandidate = new DelegateOnIceCandidate(candidate => { if (!string.IsNullOrEmpty(candidate.candidate)) { _localIceCandidate.Add(candidate); Debug.Log("アイス:add my Ice" + candidate.candidate); } else { Debug.Log("end ice candidate"); } }); Debug.Log("crete peer"); }
public void AddIceServers(List <IceServer> iceServersList) { List <string> urlsList = new List <string>(); foreach (IceServer ice in iceServersList) { foreach (string url in ice.Urls) { string checkedUrl = string.Empty; if (url.StartsWith("stun")) { checkedUrl = url; if (!url.StartsWith("stun:")) { checkedUrl = $"stun:{url}"; } } if (url.StartsWith("turn")) { checkedUrl = url; if (!url.StartsWith("turn:")) { checkedUrl = $"turn:{url}"; } } urlsList.Add(checkedUrl); } RTCIceServer server = new RTCIceServer { Urls = urlsList }; if (ice.Username != null) { server.Username = ice.Username; } if (ice.Credential != null) { server.Credential = ice.Credential; } _iceServers.Add(server); } }
public static Webrtc.PeerConnection.IceServer ToNative(this RTCIceServer iceServer) { var nativeIceServerBuilder = Webrtc.PeerConnection.IceServer.InvokeBuilder(iceServer.Urls.ToList()); if (iceServer.CredentialType.HasValue) { nativeIceServerBuilder.SetTlsCertPolicy(iceServer.CredentialType?.ToNative()); } if (iceServer.Username is not null) { nativeIceServerBuilder.SetUsername(iceServer.Username); } if (iceServer.Credential is not null) { nativeIceServerBuilder.SetPassword(iceServer.Credential); } var nativeIceServer = nativeIceServerBuilder.CreateIceServer(); return(nativeIceServer); }
RTCConfiguration GetSelectedSdpSemantics() { RTCConfiguration config = default; var rtcIceServers = new List <RTCIceServer>(); foreach (var iceServer in this.m_signaling.m_acceptMessage.iceServers) { RTCIceServer rtcIceServer = new RTCIceServer(); rtcIceServer.urls = iceServer.urls.ToArray(); rtcIceServer.username = iceServer.username; rtcIceServer.credential = iceServer.credential; rtcIceServer.credentialType = RTCIceCredentialType.OAuth; rtcIceServers.Add(rtcIceServer); } config.iceServers = rtcIceServers.ToArray(); return(config); }
/// <summary> /// Receives a new list of Ice servers and updates the local list of servers. /// </summary> /// <param name="iceServers">List of Ice servers to configure.</param> public void ConfigureIceServers(Collection <IceServer> iceServers) { _iceServers.Clear(); foreach (IceServer iceServer in iceServers) { //Url format: stun:stun.l.google.com:19302 string url = "stun:"; if (iceServer.Type == IceServer.ServerType.TURN) { url = "turn:"; } RTCIceServer server = null; url += iceServer.Host.Value; #if ORTCLIB //url += iceServer.Host.Value; server = new RTCIceServer() { Urls = new List <string>(), }; server.Urls.Add(url); #else //url += iceServer.Host.Value + ":" + iceServer.Port.Value; server = new RTCIceServer { Url = url }; #endif if (iceServer.Credential != null) { server.Credential = iceServer.Credential; } if (iceServer.Username != null) { server.Username = iceServer.Username; } _iceServers.Add(server); } }
//ピアの作成をする void CreatePeer() { //ローカル RTCConfiguration pc_config = new RTCConfiguration(); var server = new RTCIceServer(); server.urls = new string[] { "stun:stun.webrtc.ecl.ntt.com:3478" }; pc_config.iceServers = new RTCIceServer[] { server }; localConnection = new RTCPeerConnection(ref pc_config); RTCDataChannelInit conf = new RTCDataChannelInit(true); localDataChannel = localConnection.CreateDataChannel("send", ref conf); localDataChannel.OnOpen = new DelegateOnOpen(() => { Debug.Log("データチャネル:localOpen"); }); localDataChannel.OnClose = new DelegateOnClose(() => { Debug.Log("データチャネル:localClose"); }); //localDataChannel.OnMessage = onDataChannelMessage; localConnection.OnDataChannel = new DelegateOnDataChannel(x => { Debug.Log("ondatachannel"); remoteDataChannel = x; remoteDataChannel.OnMessage = onDataChannelMessage; }); localConnection.OnIceConnectionChange = new DelegateOnIceConnectionChange(state => { OnIceConnectionChange(localConnection, state); }); //ICEの登録 localConnection.OnIceCandidate = new DelegateOnIceCandidate(candidate => { if (!string.IsNullOrEmpty(candidate.candidate)) { _localIceCandidate.Add(candidate); Debug.Log("アイス:add my Ice" + candidate.candidate); } else { Debug.Log("end ice candidate"); } }); Debug.Log("crete peer"); }
private static Task <RTCPeerConnection> Createpc(WebSocketContext context, RTCIceServer stunServer, bool relayOnly) { if (_peerConnection != null) { _peerConnection.Close("normal"); } List <RTCCertificate> presetCertificates = null; if (File.Exists(LOCALHOST_CERTIFICATE_PATH)) { var localhostCert = new X509Certificate2(LOCALHOST_CERTIFICATE_PATH, (string)null, X509KeyStorageFlags.Exportable); presetCertificates = new List <RTCCertificate> { new RTCCertificate { Certificate = localhostCert } }; } RTCConfiguration pcConfiguration = new RTCConfiguration { //certificates = presetCertificates, //X_RemoteSignallingAddress = (context != null) ? context.UserEndPoint.Address : null, iceServers = stunServer != null ? new List <RTCIceServer> { stunServer } : null, iceTransportPolicy = relayOnly ? RTCIceTransportPolicy.relay : RTCIceTransportPolicy.all, //X_BindAddress = IPAddress.Any, // NOTE: Not reqd. Using this to filter out IPv6 addresses so can test with Pion. }; _peerConnection = new RTCPeerConnection(pcConfiguration); //_peerConnection.GetRtpChannel().MdnsResolve = (hostname) => Task.FromResult(NetServices.InternetDefaultAddress); _peerConnection.GetRtpChannel().MdnsResolve = MdnsResolve; //_peerConnection.GetRtpChannel().OnStunMessageReceived += (msg, ep, isrelay) => logger.LogDebug($"STUN message received from {ep}, message type {msg.Header.MessageType}."); //var dc = _peerConnection.createDataChannel(DATA_CHANNEL_LABEL, null); //dc.onmessage += (msg) => logger.LogDebug($"data channel receive ({dc.label}-{dc.id}): {msg}"); // Add a send-only audio track (this doesn't require any native libraries for encoding so is good for x-platform testing). AudioExtrasSource audioSource = new AudioExtrasSource(new AudioEncoder(), new AudioSourceOptions { AudioSource = AudioSourcesEnum.Music }); audioSource.OnAudioSourceEncodedSample += _peerConnection.SendAudio; MediaStreamTrack audioTrack = new MediaStreamTrack(audioSource.GetAudioSourceFormats(), MediaStreamStatusEnum.SendOnly); _peerConnection.addTrack(audioTrack); _peerConnection.OnAudioFormatsNegotiated += (formats) => audioSource.SetAudioSourceFormat(formats.First()); _peerConnection.onicecandidateerror += (candidate, error) => logger.LogWarning($"Error adding remote ICE candidate. {error} {candidate}"); _peerConnection.onconnectionstatechange += async(state) => { logger.LogDebug($"Peer connection state changed to {state}."); if (state == RTCPeerConnectionState.disconnected || state == RTCPeerConnectionState.failed) { _peerConnection.Close("remote disconnection"); } if (state == RTCPeerConnectionState.connected) { await audioSource.StartAudio(); } else if (state == RTCPeerConnectionState.closed) { await audioSource.CloseAudio(); } }; _peerConnection.OnReceiveReport += (re, media, rr) => logger.LogDebug($"RTCP Receive for {media} from {re}\n{rr.GetDebugSummary()}"); _peerConnection.OnSendReport += (media, sr) => logger.LogDebug($"RTCP Send for {media}\n{sr.GetDebugSummary()}"); _peerConnection.OnRtcpBye += (reason) => logger.LogDebug($"RTCP BYE receive, reason: {(string.IsNullOrWhiteSpace(reason) ? "<none>" : reason)}."); // Peer ICE connection state changes are for ICE events such as the STUN checks completing. _peerConnection.oniceconnectionstatechange += (state) => logger.LogDebug($"ICE connection state change to {state}."); _peerConnection.ondatachannel += (dc) => { logger.LogDebug($"Data channel opened by remote peer, label {dc.label}, stream ID {dc.id}."); dc.onmessage += (msg) => { logger.LogDebug($"data channel ({dc.label}:{dc.id}): {msg}."); }; }; _peerConnection.onsignalingstatechange += () => { if (_peerConnection.signalingState == RTCSignalingState.have_remote_offer) { logger.LogDebug("Remote SDP:"); logger.LogDebug(_peerConnection.remoteDescription.sdp.ToString()); } else if (_peerConnection.signalingState == RTCSignalingState.have_local_offer) { logger.LogDebug("Local SDP:"); logger.LogDebug(_peerConnection.localDescription.sdp.ToString()); } }; return(Task.FromResult(_peerConnection)); }
private static async Task RunCommand(Options options, bool noOptions) { // Plumbing code to facilitate a graceful exit. CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream. //ManualResetEvent exitMre = new ManualResetEvent(false); logger = AddConsoleLogger(); // Start MDNS server. var mdnsServer = new ServiceDiscovery(); if (options.StunServer != null) { string[] fields = options.StunServer.Split(';'); _stunServer = new RTCIceServer { urls = fields[0], username = fields.Length > 1 ? fields[1] : null, credential = fields.Length > 2 ? fields[2] : null, credentialType = RTCIceCredentialType.password }; } _relayOnly = options.RelayOnly; if (!string.IsNullOrEmpty(options.IceTypes)) { options.IceTypes.Split().ToList().ForEach(x => { if (Enum.TryParse <RTCIceCandidateType>(x, out var iceType)) { _iceTypes.Add(iceType); } }); if (!_iceTypes.Any(x => x == RTCIceCandidateType.host)) { _offerOptions = new RTCOfferOptions { X_ExcludeIceCandidates = true }; _answerOptions = new RTCAnswerOptions { X_ExcludeIceCandidates = true }; } } if (!string.IsNullOrEmpty(options.AcceptIceTypes)) { options.AcceptIceTypes.Split().ToList().ForEach(x => { if (Enum.TryParse <RTCIceCandidateType>(x, out var iceType)) { _acceptIceTypes.Add(iceType); } }); } if (options.UseWebSocket || options.UseSecureWebSocket || noOptions) { // Start web socket. Console.WriteLine("Starting web socket server..."); _webSocketServer = new WebSocketServer(IPAddress.Any, WEBSOCKET_PORT, options.UseSecureWebSocket); if (options.UseSecureWebSocket) { _webSocketServer.SslConfiguration.ServerCertificate = new X509Certificate2(LOCALHOST_CERTIFICATE_PATH); _webSocketServer.SslConfiguration.CheckCertificateRevocation = false; } _webSocketServer.AddWebSocketService <WebRTCWebSocketPeer>("/", (peer) => { peer.OfferOptions = _offerOptions; if (_acceptIceTypes != null && _acceptIceTypes.Count > 0) { peer.FilterRemoteICECandidates = (init) => _acceptIceTypes.Any(x => x == RTCIceCandidate.Parse(init.candidate).type); } peer.CreatePeerConnection = CreatePeerConnection; }); _webSocketServer.Start(); Console.WriteLine($"Waiting for browser web socket connection to {_webSocketServer.Address}:{_webSocketServer.Port}..."); } else if (!string.IsNullOrWhiteSpace(options.WebSocketServer)) { // We are the client for a web socket server. The JSON signalling exchange still occurs the same way as when the web socket // server option is used except that as the web socket client we receive the SDP offer from the server. WebRTCWebSocketClient wsockClient = new WebRTCWebSocketClient(options.WebSocketServer, CreatePeerConnection); await wsockClient.Start(exitCts.Token); Console.WriteLine("web socket client started."); } else if (options.CreateJsonOffer) { var pc = await Createpc(null, _stunServer, _relayOnly); var offerSdp = pc.createOffer(null); await pc.setLocalDescription(offerSdp); Console.WriteLine(offerSdp.sdp); var offerJson = JsonConvert.SerializeObject(offerSdp, new Newtonsoft.Json.Converters.StringEnumConverter()); var offerBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(offerJson)); Console.WriteLine(offerBase64); string remoteAnswerB64 = null; while (string.IsNullOrWhiteSpace(remoteAnswerB64)) { Console.Write("Remote Answer => "); remoteAnswerB64 = Console.ReadLine(); } string remoteAnswer = Encoding.UTF8.GetString(Convert.FromBase64String(remoteAnswerB64)); Console.WriteLine(remoteAnswer); RTCSessionDescriptionInit answerInit = JsonConvert.DeserializeObject <RTCSessionDescriptionInit>(remoteAnswer); Console.WriteLine($"Remote answer: {answerInit.sdp}"); var res = pc.setRemoteDescription(answerInit); if (res != SetDescriptionResultEnum.OK) { // No point continuing. Something will need to change and then try again. pc.Close("failed to set remote sdp"); } } else if (options.RestServer != null) { string[] fields = options.RestServer.Split(';'); if (fields.Length < 3) { throw new ArgumentException("The 'rest' option must contain 3 semi-colon separated fields, e.g. --rest=https://localhost:5001/api/webrtcsignal;myid;theirid."); } var webrtcRestPeer = new WebRTCRestSignalingPeer(fields[0], fields[1], fields[2], CreatePeerConnection); webrtcRestPeer.OfferOptions = _offerOptions; webrtcRestPeer.AnswerOptions = _answerOptions; if (_acceptIceTypes != null && _acceptIceTypes.Count > 0) { webrtcRestPeer.FilterRemoteICECandidates = (init) => _acceptIceTypes.Any(x => x == RTCIceCandidate.Parse(init.candidate).type); } await webrtcRestPeer.Start(exitCts); } _ = Task.Run(() => ProcessInput(exitCts)); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitCts.Cancel(); }; // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitCts.Token.WaitHandle.WaitOne(); Console.WriteLine(); Console.WriteLine("Exiting..."); _peerConnection?.Close("application exit"); _webSocketServer?.Stop(); Task.Delay(1000).Wait(); }
private static RTCPeerConnection Createpc(WebSocketContext context, RTCIceServer stunServer) { if (_peerConnection != null) { _peerConnection.Close("normal"); } List <RTCCertificate> presetCertificates = null; if (File.Exists(LOCALHOST_CERTIFICATE_PATH)) { var localhostCert = new X509Certificate2(LOCALHOST_CERTIFICATE_PATH, (string)null, X509KeyStorageFlags.Exportable); presetCertificates = new List <RTCCertificate> { new RTCCertificate { Certificate = localhostCert } }; } RTCConfiguration pcConfiguration = new RTCConfiguration { certificates = presetCertificates, X_RemoteSignallingAddress = (context != null) ? context.UserEndPoint.Address : null, iceServers = stunServer != null ? new List <RTCIceServer> { stunServer } : null, iceTransportPolicy = RTCIceTransportPolicy.all, //X_BindAddress = IPAddress.Any, // NOTE: Not reqd. Using this to filter out IPv6 addresses so can test with Pion. }; _peerConnection = new RTCPeerConnection(pcConfiguration); //_peerConnection.GetRtpChannel().MdnsResolve = (hostname) => Task.FromResult(NetServices.InternetDefaultAddress); _peerConnection.GetRtpChannel().MdnsResolve = MdnsResolve; _peerConnection.GetRtpChannel().OnStunMessageReceived += (msg, ep, isrelay) => logger.LogDebug($"STUN message received from {ep}, message class {msg.Header.MessageClass}."); var dc = _peerConnection.createDataChannel(DATA_CHANNEL_LABEL, null); dc.onmessage += (msg) => logger.LogDebug($"data channel receive ({dc.label}-{dc.id}): {msg}"); // Add inactive audio and video tracks. //MediaStreamTrack audioTrack = new MediaStreamTrack(SDPMediaTypesEnum.audio, false, new List<SDPMediaFormat> { new SDPMediaFormat(SDPMediaFormatsEnum.PCMU) }, MediaStreamStatusEnum.RecvOnly); //pc.addTrack(audioTrack); //MediaStreamTrack videoTrack = new MediaStreamTrack(SDPMediaTypesEnum.video, false, new List<SDPMediaFormat> { new SDPMediaFormat(SDPMediaFormatsEnum.VP8) }, MediaStreamStatusEnum.Inactive); //pc.addTrack(videoTrack); _peerConnection.onicecandidateerror += (candidate, error) => logger.LogWarning($"Error adding remote ICE candidate. {error} {candidate}"); _peerConnection.onconnectionstatechange += (state) => { logger.LogDebug($"Peer connection state changed to {state}."); if (state == RTCPeerConnectionState.disconnected || state == RTCPeerConnectionState.failed) { _peerConnection.Close("remote disconnection"); } }; _peerConnection.OnReceiveReport += (ep, type, rtcp) => logger.LogDebug($"RTCP {type} report received."); _peerConnection.OnRtcpBye += (reason) => logger.LogDebug($"RTCP BYE receive, reason: {(string.IsNullOrWhiteSpace(reason) ? "<none>" : reason)}."); _peerConnection.onicecandidate += (candidate) => { if (_peerConnection.signalingState == RTCSignalingState.have_local_offer || _peerConnection.signalingState == RTCSignalingState.have_remote_offer) { if (context != null) { context.WebSocket.Send($"candidate:{candidate}"); } } }; // Peer ICE connection state changes are for ICE events such as the STUN checks completing. _peerConnection.oniceconnectionstatechange += (state) => { logger.LogDebug($"ICE connection state change to {state}."); }; _peerConnection.ondatachannel += (dc) => { logger.LogDebug($"Data channel opened by remote peer, label {dc.label}, stream ID {dc.id}."); dc.onmessage += (msg) => { logger.LogDebug($"data channel ({dc.label}:{dc.id}): {msg}."); }; }; return(_peerConnection); }
private static async Task RunCommand(Options options, bool noOptions) { // Plumbing code to facilitate a graceful exit. CancellationTokenSource exitCts = new CancellationTokenSource(); // Cancellation token to stop the SIP transport and RTP stream. //ManualResetEvent exitMre = new ManualResetEvent(false); AddConsoleLogger(); // Start MDNS server. var mdnsServer = new ServiceDiscovery(); if (options.StunServer != null) { string[] fields = options.StunServer.Split(';'); _stunServer = new RTCIceServer { urls = fields[0], username = fields.Length > 1 ? fields[1] : null, credential = fields.Length > 2 ? fields[2] : null, credentialType = RTCIceCredentialType.password }; } if (options.UseWebSocket || options.UseSecureWebSocket || noOptions) { // Start web socket. Console.WriteLine("Starting web socket server..."); _webSocketServer = new WebSocketServer(IPAddress.Any, WEBSOCKET_PORT, options.UseSecureWebSocket); if (options.UseSecureWebSocket) { _webSocketServer.SslConfiguration.ServerCertificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(LOCALHOST_CERTIFICATE_PATH); _webSocketServer.SslConfiguration.CheckCertificateRevocation = false; } //_webSocketServer.Log.Level = WebSocketSharp.LogLevel.Debug; _webSocketServer.AddWebSocketService <WebRtcClient>("/sendoffer", (client) => { client.WebSocketOpened += SendOffer; client.OnMessageReceived += WebSocketMessageReceived; }); _webSocketServer.AddWebSocketService <WebRtcClient>("/receiveoffer", (client) => { client.WebSocketOpened += ReceiveOffer; client.OnMessageReceived += WebSocketMessageReceived; }); _webSocketServer.Start(); Console.WriteLine($"Waiting for browser web socket connection to {_webSocketServer.Address}:{_webSocketServer.Port}..."); } else if (options.CreateJsonOffer) { var pc = Createpc(null, _stunServer); var offerSdp = pc.createOffer(null); await pc.setLocalDescription(offerSdp); Console.WriteLine(offerSdp.sdp); var offerJson = JsonConvert.SerializeObject(offerSdp, new Newtonsoft.Json.Converters.StringEnumConverter()); var offerBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(offerJson)); Console.WriteLine(offerBase64); string remoteAnswerB64 = null; while (string.IsNullOrWhiteSpace(remoteAnswerB64)) { Console.Write("Remote Answer => "); remoteAnswerB64 = Console.ReadLine(); } string remoteAnswer = Encoding.UTF8.GetString(Convert.FromBase64String(remoteAnswerB64)); Console.WriteLine(remoteAnswer); RTCSessionDescriptionInit answerInit = JsonConvert.DeserializeObject <RTCSessionDescriptionInit>(remoteAnswer); Console.WriteLine($"Remote answer: {answerInit.sdp}"); var res = pc.setRemoteDescription(answerInit); if (res != SetDescriptionResultEnum.OK) { // No point continuing. Something will need to change and then try again. pc.Close("failed to set remote sdp"); } } else if (options.NodeDssServer != null) { _nodeDssUri = new Uri(options.NodeDssServer); _nodeDssclient = new HttpClient(); Console.WriteLine($"node-dss server successfully set to {_nodeDssUri}."); } _ = Task.Run(() => ProcessInput(exitCts)); // Ctrl-c will gracefully exit the call at any point. Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; exitCts.Cancel(); }; // Wait for a signal saying the call failed, was cancelled with ctrl-c or completed. exitCts.Token.WaitHandle.WaitOne(); Console.WriteLine(); Console.WriteLine("Exiting..."); _peerConnection?.Close("application exit"); _webSocketServer?.Stop(); Task.Delay(1000).Wait(); }
private void Button_Click(object sender, RoutedEventArgs e) { RTCIceGatherOptions options = new RTCIceGatherOptions(); RTCIceServer server = new RTCIceServer(); server.UserName = "******"; server.Credential = "12345"; server.Urls = new List <String>(); server.Urls.Add("stun:stun.vline.com"); options.IceServers = new List <RTCIceServer>(); options.IceServers.Add(server); _iceGatherer = new RTCIceGatherer(options); _iceGatherer.OnStateChange += this.RTCIceGatherer_onICEGathererStateChanged; _iceGatherer.OnLocalCandidate += this.RTCIceGatherer_onICEGathererLocalCandidate; _iceGatherer.OnLocalCandidateComplete += this.RTCIceGatherer_onICEGathererCandidateComplete; _iceGatherer.OnLocalCandidateGone += this.RTCIceGatherer_onICEGathererLocalCandidateGone; _iceGatherer.OnError += this.RTCIceGatherer_onICEGathererError; _iceGatherer2 = new RTCIceGatherer(options); _iceGatherer2.OnStateChange += this.RTCIceGatherer_onICEGathererStateChanged2; _iceGatherer2.OnLocalCandidate += this.RTCIceGatherer_onICEGathererLocalCandidate2; _iceGatherer2.OnLocalCandidateComplete += this.RTCIceGatherer_onICEGathererCandidateComplete2; _iceGatherer2.OnLocalCandidateGone += this.RTCIceGatherer_onICEGathererLocalCandidateGone2; _iceGatherer2.OnError += this.RTCIceGatherer_onICEGathererError; _iceTransport = new RTCIceTransport(_iceGatherer); _iceTransport.OnStateChange += RTCIceTransport_onICETransportStateChanged; _iceTransport.OnCandidatePairAvailable += RTCIceTransport_onICETransportCandidatePairAvailable; _iceTransport.OnCandidatePairGone += RTCIceTransport_onICETransportCandidatePairGone; _iceTransport.OnCandidatePairChange += RTCIceTransport_onICETransportCandidatePairChanged; _iceTransport2 = new RTCIceTransport(_iceGatherer); _iceTransport2.OnStateChange += RTCIceTransport_onICETransportStateChanged2; _iceTransport2.OnCandidatePairAvailable += RTCIceTransport_onICETransportCandidatePairAvailable2; _iceTransport2.OnCandidatePairGone += RTCIceTransport_onICETransportCandidatePairGone2; _iceTransport2.OnCandidatePairChange += RTCIceTransport_onICETransportCandidatePairChanged2; RTCCertificate.GenerateCertificate().AsTask <RTCCertificate>().ContinueWith((cert) => { String str = cert.Result.Expires.ToString(); List <RTCCertificate> certs = new List <RTCCertificate>(); certs.Add(cert.Result); _dtlsTransport = new RTCDtlsTransport(_iceTransport, certs); MediaStreamConstraints constraints = new MediaStreamConstraints(); constraints.Audio = new MediaTrackConstraints(); constraints.Video = new MediaTrackConstraints(); MediaDevices.GetUserMedia(constraints).AsTask().ContinueWith <IList <MediaStreamTrack> >((temp) => { if (temp.Result != null && temp.Result.Count() > 0) { List <MediaStreamTrack> ret = new List <MediaStreamTrack>(temp.Result); List <RTCRtpSender> senders = new List <RTCRtpSender>(); foreach (MediaStreamTrack track in temp.Result) { RTCRtpSender rtpSender = new RTCRtpSender(track, _dtlsTransport); senders.Add(rtpSender); } return(ret); } return(null); }); }); RTCCertificate.GenerateCertificate().AsTask <RTCCertificate>().ContinueWith((cert) => { var certs = new List <RTCCertificate>(); certs.Add(cert.Result); _dtlsTransport2 = new RTCDtlsTransport(_iceTransport2, certs); }); MediaDevices.EnumerateDevices().AsTask().ContinueWith <MediaDeviceInfo>((temp) => { foreach (MediaDeviceInfo info in temp.Result) { if (info.DeviceId != null) { System.Diagnostics.Debug.WriteLine("DeviceID: {0}", info.DeviceId); } } return(null); }); }
public static Core.IceServer ToNativePort(this RTCIceServer platformNative) => new Core.IceServer(urlStrings: platformNative.UrlStrings, username: platformNative.Username, credential: platformNative.Credential, policy: platformNative.TlsCertPolicy.ToNativePort(), hostname: platformNative.Hostname, tlsEllipticCurves: platformNative.TlsEllipticCurves, tlsAlpnProtocols: platformNative.TlsAlpnProtocols);