Return-Path: X-Original-To: apmail-cordova-commits-archive@www.apache.org Delivered-To: apmail-cordova-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id EEEA710B15 for ; Wed, 31 Dec 2014 04:01:04 +0000 (UTC) Received: (qmail 96082 invoked by uid 500); 31 Dec 2014 04:01:05 -0000 Delivered-To: apmail-cordova-commits-archive@cordova.apache.org Received: (qmail 95976 invoked by uid 500); 31 Dec 2014 04:01:05 -0000 Mailing-List: contact commits-help@cordova.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Delivered-To: mailing list commits@cordova.apache.org Received: (qmail 95465 invoked by uid 99); 31 Dec 2014 04:01:05 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 31 Dec 2014 04:01:05 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 9E458A3A68C; Wed, 31 Dec 2014 04:01:04 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: agrieve@apache.org To: commits@cordova.apache.org Date: Wed, 31 Dec 2014 04:01:10 -0000 Message-Id: <19a91913856a423ca27f7b0ae4b84b54@git.apache.org> In-Reply-To: <7ae74ab77b764190af819574f7800dce@git.apache.org> References: <7ae74ab77b764190af819574f7800dce@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [07/12] android commit: CB-6630 Delete bundled (and outdated) copy of OkHttp http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c6b171ba/framework/src/com/squareup/okhttp/internal/spdy/Ping.java ---------------------------------------------------------------------- diff --git a/framework/src/com/squareup/okhttp/internal/spdy/Ping.java b/framework/src/com/squareup/okhttp/internal/spdy/Ping.java deleted file mode 100755 index c585255..0000000 --- a/framework/src/com/squareup/okhttp/internal/spdy/Ping.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2012 Square, Inc. - * - * 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.spdy; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * A locally-originated ping. - */ -public final class Ping { - private final CountDownLatch latch = new CountDownLatch(1); - private long sent = -1; - private long received = -1; - - Ping() { - } - - void send() { - if (sent != -1) throw new IllegalStateException(); - sent = System.nanoTime(); - } - - void receive() { - if (received != -1 || sent == -1) throw new IllegalStateException(); - received = System.nanoTime(); - latch.countDown(); - } - - void cancel() { - if (received != -1 || sent == -1) throw new IllegalStateException(); - received = sent - 1; - latch.countDown(); - } - - /** - * Returns the round trip time for this ping in nanoseconds, waiting for the - * response to arrive if necessary. Returns -1 if the response was - * cancelled. - */ - public long roundTripTime() throws InterruptedException { - latch.await(); - return received - sent; - } - - /** - * Returns the round trip time for this ping in nanoseconds, or -1 if the - * response was cancelled, or -2 if the timeout elapsed before the round - * trip completed. - */ - public long roundTripTime(long timeout, TimeUnit unit) throws InterruptedException { - if (latch.await(timeout, unit)) { - return received - sent; - } else { - return -2; - } - } -} http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c6b171ba/framework/src/com/squareup/okhttp/internal/spdy/Settings.java ---------------------------------------------------------------------- diff --git a/framework/src/com/squareup/okhttp/internal/spdy/Settings.java b/framework/src/com/squareup/okhttp/internal/spdy/Settings.java deleted file mode 100755 index 05380e2..0000000 --- a/framework/src/com/squareup/okhttp/internal/spdy/Settings.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2012 Square, Inc. - * - * 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.spdy; - -final class Settings { - /** - * From the spdy/3 spec, the default initial window size for all streams is - * 64 KiB. (Chrome 25 uses 10 MiB). - */ - static final int DEFAULT_INITIAL_WINDOW_SIZE = 64 * 1024; - - /** Peer request to clear durable settings. */ - static final int FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS = 0x1; - - /** Sent by servers only. The peer requests this setting persisted for future connections. */ - static final int PERSIST_VALUE = 0x1; - /** Sent by clients only. The client is reminding the server of a persisted value. */ - static final int PERSISTED = 0x2; - - /** Sender's estimate of max incoming kbps. */ - static final int UPLOAD_BANDWIDTH = 1; - /** Sender's estimate of max outgoing kbps. */ - static final int DOWNLOAD_BANDWIDTH = 2; - /** Sender's estimate of milliseconds between sending a request and receiving a response. */ - static final int ROUND_TRIP_TIME = 3; - /** Sender's maximum number of concurrent streams. */ - static final int MAX_CONCURRENT_STREAMS = 4; - /** Current CWND in Packets. */ - static final int CURRENT_CWND = 5; - /** Retransmission rate. Percentage */ - static final int DOWNLOAD_RETRANS_RATE = 6; - /** Window size in bytes. */ - static final int INITIAL_WINDOW_SIZE = 7; - /** Window size in bytes. */ - static final int CLIENT_CERTIFICATE_VECTOR_SIZE = 8; - /** Flow control options. */ - static final int FLOW_CONTROL_OPTIONS = 9; - - /** Total number of settings. */ - static final int COUNT = 10; - - /** If set, flow control is disabled for streams directed to the sender of these settings. */ - static final int FLOW_CONTROL_OPTIONS_DISABLED = 0x1; - - /** Bitfield of which flags that values. */ - private int set; - - /** Bitfield of flags that have {@link #PERSIST_VALUE}. */ - private int persistValue; - - /** Bitfield of flags that have {@link #PERSISTED}. */ - private int persisted; - - /** Flag values. */ - private final int[] values = new int[COUNT]; - - void set(int id, int idFlags, int value) { - if (id >= values.length) { - return; // Discard unknown settings. - } - - int bit = 1 << id; - set |= bit; - if ((idFlags & PERSIST_VALUE) != 0) { - persistValue |= bit; - } else { - persistValue &= ~bit; - } - if ((idFlags & PERSISTED) != 0) { - persisted |= bit; - } else { - persisted &= ~bit; - } - - values[id] = value; - } - - /** Returns true if a value has been assigned for the setting {@code id}. */ - boolean isSet(int id) { - int bit = 1 << id; - return (set & bit) != 0; - } - - /** Returns the value for the setting {@code id}, or 0 if unset. */ - int get(int id) { - return values[id]; - } - - /** Returns the flags for the setting {@code id}, or 0 if unset. */ - int flags(int id) { - int result = 0; - if (isPersisted(id)) result |= Settings.PERSISTED; - if (persistValue(id)) result |= Settings.PERSIST_VALUE; - return result; - } - - /** Returns the number of settings that have values assigned. */ - int size() { - return Integer.bitCount(set); - } - - int getUploadBandwidth(int defaultValue) { - int bit = 1 << UPLOAD_BANDWIDTH; - return (bit & set) != 0 ? values[UPLOAD_BANDWIDTH] : defaultValue; - } - - int getDownloadBandwidth(int defaultValue) { - int bit = 1 << DOWNLOAD_BANDWIDTH; - return (bit & set) != 0 ? values[DOWNLOAD_BANDWIDTH] : defaultValue; - } - - int getRoundTripTime(int defaultValue) { - int bit = 1 << ROUND_TRIP_TIME; - return (bit & set) != 0 ? values[ROUND_TRIP_TIME] : defaultValue; - } - - int getMaxConcurrentStreams(int defaultValue) { - int bit = 1 << MAX_CONCURRENT_STREAMS; - return (bit & set) != 0 ? values[MAX_CONCURRENT_STREAMS] : defaultValue; - } - - int getCurrentCwnd(int defaultValue) { - int bit = 1 << CURRENT_CWND; - return (bit & set) != 0 ? values[CURRENT_CWND] : defaultValue; - } - - int getDownloadRetransRate(int defaultValue) { - int bit = 1 << DOWNLOAD_RETRANS_RATE; - return (bit & set) != 0 ? values[DOWNLOAD_RETRANS_RATE] : defaultValue; - } - - int getInitialWindowSize(int defaultValue) { - int bit = 1 << INITIAL_WINDOW_SIZE; - return (bit & set) != 0 ? values[INITIAL_WINDOW_SIZE] : defaultValue; - } - - int getClientCertificateVectorSize(int defaultValue) { - int bit = 1 << CLIENT_CERTIFICATE_VECTOR_SIZE; - return (bit & set) != 0 ? values[CLIENT_CERTIFICATE_VECTOR_SIZE] : defaultValue; - } - - // TODO: honor this setting. - boolean isFlowControlDisabled() { - int bit = 1 << FLOW_CONTROL_OPTIONS; - int value = (bit & set) != 0 ? values[FLOW_CONTROL_OPTIONS] : 0; - return (value & FLOW_CONTROL_OPTIONS_DISABLED) != 0; - } - - /** - * Returns true if this user agent should use this setting in future SPDY - * connections to the same host. - */ - boolean persistValue(int id) { - int bit = 1 << id; - return (persistValue & bit) != 0; - } - - /** Returns true if this setting was persisted. */ - boolean isPersisted(int id) { - int bit = 1 << id; - return (persisted & bit) != 0; - } - - /** - * Writes {@code other} into this. If any setting is populated by this and - * {@code other}, the value and flags from {@code other} will be kept. - */ - void merge(Settings other) { - for (int i = 0; i < COUNT; i++) { - if (!other.isSet(i)) continue; - set(i, other.flags(i), other.get(i)); - } - } -} http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c6b171ba/framework/src/com/squareup/okhttp/internal/spdy/Spdy3.java ---------------------------------------------------------------------- diff --git a/framework/src/com/squareup/okhttp/internal/spdy/Spdy3.java b/framework/src/com/squareup/okhttp/internal/spdy/Spdy3.java deleted file mode 100755 index 5d9a49b..0000000 --- a/framework/src/com/squareup/okhttp/internal/spdy/Spdy3.java +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright (C) 2011 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.spdy; - -import com.squareup.okhttp.internal.Platform; -import com.squareup.okhttp.internal.Util; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.ProtocolException; -import java.util.List; -import java.util.zip.Deflater; - -final class Spdy3 implements Variant { - static final int TYPE_DATA = 0x0; - static final int TYPE_SYN_STREAM = 0x1; - static final int TYPE_SYN_REPLY = 0x2; - static final int TYPE_RST_STREAM = 0x3; - static final int TYPE_SETTINGS = 0x4; - static final int TYPE_NOOP = 0x5; - static final int TYPE_PING = 0x6; - static final int TYPE_GOAWAY = 0x7; - static final int TYPE_HEADERS = 0x8; - static final int TYPE_WINDOW_UPDATE = 0x9; - static final int TYPE_CREDENTIAL = 0x10; - - static final int FLAG_FIN = 0x1; - static final int FLAG_UNIDIRECTIONAL = 0x2; - - static final int VERSION = 3; - - static final byte[] DICTIONARY; - static { - try { - DICTIONARY = ("\u0000\u0000\u0000\u0007options\u0000\u0000\u0000\u0004hea" - + "d\u0000\u0000\u0000\u0004post\u0000\u0000\u0000\u0003put\u0000\u0000\u0000\u0006dele" - + "te\u0000\u0000\u0000\u0005trace\u0000\u0000\u0000\u0006accept\u0000\u0000\u0000" - + "\u000Eaccept-charset\u0000\u0000\u0000\u000Faccept-encoding\u0000\u0000\u0000\u000Fa" - + "ccept-language\u0000\u0000\u0000\raccept-ranges\u0000\u0000\u0000\u0003age\u0000" - + "\u0000\u0000\u0005allow\u0000\u0000\u0000\rauthorization\u0000\u0000\u0000\rcache-co" - + "ntrol\u0000\u0000\u0000\nconnection\u0000\u0000\u0000\fcontent-base\u0000\u0000" - + "\u0000\u0010content-encoding\u0000\u0000\u0000\u0010content-language\u0000\u0000" - + "\u0000\u000Econtent-length\u0000\u0000\u0000\u0010content-location\u0000\u0000\u0000" - + "\u000Bcontent-md5\u0000\u0000\u0000\rcontent-range\u0000\u0000\u0000\fcontent-type" - + "\u0000\u0000\u0000\u0004date\u0000\u0000\u0000\u0004etag\u0000\u0000\u0000\u0006expe" - + "ct\u0000\u0000\u0000\u0007expires\u0000\u0000\u0000\u0004from\u0000\u0000\u0000" - + "\u0004host\u0000\u0000\u0000\bif-match\u0000\u0000\u0000\u0011if-modified-since" - + "\u0000\u0000\u0000\rif-none-match\u0000\u0000\u0000\bif-range\u0000\u0000\u0000" - + "\u0013if-unmodified-since\u0000\u0000\u0000\rlast-modified\u0000\u0000\u0000\blocati" - + "on\u0000\u0000\u0000\fmax-forwards\u0000\u0000\u0000\u0006pragma\u0000\u0000\u0000" - + "\u0012proxy-authenticate\u0000\u0000\u0000\u0013proxy-authorization\u0000\u0000" - + "\u0000\u0005range\u0000\u0000\u0000\u0007referer\u0000\u0000\u0000\u000Bretry-after" - + "\u0000\u0000\u0000\u0006server\u0000\u0000\u0000\u0002te\u0000\u0000\u0000\u0007trai" - + "ler\u0000\u0000\u0000\u0011transfer-encoding\u0000\u0000\u0000\u0007upgrade\u0000" - + "\u0000\u0000\nuser-agent\u0000\u0000\u0000\u0004vary\u0000\u0000\u0000\u0003via" - + "\u0000\u0000\u0000\u0007warning\u0000\u0000\u0000\u0010www-authenticate\u0000\u0000" - + "\u0000\u0006method\u0000\u0000\u0000\u0003get\u0000\u0000\u0000\u0006status\u0000" - + "\u0000\u0000\u0006200 OK\u0000\u0000\u0000\u0007version\u0000\u0000\u0000\bHTTP/1.1" - + "\u0000\u0000\u0000\u0003url\u0000\u0000\u0000\u0006public\u0000\u0000\u0000\nset-coo" - + "kie\u0000\u0000\u0000\nkeep-alive\u0000\u0000\u0000\u0006origin100101201202205206300" - + "302303304305306307402405406407408409410411412413414415416417502504505203 Non-Authori" - + "tative Information204 No Content301 Moved Permanently400 Bad Request401 Unauthorized" - + "403 Forbidden404 Not Found500 Internal Server Error501 Not Implemented503 Service Un" - + "availableJan Feb Mar Apr May Jun Jul Aug Sept Oct Nov Dec 00:00:00 Mon, Tue, Wed, Th" - + "u, Fri, Sat, Sun, GMTchunked,text/html,image/png,image/jpg,image/gif,application/xml" - + ",application/xhtml+xml,text/plain,text/javascript,publicprivatemax-age=gzip,deflate," - + "sdchcharset=utf-8charset=iso-8859-1,utf-,*,enq=0.").getBytes(Util.UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(); - } - } - - @Override public FrameReader newReader(InputStream in, boolean client) { - return new Reader(in, client); - } - - @Override public FrameWriter newWriter(OutputStream out, boolean client) { - return new Writer(out, client); - } - - /** Read spdy/3 frames. */ - static final class Reader implements FrameReader { - private final DataInputStream in; - private final boolean client; - private final NameValueBlockReader nameValueBlockReader; - - Reader(InputStream in, boolean client) { - this.in = new DataInputStream(in); - this.nameValueBlockReader = new NameValueBlockReader(in); - this.client = client; - } - - @Override public void readConnectionHeader() { - } - - /** - * Send the next frame to {@code handler}. Returns true unless there are no - * more frames on the stream. - */ - @Override public boolean nextFrame(Handler handler) throws IOException { - int w1; - try { - w1 = in.readInt(); - } catch (IOException e) { - return false; // This might be a normal socket close. - } - int w2 = in.readInt(); - - boolean control = (w1 & 0x80000000) != 0; - int flags = (w2 & 0xff000000) >>> 24; - int length = (w2 & 0xffffff); - - if (control) { - int version = (w1 & 0x7fff0000) >>> 16; - int type = (w1 & 0xffff); - - if (version != 3) { - throw new ProtocolException("version != 3: " + version); - } - - switch (type) { - case TYPE_SYN_STREAM: - readSynStream(handler, flags, length); - return true; - - case TYPE_SYN_REPLY: - readSynReply(handler, flags, length); - return true; - - case TYPE_RST_STREAM: - readRstStream(handler, flags, length); - return true; - - case TYPE_SETTINGS: - readSettings(handler, flags, length); - return true; - - case TYPE_NOOP: - if (length != 0) throw ioException("TYPE_NOOP length: %d != 0", length); - handler.noop(); - return true; - - case TYPE_PING: - readPing(handler, flags, length); - return true; - - case TYPE_GOAWAY: - readGoAway(handler, flags, length); - return true; - - case TYPE_HEADERS: - readHeaders(handler, flags, length); - return true; - - case TYPE_WINDOW_UPDATE: - readWindowUpdate(handler, flags, length); - return true; - - case TYPE_CREDENTIAL: - Util.skipByReading(in, length); - throw new UnsupportedOperationException("TODO"); // TODO: implement - - default: - throw new IOException("Unexpected frame"); - } - } else { - int streamId = w1 & 0x7fffffff; - boolean inFinished = (flags & FLAG_FIN) != 0; - handler.data(inFinished, streamId, in, length); - return true; - } - } - - private void readSynStream(Handler handler, int flags, int length) throws IOException { - int w1 = in.readInt(); - int w2 = in.readInt(); - int s3 = in.readShort(); - int streamId = w1 & 0x7fffffff; - int associatedStreamId = w2 & 0x7fffffff; - int priority = (s3 & 0xe000) >>> 13; - int slot = s3 & 0xff; - List nameValueBlock = nameValueBlockReader.readNameValueBlock(length - 10); - - boolean inFinished = (flags & FLAG_FIN) != 0; - boolean outFinished = (flags & FLAG_UNIDIRECTIONAL) != 0; - handler.headers(outFinished, inFinished, streamId, associatedStreamId, priority, - nameValueBlock, HeadersMode.SPDY_SYN_STREAM); - } - - private void readSynReply(Handler handler, int flags, int length) throws IOException { - int w1 = in.readInt(); - int streamId = w1 & 0x7fffffff; - List nameValueBlock = nameValueBlockReader.readNameValueBlock(length - 4); - boolean inFinished = (flags & FLAG_FIN) != 0; - handler.headers(false, inFinished, streamId, -1, -1, nameValueBlock, HeadersMode.SPDY_REPLY); - } - - private void readRstStream(Handler handler, int flags, int length) throws IOException { - if (length != 8) throw ioException("TYPE_RST_STREAM length: %d != 8", length); - int streamId = in.readInt() & 0x7fffffff; - int errorCodeInt = in.readInt(); - ErrorCode errorCode = ErrorCode.fromSpdy3Rst(errorCodeInt); - if (errorCode == null) { - throw ioException("TYPE_RST_STREAM unexpected error code: %d", errorCodeInt); - } - handler.rstStream(streamId, errorCode); - } - - private void readHeaders(Handler handler, int flags, int length) throws IOException { - int w1 = in.readInt(); - int streamId = w1 & 0x7fffffff; - List nameValueBlock = nameValueBlockReader.readNameValueBlock(length - 4); - handler.headers(false, false, streamId, -1, -1, nameValueBlock, HeadersMode.SPDY_HEADERS); - } - - private void readWindowUpdate(Handler handler, int flags, int length) throws IOException { - if (length != 8) throw ioException("TYPE_WINDOW_UPDATE length: %d != 8", length); - int w1 = in.readInt(); - int w2 = in.readInt(); - int streamId = w1 & 0x7fffffff; - int deltaWindowSize = w2 & 0x7fffffff; - handler.windowUpdate(streamId, deltaWindowSize, false); - } - - private void readPing(Handler handler, int flags, int length) throws IOException { - if (length != 4) throw ioException("TYPE_PING length: %d != 4", length); - int id = in.readInt(); - boolean reply = client == ((id % 2) == 1); - handler.ping(reply, id, 0); - } - - private void readGoAway(Handler handler, int flags, int length) throws IOException { - if (length != 8) throw ioException("TYPE_GOAWAY length: %d != 8", length); - int lastGoodStreamId = in.readInt() & 0x7fffffff; - int errorCodeInt = in.readInt(); - ErrorCode errorCode = ErrorCode.fromSpdyGoAway(errorCodeInt); - if (errorCode == null) { - throw ioException("TYPE_GOAWAY unexpected error code: %d", errorCodeInt); - } - handler.goAway(lastGoodStreamId, errorCode); - } - - private void readSettings(Handler handler, int flags, int length) throws IOException { - int numberOfEntries = in.readInt(); - if (length != 4 + 8 * numberOfEntries) { - throw ioException("TYPE_SETTINGS length: %d != 4 + 8 * %d", length, numberOfEntries); - } - Settings settings = new Settings(); - for (int i = 0; i < numberOfEntries; i++) { - int w1 = in.readInt(); - int value = in.readInt(); - int idFlags = (w1 & 0xff000000) >>> 24; - int id = w1 & 0xffffff; - settings.set(id, idFlags, value); - } - boolean clearPrevious = (flags & Settings.FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) != 0; - handler.settings(clearPrevious, settings); - } - - private static IOException ioException(String message, Object... args) throws IOException { - throw new IOException(String.format(message, args)); - } - - @Override public void close() throws IOException { - Util.closeAll(in, nameValueBlockReader); - } - } - - /** Write spdy/3 frames. */ - static final class Writer implements FrameWriter { - private final DataOutputStream out; - private final ByteArrayOutputStream nameValueBlockBuffer; - private final DataOutputStream nameValueBlockOut; - private final boolean client; - - Writer(OutputStream out, boolean client) { - this.out = new DataOutputStream(out); - this.client = client; - - Deflater deflater = new Deflater(); - deflater.setDictionary(DICTIONARY); - nameValueBlockBuffer = new ByteArrayOutputStream(); - nameValueBlockOut = new DataOutputStream( - Platform.get().newDeflaterOutputStream(nameValueBlockBuffer, deflater, true)); - } - - @Override public synchronized void connectionHeader() { - // Do nothing: no connection header for SPDY/3. - } - - @Override public synchronized void flush() throws IOException { - out.flush(); - } - - @Override public synchronized void synStream(boolean outFinished, boolean inFinished, - int streamId, int associatedStreamId, int priority, int slot, List nameValueBlock) - throws IOException { - writeNameValueBlockToBuffer(nameValueBlock); - int length = 10 + nameValueBlockBuffer.size(); - int type = TYPE_SYN_STREAM; - int flags = (outFinished ? FLAG_FIN : 0) | (inFinished ? FLAG_UNIDIRECTIONAL : 0); - - int unused = 0; - out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff); - out.writeInt((flags & 0xff) << 24 | length & 0xffffff); - out.writeInt(streamId & 0x7fffffff); - out.writeInt(associatedStreamId & 0x7fffffff); - out.writeShort((priority & 0x7) << 13 | (unused & 0x1f) << 8 | (slot & 0xff)); - nameValueBlockBuffer.writeTo(out); - out.flush(); - } - - @Override public synchronized void synReply( - boolean outFinished, int streamId, List nameValueBlock) throws IOException { - writeNameValueBlockToBuffer(nameValueBlock); - int type = TYPE_SYN_REPLY; - int flags = (outFinished ? FLAG_FIN : 0); - int length = nameValueBlockBuffer.size() + 4; - - out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff); - out.writeInt((flags & 0xff) << 24 | length & 0xffffff); - out.writeInt(streamId & 0x7fffffff); - nameValueBlockBuffer.writeTo(out); - out.flush(); - } - - @Override public synchronized void headers(int streamId, List nameValueBlock) - throws IOException { - writeNameValueBlockToBuffer(nameValueBlock); - int flags = 0; - int type = TYPE_HEADERS; - int length = nameValueBlockBuffer.size() + 4; - - out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff); - out.writeInt((flags & 0xff) << 24 | length & 0xffffff); - out.writeInt(streamId & 0x7fffffff); - nameValueBlockBuffer.writeTo(out); - out.flush(); - } - - @Override public synchronized void rstStream(int streamId, ErrorCode errorCode) - throws IOException { - if (errorCode.spdyRstCode == -1) throw new IllegalArgumentException(); - int flags = 0; - int type = TYPE_RST_STREAM; - int length = 8; - out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff); - out.writeInt((flags & 0xff) << 24 | length & 0xffffff); - out.writeInt(streamId & 0x7fffffff); - out.writeInt(errorCode.spdyRstCode); - out.flush(); - } - - @Override public synchronized void data(boolean outFinished, int streamId, byte[] data) - throws IOException { - data(outFinished, streamId, data, 0, data.length); - } - - @Override public synchronized void data(boolean outFinished, int streamId, byte[] data, - int offset, int byteCount) throws IOException { - int flags = (outFinished ? FLAG_FIN : 0); - out.writeInt(streamId & 0x7fffffff); - out.writeInt((flags & 0xff) << 24 | byteCount & 0xffffff); - out.write(data, offset, byteCount); - } - - private void writeNameValueBlockToBuffer(List nameValueBlock) throws IOException { - nameValueBlockBuffer.reset(); - int numberOfPairs = nameValueBlock.size() / 2; - nameValueBlockOut.writeInt(numberOfPairs); - for (String s : nameValueBlock) { - nameValueBlockOut.writeInt(s.length()); - nameValueBlockOut.write(s.getBytes("UTF-8")); - } - nameValueBlockOut.flush(); - } - - @Override public synchronized void settings(Settings settings) throws IOException { - int type = TYPE_SETTINGS; - int flags = 0; - int size = settings.size(); - int length = 4 + size * 8; - out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff); - out.writeInt((flags & 0xff) << 24 | length & 0xffffff); - out.writeInt(size); - for (int i = 0; i <= Settings.COUNT; i++) { - if (!settings.isSet(i)) continue; - int settingsFlags = settings.flags(i); - out.writeInt((settingsFlags & 0xff) << 24 | (i & 0xffffff)); - out.writeInt(settings.get(i)); - } - out.flush(); - } - - @Override public synchronized void noop() throws IOException { - int type = TYPE_NOOP; - int length = 0; - int flags = 0; - out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff); - out.writeInt((flags & 0xff) << 24 | length & 0xffffff); - out.flush(); - } - - @Override public synchronized void ping(boolean reply, int payload1, int payload2) - throws IOException { - boolean payloadIsReply = client != ((payload1 % 2) == 1); - if (reply != payloadIsReply) throw new IllegalArgumentException("payload != reply"); - int type = TYPE_PING; - int flags = 0; - int length = 4; - out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff); - out.writeInt((flags & 0xff) << 24 | length & 0xffffff); - out.writeInt(payload1); - out.flush(); - } - - @Override public synchronized void goAway(int lastGoodStreamId, ErrorCode errorCode) - throws IOException { - if (errorCode.spdyGoAwayCode == -1) throw new IllegalArgumentException(); - int type = TYPE_GOAWAY; - int flags = 0; - int length = 8; - out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff); - out.writeInt((flags & 0xff) << 24 | length & 0xffffff); - out.writeInt(lastGoodStreamId); - out.writeInt(errorCode.spdyGoAwayCode); - out.flush(); - } - - @Override public synchronized void windowUpdate(int streamId, int deltaWindowSize) - throws IOException { - int type = TYPE_WINDOW_UPDATE; - int flags = 0; - int length = 8; - out.writeInt(0x80000000 | (VERSION & 0x7fff) << 16 | type & 0xffff); - out.writeInt((flags & 0xff) << 24 | length & 0xffffff); - out.writeInt(streamId); - out.writeInt(deltaWindowSize); - out.flush(); - } - - @Override public void close() throws IOException { - Util.closeAll(out, nameValueBlockOut); - } - } -} http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c6b171ba/framework/src/com/squareup/okhttp/internal/spdy/SpdyConnection.java ---------------------------------------------------------------------- diff --git a/framework/src/com/squareup/okhttp/internal/spdy/SpdyConnection.java b/framework/src/com/squareup/okhttp/internal/spdy/SpdyConnection.java deleted file mode 100755 index 41724f0..0000000 --- a/framework/src/com/squareup/okhttp/internal/spdy/SpdyConnection.java +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright (C) 2011 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.spdy; - -import com.squareup.okhttp.internal.NamedRunnable; -import com.squareup.okhttp.internal.Util; -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * A socket connection to a remote peer. A connection hosts streams which can - * send and receive data. - * - *

Many methods in this API are synchronous: the call is - * completed before the method returns. This is typical for Java but atypical - * for SPDY. This is motivated by exception transparency: an IOException that - * was triggered by a certain caller can be caught and handled by that caller. - */ -public final class SpdyConnection implements Closeable { - - // Internal state of this connection is guarded by 'this'. No blocking - // operations may be performed while holding this lock! - // - // Socket writes are guarded by frameWriter. - // - // Socket reads are unguarded but are only made by the reader thread. - // - // Certain operations (like SYN_STREAM) need to synchronize on both the - // frameWriter (to do blocking I/O) and this (to create streams). Such - // operations must synchronize on 'this' last. This ensures that we never - // wait for a blocking operation while holding 'this'. - - private static final ExecutorService executor = new ThreadPoolExecutor(0, - Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue(), - Util.daemonThreadFactory("OkHttp SpdyConnection")); - - /** The protocol variant, like SPDY/3 or HTTP-draft-06/2.0. */ - final Variant variant; - - /** True if this peer initiated the connection. */ - final boolean client; - - /** - * User code to run in response to an incoming stream. Callbacks must not be - * run on the callback executor. - */ - private final IncomingStreamHandler handler; - private final FrameReader frameReader; - private final FrameWriter frameWriter; - - private final Map streams = new HashMap(); - private final String hostName; - private int lastGoodStreamId; - private int nextStreamId; - private boolean shutdown; - private long idleStartTimeNs = System.nanoTime(); - - /** Lazily-created map of in-flight pings awaiting a response. Guarded by this. */ - private Map pings; - private int nextPingId; - - /** Lazily-created settings for the peer. */ - Settings settings; - - private SpdyConnection(Builder builder) { - variant = builder.variant; - client = builder.client; - handler = builder.handler; - frameReader = variant.newReader(builder.in, client); - frameWriter = variant.newWriter(builder.out, client); - nextStreamId = builder.client ? 1 : 2; - nextPingId = builder.client ? 1 : 2; - - hostName = builder.hostName; - - new Thread(new Reader(), "Spdy Reader " + hostName).start(); - } - - /** - * Returns the number of {@link SpdyStream#isOpen() open streams} on this - * connection. - */ - public synchronized int openStreamCount() { - return streams.size(); - } - - private synchronized SpdyStream getStream(int id) { - return streams.get(id); - } - - synchronized SpdyStream removeStream(int streamId) { - SpdyStream stream = streams.remove(streamId); - if (stream != null && streams.isEmpty()) { - setIdle(true); - } - return stream; - } - - private synchronized void setIdle(boolean value) { - idleStartTimeNs = value ? System.nanoTime() : Long.MAX_VALUE; - } - - /** Returns true if this connection is idle. */ - public synchronized boolean isIdle() { - return idleStartTimeNs != Long.MAX_VALUE; - } - - /** - * Returns the time in ns when this connection became idle or Long.MAX_VALUE - * if connection is not idle. - */ - public synchronized long getIdleStartTimeNs() { - return idleStartTimeNs; - } - - /** - * Returns a new locally-initiated stream. - * - * @param out true to create an output stream that we can use to send data - * to the remote peer. Corresponds to {@code FLAG_FIN}. - * @param in true to create an input stream that the remote peer can use to - * send data to us. Corresponds to {@code FLAG_UNIDIRECTIONAL}. - */ - public SpdyStream newStream(List requestHeaders, boolean out, boolean in) - throws IOException { - boolean outFinished = !out; - boolean inFinished = !in; - int associatedStreamId = 0; // TODO: permit the caller to specify an associated stream? - int priority = 0; // TODO: permit the caller to specify a priority? - int slot = 0; // TODO: permit the caller to specify a slot? - SpdyStream stream; - int streamId; - - synchronized (frameWriter) { - synchronized (this) { - if (shutdown) { - throw new IOException("shutdown"); - } - streamId = nextStreamId; - nextStreamId += 2; - stream = new SpdyStream( - streamId, this, outFinished, inFinished, priority, requestHeaders, settings); - if (stream.isOpen()) { - streams.put(streamId, stream); - setIdle(false); - } - } - - frameWriter.synStream(outFinished, inFinished, streamId, associatedStreamId, priority, slot, - requestHeaders); - } - - return stream; - } - - void writeSynReply(int streamId, boolean outFinished, List alternating) - throws IOException { - frameWriter.synReply(outFinished, streamId, alternating); - } - - public void writeData(int streamId, boolean outFinished, byte[] buffer, int offset, int byteCount) - throws IOException { - frameWriter.data(outFinished, streamId, buffer, offset, byteCount); - } - - void writeSynResetLater(final int streamId, final ErrorCode errorCode) { - executor.submit(new NamedRunnable("OkHttp SPDY Writer %s stream %d", hostName, streamId) { - @Override public void execute() { - try { - writeSynReset(streamId, errorCode); - } catch (IOException ignored) { - } - } - }); - } - - void writeSynReset(int streamId, ErrorCode statusCode) throws IOException { - frameWriter.rstStream(streamId, statusCode); - } - - void writeWindowUpdateLater(final int streamId, final int deltaWindowSize) { - executor.submit(new NamedRunnable("OkHttp SPDY Writer %s stream %d", hostName, streamId) { - @Override public void execute() { - try { - writeWindowUpdate(streamId, deltaWindowSize); - } catch (IOException ignored) { - } - } - }); - } - - void writeWindowUpdate(int streamId, int deltaWindowSize) throws IOException { - frameWriter.windowUpdate(streamId, deltaWindowSize); - } - - /** - * Sends a ping frame to the peer. Use the returned object to await the - * ping's response and observe its round trip time. - */ - public Ping ping() throws IOException { - Ping ping = new Ping(); - int pingId; - synchronized (this) { - if (shutdown) { - throw new IOException("shutdown"); - } - pingId = nextPingId; - nextPingId += 2; - if (pings == null) pings = new HashMap(); - pings.put(pingId, ping); - } - writePing(false, pingId, 0x4f4b6f6b /* ASCII "OKok" */, ping); - return ping; - } - - private void writePingLater( - final boolean reply, final int payload1, final int payload2, final Ping ping) { - executor.submit(new NamedRunnable("OkHttp SPDY Writer %s ping %08x%08x", - hostName, payload1, payload2) { - @Override public void execute() { - try { - writePing(reply, payload1, payload2, ping); - } catch (IOException ignored) { - } - } - }); - } - - private void writePing(boolean reply, int payload1, int payload2, Ping ping) throws IOException { - synchronized (frameWriter) { - // Observe the sent time immediately before performing I/O. - if (ping != null) ping.send(); - frameWriter.ping(reply, payload1, payload2); - } - } - - private synchronized Ping removePing(int id) { - return pings != null ? pings.remove(id) : null; - } - - /** Sends a noop frame to the peer. */ - public void noop() throws IOException { - frameWriter.noop(); - } - - public void flush() throws IOException { - frameWriter.flush(); - } - - /** - * Degrades this connection such that new streams can neither be created - * locally, nor accepted from the remote peer. Existing streams are not - * impacted. This is intended to permit an endpoint to gracefully stop - * accepting new requests without harming previously established streams. - */ - public void shutdown(ErrorCode statusCode) throws IOException { - synchronized (frameWriter) { - int lastGoodStreamId; - synchronized (this) { - if (shutdown) { - return; - } - shutdown = true; - lastGoodStreamId = this.lastGoodStreamId; - } - frameWriter.goAway(lastGoodStreamId, statusCode); - } - } - - /** - * Closes this connection. This cancels all open streams and unanswered - * pings. It closes the underlying input and output streams and shuts down - * internal executor services. - */ - @Override public void close() throws IOException { - close(ErrorCode.NO_ERROR, ErrorCode.CANCEL); - } - - private void close(ErrorCode connectionCode, ErrorCode streamCode) throws IOException { - assert (!Thread.holdsLock(this)); - IOException thrown = null; - try { - shutdown(connectionCode); - } catch (IOException e) { - thrown = e; - } - - SpdyStream[] streamsToClose = null; - Ping[] pingsToCancel = null; - synchronized (this) { - if (!streams.isEmpty()) { - streamsToClose = streams.values().toArray(new SpdyStream[streams.size()]); - streams.clear(); - setIdle(false); - } - if (pings != null) { - pingsToCancel = pings.values().toArray(new Ping[pings.size()]); - pings = null; - } - } - - if (streamsToClose != null) { - for (SpdyStream stream : streamsToClose) { - try { - stream.close(streamCode); - } catch (IOException e) { - if (thrown != null) thrown = e; - } - } - } - - if (pingsToCancel != null) { - for (Ping ping : pingsToCancel) { - ping.cancel(); - } - } - - try { - frameReader.close(); - } catch (IOException e) { - thrown = e; - } - try { - frameWriter.close(); - } catch (IOException e) { - if (thrown == null) thrown = e; - } - - if (thrown != null) throw thrown; - } - - /** - * Sends a connection header if the current variant requires it. This should - * be called after {@link Builder#build} for all new connections. - */ - public void sendConnectionHeader() throws IOException { - frameWriter.connectionHeader(); - frameWriter.settings(new Settings()); - } - - /** - * Reads a connection header if the current variant requires it. This should - * be called after {@link Builder#build} for all new connections. - */ - public void readConnectionHeader() throws IOException { - frameReader.readConnectionHeader(); - } - - public static class Builder { - private String hostName; - private InputStream in; - private OutputStream out; - private IncomingStreamHandler handler = IncomingStreamHandler.REFUSE_INCOMING_STREAMS; - private Variant variant = Variant.SPDY3; - private boolean client; - - public Builder(boolean client, Socket socket) throws IOException { - this("", client, socket.getInputStream(), socket.getOutputStream()); - } - - public Builder(boolean client, InputStream in, OutputStream out) { - this("", client, in, out); - } - - /** - * @param client true if this peer initiated the connection; false if - * this peer accepted the connection. - */ - public Builder(String hostName, boolean client, Socket socket) throws IOException { - this(hostName, client, socket.getInputStream(), socket.getOutputStream()); - } - - /** - * @param client true if this peer initiated the connection; false if this - * peer accepted the connection. - */ - public Builder(String hostName, boolean client, InputStream in, OutputStream out) { - this.hostName = hostName; - this.client = client; - this.in = in; - this.out = out; - } - - public Builder handler(IncomingStreamHandler handler) { - this.handler = handler; - return this; - } - - public Builder spdy3() { - this.variant = Variant.SPDY3; - return this; - } - - public Builder http20Draft06() { - this.variant = Variant.HTTP_20_DRAFT_06; - return this; - } - - public SpdyConnection build() { - return new SpdyConnection(this); - } - } - - private class Reader implements Runnable, FrameReader.Handler { - @Override public void run() { - ErrorCode connectionErrorCode = ErrorCode.INTERNAL_ERROR; - ErrorCode streamErrorCode = ErrorCode.INTERNAL_ERROR; - try { - while (frameReader.nextFrame(this)) { - } - connectionErrorCode = ErrorCode.NO_ERROR; - streamErrorCode = ErrorCode.CANCEL; - } catch (IOException e) { - connectionErrorCode = ErrorCode.PROTOCOL_ERROR; - streamErrorCode = ErrorCode.PROTOCOL_ERROR; - } finally { - try { - close(connectionErrorCode, streamErrorCode); - } catch (IOException ignored) { - } - } - } - - @Override public void data(boolean inFinished, int streamId, InputStream in, int length) - throws IOException { - SpdyStream dataStream = getStream(streamId); - if (dataStream == null) { - writeSynResetLater(streamId, ErrorCode.INVALID_STREAM); - Util.skipByReading(in, length); - return; - } - dataStream.receiveData(in, length); - if (inFinished) { - dataStream.receiveFin(); - } - } - - @Override public void headers(boolean outFinished, boolean inFinished, int streamId, - int associatedStreamId, int priority, List nameValueBlock, - HeadersMode headersMode) { - SpdyStream stream; - synchronized (SpdyConnection.this) { - // If we're shutdown, don't bother with this stream. - if (shutdown) return; - - stream = getStream(streamId); - - if (stream == null) { - // The headers claim to be for an existing stream, but we don't have one. - if (headersMode.failIfStreamAbsent()) { - writeSynResetLater(streamId, ErrorCode.INVALID_STREAM); - return; - } - - // If the stream ID is less than the last created ID, assume it's already closed. - if (streamId <= lastGoodStreamId) return; - - // If the stream ID is in the client's namespace, assume it's already closed. - if (streamId % 2 == nextStreamId % 2) return; - - // Create a stream. - final SpdyStream newStream = new SpdyStream(streamId, SpdyConnection.this, outFinished, - inFinished, priority, nameValueBlock, settings); - lastGoodStreamId = streamId; - streams.put(streamId, newStream); - executor.submit(new NamedRunnable("OkHttp Callback %s stream %d", hostName, streamId) { - @Override public void execute() { - try { - handler.receive(newStream); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }); - return; - } - } - - // The headers claim to be for a new stream, but we already have one. - if (headersMode.failIfStreamPresent()) { - stream.closeLater(ErrorCode.PROTOCOL_ERROR); - removeStream(streamId); - return; - } - - // Update an existing stream. - stream.receiveHeaders(nameValueBlock, headersMode); - if (inFinished) stream.receiveFin(); - } - - @Override public void rstStream(int streamId, ErrorCode errorCode) { - SpdyStream rstStream = removeStream(streamId); - if (rstStream != null) { - rstStream.receiveRstStream(errorCode); - } - } - - @Override public void settings(boolean clearPrevious, Settings newSettings) { - SpdyStream[] streamsToNotify = null; - synchronized (SpdyConnection.this) { - if (settings == null || clearPrevious) { - settings = newSettings; - } else { - settings.merge(newSettings); - } - if (!streams.isEmpty()) { - streamsToNotify = streams.values().toArray(new SpdyStream[streams.size()]); - } - } - if (streamsToNotify != null) { - for (SpdyStream stream : streamsToNotify) { - // The synchronization here is ugly. We need to synchronize on 'this' to guard - // reads to 'settings'. We synchronize on 'stream' to guard the state change. - // And we need to acquire the 'stream' lock first, since that may block. - // TODO: this can block the reader thread until a write completes. That's bad! - synchronized (stream) { - synchronized (SpdyConnection.this) { - stream.receiveSettings(settings); - } - } - } - } - } - - @Override public void noop() { - } - - @Override public void ping(boolean reply, int payload1, int payload2) { - if (reply) { - Ping ping = removePing(payload1); - if (ping != null) { - ping.receive(); - } - } else { - // Send a reply to a client ping if this is a server and vice versa. - writePingLater(true, payload1, payload2, null); - } - } - - @Override public void goAway(int lastGoodStreamId, ErrorCode errorCode) { - synchronized (SpdyConnection.this) { - shutdown = true; - - // Fail all streams created after the last good stream ID. - for (Iterator> i = streams.entrySet().iterator(); - i.hasNext(); ) { - Map.Entry entry = i.next(); - int streamId = entry.getKey(); - if (streamId > lastGoodStreamId && entry.getValue().isLocallyInitiated()) { - entry.getValue().receiveRstStream(ErrorCode.REFUSED_STREAM); - i.remove(); - } - } - } - } - - @Override public void windowUpdate(int streamId, int deltaWindowSize, boolean endFlowControl) { - if (streamId == 0) { - // TODO: honor whole-stream flow control - return; - } - - // TODO: honor endFlowControl - SpdyStream stream = getStream(streamId); - if (stream != null) { - stream.receiveWindowUpdate(deltaWindowSize); - } - } - - @Override public void priority(int streamId, int priority) { - // TODO: honor priority. - } - } -} http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c6b171ba/framework/src/com/squareup/okhttp/internal/spdy/SpdyStream.java ---------------------------------------------------------------------- diff --git a/framework/src/com/squareup/okhttp/internal/spdy/SpdyStream.java b/framework/src/com/squareup/okhttp/internal/spdy/SpdyStream.java deleted file mode 100755 index a3ab3a4..0000000 --- a/framework/src/com/squareup/okhttp/internal/spdy/SpdyStream.java +++ /dev/null @@ -1,684 +0,0 @@ -/* - * Copyright (C) 2011 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.spdy; - -import com.squareup.okhttp.internal.Util; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; -import java.io.OutputStream; -import java.net.SocketTimeoutException; -import java.util.ArrayList; -import java.util.List; - -import static com.squareup.okhttp.internal.Util.checkOffsetAndCount; - -/** A logical bidirectional stream. */ -public final class SpdyStream { - - // Internal state is guarded by this. No long-running or potentially - // blocking operations are performed while the lock is held. - - /** - * The number of unacknowledged bytes at which the input stream will send - * the peer a {@code WINDOW_UPDATE} frame. Must be less than this client's - * window size, otherwise the remote peer will stop sending data on this - * stream. (Chrome 25 uses 5 MiB.) - */ - public static final int WINDOW_UPDATE_THRESHOLD = Settings.DEFAULT_INITIAL_WINDOW_SIZE / 2; - - private final int id; - private final SpdyConnection connection; - private final int priority; - private long readTimeoutMillis = 0; - private int writeWindowSize; - - /** Headers sent by the stream initiator. Immutable and non null. */ - private final List requestHeaders; - - /** Headers sent in the stream reply. Null if reply is either not sent or not sent yet. */ - private List responseHeaders; - - private final SpdyDataInputStream in = new SpdyDataInputStream(); - private final SpdyDataOutputStream out = new SpdyDataOutputStream(); - - /** - * The reason why this stream was abnormally closed. If there are multiple - * reasons to abnormally close this stream (such as both peers closing it - * near-simultaneously) then this is the first reason known to this peer. - */ - private ErrorCode errorCode = null; - - SpdyStream(int id, SpdyConnection connection, boolean outFinished, boolean inFinished, - int priority, List requestHeaders, Settings settings) { - if (connection == null) throw new NullPointerException("connection == null"); - if (requestHeaders == null) throw new NullPointerException("requestHeaders == null"); - this.id = id; - this.connection = connection; - this.in.finished = inFinished; - this.out.finished = outFinished; - this.priority = priority; - this.requestHeaders = requestHeaders; - - setSettings(settings); - } - - /** - * Returns true if this stream is open. A stream is open until either: - *

    - *
  • A {@code SYN_RESET} frame abnormally terminates the stream. - *
  • Both input and output streams have transmitted all data and - * headers. - *
- * Note that the input stream may continue to yield data even after a stream - * reports itself as not open. This is because input data is buffered. - */ - public synchronized boolean isOpen() { - if (errorCode != null) { - return false; - } - if ((in.finished || in.closed) && (out.finished || out.closed) && responseHeaders != null) { - return false; - } - return true; - } - - /** Returns true if this stream was created by this peer. */ - public boolean isLocallyInitiated() { - boolean streamIsClient = (id % 2 == 1); - return connection.client == streamIsClient; - } - - public SpdyConnection getConnection() { - return connection; - } - - public List getRequestHeaders() { - return requestHeaders; - } - - /** - * Returns the stream's response headers, blocking if necessary if they - * have not been received yet. - */ - public synchronized List getResponseHeaders() throws IOException { - long remaining = 0; - long start = 0; - if (readTimeoutMillis != 0) { - start = (System.nanoTime() / 1000000); - remaining = readTimeoutMillis; - } - try { - while (responseHeaders == null && errorCode == null) { - if (readTimeoutMillis == 0) { // No timeout configured. - wait(); - } else if (remaining > 0) { - wait(remaining); - remaining = start + readTimeoutMillis - (System.nanoTime() / 1000000); - } else { - throw new SocketTimeoutException("Read response header timeout. readTimeoutMillis: " - + readTimeoutMillis); - } - } - if (responseHeaders != null) { - return responseHeaders; - } - throw new IOException("stream was reset: " + errorCode); - } catch (InterruptedException e) { - InterruptedIOException rethrow = new InterruptedIOException(); - rethrow.initCause(e); - throw rethrow; - } - } - - /** - * Returns the reason why this stream was closed, or null if it closed - * normally or has not yet been closed. - */ - public synchronized ErrorCode getErrorCode() { - return errorCode; - } - - /** - * Sends a reply to an incoming stream. - * - * @param out true to create an output stream that we can use to send data - * to the remote peer. Corresponds to {@code FLAG_FIN}. - */ - public void reply(List responseHeaders, boolean out) throws IOException { - assert (!Thread.holdsLock(SpdyStream.this)); - boolean outFinished = false; - synchronized (this) { - if (responseHeaders == null) { - throw new NullPointerException("responseHeaders == null"); - } - if (isLocallyInitiated()) { - throw new IllegalStateException("cannot reply to a locally initiated stream"); - } - if (this.responseHeaders != null) { - throw new IllegalStateException("reply already sent"); - } - this.responseHeaders = responseHeaders; - if (!out) { - this.out.finished = true; - outFinished = true; - } - } - connection.writeSynReply(id, outFinished, responseHeaders); - } - - /** - * Sets the maximum time to wait on input stream reads before failing with a - * {@code SocketTimeoutException}, or {@code 0} to wait indefinitely. - */ - public void setReadTimeout(long readTimeoutMillis) { - this.readTimeoutMillis = readTimeoutMillis; - } - - public long getReadTimeoutMillis() { - return readTimeoutMillis; - } - - /** Returns an input stream that can be used to read data from the peer. */ - public InputStream getInputStream() { - return in; - } - - /** - * Returns an output stream that can be used to write data to the peer. - * - * @throws IllegalStateException if this stream was initiated by the peer - * and a {@link #reply} has not yet been sent. - */ - public OutputStream getOutputStream() { - synchronized (this) { - if (responseHeaders == null && !isLocallyInitiated()) { - throw new IllegalStateException("reply before requesting the output stream"); - } - } - return out; - } - - /** - * Abnormally terminate this stream. This blocks until the {@code RST_STREAM} - * frame has been transmitted. - */ - public void close(ErrorCode rstStatusCode) throws IOException { - if (!closeInternal(rstStatusCode)) { - return; // Already closed. - } - connection.writeSynReset(id, rstStatusCode); - } - - /** - * Abnormally terminate this stream. This enqueues a {@code RST_STREAM} - * frame and returns immediately. - */ - public void closeLater(ErrorCode errorCode) { - if (!closeInternal(errorCode)) { - return; // Already closed. - } - connection.writeSynResetLater(id, errorCode); - } - - /** Returns true if this stream was closed. */ - private boolean closeInternal(ErrorCode errorCode) { - assert (!Thread.holdsLock(this)); - synchronized (this) { - if (this.errorCode != null) { - return false; - } - if (in.finished && out.finished) { - return false; - } - this.errorCode = errorCode; - notifyAll(); - } - connection.removeStream(id); - return true; - } - - void receiveHeaders(List headers, HeadersMode headersMode) { - assert (!Thread.holdsLock(SpdyStream.this)); - ErrorCode errorCode = null; - boolean open = true; - synchronized (this) { - if (responseHeaders == null) { - if (headersMode.failIfHeadersAbsent()) { - errorCode = ErrorCode.PROTOCOL_ERROR; - } else { - responseHeaders = headers; - open = isOpen(); - notifyAll(); - } - } else { - if (headersMode.failIfHeadersPresent()) { - errorCode = ErrorCode.STREAM_IN_USE; - } else { - List newHeaders = new ArrayList(); - newHeaders.addAll(responseHeaders); - newHeaders.addAll(headers); - this.responseHeaders = newHeaders; - } - } - } - if (errorCode != null) { - closeLater(errorCode); - } else if (!open) { - connection.removeStream(id); - } - } - - void receiveData(InputStream in, int length) throws IOException { - assert (!Thread.holdsLock(SpdyStream.this)); - this.in.receive(in, length); - } - - void receiveFin() { - assert (!Thread.holdsLock(SpdyStream.this)); - boolean open; - synchronized (this) { - this.in.finished = true; - open = isOpen(); - notifyAll(); - } - if (!open) { - connection.removeStream(id); - } - } - - synchronized void receiveRstStream(ErrorCode errorCode) { - if (this.errorCode == null) { - this.errorCode = errorCode; - notifyAll(); - } - } - - private void setSettings(Settings settings) { - // TODO: For HTTP/2.0, also adjust the stream flow control window size - // by the difference between the new value and the old value. - assert (Thread.holdsLock(connection)); // Because 'settings' is guarded by 'connection'. - this.writeWindowSize = settings != null - ? settings.getInitialWindowSize(Settings.DEFAULT_INITIAL_WINDOW_SIZE) - : Settings.DEFAULT_INITIAL_WINDOW_SIZE; - } - - void receiveSettings(Settings settings) { - assert (Thread.holdsLock(this)); - setSettings(settings); - notifyAll(); - } - - synchronized void receiveWindowUpdate(int deltaWindowSize) { - out.unacknowledgedBytes -= deltaWindowSize; - notifyAll(); - } - - int getPriority() { - return priority; - } - - /** - * An input stream that reads the incoming data frames of a stream. Although - * this class uses synchronization to safely receive incoming data frames, - * it is not intended for use by multiple readers. - */ - private final class SpdyDataInputStream extends InputStream { - // Store incoming data bytes in a circular buffer. When the buffer is - // empty, pos == -1. Otherwise pos is the first byte to read and limit - // is the first byte to write. - // - // { - - - X X X X - - - } - // ^ ^ - // pos limit - // - // { X X X - - - - X X X } - // ^ ^ - // limit pos - - private final byte[] buffer = new byte[Settings.DEFAULT_INITIAL_WINDOW_SIZE]; - - /** the next byte to be read, or -1 if the buffer is empty. Never buffer.length */ - private int pos = -1; - - /** the last byte to be read. Never buffer.length */ - private int limit; - - /** True if the caller has closed this stream. */ - private boolean closed; - - /** - * True if either side has cleanly shut down this stream. We will - * receive no more bytes beyond those already in the buffer. - */ - private boolean finished; - - /** - * The total number of bytes consumed by the application (with {@link - * #read}), but not yet acknowledged by sending a {@code WINDOW_UPDATE} - * frame. - */ - private int unacknowledgedBytes = 0; - - @Override public int available() throws IOException { - synchronized (SpdyStream.this) { - checkNotClosed(); - if (pos == -1) { - return 0; - } else if (limit > pos) { - return limit - pos; - } else { - return limit + (buffer.length - pos); - } - } - } - - @Override public int read() throws IOException { - return Util.readSingleByte(this); - } - - @Override public int read(byte[] b, int offset, int count) throws IOException { - synchronized (SpdyStream.this) { - checkOffsetAndCount(b.length, offset, count); - waitUntilReadable(); - checkNotClosed(); - - if (pos == -1) { - return -1; - } - - int copied = 0; - - // drain from [pos..buffer.length) - if (limit <= pos) { - int bytesToCopy = Math.min(count, buffer.length - pos); - System.arraycopy(buffer, pos, b, offset, bytesToCopy); - pos += bytesToCopy; - copied += bytesToCopy; - if (pos == buffer.length) { - pos = 0; - } - } - - // drain from [pos..limit) - if (copied < count) { - int bytesToCopy = Math.min(limit - pos, count - copied); - System.arraycopy(buffer, pos, b, offset + copied, bytesToCopy); - pos += bytesToCopy; - copied += bytesToCopy; - } - - // Flow control: notify the peer that we're ready for more data! - unacknowledgedBytes += copied; - if (unacknowledgedBytes >= WINDOW_UPDATE_THRESHOLD) { - connection.writeWindowUpdateLater(id, unacknowledgedBytes); - unacknowledgedBytes = 0; - } - - if (pos == limit) { - pos = -1; - limit = 0; - } - - return copied; - } - } - - /** - * Returns once the input stream is either readable or finished. Throws - * a {@link SocketTimeoutException} if the read timeout elapses before - * that happens. - */ - private void waitUntilReadable() throws IOException { - long start = 0; - long remaining = 0; - if (readTimeoutMillis != 0) { - start = (System.nanoTime() / 1000000); - remaining = readTimeoutMillis; - } - try { - while (pos == -1 && !finished && !closed && errorCode == null) { - if (readTimeoutMillis == 0) { - SpdyStream.this.wait(); - } else if (remaining > 0) { - SpdyStream.this.wait(remaining); - remaining = start + readTimeoutMillis - (System.nanoTime() / 1000000); - } else { - throw new SocketTimeoutException(); - } - } - } catch (InterruptedException e) { - throw new InterruptedIOException(); - } - } - - void receive(InputStream in, int byteCount) throws IOException { - assert (!Thread.holdsLock(SpdyStream.this)); - - if (byteCount == 0) { - return; - } - - int pos; - int limit; - int firstNewByte; - boolean finished; - boolean flowControlError; - synchronized (SpdyStream.this) { - finished = this.finished; - pos = this.pos; - firstNewByte = this.limit; - limit = this.limit; - flowControlError = byteCount > buffer.length - available(); - } - - // If the peer sends more data than we can handle, discard it and close the connection. - if (flowControlError) { - Util.skipByReading(in, byteCount); - closeLater(ErrorCode.FLOW_CONTROL_ERROR); - return; - } - - // Discard data received after the stream is finished. It's probably a benign race. - if (finished) { - Util.skipByReading(in, byteCount); - return; - } - - // Fill the buffer without holding any locks. First fill [limit..buffer.length) if that - // won't overwrite unread data. Then fill [limit..pos). We can't hold a lock, otherwise - // writes will be blocked until reads complete. - if (pos < limit) { - int firstCopyCount = Math.min(byteCount, buffer.length - limit); - Util.readFully(in, buffer, limit, firstCopyCount); - limit += firstCopyCount; - byteCount -= firstCopyCount; - if (limit == buffer.length) { - limit = 0; - } - } - if (byteCount > 0) { - Util.readFully(in, buffer, limit, byteCount); - limit += byteCount; - } - - synchronized (SpdyStream.this) { - // Update the new limit, and mark the position as readable if necessary. - this.limit = limit; - if (this.pos == -1) { - this.pos = firstNewByte; - SpdyStream.this.notifyAll(); - } - } - } - - @Override public void close() throws IOException { - synchronized (SpdyStream.this) { - closed = true; - SpdyStream.this.notifyAll(); - } - cancelStreamIfNecessary(); - } - - private void checkNotClosed() throws IOException { - if (closed) { - throw new IOException("stream closed"); - } - if (errorCode != null) { - throw new IOException("stream was reset: " + errorCode); - } - } - } - - private void cancelStreamIfNecessary() throws IOException { - assert (!Thread.holdsLock(SpdyStream.this)); - boolean open; - boolean cancel; - synchronized (this) { - cancel = !in.finished && in.closed && (out.finished || out.closed); - open = isOpen(); - } - if (cancel) { - // RST this stream to prevent additional data from being sent. This - // is safe because the input stream is closed (we won't use any - // further bytes) and the output stream is either finished or closed - // (so RSTing both streams doesn't cause harm). - SpdyStream.this.close(ErrorCode.CANCEL); - } else if (!open) { - connection.removeStream(id); - } - } - - /** - * An output stream that writes outgoing data frames of a stream. This class - * is not thread safe. - */ - private final class SpdyDataOutputStream extends OutputStream { - private final byte[] buffer = new byte[8192]; - private int pos = 0; - - /** True if the caller has closed this stream. */ - private boolean closed; - - /** - * True if either side has cleanly shut down this stream. We shall send - * no more bytes. - */ - private boolean finished; - - /** - * The total number of bytes written out to the peer, but not yet - * acknowledged with an incoming {@code WINDOW_UPDATE} frame. Writes - * block if they cause this to exceed the {@code WINDOW_SIZE}. - */ - private int unacknowledgedBytes = 0; - - @Override public void write(int b) throws IOException { - Util.writeSingleByte(this, b); - } - - @Override public void write(byte[] bytes, int offset, int count) throws IOException { - assert (!Thread.holdsLock(SpdyStream.this)); - checkOffsetAndCount(bytes.length, offset, count); - checkNotClosed(); - - while (count > 0) { - if (pos == buffer.length) { - writeFrame(false); - } - int bytesToCopy = Math.min(count, buffer.length - pos); - System.arraycopy(bytes, offset, buffer, pos, bytesToCopy); - pos += bytesToCopy; - offset += bytesToCopy; - count -= bytesToCopy; - } - } - - @Override public void flush() throws IOException { - assert (!Thread.holdsLock(SpdyStream.this)); - checkNotClosed(); - if (pos > 0) { - writeFrame(false); - connection.flush(); - } - } - - @Override public void close() throws IOException { - assert (!Thread.holdsLock(SpdyStream.this)); - synchronized (SpdyStream.this) { - if (closed) { - return; - } - closed = true; - } - if (!out.finished) { - writeFrame(true); - } - connection.flush(); - cancelStreamIfNecessary(); - } - - private void writeFrame(boolean outFinished) throws IOException { - assert (!Thread.holdsLock(SpdyStream.this)); - - int length = pos; - synchronized (SpdyStream.this) { - waitUntilWritable(length, outFinished); - unacknowledgedBytes += length; - } - connection.writeData(id, outFinished, buffer, 0, pos); - pos = 0; - } - - /** - * Returns once the peer is ready to receive {@code count} bytes. - * - * @throws IOException if the stream was finished or closed, or the - * thread was interrupted. - */ - private void waitUntilWritable(int count, boolean last) throws IOException { - try { - while (unacknowledgedBytes + count >= writeWindowSize) { - SpdyStream.this.wait(); // Wait until we receive a WINDOW_UPDATE. - - // The stream may have been closed or reset while we were waiting! - if (!last && closed) { - throw new IOException("stream closed"); - } else if (finished) { - throw new IOException("stream finished"); - } else if (errorCode != null) { - throw new IOException("stream was reset: " + errorCode); - } - } - } catch (InterruptedException e) { - throw new InterruptedIOException(); - } - } - - private void checkNotClosed() throws IOException { - synchronized (SpdyStream.this) { - if (closed) { - throw new IOException("stream closed"); - } else if (finished) { - throw new IOException("stream finished"); - } else if (errorCode != null) { - throw new IOException("stream was reset: " + errorCode); - } - } - } - } -} http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c6b171ba/framework/src/com/squareup/okhttp/internal/spdy/Variant.java ---------------------------------------------------------------------- diff --git a/framework/src/com/squareup/okhttp/internal/spdy/Variant.java b/framework/src/com/squareup/okhttp/internal/spdy/Variant.java deleted file mode 100755 index 8f48bcd..0000000 --- a/framework/src/com/squareup/okhttp/internal/spdy/Variant.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 Square, Inc. - * - * 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.spdy; - -import java.io.InputStream; -import java.io.OutputStream; - -/** A version and dialect of the framed socket protocol. */ -interface Variant { - Variant SPDY3 = new Spdy3(); - Variant HTTP_20_DRAFT_06 = new Http20Draft06(); - - /** - * @param client true if this is the HTTP client's reader, reading frames from - * a peer SPDY or HTTP/2 server. - */ - FrameReader newReader(InputStream in, boolean client); - - /** - * @param client true if this is the HTTP client's writer, writing frames to a - * peer SPDY or HTTP/2 server. - */ - FrameWriter newWriter(OutputStream out, boolean client); -} http://git-wip-us.apache.org/repos/asf/cordova-android/blob/c6b171ba/framework/src/com/squareup/okhttp/internal/tls/DistinguishedNameParser.java ---------------------------------------------------------------------- diff --git a/framework/src/com/squareup/okhttp/internal/tls/DistinguishedNameParser.java b/framework/src/com/squareup/okhttp/internal/tls/DistinguishedNameParser.java deleted file mode 100755 index e0aef14..0000000 --- a/framework/src/com/squareup/okhttp/internal/tls/DistinguishedNameParser.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.tls; - -import javax.security.auth.x500.X500Principal; - -/** - * A distinguished name (DN) parser. This parser only supports extracting a - * string value from a DN. It doesn't support values in the hex-string style. - */ -final class DistinguishedNameParser { - private final String dn; - private final int length; - private int pos; - private int beg; - private int end; - - /** Temporary variable to store positions of the currently parsed item. */ - private int cur; - - /** Distinguished name characters. */ - private char[] chars; - - public DistinguishedNameParser(X500Principal principal) { - // RFC2253 is used to ensure we get attributes in the reverse - // order of the underlying ASN.1 encoding, so that the most - // significant values of repeated attributes occur first. - this.dn = principal.getName(X500Principal.RFC2253); - this.length = this.dn.length(); - } - - // gets next attribute type: (ALPHA 1*keychar) / oid - private String nextAT() { - // skip preceding space chars, they can present after - // comma or semicolon (compatibility with RFC 1779) - for (; pos < length && chars[pos] == ' '; pos++) { - } - if (pos == length) { - return null; // reached the end of DN - } - - // mark the beginning of attribute type - beg = pos; - - // attribute type chars - pos++; - for (; pos < length && chars[pos] != '=' && chars[pos] != ' '; pos++) { - // we don't follow exact BNF syntax here: - // accept any char except space and '=' - } - if (pos >= length) { - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - - // mark the end of attribute type - end = pos; - - // skip trailing space chars between attribute type and '=' - // (compatibility with RFC 1779) - if (chars[pos] == ' ') { - for (; pos < length && chars[pos] != '=' && chars[pos] == ' '; pos++) { - } - - if (chars[pos] != '=' || pos == length) { - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - } - - pos++; //skip '=' char - - // skip space chars between '=' and attribute value - // (compatibility with RFC 1779) - for (; pos < length && chars[pos] == ' '; pos++) { - } - - // in case of oid attribute type skip its prefix: "oid." or "OID." - // (compatibility with RFC 1779) - if ((end - beg > 4) && (chars[beg + 3] == '.') - && (chars[beg] == 'O' || chars[beg] == 'o') - && (chars[beg + 1] == 'I' || chars[beg + 1] == 'i') - && (chars[beg + 2] == 'D' || chars[beg + 2] == 'd')) { - beg += 4; - } - - return new String(chars, beg, end - beg); - } - - // gets quoted attribute value: QUOTATION *( quotechar / pair ) QUOTATION - private String quotedAV() { - pos++; - beg = pos; - end = beg; - while (true) { - - if (pos == length) { - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - - if (chars[pos] == '"') { - // enclosing quotation was found - pos++; - break; - } else if (chars[pos] == '\\') { - chars[end] = getEscaped(); - } else { - // shift char: required for string with escaped chars - chars[end] = chars[pos]; - } - pos++; - end++; - } - - // skip trailing space chars before comma or semicolon. - // (compatibility with RFC 1779) - for (; pos < length && chars[pos] == ' '; pos++) { - } - - return new String(chars, beg, end - beg); - } - - // gets hex string attribute value: "#" hexstring - private String hexAV() { - if (pos + 4 >= length) { - // encoded byte array must be not less then 4 c - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - - beg = pos; // store '#' position - pos++; - while (true) { - - // check for end of attribute value - // looks for space and component separators - if (pos == length || chars[pos] == '+' || chars[pos] == ',' - || chars[pos] == ';') { - end = pos; - break; - } - - if (chars[pos] == ' ') { - end = pos; - pos++; - // skip trailing space chars before comma or semicolon. - // (compatibility with RFC 1779) - for (; pos < length && chars[pos] == ' '; pos++) { - } - break; - } else if (chars[pos] >= 'A' && chars[pos] <= 'F') { - chars[pos] += 32; //to low case - } - - pos++; - } - - // verify length of hex string - // encoded byte array must be not less then 4 and must be even number - int hexLen = end - beg; // skip first '#' char - if (hexLen < 5 || (hexLen & 1) == 0) { - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - - // get byte encoding from string representation - byte[] encoded = new byte[hexLen / 2]; - for (int i = 0, p = beg + 1; i < encoded.length; p += 2, i++) { - encoded[i] = (byte) getByte(p); - } - - return new String(chars, beg, hexLen); - } - - // gets string attribute value: *( stringchar / pair ) - private String escapedAV() { - beg = pos; - end = pos; - while (true) { - if (pos >= length) { - // the end of DN has been found - return new String(chars, beg, end - beg); - } - - switch (chars[pos]) { - case '+': - case ',': - case ';': - // separator char has been found - return new String(chars, beg, end - beg); - case '\\': - // escaped char - chars[end++] = getEscaped(); - pos++; - break; - case ' ': - // need to figure out whether space defines - // the end of attribute value or not - cur = end; - - pos++; - chars[end++] = ' '; - - for (; pos < length && chars[pos] == ' '; pos++) { - chars[end++] = ' '; - } - if (pos == length || chars[pos] == ',' || chars[pos] == '+' - || chars[pos] == ';') { - // separator char or the end of DN has been found - return new String(chars, beg, cur - beg); - } - break; - default: - chars[end++] = chars[pos]; - pos++; - } - } - } - - // returns escaped char - private char getEscaped() { - pos++; - if (pos == length) { - throw new IllegalStateException("Unexpected end of DN: " + dn); - } - - switch (chars[pos]) { - case '"': - case '\\': - case ',': - case '=': - case '+': - case '<': - case '>': - case '#': - case ';': - case ' ': - case '*': - case '%': - case '_': - //FIXME: escaping is allowed only for leading or trailing space char - return chars[pos]; - default: - // RFC doesn't explicitly say that escaped hex pair is - // interpreted as UTF-8 char. It only contains an example of such DN. - return getUTF8(); - } - } - - // decodes UTF-8 char - // see http://www.unicode.org for UTF-8 bit distribution table - private char getUTF8() { - int res = getByte(pos); - pos++; //FIXME tmp - - if (res < 128) { // one byte: 0-7F - return (char) res; - } else if (res >= 192 && res <= 247) { - - int count; - if (res <= 223) { // two bytes: C0-DF - count = 1; - res = res & 0x1F; - } else if (res <= 239) { // three bytes: E0-EF - count = 2; - res = res & 0x0F; - } else { // four bytes: F0-F7 - count = 3; - res = res & 0x07; - } - - int b; - for (int i = 0; i < count; i++) { - pos++; - if (pos == length || chars[pos] != '\\') { - return 0x3F; //FIXME failed to decode UTF-8 char - return '?' - } - pos++; - - b = getByte(pos); - pos++; //FIXME tmp - if ((b & 0xC0) != 0x80) { - return 0x3F; //FIXME failed to decode UTF-8 char - return '?' - } - - res = (res << 6) + (b & 0x3F); - } - return (char) res; - } else { - return 0x3F; //FIXME failed to decode UTF-8 char - return '?' - } - } - - // Returns byte representation of a char pair - // The char pair is composed of DN char in - // specified 'position' and the next char - // According to BNF syntax: - // hexchar = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" - // / "a" / "b" / "c" / "d" / "e" / "f" - private int getByte(int position) { - if (position + 1 >= length) { - throw new IllegalStateException("Malformed DN: " + dn); - } - - int b1, b2; - - b1 = chars[position]; - if (b1 >= '0' && b1 <= '9') { - b1 = b1 - '0'; - } else if (b1 >= 'a' && b1 <= 'f') { - b1 = b1 - 87; // 87 = 'a' - 10 - } else if (b1 >= 'A' && b1 <= 'F') { - b1 = b1 - 55; // 55 = 'A' - 10 - } else { - throw new IllegalStateException("Malformed DN: " + dn); - } - - b2 = chars[position + 1]; - if (b2 >= '0' && b2 <= '9') { - b2 = b2 - '0'; - } else if (b2 >= 'a' && b2 <= 'f') { - b2 = b2 - 87; // 87 = 'a' - 10 - } else if (b2 >= 'A' && b2 <= 'F') { - b2 = b2 - 55; // 55 = 'A' - 10 - } else { - throw new IllegalStateException("Malformed DN: " + dn); - } - - return (b1 << 4) + b2; - } - - /** - * Parses the DN and returns the most significant attribute value - * for an attribute type, or null if none found. - * - * @param attributeType attribute type to look for (e.g. "ca") - */ - public String findMostSpecific(String attributeType) { - // Initialize internal state. - pos = 0; - beg = 0; - end = 0; - cur = 0; - chars = dn.toCharArray(); - - String attType = nextAT(); - if (attType == null) { - return null; - } - while (true) { - String attValue = ""; - - if (pos == length) { - return null; - } - - switch (chars[pos]) { - case '"': - attValue = quotedAV(); - break; - case '#': - attValue = hexAV(); - break; - case '+': - case ',': - case ';': // compatibility with RFC 1779: semicolon can separate RDNs - //empty attribute value - break; - default: - attValue = escapedAV(); - } - - // Values are ordered from most specific to least specific - // due to the RFC2253 formatting. So take the first match - // we see. - if (attributeType.equalsIgnoreCase(attType)) { - return attValue; - } - - if (pos >= length) { - return null; - } - - if (chars[pos] == ',' || chars[pos] == ';') { - } else if (chars[pos] != '+') { - throw new IllegalStateException("Malformed DN: " + dn); - } - - pos++; - attType = nextAT(); - if (attType == null) { - throw new IllegalStateException("Malformed DN: " + dn); - } - } - } -} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org For additional commands, e-mail: commits-help@cordova.apache.org