187 lines
6.9 KiB
CoffeeScript
187 lines
6.9 KiB
CoffeeScript
|
#-------------------------------------------------------------------------------
|
||
|
# 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
|