PageRenderTime 241ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/browser.extensions/debugger.aptana.com/content/aptanadebugger/aptanaSockets.js

https://github.com/hotrhino/ide_core
JavaScript | 295 lines | 216 code | 37 blank | 42 comment | 38 complexity | 890194549753962f89aef0a9ed4fcb78 MD5 | raw file
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * This file Copyright (c) 2005-2007 Aptana, Inc. This program is
  3. * dual-licensed under both the Aptana Public License and the GNU General
  4. * Public license. You may elect to use one or the other of these licenses.
  5. *
  6. * This program is distributed in the hope that it will be useful, but
  7. * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
  8. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  9. * NONINFRINGEMENT. Redistribution, except as permitted by whichever of
  10. * the GPL or APL you select, is prohibited.
  11. *
  12. * 1. For the GPL license (GPL), you can redistribute and/or modify this
  13. * program under the terms of the GNU General Public License,
  14. * Version 3, as published by the Free Software Foundation. You should
  15. * have received a copy of the GNU General Public License, Version 3 along
  16. * with this program; if not, write to the Free Software Foundation, Inc., 51
  17. * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. * Aptana provides a special exception to allow redistribution of this file
  20. * with certain Eclipse Public Licensed code and certain additional terms
  21. * pursuant to Section 7 of the GPL. You may view the exception and these
  22. * terms on the web at http://www.aptana.com/legal/gpl/.
  23. *
  24. * 2. For the Aptana Public License (APL), this program and the
  25. * accompanying materials are made available under the terms of the APL
  26. * v1.0 which accompanies this distribution, and is available at
  27. * http://www.aptana.com/legal/apl/.
  28. *
  29. * You may view the GPL, Aptana's exception and additional terms, and the
  30. * APL in the file titled license.html at the root of the corresponding
  31. * plugin containing this source file.
  32. *
  33. * Any modifications to this file must keep this entire header intact.
  34. *
  35. * Contributor(s):
  36. * Max Stepanov (Aptana, Inc.)
  37. *
  38. * ***** END LICENSE BLOCK ***** */
  39. (function() {
  40. // ************************************************************************************************
  41. const nsISupports = Components.interfaces.nsISupports;
  42. const nsISocketTransportService = Components.interfaces.nsISocketTransportService;
  43. const nsIServerSocket = Components.interfaces.nsIServerSocket;
  44. const nsIServerSocketListener = Components.interfaces.nsIServerSocketListener;
  45. const nsITransport = Components.interfaces.nsITransport;
  46. const nsIScriptableInputStream = Components.interfaces.nsIScriptableInputStream;
  47. const nsIAsyncInputStream = Components.interfaces.nsIAsyncInputStream;
  48. const nsIInputStreamCallback = Components.interfaces.nsIInputStreamCallback;
  49. const NS_ERROR_NO_INTERFACE = Components.results.NS_ERROR_NO_INTERFACE;
  50. const NS_ERROR_ABORT = Components.results.NS_ERROR_ABORT;
  51. const NS_BASE_STREAM_CLOSED = Components.results.NS_BASE_STREAM_CLOSED;
  52. const PACKET_START = new RegExp(/^[0-9]+\*.+/);
  53. const isClientDebugger = (typeof(document) != "undefined");
  54. const ff3 = !isClientDebugger || (AptanaUtils.compareVersion(AptanaUtils.getAppVersion(), "3.0*") >= 0);
  55. function createSocketForTransport(transport, listener)
  56. {
  57. const outstream = transport.openOutputStream(nsITransport.OPEN_BLOCKING,0,0);
  58. const stream = transport.openInputStream(0,0,0);
  59. const instream = Components.classes["@mozilla.org/scriptableinputstream;1"]
  60. .createInstance(nsIScriptableInputStream);
  61. instream.init(stream);
  62. var socket =
  63. {
  64. transport: transport,
  65. output :outstream,
  66. input: stream,
  67. close: function()
  68. {
  69. if (this.closed) {
  70. return;
  71. }
  72. dd("Socket closed.");
  73. this.closed = true;
  74. this.input.close();
  75. this.output.close();
  76. },
  77. send: function(data)
  78. {
  79. if( this.closed ) {
  80. return;
  81. }
  82. var outputData = data.length + "*" + data;
  83. this.output.write(outputData, outputData.length);
  84. dd("Socket sent: >" + outputData + "<");
  85. }
  86. };
  87. var inputStreamPump = {
  88. astream: stream.QueryInterface(nsIAsyncInputStream),
  89. eventTarget: null,
  90. state: 0,
  91. data: "",
  92. onStartRequest: function() {},
  93. onStopRequest: function() {
  94. if (!socket.closed) {
  95. socket.close();
  96. listener.onClose();
  97. }
  98. },
  99. onDataAvailable: function(count) {
  100. this.data += instream.read(count);
  101. while( this.data.match(PACKET_START) ) {
  102. var index = this.data.indexOf("*");
  103. var packetEnd = parseInt(this.data.substring(0, index));
  104. if( this.data.length < packetEnd ) {
  105. return;
  106. }
  107. var packet = this.data.substring(index+1, index+1+packetEnd);
  108. this.data = this.data.substring(index+1+packetEnd);
  109. dd("Socket recv: >" + packet + "<");
  110. listener.onPacket(packet);
  111. }
  112. },
  113. startInThread: function() {
  114. if (socket.closed) {
  115. return;
  116. }
  117. if (ff3) {
  118. this.eventTarget = Components.classes["@mozilla.org/thread-manager;1"]
  119. .getService(Components.interfaces.nsIThreadManager)
  120. .currentThread;
  121. } else {
  122. this.eventTarget = Components.classes["@mozilla.org/event-queue-service;1"]
  123. .getService(Components.interfaces.nsIEventQueueService)
  124. .getSpecialEventQueue(Components.interfaces.nsIEventQueueService.CURRENT_THREAD_EVENT_QUEUE);
  125. }
  126. this.astream.asyncWait(this, 0, 0, this.eventTarget);
  127. },
  128. stopInThread: function() {
  129. if (socket.closed) {
  130. return;
  131. }
  132. /* hack to clear socket stream callback */
  133. this.astream.asyncWait(null, 0, 0, null);
  134. },
  135. onInputStreamReady: function(astream) {
  136. var state = -1;
  137. while( state != this.state ) {
  138. state = this.state;
  139. try {
  140. var count = astream.available();
  141. if ( state == 1 ) {
  142. if ( count > 0 ) {
  143. this.onDataAvailable(count);
  144. }
  145. } else if ( state == 0 ) {
  146. this.onStartRequest();
  147. ++this.state;
  148. }
  149. astream.asyncWait(this, 0, 0, this.eventTarget);
  150. } catch(exc) {
  151. if ( exc.result != NS_BASE_STREAM_CLOSED
  152. && exc.result != NS_ERROR_ABORT) {
  153. dd(exc,'err');
  154. astream.closeWithStatus(exc.result);
  155. }
  156. this.onStopRequest();
  157. return;
  158. }
  159. }
  160. },
  161. QueryInterface: function(iid) {
  162. if (iid.equals(nsIInputStreamCallback) || iid.equals(nsISupports)) {
  163. return this;
  164. }
  165. throw NS_ERROR_NO_INTERFACE;
  166. }
  167. };
  168. socket.startProcessing = function() {
  169. try {
  170. inputStreamPump.startInThread();
  171. } catch(exc) {
  172. dd(exc);
  173. }
  174. };
  175. socket.stopProcessing = function() {
  176. try {
  177. inputStreamPump.stopInThread();
  178. } catch(exc) {
  179. dd(exc);
  180. }
  181. };
  182. socket.startProcessing();
  183. return socket;
  184. }
  185. function createServerSocket(port, listener)
  186. {
  187. const serverSocket = Components.classes["@mozilla.org/network/server-socket;1"]
  188. .createInstance(nsIServerSocket);
  189. serverSocket.init(port, false, 1);
  190. var socketProxy =
  191. {
  192. socket: null,
  193. get closed() {
  194. if ( this.socket ) {
  195. return this.socket.closed;
  196. }
  197. return false;
  198. },
  199. close: function() {
  200. if ( this.socket ) {
  201. this.socket.close();
  202. } else {
  203. serverSocket.close();
  204. }
  205. },
  206. send: function(data) {
  207. if ( this.socket ) {
  208. this.socket.send(data);
  209. }
  210. }
  211. };
  212. const serverListener = {
  213. QueryInterface: function(iid) {
  214. if (iid.equals(nsIServerSocketListener) || iid.equals(nsISupports)) {
  215. return this;
  216. }
  217. throw NS_ERROR_NO_INTERFACE;
  218. },
  219. onSocketAccepted: function(serverSocket, transport) {
  220. socketProxy.socket = createSocketForTransport(transport, listener);
  221. serverSocket.close();
  222. },
  223. onStopListening: function(serverSocket, status) {
  224. }
  225. };
  226. serverSocket.asyncListen(serverListener);
  227. return socketProxy;
  228. }
  229. this.createSocket = function(host, port, listener)
  230. {
  231. if ( host == "*" ) {
  232. return createServerSocket(port, listener);
  233. }
  234. const transportService = Components.classes["@mozilla.org/network/socket-transport-service;1"]
  235. .getService(nsISocketTransportService);
  236. const transport = transportService.createTransport(null,0,host,port,null);
  237. transport.setTimeout(nsISocketTransportService.TIMEOUT_CONNECT,2/*seconds*/);
  238. return createSocketForTransport(transport, listener);
  239. }
  240. // ************************************************************************************************
  241. function dd(message,level)
  242. {
  243. if ( typeof(message) == 'object' && "fileName" in message && "lineNumber" in message ) {
  244. message = ""+message+" at "+message.fileName+":"+message.lineNumber;
  245. }
  246. try {
  247. if ( level == 'err' ) {
  248. AptanaLogger.logError(message);
  249. return;
  250. }
  251. if ( AptanaDebugger.DEBUG ) {
  252. AptanaLogger.log(message,level);
  253. }
  254. } catch(exc) {
  255. }
  256. }
  257. // ************************************************************************************************
  258. }).apply(AptanaDebugger);