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