Пример #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="WebRTCAdapter"/> class.
        /// </summary>
        /// <param name="signalingTransporter">The signaling transporter.</param>
        /// <param name="role">The adapter role.</param>
        public WebRTCAdapter(IResonanceTransporter signalingTransporter, WebRTCAdapterRole role) : this()
        {
            Role = role;
            _signalingTransporter = signalingTransporter;

            _signalingTransporter.RegisterRequestHandler <WebRTCIceCandidateRequest, WebRTCIceCandidateResponse>(OnWebRTCCandidateRequest);
            _signalingTransporter.RegisterRequestHandler <WebRTCOfferRequest, WebRTCOfferResponse>(OnWebRTCOfferRequest);
        }
Пример #2
0
        private async void _server_ConnectionRequest(object sender, ResonanceListeningServerConnectionRequestEventArgs <BluetoothAdapter> e)
        {
            IResonanceTransporter transporter = ResonanceTransporter.Builder
                                                .Create()
                                                .WithAdapter(e.Accept())
                                                .WithJsonTranscoding()
                                                .Build();

            transporter.StateChanged += (x, ee) =>
            {
                if (ee.NewState != ResonanceComponentState.Connected)
                {
                    InvokeUI(() =>
                    {
                        ConnectedDevices.Remove(transporter);
                    });
                }
            };

            transporter.RegisterRequestHandler <ChatMessageRequest, ChatMessageResponse>(OnChatRequest);

            await transporter.ConnectAsync();

            InvokeUI(() =>
            {
                ConnectedDevices.Add(transporter);
                if (SelectedDevice == null)
                {
                    SelectedDevice = transporter;
                }
            });
        }
 /// <summary>
 /// Registers for a WebRTC offer request.
 /// Should be used only from a 'Signaling' transporter.
 /// </summary>
 /// <param name="transporter">The transporter.</param>
 /// <param name="callback">Callback method with the Offer request.</param>
 public static void OnWebRtcOffer(this IResonanceTransporter transporter, Action <ResonanceMessage <WebRTCOfferRequest> > callback)
 {
     transporter.RegisterRequestHandler <WebRTCOfferRequest>((_, request) =>
     {
         callback?.Invoke(request);
     });
 }
