function check_name($topic_name) { try { echo "Checking \"{$topic_name}\" ... "; Utility::CheckTopicName($topic_name); echo "[32mPASS[0m"; } catch (Exception $e) { echo "[31mFAILED[0m " . $e->getMessage(); } echo "\n"; }
protected function payload() { if (empty($this->topics)) { /* The Topic Filters in an UNSUBSCRIBE packet MUST be UTF-8 encoded strings as defined in Section 1.5.3, packed contiguously [MQTT-3.10.3-1]. */ throw new Exception('Missing topics!'); } $buffer = ""; # Payload foreach ($this->topics as $topic) { $buffer .= Utility::PackStringWithLength($topic); } return $buffer; }
protected function payload() { if (empty($this->topics)) { /* The payload of a SUBSCRIBE packet MUST contain at least one Topic Filter / QoS pair. A SUBSCRIBE packet with no payload is a protocol violation [MQTT-3.8.3-3] */ throw new Exception('Missing topics!'); } $buffer = ""; # Payload foreach ($this->topics as $topic => $qos_max) { $buffer .= Utility::PackStringWithLength($topic); $buffer .= chr($qos_max); } return $buffer; }
/** * Will * * @param string $topic Will Topic * @param string $message Will Message * @param int $qos Will QoS * @param int $retain Will Retain * @throws Exception */ public function __construct($topic, $message, $qos = 1, $retain = 0) { /* If the Will Flag is set to 0 the Will QoS and Will Retain fields in the Connect Flags MUST be set to zero and the Will Topic and Will Message fields MUST NOT be present in the payload [MQTT-3.1.2-11]. */ if (!$topic || !$message) { throw new Exception('Topic/Message MUST NOT be empty in Will Message'); } Utility::CheckTopicName($topic); $this->topic = $topic; $this->message = $message; Utility::CheckQoS($qos); $this->qos = (int) $qos; $this->retain = $retain ? 1 : 0; }
try { var_dump(Utility::ValidateUTF8(chr(0xef) . chr(0xbb) . chr(0xbf))); } catch (\Exception $e) { var_dump($e->getMessage()); } try { var_dump(Utility::ValidateUTF8(chr(0xef) . chr(0xff) . chr(0xa))); } catch (\Exception $e) { var_dump($e->getMessage()); } try { var_dump(Utility::ValidateUTF8(chr(0xc0) . chr(0xa))); } catch (\Exception $e) { var_dump($e->getMessage()); } try { var_dump(Utility::ValidateUTF8(chr(0xc0) . chr(0xba))); } catch (\Exception $e) { var_dump($e->getMessage()); } # U+D800 ~ U+DFFF try { var_dump(Utility::ValidateUTF8(chr(0xed) . chr(0xa0) . chr(0x80))); } catch (\Exception $e) { var_dump($e->getMessage()); } try { var_dump(Utility::ValidateUTF8(chr(0xef) . chr(0xff))); } catch (\Exception $e) { var_dump($e->getMessage()); }
/** * Set Topic * * @param string $topic */ public function setTopic($topic) { Utility::CheckTopicName($topic); $this->topic = $topic; }
/** * Process packet with Fixed Header + Message Identifier only * * @param string $message * @return array|bool */ protected final function processReadFixedHeaderWithMsgID($message) { $packet_length = 4; $name = Message::$name[$this->message_type]; if (!isset($message[$packet_length - 1])) { # error Debug::Log(Debug::DEBUG, "Message {$name}: error on reading"); return false; } $packet = unpack('Ccmd/Clength/nmsgid', $message); $packet['cmd'] = Utility::UnpackCommand($packet['cmd']); if ($packet['cmd']['message_type'] != $this->getMessageType()) { Debug::Log(Debug::DEBUG, "Message {$name}: type mismatch"); return false; } else { Debug::Log(Debug::DEBUG, "Message {$name}: success"); return $packet; } }
protected final function decodePacketIdentifier(&$packet_data, &$pos) { $msgid = Utility::ExtractUShort($packet_data, $pos); $this->setMsgID($msgid); return true; }
/** * Decode Variable Header * Topic, Packet Identifier * * @param string & $packet_data * @param int & $pos * @return bool */ protected function decodeVariableHeader(&$packet_data, &$pos) { $topic = Utility::UnpackStringWithLength($packet_data, $pos); $this->message->setTopic($topic); if ($this->getQos() > 0) { # Decode Packet Identifier if QoS > 0 $this->decodePacketIdentifier($packet_data, $pos); } return true; }
/** * Read Message And Create Message Object * * @return \sskaje\mqtt\Message\Base * @throws \sskaje\mqtt\Exception */ protected function message_read() { if ($this->socket->eof()) { if (++$this->count_eof > 5) { usleep(pow(2, $this->count_eof)); } Debug::Log(Debug::NOTICE, 'message_read(): EOF ' . $this->count_eof); if ($this->count_eof > $this->max_eof) { throw new Exception\NetworkError(); } return false; } # Reset EOF counter $this->count_eof = 0; # read 2 bytes $read_fh_bytes = 2; $read_more_length_bytes = 3; $read_bytes = 0; $read_message = $this->socket->read($read_fh_bytes); if (empty($read_message)) { throw new Exception('WTFFFFFF!!!! '); } $read_bytes += $read_fh_bytes; $cmd = Utility::ParseCommand(ord($read_message[0])); $message_type = $cmd['message_type']; $flags = $cmd['flags']; Debug::Log(Debug::DEBUG, "message_read(): message_type=" . Message::$name[$message_type] . ", flags={$flags}"); if (ord($read_message[1]) > 0x7f) { # read 3 more bytes $read_message .= $this->socket->read($read_more_length_bytes); $read_bytes += $read_more_length_bytes; } $pos = 1; $remaining_length = Utility::DecodeLength($read_message, $pos); $to_read = 0; if ($remaining_length) { $to_read = $remaining_length - ($read_bytes - $pos); } Debug::Log(Debug::DEBUG, 'message_read(): remaining length=' . $remaining_length . ', data to read=' . $to_read); if ($to_read) { $read_message .= $this->socket->read($to_read); } Debug::Log(Debug::DEBUG, 'message_read(): Dump', $read_message); $message_object = $this->getMessageObject($message_type); $message_object->decode($read_message, $remaining_length); return $message_object; }
/** * Build Variable Header * * @return string */ protected function buildVariableHeader() { $buffer = ""; # Protocol Name if ($this->message->mqtt->version() == MQTT::VERSION_3_1_1) { $buffer .= Utility::PackStringWithLength('MQTT'); } else { $buffer .= Utility::PackStringWithLength('MQIsdp'); } # End of Protocol Name # Protocol Level $buffer .= chr($this->message->mqtt->version()); # Connect Flags # Set to 0 by default $var = 0; # clean session if ($this->clean) { $var |= 0x2; } # Will flags if ($this->message->will) { $var |= $this->message->will->get(); } # User name flag if ($this->message->username != NULL) { $var |= 0x80; } # Password flag if ($this->message->password != NULL) { $var |= 0x40; } $buffer .= chr($var); # End of Connect Flags # Keep alive: unsigned short 16bits big endian $buffer .= pack('n', $this->keepalive); return $buffer; }
protected function payload() { $payload = ''; $payload .= Utility::PackStringWithLength($this->mqtt->clientid); # Adding Connect Will if ($this->will && $this->will->get()) { /* If the Will Flag is set to 0 the Will QoS and Will Retain fields in the Connect Flags MUST be set to zero and the Will Topic and Will Message fields MUST NOT be present in the payload [MQTT-3.1.2-11]. */ $payload .= Utility::PackStringWithLength($this->will->getTopic()); $payload .= Utility::PackStringWithLength($this->will->getMessage()); } # Append Username if ($this->username != NULL) { $payload .= Utility::PackStringWithLength($this->username); } # Append Password if ($this->password != NULL) { $payload .= Utility::PackStringWithLength($this->password); } return $payload; }