예제 #1
0
        public void Handle(UpdateCall update)
        {
            _call = update.Call;

            if (update.Call.State is CallStatePending pending)
            {
                if (update.Call.IsOutgoing && pending.IsCreated && pending.IsReceived)
                {
                    if (pending.IsCreated && pending.IsReceived)
                    {
                        _mediaPlayer.Source           = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/Audio/voip_ringback.mp3"));
                        _mediaPlayer.IsLoopingEnabled = true;
                        _mediaPlayer.Play();
                    }
                }
            }
            if (update.Call.State is CallStateReady ready)
            {
                var user = CacheService.GetUser(update.Call.UserId);
                if (user == null)
                {
                    return;
                }

                VoIPControllerWrapper.UpdateServerConfig(ready.Config);

                var logFile       = Path.Combine(ApplicationData.Current.LocalFolder.Path, $"{SessionId}", "tgvoip.logFile.txt");
                var statsDumpFile = Path.Combine(ApplicationData.Current.LocalFolder.Path, $"{SessionId}", "tgvoip.statsDump.txt");

                var call_packet_timeout_ms  = CacheService.GetOption <OptionValueInteger>("call_packet_timeout_ms");
                var call_connect_timeout_ms = CacheService.GetOption <OptionValueInteger>("call_connect_timeout_ms");

                if (_controller != null)
                {
                    _controller.Dispose();
                    _controller = null;
                }

                _controller = new VoIPControllerWrapper();
                _controller.SetConfig(call_packet_timeout_ms.Value / 1000.0, call_connect_timeout_ms.Value / 1000.0, base.Settings.UseLessData, true, true, true, logFile, statsDumpFile);

                _controller.CallStateChanged += (s, args) =>
                {
                    BeginOnUIThread(() =>
                    {
                        if (args == libtgvoip.CallState.WaitInit || args == libtgvoip.CallState.WaitInitAck)
                        {
                            _mediaPlayer.Source           = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/Audio/voip_connecting.mp3"));
                            _mediaPlayer.IsLoopingEnabled = false;
                            _mediaPlayer.Play();
                        }
                        else if (args == libtgvoip.CallState.Established)
                        {
                            _mediaPlayer.Source = null;
                        }
                    });
                };

                BeginOnUIThread(() =>
                {
                    Show(update.Call, _controller);
                });

                var p2p       = base.Settings.PeerToPeerMode == 0 || (base.Settings.PeerToPeerMode == 1 && user.OutgoingLink is LinkStateIsContact);
                var endpoints = new Endpoint[ready.Connections.Count];

                for (int i = 0; i < endpoints.Length; i++)
                {
                    endpoints[i] = new Endpoint {
                        id = ready.Connections[i].Id, ipv4 = ready.Connections[i].Ip, ipv6 = ready.Connections[i].Ipv6, peerTag = ready.Connections[i].PeerTag.ToArray(), port = (ushort)ready.Connections[i].Port
                    };
                }

                _controller.SetEncryptionKey(ready.EncryptionKey.ToArray(), update.Call.IsOutgoing);
                _controller.SetPublicEndpoints(endpoints, ready.Protocol.UdpP2p && p2p, 74);
                _controller.Start();
                _controller.Connect();
            }
            else if (update.Call.State is CallStateDiscarded discarded)
            {
                if (discarded.NeedDebugInformation)
                {
                    ProtoService.Send(new SendCallDebugInformation(update.Call.Id, _controller.GetDebugLog()));
                }

                if (discarded.NeedRating)
                {
                    BeginOnUIThread(async() =>
                    {
                        var dialog  = new PhoneCallRatingView();
                        var confirm = await dialog.ShowQueuedAsync();
                        if (confirm == ContentDialogResult.Primary)
                        {
                            ProtoService.Send(new SendCallRating(update.Call.Id, dialog.Rating + 1, dialog.Rating >= 0 && dialog.Rating <= 3 ? dialog.Comment : null));
                        }
                    });
                }

                _controller?.Dispose();
                _controller = null;
                _call       = null;
            }

            BeginOnUIThread(() =>
            {
                switch (update.Call.State)
                {
                case CallStateDiscarded discarded:
                    if (update.Call.IsOutgoing && discarded.Reason is CallDiscardReasonDeclined)
                    {
                        _mediaPlayer.Source           = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/Audio/voip_busy.mp3"));
                        _mediaPlayer.IsLoopingEnabled = true;
                        _mediaPlayer.Play();

                        Show(update.Call, null);
                    }
                    else
                    {
                        _mediaPlayer.Source = null;

                        Hide();
                    }
                    break;

                case CallStateError error:
                    Hide();
                    break;

                default:
                    Show(update.Call, null);
                    break;
                }
            });
        }
