You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pm...@apache.org on 2014/09/04 14:37:17 UTC
[15/15] weinre commit: pre-compile CoffeeScript files in server
pre-compile CoffeeScript files in server
Project: http://git-wip-us.apache.org/repos/asf/cordova-weinre/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-weinre/commit/03084bdb
Tree: http://git-wip-us.apache.org/repos/asf/cordova-weinre/tree/03084bdb
Diff: http://git-wip-us.apache.org/repos/asf/cordova-weinre/diff/03084bdb
Branch: refs/heads/master
Commit: 03084bdb6a23cc4f6085a16420df9182b2252e43
Parents: 34d2980
Author: Patrick Mueller <pm...@apache.org>
Authored: Sat Aug 30 14:42:05 2014 -0400
Committer: Patrick Mueller <pm...@apache.org>
Committed: Thu Sep 4 08:35:08 2014 -0400
----------------------------------------------------------------------
.wr | 2 +-
weinre.build/build.xml | 21 +
weinre.build/package.json.template | 10 +-
weinre.server/lib-src/Channel.coffee | 118 +
weinre.server/lib-src/HttpChannelHandler.coffee | 154 ++
weinre.server/lib-src/MessageQueue.coffee | 87 +
weinre.server/lib-src/channelManager.coffee | 126 ++
weinre.server/lib-src/cli.coffee | 130 ++
weinre.server/lib-src/dumpingHandler.coffee | 77 +
weinre.server/lib-src/extensionManager.coffee | 30 +
weinre.server/lib-src/jsonBodyParser.coffee | 47 +
weinre.server/lib-src/messageHandler.coffee | 59 +
.../lib-src/service/WeinreClientCommands.coffee | 126 ++
.../lib-src/service/WeinreTargetCommands.coffee | 90 +
weinre.server/lib-src/serviceManager.coffee | 95 +
weinre.server/lib-src/utils.coffee | 196 ++
weinre.server/lib-src/weinre.coffee | 186 ++
weinre.server/lib/Channel.coffee | 118 -
weinre.server/lib/Channel.js | 130 ++
weinre.server/lib/HttpChannelHandler.coffee | 154 --
weinre.server/lib/HttpChannelHandler.js | 130 ++
weinre.server/lib/MessageQueue.coffee | 87 -
weinre.server/lib/MessageQueue.js | 82 +
weinre.server/lib/channelManager.coffee | 126 --
weinre.server/lib/channelManager.js | 122 +
weinre.server/lib/cli.coffee | 130 --
weinre.server/lib/cli.js | 97 +
weinre.server/lib/dumpingHandler.coffee | 77 -
weinre.server/lib/dumpingHandler.js | 74 +
weinre.server/lib/extensionManager.coffee | 30 -
weinre.server/lib/extensionManager.js | 15 +
weinre.server/lib/jsonBodyParser.coffee | 47 -
weinre.server/lib/jsonBodyParser.js | 39 +
weinre.server/lib/messageHandler.coffee | 59 -
weinre.server/lib/messageHandler.js | 51 +
.../lib/service/WeinreClientCommands.coffee | 126 --
.../lib/service/WeinreClientCommands.js | 140 ++
.../lib/service/WeinreTargetCommands.coffee | 90 -
.../lib/service/WeinreTargetCommands.js | 78 +
weinre.server/lib/serviceManager.coffee | 95 -
weinre.server/lib/serviceManager.js | 90 +
weinre.server/lib/utils.coffee | 196 --
weinre.server/lib/utils.js | 194 ++
weinre.server/lib/weinre.coffee | 186 --
weinre.server/lib/weinre.js | 193 ++
weinre.server/node_modules/.bin/cake | 2 +-
weinre.server/node_modules/.bin/coffee | 2 +-
weinre.server/node_modules/.bin/express | 2 +-
weinre.server/node_modules/.bin/nopt | 2 +-
.../node_modules/coffee-script/CONTRIBUTING.md | 9 +
.../node_modules/coffee-script/LICENSE | 4 +-
weinre.server/node_modules/coffee-script/README | 21 +-
.../node_modules/coffee-script/README.md | 60 +
.../node_modules/coffee-script/Rakefile | 78 -
.../node_modules/coffee-script/extras/jsl.conf | 44 -
.../coffee-script/lib/coffee-script/browser.js | 100 +-
.../coffee-script/lib/coffee-script/cake.js | 11 +-
.../lib/coffee-script/coffee-script.js | 296 ++-
.../coffee-script/lib/coffee-script/command.js | 554 +++--
.../coffee-script/lib/coffee-script/grammar.js | 79 +-
.../coffee-script/lib/coffee-script/helpers.js | 181 +-
.../coffee-script/lib/coffee-script/index.js | 2 +-
.../coffee-script/lib/coffee-script/lexer.js | 412 ++--
.../coffee-script/lib/coffee-script/nodes.js | 1578 +++++++------
.../coffee-script/lib/coffee-script/optparse.js | 9 +-
.../coffee-script/lib/coffee-script/parser.js | 753 ++++---
.../coffee-script/lib/coffee-script/register.js | 66 +
.../coffee-script/lib/coffee-script/repl.js | 381 ++--
.../coffee-script/lib/coffee-script/rewriter.js | 402 ++--
.../coffee-script/lib/coffee-script/scope.js | 6 +-
.../lib/coffee-script/sourcemap.js | 161 ++
.../node_modules/mkdirp/.npmignore | 2 +
.../node_modules/mkdirp/.travis.yml | 5 +
.../coffee-script/node_modules/mkdirp/LICENSE | 21 +
.../node_modules/mkdirp/examples/pow.js | 6 +
.../coffee-script/node_modules/mkdirp/index.js | 82 +
.../node_modules/mkdirp/package.json | 34 +
.../node_modules/mkdirp/readme.markdown | 63 +
.../node_modules/mkdirp/test/chmod.js | 38 +
.../node_modules/mkdirp/test/clobber.js | 37 +
.../node_modules/mkdirp/test/mkdirp.js | 28 +
.../node_modules/mkdirp/test/perm.js | 32 +
.../node_modules/mkdirp/test/perm_sync.js | 39 +
.../node_modules/mkdirp/test/race.js | 41 +
.../node_modules/mkdirp/test/rel.js | 32 +
.../node_modules/mkdirp/test/return.js | 25 +
.../node_modules/mkdirp/test/return_sync.js | 24 +
.../node_modules/mkdirp/test/root.js | 18 +
.../node_modules/mkdirp/test/sync.js | 32 +
.../node_modules/mkdirp/test/umask.js | 28 +
.../node_modules/mkdirp/test/umask_sync.js | 32 +
.../node_modules/coffee-script/package.json | 38 +-
.../node_modules/coffee-script/register.js | 1 +
.../node_modules/coffee-script/repl.js | 1 +
weinre.server/node_modules/express/History.md | 5 +
.../node_modules/express/lib/express.js | 2 +-
.../node_modules/express/lib/request.js | 23 +-
.../express/node_modules/connect/lib/connect.js | 2 +-
.../node_modules/connect/lib/middleware/csrf.js | 2 +-
.../connect/node_modules/formidable/.npmignore | 5 +-
.../connect/node_modules/formidable/.travis.yml | 5 +-
.../connect/node_modules/formidable/LICENSE | 7 +
.../connect/node_modules/formidable/Makefile | 14 -
.../connect/node_modules/formidable/Readme.md | 468 ++--
.../connect/node_modules/formidable/TODO | 3 -
.../benchmark/bench-multipart-parser.js | 70 -
.../node_modules/formidable/example/post.js | 43 -
.../node_modules/formidable/example/upload.js | 48 -
.../connect/node_modules/formidable/index.js | 2 +-
.../connect/node_modules/formidable/lib/file.js | 45 +-
.../formidable/lib/incoming_form.js | 285 ++-
.../node_modules/formidable/lib/json_parser.js | 35 +
.../formidable/lib/multipart_parser.js | 50 +-
.../node_modules/formidable/lib/octet_parser.js | 20 +
.../formidable/lib/querystring_parser.js | 10 +-
.../connect/node_modules/formidable/lib/util.js | 6 -
.../formidable/node-gently/Makefile | 4 -
.../formidable/node-gently/Readme.md | 167 --
.../formidable/node-gently/example/dog.js | 22 -
.../node-gently/example/event_emitter.js | 11 -
.../formidable/node-gently/index.js | 1 -
.../formidable/node-gently/lib/gently/gently.js | 184 --
.../formidable/node-gently/lib/gently/index.js | 1 -
.../formidable/node-gently/package.json | 14 -
.../formidable/node-gently/test/common.js | 8 -
.../node-gently/test/simple/test-gently.js | 348 ---
.../node_modules/formidable/package.json | 27 +-
.../node_modules/formidable/test/common.js | 19 -
.../test/fixture/file/funkyfilename.txt | 1 -
.../formidable/test/fixture/file/plain.txt | 1 -
.../http/special-chars-in-filename/info.md | 3 -
.../formidable/test/fixture/js/no-filename.js | 3 -
.../fixture/js/special-chars-in-filename.js | 21 -
.../formidable/test/fixture/multipart.js | 72 -
.../test/integration/test-fixtures.js | 89 -
.../formidable/test/legacy/common.js | 24 -
.../legacy/integration/test-multipart-parser.js | 80 -
.../formidable/test/legacy/simple/test-file.js | 104 -
.../test/legacy/simple/test-incoming-form.js | 727 ------
.../test/legacy/simple/test-multipart-parser.js | 50 -
.../legacy/simple/test-querystring-parser.js | 45 -
.../legacy/system/test-multi-video-upload.js | 75 -
.../connect/node_modules/formidable/test/run.js | 2 -
.../formidable/test/unit/test-incoming-form.js | 63 -
.../node_modules/formidable/tool/record.js | 47 -
.../express/node_modules/connect/package.json | 9 +-
.../express/node_modules/connect/test.js | 39 +-
.../express/node_modules/mime/package.json | 10 +-
.../express/node_modules/mkdirp/package.json | 8 +-
.../express/node_modules/qs/package.json | 6 +
weinre.server/node_modules/express/package.json | 10 +-
weinre.server/node_modules/express/test.js | 3 +
weinre.server/node_modules/nopt/.npmignore | 1 +
weinre.server/node_modules/nopt/README.md | 15 +-
weinre.server/node_modules/nopt/bin/nopt.js | 14 +-
weinre.server/node_modules/nopt/lib/nopt.js | 282 +--
.../nopt/node_modules/abbrev/CONTRIBUTING.md | 3 +
.../nopt/node_modules/abbrev/LICENSE | 23 +
.../nopt/node_modules/abbrev/abbrev.js | 62 +
.../nopt/node_modules/abbrev/lib/abbrev.js | 106 -
.../nopt/node_modules/abbrev/package.json | 17 +-
.../nopt/node_modules/abbrev/test.js | 47 +
weinre.server/node_modules/nopt/package.json | 18 +-
weinre.server/node_modules/nopt/test/basic.js | 251 +++
.../node_modules/underscore/.npmignore | 3 -
weinre.server/node_modules/underscore/CNAME | 1 -
weinre.server/node_modules/underscore/LICENSE | 5 +-
weinre.server/node_modules/underscore/README.md | 25 +-
.../node_modules/underscore/favicon.ico | Bin 1406 -> 0 bytes
.../node_modules/underscore/index.html | 2109 ------------------
weinre.server/node_modules/underscore/index.js | 1 -
.../node_modules/underscore/package.json | 38 +-
.../node_modules/underscore/raw/underscore.psd | Bin 215540 -> 0 bytes
.../node_modules/underscore/underscore-min.js | 38 +-
.../node_modules/underscore/underscore.js | 1390 +++++++-----
weinre.server/weinre | 11 +-
176 files changed, 8950 insertions(+), 9342 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/.wr
----------------------------------------------------------------------
diff --git a/.wr b/.wr
index 265dd0a..caf5fe6 100644
--- a/.wr
+++ b/.wr
@@ -7,7 +7,7 @@ weinre.build/scripts
weinre.doc
weinre.server/interfaces
-weinre.server/lib
+weinre.server/lib-src
weinre.server/package.json
weinre.server/README.md
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.build/build.xml
----------------------------------------------------------------------
diff --git a/weinre.build/build.xml b/weinre.build/build.xml
index 5324454..17f58d5 100644
--- a/weinre.build/build.xml
+++ b/weinre.build/build.xml
@@ -174,6 +174,7 @@ To update the weinre dependencies, use
>git: ${git-log}
</concat> <!-- keep this outdented, since Ant is so wonderful -->
+ <antcall target="build-server"/>
<antcall target="build-web"/>
<antcall target="build-json-idl"/>
<antcall target="build-client"/>
@@ -202,6 +203,26 @@ To update the weinre dependencies, use
</target>
<!-- ============================================================
+ basic server resources
+ ============================================================ -->
+
+ <target name="build-server">
+ <delete dir="../${PROJECT_SERVER}/lib" />
+ <mkdir dir="../${PROJECT_SERVER}/lib" />
+ <mkdir dir="../${PROJECT_SERVER}/lib/service" />
+
+ <echo message="compiling CoffeeScript files in: ${PROJECT_SERVER}/lib-src"/>
+ <exec executable="node" failonerror="true" failifexecutionfails="true">
+ <arg value="../${PROJECT_SERVER}/node_modules/coffee-script/bin/coffee"/>
+ <arg value="--compile"/>
+ <arg value="--bare"/>
+ <arg value="--output"/>
+ <arg value="../${PROJECT_SERVER}/lib"/>
+ <arg value="../${PROJECT_SERVER}/lib-src"/>
+ </exec>
+ </target>
+
+ <!-- ============================================================
basic web resources
============================================================ -->
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.build/package.json.template
----------------------------------------------------------------------
diff --git a/weinre.build/package.json.template b/weinre.build/package.json.template
index 71f3762..1779836 100644
--- a/weinre.build/package.json.template
+++ b/weinre.build/package.json.template
@@ -21,10 +21,13 @@
},
"dependencies":
{
- "coffee-script": "1.3.x",
"express": "2.5.x",
- "nopt": "1.0.x",
- "underscore": "1.3.x"
+ "nopt": "3.0.x",
+ "underscore": "1.7.x"
+ },
+ "devDependencies":
+ {
+ "coffee-script": "1.8.x"
},
"main" : "./lib/weinre",
"bin":
@@ -39,4 +42,3 @@
"url": "https://git-wip-us.apache.org/repos/asf/cordova-weinre.git"
}
}
-
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/Channel.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/Channel.coffee b/weinre.server/lib-src/Channel.coffee
new file mode 100644
index 0000000..70f5841
--- /dev/null
+++ b/weinre.server/lib-src/Channel.coffee
@@ -0,0 +1,118 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+_ = require 'underscore'
+
+utils = require './utils'
+channelManager = require './channelManager'
+messageHandler = require './messageHandler'
+MessageQueue = require './MessageQueue'
+
+AnonymousId = 'anonymous'
+
+#-------------------------------------------------------------------------------
+module.exports = utils.registerClass class Channel
+
+ #---------------------------------------------------------------------------
+ constructor: (@pathPrefix, @id, @remoteAddress, @isClient) ->
+ prefix = if @isClient then 'c-' else 't-'
+ @name = "#{prefix}#{utils.getNextSequenceNumber()}"
+ @messageQueue = new MessageQueue
+ @isClosed = false
+ @connections = []
+ @isTarget = !@isClient
+ @readTimeout = utils.options.readTimeout * 1000
+
+ @id = AnonymousId if !@id
+
+ @description =
+ channel: @name
+ id: @id
+ hostName: @remoteAddress
+ remoteAddress: @remoteAddress
+
+ @updateLastRead()
+
+ channelManager.created @
+
+ #---------------------------------------------------------------------------
+ close: () ->
+ return if @isClosed
+
+ channelManager.destroyed @
+
+ @isClosed = true
+ @messageQueue.shutdown()
+
+ #---------------------------------------------------------------------------
+ sendCallback: (intfName, callbackId, args...) ->
+ return if !callbackId
+
+ args.unshift callbackId
+
+ @sendMessage intfName, 'sendCallback', args...
+
+ #---------------------------------------------------------------------------
+ sendMessage: (intfName, method, args...) ->
+
+ message = genJSON
+ interface: intfName
+ method: method
+ args: args
+
+ @messageQueue.push message
+
+ #---------------------------------------------------------------------------
+ handleMessages: (messages) ->
+
+ for message in messages
+ message = parseJSON(message)
+ continue if !message
+
+ messageHandler.handleMessage @, message
+
+ #---------------------------------------------------------------------------
+ getMessages: (callback) ->
+ @updateLastRead()
+ return callback.call(null, null) if @isClosed
+
+ @messageQueue.pullAll @readTimeout, callback
+
+ #---------------------------------------------------------------------------
+ updateLastRead: () ->
+ @lastRead = (new Date).valueOf()
+
+ #---------------------------------------------------------------------------
+ toString: () ->
+ connections = _.map(@connections, (val) -> val.name).join(',')
+ "Channel(#{@name}, closed:#{@isClosed}, connections:[#{connections}])"
+
+#-------------------------------------------------------------------------------
+parseJSON = (message) ->
+ try
+ return JSON.parse(message)
+ catch e
+ return null
+
+#-------------------------------------------------------------------------------
+genJSON = (message) ->
+ try
+ return JSON.stringify(message)
+ catch e
+ return null
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/HttpChannelHandler.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/HttpChannelHandler.coffee b/weinre.server/lib-src/HttpChannelHandler.coffee
new file mode 100644
index 0000000..dd7f2f4
--- /dev/null
+++ b/weinre.server/lib-src/HttpChannelHandler.coffee
@@ -0,0 +1,154 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+_ = require 'underscore'
+
+utils = require './utils'
+Channel = require './Channel'
+channelManager = require './channelManager'
+
+#-------------------------------------------------------------------------------
+module.exports = utils.registerClass class HttpChannelHandler
+
+ #---------------------------------------------------------------------------
+ constructor: (@pathPrefix) ->
+
+ if @pathPrefix == '/ws/client'
+ @isClient = true
+
+ else if @pathPrefix == '/ws/target'
+ @isClient = false
+
+ else
+ utils.pitch "invalid pathPrefix: #{@pathPrefix}"
+
+ @isTarget = !@isClient
+
+ #---------------------------------------------------------------------------
+ handle: (request, response, uri) ->
+
+ setCORSHeaders request, response
+ setCacheHeaders request, response
+
+ #-----------------
+
+ # * #{pathPrefix}a
+ if uri[0] != '/'
+ return handleError(request, response, 404)
+
+ #-----------------
+
+ if uri == '/'
+
+ # OPTIONS #{pathPrefix}/
+ if request.method == 'OPTIONS'
+ return handleOptions(request, response)
+
+ # POST #{pathPrefix}/
+ if request.method == 'POST'
+ return handleCreate(@pathPrefix, @isClient, request, response)
+
+ # * #{pathPrefix}/
+ return handleError(request, response, 405)
+
+ #-----------------
+
+ parts = uri.split('/')
+
+ # * #{pathPrefix}/x/y
+ if parts.length > 2
+ return handleError(request, response, 404)
+
+ #-----------------
+
+ channelName = parts[1]
+
+ # OPTIONS #{pathPrefix}/x
+ if request.method == 'OPTIONS'
+ return handleOptions(request, response)
+
+ # GET #{pathPrefix}/x
+ if request.method == 'GET'
+ return handleGet(request, response, channelName)
+
+ # POST #{pathPrefix}/x
+ if request.method == 'POST'
+ return handlePost(request, response, channelName)
+
+ # anything else
+ return handleError(request, response, 405)
+
+#-------------------------------------------------------------------------------
+handleCreate = (pathPrefix, isClient, request, response) ->
+ id = request.body?.id
+
+ remoteAddress = request.connection?.remoteAddress || ""
+
+ channel = new Channel(pathPrefix, id, remoteAddress, isClient)
+
+ response.contentType 'application/json'
+ response.send JSON.stringify
+ channel: channel.name
+ id: channel.id
+
+#-------------------------------------------------------------------------------
+handleGet = (request, response, channelName) ->
+ remoteAddress = request.connection?.remoteAddress || ""
+ channel = channelManager.getChannel(channelName, remoteAddress)
+ return handleError(request, response, 404) if !channel
+
+ channel.getMessages (messages) =>
+ return handleError(request, response, 404) if channel.isClosed
+ return handleError(request, response, 404) if !messages
+
+ response.contentType 'application/json'
+ response.send JSON.stringify(messages)
+
+#-------------------------------------------------------------------------------
+handlePost = (request, response, channelName) ->
+ remoteAddress = request.connection?.remoteAddress || ""
+ channel = channelManager.getChannel(channelName, remoteAddress)
+ return handleError(request, response, 404) if !channel
+
+ channel.handleMessages(request.body)
+ response.send('')
+
+#-------------------------------------------------------------------------------
+handleOptions = (request, response) ->
+ response.send('')
+
+#-------------------------------------------------------------------------------
+handleError = (request, response, status) ->
+ response.send(status)
+
+#-------------------------------------------------------------------------------
+setCORSHeaders = (request, response) ->
+ origin = request.header 'Origin'
+ return if !origin
+
+ response.header 'Access-Control-Allow-Origin', origin
+ response.header 'Access-Control-Max-Age', '600'
+ response.header 'Access-Control-Allow-Methods', 'GET, POST'
+
+#-------------------------------------------------------------------------------
+setCacheHeaders = (request, response) ->
+ response.header 'Pragma', 'no-cache'
+ response.header 'Expires', '0'
+ response.header 'Cache-Control', 'no-cache'
+ response.header 'Cache-Control', 'no-store'
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/MessageQueue.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/MessageQueue.coffee b/weinre.server/lib-src/MessageQueue.coffee
new file mode 100644
index 0000000..52af9ea
--- /dev/null
+++ b/weinre.server/lib-src/MessageQueue.coffee
@@ -0,0 +1,87 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+_ = require 'underscore'
+
+utils = require './utils'
+
+#-------------------------------------------------------------------------------
+module.exports = utils.registerClass class MessageQueue
+
+ #---------------------------------------------------------------------------
+ constructor: () ->
+ @messages = []
+ @closed = false
+ @callback = null
+ @timer = null
+
+ _.bindAll @, '_timerExpired', '_updated'
+
+ #---------------------------------------------------------------------------
+ shutdown: () ->
+ return if @closed
+
+ @closed = true
+
+ clearTimeout @timer if @timer
+ @callback.call(null, @messages) if @callback
+
+ @callback = null
+ @messages = null
+ @timer = null
+
+ #---------------------------------------------------------------------------
+ push: (message) ->
+ return if @closed
+
+ @messages.push message
+ process.nextTick @_updated
+
+ #---------------------------------------------------------------------------
+ pullAll: (timeout, callback) ->
+ return callback.call(null, null) if @closed
+ return callback.call(null, []) if @callback
+
+ if @messages.length
+ callback.call(null, @messages)
+ @messages = []
+ return
+
+ @callback = callback
+ @timer = setTimeout @_timerExpired, timeout
+
+ #---------------------------------------------------------------------------
+ _timerExpired: () ->
+ @_updated()
+
+ #---------------------------------------------------------------------------
+ _updated: () ->
+ return if @closed
+ return if !@callback
+
+ callback = @callback
+ messages = @messages
+ clearTimeout @timer if @timer
+
+ @callback = null
+ @messages = []
+ @timer = null
+
+ callback.call(null, messages)
+
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/channelManager.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/channelManager.coffee b/weinre.server/lib-src/channelManager.coffee
new file mode 100644
index 0000000..d55bb01
--- /dev/null
+++ b/weinre.server/lib-src/channelManager.coffee
@@ -0,0 +1,126 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+_ = require 'underscore'
+
+utils = require './utils'
+serviceManager = require './serviceManager'
+
+WeinreClientEvents = null
+WeinreTargetEvents = null
+
+channelManager = null
+
+#-------------------------------------------------------------------------------
+utils.registerClass class ChannelManager
+
+ #---------------------------------------------------------------------------
+ constructor: () ->
+ @channels = {}
+
+ #---------------------------------------------------------------------------
+ initialize: ->
+
+ WeinreClientEvents = serviceManager.get 'WeinreClientEvents'
+ WeinreTargetEvents = serviceManager.get 'WeinreTargetEvents'
+
+ if !WeinreClientEvents
+ utils.exit 'WeinreClientEvents service not registered'
+
+ if !WeinreTargetEvents
+ utils.exit 'WeinreTargetEvents service not registered'
+
+ #---------------------------------------------------------------------------
+ created: (channel) ->
+ @channels[channel.name] = channel
+
+ #---------------------------------------------------------------------------
+ destroyed: (channel) ->
+ if channel.isClient
+ for connection in channel.connections
+ @disconnectChannels(channel, connection)
+ else
+ for connection in channel.connections
+ @disconnectChannels(connection, channel)
+
+ clients = @getClientChannels(channel.id)
+
+ if channel.isClient
+ WeinreClientEvents.clientUnregistered(clients, channel.name)
+ else
+ WeinreClientEvents.targetUnregistered(clients, channel.name)
+
+ delete @channels[channel.name]
+
+ #---------------------------------------------------------------------------
+ getChannel: (name, remoteAddress) ->
+ return null if !_.has(@channels, name)
+
+ channel = @channels[name]
+
+ return null if !channel
+
+# if remoteAddress
+# return null if channel.remoteAddress != remoteAddress
+
+ channel
+
+ #---------------------------------------------------------------------------
+ connectChannels: (client, target) ->
+ return if client.isClosed or target.isClosed
+
+ if client.connections.length
+ @disconnectChannels(client, client.connections[0])
+
+ client.connections.push target
+ target.connections.push client
+
+ clients = @getClientChannels(client.id)
+
+ WeinreClientEvents.connectionCreated(clients, client.name, target.name)
+ WeinreTargetEvents.connectionCreated(target, client.name, target.name)
+
+ #---------------------------------------------------------------------------
+ disconnectChannels: (client, target) ->
+
+ clients = @getClientChannels(client.id)
+
+ WeinreClientEvents.connectionDestroyed(clients, client.name, target.name)
+ WeinreTargetEvents.connectionDestroyed(target, client.name, target.name)
+
+ client.connections = _.without(client.connections, target)
+ target.connections = _.without(target.connections, client)
+
+ #---------------------------------------------------------------------------
+ getChannels: (id) ->
+ if id?
+ _.filter(@channels, (item) -> item.id == id)
+ else
+ _.values(@channels)
+
+ #---------------------------------------------------------------------------
+ getClientChannels: (id) ->
+ _.filter(@channels, (item) -> item.isClient && item.id == id)
+
+ #---------------------------------------------------------------------------
+ getTargetChannels: (id) ->
+ _.filter(@channels, (item) -> item.isTarget && item.id == id)
+
+#-------------------------------------------------------------------------------
+module.exports = new ChannelManager
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/cli.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/cli.coffee b/weinre.server/lib-src/cli.coffee
new file mode 100644
index 0000000..197e39c
--- /dev/null
+++ b/weinre.server/lib-src/cli.coffee
@@ -0,0 +1,130 @@
+#-------------------------------------------------------------------------------
+# 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'
+path = require 'path'
+
+_ = require 'underscore'
+nopt = require 'nopt'
+
+utils = require './utils'
+weinre = require './weinre'
+
+optionDefaults =
+ httpPort: 8080
+ boundHost: 'localhost'
+ verbose: false
+ debug: false
+ readTimeout: 5
+
+#-------------------------------------------------------------------------------
+exports.run = ->
+
+ knownOpts =
+ httpPort: Number
+ boundHost: String
+ verbose: Boolean
+ debug: Boolean
+ readTimeout: Number
+ deathTimeout: Number
+ help: Boolean
+
+ shortHands =
+ '?': ['--help']
+ 'h': ['--help']
+
+ nopt.invalidHandler = printNoptError
+ parsedOpts = nopt(knownOpts, shortHands, process.argv, 2)
+
+ #----
+
+ printHelp() if parsedOpts.help
+
+ args = parsedOpts.argv.remain
+
+ printHelp() if args.length != 0
+
+ #----
+
+ delete parsedOpts.argv
+ opts = _.extend {}, optionDefaults, getDotWeinreServerProperties(), parsedOpts
+
+ if !opts.deathTimeout?
+ opts.deathTimeout = 3 * opts.readTimeout
+
+ utils.setOptions opts
+
+ weinre.run opts
+
+#-------------------------------------------------------------------------------
+printNoptError = (key, val, types) ->
+ utils.exit "error with option '#{key}', value '#{val}'"
+
+#-------------------------------------------------------------------------------
+printHelp = () ->
+ version = weinre.getVersion()
+
+ console.error """
+usage: #{utils.Program} [options]
+version: #{version}
+
+options:
+ --httpPort port to run the http server on default: #{optionDefaults.httpPort}
+ --boundHost ip address to bind the server to default: #{optionDefaults.boundHost}
+ --verbose print more diagnostics default: #{optionDefaults.verbose}
+ --debug print even more diagnostics default: #{optionDefaults.debug}
+ --readTimeout seconds to wait for a client message default: #{optionDefaults.readTimeout}
+ --deathTimeout seconds to wait to kill client default: 3*readTimeout
+
+--boundHost can be an ip address, hostname, or -all-, where -all-
+means binding to all ip address on the current machine'
+
+for more info see: http://people.apache.org/~pmuellr/weinre/
+"""
+ process.exit()
+
+#-------------------------------------------------------------------------------
+getDotWeinreServerProperties = () ->
+ properties = {}
+
+ fileName = replaceTilde '~/.weinre/server.properties'
+ return properties if !utils.fileExistsSync(fileName)
+
+ contents = fs.readFileSync(fileName, 'utf8')
+ lines = contents.split('\n')
+
+ for line in lines
+ line = line.replace(/#.*/,'')
+ match = line.match /\s*(\w+)\s*:\s*(.+)\s*/
+ continue if !match
+
+ key = utils.trim match[1]
+ val = utils.trim match[2]
+
+ properties[key] = val
+
+ properties
+
+#-------------------------------------------------------------------------------
+replaceTilde = (fileName) ->
+ fileName.replace('~', getTildeReplacement())
+
+#-------------------------------------------------------------------------------
+getTildeReplacement = () ->
+ process.env["HOME"] || process.env["USERPROFILE"] || '.'
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/dumpingHandler.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/dumpingHandler.coffee b/weinre.server/lib-src/dumpingHandler.coffee
new file mode 100644
index 0000000..310852d
--- /dev/null
+++ b/weinre.server/lib-src/dumpingHandler.coffee
@@ -0,0 +1,77 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+_ = require 'underscore'
+
+utils = require './utils'
+
+#-------------------------------------------------------------------------------
+dumpingHandler = (request, response, uri) ->
+ originalSend = response.send
+ response.send = (body) ->
+ dumpResponse(originalSend, body, request, response, uri)
+
+ return if request.method != 'POST'
+
+ utils.logVerbose '--------------------------------------------------'
+ utils.logVerbose "#{request.method} #{uri} [request]"
+
+ if _.isArray(request.body)
+ for element in request.body
+ utils.logVerbose " #{enhance(JSON.parse(element))}"
+ else
+ utils.logVerbose " #{enhance(request.body)}"
+
+#-------------------------------------------------------------------------------
+dumpResponse = (originalSend, body, request, response, uri) ->
+ originalSend.call(response, body)
+
+ return if request.method not in ['GET', 'POST']
+
+ try
+ body = JSON.parse(body)
+ catch e
+ return
+
+ return if _.isArray(body) && (body.length == 0)
+
+ utils.logVerbose '--------------------------------------------------'
+ utils.logVerbose "#{request.method} #{uri} #{response.statusCode} [response]"
+
+ if _.isArray(body)
+ for element in body
+ utils.logVerbose " #{enhance(JSON.parse(element))}"
+ else
+ utils.logVerbose " #{enhance(body)}"
+
+#-------------------------------------------------------------------------------
+enhance = (object) ->
+ if !object.interface || !object.method || !object.args
+ return JSON.stringify(object)
+
+ signature = "#{object.interface}.#{object.method}"
+
+ args = JSON.stringify(object.args)
+ if args.length > 500
+ args = "#{args.substr(0,50)}..."
+
+ return "#{signature}(#{args})"
+
+#-------------------------------------------------------------------------------
+module.exports = dumpingHandler
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/extensionManager.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/extensionManager.coffee b/weinre.server/lib-src/extensionManager.coffee
new file mode 100644
index 0000000..c367425
--- /dev/null
+++ b/weinre.server/lib-src/extensionManager.coffee
@@ -0,0 +1,30 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+utils = require './utils'
+
+#-------------------------------------------------------------------------------
+utils.registerClass class ExtensionManager
+
+ #---------------------------------------------------------------------------
+ constructor: () ->
+ @extensions = []
+
+#-------------------------------------------------------------------------------
+module.exports = new ExtensionManager
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/jsonBodyParser.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/jsonBodyParser.coffee b/weinre.server/lib-src/jsonBodyParser.coffee
new file mode 100644
index 0000000..58f755b
--- /dev/null
+++ b/weinre.server/lib-src/jsonBodyParser.coffee
@@ -0,0 +1,47 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+#-------------------------------------------------------------------------------
+jsonBodyParser = ->
+ return (request, response, next) -> parseBodyAsJSON(request, response, next)
+
+#-------------------------------------------------------------------------------
+parseBodyAsJSON = (request, response, next) ->
+
+ return next() if request.body
+
+ request.body = {}
+
+ return next() if request.method != 'POST'
+
+ request.setEncoding 'utf8'
+
+ buffer = ''
+ request.on 'data', (chunk) -> buffer += chunk
+ request.on 'end', ->
+ return next() if '' == buffer
+
+ try
+ request.body = JSON.parse(buffer)
+ next()
+ catch e
+ next(e)
+
+#-------------------------------------------------------------------------------
+module.exports = jsonBodyParser
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/messageHandler.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/messageHandler.coffee b/weinre.server/lib-src/messageHandler.coffee
new file mode 100644
index 0000000..0c79430
--- /dev/null
+++ b/weinre.server/lib-src/messageHandler.coffee
@@ -0,0 +1,59 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+utils = require './utils'
+channelManager = require './channelManager'
+serviceManager = require './serviceManager'
+
+#-------------------------------------------------------------------------------
+utils.registerClass class MessageHandler
+
+ #---------------------------------------------------------------------------
+ handleMessage: (channel, message) ->
+ @_serviceMethodInvoker(channel, message.interface, message.method, message.args)
+
+ #---------------------------------------------------------------------------
+ _serviceMethodInvoker: (channel, intfName, method, args) ->
+ methodSignature = "#{intfName}.#{method}()"
+ # utils.logVerbose "MessageHandler._serviceMethodInvoker(#{methodSignature})"
+
+ service = serviceManager.get(intfName)
+
+ if !service
+ return @_redirectToConnections(channel, intfName, method, args)
+
+ args = args.slice()
+ args.unshift channel
+
+ try
+ service[method].apply(service, args)
+
+ catch e
+ utils.log "error running service method #{methodSignature}: #{e}"
+ utils.log "stack:\n#{e.stack}"
+
+ #---------------------------------------------------------------------------
+ _redirectToConnections: (channel, intfName, method, args) ->
+ # utils.logVerbose "MessageHandler._redirectToConnections(#{channel.name}, #{intfName}, #{method})"
+
+ for connection in channel.connections
+ connection.sendMessage(intfName, method, args...)
+
+#-------------------------------------------------------------------------------
+module.exports = new MessageHandler
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/service/WeinreClientCommands.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/service/WeinreClientCommands.coffee b/weinre.server/lib-src/service/WeinreClientCommands.coffee
new file mode 100644
index 0000000..713a48b
--- /dev/null
+++ b/weinre.server/lib-src/service/WeinreClientCommands.coffee
@@ -0,0 +1,126 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+_ = require('underscore')
+
+weinre = require '../weinre'
+utils = require '../utils'
+channelManager = require '../channelManager'
+serviceManager = require '../serviceManager'
+extensionManager = require '../extensionManager'
+
+WeinreClientEvents = serviceManager.get 'WeinreClientEvents'
+
+#-------------------------------------------------------------------------------
+module.exports = utils.registerClass class WeinreClientCommands
+
+ #---------------------------------------------------------------------------
+ registerClient: (channel, callbackId) ->
+ if callbackId
+ WeinreClientEvents.sendCallback(channel, callbackId, channel.description)
+
+ options = _.extend {}, utils.options
+ for own key, val of options
+ if typeof val in ['number', 'boolean']
+ options[key] = "#{val}"
+
+ options.version = weinre.getVersion()
+
+ WeinreClientEvents.serverProperties(channel, options)
+
+ clients = channelManager.getClientChannels(channel.id)
+ WeinreClientEvents.clientRegistered(clients, channel.description)
+
+ #---------------------------------------------------------------------------
+ getTargets: (channel, callbackId) ->
+ channels = channelManager.getTargetChannels(channel.id)
+ result = _.pluck(channels, 'description')
+
+ if callbackId
+ WeinreClientEvents.sendCallback(channel, callbackId, [result])
+
+ #---------------------------------------------------------------------------
+ getClients: (channel, callbackId) ->
+ channels = channelManager.getClientChannels(channel.id)
+ result = _.pluck(channels, 'description')
+
+ if callbackId
+ WeinreClientEvents.sendCallback(channel, callbackId, [result])
+
+ #---------------------------------------------------------------------------
+ getExtensions: (channel, callbackId) ->
+ result = for extension in extensionManager.extensions
+ { startPage: "extensions/#{extension}/extension.html" }
+
+ if callbackId
+ WeinreClientEvents.sendCallback(channel, callbackId, [result])
+
+ #---------------------------------------------------------------------------
+ connectTarget: (channel, clientName, targetName, callbackId) ->
+ client = channelManager.getChannel(clientName)
+ return if !client
+
+ target = channelManager.getChannel(targetName)
+ return if !target
+
+ channelManager.connectChannels(client, target)
+
+ if callbackId
+ WeinreClientEvents.sendCallback(channel, callbackId)
+
+ #---------------------------------------------------------------------------
+ disconnectTarget: (channel, clientName, callbackId) ->
+ client = connectionManager.getClient(clientName)
+ return if !client
+
+ target = client.getConnectedTarget()
+ return if !target
+
+ connectionManager.disconnect(client, target)
+
+ if callbackId
+ WeinreClientEvents.sendCallback(channel, callbackId)
+
+ #---------------------------------------------------------------------------
+ logDebug: (channel, message, callbackId) ->
+ utils.logVerbose "client #{channel.name}: #{message}"
+
+ if callbackId
+ WeinreClientEvents.sendCallback(channel, callbackId)
+
+ #---------------------------------------------------------------------------
+ logInfo: (channel, message, callbackId) ->
+ utils.log "client #{channel.name}: #{message}"
+
+ if callbackId
+ WeinreClientEvents.sendCallback(channel, callbackId)
+
+ #---------------------------------------------------------------------------
+ logWarning: (channel, message, callbackId) ->
+ utils.log "client #{channel.name}: #{message}"
+
+ if callbackId
+ WeinreClientEvents.sendCallback(channel, callbackId)
+
+ #---------------------------------------------------------------------------
+ logError: (channel, message, callbackId) ->
+ utils.log "client #{channel.name}: #{message}"
+
+ if callbackId
+ WeinreClientEvents.sendCallback(channel, callbackId)
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/service/WeinreTargetCommands.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/service/WeinreTargetCommands.coffee b/weinre.server/lib-src/service/WeinreTargetCommands.coffee
new file mode 100644
index 0000000..4603e20
--- /dev/null
+++ b/weinre.server/lib-src/service/WeinreTargetCommands.coffee
@@ -0,0 +1,90 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+utils = require '../utils'
+channelManager = require '../channelManager'
+serviceManager = require '../serviceManager'
+
+WeinreClientEvents = serviceManager.get 'WeinreClientEvents'
+WeinreTargetEvents = serviceManager.get 'WeinreTargetEvents'
+
+#-------------------------------------------------------------------------------
+module.exports = utils.registerClass class WeinreTargetCommands
+
+ #---------------------------------------------------------------------------
+ registerTarget: (channel, url, callbackId) ->
+ channel.description.url = url
+
+ clients = channelManager.getClientChannels(channel.id)
+ WeinreClientEvents.targetRegistered(clients, channel.description)
+
+ if callbackId
+ WeinreTargetEvents.sendCallback(channel, callbackId, channel.description)
+
+ #---------------------------------------------------------------------------
+ sendClientCallback: (channel, clientCallbackId, args, callbackId) ->
+
+ # the channel to send the callback to is embedded in the callbackId
+ callbackChannel = getCallbackChannel(clientCallbackId)
+ if !callbackChannel
+ return main.warn "#{@constructor.name}.sendClientCallback() sent with invalid callbackId: #{clientCallbackId}"
+
+ callbackChannel = channelManager.getChannel(callbackChannel)
+ if !callbackChannel
+ # indication that channel was closed; this message may generate a lot of noise
+ return main.warn "#{@constructor.name}.sendClientCallback() unable to find channel : #{clientCallbackId}"
+
+ WeinreClientEvents.sendCallback(callbackChannel, clientCallbackId, args)
+
+ if callbackId
+ WeinreTargetEvents.sendCallback(channel, callbackId, description)
+
+ #---------------------------------------------------------------------------
+ logDebug: (channel, message, callbackId) ->
+ utils.logVerbose "target #{channel.name}: #{message}"
+
+ if callbackId
+ WeinreTargetEvents.sendCallback(channel, callbackId, description)
+
+ #---------------------------------------------------------------------------
+ logInfo: (channel, message, callbackId) ->
+ utils.log "target #{channel.name}: #{message}"
+
+ if callbackId
+ WeinreTargetEvents.sendCallback(channel, callbackId, description)
+
+ #---------------------------------------------------------------------------
+ logWarning: (channel, message, callbackId) ->
+ utils.log "target #{channel.name}: #{message}"
+
+ if callbackId
+ WeinreTargetEvents.sendCallback(channel, callbackId, description)
+
+ #---------------------------------------------------------------------------
+ logError: (channel, message, callbackId) ->
+ utils.log "target #{channel.name}: #{message}"
+
+ if callbackId
+ WeinreTargetEvents.sendCallback(channel, callbackId, description)
+
+#---------------------------------------------------------------------------
+getCallbackChannel = (callbackId) ->
+ callbackId = callbackId.toString()
+ callbackId.split('::')[0]
+
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/serviceManager.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/serviceManager.coffee b/weinre.server/lib-src/serviceManager.coffee
new file mode 100644
index 0000000..ade070f
--- /dev/null
+++ b/weinre.server/lib-src/serviceManager.coffee
@@ -0,0 +1,95 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+
+path = require 'path'
+fs = require 'fs'
+
+_ = require 'underscore'
+
+utils = require './utils'
+
+Services = {}
+
+#-------------------------------------------------------------------------------
+utils.registerClass class ServiceManager
+
+ #---------------------------------------------------------------------------
+ constructor: ->
+ @services = {}
+
+ #---------------------------------------------------------------------------
+ get: (name) ->
+ return @services[name] if _.has(@services, name)
+
+ null
+
+ #---------------------------------------------------------------------------
+ registerLocalClass: (name) ->
+
+ serviceClass = null
+ try
+ serviceClass = require "./service/#{name}"
+ catch e
+ utils.log "local service class not found: #{name}"
+ throw e
+
+ @services[name] = new serviceClass
+
+ #---------------------------------------------------------------------------
+ registerProxyClass: (name) ->
+
+ intf = getServiceInterface(name)
+
+ if !intf
+ utils.exit "proxy service class not found: #{name}"
+
+ if intf.name != name
+ utils.exit "proxy interface '#{intf.name}' loaded when '#{name}' requested"
+
+ service = {}
+
+ for method in intf.methods
+ service[method.name] = getMethodProxy(name, method.name)
+
+ @services[name] = service
+
+
+#-------------------------------------------------------------------------------
+getMethodProxy = (intfName, methodName) ->
+ (channels, args...) ->
+ channels = [channels] if !_.isArray(channels)
+
+ for channel in channels
+ channel.sendMessage(intfName, methodName, args...)
+
+#-------------------------------------------------------------------------------
+getServiceInterface = (name) ->
+ jsonName = "#{name}.json"
+ fileName = path.join utils.options.staticWebDir, 'interfaces', jsonName
+
+ return null if !utils.fileExistsSync(fileName)
+
+ contents = fs.readFileSync(fileName, 'utf8')
+
+ serviceInterface = JSON.parse(contents)
+
+ return serviceInterface.interfaces[0]
+
+#-------------------------------------------------------------------------------
+module.exports = new ServiceManager
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/utils.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/utils.coffee b/weinre.server/lib-src/utils.coffee
new file mode 100644
index 0000000..ee5a72b
--- /dev/null
+++ b/weinre.server/lib-src/utils.coffee
@@ -0,0 +1,196 @@
+#-------------------------------------------------------------------------------
+# 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'
+path = require 'path'
+
+utils = exports
+
+utils.Program = Program = path.basename process.argv[1]
+
+SequenceNumberMax = 100 * 1024 * 1024
+SequenceNumber = 0
+
+#-------------------------------------------------------------------------------
+utils.getNextSequenceNumber = (g) ->
+ SequenceNumber++
+
+ if SequenceNumber > SequenceNumberMax
+ SequenceNumber = 0
+
+ SequenceNumber
+
+#-------------------------------------------------------------------------------
+utils.trim = (string) ->
+ string.replace(/(^\s+)|(\s+$)/g,'')
+
+#-------------------------------------------------------------------------------
+utils.log = log = (message) ->
+ date = new Date()
+ time = date.toISOString()
+ console.log "#{time} #{Program}: #{message}"
+
+#-------------------------------------------------------------------------------
+utils.logVerbose = (message) ->
+ return if !utils?.options?.verbose
+
+ log message
+
+#-------------------------------------------------------------------------------
+utils.logDebug = (message) ->
+ return if !utils?.options?.debug
+
+ log message
+
+#-------------------------------------------------------------------------------
+utils.exit = (message) ->
+ log message
+ process.exit 1
+
+#-------------------------------------------------------------------------------
+utils.pitch = (message) ->
+ log message
+ throw message
+
+#-------------------------------------------------------------------------------
+utils.setOptions = (options) ->
+ utils.options = options
+
+#-------------------------------------------------------------------------------
+utils.ensureInteger = (value, message) ->
+ newValue = parseInt value
+
+ if isNaN newValue
+ utils.exit "#{message}: '#{value}'"
+
+ newValue
+
+#-------------------------------------------------------------------------------
+utils.ensureString = (value, message) ->
+
+ if typeof value != 'string'
+ utils.exit "#{message}: '#{value}'"
+
+ value
+
+#-------------------------------------------------------------------------------
+utils.ensureBoolean = (value, message) ->
+ uValue = value.toString().toUpperCase()
+
+ newValue = null
+ switch uValue
+ when 'TRUE' then newValue = true
+ when 'FALSE' then newValue = false
+
+ if typeof(newValue) != 'boolean'
+ utils.exit "#{message}: '#{value}'"
+
+ newValue
+
+#-------------------------------------------------------------------------------
+utils.setNamesForClass = (aClass) ->
+
+ for own key, val of aClass
+ if typeof(val) is "function"
+ val.signature = "#{aClass.name}::#{key}"
+ val.displayName = val.signature
+ val.name = val.signature
+
+ for own key, val of aClass.prototype
+ if typeof(val) is "function"
+ val.signature = "#{aClass.name}.#{key}"
+ val.displayName = val.signature
+ val.name = val.signature
+
+#-------------------------------------------------------------------------------
+utils.registerClass = (aClass) ->
+ utils.setNamesForClass(aClass)
+ aClass
+
+#-------------------------------------------------------------------------------
+utils.alignLeft = (string, length) ->
+ while string.length < length
+ string = "#{string} "
+
+ string
+
+#-------------------------------------------------------------------------------
+utils.alignRight = (string, length) ->
+ while string.length < length
+ string = " #{string}"
+
+ string
+
+#-------------------------------------------------------------------------------
+utils.fileExistsSync = (name) ->
+
+ if fs.existsSync
+ return fs.existsSync name
+
+ return path.existsSync(name)
+
+#-------------------------------------------------------------------------------
+Error.prepareStackTrace = (error, structuredStackTrace) ->
+ result = []
+ result.push "---------------------------------------------------------"
+ result.push "error: #{error}"
+ result.push "---------------------------------------------------------"
+ result.push "stack: "
+
+ longestFile = 0
+ longestLine = 0
+
+ for callSite in structuredStackTrace
+ file = callSite.getFileName()
+ line = callSite.getLineNumber()
+
+ file = path.basename(file)
+ line = "#{line}"
+
+ if file.length > longestFile
+ longestFile = file.length
+
+ if line.length > longestLine
+ longestLine = line.length
+
+ for callSite in structuredStackTrace
+ func = callSite.getFunction()
+ file = callSite.getFileName()
+ line = callSite.getLineNumber()
+
+ file = path.basename(file)
+ line = "#{line}"
+
+ file = utils.alignRight(file, longestFile)
+ line = utils.alignLeft( line, longestLine)
+
+ funcName = func.displayName ||
+ func.name ||
+ callSite.getFunctionName()
+ callSite.getMethodName()
+ '???'
+
+ if funcName == "Module._compile"
+ result.pop()
+ result.pop()
+ break
+
+ result.push " #{file}:#{line} - #{funcName}()"
+
+ result.join "\n"
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib-src/weinre.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib-src/weinre.coffee b/weinre.server/lib-src/weinre.coffee
new file mode 100644
index 0000000..8b7945d
--- /dev/null
+++ b/weinre.server/lib-src/weinre.coffee
@@ -0,0 +1,186 @@
+#-------------------------------------------------------------------------------
+# 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
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib/Channel.coffee
----------------------------------------------------------------------
diff --git a/weinre.server/lib/Channel.coffee b/weinre.server/lib/Channel.coffee
deleted file mode 100644
index 70f5841..0000000
--- a/weinre.server/lib/Channel.coffee
+++ /dev/null
@@ -1,118 +0,0 @@
-#-------------------------------------------------------------------------------
-# 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.
-#-------------------------------------------------------------------------------
-
-_ = require 'underscore'
-
-utils = require './utils'
-channelManager = require './channelManager'
-messageHandler = require './messageHandler'
-MessageQueue = require './MessageQueue'
-
-AnonymousId = 'anonymous'
-
-#-------------------------------------------------------------------------------
-module.exports = utils.registerClass class Channel
-
- #---------------------------------------------------------------------------
- constructor: (@pathPrefix, @id, @remoteAddress, @isClient) ->
- prefix = if @isClient then 'c-' else 't-'
- @name = "#{prefix}#{utils.getNextSequenceNumber()}"
- @messageQueue = new MessageQueue
- @isClosed = false
- @connections = []
- @isTarget = !@isClient
- @readTimeout = utils.options.readTimeout * 1000
-
- @id = AnonymousId if !@id
-
- @description =
- channel: @name
- id: @id
- hostName: @remoteAddress
- remoteAddress: @remoteAddress
-
- @updateLastRead()
-
- channelManager.created @
-
- #---------------------------------------------------------------------------
- close: () ->
- return if @isClosed
-
- channelManager.destroyed @
-
- @isClosed = true
- @messageQueue.shutdown()
-
- #---------------------------------------------------------------------------
- sendCallback: (intfName, callbackId, args...) ->
- return if !callbackId
-
- args.unshift callbackId
-
- @sendMessage intfName, 'sendCallback', args...
-
- #---------------------------------------------------------------------------
- sendMessage: (intfName, method, args...) ->
-
- message = genJSON
- interface: intfName
- method: method
- args: args
-
- @messageQueue.push message
-
- #---------------------------------------------------------------------------
- handleMessages: (messages) ->
-
- for message in messages
- message = parseJSON(message)
- continue if !message
-
- messageHandler.handleMessage @, message
-
- #---------------------------------------------------------------------------
- getMessages: (callback) ->
- @updateLastRead()
- return callback.call(null, null) if @isClosed
-
- @messageQueue.pullAll @readTimeout, callback
-
- #---------------------------------------------------------------------------
- updateLastRead: () ->
- @lastRead = (new Date).valueOf()
-
- #---------------------------------------------------------------------------
- toString: () ->
- connections = _.map(@connections, (val) -> val.name).join(',')
- "Channel(#{@name}, closed:#{@isClosed}, connections:[#{connections}])"
-
-#-------------------------------------------------------------------------------
-parseJSON = (message) ->
- try
- return JSON.parse(message)
- catch e
- return null
-
-#-------------------------------------------------------------------------------
-genJSON = (message) ->
- try
- return JSON.stringify(message)
- catch e
- return null
http://git-wip-us.apache.org/repos/asf/cordova-weinre/blob/03084bdb/weinre.server/lib/Channel.js
----------------------------------------------------------------------
diff --git a/weinre.server/lib/Channel.js b/weinre.server/lib/Channel.js
new file mode 100644
index 0000000..040e4c3
--- /dev/null
+++ b/weinre.server/lib/Channel.js
@@ -0,0 +1,130 @@
+// Generated by CoffeeScript 1.8.0
+var AnonymousId, Channel, MessageQueue, channelManager, genJSON, messageHandler, parseJSON, utils, _,
+ __slice = [].slice;
+
+_ = require('underscore');
+
+utils = require('./utils');
+
+channelManager = require('./channelManager');
+
+messageHandler = require('./messageHandler');
+
+MessageQueue = require('./MessageQueue');
+
+AnonymousId = 'anonymous';
+
+module.exports = utils.registerClass(Channel = (function() {
+ function Channel(pathPrefix, id, remoteAddress, isClient) {
+ var prefix;
+ this.pathPrefix = pathPrefix;
+ this.id = id;
+ this.remoteAddress = remoteAddress;
+ this.isClient = isClient;
+ prefix = this.isClient ? 'c-' : 't-';
+ this.name = "" + prefix + (utils.getNextSequenceNumber());
+ this.messageQueue = new MessageQueue;
+ this.isClosed = false;
+ this.connections = [];
+ this.isTarget = !this.isClient;
+ this.readTimeout = utils.options.readTimeout * 1000;
+ if (!this.id) {
+ this.id = AnonymousId;
+ }
+ this.description = {
+ channel: this.name,
+ id: this.id,
+ hostName: this.remoteAddress,
+ remoteAddress: this.remoteAddress
+ };
+ this.updateLastRead();
+ channelManager.created(this);
+ }
+
+ Channel.prototype.close = function() {
+ if (this.isClosed) {
+ return;
+ }
+ channelManager.destroyed(this);
+ this.isClosed = true;
+ return this.messageQueue.shutdown();
+ };
+
+ Channel.prototype.sendCallback = function() {
+ var args, callbackId, intfName;
+ intfName = arguments[0], callbackId = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
+ if (!callbackId) {
+ return;
+ }
+ args.unshift(callbackId);
+ return this.sendMessage.apply(this, [intfName, 'sendCallback'].concat(__slice.call(args)));
+ };
+
+ Channel.prototype.sendMessage = function() {
+ var args, intfName, message, method;
+ intfName = arguments[0], method = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
+ message = genJSON({
+ "interface": intfName,
+ method: method,
+ args: args
+ });
+ return this.messageQueue.push(message);
+ };
+
+ Channel.prototype.handleMessages = function(messages) {
+ var message, _i, _len, _results;
+ _results = [];
+ for (_i = 0, _len = messages.length; _i < _len; _i++) {
+ message = messages[_i];
+ message = parseJSON(message);
+ if (!message) {
+ continue;
+ }
+ _results.push(messageHandler.handleMessage(this, message));
+ }
+ return _results;
+ };
+
+ Channel.prototype.getMessages = function(callback) {
+ this.updateLastRead();
+ if (this.isClosed) {
+ return callback.call(null, null);
+ }
+ return this.messageQueue.pullAll(this.readTimeout, callback);
+ };
+
+ Channel.prototype.updateLastRead = function() {
+ return this.lastRead = (new Date).valueOf();
+ };
+
+ Channel.prototype.toString = function() {
+ var connections;
+ connections = _.map(this.connections, function(val) {
+ return val.name;
+ }).join(',');
+ return "Channel(" + this.name + ", closed:" + this.isClosed + ", connections:[" + connections + "])";
+ };
+
+ return Channel;
+
+})());
+
+parseJSON = function(message) {
+ var e;
+ try {
+ return JSON.parse(message);
+ } catch (_error) {
+ e = _error;
+ return null;
+ }
+};
+
+genJSON = function(message) {
+ var e;
+ try {
+ return JSON.stringify(message);
+ } catch (_error) {
+ e = _error;
+ return null;
+ }
+};