diff --git a/src/services/spr.ts b/src/services/spr.ts index 5a420a0..7668719 100644 --- a/src/services/spr.ts +++ b/src/services/spr.ts @@ -10,6 +10,7 @@ import { CECSlot } from '@/models/cec-slot'; import { SendMode } from '@/types/common/spr-slot'; import RequestException from '@/request-exception'; import type { SPRSlot } from '@/types/common/spr-slot'; +import { LOG_WARN, LOG_INFO } from '@/logger'; const spr = express.Router(); @@ -81,19 +82,21 @@ spr.post('/relay/0', multipartParser, async (request, response) => { } if (!request.pid || !request.nexAccount) { - response.sendStatus(400); + response.sendStatus(401); return; } // * Check that the account is a 3DS and isn't banned if (!request.nexAccount.friendCode || request.nexAccount.accessLevel < 0) { - response.sendStatus(400); + LOG_INFO(`{request.pid}: User is banned`); + response.sendStatus(403); return; } const sprMetadataBuffer: Buffer | undefined = request.files['spr-meta']; if (!sprMetadataBuffer) { + LOG_WARN(`{request.pid}: Missing spr-meta file`); response.sendStatus(400); return; } @@ -105,6 +108,7 @@ spr.post('/relay/0', multipartParser, async (request, response) => { const metadataHeaders = sprMetadata.split('\r\n'); // * Split header lines if (metadataHeaders.length < 1) { + LOG_WARN(`{request.pid}: spr-meta file is too short / empty`); response.sendStatus(400); return; } @@ -113,6 +117,7 @@ spr.post('/relay/0', multipartParser, async (request, response) => { const metadataHeader = metadataHeaders[i]; const [header, value] = metadataHeader.split(': '); // * Split header and value if (!header || !value) { + LOG_WARN(`{request.pid}: Bad spr-meta entry`); response.sendStatus(400); return; } @@ -121,6 +126,7 @@ spr.post('/relay/0', multipartParser, async (request, response) => { // * we can guarantee that i must match with the slot we are looking at except for 0, which will be the slotsize if (i === 0) { if (header !== 'slotsize') { + LOG_WARN(`{request.pid}: spr-meta missing slotsize`); response.sendStatus(400); return; } @@ -130,12 +136,14 @@ spr.post('/relay/0', multipartParser, async (request, response) => { try { slotsize = parseInt(value); } catch { + LOG_WARN(`{request.pid}: Invalid spr-meta slotsize`); response.sendStatus(400); return; } // * We don't count the slotsize header itself in the slot count if (slotsize !== (metadataHeaders.length - 1)) { + LOG_WARN(`{request.pid}: Bad spr-meta slotsize`); response.sendStatus(400); return; } @@ -146,6 +154,7 @@ spr.post('/relay/0', multipartParser, async (request, response) => { const metadata = value.split(','); // * Split the value to get the metadata if (metadata.length !== 3) { + LOG_WARN(`{request.pid}: Bad spr-meta entry param count`); response.sendStatus(400); return; } @@ -158,6 +167,7 @@ spr.post('/relay/0', multipartParser, async (request, response) => { gameID = parseInt(metadata[1], 16); size = parseInt(metadata[2]); } catch { + LOG_WARN(`{request.pid}: Invalid spr-meta entry params`); response.sendStatus(400); return; } @@ -168,11 +178,13 @@ spr.post('/relay/0', multipartParser, async (request, response) => { const slotData: Buffer | undefined = request.files['spr-slot' + slot]; if (!slotData) { + LOG_WARN(`{request.pid}: Missing slot data file`); response.sendStatus(400); return; } if (slotData.length !== size) { + LOG_WARN(`{request.pid}: Invalid slot data size`); response.sendStatus(400); return; } @@ -187,21 +199,25 @@ spr.post('/relay/0', multipartParser, async (request, response) => { // * Check that we at least have enough size for the StreetPass header if (slotData.length < 0x12) { + LOG_WARN(`{request.pid}: Slot is too short`); response.sendStatus(400); return; } if (slotData.readUInt32LE() !== 0x6161) { + LOG_WARN(`{request.pid}: Slot header missmatch`); response.sendStatus(400); return; } if (slotData.readUInt32LE(4) !== size) { + LOG_WARN(`{request.pid}: Slot bad size`); response.sendStatus(400); return; } if (slotData.readUInt32LE(8) !== gameID) { + LOG_WARN(`{request.pid}: Slot bad gameID`); response.sendStatus(400); return; }