1420c9859SShuo Chenpackage muduo.codec; 2420c9859SShuo Chen 3420c9859SShuo Chenimport java.nio.charset.Charset; 4420c9859SShuo Chenimport java.util.HashMap; 5420c9859SShuo Chenimport java.util.Map; 6420c9859SShuo Chenimport java.util.zip.Adler32; 7420c9859SShuo Chen 8420c9859SShuo Chenimport org.jboss.netty.buffer.ChannelBuffer; 9420c9859SShuo Chenimport org.jboss.netty.channel.Channel; 10420c9859SShuo Chenimport org.jboss.netty.channel.ChannelHandler.Sharable; 11420c9859SShuo Chenimport org.jboss.netty.channel.ChannelHandlerContext; 12420c9859SShuo Chenimport org.jboss.netty.handler.codec.oneone.OneToOneDecoder; 13420c9859SShuo Chen 14420c9859SShuo Chenimport com.google.protobuf.Message; 15420c9859SShuo Chen 16420c9859SShuo Chen@Sharable 17420c9859SShuo Chenpublic class ProtobufDecoder extends OneToOneDecoder { 18420c9859SShuo Chen 19420c9859SShuo Chen private Map<String, Message> knownTypes = new HashMap<String, Message>(); 20420c9859SShuo Chen 21420c9859SShuo Chen @Override 22420c9859SShuo Chen public Object decode(ChannelHandlerContext ctx, Channel channel, Object obj) 23420c9859SShuo Chen throws Exception { 24420c9859SShuo Chen if (!(obj instanceof ChannelBuffer)) { 25420c9859SShuo Chen return obj; 26420c9859SShuo Chen } 27420c9859SShuo Chen ChannelBuffer buffer = (ChannelBuffer) obj; 28420c9859SShuo Chen if (buffer.readableBytes() >= 10 && checksum(buffer)) { 29420c9859SShuo Chen int nameLen = buffer.readInt(); 30420c9859SShuo Chen String typeName = buffer.toString(buffer.readerIndex(), nameLen - 1, 31420c9859SShuo Chen Charset.defaultCharset()); 32420c9859SShuo Chen buffer.readerIndex(buffer.readerIndex() + nameLen); 33420c9859SShuo Chen Message prototype = knownTypes.get(typeName); 34420c9859SShuo Chen if (prototype != null) { 35420c9859SShuo Chen return prototype.newBuilderForType().mergeFrom(buffer.array(), 36420c9859SShuo Chen buffer.arrayOffset() + buffer.readerIndex(), 37420c9859SShuo Chen buffer.readableBytes() - 4).build(); 38420c9859SShuo Chen } 39420c9859SShuo Chen } 40420c9859SShuo Chen return obj; 41420c9859SShuo Chen } 42420c9859SShuo Chen 43420c9859SShuo Chen private boolean checksum(ChannelBuffer buffer) { 44420c9859SShuo Chen Adler32 adler32 = new Adler32(); 45420c9859SShuo Chen adler32.update(buffer.array(), 46420c9859SShuo Chen buffer.arrayOffset() + buffer.readerIndex(), 47420c9859SShuo Chen buffer.readableBytes() - 4); 48420c9859SShuo Chen buffer.markReaderIndex(); 49420c9859SShuo Chen buffer.readerIndex(buffer.writerIndex() - 4); 50420c9859SShuo Chen int checksum = buffer.readInt(); 51420c9859SShuo Chen buffer.resetReaderIndex(); 52420c9859SShuo Chen return checksum == (int) adler32.getValue(); 53420c9859SShuo Chen } 54420c9859SShuo Chen 55420c9859SShuo Chen public void addMessageType(Message message) { 56420c9859SShuo Chen knownTypes.put(message.getDescriptorForType().getFullName(), message); 57420c9859SShuo Chen } 58420c9859SShuo Chen} 59