Completed
Pull Request — master (#110)
by Charlotte
06:09
created

ServerHandshake::verify()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 34
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
dl 0
loc 34
ccs 0
cts 29
cp 0
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 18
nc 6
nop 1
crap 56
1
<?php
2
3
/**
4
 * This file is a part of Woketo package.
5
 *
6
 * (c) Nekland <[email protected]>
7
 *
8
 * For the full license, take a look to the LICENSE file
9
 * on the root directory of this project
10
 */
11
12
namespace Nekland\Woketo\Rfc6455;
13
use Nekland\Woketo\Exception\WebsocketException;
14
use Nekland\Woketo\Exception\WebsocketVersionException;
15
use Nekland\Woketo\Http\Request;
16
use Nekland\Woketo\Http\Response;
17
18
/**
19
 * Class ServerHandshake
20
 *
21
 * This class is highly inspired by ratchetphp/RFC6455.
22
 */
23
class ServerHandshake
24
{
25
    const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
26
    const SUPPORTED_VERSIONS = [13];
27
28
    /**
29
     * Used when doing the handshake to encode the key, verifying client/server are speaking the same language
30
     * @param string   $key
31
     * @param Response $response
32
     * @return string
33
     */
34
    public function sign($key, Response $response = null)
35
    {
36
        if ($key instanceof Request) {
37
            $key = $key->getHeader('Sec-WebSocket-Key');
38
        }
39
40
        $sign = \base64_encode(\sha1($key . ServerHandshake::GUID, true));
41
42
        if (null !== $response) {
43
            $response->addHeader('Sec-WebSocket-Accept', $sign);
44
        }
45
46
        return $sign;
47
    }
48
49
    /**
50
     * @param Request $request
51
     * @return bool
52
     * @throws WebsocketException
53
     */
54
    public function verify(Request $request)
55
    {
56
        if ($request->getHttpVersion() !== 'HTTP/1.1') {
57
            throw new WebsocketException(
58
                \sprintf('Wrong http version, HTTP/1.1 expected, "%s" received.', $request->getHttpVersion())
59
            );
60
        }
61
62
        if ($request->getMethod() !== 'GET') {
63
            throw new WebsocketException(
64
                \sprintf('Wrong http method, GET expected, "%" received.', $request->getMethod())
65
            );
66
        }
67
68
        $headers = $request->getHeaders();
69
        if (empty($headers['Sec-WebSocket-Key'])) {
70
            throw new WebsocketException(
71
                \sprintf('Missing websocket key header.')
72
            );
73
        }
74
75
        if (empty($headers['Upgrade']) || 'websocket' !== \strtolower($headers['Upgrade'])) {
76
            throw new WebsocketException(
77
                \sprintf('Wrong or missing upgrade header.')
78
            );
79
        }
80
        
81
        $version = $headers->get('Sec-WebSocket-Version');
82
        if (!\in_array($version, ServerHandshake::SUPPORTED_VERSIONS)) {
83
            throw new WebsocketVersionException(sprintf('Version %s not supported by Woketo for now.', $version));
84
        }
85
86
        return true;
87
    }
88
}
89