blob: 8b7945dd89ef5b825e77e18c0cd063790dbfa5e3 [file] [log] [blame]
#-------------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#-------------------------------------------------------------------------------
fs = require 'fs'
net = require 'net'
dns = require 'dns'
path = require 'path'
_ = require 'underscore'
express = require 'express'
utils = require './utils'
jsonBodyParser = require './jsonBodyParser'
HttpChannelHandler = require './HttpChannelHandler'
dumpingHandler = require './dumpingHandler'
channelManager = require './channelManager'
serviceManager = require './serviceManager'
#-------------------------------------------------------------------------------
exports.run = (options) ->
processOptions(options, run2)
#-------------------------------------------------------------------------------
run2 = ->
options = utils.options
serviceManager.registerProxyClass 'WeinreClientEvents'
serviceManager.registerProxyClass 'WeinreTargetEvents'
serviceManager.registerLocalClass 'WeinreClientCommands'
serviceManager.registerLocalClass 'WeinreTargetCommands'
startDeathWatcher options.deathTimeout
startServer()
#-------------------------------------------------------------------------------
processOptions = (options, cb) ->
options.httpPort = utils.ensureInteger( options.httpPort, 'the value of the option httpPort is not a number')
options.boundHost = utils.ensureString( options.boundHost, 'the value of the option boundHost is not a string')
options.verbose = utils.ensureBoolean( options.verbose, 'the value of the option verbose is not a boolean')
options.debug = utils.ensureBoolean( options.debug, 'the value of the option debug is not a boolean')
options.readTimeout = utils.ensureInteger( options.readTimeout, 'the value of the option readTimeout is not a number')
options.deathTimeout = utils.ensureInteger( options.deathTimeout, 'the value of the option deathTimeout is not a number')
options.verbose = true if options.debug
options.staticWebDir = getStaticWebDir()
utils.logVerbose "pid: #{process.pid}"
utils.logVerbose "version: #{getVersion()}"
utils.logVerbose "node versions:"
names = _.keys(process.versions)
reducer = (memo, name) -> Math.max(memo, name.length)
nameLen = _.reduce(names, reducer, 0)
for name in names
utils.logVerbose " #{utils.alignLeft(name, nameLen)}: #{process.versions[name]}"
utils.logVerbose "options:"
utils.logVerbose " httpPort: #{options.httpPort}"
utils.logVerbose " boundHost: #{options.boundHost}"
utils.logVerbose " verbose: #{options.verbose}"
utils.logVerbose " debug: #{options.debug}"
utils.logVerbose " readTimeout: #{options.readTimeout}"
utils.logVerbose " deathTimeout: #{options.deathTimeout}"
utils.setOptions options
checkHost options.boundHost, (err) ->
if err
utils.exit "unable to resolve boundHost address: #{options.boundHost}"
cb()
#-------------------------------------------------------------------------------
checkHost = (hostName, cb) ->
return cb() if hostName == '-all-'
return cb() if hostName == 'localhost'
return cb() if net.isIP(hostName)
dns.lookup hostName, cb
#-------------------------------------------------------------------------------
deathTimeout = null
#-------------------------------------------------------------------------------
startDeathWatcher = (timeout) ->
deathTimeout = utils.options.deathTimeout * 1000
setInterval checkForDeath, 1000
#-------------------------------------------------------------------------------
checkForDeath = ->
now = (new Date).valueOf()
for channel in channelManager.getChannels()
if now - channel.lastRead > deathTimeout
channel.close()
#-------------------------------------------------------------------------------
startServer = () ->
options = utils.options
clientHandler = new HttpChannelHandler('/ws/client')
targetHandler = new HttpChannelHandler('/ws/target')
channelManager.initialize()
favIcon = "#{options.staticWebDir}/images/weinre-icon-32x32.png"
staticCacheOptions =
maxObjects: 500
maxLength: 32 * 1024 * 1024
app = express.createServer()
app.on 'error', (error) ->
utils.exit "error running server: #{error}"
app.use express.favicon(favIcon)
app.use jsonBodyParser()
app.all /^\/ws\/client(.*)/, (request, response, next) ->
uri = request.params[0]
uri = '/' if uri == ''
dumpingHandler(request, response, uri) if options.debug
clientHandler.handle(request, response, uri)
app.all /^\/ws\/target(.*)/, (request, response, next) ->
uri = request.params[0]
uri = '/' if uri == ''
dumpingHandler(request, response, uri) if options.debug
targetHandler.handle(request, response, uri)
app.use express.errorHandler(dumpExceptions: true)
app.use express.staticCache(staticCacheOptions)
app.use express.static(options.staticWebDir)
if options.boundHost == '-all-'
utils.log "starting server at http://localhost:#{options.httpPort}"
app.listen options.httpPort
else
utils.log "starting server at http://#{options.boundHost}:#{options.httpPort}"
app.listen options.httpPort, options.boundHost
#-------------------------------------------------------------------------------
getStaticWebDir = () ->
webDir = path.normalize path.join(__dirname,'../web')
return webDir if utils.fileExistsSync webDir
utils.exit 'unable to find static files to serve in #{webDir}; did you do a build?'
#-------------------------------------------------------------------------------
Version = null
getVersion = exports.getVersion = () ->
return Version if Version
packageJsonName = path.join(path.dirname(fs.realpathSync(__filename)), '../package.json')
json = fs.readFileSync(packageJsonName, 'utf8')
values = JSON.parse(json)
Version = values.version
return Version