1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/network/src/TCPServerSocket.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,182 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +const Cc = Components.classes; 1.11 +const Ci = Components.interfaces; 1.12 +const Cu = Components.utils; 1.13 +const Cr = Components.results; 1.14 +const CC = Components.Constructor; 1.15 + 1.16 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.17 + 1.18 +const ServerSocket = CC( 1.19 + '@mozilla.org/network/server-socket;1', 'nsIServerSocket', 'init'), 1.20 + TCPSocketInternal = Cc[ 1.21 + '@mozilla.org/tcp-socket;1'].createInstance(Ci.nsITCPSocketInternal); 1.22 + 1.23 +/* 1.24 + * Debug logging function 1.25 + */ 1.26 + 1.27 +let debug = true; 1.28 +function LOG(msg) { 1.29 + if (debug) { 1.30 + dump("TCPServerSocket: " + msg + "\n"); 1.31 + } 1.32 +} 1.33 + 1.34 +/* 1.35 + * nsIDOMTCPServerSocket object 1.36 + */ 1.37 + 1.38 +function TCPServerSocket() { 1.39 + this._localPort = 0; 1.40 + this._binaryType = null; 1.41 + 1.42 + this._onconnect = null; 1.43 + this._onerror = null; 1.44 + 1.45 + this._inChild = false; 1.46 + this._neckoTCPServerSocket = null; 1.47 + this._serverBridge = null; 1.48 + this.useWin = null; 1.49 +} 1.50 + 1.51 +TCPServerSocket.prototype = { 1.52 + __exposedProps__: { 1.53 + port: 'r', 1.54 + onconnect: 'rw', 1.55 + onerror: 'rw' 1.56 + }, 1.57 + get localPort() { 1.58 + return this._localPort; 1.59 + }, 1.60 + get onconnect() { 1.61 + return this._onconnect; 1.62 + }, 1.63 + set onconnect(f) { 1.64 + this._onconnect = f; 1.65 + }, 1.66 + get onerror() { 1.67 + return this._onerror; 1.68 + }, 1.69 + set onerror(f) { 1.70 + this._onerror = f; 1.71 + }, 1.72 + 1.73 + _callListenerAcceptCommon: function tss_callListenerAcceptCommon(socket) { 1.74 + if (this._onconnect) { 1.75 + try { 1.76 + this["onconnect"].call(null, socket); 1.77 + } catch (e) { 1.78 + socket.close(); 1.79 + } 1.80 + } 1.81 + else { 1.82 + socket.close(); 1.83 + dump("Received unexpected connection!"); 1.84 + } 1.85 + }, 1.86 + init: function tss_init(aWindowObj) { 1.87 + this.useWin = aWindowObj; 1.88 + }, 1.89 + 1.90 + /* nsITCPServerSocketInternal method */ 1.91 + listen: function tss_listen(localPort, options, backlog) { 1.92 + this._inChild = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime) 1.93 + .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; 1.94 + this._binaryType = options.binaryType; 1.95 + 1.96 + if (this._inChild) { 1.97 + if (this._serverBridge == null) { 1.98 + this._serverBridge = Cc["@mozilla.org/tcp-server-socket-child;1"] 1.99 + .createInstance(Ci.nsITCPServerSocketChild); 1.100 + this._serverBridge.listen(this, localPort, backlog, options.binaryType); 1.101 + } 1.102 + else { 1.103 + throw new Error("Child TCPServerSocket has already listening. \n"); 1.104 + } 1.105 + } 1.106 + else { 1.107 + if (this._neckoTCPServerSocket == null) { 1.108 + this._neckoTCPServerSocket = new ServerSocket(localPort, false, backlog); 1.109 + this._localPort = this._neckoTCPServerSocket.port; 1.110 + this._neckoTCPServerSocket.asyncListen(this); 1.111 + } 1.112 + else { 1.113 + throw new Error("Parent TCPServerSocket has already listening. \n"); 1.114 + } 1.115 + } 1.116 + }, 1.117 + 1.118 + callListenerAccept: function tss_callListenerSocket(socketChild) { 1.119 + // this method is called at child process when the socket is accepted at parent process. 1.120 + let socket = TCPSocketInternal.createAcceptedChild(socketChild, this._binaryType, this.useWin); 1.121 + this._callListenerAcceptCommon(socket); 1.122 + }, 1.123 + 1.124 + callListenerError: function tss_callListenerError(message, filename, lineNumber, columnNumber) { 1.125 + if (this._onerror) { 1.126 + var type = "error"; 1.127 + var error = new Error(message, filename, lineNumber, columnNumber); 1.128 + 1.129 + this["onerror"].call(null, new TCPSocketEvent(type, this, error)); 1.130 + } 1.131 + }, 1.132 + /* end nsITCPServerSocketInternal method */ 1.133 + 1.134 + close: function tss_close() { 1.135 + if (this._inChild) { 1.136 + this._serverBridge.close(); 1.137 + return; 1.138 + } 1.139 + 1.140 + /* Close ServerSocket */ 1.141 + if (this._neckoTCPServerSocket) { 1.142 + this._neckoTCPServerSocket.close(); 1.143 + } 1.144 + }, 1.145 + 1.146 + // nsIServerSocketListener (Triggered by _neckoTCPServerSocket.asyncListen) 1.147 + onSocketAccepted: function tss_onSocketAccepted(server, trans) { 1.148 + // precondition: this._inChild == false 1.149 + try { 1.150 + let that = TCPSocketInternal.createAcceptedParent(trans, this._binaryType); 1.151 + this._callListenerAcceptCommon(that); 1.152 + } 1.153 + catch(e) { 1.154 + trans.close(Cr.NS_BINDING_ABORTED); 1.155 + } 1.156 + }, 1.157 + 1.158 + // nsIServerSocketListener (Triggered by _neckoTCPServerSocket.asyncListen) 1.159 + onStopListening: function tss_onStopListening(server, status) { 1.160 + if (status != Cr.NS_BINDING_ABORTED) { 1.161 + throw new Error("Server socket was closed by unexpected reason."); 1.162 + } 1.163 + this._neckoTCPServerSocket = null; 1.164 + }, 1.165 + 1.166 + classID: Components.ID("{73065eae-27dc-11e2-895a-000c29987aa2}"), 1.167 + 1.168 + classInfo: XPCOMUtils.generateCI({ 1.169 + classID: Components.ID("{73065eae-27dc-11e2-895a-000c29987aa2}"), 1.170 + classDescription: "Server TCP Socket", 1.171 + interfaces: [ 1.172 + Ci.nsIDOMTCPServerSocket, 1.173 + Ci.nsISupportsWeakReference 1.174 + ], 1.175 + flags: Ci.nsIClassInfo.DOM_OBJECT, 1.176 + }), 1.177 + 1.178 + QueryInterface: XPCOMUtils.generateQI([ 1.179 + Ci.nsIDOMTCPServerSocket, 1.180 + Ci.nsITCPServerSocketInternal, 1.181 + Ci.nsISupportsWeakReference 1.182 + ]) 1.183 +} 1.184 + 1.185 +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TCPServerSocket]);