Ejemplo n.º 1
0
  @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;
  }
Ejemplo n.º 5
0
  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;
  }