private static void FindSessionsPaged(MessageData mdata, DWMessage packet) { try { // TODO: paging; do this by connection // return perPage results first, then on next requests either return more starting from the last result // or return 0 results. the game should always query until equal/0 is returned? var a = packet.ByteBuffer.ReadUInt32(); // always 6 var b = packet.ByteBuffer.ReadBool(); // new paging token? var c = packet.ByteBuffer.ReadBlob(); // paging token ID, or something useless like typename var d = packet.ByteBuffer.ReadUInt32(); // results per page var ca = packet.ByteBuffer.ReadUInt32(); // netcode version var cb = packet.ByteBuffer.ReadUInt32(); // -1 var cc = packet.ByteBuffer.ReadUInt32(); // server type var cd = packet.ByteBuffer.ReadUInt32(); // stat DDL version var ce = packet.ByteBuffer.ReadUInt32(); // unknown, should be -1 actually var cf = packet.ByteBuffer.ReadUInt32(); // -1 var cg = packet.ByteBuffer.ReadUInt32(); // country ID IEnumerable <KeyValuePair <ulong, bdMatchMakingInfo> > matchingSessions = null; var wager = 0; if (cc == 2) { wager = 2; } else if (cc == 1) { wager = 1; } else { wager = 1; } var reply = packet.MakeReply(1, false); reply.ByteBuffer.Write(0x8000000000000001); reply.ByteBuffer.Write((uint)0); reply.ByteBuffer.Write((byte)13); lock (_sessions) { matchingSessions = (from session in _sessions where (session.Value.TitleID == TitleID.T5 && ((MatchMakingInfoT5)session.Value).LicenseType != 5) && ((MatchMakingInfoT5)session.Value).StatDDL == cd && ((MatchMakingInfoT5)session.Value).NetcodeVersion == ca && ((MatchMakingInfoT5)session.Value).Wager == wager && ((MatchMakingInfoT5)session.Value).Reachable == true select session).Take((int)d); reply.ByteBuffer.Write((uint)matchingSessions.Count()); reply.ByteBuffer.Write((uint)matchingSessions.Count()); foreach (var session in matchingSessions) { session.Value.Serialize(reply); } Console.WriteLine("rp {0} ptb {1} t {2} returned {3} sessions", d, b, cc, matchingSessions.Count()); } reply.Send(true); } catch (Exception e) { Log.Error(e.ToString()); } }
public static void DW_PacketReceived(MessageData data) { var type = data.Get <int>("type"); var crypt = data.Get <bool>("crypt"); if (type == 21) { var packet = DWRouter.GetMessage(data); var call = packet.ByteBuffer.ReadByte(); try { switch (call) { case 1: CreateSession(data, packet); break; case 2: UpdateSession(data, packet); break; case 3: DeleteSession(data, packet); break; case 4: FindSessionFromID(data, packet); break; case 5: FindSessions(data, packet); break; case 8: InviteToSession(data, packet); break; case 9: SubmitPerformance(data, packet); break; case 10: GetPerformanceValues(data, packet); break; case 12: UpdateSessionPlayers(data, packet); break; case 13: FindSessionsPaged(data, packet); break; case 14: FindSessionsByEntityIDs(data, packet); break; default: Log.Debug("unknown packet " + call + " in bdMatchMaking"); //DWRouter.Unknown(data, packet); break; } } catch (Exception e) { Log.Error(e.ToString()); } } }
public static void DW_PacketReceived(MessageData data) { var type = data.Get <int>("type"); var crypt = data.Get <bool>("crypt"); var weHandle = ((type == 10) || (type == 18) || (type == 8 || (crypt && type == 28) || type == 50 || type == 4 || type == 58) || (type == 23)); try { if (type == 10) { var packet = DWRouter.GetMessage(data); var call = packet.ByteBuffer.ReadByte(); var initTime = DateTime.Now; switch (call) { case 1: UploadFile(data, packet); break; case 3: GetFile(data, packet); break; case 7: GetPublisherFile(data, packet); break; default: Log.Debug("unknown packet " + call + " in bdStorage"); //DWRouter.Unknown(data, packet); break; } } else if (type == 18) { try { var packet = DWRouter.GetMessage(data); var reply = packet.MakeReply(5, false); reply.ByteBuffer.Write(new byte[] { 0x2d, 0xb3, 0xa2, 0x4f, 0x1a, 0x36, 0xd0, 0xd2, 0x00, 0x00, 0x04, 0x00, 0x00, 0xee, 0x02, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x88, 0x13, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x02, 0x0c, 0xd1, 0xaa, 0x7a, 0xb1, 0x31, 0xb1, 0xaa, 0x6b, 0x83, 0x51, 0x00, 0x00 }); reply.Send(true); } catch { } } else if (type == 8 || (crypt && type == 28) || type == 50 || type == 4 || type == 58) { try { var packet = DWRouter.GetMessage(data); try { var call = packet.ByteBuffer.ReadByte(); //Log.Debug("Service call identifier is " + call + "."); } catch { } //DWRouter.Unknown(data, packet); } catch { } } else if (type == 23) { try { var packet = DWRouter.GetMessage(data); var call = packet.ByteBuffer.ReadByte(); switch (call) { case 2: GetCounterTotals(data, packet); break; default: Log.Debug("unknown packet " + call + " in bdCounter"); //DWRouter.Unknown(data, packet); break; } } catch { } } /*else if (type != 12 && crypt) * { * var packet = DWRouter.GetMessage(data); * DWRouter.Unknown(data, packet); * }*/ } catch (Exception e) { Log.Error(e.ToString()); } if (weHandle) { var upacket = DWRouter.GetMessage(data); } }
private static void FindSessions(MessageData mdata, DWMessage packet) { var queryType = packet.ByteBuffer.ReadUInt32(); // query type var vb = packet.ByteBuffer.ReadUInt32(); // seems to be 0 var count = packet.ByteBuffer.ReadUInt32(); var titleID = DWRouter.GetTitleIDForData(mdata); if (titleID == TitleID.T5) { if (queryType == 2) { FindZombieSessions(mdata, packet); } else if (queryType == 4) { // technically a UInt64, but we don't seem to like bit shifting :) packet.ByteBuffer.ReadDataType(10); var portbytes = packet.ByteBuffer.Read(2); var ipbytes = packet.ByteBuffer.Read(4); var port = BitConverter.ToUInt16(portbytes, 0); var address = BitConverter.ToUInt32(ipbytes, 0); packet.ByteBuffer.Read(2); FindSessionByIP(mdata, packet, address, port); } } else if (titleID == TitleID.IW5) { IEnumerable <KeyValuePair <ulong, bdMatchMakingInfo> > matchingSessions = null; var reply = packet.MakeReply(1, false); reply.ByteBuffer.Write(0x8000000000000001); reply.ByteBuffer.Write((uint)0); reply.ByteBuffer.Write((byte)13); Func <MatchMakingInfoIW5, bool> condition = null; /*switch (queryType) * { * case 1: * * break; * }*/ var a = packet.ByteBuffer.ReadInt32(); var e = packet.ByteBuffer.ReadInt32(); condition = info => { return(info.Playlist == e); }; var rand = new Random(); lock (_sessions) { matchingSessions = (from session in _sessions where (session.Value.TitleID == TitleID.IW5 && condition((MatchMakingInfoIW5)session.Value)) orderby rand.Next() select session).Take((int)count); reply.ByteBuffer.Write((uint)matchingSessions.Count()); reply.ByteBuffer.Write((uint)matchingSessions.Count()); foreach (var session in matchingSessions) { session.Value.Serialize(reply); } } reply.Send(true); } }
/*void DoReceive(SocketAsyncEventArgs args) * { * var client = (TCPClient)args.UserToken; * * while (!client.socket.ReceiveAsync(args)) * { * Log.Debug("Handling stuff - " + client.ConnectionID); * HandleReceive(args); * } * }*/ public static void ForceDisconnect(MessageData message) { _instance.CloseSocket(message.Get <TCPClient>("ci").readEventArgs); }
private static void UploadFile(MessageData mdata, DWMessage packet) { var filename = packet.ByteBuffer.ReadString(); var test = packet.ByteBuffer.ReadBool(); var data = packet.ByteBuffer.ReadBlob(); // NOTE: AN UINT64 MIGHT FOLLOW HERE. THIS COULD BE USED BY DEDICATED SERVER-STYLE LICENSES FOR WRITING USER STATS. var user = (ulong)0; try { user = packet.ByteBuffer.ReadUInt64(); } catch { } if (user == 0) { /*lock (DWRouter.Connections) * { * user = (from conn in DWRouter.Connections * where conn.Value == mdata.Get<string>("cid") * select conn.Key).FirstOrDefault(); * }*/ user = DWRouter.GetIDForData(mdata); } //var user = 0x1100001ded1ca7e;//packet.ByteBuffer.ReadUInt64(); var path = filename + "_" + user.ToString("x16"); /*MySqlDataReader query = Database.Query("SELECT * FROM files WHERE filename='" + path + "'"); * if (query.HasRows) * { * query.Close(); * Log.Debug("Trying to update " + path + "... for user "); * Database.UploadQuery("UPDATE files SET data = ?filedata, filesize = '" + data.Length + "', userid='" + Convert.ToString((int)user) + "' WHERE filename='" + path + "'", data); * } * else * { * query.Close(); * Log.Debug("Trying to write " + path + "... for user "); * Database.UploadQuery("INSERT INTO files(userid, filename, data, filesize) VALUES('" + Convert.ToString((int)user) + "', '" + path + "', ?filedata, '" + data.Length + "')", data); * }*/ Log.Debug("Trying to write " + path + "..."); var file = new File() { filename = path, userid = (int)user, filesize = data.Length, data = data }; var query = Query.EQ("filename", path); var files = Database.AFiles.Find(query); if (files.Count() > 0) { file.id = files.First().id; } Database.AFiles.Save(file); var reply = packet.MakeReply(1, false); reply.ByteBuffer.Write(0x8000000000000001); reply.ByteBuffer.Write((uint)0); reply.ByteBuffer.Write((byte)1); reply.ByteBuffer.Write((uint)0); reply.ByteBuffer.Write((uint)0); reply.Send(true); }
public static void DW_PacketReceived(MessageData data) { var type = data.Get <int>("type"); if (type == 7) { var packet = DWRouter.GetMessage(data); bool initialBool; uint gameID, randomNumber; byte[] ticket; packet.BitBuffer.UseDataTypes = false; packet.BitBuffer.ReadBoolean(out initialBool); packet.BitBuffer.UseDataTypes = true; packet.BitBuffer.ReadUInt32(out gameID); packet.BitBuffer.ReadUInt32(out randomNumber); packet.BitBuffer.ReadBytes(128, out ticket); // parse LSG ticket var key = DWTickets.GetKeyFromLSGTicket(ticket); DWRouter.SetGlobalKey(packet.Data, key); lock (DWRouter.Connections) { var id = DWTickets.GetIDFromLSGTicket(ticket); DWRouter.Connections[id] = packet.Data.Get <string>("cid"); } lock (DWRouter.CIDToUser) { var id = DWTickets.GetUserFromLSGTicket(ticket); DWRouter.CIDToUser[packet.Data.Get <string>("cid")] = id; } lock (DWRouter.ConnectionsReverse) { var id = DWTickets.GetIDFromLSGTicket(ticket); DWRouter.ConnectionsReverse[packet.Data.Get <string>("cid")] = id; } lock (DWRouter.CIDToName) { var name = DWTickets.GetNameFromLSGTicket(ticket); DWRouter.CIDToName[packet.Data.Get <string>("cid")] = name; } lock (DWRouter.CIDToTitle) { var title = (TitleID)gameID; DWRouter.CIDToTitle[packet.Data.Get <string>("cid")] = title; } // now make a reply. /* * var reply = packet.MakeReply(1, false); * reply.ByteBuffer.Write(0x8000000000000000); * reply.ByteBuffer.Write(0); * reply.ByteBuffer.Write((byte)6); * reply.ByteBuffer.Write(1); * reply.ByteBuffer.Write(1); * reply.ByteBuffer.Write(0x12345678); * reply.Send(true);*/ } }
public void handlePacket(MessageData data) { var buffer = data.Get <byte[]>("data"); var source = data.Get <EndPoint>("source"); var stream = new MemoryStream(buffer); var reader = new BinaryReader(stream); var time = data.Get <DateTime>("time"); var delay = (DateTime.Now - time).TotalMilliseconds; var delay2 = DateTime.Now; try { while (stream.Position < stream.Length) { var origin = 0; var len = 0; if (_bytesRead == 0) { _totalBytes = 0; try { _totalBytes = reader.ReadInt32(); } catch { _totalBytes = 0; } //Log.Info("GOT A PACKET OF SIZE " + _totalBytes.ToString("X")); if (_totalBytes == 0xC8) { _totalBytes = 0; break; } if (_totalBytes > (256 * 1024)) { Log.Error("LENGTH IS XBOX"); break; } if (_totalBytes == 0 || _totalBytes < 0) { //TCPHandler.sendPacket(message, client); MessageData packet = new MessageData("none"); packet["data"] = new byte[4]; packet["cid"] = data.Get <string>("cid"); TCPHandler.Net_TcpSend(packet); continue; } _messageBuffer = new MemoryStream(); origin += 4; len -= 4; } len += Math.Min((buffer.Length - (int)stream.Position), (_totalBytes - _bytesRead)); var newBytes = reader.ReadBytes(len); _messageBuffer.Write(newBytes, 0, len); _bytesRead += len; if (_bytesRead > _totalBytes) { //Debugger.Break(); } if (_bytesRead >= _totalBytes) { _bytesRead = 0; _messageBuffer.Position = 0; var breader = new BinaryReader(_messageBuffer); _totalBytes--; var pdtype = breader.ReadByte(); var encrypted = (pdtype == 1); // can be 0, 1 and 0xFF var ptype = 0xFF; byte[] pdata = null; if (pdtype == 0xFF) { // TODO: handle this one Log.Debug("Got a 0xFF pdtype!"); //return; continue; } var initTime = DateTime.Now; if (!encrypted) { ptype = breader.ReadByte(); _totalBytes -= 1; pdata = breader.ReadBytes(_totalBytes); } else { try { var key = GetGlobalKey(data); var iv = DWCrypto.CalculateInitialVector(breader.ReadUInt32()); var edata = breader.ReadBytes(_totalBytes - 4); var ddata = DWCrypto.Decrypt(iv, key, edata); var dstream = new MemoryStream(ddata); var dreader = new BinaryReader(dstream); // TODO: find out why this hash isn't just truncated SHA-1 var hash = dreader.ReadUInt32(); ptype = dreader.ReadByte(); pdata = dreader.ReadBytes((int)(dstream.Length - 5)); dreader.Close(); dstream.Close(); } catch { } } var initTime2 = DateTime.Now; var delay3 = (DateTime.Now - delay2).TotalMilliseconds; //Log.Debug("Received a " + _totalBytes + " byte packet (type " + ptype + ") from DemonWare - delay " + delay + "ms. delay after reading " + delay3 + "ms."); /* * var message = Messages.NewMessage("dw.packet-received"); * message["data"] = pdata; * message["type"] = ptype; * message["crypt"] = encrypted; * message["source"] = source; * message["cid"] = data["cid"]; * message["delay"] = delay; * message["time"] = DateTime.Now; * message.SendNow(); */ MessageData message = new MessageData("none"); message["data"] = pdata; message["type"] = ptype; message["crypt"] = encrypted; message["source"] = source; message["cid"] = data["cid"]; message["ci"] = data["ci"]; message["delay"] = delay; message["time"] = DateTime.Now; redirectPacket(message); /*var msec = (int)((DateTime.Now - initTime).TotalMilliseconds); * var state = GetPerfState(ptype); * state.Add(msec); * * msec = (int)((DateTime.Now - initTime2).TotalMilliseconds); * var state2 = GetPerfState(ptype + 1000); * state2.Add(msec); * * Log.Debug("service " + ptype + " min " + state.Min + "/" + state2.Min + " max " + state.Max + "/" + state2.Max);*/ } } } catch (Exception ex) { Log.Error(ex.ToString()); // disconnect to prevent further pollution of system TCPHandler.ForceDisconnect(data); } reader.Close(); }
private void redirectPacket(MessageData data) { data.Arguments["handled"] = false; var type = data.Get <int>("type"); var crypt = data.Get <bool>("crypt"); bool routed = false; try { if (!crypt && (type == 28 || type == 12 || type == 26)) { DWAuther.DW_PacketReceived(data); routed = true; //Log.Debug("got auth packet"); } if (crypt && type == 28) { DWGroups.DW_PacketReceived(data); routed = true; } if (type == 7) { DWLobby.DW_PacketReceived(data); routed = true; //Log.Debug("got lobby packet"); } if (type == 6) { DWMessaging.DW_PacketReceived(data); routed = true; //Log.Debug("got service packet"); } if (type == 21) { DWMatch.DW_PacketReceived(data); routed = true; //Log.Debug("got match packet"); } if ((type == 10) || (type == 18) || (type == 23) || (type == 8 || type == 50 || type == 4 || type == 58)) { DWStorage.DW_PacketReceived(data); routed = true; //Log.Debug("got storage packet"); } if (type == 12 && crypt) { DWTitles.DW_PacketReceived(data); routed = true; //Log.Debug("got Title packet"); } if (type == 8) { DWProfiles.DW_PacketReceived(data); routed = true; } if (type == 27) { DWDML.DW_PacketReceived(data); } if (type == 67) { DWEventLog.DW_PacketReceived(data); } } catch (Exception e) { Log.Error("Exception: " + e.ToString()); } if (routed == false) { Log.Debug("UNHANDLED PACKET: " + type); } else { try { if (crypt && !data.Get <bool>("handled")) { DWRouter.Unknown(data, DWRouter.GetMessage(data)); } } catch { Log.Error("whoops"); // disconnect to prevent pollution of system TCPHandler.ForceDisconnect(data); } } }
private static void CreateSession(MessageData mdata, DWMessage packet) { Net_TcpDisconnected(mdata); var seed = 0; string IP = mdata.Get <string>("cid"); string[] IPParts = IP.Split(':'); seed = BitConverter.ToInt32(IPAddress.Parse(IPParts[0]).GetAddressBytes(), 0); TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)); seed += (int)ts.TotalSeconds; var rnd = new Random(seed); var sid = new byte[8]; rnd.NextBytes(sid); var titleID = DWRouter.GetTitleIDForData(mdata); MatchMakingInfoT5 info = null; if (titleID == TitleID.T5) { info = new MatchMakingInfoT5(); } else if (titleID == TitleID.IW5) { //info = new MatchMakingInfoIW5(); } info.Deserialize(packet); info.SessionID = sid; info.CID = mdata.Get <string>("cid"); info.User = (DWRouter.CIDToUser.ContainsKey(info.CID)) ? DWRouter.CIDToUser[info.CID] : 0; info.Reachable = true; lock (_sessions) { //Delete old sessions int deleted = 0; foreach (var session in _sessions) { if (session.Value.User == info.User) { _sessions.Remove(session.Key); deleted++; } } /* * var duplicateValues = _sessions.GroupBy(x => x.Value).Where(x => x.Count() > 1); * * foreach (var dupSession in _sessions) * { * _sessions.Remove(dupSession.Key); * deleted++; * } */ Console.WriteLine("Deleted {0} old sessions whilst making a new one...", deleted); _sessions.Add(BitConverter.ToUInt64(sid, 0), info); } var reply = packet.MakeReply(1, false); reply.ByteBuffer.Write(0x8000000000000001); reply.ByteBuffer.Write((uint)0); reply.ByteBuffer.Write((byte)1); reply.ByteBuffer.Write((uint)1); reply.ByteBuffer.Write((uint)1); reply.ByteBuffer.WriteBlob(info.SessionID); reply.Send(true); if (titleID == TitleID.T5) { var tInfo = (MatchMakingInfoT5)info; Log.Debug(tInfo.OnlineID.ToString("X16") + " registered session (map " + tInfo.MapName + ", gametype " + tInfo.GameTypeName + ")"); } else if (titleID == TitleID.IW5) { Log.Debug("Registered session."); } }
private static void FindZombieSessions(int count, MessageData mdata, DWMessage packet) { var a = packet.ByteBuffer.ReadInt32(); // gametype var b = packet.ByteBuffer.ReadInt32(); // netcode version packet.ByteBuffer.ReadDataType(0x14); packet.ByteBuffer.ReadDataType(0x14); packet.ByteBuffer.ReadDataType(0x14); packet.ByteBuffer.ReadDataType(0x14); var g = packet.ByteBuffer.ReadInt32(); // playlist IEnumerable <KeyValuePair <ulong, MatchMakingInfoT5> > matchingSessions = null; var reply = packet.MakeReply(1, false); reply.ByteBuffer.Write(0x8000000000000001); reply.ByteBuffer.Write((uint)0); reply.ByteBuffer.Write((byte)13); lock (_sessions) { /* * matchingSessions = (from session in _sessions * where session.Value.TitleID == TitleID.T5 && ((MatchMakingInfoT5)session.Value).NetcodeVersion == b && ((MatchMakingInfoT5)session.Value).GameType == a && ((MatchMakingInfoT5)session.Value).Playlist == g * select session); */ var rand = new Random(); matchingSessions = (from session in _sessions where session.Value.TitleID == TitleID.T5 && //((MatchMakingInfoT5)session.Value).NetcodeVersion == b && ((MatchMakingInfoT5)session.Value).GameType == a && //((MatchMakingInfoT5)session.Value).Playlist == g && ((MatchMakingInfoT5)session.Value).Reachable == true && //((MatchMakingInfoT5)session.Value).SessionID != _sessions[sid].SessionID && (DateTime.Now - ((MatchMakingInfoT5)session.Value).LastTouched).TotalSeconds < 120 orderby rand.Next() select session).Take(count); /* * if ((uint)matchingSessions.Count() == 0 && _sessions[sid].MatchRetry > 2) * { * matchingSessions = (from session in _sessions * where session.Value.TitleID == TitleID.T5 && * ((MatchMakingInfoT5)session.Value).GameType == a && * ((MatchMakingInfoT5)session.Value).SessionID != _sessions[sid].SessionID && * (DateTime.Now - _sessions[sid].LastTouched).TotalSeconds < 120 * orderby rand.Next() * select session).Take(count); * } */ //If the users has tried more than 3 times to find matches but kept asking for more. We'll assume something is going wrong. Lets return 0 so he can host his own /* * if (_sessions[sid].MatchRetry > 3) * { * _sessions[sid].MatchRetry = 0; * reply.ByteBuffer.Write((uint)0); * reply.ByteBuffer.Write((uint)0); * } * else * {*/ reply.ByteBuffer.Write((uint)matchingSessions.Count()); reply.ByteBuffer.Write((uint)matchingSessions.Count()); foreach (var session in matchingSessions) { if ((DateTime.Now - session.Value.TimeFound).TotalSeconds > 5) { _sessions[session.Key].TimeFound = DateTime.Now; session.Value.Serialize(reply); } } //} } Console.WriteLine("get zm g {0} a {1} returned {2} sessions", g, a, matchingSessions.Count()); reply.Send(true); }