Skip to content

Commit

Permalink
MCS: fallback to port 443 if 5228 is blocked
Browse files Browse the repository at this point in the history
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: #408
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
  • Loading branch information
matttbe committed Feb 4, 2022
1 parent 17b8371 commit 0bd1bc2
Showing 1 changed file with 31 additions and 16 deletions.
47 changes: 31 additions & 16 deletions play-services-core/src/main/java/org/microg/gms/gcm/McsService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand All @@ -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) {
Expand Down

0 comments on commit 0bd1bc2

Please sign in to comment.