diff -r 000000000000 -r 6474c204b198 dom/network/src/TCPServerSocket.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/network/src/TCPServerSocket.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,182 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; +const CC = Components.Constructor; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +const ServerSocket = CC( + '@mozilla.org/network/server-socket;1', 'nsIServerSocket', 'init'), + TCPSocketInternal = Cc[ + '@mozilla.org/tcp-socket;1'].createInstance(Ci.nsITCPSocketInternal); + +/* + * Debug logging function + */ + +let debug = true; +function LOG(msg) { + if (debug) { + dump("TCPServerSocket: " + msg + "\n"); + } +} + +/* + * nsIDOMTCPServerSocket object + */ + +function TCPServerSocket() { + this._localPort = 0; + this._binaryType = null; + + this._onconnect = null; + this._onerror = null; + + this._inChild = false; + this._neckoTCPServerSocket = null; + this._serverBridge = null; + this.useWin = null; +} + +TCPServerSocket.prototype = { + __exposedProps__: { + port: 'r', + onconnect: 'rw', + onerror: 'rw' + }, + get localPort() { + return this._localPort; + }, + get onconnect() { + return this._onconnect; + }, + set onconnect(f) { + this._onconnect = f; + }, + get onerror() { + return this._onerror; + }, + set onerror(f) { + this._onerror = f; + }, + + _callListenerAcceptCommon: function tss_callListenerAcceptCommon(socket) { + if (this._onconnect) { + try { + this["onconnect"].call(null, socket); + } catch (e) { + socket.close(); + } + } + else { + socket.close(); + dump("Received unexpected connection!"); + } + }, + init: function tss_init(aWindowObj) { + this.useWin = aWindowObj; + }, + + /* nsITCPServerSocketInternal method */ + listen: function tss_listen(localPort, options, backlog) { + this._inChild = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime) + .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; + this._binaryType = options.binaryType; + + if (this._inChild) { + if (this._serverBridge == null) { + this._serverBridge = Cc["@mozilla.org/tcp-server-socket-child;1"] + .createInstance(Ci.nsITCPServerSocketChild); + this._serverBridge.listen(this, localPort, backlog, options.binaryType); + } + else { + throw new Error("Child TCPServerSocket has already listening. \n"); + } + } + else { + if (this._neckoTCPServerSocket == null) { + this._neckoTCPServerSocket = new ServerSocket(localPort, false, backlog); + this._localPort = this._neckoTCPServerSocket.port; + this._neckoTCPServerSocket.asyncListen(this); + } + else { + throw new Error("Parent TCPServerSocket has already listening. \n"); + } + } + }, + + callListenerAccept: function tss_callListenerSocket(socketChild) { + // this method is called at child process when the socket is accepted at parent process. + let socket = TCPSocketInternal.createAcceptedChild(socketChild, this._binaryType, this.useWin); + this._callListenerAcceptCommon(socket); + }, + + callListenerError: function tss_callListenerError(message, filename, lineNumber, columnNumber) { + if (this._onerror) { + var type = "error"; + var error = new Error(message, filename, lineNumber, columnNumber); + + this["onerror"].call(null, new TCPSocketEvent(type, this, error)); + } + }, + /* end nsITCPServerSocketInternal method */ + + close: function tss_close() { + if (this._inChild) { + this._serverBridge.close(); + return; + } + + /* Close ServerSocket */ + if (this._neckoTCPServerSocket) { + this._neckoTCPServerSocket.close(); + } + }, + + // nsIServerSocketListener (Triggered by _neckoTCPServerSocket.asyncListen) + onSocketAccepted: function tss_onSocketAccepted(server, trans) { + // precondition: this._inChild == false + try { + let that = TCPSocketInternal.createAcceptedParent(trans, this._binaryType); + this._callListenerAcceptCommon(that); + } + catch(e) { + trans.close(Cr.NS_BINDING_ABORTED); + } + }, + + // nsIServerSocketListener (Triggered by _neckoTCPServerSocket.asyncListen) + onStopListening: function tss_onStopListening(server, status) { + if (status != Cr.NS_BINDING_ABORTED) { + throw new Error("Server socket was closed by unexpected reason."); + } + this._neckoTCPServerSocket = null; + }, + + classID: Components.ID("{73065eae-27dc-11e2-895a-000c29987aa2}"), + + classInfo: XPCOMUtils.generateCI({ + classID: Components.ID("{73065eae-27dc-11e2-895a-000c29987aa2}"), + classDescription: "Server TCP Socket", + interfaces: [ + Ci.nsIDOMTCPServerSocket, + Ci.nsISupportsWeakReference + ], + flags: Ci.nsIClassInfo.DOM_OBJECT, + }), + + QueryInterface: XPCOMUtils.generateQI([ + Ci.nsIDOMTCPServerSocket, + Ci.nsITCPServerSocketInternal, + Ci.nsISupportsWeakReference + ]) +} + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TCPServerSocket]);