Merge pull request #8 from cxxpxr/main

Added REST api functionality
This commit is contained in:
Derek S 2021-03-31 17:27:20 -05:00 committed by GitHub
commit a2719d878e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 142 additions and 33 deletions

View file

@ -11,5 +11,8 @@ namespace LightReflectiveMirror
public string AuthenticationKey = "Secret Auth Key"; public string AuthenticationKey = "Secret Auth Key";
public int UpdateLoopTime = 10; public int UpdateLoopTime = 10;
public int UpdateHeartbeatInterval = 100; public int UpdateHeartbeatInterval = 100;
public bool UseEndpoint = false;
public ushort EndpointPort = 6969;
public bool EndpointServerList = false;
} }
} }

View file

@ -0,0 +1,84 @@
using Grapevine;
using Newtonsoft.Json;
using System;
using System.Threading.Tasks;
namespace LightReflectiveMirror.Endpoints
{
[Serializable]
struct RelayStats
{
public int ConnectedClients;
public int RoomCount;
public int PublicRoomCount;
public TimeSpan Uptime;
}
[RestResource]
public class Endpoint
{
[RestRoute("Get", "/api/stats")]
public async Task Stats(IHttpContext context)
{
RelayStats stats = new RelayStats
{
ConnectedClients = Program.instance.GetConnections(),
RoomCount = Program.instance.GetRooms().Count,
PublicRoomCount = Program.instance.GetPublicRoomCount(),
Uptime = Program.instance.GetUptime()
};
string json = JsonConvert.SerializeObject(stats, Formatting.Indented);
await context.Response.SendResponseAsync(json);
}
[RestRoute("Get", "/api/servers")]
public async Task ServerList(IHttpContext context)
{
if (Program.conf.EndpointServerList)
{
string json = JsonConvert.SerializeObject(Program.instance.GetRooms(), Formatting.Indented);
await context.Response.SendResponseAsync(json);
}
else
{
await context.Response.SendResponseAsync("Access Denied");
}
}
}
public class EndpointServer
{
public bool Start(ushort port = 6969)
{
try
{
var server = RestServerBuilder.UseDefaults().Build();
server.Prefixes.Remove($"http://localhost:{1234}/");
server.Prefixes.Add($"http://*:{port}/");
server.Router.Options.SendExceptionMessages = false;
server.AfterStarting += (s) =>
{
string startup = @"
********************************************************************************
* Endpoint Server listening on "+$"{string.Join(", ", server.Prefixes)}" + @"
* Be sure to Port Forward! :^)
********************************************************************************
";
Console.WriteLine(startup);
};
server.Start();
return true;
}
catch
{
return false;
}
}
}
}

View file

@ -1,8 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using LightReflectiveMirror.Endpoints;
using Mirror; using Mirror;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -11,6 +13,7 @@ namespace LightReflectiveMirror
class Program class Program
{ {
public static Transport transport; public static Transport transport;
public static Program instance;
public static Config conf; public static Config conf;
private RelayHandler _relay; private RelayHandler _relay;
@ -19,17 +22,25 @@ namespace LightReflectiveMirror
private MethodInfo _updateMethod; private MethodInfo _updateMethod;
private MethodInfo _lateUpdateMethod; private MethodInfo _lateUpdateMethod;
private DateTime _startupTime;
private List<int> _currentConnections = new List<int>(); private List<int> _currentConnections = new List<int>();
private int _currentHeartbeatTimer = 0; private int _currentHeartbeatTimer = 0;
private const string CONFIG_PATH = "config.json"; private const string CONFIG_PATH = "config.json";
public static void Main(string[] args) public static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();
=> new Program().MainAsync().GetAwaiter().GetResult();
public int GetConnections() => _currentConnections.Count;
public TimeSpan GetUptime() => DateTime.Now - _startupTime;
public int GetPublicRoomCount() => _relay.rooms.Where(x => x.isPublic).Count();
public List<Room> GetRooms() => _relay.rooms;
public async Task MainAsync() public async Task MainAsync()
{ {
WriteTitle(); WriteTitle();
instance = this;
_startupTime = DateTime.Now;
if (!File.Exists(CONFIG_PATH)) if (!File.Exists(CONFIG_PATH))
{ {
@ -93,6 +104,16 @@ namespace LightReflectiveMirror
transport.ServerStart(); transport.ServerStart();
WriteLogMessage("Transport Started!", ConsoleColor.Green); WriteLogMessage("Transport Started!", ConsoleColor.Green);
if (conf.UseEndpoint)
{
var endpoint = new EndpointServer();
if (endpoint.Start(conf.EndpointPort))
WriteLogMessage("Endpoint Service Started!", ConsoleColor.Green);
else
WriteLogMessage("Endpoint failure, please run as administrator.", ConsoleColor.Red);
}
} }
else else
{ {

View file

@ -7,7 +7,7 @@ namespace LightReflectiveMirror
{ {
public class RelayHandler public class RelayHandler
{ {
private List<Room> _rooms = new List<Room>(); public List<Room> rooms = new List<Room>();
private List<int> _pendingAuthentication = new List<int>(); private List<int> _pendingAuthentication = new List<int>();
private ArrayPool<byte> _sendBuffers; private ArrayPool<byte> _sendBuffers;
private int _maxPacketSize = 0; private int _maxPacketSize = 0;
@ -115,16 +115,16 @@ namespace LightReflectiveMirror
int pos = 0; int pos = 0;
var buffer = _sendBuffers.Rent(500); var buffer = _sendBuffers.Rent(500);
buffer.WriteByte(ref pos, (byte)OpCodes.ServerListReponse); buffer.WriteByte(ref pos, (byte)OpCodes.ServerListReponse);
for(int i = 0; i < _rooms.Count; i++) for(int i = 0; i < rooms.Count; i++)
{ {
if (_rooms[i].isPublic) if (rooms[i].isPublic)
{ {
buffer.WriteBool(ref pos, true); buffer.WriteBool(ref pos, true);
buffer.WriteString(ref pos, _rooms[i].serverName); buffer.WriteString(ref pos, rooms[i].serverName);
buffer.WriteString(ref pos, _rooms[i].serverData); buffer.WriteString(ref pos, rooms[i].serverData);
buffer.WriteInt(ref pos, _rooms[i].serverId); buffer.WriteInt(ref pos, rooms[i].serverId);
buffer.WriteInt(ref pos, _rooms[i].maxPlayers); buffer.WriteInt(ref pos, rooms[i].maxPlayers);
buffer.WriteInt(ref pos, _rooms[i].clients.Count + 1); buffer.WriteInt(ref pos, rooms[i].clients.Count + 1);
} }
} }
buffer.WriteBool(ref pos, false); buffer.WriteBool(ref pos, false);
@ -172,13 +172,13 @@ namespace LightReflectiveMirror
Room GetRoomForPlayer(int clientId) Room GetRoomForPlayer(int clientId)
{ {
for(int i = 0; i < _rooms.Count; i++) for(int i = 0; i < rooms.Count; i++)
{ {
if (_rooms[i].hostId == clientId) if (rooms[i].hostId == clientId)
return _rooms[i]; return rooms[i];
if (_rooms[i].clients.Contains(clientId)) if (rooms[i].clients.Contains(clientId))
return _rooms[i]; return rooms[i];
} }
return null; return null;
@ -188,13 +188,13 @@ namespace LightReflectiveMirror
{ {
LeaveRoom(clientId); LeaveRoom(clientId);
for(int i = 0; i < _rooms.Count; i++) for(int i = 0; i < rooms.Count; i++)
{ {
if(_rooms[i].serverId == serverId) if(rooms[i].serverId == serverId)
{ {
if(_rooms[i].clients.Count < _rooms[i].maxPlayers) if(rooms[i].clients.Count < rooms[i].maxPlayers)
{ {
_rooms[i].clients.Add(clientId); rooms[i].clients.Add(clientId);
int sendJoinPos = 0; int sendJoinPos = 0;
byte[] sendJoinBuffer = _sendBuffers.Rent(5); byte[] sendJoinBuffer = _sendBuffers.Rent(5);
@ -203,7 +203,7 @@ namespace LightReflectiveMirror
sendJoinBuffer.WriteInt(ref sendJoinPos, clientId); sendJoinBuffer.WriteInt(ref sendJoinPos, clientId);
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos)); Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
Program.transport.ServerSend(_rooms[i].hostId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos)); Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
_sendBuffers.Return(sendJoinBuffer); _sendBuffers.Return(sendJoinBuffer);
return; return;
} }
@ -236,7 +236,7 @@ namespace LightReflectiveMirror
serverId = GetRandomServerID() serverId = GetRandomServerID()
}; };
_rooms.Add(room); rooms.Add(room);
int pos = 0; int pos = 0;
byte[] sendBuffer = _sendBuffers.Rent(5); byte[] sendBuffer = _sendBuffers.Rent(5);
@ -250,28 +250,28 @@ namespace LightReflectiveMirror
void LeaveRoom(int clientId, int requiredHostId = -1) void LeaveRoom(int clientId, int requiredHostId = -1)
{ {
for(int i = 0; i < _rooms.Count; i++) for(int i = 0; i < rooms.Count; i++)
{ {
if(_rooms[i].hostId == clientId) if(rooms[i].hostId == clientId)
{ {
int pos = 0; int pos = 0;
byte[] sendBuffer = _sendBuffers.Rent(1); byte[] sendBuffer = _sendBuffers.Rent(1);
sendBuffer.WriteByte(ref pos, (byte)OpCodes.ServerLeft); sendBuffer.WriteByte(ref pos, (byte)OpCodes.ServerLeft);
for(int x = 0; x < _rooms[i].clients.Count; x++) for(int x = 0; x < rooms[i].clients.Count; x++)
Program.transport.ServerSend(_rooms[i].clients[x], 0, new ArraySegment<byte>(sendBuffer, 0, pos)); Program.transport.ServerSend(rooms[i].clients[x], 0, new ArraySegment<byte>(sendBuffer, 0, pos));
_sendBuffers.Return(sendBuffer); _sendBuffers.Return(sendBuffer);
_rooms[i].clients.Clear(); rooms[i].clients.Clear();
_rooms.RemoveAt(i); rooms.RemoveAt(i);
return; return;
} }
else else
{ {
if (requiredHostId >= 0 && _rooms[i].hostId != requiredHostId) if (requiredHostId >= 0 && rooms[i].hostId != requiredHostId)
continue; continue;
if(_rooms[i].clients.RemoveAll(x => x == clientId) > 0) if(rooms[i].clients.RemoveAll(x => x == clientId) > 0)
{ {
int pos = 0; int pos = 0;
byte[] sendBuffer = _sendBuffers.Rent(5); byte[] sendBuffer = _sendBuffers.Rent(5);
@ -279,7 +279,7 @@ namespace LightReflectiveMirror
sendBuffer.WriteByte(ref pos, (byte)OpCodes.PlayerDisconnected); sendBuffer.WriteByte(ref pos, (byte)OpCodes.PlayerDisconnected);
sendBuffer.WriteInt(ref pos, clientId); sendBuffer.WriteInt(ref pos, clientId);
Program.transport.ServerSend(_rooms[i].hostId, 0, new ArraySegment<byte>(sendBuffer, 0, pos)); Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendBuffer, 0, pos));
_sendBuffers.Return(sendBuffer); _sendBuffers.Return(sendBuffer);
} }
} }
@ -311,8 +311,8 @@ namespace LightReflectiveMirror
bool DoesServerIdExist(int id) bool DoesServerIdExist(int id)
{ {
for (int i = 0; i < _rooms.Count; i++) for (int i = 0; i < rooms.Count; i++)
if (_rooms[i].serverId == id) if (rooms[i].serverId == id)
return true; return true;
return false; return false;

View file

@ -4,7 +4,8 @@ using System.Text;
namespace LightReflectiveMirror namespace LightReflectiveMirror
{ {
class Room [Serializable]
public class Room
{ {
public int serverId; public int serverId;
public int hostId; public int hostId;