Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ipv6 conncheck optional, and only display ipv6 when available #244

Merged
merged 1 commit into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/composables/useConnection.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { InjectionKey, Ref, ref } from 'vue';
import type { Connection } from '@/helpers/connCheck.types';
import { connCheck } from '@/helpers/connCheck';
import { connCheckIpv4, connCheckIpv6 } from '@/helpers/connCheck';

// Keep this outside of the hook to make it a singleton
const connection = ref({} as Connection);
Expand All @@ -14,7 +14,21 @@ const useConnection = () => {
isError.value = false;
error.value = undefined;
try {
connection.value = await connCheck();
const ipv4Promise = connCheckIpv4();
const ipv6Promise = connCheckIpv6();

// Wait for IPv4 result
connection.value = await ipv4Promise;

// Because IPV6 is not reliably working in socks proxy,
// don't wait IPv6 result so that it's non-blocking.
ipv6Promise
.then((ipv6) => {
connection.value = { ...connection.value, ipv6 };
})
.catch((e) => {
console.log(`IPv6 check error: ${e.message}`);
});
} catch (e) {
console.log({ useConnectionError: e });
isError.value = true;
Expand Down
45 changes: 23 additions & 22 deletions src/helpers/connCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import type {
} from '@/helpers/connCheck.types';

/*
n is an optional parameter to retry the connCheck any number of time.

By default, it will retry twice because after connecting/disconnecting to/from Mullvad server, the first request results in a NetworkError and the second is successful.

It's a workaround for the following bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1706377
Workaround can be removed when Mullvad Browser 14.0 is released (the bug is fixed!).
*/
const MAX_RETRIES = 3;

export const connCheck = async (n = 3): Promise<Connection> => {
export const connCheckIpv4 = async (retries = MAX_RETRIES): Promise<Connection> => {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 6000);
Expand All @@ -28,34 +27,36 @@ export const connCheck = async (n = 3): Promise<Connection> => {
clearTimeout(timeoutId);
const data: Ipv4ServerResponse = await response.json();

let ipv6;
try {
const ipv6Response = await fetch('https://ipv6.am.i.mullvad.net/json', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
const ipv6Data: AmIMullvadServerResponse = await ipv6Response.json();
ipv6 = ipv6Data.ip;
} catch (e) {
if (__DEV__) {
console.log(`[conCheck IPv6]: Error trying to get ipv6 data: ${(e as Error).message}`);
}
}

return {
city: data.city,
country: data.country,
ip: data.ip,
ipv6,
server: data.mullvad_exit_ip_hostname,
protocol: data.mullvad_server_type,
provider: data.organization,
isMullvad: data.mullvad_exit_ip ?? false,
};
} catch (error) {
if (n === 1) throw new Error('Connection check failed.');
return connCheck(n - 1);
if (retries === 1) throw new Error('IPv4 connection check failed.');
return connCheckIpv4(retries - 1);
}
};

export const connCheckIpv6 = async (retries = MAX_RETRIES): Promise<string | undefined> => {
try {
const response = await fetch('https://ipv6.am.i.mullvad.net/json', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
const data: AmIMullvadServerResponse = await response.json();
return data.ip;
} catch (e) {
if (__DEV__) {
console.log(`[conCheck IPv6]: Error trying to get ipv6 data: ${(e as Error).message}`);
}
if (retries === 1) return undefined;
return connCheckIpv6(retries - 1);
}
};
Loading