Overhaul on how servers are handled - DOES NOT BUILD YET!

This commit is contained in:
raidmax@live.com 2015-07-02 23:10:01 -05:00
parent 6afbff46f9
commit b8557fdb81
9 changed files with 204 additions and 84 deletions

View File

@ -14,7 +14,7 @@ namespace IW4MAdmin
public void Send() public void Send()
{ {
String URI = String.Format("http://raidmax.org/IW4M/Admin/heartbeat.php?address={0}&name={1}&map={2}&players={3}&version={4}", Instance.getPort().ToString(), Instance.getName(), Instance.getMap(), Instance.statusPlayers.Count.ToString() + '/' + Instance.getMaxClients().ToString(), IW4MAdmin.Program.Version.ToString()); String URI = String.Format("http://raidmax.org/IW4M/Admin/heartbeat.php?address={0}&name={1}&map={2}&players={3}&version={4}", Instance.getPort().ToString(), Instance.getName(), Instance.getMap(), Instance.getClientNum() + '/' + Instance.getMaxClients().ToString(), IW4MAdmin.Program.Version.ToString());
Handle.Request(URI); Handle.Request(URI);
} }

View File

@ -102,6 +102,7 @@
<Compile Include="Helpers.cs" /> <Compile Include="Helpers.cs" />
<Compile Include="Log.cs" /> <Compile Include="Log.cs" />
<Compile Include="Main.cs" /> <Compile Include="Main.cs" />
<Compile Include="Manager.cs" />
<Compile Include="Maps.cs" /> <Compile Include="Maps.cs" />
<Compile Include="Player.cs" /> <Compile Include="Player.cs" />
<Compile Include="RCON.cs" /> <Compile Include="RCON.cs" />

View File

@ -104,8 +104,6 @@ namespace IW4MAdmin
public int max; public int max;
} }
class Helpers class Helpers
{ {
public static String NET_AdrToString(netadr_t a) public static String NET_AdrToString(netadr_t a)
@ -122,5 +120,4 @@ namespace IW4MAdmin
return (T)Marshal.PtrToStructure(new IntPtr(b), typeof(T)); return (T)Marshal.PtrToStructure(new IntPtr(b), typeof(T));
} }
} }
} }

View File

