From 0bd1bc201aaec586caa70f1bea1e5cb203280429 Mon Sep 17 00:00:00 2001 From: Matthieu Baerts Date: Fri, 4 Feb 2022 17:52:43 +0100 Subject: [PATCH] MCS: fallback to port 443 if 5228 is blocked According to Google Firebase's doc, other ports than 5228 can be used: If your organization has a firewall to restrict traffic to or from the Internet, you need to configure it to allow mobile devices to connect with FCM in order for devices on your network to receive messages. FCM typically uses port 5228, but it sometimes uses 443, 5229, and 5230. Src: https://firebase.google.com/docs/cloud-messaging/concept-options#messaging-ports-and-your-firewall As suggested by @mar-v-in, it is enough to first try 5228 and then only try with 443 as fall back port. Indeed, it would be surprising to find any firewall blocking port 5228 but not 5229. Closes: https://github.com/microg/GmsCore/issues/408 Signed-off-by: Matthieu Baerts --- .../java/org/microg/gms/gcm/McsService.java | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/play-services-core/src/main/java/org/microg/gms/gcm/McsService.java b/play-services-core/src/main/java/org/microg/gms/gcm/McsService.java index 5a9eb53411..bae8b24b62 100644 --- a/play-services-core/src/main/java/org/microg/gms/gcm/McsService.java +++ b/play-services-core/src/main/java/org/microg/gms/gcm/McsService.java @@ -120,7 +120,11 @@ public class McsService extends Service implements Handler.Callback { public static final String FROM_FIELD = "gcm@android.com"; public static final String SERVICE_HOST = "mtalk.google.com"; + // A few ports are available: 443, 5228-5230 but also 5222-5223 + // See https://github.com/microg/GmsCore/issues/408 public static final int SERVICE_PORT = 5228; + // Likely if the main port 5228 is blocked by a firewall, the other 52xx are blocked as well + public static final int SERVICE_PORT_FALLBACK = 443; private static final int WAKELOCK_TIMEOUT = 5000; // On bad mobile network a ping can take >60s, so we wait for an ACK for 90s @@ -440,24 +444,15 @@ private void handleSendMessage(Intent intent) { } } - private synchronized void connect() { + private boolean connect(int port) { try { - closeAll(); - ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo(); - activeNetworkPref = GcmPrefs.get(this).getNetworkPrefForInfo(activeNetworkInfo); - if (!GcmPrefs.get(this).isEnabledFor(activeNetworkInfo)) { - logd(this, "Don't connect, because disabled for " + activeNetworkInfo.getTypeName()); - scheduleReconnect(this); - return; - } wasTornDown = false; - logd(this, "Starting MCS connection..."); - Socket socket = new Socket(SERVICE_HOST, SERVICE_PORT); - logd(this, "Connected to " + SERVICE_HOST + ":" + SERVICE_PORT); - sslSocket = SSLContext.getDefault().getSocketFactory().createSocket(socket, SERVICE_HOST, SERVICE_PORT, true); - logd(this, "Activated SSL with " + SERVICE_HOST + ":" + SERVICE_PORT); + logd(this, "Starting MCS connection to port " + port + "..."); + Socket socket = new Socket(SERVICE_HOST, port); + logd(this, "Connected to " + SERVICE_HOST + ":" + port); + sslSocket = SSLContext.getDefault().getSocketFactory().createSocket(socket, SERVICE_HOST, port, true); + logd(this, "Activated SSL with " + SERVICE_HOST + ":" + port); inputStream = new McsInputStream(sslSocket.getInputStream(), rootHandler); outputStream = new McsOutputStream(sslSocket.getOutputStream(), rootHandler); inputStream.start(); @@ -469,9 +464,29 @@ private synchronized void connect() { lastIncomingNetworkRealtime = SystemClock.elapsedRealtime(); scheduleHeartbeat(this); } catch (Exception e) { - Log.w(TAG, "Exception while connecting!", e); + Log.w(TAG, "Exception while connecting to " + SERVICE_HOST + ":" + port, e); rootHandler.sendMessage(rootHandler.obtainMessage(MSG_TEARDOWN, e)); + closeAll(); + return false; } + + return true; + } + + private synchronized void connect() { + closeAll(); + + ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo(); + activeNetworkPref = GcmPrefs.get(this).getNetworkPrefForInfo(activeNetworkInfo); + if (!GcmPrefs.get(this).isEnabledFor(activeNetworkInfo)) { + logd(this, "Don't connect, because disabled for " + activeNetworkInfo.getTypeName()); + scheduleReconnect(this); + return; + } + + if (!connect(SERVICE_PORT)) + connect(SERVICE_PORT_FALLBACK); } private void handleClose(Close close) {