| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.squareup.okhttp.internal.http; |
| |
| import com.squareup.okhttp.internal.spdy.SpdyConnection; |
| import com.squareup.okhttp.internal.spdy.SpdyStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.net.CacheRequest; |
| import java.net.URL; |
| import java.util.List; |
| |
| public final class SpdyTransport implements Transport { |
| private final HttpEngine httpEngine; |
| private final SpdyConnection spdyConnection; |
| private SpdyStream stream; |
| |
| public SpdyTransport(HttpEngine httpEngine, SpdyConnection spdyConnection) { |
| this.httpEngine = httpEngine; |
| this.spdyConnection = spdyConnection; |
| } |
| |
| @Override public OutputStream createRequestBody() throws IOException { |
| // TODO: if we aren't streaming up to the server, we should buffer the whole request |
| writeRequestHeaders(); |
| return stream.getOutputStream(); |
| } |
| |
| @Override public void writeRequestHeaders() throws IOException { |
| if (stream != null) { |
| return; |
| } |
| httpEngine.writingRequestHeaders(); |
| RawHeaders requestHeaders = httpEngine.requestHeaders.getHeaders(); |
| String version = httpEngine.connection.getHttpMinorVersion() == 1 ? "HTTP/1.1" : "HTTP/1.0"; |
| URL url = httpEngine.policy.getURL(); |
| requestHeaders.addSpdyRequestHeaders(httpEngine.method, HttpEngine.requestPath(url), version, |
| HttpEngine.getOriginAddress(url), httpEngine.uri.getScheme()); |
| boolean hasRequestBody = httpEngine.hasRequestBody(); |
| boolean hasResponseBody = true; |
| stream = spdyConnection.newStream(requestHeaders.toNameValueBlock(), hasRequestBody, |
| hasResponseBody); |
| stream.setReadTimeout(httpEngine.policy.getReadTimeout()); |
| } |
| |
| @Override public void writeRequestBody(RetryableOutputStream requestBody) throws IOException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override public void flushRequest() throws IOException { |
| stream.getOutputStream().close(); |
| } |
| |
| @Override public ResponseHeaders readResponseHeaders() throws IOException { |
| List<String> nameValueBlock = stream.getResponseHeaders(); |
| RawHeaders rawHeaders = RawHeaders.fromNameValueBlock(nameValueBlock); |
| rawHeaders.computeResponseStatusLineFromSpdyHeaders(); |
| httpEngine.receiveHeaders(rawHeaders); |
| |
| ResponseHeaders headers = new ResponseHeaders(httpEngine.uri, rawHeaders); |
| headers.setTransport("spdy/3"); |
| return headers; |
| } |
| |
| @Override public InputStream getTransferStream(CacheRequest cacheRequest) throws IOException { |
| return new UnknownLengthHttpInputStream(stream.getInputStream(), cacheRequest, httpEngine); |
| } |
| |
| @Override public boolean makeReusable(boolean streamCancelled, OutputStream requestBodyOut, |
| InputStream responseBodyIn) { |
| if (streamCancelled) { |
| if (stream != null) { |
| stream.closeLater(SpdyStream.RST_CANCEL); |
| return true; |
| } else { |
| // If stream is null, it either means that writeRequestHeaders wasn't called |
| // or that SpdyConnection#newStream threw an IOEXception. In both cases there's |
| // nothing to do here and this stream can't be reused. |
| return false; |
| } |
| } |
| return true; |
| } |
| } |