diff --git a/DEVELOP.md b/DEVELOP.md index 77ae5ccd..4d426558 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -133,9 +133,7 @@ The client is an _Android_ project located in [`app/`](app/). The [`VpnService`] is implemented by [`GnirehtetService`]. -We control the application through broadcasts received by -[`GnirehtetControlReceiver`] (we cannot send intents to `GnirehtetService` -directly, read comments in [`GnirehtetControlReceiver`]). +We control the application through intents to [`GnirehtetActivity`]. Some configuration options may be passed as extra parameters, converted to a [`VpnConfiguration`] instance. Currently, the user can configure the DNS servers @@ -158,7 +156,7 @@ of [`IPPacketOutputStream`]. [`VpnService`]: https://developer.android.com/reference/android/net/VpnService.html [`GnirehtetService`]: app/src/main/java/com/genymobile/gnirehtet/GnirehtetService.java -[`GnirehtetControlReceiver`]: app/src/main/java/com/genymobile/gnirehtet/GnirehtetControlReceiver.java +[`GnirehtetActivity`]: app/src/main/java/com/genymobile/gnirehtet/GnirehtetActivity.java [`VpnConfiguration`]: app/src/main/java/com/genymobile/gnirehtet/VpnConfiguration.java [`startActivityForResult`]: https://developer.android.com/reference/android/app/Activity.html#startActivityForResult%28android.content.Intent,%20int%29 [`Activity`]: https://developer.android.com/reference/android/app/Activity.html diff --git a/README.md b/README.md index ba08dce6..d4ec165d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Gnirehtet (v2.3) +# Gnirehtet (v2.5) This project provides **reverse tethering** over `adb` for Android: it allows devices to use the internet connection of the computer they are plugged @@ -64,24 +64,36 @@ Make sure you [enabled adb debugging][enable-adb] on your device(s). [platform-tools-windows]: https://dl.google.com/android/repository/platform-tools-latest-windows.zip -## Download +## Get the app + +### Homebrew + +If you use [Homebrew](https://brew.sh/), getting up and running is very quick. +To install the Rust version: + +``` +brew install gnirehtet +``` + +### Download Download the [latest release][latest] in the flavor you want. [latest]: https://github.com/Genymobile/gnirehtet/releases/latest -### Rust - - **Linux:** [`gnirehtet-rust-linux64-v2.3.zip`][direct-rust-linux64] - (SHA-256: _561d77e94d65ecf2d919053e5da6109b8cceb73bffedea71cd4e51304ccaa3d3_) - - **Windows:** [`gnirehtet-rust-win64-v2.3.zip`][direct-rust-win64] - (SHA-256: _4c4d961f069a663d6b826f24a8795d1752f3e316f121d2bfc296a4cd32c8d4ca_) +#### Rust + + - **Linux:** [`gnirehtet-rust-linux64-v2.5.zip`][direct-rust-linux64] + (SHA-256: _2b1ce04540e8de5df5ddbebb64bb01e27c13d556b3a04a8563dcce3786765705_) + - **Windows:** [`gnirehtet-rust-win64-v2.5.zip`][direct-rust-win64] + (SHA-256: _9f6d7700368f45d2fa43923324660eca9f879e837e10fc45d8d975273eae4755_) - **MacOS:** [`gnirehtet-rust-macos64-v2.2.1.zip`][direct-rust-macos64] - _(previous release)_ + _(old release)_ (SHA-256: _902103e6497f995e1e9b92421be212559950cca4a8b557e1f0403769aee06fc8_) -[direct-rust-linux64]: https://github.com/Genymobile/gnirehtet/releases/download/v2.3/gnirehtet-rust-linux64-v2.3.zip -[direct-rust-win64]: https://github.com/Genymobile/gnirehtet/releases/download/v2.3/gnirehtet-rust-win64-v2.3.zip +[direct-rust-linux64]: https://github.com/Genymobile/gnirehtet/releases/download/v2.5/gnirehtet-rust-linux64-v2.5.zip +[direct-rust-win64]: https://github.com/Genymobile/gnirehtet/releases/download/v2.5/gnirehtet-rust-win64-v2.5.zip [direct-rust-macos64]: https://github.com/Genymobile/gnirehtet/releases/download/v2.2.1/gnirehtet-rust-macos64-v2.2.1.zip Then extract it. @@ -96,12 +108,12 @@ The Windows archive contains: - `gnirehtet-run.cmd` -### Java +#### Java - - **All platforms:** [`gnirehtet-java-v2.3.zip`][direct-java] - (SHA-256: _93d1d46ee566376596f033832626dd5e89e76c91f2c46d2383735937b7d3b8b0_) + - **All platforms:** [`gnirehtet-java-v2.5.zip`][direct-java] + (SHA-256: _c65fc1a35e6b169ab6aa45e695c043e933f6fd650363aea7c2add0ecb0db27ca_) -[direct-java]: https://github.com/Genymobile/gnirehtet/releases/download/v2.3/gnirehtet-java-v2.3.zip +[direct-java]: https://github.com/Genymobile/gnirehtet/releases/download/v2.5/gnirehtet-java-v2.5.zip Then extract it. The archive contains: - `gnirehtet.apk` @@ -182,7 +194,7 @@ lower-level commands. You can call them manually instead. To start the relay server: - java -jar gnirehtet.jar relay + ./gnirehtet relay To install the apk: @@ -191,13 +203,28 @@ To install the apk: To start a client: adb reverse localabstract:gnirehtet tcp:31416 - adb shell am broadcast -a com.genymobile.gnirehtet.START \ - -n com.genymobile.gnirehtet/.GnirehtetControlReceiver + adb shell am start -a com.genymobile.gnirehtet.START \ + -n com.genymobile.gnirehtet/.GnirehtetActivity To stop a client: - adb shell am broadcast -a com.genymobile.gnirehtet.STOP \ - -n com.genymobile.gnirehtet/.GnirehtetControlReceiver + adb shell am start -a com.genymobile.gnirehtet.STOP \ + -n com.genymobile.gnirehtet/.GnirehtetActivity + + +## Environment variables + +`ADB` defines a custom path to the `adb` executable: + +```bash +ADB=/path/to/my/adb ./gnirehtet run +``` + +`GNIREHTET_APK` defines a custom path to `gnirehtet.apk`: + +```bash +GNIREHTET_APK=/usr/share/gnirehtet/gnirehtet.apk ./gnirehtet run +``` ## Why _gnirehtet_? diff --git a/app/build.gradle b/app/build.gradle index 0910e052..1f02e889 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,9 +8,9 @@ android { archivesBaseName = "gnirehtet" // change apk name applicationId "com.genymobile.gnirehtet" minSdkVersion 21 - targetSdkVersion 28 - versionCode 6 - versionName "2.3" + targetSdkVersion 29 + versionCode 8 + versionName "2.5" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/app/local.properties b/app/local.properties new file mode 100644 index 00000000..c82f585e --- /dev/null +++ b/app/local.properties @@ -0,0 +1,8 @@ +## This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# Location of the SDK. This is only used by Gradle. +# For customization when using a Version Control System, please read the +# header note. +#Thu Jul 01 13:56:53 MSK 2021 +sdk.dir=C\:\\Users\\barto\\AppData\\Local\\Android\\Sdk diff --git a/app/release/gnirehtet.apk b/app/release/gnirehtet.apk new file mode 100644 index 00000000..fbb6ea06 Binary files /dev/null and b/app/release/gnirehtet.apk differ diff --git a/app/release/output.json b/app/release/output.json new file mode 100644 index 00000000..16680caf --- /dev/null +++ b/app/release/output.json @@ -0,0 +1 @@ +[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":8,"versionName":"2.5","enabled":true,"outputFile":"gnirehtet-release.apk","fullName":"release","baseName":"release"},"path":"gnirehtet-release.apk","properties":{}}] \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c0a59744..c96fe049 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,10 +1,11 @@ + xmlns:tools="http://schemas.android.com/tools" + package="com.genymobile.gnirehtet"> - + + + + + + + + - - + - - \ No newline at end of file diff --git a/app/src/main/java/com/genymobile/gnirehtet/AuthorizationActivity.java b/app/src/main/java/com/genymobile/gnirehtet/AuthorizationActivity.java deleted file mode 100644 index f1153979..00000000 --- a/app/src/main/java/com/genymobile/gnirehtet/AuthorizationActivity.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2017 Genymobile - * - * 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.genymobile.gnirehtet; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; - -public class AuthorizationActivity extends Activity { - - public static final String EXTRA_VPN_INTENT = "com.genymobile.gnirehtet.VPN_INTENT"; - public static final String EXTRA_VPN_CONFIGURATION = "vpnConfiguration"; - - private static final int VPN_REQUEST_CODE = 0; - - private VpnConfiguration config; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Intent intent = getIntent(); - Intent vpnIntent = intent.getParcelableExtra(EXTRA_VPN_INTENT); - config = intent.getParcelableExtra(EXTRA_VPN_CONFIGURATION); - startActivityForResult(vpnIntent, VPN_REQUEST_CODE); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == VPN_REQUEST_CODE && resultCode == RESULT_OK) { - GnirehtetService.start(this, config); - } - finish(); - } -} diff --git a/app/src/main/java/com/genymobile/gnirehtet/Binary.java b/app/src/main/java/com/genymobile/gnirehtet/Binary.java index faec6138..ae0603d9 100644 --- a/app/src/main/java/com/genymobile/gnirehtet/Binary.java +++ b/app/src/main/java/com/genymobile/gnirehtet/Binary.java @@ -19,6 +19,8 @@ @SuppressWarnings("checkstyle:MagicNumber") public final class Binary { + private static final int MAX_STRING_PACKET_SIZE = 20; + private Binary() { // not instantiable } @@ -35,15 +37,20 @@ public static long unsigned(int value) { return value & 0xffffffffL; } - public static String toString(byte[] data, int len) { + public static String buildPacketString(byte[] data, int len) { + int limit = Math.min(MAX_STRING_PACKET_SIZE, len); StringBuilder builder = new StringBuilder(); - for (int i = 0; i < len; ++i) { - if (i % 8 == 0) { - builder.append('\n'); + builder.append('[').append(len).append(" bytes] "); + for (int i = 0; i < limit; ++i) { + if (i != 0) { + String sep = i % 4 == 0 ? " " : " "; + builder.append(sep); } - builder.append(String.format("%02X ", data[i] & 0xff)); + builder.append(String.format("%02X", data[i] & 0xff)); + } + if (limit < len) { + builder.append(" ... +").append(len - limit).append(" bytes"); } return builder.toString(); } - } diff --git a/app/src/main/java/com/genymobile/gnirehtet/Forwarder.java b/app/src/main/java/com/genymobile/gnirehtet/Forwarder.java index 0f50d9d8..61b9a16b 100644 --- a/app/src/main/java/com/genymobile/gnirehtet/Forwarder.java +++ b/app/src/main/java/com/genymobile/gnirehtet/Forwarder.java @@ -37,7 +37,7 @@ public class Forwarder { private static final String TAG = Forwarder.class.getSimpleName(); - private static final int BUFSIZE = 4096; + private static final int BUFSIZE = 0x10000; private static final byte[] DUMMY_ADDRESS = {42, 42, 42, 42}; private static final int DUMMY_PORT = 4242; @@ -129,9 +129,6 @@ private void forwardTunnelToDevice(Tunnel tunnel) throws IOException { break; } if (w > 0) { - if (GnirehtetService.VERBOSE) { - Log.d(TAG, "WRITING " + w + "..." + Binary.toString(buffer, w)); - } // blocking write packetOutputStream.write(buffer, 0, w); } else { diff --git a/app/src/main/java/com/genymobile/gnirehtet/GnirehtetActivity.java b/app/src/main/java/com/genymobile/gnirehtet/GnirehtetActivity.java new file mode 100644 index 00000000..b34885e8 --- /dev/null +++ b/app/src/main/java/com/genymobile/gnirehtet/GnirehtetActivity.java @@ -0,0 +1,97 @@ +package com.genymobile.gnirehtet; + +import android.app.Activity; +import android.content.Intent; +import android.net.VpnService; +import android.os.Bundle; +import android.util.Log; + +/** + * This (invisible) activity receives the {@link #ACTION_GNIREHTET_START START} and + * {@link #ACTION_GNIREHTET_STOP} actions from the command line. + *

