mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(p2p-stats): show peer flags for DNS6 relay hostnames
Extract embedded IPv6 addresses from dns6 multiaddrs so geo lookup and country flags work for relay peers that publish IPv6 via DNS hostnames.
This commit is contained in:
+67
@@ -256,6 +256,73 @@ describe('P2PStatsSettings', () => {
|
|||||||
expect(fetchMock).toHaveBeenCalledWith('https://free.freeipapi.com/api/json/91.234.199.189', expect.objectContaining({ signal: expect.any(AbortSignal) }));
|
expect(fetchMock).toHaveBeenCalledWith('https://free.freeipapi.com/api/json/91.234.199.189', expect.objectContaining({ signal: expect.any(AbortSignal) }));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows peer country flags for DNS6 relay hostnames with embedded IPv6 addresses', async () => {
|
||||||
|
const fetchMock = vi.fn(async (url: string | URL | Request) => {
|
||||||
|
const requestUrl = String(url);
|
||||||
|
if (requestUrl === 'https://free.freeipapi.com/api/json/2a11%3A6100%3A0%3A5e9f%3A%3A0') {
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
json: async () => ({
|
||||||
|
cityName: 'Reykjavik',
|
||||||
|
countryCode: 'IS',
|
||||||
|
ipAddress: '2a11:6100:0:5e9f::0',
|
||||||
|
latitude: 64.1466,
|
||||||
|
longitude: -21.9426,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
json: async () => ({ country: 'US', ip: '147.75.84.175' }),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
vi.stubGlobal('fetch', fetchMock);
|
||||||
|
testState.account = {
|
||||||
|
...testState.account,
|
||||||
|
pkcOptions: {
|
||||||
|
libp2pJsClientsOptions: [{ key: 'libp2pjs' }],
|
||||||
|
},
|
||||||
|
pkc: {
|
||||||
|
clients: {
|
||||||
|
libp2pJsClients: {
|
||||||
|
libp2pjs: {
|
||||||
|
key: 'libp2pjs',
|
||||||
|
_helia: {
|
||||||
|
libp2p: {
|
||||||
|
getConnections: () => [
|
||||||
|
{
|
||||||
|
remoteAddr: {
|
||||||
|
toString: () => '/dns6/2a11-6100-0-5e9f--0.k51qzi5uqu5djg5pdoi9a98.example/tcp/443/ws/p2p/relay-peer/p2p-circuit/p2p/12D3KooWIPv6Peer',
|
||||||
|
},
|
||||||
|
remotePeer: { toString: () => '12D3KooWIPv6Peer' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
getMultiaddrs: () => ['/ip4/147.75.84.175/tcp/4001/ws'],
|
||||||
|
getPeers: () => ['12D3KooWIPv6Peer'],
|
||||||
|
peerId: { toString: () => 'self-peer' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await renderSettings(false);
|
||||||
|
await act(async () => {
|
||||||
|
await Promise.resolve();
|
||||||
|
await Promise.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
const connectedPeers = container.querySelector('[data-testid="connected-peers"]');
|
||||||
|
expect(connectedPeers?.textContent).toContain('WebSocket through relay');
|
||||||
|
expect(connectedPeers?.querySelector('img[aria-label="Iceland"]')).not.toBeNull();
|
||||||
|
expect(fetchMock).toHaveBeenCalledWith(
|
||||||
|
'https://free.freeipapi.com/api/json/2a11%3A6100%3A0%3A5e9f%3A%3A0',
|
||||||
|
expect.objectContaining({ signal: expect.any(AbortSignal) }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('shows the own IP flag and a red precise map marker when leeching', async () => {
|
it('shows the own IP flag and a red precise map marker when leeching', async () => {
|
||||||
const fetchMock = vi.fn(async (url: string | URL | Request) => {
|
const fetchMock = vi.fn(async (url: string | URL | Request) => {
|
||||||
const requestUrl = String(url);
|
const requestUrl = String(url);
|
||||||
|
|||||||
@@ -37,6 +37,13 @@ describe('extractIpv6FromAddress', () => {
|
|||||||
expect(extractIpv6FromAddress('/ip6/2001:4860:4860::8888/tcp/4001/ws')).toBe('2001:4860:4860::8888');
|
expect(extractIpv6FromAddress('/ip6/2001:4860:4860::8888/tcp/4001/ws')).toBe('2001:4860:4860::8888');
|
||||||
expect(extractIpFromAddress('/ip6/2001:4860:4860::8888/tcp/4001/ws')).toBe('2001:4860:4860::8888');
|
expect(extractIpFromAddress('/ip6/2001:4860:4860::8888/tcp/4001/ws')).toBe('2001:4860:4860::8888');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('extracts an IPv6 embedded with dashes in a DNS hostname', () => {
|
||||||
|
const address = '/dns6/2a11-6100-0-5e9f--0.k51qzi5uqu5djg5pdoi9a98.example/tcp/443/wss/p2p/12D3KooWExample';
|
||||||
|
|
||||||
|
expect(extractIpv6FromAddress(address)).toBe('2a11:6100:0:5e9f::0');
|
||||||
|
expect(extractIpFromAddress(address)).toBe('2a11:6100:0:5e9f::0');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isPrivateOrReservedIpv4', () => {
|
describe('isPrivateOrReservedIpv4', () => {
|
||||||
@@ -261,6 +268,31 @@ describe('fetchPeerMapLocation', () => {
|
|||||||
|
|
||||||
vi.unstubAllGlobals();
|
vi.unstubAllGlobals();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('resolves a peer location from a DNS6 hostname with an embedded IPv6', async () => {
|
||||||
|
const fetchMock = vi.fn().mockResolvedValue({
|
||||||
|
ok: true,
|
||||||
|
json: async () => ({
|
||||||
|
cityName: 'Reykjavik',
|
||||||
|
countryCode: 'IS',
|
||||||
|
ipAddress: '2a11:6100:0:5e9f::0',
|
||||||
|
latitude: 64.1466,
|
||||||
|
longitude: -21.9426,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
vi.stubGlobal('fetch', fetchMock);
|
||||||
|
|
||||||
|
await expect(fetchPeerMapLocation('/dns6/2a11-6100-0-5e9f--0.k51qzi5uqu5djg5pdoi9a98.example/tcp/443/wss')).resolves.toMatchObject({
|
||||||
|
countryCode: 'is',
|
||||||
|
label: 'Reykjavik, IS',
|
||||||
|
lat: 64.1466,
|
||||||
|
lon: -21.9426,
|
||||||
|
source: 'geoip',
|
||||||
|
});
|
||||||
|
expect(fetchMock.mock.calls[0][0]).toBe('https://free.freeipapi.com/api/json/2a11%3A6100%3A0%3A5e9f%3A%3A0');
|
||||||
|
|
||||||
|
vi.unstubAllGlobals();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getApproximateCountryCode', () => {
|
describe('getApproximateCountryCode', () => {
|
||||||
|
|||||||
+11
-1
@@ -284,7 +284,17 @@ export const extractIpv4FromAddress = (address: string): string | null => {
|
|||||||
|
|
||||||
export const extractIpv6FromAddress = (address: string): string | null => {
|
export const extractIpv6FromAddress = (address: string): string | null => {
|
||||||
const direct = /\/ip6\/([^/]+)/.exec(address);
|
const direct = /\/ip6\/([^/]+)/.exec(address);
|
||||||
return direct ? direct[1] : null;
|
if (direct) return direct[1];
|
||||||
|
const dns = /\/dns6\/([^/]+)/i.exec(address);
|
||||||
|
const firstLabel = dns?.[1]?.split('.')[0];
|
||||||
|
if (!firstLabel || !firstLabel.includes('-') || !/^[0-9a-f-]+$/i.test(firstLabel)) return null;
|
||||||
|
const candidate = firstLabel.replaceAll('-', ':').toLowerCase();
|
||||||
|
try {
|
||||||
|
new URL(`http://[${candidate}]/`);
|
||||||
|
return candidate;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseOctets = (ip: string): number[] | null => {
|
const parseOctets = (ip: string): number[] | null => {
|
||||||
|
|||||||
Reference in New Issue
Block a user