2017-01-09 20:52:56 +00:00
using System ;
2017-01-21 18:13:42 +00:00
using System.Threading.Tasks ;
2017-07-20 12:15:11 +00:00
using System.Threading ;
2017-09-10 20:34:01 +00:00
using System.Net.Sockets ;
using System.Net ;
using System.IO ;
2017-01-19 13:13:35 +00:00
2017-09-10 20:34:01 +00:00
using SBRL.GlidingSquirrel.Websocket ;
2017-01-19 13:13:35 +00:00
using Nibriboard.RippleSpace ;
2017-01-21 18:13:42 +00:00
using Nibriboard.Client ;
2017-01-19 13:13:35 +00:00
2017-01-09 20:52:56 +00:00
namespace Nibriboard
{
2017-01-28 18:49:26 +00:00
/// <summary>
/// The main Nibriboard server.
/// This class manages not only the connected clients, but also holds the master reference to the <see cref="Nibriboard.RippleSpace.RippleSpaceManager"/>.
/// </summary>
2017-01-10 19:52:27 +00:00
public class NibriboardServer
2017-01-09 20:52:56 +00:00
{
2017-07-20 12:15:11 +00:00
private TcpListener commandServer ;
2017-09-10 20:34:01 +00:00
private NibriboardApp appServer ;
2017-01-09 20:52:56 +00:00
2017-01-21 18:13:42 +00:00
private ClientSettings clientSettings ;
2017-07-23 21:02:24 +00:00
private RippleSpaceManager planeManager ;
2017-01-19 13:13:35 +00:00
2017-07-20 12:15:11 +00:00
public readonly int CommandPort = 31587 ;
2017-01-09 20:52:56 +00:00
public readonly int Port = 31586 ;
2017-07-23 21:02:24 +00:00
public NibriboardServer ( string pathToRippleSpace , int inPort = 31586 )
2017-01-09 20:52:56 +00:00
{
2017-01-19 13:13:35 +00:00
Port = inPort ;
2017-01-09 20:52:56 +00:00
2017-07-23 21:02:24 +00:00
// Load the specified packed ripple space file if it exists - otherwise save it to disk
if ( File . Exists ( pathToRippleSpace ) ) {
planeManager = RippleSpaceManager . FromFile ( pathToRippleSpace ) . Result ;
} else {
Log . WriteLine ( "[NibriboardServer] Couldn't find packed ripple space at {0} - creating new ripple space instead." , pathToRippleSpace ) ;
planeManager = new RippleSpaceManager ( ) { SourceFilename = pathToRippleSpace } ;
}
2017-01-21 18:13:42 +00:00
clientSettings = new ClientSettings ( ) {
2017-05-04 18:53:38 +00:00
SecureWebSocket = false ,
WebSocketHost = "192.168.0.56" ,
WebSocketPort = Port ,
WebSocketPath = "/RipplespaceLink"
2017-01-21 18:13:42 +00:00
} ;
// HTTP Server setup
2017-09-10 20:34:01 +00:00
appServer = new NibriboardApp ( new NibriboardAppStartInfo ( ) {
FilePrefix = "Nibriboard.ClientFiles" ,
ClientSettings = clientSettings ,
SpaceManager = planeManager
2017-10-23 18:51:16 +00:00
} , IPAddress . Any , Port ) ;
2017-01-19 13:13:35 +00:00
}
public async Task Start ( )
{
2017-09-10 20:34:01 +00:00
await appServer . Start ( ) ;
2017-01-10 19:52:27 +00:00
Log . WriteLine ( "[NibriboardServer] Started on port {0}" , Port ) ;
2017-01-19 13:13:35 +00:00
await planeManager . StartMaintenanceMonkey ( ) ;
2017-01-10 19:52:27 +00:00
}
2017-07-20 12:15:11 +00:00
/// <summary>
/// Starts the command listener.
/// The command listener is a light tcp-based command console that allows control
/// of the Nibriboard server, since C# doesn't currently have support for signal handling.
/// It listeners on [::1] _only_, to avoid security issues.
/// In the future, a simple secret might be required to use it to aid security further.
/// </summary>
public async Task StartCommandListener ( )
{
commandServer = new TcpListener ( IPAddress . IPv6Loopback , CommandPort ) ;
commandServer . Start ( ) ;
Log . WriteLine ( "[CommandConsole] Listening on {0}." , new IPEndPoint ( IPAddress . IPv6Loopback , CommandPort ) ) ;
while ( true )
{
TcpClient nextClient = await commandServer . AcceptTcpClientAsync ( ) ;
StreamReader source = new StreamReader ( nextClient . GetStream ( ) ) ;
StreamWriter destination = new StreamWriter ( nextClient . GetStream ( ) ) { AutoFlush = true } ;
string rawCommand = await source . ReadLineAsync ( ) ;
string [ ] commandParts = rawCommand . Split ( " \t" . ToCharArray ( ) ) ;
2017-07-23 18:43:33 +00:00
Log . WriteLine ( "[CommandConsole] Client executing {0}" , rawCommand ) ;
2017-07-20 12:15:11 +00:00
try
{
switch ( commandParts [ 0 ] . Trim ( ) )
{
case "help" :
await destination . WriteLineAsync ( "NibriboardServer Command Console" ) ;
await destination . WriteLineAsync ( "================================" ) ;
await destination . WriteLineAsync ( "Available commands:" ) ;
await destination . WriteLineAsync ( " help Show this message" ) ;
await destination . WriteLineAsync ( " save Save the ripplespace to disk" ) ;
break ;
case "save" :
2017-07-29 12:20:12 +00:00
await destination . WriteAsync ( "Saving ripple space - " ) ;
2017-07-20 12:15:11 +00:00
await planeManager . Save ( ) ;
2017-07-29 12:20:12 +00:00
await destination . WriteLineAsync ( "done." ) ;
2017-07-20 12:15:11 +00:00
break ;
}
}
catch ( Exception error )
{
await destination . WriteLineAsync ( error . ToString ( ) ) ;
}
nextClient . Close ( ) ;
}
}
2017-01-09 20:52:56 +00:00
}
}