#------------------------------------------------------------------------------- # 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