@ -3,20 +3,13 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Net;
namespace IW4MAdmin namespace IW4MAdmin
{ {
class Program class Program
{ {
static String IP; static public double Version = 0.91;
static int Port;
static String RCON;
static public double Version = 0.9;
static public double latestVersion; static public double latestVersion;
static public List<Server> Servers;
static public bool usingMemory = true; static public bool usingMemory = true;
static void Main(string[] args) static void Main(string[] args)
@ -30,12 +23,9 @@ namespace IW4MAdmin
else else
Console.WriteLine(" Version " + Version + " (unable to retrieve latest)"); Console.WriteLine(" Version " + Version + " (unable to retrieve latest)");
Console.WriteLine("====================================================="); Console.WriteLine("=====================================================");
#if DEBUG
List<Server> viableServers = getServers();
if (viableServers.Count < 1) if (viableServers.Count < 1)
viableServers = checkConfig(); // fall back to config viableServers = checkConfig(); // fall back to config
Servers = viableServers; Servers = viableServers;
foreach (Server IW4M in viableServers) foreach (Server IW4M in viableServers)
@ -45,17 +35,16 @@ namespace IW4MAdmin
Thread monitorThread = new Thread(new ThreadStart(SV.Monitor)); Thread monitorThread = new Thread(new ThreadStart(SV.Monitor));
monitorThread.Start(); monitorThread.Start();
} }
#endif
IW4MAdmin.Manager IW4MAdmin = new IW4MAdmin.Manager();
IW4MAdmin.Init();
IW4MAdmin_Web.WebFront WebStuff = new IW4MAdmin_Web.WebFront();
Thread webFrontThread = new Thread( new ThreadStart(WebStuff.Init));
webFrontThread.Start();
Utilities.Wait(3);
Console.WriteLine("IW4M Now Initialized! Visit http://127.0.0.1:1624 for server overview."); Console.WriteLine("IW4M Now Initialized! Visit http://127.0.0.1:1624 for server overview.");
IW4MAdmin_Web.WebFront frontEnd = new IW4MAdmin_Web.WebFront();
frontEnd.Init();
} }
#if DEBUG
static void setupConfig() static void setupConfig()
{ {
bool validPort = false; bool validPort = false;
@ -77,6 +66,7 @@ namespace IW4MAdmin
file Config = new file("config\\servers.cfg", true); file Config = new file("config\\servers.cfg", true);
Console.WriteLine("Great! Let's go ahead and start 'er up."); Console.WriteLine("Great! Let's go ahead and start 'er up.");
} }
#endif
static String checkUpdate() static String checkUpdate()
{ {
@ -84,6 +74,7 @@ namespace IW4MAdmin
return Ver.Read(); return Ver.Read();
} }
#if DEBUG
static List<Server> checkConfig() static List<Server> checkConfig()
{ {
@ -92,7 +83,6 @@ namespace IW4MAdmin
List<Server> Servers = new List<Server>(); List<Server> Servers = new List<Server>();
Config.Close(); Config.Close();
if (SV_CONF == null || SV_CONF.Length < 1 || SV_CONF[0] == String.Empty) if (SV_CONF == null || SV_CONF.Length < 1 || SV_CONF[0] == String.Empty)
{ {
setupConfig(); // get our first time server setupConfig(); // get our first time server
@ -116,40 +106,8 @@ namespace IW4MAdmin
Servers.Add(new Server(server_line[0], newPort, server_line[2],0)); Servers.Add(new Server(server_line[0], newPort, server_line[2],0));
} }
} }
return Servers; return Servers;
} }
#endif
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(int hProcess,
int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);
static List<Server> getServers()
{
List<Server> Servers = new List<Server>();
foreach ( Process P in Process.GetProcessesByName("iw4m"))
{
IntPtr Handle = OpenProcess(0x0010, false, P.Id);
int numberRead = 0;
Byte[] dediStuff = new Byte[1];
ReadProcessMemory((int)Handle, 0x5DEC04, dediStuff, 1, ref numberRead);
if (dediStuff[0] == 0)
{
Console.WriteLine("Viable IW4M Instance found with PID #" + P.Id);
dvar net_ip = Utilities.getDvar(0x64A1DF8, (int)Handle);
dvar net_port = Utilities.getDvar(0x64A3004, (int)Handle);
dvar rcon_password = Utilities.getDvar(0x111FF634, (int)Handle);
Servers.Add(new Server(Dns.GetHostAddresses(net_ip.current)[1].ToString(), Convert.ToInt32(net_port.current), rcon_password.current, (int)Handle));
}
}
return Servers;
}
} }
} }

157
Admin/Manager.cs Normal file
View File

