PromisedNetSockets.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import {Socket} from 'net';
  2. import {Mutex} from 'async-mutex';
  3. const mutex = new Mutex();
  4. const closeError = new Error('NetSocket was closed');
  5. export class PromisedNetSockets {
  6. private client?: Socket;
  7. private closed: boolean;
  8. private stream: Buffer;
  9. private canRead?: boolean | Promise<boolean>;
  10. private resolveRead: ((value?: any) => void) | undefined;
  11. constructor() {
  12. this.client = undefined;
  13. this.closed = true
  14. this.stream = Buffer.alloc(0);
  15. }
  16. async readExactly(number: number) {
  17. let readData = Buffer.alloc(0);
  18. while (true) {
  19. const thisTime = await this.read(number);
  20. readData = Buffer.concat([readData, thisTime]);
  21. number = number - thisTime.length;
  22. if (!number) {
  23. return readData
  24. }
  25. }
  26. }
  27. async read(number: number) {
  28. if (this.closed) {
  29. throw closeError
  30. }
  31. await this.canRead;
  32. if (this.closed) {
  33. throw closeError
  34. }
  35. const toReturn = this.stream.slice(0, number);
  36. this.stream = this.stream.slice(number);
  37. if (this.stream.length === 0) {
  38. this.canRead = new Promise(resolve => {
  39. this.resolveRead = resolve
  40. })
  41. }
  42. return toReturn
  43. }
  44. async readAll() {
  45. if (this.closed || !await this.canRead) {
  46. throw closeError
  47. }
  48. const toReturn = this.stream;
  49. this.stream = Buffer.alloc(0);
  50. this.canRead = new Promise(resolve => {
  51. this.resolveRead = resolve
  52. });
  53. return toReturn
  54. }
  55. /**
  56. * Creates a new connection
  57. * @param port
  58. * @param ip
  59. * @returns {Promise<void>}
  60. */
  61. async connect(port: number, ip: string) {
  62. this.stream = Buffer.alloc(0);
  63. this.client = new Socket();
  64. this.canRead = new Promise(resolve => {
  65. this.resolveRead = resolve
  66. });
  67. this.closed = false;
  68. return new Promise((resolve, reject) => {
  69. if (this.client) {
  70. this.client.connect(port, ip, () => {
  71. this.receive();
  72. resolve(this)
  73. });
  74. this.client.on('error', reject);
  75. this.client.on('close', () => {
  76. if (this.client && this.client.destroyed) {
  77. if (this.resolveRead) {
  78. this.resolveRead(false);
  79. }
  80. this.closed = true
  81. }
  82. })
  83. }
  84. })
  85. }
  86. write(data: Buffer) {
  87. if (this.closed) {
  88. throw closeError
  89. }
  90. if (this.client) {
  91. this.client.write(data)
  92. }
  93. }
  94. async close() {
  95. if (this.client) {
  96. await this.client.destroy();
  97. this.client.unref();
  98. }
  99. this.closed = true;
  100. }
  101. async receive() {
  102. if (this.client) {
  103. this.client.on('data', async message => {
  104. const release = await mutex.acquire();
  105. try {
  106. let data;
  107. //CONTEST BROWSER
  108. this.stream = Buffer.concat([this.stream, message]);
  109. if (this.resolveRead) {
  110. this.resolveRead(true)
  111. }
  112. } finally {
  113. release()
  114. }
  115. });
  116. }
  117. }
  118. }