<commit_before>// TODO: stop refresh loops when closing connection

'use strict'

var AbstractTransport = require('./abstract')
var runtime = require('mm-runtime-info')
var turn = require('turn-js')
var TurnSession = require('./streams/turn')
var TurnTransports = turn.transports
var TurnClient = turn.TurnClient
var util = require('util')
var winston = require('winston')
var winstonWrapper = require('winston-meta-wrapper')

/**
 * Turn transport
 *
 * @constructor
 * @fires TurnTransport#listening
 * @fires TurnTransport#connection
 * @fires TurnTransport#connect
 * @fires TurnTransport#error
 * @fires TurnTransport#signaling
 */
function TurnTransport (args) {
  if (!(this instanceof TurnTransport)) {
    return new TurnTransport(args)
  }
  AbstractTransport.call(this)
  // verify runtime compatibility
  if (!TurnTransport.isCompatibleWithRuntime(args)) {
    var errorMsg = 'TURN transport cannot be used on this runtime'
    this._error(errorMsg)
  }
  // logging
  this._log = winstonWrapper(winston)
  this._log.addMeta({
    module: '1tp:transports:turn'
  })
  // verify args
  if (
    args.turnServer === undefined ||
    args.turnPort === undefined ||
    args.turnUsername === undefined ||
    args.turnPassword === undefined
  ) {
    var turnArgsError = 'incorrect args: turnServer and/or turnPort and/or turnUsername and/or turnPassword are undefined'
    this._log.error(turnArgsError)
    throw new Error(turnArgsError)
  }
  if (args.signaling === undefined) {
    var signalingArgsError = 'incorrect args: signaling is undefined'
    this._log.error(signalingArgsError)
    throw new Error(signalingArgsError)
  }
  // store args
  this._turnProtocol = (args.turnProtocol === undefined) ? new TurnTransports.UDP() : args.turnProtocol
  this._turn = turn(
    args.turnServer,
    args.turnPort,
    args.turnUsername,
    args.turnPassword,
    this._turnProtocol
  )
  this._signaling = args.signaling
  // accept new incoming connections
  this._acceptIncomingConnections = true
  // done
  this._log.debug('created ' + this.transportType() + ' transport')
}

// Inherit from abstract transport
util.inherits(TurnTransport, AbstractTransport)

TurnTransport.TIMEOUT_MARGIN = 10000

TurnTransport.isCompatibleWithRuntime = function (args) {
  // if udp
  if (args.turnProtocol === undefined ||
    args.turnProtocol instanceof TurnTransports.UDP
  ) {
    return !runtime.isBrowser()
  // if tcp
  } else if (args.turnProtocol instanceof TurnTransports.TCP) {
    return !runtime.isBrowser() && !runtime.isCordovaApp()
  } else {
    throw new Error("don't know how to process turn transport " + args.turnProtocol)
  }
}

TurnTransport.prototype.transportType = function () {
  if (this._turnProtocol instanceof TurnTransports.UDP) {
    return 'turn-udp'
  } else if (this._turnProtocol instanceof TurnTransports.TCP) {
    return 'turn-tcp'
  } else {
    this._error("don't know how to classify turn transport " + this._turnProtocol)
  }
}

TurnTransport.prototype.connectTimeout = function () {
  return 2000
}

TurnTransport.prototype.listen = function (listeningInfo, onSuccess, onFailure) {
  this._log.debug('listen to ' + JSON.stringify(listeningInfo))
  var requestedRegistrationInfo
  if (listeningInfo !== undefined) {
    // verify listeningInfo
    if (listeningInfo.transportType !== this.transportType()) {
      var transportTypeError = 'incorrect listeningInfo: unexpected transportType -- ignoring request'
      this._log.error(transportTypeError)
      this._error(transportTypeError, onFailure)
      return
    }
    if (listeningInfo.transportInfo === undefined) {
      var transportInfoUndefined = 'incorrect connectionInfo: transportInfo is undefined'
      this._log.error(transportInfoUndefined)
      this._error(transportInfoUndefined, onFailure)
      return
    }
    requestedRegistrationInfo = listeningInfo.transportInfo
  }
  // register callback with signaling connector
  var self = this
  this._signaling.registerP(this._onSignalingMessage.bind(this), requestedRegistrationInfo)
    .then(function (actualRegistrationInfo) {
      var myConnectionInfo = {
        transportType: self.transportType(),
        transportInfo: actualRegistrationInfo,
        version: self.version
      }
      self._myConnectionInfo = myConnectionInfo
      // send 'listening' event
      self._fireListeningEvent(myConnectionInfo, onSuccess)
    })
    .catch(function (error) {
      self._log.error(error)
      self._error(error, onFailure)
    })
}

TurnTransport.prototype.connect = function (peerConnectionInfo, onSuccess, onFailure) {
  this._log.debug('connect to ' + JSON.stringify(peerConnectionInfo))
  // verify peerConnectionInfo
  if (peerConnectionInfo.transportType !== this.transportType()) {
    var transportTypeError = 'incorrect connectionInfo: unexpected transportType -- ignoring request'
    this._log.error(transportTypeError)
    this._error(transportTypeError, onFailure)
    return
  }
  if (peerConnectionInfo.transportInfo === undefined) {
    var transportInfoUndefined = 'incorrect connectionInfo: transportInfo is undefined'
    this._log.error(transportInfoUndefined)
    this._error(transportInfoUndefined, onFailure)
    return
  }
  // register callback with signaling connector
  var self = this
  this._signaling.registerP(this._onSignalingMessage.bind(this))
    .then(function (actualRegistrationInfo) {
      var myConnectionInfo = {
        transportType: self.transportType(),
        transportInfo: actualRegistrationInfo,
        version: self.version
      }
      self._myConnectionInfo = myConnectionInfo
      return self._turn.allocateP()
    })
    .then(function (allocateReply) {
      self._srflxAddress = allocateReply.mappedAddress
      self._relayAddress = allocateReply.relayedAddress
      if (allocateReply.lifetime !== undefined) {
        self._allocationLifetime = allocateReply.lifetime
      }
      self._log.debug('srflx address = ' + self._srflxAddress.address + ':' + self._srflxAddress.port)
      self._log.debug('relay address = ' + self._relayAddress.address + ':' + self._relayAddress.port)
      self._log.debug('lifetime = ' + self._allocationLifetime)
      // start refresh interval
      self._startRefreshLoop()
      // store callbacks for later use
      self._connectOnSuccess = onSuccess
      self._connectOnFailure = onFailure
      self._peerConnectionInfo = peerConnectionInfo
      // send connect request to peer
      var signalingDestination = peerConnectionInfo.transportInfo
      var signalingMessage = {
        version: self.version,
        sender: self._myConnectionInfo.transportInfo,
        operationType: 'connect',
        operationContent: {
          srflxAddress: self._srflxAddress,
          relayAddress: self._relayAddress
        }
      }
      return self._signaling.sendP(signalingMessage, signalingDestination)
    })
    .then(function () {
      self._log.debug("'connect' message sent")
    })
    .catch(function (error) {
      self._log.error(error)
      self._error(error, onFailure)
    })
}

TurnTransport.prototype.blockIncomingConnections = function () {
  this._acceptIncomingConnections = false
}

TurnTransport.prototype._onSignalingMessage = function (message) {
  this._log.debug('receiving signaling message ' + JSON.stringify(message))
  if (message.version === undefined) {
    var undefinedVersionError = 'incorrect signaling message: undefined version -- ignoring request'
    this._log.error(undefinedVersionError)
    this._error(undefinedVersionError)
    return
  }
  var operationType = message.operationType
  if (operationType === undefined) {
    var undefinedOperationTypeError = 'incorrect signaling message: undefined operationType -- ignoring request'
    this._log.error(undefinedOperationTypeError)
    this._error(undefinedOperationTypeError)
    return
  }
  switch (operationType) {
    case 'connect':
      if (this._acceptIncomingConnections) {
        this._onConnectRequest(message)
      } else {
        this._log.debug('not accepting new connections -- dropping connect request on the floor')
      }
      break
    case 'ready':
      this._onReadyMessage(message)
      break
    default:
      var unknownOperationTypeError = "incorrect signaling message: don't know how to process operationType " + operationType + ' -- ignoring request'
      this._log.error(unknownOperationTypeError)
      this._error(unknownOperationTypeError)
  }
}

TurnTransport.prototype._onConnectRequest = function (message) {
  var connectRequest = message.operationContent
  if (connectRequest === undefined) {
    var undefinedOperationContentError = 'incorrect signaling message: undefined operationContent -- ignoring request'
    this._log.error(undefinedOperationContentError)
    this._error(undefinedOperationContentError)
    return
  }
  var sender = message.sender
  if (sender === undefined) {
    var undefinedSenderError = 'incorrect signaling message: undefined sender -- ignoring request'
    this._log.error(undefinedSenderError)
    this._error(undefinedSenderError)
    return
  }
  var self = this
  // first allocate TURN resource
  this._turn.allocateP()
    .then(function (allocateReply) {
      self._srflxAddress = allocateReply.mappedAddress
      self._relayAddress = allocateReply.relayedAddress
      if (allocateReply.lifetime !== undefined) {
        self._allocationLifetime = allocateReply.lifetime
      }
      self._log.debug('srflx address = ' + self._srflxAddress.address + ':' + self._srflxAddress.port)
      self._log.debug('relay address = ' + self._relayAddress.address + ':' + self._relayAddress.port)
      self._log.debug('lifetime = ' + self._allocationLifetime)
      // start refresh interval
      self._startRefreshLoop()
      // then create permission for peer to reach me
      return self._turn.createPermissionP(connectRequest.relayAddress.address)
    })
    .then(function () {
      // start permission refresh timer
      self._startCreatePermissionTimer(connectRequest.relayAddress.address)
      // create duplex stream
      var peerConnectionInfo = {
        mappedAddress: connectRequest.srflxAddress,
        relayedAddress: connectRequest.relayAddress
      }
      var stream = new TurnSession(peerConnectionInfo, self._turn)
      // fire connection event
      self._fireConnectionEvent(stream, self, peerConnectionInfo)
      // send ready response to peer
      var signalingDestination = sender
      var signalingMessage = {
        version: self.version,
        sender: self._myConnectionInfo.transportInfo,
        operationType: 'ready',
        operationContent: {
          srflxAddress: self._srflxAddress,
          relayAddress: self._relayAddress
        }
      }
      return self._signaling.sendP(signalingMessage, signalingDestination)
    })
    .then(function () {
      self._log.debug("'ready' message sent")
    })
    .catch(function (error) {
      self._log.error(error)
      self._error(error)
    })
}