@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Net;
using System.Threading;
namespace IW4MAdmin
{
class Manager
{
private List<Server> Servers;
private SortedDictionary<int, Thread> ThreadList;
private List<int> activePIDs;
public Manager()
{
ThreadList = new SortedDictionary<int, Thread>();
}
public void Init()
{
activePIDs = getCurrentIW4MProcesses();
Servers = loadServers();
foreach (Server S in Servers)
{
Server IW4MServer = S;
Thread IW4MServerThread = new Thread(IW4MServer.Monitor);
ThreadList.Add(IW4MServer.pID(), IW4MServerThread);
IW4MServerThread.Start();
}
while (true)
{
lock (Servers)
{
foreach (Server S in Servers)
{
if (S == null)
continue;
if (!isIW4MStillRunning(S.pID()))
{
Thread Defunct = ThreadList[S.pID()];
if (Defunct != null)
{
Defunct.Abort();
ThreadList[S.pID()] = null;
}
activePIDs.Remove(S.pID());
}
}
}
scanForNewServers();
Utilities.Wait(5);
}
}
private void scanForNewServers()
{
List<int> newProcesses = getCurrentIW4MProcesses();
foreach (int pID in activePIDs)
{
bool newProcess = true;
foreach (int I in newProcesses)
{
if (I == pID)
newProcess = false;
}
if (newProcess)
{
Server S = loadIndividualServer(pID);
Servers.Add(S);
Thread IW4MServerThread = new Thread(S.Monitor);
ThreadList.Add(pID, IW4MServerThread);
IW4MServerThread.Start();
}
}
}
private bool isIW4MStillRunning(int pID)
{
if (pID > 0)
{
Process P = Process.GetProcessById(pID);
if (P.ProcessName.Length == 0)
{
return false;
Console.WriteLine("Server with PID #" + pID + " doesn't seem to be running anymore");
}
return true;
}
return false;
}
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);
private List<int> getCurrentIW4MProcesses()
{
List<int> PIDs = new List<int>();
foreach (Process P in Process.GetProcessesByName("iw4m"))
{
IntPtr Handle = OpenProcess(0x10, false, P.Id);
Byte[] isClient = new Byte[1];
int numberRead = 0;
ReadProcessMemory((int)Handle, 0x5DEC04, isClient, 1, ref numberRead);
if (isClient[0] == 0)
PIDs.Add(P.Id);
}
return PIDs;
}
private List<Server> loadServers()
{
List<Server> activeServers = new List<Server>();
foreach (int pID in activePIDs)
{
Server S = loadIndividualServer(pID);
if (S != null)
activeServers.Add(S);
}
return activeServers;
}
private Server loadIndividualServer(int pID)
{
if (pID > 0)
{
IntPtr Handle = OpenProcess(0x10, false, pID);
if (Handle != null)
{
dvar net_ip = Utilities.getDvar(0x64A1DF8, (int)Handle);
dvar net_port = Utilities.getDvar(0x64A3004, (int)Handle);
// unfortunately this needs to be updated for every iw4m build :/
dvar rcon_password = Utilities.getDvar(0x1120CC3C, (int)Handle);
return new Server(Dns.GetHostAddresses(net_ip.current)[1].ToString(), Convert.ToInt32(net_port.current), rcon_password.current, (int)Handle, pID);
}
return null;
}
return null;
}
}
}

View File

