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.server;
20  
21  import java.nio.ByteBuffer;
22  
23  import org.eclipse.jetty.fcgi.generator.Flusher;
24  import org.eclipse.jetty.fcgi.generator.Generator;
25  import org.eclipse.jetty.fcgi.generator.ServerGenerator;
26  import org.eclipse.jetty.http.HttpHeader;
27  import org.eclipse.jetty.http.HttpHeaderValue;
28  import org.eclipse.jetty.http.MetaData;
29  import org.eclipse.jetty.io.ByteBufferPool;
30  import org.eclipse.jetty.server.HttpTransport;
31  import org.eclipse.jetty.util.BufferUtil;
32  import org.eclipse.jetty.util.Callback;
33  
34  public class HttpTransportOverFCGI implements HttpTransport
35  {
36      private final ServerGenerator generator;
37      private final Flusher flusher;
38      private final int request;
39      private volatile boolean head;
40      private volatile boolean shutdown;
41      private volatile boolean aborted;
42  
43      public HttpTransportOverFCGI(ByteBufferPool byteBufferPool, Flusher flusher, int request, boolean sendStatus200)
44      {
45          this.generator = new ServerGenerator(byteBufferPool, sendStatus200);
46          this.flusher = flusher;
47          this.request = request;
48      }
49  
50      @Override
51      public boolean isOptimizedForDirectBuffers()
52      {
53          return false;
54      }
55      
56      @Override
57      public void send(MetaData.Response info, boolean head, ByteBuffer content, boolean lastContent, Callback callback)
58      {
59          if (info!=null)
60              commit(info,head,content,lastContent,callback);
61          else
62          {
63              if (head)
64              {
65                  if (lastContent)
66                  {
67                      Generator.Result result = generateResponseContent(BufferUtil.EMPTY_BUFFER, true, callback);
68                      flusher.flush(result);
69                  }
70                  else
71                  {
72                      // Skip content generation
73                      callback.succeeded();
74                  }
75              }
76              else
77              {
78                  Generator.Result result = generateResponseContent(content, lastContent, callback);
79                  flusher.flush(result);
80              }
81  
82              if (lastContent && shutdown)
83                  flusher.shutdown();
84          }
85      }
86  
87      @Override
88      public boolean isPushSupported()
89      {
90          return false;
91      }
92      
93      @Override
94      public void push(org.eclipse.jetty.http.MetaData.Request request)
95      {   
96          // LOG.debug("ignore push in {}",this);
97      }
98      
99      private void commit(MetaData.Response info, boolean head, ByteBuffer content, boolean lastContent, Callback callback)
100     {
101         this.head = head;
102         boolean shutdown = this.shutdown = info.getFields().contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString());
103 
104         if (head)
105         {
106             if (lastContent)
107             {
108                 Generator.Result headersResult = generateResponseHeaders(info, Callback.NOOP);
109                 Generator.Result contentResult = generateResponseContent(BufferUtil.EMPTY_BUFFER, true, callback);
110                 flusher.flush(headersResult, contentResult);
111             }
112             else
113             {
114                 Generator.Result headersResult = generateResponseHeaders(info, callback);
115                 flusher.flush(headersResult);
116             }
117         }
118         else
119         {
120             Generator.Result headersResult = generateResponseHeaders(info, Callback.NOOP);
121             Generator.Result contentResult = generateResponseContent(content, lastContent, callback);
122             flusher.flush(headersResult, contentResult);
123         }
124 
125         if (lastContent && shutdown)
126             flusher.shutdown();
127     }
128 
129     protected Generator.Result generateResponseHeaders(MetaData.Response info, Callback callback)
130     {
131         return generator.generateResponseHeaders(request, info.getStatus(), info.getReason(), info.getFields(), callback);
132     }
133 
134     protected Generator.Result generateResponseContent(ByteBuffer buffer, boolean lastContent, Callback callback)
135     {
136         return generator.generateResponseContent(request, buffer, lastContent, aborted, callback);
137     }
138 
139     @Override
140     public void abort(Throwable failure)
141     {
142         aborted = true;
143     }
144 
145     @Override
146     public void onCompleted()
147     {
148     }
149 }