TurnTransport.prototype._onReadyMessage = function (message) {
  var connectRequest = message.operationContent
  if (connectRequest === undefined) {
    var undefinedOperationContentError = 'incorrect signaling message: undefined operationContent -- ignoring request'
    this._log.error(undefinedOperationContentError)
    this._error(undefinedOperationContentError)
    return
  }
  var sender = message.sender
  if (sender === undefined) {
    var undefinedSenderError = 'incorrect signaling message: undefined sender -- ignoring request'
    this._log.error(undefinedSenderError)
    this._error(undefinedSenderError)
    return
  }
  var self = this
  // create permission for peer to reach me
  this._turn.createPermissionP(connectRequest.relayAddress.address)
    .then(function () {
      // start permission refresh timer
      self._startCreatePermissionTimer(connectRequest.relayAddress.address)
      // create duplex stream
      var peerConnectionInfo = {
        mappedAddress: connectRequest.srflxAddress,
        relayedAddress: connectRequest.relayAddress
      }
      // create duplex stream
      var stream = new TurnSession(peerConnectionInfo, self._turn)
      // fire connect event
      self._fireConnectEvent(stream, self._peerConnectionInfo, self._connectOnSuccess)
    })
    .catch(function (error) {
      self._log.error(error)
      self._error(error)
    })
}

TurnTransport.prototype._startRefreshLoop = function () {
  var self = this
  // start refresh timer if allocation lifetime is specified
  if (this._allocationLifetime !== undefined) {
    this._log.debug('activating refresh loop -- lifetime was set to ' + this._allocationLifetime)
    this._startRefreshTimer(this._allocationLifetime)
    return
  }
  // otherwise execute refresh operation using the default TURN allocation timeout to retrieve actual lifetime
  this._turn.refreshP(TurnClient.DEFAULT_ALLOCATION_LIFETIME)
    .then(function (lifetime) {
      self._log.debug('activating refresh loop -- allocation lifetime ' + lifetime)
      self._allocationLifetime = lifetime
      self._startRefreshTimer(self._allocationLifetime)
    })
    .catch(function (error) {
      self._log.error(error)
      self._error(error)
    })
}

TurnTransport.prototype._startRefreshTimer = function (lifetime) {
  var self = this
  this._refreshTimer = setInterval(function () {
    self._turn.refreshP(lifetime)
      .then(function (duration) {
        self._log.debug('executed refresh operation, retrieving lifetime ' + duration)
      })
      .catch(function (error) {
        self._stopRefreshTimer()
        var errorMsg = 'error while sending TURN refresh message: ' + error
        self._log.error(errorMsg)
        self._error(errorMsg)
      })
  }, lifetime * 1000 - TurnTransport.TIMEOUT_MARGIN)
}

TurnTransport.prototype._stopRefreshTimer = function () {
  clearInterval(this._refreshTimer)
}

TurnTransport.prototype._startCreatePermissionTimer = function (address) {
  var self = this
  this._createPermissionTimer = setInterval(function () {
    self._turn.createPermissionP(address)
      .then(function () {
        self._log.debug('executed create permission refresh')
      })
      .catch(function (error) {
        self._stopCreatePermissionTimer()
        var errorMsg = 'error while refreshing TURN permission: ' + error
        self._log.error(errorMsg)
        self._error(errorMsg)
      })
  }, TurnClient.CREATE_PERMISSION_LIFETIME * 1000 - TurnTransport.TIMEOUT_MARGIN)
}

TurnTransport.prototype._stopCreatePermissionTimer = function () {
  clearInterval(this._createPermissionTimer)
}

TurnTransport.prototype._startChannelBindTimer = function (address, port, channel) {
  var self = this
  this._channelBindTimer = setInterval(function () {
    self._turn.bindChannelP(address, port, channel)
      .then(function (channel) {
        self._log.debug('executed bind channel refresh, retrieving channel ' + channel)
      })
      .catch(function (error) {
        self._stopChannelBindTimer()
        var errorMsg = 'failure while refreshing channel binding: ' + error
        self._log.error(errorMsg)
        self._error(errorMsg)
      })
  }, TurnClient.CHANNEL_BINDING_LIFETIME * 1000 - TurnTransport.TIMEOUT_MARGIN)
}

TurnTransport.prototype._stopChannelBindTimer = function () {
  clearInterval(this._channelBindTimer)
}

module.exports = TurnTransport
<commit_msg>keeping track of ongoing turn sessions<commit_after>// TODO: stop refresh loops when closing connection

'use strict'

var AbstractTransport = require('./abstract')
var runtime = require('mm-runtime-info')
var turn = require('turn-js')
var TurnSession = require('./streams/turn')
var TurnTransports = turn.transports
var TurnClient = turn.TurnClient
var util = require('util')
var winston = require('winston')
var winstonWrapper = require('winston-meta-wrapper')

/**
 * Turn transport
 *
 * @constructor
 * @fires TurnTransport#listening
 * @fires TurnTransport#connection
 * @fires TurnTransport#connect
 * @fires TurnTransport#error
 * @fires TurnTransport#signaling
 */
function TurnTransport (args) {
  if (!(this instanceof TurnTransport)) {
    return new TurnTransport(args)
  }
  AbstractTransport.call(this)
  // verify runtime compatibility
  if (!TurnTransport.isCompatibleWithRuntime(args)) {
    var errorMsg = 'TURN transport cannot be used on this runtime'
    this._error(errorMsg)
  }
  // logging
  this._log = winstonWrapper(winston)
  this._log.addMeta({
    module: '1tp:transports:turn'
  })
  // verify args
  if (
    args.turnServer === undefined ||
    args.turnPort === undefined ||
    args.turnUsername === undefined ||
    args.turnPassword === undefined
  ) {
    var turnArgsError = 'incorrect args: turnServer and/or turnPort and/or turnUsername and/or turnPassword are undefined'
    this._log.error(turnArgsError)
    throw new Error(turnArgsError)
  }
  if (args.signaling === undefined) {
    var signalingArgsError = 'incorrect args: signaling is undefined'
    this._log.error(signalingArgsError)
    throw new Error(signalingArgsError)
  }
  // store args
  this._turnProtocol = (args.turnProtocol === undefined) ? new TurnTransports.UDP() : args.turnProtocol
  this._turn = turn(
    args.turnServer,
    args.turnPort,
    args.turnUsername,
    args.turnPassword,
    this._turnProtocol
  )
  this._signaling = args.signaling
  // keep track of udp sessions
  this._sessions = {}
  // accept new incoming connections
  this._acceptIncomingConnections = true
  // done
  this._log.debug('created ' + this.transportType() + ' transport')
}

// Inherit from abstract transport
util.inherits(TurnTransport, AbstractTransport)

TurnTransport.TIMEOUT_MARGIN = 10000

TurnTransport.isCompatibleWithRuntime = function (args) {
  // if udp
  if (args.turnProtocol === undefined ||
    args.turnProtocol instanceof TurnTransports.UDP
  ) {
    return !runtime.isBrowser()
  // if tcp
  } else if (args.turnProtocol instanceof TurnTransports.TCP) {
    return !runtime.isBrowser() && !runtime.isCordovaApp()
  } else {
    throw new Error("don't know how to process turn transport " + args.turnProtocol)
  }
}

TurnTransport.prototype.transportType = function () {
  if (this._turnProtocol instanceof TurnTransports.UDP) {
    return 'turn-udp'
  } else if (this._turnProtocol instanceof TurnTransports.TCP) {
    return 'turn-tcp'
  } else {
    this._error("don't know how to classify turn transport " + this._turnProtocol)
  }
}

TurnTransport.prototype.connectTimeout = function () {
  return 2000
}

TurnTransport.prototype.listen = function (listeningInfo, onSuccess, onFailure) {
  this._log.debug('listen to ' + JSON.stringify(listeningInfo))
  var requestedRegistrationInfo
  if (listeningInfo !== undefined) {
    // verify listeningInfo
    if (listeningInfo.transportType !== this.transportType()) {
      var transportTypeError = 'incorrect listeningInfo: unexpected transportType -- ignoring request'
      this._log.error(transportTypeError)
      this._error(transportTypeError, onFailure)
      return
    }
    if (listeningInfo.transportInfo === undefined) {
      var transportInfoUndefined = 'incorrect connectionInfo: transportInfo is undefined'
      this._log.error(transportInfoUndefined)
      this._error(transportInfoUndefined, onFailure)
      return
    }
    requestedRegistrationInfo = listeningInfo.transportInfo
  }
  // register callback with signaling connector
  var self = this
  this._signaling.registerP(this._onSignalingMessage.bind(this), requestedRegistrationInfo)
    .then(function (actualRegistrationInfo) {
      var myConnectionInfo = {
        transportType: self.transportType(),
        transportInfo: actualRegistrationInfo,
        version: self.version
      }
      self._myConnectionInfo = myConnectionInfo
      // send 'listening' event
      self._fireListeningEvent(myConnectionInfo, onSuccess)
    })
    .catch(function (error) {
      self._log.error(error)
      self._error(error, onFailure)
    })
}

TurnTransport.prototype.connect = function (peerConnectionInfo, onSuccess, onFailure) {
  this._log.debug('connect to ' + JSON.stringify(peerConnectionInfo))
  // verify peerConnectionInfo
  if (peerConnectionInfo.transportType !== this.transportType()) {
    var transportTypeError = 'incorrect connectionInfo: unexpected transportType -- ignoring request'
    this._log.error(transportTypeError)
    this._error(transportTypeError, onFailure)
    return
  }
  if (peerConnectionInfo.transportInfo === undefined) {
    var transportInfoUndefined = 'incorrect connectionInfo: transportInfo is undefined'
    this._log.error(transportInfoUndefined)
    this._error(transportInfoUndefined, onFailure)
    return
  }
  // register callback with signaling connector
  var self = this
  this._signaling.registerP(this._onSignalingMessage.bind(this))
    .then(function (actualRegistrationInfo) {
      var myConnectionInfo = {
        transportType: self.transportType(),
        transportInfo: actualRegistrationInfo,
        version: self.version
      }
      self._myConnectionInfo = myConnectionInfo
      return self._turn.allocateP()
    })
    .then(function (allocateReply) {
      self._srflxAddress = allocateReply.mappedAddress
      self._relayAddress = allocateReply.relayedAddress
      if (allocateReply.lifetime !== undefined) {
        self._allocationLifetime = allocateReply.lifetime
      }
      self._log.debug('srflx address = ' + self._srflxAddress.address + ':' + self._srflxAddress.port)
      self._log.debug('relay address = ' + self._relayAddress.address + ':' + self._relayAddress.port)
      self._log.debug('lifetime = ' + self._allocationLifetime)
      // start refresh interval
      self._startRefreshLoop()
      // store callbacks for later use
      self._connectOnSuccess = onSuccess
      self._connectOnFailure = onFailure
      self._peerConnectionInfo = peerConnectionInfo
      // send connect request to peer
      var signalingDestination = peerConnectionInfo.transportInfo
      var signalingMessage = {
        version: self.version,
        sender: self._myConnectionInfo.transportInfo,
        operationType: 'connect',
        operationContent: {
          srflxAddress: self._srflxAddress,
          relayAddress: self._relayAddress
        }
      }
      return self._signaling.sendP(signalingMessage, signalingDestination)
    })
    .then(function () {
      self._log.debug("'connect' message sent")
    })
    .catch(function (error) {
      self._log.error(error)
      self._error(error, onFailure)
    })
}

TurnTransport.prototype.blockIncomingConnections = function () {
  this._acceptIncomingConnections = false
}

