1
This commit is contained in:
31
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttAck.java
Normal file
31
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttAck.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2019 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
/**
|
||||
* Abstract super-class of all acknowledgement messages.
|
||||
*/
|
||||
public abstract class MqttAck extends MqttPersistableWireMessage {
|
||||
public MqttAck(byte type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getMessageInfo() {
|
||||
return 0;
|
||||
}
|
||||
}
|
123
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttAuth.java
Normal file
123
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttAuth.java
Normal file
@@ -0,0 +1,123 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
|
||||
/**
|
||||
* An on-the-wire representation of an MQTT AUTH message. MQTTv5 - 3.15
|
||||
*/
|
||||
public class MqttAuth extends MqttWireMessage {
|
||||
|
||||
// Return codes
|
||||
private static final int[] validReturnCodes = { MqttReturnCode.RETURN_CODE_SUCCESS,
|
||||
MqttReturnCode.RETURN_CODE_CONTINUE_AUTHENTICATION, MqttReturnCode.RETURN_CODE_RE_AUTHENTICATE };
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.AUTH_METHOD_IDENTIFIER,
|
||||
MqttProperties.AUTH_DATA_IDENTIFIER, MqttProperties.REASON_STRING_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
// Fields
|
||||
private MqttProperties properties;
|
||||
|
||||
/**
|
||||
* Constructs an Auth message from a raw byte array
|
||||
*
|
||||
* @param data
|
||||
* - The variable header and payload bytes.
|
||||
* @throws IOException
|
||||
* - if an exception occurs when decoding an input stream
|
||||
* @throws MqttException
|
||||
* - If an exception occurs decoding this packet
|
||||
*/
|
||||
public MqttAuth(byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_AUTH);
|
||||
properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
DataInputStream inputStream = new DataInputStream(bais);
|
||||
reasonCode = inputStream.readUnsignedByte();
|
||||
validateReturnCode(reasonCode, validReturnCodes);
|
||||
this.properties.decodeProperties(inputStream);
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an Auth message from the return code
|
||||
*
|
||||
* @param returnCode
|
||||
* - The Auth Return Code
|
||||
* @param properties
|
||||
* - The {@link MqttProperties} for the packet.
|
||||
* @throws MqttException
|
||||
* - If an exception occurs encoding this packet
|
||||
*/
|
||||
public MqttAuth(int returnCode, MqttProperties properties) throws MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_AUTH);
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
this.reasonCode = returnCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Return Code
|
||||
outputStream.writeByte(reasonCode);
|
||||
|
||||
// Write Identifier / Value Fields
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
outputStream.write(identifierValueFieldsByteArray);
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getMessageInfo() {
|
||||
return (byte) (1);
|
||||
}
|
||||
|
||||
public int getReturnCode() {
|
||||
return reasonCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttAuth [returnCode=" + reasonCode + ", properties=" + properties + "]";
|
||||
}
|
||||
}
|
154
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttConnAck.java
Normal file
154
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttConnAck.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
|
||||
/**
|
||||
* An on-the-wire representation of an MQTT CONNACK.
|
||||
*/
|
||||
public class MqttConnAck extends MqttAck {
|
||||
public static final String KEY = "Con";
|
||||
|
||||
private static final int[] validReturnCodes = { MqttReturnCode.RETURN_CODE_SUCCESS,
|
||||
MqttReturnCode.RETURN_CODE_UNSPECIFIED_ERROR, MqttReturnCode.RETURN_CODE_MALFORMED_CONTROL_PACKET,
|
||||
MqttReturnCode.RETURN_CODE_PROTOCOL_ERROR, MqttReturnCode.RETURN_CODE_IMPLEMENTATION_SPECIFIC_ERROR,
|
||||
MqttReturnCode.RETURN_CODE_UNSUPPORTED_PROTOCOL_VERSION, MqttReturnCode.RETURN_CODE_IDENTIFIER_NOT_VALID,
|
||||
MqttReturnCode.RETURN_CODE_BAD_USERNAME_OR_PASSWORD, MqttReturnCode.RETURN_CODE_NOT_AUTHORIZED,
|
||||
MqttReturnCode.RETURN_CODE_SERVER_UNAVAILABLE, MqttReturnCode.RETURN_CODE_SERVER_BUSY,
|
||||
MqttReturnCode.RETURN_CODE_BANNED, MqttReturnCode.RETURN_CODE_BAD_AUTHENTICATION,
|
||||
MqttReturnCode.RETURN_CODE_TOPIC_NAME_INVALID, MqttReturnCode.RETURN_CODE_PACKET_TOO_LARGE,
|
||||
MqttReturnCode.RETURN_CODE_QUOTA_EXCEEDED, MqttReturnCode.RETURN_CODE_RETAIN_NOT_SUPPORTED,
|
||||
MqttReturnCode.RETURN_CODE_USE_ANOTHER_SERVER, MqttReturnCode.RETURN_CODE_SERVER_MOVED,
|
||||
MqttReturnCode.RETURN_CODE_CONNECTION_RATE_EXCEEDED };
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.SESSION_EXPIRY_INTERVAL_IDENTIFIER,
|
||||
MqttProperties.RECEIVE_MAXIMUM_IDENTIFIER, MqttProperties.MAXIMUM_QOS_IDENTIFIER,
|
||||
MqttProperties.RETAIN_AVAILABLE_IDENTIFIER, MqttProperties.MAXIMUM_PACKET_SIZE_IDENTIFIER,
|
||||
MqttProperties.ASSIGNED_CLIENT_IDENTIFIER_IDENTIFIER, MqttProperties.TOPIC_ALIAS_MAXIMUM_IDENTIFIER,
|
||||
MqttProperties.WILDCARD_SUB_AVAILABLE_IDENTIFIER, MqttProperties.SUBSCRIPTION_AVAILABLE_IDENTIFIER,
|
||||
MqttProperties.SHARED_SUBSCRIPTION_AVAILABLE_IDENTIFIER, MqttProperties.SERVER_KEEP_ALIVE_IDENTIFIER,
|
||||
MqttProperties.RESPONSE_INFO_IDENTIFIER, MqttProperties.SERVER_REFERENCE_IDENTIFIER,
|
||||
MqttProperties.AUTH_METHOD_IDENTIFIER, MqttProperties.AUTH_DATA_IDENTIFIER,
|
||||
MqttProperties.REASON_STRING_IDENTIFIER, MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
private boolean sessionPresent;
|
||||
private MqttProperties properties;
|
||||
|
||||
public MqttConnAck(byte[] variableHeader) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_CONNACK);
|
||||
this.properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(variableHeader);
|
||||
DataInputStream dis = new DataInputStream(bais);
|
||||
sessionPresent = (dis.readUnsignedByte() & 0x01) == 0x01;
|
||||
reasonCode = dis.readUnsignedByte();
|
||||
validateReturnCode(reasonCode, validReturnCodes);
|
||||
this.properties.decodeProperties(dis);
|
||||
dis.close();
|
||||
}
|
||||
|
||||
public MqttConnAck(boolean sessionPresent, int returnCode, MqttProperties properties) throws MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_CONNACK);
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
this.sessionPresent = sessionPresent;
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
this.reasonCode = returnCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Session Present Flag
|
||||
byte connectAchnowledgeFlag = 0;
|
||||
if (sessionPresent) {
|
||||
connectAchnowledgeFlag |= 0x01;
|
||||
}
|
||||
dos.write(connectAchnowledgeFlag);
|
||||
|
||||
// Encode the Connect Return Code
|
||||
dos.write((byte) reasonCode);
|
||||
|
||||
// Write Identifier / Value Fields
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
dos.write(identifierValueFieldsByteArray);
|
||||
dos.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this message needs to include a message ID.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMessageIdRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
public boolean getSessionPresent() {
|
||||
return sessionPresent;
|
||||
}
|
||||
|
||||
public void setSessionPresent(boolean sessionPresent) {
|
||||
this.sessionPresent = sessionPresent;
|
||||
}
|
||||
|
||||
public int getReturnCode() {
|
||||
return reasonCode;
|
||||
}
|
||||
|
||||
public void setReturnCode(int returnCode) {
|
||||
this.reasonCode = returnCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public static int[] getValidreturncodes() {
|
||||
return validReturnCodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttConnAck [returnCode=" + reasonCode + ", sessionPresent=" + sessionPresent + ", properties="
|
||||
+ properties + "]";
|
||||
}
|
||||
|
||||
}
|
337
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttConnect.java
Normal file
337
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttConnect.java
Normal file
@@ -0,0 +1,337 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.MqttMessage;
|
||||
|
||||
public class MqttConnect extends MqttWireMessage {
|
||||
|
||||
public static final String KEY = "Con";
|
||||
|
||||
private MqttProperties properties;
|
||||
|
||||
private MqttProperties willProperties;
|
||||
|
||||
// Fields
|
||||
private byte info;
|
||||
private String clientId;
|
||||
private boolean reservedByte;
|
||||
private boolean cleanStart;
|
||||
private MqttMessage willMessage;
|
||||
private String userName;
|
||||
private byte[] password;
|
||||
private int keepAliveInterval;
|
||||
private String willDestination;
|
||||
private int mqttVersion = DEFAULT_PROTOCOL_VERSION;
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.SESSION_EXPIRY_INTERVAL_IDENTIFIER,
|
||||
MqttProperties.WILL_DELAY_INTERVAL_IDENTIFIER, MqttProperties.RECEIVE_MAXIMUM_IDENTIFIER,
|
||||
MqttProperties.MAXIMUM_PACKET_SIZE_IDENTIFIER, MqttProperties.TOPIC_ALIAS_MAXIMUM_IDENTIFIER,
|
||||
MqttProperties.REQUEST_RESPONSE_INFO_IDENTIFIER, MqttProperties.REQUEST_PROBLEM_INFO_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER, MqttProperties.AUTH_METHOD_IDENTIFIER,
|
||||
MqttProperties.AUTH_DATA_IDENTIFIER };
|
||||
|
||||
private static final Byte[] validWillProperties = { MqttProperties.WILL_DELAY_INTERVAL_IDENTIFIER,
|
||||
MqttProperties.PAYLOAD_FORMAT_INDICATOR_IDENTIFIER, MqttProperties.MESSAGE_EXPIRY_INTERVAL_IDENTIFIER,
|
||||
MqttProperties.RESPONSE_TOPIC_IDENTIFIER, MqttProperties.CORRELATION_DATA_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER, MqttProperties.CONTENT_TYPE_IDENTIFIER };
|
||||
|
||||
/**
|
||||
* Constructor for an on the wire MQTT Connect message
|
||||
*
|
||||
* @param info
|
||||
* - Info Byte
|
||||
* @param data
|
||||
* - The variable header and payload bytes.
|
||||
* @throws IOException
|
||||
* - if an exception occurs when decoding an input stream
|
||||
* @throws MqttException
|
||||
* - If an exception occurs decoding this packet
|
||||
*/
|
||||
public MqttConnect(byte info, byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_CONNECT);
|
||||
this.info = info;
|
||||
this.properties = new MqttProperties(validProperties);
|
||||
this.willProperties = new MqttProperties(validWillProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
DataInputStream dis = new DataInputStream(bais);
|
||||
|
||||
// Verify the Protocol name and version
|
||||
String protocolName = MqttDataTypes.decodeUTF8(dis);
|
||||
if (!protocolName.equalsIgnoreCase(DEFAULT_PROTOCOL_NAME)) {
|
||||
throw new MqttPacketException(MqttPacketException.PACKET_CONNECT_ERROR_UNSUPPORTED_PROTOCOL_NAME);
|
||||
}
|
||||
mqttVersion = dis.readByte();
|
||||
if (mqttVersion != DEFAULT_PROTOCOL_VERSION) {
|
||||
throw new MqttPacketException(MqttPacketException.PACKET_CONNECT_ERROR_UNSUPPORTED_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
byte connectFlags = dis.readByte();
|
||||
reservedByte = (connectFlags & 0x01) != 0;
|
||||
cleanStart = (connectFlags & 0x02) != 0;
|
||||
boolean willFlag = (connectFlags & 0x04) != 0;
|
||||
int willQoS = (connectFlags >> 3) & 0x03;
|
||||
boolean willRetain = (connectFlags & 0x20) != 0;
|
||||
boolean passwordFlag = (connectFlags & 0x40) != 0;
|
||||
boolean usernameFlag = (connectFlags & 0x80) != 0;
|
||||
|
||||
if (reservedByte) {
|
||||
throw new MqttPacketException(MqttPacketException.PACKET_CONNECT_ERROR_INVALID_RESERVE_FLAG);
|
||||
}
|
||||
|
||||
keepAliveInterval = dis.readUnsignedShort();
|
||||
properties.decodeProperties(dis);
|
||||
clientId = MqttDataTypes.decodeUTF8(dis);
|
||||
|
||||
if (willFlag) {
|
||||
willProperties.decodeProperties(dis);
|
||||
if (willQoS == 3) {
|
||||
throw new MqttPacketException(MqttPacketException.PACKET_CONNECT_ERROR_INVALID_WILL_QOS);
|
||||
}
|
||||
willDestination = MqttDataTypes.decodeUTF8(dis);
|
||||
int willMessageLength = dis.readShort();
|
||||
byte[] willMessageBytes = new byte[willMessageLength];
|
||||
dis.read(willMessageBytes, 0, willMessageLength);
|
||||
willMessage = new MqttMessage(willMessageBytes);
|
||||
willMessage.setQos(willQoS);
|
||||
willMessage.setRetained(willRetain);
|
||||
}
|
||||
if (usernameFlag) {
|
||||
userName = MqttDataTypes.decodeUTF8(dis);
|
||||
}
|
||||
if (passwordFlag) {
|
||||
int passwordLength = dis.readShort();
|
||||
password = new byte[passwordLength];
|
||||
dis.read(password, 0, passwordLength);
|
||||
}
|
||||
|
||||
dis.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a new MQTT Connect Message
|
||||
*
|
||||
* @param clientId
|
||||
* - The Client Identifier
|
||||
* @param mqttVersion
|
||||
* - The MQTT Protocol version
|
||||
* @param cleanStart
|
||||
* - The Clean Session Identifier
|
||||
* @param keepAliveInterval
|
||||
* - The Keep Alive Interval
|
||||
* @param properties
|
||||
* - The {@link MqttProperties} for the packet.
|
||||
* @param willProperties
|
||||
* - The {@link MqttProperties} for the will message.
|
||||
*
|
||||
*/
|
||||
public MqttConnect(String clientId, int mqttVersion, boolean cleanStart, int keepAliveInterval,
|
||||
MqttProperties properties, MqttProperties willProperties) {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_CONNECT);
|
||||
this.clientId = clientId;
|
||||
this.mqttVersion = mqttVersion;
|
||||
this.cleanStart = cleanStart;
|
||||
this.keepAliveInterval = keepAliveInterval;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
this.willProperties = willProperties;
|
||||
this.willProperties.setValidProperties(validWillProperties);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getMessageInfo() {
|
||||
return (byte) 0;
|
||||
}
|
||||
|
||||
public boolean isCleanStart() {
|
||||
return cleanStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Protocol Name
|
||||
MqttDataTypes.encodeUTF8(dos, "MQTT");
|
||||
|
||||
// Encode the MQTT Version
|
||||
dos.write(mqttVersion);
|
||||
|
||||
byte connectFlags = 0;
|
||||
|
||||
if (cleanStart) {
|
||||
connectFlags |= 0x02;
|
||||
}
|
||||
|
||||
if (willMessage != null) {
|
||||
connectFlags |= 0x04;
|
||||
connectFlags |= (willMessage.getQos() << 3);
|
||||
if (willMessage.isRetained()) {
|
||||
connectFlags |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
if (userName != null) {
|
||||
connectFlags |= 0x80;
|
||||
}
|
||||
|
||||
if (password != null) {
|
||||
connectFlags |= 0x40;
|
||||
}
|
||||
|
||||
dos.write(connectFlags);
|
||||
dos.writeShort(keepAliveInterval);
|
||||
|
||||
// Write Identifier / Value Fields
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
dos.write(identifierValueFieldsByteArray);
|
||||
dos.flush();
|
||||
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(baos);
|
||||
MqttDataTypes.encodeUTF8(dos, clientId);
|
||||
|
||||
|
||||
|
||||
if (willMessage != null) {
|
||||
// Encode Will properties here
|
||||
byte[] willIdentifierValueFieldsByteArray = willProperties.encodeProperties();
|
||||
dos.write(willIdentifierValueFieldsByteArray);
|
||||
|
||||
MqttDataTypes.encodeUTF8(dos, willDestination);
|
||||
dos.writeShort(willMessage.getPayload().length);
|
||||
dos.write(willMessage.getPayload());
|
||||
}
|
||||
|
||||
if (userName != null) {
|
||||
MqttDataTypes.encodeUTF8(dos, userName);
|
||||
}
|
||||
|
||||
if (password != null) {
|
||||
dos.writeShort(password.length);
|
||||
dos.write(password);
|
||||
}
|
||||
dos.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this message needs to include a message ID.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMessageIdRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
public void setWillMessage(MqttMessage willMessage) {
|
||||
this.willMessage = willMessage;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public void setPassword(byte[] password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public void setWillDestination(String willDestination) {
|
||||
this.willDestination = willDestination;
|
||||
}
|
||||
|
||||
public byte getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public MqttMessage getWillMessage() {
|
||||
return willMessage;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public byte[] getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public int getKeepAliveInterval() {
|
||||
return keepAliveInterval;
|
||||
}
|
||||
|
||||
public String getWillDestination() {
|
||||
return willDestination;
|
||||
}
|
||||
|
||||
public int getMqttVersion() {
|
||||
return mqttVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public MqttProperties getWillProperties() {
|
||||
return willProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttConnect [properties=" + properties + ", willProperties=" + willProperties + ", info=" + info
|
||||
+ ", clientId=" + clientId + ", reservedByte=" + reservedByte + ", cleanStart=" + cleanStart
|
||||
+ ", willMessage=" + willMessage + ", userName=" + userName + ", password=" + Arrays.toString(password)
|
||||
+ ", keepAliveInterval=" + keepAliveInterval + ", willDestination=" + willDestination + ", mqttVersion="
|
||||
+ mqttVersion + "]";
|
||||
}
|
||||
}
|
253
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttDataTypes.java
Normal file
253
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttDataTypes.java
Normal file
@@ -0,0 +1,253 @@
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.VariableByteInteger;
|
||||
|
||||
public class MqttDataTypes {
|
||||
|
||||
private static final int TWO_BYTE_INT_MAX = 65535;
|
||||
private static final long FOUR_BYTE_INT_MAX = 4294967295L;
|
||||
public static final int VARIABLE_BYTE_INT_MAX = 268435455;
|
||||
|
||||
public MqttDataTypes() throws IllegalAccessException {
|
||||
throw new IllegalAccessException("Utility Class");
|
||||
}
|
||||
|
||||
public static void validateTwoByteInt(Integer value) throws IllegalArgumentException {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
if (value >= 0 && value <= TWO_BYTE_INT_MAX) {
|
||||
return;
|
||||
} else {
|
||||
throw new IllegalArgumentException("This property must be a number between 0 and " + TWO_BYTE_INT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateFourByteInt(Long value) throws IllegalArgumentException {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
if (value >= 0 && value <= FOUR_BYTE_INT_MAX) {
|
||||
return;
|
||||
} else {
|
||||
throw new IllegalArgumentException("This property must be a number between 0 and " + FOUR_BYTE_INT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
public static void validateVariableByteInt(int value) throws IllegalArgumentException {
|
||||
if (value >= 0 && value <= VARIABLE_BYTE_INT_MAX) {
|
||||
return;
|
||||
} else {
|
||||
throw new IllegalArgumentException("This property must be a number between 0 and " + VARIABLE_BYTE_INT_MAX);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void writeUnsignedFourByteInt(long value, DataOutputStream stream) throws IOException {
|
||||
stream.writeByte((byte) (value >>> 24));
|
||||
stream.writeByte((byte) (value >>> 16));
|
||||
stream.writeByte((byte) (value >>> 8));
|
||||
stream.writeByte((byte) (value >>> 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a Four Byte Integer, then converts it to a float. This is because Java
|
||||
* doesn't have Unsigned Integers.
|
||||
*
|
||||
* @param inputStream
|
||||
* The input stream to read from.
|
||||
* @return a {@link Long} containing the value of the Four Byte int (Between 0
|
||||
* and 4294967295)
|
||||
* @throws IOException
|
||||
* if an exception occurs whilst reading from the Input Stream
|
||||
*/
|
||||
public static Long readUnsignedFourByteInt(DataInputStream inputStream) throws IOException {
|
||||
byte[] readBuffer = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
inputStream.readFully(readBuffer, 4, 4);
|
||||
return (((long) readBuffer[0] << 56) + ((long) (readBuffer[1] & 255) << 48)
|
||||
+ ((long) (readBuffer[2] & 255) << 40) + ((long) (readBuffer[3] & 255) << 32)
|
||||
+ ((long) (readBuffer[4] & 255) << 24) + ((readBuffer[5] & 255) << 16) + ((readBuffer[6] & 255) << 8)
|
||||
+ ((readBuffer[7] & 255) << 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a Two Byte Integer, this is because Java does not have unsigned
|
||||
* integers.
|
||||
*
|
||||
* @param inputStream
|
||||
* The input stream to read from.
|
||||
* @return a {@link int} containing the value of the Two Byte int (Between 0 and
|
||||
* 65535)
|
||||
* @throws IOException
|
||||
* if an exception occurs whilst reading from the Input Stream
|
||||
*
|
||||
*/
|
||||
public static int readUnsignedTwoByteInt(DataInputStream inputStream) throws IOException {
|
||||
// byte readBuffer[] = {0,0}
|
||||
int ch1 = inputStream.read();
|
||||
int ch2 = inputStream.read();
|
||||
if ((ch1 | ch2) < 0)
|
||||
throw new EOFException();
|
||||
return (int) ((ch1 << 8) + (ch2 << 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a String given into UTF-8, before writing this to the
|
||||
* {@link DataOutputStream} the length of the encoded string is encoded into two
|
||||
* bytes and then written to the {@link DataOutputStream}.
|
||||
* {@link DataOutputStream#writeUTF(String)} should be no longer used.
|
||||
* {@link DataOutputStream#writeUTF(String)} does not correctly encode UTF-16
|
||||
* surrogate characters.
|
||||
*
|
||||
* @param dos
|
||||
* The stream to write the encoded UTF-8 string to.
|
||||
* @param stringToEncode
|
||||
* The string to be encoded
|
||||
* @throws MqttException
|
||||
* Thrown when an error occurs with either the encoding or writing
|
||||
* the data to the stream.
|
||||
*/
|
||||
public static void encodeUTF8(DataOutputStream dos, String stringToEncode) throws MqttException {
|
||||
validateUTF8String(stringToEncode);
|
||||
try {
|
||||
byte[] encodedString = stringToEncode.getBytes(STRING_ENCODING);
|
||||
byte byte1 = (byte) ((encodedString.length >>> 8) & 0xFF);
|
||||
byte byte2 = (byte) ((encodedString.length >>> 0) & 0xFF);
|
||||
|
||||
dos.write(byte1);
|
||||
dos.write(byte2);
|
||||
dos.write(encodedString);
|
||||
} catch (IOException ex) {
|
||||
throw new MqttException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected static final Charset STRING_ENCODING = StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
* Decodes a UTF-8 string from the {@link DataInputStream} provided.
|
||||
* {@link DataInputStream#readUTF()} should be no longer used, because
|
||||
* {@link DataInputStream#readUTF()} does not decode UTF-16 surrogate characters
|
||||
* correctly.
|
||||
*
|
||||
* @param input
|
||||
* The input stream from which to read the encoded string.
|
||||
* @return a decoded String from the {@link DataInputStream}.
|
||||
* @throws MqttException
|
||||
* thrown when an error occurs with either reading from the stream
|
||||
* or decoding the encoding string.
|
||||
*/
|
||||
public static String decodeUTF8(DataInputStream input) throws MqttException {
|
||||
int encodedLength;
|
||||
try {
|
||||
encodedLength = input.readUnsignedShort();
|
||||
|
||||
byte[] encodedString = new byte[encodedLength];
|
||||
input.readFully(encodedString);
|
||||
String output = new String(encodedString, STRING_ENCODING);
|
||||
validateUTF8String(output);
|
||||
|
||||
return output;
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(MqttException.REASON_CODE_MALFORMED_PACKET, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a UTF-8 String for suitability for MQTT.
|
||||
*
|
||||
* @param input
|
||||
* - The Input String
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
private static void validateUTF8String(String input) throws IllegalArgumentException {
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
boolean isBad = false;
|
||||
char c = input.charAt(i);
|
||||
/* Check for mismatched surrogates */
|
||||
if (Character.isHighSurrogate(c)) {
|
||||
if (++i == input.length()) {
|
||||
isBad = true; /* Trailing high surrogate */
|
||||
} else {
|
||||
char c2 = input.charAt(i);
|
||||
if (!Character.isLowSurrogate(c2)) {
|
||||
isBad = true; /* No low surrogate */
|
||||
} else {
|
||||
int ch = ((((int) c) & 0x3ff) << 10) | (c2 & 0x3ff);
|
||||
if ((ch & 0xffff) == 0xffff || (ch & 0xffff) == 0xfffe) {
|
||||
isBad = true; /* Noncharacter in base plane */
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Character.isISOControl(c) || Character.isLowSurrogate(c)) {
|
||||
isBad = true; /* Control character or no high surrogate */
|
||||
} else if (c >= 0xfdd0 && (c <= 0xfddf || c >= 0xfffe)) {
|
||||
isBad = true; /* Noncharacter in other nonbase plane */
|
||||
}
|
||||
}
|
||||
if (isBad) {
|
||||
throw new IllegalArgumentException(String.format("Invalid UTF-8 char: [%04x]", (int) c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes an MQTT Multi-Byte Integer from the given stream
|
||||
*
|
||||
* @param in
|
||||
* the DataInputStream to decode a Variable Byte Integer From
|
||||
* @return a new VariableByteInteger
|
||||
* @throws IOException
|
||||
* if an error occurred whilst decoding the VBI
|
||||
*/
|
||||
public static VariableByteInteger readVariableByteInteger(DataInputStream in) throws IOException {
|
||||
byte digit;
|
||||
int value = 0;
|
||||
int multiplier = 1;
|
||||
int count = 0;
|
||||
|
||||
do {
|
||||
digit = in.readByte();
|
||||
count++;
|
||||
value += ((digit & 0x7F) * multiplier);
|
||||
multiplier *= 128;
|
||||
} while ((digit & 0x80) != 0);
|
||||
|
||||
if (value < 0 || value > VARIABLE_BYTE_INT_MAX) {
|
||||
throw new IOException("This property must be a number between 0 and " + VARIABLE_BYTE_INT_MAX
|
||||
+ ". Read value was: " + value);
|
||||
}
|
||||
|
||||
return new VariableByteInteger(value, count);
|
||||
|
||||
}
|
||||
|
||||
public static byte[] encodeVariableByteInteger(int number) throws IllegalArgumentException {
|
||||
validateVariableByteInt(number);
|
||||
int numBytes = 0;
|
||||
long no = number;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
// Encode the remaining length fields in the four bytes
|
||||
do {
|
||||
byte digit = (byte) (no % 128);
|
||||
no = no / 128;
|
||||
if (no > 0) {
|
||||
digit |= 0x80;
|
||||
}
|
||||
baos.write(digit);
|
||||
numBytes++;
|
||||
} while ((no > 0) && (numBytes < 4));
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
}
|
129
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttDisconnect.java
Normal file
129
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttDisconnect.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
|
||||
public class MqttDisconnect extends MqttWireMessage {
|
||||
|
||||
public static final String KEY = "Disc";
|
||||
|
||||
private static final int[] validReturnCodes = { MqttReturnCode.RETURN_CODE_SUCCESS,
|
||||
MqttReturnCode.RETURN_CODE_DISCONNECT_WITH_WILL_MESSAGE, MqttReturnCode.RETURN_CODE_UNSPECIFIED_ERROR,
|
||||
MqttReturnCode.RETURN_CODE_MALFORMED_CONTROL_PACKET, MqttReturnCode.RETURN_CODE_PROTOCOL_ERROR,
|
||||
MqttReturnCode.RETURN_CODE_IMPLEMENTATION_SPECIFIC_ERROR, MqttReturnCode.RETURN_CODE_NOT_AUTHORIZED,
|
||||
MqttReturnCode.RETURN_CODE_SERVER_BUSY, MqttReturnCode.RETURN_CODE_SERVER_SHUTTING_DOWN,
|
||||
MqttReturnCode.RETURN_CODE_KEEP_ALIVE_TIMEOUT, MqttReturnCode.RETURN_CODE_SESSION_TAKEN_OVER,
|
||||
MqttReturnCode.RETURN_CODE_TOPIC_FILTER_NOT_VALID, MqttReturnCode.RETURN_CODE_TOPIC_NAME_INVALID,
|
||||
MqttReturnCode.RETURN_CODE_RECEIVE_MAXIMUM_EXCEEDED, MqttReturnCode.RETURN_CODE_TOPIC_ALIAS_NOT_ACCEPTED,
|
||||
MqttReturnCode.RETURN_CODE_PACKET_TOO_LARGE, MqttReturnCode.RETURN_CODE_MESSAGE_RATE_TOO_HIGH,
|
||||
MqttReturnCode.RETURN_CODE_QUOTA_EXCEEDED, MqttReturnCode.RETURN_CODE_ADMINISTRITIVE_ACTION,
|
||||
MqttReturnCode.RETURN_CODE_PAYLOAD_FORMAT_INVALID, MqttReturnCode.RETURN_CODE_RETAIN_NOT_SUPPORTED,
|
||||
MqttReturnCode.RETURN_CODE_QOS_NOT_SUPPORTED, MqttReturnCode.RETURN_CODE_USE_ANOTHER_SERVER,
|
||||
MqttReturnCode.RETURN_CODE_SERVER_MOVED, MqttReturnCode.RETURN_CODE_SHARED_SUB_NOT_SUPPORTED,
|
||||
MqttReturnCode.RETURN_CODE_CONNECTION_RATE_EXCEEDED, MqttReturnCode.RETURN_CODE_MAXIMUM_CONNECT_TIME,
|
||||
MqttReturnCode.RETURN_CODE_SUB_IDENTIFIERS_NOT_SUPPORTED,
|
||||
MqttReturnCode.RETURN_CODE_WILDCARD_SUB_NOT_SUPPORTED };
|
||||
|
||||
// Fields
|
||||
private int returnCode = MqttReturnCode.RETURN_CODE_SUCCESS;
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.SESSION_EXPIRY_INTERVAL_IDENTIFIER,
|
||||
MqttProperties.SERVER_REFERENCE_IDENTIFIER, MqttProperties.REASON_STRING_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
private MqttProperties properties;
|
||||
|
||||
public MqttDisconnect(byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_DISCONNECT);
|
||||
this.properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
CountingInputStream counter = new CountingInputStream(bais);
|
||||
DataInputStream inputStream = new DataInputStream(counter);
|
||||
if(data.length - counter.getCounter() >= 1) {
|
||||
returnCode = inputStream.readUnsignedByte();
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
}
|
||||
|
||||
long remainder = (long) data.length - counter.getCounter();
|
||||
if (remainder >= 2) {
|
||||
this.properties.decodeProperties(inputStream);
|
||||
}
|
||||
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
public MqttDisconnect(int returnCode, MqttProperties properties) throws MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_DISCONNECT);
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
this.returnCode = returnCode;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Return Code
|
||||
outputStream.writeByte(returnCode);
|
||||
|
||||
// Write Identifier / Value Fields
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
if (identifierValueFieldsByteArray.length != 0) {
|
||||
outputStream.write(identifierValueFieldsByteArray);
|
||||
outputStream.flush();
|
||||
}
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public int getReturnCode() {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getMessageInfo() {
|
||||
return (byte) 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttDisconnect [returnCode=" + returnCode + ", properties=" + properties + "]";
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
|
||||
/**
|
||||
* This is a Class containing all of the low level packet exceptions that may be useful in identifying the cause of protocol errors.
|
||||
* @author jamessutton
|
||||
*/
|
||||
public class MqttPacketException extends MqttException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
/**
|
||||
* Protocol Exceptions for the CONNECT Packet
|
||||
*/
|
||||
public static final int PACKET_CONNECT_ERROR_UNSUPPORTED_PROTOCOL_NAME = 51000; // 3.1.2.1 - If Protocol name is not 'MQTT', return Unsupported Protocol Version Error.
|
||||
public static final int PACKET_CONNECT_ERROR_UNSUPPORTED_PROTOCOL_VERSION = 51001; // 3.1.2.2 - If Protocol version is not 5, return Unsupported Protocol Version Error.
|
||||
public static final int PACKET_CONNECT_ERROR_INVALID_RESERVE_FLAG = 51002; // 3.1.2.3 - If Reserved flag is not 0, return Malformed Packet Error.
|
||||
public static final int PACKET_CONNECT_ERROR_INVALID_WILL_QOS = 51003; // 3.1.2.6 - If Will QoS is 0x03, return Malformed Packet Error.
|
||||
|
||||
|
||||
public MqttPacketException(int reasonCode) {
|
||||
super(reasonCode);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - initial API and implementation and/or initial documentation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.MqttPersistable;
|
||||
import org.eclipse.paho.mqttv5.common.MqttPersistenceException;
|
||||
|
||||
public abstract class MqttPersistableWireMessage extends MqttWireMessage
|
||||
implements MqttPersistable {
|
||||
|
||||
public MqttPersistableWireMessage(byte type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
public byte[] getHeaderBytes() throws MqttPersistenceException {
|
||||
byte[] headerBytes = null;
|
||||
try {
|
||||
if(this.getClass() == MqttPublish.class && this.getProperties().getTopicAlias() != null) {
|
||||
// Remove the Topic Alias temporarily.
|
||||
MqttProperties props = this.getProperties();
|
||||
Integer topicAlias = props.getTopicAlias();
|
||||
props.setTopicAlias(null);
|
||||
headerBytes = getHeader();
|
||||
// Re Set Topic Alias
|
||||
props.setTopicAlias(topicAlias);
|
||||
this.properties = props;
|
||||
} else {
|
||||
headerBytes = getHeader();
|
||||
}
|
||||
return headerBytes;
|
||||
}
|
||||
catch (MqttException ex) {
|
||||
throw new MqttPersistenceException(ex.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
public int getHeaderLength() throws MqttPersistenceException {
|
||||
return getHeaderBytes().length;
|
||||
}
|
||||
|
||||
public int getHeaderOffset() throws MqttPersistenceException{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public byte[] getPayloadBytes() throws MqttPersistenceException {
|
||||
try {
|
||||
return getPayload();
|
||||
}
|
||||
catch (MqttException ex) {
|
||||
throw new MqttPersistenceException(ex.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
public int getPayloadLength() throws MqttPersistenceException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getPayloadOffset() throws MqttPersistenceException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
52
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPingReq.java
Normal file
52
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPingReq.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
|
||||
public class MqttPingReq extends MqttWireMessage{
|
||||
|
||||
public static final String KEY = "Ping";
|
||||
|
||||
public MqttPingReq(){
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PINGREQ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>false</code> as message IDs are not required for MQTT
|
||||
* PINGREQ messages.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMessageIdRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getMessageInfo() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return KEY;
|
||||
}
|
||||
}
|
52
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPingResp.java
Normal file
52
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPingResp.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
|
||||
public class MqttPingResp extends MqttAck {
|
||||
|
||||
public static final String KEY = "Ping";
|
||||
|
||||
public MqttPingResp() {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PINGRESP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>false</code> as message IDs are not required for MQTT PINGREQ
|
||||
* messages.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMessageIdRequired() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getMessageInfo() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return KEY;
|
||||
}
|
||||
}
|
1419
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttProperties.java
Normal file
1419
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttProperties.java
Normal file
File diff suppressed because it is too large
Load Diff
116
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPubAck.java
Normal file
116
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPubAck.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
|
||||
public class MqttPubAck extends MqttAck {
|
||||
|
||||
private static final int[] validReturnCodes = { MqttReturnCode.RETURN_CODE_SUCCESS,
|
||||
MqttReturnCode.RETURN_CODE_NO_MATCHING_SUBSCRIBERS, MqttReturnCode.RETURN_CODE_UNSPECIFIED_ERROR,
|
||||
MqttReturnCode.RETURN_CODE_IMPLEMENTATION_SPECIFIC_ERROR, MqttReturnCode.RETURN_CODE_NOT_AUTHORIZED,
|
||||
MqttReturnCode.RETURN_CODE_TOPIC_NAME_INVALID, MqttReturnCode.RETURN_CODE_QUOTA_EXCEEDED,
|
||||
MqttReturnCode.RETURN_CODE_PAYLOAD_FORMAT_INVALID };
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.REASON_STRING_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
private MqttProperties properties;
|
||||
|
||||
public MqttPubAck(byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PUBACK);
|
||||
properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
CountingInputStream counter = new CountingInputStream(bais);
|
||||
DataInputStream dis = new DataInputStream(counter);
|
||||
msgId = dis.readUnsignedShort();
|
||||
long remainder = (long) data.length - counter.getCounter();
|
||||
if (remainder >= 1) {
|
||||
reasonCode = dis.readUnsignedByte();
|
||||
validateReturnCode(reasonCode, validReturnCodes);
|
||||
} else {
|
||||
reasonCode = 0;
|
||||
}
|
||||
if (remainder >= 4) {
|
||||
this.properties.decodeProperties(dis);
|
||||
}
|
||||
dis.close();
|
||||
}
|
||||
|
||||
public MqttPubAck(int returnCode, int msgId, MqttProperties properties) throws MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PUBACK);
|
||||
this.reasonCode = returnCode;
|
||||
this.msgId = msgId;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Message ID
|
||||
outputStream.writeShort(msgId);
|
||||
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
|
||||
if (reasonCode != MqttReturnCode.RETURN_CODE_SUCCESS && identifierValueFieldsByteArray.length == 1) {
|
||||
// Encode the Return Code
|
||||
outputStream.write((byte) reasonCode);
|
||||
} else if (reasonCode != MqttReturnCode.RETURN_CODE_SUCCESS || identifierValueFieldsByteArray.length > 1) {
|
||||
// Encode the Return Code
|
||||
outputStream.write((byte) reasonCode);
|
||||
// Write Identifier / Value Fields
|
||||
outputStream.write(identifierValueFieldsByteArray);
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public int getReturnCode() {
|
||||
return reasonCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttPubAck [returnCode=" + reasonCode + ", properties=" + properties + "]";
|
||||
}
|
||||
|
||||
}
|
118
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPubComp.java
Normal file
118
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPubComp.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
|
||||
public class MqttPubComp extends MqttAck {
|
||||
|
||||
private static final int[] validReturnCodes = { MqttReturnCode.RETURN_CODE_SUCCESS,
|
||||
MqttReturnCode.RETURN_CODE_PACKET_ID_NOT_FOUND };
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.REASON_STRING_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
// Fields
|
||||
private MqttProperties properties;
|
||||
|
||||
public MqttPubComp(byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PUBCOMP);
|
||||
properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
CountingInputStream counter = new CountingInputStream(bais);
|
||||
DataInputStream dis = new DataInputStream(counter);
|
||||
msgId = dis.readUnsignedShort();
|
||||
long remainder = (long) data.length - counter.getCounter();
|
||||
if (remainder >= 1) {
|
||||
reasonCode = dis.readUnsignedByte();
|
||||
validateReturnCode(reasonCode, validReturnCodes);
|
||||
} else {
|
||||
reasonCode = 0;
|
||||
}
|
||||
if (remainder >= 4) {
|
||||
this.properties.decodeProperties(dis);
|
||||
}
|
||||
dis.close();
|
||||
}
|
||||
|
||||
public MqttPubComp(int returnCode, int msgId, MqttProperties properties) throws MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PUBCOMP);
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
this.reasonCode = returnCode;
|
||||
this.msgId = msgId;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Message ID
|
||||
outputStream.writeShort(msgId);
|
||||
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
|
||||
if (reasonCode != MqttReturnCode.RETURN_CODE_SUCCESS && identifierValueFieldsByteArray.length == 1) {
|
||||
// Encode the Return Code
|
||||
outputStream.write((byte) reasonCode);
|
||||
} else if (reasonCode != MqttReturnCode.RETURN_CODE_SUCCESS || identifierValueFieldsByteArray.length > 1) {
|
||||
// Encode the Return Code
|
||||
outputStream.write((byte) reasonCode);
|
||||
// Write Identifier / Value Fields
|
||||
outputStream.write(identifierValueFieldsByteArray);
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public int getReturnCode() {
|
||||
return reasonCode;
|
||||
}
|
||||
|
||||
public void setReturnCode(int returnCode) {
|
||||
this.reasonCode = returnCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttPubComp [returnCode=" + reasonCode + ", properties=" + properties + "]";
|
||||
}
|
||||
|
||||
}
|
121
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPubRec.java
Normal file
121
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPubRec.java
Normal file
@@ -0,0 +1,121 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
|
||||
public class MqttPubRec extends MqttAck {
|
||||
|
||||
private static final int[] validReturnCodes = { MqttReturnCode.RETURN_CODE_SUCCESS,
|
||||
MqttReturnCode.RETURN_CODE_NO_MATCHING_SUBSCRIBERS, MqttReturnCode.RETURN_CODE_UNSPECIFIED_ERROR,
|
||||
MqttReturnCode.RETURN_CODE_IMPLEMENTATION_SPECIFIC_ERROR, MqttReturnCode.RETURN_CODE_NOT_AUTHORIZED,
|
||||
MqttReturnCode.RETURN_CODE_TOPIC_NAME_INVALID, MqttReturnCode.RETURN_CODE_PACKET_ID_IN_USE,
|
||||
MqttReturnCode.RETURN_CODE_QUOTA_EXCEEDED, MqttReturnCode.RETURN_CODE_PAYLOAD_FORMAT_INVALID };
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.REASON_STRING_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
// Fields
|
||||
private MqttProperties properties;
|
||||
|
||||
public MqttPubRec(byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PUBREC);
|
||||
properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
CountingInputStream counter = new CountingInputStream(bais);
|
||||
DataInputStream dis = new DataInputStream(counter);
|
||||
msgId = dis.readUnsignedShort();
|
||||
long remainder = (long) data.length - counter.getCounter();
|
||||
if (remainder >= 1) {
|
||||
reasonCode = dis.readUnsignedByte();
|
||||
validateReturnCode(reasonCode, validReturnCodes);
|
||||
} else {
|
||||
reasonCode = 0;
|
||||
}
|
||||
if (remainder >= 4) {
|
||||
this.properties.decodeProperties(dis);
|
||||
}
|
||||
dis.close();
|
||||
}
|
||||
|
||||
public MqttPubRec(int returnCode, int msgId, MqttProperties properties) throws MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PUBREC);
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
this.reasonCode = returnCode;
|
||||
this.msgId = msgId;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Message ID
|
||||
outputStream.writeShort(msgId);
|
||||
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
|
||||
if (reasonCode != MqttReturnCode.RETURN_CODE_SUCCESS && identifierValueFieldsByteArray.length == 1) {
|
||||
// Encode the Return Code
|
||||
outputStream.write((byte) reasonCode);
|
||||
} else if (reasonCode != MqttReturnCode.RETURN_CODE_SUCCESS || identifierValueFieldsByteArray.length > 1) {
|
||||
// Encode the Return Code
|
||||
outputStream.write((byte) reasonCode);
|
||||
// Write Identifier / Value Fields
|
||||
outputStream.write(identifierValueFieldsByteArray);
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public int getReturnCode() {
|
||||
return reasonCode;
|
||||
}
|
||||
|
||||
public void setReturnCode(int returnCode) {
|
||||
this.reasonCode = returnCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttPubRec [returnCode=" + reasonCode + ", properties=" + properties + "]";
|
||||
}
|
||||
|
||||
}
|
123
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPubRel.java
Normal file
123
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPubRel.java
Normal file
@@ -0,0 +1,123 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
|
||||
public class MqttPubRel extends MqttPersistableWireMessage {
|
||||
|
||||
private static final int[] validReturnCodes = { MqttReturnCode.RETURN_CODE_SUCCESS,
|
||||
MqttReturnCode.RETURN_CODE_PACKET_ID_NOT_FOUND };
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.REASON_STRING_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
// Fields
|
||||
private MqttProperties properties;
|
||||
|
||||
public MqttPubRel(byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PUBREL);
|
||||
properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
CountingInputStream counter = new CountingInputStream(bais);
|
||||
DataInputStream dis = new DataInputStream(counter);
|
||||
msgId = dis.readUnsignedShort();
|
||||
long remainder = (long) data.length - counter.getCounter();
|
||||
if (remainder >= 1) {
|
||||
reasonCode = dis.readUnsignedByte();
|
||||
validateReturnCode(reasonCode, validReturnCodes);
|
||||
} else {
|
||||
reasonCode = 0;
|
||||
}
|
||||
if (remainder >= 4) {
|
||||
this.properties.decodeProperties(dis);
|
||||
}
|
||||
dis.close();
|
||||
}
|
||||
|
||||
public MqttPubRel(int returnCode, int msgId, MqttProperties properties) throws MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PUBREL);
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
this.reasonCode = returnCode;
|
||||
this.msgId = msgId;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Message ID
|
||||
outputStream.writeShort(msgId);
|
||||
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
|
||||
if (reasonCode != MqttReturnCode.RETURN_CODE_SUCCESS && identifierValueFieldsByteArray.length == 1) {
|
||||
// Encode the Return Code
|
||||
outputStream.write((byte) reasonCode);
|
||||
} else if (reasonCode != MqttReturnCode.RETURN_CODE_SUCCESS || identifierValueFieldsByteArray.length > 1) {
|
||||
// Encode the Return Code
|
||||
outputStream.write((byte) reasonCode);
|
||||
// Write Identifier / Value Fields
|
||||
outputStream.write(identifierValueFieldsByteArray);
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getMessageInfo() {
|
||||
return (byte) (2 | (this.duplicate ? 8 : 0));
|
||||
}
|
||||
|
||||
public int getReturnCode() {
|
||||
return reasonCode;
|
||||
}
|
||||
|
||||
public void setReturnCode(int returnCode) {
|
||||
this.reasonCode = returnCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttPubRel [returnCode=" + reasonCode + ", properties=" + properties + "]";
|
||||
}
|
||||
|
||||
}
|
242
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPublish.java
Normal file
242
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttPublish.java
Normal file
@@ -0,0 +1,242 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.MqttMessage;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
|
||||
/**
|
||||
* An on-the-wire representation of an MQTT Publish message.
|
||||
*/
|
||||
public class MqttPublish extends MqttPersistableWireMessage {
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.PAYLOAD_FORMAT_INDICATOR_IDENTIFIER,
|
||||
MqttProperties.MESSAGE_EXPIRY_INTERVAL_IDENTIFIER, MqttProperties.TOPIC_ALIAS_IDENTIFIER,
|
||||
MqttProperties.RESPONSE_TOPIC_IDENTIFIER, MqttProperties.CORRELATION_DATA_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER, MqttProperties.CONTENT_TYPE_IDENTIFIER,
|
||||
MqttProperties.SUBSCRIPTION_IDENTIFIER_MULTI, MqttProperties.SUBSCRIPTION_IDENTIFIER };
|
||||
|
||||
private MqttProperties properties;
|
||||
|
||||
// Fields
|
||||
private byte[] payload;
|
||||
private int qos = 1;
|
||||
private boolean retained = false;
|
||||
private boolean dup = false;
|
||||
private String topicName;
|
||||
|
||||
/**
|
||||
* Constructs a new MqttPublish message
|
||||
*
|
||||
* @param topic
|
||||
* - The Destination Topic.
|
||||
* @param message
|
||||
* - The Message being sent.
|
||||
* @param properties
|
||||
* - The {@link MqttProperties} for the packet.
|
||||
*/
|
||||
public MqttPublish(String topic, MqttMessage message, MqttProperties properties) {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PUBLISH);
|
||||
this.topicName = topic;
|
||||
this.payload = message.getPayload();
|
||||
this.qos = message.getQos();
|
||||
this.dup = message.isDuplicate();
|
||||
this.retained = message.isRetained();
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new MqttPublish message from a byte array
|
||||
*
|
||||
* @param info
|
||||
* - Info Byte
|
||||
* @param data
|
||||
* - The variable header and payload bytes.
|
||||
* @throws IOException
|
||||
* - if an exception occurs when decoding an input stream
|
||||
* @throws MqttException
|
||||
* - If an exception occurs decoding this packet
|
||||
*/
|
||||
public MqttPublish(byte info, byte[] data) throws MqttException, IOException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_PUBLISH);
|
||||
this.properties = new MqttProperties(validProperties);
|
||||
this.qos = (info >> 1) & 0x03;
|
||||
if ((info & 0x01) == 0x01) {
|
||||
this.retained = true;
|
||||
}
|
||||
|
||||
if ((info & 0x08) == 0x08) {
|
||||
this.dup = true;
|
||||
}
|
||||
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
CountingInputStream counter = new CountingInputStream(bais);
|
||||
DataInputStream dis = new DataInputStream(counter);
|
||||
|
||||
topicName = MqttDataTypes.decodeUTF8(dis);
|
||||
if (this.qos > 0) {
|
||||
msgId = dis.readUnsignedShort();
|
||||
}
|
||||
this.properties.decodeProperties(dis);
|
||||
this.payload = new byte[data.length - counter.getCounter()];
|
||||
dis.readFully(this.payload);
|
||||
dis.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(baos);
|
||||
|
||||
// If we are using a Topic Alias, then the topic should be empty
|
||||
if (topicName != null) {
|
||||
MqttDataTypes.encodeUTF8(dos, topicName);
|
||||
} else {
|
||||
MqttDataTypes.encodeUTF8(dos, "");
|
||||
}
|
||||
|
||||
if (this.qos > 0) {
|
||||
dos.writeShort(msgId);
|
||||
}
|
||||
// Write Identifier / Value Fields
|
||||
byte[] identifierValueFieldsArray = this.properties.encodeProperties();
|
||||
dos.write(identifierValueFieldsArray);
|
||||
dos.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getMessageInfo() {
|
||||
byte info = (byte) (this.qos << 1);
|
||||
if (this.retained) {
|
||||
info |= 0x01;
|
||||
}
|
||||
if (this.dup || duplicate) {
|
||||
info |= 0x08;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() {
|
||||
return this.payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPayloadLength() {
|
||||
if (this.payload != null) {
|
||||
return this.payload.length;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMessageIdRequired() {
|
||||
// all publishes require a message ID as it's used as the key to the
|
||||
// token store
|
||||
return true;
|
||||
}
|
||||
|
||||
public MqttMessage getMessage() {
|
||||
MqttMessage message = new MqttMessage(payload, qos, retained, properties);
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(MqttMessage message) {
|
||||
this.payload = message.getPayload();
|
||||
this.qos = message.getQos();
|
||||
this.dup = message.isDuplicate();
|
||||
this.retained = message.isRetained();
|
||||
}
|
||||
|
||||
public String getTopicName() {
|
||||
return topicName;
|
||||
}
|
||||
|
||||
public int getQoS() {
|
||||
return qos;
|
||||
}
|
||||
|
||||
public void setTopicName(String topicName) {
|
||||
this.topicName = topicName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// Convert the first few bytes of the payload into a hex string
|
||||
StringBuilder hex = new StringBuilder();
|
||||
int limit = Math.min(payload.length, 20);
|
||||
for (int i = 0; i < limit; i++) {
|
||||
byte b = payload[i];
|
||||
String ch = Integer.toHexString(b);
|
||||
if (ch.length() == 1) {
|
||||
ch = "0" + ch;
|
||||
}
|
||||
hex.append(ch);
|
||||
}
|
||||
|
||||
// It will not always be possible to convert the binary payload into
|
||||
// characters, but never-the-less we attempt to do this as it is often
|
||||
// useful.
|
||||
String string = null;
|
||||
try {
|
||||
string = new String(payload, 0, limit, "UTF-8");
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
string = "?";
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("MqttPublish [");
|
||||
sb.append(", qos=").append(this.qos);
|
||||
if (this.qos > 0) {
|
||||
sb.append(", messageId=").append(msgId);
|
||||
}
|
||||
sb.append(", retained=").append(this.retained);
|
||||
sb.append(", duplicate=").append(duplicate);
|
||||
sb.append(", topic=").append(topicName);
|
||||
sb.append(", payload=[hex=").append(hex);
|
||||
sb.append(", utf8=").append(string);
|
||||
sb.append(", length=").append(payload.length).append("]");
|
||||
sb.append(", properties=").append(this.properties.toString());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttMessage;
|
||||
|
||||
public class MqttReceivedMessage extends MqttMessage {
|
||||
|
||||
public void setMessageId(int messageId){
|
||||
super.setId(messageId);
|
||||
}
|
||||
|
||||
public int getMessageId(){
|
||||
return super.getId();
|
||||
}
|
||||
|
||||
// This method exists here to get around the protected visibility of the
|
||||
// super class method.
|
||||
@Override
|
||||
public void setDuplicate(boolean value) {
|
||||
super.setDuplicate(value);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
/**
|
||||
* Reference of MQTT v5 Return Codes - 2.4
|
||||
*/
|
||||
public class MqttReturnCode {
|
||||
|
||||
/** Success and general Return Codes **/
|
||||
public static final int RETURN_CODE_SUCCESS = 0x00; // 0
|
||||
public static final int RETURN_CODE_MAX_QOS_0 = 0x00; // 0
|
||||
public static final int RETURN_CODE_MAX_QOS_1 = 0x01; // 1
|
||||
public static final int RETURN_CODE_MAX_QOS_2 = 0x02; // 2
|
||||
public static final int RETURN_CODE_DISCONNECT_WITH_WILL_MESSAGE = 0x04; // 4
|
||||
public static final int RETURN_CODE_NO_MATCHING_SUBSCRIBERS = 0x10; // 16
|
||||
public static final int RETURN_CODE_NO_SUBSCRIPTION_EXISTED = 0x11; // 17
|
||||
public static final int RETURN_CODE_CONTINUE_AUTHENTICATION = 0x18; // 24
|
||||
public static final int RETURN_CODE_RE_AUTHENTICATE = 0x19; // 25
|
||||
|
||||
/** Error Return Codes **/
|
||||
public static final int RETURN_CODE_UNSPECIFIED_ERROR = 0x80; // 128
|
||||
public static final int RETURN_CODE_MALFORMED_CONTROL_PACKET = 0x81; // 129
|
||||
public static final int RETURN_CODE_PROTOCOL_ERROR = 0x82; // 130
|
||||
public static final int RETURN_CODE_IMPLEMENTATION_SPECIFIC_ERROR = 0x83; // 131
|
||||
public static final int RETURN_CODE_UNSUPPORTED_PROTOCOL_VERSION = 0x84; // 132
|
||||
public static final int RETURN_CODE_IDENTIFIER_NOT_VALID = 0x85; // 133
|
||||
public static final int RETURN_CODE_BAD_USERNAME_OR_PASSWORD = 0x86; // 134
|
||||
public static final int RETURN_CODE_NOT_AUTHORIZED = 0x87; // 135
|
||||
public static final int RETURN_CODE_SERVER_UNAVAILABLE = 0x88; // 136
|
||||
public static final int RETURN_CODE_SERVER_BUSY = 0x89; // 137
|
||||
public static final int RETURN_CODE_BANNED = 0x8A; // 138
|
||||
public static final int RETURN_CODE_SERVER_SHUTTING_DOWN = 0x8B; // 139
|
||||
public static final int RETURN_CODE_BAD_AUTHENTICATION = 0x8C; // 140
|
||||
public static final int RETURN_CODE_KEEP_ALIVE_TIMEOUT = 0x8D; // 141
|
||||
public static final int RETURN_CODE_SESSION_TAKEN_OVER = 0x8E; // 142
|
||||
public static final int RETURN_CODE_TOPIC_FILTER_NOT_VALID = 0x8F; // 143
|
||||
public static final int RETURN_CODE_TOPIC_NAME_INVALID = 0x90; // 144
|
||||
public static final int RETURN_CODE_PACKET_ID_IN_USE = 0x91; // 145
|
||||
public static final int RETURN_CODE_PACKET_ID_NOT_FOUND = 0x92; // 146
|
||||
public static final int RETURN_CODE_RECEIVE_MAXIMUM_EXCEEDED = 0x93; // 147
|
||||
public static final int RETURN_CODE_TOPIC_ALIAS_NOT_ACCEPTED = 0x94; // 148
|
||||
public static final int RETURN_CODE_PACKET_TOO_LARGE = 0x95; // 149
|
||||
public static final int RETURN_CODE_MESSAGE_RATE_TOO_HIGH = 0x96; // 150
|
||||
public static final int RETURN_CODE_QUOTA_EXCEEDED = 0x97; // 151
|
||||
public static final int RETURN_CODE_ADMINISTRITIVE_ACTION = 0x98; // 152
|
||||
public static final int RETURN_CODE_PAYLOAD_FORMAT_INVALID = 0x99; // 153
|
||||
public static final int RETURN_CODE_RETAIN_NOT_SUPPORTED = 0x9A; // 154
|
||||
public static final int RETURN_CODE_QOS_NOT_SUPPORTED = 0x9B; // 155
|
||||
public static final int RETURN_CODE_USE_ANOTHER_SERVER = 0x9C; // 156
|
||||
public static final int RETURN_CODE_SERVER_MOVED = 0x9D; // 157
|
||||
public static final int RETURN_CODE_SHARED_SUB_NOT_SUPPORTED = 0x9E; // 158
|
||||
public static final int RETURN_CODE_CONNECTION_RATE_EXCEEDED = 0x9F; // 159
|
||||
public static final int RETURN_CODE_MAXIMUM_CONNECT_TIME = 0xA0; // 160
|
||||
public static final int RETURN_CODE_SUB_IDENTIFIERS_NOT_SUPPORTED = 0xA1; // 161
|
||||
public static final int RETURN_CODE_WILDCARD_SUB_NOT_SUPPORTED = 0xA2; // 162
|
||||
|
||||
|
||||
private MqttReturnCode() {
|
||||
throw new IllegalAccessError("Utility class");
|
||||
}
|
||||
|
||||
|
||||
}
|
134
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttSubAck.java
Normal file
134
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttSubAck.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
|
||||
public class MqttSubAck extends MqttAck {
|
||||
|
||||
private static final int[] validReturnCodes = { MqttReturnCode.RETURN_CODE_MAX_QOS_0,
|
||||
MqttReturnCode.RETURN_CODE_MAX_QOS_1, MqttReturnCode.RETURN_CODE_MAX_QOS_2,
|
||||
MqttReturnCode.RETURN_CODE_UNSPECIFIED_ERROR, MqttReturnCode.RETURN_CODE_IMPLEMENTATION_SPECIFIC_ERROR,
|
||||
MqttReturnCode.RETURN_CODE_NOT_AUTHORIZED, MqttReturnCode.RETURN_CODE_TOPIC_FILTER_NOT_VALID,
|
||||
MqttReturnCode.RETURN_CODE_PACKET_ID_IN_USE, MqttReturnCode.RETURN_CODE_SHARED_SUB_NOT_SUPPORTED };
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.REASON_STRING_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
// Fields
|
||||
private MqttProperties properties;
|
||||
|
||||
public MqttSubAck(byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_SUBACK);
|
||||
properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
CountingInputStream counter = new CountingInputStream(bais);
|
||||
DataInputStream inputStream = new DataInputStream(counter);
|
||||
msgId = inputStream.readUnsignedShort();
|
||||
this.properties.decodeProperties(inputStream);
|
||||
|
||||
int remainingLength = data.length - counter.getCounter();
|
||||
reasonCodes = new int[remainingLength];
|
||||
|
||||
for (int i = 0; i < remainingLength; i++) {
|
||||
int returnCode = inputStream.readUnsignedByte();
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
reasonCodes[i] = returnCode;
|
||||
}
|
||||
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
public MqttSubAck(int[] returnCodes, MqttProperties properties) throws MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_SUBACK);
|
||||
for (int returnCode : returnCodes) {
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
}
|
||||
this.reasonCodes = returnCodes;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Message ID
|
||||
outputStream.writeShort(msgId);
|
||||
|
||||
// Write Identifier / Value Fields
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
// Write Identifier / Value Fields
|
||||
outputStream.write(identifierValueFieldsByteArray);
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
for (int returnCode : reasonCodes) {
|
||||
outputStream.writeByte(returnCode);
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getReturnCodes() {
|
||||
return reasonCodes;
|
||||
}
|
||||
|
||||
public void setReturnCodes(int[] returnCodes) {
|
||||
this.reasonCodes = returnCodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttSubAck [returnCodes=" + Arrays.toString(reasonCodes) + ", properties=" + properties + "]";
|
||||
}
|
||||
|
||||
}
|
217
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttSubscribe.java
Normal file
217
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttSubscribe.java
Normal file
@@ -0,0 +1,217 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2019 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.MqttSubscription;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
|
||||
public class MqttSubscribe extends MqttPersistableWireMessage {
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.SUBSCRIPTION_IDENTIFIER,
|
||||
MqttProperties.SUBSCRIPTION_IDENTIFIER_SINGLE,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
// Fields
|
||||
private MqttProperties properties;
|
||||
private MqttSubscription[] subscriptions;
|
||||
|
||||
/**
|
||||
* Constructor for an on the Wire MQTT Subscribe message
|
||||
*
|
||||
* @param data
|
||||
* - The variable header and payload bytes.
|
||||
* @throws IOException
|
||||
* - if an exception occurs when decoding an input stream
|
||||
* @throws MqttException
|
||||
* - If an exception occurs decoding this packet
|
||||
*/
|
||||
public MqttSubscribe(byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_SUBSCRIBE);
|
||||
this.properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
CountingInputStream counter = new CountingInputStream(bais);
|
||||
DataInputStream inputStream = new DataInputStream(counter);
|
||||
msgId = inputStream.readUnsignedShort();
|
||||
|
||||
this.properties.decodeProperties(inputStream);
|
||||
|
||||
ArrayList<MqttSubscription> subscriptionList = new ArrayList<>();
|
||||
// Whilst we are reading data
|
||||
while (counter.getCounter() < data.length) {
|
||||
String topic = MqttDataTypes.decodeUTF8(inputStream);
|
||||
byte subscriptionOptions = inputStream.readByte();
|
||||
subscriptionList.add(decodeSubscription(topic, subscriptionOptions));
|
||||
}
|
||||
subscriptions = subscriptionList.toArray(new MqttSubscription[subscriptionList.size()]);
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for an on the Wire MQTT Subscribe message
|
||||
*
|
||||
* @param subscriptions
|
||||
* - An Array of {@link MqttSubscription} subscriptions.
|
||||
* @param properties
|
||||
* - The {@link MqttProperties} for the packet.
|
||||
*/
|
||||
public MqttSubscribe(MqttSubscription[] subscriptions, MqttProperties properties) {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_SUBSCRIBE);
|
||||
this.subscriptions = subscriptions;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for an on the Wire MQTT Subscribe message
|
||||
*
|
||||
* @param subscription
|
||||
* - An {@link MqttSubscription}
|
||||
* @param properties
|
||||
* - The {@link MqttProperties} for the packet.
|
||||
*/
|
||||
public MqttSubscribe(MqttSubscription subscription, MqttProperties properties) {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_SUBSCRIBE);
|
||||
this.subscriptions = new MqttSubscription[] { subscription };
|
||||
this.properties = properties;
|
||||
this.properties.setValidProperties(validProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Message ID
|
||||
outputStream.writeShort(msgId);
|
||||
|
||||
// Write Identifier / Value Fields
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
outputStream.write(identifierValueFieldsByteArray);
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
for (MqttSubscription subscription : subscriptions) {
|
||||
outputStream.write(encodeSubscription(subscription));
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRetryable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes an {@link MqttSubscription} into it's on-the-wire representation.
|
||||
* Assumes that the Subscription topic is valid.
|
||||
*
|
||||
* @param subscription
|
||||
* - The {@link MqttSubscription} to encode.
|
||||
* @return A byte array containing the encoded subscription.
|
||||
* @throws MqttException
|
||||
*/
|
||||
private byte[] encodeSubscription(MqttSubscription subscription) throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
MqttDataTypes.encodeUTF8(outputStream, subscription.getTopic());
|
||||
|
||||
// Encode Subscription QoS
|
||||
byte subscriptionOptions = (byte) subscription.getQos();
|
||||
|
||||
// Encode NoLocal Option
|
||||
if (subscription.isNoLocal()) {
|
||||
subscriptionOptions |= 0x04;
|
||||
}
|
||||
|
||||
// Encode Retain As Published Option
|
||||
if (subscription.isRetainAsPublished()) {
|
||||
subscriptionOptions |= 0x08;
|
||||
}
|
||||
|
||||
// Encode Retain Handling Level
|
||||
subscriptionOptions |= (subscription.getRetainHandling() << 4);
|
||||
|
||||
outputStream.write(subscriptionOptions);
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
private MqttSubscription decodeSubscription(String topic, byte subscriptionOptions) {
|
||||
MqttSubscription subscription = new MqttSubscription(topic);
|
||||
subscription.setQos(subscriptionOptions & 0x03);
|
||||
subscription.setNoLocal((subscriptionOptions & 0x04) != 0);
|
||||
subscription.setRetainAsPublished((subscriptionOptions & 0x08) != 0);
|
||||
subscription.setRetainHandling((subscriptionOptions >> 4) & 0x03);
|
||||
return subscription;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getMessageInfo() {
|
||||
return (byte) (2 | (duplicate ? 8 : 0));
|
||||
}
|
||||
|
||||
public MqttSubscription[] getSubscriptions() {
|
||||
return subscriptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttSubscribe [properties=" + properties + ", subscriptions=" + Arrays.toString(subscriptions) + "]";
|
||||
}
|
||||
|
||||
}
|
130
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttUnsubAck.java
Normal file
130
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttUnsubAck.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
|
||||
public class MqttUnsubAck extends MqttAck {
|
||||
|
||||
private static final int[] validReturnCodes = { MqttReturnCode.RETURN_CODE_SUCCESS,
|
||||
MqttReturnCode.RETURN_CODE_NO_SUBSCRIPTION_EXISTED, MqttReturnCode.RETURN_CODE_UNSPECIFIED_ERROR,
|
||||
MqttReturnCode.RETURN_CODE_IMPLEMENTATION_SPECIFIC_ERROR, MqttReturnCode.RETURN_CODE_NOT_AUTHORIZED,
|
||||
MqttReturnCode.RETURN_CODE_TOPIC_FILTER_NOT_VALID, MqttReturnCode.RETURN_CODE_PACKET_ID_IN_USE };
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.REASON_STRING_IDENTIFIER,
|
||||
MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
// Fields
|
||||
private MqttProperties properties;
|
||||
|
||||
public MqttUnsubAck(byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_UNSUBACK);
|
||||
properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
CountingInputStream counter = new CountingInputStream(bais);
|
||||
DataInputStream inputStream = new DataInputStream(counter);
|
||||
|
||||
msgId = inputStream.readUnsignedShort();
|
||||
|
||||
this.properties.decodeProperties(inputStream);
|
||||
|
||||
int remainingLengh = data.length - counter.getCounter();
|
||||
reasonCodes = new int[remainingLengh];
|
||||
|
||||
for (int i = 0; i < remainingLengh; i++) {
|
||||
reasonCodes[i] = inputStream.readUnsignedByte();
|
||||
validateReturnCode(reasonCodes[i], validReturnCodes);
|
||||
}
|
||||
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
public MqttUnsubAck(int[] returnCodes, MqttProperties properties) throws MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_UNSUBACK);
|
||||
for (int returnCode : returnCodes) {
|
||||
validateReturnCode(returnCode, validReturnCodes);
|
||||
}
|
||||
this.reasonCodes = returnCodes;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
// Encode the msgId
|
||||
outputStream.writeShort(msgId);
|
||||
|
||||
// Write Identifier / Value Fields
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
// Write Identifier / Value Fields
|
||||
outputStream.write(identifierValueFieldsByteArray);
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
for (int returnCode : reasonCodes) {
|
||||
outputStream.writeByte(returnCode);
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int[] getReturnCodes() {
|
||||
return reasonCodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttUnsubAck [returnCodes=" + Arrays.toString(reasonCodes) + ", properties=" + properties + "]";
|
||||
}
|
||||
|
||||
}
|
138
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttUnsubscribe.java
Normal file
138
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttUnsubscribe.java
Normal file
@@ -0,0 +1,138 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2019 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
|
||||
public class MqttUnsubscribe extends MqttPersistableWireMessage{
|
||||
|
||||
private static final Byte[] validProperties = { MqttProperties.USER_DEFINED_PAIR_IDENTIFIER };
|
||||
|
||||
|
||||
// Fields
|
||||
private String[] topics;
|
||||
private MqttProperties properties;
|
||||
|
||||
|
||||
|
||||
public MqttUnsubscribe(byte[] data) throws IOException, MqttException {
|
||||
super(MqttWireMessage.MESSAGE_TYPE_UNSUBSCRIBE);
|
||||
this.properties = new MqttProperties(validProperties);
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
CountingInputStream counter = new CountingInputStream(bais);
|
||||
DataInputStream inputStream = new DataInputStream(counter);
|
||||
msgId = inputStream.readUnsignedShort();
|
||||
|
||||
this.properties.decodeProperties(inputStream);
|
||||
|
||||
ArrayList<String> topicList = new ArrayList<>();
|
||||
// Whilst we are reading data
|
||||
while(counter.getCounter() < data.length){
|
||||
topicList.add( MqttDataTypes.decodeUTF8(inputStream));
|
||||
}
|
||||
topics = topicList.toArray(new String[topicList.size()]);
|
||||
|
||||
|
||||
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
public MqttUnsubscribe(String[] topics, MqttProperties properties){
|
||||
super(MqttWireMessage.MESSAGE_TYPE_UNSUBSCRIBE);
|
||||
this.topics = topics;
|
||||
if (properties != null) {
|
||||
this.properties = properties;
|
||||
} else {
|
||||
this.properties = new MqttProperties();
|
||||
}
|
||||
this.properties.setValidProperties(validProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getVariableHeader() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
// Encode the Message ID
|
||||
outputStream.writeShort(msgId);
|
||||
|
||||
|
||||
// Write Identifier / Value Fields
|
||||
byte[] identifierValueFieldsByteArray = this.properties.encodeProperties();
|
||||
outputStream.write(identifierValueFieldsByteArray);
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream outputStream = new DataOutputStream(baos);
|
||||
|
||||
for(String topic : topics){
|
||||
MqttDataTypes.encodeUTF8(outputStream, topic);
|
||||
}
|
||||
|
||||
outputStream.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe){
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected byte getMessageInfo() {
|
||||
return (byte)( 2 | (this.duplicate ? 8 : 0));
|
||||
}
|
||||
|
||||
public String[] getTopics() {
|
||||
return topics;
|
||||
}
|
||||
|
||||
public void setTopics(String[] topics) {
|
||||
this.topics = topics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MqttProperties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MqttUnsubscribe [topics=" + Arrays.toString(topics) + ", properties=" + properties + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
417
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttWireMessage.java
Normal file
417
mqtt/org/eclipse/paho/mqttv5/common/packet/MqttWireMessage.java
Normal file
@@ -0,0 +1,417 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.eclipse.paho.mqttv5.common.ExceptionHelper;
|
||||
import org.eclipse.paho.mqttv5.common.MqttException;
|
||||
import org.eclipse.paho.mqttv5.common.MqttPersistable;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.CountingInputStream;
|
||||
import org.eclipse.paho.mqttv5.common.packet.util.MultiByteArrayInputStream;
|
||||
|
||||
/**
|
||||
* An on-the wire representation of an MQTTv5 Message
|
||||
*/
|
||||
public abstract class MqttWireMessage {
|
||||
|
||||
public static final byte MESSAGE_TYPE_RESERVED = 0;
|
||||
public static final byte MESSAGE_TYPE_CONNECT = 1;
|
||||
public static final byte MESSAGE_TYPE_CONNACK = 2;
|
||||
public static final byte MESSAGE_TYPE_PUBLISH = 3;
|
||||
public static final byte MESSAGE_TYPE_PUBACK = 4;
|
||||
public static final byte MESSAGE_TYPE_PUBREC = 5;
|
||||
public static final byte MESSAGE_TYPE_PUBREL = 6;
|
||||
public static final byte MESSAGE_TYPE_PUBCOMP = 7;
|
||||
public static final byte MESSAGE_TYPE_SUBSCRIBE = 8;
|
||||
public static final byte MESSAGE_TYPE_SUBACK = 9;
|
||||
public static final byte MESSAGE_TYPE_UNSUBSCRIBE = 10;
|
||||
public static final byte MESSAGE_TYPE_UNSUBACK = 11;
|
||||
public static final byte MESSAGE_TYPE_PINGREQ = 12;
|
||||
public static final byte MESSAGE_TYPE_PINGRESP = 13;
|
||||
public static final byte MESSAGE_TYPE_DISCONNECT = 14;
|
||||
public static final byte MESSAGE_TYPE_AUTH = 15;
|
||||
|
||||
protected static final String STRING_ENCODING = "UTF-8";
|
||||
protected static final String DEFAULT_PROTOCOL_NAME = "MQTT";
|
||||
protected static final int DEFAULT_PROTOCOL_VERSION = 5;
|
||||
|
||||
private static final String[] PACKET_NAMES = { "reserved", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC",
|
||||
"PUBREL", "PUBCOMP", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", "DISCONNECT",
|
||||
"AUTH" };
|
||||
|
||||
private static final byte[] PACKET_RESERVED_MASKS = { 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0 };
|
||||
|
||||
// The type of the message (e.g CONNECT, PUBLISH, SUBSCRIBE)
|
||||
private byte type;
|
||||
|
||||
MqttProperties properties = new MqttProperties();
|
||||
|
||||
// The MQTT Message ID
|
||||
protected int msgId;
|
||||
protected int[] reasonCodes = null; // Multiple Reason Codes (SUBACK, UNSUBACK)
|
||||
protected int reasonCode = -1; // Single Reason Code, init with -1 as that's an invalid RC
|
||||
protected boolean duplicate = false;
|
||||
|
||||
public MqttWireMessage(byte type) {
|
||||
this.type = type;
|
||||
// Use zero as the default message ID. Can't use -1, as that is serialized
|
||||
// as 65535, which would be a valid ID.
|
||||
this.msgId = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-classes should override this to encode the message info. Only the
|
||||
* least-significant four bits will be used.
|
||||
*
|
||||
* @return The Message information byte.
|
||||
*/
|
||||
protected abstract byte getMessageInfo();
|
||||
|
||||
/**
|
||||
* Sub-classes should override this method to supply the payload bytes.
|
||||
*
|
||||
* @return The payload byte array
|
||||
* @throws MqttException
|
||||
* if an exception occurs whilst getting the payload.
|
||||
*/
|
||||
public byte[] getPayload() throws MqttException {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type of the message
|
||||
*/
|
||||
public byte getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the MQTT message ID
|
||||
*/
|
||||
public int getMessageId() {
|
||||
return msgId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the MQTT message ID.
|
||||
*
|
||||
* @param msgId
|
||||
* the MQTT message ID
|
||||
*/
|
||||
public void setMessageId(int msgId) {
|
||||
this.msgId = msgId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a key associated with the message. For most message types this will
|
||||
* be unique. For connect, disconnect and ping only one message of this type is
|
||||
* allowed so a fixed key will be returned.
|
||||
*
|
||||
* @return The key associated with the message
|
||||
*/
|
||||
public String getKey() {
|
||||
return Integer.toString(getMessageId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a byte array containing the MQTT header for the message.
|
||||
*
|
||||
* @return The MQTT Message Header
|
||||
* @throws MqttException
|
||||
* if there was an issue encoding the header
|
||||
*/
|
||||
public byte[] getHeader() throws MqttException {
|
||||
try {
|
||||
int first = ((getType() & 0x0f) << 4) ^ (getMessageInfo() & 0x0f);
|
||||
byte[] varHeader = getVariableHeader();
|
||||
int remLen = varHeader.length + getPayload().length;
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(baos);
|
||||
dos.writeByte(first);
|
||||
dos.write(encodeVariableByteInteger(remLen));
|
||||
dos.write(varHeader);
|
||||
dos.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract byte[] getVariableHeader() throws MqttException;
|
||||
|
||||
/**
|
||||
* @return whether or not this message needs to include a message ID.
|
||||
*/
|
||||
public boolean isMessageIdRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an MQTT Wire Message
|
||||
*
|
||||
* @throws MqttException
|
||||
* if an error occurred whilst creating the WireMessage
|
||||
* @param data
|
||||
* the MqttPersistable to create the message from
|
||||
* @return MqttWireMessage the de-persisted message
|
||||
*/
|
||||
public static MqttWireMessage createWireMessage(MqttPersistable data) throws MqttException {
|
||||
byte[] payload = data.getPayloadBytes();
|
||||
|
||||
// The persistable interface allows a message to be restored entirely in the
|
||||
// header array.
|
||||
// We need to treat these two arrays as a single array of bytes and use the
|
||||
// decoding
|
||||
// logic to identify the true header / payload split.
|
||||
|
||||
if (payload == null) {
|
||||
payload = new byte[0];
|
||||
}
|
||||
MultiByteArrayInputStream mbais = new MultiByteArrayInputStream(data.getHeaderBytes(), data.getHeaderOffset(),
|
||||
data.getHeaderLength(), payload, data.getPayloadOffset(), data.getPayloadLength());
|
||||
return createWireMessage(mbais);
|
||||
}
|
||||
|
||||
public static MqttWireMessage createWireMessage(byte[] bytes) throws MqttException {
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
|
||||
return createWireMessage(bais);
|
||||
}
|
||||
|
||||
private static MqttWireMessage createWireMessage(InputStream inputStream) throws MqttException {
|
||||
try {
|
||||
CountingInputStream counter = new CountingInputStream(inputStream);
|
||||
DataInputStream in = new DataInputStream(counter);
|
||||
int first = in.readUnsignedByte();
|
||||
byte type = (byte) (first >> 4);
|
||||
byte info = (byte) (first &= 0x0f);
|
||||
long remLen = MqttDataTypes.readVariableByteInteger(in).getValue();
|
||||
long totalToRead = counter.getCounter() + remLen;
|
||||
|
||||
MqttWireMessage result;
|
||||
long remainder = totalToRead - counter.getCounter();
|
||||
byte[] data = new byte[0];
|
||||
|
||||
// The remaining bytes must be the payload
|
||||
if (remainder > 0) {
|
||||
data = new byte[(int) remainder];
|
||||
in.readFully(data, 0, data.length);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case MqttWireMessage.MESSAGE_TYPE_CONNECT:
|
||||
result = new MqttConnect(info, data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_CONNACK:
|
||||
result = new MqttConnAck(data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_PUBLISH:
|
||||
result = new MqttPublish(info, data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_PUBACK:
|
||||
result = new MqttPubAck(data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_PUBREC:
|
||||
result = new MqttPubRec(data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_PUBREL:
|
||||
result = new MqttPubRel(data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_PUBCOMP:
|
||||
result = new MqttPubComp(data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_SUBSCRIBE:
|
||||
result = new MqttSubscribe(data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_SUBACK:
|
||||
result = new MqttSubAck(data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_UNSUBSCRIBE:
|
||||
result = new MqttUnsubscribe(data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_UNSUBACK:
|
||||
result = new MqttUnsubAck(data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_PINGREQ:
|
||||
result = new MqttPingReq();
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_PINGRESP:
|
||||
result = new MqttPingResp();
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_DISCONNECT:
|
||||
result = new MqttDisconnect(data);
|
||||
break;
|
||||
case MqttWireMessage.MESSAGE_TYPE_AUTH:
|
||||
result = new MqttAuth(data);
|
||||
break;
|
||||
default:
|
||||
throw ExceptionHelper.createMqttException(MqttException.REASON_CODE_MALFORMED_PACKET);
|
||||
}
|
||||
return result;
|
||||
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] encodeVariableByteInteger(int number) {
|
||||
int numBytes = 0;
|
||||
long no = number;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
// Encode the remaining length fields in the four bytes
|
||||
do {
|
||||
byte digit = (byte) (no % 128);
|
||||
no = no / 128;
|
||||
if (no > 0) {
|
||||
digit |= 0x80;
|
||||
}
|
||||
baos.write(digit);
|
||||
numBytes++;
|
||||
} while ((no > 0) && (numBytes < 4));
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the reserved bits set on an MQTT packet conform to the MQTT
|
||||
* specification.
|
||||
*
|
||||
* @param type
|
||||
* - The Message Type
|
||||
* @param reserved
|
||||
* - The Reserved Bits
|
||||
* @throws MqttException
|
||||
* If the set reserved bits do not match the specification.
|
||||
* @throws IllegalArgumentException
|
||||
* If the message type does not exist.
|
||||
*/
|
||||
public static void validateReservedBits(byte type, byte reserved) throws MqttException, IllegalArgumentException {
|
||||
if (type == MESSAGE_TYPE_PUBLISH) {
|
||||
// Publish can vary, but will be parsed separately.
|
||||
return;
|
||||
}
|
||||
if (type > MESSAGE_TYPE_AUTH) {
|
||||
throw new IllegalArgumentException("Unrecognised Message Type.");
|
||||
}
|
||||
if (reserved != PACKET_RESERVED_MASKS[type]) {
|
||||
throw new MqttException(MqttException.REASON_CODE_MALFORMED_PACKET);
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] encodeMessageId() throws MqttException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream dos = new DataOutputStream(baos);
|
||||
dos.writeShort(msgId);
|
||||
dos.flush();
|
||||
return baos.toByteArray();
|
||||
} catch (IOException ioe) {
|
||||
throw new MqttException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRetryable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setDuplicate(boolean duplicate) {
|
||||
this.duplicate = duplicate;
|
||||
}
|
||||
|
||||
public boolean isDuplicate() {
|
||||
return this.duplicate;
|
||||
}
|
||||
|
||||
public MqttProperties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public void setProperties(MqttProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return PACKET_NAMES[type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a return code is valid for this Packet
|
||||
*
|
||||
* @param returnCode
|
||||
* - The return code to validate
|
||||
* @param validReturnCodes
|
||||
* - The list of valid return codes
|
||||
* @throws MqttException
|
||||
* - Thrown if the return code is not valid
|
||||
*/
|
||||
protected void validateReturnCode(int returnCode, int[] validReturnCodes) throws MqttException {
|
||||
for (int validReturnCode : validReturnCodes) {
|
||||
if (returnCode == validReturnCode) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new MqttException(MqttException.REASON_CODE_INVALID_RETURN_CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the reason codes from the MqttWireMessage. These will be present if
|
||||
* the messages is of the following types:
|
||||
* <ul>
|
||||
* <li>CONNACK - 1 Reason Code Max.</li>
|
||||
* <li>PUBACK - 1 Reason Code Max.</li>
|
||||
* <li>PUBREC - 1 Reason Code Max.</li>
|
||||
* <li>PUBCOMP - 1 Reason Code Max.</li>
|
||||
* <li>PUBREL - 1 Reason Code Max.</li>
|
||||
* <li>SUBACK - 1 or more Reason Codes.</li>
|
||||
* <li>UNSUBACK - 1 or more Reason Codes.</li>
|
||||
* <li>AUTH - 1 Reason Code Max.</li>
|
||||
* </ul>
|
||||
*
|
||||
* Warning: This method may be removed in favour of Token.getReasonCodes()
|
||||
*
|
||||
* May be null if this message does not contain any Reason Codes.
|
||||
*
|
||||
* @return An array of return codes, or null.
|
||||
*/
|
||||
public int[] getReasonCodes() {
|
||||
if (this.reasonCodes != null) {
|
||||
return this.reasonCodes;
|
||||
} else if (this.reasonCode != -1) {
|
||||
return new int[] { this.reasonCode };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] serialize() throws MqttException {
|
||||
byte[] a = getHeader();
|
||||
byte[] b = getPayload();
|
||||
|
||||
byte[] c = new byte[a.length + b.length];
|
||||
System.arraycopy(a, 0, c, 0, a.length);
|
||||
System.arraycopy(b, 0, c, a.length, b.length);
|
||||
return c;
|
||||
}
|
||||
|
||||
}
|
40
mqtt/org/eclipse/paho/mqttv5/common/packet/UserProperty.java
Normal file
40
mqtt/org/eclipse/paho/mqttv5/common/packet/UserProperty.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package org.eclipse.paho.mqttv5.common.packet;
|
||||
|
||||
public class UserProperty {
|
||||
private final String key;
|
||||
private final String value;
|
||||
|
||||
public UserProperty(String key, String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return key.hashCode() ^ value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof UserProperty) {
|
||||
UserProperty property = (UserProperty) o;
|
||||
return this.key.equals(property.getKey()) && this.value.equals(property.getValue());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserProperty [key=" + key + ", value=" + value + "]";
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class CountingInputStream extends InputStream{
|
||||
private InputStream inputStream;
|
||||
private int counter;
|
||||
|
||||
|
||||
/**Constructs a new <code>CountingInputStream</code> wrapping the supplied
|
||||
* input stream.
|
||||
* @param inputStream The inputStream to count and provide
|
||||
*/
|
||||
public CountingInputStream(InputStream inputStream){
|
||||
this.inputStream = inputStream;
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
int i = inputStream.read();
|
||||
if (i != -1){
|
||||
counter++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes read since last reset
|
||||
* @return the counter
|
||||
*/
|
||||
public int getCounter() {
|
||||
return counter;
|
||||
}
|
||||
/**
|
||||
* Resets the counter to zero
|
||||
*/
|
||||
public void resetCounter() {
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class MultiByteArrayInputStream extends InputStream {
|
||||
|
||||
private byte[] bytesA;
|
||||
private int offsetA;
|
||||
private int lengthA;
|
||||
private byte[] bytesB;
|
||||
private int offsetB;
|
||||
private int lengthB;
|
||||
|
||||
private int pos = 0;
|
||||
|
||||
public MultiByteArrayInputStream(byte[] bytesA, int offsetA, int lengthA, byte[] bytesB, int offsetB, int lengthB) {
|
||||
this.bytesA = bytesA;
|
||||
this.bytesB = bytesB;
|
||||
this.offsetA = offsetA;
|
||||
this.offsetB = offsetB;
|
||||
this.lengthA = lengthA;
|
||||
this.lengthB = lengthB;
|
||||
}
|
||||
public int read() throws IOException {
|
||||
int result = -1;
|
||||
if (pos<lengthA) {
|
||||
result = bytesA[offsetA+pos];
|
||||
} else if (pos<lengthA+lengthB) {
|
||||
result = bytesB[offsetB+pos-lengthA];
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (result < 0) {
|
||||
result += 256;
|
||||
}
|
||||
pos++;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v2.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0
|
||||
* and the Eclipse Distribution License is available at
|
||||
* https://www.eclipse.org/org/documents/edl-v10.php
|
||||
*
|
||||
* Contributors:
|
||||
* Dave Locke - Original MQTTv3 implementation
|
||||
* James Sutton - Initial MQTTv5 implementation
|
||||
*/
|
||||
package org.eclipse.paho.mqttv5.common.packet.util;
|
||||
|
||||
/**
|
||||
* Represents a Variable Byte Integer (VBI), as defined by the MQTT v5 (1.5.5)
|
||||
* specification.
|
||||
*/
|
||||
public class VariableByteInteger {
|
||||
private int value;
|
||||
private int length;
|
||||
|
||||
public VariableByteInteger(int value) {
|
||||
this(value, -1);
|
||||
}
|
||||
|
||||
public VariableByteInteger(int value, int length) {
|
||||
this.value = value;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes read when decoding this MBI
|
||||
*
|
||||
* @return The Encoded Length of the VBI.
|
||||
*/
|
||||
public int getEncodedLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this MBI.
|
||||
*
|
||||
* @return The value of the VBI.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user