Home | History | Annotate | Download | only in http
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.squareup.okhttp.internal.http;
     18 
     19 import com.squareup.okhttp.internal.spdy.SpdyConnection;
     20 import com.squareup.okhttp.internal.spdy.SpdyStream;
     21 import java.io.IOException;
     22 import java.io.InputStream;
     23 import java.io.OutputStream;
     24 import java.net.CacheRequest;
     25 import java.net.URL;
     26 import java.util.List;
     27 
     28 public final class SpdyTransport implements Transport {
     29   private final HttpEngine httpEngine;
     30   private final SpdyConnection spdyConnection;
     31   private SpdyStream stream;
     32 
     33   public SpdyTransport(HttpEngine httpEngine, SpdyConnection spdyConnection) {
     34     this.httpEngine = httpEngine;
     35     this.spdyConnection = spdyConnection;
     36   }
     37 
     38   @Override public OutputStream createRequestBody() throws IOException {
     39     // TODO: if we aren't streaming up to the server, we should buffer the whole request
     40     writeRequestHeaders();
     41     return stream.getOutputStream();
     42   }
     43 
     44   @Override public void writeRequestHeaders() throws IOException {
     45     if (stream != null) {
     46       return;
     47     }
     48     httpEngine.writingRequestHeaders();
     49     RawHeaders requestHeaders = httpEngine.requestHeaders.getHeaders();
     50     String version = httpEngine.connection.getHttpMinorVersion() == 1 ? "HTTP/1.1" : "HTTP/1.0";
     51     URL url = httpEngine.policy.getURL();
     52     requestHeaders.addSpdyRequestHeaders(httpEngine.method, HttpEngine.requestPath(url), version,
     53         HttpEngine.getOriginAddress(url), httpEngine.uri.getScheme());
     54     boolean hasRequestBody = httpEngine.hasRequestBody();
     55     boolean hasResponseBody = true;
     56     stream = spdyConnection.newStream(requestHeaders.toNameValueBlock(), hasRequestBody,
     57         hasResponseBody);
     58     stream.setReadTimeout(httpEngine.policy.getReadTimeout());
     59   }
     60 
     61   @Override public void writeRequestBody(RetryableOutputStream requestBody) throws IOException {
     62     throw new UnsupportedOperationException();
     63   }
     64 
     65   @Override public void flushRequest() throws IOException {
     66     stream.getOutputStream().close();
     67   }
     68 
     69   @Override public ResponseHeaders readResponseHeaders() throws IOException {
     70     List<String> nameValueBlock = stream.getResponseHeaders();
     71     RawHeaders rawHeaders = RawHeaders.fromNameValueBlock(nameValueBlock);
     72     rawHeaders.computeResponseStatusLineFromSpdyHeaders();
     73     httpEngine.receiveHeaders(rawHeaders);
     74     return new ResponseHeaders(httpEngine.uri, rawHeaders);
     75   }
     76 
     77   @Override public InputStream getTransferStream(CacheRequest cacheRequest) throws IOException {
     78     return new UnknownLengthHttpInputStream(stream.getInputStream(), cacheRequest, httpEngine);
     79   }
     80 
     81   @Override public boolean makeReusable(boolean streamCancelled, OutputStream requestBodyOut,
     82       InputStream responseBodyIn) {
     83     if (streamCancelled) {
     84       if (stream != null) {
     85         stream.closeLater(SpdyStream.RST_CANCEL);
     86         return true;
     87       } else {
     88         // If stream is null, it either means that writeRequestHeaders wasn't called
     89         // or that SpdyConnection#newStream threw an IOEXception. In both cases there's
     90         // nothing to do here and this stream can't be reused.
     91         return false;
     92       }
     93     }
     94     return true;
     95   }
     96 }
     97