Completed
Push — master ( d37c8b...c70816 )
by Camilo
02:32
created

ConnAck::getConnectReturnCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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