View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package openr66.protocol.localhandler.packet;
22  
23  import goldengate.common.exception.InvalidArgumentException;
24  import openr66.protocol.exception.OpenR66ProtocolPacketException;
25  
26  import org.jboss.netty.buffer.ChannelBuffer;
27  import org.jboss.netty.channel.Channel;
28  import org.jboss.netty.channel.ChannelDownstreamHandler;
29  import org.jboss.netty.channel.ChannelEvent;
30  import org.jboss.netty.channel.ChannelHandlerContext;
31  import org.jboss.netty.channel.Channels;
32  import org.jboss.netty.channel.MessageEvent;
33  import org.jboss.netty.handler.codec.frame.FrameDecoder;
34  
35  /**
36   * Local Packet Decoder
37   *
38   * @author Frederic Bregier
39   */
40  public class LocalPacketCodec extends FrameDecoder implements
41          ChannelDownstreamHandler {
42  
43      /*
44       * (non-Javadoc)
45       *
46       * @see
47       * org.jboss.netty.handler.codec.frame.FrameDecoder#decode(org.jboss.netty
48       * .channel.ChannelHandlerContext, org.jboss.netty.channel.Channel,
49       * org.jboss.netty.buffer.ChannelBuffer)
50       */
51      @Override
52      protected Object decode(ChannelHandlerContext ctx, Channel channel,
53              ChannelBuffer buf) throws Exception {
54          // Make sure if the length field was received.
55          if (buf.readableBytes() < 4) {
56              // The length field was not received yet - return null.
57              // This method will be invoked again when more packets are
58              // received and appended to the buffer.
59              return null;
60          }
61          return decodeNetworkPacket(buf);
62      }
63  
64      public static AbstractLocalPacket decodeNetworkPacket(ChannelBuffer buf)
65      throws OpenR66ProtocolPacketException {
66          // Mark the current buffer position
67          buf.markReaderIndex();
68          // Read the length field
69          final int length = buf.readInt();
70          if (buf.readableBytes() < length) {
71              buf.resetReaderIndex();
72              return null;
73          }
74          // Now we can read the header
75          // Header: Header length field (4 bytes) = Middle length field (4
76          // bytes), End length field (4 bytes), type field (1 byte), ...
77          final int middleLength = buf.readInt();
78          final int endLength = buf.readInt();
79          // check if the packet is complete
80          if (middleLength + endLength + length - 8 > buf.readableBytes()) {
81              buf.resetReaderIndex();
82              return null;
83          }
84          // createPacketFromChannelBuffer read the buffer
85          return LocalPacketFactory.createPacketFromChannelBuffer(length - 8,
86                  middleLength, endLength, buf);
87      }
88  
89      @Override
90      public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
91              throws Exception {
92          if (e instanceof MessageEvent) {
93              final MessageEvent evt = (MessageEvent) e;
94              if (evt.getMessage() instanceof ChannelBuffer) {
95                  Channels.write(ctx, evt.getFuture(), evt.getMessage());
96                  return;
97              }
98              if (!(evt.getMessage() instanceof AbstractLocalPacket)) {
99                  throw new InvalidArgumentException("Incorrect write object: " +
100                         evt.getMessage().getClass().getName());
101             }
102             final AbstractLocalPacket packet = (AbstractLocalPacket) evt
103                     .getMessage();
104             final ChannelBuffer buf = packet.getLocalPacket();
105             Channels.write(ctx, evt.getFuture(), buf);
106         } else {
107             ctx.sendDownstream(e);
108         }
109     }
110 
111 }