<commit_before>/**
 * Connections - nocluster edition
 * Pokemon Showdown - http://pokemonshowdown.com/
 *
 * Abstraction layer for multi-process SockJS connections.
 *
 * This file handles all the communications between the users'
 * browsers, the networking processes, and users.js in the
 * main process.
 *
 * The nocluster edition uses child_process instead of cluster.
 * The main drawback is that it can only spawn one process, but
 * one process should be enough for everyone. The main advantage
 * is unknown, but I'm hoping it will be more stable.
 *
 * @license MIT license
 */

'use strict';

global.Config = require('./config/config');

if (!process.send) {
	let workers = exports.workers = {};
	let nextId = 0;

	let spawnWorker = exports.spawnWorker = function () {
		let worker = require('child_process').fork('sockets-nocluster.js', {PSPORT: Config.port, PSBINDADDR: Config.bindaddress || '', PSNOSSL: Config.ssl ? 0 : 1});
		if (!worker.id) worker.id = '' + (++nextId);
		let id = worker.id;
		workers[id] = worker;
		worker.on('message', data => {
			// console.log('master received: ' + data);
			switch (data.charAt(0)) {
			case '*': {
				// *socketid, ip
				// connect
				let nlPos = data.indexOf('\n');
				Users.socketConnect(worker, id, data.substr(1, nlPos - 1), data.substr(nlPos + 1));
				break;
			}

			case '!': {
				// !socketid
				// disconnect
				Users.socketDisconnect(worker, id, data.substr(1));
				break;
			}

			case '<': {
				// <socketid, message
				// message
				let nlPos = data.indexOf('\n');
				Users.socketReceive(worker, id, data.substr(1, nlPos - 1), data.substr(nlPos + 1));
				break;
			}

			default:
			// unhandled
			}
		});
	};

	/* worker.on('disconnect', worker => {
		// worker crashed, try our best to clean up
		require('./crashlogger.js')(new Error("Worker " + worker.id + " abruptly died"), "The main process");

		// this could get called during cleanup; prevent it from crashing
		worker.send = () => {};

		let count = 0;
		Users.connections.forEach(connection => {
			if (connection.worker === worker) {
				Users.socketDisconnect(worker, worker.id, connection.socketid);
				count++;
			}
		});
		console.error("" + count + " connections were lost.");

		// don't delete the worker, so we can investigate it if necessary.

		// attempt to recover
		spawnWorker();
	}); */

	exports.listen = function (port, bindAddress, workerCount) {
		if (port !== undefined && !isNaN(port)) {
			Config.port = port;
			Config.ssl = null;
		} else {
			port = Config.port;
			// Autoconfigure the app when running in cloud hosting environments:
			try {
				let cloudenv = require('cloud-env');
				bindAddress = cloudenv.get('IP', bindAddress);
				port = cloudenv.get('PORT', port);
			} catch (e) {}
		}
		if (bindAddress !== undefined) {
			Config.bindaddress = bindAddress;
		}<commit_msg>Support autorecovering from socket crashes<commit_after>/**
 * Connections - nocluster edition
 * Pokemon Showdown - http://pokemonshowdown.com/
 *
 * Abstraction layer for multi-process SockJS connections.
 *
 * This file handles all the communications between the users'
 * browsers, the networking processes, and users.js in the
 * main process.
 *
 * The nocluster edition uses child_process instead of cluster.
 * The main drawback is that it can only spawn one process, but
 * one process should be enough for everyone. The main advantage
 * is unknown, but I'm hoping it will be more stable.
 *
 * @license MIT license
 */

'use strict';

global.Config = require('./config/config');

if (!process.send) {
	let workers = exports.workers = {};
	let nextId = 0;

	let spawnWorker = exports.spawnWorker = function () {
		let worker = require('child_process').fork('sockets-nocluster.js', {PSPORT: Config.port, PSBINDADDR: Config.bindaddress || '', PSNOSSL: Config.ssl ? 0 : 1});
		if (!worker.id) worker.id = '' + (++nextId);
		let id = worker.id;
		workers[id] = worker;
		worker.on('message', data => {
			// console.log('master received: ' + data);
			switch (data.charAt(0)) {
			case '*': {
				// *socketid, ip
				// connect
				let nlPos = data.indexOf('\n');
				Users.socketConnect(worker, id, data.substr(1, nlPos - 1), data.substr(nlPos + 1));
				break;
			}

			case '!': {
				// !socketid
				// disconnect
				Users.socketDisconnect(worker, id, data.substr(1));
				break;
			}

			case '<': {
				// <socketid, message
				// message
				let nlPos = data.indexOf('\n');
				Users.socketReceive(worker, id, data.substr(1, nlPos - 1), data.substr(nlPos + 1));
				break;
			}

			default:
			// unhandled
			}
		});

		worker.on('disconnect', () => {
			// worker crashed, try our best to clean up
			require('./crashlogger.js')(new Error("Worker " + worker.id + " abruptly died"), "The main process");

			// this could get called during cleanup; prevent it from crashing
			worker.send = () => {};

			let count = 0;
			Users.connections.forEach(connection => {
				if (connection.worker === worker) {
					Users.socketDisconnect(worker, worker.id, connection.socketid);
					count++;
				}
			});
			console.error("" + count + " connections were lost.");

			// don't delete the worker, so we can investigate it if necessary.

			// attempt to recover
			spawnWorker();
		});
	};

	exports.listen = function (port, bindAddress, workerCount) {
		if (port !== undefined && !isNaN(port)) {
			Config.port = port;
			Config.ssl = null;
		} else {
			port = Config.port;
			// Autoconfigure the app when running in cloud hosting environments:
			try {
				let cloudenv = require('cloud-env');
				bindAddress = cloudenv.get('IP', bindAddress);
				port = cloudenv.get('PORT', port);
			} catch (e) {}
		}
		if (bindAddress !== undefined) {
			Config.bindaddress = bindAddress;
		}
{'fraction_non_alphanumeric': 0.14901007294199375, 'fraction_numerical': 0.004168113928447377, 'mean_word_length': 3.1135714285714284, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4471685', 'n_tokens_mistral': 2090, 'n_tokens_neox': 1769, 'n_words': 521}