Пример #4
0
        /// <summary>
        /// Starts a SignalR session and WebRTC session with the selected client.
        /// </summary>
        private async void StartSession()
        {
            if (!IsInSession)
            {
                try
                {
                    IsFree = false;

                    Logger.LogInformation($"Starting SignalR session with {SelectedClient.ServiceId} for signaling...");

                    _signalingTransporter = ResonanceTransporter.Builder
                                            .Create()
                                            .WithSignalRAdapter(SignalRMode.Legacy)
                                            .WithCredentials(new DemoCredentials()
                    {
                        Name = ClientID
                    })
                                            .WithServiceId(SelectedClient.ServiceId)
                                            .WithUrl(HubUrl)
                                            .WithJsonTranscoding()
                                            .Build();

                    _signalingTransporter.ConnectionLost += OnSignalingConnectionLost;

                    await _signalingTransporter.ConnectAsync();

                    Logger.LogInformation("SignalR session started.");
                    Logger.LogInformation("Initiating WebRTC session...");

                    _webRtcTransporter = ResonanceTransporter.Builder
                                         .Create()
                                         .WithWebRTCAdapter()
                                         .WithSignalingTransporter(_signalingTransporter)
                                         .WithRole(WebRTCAdapterRole.Connect)
                                         .WithDefaultIceServers()
                                         .WithJsonTranscoding()
                                         .Build();

                    _webRtcTransporter.ConnectionLost += OnWebRTCConnectionLost;

                    _webRtcTransporter.RegisterRequestHandler <EchoTextRequest, EchoTextResponse>(OnEchoTextMessageReceived);

                    Logger.LogInformation("Connecting WebRTC transporter.");
                    await _webRtcTransporter.ConnectAsync();

                    IsInSession = true;

                    Logger.LogInformation("WebRTC transporter connected!");
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex, ex.Message);
                }
                finally
                {
                    IsFree = true;
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Handles incoming signaling connection request from the registered listening service.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="ConnectionRequestEventArgs{DemoCredentials, DemoAdapterInformation}"/> instance containing the event data.</param>
        private async void OnServiceConnectionRequest(object sender, ConnectionRequestEventArgs <DemoCredentials, DemoAdapterInformation> e)
        {
            Logger.LogInformation($"Connection request from {e.RemoteAdapterInformation.Name}.");

            if (IsInSession)
            {
                Logger.LogInformation($"Already in session. Connection request declined.");
                e.Decline();
                return;
            }

            try
            {
                Logger.LogInformation("Starting SignalR session for signaling...");

                SelectedClient = ConnectedClients.FirstOrDefault(x => x.ServiceId == e.RemoteAdapterInformation.Name);

                IsFree = false;

                _signalingTransporter = ResonanceTransporter.Builder
                                        .Create()
                                        .WithAdapter(e.Accept())
                                        .WithJsonTranscoding()
                                        .Build();

                _signalingTransporter.ConnectionLost += OnSignalingConnectionLost;

                await _signalingTransporter.ConnectAsync();

                Logger.LogInformation("SignalR session started. Waiting for WebRTC offer...");

                Logger.LogInformation("Connecting WebRTC transporter...");
                _webRtcTransporter = ResonanceTransporter.Builder
                                     .Create()
                                     .WithWebRTCAdapter()
                                     .WithSignalingTransporter(_signalingTransporter)
                                     .WithRole(WebRTCAdapterRole.Accept)
                                     .WithDefaultIceServers()
                                     .WithJsonTranscoding()
                                     .Build();

                _webRtcTransporter.ConnectionLost += OnWebRTCConnectionLost;
                _webRtcTransporter.RegisterRequestHandler <EchoTextRequest, EchoTextResponse>(OnEchoTextMessageReceived);

                await _webRtcTransporter.ConnectAsync();

                IsInSession = true;
                IsFree      = true;

                Logger.LogInformation("WebRTC transporter connected!");
            }
            catch (Exception ex)
            {
                IsFree = true;
                Logger.LogError(ex, "");
            }
        }
Пример #6
0
        private async void Connect()
        {
            if (!IsConnected)
            {
                try
                {
                    IsFree = false;

                    _transporter = ResonanceTransporter.Builder
                                   .Create()
                                   .WithTcpAdapter()
                                   .WithAddress(SelectedService.Address)
                                   .WithPort(SelectedService.DiscoveryInfo.Port)
                                   .WithJsonTranscoding()
                                   .Build();

                    _transporter.ConnectionLost += ConnectionLost;
                    _transporter.RegisterRequestHandler <JoinSessionRequest>(OnJoinSessionRequest);
                    _transporter.RegisterRequestHandler <NotifyAvailableClientsRequest>(OnNotifyAvailableClientsRequest);
                    _transporter.RegisterRequestHandler <EchoTextRequest, EchoTextResponse>(OnEchoTextRequest);
                    _transporter.RegisterRequestHandler <LeaveSessionRequest>(OnLeaveSessionRequest);

                    await _transporter.ConnectAsync();

                    await _transporter.SendRequestAsync <LoginRequest, LoginResponse>(new LoginRequest()
                    {
                        ClientID = ClientID
                    });

                    await _discoveryClient.StopAsync();

                    IsConnected = true;
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex, ex.Message);
                }
                finally
                {
                    IsFree = true;
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="WebRTCAdapter"/> class.
        /// </summary>
        /// <param name="signalingTransporter">The signaling transporter.</param>
        /// <param name="role">The adapter role.</param>
        public WebRTCAdapterNative(IResonanceTransporter signalingTransporter, WebRTCAdapterRole role) : this()
        {
            Role = role;
            _signalingTransporter = signalingTransporter;

            if (_offerRequest == null)
            {
                _signalingTransporter.RegisterRequestHandler <WebRTCOfferRequest, WebRTCOfferResponse>(OnWebRTCOfferRequest);
            }
        }
Пример #8
0
        private async void Connect()
        {
            try
            {
                using (UserDialogs.Instance.Loading("Connecting..."))
                {
                    _transporter = ResonanceTransporter.Builder
                                   .Create()
                                   .WithAdapter(new BluetoothAdapter(SelectedDevice))
                                   .WithJsonTranscoding()
                                   .Build();

                    _transporter.StateChanged += (x, e) =>
                    {
                        InvokeUI(async() =>
                        {
                            SendCommand.ChangeCanExecute();

                            if (e.PreviousState == ResonanceComponentState.Connected && e.NewState == ResonanceComponentState.Failed)
                            {
                                await Navigation.PopAsync();
                                UserDialogs.Instance.Toast($"Connection lost.\n{_transporter.FailedStateException}");
                            }
                        });
                    };

                    _transporter.RegisterRequestHandler <ChatMessageRequest, ChatMessageResponse>(OnChatRequest);

                    await _transporter.ConnectAsync();

                    SelectedDevice.Refresh();
                    Logs.Clear();
                }

                await Navigation.PushAsync(new ChatPage(), true);
            }
            catch (Exception ex)
            {
                UserDialogs.Instance.Toast($"Error connecting to the selected device.\n{ex.Message}");
            }
        }
Пример #9
0
        public void Stress_Test_With_Small_Data_Volume()
        {
            if (IsRunningOnAzurePipelines)
            {
                return;
            }

            IResonanceTransporter signal1 = ResonanceTransporter.Builder
                                            .Create()
                                            .WithInMemoryAdapter()
                                            .WithAddress("TST")
                                            .WithJsonTranscoding()
                                            .Build();

            IResonanceTransporter signal2 = ResonanceTransporter.Builder
                                            .Create()
                                            .WithInMemoryAdapter()
                                            .WithAddress("TST")
                                            .WithJsonTranscoding()
                                            .Build();

            signal1.Connect();
            signal2.Connect();

            WebRTCAdapter adapter1 = null;

            signal1.RegisterRequestHandler <WebRTCOfferRequest>(async(_, request) =>
            {
                adapter1 = new WebRTCAdapter(signal1, request.Object, request.Token);
                await adapter1.ConnectAsync();
            });

            WebRTCAdapter adapter2 = new WebRTCAdapter(signal2, WebRTCAdapterRole.Connect);

            adapter2.Connect();

            IResonanceTransporter t1 = ResonanceTransporter.Builder
                                       .Create()
                                       .WithAdapter(adapter1)
                                       .WithJsonTranscoding()
                                       .Build();

            IResonanceTransporter t2 = ResonanceTransporter.Builder
                                       .Create()
                                       .WithAdapter(adapter2)
                                       .WithJsonTranscoding()
                                       .Build();

            t2.RequestReceived += (x, e) =>
            {
                t2.SendResponseAsync(new LargeMessageResponse()
                {
                    Data = (e.Message.Object as LargeMessageRequest).Data
                }, e.Message.Token);
            };

            t1.Connect();
            t2.Connect();

            t1.DefaultRequestTimeout = TimeSpan.FromSeconds(60);

            for (int i = 0; i < 100; i++)
            {
                byte[] data     = TestHelper.GetRandomByteArray(2);
                var    response = t1.SendRequest <LargeMessageRequest, LargeMessageResponse>(new LargeMessageRequest()
                {
                    Data = data
                });
                Assert.IsTrue(data.SequenceEqual(response.Data));
            }

            t1.Dispose();
            t2.Dispose();
            signal1.Dispose();
            signal2.Dispose();
        }
Пример #10
0
        public void Message_Larger_Than_16_KB_Splits()
        {
            if (IsRunningOnAzurePipelines)
            {
                return;
            }

            IResonanceTransporter signal1 = ResonanceTransporter.Builder
                                            .Create()
                                            .WithInMemoryAdapter()
                                            .WithAddress("TST")
                                            .WithJsonTranscoding()
                                            .Build();

            IResonanceTransporter signal2 = ResonanceTransporter.Builder
                                            .Create()
                                            .WithInMemoryAdapter()
                                            .WithAddress("TST")
                                            .WithJsonTranscoding()
                                            .Build();

            signal1.Connect();
            signal2.Connect();

            WebRTCAdapter adapter1 = null;

            signal1.RegisterRequestHandler <WebRTCOfferRequest>(async(_, request) =>
            {
                adapter1 = new WebRTCAdapter(signal1, request.Object, request.Token);
                await adapter1.ConnectAsync();
            });

            WebRTCAdapter adapter2 = new WebRTCAdapter(signal2, WebRTCAdapterRole.Connect);

            adapter2.Connect();

            IResonanceTransporter t1 = ResonanceTransporter.Builder
                                       .Create()
                                       .WithAdapter(adapter1)
                                       .WithJsonTranscoding()
                                       .Build();

            IResonanceTransporter t2 = ResonanceTransporter.Builder
                                       .Create()
                                       .WithAdapter(adapter2)
                                       .WithJsonTranscoding()
                                       .Build();

            t2.RequestReceived += (x, e) =>
            {
                t2.SendResponseAsync(new LargeMessageResponse()
                {
                    Data = (e.Message.Object as LargeMessageRequest).Data
                }, e.Message.Token);
            };

            t1.Connect();
            t2.Connect();

            byte[] data = TestHelper.GetRandomByteArray(200);

            var response = t1.SendRequest <LargeMessageRequest, LargeMessageResponse>(new LargeMessageRequest()
            {
                Data = data
            });

            Assert.IsTrue(data.SequenceEqual(response.Data));

            t1.Dispose();
            t2.Dispose();
            signal1.Dispose();
            signal2.Dispose();
        }
Пример #11
0
        public void Create_Adapter_From_Offer()
        {
            if (IsRunningOnAzurePipelines)
            {
                return;
            }

            IResonanceTransporter signal1 = ResonanceTransporter.Builder
                                            .Create()
                                            .WithInMemoryAdapter()
                                            .WithAddress("TST")
                                            .WithJsonTranscoding()
                                            .Build();

            IResonanceTransporter signal2 = ResonanceTransporter.Builder
                                            .Create()
                                            .WithInMemoryAdapter()
                                            .WithAddress("TST")
                                            .WithJsonTranscoding()
                                            .Build();

            signal1.Connect();
            signal2.Connect();

            WebRTCAdapter adapter1 = null;

            signal1.RegisterRequestHandler <WebRTCOfferRequest>(async(_, request) =>
            {
                adapter1 = new WebRTCAdapter(signal1, request.Object, request.Token);
                await adapter1.ConnectAsync();
            });

            WebRTCAdapter adapter2 = new WebRTCAdapter(signal2, WebRTCAdapterRole.Connect);

            adapter2.Connect();

            IResonanceTransporter t1 = ResonanceTransporter.Builder
                                       .Create()
                                       .WithAdapter(adapter1)
                                       .WithJsonTranscoding()
                                       .Build();

            IResonanceTransporter t2 = ResonanceTransporter.Builder
                                       .Create()
                                       .WithAdapter(adapter2)
                                       .WithJsonTranscoding()
                                       .Build();

            t2.RequestReceived += (x, e) =>
            {
                t2.SendResponseAsync(new CalculateResponse()
                {
                    Sum = 15
                }, e.Message.Token);
            };

            t1.Connect();
            t2.Connect();

            var response = t1.SendRequest <CalculateRequest, CalculateResponse>(new CalculateRequest()
            {
                A = 10, B = 5
            });

            Assert.IsTrue(response.Sum == 15);

            t1.Dispose();
            t2.Dispose();
            signal1.Dispose();
            signal2.Dispose();
        }
Пример #12
0
        public void Transporters_Router_Standard_Routes_Data()
        {
            IResonanceTransporter receiver1 = null;
            IResonanceTransporter client1   = null;
            IResonanceTransporter receiver2 = null;
            IResonanceTransporter client2   = null;
            TransporterRouter     router    = null;

            ResonanceTcpServer server = new ResonanceTcpServer(1333);

            server.ConnectionRequest += (x, e) =>
            {
                if (receiver1 == null)
                {
                    receiver1 = ResonanceTransporter.Builder.Create()
                                .WithAdapter(e.Accept())
                                .WithJsonTranscoding()
                                .Build();

                    receiver1.Connect();
                }
                else
                {
                    receiver2 = ResonanceTransporter.Builder.Create()
                                .WithAdapter(e.Accept())
                                .WithJsonTranscoding()
                                .Build();

                    receiver2.Connect();

                    router = new TransporterRouter(receiver1, receiver2, RoutingMode.TwoWay, WritingMode.Standard);
                    router.Bind();
                }
            };
            server.Start();


            client1 = ResonanceTransporter.Builder.Create()
                      .WithTcpAdapter()
                      .WithAddress("127.0.0.1")
                      .WithPort(1333)
                      .WithJsonTranscoding()
                      .Build();

            client1.Connect();

            client2 = ResonanceTransporter.Builder.Create()
                      .WithTcpAdapter()
                      .WithAddress("127.0.0.1")
                      .WithPort(1333)
                      .WithJsonTranscoding()
                      .Build();

            client2.Connect();

            client2.RegisterRequestHandler <CalculateRequest, CalculateResponse>((request) =>
            {
                return(new CalculateResponse()
                {
                    Sum = request.A + request.B
                });
            });

            client1.RegisterRequestHandler <CalculateRequest, CalculateResponse>((request) =>
            {
                return(new CalculateResponse()
                {
                    Sum = request.A + request.B
                });
            });

            Thread.Sleep(1000);

            receiver1.RequestReceived += (_, __) =>
            {
                Assert.Fail();
            };

            receiver2.RequestReceived += (_, __) =>
            {
                Assert.Fail();
            };

            var response = client1.SendRequest <CalculateRequest, CalculateResponse>(new CalculateRequest()
            {
                A = 10,
                B = 5
            });

            Assert.AreEqual(response.Sum, 15);

            response = client2.SendRequest <CalculateRequest, CalculateResponse>(new CalculateRequest()
            {
                A = 11,
                B = 5
            });

            Assert.AreEqual(response.Sum, 16);

            client1.Dispose();
            client2.Dispose();
            receiver1.Dispose();
            receiver2.Dispose();
            server.Dispose();
            router.Dispose();
        }
Пример #13
0
        protected override Task OnConnect()
        {
            _connectionCompleted      = false;
            _closeConnection          = false;
            _receivedSegments         = new List <byte[]>();
            _expectedSegments         = 0;
            _expectedSegmentsCheckSum = null;
            _incomingQueue            = new ProducerConsumerQueue <byte[]>();
            _conductorInitialized     = false;

            _connectionCompletionSource = new TaskCompletionSource <object>();

            _signalingTransporter.RegisterRequestHandler <WebRTCIceCandidateRequest, WebRTCIceCandidateResponse>(OnWebRTCCandidateRequest);

            Logger.LogDebug("Initializing adapter with role '{Role}'.", Role);

            if (Role == WebRTCAdapterRole.Accept)
            {
                ThreadFactory.StartNew(async() =>
                {
                    try
                    {
                        await InitConnection();

                        if (_offerRequest != null)
                        {
                            Logger.LogDebug("Adapter initialized by an offer request. sending answer...");
                            var response = await OnWebRTCOfferRequest(_offerRequest);
                            if (_closeConnection)
                            {
                                return;
                            }
                            _signalingTransporter.SendResponse(response.Response, _offerRequestToken);
                        }
                        else
                        {
                            Logger.LogDebug("Waiting for WebRTC offer...");
                        }
                    }
                    catch (Exception ex)
                    {
                        if (!_connectionCompleted)
                        {
                            _connectionCompleted = true;
                            _connectionCompletionSource.SetException(new ResonanceWebRTCConnectionFailedException(ex));
                            _closeConnection = true;
                        }
                    }
                });
            }
            else
            {
                ThreadFactory.StartNew(async() =>
                {
                    try
                    {
                        await InitConnection();

                        var offer = await CreateOffer();

                        var response = await _signalingTransporter.SendRequestAsync <WebRTCOfferRequest, WebRTCOfferResponse>(new WebRTCOfferRequest()
                        {
                            Offer = offer,
                        }, new ResonanceRequestConfig()
                        {
                            Timeout = TimeSpan.FromSeconds(30)
                        });

                        _conductor.OnOfferReply("answer", response.Answer.Sdp);

                        FlushIceCandidates();
                    }
                    catch (Exception ex)
                    {
                        if (!_connectionCompleted)
                        {
                            _connectionCompleted = true;
                            _connectionCompletionSource.SetException(new ResonanceWebRTCConnectionFailedException(ex));
                            _closeConnection = true;
                        }
                    }
                });
            }

            TimeoutTask.StartNew(() =>
            {
                if (!_connectionCompleted)
                {
                    _connectionCompleted = true;
                    _connectionCompletionSource.SetException(new ResonanceWebRTCConnectionFailedException(new TimeoutException("Could not initialize the connection within the given timeout.")));
                    _closeConnection = true;
                }
            }, ConnectionTimeout);

            return(_connectionCompletionSource.Task);
        }
Пример #14
0
        public void Tcp_Connect_Send_And_Receive_100_Concurrent_Transporters()
        {
            if (IsRunningOnAzurePipelines)
            {
                return;
            }

            List <IResonanceTransporter> receivers = new List <IResonanceTransporter>();

            ResonanceTcpServer server = new ResonanceTcpServer(4321);

            server.ConnectionRequest += (x, e) =>
            {
                IResonanceTransporter t = ResonanceTransporter.Builder.Create()
                                          .WithAdapter(e.Accept())
                                          .WithJsonTranscoding()
                                          .Build();

                receivers.Add(t);

                t.RegisterRequestHandler <CalculateRequest, CalculateResponse>((request) =>
                {
                    return(new CalculateResponse()
                    {
                        Sum = request.A + request.B
                    });
                });

                t.Connect();
            };

            server.Start();

            List <Thread> threads = new List <Thread>();

            for (int i = 0; i < 100; i++)
            {
                var t = ThreadFactory.StartNew(() =>
                {
                    IResonanceTransporter client = ResonanceTransporter.Builder.Create()
                                                   .WithTcpAdapter()
                                                   .WithAddress("127.0.0.1")
                                                   .WithPort(4321)
                                                   .WithJsonTranscoding()
                                                   .Build();

                    client.Connect();

                    var request = new CalculateRequest()
                    {
                        A = 10, B = 15
                    };
                    var response = client.SendRequest <CalculateRequest, CalculateResponse>(request, new ResonanceRequestConfig()
                    {
                        Timeout = TimeSpan.FromSeconds(5)
                    });

                    Assert.AreEqual(response.Sum, request.A + request.B);

                    client.Dispose();
                });

                threads.Add(t);
            }

            TestHelper.WaitWhile(() => threads.Count < 100 || receivers.Count < 100, TimeSpan.FromSeconds(30));

            threads.ForEach(x => x.Join());
            receivers.ForEach(x => x.Dispose());
            server.Dispose();
        }