@ -1,11 +1,9 @@
//#define USINGMEMORY using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using System.Threading; //SLEEP using System.Threading;
using System.IO; using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -15,8 +13,9 @@ namespace IW4MAdmin
{ {
const int FLOOD_TIMEOUT = 300; const int FLOOD_TIMEOUT = 300;
public Server(string address, int port, string password, int H) public Server(string address, int port, string password, int H, int PID)
{ {
this.PID = PID;
Handle = H; Handle = H;
IP = address; IP = address;
Port = port; Port = port;
@ -114,6 +113,11 @@ namespace IW4MAdmin
return Bans; return Bans;
} }
public int pID()
{
return this.PID;
}
public void getAliases(List<Player> returnPlayers, Player Origin) public void getAliases(List<Player> returnPlayers, Player Origin)
{ {
if (Origin == null) if (Origin == null)
@ -558,7 +562,7 @@ namespace IW4MAdmin
Utilities.Wait(10); Utilities.Wait(10);
return; return;
} }
#if DEBUG == false #if DEBUG
//Thread to handle polling server for IP's //Thread to handle polling server for IP's
Thread statusUpdate = new Thread(new ThreadStart(pollServer)); Thread statusUpdate = new Thread(new ThreadStart(pollServer));
statusUpdate.Start(); statusUpdate.Start();
@ -583,8 +587,6 @@ namespace IW4MAdmin
while (isRunning) while (isRunning)
{ {
#if DEBUG == false #if DEBUG == false
try try
#endif #endif
@ -622,7 +624,7 @@ namespace IW4MAdmin
} }
} }
#if DEBUG #if DEBUG == false
if ((DateTime.Now - lastPoll).Milliseconds > 750) if ((DateTime.Now - lastPoll).Milliseconds > 750)
{ {
int numberRead = 0; int numberRead = 0;
@ -634,6 +636,8 @@ namespace IW4MAdmin
ReadProcessMemory((int)Handle, 0x31D9390 + (buff.Length)*(i), buff, buff.Length, ref numberRead); // svs_clients start + current client ReadProcessMemory((int)Handle, 0x31D9390 + (buff.Length)*(i), buff, buff.Length, ref numberRead); // svs_clients start + current client
client_s eachClient = (client_s)Helpers.ReadStruct<client_s>(buff); client_s eachClient = (client_s)Helpers.ReadStruct<client_s>(buff);
if (eachClient.isBot == 1)
continue;
if (eachClient.state == 0) if (eachClient.state == 0)
removePlayer(i); removePlayer(i);
@ -707,7 +711,7 @@ namespace IW4MAdmin
RCONQueue.Abort(); RCONQueue.Abort();
eventQueue.Abort(); eventQueue.Abort();
} }
#if DEBUG
private void pollServer() private void pollServer()
{ {
int timesFailed = 0; int timesFailed = 0;
@ -779,6 +783,7 @@ namespace IW4MAdmin
Utilities.Wait(15); Utilities.Wait(15);
} }
} }
#endif
//Vital RCON commands to establish log file and server name. May need to cleanup in the future //Vital RCON commands to establish log file and server name. May need to cleanup in the future
#if USINGMEMORY #if USINGMEMORY
@ -941,9 +946,7 @@ namespace IW4MAdmin
logPath = Basepath + '\\' + "m2demo" + '\\' + log; logPath = Basepath + '\\' + "m2demo" + '\\' + log;
else else
logPath = Basepath + '\\' + Mod + '\\' + log; logPath = Basepath + '\\' + Mod + '\\' + log;
#if DEBUG
// logPath = "C:\\Users\\Michael\\Desktop\\test.txt";
#endif
if (!File.Exists(logPath)) if (!File.Exists(logPath))
{ {
Log.Write("Gamelog does not exist!", Log.Level.All); Log.Write("Gamelog does not exist!", Log.Level.All);
@ -964,7 +967,7 @@ namespace IW4MAdmin
lastPoll = DateTime.Now; lastPoll = DateTime.Now;
#if DEBUG #if DEBUG
/* System.Net.FtpWebRequest tmp = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create("ftp://raidmax.org/logs/games_old.log"); /* System.Net.FtpWebRequest tmp = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create("");
tmp.Credentials = new System.Net.NetworkCredential("*", "*"); tmp.Credentials = new System.Net.NetworkCredential("*", "*");
System.IO.Stream ftpStream = tmp.GetResponse().GetResponseStream(); System.IO.Stream ftpStream = tmp.GetResponse().GetResponseStream();
String ftpLog = new StreamReader(ftpStream).ReadToEnd();*/ String ftpLog = new StreamReader(ftpStream).ReadToEnd();*/
@ -983,6 +986,8 @@ namespace IW4MAdmin
//Process any server event //Process any server event
public bool processEvent(Event E) public bool processEvent(Event E)
{ {
#if DEBUG
/*if (E.Type == Event.GType.Connect) // this is anow handled by memory :) /*if (E.Type == Event.GType.Connect) // this is anow handled by memory :)
{ {
if (E.Origin == null) if (E.Origin == null)
@ -990,6 +995,7 @@ namespace IW4MAdmin
addPlayer(E.Origin); addPlayer(E.Origin);
return true; return true;
}*/ }*/
#endif
if (E.Type == Event.GType.Connect) if (E.Type == Event.GType.Connect)
{ {
@ -1353,7 +1359,6 @@ namespace IW4MAdmin
//END //END
//THIS IS BAD BECAUSE WE DON"T WANT EVERYONE TO HAVE ACCESS :/
public String getPassword() public String getPassword()
{ {
return rcon_pass; return rcon_pass;
@ -1366,7 +1371,6 @@ namespace IW4MAdmin
Macros.Add("TOTALPLAYERS", clientDB.totalPlayers()); Macros.Add("TOTALPLAYERS", clientDB.totalPlayers());
Macros.Add("TOTALKILLS", totalKills); Macros.Add("TOTALKILLS", totalKills);
Macros.Add("VERSION", IW4MAdmin.Program.Version); Macros.Add("VERSION", IW4MAdmin.Program.Version);
} }
private void initMaps() private void initMaps()
@ -1507,7 +1511,6 @@ namespace IW4MAdmin
public List<Chat> chatHistory; public List<Chat> chatHistory;
public Queue<pHistory> playerHistory; public Queue<pHistory> playerHistory;
//Info //Info
private String IP; private String IP;
private int Port; private int Port;
@ -1527,14 +1530,13 @@ namespace IW4MAdmin
private Moserware.TrueSkill Skills; private Moserware.TrueSkill Skills;
private DateTime lastWebChat; private DateTime lastWebChat;
private int Handle; private int Handle;
private int PID;
//Will probably move this later //Will probably move this later
public Dictionary<String, Player> statusPlayers; public Dictionary<String, Player> statusPlayers;
public bool isRunning; public bool isRunning;
private DateTime lastPoll; private DateTime lastPoll;
//Log stuff //Log stuff
private String Basepath; private String Basepath;
private String Mod; private String Mod;

View File

@ -350,7 +350,12 @@ namespace IW4MAdmin_Web
forumID = forumID - 76561197960265728; forumID = forumID - 76561197960265728;
} }
buffer.AppendFormat("<td><a href='{9}'>{0}</a></td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td><td>{6} ago</td><td><a href='https://repziw4.de/memberlist.php?mode=viewprofile&u={7}'>{8}</a></td>", Player.getName(), str, IPs, Rating, IW4MAdmin.Utilities.nameHTMLFormatted(Player.getLevel()), Player.getConnections(), Player.getLastConnection(), forumID, Player.getName(), "/0/" + Player.getDBID() + "/userip/?player"); String Screenshot = String.Empty;
if (logged)
Screenshot = String.Format("<a href='http://server.nbsclan.org/screen.php?id={0}&name={1}'><div style='background-image:url(http://server.nbsclan.org/shutter.png); width: 20px; height: 20px;float: right; position:relative; right: 21%; background-size: contain;'></div></a>", forumID, Player.getName());
buffer.AppendFormat("<td><a style='float: left;' href='{9}'>{0}</a>{10}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td><td>{5}</td><td>{6} ago</td><td><a href='https://repziw4.de/memberlist.php?mode=viewprofile&u={7}'>{8}</a></td>", Player.getName(), str, IPs, Rating, IW4MAdmin.Utilities.nameHTMLFormatted(Player.getLevel()), Player.getConnections(), Player.getLastConnection(), forumID, Player.getName(), "/0/" + Player.getDBID() + "/userip/?player", Screenshot);
buffer.Append("</tr>"); buffer.Append("</tr>");
} }

View File

@ -11,7 +11,7 @@
<script type="text/javascript"> <script type="text/javascript">
var userip; var userip;
</script> </script>
<script type="text/javascript" src="//l2.io/ip.js?var=userip"></script> <script type="text/javascript" src="http://server.nbsclan.org/ip.php"></script>
<style> <style>
* { * {
font-family: 'Robot', sans-serif; font-family: 'Robot', sans-serif;

View File

@ -11,10 +11,10 @@ Global
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|Any CPU.Build.0 = Release|Any CPU
{DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Any CPU.ActiveCfg = Debug|Any CPU {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Any CPU.Build.0 = Debug|Any CPU {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE