Vesperia / server.coffee

###
 Vesperia: A Tethealla management port proxy and api server

 Copyright 2012 Pol Cámara
 Released under the MIT license
 Check LICENSE.MIT for more details.
###

Security = require "./model/security"
crypto = require "crypto"

#The global var is used to jump from a socket to the server.
gServer = false

class Server
  clients:  {}
  socket: false
  security: false
  constructor: (@net, @port, @host, @connection, @client) ->
    gServer = this
    this.security = new Security connection
    this.client.events.on 'message', (message) -> gServer._parseTethPacket(message)
      
  ###
  Initializes the server
  Example usage:
    serverInstance.initialize()
  ###
  initialize: ->
    server = this.net.createServer this._startSocket
    server.listen this.port, this.host

  _startSocket: (socket) -> 
    socket.authenticated = false
    socket.uid = false
    socket.write "100"
    socket.on 'data', (data) -> gServer._onData this,data.toString().replace("\n","")

  _onData: (socket, data) ->
    this._parsePacket socket, data if this._authenticate socket, data

  _authenticate: (socket, data) ->
    hashed = false
    return true if socket.authenticated == true
    if data.length > 3
      command = data.substring 0, 3
      if command == "110" || command == "111"
        hashed = true if command == "111"
        password = data.substring 3, data.length
        password = password.trim()
        this.security.valKey password, hashed, (keyExists) ->
          if keyExists
            socket.authenticated = true
            socket.uid =  crypto.createHash("md5").update((new Date().getTime()+Math.floor(Math.random()*1000)).toString()).digest("hex")
            socket.write "102"
            gServer.clients[socket.uid] = socket
          else
            gServer._disconnectClient socket, "101"
      else
        gServer._disconnectClient socket, "101"
    return false
 
  _disconnectClient: (socket,code) ->
    delete gServer.clients[socket.uid] if socket.uid
    socket.write(code)
    socket.end()

  _parsePacket: (socket,data) ->
    command = data.substring 0, 3
    details = data.substring 3, data.length
    details = details.trim()
    switch command
      when "210" then gServer._sendToTethealla(socket,details)

  _parseTethPacket: (data) ->
    if data.length > 35
      command = data.substring 0, 3
      uid = data.substring 3, 35
      message = data.substring 35, data.length
      if gServer.clients[uid] != "undefined"
        gServer.clients[uid].write message
    else
      console.log data.toString()

  _sendToTethealla: (socket,action) ->    
    if gServer.client
      if gServer.client.connected
        gServer.client.stream.write "200"+socket.uid+action
      else
        gServer.client.reconnect()        
        socket.write "202"

module.exports.Server = Server
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.