Package org.jboss.netty.channel.socket.http

Source Code of org.jboss.netty.channel.socket.http.HttpTunnelingServlet

/*
* JBoss, Home of Professional Open Source
* Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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 software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.netty.channel.socket.http;

import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.MessageEvent;

/**
* A Servlet that acts as a proxy for a netty channel
*
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Andy Taylor (andy.taylor@jboss.org)
* @version $Rev: 1021 $, $Date: 2009-03-12 16:27:19 +0900 (Thu, 12 Mar 2009) $
*/
public class HttpTunnelingServlet extends HttpServlet {

    private static final long serialVersionUID = -872309493835745385L;

    final static String CHANNEL_PROP = "channel";
    final static String HANDLER_PROP = "handler";

    protected void doRequest(
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        Channel channel = (Channel) session.getAttribute(CHANNEL_PROP);
        HttpTunnelingChannelHandler handler =
                (HttpTunnelingChannelHandler) session.getAttribute(HANDLER_PROP);
        if (handler.isStreaming()) {
            streamResponse(request, response, session, handler, channel);
        } else {
            pollResponse(channel, request, response, session, handler);
        }
    }

    private void streamResponse(
            final HttpServletRequest request,
            final HttpServletResponse response, HttpSession session,
            HttpTunnelingChannelHandler handler, Channel channel) throws IOException {

        try {
            response.setHeader("JSESSIONID", session.getId());
            response.setHeader("Content-Type", "application/octet-stream");
            response.setContentLength(-1);
            response.setStatus(HttpServletResponse.SC_OK);
            response.getOutputStream().flush();
            handler.setOutputStream(response.getOutputStream());

            PushbackInputStream in =
                    new PushbackInputStream(request.getInputStream());
            for (;;) {
                try {
                    ChannelBuffer buffer = read(in);
                    if (buffer == null) {
                        break;
                    }
                    channel.write(buffer);
                } catch (IOException e) {
                    // this is ok, the client can reconnect.
                    break;
                }
            }
        } finally {
            // Mark the channel as closed if the client didn't reconnect in time.
            if (!handler.awaitReconnect()) {
                channel.close();
            }
        }
    }

    private ChannelBuffer read(PushbackInputStream in) throws IOException {
        byte[] buf;
        int readBytes;

        for (;;) {
            int bytesToRead = in.available();
            if (bytesToRead > 0) {
                buf = new byte[bytesToRead];
                readBytes = in.read(buf);
                break;
            } else if (bytesToRead == 0) {
                int b = in.read();
                if (b < 0 || in.available() < 0) {
                    return null;
                }
                if (b == 13) {
                    in.read();
                } else {
                    in.unread(b);
                }

            } else {
                return null;
            }
        }

        ChannelBuffer buffer;
        if (readBytes == buf.length) {
            buffer = ChannelBuffers.wrappedBuffer(buf);
        } else {
            // A rare case, but it sometimes happen.
            buffer = ChannelBuffers.wrappedBuffer(buf, 0, readBytes);
        }
        return buffer;
    }

    private void pollResponse(
            Channel channel,
            HttpServletRequest request,
            HttpServletResponse response, HttpSession session,
            HttpTunnelingChannelHandler handler) throws IOException {

        InputStream in = request.getInputStream();
        if (in != null) {
            ChannelBuffer requestContent = ChannelBuffers.dynamicBuffer();
            for (;;) {
                int writtenBytes = requestContent.writeBytes(in, 4096);
                if (writtenBytes < 0) {
                    break;
                }
            }
            if (requestContent.readable()) {
                channel.write(requestContent);
            }
        }

        handler.setOutputStream(response.getOutputStream());
        List<MessageEvent> buffers = handler.getAwaitingEvents();
        int length = 0;
        if (buffers.size() > 0) {
            for (MessageEvent buffer: buffers) {
                length += ((ChannelBuffer) buffer.getMessage()).readableBytes();
            }
        }
        response.setHeader("JSESSIONID", session.getId());
        response.setContentLength(length);
        response.setStatus(HttpServletResponse.SC_OK);
        for (MessageEvent event: buffers) {
            ChannelBuffer buffer = (ChannelBuffer) event.getMessage();
            byte[] b = new byte[buffer.readableBytes()];
            buffer.readBytes(b);
            try {
                response.getOutputStream().write(b);
                event.getFuture().setSuccess();
            } catch (IOException e) {
                event.getFuture().setFailure(e);
            }
        }
    }

    @Override
    protected void doGet(
            HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse) throws ServletException, IOException {
        doRequest(httpServletRequest, httpServletResponse);
    }

    @Override
    protected void doPost(
            HttpServletRequest httpServletRequest,
            HttpServletResponse httpServletResponse) throws ServletException, IOException {
        doRequest(httpServletRequest, httpServletResponse);
    }
}
TOP

Related Classes of org.jboss.netty.channel.socket.http.HttpTunnelingServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.