// -----------------------------------------------------------------------
//
// TODO: Update copyright text.
//
// -----------------------------------------------------------------------
using Pithos.Network;
using log4net;
namespace Pithos.Client.WPF
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading.Tasks;
using System.Diagnostics.Contracts;
using System.Diagnostics;
using System.Net.Sockets;
///
/// TODO: Update summary.
///
///
/// Retrieves an account name and token from PITHOS
///
public static class PithosAccount
{
private static readonly ILog Log = LogManager.GetLogger(typeof(PithosAccount));
///
/// Asynchronously retrieves PITHOS credentials
///
/// URL to retrieve the account info from PITHOS. Must end with =
/// The credentials wrapped in a Task
public static Task RetrieveCredentialsAsync(string pithosSite)
{
Contract.Requires(Uri.IsWellFormedUriString(pithosSite, UriKind.Absolute));
if (!Uri.IsWellFormedUriString(pithosSite, UriKind.Absolute))
throw new ArgumentException("The pithosSite parameter must be a valid absolute URL", "pithosSite");
int port = GetFreePort();
var listenerUrl = String.Format("http://127.0.0.1:{0}/", port);
HttpListener listener = new HttpListener();
listener.Prefixes.Add(listenerUrl);
Log.InfoFormat("[RETRIEVE] Listening at {0}", listenerUrl);
listener.Start();
var startListening = Task.Factory.FromAsync(listener.BeginGetContext, listener.EndGetContext, null)
.WithTimeout(TimeSpan.FromMinutes(5));
var receiveCredentials=startListening.ContinueWith(tc =>
{
try
{
if (tc.IsFaulted)
{
Log.Error("[RETRIEVE][ERROR] Receive connection {0}", tc.Exception);
throw tc.Exception;
}
else
{
var context = tc.Result;
var request = context.Request;
Log.InfoFormat("[RETRIEVE] Got Connection {0}", request.RawUrl);
var query = request.QueryString;
var userName = query["user"];
var token = query["token"];
Log.InfoFormat("[RETRIEVE] Credentials retrieved user:{0} token:{1}", userName, token);
Respond(context);
return new NetworkCredential(userName, token);
}
}
finally
{
listener.Close();
}
});
var uriBuilder=new UriBuilder(pithosSite);
uriBuilder.Path="login";
uriBuilder.Query="next=" + listenerUrl;
var retrieveUri = uriBuilder.Uri;
Log.InfoFormat("[RETRIEVE] Open Browser at {0}", retrieveUri);
Process.Start(retrieveUri.ToString());
return receiveCredentials;
}
private static void Respond(HttpListenerContext context)
{
var response = context.Response;
var outBuffer = Encoding.UTF8.GetBytes("AuthenticatedGot It
");
response.ContentLength64 = outBuffer.Length;
using (var stream = response.OutputStream)
{
stream.Write(outBuffer, 0, outBuffer.Length);
}
Log.InfoFormat("[RETRIEVE] Responded");
}
///
/// Locates a free local port
///
/// A free port
/// The method starts and stops a TcpListener on port 0 to locate a free port.
public static int GetFreePort()
{
//The TcpListener will locate a free port
var listener = new TcpListener(IPAddress.Any, 0);
listener.Start();
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
listener.Stop();
return port;
}
}
}