예제 #2
0
        private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            var deferral = args.GetDeferral();
            var message  = args.Request.Message;

            try
            {
                if (message.ContainsKey("caption") && message.ContainsKey("request"))
                {
                    var caption = message["caption"] as string;
                    var buffer  = message["request"] as string;
                    var req     = TLSerializationService.Current.Deserialize(buffer);

                    if (caption.Equals("voip.getUser") && req is TLPeerUser userPeer)
                    {
                        var user = InMemoryCacheService.Current.GetUser(userPeer.UserId);
                        if (user != null)
                        {
                            await args.Request.SendResponseAsync(new ValueSet { { "result", TLSerializationService.Current.Serialize(user) } });
                        }
                        else
                        {
                            await args.Request.SendResponseAsync(new ValueSet { { "error", TLSerializationService.Current.Serialize(new TLRPCError {
                                        ErrorMessage = "USER_NOT_FOUND", ErrorCode = 404
                                    }) } });
                        }
                    }
                    else if (caption.Equals("voip.getConfig"))
                    {
                        var config = InMemoryCacheService.Current.GetConfig();
                        await args.Request.SendResponseAsync(new ValueSet { { "result", TLSerializationService.Current.Serialize(config) } });
                    }
                    else if (caption.Equals("voip.callInfo") && req is byte[] data)
                    {
                        using (var from = new TLBinaryReader(data))
                        {
                            var tupleBase = new TLTuple <int, TLPhoneCallBase, TLUserBase, string>(from);
                            var tuple     = new TLTuple <TLPhoneCallState, TLPhoneCallBase, TLUserBase, string>((TLPhoneCallState)tupleBase.Item1, tupleBase.Item2, tupleBase.Item3, tupleBase.Item4);

                            if (tuple.Item2 is TLPhoneCallDiscarded)
                            {
                                if (_phoneView != null)
                                {
                                    var newView = _phoneView;
                                    _phoneViewExists = false;
                                    _phoneView       = null;

                                    await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                                    {
                                        newView.SetCall(tuple);
                                        newView.Dispose();
                                        Window.Current.Close();
                                    });
                                }

                                return;
                            }

                            if (_phoneViewExists == false)
                            {
                                VoIPCallTask.Log("Creating VoIP UI", "Creating VoIP UI");

                                _phoneViewExists = true;

                                PhoneCallPage       newPlayer = null;
                                CoreApplicationView newView   = CoreApplication.CreateNewView();
                                var newViewId = 0;
                                await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                                {
                                    newPlayer = new PhoneCallPage();
                                    Window.Current.Content = newPlayer;
                                    Window.Current.Activate();
                                    newViewId = ApplicationView.GetForCurrentView().Id;

                                    newPlayer.SetCall(tuple);
                                    _phoneView = newPlayer;
                                });

                                await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() =>
                                {
                                    if (ApiInformation.IsMethodPresent("Windows.UI.ViewManagement.ApplicationView", "IsViewModeSupported") && ApplicationView.GetForCurrentView().IsViewModeSupported(ApplicationViewMode.CompactOverlay))
                                    {
                                        var preferences        = ViewModePreferences.CreateDefault(ApplicationViewMode.CompactOverlay);
                                        preferences.CustomSize = new Size(340, 200);

                                        var viewShown = await ApplicationViewSwitcher.TryShowAsViewModeAsync(newViewId, ApplicationViewMode.CompactOverlay, preferences);
                                    }
                                    else
                                    {
                                        //await ApplicationViewSwitcher.SwitchAsync(newViewId);
                                        await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
                                    }
                                });
                            }
                            else if (_phoneView != null)
                            {
                                VoIPCallTask.Log("VoIP UI already exists", "VoIP UI already exists");

                                await _phoneView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                                {
                                    _phoneView.SetCall(tuple);
                                });
                            }
                        }
                    }
                    else if (caption.Equals("voip.signalBars") && req is byte[] data2)
                    {
                        using (var from = new TLBinaryReader(data2))
                        {
                            var tuple = new TLTuple <int>(from);

                            if (_phoneView != null)
                            {
                                await _phoneView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                                {
                                    _phoneView.SetSignalBars(tuple.Item1);
                                });
                            }
                        }
                    }
                    else if (caption.Equals("voip.setCallRating") && req is TLInputPhoneCall peer)
                    {
                        Execute.BeginOnUIThread(async() =>
                        {
                            var dialog  = new PhoneCallRatingView();
                            var confirm = await dialog.ShowQueuedAsync();
                            if (confirm == ContentDialogResult.Primary)
                            {
                                await MTProtoService.Current.SetCallRatingAsync(peer, dialog.Rating, dialog.Rating >= 0 && dialog.Rating <= 3 ? dialog.Comment : null);
                            }
                        });
                    }
                    else
                    {
                        var response = await MTProtoService.Current.SendRequestAsync <object>(caption, req as TLObject);

                        if (response.IsSucceeded)
                        {
                            await args.Request.SendResponseAsync(new ValueSet { { "result", TLSerializationService.Current.Serialize(response.Result) } });
                        }
                        else
                        {
                            await args.Request.SendResponseAsync(new ValueSet { { "error", TLSerializationService.Current.Serialize(response.Error) } });
                        }
                    }
                }
            }
            finally
            {
                deferral.Complete();
            }
        }