You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
linphone-tutorials/uwp/cs/01_AccountLogin/MainPage.xaml.cs

270 lines
9.6 KiB

/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of Linphone TutorialCS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Linphone;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using Windows.Storage;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
namespace _01_AccountLogin
{
/// <summary>
/// A really simple page for a first Login with LinphoneSDK x UWP
/// </summary>
public sealed partial class MainPage : Page
{
private Core StoredCore { get; set; }
private LoggingService LoggingService { get; set; }
private Timer Timer;
public MainPage()
{
InitializeComponent();
// Core is the main object of the SDK. You can't do much without it
// If you're not familiar with Linphone Core creation, see the 00_HelloWorld project.
LoggingService = LoggingService.Instance;
LoggingService.LogLevel = LogLevel.Debug;
LoggingService.Listener.OnLogMessageWritten = OnLog;
Factory factory = Factory.Instance;
string assetsPath = Path.Combine(Windows.ApplicationModel.Package.Current.InstalledLocation.Path, "Assets");
factory.TopResourcesDir = assetsPath;
factory.DataResourcesDir = assetsPath;
factory.SoundResourcesDir = Path.Combine(assetsPath, "sounds", "linphone");
factory.RingResourcesDir = Path.Combine(factory.SoundResourcesDir, "rings");
factory.ImageResourcesDir = Path.Combine(assetsPath, "images");
factory.MspluginsDir = ".";
Core core = factory.CreateCore("", "", IntPtr.Zero);
StoredCore = core;
// We need to indicate to the core where to find the root and user certificates, for future TLS exchange.
StoredCore.RootCa = Path.Combine(Windows.ApplicationModel.Package.Current.InstalledLocation.Path, "share", "Linphone", "rootca.pem");
StoredCore.UserCertificatesPath = ApplicationData.Current.LocalFolder.Path;
// In this tutorial we are going to log in and our registration state will change.
// Here we show you how to register a delegate method called every time the
// OnAccountRegistrationStateChanged callback is triggered.
StoredCore.Listener.OnAccountRegistrationStateChanged += OnAccountRegistrationStateChanged;
// Start the core after setup, and before everything else.
StoredCore.Start();
StoredCore.AutoIterateEnabled = true;
// The method Iterate must be permanently called on our core.
// The Iterate method runs all the waiting backgrounds tasks and poll networks notifications.
// Here how to setup a function called every 20ms, 20ms after the Timer object instantiation.
// See OnTimedEvent for more informations.
Timer = new Timer(OnTimedEvent, null, 20, 20);
// Setup GUI
Identity.Text = "sip:";
Password.PlaceholderText = "myPasswd";
LogoutGuiChanges();
// Now use the GUI to log in, and see LogInClick to see how to handle login.
}
/// <summary>
/// Here we scheduled a callback to the Iterate method on the UI thread. While the
/// Linphone API calls are not thread safe, we ensure all our callbacks are done on the UI thread.
/// Doing this, we allow callbacks to manipulate UI without dispatcher.
/// </summary>
private async void OnTimedEvent(object state)
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
StoredCore.Iterate();
});
}
/// <summary>
/// Called when you click on the "Login" button.
/// </summary>
private void LogInClick(object sender, RoutedEventArgs e)
{
if (LogIn.IsEnabled)
{
LogIn.IsEnabled = false;
// To configure a SIP account, we need an Account object and an AuthInfo object
// The first one is how to connect to the proxy server, the second one stores the credentials
// Here we are creating an AuthInfo object from the identity Address and password provided by the user.
Address address = Factory.Instance.CreateAddress(Identity.Text);
// The AuthInfo can be created from the Factory as it's only a data class
// userID is set to null as it's the same as the username in our case
// ha1 is set to null as we are using the clear text password. Upon first register, the hash will be computed automatically.
// The realm will be determined automatically from the first register, as well as the algorithm
AuthInfo authInfo = Factory.Instance.CreateAuthInfo(address.Username, "", Password.Password, "", "", address.Domain);
// And we add it to the Core
StoredCore.AddAuthInfo(authInfo);
// Then we create an AccountParams object.
// It contains the account informations needed by the core
AccountParams accountParams = StoredCore.CreateAccountParams();
// A SIP account is identified by an identity address that we can construct from the username and domain
accountParams.IdentityAddress = address;
// We also need to configure where the proxy server is located
Address serverAddr = Factory.Instance.CreateAddress("sip:" + address.Domain);
// We use the Address object to easily set the transport protocol
if (TlsRadio.IsChecked == true) {
serverAddr.Transport = TransportType.Tls;
}
else if (TcpRadio.IsChecked == true)
{
serverAddr.Transport = TransportType.Tcp;
}
else
{
serverAddr.Transport = TransportType.Udp;
}
accountParams.ServerAddress = serverAddr;
// If RegisterEnabled is set to true, when this account will be added to the core it will
// automatically try to connect.
accountParams.RegisterEnabled = true;
// We can now create an Account object from the AccountParams ...
Account account = StoredCore.CreateAccount(accountParams);
// ... and add it to the core, launching the connection process.
StoredCore.AddAccount(account);
// Also set the newly added account as default
StoredCore.DefaultAccount = account;
}
}
/// <summary>
/// Called when a key is pressed and released on the login page.
/// If you pressed "Enter", simulate a login click.
/// </summary>
private void GridKeyUp(object sender, KeyRoutedEventArgs e)
{
if (VirtualKey.Enter.Equals(e.Key))
{
LogInClick(null, null);
}
}
/// <summary>
/// Called when you click on the "Logout" button.
/// </summary>
private void LogOutClick(object sender, RoutedEventArgs e)
{
if (LogOut.IsEnabled)
{
LogOut.IsEnabled = false;
// Setting RegisterEnabled to false on a connected Account object will
// launch the logout action.
Account account = StoredCore.DefaultAccount;
if (account != null)
{
// BUT BE CAREFUL : the Params attribute of an account is read-only
// You MUST Clone it :
AccountParams accountParams = account.Params.Clone();
// Then you can modify the clone :
accountParams.RegisterEnabled = false;
// And finally setting the new Params value triggers the changes, here the logout.
account.Params = accountParams;
}
}
}
/// <summary>
/// This method is called every time the RegistrationState is updated by background core's actions.
/// In this example we use this to update the GUI.
/// </summary>
private void OnAccountRegistrationStateChanged(Core core, Account account, RegistrationState state, string message)
{
RegistrationText.Text = "Your registration state is : " + state.ToString();
switch (state)
{
// If the Account was logged out, we clear the Core.
case RegistrationState.Cleared:
case RegistrationState.None:
StoredCore.ClearAllAuthInfo();
StoredCore.ClearAccounts();
LogoutGuiChanges();
break;
case RegistrationState.Ok:
LoginGuiChanges();
break;
case RegistrationState.Progress:
LoginInProgressGuiChanges();
break;
case RegistrationState.Failed:
LoginFailedChanges();
break;
default:
break;
}
}
private void LogoutGuiChanges()
{
LogIn.IsEnabled = true;
LogOut.IsEnabled = false;
LoginText.Text = "You are logged out";
}
private void LoginFailedChanges()
{
LogIn.IsEnabled = true;
LogOut.IsEnabled = false;
LoginText.Text = "Login failed, try again";
}
private void LoginGuiChanges()
{
LogIn.IsEnabled = false;
LogOut.IsEnabled = true;
LoginText.Text = "You are logged in, with identity " + StoredCore.Identity + ".";
}
private void LoginInProgressGuiChanges()
{
LogIn.IsEnabled = false;
LogOut.IsEnabled = false;
LoginText.Text = "Login in progress, with identity " + StoredCore.Identity + ".";
}
private void OnLog(LoggingService logService, string domain, LogLevel lev, string message)
{
StringBuilder builder = new StringBuilder();
_ = builder.Append("Linphone-[").Append(lev.ToString()).Append("](").Append(domain).Append(")").Append(message);
Debug.WriteLine(builder.ToString());
}
}
}