/* * Copyright (c) 2012-2015 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package org.eclipse.moquette.proto; import org.eclipse.moquette.proto.messages.AbstractMessage; /** * Common utils methodd used in codecs. * * @author andrea */ public class Utils { public static final int MAX_LENGTH_LIMIT = 268435455; // /** // * Read 2 bytes from in buffer first MSB, and then LSB returning as int. // */ // static int readWord(IoBuffer in) { // int msb = in.get() & 0x00FF; //remove sign extension due to casting // int lsb = in.get() & 0x00FF; // msb = (msb << 8) | lsb ; // return msb; // } // // /** // * Writes as 2 bytes the int value into buffer first MSB, and then LSB. // */ // static void writeWord(IoBuffer out, int value) { // out.put((byte) ((value & 0xFF00) >> 8)); //msb // out.put((byte) (value & 0x00FF)); //lsb // } // // /** // * Decode the variable remaining lenght as defined in MQTT v3.1 specification // * (section 2.1). // * // * @return the decoded length or -1 if needed more data to decode the length field. // */ // static int decodeRemainingLenght(IoBuffer in) { // int multiplier = 1; // int value = 0; // byte digit; // do { // if (in.remaining() < 1) { // return -1; // } // digit = in.get(); // value += (digit & 0x7F) * multiplier; // multiplier *= 128; // } while ((digit & 0x80) != 0); // return value; // } /** * Return the number of bytes to encode the gicen remaining length value */ static int numBytesToEncode(int len) { if (0 <= len && len <= 127) return 1; if (128 <= len && len <= 16383) return 2; if (16384 <= len && len <= 2097151) return 3; if (2097152 <= len && len <= 268435455) return 4; throw new IllegalArgumentException("value shoul be in the range [0..268435455]"); } // /** // * Encode the value in the format defined in specification as variable length // * array. // * // * @throws IllegalArgumentException if the value is not in the specification bounds // * [0..268435455]. // */ // static IoBuffer encodeRemainingLength(int value) throws IllegalAccessException { // if (value > MAX_LENGTH_LIMIT || value < 0) { // throw new IllegalAccessException("Value should in range 0.." + MAX_LENGTH_LIMIT + " found " + value); // } // // IoBuffer encoded = IoBuffer.allocate(4); // byte digit; // do { // digit = (byte) (value % 128); // value = value / 128; // // if there are more digits to encode, set the top bit of this digit // if (value > 0) { // digit = (byte) (digit | 0x80); // } // encoded.put(digit); // } while (value > 0); // encoded.flip(); // return encoded; // } // // static MessageDecoderResult checkDecodable(byte type, IoBuffer in) { // if (in.remaining() < 1) { // return MessageDecoderResult.NEED_DATA; // } // byte h1 = in.get(); // byte messageType = (byte) ((h1 & 0x00F0) >> 4); // // int remainingLength = Utils.decodeRemainingLenght(in); // if (remainingLength == -1) { // return MessageDecoderResult.NEED_DATA; // } // // //check remaining length // if (in.remaining() < remainingLength) { // return MessageDecoderResult.NEED_DATA; // } // // return messageType == type ? MessageDecoderResult.OK : MessageDecoderResult.NOT_OK; // } // // /** // * Return the IoBuffer with string encoded as MSB, LSB and UTF-8 encoded // * string content. // */ // static IoBuffer encodeString(String str) { // IoBuffer out = IoBuffer.allocate(2).setAutoExpand(true); // byte[] raw; // try { // raw = str.getBytes("UTF-8"); // //NB every Java platform has got UTF-8 encoding by default, so this // //exception are never raised. // } catch (UnsupportedEncodingException ex) { // LoggerFactory.getLogger(ConnectEncoder.class).error(null, ex); // return null; // } // Utils.writeWord(out, raw.length); // out.put(raw).flip(); // return out; // } // // // /** // * Load a string from the given buffer, reading first the two bytes of len // * and then the UTF-8 bytes of the string. // * // * @return the decoded string or null if NEED_DATA // */ // static String decodeString(IoBuffer in) throws UnsupportedEncodingException { // if (in.remaining() < 2) { // return null; // } // int strLen = Utils.readWord(in); // if (in.remaining() < strLen) { // return null; // } // byte[] strRaw = new byte[strLen]; // in.get(strRaw); // // return new String(strRaw, "UTF-8"); // } static byte encodeFlags(AbstractMessage message) { byte flags = 0; if (message.isDupFlag()) { flags |= 0x08; } if (message.isRetainFlag()) { flags |= 0x01; } flags |= ((message.getQos().ordinal() & 0x03) << 1); return flags; } /** * Converts MQTT message type to a textual description. * */ public static String msgType2String(int type) { switch (type) { case AbstractMessage.CONNECT: return "CONNECT"; case AbstractMessage.CONNACK: return "CONNACK"; case AbstractMessage.PUBLISH: return "PUBLISH"; case AbstractMessage.PUBACK: return "PUBACK"; case AbstractMessage.PUBREC: return "PUBREC"; case AbstractMessage.PUBREL: return "PUBREL"; case AbstractMessage.PUBCOMP: return "PUBCOMP"; case AbstractMessage.SUBSCRIBE: return "SUBSCRIBE"; case AbstractMessage.SUBACK: return "SUBACK"; case AbstractMessage.UNSUBSCRIBE: return "UNSUBSCRIBE"; case AbstractMessage.UNSUBACK: return "UNSUBACK"; case AbstractMessage.PINGREQ: return "PINGREQ"; case AbstractMessage.PINGRESP: return "PINGRESP"; case AbstractMessage.DISCONNECT: return "DISCONNECT"; default: throw new RuntimeException("Can't decode message type " + type); } } }