package cc.blynk.client.handlers.decoders; import cc.blynk.server.core.protocol.enums.Command; import cc.blynk.server.core.protocol.enums.Response; import cc.blynk.server.core.protocol.handlers.DefaultExceptionHandler; import cc.blynk.server.core.protocol.model.messages.MessageBase; import cc.blynk.server.core.protocol.model.messages.ResponseMessage; import cc.blynk.server.core.protocol.model.messages.ResponseWithBodyMessage; import cc.blynk.server.core.protocol.model.messages.appllication.GetGraphDataBinaryMessage; import cc.blynk.server.core.protocol.model.messages.appllication.GetProjectByTokenBinaryMessage; import cc.blynk.server.core.protocol.model.messages.appllication.LoadProfileGzippedBinaryMessage; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.nio.charset.StandardCharsets; import java.util.List; import static cc.blynk.server.core.protocol.model.messages.MessageFactory.produce; /** * Decodes input byte array into java message. * * The Blynk Project. * Created by Dmitriy Dumanskiy. * Created on 2/1/2015. */ public class ClientMessageDecoder extends ByteToMessageDecoder implements DefaultExceptionHandler { protected static final Logger log = LogManager.getLogger(ClientMessageDecoder.class); @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.readableBytes() < 5) { return; } in.markReaderIndex(); short command = in.readUnsignedByte(); int messageId = in.readUnsignedShort(); MessageBase message; if (command == Command.RESPONSE) { int responseCode = in.readUnsignedShort(); if (responseCode == Response.DEVICE_WENT_OFFLINE) { message = new ResponseWithBodyMessage(messageId, Command.RESPONSE, responseCode, in.readInt()); } else { message = new ResponseMessage(messageId, responseCode); } } else { int length = in.readUnsignedShort(); if (in.readableBytes() < length) { in.resetReaderIndex(); return; } ByteBuf buf = in.readSlice(length); switch (command) { case Command.GET_GRAPH_DATA_RESPONSE : byte[] bytes = new byte[buf.readableBytes()]; buf.readBytes(bytes); message = new GetGraphDataBinaryMessage(messageId, bytes); break; case Command.LOAD_PROFILE_GZIPPED : bytes = new byte[buf.readableBytes()]; buf.readBytes(bytes); message = new LoadProfileGzippedBinaryMessage(messageId, bytes); break; case Command.GET_PROJECT_BY_TOKEN : bytes = new byte[buf.readableBytes()]; buf.readBytes(bytes); message = new GetProjectByTokenBinaryMessage(messageId, bytes); break; default: message = produce(messageId, command, buf.toString(StandardCharsets.UTF_8)); } } log.trace("Incoming client {}", message); out.add(message); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { handleGeneralException(ctx, cause); } }