1
0
mirror of synced 2024-09-24 03:08:26 +02:00

Add mucha & allnet emulation in bayshore

This commit is contained in:
Rin 2022-07-12 11:42:38 +01:00
parent 4cf03efa0b
commit 868d3fd3bd
8 changed files with 281 additions and 8 deletions

3
.gitignore vendored
View File

@ -6,4 +6,5 @@ proto/
dist/
server_wangan.key
cert.pfx
key.pem
key.pem
config.json

4
config.example.json Normal file
View File

@ -0,0 +1,4 @@
{
"shopName": "Bayshore",
"shopNickname": "BSH"
}

View File

@ -24,6 +24,9 @@
"@types/pem": "^1.9.6",
"body-parser": "^1.20.0",
"express": "^4.18.1",
"form-urlencoded": "^6.0.6",
"iconv-lite": "^0.6.3",
"moment": "^2.29.4",
"pem": "^1.14.6",
"protobufjs": "^7.0.0",
"ts-proto": "^1.117.0"

102
src/allnet.ts Normal file
View File

@ -0,0 +1,102 @@
import bodyParser from "body-parser";
import { Application } from "express";
import { unzipSync } from "zlib";
import { Module } from "./module";
import iconv from "iconv-lite";
import { Config } from "./config";
// TODO: Move this into the config
const STARTUP_URI = "https://localhost:9002";
const STARTUP_HOST = "localhost:9002";
export default class AllnetModule extends Module {
register(app: Application): void {
app.use(bodyParser.raw({
type: '*/*'
}));
app.use("/sys/servlet/PowerOn", async function(req, res, next) {
if (req.method !== "POST") {
return res.status(405).end();
}
if (!req.is("application/x-www-form-urlencoded")) {
return next();
}
const base64 = req.body.toString('ascii');
const zbytes = Buffer.from(base64, "base64");
const bytes = unzipSync(zbytes);
const str = bytes.toString("ascii").trim();
const kvps = str.split("&");
const reqParams: any = {};
// Keys and values are not URL-escaped
kvps.forEach(kvp => {
const [key, val] = kvp.split("=");
reqParams[key] = val;
});
const send_ = res.send;
req.body = reqParams;
res.send = resParams => {
const str =
Object.entries(resParams)
.map(([key, val]) => key + "=" + val)
.join("&") + "\n";
res.set("content-type", "text/plain");
const bin = iconv.encode(str, "shift_jis");
return send_.apply(res, [bin]);
};
return next();
});
app.post("/sys/servlet/PowerOn", function(req, res) {
console.log('ALL.net: Startup request');
// Cut milliseconds out of ISO timestamp
const now = new Date();
const adjusted = now;
let shopName = Config.getConfig().shopName;
let shopNick = Config.getConfig().shopNickname;
const resParams = {
stat: 1,
uri: STARTUP_URI,
host: STARTUP_HOST,
place_id: "JPN0123",
name: shopName,
nickname: shopNick,
region0: "1",
region_name0: "W",
region_name1: "X",
region_name2: "Y",
region_name3: "Z",
country: "JPN",
allnet_id: "456",
timezone: "002:00",
setting: "",
year: adjusted.getFullYear(),
month: adjusted.getMonth() + 1, // I hate JS
day: adjusted.getDate(),
hour: adjusted.getHours(),
minute: adjusted.getMinutes(),
second: adjusted.getSeconds(),
res_class: "PowerOnResponseVer2",
token: req.body.token,
};
res.send(resParams);
});
}
}

21
src/config.ts Normal file
View File

@ -0,0 +1,21 @@
import fs from 'fs';
export interface ConfigFile {
shopName: string;
shopNickname: string;
}
export class Config {
private static cfg: ConfigFile;
static load() {
console.log('Loading config file...');
let cfg = fs.readFileSync('./config.json', 'utf-8');
let json = JSON.parse(cfg);
this.cfg = json as ConfigFile;
}
static getConfig(): ConfigFile {
return this.cfg;
}
}

View File

