From d21e84476c0d8689fcaa872cd5c7d4c5346678c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen?= Date: Tue, 19 Jul 2016 21:15:22 +0200 Subject: [PATCH] AuthenticationFactory --- SpotifyAPI/SpotifyAPI.csproj | 1 + SpotifyAPI/Web/Auth/AuthenticationFactory.cs | 85 ++++++++++++++++++++ SpotifyAPI/Web/SimpleHttpServer.cs | 16 +++- 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 SpotifyAPI/Web/Auth/AuthenticationFactory.cs diff --git a/SpotifyAPI/SpotifyAPI.csproj b/SpotifyAPI/SpotifyAPI.csproj index 3f025e4b..e414942c 100644 --- a/SpotifyAPI/SpotifyAPI.csproj +++ b/SpotifyAPI/SpotifyAPI.csproj @@ -58,6 +58,7 @@ + diff --git a/SpotifyAPI/Web/Auth/AuthenticationFactory.cs b/SpotifyAPI/Web/Auth/AuthenticationFactory.cs new file mode 100644 index 00000000..2653ef11 --- /dev/null +++ b/SpotifyAPI/Web/Auth/AuthenticationFactory.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using SpotifyAPI.Web.Enums; +using SpotifyAPI.Web.Models; + +namespace SpotifyAPI.Web.Auth +{ + public class AuthenticationFactory + { + private readonly string m_RedirectUrl; + private readonly int m_ListeningPort; + private readonly string m_ClientId; + private readonly TimeSpan m_Timeout; + private Scope m_Scope; + + public AuthenticationFactory(string redirectUrl, int listeningPort, string clientId, Scope scope, TimeSpan timeout) + { + m_RedirectUrl = redirectUrl; + m_ListeningPort = listeningPort; + m_ClientId = clientId; + m_Scope = scope; + m_Timeout = timeout; + } + + public Task GetWebApi() + { + var authentication = new ImplicitGrantAuth + { + RedirectUri = $"{m_RedirectUrl}:{m_ListeningPort}", + ClientId = m_ClientId, + Scope = m_Scope, + State = "XSS" + }; + + AutoResetEvent authenticationWaitFlag = new AutoResetEvent(false); + SpotifyWebAPI spotifyWebApi = null; + authentication.OnResponseReceivedEvent += (token, state) => + { + spotifyWebApi = HandleSpotifyResponse(state, token); + authenticationWaitFlag.Set(); + }; + + authentication.StartHttpServer(m_ListeningPort); + + authentication.DoAuth(); + + authenticationWaitFlag.WaitOne(m_Timeout); + if (spotifyWebApi == null) + throw new TimeoutException($"No valid response received for the last {m_Timeout.TotalSeconds} seconds"); + + authentication.StopHttpServer(); + + return Task.FromResult(spotifyWebApi); + } + + private static SpotifyWebAPI HandleSpotifyResponse(string state, Token token) + { + if (state != "XSS") + throw new SpotifyWebApiException($"Wrong state '{state}' received."); + + if (token.Error != null) + throw new SpotifyWebApiException($"Error: {token.Error}"); + + var spotifyWebApi = new SpotifyWebAPI + { + UseAuth = true, + AccessToken = token.AccessToken, + TokenType = token.TokenType + }; + + return spotifyWebApi; + } + } + + [Serializable] + public class SpotifyWebApiException : Exception + { + public SpotifyWebApiException(string message) : base(message) + { } + } +} diff --git a/SpotifyAPI/Web/SimpleHttpServer.cs b/SpotifyAPI/Web/SimpleHttpServer.cs index 1f417b6c..369d7629 100644 --- a/SpotifyAPI/Web/SimpleHttpServer.cs +++ b/SpotifyAPI/Web/SimpleHttpServer.cs @@ -223,8 +223,20 @@ namespace SpotifyAPI.Web { while (IsActive) { - TcpClient s = _listener.AcceptTcpClient(); - processor.Process(s); + _listener.BeginAcceptTcpClient(ar => + { + try + { + TcpListener listener = (TcpListener)ar.AsyncState; + var tcpCLient = listener.EndAcceptTcpClient(ar); + processor.Process(tcpCLient); + + } + catch (ObjectDisposedException) + { + // Ignore + } + }, _listener); } } }