PocketMine-MP 5.21.1 git-2ff647079265e7c600203af4fd902b15e99d49a4
EncapsulatedPacket.php
1<?php
2
3/*
4 * This file is part of RakLib.
5 * Copyright (C) 2014-2022 PocketMine Team <https://github.com/pmmp/RakLib>
6 *
7 * RakLib is not affiliated with Jenkins Software LLC nor RakNet.
8 *
9 * RakLib is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 */
14
15declare(strict_types=1);
16
17namespace raklib\protocol;
18
22use function ceil;
23use function chr;
24use function strlen;
25
27 private const RELIABILITY_SHIFT = 5;
28 private const RELIABILITY_FLAGS = 0b111 << self::RELIABILITY_SHIFT;
29
30 private const SPLIT_FLAG = 0b00010000;
31
32 public const SPLIT_INFO_LENGTH = 4 + 2 + 4; //split count (4) + split ID (2) + split index (4)
33
34 public int $reliability;
35 public ?int $messageIndex = null;
36 public ?int $sequenceIndex = null;
37 public ?int $orderIndex = null;
38 public ?int $orderChannel = null;
39 public ?SplitPacketInfo $splitInfo = null;
40 public string $buffer = "";
41 public ?int $identifierACK = null;
42
46 public static function fromBinary(BinaryStream $stream) : EncapsulatedPacket{
47 $packet = new EncapsulatedPacket();
48
49 $flags = $stream->getByte();
50 $packet->reliability = $reliability = ($flags & self::RELIABILITY_FLAGS) >> self::RELIABILITY_SHIFT;
51 $hasSplit = ($flags & self::SPLIT_FLAG) !== 0;
52
53 $length = (int) ceil($stream->getShort() / 8);
54 if($length === 0){
55 throw new BinaryDataException("Encapsulated payload length cannot be zero");
56 }
57
58 if(PacketReliability::isReliable($reliability)){
59 $packet->messageIndex = $stream->getLTriad();
60 }
61
62 if(PacketReliability::isSequenced($reliability)){
63 $packet->sequenceIndex = $stream->getLTriad();
64 }
65
66 if(PacketReliability::isSequencedOrOrdered($reliability)){
67 $packet->orderIndex = $stream->getLTriad();
68 $packet->orderChannel = $stream->getByte();
69 }
70
71 if($hasSplit){
72 $splitCount = $stream->getInt();
73 $splitID = $stream->getShort();
74 $splitIndex = $stream->getInt();
75 $packet->splitInfo = new SplitPacketInfo($splitID, $splitIndex, $splitCount);
76 }
77
78 $packet->buffer = $stream->get($length);
79 return $packet;
80 }
81
82 public function toBinary() : string{
83 return
84 chr(($this->reliability << self::RELIABILITY_SHIFT) | ($this->splitInfo !== null ? self::SPLIT_FLAG : 0)) .
85 Binary::writeShort(strlen($this->buffer) << 3) .
86 (PacketReliability::isReliable($this->reliability) ? Binary::writeLTriad($this->messageIndex) : "") .
87 (PacketReliability::isSequenced($this->reliability) ? Binary::writeLTriad($this->sequenceIndex) : "") .
88 (PacketReliability::isSequencedOrOrdered($this->reliability) ? Binary::writeLTriad($this->orderIndex) . chr($this->orderChannel) : "") .
89 ($this->splitInfo !== null ? Binary::writeInt($this->splitInfo->getTotalPartCount()) . Binary::writeShort($this->splitInfo->getId()) . Binary::writeInt($this->splitInfo->getPartIndex()) : "")
90 . $this->buffer;
91 }
92
96 public function getHeaderLength() : int{
97 return
98 1 + //reliability
99 2 + //length
100 (PacketReliability::isReliable($this->reliability) ? 3 : 0) + //message index
101 (PacketReliability::isSequenced($this->reliability) ? 3 : 0) + //sequence index
102 (PacketReliability::isSequencedOrOrdered($this->reliability) ? 3 + 1 : 0) + //order index (3) + order channel (1)
103 ($this->splitInfo !== null ? self::SPLIT_INFO_LENGTH : 0);
104 }
105
106 public function getTotalLength() : int{
107 return $this->getHeaderLength() + strlen($this->buffer);
108 }
109
110 public function __toString() : string{
111 return $this->toBinary();
112 }
113}
static fromBinary(BinaryStream $stream)