mirror of https://github.com/icedream/npsharp.git
Very slowly getting there.
parent
5ce198cbf6
commit
b13d462f0d
|
@ -0,0 +1,35 @@
|
||||||
|
using NPSharp.Steam;
|
||||||
|
|
||||||
|
namespace NPSharp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents details about the outcome of an authentication attempt.
|
||||||
|
/// </summary>
|
||||||
|
public class AuthenticationResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an authentication result instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="npid">
|
||||||
|
/// Set this to null if authentication should fail, otherwise use an instance of a steam ID which is
|
||||||
|
/// unique to the user.
|
||||||
|
/// </param>
|
||||||
|
public AuthenticationResult(CSteamID npid = null)
|
||||||
|
{
|
||||||
|
UserID = npid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if authentiation succeeded, otherwise false.
|
||||||
|
/// </summary>
|
||||||
|
public bool Result
|
||||||
|
{
|
||||||
|
get { return UserID != null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The assigned user ID by the authentication provider. Can be null for failed authentication attempts.
|
||||||
|
/// </summary>
|
||||||
|
public CSteamID UserID { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,11 +4,11 @@ namespace NPSharp
|
||||||
{
|
{
|
||||||
public class ClientEventArgs : EventArgs
|
public class ClientEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
internal ClientEventArgs(NPServer.NPServerClient client)
|
internal ClientEventArgs(NPServerClient client)
|
||||||
{
|
{
|
||||||
Client = client;
|
Client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NPServer.NPServerClient Client { get; private set; }
|
public NPServerClient Client { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace NPSharp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate for all general client-related events.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The instance of the NP server</param>
|
||||||
|
/// <param name="args">All related arguments to this event</param>
|
||||||
|
public delegate void ClientEventHandler(NPServer sender, ClientEventArgs args);
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
namespace NPSharp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a handler for all authentication-related requests.
|
||||||
|
/// </summary>
|
||||||
|
public interface IAuthenticationHandler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Authenticates a user based on username and password.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">The NP server client to authenticate</param>
|
||||||
|
/// <param name="username">The username to use for authentication</param>
|
||||||
|
/// <param name="password">The password to use for authentication</param>
|
||||||
|
/// <returns>An instance of <seealso cref="AuthenticationResult" /></returns>
|
||||||
|
AuthenticationResult AuthenticateUser(NPServerClient client, string username, string password);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Authenticates a user based on a session token.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">The NP server client to authenticate</param>
|
||||||
|
/// <param name="token">The session token to use for authentication</param>
|
||||||
|
/// <returns>An instance of <seealso cref="AuthenticationResult" /></returns>
|
||||||
|
AuthenticationResult AuthenticateUser(NPServerClient client, string token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Authenticates a dedicated server based on its license key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">The NP server client of the dedicated server to authenticate</param>
|
||||||
|
/// <param name="licenseKey">The license key to use for authentication</param>
|
||||||
|
/// <returns>An instance of <see cref="AuthenticationResult" /></returns>
|
||||||
|
AuthenticationResult AuthenticateServer(NPServerClient client, string licenseKey);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates a ticket.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">The NP server client of the user who is trying to get the ticket validated</param>
|
||||||
|
/// <param name="server">The server that the user wants to connect to using this ticket</param>
|
||||||
|
/// <returns>A <see cref="TicketValidationResult" /> determining if the ticket is valid</returns>
|
||||||
|
TicketValidationResult ValidateTicket(NPServerClient client, NPServerClient server);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
namespace NPSharp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a handler for all file-related requests.
|
||||||
|
/// </summary>
|
||||||
|
public interface IFileServingHandler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a file assigned to the user.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The file contents as byte array or null if the file could not be read, opened or generated</returns>
|
||||||
|
/// <param name="client">NP server client of the user</param>
|
||||||
|
/// <param name="file">The file name</param>
|
||||||
|
byte[] ReadUserFile(NPServerClient client, string file);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a publisher file.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The file contents as byte array or null if the file could not be read, opened or generated</returns>
|
||||||
|
/// <param name="client">NP server client of the user</param>
|
||||||
|
/// <param name="file">The file name</param>
|
||||||
|
byte[] ReadPublisherFile(NPServerClient client, string file);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a file and assigns it to the client user.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">NP server client of the user</param>
|
||||||
|
/// <param name="file">The file name</param>
|
||||||
|
/// <param name="data">The file contents as byte array</param>
|
||||||
|
void WriteUserFile(NPServerClient client, string file, byte[] data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NPSharp.RPC.Messages;
|
||||||
|
|
||||||
|
namespace NPSharp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a handler for all friends-related requests.
|
||||||
|
/// </summary>
|
||||||
|
public interface IFriendsHandler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches all friends of the connected user.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">The NP server client of the user</param>
|
||||||
|
/// <returns>All friend details found for the user</returns>
|
||||||
|
IEnumerable<FriendDetails> GetFriends(NPServerClient client);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using NPSharp.Steam;
|
||||||
|
|
||||||
|
namespace NPSharp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a handler for all user avatar-related requests.
|
||||||
|
/// </summary>
|
||||||
|
public interface IUserAvatarHandler
|
||||||
|
{
|
||||||
|
byte[] GetUserAvatar(CSteamID id);
|
||||||
|
|
||||||
|
byte[] GetDefaultAvatar();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Configuration;
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using log4net;
|
using log4net;
|
||||||
using NPSharp.RPC;
|
using NPSharp.RPC;
|
||||||
using NPSharp.RPC.Messages;
|
using NPSharp.RPC.Messages;
|
||||||
|
@ -12,34 +15,118 @@ namespace NPSharp
|
||||||
{
|
{
|
||||||
public class NPServer
|
public class NPServer
|
||||||
{
|
{
|
||||||
public delegate void ClientEventHandler(object sender, ClientEventArgs args);
|
|
||||||
|
|
||||||
public IFileServingHandler FileHandler { get; set; }
|
|
||||||
|
|
||||||
public IUserAvatarHandler UserAvatarHandler { get; set; }
|
|
||||||
|
|
||||||
public interface IUserAvatarHandler
|
|
||||||
{
|
|
||||||
byte[] GetUserAvatar(CSteamID id);
|
|
||||||
|
|
||||||
byte[] GetDefaultAvatar();
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly List<NPServerClient> _clients;
|
private readonly List<NPServerClient> _clients;
|
||||||
private readonly ILog _log;
|
private readonly ILog _log;
|
||||||
|
private readonly Socket _socket;
|
||||||
|
private readonly ushort _port;
|
||||||
|
|
||||||
public NPServer()
|
/// <summary>
|
||||||
|
/// Constructs a new NP server.
|
||||||
|
/// </summary>
|
||||||
|
public NPServer(ushort port = 3025)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetLogger("NPServer");
|
_log = LogManager.GetLogger("NPServer");
|
||||||
_clients = new List<NPServerClient>();
|
_clients = new List<NPServerClient>();
|
||||||
|
|
||||||
|
_socket = new Socket(SocketType.Stream, ProtocolType.IP);
|
||||||
|
_port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _handleClient(NPServerClient client)
|
/// <summary>
|
||||||
|
/// Starts up the NP server.
|
||||||
|
/// </summary>
|
||||||
|
public void Start()
|
||||||
{
|
{
|
||||||
|
if (_socket.IsBound)
|
||||||
|
throw new InvalidOperationException("This server is already running");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// ReSharper disable once ObjectCreationAsStatement
|
||||||
|
// TODO: fix this shit permission code
|
||||||
|
new SocketPermission(NetworkAccess.Accept, TransportType.Tcp, "", _port);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_log.Error("Socket permission request failed, can't start server.");
|
||||||
|
throw new SocketException(10013 /* Permission denied */);
|
||||||
|
}
|
||||||
|
|
||||||
|
_socket.Bind(new IPEndPoint(IPAddress.IPv6Any, _port));
|
||||||
|
_socket.Listen(4);
|
||||||
|
|
||||||
|
Task.Factory.StartNew(() =>
|
||||||
|
{
|
||||||
|
_log.Debug("Listener loop started");
|
||||||
|
var allDone = new ManualResetEvent(false);
|
||||||
|
while (_socket != null && _socket.IsBound)
|
||||||
|
{
|
||||||
|
allDone.Reset();
|
||||||
|
_socket.BeginAccept(ar =>
|
||||||
|
{
|
||||||
|
_log.Debug("Async accept client start");
|
||||||
|
allDone.Set();
|
||||||
|
|
||||||
|
var serverSocket = (Socket) ar.AsyncState;
|
||||||
|
var clientSocket = serverSocket.EndAccept(ar);
|
||||||
|
|
||||||
|
var npsc = new NPServerClient(this, new RPCServerStream(clientSocket));
|
||||||
|
|
||||||
|
_log.Debug("Async accept client end");
|
||||||
|
|
||||||
|
_handleClient(npsc);
|
||||||
|
}, _socket);
|
||||||
|
allDone.WaitOne();
|
||||||
|
}
|
||||||
|
_log.Debug("Listener loop shut down");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shuts down all connections and stops the NP server.
|
||||||
|
/// </summary>
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
_socket.Shutdown(SocketShutdown.Both);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The handler to use for file requests to this NP server.
|
||||||
|
/// </summary>
|
||||||
|
public IFileServingHandler FileHandler { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The handler to use for user avatar requests to this NP server.
|
||||||
|
/// </summary>
|
||||||
|
public IUserAvatarHandler UserAvatarHandler { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all currently connected clients
|
||||||
|
/// </summary>
|
||||||
|
public NPServerClient[] Clients
|
||||||
|
{
|
||||||
|
get { return _clients.ToArray(); } // Avoid race condition by IEnum changes
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The handler to use for authentication requests to this NP server.
|
||||||
|
/// </summary>
|
||||||
|
public IAuthenticationHandler AuthenticationHandler { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The handler to use for friends-related requests to this NP server.
|
||||||
|
/// </summary>
|
||||||
|
public IFriendsHandler FriendsHandler { get; set; }
|
||||||
|
|
||||||
|
internal void _handleClient(NPServerClient client)
|
||||||
|
{
|
||||||
|
_log.Debug("Client now being handled");
|
||||||
|
|
||||||
#region RPC authentication message handlers
|
#region RPC authentication message handlers
|
||||||
|
|
||||||
client.RPC.AttachHandlerForMessageType<AuthenticateWithKeyMessage>(msg =>
|
client.RPC.AttachHandlerForMessageType<AuthenticateWithKeyMessage>(msg =>
|
||||||
{
|
{
|
||||||
var result = new AuthenticationResult();;
|
var result = new AuthenticationResult();
|
||||||
if (AuthenticationHandler != null)
|
if (AuthenticationHandler != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -109,11 +196,11 @@ namespace NPSharp
|
||||||
client.UserID = result.UserID;
|
client.UserID = result.UserID;
|
||||||
|
|
||||||
// Send "online" notification to all friends of this player
|
// Send "online" notification to all friends of this player
|
||||||
foreach (var fconn in client.FriendConnections)
|
foreach (NPServerClient fconn in client.FriendConnections)
|
||||||
{
|
{
|
||||||
fconn.RPC.Send(new FriendsPresenceMessage
|
fconn.RPC.Send(new FriendsPresenceMessage
|
||||||
{
|
{
|
||||||
CurrentServer = client.DedicatedServer == null ? 0 : client.DedicatedServer.NPID,
|
CurrentServer = client.DedicatedServer == null ? 0 : client.DedicatedServer.UserID,
|
||||||
Friend = client.UserID,
|
Friend = client.UserID,
|
||||||
Presence = client.PresenceData,
|
Presence = client.PresenceData,
|
||||||
PresenceState = client.DedicatedServer == null ? 1 : 2
|
PresenceState = client.DedicatedServer == null ? 1 : 2
|
||||||
|
@ -157,7 +244,7 @@ namespace NPSharp
|
||||||
client.UserID = result.UserID;
|
client.UserID = result.UserID;
|
||||||
|
|
||||||
// Send "online" notification to all friends of this player
|
// Send "online" notification to all friends of this player
|
||||||
foreach (var fconn in client.FriendConnections)
|
foreach (NPServerClient fconn in client.FriendConnections)
|
||||||
{
|
{
|
||||||
fconn.RPC.Send(new FriendsPresenceMessage
|
fconn.RPC.Send(new FriendsPresenceMessage
|
||||||
{
|
{
|
||||||
|
@ -185,7 +272,6 @@ namespace NPSharp
|
||||||
|
|
||||||
_log.DebugFormat("Ticket[Version={0},ServerID={1},Time={2}]", ticketData.Version,
|
_log.DebugFormat("Ticket[Version={0},ServerID={1},Time={2}]", ticketData.Version,
|
||||||
ticketData.ServerID, ticketData.Time);
|
ticketData.ServerID, ticketData.Time);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (ArgumentException error)
|
catch (ArgumentException error)
|
||||||
{
|
{
|
||||||
|
@ -198,7 +284,9 @@ namespace NPSharp
|
||||||
{
|
{
|
||||||
if (ticketData.ClientID == client.UserID) // NPID enforcement
|
if (ticketData.ClientID == client.UserID) // NPID enforcement
|
||||||
{
|
{
|
||||||
var s = _clients.Where(c => c.IsServer && !c.IsDirty && c.UserID == ticketData.ServerID).ToArray();
|
var s =
|
||||||
|
_clients.Where(c => c.IsServer && !c.IsDirty && c.UserID == ticketData.ServerID)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
if (s.Any())
|
if (s.Any())
|
||||||
{
|
{
|
||||||
|
@ -236,12 +324,14 @@ namespace NPSharp
|
||||||
Result = validTicket ? 0 : 1
|
Result = validTicket ? 0 : 1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region RPC friend message handlers
|
#region RPC friend message handlers
|
||||||
|
|
||||||
client.RPC.AttachHandlerForMessageType<FriendsSetPresenceMessage>(msg =>
|
client.RPC.AttachHandlerForMessageType<FriendsSetPresenceMessage>(msg =>
|
||||||
{
|
{
|
||||||
foreach (var pdata in msg.Presence)
|
foreach (FriendsPresence pdata in msg.Presence)
|
||||||
{
|
{
|
||||||
client.SetPresence(pdata.Key, pdata.Value);
|
client.SetPresence(pdata.Key, pdata.Value);
|
||||||
_log.DebugFormat("Client says presence \"{0}\" is \"{1}\"", pdata.Key, pdata.Value);
|
_log.DebugFormat("Client says presence \"{0}\" is \"{1}\"", pdata.Key, pdata.Value);
|
||||||
|
@ -252,10 +342,10 @@ namespace NPSharp
|
||||||
{
|
{
|
||||||
// Why so goddamn complicated, NTA. Fuck.
|
// Why so goddamn complicated, NTA. Fuck.
|
||||||
// TODO: Not compatible with non-public accounts
|
// TODO: Not compatible with non-public accounts
|
||||||
var npid = new CSteamID((uint) msg.Guid, EUniverse.Public,
|
ulong npid = new CSteamID((uint) msg.Guid, EUniverse.Public,
|
||||||
EAccountType.Individual).ConvertToUint64();
|
EAccountType.Individual).ConvertToUint64();
|
||||||
|
|
||||||
var avatar = UserAvatarHandler.GetUserAvatar(npid) ?? UserAvatarHandler.GetDefaultAvatar();
|
byte[] avatar = UserAvatarHandler.GetUserAvatar(npid) ?? UserAvatarHandler.GetDefaultAvatar();
|
||||||
|
|
||||||
client.RPC.Send(new FriendsGetUserAvatarResultMessage
|
client.RPC.Send(new FriendsGetUserAvatarResultMessage
|
||||||
{
|
{
|
||||||
|
@ -269,11 +359,197 @@ namespace NPSharp
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
// TODO: RPC message handling for storage
|
#region RPC storage message handlers
|
||||||
|
|
||||||
|
client.RPC.AttachHandlerForMessageType<StorageGetPublisherFileMessage>(msg =>
|
||||||
|
{
|
||||||
|
if (FileHandler == null)
|
||||||
|
{
|
||||||
|
client.RPC.Send(new StoragePublisherFileMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 2,
|
||||||
|
FileName = msg.FileName
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (client.UserID == null)
|
||||||
|
{
|
||||||
|
client.RPC.Send(new StoragePublisherFileMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 2,
|
||||||
|
FileName = msg.FileName
|
||||||
|
});
|
||||||
|
_log.WarnFormat("Client tried to read publisher file {0} while not logged in", msg.FileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data = FileHandler.ReadPublisherFile(client, msg.FileName);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
client.RPC.Send(new StoragePublisherFileMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 1,
|
||||||
|
FileName = msg.FileName
|
||||||
|
});
|
||||||
|
_log.DebugFormat("Could not open publisher file {0}", msg.FileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.RPC.Send(new StoragePublisherFileMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 0,
|
||||||
|
FileName = msg.FileName
|
||||||
|
});
|
||||||
|
_log.DebugFormat("Sent publisher file {0}", msg.FileName);
|
||||||
|
}
|
||||||
|
catch (Exception error)
|
||||||
|
{
|
||||||
|
_log.Warn("GetPublisherFile handler error", error);
|
||||||
|
client.RPC.Send(new StoragePublisherFileMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 2,
|
||||||
|
FileName = msg.FileName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
client.RPC.AttachHandlerForMessageType<StorageGetUserFileMessage>(msg =>
|
||||||
|
{
|
||||||
|
if (FileHandler == null)
|
||||||
|
{
|
||||||
|
client.RPC.Send(new StorageUserFileMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 2,
|
||||||
|
FileName = msg.FileName
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (client.UserID == null)
|
||||||
|
{
|
||||||
|
client.RPC.Send(new StorageUserFileMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 2,
|
||||||
|
FileName = msg.FileName,
|
||||||
|
NPID = client.UserID
|
||||||
|
});
|
||||||
|
_log.WarnFormat("Client tried to read user file {0} while not logged in", msg.FileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data = FileHandler.ReadUserFile(client, msg.FileName);
|
||||||
|
if (data == null)
|
||||||
|
{
|
||||||
|
client.RPC.Send(new StorageUserFileMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 1,
|
||||||
|
FileName = msg.FileName,
|
||||||
|
NPID = client.UserID
|
||||||
|
});
|
||||||
|
_log.DebugFormat("Could not open user file {0}", msg.FileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.RPC.Send(new StorageUserFileMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 0,
|
||||||
|
FileName = msg.FileName,
|
||||||
|
FileData = data,
|
||||||
|
NPID = client.UserID
|
||||||
|
});
|
||||||
|
_log.DebugFormat("Sent user file {0}", msg.FileName);
|
||||||
|
}
|
||||||
|
catch (Exception error)
|
||||||
|
{
|
||||||
|
_log.Warn("GetUserFile handler error", error);
|
||||||
|
client.RPC.Send(new StorageUserFileMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 2,
|
||||||
|
FileName = msg.FileName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
client.RPC.AttachHandlerForMessageType<StorageSendRandomStringMessage>(msg =>
|
||||||
|
{
|
||||||
|
// TODO: Handle "random string" messages
|
||||||
|
});
|
||||||
|
|
||||||
|
client.RPC.AttachHandlerForMessageType<StorageWriteUserFileMessage>(msg =>
|
||||||
|
{
|
||||||
|
if (FileHandler == null)
|
||||||
|
{
|
||||||
|
client.RPC.Send(new StorageWriteUserFileResultMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 2,
|
||||||
|
FileName = msg.FileName
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (client.UserID == null)
|
||||||
|
{
|
||||||
|
client.RPC.Send(new StorageWriteUserFileResultMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 2,
|
||||||
|
FileName = msg.FileName,
|
||||||
|
NPID = client.UserID
|
||||||
|
});
|
||||||
|
_log.WarnFormat("Client tried to write user file {0} while not logged in", msg.FileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileHandler.WriteUserFile(client, msg.FileName, msg.FileData);
|
||||||
|
|
||||||
|
client.RPC.Send(new StorageWriteUserFileResultMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 0,
|
||||||
|
FileName = msg.FileName,
|
||||||
|
NPID = client.UserID
|
||||||
|
});
|
||||||
|
_log.DebugFormat("Received and wrote user file {0}", msg.FileName);
|
||||||
|
}
|
||||||
|
catch (Exception error)
|
||||||
|
{
|
||||||
|
_log.Warn("WriteUserFile handler error", error);
|
||||||
|
client.RPC.Send(new StorageWriteUserFileResultMessage
|
||||||
|
{
|
||||||
|
MessageId = msg.MessageId,
|
||||||
|
Result = 2,
|
||||||
|
FileName = msg.FileName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
// TODO: RPC message handling for MessagingSendData
|
// TODO: RPC message handling for MessagingSendData
|
||||||
// TODO: RPC message handling for server sessions
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region RPC server session message handler
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
_clients.Add(client);
|
_clients.Add(client);
|
||||||
try
|
try
|
||||||
|
@ -298,123 +574,15 @@ namespace NPSharp
|
||||||
_clients.Remove(client);
|
_clients.Remove(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NPServerClient[] Clients
|
|
||||||
{
|
|
||||||
get { return _clients.ToArray(); } // Avoid race condition by IEnum changes
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IFileServingHandler
|
|
||||||
{
|
|
||||||
Stream ReadUserFile(NPServerClient client, string file);
|
|
||||||
|
|
||||||
Stream ReadPublisherFile(NPServerClient client, string file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IAuthenticationHandler AuthenticationHandler { get; set; }
|
|
||||||
|
|
||||||
public interface IAuthenticationHandler
|
|
||||||
{
|
|
||||||
AuthenticationResult AuthenticateUser(NPServerClient client, string username, string password);
|
|
||||||
|
|
||||||
AuthenticationResult AuthenticateUser(NPServerClient client, string token);
|
|
||||||
|
|
||||||
AuthenticationResult AuthenticateServer(NPServerClient client, string licenseKey);
|
|
||||||
|
|
||||||
TicketValidationResult ValidateTicket(NPServerClient client, NPServerClient server);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AuthenticationResult
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs an authentication result instance.
|
/// Triggered when a client has connected but is not authenticating yet.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="npid">Set this to null if authentication should fail, otherwise use an instance of a steam ID which is unique to the user.</param>
|
|
||||||
public AuthenticationResult(CSteamID npid = null)
|
|
||||||
{
|
|
||||||
UserID = npid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Result { get { return UserID != null; } }
|
|
||||||
|
|
||||||
public CSteamID UserID { get; private set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TicketValidationResult
|
|
||||||
{
|
|
||||||
Valid = 0,
|
|
||||||
Invalid = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
public IFriendsHandler FriendsHandler { get; set; }
|
|
||||||
|
|
||||||
public interface IFriendsHandler
|
|
||||||
{
|
|
||||||
IEnumerable<FriendDetails> GetFriends(NPServerClient client);
|
|
||||||
|
|
||||||
/*
|
|
||||||
void SetFriendStatus(NPServerClient client, PresenceState presenceState,
|
|
||||||
Dictionary<string, string> presenceData, ulong serverID)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
public class NPServerClient
|
|
||||||
{
|
|
||||||
internal NPServerClient(NPServer np, RPCServerStream rpcclient)
|
|
||||||
{
|
|
||||||
NP = np;
|
|
||||||
RPC = rpcclient;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal readonly RPCServerStream RPC;
|
|
||||||
|
|
||||||
internal readonly NPServer NP;
|
|
||||||
|
|
||||||
public CSteamID UserID { get; internal set; }
|
|
||||||
|
|
||||||
public IEnumerable<FriendDetails> Friends
|
|
||||||
{
|
|
||||||
get { return NP.FriendsHandler.GetFriends(this).ToArray(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<NPServerClient> FriendConnections
|
|
||||||
{
|
|
||||||
get { return NP.Clients.Where(c => Friends.Any(f => f.NPID == c.NPID)); }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal NPServerClient DedicatedServer;
|
|
||||||
|
|
||||||
private readonly Dictionary<string, string> _presence = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
public FriendsPresence[] PresenceData { get
|
|
||||||
{
|
|
||||||
return _presence.Select(i => new FriendsPresence {Key = i.Key, Value = i.Value}).ToArray();
|
|
||||||
} }
|
|
||||||
|
|
||||||
public bool IsServer { get; set; }
|
|
||||||
public bool IsDirty { get; set; }
|
|
||||||
public int GroupID { get; set; }
|
|
||||||
|
|
||||||
internal void SetPresence(string key, string value)
|
|
||||||
{
|
|
||||||
if (!_presence.ContainsKey(key))
|
|
||||||
_presence.Add(key, value);
|
|
||||||
else
|
|
||||||
_presence[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PresenceState
|
|
||||||
{
|
|
||||||
Offline = 0,
|
|
||||||
Online = 1,
|
|
||||||
Playing = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
public event ClientEventHandler ClientConnected;
|
public event ClientEventHandler ClientConnected;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ClientConnected" /> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">The client</param>
|
||||||
protected virtual void OnClientConnected(NPServerClient client)
|
protected virtual void OnClientConnected(NPServerClient client)
|
||||||
{
|
{
|
||||||
var handler = ClientConnected;
|
var handler = ClientConnected;
|
||||||
|
@ -422,8 +590,15 @@ namespace NPSharp
|
||||||
if (handler != null) handler(this, args);
|
if (handler != null) handler(this, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggered when a client has disconnected.
|
||||||
|
/// </summary>
|
||||||
public event ClientEventHandler ClientDisconnected;
|
public event ClientEventHandler ClientDisconnected;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ClientDisconnected" /> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">The client</param>
|
||||||
protected virtual void OnClientDisconnected(NPServerClient client)
|
protected virtual void OnClientDisconnected(NPServerClient client)
|
||||||
{
|
{
|
||||||
var handler = ClientDisconnected;
|
var handler = ClientDisconnected;
|
||||||
|
@ -431,8 +606,15 @@ namespace NPSharp
|
||||||
if (handler != null) handler(this, args);
|
if (handler != null) handler(this, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggered when a client has authenticated successfully.
|
||||||
|
/// </summary>
|
||||||
public event ClientEventHandler ClientAuthenticated;
|
public event ClientEventHandler ClientAuthenticated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ClientAuthenticated" /> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">The client</param>
|
||||||
protected virtual void OnClientAuthenticated(NPServerClient client)
|
protected virtual void OnClientAuthenticated(NPServerClient client)
|
||||||
{
|
{
|
||||||
var handler = ClientAuthenticated;
|
var handler = ClientAuthenticated;
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NPSharp.RPC;
|
||||||
|
using NPSharp.RPC.Messages;
|
||||||
|
using NPSharp.Steam;
|
||||||
|
|
||||||
|
namespace NPSharp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a remote client connection to an NP server.
|
||||||
|
/// </summary>
|
||||||
|
public class NPServerClient
|
||||||
|
{
|
||||||
|
internal readonly NPServer NP;
|
||||||
|
internal readonly RPCServerStream RPC;
|
||||||
|
private readonly Dictionary<string, string> _presence = new Dictionary<string, string>();
|
||||||
|
internal NPServerClient DedicatedServer;
|
||||||
|
|
||||||
|
internal NPServerClient(NPServer np, RPCServerStream rpcclient)
|
||||||
|
{
|
||||||
|
NP = np;
|
||||||
|
RPC = rpcclient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CSteamID UserID { get; internal set; }
|
||||||
|
|
||||||
|
public IEnumerable<FriendDetails> Friends
|
||||||
|
{
|
||||||
|
get { return NP.FriendsHandler.GetFriends(this).ToArray(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<NPServerClient> FriendConnections
|
||||||
|
{
|
||||||
|
get { return NP.Clients.Where(c => Friends.Any(f => f.NPID == c.UserID)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public FriendsPresence[] PresenceData
|
||||||
|
{
|
||||||
|
get { return _presence.Select(i => new FriendsPresence {Key = i.Key, Value = i.Value}).ToArray(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsServer { get; set; }
|
||||||
|
public bool IsDirty { get; set; }
|
||||||
|
public int GroupID { get; set; }
|
||||||
|
|
||||||
|
internal void SetPresence(string key, string value)
|
||||||
|
{
|
||||||
|
if (!_presence.ContainsKey(key))
|
||||||
|
_presence.Add(key, value);
|
||||||
|
else
|
||||||
|
_presence[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace NPSharp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the friend's current presence activity.
|
||||||
|
/// </summary>
|
||||||
|
public enum PresenceState
|
||||||
|
{
|
||||||
|
Offline = 0,
|
||||||
|
Online = 1,
|
||||||
|
Playing = 2
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Diagnostics;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
@ -33,7 +34,9 @@ namespace NPSharp.RPC.Messages
|
||||||
{
|
{
|
||||||
var header = new byte[4*sizeof (uint)];
|
var header = new byte[4*sizeof (uint)];
|
||||||
|
|
||||||
while (sock.Connected && !sock.Poll(1000, SelectMode.SelectRead)) { }
|
while (sock.Connected && !sock.Poll(1000, SelectMode.SelectRead))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
if (!sock.Connected)
|
if (!sock.Connected)
|
||||||
{
|
{
|
||||||
|
@ -41,7 +44,7 @@ namespace NPSharp.RPC.Messages
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var l = sock.Receive(header);
|
int l = sock.Receive(header);
|
||||||
if (l == 0)
|
if (l == 0)
|
||||||
{
|
{
|
||||||
Log.Debug("Received 0 bytes");
|
Log.Debug("Received 0 bytes");
|
||||||
|
@ -53,7 +56,7 @@ namespace NPSharp.RPC.Messages
|
||||||
throw new ProtocolViolationException("Received incomplete header");
|
throw new ProtocolViolationException("Received incomplete header");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint signature, length, type, pid;
|
uint signature, length, type, mid;
|
||||||
using (var ms = new MemoryStream(header))
|
using (var ms = new MemoryStream(header))
|
||||||
{
|
{
|
||||||
using (var br = new BinaryReader(ms))
|
using (var br = new BinaryReader(ms))
|
||||||
|
@ -61,7 +64,7 @@ namespace NPSharp.RPC.Messages
|
||||||
signature = br.ReadUInt32();
|
signature = br.ReadUInt32();
|
||||||
length = br.ReadUInt32();
|
length = br.ReadUInt32();
|
||||||
type = br.ReadUInt32();
|
type = br.ReadUInt32();
|
||||||
pid = br.ReadUInt32();
|
mid = br.ReadUInt32();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,11 +77,11 @@ namespace NPSharp.RPC.Messages
|
||||||
throw new ProtocolViolationException("Received packet with invalid signature");
|
throw new ProtocolViolationException("Received packet with invalid signature");
|
||||||
}
|
}
|
||||||
|
|
||||||
T packet;
|
T message;
|
||||||
|
|
||||||
using (var ms = new MemoryStream(buffer))
|
using (var ms = new MemoryStream(buffer))
|
||||||
{
|
{
|
||||||
var types = Assembly.GetExecutingAssembly().GetTypes().Where(
|
Type[] types = Assembly.GetExecutingAssembly().GetTypes().Where(
|
||||||
t =>
|
t =>
|
||||||
t.IsSubclassOf(typeof (T))
|
t.IsSubclassOf(typeof (T))
|
||||||
&&
|
&&
|
||||||
|
@ -96,27 +99,27 @@ namespace NPSharp.RPC.Messages
|
||||||
return null;
|
return null;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
packet = (T) Serializer.NonGeneric.Deserialize(
|
message = (T) Serializer.NonGeneric.Deserialize(
|
||||||
types.Single(),
|
types.Single(),
|
||||||
ms
|
ms
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
packet.MessageId = pid;
|
message.MessageId = mid;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Log.DebugFormat("{3}[ID={0},Type={1},TypeName={2}] {{", pid, packet.GetTypeId(), packet.GetType().Name,
|
Log.DebugFormat("{3}[ID={0},Type={1},TypeName={2}] {{", mid, message.GetTypeId(), message.GetType().Name,
|
||||||
typeof (T).Name);
|
typeof (T).Name);
|
||||||
foreach (
|
foreach (
|
||||||
var prop in
|
PropertyInfo prop in
|
||||||
packet.GetType().GetProperties().Where(p => !(p.DeclaringType == typeof (RPCServerMessage))))
|
message.GetType().GetProperties().Where(p => !(p.DeclaringType == typeof (RPCServerMessage))))
|
||||||
{
|
{
|
||||||
Log.DebugFormat("\t{0} = {1}", prop.Name, prop.GetValue(packet));
|
Log.DebugFormat("\t{0} = {1}", prop.Name, prop.GetValue(message));
|
||||||
}
|
}
|
||||||
Log.DebugFormat("}} // deserialized from {0} bytes", header.Length + buffer.Length);
|
Log.DebugFormat("}} // deserialized from {0} bytes", header.Length + buffer.Length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return packet;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Serialize()
|
public byte[] Serialize()
|
||||||
|
@ -149,7 +152,7 @@ namespace NPSharp.RPC.Messages
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Log.DebugFormat("{3}[ID={0},Type={1},TypeName={2}] {{", MessageId, GetTypeId(), GetType().Name,
|
Log.DebugFormat("{3}[ID={0},Type={1},TypeName={2}] {{", MessageId, GetTypeId(), GetType().Name,
|
||||||
GetType().Name);
|
GetType().Name);
|
||||||
foreach (var prop in GetType().GetProperties())
|
foreach (PropertyInfo prop in GetType().GetProperties())
|
||||||
{
|
{
|
||||||
Log.DebugFormat("\t{0} = {1}", prop.Name, prop.GetValue(this));
|
Log.DebugFormat("\t{0} = {1}", prop.Name, prop.GetValue(this));
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace NPSharp.RPC
|
||||||
TypeCallbacks.Add(
|
TypeCallbacks.Add(
|
||||||
new KeyValuePair<uint, Action<TRecv>>(
|
new KeyValuePair<uint, Action<TRecv>>(
|
||||||
((PacketAttribute) typeof (T).GetCustomAttributes(typeof (PacketAttribute), false).Single()).Type,
|
((PacketAttribute) typeof (T).GetCustomAttributes(typeof (PacketAttribute), false).Single()).Type,
|
||||||
(Action<TRecv>)callback));
|
msg => callback.Invoke((T)msg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -131,12 +131,14 @@ namespace NPSharp.RPC
|
||||||
if (_sock == null)
|
if (_sock == null)
|
||||||
throw new InvalidOperationException("You need to open the stream first.");
|
throw new InvalidOperationException("You need to open the stream first.");
|
||||||
|
|
||||||
|
if (message.MessageId == default(uint))
|
||||||
message.MessageId = MessageID;
|
message.MessageId = MessageID;
|
||||||
|
|
||||||
var buffer = message.Serialize();
|
byte[] buffer = message.Serialize();
|
||||||
|
|
||||||
_sock.Send(buffer);
|
_sock.Send(buffer);
|
||||||
|
|
||||||
|
if (typeof (TSend) == typeof (RPCClientMessage))
|
||||||
IterateMessageID();
|
IterateMessageID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +158,9 @@ namespace NPSharp.RPC
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof (TRecv) == typeof (RPCClientMessage))
|
||||||
|
MessageID = message.MessageId;
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
foreach (var cbi in IDCallbacks.Where(p => p.Key == message.MessageId))
|
foreach (var cbi in IDCallbacks.Where(p => p.Key == message.MessageId))
|
||||||
cbi.Value.Invoke(message);
|
cbi.Value.Invoke(message);
|
||||||
|
|
|
@ -174,7 +174,9 @@ namespace NPSharp.Steam
|
||||||
{
|
{
|
||||||
case EAccountType.Invalid:
|
case EAccountType.Invalid:
|
||||||
case EAccountType.Individual:
|
case EAccountType.Individual:
|
||||||
return AccountUniverse <= EUniverse.Public ? String.Format("STEAM_0:{0}:{1}", AccountID & 1, AccountID >> 1) : String.Format("STEAM_{2}:{0}:{1}", AccountID & 1, AccountID >> 1, (int) AccountUniverse);
|
return AccountUniverse <= EUniverse.Public
|
||||||
|
? String.Format("STEAM_0:{0}:{1}", AccountID & 1, AccountID >> 1)
|
||||||
|
: String.Format("STEAM_{2}:{0}:{1}", AccountID & 1, AccountID >> 1, (int) AccountUniverse);
|
||||||
default:
|
default:
|
||||||
return Convert.ToString(this);
|
return Convert.ToString(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using log4net.Appender;
|
|
||||||
|
|
||||||
namespace NPSharp
|
namespace NPSharp
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace NPSharp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the outcome of a ticket validation attempt.
|
||||||
|
/// </summary>
|
||||||
|
public enum TicketValidationResult
|
||||||
|
{
|
||||||
|
Valid = 0,
|
||||||
|
Invalid = 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,10 +54,18 @@
|
||||||
<Reference Include="System.Xml.Serialization" />
|
<Reference Include="System.Xml.Serialization" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="AuthenticationResult.cs" />
|
||||||
<Compile Include="ClientEventArgs.cs" />
|
<Compile Include="ClientEventArgs.cs" />
|
||||||
|
<Compile Include="ClientEventHandler.cs" />
|
||||||
|
<Compile Include="IAuthenticationHandler.cs" />
|
||||||
|
<Compile Include="IFileServingHandler.cs" />
|
||||||
|
<Compile Include="IFriendsHandler.cs" />
|
||||||
|
<Compile Include="IUserAvatarHandler.cs" />
|
||||||
<Compile Include="NPClient.cs" />
|
<Compile Include="NPClient.cs" />
|
||||||
<Compile Include="NPFileException.cs" />
|
<Compile Include="NPFileException.cs" />
|
||||||
<Compile Include="NPServer.cs" />
|
<Compile Include="NPServer.cs" />
|
||||||
|
<Compile Include="NPServerClient.cs" />
|
||||||
|
<Compile Include="PresenceState.cs" />
|
||||||
<Compile Include="RPC\Messages\AuthenticateRegisterServerMessage.cs" />
|
<Compile Include="RPC\Messages\AuthenticateRegisterServerMessage.cs" />
|
||||||
<Compile Include="RPC\Messages\AuthenticateRegisterServerResultMessage.cs" />
|
<Compile Include="RPC\Messages\AuthenticateRegisterServerResultMessage.cs" />
|
||||||
<Compile Include="RPC\Messages\AuthenticateUserGroupMessage.cs" />
|
<Compile Include="RPC\Messages\AuthenticateUserGroupMessage.cs" />
|
||||||
|
@ -104,6 +112,7 @@
|
||||||
<Compile Include="Steam\InteropHelp.cs" />
|
<Compile Include="Steam\InteropHelp.cs" />
|
||||||
<Compile Include="Steam\SteamID_t.cs" />
|
<Compile Include="Steam\SteamID_t.cs" />
|
||||||
<Compile Include="Ticket.cs" />
|
<Compile Include="Ticket.cs" />
|
||||||
|
<Compile Include="TicketValidationResult.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Steam\README.txt" />
|
<Content Include="Steam\README.txt" />
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NPSharp.Steam;
|
||||||
|
|
||||||
|
namespace NPSharp.CommandLine.Server
|
||||||
|
{
|
||||||
|
class DummyAuthenticationHandler : IAuthenticationHandler
|
||||||
|
{
|
||||||
|
private uint _userID = 0;
|
||||||
|
|
||||||
|
public DummyAuthenticationHandler()
|
||||||
|
{
|
||||||
|
// TODO: Listener on port 12003 accepting HTTP token retrievals
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationResult AuthenticateUser(NPServerClient client, string username, string password)
|
||||||
|
{
|
||||||
|
return new AuthenticationResult(new CSteamID()
|
||||||
|
{
|
||||||
|
AccountID = _userID++
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationResult AuthenticateUser(NPServerClient client, string token)
|
||||||
|
{
|
||||||
|
return new AuthenticationResult(new CSteamID()
|
||||||
|
{
|
||||||
|
AccountID = _userID++
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationResult AuthenticateServer(NPServerClient client, string licenseKey)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TicketValidationResult ValidateTicket(NPServerClient client, NPServerClient server)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,85 @@
|
||||||
namespace NPSharp.CommandLine.Server
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using log4net;
|
||||||
|
using log4net.Appender;
|
||||||
|
using log4net.Config;
|
||||||
|
using log4net.Core;
|
||||||
|
using log4net.Layout;
|
||||||
|
|
||||||
|
namespace NPSharp.CommandLine.Server
|
||||||
{
|
{
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// log4net setup
|
||||||
|
if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
|
||||||
|
{
|
||||||
|
var appender = new ConsoleAppender
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
Threshold = Level.Debug,
|
||||||
|
#else
|
||||||
|
Threshold = Level.Info,
|
||||||
|
#endif
|
||||||
|
Layout = new PatternLayout("<%d{HH:mm:ss}> [%logger:%thread] %level: %message%newline"),
|
||||||
|
};
|
||||||
|
BasicConfigurator.Configure(new IAppender[] { appender, new DebugAppender { Layout = appender.Layout, Threshold = Level.All } });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var appender = new ColoredConsoleAppender
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
Threshold = Level.Debug,
|
||||||
|
#else
|
||||||
|
Threshold = Level.Info,
|
||||||
|
#endif
|
||||||
|
Layout = new PatternLayout("<%d{HH:mm:ss}> [%logger:%thread] %level: %message%newline"),
|
||||||
|
};
|
||||||
|
appender.AddMapping(new ColoredConsoleAppender.LevelColors
|
||||||
|
{
|
||||||
|
Level = Level.Debug,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.Cyan | ColoredConsoleAppender.Colors.HighIntensity
|
||||||
|
});
|
||||||
|
appender.AddMapping(new ColoredConsoleAppender.LevelColors
|
||||||
|
{
|
||||||
|
Level = Level.Info,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.Green | ColoredConsoleAppender.Colors.HighIntensity
|
||||||
|
});
|
||||||
|
appender.AddMapping(new ColoredConsoleAppender.LevelColors
|
||||||
|
{
|
||||||
|
Level = Level.Warn,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.Purple | ColoredConsoleAppender.Colors.HighIntensity
|
||||||
|
});
|
||||||
|
appender.AddMapping(new ColoredConsoleAppender.LevelColors
|
||||||
|
{
|
||||||
|
Level = Level.Error,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.Red | ColoredConsoleAppender.Colors.HighIntensity
|
||||||
|
});
|
||||||
|
appender.AddMapping(new ColoredConsoleAppender.LevelColors
|
||||||
|
{
|
||||||
|
Level = Level.Fatal,
|
||||||
|
ForeColor = ColoredConsoleAppender.Colors.White | ColoredConsoleAppender.Colors.HighIntensity,
|
||||||
|
BackColor = ColoredConsoleAppender.Colors.Red
|
||||||
|
});
|
||||||
|
appender.ActivateOptions();
|
||||||
|
BasicConfigurator.Configure(new IAppender[] { appender, new DebugAppender { Layout = appender.Layout, Threshold = Level.All } });
|
||||||
|
}
|
||||||
|
|
||||||
|
var log = LogManager.GetLogger("Main");
|
||||||
|
|
||||||
|
log.Info("Now starting NP server...");
|
||||||
|
var np = new NPServer(3036)
|
||||||
|
{
|
||||||
|
AuthenticationHandler = new DummyAuthenticationHandler(),
|
||||||
|
// TODO: Implement the other handlers
|
||||||
|
};
|
||||||
|
np.Start();
|
||||||
|
log.Info("NP server started up and is now ready.");
|
||||||
|
|
||||||
|
Thread.Sleep(Timeout.Infinite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
<AssemblyName>npserv</AssemblyName>
|
<AssemblyName>npserv</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
|
||||||
|
<RestorePackages>true</RestorePackages>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
@ -37,22 +39,29 @@
|
||||||
<OutputPath>$(SolutionDir)\bin\$(Configuration)\$(Platform)\</OutputPath>
|
<OutputPath>$(SolutionDir)\bin\$(Configuration)\$(Platform)\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\..\packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="DummyAuthenticationHandler.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="App.config" />
|
<None Include="App.config" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\libnpsharp\libnpsharp.csproj">
|
||||||
|
<Project>{1a5ac63a-250e-4bc8-b81a-822ac31f5e37}</Project>
|
||||||
|
<Name>libnpsharp</Name>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
<Target Name="BeforeBuild">
|
<Target Name="BeforeBuild">
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="log4net" version="2.0.3" targetFramework="net45" />
|
||||||
|
</packages>
|
Loading…
Reference in New Issue