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()
{
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);
}

View File

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

View File

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

View File

@ -3,20 +3,13 @@ using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Net;
namespace IW4MAdmin
{
class Program
{
static String IP;
static int Port;
static String RCON;
static public double Version = 0.9;
static public double Version = 0.91;
static public double latestVersion;
static public List<Server> Servers;
static public bool usingMemory = true;
static void Main(string[] args)
@ -30,12 +23,9 @@ namespace IW4MAdmin
else
Console.WriteLine(" Version " + Version + " (unable to retrieve latest)");
Console.WriteLine("=====================================================");
List<Server> viableServers = getServers();
#if DEBUG
if (viableServers.Count < 1)
viableServers = checkConfig(); // fall back to config
Servers = viableServers;
foreach (Server IW4M in viableServers)
@ -45,17 +35,16 @@ namespace IW4MAdmin
Thread monitorThread = new Thread(new ThreadStart(SV.Monitor));
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.");
}
IW4MAdmin_Web.WebFront frontEnd = new IW4MAdmin_Web.WebFront();
frontEnd.Init();
}
#if DEBUG
static void setupConfig()
{
bool validPort = false;
@ -77,6 +66,7 @@ namespace IW4MAdmin
file Config = new file("config\\servers.cfg", true);
Console.WriteLine("Great! Let's go ahead and start 'er up.");
}
#endif
static String checkUpdate()
{
@ -84,6 +74,7 @@ namespace IW4MAdmin
return Ver.Read();
}
#if DEBUG
static List<Server> checkConfig()
{
@ -92,7 +83,6 @@ namespace IW4MAdmin
List<Server> Servers = new List<Server>();
Config.Close();
if (SV_CONF == null || SV_CONF.Length < 1 || SV_CONF[0] == String.Empty)
{
setupConfig(); // get our first time server
@ -116,40 +106,8 @@ namespace IW4MAdmin
Servers.Add(new Server(server_line[0], newPort, server_line[2],0));
}
}
return Servers;
}
[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;
}
#endif
}
}

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

View File

@ -350,7 +350,12 @@ namespace IW4MAdmin_Web
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>");
}

View File

@ -11,7 +11,7 @@
<script type="text/javascript">
var userip;
</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>
* {
font-family: 'Robot', sans-serif;

View File

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