SDK/MrAG/Serverlist.cs

333 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace MrAG {
public class Serverlist {
public class GamerServicesServerlistException : Exception{
public GamerServicesServerlistException(string msg): base(msg){
}
}
public class ServerInfo {
public string Servername;
public string IP;
public string Meta;
public int Users;
public int MaxUsers;
public int Port;
}
public class Server {
public string Servername;
public int Users;
public int MaxUsers;
public int Port;
public int Timeout;
public bool Legit;
public bool Started;
public byte[] Headers = new byte[] { 1, 3, 3, 7 };
public Delegate OnIncomingConnection;
public Delegate OnFinishedConnection;
private string Meta;
private TcpListener Connection;
private MrAG.Networking.TCPClient GSServerConnection;
private double Lastupdate = 0;
public void Start() {
if (this.Started) this.Connection.Stop();
this.Started = true;
this.Connection = new TcpListener(IPAddress.Any, Port);
this.Connection.Start();
if (!this.Legit)
return;
this.Lastupdate = DateTime.Now.TimeOfDay.TotalSeconds;
this.GSServerConnection = new MrAG.Networking.TCPClient("mrag.nl", 8443);
this.GSServerConnection.Connection.Start_Send();
this.GSServerConnection.Connection.AddInt(0);
this.GSServerConnection.Connection.Finish_Send();
this.GSServerConnection.Connection.Start_Recieve();
bool canconnect = this.GSServerConnection.Connection.ReadBool();
this.GSServerConnection.Connection.Finish_Recieve();
if (canconnect) {
this.GSServerConnection.Connection.Start_Send();
this.GSServerConnection.Connection.AddBool(true);
this.GSServerConnection.Connection.Finish_Send();
} else {
throw new MrAG.Networking.GamerServicesNetworkingException("The masterserver dumped you in the ditch at the side of the road.");
}
this.GSServerConnection.Packets[0] = new Action<MrAG.Networking.Packet>(this.Packet_00); // Register
this.GSServerConnection.Packets[1] = new Action<MrAG.Networking.Packet>(this.Packet_01); // Update
this.GSServerConnection.Packets[2] = new Action<MrAG.Networking.Packet>(this.Packet_02); // Shutdown/remove
this.GSServerConnection.Packets[3] = new Action<MrAG.Networking.Packet>(this.Packet_03); // Update Playerrcount
this.GSServerConnection.Packets[4] = new Action<MrAG.Networking.Packet>(this.Packet_04); // Update Meta
this.GSServerConnection.Connection.Send(0, 0, this.Servername, this.Meta, MrAG.Gamerservices.GetIdentifier(), this.Port, this.MaxUsers);
}
public void Stop() {
this.Started = false;
this.Connection.Stop();
if (this.Legit && this.GSServerConnection.Connected) {
this.GSServerConnection.Send(2, 1);
}
}
public void Close(){
this.Stop();
if (this.GSServerConnection != null)
this.GSServerConnection.Close();
this.GSServerConnection = null;
this.Connection = null;
}
public void Update(){
if (this.Legit && this.GSServerConnection.Connected) {
this.GSServerConnection.Update();
if (Math.Abs(this.Lastupdate - DateTime.Now.TimeOfDay.TotalSeconds) > 10) {
this.GSServerConnection.Send(1, 1);
this.Lastupdate = DateTime.Now.TimeOfDay.TotalSeconds;
}
}
start:
while (Connection.Pending()) {
Networking.TCPClient c = new Networking.TCPClient(Connection.AcceptTcpClient());
c.Connection.SetTimeout(Timeout);
try {
Networking.IncomingConnection newcon = new Networking.IncomingConnection();
newcon.Connection = c;
string[] tmpipport = c.Connection.GetClient().Client.RemoteEndPoint.ToString().Split(':');
newcon.IP = tmpipport[0];
newcon.Port = uint.Parse(tmpipport[1]);
c.Connection.Start_Recieve();
foreach(byte header in this.Headers){
if (header != c.Connection.ReadByte()){
c.Connection.Start_Send();
c.Connection.AddString("Invalid Headers");
c.Connection.Finish_Send();
c.Close();
goto start;
}
}
newcon.Username = c.Connection.ReadString(64);
c.Connection.Finish_Recieve();
/*if (this.Legit) {
try {
//this.GSServerConnection.Connection.Send(0, newcon.Username);
string[] respons = Networking.PostData("serverlist", "sub=check&ip=" + newcon.IP + "&port=" + newcon.Port + "&servername=" + Servername + "&identifier=" + MrAG.Gamerservices.GetIdentifier() + "&user=" + newcon.Username);
} catch {
c.Connection.Start_Send();
c.Connection.AddBool(false);
c.Connection.AddText("Error while validating.");
c.Connection.Finish_Send();
c.Connection.Close();
goto start;
}
}*/
bool canconnect = true;
if (OnIncomingConnection != null) {
OnIncomingConnection.DynamicInvoke(newcon);
if (newcon._KickReason != null) canconnect = newcon._KickReason.Length == 0;
}
double curtime = DateTime.Now.TimeOfDay.TotalMilliseconds;
c.Connection.Start_Send();
c.Connection.AddBool(canconnect);
c.Connection.Finish_Send();
if (canconnect) {
c.Connection.Start_Recieve();
c.Connection.ReadBool();
c.Connection.Finish_Recieve();
newcon.Ping = (int)(DateTime.Now.TimeOfDay.TotalMilliseconds - curtime);
if (OnFinishedConnection != null) {
OnFinishedConnection.DynamicInvoke(newcon);
} else {
throw new Networking.GamerServicesNetworkingException("Unhandled connection.");
}
} else {
c.Connection.Start_Send();
c.Connection.AddText(newcon._KickReason);
c.Connection.Finish_Send();
c.Connection.Close();
}
newcon.FinishedConnecting = true;
} catch {
c.Connection.Close();
}
}
}
public void SetMeta(string meta) {
this.Meta = meta;
if (this.Legit)
this.GSServerConnection.Send(4, 0, this.Meta);
}
public string GetMeta() {
return this.Meta;
}
public void IncreeseUserCount() {
this.Users++;
this.GSServerConnection.Send(3, 0, this.Users);
}
public void DecreeseUserCount() {
this.Users--;
this.GSServerConnection.Send(3, 0, this.Users);
}
private void Packet_00(MrAG.Networking.Packet p) {
if (!p.ReadBool()) {
throw new MrAG.Networking.GamerServicesNetworkingException("Error while attempting to host: " + p.ReadString());
}
}
private void Packet_01(MrAG.Networking.Packet p) {
if (!p.ReadBool()) {
p.Send(0, 0, this.Servername, this.Meta, MrAG.Gamerservices.GetIdentifier(), this.Port, this.MaxUsers);
p.Send(3, 9, this.Users);
}
}
private void Packet_02(MrAG.Networking.Packet p) {
p.Send(0, 0, this.Servername, this.Meta, MrAG.Gamerservices.GetIdentifier(), this.Port, this.MaxUsers);
p.Send(3, 9, this.Users, this.MaxUsers);
}
private void Packet_03(MrAG.Networking.Packet p) {
}
private void Packet_04(MrAG.Networking.Packet p) {
}
}
public static Server Host(string servername, int port, string meta, bool show_in_serverlist) {
Server s = new Server();
s.Servername = servername;
s.Port = port;
s.SetMeta(meta);
s.Legit = show_in_serverlist;
s.Start();
return s;
}
public static void GetList(Action<List<MrAG.Serverlist.ServerInfo>> callback) {
MrAG.Gamerservices.ServerListCallback = callback;
MrAG.Gamerservices.GetAPIConnection().Send(7, 0, MrAG.Gamerservices.GetIdentifier());
}
public static MrAG.Networking.TCPClient Connect(string ip, int port) {
return Connect(ip, port, new byte[] { 1, 3, 3, 7 });
}
public static MrAG.Networking.TCPClient Connect(string ip, int port, byte[] headers) {
//if (legit){
// string[] res = MrAG.Networking.PostData("serverlist", "sub=connect&ip" + ip + "&port=" + port + "&identifier=" + MrAG.Gamerservices.GetIdentifier());
//}
MrAG.Networking.TCPClient c = new MrAG.Networking.TCPClient(ip, port);
c.Connection.Start_Send();
foreach (byte b in headers)
c.Connection.AddByte(b);
c.Connection.AddString(MrAG.Gamerservices.GetUser());
c.Connection.Finish_Send();
c.Connection.Start_Recieve();
bool canconnect = c.Connection.ReadBool();
c.Connection.Finish_Recieve();
if (canconnect) {
c.Connection.Start_Send();
c.Connection.AddBool(true);
c.Connection.Finish_Send();
} else {
c.Connection.Start_Recieve();
string reason = c.Connection.ReadString();
c.Connection.Finish_Recieve();
throw new MrAG.Networking.GamerServicesNetworkingException("Kicked: " + reason);
}
return c;
}
public static MrAG.Networking.TCPClient Connect(System.Net.Sockets.TcpClient c) {
return Connect(c, new byte[] { 1, 3, 3, 7 });
}
public static MrAG.Networking.TCPClient Connect(System.Net.Sockets.TcpClient tcpc, byte[] headers) {
//if (legit){
// string[] res = MrAG.Networking.PostData("serverlist", "sub=connect&ip" + ip + "&port=" + port + "&identifier=" + MrAG.Gamerservices.GetIdentifier());
//}
MrAG.Networking.TCPClient c = new MrAG.Networking.TCPClient(tcpc);
c.Connection.Start_Send();
foreach (byte b in headers)
c.Connection.AddByte(b);
c.Connection.AddString(MrAG.Gamerservices.GetUser());
c.Connection.Finish_Send();
c.Connection.Start_Recieve();
bool canconnect = c.Connection.ReadBool();
c.Connection.Finish_Recieve();
if (canconnect) {
c.Connection.Start_Send();
c.Connection.AddBool(true);
c.Connection.Finish_Send();
} else {
c.Connection.Start_Recieve();
string reason = c.Connection.ReadString();
c.Connection.Finish_Recieve();
throw new MrAG.Networking.GamerServicesNetworkingException("Kicked: " + reason);
}
return c;
}
}
}