TurnTransport.prototype._onSignalingMessage = function (message) {
  this._log.debug('receiving signaling message ' + JSON.stringify(message))
  if (message.version === undefined) {
    var undefinedVersionError = 'incorrect signaling message: undefined version -- ignoring request'
    this._log.error(undefinedVersionError)
    this._error(undefinedVersionError)
    return
  }
  var operationType = message.operationType
  if (operationType === undefined) {
    var undefinedOperationTypeError = 'incorrect signaling message: undefined operationType -- ignoring request'
    this._log.error(undefinedOperationTypeError)
    this._error(undefinedOperationTypeError)
    return
  }
  switch (operationType) {
    case 'connect':
      if (this._acceptIncomingConnections) {
        this._onConnectRequest(message)
      } else {
        this._log.debug('not accepting new connections -- dropping connect request on the floor')
      }
      break
    case 'ready':
      this._onReadyMessage(message)
      break
    default:
      var unknownOperationTypeError = "incorrect signaling message: don't know how to process operationType " + operationType + ' -- ignoring request'
      this._log.error(unknownOperationTypeError)
      this._error(unknownOperationTypeError)
  }
}

TurnTransport.prototype._onConnectRequest = function (message) {
  var connectRequest = message.operationContent
  if (connectRequest === undefined) {
    var undefinedOperationContentError = 'incorrect signaling message: undefined operationContent -- ignoring request'
    this._log.error(undefinedOperationContentError)
    this._error(undefinedOperationContentError)
    return
  }
  var sender = message.sender
  if (sender === undefined) {
    var undefinedSenderError = 'incorrect signaling message: undefined sender -- ignoring request'
    this._log.error(undefinedSenderError)
    this._error(undefinedSenderError)
    return
  }
  var self = this
  // first allocate TURN resource
  this._turn.allocateP()
    .then(function (allocateReply) {
      self._srflxAddress = allocateReply.mappedAddress
      self._relayAddress = allocateReply.relayedAddress
      if (allocateReply.lifetime !== undefined) {
        self._allocationLifetime = allocateReply.lifetime
      }
      self._log.debug('srflx address = ' + self._srflxAddress.address + ':' + self._srflxAddress.port)
      self._log.debug('relay address = ' + self._relayAddress.address + ':' + self._relayAddress.port)
      self._log.debug('lifetime = ' + self._allocationLifetime)
      // start refresh interval
      self._startRefreshLoop()
      // then create permission for peer to reach me
      return self._turn.createPermissionP(connectRequest.relayAddress.address)
    })
    .then(function () {
      // start permission refresh timer
      self._startCreatePermissionTimer(connectRequest.relayAddress.address)
      // create turn session
      var peerConnectionInfo = {
        mappedAddress: connectRequest.srflxAddress,
        relayedAddress: connectRequest.relayAddress
      }
      var session = self._createTurnSession(peerConnectionInfo, self._turn)
      // fire connection event
      self._fireConnectionEvent(session, self, peerConnectionInfo)
      // send ready response to peer
      var signalingDestination = sender
      var signalingMessage = {
        version: self.version,
        sender: self._myConnectionInfo.transportInfo,
        operationType: 'ready',
        operationContent: {
          srflxAddress: self._srflxAddress,
          relayAddress: self._relayAddress
        }
      }
      return self._signaling.sendP(signalingMessage, signalingDestination)
    })
    .then(function () {
      self._log.debug("'ready' message sent")
    })
    .catch(function (error) {
      self._log.error(error)
      self._error(error)
    })
}

TurnTransport.prototype._onReadyMessage = function (message) {
  var connectRequest = message.operationContent
  if (connectRequest === undefined) {
    var undefinedOperationContentError = 'incorrect signaling message: undefined operationContent -- ignoring request'
    this._log.error(undefinedOperationContentError)
    this._error(undefinedOperationContentError)
    return
  }
  var sender = message.sender
  if (sender === undefined) {
    var undefinedSenderError = 'incorrect signaling message: undefined sender -- ignoring request'
    this._log.error(undefinedSenderError)
    this._error(undefinedSenderError)
    return
  }
  var self = this
  // create permission for peer to reach me
  this._turn.createPermissionP(connectRequest.relayAddress.address)
    .then(function () {
      // start permission refresh timer
      self._startCreatePermissionTimer(connectRequest.relayAddress.address)
      // create turn session
      var peerConnectionInfo = {
        mappedAddress: connectRequest.srflxAddress,
        relayedAddress: connectRequest.relayAddress
      }
      var session = self._createTurnSession(peerConnectionInfo, self._turn)
      // fire connect event
      self._fireConnectEvent(session, self._peerConnectionInfo, self._connectOnSuccess)
    })
    .catch(function (error) {
      self._log.error(error)
      self._error(error)
    })
}

TurnTransport.prototype._startRefreshLoop = function () {
  var self = this
  // start refresh timer if allocation lifetime is specified
  if (this._allocationLifetime !== undefined) {
    this._log.debug('activating refresh loop -- lifetime was set to ' + this._allocationLifetime)
    this._startRefreshTimer(this._allocationLifetime)
    return
  }
  // otherwise execute refresh operation using the default TURN allocation timeout to retrieve actual lifetime
  this._turn.refreshP(TurnClient.DEFAULT_ALLOCATION_LIFETIME)
    .then(function (lifetime) {
      self._log.debug('activating refresh loop -- allocation lifetime ' + lifetime)
      self._allocationLifetime = lifetime
      self._startRefreshTimer(self._allocationLifetime)
    })
    .catch(function (error) {
      self._log.error(error)
      self._error(error)
    })
}

TurnTransport.prototype._startRefreshTimer = function (lifetime) {
  var self = this
  this._refreshTimer = setInterval(function () {
    self._turn.refreshP(lifetime)
      .then(function (duration) {
        self._log.debug('executed refresh operation, retrieving lifetime ' + duration)
      })
      .catch(function (error) {
        self._stopRefreshTimer()
        var errorMsg = 'error while sending TURN refresh message: ' + error
        self._log.error(errorMsg)
        self._error(errorMsg)
      })
  }, lifetime * 1000 - TurnTransport.TIMEOUT_MARGIN)
}

TurnTransport.prototype._stopRefreshTimer = function () {
  clearInterval(this._refreshTimer)
}

TurnTransport.prototype._startCreatePermissionTimer = function (address) {
  var self = this
  this._createPermissionTimer = setInterval(function () {
    self._turn.createPermissionP(address)
      .then(function () {
        self._log.debug('executed create permission refresh')
      })
      .catch(function (error) {
        self._stopCreatePermissionTimer()
        var errorMsg = 'error while refreshing TURN permission: ' + error
        self._log.error(errorMsg)
        self._error(errorMsg)
      })
  }, TurnClient.CREATE_PERMISSION_LIFETIME * 1000 - TurnTransport.TIMEOUT_MARGIN)
}

TurnTransport.prototype._stopCreatePermissionTimer = function () {
  clearInterval(this._createPermissionTimer)
}

TurnTransport.prototype._startChannelBindTimer = function (address, port, channel) {
  var self = this
  this._channelBindTimer = setInterval(function () {
    self._turn.bindChannelP(address, port, channel)
      .then(function (channel) {
        self._log.debug('executed bind channel refresh, retrieving channel ' + channel)
      })
      .catch(function (error) {
        self._stopChannelBindTimer()
        var errorMsg = 'failure while refreshing channel binding: ' + error
        self._log.error(errorMsg)
        self._error(errorMsg)
      })
  }, TurnClient.CHANNEL_BINDING_LIFETIME * 1000 - TurnTransport.TIMEOUT_MARGIN)
}

TurnTransport.prototype._stopChannelBindTimer = function () {
  clearInterval(this._channelBindTimer)
}

TurnTransport.prototype._createTurnSession = function (peerAddress, turnClient) {
  // create new TURN session
  var session = new TurnSession(peerAddress, turnClient)
  // store session
  this._sessions[session._sessionId] = session
  // register handlers for closing events
  var self = this
  session.once('close', function () {
    delete self._sessions[session._sessionId]
  })
  session.once('end', function () {
    // delete if finished + ended
    if (self.finished) {
      delete self._sessions[session._sessionId]
    }
  })
  session.once('finish', function () {
    // delete if finished + ended
    if (self.ended) {
      delete self._sessions[session._sessionId]
    }
  })
  // done
  this._log.debug('created new session for ' + JSON.stringify(peerAddress))
  return session
}

module.exports = TurnTransport
<|endoftext|>


