From e006e215b274b1b834e098b199ea2697bc11b0f1 Mon Sep 17 00:00:00 2001
From: Georg Koppen <gk@torproject.org>
Date: Sun, 10 May 2020 08:29:10 +0000
Subject: [PATCH] Bug 30318: Add snowflake support


diff --git a/android/build.gradle b/android/build.gradle
index a8d9bdc..2392731 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -93,6 +93,9 @@ task copyPluggableTransports(type: Copy) {
     rename { filename ->
         filename.replace 'obfs4proxy', 'libObfs4proxy.so'
     }
+    rename { filename ->
+        filename.replace 'snowflake-client', 'libSnowflake.so'
+    }
 }
 
 gradle.projectsEvaluated {
diff --git a/universal/src/main/java/com/msopentech/thali/toronionproxy/TorConfigBuilder.java b/universal/src/main/java/com/msopentech/thali/toronionproxy/TorConfigBuilder.java
index 2405097..bcb6a37 100644
--- a/universal/src/main/java/com/msopentech/thali/toronionproxy/TorConfigBuilder.java
+++ b/universal/src/main/java/com/msopentech/thali/toronionproxy/TorConfigBuilder.java
@@ -109,22 +109,33 @@ public final class TorConfigBuilder {
         return this;
     }
 
-    public TorConfigBuilder configurePluggableTransportsFromSettings(File pluggableTransportClient) throws IOException {
-        if (pluggableTransportClient == null) {
+    public TorConfigBuilder configurePluggableTransportsFromSettings(File pluggableTransportObfs, File pluggableTransportSnow) throws IOException {
+        if (pluggableTransportObfs == null  || pluggableTransportSnow == null) {
             return this;
         }
 
-        if (!pluggableTransportClient.exists()) {
-            throw new IOException("Bridge binary does not exist: " + pluggableTransportClient
+        if (!pluggableTransportObfs.exists()) {
+            throw new IOException("Obfs4proxy binary does not exist: " + pluggableTransportObfs
                     .getCanonicalPath());
         }
 
-        if (!pluggableTransportClient.canExecute()) {
-            throw new IOException("Bridge binary is not executable: " + pluggableTransportClient
+        if (!pluggableTransportSnow.exists()) {
+            throw new IOException("Snowflake binary does not exist: " + pluggableTransportSnow
                     .getCanonicalPath());
         }
 
-        transportPlugin(pluggableTransportClient.getCanonicalPath());
+        if (!pluggableTransportObfs.canExecute()) {
+            throw new IOException("Obfs4proxy binary is not executable: " + pluggableTransportObfs
+                    .getCanonicalPath());
+        }
+
+        if (!pluggableTransportSnow.canExecute()) {
+            throw new IOException("Snowflake binary is not executable: " + pluggableTransportSnow
+                    .getCanonicalPath());
+        }
+
+
+        transportPlugin(pluggableTransportObfs.getCanonicalPath(), pluggableTransportSnow.getCanonicalPath());
         return this;
     }
 
@@ -491,8 +502,9 @@ public final class TorConfigBuilder {
         return transPort(settings.transPort());
     }
 
-    public TorConfigBuilder transportPlugin(String clientPath) {
-        buffer.append("ClientTransportPlugin meek_lite,obfs3,obfs4 exec ").append(clientPath).append('\n');
+    public TorConfigBuilder transportPlugin(String obfsPath, String snowPath) {
+        buffer.append("ClientTransportPlugin meek_lite,obfs3,obfs4 exec ").append(obfsPath).append('\n');
+        buffer.append("ClientTransportPlugin snowflake exec ").append(snowPath).append(" -url https://snowflake-broker.torproject.net.global.prod.fastly.net/ -front cdn.sstatic.net -ice stun:stun.l.google.com:19302,stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478\n");
         return this;
     }
 
@@ -557,6 +569,9 @@ public final class TorConfigBuilder {
                     case 3:
                         reqBridgeType = "meek_lite";
                         break;
+                    case 4:
+                        reqBridgeType = "snowflake";
+                        break;
                     default:
                         throw new IOException("Requested unknown transport type: " + bridgesType);
                 }
-- 
2.26.2

