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.util.CharsetUtil;
21  import io.netty.util.internal.EmptyArrays;
22  
23  /**
24   * Web Socket Frame for closing the connection
25   */
26  public class CloseWebSocketFrame extends WebSocketFrame {
27  
28      /**
29       * Creates a new empty close frame.
30       */
31      public CloseWebSocketFrame() {
32          super(Unpooled.buffer(0));
33      }
34  
35      /**
36       * Creates a new empty close frame with closing getStatus code and reason text
37       *
38       * @param statusCode
39       *            Integer status code as per <a href="http://tools.ietf.org/html/rfc6455#section-7.4">RFC 6455</a>. For
40       *            example, <tt>1000</tt> indicates normal closure.
41       * @param reasonText
42       *            Reason text. Set to null if no text.
43       */
44      public CloseWebSocketFrame(int statusCode, String reasonText) {
45          this(true, 0, statusCode, reasonText);
46      }
47  
48      /**
49       * Creates a new close frame with no losing getStatus code and no reason text
50       *
51       * @param finalFragment
52       *            flag indicating if this frame is the final fragment
53       * @param rsv
54       *            reserved bits used for protocol extensions
55       */
56      public CloseWebSocketFrame(boolean finalFragment, int rsv) {
57          this(finalFragment, rsv, Unpooled.buffer(0));
58      }
59  
60      /**
61       * Creates a new close frame with closing status code and reason text
62       *
63       * @param finalFragment
64       *            flag indicating if this frame is the final fragment
65       * @param rsv
66       *            reserved bits used for protocol extensions
67       * @param statusCode
68       *            Integer status code as per <a href="http://tools.ietf.org/html/rfc6455#section-7.4">RFC 6455</a>. For
69       *            example, <tt>1000</tt> indicates normal closure.
70       * @param reasonText
71       *            Reason text. Set to null if no text.
72       */
73      public CloseWebSocketFrame(boolean finalFragment, int rsv, int statusCode, String reasonText) {
74          super(finalFragment, rsv, newBinaryData(statusCode, reasonText));
75      }
76  
77      private static ByteBuf newBinaryData(int statusCode, String reasonText) {
78          byte[] reasonBytes = EmptyArrays.EMPTY_BYTES;
79          if (reasonText != null) {
80              reasonBytes = reasonText.getBytes(CharsetUtil.UTF_8);
81          }
82  
83          ByteBuf binaryData = Unpooled.buffer(2 + reasonBytes.length);
84          binaryData.writeShort(statusCode);
85          if (reasonBytes.length > 0) {
86              binaryData.writeBytes(reasonBytes);
87          }
88  
89          binaryData.readerIndex(0);
90          return binaryData;
91      }
92  
93      /**
94       * Creates a new close frame
95       *
96       * @param finalFragment
97       *            flag indicating if this frame is the final fragment
98       * @param rsv
99       *            reserved bits used for protocol extensions
100      * @param binaryData
101      *            the content of the frame. Must be 2 byte integer followed by optional UTF-8 encoded string.
102      */
103     public CloseWebSocketFrame(boolean finalFragment, int rsv, ByteBuf binaryData) {
104         super(finalFragment, rsv, binaryData);
105     }
106 
107     /**
108      * Returns the closing status code as per <a href="http://tools.ietf.org/html/rfc6455#section-7.4">RFC 6455</a>. If
109      * a getStatus code is set, -1 is returned.
110      */
111     public int statusCode() {
112         ByteBuf binaryData = content();
113         if (binaryData == null || binaryData.capacity() == 0) {
114             return -1;
115         }
116 
117         binaryData.readerIndex(0);
118         int statusCode = binaryData.readShort();
119         binaryData.readerIndex(0);
120 
121         return statusCode;
122     }
123 
124     /**
125      * Returns the reason text as per <a href="http://tools.ietf.org/html/rfc6455#section-7.4">RFC 6455</a> If a reason
126      * text is not supplied, an empty string is returned.
127      */
128     public String reasonText() {
129         ByteBuf binaryData = content();
130         if (binaryData == null || binaryData.capacity() <= 2) {
131             return "";
132         }
133 
134         binaryData.readerIndex(2);
135         String reasonText = binaryData.toString(CharsetUtil.UTF_8);
136         binaryData.readerIndex(0);
137 
138         return reasonText;
139     }
140 
141     @Override
142     public CloseWebSocketFrame copy() {
143         return new CloseWebSocketFrame(isFinalFragment(), rsv(), content().copy());
144     }
145 
146     @Override
147     public CloseWebSocketFrame duplicate() {
148         return new CloseWebSocketFrame(isFinalFragment(), rsv(), content().duplicate());
149     }
150 
151     @Override
152     public CloseWebSocketFrame retain() {
153         super.retain();
154         return this;
155     }
156 
157     @Override
158     public CloseWebSocketFrame retain(int increment) {
159         super.retain(increment);
160         return this;
161     }
162 
163     @Override
164     public CloseWebSocketFrame touch() {
165         super.touch();
166         return this;
167     }
168 
169     @Override
170     public CloseWebSocketFrame touch(Object hint) {
171         super.touch(hint);
172         return this;
173     }
174 }