+ * Recent versions of Android refuse to directly start a {@link android.app.Service Service} or a + * {@link android.content.BroadcastReceiver BroadcastReceiver}, so actions are always managed by + * this activity. + */ +public class GnirehtetActivity extends Activity { + + private static final String TAG = GnirehtetActivity.class.getSimpleName(); + + public static final String ACTION_GNIREHTET_START = "com.genymobile.gnirehtet.START"; + public static final String ACTION_GNIREHTET_STOP = "com.genymobile.gnirehtet.STOP"; + + public static final String EXTRA_DNS_SERVERS = "dnsServers"; + public static final String EXTRA_ROUTES = "routes"; + + private static final int VPN_REQUEST_CODE = 0; + + private VpnConfiguration requestedConfig; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + handleIntent(getIntent()); + } + + private void handleIntent(Intent intent) { + String action = intent.getAction(); + Log.d(TAG, "Received request " + action); + boolean finish = true; + if (ACTION_GNIREHTET_START.equals(action)) { + VpnConfiguration config = createConfig(intent); + finish = startGnirehtet(config); + } else if (ACTION_GNIREHTET_STOP.equals(action)) { + stopGnirehtet(); + } + + if (finish) { + finish(); + } + } + + private static VpnConfiguration createConfig(Intent intent) { + String[] dnsServers = intent.getStringArrayExtra(EXTRA_DNS_SERVERS); + if (dnsServers == null) { + dnsServers = new String[0]; + } + String[] routes = intent.getStringArrayExtra(EXTRA_ROUTES); + if (routes == null) { + routes = new String[0]; + } + return new VpnConfiguration(Net.toInetAddresses(dnsServers), Net.toCIDRs(routes)); + } + + private boolean startGnirehtet(VpnConfiguration config) { + Intent vpnIntent = VpnService.prepare(this); + if (vpnIntent == null) { + Log.d(TAG, "VPN was already authorized"); + // we got the permission, start the service now + GnirehtetService.start(this, config); + return true; + } + + Log.w(TAG, "VPN requires the authorization from the user, requesting..."); + requestAuthorization(vpnIntent, config); + return false; // do not finish now + } + + private void stopGnirehtet() { + GnirehtetService.stop(this); + } + + private void requestAuthorization(Intent vpnIntent, VpnConfiguration config) { + requestedConfig = config; + startActivityForResult(vpnIntent, VPN_REQUEST_CODE); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == VPN_REQUEST_CODE && resultCode == RESULT_OK) { + GnirehtetService.start(this, requestedConfig); + } + requestedConfig = null; + finish(); + } +} diff --git a/app/src/main/java/com/genymobile/gnirehtet/GnirehtetControlReceiver.java b/app/src/main/java/com/genymobile/gnirehtet/GnirehtetControlReceiver.java index 04379516..23f81b73 100644 --- a/app/src/main/java/com/genymobile/gnirehtet/GnirehtetControlReceiver.java +++ b/app/src/main/java/com/genymobile/gnirehtet/GnirehtetControlReceiver.java @@ -1,92 +1,23 @@ -/* - * Copyright (C) 2017 Genymobile - * - * 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.genymobile.gnirehtet; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.net.VpnService; import android.util.Log; -import static com.genymobile.gnirehtet.AuthorizationActivity.EXTRA_VPN_CONFIGURATION; - -/** - * Receiver to expose {@link #ACTION_GNIREHTET_START START} and {@link #ACTION_GNIREHTET_STOP} - * actions. - *

- * Since {@link GnirehtetService} extends {@link VpnService}, it requires the clients to have the - * system permission {@code android.permission.BIND_VPN_SERVICE}, which {@code shell} have not. As a - * consequence, we cannot expose our own actions intended to be called from {@code shell} directly - * in {@link GnirehtetService}. - *

- * Starting the VPN requires authorization from the user. If the authorization is not granted yet, - * an {@code Intent}, returned by the system, must be sent from an Activity - * (through {@link android.app.Activity#startActivityForResult(Intent, int) - * startActivityForResult()}. However, if the authorization is already granted, it is better to - * avoid starting an {@link android.app.Activity Activity} (which would be useless), since it may - * cause (minor) side effects (like closing any open virtual keyboard). Therefore, this {@link - * GnirehtetControlReceiver} starts an {@link android.app.Activity Activity} only when necessary. - *

- * Stopping the VPN just consists in delegating the request to {@link GnirehtetService} (which is - * accessible from here). - */ public class GnirehtetControlReceiver extends BroadcastReceiver { - - public static final String ACTION_GNIREHTET_START = "com.genymobile.gnirehtet.START"; - public static final String ACTION_GNIREHTET_STOP = "com.genymobile.gnirehtet.STOP"; - - public static final String EXTRA_DNS_SERVERS = "dnsServers"; - public static final String EXTRA_ROUTES = "routes"; - private static final String TAG = GnirehtetControlReceiver.class.getSimpleName(); - @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.d(TAG, "Received request " + action); - if (ACTION_GNIREHTET_START.equals(action)) { - VpnConfiguration config = createConfig(intent); - startGnirehtet(context, config); - } else if (ACTION_GNIREHTET_STOP.equals(action)) { - stopGnirehtet(context); - } - } - - private static VpnConfiguration createConfig(Intent intent) { - String[] dnsServers = intent.getStringArrayExtra(EXTRA_DNS_SERVERS); - if (dnsServers == null) { - dnsServers = new String[0]; - } - String[] routes = intent.getStringArrayExtra(EXTRA_ROUTES); - if (routes == null) { - routes = new String[0]; - } - return new VpnConfiguration(Net.toInetAddresses(dnsServers), Net.toCIDRs(routes)); - } - - private void startGnirehtet(Context context, VpnConfiguration config) { - Intent vpnIntent = VpnService.prepare(context); - if (vpnIntent == null) { - Log.d(TAG, "VPN was already authorized"); - // we got the permission, start the service now - GnirehtetService.start(context, config); - } else { - Log.w(TAG, "VPN requires the authorization from the user, requesting..."); - requestAuthorization(context, vpnIntent, config); + if ("android.hardware.usb.action.USB_STATE".equals(action)) { + if (intent.getExtras().getBoolean("connected")) { + // USB was connected + } else { + // USB was disconnected + stopGnirehtet(context); + } } } @@ -94,12 +25,4 @@ private void stopGnirehtet(Context context) { GnirehtetService.stop(context); } - private void requestAuthorization(Context context, Intent vpnIntent, VpnConfiguration config) { - // we must send the intent with startActivityForResult, so we need to send it from an activity - Intent intent = new Intent(context, AuthorizationActivity.class); - intent.putExtra(AuthorizationActivity.EXTRA_VPN_INTENT, vpnIntent); - intent.putExtra(EXTRA_VPN_CONFIGURATION, config); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - } } diff --git a/app/src/main/java/com/genymobile/gnirehtet/GnirehtetService.java b/app/src/main/java/com/genymobile/gnirehtet/GnirehtetService.java index 7e8b716e..7ec55a56 100644 --- a/app/src/main/java/com/genymobile/gnirehtet/GnirehtetService.java +++ b/app/src/main/java/com/genymobile/gnirehtet/GnirehtetService.java @@ -225,6 +225,7 @@ public void handleMessage(Message message) { case RelayTunnelListener.MSG_RELAY_TUNNEL_DISCONNECTED: Log.d(TAG, "Relay tunnel disconnected"); vpnService.notifier.setFailure(true); + vpnService.stop(vpnService); break; default: } diff --git a/app/src/main/java/com/genymobile/gnirehtet/Notifier.java b/app/src/main/java/com/genymobile/gnirehtet/Notifier.java index eb1bdf40..a83561cd 100644 --- a/app/src/main/java/com/genymobile/gnirehtet/Notifier.java +++ b/app/src/main/java/com/genymobile/gnirehtet/Notifier.java @@ -20,7 +20,6 @@ public class Notifier { private final Service context; private boolean failure; - public Notifier(Service context) { this.context = context; } @@ -35,7 +34,6 @@ private Notification createNotification(boolean failure) { notificationBuilder.setContentText(context.getString(R.string.relay_connected)); notificationBuilder.setSmallIcon(R.drawable.ic_usb_24dp); } - notificationBuilder.addAction(createStopAction()); return notificationBuilder.build(); } @@ -64,7 +62,7 @@ public void start() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { createNotificationChannel(); } - context.startForeground(NOTIFICATION_ID, createNotification(false)); + context.startForeground(NOTIFICATION_ID, createNotification(failure)); } public void stop() { @@ -82,16 +80,6 @@ public void setFailure(boolean failure) { } } - private Notification.Action createStopAction() { - Intent stopIntent = GnirehtetService.createStopIntent(context); - PendingIntent stopPendingIntent = PendingIntent.getService(context, 0, stopIntent, PendingIntent.FLAG_ONE_SHOT); - // the non-deprecated constructor is not available in API 21 - @SuppressWarnings("deprecation") - Notification.Action.Builder actionBuilder = new Notification.Action.Builder(R.drawable.ic_close_24dp, context.getString(R.string.stop_vpn), - stopPendingIntent); - return actionBuilder.build(); - } - private NotificationManager getNotificationManager() { return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); } diff --git a/app/src/main/java/com/genymobile/gnirehtet/RelayTunnel.java b/app/src/main/java/com/genymobile/gnirehtet/RelayTunnel.java index a0b09af0..51aa436f 100644 --- a/app/src/main/java/com/genymobile/gnirehtet/RelayTunnel.java +++ b/app/src/main/java/com/genymobile/gnirehtet/RelayTunnel.java @@ -76,7 +76,7 @@ private static void readClientId(InputStream inputStream) throws IOException { @Override public void send(byte[] packet, int len) throws IOException { if (GnirehtetService.VERBOSE) { - Log.d(TAG, "Sending..." + Binary.toString(packet, len)); + Log.v(TAG, "Sending packet: " + Binary.buildPacketString(packet, len)); } localSocket.getOutputStream().write(packet, 0, len); } @@ -85,7 +85,7 @@ public void send(byte[] packet, int len) throws IOException { public int receive(byte[] packet) throws IOException { int r = localSocket.getInputStream().read(packet); if (GnirehtetService.VERBOSE) { - Log.d(TAG, "Receiving..." + Binary.toString(packet, r)); + Log.v(TAG, "Receiving packet: " + Binary.buildPacketString(packet, r)); } return r; } diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index e68b4351..a6acd6aa 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -2,5 +2,4 @@ Reverse tethering activé Déconnecté du serveur relais - Arrêter Gnirehtet \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml new file mode 100644 index 00000000..7d67c4e6 --- /dev/null +++ b/app/src/main/res/values-ru/strings.xml @@ -0,0 +1,5 @@ + + + Передача по USB активирована + Передача по USB отключена + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7ffac67a..e0bc6eac 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,5 +2,4 @@ Gnirehtet Reverse tethering enabled Disconnected from the relay server - Stop Gnirehtet diff --git a/build.gradle b/build.gradle index 2f9b032e..e87852c0 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:3.5.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1fdfe3c6..b81e6d75 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Jan 20 13:10:05 CET 2018 +#Sat Sep 07 21:43:49 CEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/relay-java/src/main/java/com/genymobile/gnirehtet/CommandLineArguments.java b/relay-java/src/main/java/com/genymobile/gnirehtet/CommandLineArguments.java index aca58edb..6413d0c8 100644 --- a/relay-java/src/main/java/com/genymobile/gnirehtet/CommandLineArguments.java +++ b/relay-java/src/main/java/com/genymobile/gnirehtet/CommandLineArguments.java @@ -19,13 +19,18 @@ /** * Simple specific command-line arguments parser. */ +@SuppressWarnings("checkstyle:MagicNumber") public class CommandLineArguments { public static final int PARAM_NONE = 0; public static final int PARAM_SERIAL = 1; public static final int PARAM_DNS_SERVER = 1 << 1; public static final int PARAM_ROUTES = 1 << 2; + public static final int PARAM_PORT = 1 << 3; + public static final int DEFAULT_PORT = 31416; + + private int port; private String serial; private String dnsServers; private String routes; @@ -52,12 +57,27 @@ public static CommandLineArguments parse(int acceptedParameters, String... args) } arguments.routes = args[i + 1]; ++i; // consume the -r parameter + } else if ((acceptedParameters & PARAM_PORT) != 0 && "-p".equals(arg)) { + if (arguments.port != 0) { + throw new IllegalArgumentException("Port already set"); + } + if (i == args.length - 1) { + throw new IllegalArgumentException("Missing -p parameter"); + } + arguments.port = Integer.parseInt(args[i + 1]); + if (arguments.port <= 0 || arguments.port >= 65536) { + throw new IllegalArgumentException("Invalid port: " + arguments.port); + } + ++i; } else if ((acceptedParameters & PARAM_SERIAL) != 0 && arguments.serial == null) { arguments.serial = arg; } else { throw new IllegalArgumentException("Unexpected argument: \"" + arg + "\""); } } + if (arguments.port == 0) { + arguments.port = DEFAULT_PORT; + } return arguments; } @@ -72,4 +92,8 @@ public String getDnsServers() { public String getRoutes() { return routes; } + + public int getPort() { + return port; + } } diff --git a/relay-java/src/main/java/com/genymobile/gnirehtet/Main.java b/relay-java/src/main/java/com/genymobile/gnirehtet/Main.java index 25bf68bf..03b6efcb 100644 --- a/relay-java/src/main/java/com/genymobile/gnirehtet/Main.java +++ b/relay-java/src/main/java/com/genymobile/gnirehtet/Main.java @@ -32,12 +32,22 @@ public final class Main { private static final String TAG = "Gnirehtet"; private static final String NL = System.lineSeparator(); - private static final String REQUIRED_APK_VERSION_CODE = "6"; + private static final String REQUIRED_APK_VERSION_CODE = "8"; private Main() { // not instantiable } + private static String getAdbPath() { + String adb = System.getenv("ADB"); + return adb != null ? adb : "adb"; + } + + private static String getApkPath() { + String apk = System.getenv("GNIREHTET_APK"); + return apk != null ? apk : "gnirehtet.apk"; + } + enum Command { INSTALL("install", CommandLineArguments.PARAM_SERIAL) { @Override @@ -76,7 +86,8 @@ void execute(CommandLineArguments args) throws Exception { cmdReinstall(args.getSerial()); } }, - RUN("run", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES) { + RUN("run", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES + | CommandLineArguments.PARAM_PORT) { @Override String getDescription() { return "Enable reverse tethering for exactly one device:\n" @@ -88,10 +99,10 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdRun(args.getSerial(), args.getDnsServers(), args.getRoutes()); + cmdRun(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort()); } }, - AUTORUN("autorun", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES) { + AUTORUN("autorun", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES | CommandLineArguments.PARAM_PORT) { @Override String getDescription() { return "Enable reverse tethering for all devices:\n" @@ -101,10 +112,11 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdAutorun(args.getDnsServers(), args.getRoutes()); + cmdAutorun(args.getDnsServers(), args.getRoutes(), args.getPort()); } }, - START("start", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES) { + START("start", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES + | CommandLineArguments.PARAM_PORT) { @Override String getDescription() { return "Start a client on the Android device and exit.\n" @@ -113,6 +125,8 @@ String getDescription() { + "If -d is given, then make the Android device use the specified\n" + "DNS server(s). Otherwise, use 8.8.8.8 (Google public DNS).\n" + "If -r is given, then only reverse tether the specified routes.\n" + + "If -p is given, then make the relay server listen on the specified\n" + + "port. Otherwise, use port 31416.\n" + "Otherwise, use 0.0.0.0/0 (redirect the whole traffic).\n" + "If the client is already started, then do nothing, and ignore\n" + "the other parameters.\n" @@ -121,10 +135,10 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdStart(args.getSerial(), args.getDnsServers(), args.getRoutes()); + cmdStart(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort()); } }, - AUTOSTART("autostart", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES) { + AUTOSTART("autostart", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES | CommandLineArguments.PARAM_PORT) { @Override String getDescription() { return "Listen for device connexions and start a client on every detected\n" @@ -135,7 +149,7 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdAutostart(args.getDnsServers(), args.getRoutes()); + cmdAutostart(args.getDnsServers(), args.getRoutes(), args.getPort()); } }, STOP("stop", CommandLineArguments.PARAM_SERIAL) { @@ -151,7 +165,8 @@ void execute(CommandLineArguments args) throws Exception { cmdStop(args.getSerial()); } }, - RESTART("restart", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES) { + RESTART("restart", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES + | CommandLineArguments.PARAM_PORT) { @Override String getDescription() { return "Stop then start."; @@ -159,10 +174,10 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdRestart(args.getSerial(), args.getDnsServers(), args.getRoutes()); + cmdRestart(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort()); } }, - TUNNEL("tunnel", CommandLineArguments.PARAM_SERIAL) { + TUNNEL("tunnel", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_PORT) { @Override String getDescription() { return "Set up the 'adb reverse' tunnel.\n" @@ -173,10 +188,10 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdTunnel(args.getSerial()); + cmdTunnel(args.getSerial(), args.getPort()); } }, - RELAY("relay", CommandLineArguments.PARAM_NONE) { + RELAY("relay", CommandLineArguments.PARAM_PORT) { @Override String getDescription() { return "Start the relay server in the current terminal."; @@ -184,7 +199,7 @@ String getDescription() { @Override void execute(CommandLineArguments args) throws Exception { - cmdRelay(); + cmdRelay(args.getPort()); } }; @@ -203,7 +218,7 @@ void execute(CommandLineArguments args) throws Exception { private static void cmdInstall(String serial) throws InterruptedException, IOException, CommandExecutionException { Log.i(TAG, "Installing gnirehtet client..."); - execAdb(serial, "install", "-r", "gnirehtet.apk"); + execAdb(serial, "install", "-r", getApkPath()); } private static void cmdUninstall(String serial) throws InterruptedException, IOException, CommandExecutionException { @@ -216,9 +231,9 @@ private static void cmdReinstall(String serial) throws InterruptedException, IOE cmdInstall(serial); } - private static void cmdRun(String serial, String dnsServers, String routes) throws InterruptedException, IOException, CommandExecutionException { + private static void cmdRun(String serial, String dnsServers, String routes, int port) throws IOException { // start in parallel so that the relay server is ready when the client connects - asyncStart(serial, dnsServers, routes); + asyncStart(serial, dnsServers, routes, port); Runtime.getRuntime().addShutdownHook(new Thread(() -> { // executed on Ctrl+C @@ -229,23 +244,23 @@ private static void cmdRun(String serial, String dnsServers, String routes) thro } })); - cmdRelay(); + cmdRelay(port); } - private static void cmdAutorun(final String dnsServers, final String routes) throws InterruptedException, IOException, CommandExecutionException { + private static void cmdAutorun(final String dnsServers, final String routes, int port) throws IOException { new Thread(() -> { try { - cmdAutostart(dnsServers, routes); + cmdAutostart(dnsServers, routes, port); } catch (Exception e) { Log.e(TAG, "Cannot auto start clients", e); } }).start(); - cmdRelay(); + cmdRelay(port); } @SuppressWarnings("checkstyle:MagicNumber") - private static void cmdStart(String serial, String dnsServers, String routes) throws InterruptedException, IOException, + private static void cmdStart(String serial, String dnsServers, String routes, int port) throws InterruptedException, IOException, CommandExecutionException { if (mustInstallClient(serial)) { cmdInstall(serial); @@ -254,11 +269,11 @@ private static void cmdStart(String serial, String dnsServers, String routes) th } Log.i(TAG, "Starting client..."); - cmdTunnel(serial); + cmdTunnel(serial, port); List cmd = new ArrayList<>(); - Collections.addAll(cmd, "shell", "am", "broadcast", "-a", "com.genymobile.gnirehtet.START", "-n", - "com.genymobile.gnirehtet/.GnirehtetControlReceiver"); + Collections.addAll(cmd, "shell", "am", "start", "-a", "com.genymobile.gnirehtet.START", "-n", + "com.genymobile.gnirehtet/.GnirehtetActivity"); if (dnsServers != null) { Collections.addAll(cmd, "--esa", "dnsServers", dnsServers); } @@ -268,38 +283,38 @@ private static void cmdStart(String serial, String dnsServers, String routes) th execAdb(serial, cmd); } - private static void cmdAutostart(final String dnsServers, final String routes) { + private static void cmdAutostart(final String dnsServers, final String routes, int port) { AdbMonitor adbMonitor = new AdbMonitor((serial) -> { - asyncStart(serial, dnsServers, routes); + asyncStart(serial, dnsServers, routes, port); }); adbMonitor.monitor(); } private static void cmdStop(String serial) throws InterruptedException, IOException, CommandExecutionException { Log.i(TAG, "Stopping client..."); - execAdb(serial, "shell", "am", "broadcast", "-a", "com.genymobile.gnirehtet.STOP", "-n", - "com.genymobile.gnirehtet/.GnirehtetControlReceiver"); + execAdb(serial, "shell", "am", "start", "-a", "com.genymobile.gnirehtet.STOP", "-n", + "com.genymobile.gnirehtet/.GnirehtetActivity"); } - private static void cmdRestart(String serial, String dnsServers, String routes) throws InterruptedException, IOException, + private static void cmdRestart(String serial, String dnsServers, String routes, int port) throws InterruptedException, IOException, CommandExecutionException { cmdStop(serial); - cmdStart(serial, dnsServers, routes); + cmdStart(serial, dnsServers, routes, port); } - private static void cmdTunnel(String serial) throws InterruptedException, IOException, CommandExecutionException { - execAdb(serial, "reverse", "localabstract:gnirehtet", "tcp:31416"); + private static void cmdTunnel(String serial, int port) throws InterruptedException, IOException, CommandExecutionException { + execAdb(serial, "reverse", "localabstract:gnirehtet", "tcp:" + port); } - private static void cmdRelay() throws IOException { - Log.i(TAG, "Starting relay server..."); - new Relay().run(); + private static void cmdRelay(int port) throws IOException { + Log.i(TAG, "Starting relay server on port " + port + "..."); + new Relay(port).run(); } - private static void asyncStart(String serial, String dnsServers, String routes) { + private static void asyncStart(String serial, String dnsServers, String routes, int port) { new Thread(() -> { try { - cmdStart(serial, dnsServers, routes); + cmdStart(serial, dnsServers, routes, port); } catch (Exception e) { Log.e(TAG, "Cannot start client", e); } @@ -312,7 +327,7 @@ private static void execAdb(String serial, String... adbArgs) throws Interrupted private static List createAdbCommand(String serial, String... adbArgs) { List command = new ArrayList<>(); - command.add("adb"); + command.add(getAdbPath()); if (serial != null) { command.add("-s"); command.add(serial); @@ -387,6 +402,9 @@ private static void appendCommandUsage(StringBuilder builder, Command command) { if ((command.acceptedParameters & CommandLineArguments.PARAM_DNS_SERVER) != 0) { builder.append(" [-d DNS[,DNS2,...]]"); } + if ((command.acceptedParameters & CommandLineArguments.PARAM_PORT) != 0) { + builder.append(" [-p PORT]"); + } if ((command.acceptedParameters & CommandLineArguments.PARAM_ROUTES) != 0) { builder.append(" [-r ROUTE[,ROUTE2,...]]"); } diff --git a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Binary.java b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Binary.java index 4dd7eb61..a7b5241b 100644 --- a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Binary.java +++ b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Binary.java @@ -21,31 +21,31 @@ @SuppressWarnings("checkstyle:MagicNumber") public final class Binary { + private static final int MAX_STRING_PACKET_SIZE = 20; + private Binary() { // not instantiable } - public static String toString(byte[] data, int offset, int length) { + public static String buildPacketString(byte[] data, int offset, int len) { + int limit = Math.min(MAX_STRING_PACKET_SIZE, len); StringBuilder builder = new StringBuilder(); - for (int i = 0; i < length; ++i) { - byte b = data[offset + i]; - if (i % 16 == 0) { - builder.append('\n'); - } else if (i % 8 == 0) { - builder.append(' '); + builder.append('[').append(len).append(" bytes] "); + for (int i = 0; i < limit; ++i) { + if (i != 0) { + String sep = i % 4 == 0 ? " " : " "; + builder.append(sep); } - ++i; - builder.append(String.format("%02X ", b & 0xff)); + builder.append(String.format("%02X", data[offset + i] & 0xff)); + } + if (limit < len) { + builder.append(" ... +").append(len - limit).append(" bytes"); } return builder.toString(); } - public static String toString(byte[] data) { - return toString(data, 0, data.length); - } - - public static String toString(ByteBuffer buffer) { - return toString(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining()); + public static String buildPacketString(ByteBuffer buffer) { + return buildPacketString(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining()); } public static ByteBuffer copy(ByteBuffer buffer) { diff --git a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/IPv4Packet.java b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/IPv4Packet.java index ae0316e2..85ef2b1e 100644 --- a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/IPv4Packet.java +++ b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/IPv4Packet.java @@ -33,6 +33,10 @@ public IPv4Packet(ByteBuffer raw) { this.raw = raw; raw.rewind(); + if (Log.isVerboseEnabled()) { + Log.v(TAG, "IPv4Packet: " + Binary.buildPacketString(raw)); + } + ipv4Header = new IPv4Header(raw.duplicate()); if (!ipv4Header.isSupported()) { Log.d(TAG, "Unsupported IPv4 headers"); diff --git a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Relay.java b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Relay.java index 5d452c6a..d84b06f4 100644 --- a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Relay.java +++ b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Relay.java @@ -25,15 +25,10 @@ public class Relay { private static final String TAG = Relay.class.getSimpleName(); - private static final int DEFAULT_PORT = 31416; private static final int CLEANING_INTERVAL = 60 * 1000; private final int port; - public Relay() { - this(DEFAULT_PORT); - } - public Relay(int port) { this.port = port; } @@ -53,11 +48,9 @@ public void run() throws IOException { Set selectedKeys = selector.selectedKeys(); long now = System.currentTimeMillis(); - if (now >= nextCleaningDeadline) { + if (now >= nextCleaningDeadline || selectedKeys.isEmpty()) { tunnelServer.cleanUp(); nextCleaningDeadline = now + CLEANING_INTERVAL; - } else if (selectedKeys.isEmpty()) { - throw new AssertionError("selector.select() returned without any event, an invalid SelectionKey was probably been registered"); } for (SelectionKey selectedKey : selectedKeys) { diff --git a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Router.java b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Router.java index ef65738a..5ad6e1e7 100644 --- a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Router.java +++ b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/Router.java @@ -40,7 +40,7 @@ public void sendToNetwork(IPv4Packet packet) { if (!packet.isValid()) { Log.w(TAG, "Dropping invalid packet"); if (Log.isVerboseEnabled()) { - Log.v(TAG, Binary.toString(packet.getRaw())); + Log.v(TAG, Binary.buildPacketString(packet.getRaw())); } return; } diff --git a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/TCPConnection.java b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/TCPConnection.java index 3cc09b8f..731b668f 100644 --- a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/TCPConnection.java +++ b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/TCPConnection.java @@ -353,7 +353,7 @@ private void handleAck(IPv4Packet packet) { } if (Log.isVerboseEnabled()) { - logv(TAG, Binary.toString(packet.getRaw())); + logv(TAG, Binary.buildPacketString(packet.getRaw())); } int payloadLength = packet.getPayloadLength(); @@ -405,7 +405,7 @@ private IPv4Packet createEmptyResponsePacket(int flags) { IPv4Packet packet = networkToClient.packetizeEmptyPayload(); logd(TAG, "Forging empty response (flags=" + flags + ") " + numbers()); if (Log.isVerboseEnabled()) { - logd(TAG, Binary.toString(packet.getRaw())); + logd(TAG, Binary.buildPacketString(packet.getRaw())); } if ((flags & TCPHeader.FLAG_ACK) != 0) { logd(TAG, "Acking " + numbers()); @@ -478,7 +478,7 @@ private void updateAcknowledgementNumber(IPv4Packet packet) { public void next() { logd(TAG, "Packet (" + packetForClient.getPayloadLength() + " bytes) sent to client " + numbers()); if (Log.isVerboseEnabled()) { - logv(TAG, Binary.toString(packetForClient.getRaw())); + logv(TAG, Binary.buildPacketString(packetForClient.getRaw())); } sequenceNumber += packetForClient.getPayloadLength(); packetForClient = null; diff --git a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/UDPConnection.java b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/UDPConnection.java index e0fa0d7d..6dd506cb 100644 --- a/relay-java/src/main/java/com/genymobile/gnirehtet/relay/UDPConnection.java +++ b/relay-java/src/main/java/com/genymobile/gnirehtet/relay/UDPConnection.java @@ -137,7 +137,7 @@ private void pushToClient(IPv4Packet packet) { } logd(TAG, "Packet (" + packet.getPayloadLength() + " bytes) sent to client"); if (Log.isVerboseEnabled()) { - logv(TAG, Binary.toString(packet.getRaw())); + logv(TAG, Binary.buildPacketString(packet.getRaw())); } } diff --git a/relay-rust/Cargo.lock b/relay-rust/Cargo.lock index 51c7aa09..c78116e1 100644 --- a/relay-rust/Cargo.lock +++ b/relay-rust/Cargo.lock @@ -1,48 +1,56 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" -version = "1.0.4" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.6" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "cc" -version = "1.0.23" +name = "c2-chacha" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "cfg-if" -version = "0.1.5" +name = "cc" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "chrono" -version = "0.4.6" +name = "cfg-if" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "chrono" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ctrlc" -version = "3.1.1" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -50,7 +58,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -59,26 +67,35 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "getrandom" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gnirehtet" -version = "2.3.0" +version = "2.5.0" dependencies = [ - "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "iovec" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -90,39 +107,33 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "lazycell" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libc" -version = "0.2.43" +version = "0.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" -version = "0.4.4" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio" -version = "0.6.15" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -142,71 +153,100 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "nix" -version = "0.11.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-integer" -version = "0.1.39" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.5" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rand" -version = "0.5.5" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_core" +name = "rand_chacha" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "redox_syscall" -version = "0.1.40" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "slab" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "time" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -214,6 +254,11 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -221,7 +266,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -253,34 +298,39 @@ dependencies = [ ] [metadata] -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" -"checksum cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "c37f0efaa4b9b001fa6f02d4b644dee4af97d3414df07c51e3e4f015f3a3e131" -"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" -"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" +"checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" +"checksum ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7dfd2d8b4c82121dfdff120f818e09fc4380b0b7e17a742081a89b94853e87f" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" -"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" -"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" -"checksum mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4fcfcb32d63961fb6f367bfd5d21e4600b92cd310f71f9dca25acae196eb1560" +"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" -"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" -"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" +"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "443c53b3c3531dfcbfa499d8893944db78474ad7a1d87fa2d94d1a2231693ac6" +"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/relay-rust/Cargo.toml b/relay-rust/Cargo.toml index 55302894..13a22a85 100644 --- a/relay-rust/Cargo.toml +++ b/relay-rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gnirehtet" -version = "2.3.0" +version = "2.5.0" authors = ["Romain Vimont "] edition = "2018" @@ -13,8 +13,8 @@ mio = "0.6" # for async I/O slab = "0.4" # helper for mio Tokens log = "0.4" # for logs chrono = "0.4" # for formatting timestamp in logs -byteorder = "1.2" # for reading/writing binary -rand = "0.5" # for random TCP sequence number +byteorder = "1.3" # for reading/writing binary +rand = "0.7" # for random TCP sequence number ctrlc = { version = "3.0", features = ["termination"] } # for handling Ctrl+C [profile.release] diff --git a/relay-rust/src/adb_monitor.rs b/relay-rust/src/adb_monitor.rs index d09ad97e..102f79f2 100644 --- a/relay-rust/src/adb_monitor.rs +++ b/relay-rust/src/adb_monitor.rs @@ -57,7 +57,7 @@ impl AdbMonitor { } } - pub fn monitor(&mut self) -> io::Result<()> { + pub fn monitor(&mut self) { loop { if let Err(err) = self.track_devices() { error!(target: TAG, "Failed to monitor adb devices: {}", err); diff --git a/relay-rust/src/cli_args.rs b/relay-rust/src/cli_args.rs index 6968af02..438427fb 100644 --- a/relay-rust/src/cli_args.rs +++ b/relay-rust/src/cli_args.rs @@ -18,11 +18,15 @@ pub const PARAM_NONE: u8 = 0; pub const PARAM_SERIAL: u8 = 1; pub const PARAM_DNS_SERVERS: u8 = 1 << 1; pub const PARAM_ROUTES: u8 = 1 << 2; +pub const PARAM_PORT: u8 = 1 << 3; + +pub const DEFAULT_PORT: u16 = 31416; pub struct CommandLineArguments { serial: Option, dns_servers: Option, routes: Option, + port: u16, } impl CommandLineArguments { @@ -31,6 +35,7 @@ impl CommandLineArguments { let mut serial = None; let mut dns_servers = None; let mut routes = None; + let mut port = 0; let mut iter = args.into_iter(); while let Some(arg) = iter.next() { @@ -53,29 +58,49 @@ impl CommandLineArguments { } else { return Err(String::from("Missing -r parameter")); } + } else if (accepted_parameters & PARAM_PORT) != 0 && "-p" == arg { + if port != 0 { + return Err(String::from("Port already set")); + } + if let Some(value) = iter.next() { + port = value.into().parse().unwrap(); + if port == 0 { + return Err(String::from("Invalid port: 0")); + } + } else { + return Err(String::from("Missing -p parameter")); + } } else if (accepted_parameters & PARAM_SERIAL) != 0 && serial.is_none() { serial = Some(arg); } else { return Err(format!("Unexpected argument: \"{}\"", arg)); } } + if port == 0 { + port = DEFAULT_PORT; + } Ok(Self { serial, dns_servers, routes, + port, }) } pub fn serial(&self) -> Option<&str> { - self.serial.as_ref().map(String::as_str) + self.serial.as_deref() } pub fn dns_servers(&self) -> Option<&str> { - self.dns_servers.as_ref().map(String::as_str) + self.dns_servers.as_deref() } pub fn routes(&self) -> Option<&str> { - self.routes.as_ref().map(String::as_str) + self.routes.as_deref() + } + + pub fn port(&self) -> u16 { + self.port } } diff --git a/relay-rust/src/execution_error.rs b/relay-rust/src/execution_error.rs index 90be6545..39b5610b 100644 --- a/relay-rust/src/execution_error.rs +++ b/relay-rust/src/execution_error.rs @@ -107,15 +107,7 @@ impl fmt::Display for ProcessStatusError { } } -impl error::Error for ProcessStatusError { - fn description(&self) -> &str { - "Execution terminated with failure" - } - - fn cause(&self) -> Option<&error::Error> { - None - } -} +impl error::Error for ProcessStatusError {} impl ProcessIoError { pub fn new(cmd: Cmd, error: io::Error) -> Self { @@ -130,11 +122,7 @@ impl fmt::Display for ProcessIoError { } impl error::Error for ProcessIoError { - fn description(&self) -> &str { - "Execution I/O failed" - } - - fn cause(&self) -> Option<&error::Error> { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(&self.error) } } @@ -150,15 +138,7 @@ impl fmt::Display for CommandExecutionError { } impl error::Error for CommandExecutionError { - fn description(&self) -> &str { - match *self { - CommandExecutionError::ProcessIo(ref err) => err.description(), - CommandExecutionError::ProcessStatus(ref err) => err.description(), - CommandExecutionError::Io(ref err) => err.description(), - } - } - - fn cause(&self) -> Option<&error::Error> { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { CommandExecutionError::ProcessIo(ref err) => Some(err), CommandExecutionError::ProcessStatus(ref err) => Some(err), diff --git a/relay-rust/src/lib.rs b/relay-rust/src/lib.rs index 5c149108..e50ca4e7 100644 --- a/relay-rust/src/lib.rs +++ b/relay-rust/src/lib.rs @@ -20,7 +20,6 @@ pub use crate::relay::byte_buffer; use crate::relay::Relay; use std::io; -pub fn relay() -> io::Result<()> { - const PORT: u16 = 31416; - Relay::new(PORT).run() +pub fn relay(port: u16) -> io::Result<()> { + Relay::new(port).run() } diff --git a/relay-rust/src/main.rs b/relay-rust/src/main.rs index 44e8eb36..cb80e9c8 100644 --- a/relay-rust/src/main.rs +++ b/relay-rust/src/main.rs @@ -34,9 +34,27 @@ use std::thread; use std::time::Duration; const TAG: &str = "Main"; -const REQUIRED_APK_VERSION_CODE: &str = "6"; +const REQUIRED_APK_VERSION_CODE: &str = "8"; -const COMMANDS: &[&Command] = &[ +#[inline] +fn get_adb_path() -> String { + if let Some(env_adb) = std::env::var_os("ADB") { + env_adb.into_string().expect("invalid ADB value") + } else { + "adb".to_string() + } +} + +#[inline] +fn get_apk_path() -> String { + if let Some(env_adb) = std::env::var_os("GNIREHTET_APK") { + env_adb.into_string().expect("invalid GNIREHTET_APK value") + } else { + "gnirehtet.apk".to_string() + } +} + +const COMMANDS: &[&dyn Command] = &[ &InstallCommand, &UninstallCommand, &ReinstallCommand, @@ -133,7 +151,10 @@ impl Command for RunCommand { } fn accepted_parameters(&self) -> u8 { - cli_args::PARAM_SERIAL | cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES + cli_args::PARAM_SERIAL + | cli_args::PARAM_DNS_SERVERS + | cli_args::PARAM_ROUTES + | cli_args::PARAM_PORT } fn description(&self) -> &'static str { @@ -145,7 +166,12 @@ impl Command for RunCommand { } fn execute(&self, args: &CommandLineArguments) -> Result<(), CommandExecutionError> { - cmd_run(args.serial(), args.dns_servers(), args.routes()) + cmd_run( + args.serial(), + args.dns_servers(), + args.routes(), + args.port(), + ) } } @@ -155,7 +181,7 @@ impl Command for AutorunCommand { } fn accepted_parameters(&self) -> u8 { - cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES + cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES | cli_args::PARAM_PORT } fn description(&self) -> &'static str { @@ -165,7 +191,7 @@ impl Command for AutorunCommand { } fn execute(&self, args: &CommandLineArguments) -> Result<(), CommandExecutionError> { - cmd_autorun(args.dns_servers(), args.routes()) + cmd_autorun(args.dns_servers(), args.routes(), args.port()) } } @@ -175,7 +201,10 @@ impl Command for StartCommand { } fn accepted_parameters(&self) -> u8 { - cli_args::PARAM_SERIAL | cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES + cli_args::PARAM_SERIAL + | cli_args::PARAM_DNS_SERVERS + | cli_args::PARAM_ROUTES + | cli_args::PARAM_PORT } fn description(&self) -> &'static str { @@ -186,13 +215,20 @@ impl Command for StartCommand { DNS server(s). Otherwise, use 8.8.8.8 (Google public DNS).\n\ If -r is given, then only reverse tether the specified routes.\n\ Otherwise, use 0.0.0.0/0 (redirect the whole traffic).\n\ + If -p is given, then make the relay server listen on the specified\n\ + port. Otherwise, use port 31416.\n\ If the client is already started, then do nothing, and ignore\n\ the other parameters.\n\ 10.0.2.2 is mapped to the host 'localhost'." } fn execute(&self, args: &CommandLineArguments) -> Result<(), CommandExecutionError> { - cmd_start(args.serial(), args.dns_servers(), args.routes()) + cmd_start( + args.serial(), + args.dns_servers(), + args.routes(), + args.port(), + ) } } @@ -202,7 +238,7 @@ impl Command for AutostartCommand { } fn accepted_parameters(&self) -> u8 { - cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES + cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES | cli_args::PARAM_PORT } fn description(&self) -> &'static str { @@ -213,7 +249,7 @@ impl Command for AutostartCommand { } fn execute(&self, args: &CommandLineArguments) -> Result<(), CommandExecutionError> { - cmd_autostart(args.dns_servers(), args.routes()) + cmd_autostart(args.dns_servers(), args.routes(), args.port()) } } @@ -243,7 +279,10 @@ impl Command for RestartCommand { } fn accepted_parameters(&self) -> u8 { - cli_args::PARAM_SERIAL | cli_args::PARAM_DNS_SERVERS | cli_args::PARAM_ROUTES + cli_args::PARAM_SERIAL + | cli_args::PARAM_DNS_SERVERS + | cli_args::PARAM_ROUTES + | cli_args::PARAM_PORT } fn description(&self) -> &'static str { @@ -252,7 +291,12 @@ impl Command for RestartCommand { fn execute(&self, args: &CommandLineArguments) -> Result<(), CommandExecutionError> { cmd_stop(args.serial())?; - cmd_start(args.serial(), args.dns_servers(), args.routes())?; + cmd_start( + args.serial(), + args.dns_servers(), + args.routes(), + args.port(), + )?; Ok(()) } } @@ -263,7 +307,7 @@ impl Command for TunnelCommand { } fn accepted_parameters(&self) -> u8 { - cli_args::PARAM_SERIAL + cli_args::PARAM_SERIAL | cli_args::PARAM_PORT } fn description(&self) -> &'static str { @@ -274,7 +318,7 @@ impl Command for TunnelCommand { } fn execute(&self, args: &CommandLineArguments) -> Result<(), CommandExecutionError> { - cmd_tunnel(args.serial()) + cmd_tunnel(args.serial(), args.port()) } } @@ -284,22 +328,22 @@ impl Command for RelayCommand { } fn accepted_parameters(&self) -> u8 { - cli_args::PARAM_NONE + cli_args::PARAM_NONE | cli_args::PARAM_PORT } fn description(&self) -> &'static str { "Start the relay server in the current terminal." } - fn execute(&self, _: &CommandLineArguments) -> Result<(), CommandExecutionError> { - cmd_relay()?; + fn execute(&self, args: &CommandLineArguments) -> Result<(), CommandExecutionError> { + cmd_relay(args.port())?; Ok(()) } } fn cmd_install(serial: Option<&str>) -> Result<(), CommandExecutionError> { info!(target: TAG, "Installing gnirehtet client..."); - exec_adb(serial, vec!["install", "-r", "gnirehtet.apk"]) + exec_adb(serial, vec!["install".into(), "-r".into(), get_apk_path()]) } fn cmd_uninstall(serial: Option<&str>) -> Result<(), CommandExecutionError> { @@ -317,9 +361,10 @@ fn cmd_run( serial: Option<&str>, dns_servers: Option<&str>, routes: Option<&str>, + port: u16, ) -> Result<(), CommandExecutionError> { // start in parallel so that the relay server is ready when the client connects - async_start(serial, dns_servers, routes); + async_start(serial, dns_servers, routes, port); let ctrlc_serial = serial.map(String::from); ctrlc::set_handler(move || { @@ -334,12 +379,13 @@ fn cmd_run( }) .expect("Error setting Ctrl-C handler"); - cmd_relay() + cmd_relay(port) } fn cmd_autorun( dns_servers: Option<&str>, routes: Option<&str>, + port: u16, ) -> Result<(), CommandExecutionError> { { let autostart_dns_servers = dns_servers.map(String::from); @@ -347,19 +393,20 @@ fn cmd_autorun( thread::spawn(move || { let dns_servers = autostart_dns_servers.as_ref().map(String::as_ref); let routes = autostart_routes.as_ref().map(String::as_ref); - if let Err(err) = cmd_autostart(dns_servers, routes) { + if let Err(err) = cmd_autostart(dns_servers, routes, port) { error!(target: TAG, "Cannot auto start clients: {}", err); } }); } - cmd_relay() + cmd_relay(port) } fn cmd_start( serial: Option<&str>, dns_servers: Option<&str>, routes: Option<&str>, + port: u16, ) -> Result<(), CommandExecutionError> { if must_install_client(serial)? { cmd_install(serial)?; @@ -369,16 +416,16 @@ fn cmd_start( } info!(target: TAG, "Starting client..."); - cmd_tunnel(serial)?; + cmd_tunnel(serial, port)?; let mut adb_args = vec![ "shell", "am", - "broadcast", + "start", "-a", "com.genymobile.gnirehtet.START", "-n", - "com.genymobile.gnirehtet/.GnirehtetControlReceiver", + "com.genymobile.gnirehtet/.GnirehtetActivity", ]; if let Some(dns_servers) = dns_servers { adb_args.append(&mut vec!["--esa", "dnsServers", dns_servers]); @@ -392,15 +439,16 @@ fn cmd_start( fn cmd_autostart( dns_servers: Option<&str>, routes: Option<&str>, + port: u16, ) -> Result<(), CommandExecutionError> { let start_dns_servers = dns_servers.map(String::from); let start_routes = routes.map(String::from); let mut adb_monitor = AdbMonitor::new(Box::new(move |serial: &str| { let dns_servers = start_dns_servers.as_ref().map(String::as_ref); let routes = start_routes.as_ref().map(String::as_ref); - async_start(Some(serial), dns_servers, routes) + async_start(Some(serial), dns_servers, routes, port) })); - adb_monitor.monitor()?; + adb_monitor.monitor(); Ok(()) } @@ -411,29 +459,33 @@ fn cmd_stop(serial: Option<&str>) -> Result<(), CommandExecutionError> { vec![ "shell", "am", - "broadcast", + "start", "-a", "com.genymobile.gnirehtet.STOP", "-n", - "com.genymobile.gnirehtet/.GnirehtetControlReceiver", + "com.genymobile.gnirehtet/.GnirehtetActivity", ], ) } -fn cmd_tunnel(serial: Option<&str>) -> Result<(), CommandExecutionError> { +fn cmd_tunnel(serial: Option<&str>, port: u16) -> Result<(), CommandExecutionError> { exec_adb( serial, - vec!["reverse", "localabstract:gnirehtet", "tcp:31416"], + vec![ + "reverse", + "localabstract:gnirehtet", + format!("tcp:{}", port).as_str(), + ], ) } -fn cmd_relay() -> Result<(), CommandExecutionError> { - info!(target: TAG, "Starting relay server..."); - relaylib::relay()?; +fn cmd_relay(port: u16) -> Result<(), CommandExecutionError> { + info!(target: TAG, "Starting relay server on port {}...", port); + relaylib::relay(port)?; Ok(()) } -fn async_start(serial: Option<&str>, dns_servers: Option<&str>, routes: Option<&str>) { +fn async_start(serial: Option<&str>, dns_servers: Option<&str>, routes: Option<&str>, port: u16) { let start_serial = serial.map(String::from); let start_dns_servers = dns_servers.map(String::from); let start_routes = routes.map(String::from); @@ -441,7 +493,7 @@ fn async_start(serial: Option<&str>, dns_servers: Option<&str>, routes: Option<& let serial = start_serial.as_ref().map(String::as_ref); let dns_servers = start_dns_servers.as_ref().map(String::as_ref); let routes = start_routes.as_ref().map(String::as_ref); - if let Err(err) = cmd_start(serial, dns_servers, routes) { + if let Err(err) = cmd_start(serial, dns_servers, routes, port) { error!(target: TAG, "Cannot start client: {}", err); } }); @@ -464,18 +516,19 @@ fn exec_adb>( args: Vec, ) -> Result<(), CommandExecutionError> { let adb_args = create_adb_args(serial, args); - debug!(target: TAG, "Execute: adb {:?}", adb_args); - match process::Command::new("adb").args(&adb_args[..]).status() { + let adb = get_adb_path(); + debug!(target: TAG, "Execute: {:?} {:?}", adb, adb_args); + match process::Command::new(&adb).args(&adb_args[..]).status() { Ok(exit_status) => { if exit_status.success() { Ok(()) } else { - let cmd = Cmd::new("adb", adb_args); + let cmd = Cmd::new(adb, adb_args); Err(ProcessStatusError::new(cmd, exit_status).into()) } } Err(err) => { - let cmd = Cmd::new("adb", adb_args); + let cmd = Cmd::new(adb, adb_args); Err(ProcessIoError::new(cmd, err).into()) } } @@ -487,8 +540,9 @@ fn must_install_client(serial: Option<&str>) -> Result { if output.status.success() { // the "regex" crate makes the binary far bigger, so just parse the versionCode @@ -509,12 +563,12 @@ fn must_install_client(serial: Option<&str>) -> Result { - let cmd = Cmd::new("adb", args); + let cmd = Cmd::new(adb, args); Err(ProcessIoError::new(cmd, err).into()) } } @@ -545,6 +599,9 @@ fn append_command_usage(msg: &mut String, command: &dyn Command) { if (accepted_parameters & cli_args::PARAM_DNS_SERVERS) != 0 { msg.push_str(" [-d DNS[,DNS2,...]]"); } + if (accepted_parameters & cli_args::PARAM_PORT) != 0 { + msg.push_str(" [-p PORT]"); + } if (accepted_parameters & cli_args::PARAM_ROUTES) != 0 { msg.push_str(" [-r ROUTE[,ROUTE2,...]]"); } diff --git a/relay-rust/src/relay/binary.rs b/relay-rust/src/relay/binary.rs index 15e58b9c..47a58294 100644 --- a/relay-rust/src/relay/binary.rs +++ b/relay-rust/src/relay/binary.rs @@ -15,23 +15,29 @@ */ use byteorder::{BigEndian, ByteOrder}; +use std::cmp::min; use std::fmt::Write; +const MAX_STRING_PACKET_SIZE: usize = 20; + pub fn to_byte_array(value: u32) -> [u8; 4] { let mut raw = [0u8; 4]; BigEndian::write_u32(&mut raw, value); raw } -pub fn to_string(data: &[u8]) -> String { +pub fn build_packet_string(data: &[u8]) -> String { let mut s = String::new(); - for (i, &byte) in data.iter().enumerate() { - if i % 16 == 0 { - writeln!(&mut s).unwrap(); - } else if i % 8 == 0 { - write!(&mut s, " ").unwrap(); + let limit = min(MAX_STRING_PACKET_SIZE, data.len()); + for (i, &byte) in data.iter().take(limit).enumerate() { + if i != 0 { + let sep = if (i % 4) == 0 { " " } else { " " }; + write!(&mut s, "{}", sep).unwrap(); } - write!(&mut s, "{:02X} ", byte).unwrap(); + write!(&mut s, "{:02X}", byte).unwrap(); + } + if limit < data.len() { + write!(&mut s, " ... +{} bytes", data.len() - limit).unwrap(); } s } diff --git a/relay-rust/src/relay/byte_buffer.rs b/relay-rust/src/relay/byte_buffer.rs index 01cc476e..50a1c8c2 100644 --- a/relay-rust/src/relay/byte_buffer.rs +++ b/relay-rust/src/relay/byte_buffer.rs @@ -30,7 +30,7 @@ impl ByteBuffer { } } - pub fn read_from(&mut self, source: &mut R) -> io::Result<(bool)> { + pub fn read_from(&mut self, source: &mut R) -> io::Result { let target_slice = &mut self.buf[self.head..]; let r = source.read(target_slice)?; self.head += r; diff --git a/relay-rust/src/relay/client.rs b/relay-rust/src/relay/client.rs index 7861dc8b..b98a85f6 100644 --- a/relay-rust/src/relay/client.rs +++ b/relay-rust/src/relay/client.rs @@ -287,7 +287,7 @@ impl Client { self.channel().update_interests(selector); } - fn read(&mut self) -> io::Result<(bool)> { + fn read(&mut self) -> io::Result { self.client_to_network.read_from(&mut self.stream) } diff --git a/relay-rust/src/relay/ipv4_packet_buffer.rs b/relay-rust/src/relay/ipv4_packet_buffer.rs index 0d526dc5..a0a42f7d 100644 --- a/relay-rust/src/relay/ipv4_packet_buffer.rs +++ b/relay-rust/src/relay/ipv4_packet_buffer.rs @@ -14,9 +14,12 @@ * limitations under the License. */ +use super::binary; use super::byte_buffer::ByteBuffer; use super::ipv4_header; use super::ipv4_packet::{Ipv4Packet, MAX_PACKET_LENGTH}; + +use log::*; use std::io; pub struct Ipv4PacketBuffer { @@ -30,12 +33,13 @@ impl Ipv4PacketBuffer { } } - pub fn read_from(&mut self, source: &mut R) -> io::Result<(bool)> { + pub fn read_from(&mut self, source: &mut R) -> io::Result { self.buf.read_from(source) } fn available_packet_length(&self) -> Option { let data = self.buf.peek(); + trace!("Parse packet: {}", binary::build_packet_string(data)); if let Some((version, length)) = ipv4_header::peek_version_length(data) { assert!(version == 4, "Not an Ipv4 packet, version={}", version); if length as usize <= data.len() { diff --git a/relay-rust/src/relay/router.rs b/relay-rust/src/relay/router.rs index fb366d02..88a8d9e6 100644 --- a/relay-rust/src/relay/router.rs +++ b/relay-rust/src/relay/router.rs @@ -83,7 +83,11 @@ impl Router { } else { warn!(target: TAG, "Dropping invalid packet"); if log_enabled!(target: TAG, Level::Trace) { - trace!(target: TAG, "{}", binary::to_string(ipv4_packet.raw())); + trace!( + target: TAG, + "{}", + binary::build_packet_string(ipv4_packet.raw()) + ); } } } diff --git a/relay-rust/src/relay/tcp_connection.rs b/relay-rust/src/relay/tcp_connection.rs index 91af24a6..4935f306 100644 --- a/relay-rust/src/relay/tcp_connection.rs +++ b/relay-rust/src/relay/tcp_connection.rs @@ -682,7 +682,7 @@ impl TcpConnection { target: TAG, self.id, "{}", - binary::to_string(ipv4_packet.raw()) + binary::build_packet_string(ipv4_packet.raw()) ); } @@ -720,7 +720,12 @@ impl TcpConnection { } let ipv4_packet = packetizer.packetize_empty_payload(); if log_enabled!(target: TAG, Level::Trace) { - cx_trace!(target: TAG, id, "{}", binary::to_string(ipv4_packet.raw())); + cx_trace!( + target: TAG, + id, + "{}", + binary::build_packet_string(ipv4_packet.raw()) + ); } ipv4_packet } @@ -785,7 +790,16 @@ impl Connection for TcpConnection { fn close(&mut self, selector: &mut Selector) { cx_info!(target: TAG, self.id, "Close"); self.closed = true; - selector.deregister(&self.stream, self.token).unwrap(); + if let Err(err) = selector.deregister(&self.stream, self.token) { + // do not panic, this can happen in mio + // see + cx_warn!( + target: TAG, + self.id, + "Fail to deregister TCP stream: {:?}", + err + ); + } // socket will be closed by RAII } diff --git a/relay-rust/src/relay/tunnel_server.rs b/relay-rust/src/relay/tunnel_server.rs index 2976bdf6..7ae2f3bd 100644 --- a/relay-rust/src/relay/tunnel_server.rs +++ b/relay-rust/src/relay/tunnel_server.rs @@ -15,7 +15,7 @@ */ use log::*; -use mio::tcp::TcpListener; +use mio::net::TcpListener; use mio::{Event, PollOpt, Ready}; use std::cell::RefCell; use std::io; diff --git a/relay-rust/src/relay/udp_connection.rs b/relay-rust/src/relay/udp_connection.rs index f07d6ee7..936d578b 100644 --- a/relay-rust/src/relay/udp_connection.rs +++ b/relay-rust/src/relay/udp_connection.rs @@ -206,7 +206,7 @@ impl UdpConnection { target: TAG, self.id, "{}", - binary::to_string(ipv4_packet.raw()) + binary::build_packet_string(ipv4_packet.raw()) ); } } @@ -271,7 +271,16 @@ impl Connection for UdpConnection { fn close(&mut self, selector: &mut Selector) { cx_info!(target: TAG, self.id, "Close"); self.closed = true; - selector.deregister(&self.socket, self.token).unwrap(); + if let Err(err) = selector.deregister(&self.socket, self.token) { + // do not panic, this can happen in mio + // see + cx_warn!( + target: TAG, + self.id, + "Fail to deregister UDP stream: {:?}", + err + ); + } // socket will be closed by RAII } diff --git a/setup/AdbWinApi.dll b/setup/AdbWinApi.dll new file mode 100644 index 00000000..7abe26cf Binary files /dev/null and b/setup/AdbWinApi.dll differ diff --git a/setup/AdbWinUsbApi.dll b/setup/AdbWinUsbApi.dll new file mode 100644 index 00000000..e7a6de12 Binary files /dev/null and b/setup/AdbWinUsbApi.dll differ diff --git a/setup/adb.exe b/setup/adb.exe new file mode 100644 index 00000000..623fa466 Binary files /dev/null and b/setup/adb.exe differ diff --git a/setup/fastboot.exe b/setup/fastboot.exe new file mode 100644 index 00000000..2a5d7683 Binary files /dev/null and b/setup/fastboot.exe differ diff --git a/setup/gnirehtet-autorun.lnk b/setup/gnirehtet-autorun.lnk new file mode 100644 index 00000000..57a549c7 Binary files /dev/null and b/setup/gnirehtet-autorun.lnk differ diff --git a/setup/gnirehtet-run.cmd b/setup/gnirehtet-run.cmd new file mode 100644 index 00000000..ffefea65 --- /dev/null +++ b/setup/gnirehtet-run.cmd @@ -0,0 +1,2 @@ +@gnirehtet.exe run +@pause diff --git a/setup/gnirehtet.apk b/setup/gnirehtet.apk new file mode 100644 index 00000000..7327ab74 Binary files /dev/null and b/setup/gnirehtet.apk differ diff --git a/setup/gnirehtet.exe b/setup/gnirehtet.exe new file mode 100644 index 00000000..fc31676b Binary files /dev/null and b/setup/gnirehtet.exe differ diff --git a/setup/libwinpthread-1.dll b/setup/libwinpthread-1.dll new file mode 100644 index 00000000..94e343a6 Binary files /dev/null and b/setup/libwinpthread-1.dll differ diff --git a/setup/remote-install_app.cmd b/setup/remote-install_app.cmd new file mode 100644 index 00000000..549452c5 --- /dev/null +++ b/setup/remote-install_app.cmd @@ -0,0 +1,6 @@ +@adb start-server +@adb push -p app.apk /data/local/tmp +@adb shell pm install /data/local/tmp/app.apk +@adb shell rm /data/local/tmp/app.apk +@adb kill-server +@pause