<commit_before>var mainObject = {
    elm: null,
    elm1: null,
    myDetails: null,
    equalsBtn: null,
    resultDisplayer: null,
    lhs: null,
    rhs: null,
    result: true,
    x: null,
    y: null,
    obj: null,
    computedStyle: null,
    incX: 1,
    incY: 1,
    inter: 0,
    init: function(eventBinding) {
        eventBinding = eventBinding || false;
        if (eventBinding) {
            this.elm = $(".innerBox").get(0);
            this.elm1 = $(".headerWrapper").get(0);
            this.myDetails = $(".myDetails");
            this.resultDisplayer = $(".resultDisplayer");
            this.rhs = $(".rhs");
            this.lhs = $(".lhs");
            this.equalsBtn = $(".componentButton.equals");
			this.buildUp = $(".buildUp");
            this.bindEvents();
            window.console.log = (str, cls) => {
                this.setItInParagraph(str, cls);
            }
        }
        clearInterval(this.inter);
        this.inter = setInterval(this.doBounce.bind(this), 20);
    },
    bindEvents: function() {
        var _this = this;
        $(_this.elm).hover(function() {
            clearInterval(_this.inter);
            $(this).removeClass("animate").addClass("stopped");
            _this.myDetails.finish().slideDown("fast");
        }, function() {
            _this.init();
            $(this).removeClass("stopped").addClass("animate");
            _this.myDetails.finish().slideUp("fast");
        }).click(function() {
            window.open("https://www.facebook.com/profile.php?id=100007985747854", "_blank");
        });
		_this.resultDisplayer.on("click", ".reference", function(){
			window.open("http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3", "_blank");
		});
		_this.lhs.add(_this.rhs).keydown(function(e){
			if(e.keyCode == 13)	_this.equalsBtn.click();
		});
		_this.buildUp.click(function(){
			window.localStorage.setItem("buildUp", 1);
			$(this).fadeOut("fast", function(){
				$(this).remove();
			})
		});
        _this.equalsBtn.click(function() {
            var x = _this.lhs.val().trim(),
                y = _this.rhs.val().trim(),evalX,evalY;
			if(x.length == 0 || y.length ==0) {
				_this.lhs.add(_this.rhs).css("borderBottomColor", "rgba(54, 88, 153, 0.1)").data("reset","0")
				clearTimeout(_this.timeout);
				_this.blinkIt(x.length == 0 ? _this.lhs : _this.rhs);
				return;
			}
            try {
				_this.setResultsArea();
                _this.result = eval("(" + x + ") == (" + y + ")");
				evalX = eval("(" + x + ")");
				evalY = eval("(" + y + ")");
                _this.processAlgo(evalX, evalY, 1, (typeof evalX == "object" && evalX !== null) ? _this.getObjectRep(evalX) : x, (typeof evalY == "object" && evalY !== null) ? _this.getObjectRep(evalY) : y);
				console.log("RESULT : " + _this.result.toString().toUpperCase(), _this.result.toString())
            } catch (e) {
                console.log("⛔ " + e, "error");
            }
        });
        $(window).resize(function() {
            _this.obj = _this.elm1.getBoundingClientRect();
        }).resize().load(function() {
            setTimeout(function() {
                $("#disqus_thread").addClass("discussPartialDisplay");
				if(window.localStorage.getItem("buildUp") == null) _this.buildUp.slideDown("slow");
            }, 2000);
        });
    },
    doBounce: function() {
        this.computedStyle = window.getComputedStyle(this.elm);
        this.x = parseInt(this.computedStyle.left);
        this.y = parseInt(this.computedStyle.top);
        if (this.x < 0 || (this.x + 20) > this.obj.width) this.incX = -this.incX;
        if (this.y < 0 || (this.y + 20) > this.obj.height) this.incY = -this.incY;
        this.elm.style.left = this.x + this.incX + "px";
        this.elm.style.top = this.y + this.incY + "px";
    },
	blinkIt : function(elm, cnt = 1){
		this.timeout = setTimeout((reset) => {
			reset = +elm.data("reset");
			elm.css("borderBottomColor", reset == 0 ? "rgb(255, 0, 0)" : "rgba(54, 88, 153, 0.1)");
			elm.data("reset", +!reset);
			if(cnt != 6){ this.blinkIt(elm, ++cnt); }
		},200);
	},
    setResultsArea : function(){
	this.resultDisplayer.empty().removeClass("center");
    },
    setItInParagraph: function(str, cls) {
        return $("
").html(((cls == "explanation") ? "⇨ " : "") + str).appendTo(this.resultDisplayer);
    },
    stringChecker: function(val) {
        return typeof val == "string" ? "\"" + val + "\"" : typeof val == "object" ? this.getObjectRep(val) : val;
    },
    getValForNSOBool: function(val, valType) {
        val = valType == "boolean" ? +val : val;
        return val;
    },
    getValForNSObject: function(val, helper, helperVal) {
        val = (helper == helperVal) ? this.toPrimitive(val) : val;
        return val;
    },
    toPrimitive: function(obj, helper) {
        helper = typeof obj.valueOf();
        return (helper === "object") ? obj.valueOf().toString() : (helper == "string") ? obj.valueOf() : obj.valueOf();
    },
    getObjectRep: function(val) {
        return Object.prototype.toString.call(val).includes("Array") ? "[...]" : "{Object...}";
    },
    isUndefinedOrNull: function(type, val) {
        return (type === "undefined" || (type === "object" && val === null));
    },
    isNumberStringObjectCombination: function(xType, yType, x , y) {
        return (xType == "number" && (yType == "object" && y != null)) || ((xType == "object" && x != null) && yType == "number") || (xType == "string" && (yType == "object" && y != null)) || ((xType == "object" && x != null) && yType == "string");
    },
    isNumberStringCombination: function(xType, yType) {
        return ((xType === "number" && yType === "string") || (xType === "string" && yType === "number"));
    },
    isNumberStringObject_WithBooleanCombination: function(xType, yType) {
        return xType === "boolean" || yType === "boolean";
    },
    renderReferenceLookup: function(id, additionalId) {
        switch (id) {
            case 1000:
                console.log("Refer line numbers 1.A and B in AECA.", "reference");
                break;
            case 1001:
                console.log("Refer line numbers 1.C.i and ii in AECA.", "reference");
                break;
            case 1002:
                switch (additionalId) {
                    case "number":
                        console.log("Refer line numbers 1.C.iii ,iv ,v and vi in AECA.", "reference");
                        break;
                    case "string":
                        console.log("Refer line number 1.D in AECA.", "reference");
                        break;
                    case "boolean":
                        console.log("Refer line number 1.E in AECA.", "reference");
                        break;
                    case "object":
                        console.log("Refer line number 1.F in AECA.", "reference");
                        break;
                }
                break;
            case 1003:
                console.log("Refer line number 2 and 3 in AECA.", "reference");
                break;
            case 1004:
                console.log("Refer line number 4 and 5 in AECA.", "reference");
                break;
            case 1005:
                console.log("Refer line number 6 and 7 in AECA.", "reference");
                break;
            case 1006:
                console.log("Refer line number 8 and 9 in AECA.", "reference");
                break;
            case 1007:
                console.log("Refer line number 10 in AECA.", "reference");
                break;
        }
    },
    processAlgo: function(x, y, stepNumber, stringX, stringY, helper) {
        var xType = typeof x,
            yType = typeof y;
        xType = (xType == "function") ? "object" : xType;
        yType = (yType == "function") ? "object" : yType;
        console.log("CALL #" + stepNumber + "Arguments - LHS : " + stringX + " RHS : " + stringY + "", "steps");
        if (xType === yType) {
            if (this.isUndefinedOrNull(xType, x)) {
                console.log("Both LHS and RHS are '" + (x + "") + "'. Hence the given expression will always be evaluated to 'true'.", "explanation");
                this.renderReferenceLookup(1000);
                return;
            } else if (xType === "number") {
                if (x !== x || y !== y) {
                    console.log("Though LHS and RHS are of type number, " + ((x !== x) ? "LHS" : "RHS") + " is 'NaN'. Basically 'NaN' will be evaluated to false even it is compared with itself. So the given expression will yield 'false' always.", "explanation");
                    this.renderReferenceLookup(1001);
                    return;
                }
            }
            console.log("LHS and RHS are of same type '" + xType + "'. Additionally, both are having " + ((x === y) ? "same" : "different") + ((xType === "object") ? " References" : " values") + ". So the given expression will be evaluated to '" + (x === y).toString() + "'.", "explanation");
            this.renderReferenceLookup(1002, xType);
            return;
        } else if (this.isUndefinedOrNull(xType, x) && this.isUndefinedOrNull(yType, y)) {
            console.log("When 'undefined' and 'null' are compared the result will always be 'true'. In our case LHS resolves to '" + (x + "") + "' and RHS resolves to '" + (y + "") + "'. So the given expression will evalautes to 'true'", "explanation");
            this.renderReferenceLookup(1003);
            return;
        } else if (this.isNumberStringCombination(xType, yType)) {
            console.log("LHS is a '" + xType + "' and RHS is a '" + yType + "', Hence " + ((xType === "string") ? "LHS" : "RHS") + " will be converted to 'number' first.", "explanation");
            console.log(((xType === "string") ? "LHS" : "RHS") + " will be converted as number to form the expression (" + (x = +x, x) + " == " + (y = +y, y) + "). After that, algorithm will be called recursively by supplying the gained expression.", "explanation");
            this.renderReferenceLookup(1004);
            return this.processAlgo(x, y, ++stepNumber, x , y);
        } else if (this.isNumberStringObject_WithBooleanCombination(xType, yType)) {
            console.log("If either RHS or LHS is a boolean, then it has to be converted to number first.", "explanation");
            console.log("Here, " + ((xType == "boolean") ? "LHS" : "RHS") + " is boolean. So after translating it into a number the whole expression becomes like below,", "explanation");
            x = this.getValForNSOBool(x, xType);
            y = this.getValForNSOBool(y, yType);
            console.log(this.stringChecker(x) + " == " + this.stringChecker(y) + ". And here we need a recursive call to the algorithm, to evaluate the newly generated expression.", "explanation");
            this.renderReferenceLookup(1005);
            return this.processAlgo(x, y, ++stepNumber, this.stringChecker(x), this.stringChecker(y));
        } else if (this.isNumberStringObjectCombination(xType, yType, x , y)) {
            helper = (xType === "object") ? "RHS" : "LHS";
            console.log(helper + " is a " + ((xType === "object") ? yType : xType) + ". And its opponent is an object. So object has to be converted to its primitive form first before further evaluations.", "explanation");
            console.log("ToPrimitve(" + (helper == "RHS" ? "LHS" : "RHS") + ") will be called and the following expression will be framed,", "explanation");
            x = this.getValForNSObject(x, helper, "RHS");
            y = this.getValForNSObject(y, helper, "LHS");
            console.log(this.stringChecker(x) + " == " + this.stringChecker(y) + ". Next, the framed expression will be passed to a recursive call of the algorithm.", "explanation");
            this.renderReferenceLookup(1006);
            return this.processAlgo(x, y, ++stepNumber, this.stringChecker(x), this.stringChecker(y));
        } else {
            console.log("No condition match found in AECA! Hence the given expression will be evaluated as 'false'", "explanation")
            this.renderReferenceLookup(1007);
        }
    }
};

$(mainObject.init.bind(mainObject, true));
<commit_msg>function bug fix<commit_after>var mainObject = {
    elm: null,
    elm1: null,
    myDetails: null,
    equalsBtn: null,
    resultDisplayer: null,
    lhs: null,
    rhs: null,
    result: true,
    x: null,
    y: null,
    obj: null,
    computedStyle: null,
    incX: 1,
    incY: 1,
    inter: 0,
    init: function(eventBinding) {
        eventBinding = eventBinding || false;
        if (eventBinding) {
            this.elm = $(".innerBox").get(0);
            this.elm1 = $(".headerWrapper").get(0);
            this.myDetails = $(".myDetails");
            this.resultDisplayer = $(".resultDisplayer");
            this.rhs = $(".rhs");
            this.lhs = $(".lhs");
            this.equalsBtn = $(".componentButton.equals");
			this.buildUp = $(".buildUp");
            this.bindEvents();
            window.console.log = (str, cls) => {
                this.setItInParagraph(str, cls);
            }
        }
        clearInterval(this.inter);
        this.inter = setInterval(this.doBounce.bind(this), 20);
    },
    bindEvents: function() {
        var _this = this;
        $(_this.elm).hover(function() {
            clearInterval(_this.inter);
            $(this).removeClass("animate").addClass("stopped");
            _this.myDetails.finish().slideDown("fast");
        }, function() {
            _this.init();
            $(this).removeClass("stopped").addClass("animate");
            _this.myDetails.finish().slideUp("fast");
        }).click(function() {
            window.open("https://www.facebook.com/profile.php?id=100007985747854", "_blank");
        });
		_this.resultDisplayer.on("click", ".reference", function(){
			window.open("http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3", "_blank");
		});
		_this.lhs.add(_this.rhs).keydown(function(e){
			if(e.keyCode == 13)	_this.equalsBtn.click();
		});
		_this.buildUp.click(function(){
			window.localStorage.setItem("buildUp", 1);
			$(this).fadeOut("fast", function(){
				$(this).remove();
			})
		});
        _this.equalsBtn.click(function() {
            var x = _this.lhs.val().trim(),
                y = _this.rhs.val().trim(),evalX,evalY;
			if(x.length == 0 || y.length ==0) {
				_this.lhs.add(_this.rhs).css("borderBottomColor", "rgba(54, 88, 153, 0.1)").data("reset","0")
				clearTimeout(_this.timeout);
				_this.blinkIt(x.length == 0 ? _this.lhs : _this.rhs);
				return;
			}
            try {
				_this.setResultsArea();
                _this.result = eval("(" + x + ") == (" + y + ")");
		var evalX = eval("(" + x + ")"), evalY = eval("(" + y + ")"), xType = typeof evalX, yType = typeof evalY;
		xType = (xType == "function") ? "object" : xType; yType = (yType == "function") ? "object" : yType;
                _this.processAlgo(evalX, evalY, 1, (xType == "object" && evalX !== null) ? _this.getObjectRep(evalX) : x, (yType == "object" && evalY !== null) ? _this.getObjectRep(evalY) : y);
				console.log("RESULT : " + _this.result.toString().toUpperCase(), _this.result.toString())
            } catch (e) {
                console.log("⛔ " + e, "error");
            }
        });
        $(window).resize(function() {
            _this.obj = _this.elm1.getBoundingClientRect();
        }).resize().load(function() {
            setTimeout(function() {
                $("#disqus_thread").addClass("discussPartialDisplay");
				if(window.localStorage.getItem("buildUp") == null) _this.buildUp.slideDown("slow");
            }, 2000);
        });
    },
    doBounce: function() {
        this.computedStyle = window.getComputedStyle(this.elm);
        this.x = parseInt(this.computedStyle.left);
        this.y = parseInt(this.computedStyle.top);
        if (this.x < 0 || (this.x + 20) > this.obj.width) this.incX = -this.incX;
        if (this.y < 0 || (this.y + 20) > this.obj.height) this.incY = -this.incY;
        this.elm.style.left = this.x + this.incX + "px";
        this.elm.style.top = this.y + this.incY + "px";
    },
	blinkIt : function(elm, cnt = 1){
		this.timeout = setTimeout((reset) => {
			reset = +elm.data("reset");
			elm.css("borderBottomColor", reset == 0 ? "rgb(255, 0, 0)" : "rgba(54, 88, 153, 0.1)");
			elm.data("reset", +!reset);
			if(cnt != 6){ this.blinkIt(elm, ++cnt); }
		},200);
	},
    setResultsArea : function(){
	this.resultDisplayer.empty().removeClass("center");
    },
    setItInParagraph: function(str, cls) {
        return $("
").html(((cls == "explanation") ? "⇨ " : "") + str).appendTo(this.resultDisplayer);
    },
    stringChecker: function(val) {
        return typeof val == "string" ? "\"" + val + "\"" : typeof val == "object" ? this.getObjectRep(val) : val;
    },
    getValForNSOBool: function(val, valType) {
        val = valType == "boolean" ? +val : val;
        return val;
    },
    getValForNSObject: function(val, helper, helperVal) {
        val = (helper == helperVal) ? this.toPrimitive(val) : val;
        return val;
    },
    toPrimitive: function(obj, helper) {
        helper = typeof obj.valueOf();
        return (helper === "object") ? obj.valueOf().toString() : (helper == "string") ? obj.valueOf() : obj.valueOf();
    },
    getObjectRep: function(val) {
        return Object.prototype.toString.call(val).includes("Array") ? "[...]" : "{Object...}";
    },
    isUndefinedOrNull: function(type, val) {
        return (type === "undefined" || (type === "object" && val === null));
    },
    isNumberStringObjectCombination: function(xType, yType, x , y) {
        return (xType == "number" && (yType == "object" && y != null)) || ((xType == "object" && x != null) && yType == "number") || (xType == "string" && (yType == "object" && y != null)) || ((xType == "object" && x != null) && yType == "string");
    },
    isNumberStringCombination: function(xType, yType) {
        return ((xType === "number" && yType === "string") || (xType === "string" && yType === "number"));
    },
    isNumberStringObject_WithBooleanCombination: function(xType, yType) {
        return xType === "boolean" || yType === "boolean";
    },
    renderReferenceLookup: function(id, additionalId) {
        switch (id) {
            case 1000:
                console.log("Refer line numbers 1.A and B in AECA.", "reference");
                break;
            case 1001:
                console.log("Refer line numbers 1.C.i and ii in AECA.", "reference");
                break;
            case 1002:
                switch (additionalId) {
                    case "number":
                        console.log("Refer line numbers 1.C.iii ,iv ,v and vi in AECA.", "reference");
                        break;
                    case "string":
                        console.log("Refer line number 1.D in AECA.", "reference");
                        break;
                    case "boolean":
                        console.log("Refer line number 1.E in AECA.", "reference");
                        break;
                    case "object":
                        console.log("Refer line number 1.F in AECA.", "reference");
                        break;
                }
                break;
            case 1003:
                console.log("Refer line number 2 and 3 in AECA.", "reference");
                break;
            case 1004:
                console.log("Refer line number 4 and 5 in AECA.", "reference");
                break;
            case 1005:
                console.log("Refer line number 6 and 7 in AECA.", "reference");
                break;
            case 1006:
                console.log("Refer line number 8 and 9 in AECA.", "reference");
                break;
            case 1007:
                console.log("Refer line number 10 in AECA.", "reference");
                break;
        }
    },
    processAlgo: function(x, y, stepNumber, stringX, stringY, helper) {
        var xType = typeof x,
            yType = typeof y;
        xType = (xType == "function") ? "object" : xType;
        yType = (yType == "function") ? "object" : yType;
        console.log("CALL #" + stepNumber + "Arguments - LHS : " + stringX + " RHS : " + stringY + "", "steps");
        if (xType === yType) {
            if (this.isUndefinedOrNull(xType, x)) {
                console.log("Both LHS and RHS are '" + (x + "") + "'. Hence the given expression will always be evaluated to 'true'.", "explanation");
                this.renderReferenceLookup(1000);
                return;
            } else if (xType === "number") {
                if (x !== x || y !== y) {
                    console.log("Though LHS and RHS are of type number, " + ((x !== x) ? "LHS" : "RHS") + " is 'NaN'. Basically 'NaN' will be evaluated to false even it is compared with itself. So the given expression will yield 'false' always.", "explanation");
                    this.renderReferenceLookup(1001);
                    return;
                }
            }
            console.log("LHS and RHS are of same type '" + xType + "'. Additionally, both are having " + ((x === y) ? "same" : "different") + ((xType === "object") ? " References" : " values") + ". So the given expression will be evaluated to '" + (x === y).toString() + "'.", "explanation");
            this.renderReferenceLookup(1002, xType);
            return;
        } else if (this.isUndefinedOrNull(xType, x) && this.isUndefinedOrNull(yType, y)) {
            console.log("When 'undefined' and 'null' are compared the result will always be 'true'. In our case LHS resolves to '" + (x + "") + "' and RHS resolves to '" + (y + "") + "'. So the given expression will evalautes to 'true'", "explanation");
            this.renderReferenceLookup(1003);
            return;
        } else if (this.isNumberStringCombination(xType, yType)) {
            console.log("LHS is a '" + xType + "' and RHS is a '" + yType + "', Hence " + ((xType === "string") ? "LHS" : "RHS") + " will be converted to 'number' first.", "explanation");
            console.log(((xType === "string") ? "LHS" : "RHS") + " will be converted as number to form the expression (" + (x = +x, x) + " == " + (y = +y, y) + "). After that, algorithm will be called recursively by supplying the gained expression.", "explanation");
            this.renderReferenceLookup(1004);
            return this.processAlgo(x, y, ++stepNumber, x , y);
        } else if (this.isNumberStringObject_WithBooleanCombination(xType, yType)) {
            console.log("If either RHS or LHS is a boolean, then it has to be converted to number first.", "explanation");
            console.log("Here, " + ((xType == "boolean") ? "LHS" : "RHS") + " is boolean. So after translating it into a number the whole expression becomes like below,", "explanation");
            x = this.getValForNSOBool(x, xType);
            y = this.getValForNSOBool(y, yType);
            console.log(this.stringChecker(x) + " == " + this.stringChecker(y) + ". And here we need a recursive call to the algorithm, to evaluate the newly generated expression.", "explanation");
            this.renderReferenceLookup(1005);
            return this.processAlgo(x, y, ++stepNumber, this.stringChecker(x), this.stringChecker(y));
        } else if (this.isNumberStringObjectCombination(xType, yType, x , y)) {
            helper = (xType === "object") ? "RHS" : "LHS";
            console.log(helper + " is a " + ((xType === "object") ? yType : xType) + ". And its opponent is an object. So object has to be converted to its primitive form first before further evaluations.", "explanation");
            console.log("ToPrimitve(" + (helper == "RHS" ? "LHS" : "RHS") + ") will be called and the following expression will be framed,", "explanation");
            x = this.getValForNSObject(x, helper, "RHS");
            y = this.getValForNSObject(y, helper, "LHS");
            console.log(this.stringChecker(x) + " == " + this.stringChecker(y) + ". Next, the framed expression will be passed to a recursive call of the algorithm.", "explanation");
            this.renderReferenceLookup(1006);
            return this.processAlgo(x, y, ++stepNumber, this.stringChecker(x), this.stringChecker(y));
        } else {
            console.log("No condition match found in AECA! Hence the given expression will be evaluated as 'false'", "explanation")
            this.renderReferenceLookup(1007);
        }
    }
};

$(mainObject.init.bind(mainObject, true));
<|endoftext|>


<commit_before>exports.trimRight = function(path, useLog) {
    var pattern = /([^a-zA-Z_\-:0-9]{1,})$/;
    path = path.replace(pattern, '');
    log(path, useLog);
    return path;
};

exports.trimLeft = function(path, useLog) {
    var pattern = /^([^a-zA-Z_\-]{1,})/;
    path = path.replace(pattern, '');
    log(path, useLog);
    return path;
};

exports.trimBoth = function(path, useLog) {
    path = exports.trimRight(exports.trimLeft(path, false), false);
    log(path, useLog);
    return path;
};

exports.inside = function(path, useLog) {
    // fixPath
    path = exports.trimRight(path, false) + '/*';
    log(path, useLog);
    return path;
};

exports.toParent = function(path, useLog) {
    // cleanStartPath
    path = '../' + exports.trimLeft(path, false);
    log(path, useLog);
    return path;
};

exports.fromModule = function(targetPath) {
    return __dirname + '/../' + exports.trimLeft(targetPath);
};

exports.fromProcess = function(targetPath) {
    return process.cwd() + '/' + exports.trimBoth(targetPath);
};

function log(path, useLog) {
    if (useLog !== undefined && useLog !== false) {
        console.log(path);
    }
};
<commit_msg>Moves function<commit_after>function log(path, useLog) {
    if (useLog !== undefined && useLog !== false) {
        console.log(path);
    }
}

exports.trimRight = function(path, useLog) {
    var pattern = /([^a-zA-Z_\-:0-9]{1,})$/;
    path = path.replace(pattern, '');
    log(path, useLog);
    return path;
};

exports.trimLeft = function(path, useLog) {
    var pattern = /^([^a-zA-Z_\-]{1,})/;
    path = path.replace(pattern, '');
    log(path, useLog);
    return path;
};

exports.trimBoth = function(path, useLog) {
    path = exports.trimRight(exports.trimLeft(path, false), false);
    log(path, useLog);
    return path;
};

exports.inside = function(path, useLog) {
    // fixPath
    path = exports.trimRight(path, false) + '/*';
    log(path, useLog);
    return path;
};

exports.toParent = function(path, useLog) {
    // cleanStartPath
    path = '../' + exports.trimLeft(path, false);
    log(path, useLog);
    return path;
};

exports.fromModule = function(targetPath) {
    return __dirname + '/../' + exports.trimLeft(targetPath);
};

exports.fromProcess = function(targetPath) {
    return process.cwd() + '/' + exports.trimBoth(targetPath);
};
<|endoftext|>


<commit_before>'use strict';

var EventsMixin         = require('../events'),
    Model               = require('../models/base'),
    utils               = require('../utils')

class DragonBaseCollection {

  constructor(entries = [], options = {}) {
    this.uid = utils.uniqueId(this)

    Object.assign(this, EventsMixin)

    this.models = []

    if(!(entries[Symbol.iterator])) {
      throw new Error('Collection entries must be an iterable')
    }

    if(!this.model || !(this.model instanceof Function)) {
      throw new Error('Collection requires a valid Model Class')
    }

    if(typeof this.url != 'string') {
      throw new Error('Collection requires a valid url')
    }

    this.ensureEntries(entries)

  }

  add(entries) {

    this.ensureEntries(entries)

  }

  clear() {

    this.models = []

  }

  /*
  TODO: Clean this up, make checks stronger
  Currently, a mixed array of objects and models could be passed; it's an odd scenario that would cause that to hapen thoug.
  Tecnnically a model instance of a different model could be passed; need to check and prevent that.
  Should also consider concatting arrays as pushing arrays of 1000 or more can be very time consuming/lots of looping.
  Overall this function sucks but helps move the project forward atm.
  */

  ensureEntries(entries) {
    // we will suppport all kind of iterable  here !!
    // It is simpler to manage things by making a single item an array
    if(!(entries[Symbol.iterator])) {
      entries = [entries]
    }

    for(let entry of entries) {
      if(entry instanceof this.model) {
        this.models.push(entry)
      }

      else {
        this.models.push(new this.model(entry))
      }

    }

  }

  toJSON() {

  }

  [Symbol.iterator](){
    var collectionsModels = this.models,index = 0
    return {
      next: function next () {
        if (index + 1 > collectionsModels.length) {
          return { done: true };
        }
        return { value: collectionsModels[index++], done: false };
      }
    }
  }

  dispose() {

    if(!this.disposed) {

      utils.dispose(this)

    }

  }

}

DragonBaseCollection.prototype.dispose = false

DragonBaseCollection.prototype.model = Model

DragonBaseCollection.prototype.url = ''

module.exports = DragonBaseCollection
<commit_msg>partial state of new collections methods<commit_after>'use strict';

var EventsMixin         = require('../events'),
    Model               = require('../models/base'),
    utils               = require('../utils')

class DragonBaseCollection {

  constructor(entries = [], options = {}) {
    this.uid = utils.uniqueId(this)

    Object.assign(this, EventsMixin)

    this.models = []

    if(!(entries[Symbol.iterator])) {
      throw new Error('Collection entries must be an iterable')
    }

    if(!this.model || !(this.model instanceof Function)) {
      throw new Error('Collection requires a valid Model Class')
    }

    if(typeof this.url != 'string') {
      throw new Error('Collection requires a valid url')
    }

    this.ensureEntries(entries)

  }

  var collectionArray =
  [0,[{name:"reduce"},{name:"inject",alias:"reduce"},{name:"foldl",alias:"reduce"},
      {name:"invoke"},{name:"reduceRight"},{name:"foldr",alias:"reduceRight"},
      {name:"without"},{name:"difference"}],
  [1,[{name:"toArray"},{name:"size"},{name:"shuffle"},{name:"isEmpty"},{name:"chain"}]],
  [3,[{name:"forEach"},{name:"each"},{name:"map"},{name:"collect"},{name:"find"},
      {name:"detect"},{name:"filter"},{name:"select"},{name:"reject"},{name:"every"},{name:"all"},
      {name:"some"},{name:"any"},{name:"include"},{name:"includes"},{name:"contains"},{name:"max"},
      {name:"min"},{name:"first"},{name:"head"},{name:"take"},{name:"initial"},{name:"rest"},
      {name:"tail"},{name:"drop"},{name:"last"},{name:"indexOf"},{name:"lastIndexOf"},{name:"sample"},{name:"partition"},
      {name:"groupBy"},{name:"countBy"},{name:"sortBy"},{name:"indexBy"},{name:"findIndex"},{name:"findLastIndex"}]]
  ] , collectionMethods = new map(collectionArray);

 console.log(collectionsModels);

  add(entries) {
    this.ensureEntries(entries)
  }

  clear() {

    this.models = []

  }

  /*
  TODO: Clean this up, make checks stronger
  Currently, a mixed array of objects and models could be passed; it's an odd scenario that would cause that to hapen thoug.
  Tecnnically a model instance of a different model could be passed; need to check and prevent that.
  Should also consider concatting arrays as pushing arrays of 1000 or more can be very time consuming/lots of looping.
  Overall this function sucks but helps move the project forward atm.
  */

  ensureEntries(entries) {
    // we will suppport all kind of iterable  here !!
    // It is simpler to manage things by making a single item an array
    if(!(entries[Symbol.iterator])) {
      entries = [entries]
    }

    for(let entry of entries) {
      if(entry instanceof this.model) {
        this.models.push(entry)
      }

      else {
        this.models.push(new this.model(entry))
      }

    }

  }

  toJSON() {

  }

  [Symbol.iterator](){
    var collectionsModels = this.models,index = 0
    return {
      next: function next () {
        if (index + 1 > collectionsModels.length) {
          return { done: true };
        }
        return { value: collectionsModels[index++], done: false };
      }
    }
  }

  dispose() {

    if(!this.disposed) {

      utils.dispose(this)

    }

  }

}

DragonBaseCollection.prototype.dispose = false

DragonBaseCollection.prototype.model = Model

DragonBaseCollection.prototype.url = ''

module.exports = DragonBaseCollection
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
  classNames: 'spectrum-color-picker',

  tagName: 'input',

  color: null,

  flatMode: false,

  allowEmpty: false,

  disabled: false,

  showInput: false,

  showAlpha: false,

  showInitial: false,

  showButtons: true,

  showPalette: false,

  showPaletteOnly: false,

  palette: [],

  togglePaletteOnly: false,

  showSelectionPalette: false,

  hideAfterPaletteSelect: false,

  preferredFormat: null,

  moveFiresChange: false,

  clickoutFiresChange: false,

  chooseText: 'Choose',

  cancelText: 'Cancel',

  togglePaletteMoreText: 'More',

  togglePaletteLessText: 'Less',

  appendTo: 'body',

  localStorageKey: 'spectrum-color-picker',

  updatePicker: Ember.observer('color', function () {
    this.$().spectrum('set', this.get('color'));
  }),

  updateDisabled: Ember.observer('disabled', function () {
    this.$().spectrum(this.get('disabled') ? 'disable' : 'enable');
  }),

  didInsertElement() {
    let palette = this.get('palette');
    let opts = {
      color: this.get('color'),
      flat: this.get('flatMode'),
      allowEmpty: this.get('allowEmpty'),
      disabled: this.get('disabled'),
      showInput: this.get('showInput'),
      showAlpha: this.get('showAlpha'),
      showInitial: this.get('showInitial'),
      showButtons: this.get('showButtons'),
      showPalette: this.get('showPalette'),
      showPaletteOnly: this.get('showPaletteOnly'),
      palette: (typeof(palette) === 'string') ? JSON.parse(palette) : palette,
      togglePaletteOnly: this.get('togglePaletteOnly'),
      showSelectionPalette: this.get('showSelectionPalette'),
      hideAfterPaletteSelect: this.get('hideAfterPaletteSelect'),
      preferredFormat: this.get('preferredFormat'),
      clickoutFiresChange: this.get('clickoutFiresChange'),
      chooseText: this.get('chooseText'),
      cancelText: this.get('cancelText'),
      togglePaletteMoreText: this.get('togglePaletteMoreText'),
      togglePaletteLessText: this.get('togglePaletteLessText'),
      appendTo: this.get('appendTo'),
      localStorageKey: this.get('localStorageKey')
    };
    let self = this;
    let updateFunction = function (newColor) {
      let color = newColor ? newColor.toString() : null;
      let onChange = self.get('onChange');

      self.set('color', color);

      if (onChange) {
        onChange(color);
      }
    };

    opts.change = updateFunction;

    if (this.get('moveFiresChange')) {
      opts.move = updateFunction;
    }

    // Move Event
    let onMove = self.get('onMove');
    if (onMove) {
        opts.move = function (newColor) {
          onMove(newColor ? newColor.toString() : null);
        };
    }

    // Hide Event
    let onHide = self.get('onHide');
    if (onHide) {
        opts.hide = function (newColor) {
          onHide(newColor ? newColor.toString() : null);
        };
    }

    // Show Event
    let onShow = self.get('onShow');
    if (onShow) {
        opts.show = function (newColor) {
          onShow(newColor ? newColor.toString() : null);
        };
    }

    this.$().spectrum(opts);
  }
});
<commit_msg>Destroy spectrum on component destroy, fixes #10<commit_after>import Ember from 'ember';

