private static short checksum(ChannelBuffer buf) { short sum = 0; for (int i = 0; i < buf.readableBytes(); i++) { sum ^= buf.getUnsignedByte(i); } return sum; }
/** * Read a PeerAddress from a Netty buffer. I did not want to include ChannelBuffer in the class * PeerAddress * * @param buffer The Netty buffer * @return A PeerAddress created from the buffer (deserialized) */ private static PeerAddress readPeerAddress(final ChannelBuffer buffer) { if (buffer.readableBytes() < 21) return null; Number160 id = readID(buffer); // peek int type = buffer.getUnsignedByte(buffer.readerIndex()); // now we know the length int len = PeerAddress.expectedSocketLength(type); if (buffer.readableBytes() < len) return null; PeerAddress peerAddress = new PeerAddress(id, buffer.array(), buffer.arrayOffset() + buffer.readerIndex()); buffer.skipBytes(len); return peerAddress; }
/** * Simple "content sniffing". May not be a great idea, but will do until this class has a better * API. * * @param buf The content of the reply to send. * @return The MIME type guessed from {@code buf}. */ private String guessMimeTypeFromContents(final ChannelBuffer buf) { if (!buf.readable()) { logWarn("Sending an empty result?! buf=" + buf); return "text/plain"; } final int firstbyte = buf.getUnsignedByte(buf.readerIndex()); switch (firstbyte) { case '<': // <html or <!DOCTYPE return HTML_CONTENT_TYPE; case '{': // JSON object case '[': // JSON array return "application/json"; // RFC 4627 section 6 mandates this. case 0x89: // magic number in PNG files. return "image/png"; } return "text/plain"; // Default. }
@Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) throws Exception { // Check minimum length if (buf.readableBytes() < 12) { return null; } int length; switch (buf.getUnsignedByte(buf.readerIndex())) { case AutoFonProtocolDecoder.MSG_LOGIN: length = 12; break; case AutoFonProtocolDecoder.MSG_LOCATION: length = 78; break; case AutoFonProtocolDecoder.MSG_HISTORY: length = 257; break; case AutoFonProtocolDecoder.MSG_45_LOGIN: length = 19; break; case AutoFonProtocolDecoder.MSG_45_LOCATION: length = 34; break; default: length = 0; break; } // Check length and return buffer if (length != 0 && buf.readableBytes() >= length) { return buf.readBytes(length); } return null; }
@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; buf.skipBytes(4); // system code int type = buf.readUnsignedByte(); long deviceUniqueId = buf.readUnsignedInt(); if (type != MSG_CLIENT_SERIAL) { buf.readUnsignedShort(); // communication control } byte packetNumber = buf.readByte(); // Send reply sendReply(channel, deviceUniqueId, packetNumber); // Parse location if (type == MSG_CLIENT_STATUS) { Position position = new Position(); position.setProtocol(getProtocolName()); // Device identifier if (!identify(String.valueOf(deviceUniqueId), channel)) { return null; } position.setDeviceId(getDeviceId()); buf.readUnsignedByte(); // hardware version buf.readUnsignedByte(); // software version buf.readUnsignedByte(); // protocol version // Status position.set(Event.KEY_STATUS, buf.getUnsignedByte(buf.readerIndex()) & 0x0f); int operator = (buf.readUnsignedByte() & 0xf0) << 4; operator += buf.readUnsignedByte(); buf.readUnsignedByte(); // reason data buf.readUnsignedByte(); // reason buf.readUnsignedByte(); // mode buf.readUnsignedInt(); // IO operator <<= 8; operator += buf.readUnsignedByte(); position.set("operator", operator); buf.readUnsignedInt(); // ADC buf.readUnsignedMedium(); // Odometer buf.skipBytes(6); // multi-purpose data buf.readUnsignedShort(); // gps fix buf.readUnsignedByte(); // location status buf.readUnsignedByte(); // mode 1 buf.readUnsignedByte(); // mode 2 position.setValid(buf.readUnsignedByte() >= 3); // satellites // Location data position.setLongitude(buf.readInt() / Math.PI * 180 / 100000000); position.setLatitude(buf.readInt() / Math.PI * 180 / 100000000.0); position.setAltitude(buf.readInt() * 0.01); position.setSpeed(UnitsConverter.knotsFromMps(buf.readInt() * 0.01)); position.setCourse(buf.readUnsignedShort() / Math.PI * 180.0 / 1000.0); // Time Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); time.clear(); time.set(Calendar.SECOND, buf.readUnsignedByte()); time.set(Calendar.MINUTE, buf.readUnsignedByte()); time.set(Calendar.HOUR_OF_DAY, buf.readUnsignedByte()); time.set(Calendar.DAY_OF_MONTH, buf.readUnsignedByte()); time.set(Calendar.MONTH, buf.readUnsignedByte() - 1); time.set(Calendar.YEAR, buf.readUnsignedShort()); position.setTime(time.getTime()); return position; } return null; }
private ParseResult parsePosition(ChannelBuffer buf) { Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(getDeviceId()); int format; if (buf.getUnsignedByte(buf.readerIndex()) == 0) { format = buf.readUnsignedShort(); } else { format = buf.readUnsignedByte(); } position.set("format", format); long index = buf.readUnsignedInt(); position.set(Event.KEY_INDEX, index); position.set(Event.KEY_EVENT, buf.readUnsignedShort()); buf.skipBytes(6); // event time position.set(Event.KEY_ALARM, buf.readUnsignedByte()); position.set(Event.KEY_STATUS, buf.readUnsignedByte()); position.set(Event.KEY_GSM, buf.readUnsignedByte()); if (isFormat(format, F10, F20, F30)) { position.set(Event.KEY_OUTPUT, buf.readUnsignedShort()); } else if (isFormat(format, F40, F50, F51, F52)) { position.set(Event.KEY_OUTPUT, buf.readUnsignedByte()); } if (isFormat(format, F10, F20, F30, F40)) { position.set(Event.KEY_INPUT, buf.readUnsignedShort()); } else if (isFormat(format, F50, F51, F52)) { position.set(Event.KEY_INPUT, buf.readUnsignedByte()); } position.set(Event.KEY_POWER, buf.readUnsignedShort() * 0.001); position.set(Event.KEY_BATTERY, buf.readUnsignedShort()); if (isFormat(format, F10, F20, F30)) { position.set(Event.PREFIX_TEMP + 1, buf.readShort()); } if (isFormat(format, F10, F20, F50, F52)) { position.set(Event.PREFIX_ADC + 1, buf.readUnsignedShort()); position.set(Event.PREFIX_ADC + 2, buf.readUnsignedShort()); } // Impulse counters if (isFormat(format, F20, F50, F51, F52)) { buf.readUnsignedInt(); buf.readUnsignedInt(); } if (isFormat(format, F20, F50, F51, F52)) { int locationStatus = buf.readUnsignedByte(); position.setValid(BitUtil.check(locationStatus, 1)); DateBuilder dateBuilder = new DateBuilder() .setTime(buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()) .setDateReverse( buf.readUnsignedByte(), buf.readUnsignedByte(), buf.readUnsignedByte()); position.setTime(dateBuilder.getDate()); position.setLatitude(buf.readFloat() / Math.PI * 180); position.setLongitude(buf.readFloat() / Math.PI * 180); position.setSpeed(buf.readFloat()); position.setCourse(buf.readUnsignedShort()); position.set(Event.KEY_ODOMETER, buf.readFloat()); position.set("segment", buf.readFloat()); // last segment // Segment times buf.readUnsignedShort(); buf.readUnsignedShort(); } // Other if (isFormat(format, F51, F52)) { buf.readUnsignedShort(); buf.readByte(); buf.readUnsignedShort(); buf.readUnsignedShort(); buf.readByte(); buf.readUnsignedShort(); buf.readUnsignedShort(); buf.readByte(); buf.readUnsignedShort(); } // Four temperature sensors if (isFormat(format, F40, F52)) { buf.readByte(); buf.readByte(); buf.readByte(); buf.readByte(); } return new ParseResult(index, position); }
@Override public int getUnsignedByte() { return buffer.getUnsignedByte(buffer.readerIndex()); }
@Override protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { ChannelBuffer buf = (ChannelBuffer) msg; buf.readUnsignedShort(); // device id buf.readUnsignedByte(); // length int type = buf.readUnsignedByte(); DeviceSession deviceSession; if (type == MSG_IMEI) { deviceSession = getDeviceSession( channel, remoteAddress, buf.readBytes(15).toString(StandardCharsets.US_ASCII)); } else { deviceSession = getDeviceSession(channel, remoteAddress); } if (deviceSession == null) { return null; } if (BitUtil.to(type, 2) == 0) { Position position = new Position(); position.setProtocol(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); buf.readUnsignedByte(); // firmware version buf.readUnsignedShort(); // index position.set(Position.KEY_STATUS, buf.readUnsignedShort()); position.setValid(true); position.setLatitude(buf.readFloat()); position.setLongitude(buf.readFloat()); position.setCourse(buf.readUnsignedShort() * 0.1); position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShort() * 0.1)); buf.readUnsignedByte(); // acceleration position.setAltitude(buf.readUnsignedShort()); position.set(Position.KEY_HDOP, buf.readUnsignedByte() * 0.1); position.set(Position.KEY_SATELLITES, buf.readUnsignedByte() & 0x0f); position.setTime(new Date(buf.readUnsignedInt() * 1000)); position.set(Position.KEY_POWER, buf.readUnsignedShort()); position.set(Position.KEY_BATTERY, buf.readUnsignedShort()); if (BitUtil.check(type, 2)) { buf.skipBytes(4); } if (BitUtil.check(type, 3)) { buf.skipBytes(12); } if (BitUtil.check(type, 4)) { buf.skipBytes(8); } if (BitUtil.check(type, 5)) { buf.skipBytes(9); } if (BitUtil.check(type, 6)) { buf.skipBytes(buf.getUnsignedByte(buf.readerIndex())); } if (BitUtil.check(type, 7)) { position.set(Position.KEY_ODOMETER, buf.readUnsignedInt()); } return position; } return null; }