View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.handler.codec.http.websocketx;
17  
18  import io.netty.buffer.ByteBuf;
19  import io.netty.buffer.Unpooled;
20  import io.netty.channel.ChannelHandler.Sharable;
21  import io.netty.channel.ChannelHandlerContext;
22  import io.netty.handler.codec.MessageToMessageEncoder;
23  
24  import java.util.List;
25  
26  /**
27   * Encodes a {@link WebSocketFrame} into a {@link ByteBuf}.
28   * <p>
29   * For the detailed instruction on adding add Web Socket support to your HTTP server, take a look into the
30   * <tt>WebSocketServer</tt> example located in the {@code io.netty.example.http.websocket} package.
31   */
32  @Sharable
33  public class WebSocket00FrameEncoder extends MessageToMessageEncoder<WebSocketFrame> implements WebSocketFrameEncoder {
34      private static final ByteBuf _0X00 = Unpooled.unreleasableBuffer(
35              Unpooled.directBuffer(1, 1).writeByte((byte) 0x00));
36      private static final ByteBuf _0XFF = Unpooled.unreleasableBuffer(
37              Unpooled.directBuffer(1, 1).writeByte((byte) 0xFF));
38      private static final ByteBuf _0XFF_0X00 = Unpooled.unreleasableBuffer(
39              Unpooled.directBuffer(2, 2).writeByte((byte) 0xFF).writeByte((byte) 0x00));
40  
41      @Override
42      protected void encode(ChannelHandlerContext ctx, WebSocketFrame msg, List<Object> out) throws Exception {
43          if (msg instanceof TextWebSocketFrame) {
44              // Text frame
45              ByteBuf data = msg.content();
46  
47              out.add(_0X00.duplicate());
48              out.add(data.retain());
49              out.add(_0XFF.duplicate());
50          } else if (msg instanceof CloseWebSocketFrame) {
51              // Close frame, needs to call duplicate to allow multiple writes.
52              // See https://github.com/netty/netty/issues/2768
53              out.add(_0XFF_0X00.duplicate());
54          } else {
55              // Binary frame
56              ByteBuf data = msg.content();
57              int dataLen = data.readableBytes();
58  
59              ByteBuf buf = ctx.alloc().buffer(5);
60              boolean release = true;
61              try {
62                  // Encode type.
63                  buf.writeByte((byte) 0x80);
64  
65                  // Encode length.
66                  int b1 = dataLen >>> 28 & 0x7F;
67                  int b2 = dataLen >>> 14 & 0x7F;
68                  int b3 = dataLen >>> 7 & 0x7F;
69                  int b4 = dataLen & 0x7F;
70                  if (b1 == 0) {
71                      if (b2 == 0) {
72                          if (b3 == 0) {
73                              buf.writeByte(b4);
74                          } else {
75                              buf.writeByte(b3 | 0x80);
76                              buf.writeByte(b4);
77                          }
78                      } else {
79                          buf.writeByte(b2 | 0x80);
80                          buf.writeByte(b3 | 0x80);
81                          buf.writeByte(b4);
82                      }
83                  } else {
84                      buf.writeByte(b1 | 0x80);
85                      buf.writeByte(b2 | 0x80);
86                      buf.writeByte(b3 | 0x80);
87                      buf.writeByte(b4);
88                  }
89  
90                  // Encode binary data.
91                  out.add(buf);
92                  out.add(data.retain());
93                  release = false;
94              } finally {
95                  if (release) {
96                      buf.release();
97                  }
98              }
99          }
100     }
101 }