Skip to content

Commit e2e18bd

Browse files
committed
feat: migrate to 443 port for relays
1 parent 0c94457 commit e2e18bd

4 files changed

Lines changed: 47 additions & 11 deletions

File tree

lib/app/features/ion_connect/providers/mixins/relay_create_mixin.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import 'dart:async';
44
import 'dart:io' hide WebSocket;
55

6+
import 'package:collection/collection.dart';
67
import 'package:hooks_riverpod/hooks_riverpod.dart';
78
import 'package:ion/app/exceptions/exceptions.dart';
89
import 'package:ion/app/features/core/providers/internet_connection_checker_provider.r.dart';
@@ -46,9 +47,8 @@ mixin RelayCreateMixin {
4647

4748
lastConnectionState = connectionState;
4849

49-
final usedDomain = proxyDomains.firstWhere(
50+
final usedDomain = proxyDomains.firstWhereOrNull(
5051
(d) => connectUri.host.endsWith(d),
51-
orElse: () => '',
5252
);
5353

5454
final hasInternetConnection = ref.read(hasInternetConnectionProvider);
@@ -62,7 +62,7 @@ mixin RelayCreateMixin {
6262
// If we connected directly (no proxy domain), clear any previously saved preference.
6363
ref
6464
.read(relayProxyDomainPreferenceProvider(url).notifier)
65-
.persistPreferredProxyDomain(usedDomain.isEmpty ? null : usedDomain);
65+
.persistPreferredProxyDomain(usedDomain);
6666

6767
await ref.read(relayReachabilityProvider.notifier).clear(url);
6868
return relay;

lib/app/features/ion_connect/providers/relays/relay_proxy_domains_provider.r.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,17 @@ List<String> relaysProxyDomains(Ref ref) {
2828
/// Candidates are returned in the following order:
2929
/// 1) Preferred proxy URI (if saved for this logical relay)
3030
/// 2) The original logical relay URI (direct IP)
31-
/// 3) Remaining proxy URIs built as `wss://<sha256(ip)[0:16]>.443`
31+
/// 3) Remaining proxy URIs built as `wss://<sha256(ip)[0:16]>.domain:443`
3232
@riverpod
3333
List<Uri> relayConnectUris(Ref ref, String logicalRelayUrl) {
3434
final logicalUri = Uri.parse(logicalRelayUrl);
35+
final normalizedLogicalUri =
36+
(logicalUri.hasPort && logicalUri.port == 4443) ? logicalUri.replace(port: 443) : logicalUri;
3537
final ip = logicalUri.host;
3638

3739
// If we can't extract an IP/host, fall back to the original URI only.
3840
if (ip.isEmpty) {
39-
return <Uri>[logicalUri];
41+
return <Uri>[normalizedLogicalUri];
4042
}
4143

4244
final domains = ref.read(relaysProxyDomainsProvider);
@@ -47,9 +49,9 @@ List<Uri> relayConnectUris(Ref ref, String logicalRelayUrl) {
4749
final normalizedIp = hashHex.substring(0, 16);
4850

4951
Uri proxyUriForDomain(String domain) => Uri(
50-
scheme: logicalUri.scheme.isNotEmpty ? logicalUri.scheme : 'wss',
52+
scheme: normalizedLogicalUri.scheme.isNotEmpty ? normalizedLogicalUri.scheme : 'wss',
5153
host: '$normalizedIp.$domain',
52-
port: 443,
54+
port: normalizedLogicalUri.hasPort ? normalizedLogicalUri.port : null,
5355
);
5456

5557
final candidates = <Uri>[];
@@ -60,7 +62,7 @@ List<Uri> relayConnectUris(Ref ref, String logicalRelayUrl) {
6062
}
6163

6264
// Then try direct IP.
63-
candidates.add(logicalUri);
65+
candidates.add(normalizedLogicalUri);
6466

6567
// Then try the rest of proxy domains.
6668
for (final domain in domains) {

lib/app/features/user/providers/relays/user_relays_manager.r.dart

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,35 @@ class UserRelaysManager extends _$UserRelaysManager {
238238
}
239239
}
240240

241+
String normalizeRelayUrl(String raw) {
242+
final trimmed = raw.trim();
243+
if (trimmed.isEmpty) return trimmed;
244+
245+
try {
246+
final uri = Uri.parse(trimmed);
247+
248+
// Migration: old relays used :4443, new standard is :443.
249+
if (uri.hasPort && uri.port == 4443) {
250+
return uri.replace(port: 443).toString();
251+
}
252+
253+
return uri.toString();
254+
} catch (_) {
255+
// If parsing fails, keep the original string.
256+
return trimmed;
257+
}
258+
}
259+
241260
@riverpod
242261
Future<UserRelaysEntity?> currentUserRelays(Ref ref) async {
243262
final identityConnectRelays = await ref.watch(currentUserIdentityConnectRelaysProvider.future);
244263
if (identityConnectRelays == null) {
245264
return null;
246265
}
247-
final updatedUserRelays = UserRelaysData(list: identityConnectRelays);
266+
267+
final updatedUserRelays = UserRelaysData(
268+
list: identityConnectRelays.map((r) => r.copyWith(url: normalizeRelayUrl(r.url))).toList(),
269+
);
248270
final userRelaysEvent =
249271
await ref.read(ionConnectNotifierProvider.notifier).sign(updatedUserRelays);
250272

@@ -254,7 +276,7 @@ Future<UserRelaysEntity?> currentUserRelays(Ref ref) async {
254276
extension IonConnectRelayInfoToUserRelay on IonConnectRelayInfo {
255277
UserRelay toUserRelay() {
256278
return UserRelay(
257-
url: url,
279+
url: normalizeRelayUrl(url),
258280
write: type == null || type == IonConnectRelayType.write,
259281
read: type == null || type == IonConnectRelayType.read,
260282
);

packages/ion_identity_client/lib/src/users/available_ion_connect_relays/data_sources/available_ion_connect_relays_data_source.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@ import 'package:ion_identity_client/src/core/storage/token_storage.dart';
77
import 'package:ion_identity_client/src/core/types/request_headers.dart';
88
import 'package:ion_identity_client/src/users/available_ion_connect_relays/models/available_ion_connect_relays_response.f.dart';
99

10+
String normalizeRelayUrlNo443(String raw) {
11+
final uri = Uri.tryParse(raw.trim());
12+
if (uri == null) return raw.trim();
13+
14+
// Only strip explicit :443 for secure websockets.
15+
if (uri.scheme == 'wss' && uri.hasPort && uri.port == 443) {
16+
return uri.replace(port: 0).toString(); // port:0 removes the explicit port
17+
}
18+
19+
return uri.toString();
20+
}
21+
1022
class AvailableIONConnectRelaysDataSource {
1123
AvailableIONConnectRelaysDataSource(
1224
this._networkClient,
@@ -33,7 +45,7 @@ class AvailableIONConnectRelaysDataSource {
3345
headers: RequestHeaders.getTokenHeader(
3446
token: token.token,
3547
),
36-
queryParams: {'ion-connect-relay': relayUrl},
48+
queryParams: {'ion-connect-relay': normalizeRelayUrlNo443(relayUrl)},
3749
decoder: (result, _) =>
3850
parseJsonObject(result, fromJson: AvailableIONConnectRelaysResponse.fromJson),
3951
);

0 commit comments

Comments
 (0)