@ -6,18 +6,40 @@ import {PrismaClient} from '@prisma/client';
import https, {globalAgent} from 'https';
import fs from 'fs';
import bodyParser from 'body-parser';
import AllnetModule from './allnet';
import MuchaModule from './mucha';
import { Config } from './config';
globalAgent.options.keepAlive = true;
// @ts-ignore
require('http').globalAgent.options.keepAlive = true;
const PORT_ALLNET = 80;
const PORT_MUCHA = 10082;
const PORT_BNGI = 9002;
Config.load();
const app = express();
app.use(bodyParser.raw({
type: '*/*'
}));
const muchaApp = express();
const allnetApp = express();
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
console.log(`[ MAIN] ${req.method} ${req.url}`);
next()
});
muchaApp.use((req, res, next) => {
console.log(`[ MUCHA] ${req.method} ${req.url}`);
next()
});
allnetApp.use((req, res, next) => {
console.log(`[ALLNET] ${req.method} ${req.url}`);
next()
});
@ -34,9 +56,20 @@ app.all('*', (req, res) => {
res.status(200).end();
})
https.createServer({
key: fs.readFileSync('./server_wangan.key'),
cert: fs.readFileSync('./server_wangan.crt')
}, app).listen(9002, () => {
console.log('Server listening on port 9002!');
new AllnetModule().register(allnetApp);
new MuchaModule().register(muchaApp);
let key = fs.readFileSync('./server_wangan.key');
let cert = fs.readFileSync('./server_wangan.crt');
https.createServer({key, cert}, allnetApp).listen(PORT_ALLNET, () => {
console.log(`ALL.net server listening on port ${PORT_ALLNET}!`);
})
https.createServer({key, cert}, muchaApp).listen(PORT_MUCHA, () => {
console.log(`Mucha server listening on port ${PORT_MUCHA}!`);
})
https.createServer({key, cert}, app).listen(PORT_BNGI, () => {
console.log(`Game server listening on port ${PORT_BNGI}!`);
})

92
src/mucha.ts Normal file
View File

@ -0,0 +1,92 @@
import express, { Application } from "express";
import formUrlEncoded from "form-urlencoded";
import moment from "moment";
import { Config } from "./config";
import { Module } from "./module";
const PORT = 10082;
export default class MuchaModule extends Module {
register(app: Application): void {
const URL_BASE = `https://localhost:${PORT}`
app.use(express.urlencoded({
type: '*/*',
extended: true
}))
app.post('/updatacheck.do', (req, res) => {
let response = {
RESULTS: "001",
UPDATE_VER_1: req.body.gameVer,
UPDATE_URL_1: `${URL_BASE}/updUrl1/`,
UPDATE_SIZE_1: 9318000,
UPDATE_CRC_1: "55C4000000000000",
CHECK_URL_1: `${URL_BASE}/checkUrl/`,
EXE_VER_1: req.body.gameVer,
INFO_SIZE_1: 180,
COM_SIZE_1: 16384,
COM_TIME_1: 100,
LAN_INFO_SIZE_1: 180
}
let urlResponse = formUrlEncoded(response);
let decResponse = decodeURIComponent(urlResponse);
res.status(200).send(decResponse);
})
app.post('/boardauth.do', (req, res) => {
let serverTime = moment().format('YYYYMMDDHHmm');
let utcServerTime = moment().utc().format('YYYYMMDDHHmm');
let shopName = Config.getConfig().shopName;
let shopNick = Config.getConfig().shopNickname;
let response = {
RESULTS: "001",
AREA_0: "008",
AREA_0_EN: "",
AREA_1: "009",
AREA_1_EN: "",
AREA_2: "010",
AREA_2_EN: "",
AREA_3: "011",
AREA_3_EN: "",
AREA_FULL_0: "",
AREA_FULL_0_EN: "",
AREA_FULL_1: "",
AREA_FULL_1_EN: "",
AREA_FULL_2: "",
AREA_FULL_2_EN: "",
AREA_FULL_3: "",
AREA_FULL_3_EN: "",
AUTH_INTERVAL: "86400",
CHARGE_URL: `${URL_BASE}/charge/`,
CONSUME_TOKEN: "0",
COUNTRY_CD: "JPN",
DONGLE_FLG: "1",
EXPIRATION_DATE: "null",
FILE_URL: `${URL_BASE}/file/`,
FORCE_BOOT: "0",
PLACE_ID: req.body.placeId,
PREFECTURE_ID: "14",
SERVER_TIME: serverTime,
UTC_SERVER_TIME: utcServerTime,
SHOP_NAME: shopName,
SHOP_NAME_EN: shopName,
SHOP_NICKNAME: shopNick,
SHOP_NICKNAME_EN: shopNick,
URL_1: `${URL_BASE}/url1/`,
URL_2: `${URL_BASE}/url2/`,
URL_3: `${URL_BASE}/url3/`,
USE_TOKEN: "0"
}
let urlResponse = formUrlEncoded(response);
let decResponse = decodeURIComponent(urlResponse);
res.status(200).send(decResponse);
})
}
}

View File

@ -557,6 +557,11 @@ finalhandler@1.2.0:
statuses "2.0.1"
unpipe "~1.0.0"
form-urlencoded@^6.0.6:
version "6.0.6"
resolved "https://registry.yarnpkg.com/form-urlencoded/-/form-urlencoded-6.0.6.tgz#6505aca762436f90f2a736f79c24ad30787daacc"
integrity sha512-5n3L86l3uVJLFk8w+HTcuaV8WrEeH9pPqJcICxAbs3oW/gsKg9kJ8XVPZ3I1PJR50ld2fQjstT94p4G90JDMAg==
forwarded@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
@ -644,6 +649,13 @@ iconv-lite@0.4.24:
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
dependencies:
safer-buffer ">= 2.1.2 < 3.0.0"
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
@ -838,6 +850,11 @@ mkdirp@^1.0.4:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
moment@^2.29.4:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@ -1039,7 +1056,7 @@ safe-buffer@5.2.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
"safer-buffer@>= 2.1.2 < 3":
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==