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
19package org.eclipse.jetty.server;
20
21import java.io.IOException;
22
23import org.eclipse.jetty.http.Generator;
24import org.eclipse.jetty.http.HttpException;
25import org.eclipse.jetty.http.HttpStatus;
26import org.eclipse.jetty.http.Parser;
27import org.eclipse.jetty.io.Connection;
28import org.eclipse.jetty.io.EndPoint;
29import org.eclipse.jetty.util.log.Log;
30import org.eclipse.jetty.util.log.Logger;
31
32
33/* ------------------------------------------------------------ */
34/** Blocking Server HTTP Connection
35 */
36public class BlockingHttpConnection extends AbstractHttpConnection
37{
38    private static final Logger LOG = Log.getLogger(BlockingHttpConnection.class);
39
40    public BlockingHttpConnection(Connector connector, EndPoint endpoint, Server server)
41    {
42        super(connector,endpoint,server);
43    }
44
45    public BlockingHttpConnection(Connector connector, EndPoint endpoint, Server server, Parser parser, Generator generator, Request request)
46    {
47        super(connector,endpoint,server,parser,generator,request);
48    }
49
50    @Override
51    protected void handleRequest() throws IOException
52    {
53        super.handleRequest();
54    }
55
56    public Connection handle() throws IOException
57    {
58        Connection connection = this;
59
60        try
61        {
62            setCurrentConnection(this);
63
64            // do while the endpoint is open
65            // AND the connection has not changed
66            while (_endp.isOpen() && connection==this)
67            {
68                try
69                {
70                    // If we are not ended then parse available
71                    if (!_parser.isComplete() && !_endp.isInputShutdown())
72                        _parser.parseAvailable();
73
74                    // Do we have more generating to do?
75                    // Loop here because some writes may take multiple steps and
76                    // we need to flush them all before potentially blocking in the
77                    // next loop.
78                    if (_generator.isCommitted() && !_generator.isComplete() && !_endp.isOutputShutdown())
79                        _generator.flushBuffer();
80
81                    // Flush buffers
82                    _endp.flush();
83                }
84                catch (HttpException e)
85                {
86                    if (LOG.isDebugEnabled())
87                    {
88                        LOG.debug("uri="+_uri);
89                        LOG.debug("fields="+_requestFields);
90                        LOG.debug(e);
91                    }
92                    _generator.sendError(e.getStatus(), e.getReason(), null, true);
93                    _parser.reset();
94                    _endp.shutdownOutput();
95                }
96                finally
97                {
98                    //  Is this request/response round complete and are fully flushed?
99                    if (_parser.isComplete() && _generator.isComplete())
100                    {
101                        // Reset the parser/generator
102                        reset();
103
104                        // look for a switched connection instance?
105                        if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
106                        {
107                            Connection switched=(Connection)_request.getAttribute("org.eclipse.jetty.io.Connection");
108                            if (switched!=null)
109                                connection=switched;
110                        }
111
112                        // TODO Is this required?
113                        if (!_generator.isPersistent() && !_endp.isOutputShutdown())
114                        {
115                            LOG.warn("Safety net oshut!!! Please open a bugzilla");
116                            _endp.shutdownOutput();
117                        }
118                    }
119
120                    // If we don't have a committed response and we are not suspended
121                    if (_endp.isInputShutdown() && _generator.isIdle() && !_request.getAsyncContinuation().isSuspended())
122                    {
123                        // then no more can happen, so close.
124                        _endp.close();
125                    }
126                }
127            }
128
129            return connection;
130        }
131        finally
132        {
133            setCurrentConnection(null);
134            _parser.returnBuffers();
135            _generator.returnBuffers();
136        }
137    }
138}
139