From 31a230caf767caae8ac6a8b6b83decfba2f6fd0a Mon Sep 17 00:00:00 2001 From: Felix Date: Fri, 19 Aug 2016 12:19:48 +0200 Subject: [PATCH] Update - Refactored config - Fixed mongodb bug, where player avatar didnt got saved into db - Deleted requests.js, instead use protobuf - Player parallelism should work now, dont share instanced player object anymore *facepalm* - Updated version --- cfg.js | 80 +++++------ package.json | 2 +- src/cycle.js | 8 +- src/db/mongo.js | 24 ++-- src/db/mysql.js | 22 +-- src/index.js | 50 ++++--- src/packets/Responses.CheckAwardedBadges.js | 2 +- src/packets/Responses.DownloadSettings.js | 4 +- src/packets/Responses.Encounter.js | 2 +- src/packets/Responses.EvolvePokemon.js | 2 +- src/packets/Responses.FortDetails.js | 2 +- src/packets/Responses.FortSearch.js | 4 +- src/packets/Responses.GetAssetDigest.js | 2 +- src/packets/Responses.ItemTemplates.js | 2 +- src/packets/Responses.NicknamePokemon.js | 2 +- src/packets/Responses.SetContactSettings.js | 2 +- src/packets/Responses.SetFavoritePokemon.js | 2 +- src/packets/Responses.SfidaActionLog.js | 2 +- src/packets/Responses.UpgradePokemon.js | 2 +- src/player.js | 146 ++++++++++++++++---- src/process.js | 8 +- src/request.js | 127 ++--------------- src/requests.js | 73 ---------- src/response.js | 47 ++++--- src/setup.js | 12 +- src/utils.js | 2 +- 26 files changed, 276 insertions(+), 355 deletions(-) delete mode 100644 src/requests.js diff --git a/cfg.js b/cfg.js index cdf084e..d448361 100644 --- a/cfg.js +++ b/cfg.js @@ -1,51 +1,45 @@ -export const MINIMUM_CLIENT_VERSION = "0.33.0"; +export default { -export const SERVER_GAME_MODE = 0; -export const SERVER_TICK_INTERVAL = 1; // better dont change -export const SERVER_SAVE_INTERVAL = 1e3 * 60; // 1min -export const SERVER_MAX_CONNECTIONS = 64; -export const SERVER_PLAYER_CONNECTION_TIMEOUT = 1e3 * 60 * 30; // 30min + // Server settings + MAX_CONNECTIONS: 64, + PORT: 3000, + GAME_MODE: 0, + TICK_INTERVAL: 1, + SAVE_INTERVAL: 60000, + PLAYER_CONNECTION_TIMEOUT: 1800000, + BOOT_TIMEOUT: 10000, + MINIMUM_CLIENT_VERSION: "0.33.0", + DEFAULT_CONSOLE_COLOR: 32, + TRANSFER_ACCOUNTS: false, -export const SERVER_BOOT_TIMEOUT = 10e3; + // Choose a database type + DATABASE_TYPE: "MYSQL", -export const SERVER_DEFAULT_CONSOLE_COLOR = 32; + // MySQL credentials + MYSQL_PORT: 3306, + MYSQL_HOST_IP: "127.0.0.1", + MYSQL_DB_NAME: "pogosql", + MYSQL_USERNAME: "root", + MYSQL_PASSWORD: "", + MYSQL_TABLE: "users", -// HTTP -export const SERVER_PORT = 3000; -export const SERVER_HOST_IP = "127.0.0.1"; + // MongoDB credentials + MONGO_PORT: 27017, + MONGO_HOST_IP: "127.0.0.1", + MONGO_DB_NAME: "pokemongo", + MONGO_COLLECTION_USERS: "users", -// Either mongo or mysql -export const SERVER_USE_DATABASE = "MONGO"; + // Used for asset download session + DOWNLOAD_PROVIDER: "GOOGLE", + DOWNLOAD_USERNAME: "USERNAME", + DOWNLOAD_PASSWORD: "PASSWORD", -// MONGODB -export const SERVER_MONGO_PORT = 27017; -export const SERVER_MONGO_HOST_IP = "127.0.0.1"; -export const SERVER_MONGO_DB_NAME = "pokemongo"; -export const SERVER_MONGO_COLLECTION_USERS = "users"; + // Google maps api key + GMAPS_KEY: "AIzaSyDF9rkP8lhcddBtvH9gVFzjnNo13WtmJIM", -// MYSQL -export const SERVER_MYSQL_PORT = 3306; -export const SERVER_MYSQL_HOST_IP = "127.0.0.1"; -export const SERVER_MYSQL_DB_NAME = "pogosql"; -export const SERVER_MYSQL_USERNAME = "root"; -export const SERVER_MYSQL_PASSWORD = ""; -export const SERVER_MYSQL_TABLE = "users"; + // Server debug options + DEBUG_DUMP_PATH: "./logs/", + DEBUG_DUMP_TRAFFIC: true, + DEBUG_LOG_REQUESTS: true -// account used for pogo-asset-downloader lib -export const SERVER_POGO_CLIENT_PROVIDER = "GOOGLE"; // either google or ptc -export const SERVER_POGO_CLIENT_USERNAME = "USERNAME"; -export const SERVER_POGO_CLIENT_PASSWORD = "PASSWORD"; - -export const SERVER_GMAPS_API_KEY = "AIzaSyDF9rkP8lhcddBtvH9gVFzjnNo13WtmJIM"; - -// path to save logs into -export const SERVER_DUMP_PATH = "./logs/"; - -// save traffic dumps into /logs -export const SERVER_DUMP_TRAFFIC = true; - -// show request types in console -export const SERVER_LOG_REQUESTS = true; - -// transfer account progress from official servers -export const SERVER_CLONE_NEW_ACCOUNTS_FROM_OFFICIAL_SERVER = false; \ No newline at end of file +} \ No newline at end of file diff --git a/package.json b/package.json index 218b398..2a4bd29 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "POGOServer", - "version": "0.3.1", + "version": "0.3.2", "description": "", "repository": { "type": "git", diff --git a/src/cycle.js b/src/cycle.js index 89f7209..0fcf96e 100644 --- a/src/cycle.js +++ b/src/cycle.js @@ -1,7 +1,7 @@ -import * as CFG from "../cfg"; +import CFG from "../cfg"; export function startCycle() { - this.cycleInstance = setTimeout(() => this.cycle(), CFG.SERVER_TICK_INTERVAL); + this.cycleInstance = setTimeout(() => this.cycle(), CFG.TICK_INTERVAL); } export function stopCycle() { @@ -48,7 +48,7 @@ export function resetTimers() { } this.saveTick++; // Save interval - if (this.saveTick >= CFG.SERVER_SAVE_INTERVAL) { + if (this.saveTick >= CFG.SAVE_INTERVAL) { this.saveAllPlayers(); this.saveTick = 0; } @@ -58,7 +58,7 @@ export function resetTimers() { export function playerTimeoutTick() { let client = null; - let maxTimeout = CFG.SERVER_PLAYER_CONNECTION_TIMEOUT; + let maxTimeout = CFG.PLAYER_CONNECTION_TIMEOUT; let ii = 0, length = this.clients.length; diff --git a/src/db/mongo.js b/src/db/mongo.js index 57d6277..da6c8d7 100644 --- a/src/db/mongo.js +++ b/src/db/mongo.js @@ -1,10 +1,10 @@ import mongodb from "mongodb"; -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; export function setupConnection() { - let url = `mongodb://${CFG.SERVER_MONGO_HOST_IP}:${CFG.SERVER_MONGO_PORT}/${CFG.SERVER_MONGO_DB_NAME}`; + let url = `mongodb://${CFG.MONGO_HOST_IP}:${CFG.MONGO_PORT}/${CFG.MONGO_DB_NAME}`; return new Promise((resolve) => { mongodb.MongoClient.connect(url, (error, db) => { @@ -14,7 +14,7 @@ export function setupConnection() { return void 0; } else { this.db.instance = db; - this.loadCollection(CFG.SERVER_MONGO_COLLECTION_USERS).then(() => { + this.loadCollection(CFG.MONGO_COLLECTION_USERS).then(() => { this.print(`\x1b[36;1mMongoDB\x1b[0m\x1b[32;1m connection established\x1b[0m`); resolve(); }); @@ -81,7 +81,7 @@ export function getUserByEmail(email) { export function getUserCollection() { return ( - this.db.instance.collection(CFG.SERVER_MONGO_COLLECTION_USERS) + this.db.instance.collection(CFG.MONGO_COLLECTION_USERS) ); } @@ -133,14 +133,14 @@ export function getUserData(obj) { team: obj.team, skin: obj.skin, - hair: obj.skin, - shirt: obj.skin, - pants: obj.skin, - hat: obj.skin, - shoes: obj.skin, - eyes: obj.skin, - gender: obj.skin, - backpack: obj.skin, + hair: obj.hair, + shirt: obj.shirt, + pants: obj.pants, + hat: obj.hat, + shoes: obj.shoes, + eyes: obj.eyes, + gender: obj.gender, + backpack: obj.backpack, latitude: obj.latitude, longitude: obj.latitude, diff --git a/src/db/mysql.js b/src/db/mysql.js index 3265c84..e0a68a0 100644 --- a/src/db/mysql.js +++ b/src/db/mysql.js @@ -1,15 +1,15 @@ import mysql from "mysql"; -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; export function setupConnection() { let connection = mysql.createConnection({ - host : CFG.SERVER_MYSQL_HOST_IP, - port : CFG.SERVER_MYSQL_PORT, - database : CFG.SERVER_MYSQL_DB_NAME, - user : CFG.SERVER_MYSQL_USERNAME, - password : CFG.SERVER_MYSQL_PASSWORD + host : CFG.MYSQL_HOST_IP, + port : CFG.MYSQL_PORT, + database : CFG.MYSQL_DB_NAME, + user : CFG.MYSQL_USERNAME, + password : CFG.MYSQL_PASSWORD }); return new Promise((resolve) => { @@ -44,13 +44,13 @@ export function closeConnection(resolve) { export function createTableIfNoExists() { return new Promise((resolve) => { - this.db.instance.query(`SHOW TABLES LIKE '${CFG.SERVER_MYSQL_TABLE}';`, (e, rows, fields) => { + this.db.instance.query(`SHOW TABLES LIKE '${CFG.MYSQL_TABLE}';`, (e, rows, fields) => { if (e) console.log(e); else { // exists if (rows && rows.length) resolve(); // create user table - else this.createTable(CFG.SERVER_MYSQL_TABLE).then(resolve); + else this.createTable(CFG.MYSQL_TABLE).then(resolve); } }); }); @@ -60,7 +60,7 @@ export function createTableIfNoExists() { * @param {String} name */ export function createTable(name) { - this.print(`Creating table ${CFG.SERVER_MYSQL_TABLE}`, 36); + this.print(`Creating table ${CFG.MYSQL_TABLE}`, 36); return new Promise((resolve) => { let query = ` CREATE TABLE ${name} ( @@ -100,7 +100,7 @@ export function createTable(name) { */ export function getUserByEmail(email) { return new Promise((resolve) => { - this.db.instance.query(`SELECT * FROM ${CFG.SERVER_MYSQL_TABLE} WHERE email=? LIMIT 1`, [email], (e, rows, fields) => { + this.db.instance.query(`SELECT * FROM ${CFG.MYSQL_TABLE} WHERE email=? LIMIT 1`, [email], (e, rows, fields) => { if (e) console.log(e); if (rows && rows.length) resolve(rows[0]); else resolve(void 0); @@ -141,7 +141,7 @@ export function updateUser(obj) { */ export function getUserQuery(cmd, after) { return (` - ${cmd} ${CFG.SERVER_MYSQL_TABLE} + ${cmd} ${CFG.MYSQL_TABLE} SET username=?, email=?, diff --git a/src/index.js b/src/index.js index cf74759..3ac6fdc 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,5 @@ import fs from "fs"; +import os from "os"; import fse from "fs-extra"; import http from "http"; import proto from "./proto"; @@ -8,7 +9,7 @@ import { inherit } from "./utils"; -import * as CFG from "../cfg"; +import CFG from "../cfg"; import pogodown from "pogo-asset-downloader"; @@ -42,11 +43,7 @@ class GameServer { collections: {} }; - this.proto = null; this.socket = null; - this.player = null; - this.request = null; - this.response = null; this.cycleInstance = null; // Timer things @@ -84,9 +81,9 @@ class GameServer { return new Promise((resolve) => { pogodown.login({ - provider: String(CFG.SERVER_POGO_CLIENT_PROVIDER).toLowerCase(), - username: CFG.SERVER_POGO_CLIENT_USERNAME, - password: CFG.SERVER_POGO_CLIENT_PASSWORD, + provider: String(CFG.DOWNLOAD_PROVIDER).toLowerCase(), + username: CFG.DOWNLOAD_USERNAME, + password: CFG.DOWNLOAD_PASSWORD, downloadModels: false }).then((asset) => { if (asset && asset.digest && asset.digest.length) { @@ -119,15 +116,16 @@ class GameServer { */ createHTTPServer() { let server = http.createServer((req, res) => { - if (this.clients.length >= CFG.SERVER_MAX_CONNECTIONS) { + if (this.clients.length >= CFG.MAX_CONNECTIONS) { this.print(`Server is full! Refused ${req.headers.host}`, 31); return void 0; } - this.response = res; - // client already connected - if (!this.clientAlreadyConnected(req)) { - this.addPlayer(req); - } + + let player = null; + + if (this.clientAlreadyConnected(req)) player = this.getPlayerByRequest(req); + else player = this.addPlayer(req, res); + let chunks = []; req.on("data", (chunk) => { chunks.push(chunk); @@ -135,11 +133,11 @@ class GameServer { req.on("end", () => { let buffer = Buffer.concat(chunks); req.body = buffer; - this.request = req; - this.routeRequest(req, res); + player.updateResponse(res); + this.routeRequest(req); }); }); - server.listen(CFG.SERVER_PORT); + server.listen(CFG.PORT); return (server); } @@ -147,7 +145,7 @@ class GameServer { return new Promise((resolve) => { - let name = String(CFG.SERVER_USE_DATABASE).toUpperCase(); + let name = String(CFG.DATABASE_TYPE).toUpperCase(); switch (name) { case "MONGO": @@ -186,7 +184,7 @@ class GameServer { * @param {Boolean} nl */ print(msg, color, nl) { - color = Number.isInteger(color) ? color : CFG.SERVER_DEFAULT_CONSOLE_COLOR; + color = Number.isInteger(color) ? color : CFG.DEFAULT_CONSOLE_COLOR; process.stdout.write(`[Console] \x1b[${color};1m${msg}\x1b[0m${nl === void 0 ? "\n" : ""}`); } @@ -216,13 +214,25 @@ class GameServer { try { let decoded = JSON.stringify(decode(req, res, opts), null, 2); - fse.outputFileSync(CFG.SERVER_DUMP_PATH + Date.now(), decoded); + fse.outputFileSync(CFG.DEBUG_DUMP_PATH + Date.now(), decoded); } catch (e) { this.print("Dump traffic: " + e, 31); } } + getLocalIPv4() { + + let address = null; + let interfaces = os.networkInterfaces(); + + for (var dev in interfaces) { + interfaces[dev].filter((details) => details.family === "IPv4" && details.internal === false ? address = details.address: void 0); + }; + + return (address); + } + greet() { console.log(greetMessage); } diff --git a/src/packets/Responses.CheckAwardedBadges.js b/src/packets/Responses.CheckAwardedBadges.js index 5e8bbdf..238efb2 100644 --- a/src/packets/Responses.CheckAwardedBadges.js +++ b/src/packets/Responses.CheckAwardedBadges.js @@ -1,4 +1,4 @@ -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; import proto from "../proto"; diff --git a/src/packets/Responses.DownloadSettings.js b/src/packets/Responses.DownloadSettings.js index 17f0af5..417c419 100644 --- a/src/packets/Responses.DownloadSettings.js +++ b/src/packets/Responses.DownloadSettings.js @@ -1,6 +1,6 @@ import proto from "../proto"; -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; /** * @param {Request} req @@ -30,7 +30,7 @@ export default function DownloadSettings(req) { "get_map_objects_min_refresh_seconds": 10.007843017578125, "get_map_objects_max_refresh_seconds": 30.01568603515625, "get_map_objects_min_distance_meters": 10.007843017578125, - "google_maps_api_key": CFG.SERVER_GMAPS_API_KEY + "google_maps_api_key": CFG.GMAPS_KEY }), inventory_settings: new proto.Settings.InventorySettings({ "max_pokemon": 1000, diff --git a/src/packets/Responses.Encounter.js b/src/packets/Responses.Encounter.js index 2c4d596..7729398 100644 --- a/src/packets/Responses.Encounter.js +++ b/src/packets/Responses.Encounter.js @@ -1,4 +1,4 @@ -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; import proto from "../proto"; diff --git a/src/packets/Responses.EvolvePokemon.js b/src/packets/Responses.EvolvePokemon.js index d1f717c..e157f2c 100644 --- a/src/packets/Responses.EvolvePokemon.js +++ b/src/packets/Responses.EvolvePokemon.js @@ -1,4 +1,4 @@ -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; import proto from "../proto"; diff --git a/src/packets/Responses.FortDetails.js b/src/packets/Responses.FortDetails.js index 14ee87e..0f47ba7 100644 --- a/src/packets/Responses.FortDetails.js +++ b/src/packets/Responses.FortDetails.js @@ -1,4 +1,4 @@ -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; import proto from "../proto"; diff --git a/src/packets/Responses.FortSearch.js b/src/packets/Responses.FortSearch.js index a5aa03b..acddeb5 100644 --- a/src/packets/Responses.FortSearch.js +++ b/src/packets/Responses.FortSearch.js @@ -1,4 +1,4 @@ -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; import proto from "../proto"; @@ -14,7 +14,7 @@ export default function FortSearch(obj) { items_awarded: [ new proto.Inventory.Item.ItemAward({ item_id: proto.Inventory.Item.ItemId.ITEM_MASTER_BALL, - item_count: 3 + item_count: 10 }), new proto.Inventory.Item.ItemAward({ item_id: proto.Inventory.Item.ItemId.ITEM_ULTRA_BALL, diff --git a/src/packets/Responses.GetAssetDigest.js b/src/packets/Responses.GetAssetDigest.js index 6e459f8..2d93009 100644 --- a/src/packets/Responses.GetAssetDigest.js +++ b/src/packets/Responses.GetAssetDigest.js @@ -1,7 +1,7 @@ import fs from "fs"; import proto from "../proto"; -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; /** * @param {Request} req diff --git a/src/packets/Responses.ItemTemplates.js b/src/packets/Responses.ItemTemplates.js index d67eab1..01e24eb 100644 --- a/src/packets/Responses.ItemTemplates.js +++ b/src/packets/Responses.ItemTemplates.js @@ -1,4 +1,4 @@ -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; import proto from "../proto"; diff --git a/src/packets/Responses.NicknamePokemon.js b/src/packets/Responses.NicknamePokemon.js index 098b8c2..e6959a7 100644 --- a/src/packets/Responses.NicknamePokemon.js +++ b/src/packets/Responses.NicknamePokemon.js @@ -1,4 +1,4 @@ -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; import proto from "../proto"; diff --git a/src/packets/Responses.SetContactSettings.js b/src/packets/Responses.SetContactSettings.js index 0a54f7b..e11041d 100644 --- a/src/packets/Responses.SetContactSettings.js +++ b/src/packets/Responses.SetContactSettings.js @@ -1,4 +1,4 @@ -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; import proto from "../proto"; diff --git a/src/packets/Responses.SetFavoritePokemon.js b/src/packets/Responses.SetFavoritePokemon.js index 1f23cf8..ca7322c 100644 --- a/src/packets/Responses.SetFavoritePokemon.js +++ b/src/packets/Responses.SetFavoritePokemon.js @@ -1,4 +1,4 @@ -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; import proto from "../proto"; diff --git a/src/packets/Responses.SfidaActionLog.js b/src/packets/Responses.SfidaActionLog.js index 39c1a94..e879396 100644 --- a/src/packets/Responses.SfidaActionLog.js +++ b/src/packets/Responses.SfidaActionLog.js @@ -1,6 +1,6 @@ import proto from "../proto"; -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; /** * @param {Object} obj diff --git a/src/packets/Responses.UpgradePokemon.js b/src/packets/Responses.UpgradePokemon.js index 2cdda5a..bd78790 100644 --- a/src/packets/Responses.UpgradePokemon.js +++ b/src/packets/Responses.UpgradePokemon.js @@ -1,4 +1,4 @@ -import * as CFG from "../../cfg"; +import CFG from "../../cfg"; import proto from "../proto"; diff --git a/src/player.js b/src/player.js index a4fa391..f6d72c9 100644 --- a/src/player.js +++ b/src/player.js @@ -1,12 +1,19 @@ import proto from "./proto"; -import * as CFG from "../cfg"; +import CFG from "../cfg"; import { getHashCodeFrom, decodeRequestEnvelope } from "./utils"; +import { + ResponseEnvelope, + ResponseEnvelopeAuth +} from "./packets"; + +import jwtDecode from "jwt-decode"; + import { GetPlayer } from "./packets"; /** @@ -55,7 +62,9 @@ class Player { this.isPTCAccount = false; this.isGoogleAccount = false; - this.response = obj.response; + this.request = obj.request; + // gets updated after each chunk end event + this.response = null; this.connection = obj.connection; this.timeout = obj.timeout; @@ -77,6 +86,20 @@ class Player { this.uid = getHashCodeFrom(String(email)); } + /** + * @param {Buffer} buffer + */ + sendResponse(buffer) { + this.response.end(buffer); + } + + /** + * @param {Response} res + */ + updateResponse(res) { + this.response = res; + } + updateByObject(obj) { for (let key in obj) { if (this.hasOwnProperty(key)) { @@ -199,18 +222,23 @@ export function getPlayerByName(name) { /** * @param {Request} req + * @return {Player} */ export function addPlayer(req) { let connection = req.connection; - this.clients.push(new Player({ + let player = new Player({ timeout: this.time, connection: connection, - response: this.response, + request: req, remotePort: connection.remotePort, remoteAddress: req.headers.host - })); + }); + + this.clients.push(player); + + return (player); } @@ -283,24 +311,10 @@ export function savePlayer(player) { }); } -export function loginPlayer() { - - let buffer = null; - let player = this.player; - - return new Promise((resolve) => { - this.getUserByEmail(player.email).then((doc) => { - player.updateByObject(doc); - buffer = GetPlayer(player).encode(); - resolve(buffer); - }); - }); - -} - -export function forwardPlayer() { - - let player = this.player; +/** + * @param {Player} player + */ +export function forwardPlayer(player) { return new Promise((resolve) => { this.getUserByEmail(player.email).then((doc) => { @@ -309,12 +323,12 @@ export function forwardPlayer() { this.print(`${player.email.replace("@gmail.com", "")} authenticated via ${provider}!`, 36); } if (doc) { - this.loginPlayer().then((res) => { + this.loginPlayer(player).then((res) => { resolve(res); }); } else { - this.registerPlayer().then((res) => { + this.registerPlayer(player).then((res) => { resolve(res); }); } @@ -323,18 +337,90 @@ export function forwardPlayer() { } -export function registerPlayer() { +/** + * @param {Player} player + */ +export function loginPlayer(player) { - let player = this.player; + return new Promise((resolve) => { + this.getUserByEmail(player.email).then((doc) => { + player.updateByObject(doc); + let buffer = GetPlayer(player).encode(); + resolve(buffer); + }); + }); + +} + +/** + * @param {Player} player + */ +export function registerPlayer(player) { return new Promise((resolve) => { this.createUser(player).then(() => { - this.print(`${this.player.email.replace("@gmail.com", "")} registered!`, 36); + this.print(`${player.email.replace("@gmail.com", "")} registered!`, 36); player.tutorial_state = []; - this.loginPlayer().then((res) => { + this.loginPlayer(player).then((res) => { resolve(res); }); }); }); -} \ No newline at end of file +} + +/** + * @param {Player} player + * @return {Buffer} + */ +export function authenticatePlayer(player) { + + let request = decodeRequestEnvelope(player.request.body); + + let msg = ResponseEnvelopeAuth({ + id: request.request_id + }); + + let token = request.auth_info; + + // TODO: Support PTC server authentification + + if (!token || !token.provider) { + this.print("Invalid authentication token! Kicking..", 31); + this.removePlayer(player); + return void 0; + } + + if (token.provider === "google") { + if (token.token !== null) { + let decoded = jwtDecode(token.token.contents); + player.generateUid(decoded.email); + player.email = decoded.email; + player.email_verified = decoded.email_verified; + player.isGoogleAccount = true; + this.print(`${player.email.replace("@gmail.com", "")} connected!`, 36); + } + else { + this.print("Invalid authentication token! Kicking..", 31); + this.removePlayer(player); + return void 0; + } + } + else if (token.provider === "ptc") { + let decoded = token.token.contents; + player.isPTCAccount = true; + this.print("PTC auth isnt supported yet! Kicking..", 31); + this.removePlayer(player); + return void 0; + } + else { + this.print("Invalid provider! Kicking..", 31); + this.removePlayer(player); + return void 0; + } + + player.authenticated = true; + + return (msg); + +} diff --git a/src/process.js b/src/process.js index 33feb3b..c6d4c39 100644 --- a/src/process.js +++ b/src/process.js @@ -1,6 +1,6 @@ import fs from "fs"; -import * as CFG from "../cfg"; +import CFG from "../cfg"; const helpMessage = fs.readFileSync(".help", "utf8"); @@ -9,7 +9,7 @@ export function processCommand(cmd, data) { // How many active connections there are case "/clients": var length = this.clients.length; - this.print(`${length}:${CFG.SERVER_MAX_CONNECTIONS} connected players!`, 33); + this.print(`${length}:${CFG.MAX_CONNECTIONS} connected players!`, 33); break; // Exit the server case "/exit": @@ -30,7 +30,7 @@ export function processCommand(cmd, data) { break; case "/help": console.log("\x1b[36;1m==================================== HELP =====================================\x1b[0m"); - console.log(`\x1b[${CFG.SERVER_DEFAULT_CONSOLE_COLOR};1m${helpMessage}\x1b[0m`); + console.log(`\x1b[${CFG.DEFAULT_CONSOLE_COLOR};1m${helpMessage}\x1b[0m`); console.log("\x1b[36;1m===============================================================================\x1b[0m"); break; case "/save": @@ -58,7 +58,7 @@ export function stdinInput(data) { export function uncaughtException(excp) { switch (excp.errno) { case "EADDRINUSE": - this.print(`Port ${CFG.SERVER_PORT} is already in use!`, 31); + this.print(`Port ${CFG.PORT} is already in use!`, 31); break; case "EACCES": this.print("No root privileges!", 31); diff --git a/src/request.js b/src/request.js index 782b1fd..a1bf5cf 100644 --- a/src/request.js +++ b/src/request.js @@ -1,78 +1,13 @@ import proto from "./proto"; -import * as CFG from "../cfg"; -import { REQUEST } from "./requests"; +import CFG from "../cfg"; import { ResponseEnvelope, - ResponseEnvelopeAuth, - AuthTicket, - GetInventory + AuthTicket } from "./packets"; -import { - decodeLong, - decodeRequestEnvelope -} from "./utils"; - -import jwtDecode from "jwt-decode"; - -/** - * @return {Buffer} - */ -export function authenticatePlayer() { - - let player = this.player; - - let request = decodeRequestEnvelope(this.getRequestBody()); - - let msg = ResponseEnvelopeAuth({ - id: request.request_id - }); - - let token = request.auth_info; - - // TODO: Support PTC server authentification - - if (!token || !token.provider) { - this.print("Invalid authentication token! Kicking..", 31); - this.removePlayer(player); - return void 0; - } - - if (token.provider === "google") { - if (token.token !== null) { - let decoded = jwtDecode(token.token.contents); - player.generateUid(decoded.email); - player.email = decoded.email; - player.email_verified = decoded.email_verified; - player.isGoogleAccount = true; - this.print(`${player.email.replace("@gmail.com", "")} connected!`, 36); - } - else { - this.print("Invalid authentication token! Kicking..", 31); - this.removePlayer(player); - return void 0; - } - } - else if (token.provider === "ptc") { - let decoded = token.token.contents; - player.isPTCAccount = true; - this.print("PTC auth isnt supported yet! Kicking..", 31); - this.removePlayer(player); - return void 0; - } - else { - this.print("Invalid provider! Kicking..", 31); - this.removePlayer(player); - return void 0; - } - - player.authenticated = true; - - return (msg); - -} +const REQUEST = proto.Networking.Requests.RequestType; /** * @param {Request} req @@ -92,14 +27,10 @@ export function getRequestType(req) { /** * @param {Request} req - * @param {Response} res */ -export function onRequest(req, res) { +export function onRequest(req) { - this.player = this.getPlayerByRequest(req); - this.player.response = res; - - let player = this.player; + let player = this.getPlayerByRequest(req); // Validate email verification if (player.authenticated) { @@ -117,7 +48,7 @@ export function onRequest(req, res) { return void 0; } - if (CFG.SERVER_LOG_REQUESTS) { + if (CFG.DEBUG_LOG_REQUESTS) { console.log("#####"); request.requests.map((request) => { console.log("Got request:", this.getRequestType(request)); @@ -125,16 +56,16 @@ export function onRequest(req, res) { } if (!player.authenticated) { - this.send(this.authenticatePlayer()); + player.sendResponse(this.authenticatePlayer(player)); return void 0; } - this.processRequests(request.requests).then((answer) => { + this.processRequests(player, request.requests).then((answer) => { let msg = this.envelopResponse(1, request.request_id, answer, !!request.auth_ticket); - if (CFG.SERVER_DUMP_TRAFFIC) { + if (CFG.DEBUG_DUMP_TRAFFIC) { this.dumpTraffic(req.body, msg); } - this.send(msg); + player.sendResponse(msg); }); } @@ -161,10 +92,11 @@ export function envelopResponse(status, id, response, auth) { } /** + * @param {Player} player * @param {Array} requests * @return {Array} */ -export function processRequests(requests) { +export function processRequests(player, requests) { return new Promise((resolve) => { @@ -173,7 +105,7 @@ export function processRequests(requests) { let body = []; let loop = (index) => { - this.processResponse(requests[index]).then((request) => { + this.processResponse(player, requests[index]).then((request) => { body.push(request); if (++index >= length) resolve(body); else return loop(index); @@ -188,9 +120,8 @@ export function processRequests(requests) { /** * @param {Request} req - * @param {Response} res */ -export function routeRequest(req, res) { +export function routeRequest(req) { let url = String(req.url); let route = url.substring(url.lastIndexOf("/") + 1); @@ -198,17 +129,7 @@ export function routeRequest(req, res) { switch (route) { case "rpc": - this.onRequest(req, res); - break; - case "oauth": - let out = null; - let buffer = req.body.toString(); - let signature = "321187995bc7cdc2b5fc91b11a96e2baa8602c62"; - if (/Email.*com.nianticlabs.pokemongo/.test(buffer)) { - out = new Buffer(buffer.replace(/&client_sig=[^&]*&/, "&client_sig=" + signature + "&")); - } - console.log("OAUTH", out); - if (out instanceof Buffer) this.send(out); + this.onRequest(req); break; default: console.log(`Unknown request url: https://${req.headers.host}${req.url}`); @@ -223,22 +144,4 @@ export function routeRequest(req, res) { */ export function validRequest(req) { return (true); -} - -/** - * @return {Buffer} - */ -export function getRequestBody() { - return ( - this.request.body - ); -} - -/** - * @param {Buffer} buffer - */ -export function send(buffer) { - - this.player.response.end(buffer); - } \ No newline at end of file diff --git a/src/requests.js b/src/requests.js deleted file mode 100644 index b777c38..0000000 --- a/src/requests.js +++ /dev/null @@ -1,73 +0,0 @@ -export const REQUEST = { - METHOD_UNSET: 0, // No implementation required - PLAYER_UPDATE: 1, // Implemented [R & M] - GET_PLAYER: 2, // Implemented [R & M] - GET_INVENTORY: 4, // Implemented [R & M] - DOWNLOAD_SETTINGS: 5, // Implemented [R & M] - DOWNLOAD_ITEM_TEMPLATES: 6, // Implemented [R & M] - DOWNLOAD_REMOTE_CONFIG_VERSION: 7, // Implemented [R & M] - FORT_SEARCH: 101, // Implemented [R & M] - ENCOUNTER: 102, // Implemented [R & M] - CATCH_POKEMON: 103, // Implemented [R & M] - FORT_DETAILS: 104, // Implemented [R & M] - ITEM_USE: 105, // Can't find this one - GET_MAP_OBJECTS: 106, // Implemented [R & M] - FORT_DEPLOY_POKEMON: 110, // Implemented [R & M] - FORT_RECALL_POKEMON: 111, // Implemented [R & M] - RELEASE_POKEMON: 112, // Implemented [R & M] - USE_ITEM_POTION: 113, // Implemented [R & M] - USE_ITEM_CAPTURE: 114, // Implemented [R & M] - USE_ITEM_FLEE: 115, // Can't find this one - USE_ITEM_REVIVE: 116, // Implemented [R & M] - TRADE_SEARCH: 117, // Not yet implemented in the game - TRADE_OFFER: 118, // Not yet implemented in the game - TRADE_RESPONSE: 119, // Not yet implemented in the game - TRADE_RESULT: 120, // Not yet implemented in the game - GET_PLAYER_PROFILE: 121, // Implemented [R & M] - GET_ITEM_PACK: 122, // Can't find this one - BUY_ITEM_PACK: 123, // Can't find this one - BUY_GEM_PACK: 124, // Can't find this one - EVOLVE_POKEMON: 125, // Implemented [R & M] - GET_HATCHED_EGGS: 126, // Implemented [R & M] - ENCOUNTER_TUTORIAL_COMPLETE: 127, // Implemented [R & M] - LEVEL_UP_REWARDS: 128, // Implemented [R & M] - CHECK_AWARDED_BADGES: 129, // Implemented [R & M] - USE_ITEM_GYM: 133, // Implemented [R & M] - GET_GYM_DETAILS: 134, // Implemented [R & M] - START_GYM_BATTLE: 135, // Implemented [R & M] - ATTACK_GYM: 136, // Implemented [R & M] - RECYCLE_INVENTORY_ITEM: 137, // Implemented [R & M] - COLLECT_DAILY_BONUS: 138, // Implemented [R & M] - USE_ITEM_XP_BOOST: 139, // Implemented [R & M] - USE_ITEM_EGG_INCUBATOR: 140, // Implemented [R & M] - USE_INCENSE: 141, // Implemented [R & M] - GET_INCENSE_POKEMON: 142, // Implemented [R & M] - INCENSE_ENCOUNTER: 143, // Implemented [R & M] - ADD_FORT_MODIFIER: 144, // Implemented [R & M] - DISK_ENCOUNTER: 145, // Implemented [R & M] - COLLECT_DAILY_DEFENDER_BONUS: 146, // Implemented [R & M] - UPGRADE_POKEMON: 147, // Implemented [R & M] - SET_FAVORITE_POKEMON: 148, // Implemented [R & M] - NICKNAME_POKEMON: 149, // Implemented [R & M] - EQUIP_BADGE: 150, // Implemented [R & M] - SET_CONTACT_SETTINGS: 151, // Implemented [R & M] - GET_ASSET_DIGEST: 300, // Implemented [R & M] - GET_DOWNLOAD_URLS: 301, // Implemented [R & M] - GET_SUGGESTED_CODENAMES: 401, // Implemented [R & M] - CHECK_CODENAME_AVAILABLE: 402, // Implemented [R & M] TEST RESPONSE - CLAIM_CODENAME: 403, // Implemented [R & M] TEST RESPONSE - SET_AVATAR: 404, // Implemented [R & M] - SET_PLAYER_TEAM: 405, // Implemented [R & M] - MARK_TUTORIAL_COMPLETE: 406, // Implemented [R & M] - LOAD_SPAWN_POINTS: 500, // Can't find this one - ECHO: 666, // Implemented [R & M] - DEBUG_UPDATE_INVENTORY: 700, - DEBUG_DELETE_PLAYER: 701, - SFIDA_REGISTRATION: 800, // Not yet released. - SFIDA_ACTION_LOG: 801, // Not yet released. - SFIDA_CERTIFICATION: 802, // Not yet released. - SFIDA_UPDATE: 803, // Not yet released. - SFIDA_ACTION: 804, // Not yet released. - SFIDA_DOWSER: 805, // Not yet released. - SFIDA_CAPTURE: 806 // Not yet released. -}; \ No newline at end of file diff --git a/src/response.js b/src/response.js index ff975ba..ec8cfb7 100644 --- a/src/response.js +++ b/src/response.js @@ -1,7 +1,6 @@ import proto from "./proto"; -import * as CFG from "../cfg"; -import { REQUEST } from "./requests"; +import CFG from "../cfg"; import { GetInventory, @@ -30,21 +29,23 @@ import { ClaimCodeName } from "./packets"; +const REQUEST = proto.Networking.Requests.RequestType; + /** + * @param {Player} player * @param {Request} req * @return {Buffer} */ -export function processResponse(request) { +export function processResponse(player, req) { let buffer = null; - let player = this.player; return new Promise((resolve) => { try { - switch (request.request_type) { + switch (req.request_type) { case REQUEST.GET_PLAYER: - this.forwardPlayer().then((res) => resolve(res)); + this.forwardPlayer(player).then((res) => resolve(res)); return void 0; break; case REQUEST.GET_HATCHED_EGGS: @@ -57,36 +58,36 @@ export function processResponse(request) { buffer = CheckAwardedBadges(); break; case REQUEST.DOWNLOAD_SETTINGS: - buffer = DownloadSettings(request); + buffer = DownloadSettings(req); break; case REQUEST.DOWNLOAD_ITEM_TEMPLATES: buffer = ItemTemplates(); break; case REQUEST.DOWNLOAD_REMOTE_CONFIG_VERSION: - buffer = DownloadRemoteConfigVersion(request); + buffer = DownloadRemoteConfigVersion(req); break; case REQUEST.GET_ASSET_DIGEST: - buffer = GetAssetDigest(this.asset, request); + buffer = GetAssetDigest(this.asset, req); break; case REQUEST.GET_PLAYER_PROFILE: buffer = GetPlayerProfile(); break; case REQUEST.GET_MAP_OBJECTS: - this.player.updatePosition(request); - buffer = GetMapObjects(player, request); + player.updatePosition(req); + buffer = GetMapObjects(player, req); this.savePlayer(player).then(() => { resolve(buffer); }); return void 0; break; case REQUEST.GET_DOWNLOAD_URLS: - GetDownloadUrls(this.asset, request, this.generateDownloadUrlByAssetId).then((res) => { + GetDownloadUrls(this.asset, req, this.generateDownloadUrlByAssetId).then((res) => { resolve(res); }); return void 0; break; case REQUEST.SET_AVATAR: - player.updateAvatar(request); + player.updateAvatar(req); buffer = SetAvatar(player); this.savePlayer(player).then(() => { resolve(buffer); @@ -104,7 +105,7 @@ export function processResponse(request) { return void 0; break; case REQUEST.CLAIM_CODENAME: - buffer = ClaimCodeName(request, player); + buffer = ClaimCodeName(req, player); this.savePlayer(player).then(() => { resolve(buffer); }); @@ -114,13 +115,13 @@ export function processResponse(request) { buffer = LevelUpRewards(); break; case REQUEST.FORT_DETAILS: - buffer = FortDetails(request); + buffer = FortDetails(req); break; case REQUEST.FORT_SEARCH: buffer = FortSearch(); break; case REQUEST.SET_CONTACT_SETTINGS: - player.updateContactSettings(request); + player.updateContactSettings(req); buffer = SetContactSettings(player); this.savePlayer(player).then(() => { resolve(buffer); @@ -128,26 +129,26 @@ export function processResponse(request) { return void 0; break; case REQUEST.ENCOUNTER: - buffer = Encounter(request); + buffer = Encounter(req); break; case REQUEST.NICKNAME_POKEMON: - buffer = NicknamePokemon(request); + buffer = NicknamePokemon(req); break; case REQUEST.UPGRADE_POKEMON: - buffer = UpgradePokemon(request); + buffer = UpgradePokemon(req); break; case REQUEST.EVOLVE_POKEMON: - buffer = EvolvePokemon(request); + buffer = EvolvePokemon(req); break; case REQUEST.SET_FAVORITE_POKEMON: - buffer = SetFavoritePokemon(request); + buffer = SetFavoritePokemon(req); break; case REQUEST.CATCH_POKEMON: - let data = proto.Networking.Requests.Messages.CatchPokemonMessage.decode(request.request_message.toBuffer()); + let data = proto.Networking.Requests.Messages.CatchPokemonMessage.decode(req.request_message.toBuffer()); console.log(data); break; default: - this.print(`Unknown request: ${this.getRequestType(request)}`, 31); + this.print(`Unknown request: ${this.getRequestType(req)}`, 31); break; }; } catch (e) { diff --git a/src/setup.js b/src/setup.js index e552bf3..c2a3f1a 100644 --- a/src/setup.js +++ b/src/setup.js @@ -1,6 +1,4 @@ -import path from "path"; - -import * as CFG from "../cfg"; +import CFG from "../cfg"; export function setup() { @@ -12,14 +10,14 @@ export function setup() { if (!assetSessionLoaded) { this.print("Boot timeout, please check your login details!", 31); } - }, CFG.SERVER_BOOT_TIMEOUT); + }, CFG.BOOT_TIMEOUT); this.createAssetDownloadSession().then((asset) => { assetSessionLoaded = true; this.asset = asset; this.setupDatabaseConnection().then(() => { - if (CFG.SERVER_PORT < 1) { + if (CFG.PORT < 1) { this.print("Invalid port!", 31); return void 0; } @@ -28,7 +26,9 @@ export function setup() { setTimeout(this::this.cycle, 1); - this.print(`Server running at ${CFG.SERVER_HOST_IP}:${CFG.SERVER_PORT}`); + let localIPv4 = this.getLocalIPv4(); + + this.print(`Server running at ${localIPv4}:${CFG.PORT}`); }); }); diff --git a/src/utils.js b/src/utils.js index e518ab3..4474ca6 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,7 +1,7 @@ import Long from "long"; import proto from "./proto"; -import * as CFG from "../cfg"; +import CFG from "../cfg"; /** * @param {Object} cls