export default Ember.Component.extend({
  classNames: 'spectrum-color-picker',

  tagName: 'input',

  color: null,

  flatMode: false,

  allowEmpty: false,

  disabled: false,

  showInput: false,

  showAlpha: false,

  showInitial: false,

  showButtons: true,

  showPalette: false,

  showPaletteOnly: false,

  palette: [],

  togglePaletteOnly: false,

  showSelectionPalette: false,

  hideAfterPaletteSelect: false,

  preferredFormat: null,

  moveFiresChange: false,

  clickoutFiresChange: false,

  chooseText: 'Choose',

  cancelText: 'Cancel',

  togglePaletteMoreText: 'More',

  togglePaletteLessText: 'Less',

  appendTo: 'body',

  localStorageKey: 'spectrum-color-picker',

  updatePicker: Ember.observer('color', function () {
    this.$().spectrum('set', this.get('color'));
  }),

  updateDisabled: Ember.observer('disabled', function () {
    this.$().spectrum(this.get('disabled') ? 'disable' : 'enable');
  }),

  didInsertElement() {
    let palette = this.get('palette');
    let opts = {
      color: this.get('color'),
      flat: this.get('flatMode'),
      allowEmpty: this.get('allowEmpty'),
      disabled: this.get('disabled'),
      showInput: this.get('showInput'),
      showAlpha: this.get('showAlpha'),
      showInitial: this.get('showInitial'),
      showButtons: this.get('showButtons'),
      showPalette: this.get('showPalette'),
      showPaletteOnly: this.get('showPaletteOnly'),
      palette: (typeof(palette) === 'string') ? JSON.parse(palette) : palette,
      togglePaletteOnly: this.get('togglePaletteOnly'),
      showSelectionPalette: this.get('showSelectionPalette'),
      hideAfterPaletteSelect: this.get('hideAfterPaletteSelect'),
      preferredFormat: this.get('preferredFormat'),
      clickoutFiresChange: this.get('clickoutFiresChange'),
      chooseText: this.get('chooseText'),
      cancelText: this.get('cancelText'),
      togglePaletteMoreText: this.get('togglePaletteMoreText'),
      togglePaletteLessText: this.get('togglePaletteLessText'),
      appendTo: this.get('appendTo'),
      localStorageKey: this.get('localStorageKey')
    };
    let self = this;
    let updateFunction = function (newColor) {
      let color = newColor ? newColor.toString() : null;
      let onChange = self.get('onChange');

      self.set('color', color);

      if (onChange) {
        onChange(color);
      }
    };

    opts.change = updateFunction;

    if (this.get('moveFiresChange')) {
      opts.move = updateFunction;
    }

    // Move Event
    let onMove = self.get('onMove');
    if (onMove) {
        opts.move = function (newColor) {
          onMove(newColor ? newColor.toString() : null);
        };
    }

    // Hide Event
    let onHide = self.get('onHide');
    if (onHide) {
        opts.hide = function (newColor) {
          onHide(newColor ? newColor.toString() : null);
        };
    }

    // Show Event
    let onShow = self.get('onShow');
    if (onShow) {
        opts.show = function (newColor) {
          onShow(newColor ? newColor.toString() : null);
        };
    }

    this.$().spectrum(opts);
  },

  willDestroyElement: function() {
    this.$().spectrum('destroy');
  }
});
<|endoftext|>


