View Javadoc

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.fcgi.client.http;
20  
21  import java.nio.ByteBuffer;
22  import java.util.concurrent.TimeoutException;
23  
24  import org.eclipse.jetty.client.HttpChannel;
25  import org.eclipse.jetty.client.HttpExchange;
26  import org.eclipse.jetty.client.HttpReceiver;
27  import org.eclipse.jetty.client.HttpSender;
28  import org.eclipse.jetty.client.api.Result;
29  import org.eclipse.jetty.fcgi.generator.Flusher;
30  import org.eclipse.jetty.fcgi.generator.Generator;
31  import org.eclipse.jetty.http.HttpField;
32  import org.eclipse.jetty.http.HttpFields;
33  import org.eclipse.jetty.http.HttpVersion;
34  import org.eclipse.jetty.io.IdleTimeout;
35  import org.eclipse.jetty.util.Callback;
36  
37  public class HttpChannelOverFCGI extends HttpChannel
38  {
39      private final HttpConnectionOverFCGI connection;
40      private final Flusher flusher;
41      private final int request;
42      private final HttpSenderOverFCGI sender;
43      private final HttpReceiverOverFCGI receiver;
44      private final FCGIIdleTimeout idle;
45      private HttpVersion version;
46  
47      public HttpChannelOverFCGI(final HttpConnectionOverFCGI connection, Flusher flusher, int request, long idleTimeout)
48      {
49          super(connection.getHttpDestination());
50          this.connection = connection;
51          this.flusher = flusher;
52          this.request = request;
53          this.sender = new HttpSenderOverFCGI(this);
54          this.receiver = new HttpReceiverOverFCGI(this);
55          this.idle = new FCGIIdleTimeout(connection, idleTimeout);
56      }
57  
58      protected int getRequest()
59      {
60          return request;
61      }
62  
63      @Override
64      protected HttpSender getHttpSender()
65      {
66          return sender;
67      }
68  
69      @Override
70      protected HttpReceiver getHttpReceiver()
71      {
72          return receiver;
73      }
74  
75      @Override
76      public void send()
77      {
78          HttpExchange exchange = getHttpExchange();
79          if (exchange != null)
80          {
81              version = exchange.getRequest().getVersion();
82              idle.onOpen();
83              sender.send(exchange);
84          }
85      }
86  
87      @Override
88      public void release()
89      {
90          connection.release(this);
91      }
92  
93      protected boolean responseBegin(int code, String reason)
94      {
95          idle.notIdle();
96          HttpExchange exchange = getHttpExchange();
97          if (exchange == null)
98              return false;
99          exchange.getResponse().version(version).status(code).reason(reason);
100         return receiver.responseBegin(exchange);
101     }
102 
103     protected boolean responseHeader(HttpField field)
104     {
105         HttpExchange exchange = getHttpExchange();
106         return exchange != null && receiver.responseHeader(exchange, field);
107     }
108 
109     protected boolean responseHeaders()
110     {
111        idle.notIdle();
112         HttpExchange exchange = getHttpExchange();
113         return exchange != null && receiver.responseHeaders(exchange);
114     }
115 
116     protected boolean content(ByteBuffer buffer, Callback callback)
117     {
118         idle.notIdle();
119         HttpExchange exchange = getHttpExchange();
120         if (exchange != null)
121             return receiver.responseContent(exchange, buffer, callback);
122         callback.succeeded();
123         return false;
124     }
125 
126     protected boolean responseSuccess()
127     {
128         HttpExchange exchange = getHttpExchange();
129         return exchange != null && receiver.responseSuccess(exchange);
130     }
131 
132     protected boolean responseFailure(Throwable failure)
133     {
134         HttpExchange exchange = getHttpExchange();
135         return exchange != null && receiver.responseFailure(failure);
136     }
137 
138     @Override
139     public void exchangeTerminated(HttpExchange exchange, Result result)
140     {
141         super.exchangeTerminated(exchange, result);
142         idle.onClose();
143         HttpFields responseHeaders = result.getResponse().getHeaders();
144         if (result.isFailed())
145             connection.close(result.getFailure());
146         else if (!connection.closeByHTTP(responseHeaders))
147             release();
148     }
149 
150     protected void flush(Generator.Result... results)
151     {
152         flusher.flush(results);
153     }
154 
155     private class FCGIIdleTimeout extends IdleTimeout
156     {
157         private final HttpConnectionOverFCGI connection;
158         private boolean open;
159 
160         public FCGIIdleTimeout(HttpConnectionOverFCGI connection, long idleTimeout)
161         {
162             super(connection.getHttpDestination().getHttpClient().getScheduler());
163             this.connection = connection;
164             setIdleTimeout(idleTimeout);
165         }
166 
167         @Override
168         public void onOpen()
169         {
170             open = true;
171             notIdle();
172             super.onOpen();
173         }
174 
175         @Override
176         public void onClose()
177         {
178             super.onClose();
179             open = false;
180         }
181 
182         @Override
183         protected void onIdleExpired(TimeoutException timeout)
184         {
185             if (LOG.isDebugEnabled())
186                 LOG.debug("Idle timeout for request {}", request);
187             connection.abort(timeout);
188         }
189 
190         @Override
191         public boolean isOpen()
192         {
193             return open;
194         }
195     }
196 }