add validateticket call

feature-npv2
NTAuthority 2014-05-30 23:57:39 +02:00
parent 612fd05702
commit ac7e1b1a78
1 changed files with 276 additions and 247 deletions

View File

@ -1,147 +1,147 @@
using System; using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using log4net; using log4net;
using NPSharp.RPC; using NPSharp.RPC;
using NPSharp.RPC.Messages.Client; using NPSharp.RPC.Messages.Client;
using NPSharp.RPC.Messages.Server; using NPSharp.RPC.Messages.Server;
namespace NPSharp.NP namespace NPSharp.NP
{ {
/// <summary> /// <summary>
/// Represents a high-level network platform client. /// Represents a high-level network platform client.
/// </summary> /// </summary>
public class NPClient public class NPClient
{ {
private readonly string _host; private readonly string _host;
private readonly ILog _log; private readonly ILog _log;
private readonly ushort _port; private readonly ushort _port;
private CancellationToken _cancellationToken; private CancellationToken _cancellationToken;
private CancellationTokenSource _cancellationTokenSource; private CancellationTokenSource _cancellationTokenSource;
private RPCClientStream _rpc; private RPCClientStream _rpc;
/// <summary> /// <summary>
/// Initializes the NP client with a specified host and port. /// Initializes the NP client with a specified host and port.
/// </summary>
/// <param name="host">The host to connect to.</param>
/// <param name="port">The port to use. Default: 3025.</param>
public NPClient(string host, ushort port = 3025)
{
_host = host;
_port = port;
_log = LogManager.GetLogger("NPClient");
}
/// <summary>
/// The internal RPC client.
/// </summary> /// </summary>
public RPCClientStream RPCClient { get { return _rpc; } } /// <param name="host">The host to connect to.</param>
/// <param name="port">The port to use. Default: 3025.</param>
/// <summary> public NPClient(string host, ushort port = 3025)
/// The assigned NP user ID. Will be set on successful authentication. {
/// </summary> _host = host;
public ulong LoginId { get; private set; } _port = port;
_log = LogManager.GetLogger("NPClient");
/// <summary> }
/// The assigned session token for this client. Will be set on successful authentication.
/// </summary> /// <summary>
public string SessionToken { get; private set; } /// The internal RPC client.
/// </summary>
// TODO: Handle connection failures via exception public RPCClientStream RPCClient { get { return _rpc; } }
/// <summary>
/// Connects the client to the NP server. /// <summary>
/// </summary> /// The assigned NP user ID. Will be set on successful authentication.
/// <returns>True if the connection succeeded, otherwise false.</returns> /// </summary>
public bool Connect() public ulong LoginId { get; private set; }
{
_log.Debug("Connect() start"); /// <summary>
/// The assigned session token for this client. Will be set on successful authentication.
_cancellationTokenSource = new CancellationTokenSource(); /// </summary>
_cancellationToken = _cancellationTokenSource.Token; public string SessionToken { get; private set; }
try // TODO: Handle connection failures via exception
{ /// <summary>
_rpc = RPCClientStream.Open(_host, _port); /// Connects the client to the NP server.
} /// </summary>
catch (Exception err) /// <returns>True if the connection succeeded, otherwise false.</returns>
{ public bool Connect()
#if DEBUG {
_log.ErrorFormat(@"Could not initialize RPC: {0}", err); _log.Debug("Connect() start");
#else
_log.ErrorFormat(@"Could not initialize RPC: {0}", err.Message); _cancellationTokenSource = new CancellationTokenSource();
#endif _cancellationToken = _cancellationTokenSource.Token;
return false;
} try
{
Task.Factory.StartNew(() => _rpc = RPCClientStream.Open(_host, _port);
{ }
_log.Debug("Now receiving RPC messages"); catch (Exception err)
try {
{ #if DEBUG
while (true) _log.ErrorFormat(@"Could not initialize RPC: {0}", err);
{ #else
if (_rpc.Read() == null) _log.ErrorFormat(@"Could not initialize RPC: {0}", err.Message);
break; #endif
} return false;
} }
catch (ProtocolViolationException error)
{ Task.Factory.StartNew(() =>
_log.ErrorFormat("Protocol violation: {0}. Disconnect imminent.", error.Message); {
Disconnect(); _log.Debug("Now receiving RPC messages");
} try
{
_log.Debug("Now not receiving RPC messages anymore"); while (true)
}, _cancellationToken); {
if (_rpc.Read() == null)
_log.Debug("Connect() done"); break;
return true; }
} }
catch (ProtocolViolationException error)
/// <summary> {
/// Disconnects the client from the NP server. _log.ErrorFormat("Protocol violation: {0}. Disconnect imminent.", error.Message);
/// </summary> Disconnect();
public void Disconnect() }
{
_log.Debug("Disconnect() start"); _log.Debug("Now not receiving RPC messages anymore");
}, _cancellationToken);
_cancellationTokenSource.Cancel(true);
// TODO: Find a cleaner way to cancel _processingTask (focus: _rpc.Read) _log.Debug("Connect() done");
//_procTask.Wait(_cancellationToken); return true;
_rpc.Close(); }
LoginId = 0; /// <summary>
/// Disconnects the client from the NP server.
_log.Debug("Disconnect() done"); /// </summary>
} public void Disconnect()
{
// TODO: Try to use an exception for failed action instead _log.Debug("Disconnect() start");
/// <summary>
/// Authenticates this connection via a token. This token has to be requested via an external interface like _cancellationTokenSource.Cancel(true);
/// remauth.php. // TODO: Find a cleaner way to cancel _processingTask (focus: _rpc.Read)
/// </summary> //_procTask.Wait(_cancellationToken);
/// <param name="token">The token to use for authentication</param> _rpc.Close();
/// <returns>True if the login succeeded, otherwise false.</returns>
public async Task<bool> AuthenticateWithToken(string token) LoginId = 0;
{
var tcs = new TaskCompletionSource<bool>(); _log.Debug("Disconnect() done");
}
_rpc.AttachHandlerForNextMessage(packet =>
{ // TODO: Try to use an exception for failed action instead
var result = packet as AuthenticateResultMessage; /// <summary>
if (result == null) /// Authenticates this connection via a token. This token has to be requested via an external interface like
return; /// remauth.php.
/// </summary>
if (result.Result != 0) /// <param name="token">The token to use for authentication</param>
tcs.SetResult(false); /// <returns>True if the login succeeded, otherwise false.</returns>
LoginId = result.NPID; public async Task<bool> AuthenticateWithToken(string token)
SessionToken = result.SessionToken; {
tcs.SetResult(true); var tcs = new TaskCompletionSource<bool>();
});
_rpc.Send(new AuthenticateWithTokenMessage {Token = token}); _rpc.AttachHandlerForNextMessage(packet =>
{
return await tcs.Task; var result = packet as AuthenticateResultMessage;
if (result == null)
return;
if (result.Result != 0)
tcs.SetResult(false);
LoginId = result.NPID;
SessionToken = result.SessionToken;
tcs.SetResult(true);
});
_rpc.Send(new AuthenticateWithTokenMessage {Token = token});
return await tcs.Task;
} }
/// <summary> /// <summary>
@ -161,7 +161,12 @@ namespace NPSharp.NP
return; return;
if (result.Result != 0) if (result.Result != 0)
{
tcs.SetResult(false); tcs.SetResult(false);
return;
}
LoginId = result.NPID; LoginId = result.NPID;
SessionToken = result.SessionToken; SessionToken = result.SessionToken;
tcs.SetResult(true); tcs.SetResult(true);
@ -169,108 +174,132 @@ namespace NPSharp.NP
_rpc.Send(new AuthenticateWithKeyMessage { LicenseKey = key }); _rpc.Send(new AuthenticateWithKeyMessage { LicenseKey = key });
return await tcs.Task; return await tcs.Task;
} }
// TODO: Try to use an exception for failed action instead public async Task<bool> ValidateTicket(uint clientIP, ulong npID, byte[] ticket)
/// <summary> {
/// Uploads a user file. var tcs = new TaskCompletionSource<bool>();
/// </summary>
/// <param name="filename">The file name to save the contents to on the server</param> _rpc.AttachHandlerForNextMessage(packet =>
/// <param name="contents">The raw byte contents</param> {
/// <returns>True if the upload succeeded, otherwise false.</returns> var result = packet as AuthenticateValidateTicketResultMessage;
public async Task<bool> UploadUserFile(string filename, byte[] contents) if (result == null)
{ return;
var tcs = new TaskCompletionSource<bool>();
if (result.Result != 0)
_rpc.AttachHandlerForNextMessage(packet => {
{ tcs.SetResult(false);
var result = (StorageWriteUserFileResultMessage) packet; }
if (result.Result != 0) else
tcs.SetResult(false); {
tcs.SetResult(true); tcs.SetResult(true);
}); }
_rpc.Send(new StorageWriteUserFileMessage {FileData = contents, FileName = filename, NPID = LoginId}); });
_rpc.Send(new AuthenticateValidateTicketMessage { ClientIP = clientIP, Ticket = ticket, NPID = npID });
return await tcs.Task;
} return await tcs.Task;
}
/// <summary>
/// Downloads a user file and returns its contents. // TODO: Try to use an exception for failed action instead
/// </summary> /// <summary>
/// <param name="filename">The file to download</param> /// Uploads a user file.
/// <returns>File contents as byte array</returns> /// </summary>
public async Task<byte[]> GetUserFile(string filename) /// <param name="filename">The file name to save the contents to on the server</param>
{ /// <param name="contents">The raw byte contents</param>
var tcs = new TaskCompletionSource<byte[]>(); /// <returns>True if the upload succeeded, otherwise false.</returns>
public async Task<bool> UploadUserFile(string filename, byte[] contents)
_rpc.AttachHandlerForNextMessage(packet => {
{ var tcs = new TaskCompletionSource<bool>();
var result = (StorageUserFileMessage) packet;
if (result.Result != 0) _rpc.AttachHandlerForNextMessage(packet =>
{ {
tcs.SetException(new NpFileException(result.Result)); var result = (StorageWriteUserFileResultMessage) packet;
return; if (result.Result != 0)
} tcs.SetResult(false);
tcs.SetResult(result.FileData); tcs.SetResult(true);
}); });
_rpc.Send(new StorageGetUserFileMessage {FileName = filename, NPID = LoginId}); _rpc.Send(new StorageWriteUserFileMessage {FileData = contents, FileName = filename, NPID = LoginId});
return await tcs.Task; return await tcs.Task;
} }
/// <summary>
/// <summary> /// Downloads a user file and returns its contents.
/// Downloads a user file onto the harddisk. /// </summary>
/// </summary> /// <param name="filename">The file to download</param>
/// <param name="filename">The file to download</param> /// <returns>File contents as byte array</returns>
/// <param name="targetpath">Path where to save the file</param> public async Task<byte[]> GetUserFile(string filename)
public async void DownloadUserFileTo(string filename, string targetpath) {
{ var tcs = new TaskCompletionSource<byte[]>();
var contents = await GetUserFile(filename);
_rpc.AttachHandlerForNextMessage(packet =>
File.WriteAllBytes(targetpath, contents); {
} var result = (StorageUserFileMessage) packet;
if (result.Result != 0)
{
/// <summary> tcs.SetException(new NpFileException(result.Result));
/// Downloads a publisher file and returns its contents. return;
/// </summary> }
/// <param name="filename">The file to download</param> tcs.SetResult(result.FileData);
/// <returns>File contents as byte array</returns> });
public async Task<byte[]> GetPublisherFile(string filename) _rpc.Send(new StorageGetUserFileMessage {FileName = filename, NPID = LoginId});
{
var tcs = new TaskCompletionSource<byte[]>(); return await tcs.Task;
}
_rpc.AttachHandlerForNextMessage(packet =>
{
var result = (StoragePublisherFileMessage) packet; /// <summary>
if (result.Result != 0) /// Downloads a user file onto the harddisk.
{ /// </summary>
tcs.SetException(new NpFileException(result.Result)); /// <param name="filename">The file to download</param>
return; /// <param name="targetpath">Path where to save the file</param>
} public async void DownloadUserFileTo(string filename, string targetpath)
tcs.SetResult(result.FileData); {
}); var contents = await GetUserFile(filename);
_rpc.Send(new StorageGetPublisherFileMessage {FileName = filename});
File.WriteAllBytes(targetpath, contents);
return await tcs.Task; }
}
/// <summary> /// <summary>
/// Downloads a publisher file onto the harddisk. /// Downloads a publisher file and returns its contents.
/// </summary> /// </summary>
/// <param name="filename">The file to download</param> /// <param name="filename">The file to download</param>
/// <param name="targetpath">Path where to save the file</param> /// <returns>File contents as byte array</returns>
public async void DownloadPublisherFileTo(string filename, string targetpath) public async Task<byte[]> GetPublisherFile(string filename)
{ {
var contents = await GetPublisherFile(filename); var tcs = new TaskCompletionSource<byte[]>();
File.WriteAllBytes(targetpath, contents); _rpc.AttachHandlerForNextMessage(packet =>
} {
var result = (StoragePublisherFileMessage) packet;
public void SendRandomString(string data) if (result.Result != 0)
{ {
_rpc.Send(new StorageSendRandomStringMessage {RandomString = data}); tcs.SetException(new NpFileException(result.Result));
} return;
} }
tcs.SetResult(result.FileData);
});
_rpc.Send(new StorageGetPublisherFileMessage {FileName = filename});
return await tcs.Task;
}
/// <summary>
/// Downloads a publisher file onto the harddisk.
/// </summary>
/// <param name="filename">The file to download</param>
/// <param name="targetpath">Path where to save the file</param>
public async void DownloadPublisherFileTo(string filename, string targetpath)
{
var contents = await GetPublisherFile(filename);
File.WriteAllBytes(targetpath, contents);
}
public void SendRandomString(string data)
{
_rpc.Send(new StorageSendRandomStringMessage {RandomString = data});
}
}
} }