<commit_before>
var amqp = require('amqp');
var fs   = require('fs');
var logger = require('./logger');

var rabbitqueue;
var exchangeName;
var queueName;
var connExchange_;
var connQueue_;
var routing_;
var deliveryMode;
exports.exchangeMapping = {}

//This method registers the hook and try to initialize the connection to rabbitmq server for later use.
exports.register = function () {

    logger.logdebug("About to connect and initialize queue object");
	this.init_rabbitmq_server();
	logger.logdebug("Finished initiating : " + exports.exchangeMapping[exchangeName + queueName]);
}

//Actual magic of publishing message to rabbit when email comes happen here.
exports.hook_queue = function(next, connection) {

    //Calling the get_data method and when it gets the data on callback, publish the message to queue with routing key.
    var stream = connection.transaction.message_stream.get_data(function(buffere) {
    	var exchangeData = exports.exchangeMapping[exchangeName + queueName]
    	logger.logdebug("Sending the data: "+ queueName+" Routing : "+ exchangeData + " exchange :"+connExchange_);
    	if (connExchange_ && routing_) {
    		//This is publish function of rabbitmq amqp library, currently direct queue is configured and routing is fixed.
    		//Needs to be changed.

    		connExchange_.publish(routing_, buffere,{deliveryMode: 2}, function(error){
				if (error) {
					//There was some error while sending the email to queue.
					logger.logdebug("queueFailure: #{JSON.stringify(error)}");
					exports.init_rabbitmq_server();
					return next();
				}
				else {
					//Queueing was successful, send ok as reply
					logger.logdebug( "queueSuccess");
					return next(OK,"Successfully Queued! in rabbitmq");
				}

			});

		}
		else {
			//Seems like connExchange is not defined , lets create one for next call
			exports.init_rabbitmq_server();
			return next();
		}

    });

}

