1 // 2 // ======================================================================== 3 // Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // All rights reserved. This program and the accompanying materials 6 // are made available under the terms of the Eclipse Public License v1.0 7 // and Apache License v2.0 which accompanies this distribution. 8 // 9 // The Eclipse Public License is available at 10 // http://www.eclipse.org/legal/epl-v10.html 11 // 12 // The Apache License v2.0 is available at 13 // http://www.opensource.org/licenses/apache2.0.php 14 // 15 // You may elect to redistribute this code under either of these licenses. 16 // ======================================================================== 17 // 18 19 package org.eclipse.jetty.websocket.servlet; 20 21 import java.io.IOException; 22 23 import javax.servlet.ServletException; 24 import javax.servlet.http.HttpServlet; 25 import javax.servlet.http.HttpServletRequest; 26 import javax.servlet.http.HttpServletResponse; 27 28 import org.eclipse.jetty.websocket.api.WebSocketBehavior; 29 import org.eclipse.jetty.websocket.api.WebSocketPolicy; 30 import org.eclipse.jetty.websocket.api.annotations.WebSocket; 31 32 /** 33 * Abstract Servlet used to bridge the Servlet API to the WebSocket API. 34 * <p> 35 * To use this servlet, you will be required to register your websockets with the {@link WebSocketServletFactory} so that it can create your websockets under the 36 * appropriate conditions. 37 * <p> 38 * The most basic implementation would be as follows. 39 * 40 * <pre> 41 * package my.example; 42 * 43 * import org.eclipse.jetty.websocket.servlet.WebSocketServlet; 44 * import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; 45 * 46 * public class MyEchoServlet extends WebSocketServlet 47 * { 48 * @Override 49 * public void configure(WebSocketServletFactory factory) 50 * { 51 * // set a 10 second idle timeout 52 * factory.getPolicy().setIdleTimeout(10000); 53 * // register my socket 54 * factory.register(MyEchoSocket.class); 55 * } 56 * } 57 * </pre> 58 * 59 * Note: that only request that conforms to a "WebSocket: Upgrade" handshake request will trigger the {@link WebSocketServletFactory} handling of creating 60 * WebSockets.<br> 61 * All other requests are treated as normal servlet requests. 62 * 63 * <p> 64 * <b>Configuration / Init-Parameters:</b><br> 65 * Note: If you use the {@link WebSocket @WebSocket} annotation, these configuration settings can be specified on a per WebSocket basis, vs a per Servlet 66 * basis. 67 * 68 * <dl> 69 * <dt>maxIdleTime</dt> 70 * <dd>set the time in ms that a websocket may be idle before closing<br> 71 * 72 * <dt>maxTextMessageSize</dt> 73 * <dd>set the size in UTF-8 bytes that a websocket may be accept as a Text Message before closing<br> 74 * 75 * <dt>maxBinaryMessageSize</dt> 76 * <dd>set the size in bytes that a websocket may be accept as a Binary Message before closing<br> 77 * 78 * <dt>inputBufferSize</dt> 79 * <dd>set the size in bytes of the buffer used to read raw bytes from the network layer<br> 80 * </dl> 81 */ 82 @SuppressWarnings("serial") 83 public abstract class WebSocketServlet extends HttpServlet 84 { 85 private WebSocketServletFactory factory; 86 87 public abstract void configure(WebSocketServletFactory factory); 88 89 @Override 90 public void destroy() 91 { 92 factory.cleanup(); 93 } 94 95 /** 96 * @see javax.servlet.GenericServlet#init() 97 */ 98 @Override 99 public void init() throws ServletException 100 { 101 try 102 { 103 WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER); 104 105 String max = getInitParameter("maxIdleTime"); 106 if (max != null) 107 { 108 policy.setIdleTimeout(Long.parseLong(max)); 109 } 110 111 max = getInitParameter("maxTextMessageSize"); 112 if (max != null) 113 { 114 policy.setMaxTextMessageSize(Integer.parseInt(max)); 115 } 116 117 max = getInitParameter("maxBinaryMessageSize"); 118 if (max != null) 119 { 120 policy.setMaxBinaryMessageSize(Integer.parseInt(max)); 121 } 122 123 max = getInitParameter("inputBufferSize"); 124 if (max != null) 125 { 126 policy.setInputBufferSize(Integer.parseInt(max)); 127 } 128 129 factory = WebSocketServletFactory.Loader.create(policy); 130 131 configure(factory); 132 133 factory.init(); 134 } 135 catch (Exception x) 136 { 137 throw new ServletException(x); 138 } 139 } 140 141 /** 142 * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 143 */ 144 @Override 145 protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 146 { 147 if (factory.isUpgradeRequest(request,response)) 148 { 149 // We have an upgrade request 150 if (factory.acceptWebSocket(request,response)) 151 { 152 // We have a socket instance created 153 return; 154 } 155 // If we reach this point, it means we had an incoming request to upgrade 156 // but it was either not a proper websocket upgrade, or it was possibly rejected 157 // due to incoming request constraints (controlled by WebSocketCreator) 158 if (response.isCommitted()) 159 { 160 // not much we can do at this point. 161 return; 162 } 163 } 164 165 // All other processing 166 super.service(request,response); 167 } 168 }