1 | <?php |
||
24 | class Handshake implements HandshakeInterface |
||
25 | { |
||
26 | /** |
||
27 | * @var string |
||
28 | */ |
||
29 | private $username; |
||
30 | |||
31 | /** |
||
32 | * @var string |
||
33 | */ |
||
34 | private $password; |
||
35 | |||
36 | /** |
||
37 | * @var string |
||
38 | */ |
||
39 | private $protocolVersion = 0; |
||
40 | |||
41 | /** |
||
42 | * @var int |
||
43 | */ |
||
44 | private $state; |
||
45 | |||
46 | /** |
||
47 | * @var string |
||
48 | */ |
||
49 | private $myR; |
||
50 | |||
51 | /** |
||
52 | * @var string |
||
53 | */ |
||
54 | private $clientFirstMessage; |
||
55 | |||
56 | /** |
||
57 | * @var string |
||
58 | */ |
||
59 | private $serverSignature; |
||
60 | |||
61 | /** |
||
62 | * @var int |
||
63 | */ |
||
64 | private $version; |
||
65 | |||
66 | /** |
||
67 | * @param string $username |
||
68 | * @param string $password |
||
69 | * @param int $version |
||
70 | */ |
||
71 | 22 | public function __construct(string $username, string $password, int $version) |
|
72 | { |
||
73 | 22 | $this->username = $username; |
|
74 | 22 | $this->password = $password; |
|
75 | 22 | $this->state = 0; |
|
76 | 22 | $this->version = $version; |
|
77 | 22 | } |
|
78 | |||
79 | /** |
||
80 | * @inheritdoc |
||
81 | * @throws \RuntimeException |
||
82 | * @throws Exception |
||
83 | */ |
||
84 | 20 | public function hello(StreamInterface $stream): void |
|
85 | { |
||
86 | try { |
||
87 | 20 | $handshakeResponse = null; |
|
88 | 20 | while (true) { |
|
89 | 20 | if (!$stream->isWritable()) { |
|
90 | 1 | throw new Exception('Not connected'); |
|
91 | } |
||
92 | |||
93 | 19 | $this->checkResponse($handshakeResponse); |
|
94 | |||
95 | try { |
||
96 | 19 | $msg = $this->nextMessage($handshakeResponse); |
|
97 | 2 | } catch (Exception $e) { |
|
98 | 2 | $stream->close(); |
|
99 | 2 | throw $e; |
|
100 | } |
||
101 | |||
102 | 19 | if ($msg === 'successful') { |
|
103 | 15 | break; |
|
104 | } |
||
105 | |||
106 | 19 | if ($msg !== '') { |
|
107 | 19 | $stream->write($msg); |
|
108 | } |
||
109 | |||
110 | // Read null-terminated response |
||
111 | 19 | $handshakeResponse = $stream->getContents(); |
|
112 | } |
||
113 | 5 | } catch (Exception $e) { |
|
114 | 5 | $stream->close(); |
|
115 | 5 | throw $e; |
|
116 | } |
||
117 | |||
118 | 15 | } |
|
119 | |||
120 | /** |
||
121 | * @param $response |
||
122 | * @return string |
||
123 | * @throws Exception |
||
124 | */ |
||
125 | 19 | private function nextMessage(string $response = null): ?string |
|
126 | { |
||
127 | 19 | switch ($this->state) { |
|
128 | 19 | case 0: |
|
|
|||
129 | 19 | return $this->createHandshakeMessage($response); |
|
130 | 17 | case 1: |
|
131 | 17 | return $this->verifyProtocol($response); |
|
132 | 15 | case 2: |
|
133 | 15 | return $this->createAuthenticationMessage($response); |
|
134 | 15 | case 3: |
|
135 | 15 | return $this->verifyAuthentication($response); |
|
136 | default: |
||
137 | throw new Exception('Illegal handshake state'); |
||
138 | } |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * @param string $password |
||
143 | * @param string $salt |
||
144 | * @param int $iterations |
||
145 | * @return string |
||
146 | */ |
||
147 | 15 | private function pkbdf2Hmac(string $password, string $salt, int $iterations): string |
|
158 | |||
159 | /** |
||
160 | * @param null|string $response |
||
161 | * @return string |
||
162 | */ |
||
163 | 19 | private function createHandshakeMessage(?string $response): string |
|
185 | |||
186 | /** |
||
187 | * @param null|string $response |
||
188 | * @return string |
||
189 | * @throws Exception |
||
190 | */ |
||
191 | 17 | private function verifyProtocol(?string $response): string |
|
214 | |||
215 | /** |
||
216 | * @param $response |
||
217 | * @return null|string |
||
218 | * @throws Exception |
||
219 | */ |
||
220 | 15 | private function createAuthenticationMessage($response): string |
|
265 | |||
266 | /** |
||
267 | * @param null|string $response |
||
268 | * @return string |
||
269 | * @throws Exception |
||
270 | */ |
||
271 | 15 | private function verifyAuthentication(string $response): string |
|
289 | |||
290 | /** |
||
291 | * @param null|string $handshakeResponse |
||
292 | */ |
||
293 | 19 | private function checkResponse(?string $handshakeResponse): void |
|
300 | |||
301 | /** |
||
302 | * @param string $signature |
||
303 | * @throws Exception |
||
304 | */ |
||
305 | 15 | private function checkSignature(string $signature): void |
|
311 | } |
||
312 |
As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next
break
.There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.