//This initializes the connection to rabbitmq server, It reads values from rabbitmq.ini file in config directory.
exports.init_rabbitmq_server = function() {
	 var plugin = this;
    // this is called during init of rabbitmq

    //Read the config file rabbitmq
    var config     = plugin.config.get('rabbitmq.ini');
    //Just putting the defaults
    var rabbitmq_ip  = '127.0.0.1';
    var rabbitmq_port = '6379';
    var confirm = true;
    var durable = true;
    var autoDelete = false;
    var exchangeType = 'direct';

    //Getting the values from config file rabbitmq.ini
    if (config.rabbitmq) {
        rabbitmq_ip = config.rabbitmq.server_ip || '127.0.0.1';
        rabbitmq_port = config.rabbitmq.server_port || '6379';
        exchangeName = config.rabbitmq.exchangeName || 'emailMessages';
        exchangeType = config.rabbitmq.exchangeType || 'direct';
        confirm = config.rabbitmq.confirm === 'true'|| true;
        durable = config.rabbitmq.durable === 'true'|| true;
        autoDelete = config.rabbitmq.autoDelete == 'true' || false;
        deliveryMode = config.rabbitmq.deliveryMode || 2;
        queueName = config.rabbitmq.queueName || 'emails';
    }
    else {
    	//If config file is not available , lets get the default values
    	queueName = 'emails';
    	exchangeName = 'emailMessages';
    	deliveryMode = 2;
    	durable = true;
    }

    //Create connection to the rabbitmq server
    logger.logdebug("About to Create connection with server");
    rabbitqueue = amqp.createConnection({ host: rabbitmq_ip });

    //Declaring listerner on error on connection.
    rabbitqueue.on('error',function(error) {
    	logger.logdebug("There was some error on the connection : "+error);
    });

	//Declaring listerner on close on connection.
    rabbitqueue.on('close',function(close) {
    	logger.logdebug(" Connection  is beingclosed : "+close);
    });

	/* Declaring the function to perform when connection is established and ready, function involves like:
	 *	1. Creating or connecting to Exchange.
	 *  2. Creating or connecting to Queue.
	 *  3. Binding the Exchange and Queue.
	 *  4. Saving some variables in global to be used while publishing message.
	 */

    rabbitqueue.on('ready', function () {
    	logger.logdebug("Connection is ready, will try making exchange");
    	// Now connection is ready will try to open exchange with config data.
    	rabbitqueue.exchange(exchangeName, {  type: exchangeType,  confirm: confirm,  durable: durable }, function(connExchange) {

    		logger.logdebug("connExchange with server "+connExchange + " autoDelete : "+autoDelete);

    		//Exchange is now open, will try to open queue.
  			return rabbitqueue.queue(queueName,{autoDelete: autoDelete,  durable:  durable  } , function(connQueue) {
  			logger.logdebug("connQueue with server "+connQueue);

  			//Creating the Routing key to bind the queue and exchange.
    		var key, routing;
    		routing = "" + queueName + "Routing";

    		//Will try to bing queue and exchange which was created above.
    		connQueue.bind(connExchange, routing);
    		key = exchangeName + queueName;

    		//Save the variables for publising later.
    		if (!exports.exchangeMapping[key]) {
      			exports.exchangeMapping[key] = [];
    		}
    		connExchange_ = connExchange;
    		connQueue_ = connQueue;
    		routing_ = routing;
    		exports.exchangeMapping[key].push({
      			exchange : connExchange_,
      			queue : connQueue_,
      			routing : routing_,
      			queueName : queueName
    		});
    		logger.logdebug("exchange: " + exchangeName + ", queue: " + queueName+"  exchange : "+connExchange_ +" queue : "+connQueue_ );
  			});
		});

	});

}
<commit_msg>Added the port while creating connection<commit_after>
var amqp = require('amqp');
var fs   = require('fs');
var logger = require('./logger');

var rabbitqueue;
var exchangeName;
var queueName;
var connExchange_;
var connQueue_;
var routing_;
var deliveryMode;
exports.exchangeMapping = {}

//This method registers the hook and try to initialize the connection to rabbitmq server for later use.
exports.register = function () {

    logger.logdebug("About to connect and initialize queue object");
	this.init_rabbitmq_server();
	logger.logdebug("Finished initiating : " + exports.exchangeMapping[exchangeName + queueName]);
}

//Actual magic of publishing message to rabbit when email comes happen here.
exports.hook_queue = function(next, connection) {

    //Calling the get_data method and when it gets the data on callback, publish the message to queue with routing key.
    var stream = connection.transaction.message_stream.get_data(function(buffere) {
    	var exchangeData = exports.exchangeMapping[exchangeName + queueName]
    	logger.logdebug("Sending the data: "+ queueName+" Routing : "+ exchangeData + " exchange :"+connExchange_);
    	if (connExchange_ && routing_) {
    		//This is publish function of rabbitmq amqp library, currently direct queue is configured and routing is fixed.
    		//Needs to be changed.

    		connExchange_.publish(routing_, buffere,{deliveryMode: 2}, function(error){
				if (error) {
					//There was some error while sending the email to queue.
					logger.logdebug("queueFailure: #{JSON.stringify(error)}");
					exports.init_rabbitmq_server();
					return next();
				}
				else {
					//Queueing was successful, send ok as reply
					logger.logdebug( "queueSuccess");
					return next(OK,"Successfully Queued! in rabbitmq");
				}

			});

		}
		else {
			//Seems like connExchange is not defined , lets create one for next call
			exports.init_rabbitmq_server();
			return next();
		}

    });

}

//This initializes the connection to rabbitmq server, It reads values from rabbitmq.ini file in config directory.
exports.init_rabbitmq_server = function() {
	 var plugin = this;
    // this is called during init of rabbitmq

    //Read the config file rabbitmq
    var config     = plugin.config.get('rabbitmq.ini');
    //Just putting the defaults
    var rabbitmq_ip  = '127.0.0.1';
    var rabbitmq_port = '6379';
    var confirm = true;
    var durable = true;
    var autoDelete = false;
    var exchangeType = 'direct';

    //Getting the values from config file rabbitmq.ini
    if (config.rabbitmq) {
        rabbitmq_ip = config.rabbitmq.server_ip || '127.0.0.1';
        rabbitmq_port = config.rabbitmq.server_port || '6379';
        exchangeName = config.rabbitmq.exchangeName || 'emailMessages';
        exchangeType = config.rabbitmq.exchangeType || 'direct';
        confirm = config.rabbitmq.confirm === 'true'|| true;
        durable = config.rabbitmq.durable === 'true'|| true;
        autoDelete = config.rabbitmq.autoDelete == 'true' || false;
        deliveryMode = config.rabbitmq.deliveryMode || 2;
        queueName = config.rabbitmq.queueName || 'emails';
    }
    else {
    	//If config file is not available , lets get the default values
    	queueName = 'emails';
    	exchangeName = 'emailMessages';
    	deliveryMode = 2;
    	durable = true;
    }

    //Create connection to the rabbitmq server
    logger.logdebug("About to Create connection with server");
    rabbitqueue = amqp.createConnection({ host: rabbitmq_ip , port : rabbitmq_port });

    //Declaring listerner on error on connection.
    rabbitqueue.on('error',function(error) {
    	logger.logdebug("There was some error on the connection : "+error);
    });

	//Declaring listerner on close on connection.
    rabbitqueue.on('close',function(close) {
    	logger.logdebug(" Connection  is beingclosed : "+close);
    });

	/* Declaring the function to perform when connection is established and ready, function involves like:
	 *	1. Creating or connecting to Exchange.
	 *  2. Creating or connecting to Queue.
	 *  3. Binding the Exchange and Queue.
	 *  4. Saving some variables in global to be used while publishing message.
	 */

    rabbitqueue.on('ready', function () {
    	logger.logdebug("Connection is ready, will try making exchange");
    	// Now connection is ready will try to open exchange with config data.
    	rabbitqueue.exchange(exchangeName, {  type: exchangeType,  confirm: confirm,  durable: durable }, function(connExchange) {

    		logger.logdebug("connExchange with server "+connExchange + " autoDelete : "+autoDelete);

    		//Exchange is now open, will try to open queue.
  			return rabbitqueue.queue(queueName,{autoDelete: autoDelete,  durable:  durable  } , function(connQueue) {
  			logger.logdebug("connQueue with server "+connQueue);

  			//Creating the Routing key to bind the queue and exchange.
    		var key, routing;
    		routing = "" + queueName + "Routing";

    		//Will try to bing queue and exchange which was created above.
    		connQueue.bind(connExchange, routing);
    		key = exchangeName + queueName;

    		//Save the variables for publising later.
    		if (!exports.exchangeMapping[key]) {
      			exports.exchangeMapping[key] = [];
    		}
    		connExchange_ = connExchange;
    		connQueue_ = connQueue;
    		routing_ = routing;
    		exports.exchangeMapping[key].push({
      			exchange : connExchange_,
      			queue : connQueue_,
      			routing : routing_,
      			queueName : queueName
    		});
    		logger.logdebug("exchange: " + exchangeName + ", queue: " + queueName+"  exchange : "+connExchange_ +" queue : "+connQueue_ );
  			});
		});

	});

}
<|endoftext|>


