PageRenderTime 28ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/src/pocketmine/network/Network.php

https://gitlab.com/Skull3x/GladiatorMine
PHP | 366 lines | 256 code | 41 blank | 69 comment | 10 complexity | d8f312e6426aee7a97965bf0c2bf122b MD5 | raw file
  1. <?php
  2. /*
  3. *
  4. * ____ _ _ __ __ _ __ __ ____
  5. * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
  6. * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
  7. * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
  8. * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Lesser General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * @author PocketMine Team
  16. * @link http://www.pocketmine.net/
  17. *
  18. *
  19. */
  20. /**
  21. * Network-related classes
  22. */
  23. namespace pocketmine\network;
  24. use pocketmine\network\protocol\AddEntityPacket;
  25. use pocketmine\network\protocol\AddItemEntityPacket;
  26. use pocketmine\network\protocol\AddPaintingPacket;
  27. use pocketmine\network\protocol\AddPlayerPacket;
  28. use pocketmine\network\protocol\AdventureSettingsPacket;
  29. use pocketmine\network\protocol\AnimatePacket;
  30. use pocketmine\network\protocol\BatchPacket;
  31. use pocketmine\network\protocol\ChunkRadiusUpdatePacket;
  32. use pocketmine\network\protocol\ContainerClosePacket;
  33. use pocketmine\network\protocol\ContainerOpenPacket;
  34. use pocketmine\network\protocol\ContainerSetContentPacket;
  35. use pocketmine\network\protocol\ContainerSetDataPacket;
  36. use pocketmine\network\protocol\ContainerSetSlotPacket;
  37. use pocketmine\network\protocol\CraftingDataPacket;
  38. use pocketmine\network\protocol\CraftingEventPacket;
  39. use pocketmine\network\protocol\ChangeDimensionPacket;
  40. use pocketmine\network\protocol\DataPacket;
  41. use pocketmine\network\protocol\DropItemPacket;
  42. use pocketmine\network\protocol\FullChunkDataPacket;
  43. use pocketmine\network\protocol\Info;
  44. use pocketmine\network\protocol\RequestChunkRadiusPacket;
  45. use pocketmine\network\protocol\SetEntityLinkPacket;
  46. use pocketmine\network\protocol\BlockEntityDataPacket;
  47. use pocketmine\network\protocol\EntityEventPacket;
  48. use pocketmine\network\protocol\ExplodePacket;
  49. use pocketmine\network\protocol\HurtArmorPacket;
  50. use pocketmine\network\protocol\Info as ProtocolInfo;
  51. use pocketmine\network\protocol\InteractPacket;
  52. use pocketmine\network\protocol\LevelEventPacket;
  53. use pocketmine\network\protocol\DisconnectPacket;
  54. use pocketmine\network\protocol\LoginPacket;
  55. use pocketmine\network\protocol\PlayStatusPacket;
  56. use pocketmine\network\protocol\TextPacket;
  57. use pocketmine\network\protocol\MoveEntityPacket;
  58. use pocketmine\network\protocol\MovePlayerPacket;
  59. use pocketmine\network\protocol\PlayerActionPacket;
  60. use pocketmine\network\protocol\MobArmorEquipmentPacket;
  61. use pocketmine\network\protocol\MobEquipmentPacket;
  62. use pocketmine\network\protocol\RemoveBlockPacket;
  63. use pocketmine\network\protocol\RemoveEntityPacket;
  64. use pocketmine\network\protocol\RemovePlayerPacket;
  65. use pocketmine\network\protocol\RespawnPacket;
  66. use pocketmine\network\protocol\SetDifficultyPacket;
  67. use pocketmine\network\protocol\SetEntityDataPacket;
  68. use pocketmine\network\protocol\SetEntityMotionPacket;
  69. use pocketmine\network\protocol\SetHealthPacket;
  70. use pocketmine\network\protocol\SetPlayerGameTypePacket;
  71. use pocketmine\network\protocol\SetSpawnPositionPacket;
  72. use pocketmine\network\protocol\SetTimePacket;
  73. use pocketmine\network\protocol\StartGamePacket;
  74. use pocketmine\network\protocol\TakeItemEntityPacket;
  75. use pocketmine\network\protocol\BlockEventPacket;
  76. use pocketmine\network\protocol\UpdateBlockPacket;
  77. use pocketmine\network\protocol\UseItemPacket;
  78. use pocketmine\network\protocol\PlayerListPacket;
  79. use pocketmine\network\protocol\PlayerInputPacket;
  80. use pocketmine\Player;
  81. use pocketmine\Server;
  82. use pocketmine\utils\Binary;
  83. use pocketmine\utils\MainLogger;
  84. class Network {
  85. public static $BATCH_THRESHOLD = 512;
  86. /** @deprecated */
  87. const CHANNEL_NONE = 0;
  88. /** @deprecated */
  89. const CHANNEL_PRIORITY = 1; //Priority channel, only to be used when it matters
  90. /** @deprecated */
  91. const CHANNEL_WORLD_CHUNKS = 2; //Chunk sending
  92. /** @deprecated */
  93. const CHANNEL_MOVEMENT = 3; //Movement sending
  94. /** @deprecated */
  95. const CHANNEL_BLOCKS = 4; //Block updates or explosions
  96. /** @deprecated */
  97. const CHANNEL_WORLD_EVENTS = 5; //Entity, level or tile entity events
  98. /** @deprecated */
  99. const CHANNEL_ENTITY_SPAWNING = 6; //Entity spawn/despawn channel
  100. /** @deprecated */
  101. const CHANNEL_TEXT = 7; //Chat and other text stuff
  102. /** @deprecated */
  103. const CHANNEL_END = 31;
  104. /** @var \SplFixedArray */
  105. private $packetPool;
  106. /** @var Server */
  107. private $server;
  108. /** @var SourceInterface[] */
  109. private $interfaces = [];
  110. /** @var AdvancedSourceInterface[] */
  111. private $advancedInterfaces = [];
  112. private $upload = 0;
  113. private $download = 0;
  114. private $name;
  115. public function __construct(Server $server) {
  116. $this->registerPackets();
  117. $this->server = $server;
  118. }
  119. public function addStatistics($upload, $download) {
  120. $this->upload += $upload;
  121. $this->download += $download;
  122. }
  123. public function getUpload() {
  124. return $this->upload;
  125. }
  126. public function getDownload() {
  127. return $this->download;
  128. }
  129. public function resetStatistics() {
  130. $this->upload = 0;
  131. $this->download = 0;
  132. }
  133. /**
  134. * @return SourceInterface[]
  135. */
  136. public function getInterfaces() {
  137. return $this->interfaces;
  138. }
  139. public function processInterfaces() {
  140. foreach ($this->interfaces as $interface) {
  141. try {
  142. $interface->process();
  143. } catch (\Throwable $e) {
  144. $logger = $this->server->getLogger();
  145. if (\pocketmine\DEBUG > 1) {
  146. if ($logger instanceof MainLogger) {
  147. $logger->logException($e);
  148. }
  149. }
  150. $interface->emergencyShutdown();
  151. $this->unregisterInterface($interface);
  152. $logger->critical($this->server->getLanguage()->translateString("pocketmine.server.networkError", [get_class($interface), $e->getMessage()]));
  153. }
  154. }
  155. }
  156. /**
  157. * @param SourceInterface $interface
  158. */
  159. public function registerInterface(SourceInterface $interface) {
  160. $this->interfaces[$hash = spl_object_hash($interface)] = $interface;
  161. if ($interface instanceof AdvancedSourceInterface) {
  162. $this->advancedInterfaces[$hash] = $interface;
  163. $interface->setNetwork($this);
  164. }
  165. $interface->setName($this->name);
  166. }
  167. /**
  168. * @param SourceInterface $interface
  169. */
  170. public function unregisterInterface(SourceInterface $interface) {
  171. unset($this->interfaces[$hash = spl_object_hash($interface)],
  172. $this->advancedInterfaces[$hash]);
  173. }
  174. /**
  175. * Sets the server name shown on each interface Query
  176. *
  177. * @param string $name
  178. */
  179. public function setName($name) {
  180. $this->name = (string)$name;
  181. foreach ($this->interfaces as $interface) {
  182. $interface->setName($this->name);
  183. }
  184. }
  185. public function getName() {
  186. return $this->name;
  187. }
  188. public function updateName() {
  189. foreach ($this->interfaces as $interface) {
  190. $interface->setName($this->name);
  191. }
  192. }
  193. /**
  194. * @param int $id 0-255
  195. * @param DataPacket $class
  196. */
  197. public function registerPacket($id, $class) {
  198. $this->packetPool[$id] = new $class;
  199. }
  200. public function getServer() {
  201. return $this->server;
  202. }
  203. public function processBatch(BatchPacket $packet, Player $p) {
  204. $str = zlib_decode($packet->payload, 1024 * 1024 * 64); //Max 64MB
  205. $len = strlen($str);
  206. $offset = 0;
  207. try {
  208. while ($offset < $len) {
  209. $pkLen = Binary::readInt(substr($str, $offset, 4));
  210. $offset += 4;
  211. $buf = substr($str, $offset, $pkLen);
  212. $offset += $pkLen;
  213. if (($pk = $this->getPacket(ord($buf{1}))) !== null) {
  214. if ($pk::NETWORK_ID === Info::BATCH_PACKET) {
  215. throw new \InvalidStateException("Invalid BatchPacket inside BatchPacket");
  216. }
  217. $pk->setBuffer($buf, 2);
  218. $pk->decode();
  219. $p->handleDataPacket($pk);
  220. if ($pk->getOffset() <= 0) {
  221. return;
  222. }
  223. }
  224. }
  225. } catch (\Throwable $e) {
  226. if (\pocketmine\DEBUG > 1) {
  227. $logger = $this->server->getLogger();
  228. if ($logger instanceof MainLogger) {
  229. $logger->debug("BatchPacket " . " 0x" . bin2hex($packet->payload));
  230. $logger->logException($e);
  231. }
  232. }
  233. }
  234. }
  235. /**
  236. * @param $id
  237. *
  238. * @return DataPacket
  239. */
  240. public function getPacket($id) {
  241. /** @var DataPacket $class */
  242. $class = $this->packetPool[$id];
  243. if ($class !== null) {
  244. return clone $class;
  245. }
  246. return null;
  247. }
  248. /**
  249. * @param string $address
  250. * @param int $port
  251. * @param string $payload
  252. */
  253. public function sendPacket($address, $port, $payload) {
  254. foreach ($this->advancedInterfaces as $interface) {
  255. $interface->sendRawPacket($address, $port, $payload);
  256. }
  257. }
  258. /**
  259. * Blocks an IP address from the main interface. Setting timeout to -1 will block it forever
  260. *
  261. * @param string $address
  262. * @param int $timeout
  263. */
  264. public function blockAddress($address, $timeout = 300) {
  265. foreach ($this->advancedInterfaces as $interface) {
  266. $interface->blockAddress($address, $timeout);
  267. }
  268. }
  269. private function registerPackets() {
  270. $this->packetPool = new \SplFixedArray(256);
  271. $this->registerPacket(ProtocolInfo::LOGIN_PACKET, LoginPacket::class);
  272. $this->registerPacket(ProtocolInfo::PLAY_STATUS_PACKET, PlayStatusPacket::class);
  273. $this->registerPacket(ProtocolInfo::DISCONNECT_PACKET, DisconnectPacket::class);
  274. $this->registerPacket(ProtocolInfo::BATCH_PACKET, BatchPacket::class);
  275. $this->registerPacket(ProtocolInfo::TEXT_PACKET, TextPacket::class);
  276. $this->registerPacket(ProtocolInfo::SET_TIME_PACKET, SetTimePacket::class);
  277. $this->registerPacket(ProtocolInfo::START_GAME_PACKET, StartGamePacket::class);
  278. $this->registerPacket(ProtocolInfo::ADD_PLAYER_PACKET, AddPlayerPacket::class);
  279. $this->registerPacket(ProtocolInfo::REMOVE_PLAYER_PACKET, RemovePlayerPacket::class);
  280. $this->registerPacket(ProtocolInfo::ADD_ENTITY_PACKET, AddEntityPacket::class);
  281. $this->registerPacket(ProtocolInfo::REMOVE_ENTITY_PACKET, RemoveEntityPacket::class);
  282. $this->registerPacket(ProtocolInfo::ADD_ITEM_ENTITY_PACKET, AddItemEntityPacket::class);
  283. $this->registerPacket(ProtocolInfo::TAKE_ITEM_ENTITY_PACKET, TakeItemEntityPacket::class);
  284. $this->registerPacket(ProtocolInfo::MOVE_ENTITY_PACKET, MoveEntityPacket::class);
  285. $this->registerPacket(ProtocolInfo::MOVE_PLAYER_PACKET, MovePlayerPacket::class);
  286. $this->registerPacket(ProtocolInfo::REMOVE_BLOCK_PACKET, RemoveBlockPacket::class);
  287. $this->registerPacket(ProtocolInfo::UPDATE_BLOCK_PACKET, UpdateBlockPacket::class);
  288. $this->registerPacket(ProtocolInfo::ADD_PAINTING_PACKET, AddPaintingPacket::class);
  289. $this->registerPacket(ProtocolInfo::EXPLODE_PACKET, ExplodePacket::class);
  290. $this->registerPacket(ProtocolInfo::LEVEL_EVENT_PACKET, LevelEventPacket::class);
  291. $this->registerPacket(ProtocolInfo::BLOCK_EVENT_PACKET, BlockEventPacket::class);
  292. $this->registerPacket(ProtocolInfo::ENTITY_EVENT_PACKET, EntityEventPacket::class);
  293. $this->registerPacket(ProtocolInfo::MOB_EQUIPMENT_PACKET, MobEquipmentPacket::class);
  294. $this->registerPacket(ProtocolInfo::MOB_ARMOR_EQUIPMENT_PACKET, MobArmorEquipmentPacket::class);
  295. $this->registerPacket(ProtocolInfo::INTERACT_PACKET, InteractPacket::class);
  296. $this->registerPacket(ProtocolInfo::USE_ITEM_PACKET, UseItemPacket::class);
  297. $this->registerPacket(ProtocolInfo::PLAYER_ACTION_PACKET, PlayerActionPacket::class);
  298. $this->registerPacket(ProtocolInfo::HURT_ARMOR_PACKET, HurtArmorPacket::class);
  299. $this->registerPacket(ProtocolInfo::SET_ENTITY_DATA_PACKET, SetEntityDataPacket::class);
  300. $this->registerPacket(ProtocolInfo::SET_ENTITY_MOTION_PACKET, SetEntityMotionPacket::class);
  301. $this->registerPacket(ProtocolInfo::SET_ENTITY_LINK_PACKET, SetEntityLinkPacket::class);
  302. $this->registerPacket(ProtocolInfo::SET_HEALTH_PACKET, SetHealthPacket::class);
  303. $this->registerPacket(ProtocolInfo::SET_SPAWN_POSITION_PACKET, SetSpawnPositionPacket::class);
  304. $this->registerPacket(ProtocolInfo::ANIMATE_PACKET, AnimatePacket::class);
  305. $this->registerPacket(ProtocolInfo::RESPAWN_PACKET, RespawnPacket::class);
  306. $this->registerPacket(ProtocolInfo::DROP_ITEM_PACKET, DropItemPacket::class);
  307. $this->registerPacket(ProtocolInfo::CONTAINER_OPEN_PACKET, ContainerOpenPacket::class);
  308. $this->registerPacket(ProtocolInfo::CONTAINER_CLOSE_PACKET, ContainerClosePacket::class);
  309. $this->registerPacket(ProtocolInfo::CONTAINER_SET_SLOT_PACKET, ContainerSetSlotPacket::class);
  310. $this->registerPacket(ProtocolInfo::CONTAINER_SET_DATA_PACKET, ContainerSetDataPacket::class);
  311. $this->registerPacket(ProtocolInfo::CONTAINER_SET_CONTENT_PACKET, ContainerSetContentPacket::class);
  312. $this->registerPacket(ProtocolInfo::CRAFTING_DATA_PACKET, CraftingDataPacket::class);
  313. $this->registerPacket(ProtocolInfo::CRAFTING_EVENT_PACKET, CraftingEventPacket::class);
  314. $this->registerPacket(ProtocolInfo::ADVENTURE_SETTINGS_PACKET, AdventureSettingsPacket::class);
  315. $this->registerPacket(ProtocolInfo::BLOCK_ENTITY_DATA_PACKET, BlockEntityDataPacket::class);
  316. $this->registerPacket(ProtocolInfo::FULL_CHUNK_DATA_PACKET, FullChunkDataPacket::class);
  317. $this->registerPacket(ProtocolInfo::SET_DIFFICULTY_PACKET, SetDifficultyPacket::class);
  318. $this->registerPacket(ProtocolInfo::PLAYER_LIST_PACKET, PlayerListPacket::class);
  319. $this->registerPacket(ProtocolInfo::PLAYER_INPUT_PACKET, PlayerInputPacket::class);
  320. $this->registerPacket(ProtocolInfo::SET_PLAYER_GAMETYPE_PACKET, SetPlayerGameTypePacket::class);
  321. $this->registerPacket(ProtocolInfo::CHANGE_DIMENSION_PACKET, ChangeDimensionPacket::class);
  322. $this->registerPacket(ProtocolInfo::REQUEST_CHUNK_RADIUS_PACKET, RequestChunkRadiusPacket::class);
  323. $this->registerPacket(ProtocolInfo::CHUNK_RADIUS_UPDATE_PACKET, ChunkRadiusUpdatePacket::class);
  324. }
  325. }