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 org.jboss.netty.handler.codec.http.websocketx;
17  
18  import java.io.UnsupportedEncodingException;
19  
20  import org.jboss.netty.buffer.ChannelBuffer;
21  import org.jboss.netty.buffer.ChannelBuffers;
22  import org.jboss.netty.util.CharsetUtil;
23  
24  /**
25   * Web Socket Frame for closing the connection
26   */
27  public class CloseWebSocketFrame extends WebSocketFrame {
28      /**
29       * Creates a new empty close frame.
30       */
31      public CloseWebSocketFrame() {
32          setBinaryData(ChannelBuffers.EMPTY_BUFFER);
33      }
34  
35      /**
36       * Creates a new empty close frame with closing status 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 status 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, null);
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          setFinalFragment(finalFragment);
75          setRsv(rsv);
76  
77          byte[] reasonBytes = new byte[0];
78          if (reasonText != null) {
79              try {
80                  reasonBytes = reasonText.getBytes("UTF-8");
81              } catch (UnsupportedEncodingException e) {
82                  // This should never happen, anyway provide a fallback here
83                  reasonBytes = reasonText.getBytes();
84              }
85          }
86  
87          ChannelBuffer binaryData = ChannelBuffers.buffer(2 + reasonBytes.length);
88          binaryData.writeShort(statusCode);
89          if (reasonBytes.length > 0) {
90              binaryData.writeBytes(reasonBytes);
91          }
92  
93          binaryData.readerIndex(0);
94          setBinaryData(binaryData);
95      }
96  
97      /**
98       * Creates a new close frame
99       *
100      * @param finalFragment
101      *            flag indicating if this frame is the final fragment
102      * @param rsv
103      *            reserved bits used for protocol extensions
104      * @param binaryData
105      *            the content of the frame. Must be 2 byte integer followed by optional UTF-8 encoded string.
106      */
107     public CloseWebSocketFrame(boolean finalFragment, int rsv, ChannelBuffer binaryData) {
108         setFinalFragment(finalFragment);
109         setRsv(rsv);
110         if (binaryData == null) {
111             setBinaryData(ChannelBuffers.EMPTY_BUFFER);
112         } else {
113             setBinaryData(binaryData);
114         }
115     }
116 
117     /**
118      * Returns the closing status code as per <a href="http://tools.ietf.org/html/rfc6455#section-7.4">RFC 6455</a>. If
119      * a status code is set, -1 is returned.
120      */
121     public int getStatusCode() {
122         ChannelBuffer binaryData = getBinaryData();
123         if (binaryData == null || binaryData.capacity() == 0) {
124             return -1;
125         }
126 
127         binaryData.readerIndex(0);
128         int statusCode = binaryData.readShort();
129         binaryData.readerIndex(0);
130 
131         return statusCode;
132     }
133 
134     /**
135      * Returns the reason text as per <a href="http://tools.ietf.org/html/rfc6455#section-7.4">RFC 6455</a> If a reason
136      * text is not supplied, an empty string is returned.
137      */
138     public String getReasonText() {
139         ChannelBuffer binaryData = getBinaryData();
140         if (binaryData == null || binaryData.capacity() <= 2) {
141             return "";
142         }
143 
144         binaryData.readerIndex(2);
145         String reasonText = binaryData.toString(CharsetUtil.UTF_8);
146         binaryData.readerIndex(0);
147 
148         return reasonText;
149     }
150 
151     @Override
152     public String toString() {
153         return getClass().getSimpleName();
154     }
155 }