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.StringUtil;
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          if (reasonText == null) {
79              reasonText = StringUtil.EMPTY_STRING;
80          }
81  
82          ByteBuf binaryData = Unpooled.buffer(2 + reasonText.length());
83          binaryData.writeShort(statusCode);
84          if (!reasonText.isEmpty()) {
85              binaryData.writeCharSequence(reasonText, CharsetUtil.UTF_8);
86          }
87  
88          binaryData.readerIndex(0);
89          return binaryData;
90      }
91  
92      /**
93       * Creates a new close frame
94       *
95       * @param finalFragment
96       *            flag indicating if this frame is the final fragment
97       * @param rsv
98       *            reserved bits used for protocol extensions
99       * @param binaryData
100      *            the content of the frame. Must be 2 byte integer followed by optional UTF-8 encoded string.
101      */
102     public CloseWebSocketFrame(boolean finalFragment, int rsv, ByteBuf binaryData) {
103         super(finalFragment, rsv, binaryData);
104     }
105 
106     /**
107      * Returns the closing status code as per <a href="http://tools.ietf.org/html/rfc6455#section-7.4">RFC 6455</a>. If
108      * a getStatus code is set, -1 is returned.
109      */
110     public int statusCode() {
111         ByteBuf binaryData = content();
112         if (binaryData == null || binaryData.capacity() == 0) {
113             return -1;
114         }
115 
116         binaryData.readerIndex(0);
117         int statusCode = binaryData.readShort();
118         binaryData.readerIndex(0);
119 
120         return statusCode;
121     }
122 
123     /**
124      * Returns the reason text as per <a href="http://tools.ietf.org/html/rfc6455#section-7.4">RFC 6455</a> If a reason
125      * text is not supplied, an empty string is returned.
126      */
127     public String reasonText() {
128         ByteBuf binaryData = content();
129         if (binaryData == null || binaryData.capacity() <= 2) {
130             return "";
131         }
132 
133         binaryData.readerIndex(2);
134         String reasonText = binaryData.toString(CharsetUtil.UTF_8);
135         binaryData.readerIndex(0);
136 
137         return reasonText;
138     }
139 
140     @Override
141     public CloseWebSocketFrame copy() {
142         return (CloseWebSocketFrame) super.copy();
143     }
144 
145     @Override
146     public CloseWebSocketFrame duplicate() {
147         return (CloseWebSocketFrame) super.duplicate();
148     }
149 
150     @Override
151     public CloseWebSocketFrame retainedDuplicate() {
152         return (CloseWebSocketFrame) super.retainedDuplicate();
153     }
154 
155     @Override
156     public CloseWebSocketFrame replace(ByteBuf content) {
157         return new CloseWebSocketFrame(isFinalFragment(), rsv(), content);
158     }
159 
160     @Override
161     public CloseWebSocketFrame retain() {
162         super.retain();
163         return this;
164     }
165 
166     @Override
167     public CloseWebSocketFrame retain(int increment) {
168         super.retain(increment);
169         return this;
170     }
171 
172     @Override
173     public CloseWebSocketFrame touch() {
174         super.touch();
175         return this;
176     }
177 
178     @Override
179     public CloseWebSocketFrame touch(Object hint) {
180         super.touch(hint);
181         return this;
182     }
183 }