ConnAck::throwConnectException()   A
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 19
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 16
c 1
b 0
f 0
dl 0
loc 19
ccs 16
cts 16
cp 1
rs 9.1111
cc 6
nc 6
nop 0
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace unreal4u\MQTT\Protocol;
6
7
use unreal4u\MQTT\Exceptions\Connect\BadUsernameOrPassword;
8
use unreal4u\MQTT\Exceptions\Connect\GenericError;
9
use unreal4u\MQTT\Exceptions\Connect\IdentifierRejected;
10
use unreal4u\MQTT\Exceptions\Connect\NotAuthorized;
11
use unreal4u\MQTT\Exceptions\Connect\ServerUnavailable;
12
use unreal4u\MQTT\Exceptions\Connect\UnacceptableProtocolVersion;
13
use unreal4u\MQTT\Internals\ClientInterface;
14
use unreal4u\MQTT\Internals\ProtocolBase;
15
use unreal4u\MQTT\Internals\ReadableContent;
16
use unreal4u\MQTT\Internals\ReadableContentInterface;
17
use unreal4u\MQTT\Internals\WritableContentInterface;
18
19
use function ord;
20
use function sprintf;
21
22
/**
23
 * The CONNACK Packet is the packet sent by the Server in response to a CONNECT Packet received from a Client.
24
 */
25
final class ConnAck extends ProtocolBase implements ReadableContentInterface
26
{
27 1
    use ReadableContent;
28
29
    private const CONTROL_PACKET_VALUE = 2;
30
31
    /**
32
     * The connect return code. If a server sends a CONNACK packet containing a non-zero return code it MUST then close
33
     * the Network Connection
34
     *
35
     * @see http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Table_3.1_-
36
     *
37
     * 0 = Connection accepted
38
     * 1 = Connection Refused, unacceptable protocol version
39
     * 2 = Connection Refused, identifier rejected
40
     * 3 = Connection Refused, Server unavailable
41
     * 4 = Connection Refused, bad user name or password
42
     * 5 = Connection Refused, not authorized
43
     * 6-255 = Reserved for future use
44
     * @var int
45
     */
46
    private $connectReturnCode = -1;
47
48
    /**
49
     * @inheritdoc
50
     *
51
     * @param string $rawMQTTHeaders
52
     * @param ClientInterface $client
53
     * @return ReadableContentInterface
54
     * @throws GenericError
55
     * @throws NotAuthorized
56
     * @throws BadUsernameOrPassword
57
     * @throws ServerUnavailable
58
     * @throws IdentifierRejected
59
     * @throws UnacceptableProtocolVersion
60
     */
61 8
    public function fillObject(string $rawMQTTHeaders, ClientInterface $client): ReadableContentInterface
62
    {
63 8
        $this->connectReturnCode = ord($rawMQTTHeaders[3]);
64 8
        if ($this->connectReturnCode !== 0) {
65
            // We have detected a problem while connecting to the broker, send out the correct exception
66 6
            $this->throwConnectException();
67
        }
68
69 2
        return $this;
70
    }
71
72
    /**
73
     * Don't know why you should ever need this, but don't allow to overwrite it
74
     * @return int
75
     */
76 1
    public function getConnectReturnCode(): int
77
    {
78 1
        return $this->connectReturnCode;
79
    }
80
81
    /**
82
     * Will throw an exception in case there is something bad with the connection
83
     *
84
     * @see http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc385349257
85
     *
86
     * @return ConnAck
87
     * @throws GenericError
88
     * @throws NotAuthorized
89
     * @throws BadUsernameOrPassword
90
     * @throws ServerUnavailable
91
     * @throws IdentifierRejected
92
     * @throws UnacceptableProtocolVersion
93
     */
94 6
    private function throwConnectException(): self
95
    {
96 6
        switch ($this->connectReturnCode) {
97 6
            case 1:
98 1
                throw new UnacceptableProtocolVersion(
99 1
                    'The Server does not support the level of the MQTT protocol requested by the Client'
100
                );
101 5
            case 2:
102 1
                throw new IdentifierRejected('The Client identifier is correct UTF-8 but not allowed by the Server');
103 4
            case 3:
104 1
                throw new ServerUnavailable('The Network Connection has been made but the MQTT service is unavailable');
105 3
            case 4:
106 1
                throw new BadUsernameOrPassword('The data in the user name or password is malformed');
107 2
            case 5:
108 1
                throw new NotAuthorized('The Client is not authorized to connect');
109
            default:
110 1
                throw new GenericError(sprintf(
111 1
                    'Reserved for future use or error not implemented yet (Error code: %d)',
112 1
                    $this->connectReturnCode
113
                ));
114
        }
115
    }
116
117
    /**
118
     * @inheritdoc
119
     */
120 1
    public function performSpecialActions(ClientInterface $client, WritableContentInterface $originalRequest): bool
121
    {
122
        $client
123 1
            ->setConnected(true)
124 1
            ->updateLastCommunication();
125
126 1
        return true;
127
    }
128
129
    /**
130
     * @inheritdoc
131
     */
132 1
    public function getOriginControlPacket(): int
133
    {
134 1
        return Connect::getControlPacketValue();
135
    }
136
}
137