feat: Introduce StreetPass Relays

StreetPass Relay allows 3DS users to exchange StreetPass data over the
Internet. This is handled through SpotPass, and no user interaction is
required.

Also reenable the user agent checks as it's needed to identify the user
using the PID present on it.
This commit is contained in:
Daniel López Guimaraes
2024-04-27 00:03:32 +01:00
parent 16a762b972
commit 5f83d7a655
14 changed files with 490 additions and 41 deletions

View File

@@ -1,5 +1,5 @@
import express from 'express';
import RequestException from '@/request-exception';
// import RequestException from '@/request-exception';
import type { UserAgentInfo } from '@/types/common/user-agent-info';
const FIRMWARE_PATCH_REGION_WIIU_REGEX = /(\d)([JEU])/;
@@ -8,7 +8,9 @@ export default function parseUserAgentMiddleware(request: express.Request, respo
const userAgent = request.header('user-agent');
if (!userAgent) {
return next(new RequestException('Missing or invalid user agent', 400));
// TODO - Error when no user agent is given!
// return next(new RequestException('Missing or invalid user agent', 400));
return next();
}
let result: UserAgentInfo | null = null;
@@ -20,7 +22,9 @@ export default function parseUserAgentMiddleware(request: express.Request, respo
}
if (!result) {
return next(new RequestException('Missing or invalid user agent', 400));
// TODO - Error when invalid user agent is given!
// return next(new RequestException('Missing or invalid user agent', 400));
return next();
}
request.pid = result.userPID;
@@ -85,10 +89,10 @@ function parse3DS(userAgent: string): UserAgentInfo | null {
return null;
}
const [bossLibraryInfo, userInfo, firmwareVersion, unknownPart1, unknownPart2] = parts;
const [bossLibraryInfo, userInfo, firmwareVersion, ctrSdkVersion, consoleModel] = parts;
const [bossLibraryName, bossLibraryVersion] = bossLibraryInfo.split('-');
const [bossLibraryVersionMajor, bossLibraryVersionMinor] = bossLibraryVersion.split('.');
const [unknownUserInfo1Hex, unknownUserInfo2Hex] = userInfo.split('-');
const [localFriendCodeSeedHex, friendCodeHex] = userInfo.split('-');
const [firmwareMajor, firmwareMinor, firmwarePatchAndRegion] = firmwareVersion.split('.');
if (
@@ -98,38 +102,34 @@ function parse3DS(userAgent: string): UserAgentInfo | null {
firmwareMajor !== '11' ||
firmwareMinor !== '17' ||
!['0-50J', '0-50U', '0-50E'].includes(firmwarePatchAndRegion) || // TODO - Make this more dynamic?
unknownPart1 !== '62452' || // TODO - Is this right?
!unknownPart2 || // TODO - Actually check this
unknownUserInfo1Hex.length !== 16 ||
unknownUserInfo2Hex.length !== 16
ctrSdkVersion !== '62452' ||
!consoleModel || // TODO - Actually check this
localFriendCodeSeedHex.length !== 16 ||
friendCodeHex.length !== 16
) {
return null;
}
let unknownUserInfo1: number;
let unknownUserInfo2: number;
let localFriendCodeSeed: bigint;
let friendCode: bigint;
// TODO - Parse this data? What is this?
try {
unknownUserInfo1 = parseInt(unknownUserInfo1Hex, 16);
localFriendCodeSeed = BigInt('0x' + localFriendCodeSeedHex); // * Parse hex string to bigint
} catch {
return null;
}
// TODO - Validate the friend code
try {
unknownUserInfo2 = parseInt(unknownUserInfo2Hex, 16);
friendCode = BigInt('0x' + friendCodeHex); // * Parse hex string to bigint
} catch {
return null;
}
// TODO - What is the upper 4 bytes?
const localFriendCodeSeed = (unknownUserInfo1 & 0xFFFFFFFF); // * LFCS is the lower 4 bytes
// TODO - What is the upper 4 bytes?
const userPID = (unknownUserInfo2 & 0xFFFFFFFF); // * PID is the lower 4 bytes
const userPID = Number(friendCode & 0xFFFFFFFFn); // * PID is the lower 4 bytes
return {
localFriendCodeSeed,
userPID
};
}
}