<commit_before>/**
 * Lightbox - frontend website
 *
 * .lightbox-container will have the class .lightbox-loading when Content is being retreived
 */

(function($, document, window) {

	// Common selectors
	var $html = $('html'),
		$scroll = $(window).add('html').add('body');

	// Modal mark-up, may move this to somewhere else laster
	var modal = $([
		'
',
			'
',
				'<button class="lightbox-close-btn" title="Close" type="button">Close</button>',
				'

',
			'
',
			'

',
		'
'].join('')
	).appendTo('body');

	/**
	 * Device detection
	 * ================
	 *
	 * Mainly to target devices on Android OS, as it does not support `position: fixed;` very well.
	 *
 	 */

	var ua = window.navigator.userAgent.toLowerCase(),
		isAndroid = ua.indexOf('android') > -1,
		screenPos;

	// Android workarounds
	if (isAndroid) {
		$html.addClass('android'); // Add class to allow Android specific styling
	}

	// Bind click events
	$(document)
		.on('click', 'a.lightbox', function (e) {
			// data url property first, otherwise href as a fallback
			var href = $(this).data('url') || $(this).attr('href'),
				content = modal.find('.lightbox-content').html('');
			modal.show().addClass('lightbox-loading');

			$html.addClass('lightbox');
			modal.show().addClass('lightbox-loading');

			if (isAndroid) {
				screenPos = $(window).scrollTop(); // Get current screen position
				$scroll.scrollTop(modal.scrollTop()); // Scroll view to the top of the page
			}

			// get the content linked and inject it to the content of the lightbox.
			$.ajax({
				url: href,
				complete: function () {
					modal.removeClass('lightbox-loading');
				},
				success: function (html) {
					var $html = $(html);
					content.empty().append($html);
					$(document).trigger('lightbox:displayed', [$html]);
				},
				error: function (jqXHR, textStatus) {
					content.html(textStatus);
				}
			});

			// stop the link from following the link
			e.preventDefault();
		})
		.on('click', '.lightbox-close-btn, .lightbox-overlay', function (e) {

			// hide the modal
			modal.hide();
			$html.removeClass('lightbox');
			$(document).trigger('lightbox:closed', [$html]);

			if (isAndroid) {
				// Scroll back to screen position before lightbox is opened
				$scroll.scrollTop(screenPos);
			}

			e.preventDefault();
		});

}(jQuery, document, window));<commit_msg>Added touch events and removed $html from closed trigger<commit_after>/**
 * Lightbox - frontend website
 *
 * .lightbox-container will have the class .lightbox-loading when Content is being retreived
 */

(function($, document, window) {

	// Common selectors
	var $html = $('html'),
		$scroll = $(window).add('html').add('body');

	// Modal mark-up, may move this to somewhere else laster
	var modal = $([
		'
',
			'
',
				'<button class="lightbox-close-btn" title="Close" type="button">Close</button>',
				'

',
			'
',
			'

',
		'
'].join('')
	).appendTo('body');

	/**
	 * Device detection
	 * ================
	 *
	 * Mainly to target devices on Android OS, as it does not support `position: fixed;` very well.
	 *
 	 */

	var ua = window.navigator.userAgent.toLowerCase(),
		isAndroid = ua.indexOf('android') > -1,
		screenPos;

	// Android workarounds
	if (isAndroid) {
		$html.addClass('android'); // Add class to allow Android specific styling
	}

	// Bind click events
	$(document)
		.on('click touchend MSPointerUp', 'a.lightbox', function (e) {
			// data url property first, otherwise href as a fallback
			var href = $(this).data('url') || $(this).attr('href'),
				content = modal.find('.lightbox-content').html('');
			modal.show().addClass('lightbox-loading');

			$html.addClass('lightbox');
			modal.show().addClass('lightbox-loading');

			if (isAndroid) {
				screenPos = $(window).scrollTop(); // Get current screen position
				$scroll.scrollTop(modal.scrollTop()); // Scroll view to the top of the page
			}

			// get the content linked and inject it to the content of the lightbox.
			$.ajax({
				url: href,
				complete: function () {
					modal.removeClass('lightbox-loading');
				},
				success: function (html) {
					var $html = $(html);
					content.empty().append($html);
					$(document).trigger('lightbox:displayed', [$html]);
				},
				error: function (jqXHR, textStatus) {
					content.html(textStatus);
				}
			});

			// stop the link from following the link
			e.preventDefault();
		})
		.on('click touchend MSPointerUp', '.lightbox-close-btn, .lightbox-overlay', function (e) {

			// hide the modal
			modal.hide();
			$html.removeClass('lightbox');
			$(document).trigger('lightbox:closed');

			if (isAndroid) {
				// Scroll back to screen position before lightbox is opened
				$scroll.scrollTop(screenPos);
			}

			e.preventDefault();
		});

}(jQuery, document, window));<|endoftext|>


<commit_before>// Import all the libraries
import alt from '../alt';
import Actions from '../actions/Actions';
import Socket from '../utils/socket';
import Favicon from '../utils/favicon';

// Custom function to concatenate two arrays without duplicates
function uniqueArray(arr1, arr2) {
  var arr = arr1.concat(arr2);
  for(var i=0; i < arr.length; ++i) {
    for(var j=i+1; j < arr.length; ++j) {
      if(arr[i] === arr[j]) arr.splice(j--, 1);
    }
  }
  return arr;
};

// The store where all the client side data is being stored
class PersonStore {
  constructor() {
    // Make the store functions trigger when actions are called
    this.bindActions(Actions);
    // Initialize users array
    this.users = [];
    // Initialize messages array
    this.messages = [];
    // Initialize the hiddenMessages num for the favicon
    this.hiddenMessages = 0;
    // Give the user a default name
    this.user = 'Default Name';

    // Add eventlistener to reset the favicon
    document.addEventListener('visibilitychange', this.resetMessageCount);
  }
  // Reset the hiddenMessage count and favicon
  resetMessageCount() {
    if(!document.hidden) {
      this.hiddenMessages = 0;
      Favicon.setBubble(this.hiddenMessages);
    }
  }
  // When the client joins set their username
  onClientJoin(name) {
    this.user = name;
    localStorage.setItem('chatName', this.user);
    Socket.sendJoin(this.user)
  }
  // Send the websocket leave command
  onClientLeave() {
    Socket.sendLeave(this.user)
  }
  // When you send a message
  onNewMessage(message) {
    this.messages.push(message);
    Socket.sendMessage(this.user, message.content, message.timestamp)
  }
  // When you receive a message
  onAddMessage(message) {
    if(document.hidden) {
      this.hiddenMessages += 1;
      Favicon.setBubble(this.hiddenMessages);
    }
    this.messages.push(message);
  }
  // When people join, diff the array and make it so there are no doubles
  onPersonJoin(newPeople) {
    this.users = uniqueArray(this.users, newPeople);
  }
  // Set users array to people provided by server
  onPersonLeave(newPeople) {
    this.users = newPeople;
  }
  // Return a list of messages
  static getMessages() {
    return this.getState().messages;
  }
  // Return a list of users
  static getPeople() {
    return this.getState().users;
  }
  // Return username
  static getName() {
    return this.getState().user;
  }
}

export default alt.createStore(PersonStore)
<commit_msg>fix the favicon<commit_after>// Import all the libraries
import alt from '../alt';
import Actions from '../actions/Actions';
import Socket from '../utils/socket';
import Favicon from '../utils/favicon';

// Custom function to concatenate two arrays without duplicates
function uniqueArray(arr1, arr2) {
  var arr = arr1.concat(arr2);
  for(var i=0; i < arr.length; ++i) {
    for(var j=i+1; j < arr.length; ++j) {
      if(arr[i] === arr[j]) arr.splice(j--, 1);
    }
  }
  return arr;
};

// The store where all the client side data is being stored
class PersonStore {
  constructor() {
    // Make the store functions trigger when actions are called
    this.bindActions(Actions);
    // Initialize users array
    this.users = [];
    // Initialize messages array
    this.messages = [];
    // Initialize the hiddenMessages num for the favicon
    this.hiddenMessages = 0;
    // Give the user a default name
    this.user = 'Default Name';

    // Add eventlistener to reset the favicon
    document.addEventListener('visibilitychange', this.resetMessageCount.bind(this));
  }
  // Reset the hiddenMessage count and favicon
  resetMessageCount() {
    if(!document.hidden) {
      this.hiddenMessages = 0;
      Favicon.reset();
    }
  }
  // When the client joins set their username
  onClientJoin(name) {
    this.user = name;
    localStorage.setItem('chatName', this.user);
    Socket.sendJoin(this.user)
  }
  // Send the websocket leave command
  onClientLeave() {
    Socket.sendLeave(this.user)
  }
  // When you send a message
  onNewMessage(message) {
    this.messages.push(message);
    Socket.sendMessage(this.user, message.content, message.timestamp)
  }
  // When you receive a message
  onAddMessage(message) {
    if(document.hidden) {
      this.hiddenMessages += 1;
      Favicon.setBubble(this.hiddenMessages);
    }
    this.messages.push(message);
  }
  // When people join, diff the array and make it so there are no doubles
  onPersonJoin(newPeople) {
    this.users = uniqueArray(this.users, newPeople);
  }
  // Set users array to people provided by server
  onPersonLeave(newPeople) {
    this.users = newPeople;
  }
  // Return a list of messages
  static getMessages() {
    return this.getState().messages;
  }
  // Return a list of users
  static getPeople() {
    return this.getState().users;
  }
  // Return username
  static getName() {
    return this.getState().user;
  }
}

export default alt.createStore(PersonStore)
<|endoftext|>