package org.red5.server.net.servlet; /* * RED5 Open Source Flash Server - http://www.osflash.org/red5 * * Copyright (c) 2006-2009 by respective authors (see below). All rights reserved. * * This library is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or (at your option) any later * version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.methods.InputStreamRequestEntity; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.mina.common.ByteBuffer; import org.red5.logging.Red5LoggerFactory; import org.slf4j.Logger; /** * Servlet to tunnel to the AMF gateway servlet. * * @author The Red5 Project (red5@osflash.org) * @author Paul Gregoire (mondain@gmail.com) */ public class AMFTunnelServlet extends HttpServlet { /** * Serialization UID */ private static final long serialVersionUID = -35436145164322090L; protected Logger logger = Red5LoggerFactory.getLogger(AMFTunnelServlet.class); private static final String REQUEST_TYPE = "application/x-amf"; private static String postAcceptorURL = "http://localhost:8080/gateway"; private static int connectionTimeout = 30000; @Override public void init(ServletConfig config) throws ServletException { super.init(config); //get the url for posting if (config.getInitParameter("tunnel.acceptor.url") != null) { postAcceptorURL = config.getInitParameter("tunnel.acceptor.url"); } logger.debug("POST acceptor URL: {}", postAcceptorURL); //get the connection timeout if (config.getInitParameter("tunnel.timeout") != null) { connectionTimeout = Integer.valueOf(config.getInitParameter("tunnel.timeout")); } logger.debug("POST connection timeout: {}", postAcceptorURL); } /** * Redirect to HTTP port. */ @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpClient client = new HttpClient( new MultiThreadedHttpConnectionManager()); client.getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout); PostMethod get = new PostMethod(postAcceptorURL); try { // copy all the headers // Enumeration headerNames = req.getHeaderNames(); // while (headerNames.hasMoreElements()) { // String headerName = (String) headerNames.nextElement(); // logger.debug("Adding received header to tunnel request: " // + headerName); // get.addRequestHeader(headerName, req.getHeader(headerName)); // } // Enumeration parameterNames = req.getParameterNames(); // while (parameterNames.hasMoreElements()) { // String parameterName = (String) parameterNames.nextElement(); // logger.debug("Adding received parameter to tunnel request: " // + parameterName); // get.getParams().setParameter(parameterName, // req.getParameter(parameterName)); // } // Enumeration attributeNames = req.getAttributeNames(); // while (attributeNames.hasMoreElements()) { // String attributeName = (String) attributeNames.nextElement(); // logger.debug("Adding received attribute to tunnel request: " // + attributeName); // } String path = req.getContextPath(); if (path == null) { path = ""; } logger.debug("Path: {}", path); if (req.getPathInfo() != null) { path += req.getPathInfo(); } logger.debug("Path 2: {}", path); int reqContentLength = req.getContentLength(); if (reqContentLength > 0) { logger.debug("Request content length: {}", reqContentLength); ByteBuffer reqBuffer = ByteBuffer.allocate(reqContentLength); ServletUtils.copy(req.getInputStream(), reqBuffer .asOutputStream()); reqBuffer.flip(); get .setRequestEntity(new InputStreamRequestEntity( reqBuffer.asInputStream(), reqContentLength, REQUEST_TYPE)); // get.setPath(path); get.addRequestHeader("Tunnel-request", path); client.executeMethod(get); logger.debug("Response code: {}", get.getStatusCode()); if (get.getStatusCode() == HttpStatus.SC_OK) { resp.setContentType(REQUEST_TYPE); int responseLength = ((Long) get.getResponseContentLength()) .intValue(); ByteBuffer respBuffer = ByteBuffer.allocate(responseLength); ServletUtils.copy(get.getResponseBodyAsStream(), respBuffer .asOutputStream()); respBuffer.flip(); ServletUtils.copy(respBuffer.asInputStream(), resp .getOutputStream()); resp.flushBuffer(); } else { resp.sendError(get.getStatusCode()); } } else { resp.sendError(HttpStatus.SC_BAD_REQUEST); } } catch (Exception ex) { logger.error("", ex); } finally { get.releaseConnection(); } } }