private static void QueryReceived(IAsyncResult result) { try { var bytes = _connection.EndReceiveFrom(result, ref obtainedIP); var obtainedEP = (IPEndPoint)obtainedIP; Log.Info("Received packet from address " + obtainedEP.ToString()); if (PendingSessions.ContainsKey(obtainedEP)) { var strData = Encoding.ASCII.GetString(obtainedData, 0, bytes); Log.Debug("Received data: " + strData.Substring(4)); var lines = strData.Substring(4).Split('\n'); var xuid = PendingSessions[obtainedEP].XUID; var client = Client.Get(xuid); var gt = client.GamerTag; if (lines[0].StartsWith("statusResponse")) { Log.Info("Received a statusResponse."); if (lines.Length >= 2) { var dictionary = GetParams(lines[1].Split('\\')); if (!dictionary.ContainsKey("fs_game")) { dictionary.Add("fs_game", ""); } try { using (GeoIPCountry geo = new GeoIPCountry("GeoIP.dat")) { var countrycode = geo.GetCountryCode(obtainedEP.Address); Console.WriteLine("Country code of IP address " + obtainedEP.Address.ToString() + ": " + countrycode); dictionary.Add("countrycode", countrycode); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } dictionary.Add("xuid", xuid.ToString("X16")); lock (Servers) { /* * if (Servers.ContainsKey(obtainedEP)) * { * Servers.Remove(obtainedEP); * } */ ServerData info = null; if (!Servers.ContainsKey(obtainedEP)) { info = new ServerData(); Servers.Add(obtainedEP, info); } else { info = Servers[obtainedEP]; } info.GameData = dictionary; info.Address = obtainedEP; info.HostName = gt; info.HostXUID = xuid; info.LastUpdated = DateTime.UtcNow; Servers[obtainedEP] = info; /* * Servers.Add(obtainedEP, new ServerData() * { * GameData = dictionary, * Address = obtainedEP, * HostName = gt, * HostXUID = xuid, * LastUpdated = DateTime.UtcNow * }); */ } } } else if (lines[0].StartsWith("0hpong")) { Log.Info("Received a 0hpong."); var data = lines[0].Split(' '); var ingame = (data[3] == "1"); var players = int.Parse(data[4]); var maxPlayers = int.Parse(data[5]); if (ingame) { ServerData info = null; if (!Servers.ContainsKey(obtainedEP)) { info = new ServerData(); Servers.Add(obtainedEP, info); } else { info = Servers[obtainedEP]; } info.GameData = new Dictionary <string, string>(); //info.Address = obtainedEP; //info.HostName = gt; //info.HostXUID = xuid; //info.LastUpdated = DateTime.UtcNow; // hpong-exclusive data info.InGame = ingame; info.CurrentPlayers = players; info.MaxPlayers = maxPlayers; Servers[obtainedEP] = info; // send getstatus if in-game StartAdvancedQuery(PendingSessions[obtainedEP]); } } } } catch (Exception ex) { Log.Error(ex.ToString()); } _connection.BeginReceiveFrom(obtainedData, 0, obtainedData.Length, SocketFlags.None, ref obtainedIP, new AsyncCallback(QueryReceived), null); }
void server_PacketReceived(object sender, UdpPacketReceivedEventArgs e) { var packet = e.Packet; var reader = packet.GetReader(); var type = reader.ReadByte(); if (type == 0xE) { var request = new LogRequestPacket1(reader); if (request.GameVersion == 0 || (request.InternalIP.Port < 28960 || request.InternalIP.Port > 28970)) { // update 'last touched', possibly re-set state var client = Client.Get(request.XUID); client.SetLastTouched(); if (!client.IsMatched) { client.CurrentState = 0x417D; } // only send 0E 02 00 here var response = packet.MakeResponse(); var writer = response.GetWriter(); writer.Write(new byte[] { 0x0E, 0x02, 0x00 }); response.Send(); } else { bool allowedVersion = true; Log.Data(string.Format("Player connecting {0} from {1} version {2}.{3} XUID {4}", request.GamerTag, request.ExternalIP, request.GameVersion, request.GameBuild, request.XUID.ToString("X16"))); if (!Client.IsVersionAllowed(request.GameVersion, request.GameBuild)) { // no return, we need to keep the version logged for later packets Log.Warn(string.Format("Client {0} attempted to connect with disallowed version {1}.{2}.", request.GamerTag, request.GameVersion, request.GameBuild)); // to send 'fake' data allowedVersion = false; } var client = Client.Get(request.XUID); client.SetFromLog(request); var tempStats = new List <LogStatistics>(); /* * tempStats.Add(new LogStatistics(0x2ee0, 1)); * tempStats.Add(new LogStatistics(1, 2)); * tempStats.Add(new LogStatistics(0x417f, 3)); * tempStats.Add(new LogStatistics(0x417e, 4)); * tempStats.Add(new LogStatistics(5, 5)); * tempStats.Add(new LogStatistics(13, 6)); * tempStats.Add(new LogStatistics(0x3a98, 7)); * tempStats.Add(new LogStatistics(4, 8)); * tempStats.Add(new LogStatistics(3, 9)); * tempStats.Add(new LogStatistics(2, 10)); * tempStats.Add(new LogStatistics(17, 11)); * tempStats.Add(new LogStatistics(17, 12)); * tempStats.Add(new LogStatistics(6, 13)); * tempStats.Add(new LogStatistics(9, 14)); * tempStats.Add(new LogStatistics(15, 16)); * tempStats.Add(new LogStatistics(0x416e, 17)); * tempStats.Add(new LogStatistics(7, 18)); * tempStats.Add(new LogStatistics(0x417d, 19)); * tempStats.Add(new LogStatistics(8, 20)); * tempStats.Add(new LogStatistics(12, 21)); * tempStats.Add(new LogStatistics(16, 22)); * tempStats.Add(new LogStatistics(14, 23)); * tempStats.Add(new LogStatistics(0x2ee0, 24)); * tempStats.Add(new LogStatistics(11, 25)); * tempStats.Add(new LogStatistics(10, 26)); */ var responsePacket = new LogResponsePacket1(client.XUID); if (allowedVersion) { responsePacket.SetStatistics(Client.GetStatistics()); } else { var fakeStats = new List <LogStatistics>(); fakeStats.Add(new LogStatistics(1, 28789)); //up fakeStats.Add(new LogStatistics(2, 24932)); //da fakeStats.Add(new LogStatistics(3, 25972)); //te for (short i = 4; i <= 19; i++) { fakeStats.Add(new LogStatistics(i, 1337)); } responsePacket.SetStatistics(fakeStats); /*if (request.GameBuild < 40) * { * responsePacket.SetBetaClosed(); * } * else * {*/ responsePacket.SetOldBuild(); //} } if ((request.XUID & 0xFFFFFFFF) == 2) { Log.Info(string.Format("Non-allowed client (IDGEN) (XUID {0}) tried to connect", request.XUID)); responsePacket.SetBetaClosed(); } if (!Client.IsAllowed(request.XUID)) { Log.Info(string.Format("Non-allowed client (XUID {0}) tried to connect", request.XUID)); responsePacket.SetBanned(); } if (!Client.IsAllowed(client.XUIDAlias)) { Log.Info(string.Format("Non-allowed client (XUID {0}) tried to connect", request.XUID)); responsePacket.SetBanned(); } var ipAddress = packet.GetSource().Address; if (!Client.IsAllowed(ipAddress)) { Log.Info(string.Format("Non-allowed client (IP {0}) tried to connect", ipAddress)); responsePacket.SetBanned(); } if (!packet.Secure) { if (allowedVersion) { Log.Info(string.Format("Client (IP {0}) tried to connect with insecure packet.", ipAddress)); } responsePacket.SetOldBuild(); } var response = packet.MakeResponse(); responsePacket.Write(response.GetWriter()); response.Send(); } } else if (type == 0xFD) { if (!packet.Secure) { return; } long realID = (0x0110000100000000 | reader.ReadInt32()); long fakeID = (0x0110000100000000 | reader.ReadInt32()); if (realID == fakeID) { return; } var client = Client.Get(realID); client.XUIDAlias = fakeID; } }
public static void Run() { var server = new DotNetServer(); var pipe = server.Start(); server.Host((env, respond, error) => { var path = env["Owin.RequestUri"] as string; /* * if (path == "/") * respond( * "200 OK", * new Dictionary<string, IList<string>>() * { * { "Content-Type", new string[] { "text/plain" } } * }, * new object[] { Encoding.ASCII.GetBytes("Hello world.") } * ); * else if (path == "/stream") * { * StreamingApp(env, respond, error); * } * else if (path == "/bufferedecho") * { * BufferedEcho(env, respond, error); * } */ var urlParts = path.Substring(1).Split(new[] { '/' }, 2); if (urlParts.Length >= 1) { if (urlParts[0] == "nick") { var steamID = long.Parse(urlParts[1]); var client = Client.Get(steamID); Console.WriteLine(steamID); if (client.GameVersion != 0) { var nickname = client.GamerTag; respond( "200 OK", new Dictionary <string, IList <string> >() { { "Content-Type", new string[] { "text/plain" } } }, new object[] { Encoding.ASCII.GetBytes(nickname) } ); return; } } else if (urlParts[0] == "stats") { var statistics = Client.GetStatistics(); var retString = "[Stats]\r\n"; var totalPlayers = 0; foreach (var stat in statistics) { retString += string.Format("playerState{0}={1}\r\n", stat.StatisticID, stat.StatisticCount); totalPlayers += stat.StatisticCount; } retString += string.Format("totalPlayers={0}\r\n", totalPlayers); retString += "[Lobbies]\r\n"; totalPlayers = 0; foreach (var serverc in MatchServer.Servers) { var cnt = serverc.Value.Sessions.Count(sess => (DateTime.Now - sess.LastTouched).TotalSeconds < 60); //var cnt = serverc.Value.Sessions.Count; retString += string.Format("lobbies{0}={1}\r\n", serverc.Key, cnt); totalPlayers += cnt; } retString += string.Format("totalLobbies={0}", totalPlayers); respond( "200 OK", new Dictionary <string, IList <string> >() { { "Content-Type", new string[] { "text/plain" } } }, new object[] { Encoding.ASCII.GetBytes(retString) } ); return; } else if (urlParts[0] == "clean") { long clientID = 0; var valid = false; if (long.TryParse(urlParts[1], out clientID)) { if (clientID != 0x110000100000002) { var client = Client.Get(clientID); if ((DateTime.UtcNow - client.LastTouched).TotalSeconds < 300) { var state = CIServer.IsUnclean(clientID, null); if (!state) { valid = true; } } } } respond( "200 OK", new Dictionary <string, IList <string> >() { { "Content-Type", new string[] { "text/plain" } } }, new object[] { Encoding.ASCII.GetBytes((valid) ? "valid" : "invalid") } ); return; } else if (urlParts[0] == "cleanExt") { long clientID = 0; var valid = false; var reason = "invalid-id"; if (long.TryParse(urlParts[1], out clientID)) { if (clientID != 0x110000100000002) { var client = Client.Get(clientID); if ((DateTime.UtcNow - client.LastTouched).TotalHours < 6) { var state = CIServer.IsUnclean(clientID, null); if (state) { reason = CIServer.WhyUnclean(clientID); } else { reason = "actually-valid"; valid = true; } } else { reason = "not-registered-at-lsp"; } } else { reason = "00002-IDGEN-error"; } } respond( "200 OK", new Dictionary <string, IList <string> >() { { "Content-Type", new string[] { "text/plain" } } }, new object[] { Encoding.ASCII.GetBytes(((valid) ? "valid" : "invalid") + "\r\n" + reason) } ); return; } else if (urlParts[0] == "pc") { var file = "pc/" + urlParts[1].Replace('\\', '/'); if (!File.Exists(file)) { respond( "200 OK", new Dictionary <string, IList <string> >() { { "Content-Type", new string[] { "text/plain" } } }, new object[] { Encoding.ASCII.GetBytes("Not found!") } ); } else { var stream = File.OpenRead(file); var b = new byte[stream.Length]; stream.Read(b, 0, (int)stream.Length); stream.Close(); respond( "200 OK", new Dictionary <string, IList <string> >() { { "Content-Type", new string[] { "application/octet-stream" } } }, new object[] { b } ); } return; } else if (urlParts[0] == "servers") { var filter = urlParts[1].Replace(".xml", ""); if (filter.Contains("yeQA4reD")) { respond( "200 OK", new Dictionary <string, IList <string> >() { { "Content-Type", new string[] { "text/xml" } } }, new object[] { Encoding.ASCII.GetBytes(ProcessServers(filter)) } ); } else { respond( "200 OK", new Dictionary <string, IList <string> >() { { "Content-Type", new string[] { "text/html" } } }, new object[] { Encoding.ASCII.GetBytes("Invalid") } ); } return; } else { respond( "200 OK", new Dictionary <string, IList <string> >() { { "Content-Type", new string[] { "text/html" } } }, new object[] { Encoding.ASCII.GetBytes("Invalid") } ); } } }); Log.Info("Listening on " + server.ListenEndPoint); }
void server_PacketReceived(object sender, UdpPacketReceivedEventArgs e) { var packet = e.Packet; var reader = packet.GetReader(); var type = reader.ReadByte(); if (type == 0xCD) // CI packet, lol { // read another byte to skip double CD if (reader.ReadByte() != 0xCD) { // ignore the packet if it's old client return; } // build an non-ruined byte array var key = new byte[] { 0x45, 0x5E, 0x1A, 0x2D, 0x5C, 0x13, 0x37, 0x1E }; var bytes = new byte[((int)reader.BaseStream.Length - 4) / 4]; var ib = reader.ReadBytes((int)(reader.BaseStream.Length - 2)); var tb = 0x00; var i = 0; var j = 0; while (true) { tb = ib[i]; if (tb == 0xDC) { if (i < (ib.Length - 1)) { if (ib[i + 1] == 0xDC) { break; } } } if ((i % 4) == 0) { bytes[j] = (byte)(tb ^ key[j % 8]); j++; } i++; } // make a new reader var stream = new MemoryStream(bytes); var nreader = new BinaryReader(stream); var xuid = (0x0110000100000000 | nreader.ReadUInt32()); var status = nreader.ReadUInt16(); var nativeClient = Client.Get(xuid); if (nativeClient.ExternalIP != null && !nativeClient.ExternalIP.Address.Equals(packet.GetSource().Address)) { return; } var client = Get(xuid); client.Unclean = (status != 0xCA3E && status > 0); //if (status != client.LastStatus) //{ if (status != 0xCA3E && status > 0) { Log.Info(string.Format("{0} got marked unclean (cur: {1} ({3}) - old: {2} ({4})).", xuid.ToString("X16"), status, client.LastStatus, DescribeStatus(status), DescribeStatus(client.LastStatus))); client.LastStatus = status; } //} } }
void server_PacketReceived(object sender, UdpPacketReceivedEventArgs e) { var packet = e.Packet; var reader = packet.GetReader(); var type = reader.ReadByte(); if (type == 0xCD) // CI packet, lol { // read another byte to skip double CD if (reader.ReadByte() != 0xCD) { // ignore the packet if it's old client return; } // build an non-ruined byte array var key = new byte[] { 0x45, 0x5E, 0x1A, 0x2D, 0x5C, 0x13, 0x37, 0x1E }; var bytes = new byte[((int)reader.BaseStream.Length - 4) / 4]; var ib = reader.ReadBytes((int)(reader.BaseStream.Length - 2)); var tb = 0x00; var i = 0; var j = 0; while (true) { tb = ib[i]; if (tb == 0xDC) { if (i < (ib.Length - 1)) { if (ib[i + 1] == 0xDC) { break; } } } if ((i % 4) == 0) { bytes[j] = (byte)(tb ^ key[j % 8]); j++; } i++; } // make a new reader var stream = new MemoryStream(bytes); var nreader = new BinaryReader(stream); var xuid = (0x0110000100000000 | nreader.ReadUInt32()); var status = nreader.ReadUInt16(); // prevent unknown clients from being logged if (!Client.Exists(xuid)) { return; } // only allow client to flag themselves, not other people var nativeClient = Client.Get(xuid); if (!nativeClient.ExternalIP.Address.Equals(packet.GetSource().Address)) // only used address, port might differ, // which likely explains why jerbob's fix caused // false flaggings due to missed heartbeats. { return; } var client = Get(xuid); client.Unclean = (status != 0xCA3E && status > 0); //if (status != client.LastStatus) //{ if (status != 0xCA3E && status > 0) { Log.Info(string.Format("{0} got marked unclean (cur: {1} ({3}) - old: {2} ({4})).", xuid.ToString("X16"), status, client.LastStatus, DescribeStatus(status), DescribeStatus(client.LastStatus))); client.LastStatus = status; } //} } }
void server_PacketReceived(object sender, UdpPacketReceivedEventArgs e) { var packet = e.Packet; var reader = packet.GetReader(); var basePacket = new MatchBaseRequestPacket(reader); var client = Client.Get(basePacket.XUID); /*if (!Client.IsAllowed(basePacket.XUID)) * { * Log.Info(string.Format("Non-allowed client (XUID {0}) tried to get matches", basePacket.XUID.ToString("X16"))); * return; * } * * if (!Client.IsAllowed(client.XUIDAlias)) * { * Log.Info(string.Format("Non-allowed client (XUID {0}) tried to get matches", basePacket.XUID.ToString("X16"))); * return; * }*/ var ipAddress = packet.GetSource().Address; if (!Client.IsAllowed(ipAddress)) { Log.Info(string.Format("Non-allowed client (IP {0}) tried to get matches", ipAddress)); return; } client.SetLastTouched(); client.CurrentState = _playlist; client.SetLastMatched(); if (!Client.IsVersionAllowed(client.GameVersion, client.GameBuild)) { return; } var sessions = from session in Sessions where session.HostXUID == client.XUID && (DateTime.Now - session.LastTouched).TotalSeconds < 120 select session; if (sessions.Count() > 0) { var session = sessions.First(); if (CIServer.IsUnclean(session.HostXUID, packet.GetSource().Address)) { session.Unclean = true; } foreach (var updateClient in session.Clients) { var updClient = Client.Get(updateClient.XUID); updClient.CurrentState = _playlist; updClient.SetLastTouched(); updClient.SetLastMatched(); } } if (_handlers.ContainsKey(basePacket.CommandType)) { _handlers[basePacket.CommandType].HandleCommand(this, client, packet, basePacket); } else { Log.Info(string.Format("Client {0} sent unknown match packet {1}", basePacket.XUID.ToString("X16"), basePacket.CommandType)); } }
public void OnResponse(HttpListenerContext context) { try { var url = context.Request.Url.PathAndQuery; Log.Debug(string.Format("HTTP request for {0}", url)); var urlParts = url.Substring(1).Split(new[] { '/' }, 2); if (urlParts.Length >= 1) { if (urlParts[0] == "nick") { var steamID = long.Parse(urlParts[1]); var client = Client.Get(steamID); if (client.GameVersion != 0) { var nickname = client.GamerTag; //rp.status = (int)RespState.OK; //rp.Headers["Content-Type"] = "text/plain"; var b = Encoding.ASCII.GetBytes(nickname); context.Response.ContentLength64 = b.Length; context.Response.ContentType = "text/plain"; context.Response.OutputStream.Write(b, 0, b.Length); context.Response.OutputStream.Close(); return; } } else if (urlParts[0] == "stats") { var statistics = Client.GetStatistics(); var retString = "[Stats]\r\n"; var totalPlayers = 0; foreach (var stat in statistics) { retString += string.Format("playerState{0}={1}\r\n", stat.StatisticID, stat.StatisticCount); totalPlayers += stat.StatisticCount; } retString += string.Format("totalPlayers={0}\r\n", totalPlayers); retString += "[Lobbies]\r\n"; totalPlayers = 0; foreach (var server in MatchServer.Servers) { var cnt = server.Value.Sessions.Count(sess => (DateTime.Now - sess.LastTouched).TotalSeconds < 60); retString += string.Format("lobbies{0}={1}\r\n", server.Key, cnt); totalPlayers += cnt; } retString += string.Format("totalLobbies={0}", totalPlayers); /*rp.status = (int)RespState.OK; * rp.Headers["Content-Type"] = "text/plain"; * rp.BodyData = Encoding.ASCII.GetBytes(retString);*/ var b = Encoding.ASCII.GetBytes(retString); context.Response.ContentLength64 = b.Length; context.Response.ContentType = "text/plain"; context.Response.OutputStream.Write(b, 0, b.Length); context.Response.OutputStream.Close(); return; } else if (urlParts[0] == "clean") { long clientID = 0; var valid = false; if (long.TryParse(urlParts[1], out clientID)) { var client = Client.Get(clientID); if ((DateTime.UtcNow - client.LastTouched).TotalSeconds < 300) { var state = CIServer.IsUnclean(clientID, null); if (!state) { valid = true; } } } var b = Encoding.ASCII.GetBytes((valid) ? "valid" : "invalid"); context.Response.ContentLength64 = b.Length; context.Response.ContentType = "text/plain"; context.Response.OutputStream.Write(b, 0, b.Length); context.Response.OutputStream.Close(); return; } else if (urlParts[0] == "cleanExt") { long clientID = 0; var valid = false; var reason = "invalid-id"; if (long.TryParse(urlParts[1], out clientID)) { var client = Client.Get(clientID); if ((DateTime.UtcNow - client.LastTouched).TotalHours < 6) { var state = CIServer.IsUnclean(clientID, null); if (state) { reason = CIServer.WhyUnclean(clientID); } else { reason = "actually-valid"; valid = true; } } else { reason = "not-registered-at-lsp"; } } var b = Encoding.ASCII.GetBytes(((valid) ? "valid" : "invalid") + "\r\n" + reason); context.Response.ContentLength64 = b.Length; context.Response.ContentType = "text/plain"; context.Response.OutputStream.Write(b, 0, b.Length); context.Response.OutputStream.Close(); return; } /*else if (urlParts[0] == "key_public.xml") * { * if (_keyXML == string.Empty) * { * _keyXML = File.ReadAllText("key-public.xml"); * } * * var b = Encoding.ASCII.GetBytes(_keyXML); * context.Response.ContentLength64 = b.Length; * context.Response.ContentType = "text/plain"; * context.Response.OutputStream.Write(b, 0, b.Length); * context.Response.OutputStream.Close(); * return; * }*/ else if (urlParts[0] == "pc") { var file = "pc/" + urlParts[1].Replace('\\', '/'); if (!File.Exists(file)) { /*rp.status = (int)RespState.NOT_FOUND; * rp.Headers["Content-Type"] = "text/plain"; * rp.BodyData = Encoding.ASCII.GetBytes("Not Found!");*/ var b = Encoding.ASCII.GetBytes("Not Found!"); context.Response.ContentLength64 = b.Length; context.Response.ContentType = "text/plain"; context.Response.OutputStream.Write(b, 0, b.Length); context.Response.OutputStream.Close(); } else { var stream = File.OpenRead(file); var b = new byte[stream.Length]; stream.Read(b, 0, (int)stream.Length); stream.Close(); context.Response.ContentLength64 = b.Length; context.Response.ContentType = "application/octet-stream"; context.Response.OutputStream.Write(b, 0, b.Length); context.Response.OutputStream.Close(); } return; } else if (urlParts[0] == "servers") { var filter = urlParts[1].Replace(".xml", ""); if (filter.Contains("yeQA4reD")) { var b = Encoding.ASCII.GetBytes(ProcessServers(filter)); context.Response.ContentLength64 = b.Length; context.Response.ContentType = "text/xml"; context.Response.OutputStream.Write(b, 0, b.Length); context.Response.OutputStream.Close(); } return; } } } catch (Exception e) { Log.Error(e.ToString()); var b = Encoding.ASCII.GetBytes(e.Message); context.Response.ContentLength64 = b.Length; context.Response.ContentType = "text/plain"; context.Response.OutputStream.Write(b, 0, b.Length); context.Response.OutputStream.Close(); return; } var bt = Encoding.ASCII.GetBytes("Unknown Player"); context.Response.ContentLength64 = bt.Length; context.Response.ContentType = "text/plain"; context.Response.OutputStream.Write(bt, 0, bt.Length); context.Response.OutputStream.Close(); }