<commit_before>'use strict';

var debug   = require('debug')('kiss.io:socket');
var parser  = require('socket.io-parser');
var url     = require('url');
var hasBin  = require('has-binary');

var Router  = require('./router');


/**
 * A socket is a representation of a singular socket connection that
 * ..might be part of a larger connection pool, represented by `Client`.
 * Socket is specific to one namespace of one server.
 *
 * @constructs Socket
 * @access public
 *
 * @param {Namespace} nsp: the namespace that the socket is connected to.
 * @param {Client} client: the client instance that owns the socket.
 * @param {Object} query: the query params of the request.
 * @returns {Socket}
 */
function Socket(nsp, client, query)
{
  if(!(this instanceof Socket))
  {
    return new Socket(nsp, client, query);
  }

  this.nsp = nsp;
  this.id = nsp.name !== '/' ? nsp.name + '#' + client.id : client.id;
  this.opts = this.nsp.opts || {};
  this.client = client;
  this.conn = client.conn;
  this.request = this.conn.request;
  this.acks = {};
  this.connected = true;
  this.handshake = this.buildHandshake(query);
}

/**
 * Built-in, emitted by default events.
 */
Socket.events =
[
  'error',
  'pre-setup',
  'connect',
  'connection',
  'pre-disconnect',
  'pre-disconnection',
  'disconnect',
  'disconnection',
  'newListener',
  'removeListener'
];

/**
 * Set/get a temporary flag.
 *
 * @access public
 *
 * @param {String} key: the name of the flag.
 * @param {*} [value]
 * @returns {*|undefined} value
 */
Socket.prototype.flag = function(key, value)
{
  this._flags = this._flags || {};

  if(arguments.length == 2)
  {
    this._flags[key] = value;
  }

  return this._flags;
};

/**
 * Reset temporary flags
 *
 * @access public
 */
Socket.prototype.reset = function()
{
  delete this._flags;
};

/**
 * Builds the `handshake` BC object
 *
 * @access private
 *
 * @param {Object} [query]: if not provided, uses Socket.request query.
 * @returns {Object} handshake
 */
Socket.prototype.buildHandshake = function(query)
{
  var requestQuery = url.parse(this.request.url, true).query || {};

  query = query || requestQuery;
  query.t = requestQuery.t;
  query.EIO = requestQuery.EIO;
  query.transport = requestQuery.transport;

  return {
    headers: this.request.headers,
    time: (new Date) + '',
    address: this.conn.remoteAddress,
    xdomain: !!this.request.headers.origin,
    secure: !!this.request.connection.encrypted,
    issued: +(new Date),
    url: this.request.url,
    query: query
  };
};

Socket.prototype.plug =
Socket.prototype.plugin = function(plugin)
{
  var exports = plugin.exports.socket || {};

  for(let key of Object.keys(exports))
  {
    let value = exports[key];

    if(typeof value == 'function')
    {
      value = value.bind(plugin, this);
    }
    else if(typeof value == 'object')
    {
      value = Object.create(value);
    }

    this[key] = value;
  }

  return this;
};

/**
 * Trigger an inside event for Socket.
 *
 * @access private
 *
 * @param {String} ev
 */
Socket.prototype.trigger = function(ev)
{
};

/**
 * Emits an event to the owning `Client`.
 * If event not in the reserved event list (Socket.events),
 * ..then send a packet to the socket with the given arguments.
 *<commit_msg>[major] Instead of binding context to router, passes socket as first param<commit_after>'use strict';

var debug   = require('debug')('kiss.io:socket');
var parser  = require('socket.io-parser');
var url     = require('url');
var hasBin  = require('has-binary');

var Router  = require('./router');


/**
 * A socket is a representation of a singular socket connection that
 * ..might be part of a larger connection pool, represented by `Client`.
 * Socket is specific to one namespace of one server.
 *
 * @constructs Socket
 * @access public
 *
 * @param {Namespace} nsp: the namespace that the socket is connected to.
 * @param {Client} client: the client instance that owns the socket.
 * @param {Object} query: the query params of the request.
 * @returns {Socket}
 */
function Socket(nsp, client, query)
{
  if(!(this instanceof Socket))
  {
    return new Socket(nsp, client, query);
  }

  this.nsp = nsp;
  this.id = nsp.name !== '/' ? nsp.name + '#' + client.id : client.id;
  this.opts = this.nsp.opts || {};
  this.client = client;
  this.conn = client.conn;
  this.request = this.conn.request;
  this.acks = {};
  this.connected = true;
  this.handshake = this.buildHandshake(query);
}

/**
 * Built-in, emitted by default events.
 */
Socket.events =
[
  'error',
  'pre-setup',
  'connect',
  'connection',
  'pre-disconnect',
  'pre-disconnection',
  'disconnect',
  'disconnection',
  'newListener',
  'removeListener'
];

/**
 * Set/get a temporary flag.
 *
 * @access public
 *
 * @param {String} key: the name of the flag.
 * @param {*} [value]
 * @returns {*|undefined} value
 */
Socket.prototype.flag = function(key, value)
{
  this._flags = this._flags || {};

  if(arguments.length == 2)
  {
    this._flags[key] = value;
  }

  return this._flags;
};

/**
 * Reset temporary flags
 *
 * @access public
 */
Socket.prototype.reset = function()
{
  delete this._flags;
};

/**
 * Builds the `handshake` BC object
 *
 * @access private
 *
 * @param {Object} [query]: if not provided, uses Socket.request query.
 * @returns {Object} handshake
 */
Socket.prototype.buildHandshake = function(query)
{
  var requestQuery = url.parse(this.request.url, true).query || {};

  query = query || requestQuery;
  query.t = requestQuery.t;
  query.EIO = requestQuery.EIO;
  query.transport = requestQuery.transport;

  return {
    headers: this.request.headers,
    time: (new Date) + '',
    address: this.conn.remoteAddress,
    xdomain: !!this.request.headers.origin,
    secure: !!this.request.connection.encrypted,
    issued: +(new Date),
    url: this.request.url,
    query: query
  };
};

Socket.prototype.plug =
Socket.prototype.plugin = function(plugin)
{
  var exports = plugin.exports.socket || {};

  for(let key of Object.keys(exports))
  {
    let value = exports[key];

    if(typeof value == 'function')
    {
      value = value.bind(plugin, this);
    }
    else if(typeof value == 'object')
    {
      value = Object.create(value);
    }

    this[key] = value;
  }

  return this;
};

/**
 * Trigger an inside event for Socket.
 *
 * @access private
 *
 * @param {String} ev
 */
Socket.prototype.trigger = function(ev)
{
  var args = Array.prototype.slice.call(arguments);
  args.splice(1, 0, this);

  this.nsp.router.emit.apply(this.nsp.router, args);
};

/**
 * Emits an event to the owning `Client`.
 * If event not in the reserved event list (Socket.events),
 * ..then send a packet to the socket with the given arguments.
 *
{'fraction_non_alphanumeric': 0.1524517087667162, 'fraction_numerical': 0.0005943536404160475, 'mean_word_length': 3.2763659466327826, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '292312', 'n_tokens_mistral': 2203, 'n_tokens_neox': 2171, 'n_words': 605}