@Override protected Object decode(final ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { if (buffer.readableBytes() < 5) { return null; } int packetLength = 0; // SSLv3 or TLS - Check ContentType boolean tls; switch (buffer.getUnsignedByte(buffer.readerIndex())) { case 20: // change_cipher_spec case 21: // alert case 22: // handshake case 23: // application_data tls = true; break; default: // SSLv2 or bad data tls = false; } if (tls) { // SSLv3 or TLS - Check ProtocolVersion int majorVersion = buffer.getUnsignedByte(buffer.readerIndex() + 1); if (majorVersion >= 3 && majorVersion < 10) { // SSLv3 or TLS packetLength = (buffer.getShort(buffer.readerIndex() + 3) & 0xFFFF) + 5; if (packetLength <= 5) { // Neither SSLv2 or TLSv1 (i.e. SSLv2 or bad data) tls = false; } } else { // Neither SSLv2 or TLSv1 (i.e. SSLv2 or bad data) tls = false; } } if (!tls) { // SSLv2 or bad data - Check the version boolean sslv2 = true; int headerLength = (buffer.getUnsignedByte(buffer.readerIndex()) & 0x80) != 0 ? 2 : 3; int majorVersion = buffer.getUnsignedByte(buffer.readerIndex() + headerLength + 1); if (majorVersion >= 2 && majorVersion < 10) { // SSLv2 if (headerLength == 2) { packetLength = (buffer.getShort(buffer.readerIndex()) & 0x7FFF) + 2; } else { packetLength = (buffer.getShort(buffer.readerIndex()) & 0x3FFF) + 3; } if (packetLength <= headerLength) { sslv2 = false; } } else { sslv2 = false; } if (!sslv2) { // Bad data - discard the buffer and raise an exception. SSLException e = new SSLException("not an SSL/TLS record: " + ChannelBuffers.hexDump(buffer)); buffer.skipBytes(buffer.readableBytes()); throw e; } } assert packetLength > 0; if (buffer.readableBytes() < packetLength) { return null; } // We advance the buffer's readerIndex before calling unwrap() because // unwrap() can trigger FrameDecoder call decode(), this method, recursively. // The recursive call results in decoding the same packet twice if // the readerIndex is advanced *after* decode(). // // Here's an example: // 1) An SSL packet is received from the wire. // 2) SslHandler.decode() deciphers the packet and calls the user code. // 3) The user closes the channel in the same thread. // 4) The same thread triggers a channelDisconnected() event. // 5) FrameDecoder.cleanup() is called, and it calls SslHandler.decode(). // 6) SslHandler.decode() will feed the same packet with what was // deciphered at the step 2 again if the readerIndex was not advanced // before calling the user code. final int packetOffset = buffer.readerIndex(); buffer.skipBytes(packetLength); return unwrap(ctx, channel, buffer, packetOffset, packetLength); }
@Override protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { ChannelBuffer buf = (ChannelBuffer) msg; int type = buf.readUnsignedShort(); buf.readUnsignedShort(); // length if (type == MSG_IDENT || type == MSG_IDENT_FULL) { buf.readUnsignedInt(); // id int length = buf.readUnsignedShort(); buf.skipBytes(length); length = buf.readUnsignedShort(); buf.skipBytes(length); length = buf.readUnsignedShort(); String imei = buf.readBytes(length).toString(Charset.defaultCharset()); identify(imei, channel, remoteAddress); } else if (hasDeviceId() && (type == MSG_POINT || type == MSG_ALARM || type == MSG_LOGMSG)) { List<Position> positions = new LinkedList<>(); int recordCount = 1; if (type == MSG_LOGMSG) { recordCount = buf.readUnsignedShort(); } for (int j = 0; j < recordCount; j++) { Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(getDeviceId()); if (type == MSG_LOGMSG) { position.set(Event.KEY_ARCHIVE, true); int subtype = buf.readUnsignedShort(); if (subtype == MSG_ALARM) { position.set(Event.KEY_ALARM, true); } if (buf.readUnsignedShort() > buf.readableBytes()) { lastIndex += 1; break; // workaround for device bug } lastIndex = buf.readUnsignedInt(); position.set(Event.KEY_INDEX, lastIndex); } else { newIndex = buf.readUnsignedInt(); } position.setTime(new Date(buf.readUnsignedInt() * 1000)); position.setLatitude(buf.readInt() * 180.0 / 0x7FFFFFFF); position.setLongitude(buf.readInt() * 180.0 / 0x7FFFFFFF); position.setSpeed(buf.readUnsignedInt() * 0.01); position.setCourse(buf.readUnsignedShort() * 0.01); position.setAltitude(buf.readUnsignedShort() * 0.01); int satellites = buf.readUnsignedByte(); position.setValid(satellites >= 3); position.set(Event.KEY_SATELLITES, satellites); position.set(Event.KEY_GSM, buf.readUnsignedByte()); position.set(Event.KEY_ODOMETER, buf.readUnsignedInt()); long extraFlags = buf.readLong(); if (BitUtil.check(extraFlags, 0)) { int count = buf.readUnsignedShort(); for (int i = 1; i <= count; i++) { position.set(Event.PREFIX_ADC + i, buf.readUnsignedShort()); } } if (BitUtil.check(extraFlags, 1)) { int size = buf.readUnsignedShort(); position.set("can", buf.toString(buf.readerIndex(), size, Charset.defaultCharset())); buf.skipBytes(size); } if (BitUtil.check(extraFlags, 2)) { position.set("passenger", ChannelBuffers.hexDump(buf.readBytes(buf.readUnsignedShort()))); } if (type == MSG_ALARM) { position.set(Event.KEY_ALARM, true); byte[] response = {(byte) 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; channel.write(ChannelBuffers.wrappedBuffer(response)); } buf.readUnsignedInt(); // crc positions.add(position); } requestArchive(channel); return positions; } return null; }
private void decodeCanData(ChannelBuffer buf, Position position) { buf.readUnsignedMedium(); // packet identifier buf.readUnsignedByte(); // version int count = buf.readUnsignedByte(); buf.readUnsignedByte(); // batch count buf.readUnsignedShort(); // selector bit buf.readUnsignedInt(); // timestamp buf.skipBytes(8); ArrayList<ChannelBuffer> values = new ArrayList<>(count); for (int i = 0; i < count; i++) { values.add(buf.readBytes(8)); } for (int i = 0; i < count; i++) { ChannelBuffer value = values.get(i); switch (buf.readInt()) { case 0x20D: position.set(Event.KEY_RPM, ChannelBuffers.swapShort(value.readShort())); position.set("diesel-temperature", ChannelBuffers.swapShort(value.readShort()) * 0.1); position.set("battery-voltage", ChannelBuffers.swapShort(value.readShort()) * 0.01); position.set("supply-air-temp-dep1", ChannelBuffers.swapShort(value.readShort()) * 0.1); break; case 0x30D: position.set("active-alarm", ChannelBuffers.hexDump(value)); break; case 0x40C: position.set("air-temp-dep1", ChannelBuffers.swapShort(value.readShort()) * 0.1); position.set("air-temp-dep2", ChannelBuffers.swapShort(value.readShort()) * 0.1); break; case 0x40D: position.set("cold-unit-state", ChannelBuffers.hexDump(value)); break; case 0x50C: position.set("defrost-temp-dep1", ChannelBuffers.swapShort(value.readShort()) * 0.1); position.set("defrost-temp-dep2", ChannelBuffers.swapShort(value.readShort()) * 0.1); break; case 0x50D: position.set("condenser-pressure", ChannelBuffers.swapShort(value.readShort()) * 0.1); position.set("suction-pressure", ChannelBuffers.swapShort(value.readShort()) * 0.1); break; case 0x58C: value.readByte(); value.readShort(); // index switch (value.readByte()) { case 0x01: position.set("setpoint-zone1", ChannelBuffers.swapInt(value.readInt()) * 0.1); break; case 0x02: position.set("setpoint-zone2", ChannelBuffers.swapInt(value.readInt()) * 0.1); break; case 0x05: position.set("unit-type", ChannelBuffers.swapInt(value.readInt())); break; case 0x13: position.set("diesel-hours", ChannelBuffers.swapInt(value.readInt()) / 60 / 60); break; case 0x14: position.set("electric-hours", ChannelBuffers.swapInt(value.readInt()) / 60 / 60); break; case 0x17: position.set("service-indicator", ChannelBuffers.swapInt(value.readInt())); break; case 0x18: position.set("software-version", ChannelBuffers.swapInt(value.readInt()) * 0.01); break; default: break; } break; default: Log.warning(new UnsupportedOperationException()); break; } } }
@Override protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { ChannelBuffer buf = (ChannelBuffer) msg; buf.skipBytes(2); // header buf.readUnsignedShort(); // length String imei = ChannelBuffers.hexDump(buf.readBytes(7)); if (!identify(imei, channel, null, false) && !identify(imei + Checksum.luhn(Long.parseLong(imei)), channel)) { return null; } int type = buf.readUnsignedShort(); if (type == MSG_LOCATION_REPORT || type == MSG_LOCATION_REQUEST) { String sentence = buf.toString(buf.readerIndex(), buf.readableBytes() - 8, Charset.defaultCharset()); Parser parser = new Parser(PATTERN, sentence); if (!parser.matches()) { return null; } Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(getDeviceId()); if (parser.hasNext(15)) { DateBuilder dateBuilder = new DateBuilder() .setDate(parser.nextInt(), parser.nextInt(), parser.nextInt()) .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt()); position.setTime(dateBuilder.getDate()); position.setValid(parser.next().equals("A")); position.set(Event.KEY_SATELLITES, parser.next()); position.setLatitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG)); position.setLongitude(parser.nextCoordinate(Parser.CoordinateFormat.HEM_DEG)); position.setSpeed(parser.nextDouble()); position.set(Event.KEY_HDOP, parser.nextDouble()); position.setAltitude(parser.nextDouble()); } else { getLastLocation(position, null); } position.set(Event.KEY_MCC, parser.nextInt()); position.set(Event.KEY_MNC, parser.nextInt()); position.set(Event.KEY_LAC, parser.nextInt()); position.set(Event.KEY_CELL, parser.nextInt()); return position; } return null; }
private Position decodeNormalMessage( ChannelBuffer buf, Channel channel, SocketAddress remoteAddress) { Position position = new Position(); position.setProtocol(getProtocolName()); buf.readByte(); // header String id = String.valueOf(Long.parseLong(ChannelBuffers.hexDump(buf.readBytes(5)))); if (!identify(id, channel, remoteAddress)) { return null; } position.setDeviceId(getDeviceId()); int version = ChannelBufferTools.readHexInteger(buf, 1); buf.readUnsignedByte(); // type buf.readBytes(2); // length DateBuilder dateBuilder = new DateBuilder() .setDay(ChannelBufferTools.readHexInteger(buf, 2)) .setMonth(ChannelBufferTools.readHexInteger(buf, 2)) .setYear(ChannelBufferTools.readHexInteger(buf, 2)) .setHour(ChannelBufferTools.readHexInteger(buf, 2)) .setMinute(ChannelBufferTools.readHexInteger(buf, 2)) .setSecond(ChannelBufferTools.readHexInteger(buf, 2)); position.setTime(dateBuilder.getDate()); double latitude = convertCoordinate(ChannelBufferTools.readHexInteger(buf, 8)); double longitude = convertCoordinate(ChannelBufferTools.readHexInteger(buf, 9)); byte flags = buf.readByte(); position.setValid((flags & 0x1) == 0x1); if ((flags & 0x2) == 0) { latitude = -latitude; } position.setLatitude(latitude); if ((flags & 0x4) == 0) { longitude = -longitude; } position.setLongitude(longitude); position.setSpeed(ChannelBufferTools.readHexInteger(buf, 2)); position.setCourse(buf.readUnsignedByte() * 2.0); if (version == 1) { position.set(Event.KEY_SATELLITES, buf.readUnsignedByte()); position.set(Event.KEY_POWER, buf.readUnsignedByte()); buf.readByte(); // other flags and sensors position.setAltitude(buf.readUnsignedShort()); int cid = buf.readUnsignedShort(); int lac = buf.readUnsignedShort(); if (cid != 0 && lac != 0) { position.set(Event.KEY_CID, cid); position.set(Event.KEY_LAC, lac); } position.set(Event.KEY_GSM, buf.readUnsignedByte()); } else if (version == 2) { int fuel = buf.readUnsignedByte() << 8; position.set(Event.KEY_STATUS, buf.readUnsignedInt()); position.set(Event.KEY_ODOMETER, buf.readUnsignedInt()); fuel += buf.readUnsignedByte(); position.set(Event.KEY_FUEL, fuel); } return position; }