Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Unified Diff: components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridge.java

Issue 517233002: DevTools socket tunnel. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@glue
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridge.java
diff --git a/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridge.java b/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridge.java
new file mode 100644
index 0000000000000000000000000000000000000000..c42909f0ae8ea9dd3bb3ff0cc0a0dfeb7bf2f21c
--- /dev/null
+++ b/components/devtools_bridge/test/android/javatests/src/org/chromium/components/devtools_bridge/LocalTunnelBridge.java
@@ -0,0 +1,190 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.devtools_bridge;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * It allows testing DevTools socket tunneling on a single device.
+ *
+ * SocketTunnelClient opens LocalServerSocket named |socketToExpose| and
+ * tunnels all incoming connections to |socketToReplicate| using
+ * SocketTunnelServer and DataPipe between them. All data passes through
+ * WebRTC data channel but doens't leave the device.
+ */
+public class LocalTunnelBridge {
+ private static final String TAG = "LocalTunnelBridge";
+
+ private final DataPipe mPipe;
+ private final SocketTunnelServer mServer;
+ private final SocketTunnelClient mClient;
+ private boolean mLogPackets = false;
+
+ private final CountDownLatch mServerDataChannelOpenedFlag = new CountDownLatch(1);
+ private final CountDownLatch mServerDataChannelClosedFlag = new CountDownLatch(1);
+
+ public LocalTunnelBridge(String socketToReplicate, String socketToExpose) throws IOException {
+ mPipe = new DataPipe();
+
+ mServer = new SocketTunnelServer(socketToReplicate) {
+ @Override
+ protected void onProtocolError(ProtocolError e) {
+ throw new RuntimeException("Protocol error on server", e);
+ }
+
+ @Override
+ protected void sendToDataChannel(ByteBuffer packet) {
+ if (mLogPackets)
+ Log.d(TAG, "Sending " + stringifyServerPacket(packet));
+ super.sendToDataChannel(packet);
+ }
+
+ @Override
+ protected void onReceivedDataPacket(int connectionId, byte[] data)
+ throws ProtocolError {
+ if (mLogPackets) {
+ Log.d(TAG, "Received client data packet with " +
+ Integer.toString(data.length) + " bytes");
+ }
+ super.onReceivedDataPacket(connectionId, data);
+ }
+
+ @Override
+ protected void onReceivedControlPacket(int connectionId, byte opCode)
+ throws ProtocolError {
+ if (mLogPackets) {
+ Log.d(TAG, "Received client control packet");
+ }
+ super.onReceivedControlPacket(connectionId, opCode);
+ }
+
+ @Override
+ protected void onSocketException(IOException e, int connectionId) {
+ Log.d(TAG, "Server socket exception on " + e +
+ " (connection " + Integer.toString(connectionId) + ")");
+ super.onSocketException(e, connectionId);
+ }
+
+ protected void onDataChannelOpened() {
+ Log.d(TAG, "Server data channel opened");
+ super.onDataChannelOpened();
+ mServerDataChannelOpenedFlag.countDown();
+ }
+
+ protected void onDataChannelClosed() {
+ Log.d(TAG, "Client data channel opened");
+ super.onDataChannelClosed();
+ mServerDataChannelClosedFlag.countDown();
+ }
+ };
+
+ mServer.bind(mPipe.dataChannel(0));
+
+ mClient = new SocketTunnelClient(socketToExpose) {
+ @Override
+ protected void onProtocolError(ProtocolError e) {
+ throw new RuntimeException("Protocol error on client" + e);
+ }
+
+ @Override
+ protected void onReceivedDataPacket(int connectionId, byte[] data)
+ throws ProtocolError {
+ if (mLogPackets) {
+ Log.d(TAG, "Received server data packet with "
+ + Integer.toString(data.length) + " bytes");
+ }
+ super.onReceivedDataPacket(connectionId, data);
+ }
+
+ @Override
+ protected void onReceivedControlPacket(int connectionId, byte opCode)
+ throws ProtocolError {
+ if (mLogPackets) {
+ Log.d(TAG, "Received server control packet");
+ }
+ super.onReceivedControlPacket(connectionId, opCode);
+ }
+
+ @Override
+ protected void sendToDataChannel(ByteBuffer packet) {
+ if (mLogPackets) {
+ Log.d(TAG, "Sending " + stringifyClientPacket(packet));
+ }
+ super.sendToDataChannel(packet);
+ }
+ };
+ mClient.bind(mPipe.dataChannel(1));
+ }
+
+ public void start() {
+ mPipe.connect();
+ }
+
+ public void stop() {
+ mPipe.disconnect();
+ }
+
+ public void dispose() {
+ mClient.unbind();
+ mServer.unbind();
+ mPipe.dispose();
+ }
+
+ public void waitAllConnectionsClosed() throws InterruptedException {
+ while (mServer.hasConnections() || mClient.hasConnections()) {
+ Thread.sleep(50);
+ }
+ }
+
+ private String stringifyDataPacket(String type, PacketDecoder decoder) {
+ if (!decoder.isDataPacket()) {
+ throw new RuntimeException("Invalid packet");
+ }
+ return type + "_DATA:" + Integer.toString(decoder.data().length);
+ }
+
+ private String stringifyClientPacket(ByteBuffer packet) {
+ PacketDecoder decoder = decode(packet);
+ if (!decoder.isControlPacket())
+ return stringifyDataPacket("CLIENT", decoder);
+ switch (decoder.opCode()) {
+ case SocketTunnelBase.CLIENT_OPEN:
+ return "CLIENT_OPEN " + Integer.valueOf(decoder.connectionId());
+ case SocketTunnelBase.CLIENT_CLOSE:
+ return "CLIENT_CLOSE " + Integer.valueOf(decoder.connectionId());
+ default:
+ throw new RuntimeException("Invalid packet");
+ }
+ }
+
+ private String stringifyServerPacket(ByteBuffer packet) {
+ PacketDecoder decoder = decode(packet);
+ if (!decoder.isControlPacket())
+ return stringifyDataPacket("SERVER", decoder);
+ switch (decoder.opCode()) {
+ case SocketTunnelBase.SERVER_OPEN_ACK:
+ return "SERVER_OPEN_ACK " + Integer.valueOf(decoder.connectionId());
+ case SocketTunnelBase.SERVER_CLOSE:
+ return "SERVER_CLOSE " + Integer.valueOf(decoder.connectionId());
+ default:
+ throw new RuntimeException("Invalid packet");
+ }
+ }
+
+ private PacketDecoder decode(ByteBuffer packet) {
+ int position = packet.position();
+ packet.position(0);
+ if (position == 0) {
+ throw new RuntimeException("Empty packet");
+ }
+ PacketDecoder decoder = PacketDecoder.decode(packet);
+ packet.position(position);
+ return decoder;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698