333 lines
13 KiB
C#
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;
|
|
}
|
|
}
|
|
} |