Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / PithosAccount.cs @ 437abfca

History | View | Annotate | Download (5.3 kB)

1
// -----------------------------------------------------------------------
2
// <copyright file="PithosAccount.cs" company="Microsoft">
3
// TODO: Update copyright text.
4
// </copyright>
5
// -----------------------------------------------------------------------
6

    
7
using Pithos.Network;
8
using log4net;
9

    
10
namespace Pithos.Client.WPF
11
{
12
    using System;
13
    using System.Collections.Generic;
14
    using System.Linq;
15
    using System.Text;
16
    using System.Net;
17
    using System.Threading.Tasks;
18
    using System.Diagnostics.Contracts;
19
    using System.Diagnostics;
20
    using System.Net.Sockets;
21

    
22
    /// <summary>
23
    /// TODO: Update summary.
24
    /// </summary>
25
    /// <summary>
26
    /// Retrieves an account name and token from PITHOS
27
    /// </summary>
28
    public static class PithosAccount
29
    {
30
        private static readonly ILog Log = LogManager.GetLogger(typeof(PithosAccount));
31

    
32
        /// <summary>
33
        /// Asynchronously retrieves PITHOS credentials
34
        /// </summary>
35
        /// <param name="pithosSite">URL to retrieve the account info from PITHOS. Must end with =</param>
36
        /// <returns>The credentials wrapped in a Task</returns>
37
        public static Task<NetworkCredential> RetrieveCredentialsAsync(string pithosSite)
38
        {
39
            Contract.Requires(Uri.IsWellFormedUriString(pithosSite, UriKind.Absolute));
40

    
41
            if (!Uri.IsWellFormedUriString(pithosSite, UriKind.Absolute))
42
                throw new ArgumentException("The pithosSite parameter must be a valid absolute URL", "pithosSite");
43
            
44
            int port = GetFreePort();
45

    
46

    
47
            var listenerUrl = String.Format("http://127.0.0.1:{0}/", port);
48

    
49
            HttpListener listener = new HttpListener();
50
            listener.Prefixes.Add(listenerUrl);
51

    
52
            Log.InfoFormat("[RETRIEVE] Listening at {0}", listenerUrl);
53

    
54
            listener.Start();
55
            
56
            var startListening = Task.Factory.FromAsync<HttpListenerContext>(listener.BeginGetContext, listener.EndGetContext, null)
57
                .WithTimeout(TimeSpan.FromMinutes(5));
58

    
59
            var receiveCredentials=startListening.ContinueWith(tc =>
60
                {
61
                    try
62
                    {
63
                        if (tc.IsFaulted)
64
                        {
65
                            Log.Error("[RETRIEVE][ERROR] Receive connection {0}", tc.Exception);
66
                            throw tc.Exception;
67
                        }
68
                        else
69
                        {
70

    
71
                            var context = tc.Result;
72
                            var request = context.Request;
73
                            Log.InfoFormat("[RETRIEVE] Got Connection {0}", request.RawUrl);
74

    
75
                            var query = request.QueryString;
76
                            var userName = query["user"];
77
                            var token = query["token"];
78
                            if (String.IsNullOrWhiteSpace(userName) || String.IsNullOrWhiteSpace(token))
79
                            {
80
                                Respond(context, "Failure", "The server did not return a username or token");
81
                                Log.ErrorFormat("[RETRIEVE] No credentials returned by server");
82
                                throw new Exception("The server did not return a username or token");
83
                            }
84
                            else
85
                            {
86

    
87
                                Log.InfoFormat("[RETRIEVE] Credentials retrieved user:{0} token:{1}", userName, token);
88
                                Respond(context, "Authenticated", "Got It");
89

    
90
                                return new NetworkCredential(userName, token);
91
                            }
92
                        }
93

    
94
                    }
95
                    finally
96
                    {
97
                        listener.Close();
98
                    }
99
                });
100

    
101
            var uriBuilder=new UriBuilder(pithosSite);
102
            uriBuilder.Path="login";            
103
            uriBuilder.Query="next=" + listenerUrl;
104

    
105
            var retrieveUri = uriBuilder.Uri;
106
            Log.InfoFormat("[RETRIEVE] Open Browser at {0}", retrieveUri);
107
            Process.Start(retrieveUri.ToString());
108

    
109
            return receiveCredentials;
110
        }
111

    
112
        private static void Respond(HttpListenerContext context,string title,string message)
113
        {
114
            var response = context.Response;
115
            var html = String.Format("<html><head><title>{0}</title></head><body><h1>{1}</h1></body></html>", title, message);
116
            var outBuffer = Encoding.UTF8.GetBytes(html);
117
            response.ContentLength64 = outBuffer.Length;
118
            using (var stream = response.OutputStream)
119
            {
120
                stream.Write(outBuffer, 0, outBuffer.Length);
121
            }
122

    
123
            Log.InfoFormat("[RETRIEVE] Responded");
124
        }
125
        /// <summary>
126
        /// Locates a free local port 
127
        /// </summary>
128
        /// <returns>A free port</returns>
129
        /// <remarks>The method starts and stops a TcpListener on port 0 to locate a free port.</remarks>
130
        public static int GetFreePort()
131
        {
132
            //The TcpListener will locate a free port             
133
            var listener = new TcpListener(IPAddress.Any, 0);
134
            listener.Start();
135
            var port = ((IPEndPoint)listener.LocalEndpoint).Port;
136
            listener.Stop();
137
            return port;
138
        }
139
    }
140
}