public void HandleCommand(MatchServer server, Client client, UdpPacket packet, MatchBaseRequestPacket baseRequest) { if (!packet.Secure) { return; } var random = new Random(); var reader = packet.GetReader(); var request = new MatchRequestListRequestPacket(reader); var playlist = server.Playlist; var country = ""; try { country = geo.GetCountryCode(client.ExternalIP.Address); } catch { } client.CurrentState = playlist; // set player as being in this playlist var unclean = CIServer.IsUnclean(client.XUID, packet.GetSource().Address) || CIServer.IsUnclean(client.XUIDAlias, packet.GetSource().Address); // match hosts // TODO: possibly skew 'preferred' players like XBL... 'random' isn't really a matchmaking algorithm lock (server.Sessions) { IEnumerable <MatchSession> sessions = null; if (client.GameBuild < 47) { sessions = (from session in server.Sessions where /*session.HostXUID != client.XUID && */ (DateTime.Now - session.LastTouched).TotalSeconds < 60 && session.Unclean == unclean orderby random.Next() select session).Take(19); } else { var localsessions = (from session in server.Sessions where (DateTime.Now - session.LastTouched).TotalSeconds < 60 && session.Unclean == unclean && session.Country == country orderby random.Next() select session).Take(20); var remaining = (50 - localsessions.Count()); var othersessions = (from session in server.Sessions where /*session.HostXUID != client.XUID && */ (DateTime.Now - session.LastTouched).TotalSeconds < 60 && session.Unclean == unclean orderby random.Next() select session).Take(remaining); sessions = localsessions.Concat(othersessions); } if (unclean) { var list = sessions.ToList(); var i = 0; while (list.Count < 19) { list.Add(new MatchSession() { Clients = new List <MatchSessionClient>(), ExternalIP = new IPEndPoint(0x7F000001, 28960 + i), GameID = i, HostXUID = i + 123, InternalIP = new IPEndPoint(0x7F000001, 28960 + i) }); i++; } sessions = list.Take(19); } var responsePacket = new MatchRequestListResponsePacket(request.ReplyType, request.Sequence, sessions); var response = packet.MakeResponse(); responsePacket.Write(response.GetWriter(), Client.IsVersionAllowed(client.GameVersion, client.GameBuild)); response.Send(); Log.Debug(string.Format("Sent {0} sessions to {1}", sessions.Count(), client.XUID.ToString("X16"))); } }
public void HandleCommand(MatchServer server, Client client, UdpPacket packet, MatchBaseRequestPacket baseRequest) { var reader = packet.GetReader(); var request = new MatchRegisterHostingRequestPacket(reader); var playlist = server.Playlist; var challengePassed = false; if (MatchRequestHostingHandler.Challenges.ContainsKey(client.XUID)) { var oldChallenge = MatchRequestHostingHandler.Challenges[client.XUID]; if (request.Challenge == oldChallenge) { challengePassed = true; } } if (!challengePassed) { Log.Warn(string.Format("Client {0} replied with a wrong host registration challenge.", client.XUID.ToString("X16"))); } var existingMatches = from session in server.Sessions where session.HostXUID == client.XUID select session; if (existingMatches.Count() > 0) { var match = existingMatches.First(); match.GameID = request.Session.GameID; match.SetLastTouched(); Log.Debug(string.Format("Updated match as registered by {0}", client.XUID.ToString("X16"))); } else { if (!Client.IsHostAllowed(client.XUID)) { Log.Info(string.Format("Non-allowed client (XUID {0}) tried to register lobby", client.XUID.ToString("X16"))); return; } else if (!Client.IsHostAllowed(request.Session.ExternalIP.Address)) { Log.Info(string.Format("Non-allowed client (IP {0}) tried to register lobby", request.Session.ExternalIP)); return; } else { request.Session.Unclean = (CIServer.IsUnclean(client.XUID, packet.GetSource().Address) || CIServer.IsUnclean(client.XUIDAlias, packet.GetSource().Address)); request.Session.HostXUID = client.XUID; request.Session.Country = ""; try { var countrycode = geo.GetCountryCode(request.Session.ExternalIP.Address); Console.WriteLine("Country code of IP address " + request.Session.ExternalIP.ToString() + ": " + countrycode.ToString()); request.Session.Country = countrycode; } catch { } server.Sessions.Add(request.Session); Log.Info(string.Format("Registered session by {0}; lobby at {1}", client.XUID.ToString("X16"), request.Session.ExternalIP)); } } // this response appears wrong for now var responsePacket = new MatchRegisterHostingResponsePacket(request.ReplyType, request.Sequence); var response = packet.MakeResponse(); responsePacket.Write(response.GetWriter()); response.Send(); }
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 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); }
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(); }