Skip to content

Commit c511e59

Browse files
authored
Merge pull request #22 from jjok/keep-alive
Keep Alive support
2 parents 68c22a1 + 848303a commit c511e59

File tree

5 files changed

+79
-26
lines changed

5 files changed

+79
-26
lines changed

examples/config.php.example

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
$config = array(
44
'server' => 'yourMqttBroker.tld',
55
'port' => 1883,
6-
'options' => null,
6+
'options' => new \oliverlorenz\reactphpmqtt\packet\ConnectionOptions(array(
7+
'keepAlive' => 120,
8+
)),
79
);
810

911
return $config;

src/Connector.php

+13-8
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ public function create(
7676
->then(function (Stream $stream) {
7777
return $this->listenForPackets($stream);
7878
})
79-
->then(function(Stream $stream) {
80-
return $this->keepAlive($stream);
79+
->then(function(Stream $stream) use ($options) {
80+
return $this->keepAlive($stream, $options->keepAlive);
8181
});
8282
}
8383

@@ -119,12 +119,16 @@ private function listenForPackets(Stream $stream)
119119
return $deferred->promise();
120120
}
121121

122-
private function keepAlive(Stream $stream)
122+
private function keepAlive(Stream $stream, $keepAlive)
123123
{
124-
$this->getLoop()->addPeriodicTimer(10, function(Timer $timer) use ($stream) {
125-
$packet = new PingRequest($this->version);
126-
$this->sendPacketToStream($stream, $packet);
127-
});
124+
if($keepAlive > 0) {
125+
$interval = $keepAlive / 2;
126+
127+
$this->getLoop()->addPeriodicTimer($interval, function(Timer $timer) use ($stream) {
128+
$packet = new PingRequest($this->version);
129+
$this->sendPacketToStream($stream, $packet);
130+
});
131+
}
128132

129133
return new FulfilledPromise($stream);
130134
}
@@ -142,7 +146,8 @@ public function connect(Stream $stream, ConnectionOptions $options) {
142146
$options->willTopic,
143147
$options->willMessage,
144148
$options->willQos,
145-
$options->willRetain
149+
$options->willRetain,
150+
$options->keepAlive
146151
);
147152
$message = $packet->get();
148153
echo MessageHelper::getReadableByRawString($message);

src/packet/Connect.php

+25-9
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class Connect extends ControlPacket {
3939
/** @var null */
4040
protected $willRetain;
4141

42+
/** @var int */
43+
private $keepAlive;
44+
4245
/**
4346
* @param Version $version
4447
* @param string|null $username
@@ -49,6 +52,7 @@ class Connect extends ControlPacket {
4952
* @param string|null $willMessage
5053
* @param bool|null $willQos
5154
* @param null $willRetain
55+
* @param int $keepAlive
5256
*/
5357
public function __construct(
5458
Version $version,
@@ -59,7 +63,8 @@ public function __construct(
5963
$willTopic = null,
6064
$willMessage = null,
6165
$willQos = null,
62-
$willRetain = null
66+
$willRetain = null,
67+
$keepAlive = 0
6368
) {
6469
parent::__construct($version);
6570
$this->clientId = $clientId;
@@ -70,6 +75,7 @@ public function __construct(
7075
$this->willMessage = $willMessage;
7176
$this->willQos = boolval($willQos);
7277
$this->willRetain = $willRetain;
78+
$this->keepAlive = $keepAlive;
7379
$this->buildPayload();
7480
}
7581

@@ -101,14 +107,24 @@ public static function getControlPacketType()
101107
*/
102108
protected function getVariableHeader()
103109
{
104-
return chr(ControlPacketType::MOST_SIGNIFICANT_BYTE) // byte 1
105-
. chr(strlen($this->version->getProtocolIdentifierString())) // byte 2
106-
. $this->version->getProtocolIdentifierString() // byte 3,4,5,6
107-
. chr($this->version->getProtocolVersion()) // byte 7
108-
. chr($this->getConnectFlags()) // byte 8
109-
. chr(0) // byte 9
110-
. chr(10) // byte 10
111-
;
110+
return chr(ControlPacketType::MOST_SIGNIFICANT_BYTE) // byte 1
111+
. chr(strlen($this->version->getProtocolIdentifierString())) // byte 2
112+
. $this->version->getProtocolIdentifierString() // byte 3,4,5,6
113+
. chr($this->version->getProtocolVersion()) // byte 7
114+
. chr($this->getConnectFlags()) // byte 8
115+
. $this->getKeepAlive(); // byte 9,10
116+
}
117+
118+
/**
119+
* @return string
120+
*/
121+
private function getKeepAlive()
122+
{
123+
$msb = $this->keepAlive >> 8;
124+
$lsb = $this->keepAlive % 256;
125+
126+
return chr($msb)
127+
. chr($lsb);
112128
}
113129

114130
/**

src/packet/ConnectionOptions.php

+9
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ class ConnectionOptions
100100
*/
101101
public $willRetain = false;
102102

103+
/**
104+
* The Keep Alive is a time interval measured in seconds.
105+
*
106+
* @see http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Keep_Alive
107+
*
108+
* @var int
109+
*/
110+
public $keepAlive = 0;
111+
103112
/**
104113
* ConnectionOptions constructor.
105114
*

tests/unit/packet/ConnectTest.php

+29-8
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function testGetHeaderTestVariableHeaderWithoutConnectFlags()
4040
chr(4) . // byte 7
4141
chr(0) . // byte 8
4242
chr(0) . // byte 9
43-
chr(10) // byte 10
43+
chr(0) // byte 10
4444
),
4545
MessageHelper::getReadableByRawString(substr($packet->get(), 2, 10))
4646
);
@@ -59,7 +59,7 @@ public function testGetHeaderTestVariableHeaderWithConnectFlagsCleanSession()
5959
chr(4) . // byte 7
6060
chr(2) . // byte 8
6161
chr(0) . // byte 9
62-
chr(10) // byte 10
62+
chr(0) // byte 10
6363
),
6464
MessageHelper::getReadableByRawString(substr($packet->get(), 2, 10))
6565
);
@@ -80,7 +80,7 @@ public function testGetHeaderTestVariableHeaderWithConnectFlagWillFlag()
8080
chr(4) . // byte 7
8181
chr(4) . // byte 8
8282
chr(0) . // byte 9
83-
chr(10) // byte 10
83+
chr(0) // byte 10
8484
),
8585
MessageHelper::getReadableByRawString(substr($packet->get(), 2, 10))
8686
);
@@ -101,7 +101,7 @@ public function testGetHeaderTestVariableHeaderWithConnectFlagWillRetain()
101101
chr(4) . // byte 7
102102
chr(32) . // byte 8
103103
chr(0) . // byte 9
104-
chr(10) // byte 10
104+
chr(0) // byte 10
105105
),
106106
MessageHelper::getReadableByRawString(substr($packet->get(), 2, 10))
107107
);
@@ -122,7 +122,7 @@ public function testGetHeaderTestVariableHeaderWithConnectFlagUsername()
122122
chr(4) . // byte 7
123123
chr(128) . // byte 8
124124
chr(0) . // byte 9
125-
chr(10) // byte 10
125+
chr(0) // byte 10
126126
),
127127
MessageHelper::getReadableByRawString(substr($packet->get(), 2, 10))
128128
);
@@ -143,7 +143,7 @@ public function testGetHeaderTestVariableHeaderWithConnectFlagPassword()
143143
chr(4) . // byte 7
144144
chr(64) . // byte 8
145145
chr(0) . // byte 9
146-
chr(10) // byte 10
146+
chr(0) // byte 10
147147
),
148148
MessageHelper::getReadableByRawString(substr($packet->get(), 2, 10))
149149
);
@@ -164,7 +164,7 @@ public function testGetHeaderTestVariableHeaderWithConnectFlagWillWillQos()
164164
chr(4) . // byte 7
165165
chr(8) . // byte 8
166166
chr(0) . // byte 9
167-
chr(10) // byte 10
167+
chr(0) // byte 10
168168
),
169169
MessageHelper::getReadableByRawString(substr($packet->get(), 2, 10))
170170
);
@@ -185,7 +185,28 @@ public function testGetHeaderTestVariableHeaderWithConnectFlagUserNamePasswordCl
185185
chr(4) . // byte 7
186186
chr(194) . // byte 8
187187
chr(0) . // byte 9
188-
chr(10) // byte 10
188+
chr(0) // byte 10
189+
),
190+
MessageHelper::getReadableByRawString(substr($packet->get(), 2, 10))
191+
);
192+
}
193+
194+
public function testBytesNineAndTenOfVariableHeaderAreKeepAlive()
195+
{
196+
$version = new \oliverlorenz\reactphpmqtt\protocol\Version4();
197+
$packet = new \oliverlorenz\reactphpmqtt\packet\Connect(
198+
$version, null, null, null, true, null, null, null, null, 999
199+
);
200+
201+
$this->assertEquals(
202+
MessageHelper::getReadableByRawString(
203+
chr(0) . // byte 1
204+
chr(4) . // byte 2
205+
'MQTT' . // byte 3,4,5,6
206+
chr(4) . // byte 7
207+
chr(2) . // byte 8
208+
chr(3) . // byte 9
209+
chr(231) // byte 10
189210
),
190211
MessageHelper::getReadableByRawString(substr($packet->get(), 2, 10))
191212
);

0 commit comments

Comments
 (0)