public async Task OutOfBand() { // Disable auto-renegotiation suspendOffer1_ = true; suspendOffer2_ = true; // Add out-of-band data channels const int DataChannelId = 42; DataChannel data1 = await pc1_.AddDataChannelAsync(DataChannelId, "my_channel", ordered : true, reliable : true); DataChannel data2 = await pc2_.AddDataChannelAsync(DataChannelId, "my_channel", ordered : true, reliable : true); // Check consistency Assert.AreEqual(data1.ID, data2.ID); Assert.AreEqual(data1.Label, data2.Label); // Prepare for state change var evOpen1 = new ManualResetEventSlim(initialState: false); data1.StateChanged += () => { if (data1.State == DataChannel.ChannelState.Open) { evOpen1.Set(); } }; var evOpen2 = new ManualResetEventSlim(initialState: false); data2.StateChanged += () => { if (data2.State == DataChannel.ChannelState.Open) { evOpen2.Set(); } }; // Connect StartOfferWith(pc1_); WaitForSdpExchangeCompleted(); // Wait until the data channels are ready Assert.True(evOpen1.Wait(TimeSpan.FromSeconds(60.0))); Assert.True(evOpen2.Wait(TimeSpan.FromSeconds(60.0))); // Send data { var c2 = new ManualResetEventSlim(false); string sentText = "Some sample text"; byte[] msg = Encoding.UTF8.GetBytes(sentText); data2.MessageReceived += (byte[] _msg) => { var receivedText = Encoding.UTF8.GetString(_msg); Assert.AreEqual(sentText, receivedText); c2.Set(); }; data1.SendMessage(msg); Assert.True(c2.Wait(TimeSpan.FromSeconds(60.0))); } }
/// <summary> /// This method is called when new data could be send. /// It will call send() and serialize the data and send it using the dataChannel. /// </summary> protected void PosMessageSend() { var r = Send(); if (r == null) { return; } using (var ms = new MemoryStream()) { binaryFormatter.Serialize(ms, r); dataChannel.SendMessage(ms.ToArray()); } }
private void ChatSendButton_Click(object sender, RoutedEventArgs e) { if (string.IsNullOrWhiteSpace(chatInputBox.Text)) { return; } byte[] chatMessage = System.Text.Encoding.UTF8.GetBytes(chatInputBox.Text); _chatDataChannel.SendMessage(chatMessage); chatTextBox.Text += $"[local] {chatInputBox.Text}\n"; chatScrollViewer.ChangeView(chatScrollViewer.HorizontalOffset, chatScrollViewer.ScrollableHeight, chatScrollViewer.ZoomFactor); // scroll to end chatInputBox.Text = string.Empty; }
private void Window_MouseMove(object sender, MouseEventArgs e) { if (_dc != null && _dc.State == DataChannel.ChannelState.Open) { var mousePos = Mouse.GetPosition(this); var mouseEvent = new MouseMoveEvent() { WindowHeight = this.Height, WindowWidth = this.Width, MouseX = mousePos.X, MouseY = mousePos.Y, }; var msg = JsonConvert.SerializeObject(mouseEvent); _dc.SendMessage(Encoding.UTF8.GetBytes(msg)); } }
public async Task InBand() { // Setup var config = new PeerConnectionConfiguration(); var pc1 = new PeerConnection(); var pc2 = new PeerConnection(); await pc1.InitializeAsync(config); await pc2.InitializeAsync(config); pc1.LocalSdpReadytoSend += (string type, string sdp) => { pc2.SetRemoteDescription(type, sdp); if (type == "offer") { pc2.CreateAnswer(); } }; pc2.LocalSdpReadytoSend += (string type, string sdp) => { pc1.SetRemoteDescription(type, sdp); if (type == "offer") { pc1.CreateAnswer(); } }; pc1.IceCandidateReadytoSend += (string candidate, int sdpMlineindex, string sdpMid) => pc2.AddIceCandidate(sdpMid, sdpMlineindex, candidate); pc2.IceCandidateReadytoSend += (string candidate, int sdpMlineindex, string sdpMid) => pc1.AddIceCandidate(sdpMid, sdpMlineindex, candidate); // Add dummy out-of-band data channel to force SCTP negotiating. // Otherwise after connecting AddDataChannelAsync() will fail. await pc1.AddDataChannelAsync(42, "dummy", false, false); await pc2.AddDataChannelAsync(42, "dummy", false, false); // Connect { var c1 = new ManualResetEventSlim(false); var c2 = new ManualResetEventSlim(false); pc1.Connected += () => c1.Set(); pc2.Connected += () => c2.Set(); Assert.True(pc1.CreateOffer()); Assert.True(c1.Wait(TimeSpan.FromSeconds(60.0))); Assert.True(c2.Wait(TimeSpan.FromSeconds(60.0))); Assert.True(pc1.IsConnected); Assert.True(pc1.IsConnected); } // Negotiate data channel in-band DataChannel data1 = null; DataChannel data2 = null; { var c2 = new ManualResetEventSlim(false); pc2.DataChannelAdded += (DataChannel channel) => { data2 = channel; c2.Set(); }; data1 = await pc1.AddDataChannelAsync("test_data_channel", true, true); Assert.IsNotNull(data1); Assert.True(c2.Wait(TimeSpan.FromSeconds(60.0))); Assert.IsNotNull(data2); Assert.AreEqual(data1.Label, data2.Label); // Do not test DataChannel.ID; at this point for in-band channels the ID has not // been agreed upon with the remote peer yet. } // Send data { var c2 = new ManualResetEventSlim(false); string sentText = "Some sample text"; byte[] msg = Encoding.UTF8.GetBytes(sentText); data2.MessageReceived += (byte[] _msg) => { var receivedText = Encoding.UTF8.GetString(_msg); Assert.AreEqual(sentText, receivedText); c2.Set(); }; data1.SendMessage(msg); Assert.True(c2.Wait(TimeSpan.FromSeconds(60.0))); } // Clean-up pc1.Close(); pc1.Dispose(); pc2.Close(); pc2.Dispose(); }
public async Task InBand() { // Disable auto-renegotiation suspendOffer1_ = true; suspendOffer2_ = true; // Add dummy out-of-band data channel to force SCTP negotiating. // Otherwise after connecting AddDataChannelAsync() will fail. await pc1_.AddDataChannelAsync(42, "dummy", false, false); await pc2_.AddDataChannelAsync(42, "dummy", false, false); Assert.True(renegotiationEvent1_.Wait(TimeSpan.FromSeconds(60.0))); Assert.True(renegotiationEvent2_.Wait(TimeSpan.FromSeconds(60.0))); renegotiationEvent1_.Reset(); renegotiationEvent2_.Reset(); // Connect StartOfferWith(pc1_); WaitForSdpExchangeCompleted(); // Ensure auto-renegotiation is active suspendOffer1_ = false; suspendOffer2_ = false; // Negotiate data channel in-band DataChannel data1 = null; DataChannel data2 = null; { var c2 = new ManualResetEventSlim(false); pc2_.DataChannelAdded += (DataChannel channel) => { data2 = channel; c2.Set(); }; // Note that for SCTP data channels (always the case in MixedReality-WebRTC) a renegotiation // needed event is triggered only on the first data channel created. Since dummy channels were // added above to trigger SCTP handshake, this one below will not trigger a renegotiation event. data1 = await pc1_.AddDataChannelAsync("test_data_channel", ordered : true, reliable : true); Assert.IsNotNull(data1); Assert.True(c2.Wait(TimeSpan.FromSeconds(60.0))); Assert.IsNotNull(data2); Assert.AreEqual(data1.ID, data2.ID); Assert.AreEqual(data1.Label, data2.Label); } // Send data { var c2 = new ManualResetEventSlim(false); string sentText = "Some sample text"; byte[] msg = Encoding.UTF8.GetBytes(sentText); data2.MessageReceived += (byte[] _msg) => { var receivedText = Encoding.UTF8.GetString(_msg); Assert.AreEqual(sentText, receivedText); c2.Set(); }; data1.SendMessage(msg); Assert.True(c2.Wait(TimeSpan.FromSeconds(60.0))); } }
static async Task Main(string[] args) { DataChannel dataChannel = null; try { // Create a new peer connection automatically disposed at the end of the program using var pc = new PeerConnection(); // Initialize the connection with a STUN server to allow remote access var config = new PeerConnectionConfiguration { IceServers = new List <IceServer> { new IceServer { Urls = { "stun:stun.l.google.com:19302" } } } }; await pc.InitializeAsync(config); Console.WriteLine("Peer connection initialized."); Console.WriteLine("Opening data channel"); dataChannel = await pc.AddDataChannelAsync("data", true, true); // Setup signaling Console.WriteLine("Starting signaling..."); var signaler = new NamedPipeSignaler.NamedPipeSignaler(pc, "testpipe"); signaler.SdpMessageReceived += (string type, string sdp) => { pc.SetRemoteDescription(type, sdp); if (type == "offer") { pc.CreateAnswer(); } }; signaler.IceCandidateReceived += (string sdpMid, int sdpMlineindex, string candidate) => { pc.AddIceCandidate(sdpMid, sdpMlineindex, candidate); }; await signaler.StartAsync(); // Start peer connection pc.Connected += () => { Console.WriteLine("PeerConnection: connected."); }; pc.IceStateChanged += (IceConnectionState newState) => { Console.WriteLine($"ICE state: {newState}"); }; pc.DataChannelAdded += (DataChannel c) => { Console.WriteLine("DataChannel added"); c.MessageReceived += (byte[] _msg) => { Console.WriteLine("received {0} bytes", _msg.Length); }; }; if (signaler.IsClient) { Console.WriteLine("Connecting to remote peer..."); pc.CreateOffer(); } else { Console.WriteLine("Waiting for offer from remote peer..."); } Console.WriteLine("Press a 'S' to send data. 'Esc' to exit ..."); ConsoleKeyInfo key; while ((key = Console.ReadKey(true)).Key != ConsoleKey.Escape) { if (key.Key == ConsoleKey.S) { Console.WriteLine("Sending data"); dataChannel.SendMessage(new byte[3000]); } } signaler.Stop(); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("Program termined."); }