From 1337fc21f364caaa66a83aae411476da61673fda Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 7 Mar 2019 23:23:25 -0500 Subject: [PATCH] Apply Prettier --- src/aimedb/cmd.js | 159 ++++++++++++++++--------------- src/aimedb/cmd.test.js | 133 +++++++++++++++++++------- src/aimedb/frame.js | 30 +++--- src/aimedb/index.js | 68 ++++++------- src/aimedb/pipeline.js | 32 +++---- src/billing.js | 116 +++++++++++----------- src/chunithm.js | 212 +++++++++++++++++++++-------------------- src/index.js | 30 +++--- src/startup.js | 100 +++++++++---------- 9 files changed, 480 insertions(+), 400 deletions(-) diff --git a/src/aimedb/cmd.js b/src/aimedb/cmd.js index af07f0b..259ba6a 100644 --- a/src/aimedb/cmd.js +++ b/src/aimedb/cmd.js @@ -1,4 +1,4 @@ -const { Transform } = require('stream') +const { Transform } = require("stream"); class Decoder extends Transform { constructor(options) { @@ -6,84 +6,91 @@ class Decoder extends Transform { readableObjectMode: true, writableObjectMode: true, ...options, - }) + }); } static ident(chunk) { - const gameId = chunk.toString('ascii', 0x000A, 0x000E) - const keychipId = chunk.toString('ascii', 0x0014, 0x001F) + const gameId = chunk.toString("ascii", 0x000a, 0x000e); + const keychipId = chunk.toString("ascii", 0x0014, 0x001f); - return { gameId, keychipId } + return { gameId, keychipId }; } static cardId(chunk) { - const luid = chunk.slice(0x0020, 0x002A) + const luid = chunk.slice(0x0020, 0x002a); - return { luid, ...Decoder.ident(chunk) } + return { luid, ...Decoder.ident(chunk) }; } static log(chunk) { // idk what any of this stuff means yet // field20 and field28 appear to be an aime id but that is all. - const field20 = chunk.readUInt32LE(0x20) - const field24 = chunk.readUInt32LE(0x24) - const field28 = chunk.readUInt32LE(0x28) - const field2C = chunk.readUInt32LE(0x2C) - const field30 = chunk.readUInt32LE(0x30) - const field34 = chunk.readUInt32LE(0x34) - const field38 = chunk.readUInt32LE(0x38) - const field3C = chunk.readUInt32LE(0x3C) + const field20 = chunk.readUInt32LE(0x20); + const field24 = chunk.readUInt32LE(0x24); + const field28 = chunk.readUInt32LE(0x28); + const field2C = chunk.readUInt32LE(0x2c); + const field30 = chunk.readUInt32LE(0x30); + const field34 = chunk.readUInt32LE(0x34); + const field38 = chunk.readUInt32LE(0x38); + const field3C = chunk.readUInt32LE(0x3c); return { - field20, field24, field28, field2C, field30, field34, field38, field3C, - ...Decoder.ident(chunk) - } + field20, + field24, + field28, + field2C, + field30, + field34, + field38, + field3C, + ...Decoder.ident(chunk), + }; } _transform(chunk, encoding, callback) { - const cmd = chunk.readUInt16LE(0x04) + const cmd = chunk.readUInt16LE(0x04); switch (cmd) { case 0x0005: return callback(null, { - cmd: 'register', + cmd: "register", ...Decoder.cardId(chunk), - }) + }); case 0x0009: return callback(null, { - cmd: 'log', + cmd: "log", ...Decoder.log(chunk), - }) + }); - case 0x000B: + case 0x000b: return callback(null, { - cmd: 'campaign', + cmd: "campaign", ...Decoder.ident(chunk), - }) + }); - case 0x000F: + case 0x000f: return callback(null, { - cmd: 'lookup', + cmd: "lookup", ...Decoder.cardId(chunk), - }) + }); case 0x0064: return callback(null, { - cmd: 'hello', - ...Decoder.ident(chunk) - }) + cmd: "hello", + ...Decoder.ident(chunk), + }); case 0x0066: return callback(null, { - cmd: 'goodbye', - }) + cmd: "goodbye", + }); default: return callback(null, { cmd: `unknown_${cmd}`, - }) + }); } } } @@ -94,78 +101,78 @@ class Encoder extends Transform { readableObjectMode: true, writableObjectMode: true, ...options, - }) + }); } static init(length) { - const buf = Buffer.alloc(length) + const buf = Buffer.alloc(length); - buf.writeUInt16LE(0xA13E, 0x0000) // Magic? - buf.writeUInt16LE(0x3087, 0x0002) // ??? - buf.writeUInt16LE(length, 0x0006) + buf.writeUInt16LE(0xa13e, 0x0000); // Magic? + buf.writeUInt16LE(0x3087, 0x0002); // ??? + buf.writeUInt16LE(length, 0x0006); - return buf + return buf; } _transform(chunk, encoding, callback) { - console.log('Aimedb: Encode', chunk) + console.log("Aimedb: Encode", chunk); - let buf + let buf; switch (chunk.cmd) { - case 'hello': - buf = Encoder.init(0x0020) - buf.writeUInt16LE(0x0065, 0x0004) // cmd code - buf.writeUInt16LE(chunk.status, 0x0008) + case "hello": + buf = Encoder.init(0x0020); + buf.writeUInt16LE(0x0065, 0x0004); // cmd code + buf.writeUInt16LE(chunk.status, 0x0008); - break + break; - case 'campaign': + case "campaign": // Still figuring this out... - buf = Encoder.init(0x0200) - buf.writeUInt16LE(0x000C, 0x0004) // cmd code - buf.writeUInt16LE(chunk.status, 0x0008) + buf = Encoder.init(0x0200); + buf.writeUInt16LE(0x000c, 0x0004); // cmd code + buf.writeUInt16LE(chunk.status, 0x0008); // Campaign array starts at 0x20 // Element size is 0xA0 - break + break; - case 'lookup': + case "lookup": // -1 aime id means card is not registered // register level does not seem to matter - buf = Encoder.init(0x0130) - buf.writeUInt16LE(0x0010, 0x0004) // cmd code - buf.writeUInt16LE(chunk.status, 0x0008) - buf.writeInt32LE(chunk.aimeId || -1, 0x0020) - buf.writeUInt8(Encoder.registerLevels[chunk.registerLevel], 0x0024) + buf = Encoder.init(0x0130); + buf.writeUInt16LE(0x0010, 0x0004); // cmd code + buf.writeUInt16LE(chunk.status, 0x0008); + buf.writeInt32LE(chunk.aimeId || -1, 0x0020); + buf.writeUInt8(Encoder.registerLevels[chunk.registerLevel], 0x0024); - break + break; - case 'register': - buf = Encoder.init(0x0030) - buf.writeUInt16LE(0x0006, 0x0004) // cmd code - buf.writeUInt16LE(chunk.status, 0x0008) - buf.writeInt32LE(chunk.aimeId, 0x0020) + case "register": + buf = Encoder.init(0x0030); + buf.writeUInt16LE(0x0006, 0x0004); // cmd code + buf.writeUInt16LE(chunk.status, 0x0008); + buf.writeInt32LE(chunk.aimeId, 0x0020); - break + break; - case 'log': - buf = Encoder.init(0x0020) - buf.writeUInt16LE(0x000A, 0x0004) // cmd code - buf.writeUInt16LE(chunk.status, 0x0008) + case "log": + buf = Encoder.init(0x0020); + buf.writeUInt16LE(0x000a, 0x0004); // cmd code + buf.writeUInt16LE(chunk.status, 0x0008); - break + break; default: - return callback(new Error(`Unimplemented response: ${cmd}`)) + return callback(new Error(`Unimplemented response: ${cmd}`)); } - console.log('Aimedb: Send', buf) + console.log("Aimedb: Send", buf); - return callback(null, buf) + return callback(null, buf); } } @@ -173,9 +180,9 @@ Encoder.registerLevels = { none: 0, portal: 1, segaid: 2, -} +}; module.exports = { Decoder, Encoder, -} +}; diff --git a/src/aimedb/cmd.test.js b/src/aimedb/cmd.test.js index 031cb56..55f3dd2 100644 --- a/src/aimedb/cmd.test.js +++ b/src/aimedb/cmd.test.js @@ -1,47 +1,114 @@ -const { Decoder } = require('./cmd') +const { Decoder } = require("./cmd"); function decode(req) { - const decoder = new Decoder() + const decoder = new Decoder(); - decoder.write(req) + decoder.write(req); - return decoder.read() + return decoder.read(); } -test('decode hello', () => { +test("decode hello", () => { const req = Buffer.from([ - 0x3e, 0xa1, 0x87, 0x30, 0x64, 0x00, 0x20, 0x00, - 0x00, 0x00, 0x53, 0x44, 0x42, 0x54, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x41, 0x36, 0x39, 0x45, - 0x30, 0x31, 0x41, 0x39, 0x39, 0x39, 0x39, 0x00, - ]) + 0x3e, + 0xa1, + 0x87, + 0x30, + 0x64, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x53, + 0x44, + 0x42, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x41, + 0x36, + 0x39, + 0x45, + 0x30, + 0x31, + 0x41, + 0x39, + 0x39, + 0x39, + 0x39, + 0x00, + ]); - const obj = decode(req) + const obj = decode(req); - expect(obj.cmd).toBe('hello') - expect(obj.gameId).toBe('SDBT') - expect(obj.keychipId).toBe('A69E01A9999') -}) + expect(obj.cmd).toBe("hello"); + expect(obj.gameId).toBe("SDBT"); + expect(obj.keychipId).toBe("A69E01A9999"); +}); -test('decode lookup', () => { +test("decode lookup", () => { const req = Buffer.from([ - 0x3e, 0xa1, 0x87, 0x30, 0x0f, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x53, 0x44, 0x42, 0x54, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x41, 0x36, 0x39, 0x45, - 0x30, 0x31, 0x41, 0x39, 0x39, 0x39, 0x39, 0x00, - 0x01, 0x03, 0x64, 0x95, 0x85, 0x05, 0x23, 0x03, - 0x06, 0x76, 0x01, 0x02, 0x22, 0xc6, 0x4e, 0x00, - ]) + 0x3e, + 0xa1, + 0x87, + 0x30, + 0x0f, + 0x00, + 0x30, + 0x00, + 0x00, + 0x00, + 0x53, + 0x44, + 0x42, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x41, + 0x36, + 0x39, + 0x45, + 0x30, + 0x31, + 0x41, + 0x39, + 0x39, + 0x39, + 0x39, + 0x00, + 0x01, + 0x03, + 0x64, + 0x95, + 0x85, + 0x05, + 0x23, + 0x03, + 0x06, + 0x76, + 0x01, + 0x02, + 0x22, + 0xc6, + 0x4e, + 0x00, + ]); - const obj = decode(req) + const obj = decode(req); - expect(obj.cmd).toBe('lookup') - expect(obj.gameId).toBe('SDBT') - expect(obj.keychipId).toBe('A69E01A9999') + expect(obj.cmd).toBe("lookup"); + expect(obj.gameId).toBe("SDBT"); + expect(obj.keychipId).toBe("A69E01A9999"); expect(obj.luid).toEqual( - Buffer.from([ - 0x01, 0x03, 0x64, 0x95, 0x85, 0x05, 0x23, 0x03, - 0x06, 0x76, - ]) - ) -}) + Buffer.from([0x01, 0x03, 0x64, 0x95, 0x85, 0x05, 0x23, 0x03, 0x06, 0x76]) + ); +}); diff --git a/src/aimedb/frame.js b/src/aimedb/frame.js index 67227a2..846d49f 100644 --- a/src/aimedb/frame.js +++ b/src/aimedb/frame.js @@ -1,44 +1,44 @@ -const { Transform } = require('stream') +const { Transform } = require("stream"); class Deframer extends Transform { constructor(options) { super({ readableObjectMode: true, ...options, - }) + }); - this.state = Buffer.alloc(0) + this.state = Buffer.alloc(0); } _transform(chunk, encoding, callback) { - this.state = Buffer.concat([ this.state, chunk ]) + this.state = Buffer.concat([this.state, chunk]); if (this.state.length < 8) { - return + return; } - const magic = this.state.readUInt16LE(0x0000) + const magic = this.state.readUInt16LE(0x0000); - if (magic != 0xA13E) { - return callback(new Error(`Invalid magic (decimal ${magic})`)) + if (magic != 0xa13e) { + return callback(new Error(`Invalid magic (decimal ${magic})`)); } - const len = this.state.readUInt16LE(0x0006) + const len = this.state.readUInt16LE(0x0006); if (this.state.length < len) { - return + return; } - const frame = this.state.slice(0, len) + const frame = this.state.slice(0, len); - console.log('Aimedb: Recv', frame) + console.log("Aimedb: Recv", frame); - this.state = this.state.slice(len) + this.state = this.state.slice(len); - return callback(null, frame) + return callback(null, frame); } } module.exports = { Deframer, -} +}; diff --git a/src/aimedb/index.js b/src/aimedb/index.js index 381c13e..92d2921 100644 --- a/src/aimedb/index.js +++ b/src/aimedb/index.js @@ -1,66 +1,66 @@ -const setup = require('./pipeline') +const setup = require("./pipeline"); async function aimedb(socket) { - console.log('Aimedb: Connection opened') + console.log("Aimedb: Connection opened"); - const { input, output } = setup(socket) + const { input, output } = setup(socket); try { for await (const req of input) { - console.log('Aimedb: Decode', req) + console.log("Aimedb: Decode", req); - const { cmd } = req + const { cmd } = req; switch (cmd) { - case 'hello': - console.log('Aimedb: Hello') - output.write({ cmd, status: 1 }) + case "hello": + console.log("Aimedb: Hello"); + output.write({ cmd, status: 1 }); - break + break; - case 'campaign': - console.log('Aimedb: Campaign stuff') - output.write({ cmd, status: 1 }) + case "campaign": + console.log("Aimedb: Campaign stuff"); + output.write({ cmd, status: 1 }); - break + break; - case 'lookup': - console.log('Aimedb: Mifare lookup', req.luid) - output.write({ cmd, status: 1 }) // Add aimeId if desired + case "lookup": + console.log("Aimedb: Mifare lookup", req.luid); + output.write({ cmd, status: 1 }); // Add aimeId if desired - break + break; - case 'register': + case "register": // We get sent here if lookup does not return an aimeId - console.log('Aimedb: Mifare register', req.luid) - output.write({ cmd, status: 1, aimeId: 12345678 }) + console.log("Aimedb: Mifare register", req.luid); + output.write({ cmd, status: 1, aimeId: 12345678 }); - break + break; - case 'log': - console.log('Aimedb: Log message') - output.write({ cmd, status: 1 }) + case "log": + console.log("Aimedb: Log message"); + output.write({ cmd, status: 1 }); - break + break; - case 'goodbye': - console.log('Aimedb: Goodbye') + case "goodbye": + console.log("Aimedb: Goodbye"); - break + break; default: - console.log('Aimedb: Handler not implemented!') + console.log("Aimedb: Handler not implemented!"); - break + break; } } } catch (e) { - console.log('Aimedb: Connection error:\n', e) + console.log("Aimedb: Connection error:\n", e); } - console.log('Aimedb: Connection closed\n') - socket.end() + console.log("Aimedb: Connection closed\n"); + socket.end(); } -module.exports = aimedb +module.exports = aimedb; diff --git a/src/aimedb/pipeline.js b/src/aimedb/pipeline.js index a737644..77ce5c7 100644 --- a/src/aimedb/pipeline.js +++ b/src/aimedb/pipeline.js @@ -1,32 +1,28 @@ -const crypto = require('crypto') -const { pipeline } = require('stream') +const crypto = require("crypto"); +const { pipeline } = require("stream"); -const { Deframer } = require('./frame') -const { Decoder, Encoder } = require('./cmd') +const { Deframer } = require("./frame"); +const { Decoder, Encoder } = require("./cmd"); -const K = Buffer.from('Copyright(C)SEGA', 'utf8') +const K = Buffer.from("Copyright(C)SEGA", "utf8"); function setup(socket) { const input = pipeline( socket, - crypto - .createDecipheriv('aes-128-ecb', K, null) - .setAutoPadding(false), + crypto.createDecipheriv("aes-128-ecb", K, null).setAutoPadding(false), new Deframer(), - new Decoder(), - ) + new Decoder() + ); - const output = new Encoder() + const output = new Encoder(); pipeline( output, - crypto - .createCipheriv('aes-128-ecb', K, null) - .setAutoPadding(false), - socket, - ) + crypto.createCipheriv("aes-128-ecb", K, null).setAutoPadding(false), + socket + ); - return { input, output } + return { input, output }; } -module.exports = setup +module.exports = setup; diff --git a/src/billing.js b/src/billing.js index e6676e9..610c8c4 100644 --- a/src/billing.js +++ b/src/billing.js @@ -1,77 +1,79 @@ -const bodyParser = require('body-parser') -const express = require('express') -const crypto = require('crypto') -const zlib = require('zlib') -const fs = require('fs') +const bodyParser = require("body-parser"); +const express = require("express"); +const crypto = require("crypto"); +const zlib = require("zlib"); +const fs = require("fs"); -const billingKeyPair = fs.readFileSync('pki/billing.key') +const billingKeyPair = fs.readFileSync("pki/billing.key"); -const playlimit = 1024 -const nearfull = 0x00010200 +const playlimit = 1024; +const nearfull = 0x00010200; // nearfull: high 16 bits is billing mode, low 16 bits is actual nearfull val. -const app = express() +const app = express(); function decodeRequest(buf) { - const reqBytes = zlib.inflateRawSync(buf) - const reqStr = reqBytes.toString() + const reqBytes = zlib.inflateRawSync(buf); + const reqStr = reqBytes.toString(); - return reqStr.trim().split('\r\n').map(line => { - // Crack key-value pairs + return reqStr + .trim() + .split("\r\n") + .map(line => { + // Crack key-value pairs - const params = {} + const params = {}; - for (const kvp of line.split('&')) { - const [ key, val ] = kvp.split('=') - params[key] = val - } + for (const kvp of line.split("&")) { + const [key, val] = kvp.split("="); + params[key] = val; + } - return params - }) + return params; + }); } function encodeResponse(items) { - return items.map( - item => Object.entries( - item - ).map( ([ key, val ]) => - key + '=' + val // Keys,vals are not url escaped - ).join('&') - ).join( - '\r\n' - ) + '\r\n' + return ( + items + .map(item => + Object.entries(item) + .map( + ([key, val]) => key + "=" + val // Keys,vals are not url escaped + ) + .join("&") + ) + .join("\r\n") + "\r\n" + ); } -app.use(bodyParser.raw()) +app.use(bodyParser.raw()); -app.post('/request/', function (req, resp) { - const reqItems = decodeRequest(req.body) +app.post("/request/", function(req, resp) { + const reqItems = decodeRequest(req.body); - console.log('\n--- Billing Request ---\n\n', reqItems) + console.log("\n--- Billing Request ---\n\n", reqItems); - const first = reqItems[0] + const first = reqItems[0]; // Do cryptographic signatures - const [ - playlimitsig, nearfullsig - ] = [ - playlimit, nearfull - ].map(value => { - const buf = Buffer.alloc(15) + const [playlimitsig, nearfullsig] = [playlimit, nearfull].map(value => { + const buf = Buffer.alloc(15); - buf.writeInt32LE(value, 0) - buf.write(first.keychipid, 4) + buf.writeInt32LE(value, 0); + buf.write(first.keychipid, 4); - return crypto.createSign('RSA-SHA1') - .update(buf) - .sign(billingKeyPair, 'hex') - }) + return crypto + .createSign("RSA-SHA1") + .update(buf) + .sign(billingKeyPair, "hex"); + }); // Assemble other params - const respItems = [] + const respItems = []; respItems.push({ // 0 or 6 is success, anything else is an error @@ -85,7 +87,7 @@ app.post('/request/', function (req, resp) { linelimit: 1, // Server error message, copied to ALLNet debug log - message: '', + message: "", // Keychip odometer limit. Game will lock out if the odometer reaches // this value @@ -95,7 +97,7 @@ app.post('/request/', function (req, resp) { playlimitsig, // idk - protocolver: '1.000', + protocolver: "1.000", // A compound of two values. High 16 bits is the billing mode, low 16 bits // is the actual "nearfull" value. Not sure exactly what nearfull is, at a @@ -122,15 +124,15 @@ app.post('/request/', function (req, resp) { // Month 2018/09: 123 total plays // Month 2018/10: 456 total plays // Month 2018/11: 789 total plays - playhistory: '000000/0:000000/0:000000/0', - }) + playhistory: "000000/0:000000/0:000000/0", + }); - console.log('\n--- Billing Response ---\n\n', respItems) + console.log("\n--- Billing Response ---\n\n", respItems); - const respStr = encodeResponse(respItems) + const respStr = encodeResponse(respItems); - resp.set('content-type', 'text/plain') - resp.send(respStr) -}) + resp.set("content-type", "text/plain"); + resp.send(respStr); +}); -module.exports = app +module.exports = app; diff --git a/src/chunithm.js b/src/chunithm.js index f853d94..a8d67b9 100644 --- a/src/chunithm.js +++ b/src/chunithm.js @@ -1,107 +1,107 @@ -const express = require('express') -const zlib = require('zlib') +const express = require("express"); +const zlib = require("zlib"); -const app = express() +const app = express(); // Standard inbound JSON deserialization -app.use(express.json()) +app.use(express.json()); // Custom outbound JSON serialization that forces compression. Client tries to // inflate the response whether you have a Transfer-Encoding header or not -.- -app.use(function (req, resp, next) { - resp.json = function (obj) { - const str = JSON.stringify(obj) - const buf = Buffer.from(str) - const comp = zlib.deflateSync(buf) +app.use(function(req, resp, next) { + resp.json = function(obj) { + const str = JSON.stringify(obj); + const buf = Buffer.from(str); + const comp = zlib.deflateSync(buf); - resp.set('Content-Type', 'application/json') - resp.set('Content-Length', comp.length) - resp.set('Transfer-Encoding', 'deflate') - resp.send(comp) - } + resp.set("Content-Type", "application/json"); + resp.set("Content-Length", comp.length); + resp.set("Transfer-Encoding", "deflate"); + resp.send(comp); + }; - next() -}) + next(); +}); // Trace requests and responses -app.use(function (req, resp, next) { - console.log('\n--- Chunithm %s ---\n', req.url) - console.log('Request:', req.body) +app.use(function(req, resp, next) { + console.log("\n--- Chunithm %s ---\n", req.url); + console.log("Request:", req.body); - const prevJson = resp.json + const prevJson = resp.json; - resp.json = function (obj) { - console.log('Response:', obj) + resp.json = function(obj) { + console.log("Response:", obj); - resp.json = prevJson - resp.json.apply(this, arguments) - } + resp.json = prevJson; + resp.json.apply(this, arguments); + }; - next() -}) + next(); +}); -app.post('/ChuniServlet/GetGameSettingApi', function (req, resp) { +app.post("/ChuniServlet/GetGameSettingApi", function(req, resp) { resp.json({ - gameSetting: { - dataVersion: 1, - isMaintenance: false, - requestInterval: 10, - rebootStartTime: 0, - rebootEndTime: 0, - isBackgroundDistribute: false, - maxCountCharacter: 999, - maxCountItem: 999, - maxCountMusic: 999, - }, - isDumpUpload: false, - isAou: false - }) -}) + gameSetting: { + dataVersion: 1, + isMaintenance: false, + requestInterval: 10, + rebootStartTime: 0, + rebootEndTime: 0, + isBackgroundDistribute: false, + maxCountCharacter: 999, + maxCountItem: 999, + maxCountMusic: 999, + }, + isDumpUpload: false, + isAou: false, + }); +}); -app.post('/ChuniServlet/UpsertClientSettingApi', function (req, resp) { +app.post("/ChuniServlet/UpsertClientSettingApi", function(req, resp) { resp.json({ - returnCode: 1, - apiName: "UpsertClientSettingApi" - }) -}) + returnCode: 1, + apiName: "UpsertClientSettingApi", + }); +}); -app.post('/ChuniServlet/UpsertClientBookkeepingApi', function (req, resp) { +app.post("/ChuniServlet/UpsertClientBookkeepingApi", function(req, resp) { resp.json({ - returnCode: 1, - apiName: "UpsertClientBookkeepingApi" - }) -}) + returnCode: 1, + apiName: "UpsertClientBookkeepingApi", + }); +}); -app.post('/ChuniServlet/UpsertClientTestmodeApi', function (req, resp) { +app.post("/ChuniServlet/UpsertClientTestmodeApi", function(req, resp) { resp.json({ - returnCode: 1, - apiName: "UpsertClientTestmodeApi" - }) -}) + returnCode: 1, + apiName: "UpsertClientTestmodeApi", + }); +}); -app.post('/ChuniServlet/UpsertClientErrorApi', function (req, resp) { +app.post("/ChuniServlet/UpsertClientErrorApi", function(req, resp) { resp.json({ - returnCode: 1, - apiName: "UpsertClientErrorApi" - }) -}) + returnCode: 1, + apiName: "UpsertClientErrorApi", + }); +}); -app.post('/ChuniServlet/UpsertClientDevelopApi', function (req, resp) { +app.post("/ChuniServlet/UpsertClientDevelopApi", function(req, resp) { resp.json({ - returnCode: 1, - apiName: "UpsertClientDevelopApi" - }) -}) + returnCode: 1, + apiName: "UpsertClientDevelopApi", + }); +}); -app.post('/ChuniServlet/GetGameMessageApi', function (req, resp) { +app.post("/ChuniServlet/GetGameMessageApi", function(req, resp) { resp.json({ - type: 1, - length: 0, - gameMessageList: [ -/* { + type: 1, + length: 0, + gameMessageList: [ + /* { type: 2, id: 1, message: "true", @@ -109,56 +109,61 @@ app.post('/ChuniServlet/GetGameMessageApi', function (req, resp) { endDate: "0" },*/ ], - }) -}) + }); +}); -app.post('/ChuniServlet/GetGameIdlistApi', function (req, resp) { - const { type } = req.body +app.post("/ChuniServlet/GetGameIdlistApi", function(req, resp) { + const { type } = req.body; resp.json({ type, length: 0, gameIdlistList: [], - }) -}) + }); +}); -app.post('/ChuniServlet/GetGameEventApi', function (req, resp) { +app.post("/ChuniServlet/GetGameEventApi", function(req, resp) { resp.json({ type: 1, length: 0, - gameEventList: [/* + gameEventList: [ + /* { type: 1, id: 1102, // data/A000/event/event00001102 startDate: 'STRINGIDK', endDate: 'STRINGIDK', }, - */], - }) -}) + */ + ], + }); +}); -app.post('/ChuniServlet/GetGameRankingApi', function (req, resp) { - const { type } = req.body +app.post("/ChuniServlet/GetGameRankingApi", function(req, resp) { + const { type } = req.body; resp.json({ type, - gameRankingList: [/* + gameRankingList: [ + /* // QWORD fields maybe? { id: 1, point: 1, } - */], - }) -}) + */ + ], + }); +}); -app.post('/ChuniServlet/GetGameSaleApi', function (req, resp) { - const { type } = req.body +app.post("/ChuniServlet/GetGameSaleApi", function(req, resp) { + const { type } = req.body; resp.json({ type, length: 0, - gameSaleList: [/* + gameSaleList: [ + /* { orderId: 1234, type, @@ -167,14 +172,16 @@ app.post('/ChuniServlet/GetGameSaleApi', function (req, resp) { startDate: 'STRINGIDK', endDate: 'STRINGIDK', }, - */], - }) -}) + */ + ], + }); +}); -app.post('/ChuniServlet/GetGameChargeApi', function (req, resp) { +app.post("/ChuniServlet/GetGameChargeApi", function(req, resp) { resp.json({ length: 0, - gameChargeList: [/* + gameChargeList: [ + /* { orderId: 1, chargeId: 1, @@ -185,8 +192,9 @@ app.post('/ChuniServlet/GetGameChargeApi', function (req, resp) { saleStartDate: 'STRINGIDK', saleEndDate: 'STRINGIDK', }, - */], - }) -}) + */ + ], + }); +}); -module.exports = app +module.exports = app; diff --git a/src/index.js b/src/index.js index ae3b5d6..812fdc4 100644 --- a/src/index.js +++ b/src/index.js @@ -1,19 +1,19 @@ -const fs = require('fs') -const https = require('https') -const http = require('http') -const net = require('net') +const fs = require("fs"); +const https = require("https"); +const http = require("http"); +const net = require("net"); -const aimedb = require('./aimedb') -const billing = require('./billing') -const startup = require('./startup') -const chunithm = require('./chunithm') +const aimedb = require("./aimedb"); +const billing = require("./billing"); +const startup = require("./startup"); +const chunithm = require("./chunithm"); const tls = { - cert: fs.readFileSync('pki/server.pem'), - key: fs.readFileSync('pki/server.key'), -} + cert: fs.readFileSync("pki/server.pem"), + key: fs.readFileSync("pki/server.key"), +}; -net.createServer(aimedb).listen(22345) -http.createServer(startup).listen(80) -https.createServer(tls, billing).listen(8443) -http.createServer(chunithm).listen(9000) +net.createServer(aimedb).listen(22345); +http.createServer(startup).listen(80); +https.createServer(tls, billing).listen(8443); +http.createServer(chunithm).listen(9000); diff --git a/src/startup.js b/src/startup.js index bd4f4d0..028ca9c 100644 --- a/src/startup.js +++ b/src/startup.js @@ -1,92 +1,92 @@ -const bodyParser = require('body-parser') -const leftPad = require('left-pad') // the infamous... -const express = require('express') -const zlib = require('zlib') -const os = require('os') +const bodyParser = require("body-parser"); +const leftPad = require("left-pad"); // the infamous... +const express = require("express"); +const zlib = require("zlib"); +const os = require("os"); const services = new Map(); services.set("SDBT", 9000); // Chunithm function decodeRequest(req) { - const buf = Buffer.from(req, 'base64') - const bytes = zlib.unzipSync(buf) - const str = bytes.toString().trim() + const buf = Buffer.from(req, "base64"); + const bytes = zlib.unzipSync(buf); + const str = bytes.toString().trim(); - const kvps = str.split('&') - const params = {} + const kvps = str.split("&"); + const params = {}; kvps.forEach(kvp => { - const [ key, val ] = kvp.split('=') + const [key, val] = kvp.split("="); - params[key] = val - }) + params[key] = val; + }); - return params + return params; } function encodeResponse(params) { - const str = Object.entries( - params - ).map( ([ key, val ]) => - key + '=' + val - ).join('&') // Keys and values are not URL-escaped + const str = Object.entries(params) + .map(([key, val]) => key + "=" + val) + .join("&"); // Keys and values are not URL-escaped - return str + '\r\n' + return str + "\r\n"; } -const app = express() +const app = express(); // Startup request is url-encoded-ish... except it's also zlibed and base64ed. // So in the absence of any exotic Transfer-Encoding headers this Content-Type // is incorrect and we have to override Express' built-in handling. -app.use(bodyParser.raw({ - type: 'application/x-www-form-urlencoded', -})) +app.use( + bodyParser.raw({ + type: "application/x-www-form-urlencoded", + }) +); -app.post('/sys/servlet/PowerOn', function (req, resp) { - const reqParams = decodeRequest(req.body.toString()) +app.post("/sys/servlet/PowerOn", function(req, resp) { + const reqParams = decodeRequest(req.body.toString()); - console.log('\n--- Startup Request ---\n\n', reqParams) + console.log("\n--- Startup Request ---\n\n", reqParams); - const now = new Date() + const now = new Date(); // Cut milliseconds out of ISO timestamp - const isoStrWithMs = now.toISOString() - const isoStr = isoStrWithMs.substr(0, 19) + 'Z' + const isoStrWithMs = now.toISOString(); + const isoStr = isoStrWithMs.substr(0, 19) + "Z"; const respParams = { stat: 1, uri: `http://${os.hostname()}:${services.get(reqParams.game_id)}/`, - host: '', - place_id: '123', - name: 'Name', - nickname: 'Nick', - region0: '1', - region_name0: 'W', - region_name1: 'X', - region_name2: 'Y', - region_name3: 'Z', - country: 'JPN', - allnet_id: '456', + host: "", + place_id: "123", + name: "Name", + nickname: "Nick", + region0: "1", + region_name0: "W", + region_name1: "X", + region_name2: "Y", + region_name3: "Z", + country: "JPN", + allnet_id: "456", // Always UTC to simplify the segatools fake time system // (which is used to skip the hardcoded 2AM - 7AM warn/unplayable period) - client_timezone: '+0000', + client_timezone: "+0000", utc_time: isoStr, - setting: '', - res_ver: '3', + setting: "", + res_ver: "3", token: reqParams.token, - } + }; - console.log('\n--- Startup Response ---\n\n', respParams) + console.log("\n--- Startup Response ---\n\n", respParams); - const respStrZ = encodeResponse(respParams) + const respStrZ = encodeResponse(respParams); - resp.send(respStrZ) -}) + resp.send(respStrZ); +}); -module.exports = app +module.exports = app;