public void TickSocket(Socket sock, ref byte[] rd, ref int rdsf) { int avail = sock.Available; if (avail <= 0) { return; } if (avail + rdsf > MAX) { avail = MAX - rdsf; if (avail == 0) { throw new Exception("Received overly massive packet?!"); } } sock.Receive(rd, rdsf, avail, SocketFlags.None); rdsf += avail; if (rdsf < 5) { return; } while (true) { byte[] len_bytes = new byte[4]; Array.Copy(rd, len_bytes, 4); int len = Utilities.BytesToInt(len_bytes); if (len + 5 > MAX) { throw new Exception("Unreasonably huge packet!"); } if (rdsf < 5 + len) { return; } ServerToClientPacket packetID = (ServerToClientPacket)rd[4]; byte[] data = new byte[len]; Array.Copy(rd, 5, data, 0, len); byte[] rem_data = new byte[rdsf - (len + 5)]; if (rem_data.Length > 0) { Array.Copy(rd, len + 5, rem_data, 0, rem_data.Length); Array.Copy(rem_data, rd, rem_data.Length); } rdsf -= len + 5; AbstractPacketIn packet; bool asyncable = false; NetUsageType usage; switch (packetID) // TODO: Packet registry! { case ServerToClientPacket.PING: packet = new PingPacketIn(); usage = NetUsageType.PINGS; break; case ServerToClientPacket.YOUR_POSITION: packet = new YourPositionPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.SPAWN_ENTITY: packet = new SpawnEntityPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.PHYSICS_ENTITY_UPDATE: packet = new PhysicsEntityUpdatePacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.MESSAGE: packet = new MessagePacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.CHARACTER_UPDATE: packet = new CharacterUpdatePacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.TOPS: packet = new TopsPacketIn(); usage = NetUsageType.CHUNKS; break; case ServerToClientPacket.DESPAWN_ENTITY: packet = new DespawnEntityPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.NET_STRING: packet = new NetStringPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.SPAWN_ITEM: packet = new SpawnItemPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.YOUR_STATUS: packet = new YourStatusPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.ADD_JOINT: packet = new AddJointPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.YOUR_EID: packet = new YourEIDPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.DESTROY_JOINT: packet = new DestroyJointPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.TOPS_DATA: packet = new TopsDataPacketIn(); usage = NetUsageType.CHUNKS; break; case ServerToClientPacket.PRIMITIVE_ENTITY_UPDATE: packet = new PrimitiveEntityUpdatePacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.ANIMATION: packet = new AnimationPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.FLASHLIGHT: packet = new FlashLightPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.REMOVE_ITEM: packet = new RemoveItemPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.SET_ITEM: packet = new SetItemPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.CVAR_SET: packet = new CVarSetPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.SET_HELD_ITEM: packet = new SetHeldItemPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.CHUNK_INFO: packet = new ChunkInfoPacketIn(); usage = NetUsageType.CHUNKS; break; case ServerToClientPacket.BLOCK_EDIT: packet = new BlockEditPacketIn(); usage = NetUsageType.CHUNKS; break; case ServerToClientPacket.SUN_ANGLE: packet = new SunAnglePacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.TELEPORT: packet = new TeleportPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.OPERATION_STATUS: packet = new OperationStatusPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.PARTICLE_EFFECT: packet = new ParticleEffectPacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.PATH: packet = new PathPacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.CHUNK_FORGET: packet = new ChunkForgetPacketIn(); usage = NetUsageType.CHUNKS; break; case ServerToClientPacket.FLAG_ENTITY: packet = new FlagEntityPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.DEFAULT_SOUND: packet = new DefaultSoundPacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.GAIN_CONTROL_OF_VEHICLE: packet = new GainControlOfVehiclePacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.ADD_CLOUD: packet = new AddCloudPacketIn(); usage = NetUsageType.CLOUDS; break; case ServerToClientPacket.REMOVE_CLOUD: packet = new RemoveCloudPacketIn(); usage = NetUsageType.CLOUDS; break; case ServerToClientPacket.ADD_TO_CLOUD: packet = new AddToCloudPacketIn(); usage = NetUsageType.CLOUDS; break; case ServerToClientPacket.YOUR_VEHICLE: packet = new YourVehiclePacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.SET_STATUS: packet = new SetStatusPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.HIGHLIGHT: packet = new HighlightPacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.PLAY_SOUND: packet = new PlaySoundPacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.LOD_MODEL: packet = new LODModelPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.LOSE_CONTROL_OF_VEHICLE: packet = new LoseControlOfVehiclePacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.JOINT_UPDATE: packet = new JointUpdatePacketIn(); usage = NetUsageType.ENTITIES; break; default: throw new Exception("Invalid packet ID: " + packetID); } UsagesThisSecond[(int)usage] += 5 + data.Length; UsagesTotal[(int)usage] += 5 + data.Length; packet.TheClient = TheClient; packet.ChunkN = sock == ChunkSocket; ServerToClientPacket pid = packetID; if (asyncable) { // TODO: StartAsyncTask? if (!packet.ParseBytesAndExecute(data)) { SysConsole.Output(OutputType.ERROR, "Bad async packet (ID=" + pid + ") data!"); } } else { TheClient.Schedule.ScheduleSyncTask(() => { try { if (!packet.ParseBytesAndExecute(data)) { SysConsole.Output(OutputType.ERROR, "Bad sync packet (ID=" + pid + ") data!"); } } catch (Exception ex) { if (ex is ThreadAbortException) { throw ex; } SysConsole.Output(OutputType.ERROR, "Bad sync packet (ID=" + pid + ") data: " + ex.ToString()); } }); } } }
public void TickSocket(Socket sock, ref byte[] rd, ref int rdsf) { int avail = sock.Available; if (avail <= 0) { return; } if (avail + rdsf > MAX) { avail = MAX - rdsf; if (avail == 0) { throw new Exception("Received overly massive packet?!"); } } sock.Receive(rd, rdsf, avail, SocketFlags.None); rdsf += avail; if (rdsf < 5) { return; } while (true) { byte[] len_bytes = new byte[4]; Array.Copy(rd, len_bytes, 4); int len = Utilities.BytesToInt(len_bytes); if (len + 5 > MAX) { throw new Exception("Unreasonably huge packet!"); } if (rdsf < 5 + len) { return; } ServerToClientPacket packetID = (ServerToClientPacket)rd[4]; byte[] data = new byte[len]; Array.Copy(rd, 5, data, 0, len); byte[] rem_data = new byte[rdsf - (len + 5)]; if (rem_data.Length > 0) { Array.Copy(rd, len + 5, rem_data, 0, rem_data.Length); Array.Copy(rem_data, rd, rem_data.Length); } rdsf -= len + 5; AbstractPacketIn packet; bool asyncable = false; NetUsageType usage; switch (packetID) // TODO: Packet registry? { case ServerToClientPacket.PING: packet = new PingPacketIn(); usage = NetUsageType.PINGS; break; case ServerToClientPacket.YOUR_POSITION: packet = new YourPositionPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.SPAWN_ENTITY: packet = new SpawnEntityPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.PHYSICS_ENTITY_UPDATE: packet = new PhysicsEntityUpdatePacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.MESSAGE: packet = new MessagePacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.CHARACTER_UPDATE: packet = new CharacterUpdatePacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.DESPAWN_ENTITY: packet = new DespawnEntityPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.NET_STRING: packet = new NetStringPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.SPAWN_ITEM: packet = new SpawnItemPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.YOUR_STATUS: packet = new YourStatusPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.ADD_JOINT: packet = new AddJointPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.YOUR_EID: packet = new YourEIDPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.DESTROY_JOINT: packet = new DestroyJointPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.PRIMITIVE_ENTITY_UPDATE: packet = new PrimitiveEntityUpdatePacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.ANIMATION: packet = new AnimationPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.FLASHLIGHT: packet = new FlashLightPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.REMOVE_ITEM: packet = new RemoveItemPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.SET_ITEM: packet = new SetItemPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.CVAR_SET: packet = new CVarSetPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.SET_HELD_ITEM: packet = new SetHeldItemPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.CHUNK_INFO: packet = new ChunkInfoPacketIn(); usage = NetUsageType.CHUNKS; break; case ServerToClientPacket.BLOCK_EDIT: packet = new BlockEditPacketIn(); usage = NetUsageType.CHUNKS; break; case ServerToClientPacket.SUN_ANGLE: packet = new SunAnglePacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.TELEPORT: packet = new TeleportPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.OPERATION_STATUS: packet = new OperationStatusPacketIn(); usage = NetUsageType.GENERAL; break; case ServerToClientPacket.PARTICLE_EFFECT: packet = new ParticleEffectPacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.PATH: packet = new PathPacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.CHUNK_FORGET: packet = new ChunkForgetPacketIn(); usage = NetUsageType.CHUNKS; break; case ServerToClientPacket.FLAG_ENTITY: packet = new FlagEntityPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.DEFAULT_SOUND: packet = new DefaultSoundPacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.GAIN_CONTROL_OF_VEHICLE: packet = new GainControlOfVehiclePacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.ADD_CLOUD: packet = new AddCloudPacketIn(); usage = NetUsageType.CLOUDS; break; case ServerToClientPacket.REMOVE_CLOUD: packet = new RemoveCloudPacketIn(); usage = NetUsageType.CLOUDS; break; case ServerToClientPacket.ADD_TO_CLOUD: packet = new AddToCloudPacketIn(); usage = NetUsageType.CLOUDS; break; case ServerToClientPacket.SET_STATUS: packet = new SetStatusPacketIn(); usage = NetUsageType.PLAYERS; break; case ServerToClientPacket.HIGHLIGHT: packet = new HighlightPacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.PLAY_SOUND: packet = new PlaySoundPacketIn(); usage = NetUsageType.EFFECTS; break; case ServerToClientPacket.LOD_MODEL: packet = new LODModelPacketIn(); usage = NetUsageType.ENTITIES; break; case ServerToClientPacket.LOSE_CONTROL_OF_VEHICLE: packet = new LoseControlOfVehiclePacketIn(); usage = NetUsageType.ENTITIES; break; default: throw new Exception("Invalid packet ID: " + packetID); } UsagesThisSecond[(int)usage] += 5 + data.Length; UsagesTotal[(int)usage] += 5 + data.Length; packet.TheClient = TheClient; packet.ChunkN = sock == ChunkSocket; ServerToClientPacket pid = packetID; if (asyncable) { // TODO: StartASyncTask? if (!packet.ParseBytesAndExecute(data)) { SysConsole.Output(OutputType.ERROR, "Bad async packet (ID=" + pid + ") data!"); } } else { TheClient.Schedule.ScheduleSyncTask(() => { try { if (!packet.ParseBytesAndExecute(data)) { SysConsole.Output(OutputType.ERROR, "Bad sync packet (ID=" + pid + ") data!"); } } catch (Exception ex) { SysConsole.Output(OutputType.ERROR, "Bad sync packet (ID=" + pid + ") data: " + ex.ToString()); } }); } } }