PocketMine-MP 5.15.1 git-08c6e63aac45a450fe3b437616ee8aa2500e04e2
LoginPacket.php
1<?php
2
3/*
4 * This file is part of BedrockProtocol.
5 * Copyright (C) 2014-2022 PocketMine Team <https://github.com/pmmp/BedrockProtocol>
6 *
7 * BedrockProtocol is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
13declare(strict_types=1);
14
15namespace pocketmine\network\mcpe\protocol;
16
20use function count;
21use function is_array;
22use function is_string;
23use function json_decode;
24use function json_encode;
25use function strlen;
26use const JSON_THROW_ON_ERROR;
27
28class LoginPacket extends DataPacket implements ServerboundPacket{
29 public const NETWORK_ID = ProtocolInfo::LOGIN_PACKET;
30
31 public int $protocol;
32 public JwtChain $chainDataJwt;
33 public string $clientDataJwt;
34
38 public static function create(int $protocol, JwtChain $chainDataJwt, string $clientDataJwt) : self{
39 $result = new self;
40 $result->protocol = $protocol;
41 $result->chainDataJwt = $chainDataJwt;
42 $result->clientDataJwt = $clientDataJwt;
43 return $result;
44 }
45
46 public function canBeSentBeforeLogin() : bool{
47 return true;
48 }
49
50 protected function decodePayload(PacketSerializer $in) : void{
51 $this->protocol = $in->getInt();
52 $this->decodeConnectionRequest($in->getString());
53 }
54
55 protected function decodeConnectionRequest(string $binary) : void{
56 $connRequestReader = new BinaryStream($binary);
57
58 $chainDataJsonLength = $connRequestReader->getLInt();
59 if($chainDataJsonLength <= 0){
60 //technically this is always positive; the problem results because getLInt() is implicitly signed
61 //this is inconsistent with many other methods, but we can't do anything about that for now
62 throw new PacketDecodeException("Length of chain data JSON must be positive");
63 }
64 try{
65 $chainDataJson = json_decode($connRequestReader->get($chainDataJsonLength), associative: true, flags: JSON_THROW_ON_ERROR);
66 }catch(\JsonException $e){
67 throw new PacketDecodeException("Failed decoding chain data JSON: " . $e->getMessage());
68 }
69 if(!is_array($chainDataJson) || count($chainDataJson) !== 1 || !isset($chainDataJson["chain"])){
70 throw new PacketDecodeException("Chain data must be a JSON object containing only the 'chain' element");
71 }
72 if(!is_array($chainDataJson["chain"])){
73 throw new PacketDecodeException("Chain data 'chain' element must be a list of strings");
74 }
75 $jwts = [];
76 foreach($chainDataJson["chain"] as $jwt){
77 if(!is_string($jwt)){
78 throw new PacketDecodeException("Chain data 'chain' must contain only strings");
79 }
80 $jwts[] = $jwt;
81 }
82 //TODO: this pointless JwtChain model is here for BC - get rid of it next chance we get
83 $wrapper = new JwtChain;
84 $wrapper->chain = $jwts;
85 $this->chainDataJwt = $wrapper;
86
87 $clientDataJwtLength = $connRequestReader->getLInt();
88 if($clientDataJwtLength <= 0){
89 //technically this is always positive; the problem results because getLInt() is implicitly signed
90 //this is inconsistent with many other methods, but we can't do anything about that for now
91 throw new PacketDecodeException("Length of clientData JWT must be positive");
92 }
93 $this->clientDataJwt = $connRequestReader->get($clientDataJwtLength);
94 }
95
96 protected function encodePayload(PacketSerializer $out) : void{
97 $out->putInt($this->protocol);
98 $out->putString($this->encodeConnectionRequest());
99 }
100
101 protected function encodeConnectionRequest() : string{
102 $connRequestWriter = new BinaryStream();
103
104 $chainDataJson = json_encode($this->chainDataJwt, JSON_THROW_ON_ERROR);
105 $connRequestWriter->putLInt(strlen($chainDataJson));
106 $connRequestWriter->put($chainDataJson);
107
108 $connRequestWriter->putLInt(strlen($this->clientDataJwt));
109 $connRequestWriter->put($this->clientDataJwt);
110
111 return $connRequestWriter->getBuffer();
112 }
113
114 public function handle(PacketHandlerInterface $handler) : bool{
115 return $handler->handleLogin($this);
116 }
117}
handle(PacketHandlerInterface $handler)
static create(int $protocol, JwtChain $chainDataJwt, string $clientDataJwt)
Definition: LoginPacket.php:38