PageRenderTime 48ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/chrome/oneteam/content/JavaScript/socks5.js

https://github.com/qiu198022/oneteam
JavaScript | 727 lines | 604 code | 112 blank | 11 comment | 103 complexity | da57e923dcac5d69e8f50ee4943d8929 MD5 | raw file
  1. var EXPORTED_SYMBOLS = ["socks5Service"];
  2. function SOCKS5Service()
  3. {
  4. }
  5. _DECL_(SOCKS5Service).prototype =
  6. {
  7. ipAddresses: [],
  8. transfers: {},
  9. proxies: {},
  10. registerProxy: function(jid)
  11. {
  12. var bsp = new JSJaCIQ();
  13. bsp.setIQ(jid, "get");
  14. bsp.setQuery("http://jabber.org/protocol/bytestreams");
  15. account.connection.send(bsp, new Callback(this._onProxyAddress, this));
  16. },
  17. _onProxyAddress: function(pkt)
  18. {
  19. var sh = pkt.getNode().getElementsByTagNameNS(
  20. "http://jabber.org/protocol/bytestreams", "streamhost");
  21. for (var i = 0; i < sh.length; i++)
  22. if (sh[i].getAttribute("port")) {
  23. this.proxies[sh[i].getAttribute("jid")] = {
  24. host: sh[i].getAttribute("host"),
  25. port: +sh[i].getAttribute("port")
  26. };
  27. };
  28. },
  29. canReceive: function() {
  30. return true;
  31. },
  32. canSendTo: function(contact)
  33. {
  34. return contact != null;
  35. },
  36. sendFile: function(fileTransfer, rangeOffset, rangeLength)
  37. {
  38. var bsNS = new Namespace("http://jabber.org/protocol/bytestreams");
  39. var xml = <query xmlns="http://jabber.org/protocol/bytestreams" mode="tcp"
  40. sid={fileTransfer.streamID}/>;
  41. var SOCKSHostName = hex_sha1(fileTransfer.streamID + fileTransfer.ourJid +
  42. fileTransfer.jid);
  43. var token = {
  44. fileTransfer: fileTransfer,
  45. accepted: false
  46. };
  47. token.bytestream = new SOCKSBytestreamInitiator(SOCKSHostName, this, token);
  48. if (!this.ipAddresses.length) {
  49. try {
  50. var jnrs = Components.classes["@process-one.net/jnrelay;1"].
  51. getService(Components.interfaces.otIJNRelayService);
  52. var record = jnrs.ips;
  53. while (record && record.hasMore()) {
  54. var ip = record.getNextAddrAsString();
  55. if (ip.indexOf("127.") != 0 && this.ipAddresses.indexOf(ip) < 0)
  56. this.ipAddresses.push(ip);
  57. }
  58. } catch (ex) { }
  59. if (this.ipAddresses.length == 0) {
  60. var ds = Components.classes["@mozilla.org/network/dns-service;1"].
  61. getService(Components.interfaces.nsIDNSService);
  62. for each (var name in [ds.myHostName, "localhost"])
  63. try {
  64. var record = ds.resolve(name, 0);
  65. while (record && record.hasMore()) {
  66. var ip = record.getNextAddrAsString();
  67. if (ip.indexOf("127.") != 0 && this.ipAddresses.indexOf(ip) < 0)
  68. this.ipAddresses.push(ip);
  69. }
  70. } catch (ex) { }
  71. }
  72. }
  73. for (var i = 0; i < this.ipAddresses.length; i++)
  74. xml.appendChild(<streamhost host={this.ipAddresses[i]} jid={fileTransfer.ourJid}
  75. port={token.bytestream.port} />);
  76. for (i in this.proxies)
  77. xml.appendChild(<streamhost host={this.proxies[i].host} jid={i}
  78. port={this.proxies[i].port} />);
  79. var pkt = new JSJaCIQ();
  80. pkt.setIQ(fileTransfer.jid, "set");
  81. pkt.getNode().appendChild(E4XtoDOM(xml, pkt.getDoc()));
  82. account.connection.send(pkt, new Callback(this._sendFileStep, this), token);
  83. return token;
  84. },
  85. abort: function(token)
  86. {
  87. if (token.bytestreams)
  88. for (var i = 0; i < token.bytestreams.length; i++)
  89. token.bytestreams[i].abort();
  90. if (token.bytestream)
  91. token.bytestream.abort();
  92. delete token.bytestreams;
  93. delete token.bytestream;
  94. },
  95. _sendFileStep: function(pkt, token)
  96. {
  97. if (pkt.getType() != "result") {
  98. token.bytestream.abort();
  99. token.fileTransfer.onRejected();
  100. return;
  101. }
  102. var xml = DOMtoE4X(pkt.getNode());
  103. var bsNS = new Namespace("http://jabber.org/protocol/bytestreams");
  104. var jid = xml..bsNS::["streamhost-used"].@jid.toString();
  105. if (jid == token.fileTransfer.ourJid.toString()) {
  106. if (token.accepted) {
  107. token.fileTransfer.file.open(null, token.fileTransfer.file.MODE_RDONLY);
  108. token.bytestream.sendFile(token.fileTransfer.file);
  109. token.fileTransfer.onTransferStart();
  110. } else
  111. token.accepted = true;
  112. } else {
  113. var SOCKSHostName = token.bytestream.socksAddr;
  114. token.bytestream.abort();
  115. token.bytestream = new SOCKSBytestreamTarget([this.proxies[jid]],
  116. SOCKSHostName, this, token);
  117. token.proxy = jid;
  118. }
  119. },
  120. _sendFileStep2: function(pkt, token)
  121. {
  122. if (pkt.getType() != "result") {
  123. token.bytestream.abort();
  124. token.fileTransfer.onTransferFailure();
  125. return;
  126. }
  127. token.fileTransfer.file.open(null, token.fileTransfer.file.MODE_RDONLY);
  128. token.bytestream.sendFile(token.fileTransfer.file);
  129. token.fileTransfer.onTransferStart();
  130. },
  131. recvFile: function(fileTransfer)
  132. {
  133. return this.transfers[fileTransfer.streamID] = {
  134. bytestreams: [],
  135. fileTransfer: fileTransfer
  136. }
  137. },
  138. onIQ: function(pkt)
  139. {
  140. if (pkt.getType() != "set")
  141. return;
  142. var xml = DOMtoE4X(pkt.getNode());
  143. var bsNS = new Namespace("http://jabber.org/protocol/bytestreams");
  144. var token;
  145. if (!(token = this.transfers[xml.bsNS::query.@sid]))
  146. return;
  147. delete this.transfers[xml.bsNS::query.@sid];
  148. var bs = {};
  149. for each (var sh in xml..bsNS::streamhost) {
  150. if (sh.@port)
  151. if (bs[sh.@jid])
  152. bs[sh.@jid].push({host: sh.@host, port: sh.@port});
  153. else
  154. bs[sh.@jid] = [{host: sh.@host, port: sh.@port}];
  155. }
  156. var SOCKSHostName = hex_sha1(token.fileTransfer.streamID + token.fileTransfer.jid +
  157. token.fileTransfer.ourJid);
  158. token.id = pkt.getID();
  159. for (var i in bs) {
  160. var bytestream = new SOCKSBytestreamTarget(bs[i], SOCKSHostName,
  161. this, token);
  162. bytestream._jid = i;
  163. token.bytestreams.push(bytestream);
  164. }
  165. token.pendingConnections = token.bytestreams.length;
  166. },
  167. onBytestreamReady: function(initiator, token)
  168. {
  169. if (token.fileTransfer.type == "recv") {
  170. for (var i = 0; i < token.bytestreams.length; i++)
  171. if (token.bytestreams[i] != initiator)
  172. token.bytestreams[i].abort();
  173. delete token.bytestreams;
  174. token.bytestream = initiator;
  175. var pkt = new JSJaCIQ();
  176. pkt.setIQ(token.fileTransfer.jid, "result", token.id);
  177. pkt.getNode().appendChild(E4XtoDOM(
  178. <query xmlns='http://jabber.org/protocol/bytestreams'>
  179. <streamhost-used jid={initiator._jid}/>
  180. </query>, pkt.getDoc()));
  181. account.connection.send(pkt);
  182. token.fileTransfer.file.open(null, 0x2|0x8|0x20);
  183. token.bytestream.recvFile(token.fileTransfer.file);
  184. token.fileTransfer.onTransferStart();
  185. return;
  186. }
  187. if (token.proxy) {
  188. var pkt = new JSJaCIQ();
  189. pkt.setIQ(token.proxy, "set");
  190. pkt.getNode().appendChild(E4XtoDOM(
  191. <query xmlns='http://jabber.org/protocol/bytestreams'
  192. sid={token.fileTransfer.streamID}>
  193. <activate>{token.fileTransfer.jid}</activate>
  194. </query>, pkt.getDoc()));
  195. account.connection.send(pkt, new Callback(this._sendFileStep2, this), token);
  196. return;
  197. }
  198. if (token.accepted) {
  199. token.fileTransfer.file.open(null, token.fileTransfer.file.MODE_RDONLY);
  200. token.bytestream.sendFile(token.fileTransfer.file);
  201. token.fileTransfer.onTransferStart();
  202. } else
  203. token.accepted = true;
  204. },
  205. onBytestreamComplete: function(initiator, token)
  206. {
  207. token.fileTransfer.onTransferCompleted();
  208. },
  209. onBytestreamProgress: function(initiator, token, bytes)
  210. {
  211. token.fileTransfer.onTransferProgress(bytes);
  212. },
  213. onBytestreamFailure: function(initiator, token)
  214. {
  215. if (!token.bytestreams || --token.pendingConnections <= 0)
  216. token.fileTransfer.onTransferFailure();
  217. }
  218. }
  219. function SOCKSBytestreamTarget(addresses, socksAddr, callback, token)
  220. {
  221. this.addresses = addresses;
  222. this.socksAddr = socksAddr;
  223. this.callback = callback;
  224. this.token = token;
  225. this.currentAddr = 0;
  226. this.socktranssrv =
  227. Components.classes["@mozilla.org/network/socket-transport-service;1"].
  228. getService(Components.interfaces.nsISocketTransportService);
  229. this.eventQ = Components.classes["@mozilla.org/event-queue-service;1"] ?
  230. Components.classes["@mozilla.org/event-queue-service;1"].
  231. getService(Components.interfaces.nsIEventQueueService).
  232. getSpecialEventQueue(eqs.CURRENT_THREAD_EVENT_QUEUE) :
  233. Components.classes["@mozilla.org/thread-manager;1"].
  234. getService().mainThread;
  235. this.connect();
  236. }
  237. SOCKSBytestreamTarget.prototype =
  238. {
  239. sendFile: function(file)
  240. {
  241. this.file = file;
  242. this.state = 10;
  243. this.os.asyncWait(this, 0, 512, this.eventQ);
  244. },
  245. recvFile: function(file)
  246. {
  247. this.file = file;
  248. this.state = 11;
  249. this.is.asyncWait(this, 0, 512, this.eventQ);
  250. },
  251. abort: function(file)
  252. {
  253. this.ilen = 0;
  254. this.state = 12;
  255. this.is.close();
  256. this.os.close();
  257. this.os.asyncWait(this, this.os.WAIT_CLOSURE_ONLY, 0, this.eventQ);
  258. this.is.asyncWait(this, this.is.WAIT_CLOSURE_ONLY, 0, this.eventQ);
  259. },
  260. connect: function()
  261. {
  262. if (this.addresses.length <= this.currentAddr) {
  263. this.callback.onBytestreamFailure(this, this.token);
  264. return
  265. }
  266. var addr = this.addresses[this.currentAddr++];
  267. var transport = this.transport =
  268. this.socktranssrv.createTransport(null, 0, addr.host,
  269. addr.port, null);
  270. this.is = transport.openInputStream(0, 0, 0).
  271. QueryInterface(Components.interfaces.nsIAsyncInputStream);
  272. this.bis = Components.classes["@mozilla.org/binaryinputstream;1"].
  273. createInstance(Components.interfaces.nsIBinaryInputStream);
  274. this.bis.setInputStream(this.is);
  275. this.os = transport.openOutputStream(0, 0, 0).
  276. QueryInterface(Components.interfaces.nsIAsyncOutputStream);
  277. this.bos = Components.classes["@mozilla.org/binaryoutputstream;1"].
  278. createInstance(Components.interfaces.nsIBinaryOutputStream);
  279. this.bos.setOutputStream(this.os);
  280. this.data = [];
  281. this.os.asyncWait(this, 0, 3, this.eventQ);
  282. this.state = 0;
  283. },
  284. finish: function()
  285. {
  286. if (this.state == 12)
  287. return;
  288. this.ilen = 0;
  289. this.state = this.state > 9 ? 8 : 6;
  290. this.is.close();
  291. this.os.close();
  292. this.os.asyncWait(this, this.os.WAIT_CLOSURE_ONLY, 0, this.eventQ);
  293. this.is.asyncWait(this, this.is.WAIT_CLOSURE_ONLY, 0, this.eventQ);
  294. },
  295. onInputStreamReady: function(stream)
  296. {
  297. var len, available, data;
  298. try {
  299. if (this.state < 10 && this.ilen > 0) {
  300. available = this.is.available();
  301. len = this.ilen - this.data.length;
  302. if (available > len)
  303. available = len;
  304. this.data.push.apply(this.data, this.bis.readByteArray(available));
  305. if (len > available)
  306. return this.is.asyncWait(this, 0, len - available, this.eventQ);
  307. data = this.data;
  308. this.data = [];
  309. }
  310. switch (this.state) {
  311. case 1:
  312. if (data[0] != 0x5 || data[1] != 0)
  313. return this.finish();
  314. this.state = 2;
  315. this.os.asyncWait(this, 0, 47, this.eventQ);
  316. break;
  317. case 3:
  318. if (data[0] != 0x5 || data[1] != 0)
  319. return this.finish();
  320. if (data[3] == 0x1)
  321. this.ilen = 5;
  322. else if (data[3] == 0x3)
  323. this.ilen = data[4]+2;
  324. else if (data[3] == 0x4)
  325. this.ilen = 17;
  326. else
  327. return this.finish();
  328. this.state = 4;
  329. this.is.asyncWait(this, 0, this.ilen, this.eventQ);
  330. break;
  331. case 4:
  332. this.state = 5;
  333. this.ilen = 0;
  334. this.callback.onBytestreamReady(this, this.token);
  335. break;
  336. case 6:
  337. case 8:
  338. this.state++;
  339. break;
  340. case 7:
  341. this.connect();
  342. break;
  343. case 9:
  344. this.callback.onBytestreamComplete(this, this.token);
  345. break;
  346. case 11:
  347. data = this.bis.readBytes(this.is.available());
  348. this.file.write(data);
  349. this.is.asyncWait(this, 0, 512, this.eventQ);
  350. this.callback.onBytestreamProgress(this, this.token, data.length);
  351. break;
  352. }
  353. } catch (ex) {
  354. return this.finish();
  355. }
  356. return 0;
  357. },
  358. onOutputStreamReady: function(stream)
  359. {
  360. var len, data;
  361. try {
  362. switch (this.state) {
  363. case 0:
  364. this.state = 1;
  365. this.bos.writeByteArray([0x5, 0x1, 0x00], 3);
  366. this.is.asyncWait(this, 0, this.ilen = 2, this.eventQ);
  367. break;
  368. case 2:
  369. this.state = 3;
  370. var arr = [0x5, 0x1, 0x0, 0x03, 0x28];
  371. for (var i = 0; i < this.socksAddr.length; i++)
  372. arr.push(this.socksAddr.charCodeAt(i));
  373. arr.push(0, 0);
  374. this.bos.writeByteArray(arr, arr.length);
  375. /* this.bos.writeByteArray([0x5, 0x1, 0x00, 0x03, 0x28], 5);
  376. this.bos.writeBytes(this.socksAddr, 0x28);
  377. this.bos.write16(0);*/
  378. this.is.asyncWait(this, 0, this.ilen = 5, this.eventQ);
  379. break;
  380. case 6:
  381. case 8:
  382. this.state++;
  383. break;
  384. case 7:
  385. this.connect();
  386. break;
  387. case 9:
  388. this.callback.onBytestreamComplete(this, this.token);
  389. // this.finish();
  390. break;
  391. case 10:
  392. try {
  393. data = this.file.read(4096);
  394. if (!data.length) {
  395. this.finish();
  396. return;
  397. }
  398. this.bos.writeBytes(data, data.length);
  399. this.os.asyncWait(this, 0, 4096, this.eventQ);
  400. this.callback.onBytestreamProgress(this, this.token, data.length);
  401. } catch (ex) {
  402. this.finish()
  403. }
  404. }
  405. } catch (ex) {
  406. this.finish()
  407. }
  408. }
  409. }
  410. function SOCKSBytestreamInitiator(socksAddr, callback, token)
  411. {
  412. this.socksAddr = socksAddr;
  413. this.callback = callback;
  414. this.token = token;
  415. this.socket =
  416. Components.classes["@mozilla.org/network/server-socket;1"].
  417. createInstance(Components.interfaces.nsIServerSocket);
  418. this.eventQ = Components.classes["@mozilla.org/event-queue-service;1"] ?
  419. Components.classes["@mozilla.org/event-queue-service;1"].
  420. getService(Components.interfaces.nsIEventQueueService).
  421. getSpecialEventQueue(eqs.CURRENT_THREAD_EVENT_QUEUE) :
  422. Components.classes["@mozilla.org/thread-manager;1"].
  423. getService().mainThread;
  424. this.socket.init(-1, false, 1);
  425. this.socket.asyncListen(this);
  426. this.port = this.socket.port;
  427. }
  428. SOCKSBytestreamInitiator.prototype =
  429. {
  430. sendFile: function(file)
  431. {
  432. this.file = file;
  433. this.state = 10;
  434. this.os.asyncWait(this, 0, 512, this.eventQ);
  435. },
  436. recvFile: function(file)
  437. {
  438. this.file = file;
  439. this.state = 11;
  440. this.is.asyncWait(this, 0, 512, this.eventQ);
  441. },
  442. abort: function(file)
  443. {
  444. this.socket.close();
  445. if (this.is) {
  446. this.ilen = 0;
  447. this.state = 12;
  448. this.is.close();
  449. this.os.close();
  450. this.os.asyncWait(this, this.os.WAIT_CLOSURE_ONLY, 0, this.eventQ);
  451. this.is.asyncWait(this, this.is.WAIT_CLOSURE_ONLY, 0, this.eventQ);
  452. }
  453. },
  454. onSocketAccepted: function(socket, transport)
  455. {
  456. this.socket.close();
  457. if (this.is) {
  458. transport.close(Components.results.NS_OK);
  459. return;
  460. }
  461. this.is = transport.openInputStream(0, 0, 0).
  462. QueryInterface(Components.interfaces.nsIAsyncInputStream);
  463. this.bis = Components.classes["@mozilla.org/binaryinputstream;1"].
  464. createInstance(Components.interfaces.nsIBinaryInputStream);
  465. this.bis.setInputStream(this.is);
  466. this.os = transport.openOutputStream(0, 0, 0).
  467. QueryInterface(Components.interfaces.nsIAsyncOutputStream);
  468. this.bos = Components.classes["@mozilla.org/binaryoutputstream;1"].
  469. createInstance(Components.interfaces.nsIBinaryOutputStream);
  470. this.bos.setOutputStream(this.os);
  471. this.data = [];
  472. this.state = 0;
  473. this.is.asyncWait(this, 0, this.ilen = 2, this.eventQ);
  474. },
  475. onStopListening: function(socket, status)
  476. {
  477. },
  478. finish: function()
  479. {
  480. if (this.state == 12)
  481. return;
  482. this.ilen = 0;
  483. this.state = this.state > 9 ? 8 : 6;
  484. this.is.close()
  485. this.os.close()
  486. this.os.asyncWait(this, this.os.WAIT_CLOSURE_ONLY, 0, this.eventQ);
  487. this.is.asyncWait(this, this.is.WAIT_CLOSURE_ONLY, 0, this.eventQ);
  488. },
  489. onInputStreamReady: function(stream)
  490. {
  491. var len, available, data;
  492. try {
  493. if (this.state < 10 && this.ilen) {
  494. available = this.is.available();
  495. len = this.ilen - this.data.length;
  496. if (available > len)
  497. available = len;
  498. this.data.push.apply(this.data, this.bis.readByteArray(available));
  499. if (len > available)
  500. return this.is.asyncWait(this, 0, len - available, this.eventQ);
  501. data = this.data;
  502. this.data = [];
  503. }
  504. switch (this.state) {
  505. case 0:
  506. if (data[0] != 0x5)
  507. return this.finish();
  508. this.state = 1;
  509. this.is.asyncWait(this, 0, this.ilen = data[1], this.eventQ);
  510. break;
  511. case 1:
  512. this.state = 13;
  513. for (len = 0; len < this.ilen; len++)
  514. if (data[len] == 0)
  515. this.state = 1
  516. this.os.asyncWait(this, 0, 2, this.eventQ);
  517. break;
  518. case 2:
  519. if (data[0] != 0x5 || data[1] != 1 || data[3] != 3 || data[4] != 0x28)
  520. return this.finish();
  521. this.state = 3;
  522. this.is.asyncWait(this, 0, this.ilen = 42, this.eventQ);
  523. break;
  524. case 3:
  525. if ((data[40] != 0) || (data[41] != 0) ||
  526. (String.fromCharCode.apply(null,data.slice(0, 40))
  527. != this.socksAddr))
  528. return this.finish();
  529. this.state = 4;
  530. this.os.asyncWait(this, 0, 22, this.eventQ);
  531. break;
  532. case 6:
  533. case 8:
  534. this.state++;
  535. break;
  536. case 7:
  537. this.callback.onBytestreamFailure(this, this.token);
  538. // this.finish();
  539. break;
  540. case 9:
  541. this.callback.onBytestreamComplete(this, this.token);
  542. // this.finish();
  543. break;
  544. case 11:
  545. var data = this.bis.readBytes(this.is.available());
  546. this.file.write(data);
  547. this.is.asyncWait(this, 0, 4096, this.eventQ);
  548. this.callback.onBytestreamProgress(this, this.token, data.length);
  549. break;
  550. }
  551. } catch (ex) {
  552. return this.finish();
  553. }
  554. return 0;
  555. },
  556. onOutputStreamReady: function(stream)
  557. {
  558. var len, data;
  559. try {
  560. switch (this.state) {
  561. case 1:
  562. this.state = 2;
  563. this.bos.writeByteArray([0x5, 0x00], 2);
  564. this.is.asyncWait(this, 0, this.ilen = 5, this.eventQ);
  565. break;
  566. case 13:
  567. this.state = 1;
  568. this.bos.writeByteArray([0x5, 0xff], 2);
  569. this.finish();
  570. break;
  571. case 4:
  572. this.state = 5;
  573. var arr = [0x5, 0x0, 0x0, 0x03, 0x28];
  574. for (var i = 0; i < this.socksAddr.length; i++)
  575. arr.push(this.socksAddr.charCodeAt(i));
  576. arr.push(0, 0);
  577. this.bos.writeByteArray(arr, arr.length);
  578. /* this.bos.writeByteArray([0x5, 0x0, 0x0, 0x03, 0x28], 5);
  579. this.bos.writeBytes(this.socksAddr, 0x28);
  580. this.bos.write16(0);*/
  581. this.callback.onBytestreamReady(this, this.token);
  582. break;
  583. case 6:
  584. case 8:
  585. this.state++;
  586. break;
  587. case 7:
  588. this.callback.onBytestreamFailure(this, this.token);
  589. // this.finish();
  590. break;
  591. case 9:
  592. this.callback.onBytestreamComplete(this, this.token);
  593. // this.finish();
  594. break;
  595. case 10:
  596. try {
  597. data = this.file.read(4096);
  598. if (!data.length)
  599. return this.finish();
  600. this.bos.writeBytes(data, data.length);
  601. this.os.asyncWait(this, 0, 4096, this.eventQ);
  602. this.callback.onBytestreamProgress(this, this.token, data.length);
  603. } catch (ex) {
  604. this.finish()
  605. }
  606. }
  607. } catch (ex) {
  608. return this.finish();
  609. }
  610. return 0;
  611. }
  612. }
  613. var socks5Service = new SOCKS5Service();
  614. servicesManager.addIQService("http://jabber.org/protocol/bytestreams",
  615. new Callback(socks5Service.onIQ, socks5Service));