PromisedNetSockets.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import * as net from "./net";
  2. import { SocksClient } from "./socks";
  3. import { Mutex } from "async-mutex";
  4. import { ProxyInterface } from "../network/connection/TCPMTProxy";
  5. const mutex = new Mutex();
  6. const closeError = new Error("NetSocket was closed");
  7. export class PromisedNetSockets {
  8. private client?: net.Socket;
  9. private closed: boolean;
  10. private stream: Buffer;
  11. private canRead?: boolean | Promise<boolean>;
  12. private resolveRead: ((value?: any) => void) | undefined;
  13. private proxy?: ProxyInterface;
  14. constructor(proxy?: ProxyInterface) {
  15. this.client = undefined;
  16. this.closed = true;
  17. this.stream = Buffer.alloc(0);
  18. if (!proxy?.MTProxy) {
  19. // we only want to use this when it's not an MTProto proxy.
  20. if (proxy) {
  21. if (!proxy.ip || !proxy.port || !proxy.socksType) {
  22. throw new Error(
  23. `Invalid sockets params. ${proxy.ip}, ${proxy.port}, ${proxy.socksType}`
  24. );
  25. }
  26. }
  27. this.proxy = proxy;
  28. }
  29. }
  30. async readExactly(number: number) {
  31. let readData = Buffer.alloc(0);
  32. while (true) {
  33. const thisTime = await this.read(number);
  34. readData = Buffer.concat([readData, thisTime]);
  35. number = number - thisTime.length;
  36. if (!number) {
  37. return readData;
  38. }
  39. }
  40. }
  41. async read(number: number) {
  42. if (this.closed) {
  43. throw closeError;
  44. }
  45. await this.canRead;
  46. if (this.closed) {
  47. throw closeError;
  48. }
  49. const toReturn = this.stream.slice(0, number);
  50. this.stream = this.stream.slice(number);
  51. if (this.stream.length === 0) {
  52. this.canRead = new Promise((resolve) => {
  53. this.resolveRead = resolve;
  54. });
  55. }
  56. return toReturn;
  57. }
  58. async readAll() {
  59. if (this.closed || !(await this.canRead)) {
  60. throw closeError;
  61. }
  62. const toReturn = this.stream;
  63. this.stream = Buffer.alloc(0);
  64. this.canRead = new Promise((resolve) => {
  65. this.resolveRead = resolve;
  66. });
  67. return toReturn;
  68. }
  69. /**
  70. * Creates a new connection
  71. * @param port
  72. * @param ip
  73. * @returns {Promise<void>}
  74. */
  75. async connect(port: number, ip: string) {
  76. this.stream = Buffer.alloc(0);
  77. let connected = false;
  78. if (this.proxy) {
  79. const info = await SocksClient.createConnection({
  80. proxy: {
  81. host: this.proxy.ip,
  82. port: this.proxy.port,
  83. type:
  84. this.proxy.socksType != undefined
  85. ? this.proxy.socksType
  86. : 5, // Proxy version (4 or 5)
  87. userId: this.proxy.username,
  88. password: this.proxy.password,
  89. },
  90. command: "connect",
  91. timeout: (this.proxy.timeout || 5) * 1000,
  92. destination: {
  93. host: ip,
  94. port: port,
  95. },
  96. });
  97. this.client = info.socket;
  98. connected = true;
  99. } else {
  100. this.client = new net.Socket();
  101. }
  102. this.canRead = new Promise((resolve) => {
  103. this.resolveRead = resolve;
  104. });
  105. this.closed = false;
  106. return new Promise((resolve, reject) => {
  107. if (this.client) {
  108. if (connected) {
  109. this.receive();
  110. resolve(this);
  111. } else {
  112. this.client.connect(port, ip, () => {
  113. this.receive();
  114. resolve(this);
  115. });
  116. }
  117. this.client.on("error", reject);
  118. this.client.on("close", () => {
  119. if (this.client && this.client.destroyed) {
  120. if (this.resolveRead) {
  121. this.resolveRead(false);
  122. }
  123. this.closed = true;
  124. }
  125. });
  126. }
  127. });
  128. }
  129. write(data: Buffer) {
  130. if (this.closed) {
  131. throw closeError;
  132. }
  133. if (this.client) {
  134. this.client.write(data);
  135. }
  136. }
  137. async close() {
  138. if (this.client) {
  139. await this.client.destroy();
  140. this.client.unref();
  141. }
  142. this.closed = true;
  143. }
  144. async receive() {
  145. if (this.client) {
  146. this.client.on("data", async (message: Buffer) => {
  147. const release = await mutex.acquire();
  148. try {
  149. let data;
  150. //CONTEST BROWSER
  151. this.stream = Buffer.concat([this.stream, message]);
  152. if (this.resolveRead) {
  153. this.resolveRead(true);
  154. }
  155. } finally {
  156. release();
  157. }
  158. });
  159. }
  160. }
  161. toString() {
  162. return "PromisedNetSocket";
  163. }
  164. }