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