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 org.jboss.netty.channel.Channel;
19  import org.jboss.netty.channel.ChannelFuture;
20  import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
21  import org.jboss.netty.handler.codec.http.HttpHeaders.Names;
22  import org.jboss.netty.handler.codec.http.HttpRequest;
23  import org.jboss.netty.handler.codec.http.HttpResponse;
24  import org.jboss.netty.handler.codec.http.HttpResponseStatus;
25  import org.jboss.netty.handler.codec.http.HttpVersion;
26  
27  /**
28   * Instances the appropriate handshake class to use for servers
29   */
30  public class WebSocketServerHandshakerFactory {
31  
32      private final String webSocketURL;
33  
34      private final String subprotocols;
35  
36      private final boolean allowExtensions;
37  
38      private final long maxFramePayloadLength;
39  
40      /**
41       * Constructor
42  
43       * @param subprotocols
44       *            CSV of supported protocols. Null if sub protocols not supported.
45       * @param allowExtensions
46       *            Allow extensions to be used in the reserved bits of the web socket frame
47       */
48      public WebSocketServerHandshakerFactory(String webSocketURL, String subprotocols, boolean allowExtensions) {
49          this(webSocketURL, subprotocols, allowExtensions, Long.MAX_VALUE);
50      }
51  
52      /**
53       * Constructor
54       *
55       * @param webSocketURL
56       *            URL for web socket communications. e.g "ws://myhost.com/mypath".
57       *            Subsequent web socket frames will be sent to this URL.
58       * @param subprotocols
59       *            CSV of supported protocols. Null if sub protocols not supported.
60       * @param allowExtensions
61       *            Allow extensions to be used in the reserved bits of the web socket frame
62       * @param maxFramePayloadLength
63       *            Maximum allowable frame payload length. Setting this value to your application's
64       *            requirement may reduce denial of service attacks using long data frames.
65       */
66      public WebSocketServerHandshakerFactory(String webSocketURL, String subprotocols, boolean allowExtensions,
67              long maxFramePayloadLength) {
68          this.webSocketURL = webSocketURL;
69          this.subprotocols = subprotocols;
70          this.allowExtensions = allowExtensions;
71          this.maxFramePayloadLength = maxFramePayloadLength;
72      }
73  
74      /**
75       * Instances a new handshaker
76       *
77       * @return A new WebSocketServerHandshaker for the requested web socket version. Null if web
78       *         socket version is not supported.
79       */
80      public WebSocketServerHandshaker newHandshaker(HttpRequest req) {
81  
82          String version = req.headers().get(Names.SEC_WEBSOCKET_VERSION);
83  
84          if (version != null) {
85              if (version.equals(WebSocketVersion.V13.toHttpHeaderValue())) {
86                  // Version 13 of the wire protocol - RFC 6455 (version 17 of the draft hybi specification).
87                  return new WebSocketServerHandshaker13(
88                          webSocketURL, subprotocols, allowExtensions, maxFramePayloadLength);
89              } else if (version.equals(WebSocketVersion.V08.toHttpHeaderValue())) {
90                  // Version 8 of the wire protocol - version 10 of the draft hybi specification.
91                  return new WebSocketServerHandshaker08(
92                          webSocketURL, subprotocols, allowExtensions, maxFramePayloadLength);
93              } else if (version.equals(WebSocketVersion.V07.toHttpHeaderValue())) {
94                  // Version 8 of the wire protocol - version 07 of the draft hybi specification.
95                  return new WebSocketServerHandshaker07(
96                          webSocketURL, subprotocols, allowExtensions, maxFramePayloadLength);
97              } else {
98                  return null;
99              }
100         } else {
101             // Assume version 00 where version header was not specified
102             return new WebSocketServerHandshaker00(
103                     webSocketURL, subprotocols, maxFramePayloadLength);
104         }
105     }
106 
107     /**
108      * Return that we need cannot not support the web socket version
109      *
110      * @param channel
111      *            Channel
112      */
113     public ChannelFuture sendUnsupportedWebSocketVersionResponse(Channel channel) {
114         HttpResponse res = new DefaultHttpResponse(
115                 HttpVersion.HTTP_1_1,
116                 HttpResponseStatus.SWITCHING_PROTOCOLS);
117         res.setStatus(HttpResponseStatus.UPGRADE_REQUIRED);
118         res.headers().set(Names.SEC_WEBSOCKET_VERSION, WebSocketVersion.V13.toHttpHeaderValue());
119         return channel.write(res);
120     }
121 
122 }