@colyseus/uwebsockets-transport 0.16.0-preview.12 → 0.16.0-preview.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,19 +7,19 @@
7
7
  <a href="https://npmjs.com/package/colyseus">
8
8
  <img src="https://img.shields.io/npm/dm/colyseus.svg?style=for-the-badge&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAHdElNRQfjAgETESWYxR33AAAAtElEQVQoz4WQMQrCQBRE38Z0QoTcwF4Qg1h4BO0sxGOk80iCtViksrIQRRBTewWxMI1mbELYjYu+4rPMDPtn12ChMT3gavb4US5Jym0tcBIta3oDHv4Gwmr7nC4QAxBrCdzM2q6XqUnm9m9r59h7Rc0n2pFv24k4ttGMUXW+sGELTJjSr7QDKuqLS6UKFChVWWuFkZw9Z2AAvAirKT+JTlppIRnd6XgaP4goefI2Shj++OnjB3tBmHYK8z9zAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE5LTAyLTAxVDE4OjE3OjM3KzAxOjAwGQQixQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOS0wMi0wMVQxODoxNzozNyswMTowMGhZmnkAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC">
9
9
  </a>
10
- <a href="http://chat.colyseus.io">
11
- <img src="https://img.shields.io/discord/525739117951320081.svg?style=for-the-badge&colorB=7581dc&logo=discord&logoColor=white">
12
- </a>
13
10
  <a href="https://github.com/colyseus/colyseus/discussions" title="Discuss on Forum">
14
11
  <img src="https://img.shields.io/badge/discuss-on%20forum-brightgreen.svg?style=for-the-badge&colorB=0069b8&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAHdElNRQfjAgETDROxCNUzAAABB0lEQVQoz4WRvyvEARjGP193CnWRH+dHQmGwKZtFGcSmxHAL400GN95ktIpV2dzlLzDJgsGgGNRdDAzoQueS/PgY3HXHyT3T+/Y87/s89UANBKXBdoZo5J6L4K1K5ZxHfnjnlQUf3bKvkgy57a0r9hS3cXfMO1kWJMza++tj3Ac7/LY343x1NA9cNmYMwnSS/SP8JVFuSJmr44iFqvtmpjhmhBCrOOazCesq6H4P3bPBjFoIBydOk2bUA17I080Es+wSZ51B4DIA2zgjSpYcEe44Js01G0XjRcCU+y4ZMrDeLmfc9EnVd5M/o0VMeu6nJZxWJivLmhyw1WHTvrr2b4+2OFqra+ALwouTMDcqmjMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTktMDItMDFUMTg6MTM6MTkrMDE6MDAC9f6fAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE5LTAyLTAxVDE4OjEzOjE5KzAxOjAwc6hGIwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAASUVORK5CYII=" alt="Discussion forum" />
15
12
  </a>
13
+ <a href="http://chat.colyseus.io">
14
+ <img src="https://img.shields.io/discord/525739117951320081.svg?style=for-the-badge&colorB=7581dc&logo=discord&logoColor=white">
15
+ </a>
16
16
  <h3>
17
17
  Multiplayer Framework for Node.js. <br /><a href="https://docs.colyseus.io/">View documentation</a>
18
18
  </h3>
19
19
  </div>
20
20
 
21
- Colyseus is an Authoritative Multiplayer Framework for Node.js, with SDKs
22
- available for the Web, Unity, Defold, Haxe, Cocos and Construct3. ([See official SDKs](https://docs.colyseus.io/client/))
21
+ Colyseus is an Authoritative Multiplayer Framework for Node.js, with clients
22
+ available for the Web, Unity3d, Defold, Haxe, and Cocos. ([See official clients](#%EF%B8%8F-official-client-integration))
23
23
 
24
24
  The project focuses on providing synchronizable data structures for realtime and
25
25
  turn-based games, matchmaking, and ease of usage both on the server-side and
@@ -97,7 +97,7 @@ class uWebSocketClient {
97
97
  }
98
98
  error(code, message = "", cb) {
99
99
  this.raw(import_core.getMessageBytes[import_core.Protocol.ERROR](code, message));
100
- setTimeout(cb, 0);
100
+ setTimeout(cb, 1);
101
101
  }
102
102
  leave(code, data) {
103
103
  if (this.readyState !== 1 /* OPEN */) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/uWebSocketClient.ts"],
4
- "sourcesContent": ["import EventEmitter from 'events';\nimport uWebSockets from 'uWebSockets.js';\n\nimport { getMessageBytes, Protocol, Client, ClientPrivate, ClientState, ISendOptions, logger, debugMessage } from '@colyseus/core';\n\nexport class uWebSocketWrapper extends EventEmitter {\n constructor(public ws: uWebSockets.WebSocket<any>) {\n super();\n }\n}\n\nexport enum ReadyState {\n CONNECTING = 0,\n OPEN = 1,\n CLOSING = 2,\n CLOSED = 3,\n}\n\nexport class uWebSocketClient implements Client, ClientPrivate {\n public sessionId: string;\n public state: ClientState = ClientState.JOINING;\n public readyState: number = ReadyState.OPEN;\n public reconnectionToken: string;\n\n public _enqueuedMessages: any[] = [];\n public _afterNextPatchQueue;\n public _reconnectionToken: string;\n public _joinedAt: number;\n\n constructor(\n public id: string,\n public _ref: uWebSocketWrapper,\n ) {\n this.sessionId = id;\n\n _ref.on('close', () => this.readyState = ReadyState.CLOSED);\n }\n\n get ref() { return this._ref; }\n set ref(_ref: uWebSocketWrapper) {\n this._ref = _ref;\n this.readyState = ReadyState.OPEN;\n }\n\n public sendBytes(type: string | number, bytes: Buffer | Uint8Array, options?: ISendOptions) {\n debugMessage(\"send bytes(to %s): '%s' -> %j\", this.sessionId, type, bytes);\n\n this.enqueueRaw(\n getMessageBytes.raw(Protocol.ROOM_DATA_BYTES, type, undefined, bytes),\n options,\n );\n }\n\n public send(messageOrType: any, messageOrOptions?: any | ISendOptions, options?: ISendOptions) {\n debugMessage(\"send(to %s): '%s' -> %O\", this.sessionId, messageOrType, messageOrOptions);\n\n this.enqueueRaw(\n getMessageBytes.raw(Protocol.ROOM_DATA, messageOrType, messageOrOptions),\n options,\n );\n }\n\n public enqueueRaw(data: Uint8Array | Buffer, options?: ISendOptions) {\n // use room's afterNextPatch queue\n if (options?.afterNextPatch) {\n this._afterNextPatchQueue.push([this, [Buffer.from(data)]]);\n return;\n }\n\n if (this.state === ClientState.JOINING) {\n // sending messages during `onJoin`.\n // - the client-side cannot register \"onMessage\" callbacks at this point.\n // - enqueue the messages to be send after JOIN_ROOM message has been sent\n // - create a new buffer for enqueued messages, as the underlying buffer might be modified\n this._enqueuedMessages.push(Buffer.from(data));\n return;\n }\n\n this.raw(data, options);\n }\n\n public raw(data: Uint8Array | Buffer, options?: ISendOptions, cb?: (err?: Error) => void) {\n // skip if client not open\n if (this.readyState !== ReadyState.OPEN) {\n return;\n }\n\n this._ref.ws.send(data, true, false);\n }\n\n public error(code: number, message: string = '', cb?: (err?: Error) => void) {\n this.raw(getMessageBytes[Protocol.ERROR](code, message));\n // respond with callback after the message has been sent\n setTimeout(cb, 0);\n }\n\n public leave(code?: number, data?: string) {\n if (this.readyState !== ReadyState.OPEN) {\n // connection already closed. ignore.\n return;\n }\n\n this.readyState = ReadyState.CLOSING;\n\n if (code !== undefined) {\n this._ref.ws.end(code, data);\n\n } else {\n this._ref.ws.close();\n }\n }\n\n public close(code?: number, data?: string) {\n logger.warn('DEPRECATION WARNING: use client.leave() instead of client.close()');\n try {\n throw new Error();\n } catch (e) {\n logger.info(e.stack);\n }\n this.leave(code, data);\n }\n\n public toJSON() {\n return { sessionId: this.sessionId, readyState: this.readyState };\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAyB;AAGzB,kBAAkH;AAE3G,MAAM,0BAA0B,cAAAA,QAAa;AAAA,EAClD,YAAmB,IAAgC;AACjD,UAAM;AADW;AAAA,EAEnB;AACF;AAEO,IAAK,aAAL,kBAAKC,gBAAL;AACL,EAAAA,wBAAA,gBAAa,KAAb;AACA,EAAAA,wBAAA,UAAO,KAAP;AACA,EAAAA,wBAAA,aAAU,KAAV;AACA,EAAAA,wBAAA,YAAS,KAAT;AAJU,SAAAA;AAAA,GAAA;AAOL,MAAM,iBAAkD;AAAA,EAW7D,YACS,IACA,MACP;AAFO;AACA;AAXT,SAAO,QAAqB,wBAAY;AACxC,SAAO,aAAqB;AAG5B,SAAO,oBAA2B,CAAC;AASjC,SAAK,YAAY;AAEjB,SAAK,GAAG,SAAS,MAAM,KAAK,aAAa,cAAiB;AAAA,EAC5D;AAAA,EAEA,IAAI,MAAM;AAAE,WAAO,KAAK;AAAA,EAAM;AAAA,EAC9B,IAAI,IAAI,MAAyB;AAC/B,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AAAA,EAEO,UAAU,MAAuB,OAA4B,SAAwB;AAC1F,kCAAa,iCAAiC,KAAK,WAAW,MAAM,KAAK;AAEzE,SAAK;AAAA,MACH,4BAAgB,IAAI,qBAAS,iBAAiB,MAAM,QAAW,KAAK;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AAAA,EAEO,KAAK,eAAoB,kBAAuC,SAAwB;AAC7F,kCAAa,2BAA2B,KAAK,WAAW,eAAe,gBAAgB;AAEvF,SAAK;AAAA,MACH,4BAAgB,IAAI,qBAAS,WAAW,eAAe,gBAAgB;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA,EAEO,WAAW,MAA2B,SAAwB;AAEnE,QAAI,SAAS,gBAAgB;AAC3B,WAAK,qBAAqB,KAAK,CAAC,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC;AAC1D;AAAA,IACF;AAEA,QAAI,KAAK,UAAU,wBAAY,SAAS;AAKtC,WAAK,kBAAkB,KAAK,OAAO,KAAK,IAAI,CAAC;AAC7C;AAAA,IACF;AAEA,SAAK,IAAI,MAAM,OAAO;AAAA,EACxB;AAAA,EAEO,IAAI,MAA2B,SAAwB,IAA4B;AAExF,QAAI,KAAK,eAAe,cAAiB;AACvC;AAAA,IACF;AAEA,SAAK,KAAK,GAAG,KAAK,MAAM,MAAM,KAAK;AAAA,EACrC;AAAA,EAEO,MAAM,MAAc,UAAkB,IAAI,IAA4B;AAC3E,SAAK,IAAI,4BAAgB,qBAAS,KAAK,EAAE,MAAM,OAAO,CAAC;AAEvD,eAAW,IAAI,CAAC;AAAA,EAClB;AAAA,EAEO,MAAM,MAAe,MAAe;AACzC,QAAI,KAAK,eAAe,cAAiB;AAEvC;AAAA,IACF;AAEA,SAAK,aAAa;AAElB,QAAI,SAAS,QAAW;AACtB,WAAK,KAAK,GAAG,IAAI,MAAM,IAAI;AAAA,IAE7B,OAAO;AACL,WAAK,KAAK,GAAG,MAAM;AAAA,IACrB;AAAA,EACF;AAAA,EAEO,MAAM,MAAe,MAAe;AACzC,uBAAO,KAAK,mEAAmE;AAC/E,QAAI;AACF,YAAM,IAAI,MAAM;AAAA,IAClB,SAAS,GAAG;AACV,yBAAO,KAAK,EAAE,KAAK;AAAA,IACrB;AACA,SAAK,MAAM,MAAM,IAAI;AAAA,EACvB;AAAA,EAEO,SAAS;AACd,WAAO,EAAE,WAAW,KAAK,WAAW,YAAY,KAAK,WAAW;AAAA,EAClE;AACF;",
4
+ "sourcesContent": ["import EventEmitter from 'events';\nimport uWebSockets from 'uWebSockets.js';\n\nimport { getMessageBytes, Protocol, Client, ClientPrivate, ClientState, ISendOptions, logger, debugMessage } from '@colyseus/core';\n\nexport class uWebSocketWrapper extends EventEmitter {\n constructor(public ws: uWebSockets.WebSocket<any>) {\n super();\n }\n}\n\nexport enum ReadyState {\n CONNECTING = 0,\n OPEN = 1,\n CLOSING = 2,\n CLOSED = 3,\n}\n\nexport class uWebSocketClient implements Client, ClientPrivate {\n public sessionId: string;\n public state: ClientState = ClientState.JOINING;\n public readyState: number = ReadyState.OPEN;\n public reconnectionToken: string;\n\n public _enqueuedMessages: any[] = [];\n public _afterNextPatchQueue;\n public _reconnectionToken: string;\n public _joinedAt: number;\n\n constructor(\n public id: string,\n public _ref: uWebSocketWrapper,\n ) {\n this.sessionId = id;\n\n _ref.on('close', () => this.readyState = ReadyState.CLOSED);\n }\n\n get ref() { return this._ref; }\n set ref(_ref: uWebSocketWrapper) {\n this._ref = _ref;\n this.readyState = ReadyState.OPEN;\n }\n\n public sendBytes(type: string | number, bytes: Buffer | Uint8Array, options?: ISendOptions) {\n debugMessage(\"send bytes(to %s): '%s' -> %j\", this.sessionId, type, bytes);\n\n this.enqueueRaw(\n getMessageBytes.raw(Protocol.ROOM_DATA_BYTES, type, undefined, bytes),\n options,\n );\n }\n\n public send(messageOrType: any, messageOrOptions?: any | ISendOptions, options?: ISendOptions) {\n debugMessage(\"send(to %s): '%s' -> %O\", this.sessionId, messageOrType, messageOrOptions);\n\n this.enqueueRaw(\n getMessageBytes.raw(Protocol.ROOM_DATA, messageOrType, messageOrOptions),\n options,\n );\n }\n\n public enqueueRaw(data: Uint8Array | Buffer, options?: ISendOptions) {\n // use room's afterNextPatch queue\n if (options?.afterNextPatch) {\n this._afterNextPatchQueue.push([this, [Buffer.from(data)]]);\n return;\n }\n\n if (this.state === ClientState.JOINING) {\n // sending messages during `onJoin`.\n // - the client-side cannot register \"onMessage\" callbacks at this point.\n // - enqueue the messages to be send after JOIN_ROOM message has been sent\n // - create a new buffer for enqueued messages, as the underlying buffer might be modified\n this._enqueuedMessages.push(Buffer.from(data));\n return;\n }\n\n this.raw(data, options);\n }\n\n public raw(data: Uint8Array | Buffer, options?: ISendOptions, cb?: (err?: Error) => void) {\n // skip if client not open\n if (this.readyState !== ReadyState.OPEN) {\n return;\n }\n\n this._ref.ws.send(data, true, false);\n }\n\n public error(code: number, message: string = '', cb?: (err?: Error) => void) {\n this.raw(getMessageBytes[Protocol.ERROR](code, message));\n\n // delay callback execution - uWS doesn't acknowledge when the message was sent\n // (same API as \"ws\" transport)\n setTimeout(cb, 1);\n }\n\n public leave(code?: number, data?: string) {\n if (this.readyState !== ReadyState.OPEN) {\n // connection already closed. ignore.\n return;\n }\n\n this.readyState = ReadyState.CLOSING;\n\n if (code !== undefined) {\n this._ref.ws.end(code, data);\n\n } else {\n this._ref.ws.close();\n }\n }\n\n public close(code?: number, data?: string) {\n logger.warn('DEPRECATION WARNING: use client.leave() instead of client.close()');\n try {\n throw new Error();\n } catch (e) {\n logger.info(e.stack);\n }\n this.leave(code, data);\n }\n\n public toJSON() {\n return { sessionId: this.sessionId, readyState: this.readyState };\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAyB;AAGzB,kBAAkH;AAE3G,MAAM,0BAA0B,cAAAA,QAAa;AAAA,EAClD,YAAmB,IAAgC;AACjD,UAAM;AADW;AAAA,EAEnB;AACF;AAEO,IAAK,aAAL,kBAAKC,gBAAL;AACL,EAAAA,wBAAA,gBAAa,KAAb;AACA,EAAAA,wBAAA,UAAO,KAAP;AACA,EAAAA,wBAAA,aAAU,KAAV;AACA,EAAAA,wBAAA,YAAS,KAAT;AAJU,SAAAA;AAAA,GAAA;AAOL,MAAM,iBAAkD;AAAA,EAW7D,YACS,IACA,MACP;AAFO;AACA;AAXT,SAAO,QAAqB,wBAAY;AACxC,SAAO,aAAqB;AAG5B,SAAO,oBAA2B,CAAC;AASjC,SAAK,YAAY;AAEjB,SAAK,GAAG,SAAS,MAAM,KAAK,aAAa,cAAiB;AAAA,EAC5D;AAAA,EAEA,IAAI,MAAM;AAAE,WAAO,KAAK;AAAA,EAAM;AAAA,EAC9B,IAAI,IAAI,MAAyB;AAC/B,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AAAA,EAEO,UAAU,MAAuB,OAA4B,SAAwB;AAC1F,kCAAa,iCAAiC,KAAK,WAAW,MAAM,KAAK;AAEzE,SAAK;AAAA,MACH,4BAAgB,IAAI,qBAAS,iBAAiB,MAAM,QAAW,KAAK;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AAAA,EAEO,KAAK,eAAoB,kBAAuC,SAAwB;AAC7F,kCAAa,2BAA2B,KAAK,WAAW,eAAe,gBAAgB;AAEvF,SAAK;AAAA,MACH,4BAAgB,IAAI,qBAAS,WAAW,eAAe,gBAAgB;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA,EAEO,WAAW,MAA2B,SAAwB;AAEnE,QAAI,SAAS,gBAAgB;AAC3B,WAAK,qBAAqB,KAAK,CAAC,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC;AAC1D;AAAA,IACF;AAEA,QAAI,KAAK,UAAU,wBAAY,SAAS;AAKtC,WAAK,kBAAkB,KAAK,OAAO,KAAK,IAAI,CAAC;AAC7C;AAAA,IACF;AAEA,SAAK,IAAI,MAAM,OAAO;AAAA,EACxB;AAAA,EAEO,IAAI,MAA2B,SAAwB,IAA4B;AAExF,QAAI,KAAK,eAAe,cAAiB;AACvC;AAAA,IACF;AAEA,SAAK,KAAK,GAAG,KAAK,MAAM,MAAM,KAAK;AAAA,EACrC;AAAA,EAEO,MAAM,MAAc,UAAkB,IAAI,IAA4B;AAC3E,SAAK,IAAI,4BAAgB,qBAAS,KAAK,EAAE,MAAM,OAAO,CAAC;AAIvD,eAAW,IAAI,CAAC;AAAA,EAClB;AAAA,EAEO,MAAM,MAAe,MAAe;AACzC,QAAI,KAAK,eAAe,cAAiB;AAEvC;AAAA,IACF;AAEA,SAAK,aAAa;AAElB,QAAI,SAAS,QAAW;AACtB,WAAK,KAAK,GAAG,IAAI,MAAM,IAAI;AAAA,IAE7B,OAAO;AACL,WAAK,KAAK,GAAG,MAAM;AAAA,IACrB;AAAA,EACF;AAAA,EAEO,MAAM,MAAe,MAAe;AACzC,uBAAO,KAAK,mEAAmE;AAC/E,QAAI;AACF,YAAM,IAAI,MAAM;AAAA,IAClB,SAAS,GAAG;AACV,yBAAO,KAAK,EAAE,KAAK;AAAA,IACrB;AACA,SAAK,MAAM,MAAM,IAAI;AAAA,EACvB;AAAA,EAEO,SAAS;AACd,WAAO,EAAE,WAAW,KAAK,WAAW,YAAY,KAAK,WAAW;AAAA,EAClE;AACF;",
6
6
  "names": ["EventEmitter", "ReadyState"]
7
7
  }
@@ -64,7 +64,7 @@ var uWebSocketClient = class {
64
64
  }
65
65
  error(code, message = "", cb) {
66
66
  this.raw(getMessageBytes[Protocol.ERROR](code, message));
67
- setTimeout(cb, 0);
67
+ setTimeout(cb, 1);
68
68
  }
69
69
  leave(code, data) {
70
70
  if (this.readyState !== 1 /* OPEN */) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/uWebSocketClient.ts"],
4
- "sourcesContent": ["import EventEmitter from 'events';\nimport uWebSockets from 'uWebSockets.js';\n\nimport { getMessageBytes, Protocol, Client, ClientPrivate, ClientState, ISendOptions, logger, debugMessage } from '@colyseus/core';\n\nexport class uWebSocketWrapper extends EventEmitter {\n constructor(public ws: uWebSockets.WebSocket<any>) {\n super();\n }\n}\n\nexport enum ReadyState {\n CONNECTING = 0,\n OPEN = 1,\n CLOSING = 2,\n CLOSED = 3,\n}\n\nexport class uWebSocketClient implements Client, ClientPrivate {\n public sessionId: string;\n public state: ClientState = ClientState.JOINING;\n public readyState: number = ReadyState.OPEN;\n public reconnectionToken: string;\n\n public _enqueuedMessages: any[] = [];\n public _afterNextPatchQueue;\n public _reconnectionToken: string;\n public _joinedAt: number;\n\n constructor(\n public id: string,\n public _ref: uWebSocketWrapper,\n ) {\n this.sessionId = id;\n\n _ref.on('close', () => this.readyState = ReadyState.CLOSED);\n }\n\n get ref() { return this._ref; }\n set ref(_ref: uWebSocketWrapper) {\n this._ref = _ref;\n this.readyState = ReadyState.OPEN;\n }\n\n public sendBytes(type: string | number, bytes: Buffer | Uint8Array, options?: ISendOptions) {\n debugMessage(\"send bytes(to %s): '%s' -> %j\", this.sessionId, type, bytes);\n\n this.enqueueRaw(\n getMessageBytes.raw(Protocol.ROOM_DATA_BYTES, type, undefined, bytes),\n options,\n );\n }\n\n public send(messageOrType: any, messageOrOptions?: any | ISendOptions, options?: ISendOptions) {\n debugMessage(\"send(to %s): '%s' -> %O\", this.sessionId, messageOrType, messageOrOptions);\n\n this.enqueueRaw(\n getMessageBytes.raw(Protocol.ROOM_DATA, messageOrType, messageOrOptions),\n options,\n );\n }\n\n public enqueueRaw(data: Uint8Array | Buffer, options?: ISendOptions) {\n // use room's afterNextPatch queue\n if (options?.afterNextPatch) {\n this._afterNextPatchQueue.push([this, [Buffer.from(data)]]);\n return;\n }\n\n if (this.state === ClientState.JOINING) {\n // sending messages during `onJoin`.\n // - the client-side cannot register \"onMessage\" callbacks at this point.\n // - enqueue the messages to be send after JOIN_ROOM message has been sent\n // - create a new buffer for enqueued messages, as the underlying buffer might be modified\n this._enqueuedMessages.push(Buffer.from(data));\n return;\n }\n\n this.raw(data, options);\n }\n\n public raw(data: Uint8Array | Buffer, options?: ISendOptions, cb?: (err?: Error) => void) {\n // skip if client not open\n if (this.readyState !== ReadyState.OPEN) {\n return;\n }\n\n this._ref.ws.send(data, true, false);\n }\n\n public error(code: number, message: string = '', cb?: (err?: Error) => void) {\n this.raw(getMessageBytes[Protocol.ERROR](code, message));\n // respond with callback after the message has been sent\n setTimeout(cb, 0);\n }\n\n public leave(code?: number, data?: string) {\n if (this.readyState !== ReadyState.OPEN) {\n // connection already closed. ignore.\n return;\n }\n\n this.readyState = ReadyState.CLOSING;\n\n if (code !== undefined) {\n this._ref.ws.end(code, data);\n\n } else {\n this._ref.ws.close();\n }\n }\n\n public close(code?: number, data?: string) {\n logger.warn('DEPRECATION WARNING: use client.leave() instead of client.close()');\n try {\n throw new Error();\n } catch (e) {\n logger.info(e.stack);\n }\n this.leave(code, data);\n }\n\n public toJSON() {\n return { sessionId: this.sessionId, readyState: this.readyState };\n }\n}\n"],
5
- "mappings": ";AAAA,OAAO,kBAAkB;AAGzB,SAAS,iBAAiB,UAAiC,aAA2B,QAAQ,oBAAoB;AAE3G,IAAM,oBAAN,cAAgC,aAAa;AAAA,EAClD,YAAmB,IAAgC;AACjD,UAAM;AADW;AAAA,EAEnB;AACF;AAEO,IAAK,aAAL,kBAAKA,gBAAL;AACL,EAAAA,wBAAA,gBAAa,KAAb;AACA,EAAAA,wBAAA,UAAO,KAAP;AACA,EAAAA,wBAAA,aAAU,KAAV;AACA,EAAAA,wBAAA,YAAS,KAAT;AAJU,SAAAA;AAAA,GAAA;AAOL,IAAM,mBAAN,MAAwD;AAAA,EAW7D,YACS,IACA,MACP;AAFO;AACA;AAXT,SAAO,QAAqB,YAAY;AACxC,SAAO,aAAqB;AAG5B,SAAO,oBAA2B,CAAC;AASjC,SAAK,YAAY;AAEjB,SAAK,GAAG,SAAS,MAAM,KAAK,aAAa,cAAiB;AAAA,EAC5D;AAAA,EAEA,IAAI,MAAM;AAAE,WAAO,KAAK;AAAA,EAAM;AAAA,EAC9B,IAAI,IAAI,MAAyB;AAC/B,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AAAA,EAEO,UAAU,MAAuB,OAA4B,SAAwB;AAC1F,iBAAa,iCAAiC,KAAK,WAAW,MAAM,KAAK;AAEzE,SAAK;AAAA,MACH,gBAAgB,IAAI,SAAS,iBAAiB,MAAM,QAAW,KAAK;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AAAA,EAEO,KAAK,eAAoB,kBAAuC,SAAwB;AAC7F,iBAAa,2BAA2B,KAAK,WAAW,eAAe,gBAAgB;AAEvF,SAAK;AAAA,MACH,gBAAgB,IAAI,SAAS,WAAW,eAAe,gBAAgB;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA,EAEO,WAAW,MAA2B,SAAwB;AAEnE,QAAI,SAAS,gBAAgB;AAC3B,WAAK,qBAAqB,KAAK,CAAC,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC;AAC1D;AAAA,IACF;AAEA,QAAI,KAAK,UAAU,YAAY,SAAS;AAKtC,WAAK,kBAAkB,KAAK,OAAO,KAAK,IAAI,CAAC;AAC7C;AAAA,IACF;AAEA,SAAK,IAAI,MAAM,OAAO;AAAA,EACxB;AAAA,EAEO,IAAI,MAA2B,SAAwB,IAA4B;AAExF,QAAI,KAAK,eAAe,cAAiB;AACvC;AAAA,IACF;AAEA,SAAK,KAAK,GAAG,KAAK,MAAM,MAAM,KAAK;AAAA,EACrC;AAAA,EAEO,MAAM,MAAc,UAAkB,IAAI,IAA4B;AAC3E,SAAK,IAAI,gBAAgB,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC;AAEvD,eAAW,IAAI,CAAC;AAAA,EAClB;AAAA,EAEO,MAAM,MAAe,MAAe;AACzC,QAAI,KAAK,eAAe,cAAiB;AAEvC;AAAA,IACF;AAEA,SAAK,aAAa;AAElB,QAAI,SAAS,QAAW;AACtB,WAAK,KAAK,GAAG,IAAI,MAAM,IAAI;AAAA,IAE7B,OAAO;AACL,WAAK,KAAK,GAAG,MAAM;AAAA,IACrB;AAAA,EACF;AAAA,EAEO,MAAM,MAAe,MAAe;AACzC,WAAO,KAAK,mEAAmE;AAC/E,QAAI;AACF,YAAM,IAAI,MAAM;AAAA,IAClB,SAAS,GAAG;AACV,aAAO,KAAK,EAAE,KAAK;AAAA,IACrB;AACA,SAAK,MAAM,MAAM,IAAI;AAAA,EACvB;AAAA,EAEO,SAAS;AACd,WAAO,EAAE,WAAW,KAAK,WAAW,YAAY,KAAK,WAAW;AAAA,EAClE;AACF;",
4
+ "sourcesContent": ["import EventEmitter from 'events';\nimport uWebSockets from 'uWebSockets.js';\n\nimport { getMessageBytes, Protocol, Client, ClientPrivate, ClientState, ISendOptions, logger, debugMessage } from '@colyseus/core';\n\nexport class uWebSocketWrapper extends EventEmitter {\n constructor(public ws: uWebSockets.WebSocket<any>) {\n super();\n }\n}\n\nexport enum ReadyState {\n CONNECTING = 0,\n OPEN = 1,\n CLOSING = 2,\n CLOSED = 3,\n}\n\nexport class uWebSocketClient implements Client, ClientPrivate {\n public sessionId: string;\n public state: ClientState = ClientState.JOINING;\n public readyState: number = ReadyState.OPEN;\n public reconnectionToken: string;\n\n public _enqueuedMessages: any[] = [];\n public _afterNextPatchQueue;\n public _reconnectionToken: string;\n public _joinedAt: number;\n\n constructor(\n public id: string,\n public _ref: uWebSocketWrapper,\n ) {\n this.sessionId = id;\n\n _ref.on('close', () => this.readyState = ReadyState.CLOSED);\n }\n\n get ref() { return this._ref; }\n set ref(_ref: uWebSocketWrapper) {\n this._ref = _ref;\n this.readyState = ReadyState.OPEN;\n }\n\n public sendBytes(type: string | number, bytes: Buffer | Uint8Array, options?: ISendOptions) {\n debugMessage(\"send bytes(to %s): '%s' -> %j\", this.sessionId, type, bytes);\n\n this.enqueueRaw(\n getMessageBytes.raw(Protocol.ROOM_DATA_BYTES, type, undefined, bytes),\n options,\n );\n }\n\n public send(messageOrType: any, messageOrOptions?: any | ISendOptions, options?: ISendOptions) {\n debugMessage(\"send(to %s): '%s' -> %O\", this.sessionId, messageOrType, messageOrOptions);\n\n this.enqueueRaw(\n getMessageBytes.raw(Protocol.ROOM_DATA, messageOrType, messageOrOptions),\n options,\n );\n }\n\n public enqueueRaw(data: Uint8Array | Buffer, options?: ISendOptions) {\n // use room's afterNextPatch queue\n if (options?.afterNextPatch) {\n this._afterNextPatchQueue.push([this, [Buffer.from(data)]]);\n return;\n }\n\n if (this.state === ClientState.JOINING) {\n // sending messages during `onJoin`.\n // - the client-side cannot register \"onMessage\" callbacks at this point.\n // - enqueue the messages to be send after JOIN_ROOM message has been sent\n // - create a new buffer for enqueued messages, as the underlying buffer might be modified\n this._enqueuedMessages.push(Buffer.from(data));\n return;\n }\n\n this.raw(data, options);\n }\n\n public raw(data: Uint8Array | Buffer, options?: ISendOptions, cb?: (err?: Error) => void) {\n // skip if client not open\n if (this.readyState !== ReadyState.OPEN) {\n return;\n }\n\n this._ref.ws.send(data, true, false);\n }\n\n public error(code: number, message: string = '', cb?: (err?: Error) => void) {\n this.raw(getMessageBytes[Protocol.ERROR](code, message));\n\n // delay callback execution - uWS doesn't acknowledge when the message was sent\n // (same API as \"ws\" transport)\n setTimeout(cb, 1);\n }\n\n public leave(code?: number, data?: string) {\n if (this.readyState !== ReadyState.OPEN) {\n // connection already closed. ignore.\n return;\n }\n\n this.readyState = ReadyState.CLOSING;\n\n if (code !== undefined) {\n this._ref.ws.end(code, data);\n\n } else {\n this._ref.ws.close();\n }\n }\n\n public close(code?: number, data?: string) {\n logger.warn('DEPRECATION WARNING: use client.leave() instead of client.close()');\n try {\n throw new Error();\n } catch (e) {\n logger.info(e.stack);\n }\n this.leave(code, data);\n }\n\n public toJSON() {\n return { sessionId: this.sessionId, readyState: this.readyState };\n }\n}\n"],
5
+ "mappings": ";AAAA,OAAO,kBAAkB;AAGzB,SAAS,iBAAiB,UAAiC,aAA2B,QAAQ,oBAAoB;AAE3G,IAAM,oBAAN,cAAgC,aAAa;AAAA,EAClD,YAAmB,IAAgC;AACjD,UAAM;AADW;AAAA,EAEnB;AACF;AAEO,IAAK,aAAL,kBAAKA,gBAAL;AACL,EAAAA,wBAAA,gBAAa,KAAb;AACA,EAAAA,wBAAA,UAAO,KAAP;AACA,EAAAA,wBAAA,aAAU,KAAV;AACA,EAAAA,wBAAA,YAAS,KAAT;AAJU,SAAAA;AAAA,GAAA;AAOL,IAAM,mBAAN,MAAwD;AAAA,EAW7D,YACS,IACA,MACP;AAFO;AACA;AAXT,SAAO,QAAqB,YAAY;AACxC,SAAO,aAAqB;AAG5B,SAAO,oBAA2B,CAAC;AASjC,SAAK,YAAY;AAEjB,SAAK,GAAG,SAAS,MAAM,KAAK,aAAa,cAAiB;AAAA,EAC5D;AAAA,EAEA,IAAI,MAAM;AAAE,WAAO,KAAK;AAAA,EAAM;AAAA,EAC9B,IAAI,IAAI,MAAyB;AAC/B,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AAAA,EAEO,UAAU,MAAuB,OAA4B,SAAwB;AAC1F,iBAAa,iCAAiC,KAAK,WAAW,MAAM,KAAK;AAEzE,SAAK;AAAA,MACH,gBAAgB,IAAI,SAAS,iBAAiB,MAAM,QAAW,KAAK;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AAAA,EAEO,KAAK,eAAoB,kBAAuC,SAAwB;AAC7F,iBAAa,2BAA2B,KAAK,WAAW,eAAe,gBAAgB;AAEvF,SAAK;AAAA,MACH,gBAAgB,IAAI,SAAS,WAAW,eAAe,gBAAgB;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA,EAEO,WAAW,MAA2B,SAAwB;AAEnE,QAAI,SAAS,gBAAgB;AAC3B,WAAK,qBAAqB,KAAK,CAAC,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC;AAC1D;AAAA,IACF;AAEA,QAAI,KAAK,UAAU,YAAY,SAAS;AAKtC,WAAK,kBAAkB,KAAK,OAAO,KAAK,IAAI,CAAC;AAC7C;AAAA,IACF;AAEA,SAAK,IAAI,MAAM,OAAO;AAAA,EACxB;AAAA,EAEO,IAAI,MAA2B,SAAwB,IAA4B;AAExF,QAAI,KAAK,eAAe,cAAiB;AACvC;AAAA,IACF;AAEA,SAAK,KAAK,GAAG,KAAK,MAAM,MAAM,KAAK;AAAA,EACrC;AAAA,EAEO,MAAM,MAAc,UAAkB,IAAI,IAA4B;AAC3E,SAAK,IAAI,gBAAgB,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC;AAIvD,eAAW,IAAI,CAAC;AAAA,EAClB;AAAA,EAEO,MAAM,MAAe,MAAe;AACzC,QAAI,KAAK,eAAe,cAAiB;AAEvC;AAAA,IACF;AAEA,SAAK,aAAa;AAElB,QAAI,SAAS,QAAW;AACtB,WAAK,KAAK,GAAG,IAAI,MAAM,IAAI;AAAA,IAE7B,OAAO;AACL,WAAK,KAAK,GAAG,MAAM;AAAA,IACrB;AAAA,EACF;AAAA,EAEO,MAAM,MAAe,MAAe;AACzC,WAAO,KAAK,mEAAmE;AAC/E,QAAI;AACF,YAAM,IAAI,MAAM;AAAA,IAClB,SAAS,GAAG;AACV,aAAO,KAAK,EAAE,KAAK;AAAA,IACrB;AACA,SAAK,MAAM,MAAM,IAAI;AAAA,EACvB;AAAA,EAEO,SAAS;AACd,WAAO,EAAE,WAAW,KAAK,WAAW,YAAY,KAAK,WAAW;AAAA,EAClE;AACF;",
6
6
  "names": ["ReadyState"]
7
7
  }
@@ -1,17 +1,12 @@
1
1
  import uWebSockets from 'uWebSockets.js';
2
2
  import { Application } from "uwebsockets-express";
3
- import { Transport } from '@colyseus/core';
3
+ import { AuthContext, Transport } from '@colyseus/core';
4
4
  import { uWebSocketWrapper } from './uWebSocketClient.js';
5
5
  export type TransportOptions = Omit<uWebSockets.WebSocketBehavior<any>, "upgrade" | "open" | "pong" | "close" | "message">;
6
6
  type RawWebSocketClient = uWebSockets.WebSocket<any> & {
7
7
  url: string;
8
8
  query: string;
9
- headers: {
10
- [key: string]: string;
11
- };
12
- connection: {
13
- remoteAddress: string;
14
- };
9
+ context: AuthContext;
15
10
  };
16
11
  export declare class uWebSocketsTransport extends Transport {
17
12
  app: uWebSockets.TemplatedApp;
@@ -67,10 +67,10 @@ class uWebSocketsTransport extends import_core.Transport {
67
67
  {
68
68
  url: req.getUrl(),
69
69
  query: req.getQuery(),
70
- // compatibility with @colyseus/ws-transport
71
- headers,
72
- connection: {
73
- remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString()
70
+ context: {
71
+ token: (0, import_core.getBearerToken)(req.getHeader("authorization")),
72
+ headers,
73
+ ip: Buffer.from(res.getRemoteAddressAsText()).toString()
74
74
  }
75
75
  },
76
76
  req.getHeader("sec-websocket-key"),
@@ -145,10 +145,10 @@ class uWebSocketsTransport extends import_core.Transport {
145
145
  if (!room || !room.hasReservedSeat(sessionId, searchParams.reconnectionToken)) {
146
146
  throw new Error("seat reservation expired.");
147
147
  }
148
- await room._onJoin(client, rawClient);
148
+ await room._onJoin(client, rawClient.context);
149
149
  } catch (e) {
150
150
  (0, import_core.debugAndPrintError)(e);
151
- client.error(e.code, e.message, () => rawClient.close());
151
+ client.error(e.code, e.message, () => client.leave());
152
152
  }
153
153
  }
154
154
  registerMatchMakeRequest() {
@@ -172,8 +172,10 @@ class uWebSocketsTransport extends import_core.Transport {
172
172
  if (res.aborted) {
173
173
  return;
174
174
  }
175
- res.writeStatus("406 Not Acceptable");
176
- res.end(JSON.stringify(error));
175
+ res.cork(() => {
176
+ res.writeStatus("406 Not Acceptable");
177
+ res.end(JSON.stringify(error));
178
+ });
177
179
  };
178
180
  const onAborted = (res) => {
179
181
  res.aborted = true;
@@ -195,7 +197,6 @@ class uWebSocketsTransport extends import_core.Transport {
195
197
  const url = req.getUrl();
196
198
  const matchedParams = url.match(allowedRoomNameChars);
197
199
  const matchmakeIndex = matchedParams.indexOf(matchmakeRoute);
198
- const authToken = (0, import_core.getBearerToken)(req.getHeader("authorization"));
199
200
  const headers = {};
200
201
  req.forEach((key, value) => headers[key] = value);
201
202
  this.readJson(res, async (clientOptions) => {
@@ -209,11 +210,17 @@ class uWebSocketsTransport extends import_core.Transport {
209
210
  method,
210
211
  roomName,
211
212
  clientOptions,
212
- { token: authToken, request: { headers } }
213
+ {
214
+ token: (0, import_core.getBearerToken)(req.getHeader("authorization")),
215
+ headers,
216
+ ip: headers["x-real-ip"] ?? Buffer.from(res.getRemoteAddressAsText()).toString()
217
+ }
213
218
  );
214
219
  if (!res.aborted) {
215
- res.writeStatus("200 OK");
216
- res.end(JSON.stringify(response));
220
+ res.cork(() => {
221
+ res.writeStatus("200 OK");
222
+ res.end(JSON.stringify(response));
223
+ });
217
224
  }
218
225
  } catch (e) {
219
226
  (0, import_core.debugAndPrintError)(e);
@@ -234,8 +241,10 @@ class uWebSocketsTransport extends import_core.Transport {
234
241
  try {
235
242
  const response = await import_core.matchMaker.controller.getAvailableRooms(roomName || "");
236
243
  if (!res.aborted) {
237
- res.writeStatus("200 OK");
238
- res.end(JSON.stringify(response));
244
+ res.cork(() => {
245
+ res.writeStatus("200 OK");
246
+ res.end(JSON.stringify(response));
247
+ });
239
248
  }
240
249
  } catch (e) {
241
250
  (0, import_core.debugAndPrintError)(e);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/uWebSocketsTransport.ts"],
4
- "sourcesContent": ["import http from 'http';\nimport querystring from 'querystring';\nimport uWebSockets from 'uWebSockets.js';\nimport expressify, { Application } from \"uwebsockets-express\";\n\nimport { HttpServerMock, ErrorCode, matchMaker, getBearerToken, Transport, debugAndPrintError, spliceOne } from '@colyseus/core';\nimport { uWebSocketClient, uWebSocketWrapper } from './uWebSocketClient.js';\n\nexport type TransportOptions = Omit<uWebSockets.WebSocketBehavior<any>, \"upgrade\" | \"open\" | \"pong\" | \"close\" | \"message\">;\n\ntype RawWebSocketClient = uWebSockets.WebSocket<any> & {\n url: string,\n query: string,\n headers: {[key: string]: string},\n connection: { remoteAddress: string },\n};\n\nexport class uWebSocketsTransport extends Transport {\n public app: uWebSockets.TemplatedApp;\n public expressApp: Application;\n\n protected clients: RawWebSocketClient[] = [];\n protected clientWrappers = new WeakMap<RawWebSocketClient, uWebSocketWrapper>();\n\n private _listeningSocket: any;\n private _originalRawSend: typeof uWebSocketClient.prototype.raw | null = null;\n\n constructor(options: TransportOptions = {}, appOptions: uWebSockets.AppOptions = {}) {\n super();\n\n this.app = (appOptions.cert_file_name && appOptions.key_file_name)\n ? uWebSockets.SSLApp(appOptions)\n : uWebSockets.App(appOptions);\n\n this.expressApp = expressify(this.app);\n\n if (options.maxBackpressure === undefined) {\n options.maxBackpressure = 1024 * 1024;\n }\n\n if (options.compression === undefined) {\n options.compression = uWebSockets.DISABLED;\n }\n\n if (options.maxPayloadLength === undefined) {\n options.maxPayloadLength = 4 * 1024;\n }\n\n if (options.sendPingsAutomatically === undefined) {\n options.sendPingsAutomatically = true;\n }\n\n // https://github.com/colyseus/colyseus/issues/458\n // Adding a mock object for Transport.server\n if(!this.server) {\n // @ts-ignore\n this.server = new HttpServerMock();\n }\n\n this.app.ws('/*', {\n ...options,\n\n upgrade: (res, req, context) => {\n // get all headers\n const headers: {[id: string]: string} = {};\n req.forEach((key, value) => headers[key] = value);\n\n /* This immediately calls open handler, you must not use res after this call */\n /* Spell these correctly */\n res.upgrade(\n {\n url: req.getUrl(),\n query: req.getQuery(),\n\n // compatibility with @colyseus/ws-transport\n headers,\n connection: {\n remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString()\n }\n },\n req.getHeader('sec-websocket-key'),\n req.getHeader('sec-websocket-protocol'),\n req.getHeader('sec-websocket-extensions'),\n context\n );\n },\n\n open: async (ws: RawWebSocketClient) => {\n // ws.pingCount = 0;\n await this.onConnection(ws);\n },\n\n // pong: (ws: RawWebSocketClient) => {\n // ws.pingCount = 0;\n // },\n\n close: (ws: RawWebSocketClient, code: number, message: ArrayBuffer) => {\n // remove from client list\n spliceOne(this.clients, this.clients.indexOf(ws));\n\n const clientWrapper = this.clientWrappers.get(ws);\n if (clientWrapper) {\n this.clientWrappers.delete(ws);\n\n // emit 'close' on wrapper\n clientWrapper.emit('close', code);\n }\n },\n\n message: (ws: RawWebSocketClient, message: ArrayBuffer, isBinary: boolean) => {\n // emit 'message' on wrapper\n this.clientWrappers.get(ws)?.emit('message', Buffer.from(message));\n },\n\n });\n\n this.registerMatchMakeRequest();\n }\n\n public listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void) {\n const callback = (listeningSocket: any) => {\n this._listeningSocket = listeningSocket;\n listeningListener?.();\n // @ts-ignore\n this.server.emit(\"listening\"); // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n };\n\n if (typeof(port) === \"string\") {\n // @ts-ignore\n this.app.listen_unix(callback, port);\n\n } else {\n this.app.listen(port, callback);\n\n }\n return this;\n }\n\n public shutdown() {\n if (this._listeningSocket) {\n uWebSockets.us_listen_socket_close(this._listeningSocket);\n // @ts-ignore\n this.server.emit(\"close\"); // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n }\n }\n\n public simulateLatency(milliseconds: number) {\n if (this._originalRawSend == null) {\n this._originalRawSend = uWebSocketClient.prototype.raw;\n }\n\n const originalRawSend = this._originalRawSend;\n uWebSocketClient.prototype.raw = milliseconds <= Number.EPSILON ? originalRawSend : function (...args: any[]) {\n // copy buffer\n let [buf, ...rest] = args;\n buf = Array.from(buf);\n setTimeout(() => originalRawSend.apply(this, [buf, ...rest]), milliseconds);\n };\n }\n\n protected async onConnection(rawClient: RawWebSocketClient) {\n const wrapper = new uWebSocketWrapper(rawClient);\n // keep reference to client and its wrapper\n this.clients.push(rawClient);\n this.clientWrappers.set(rawClient, wrapper);\n\n const query = rawClient.query;\n const url = rawClient.url;\n const searchParams = querystring.parse(query);\n\n const sessionId = searchParams.sessionId as string;\n const processAndRoomId = url.match(/\\/[a-zA-Z0-9_\\-]+\\/([a-zA-Z0-9_\\-]+)$/);\n const roomId = processAndRoomId && processAndRoomId[1];\n\n const room = matchMaker.getLocalRoomById(roomId);\n const client = new uWebSocketClient(sessionId, wrapper);\n\n //\n // TODO: DRY code below with all transports\n //\n\n try {\n if (!room || !room.hasReservedSeat(sessionId, searchParams.reconnectionToken as string)) {\n throw new Error('seat reservation expired.');\n }\n\n await room._onJoin(client, rawClient as unknown as http.IncomingMessage);\n\n } catch (e) {\n debugAndPrintError(e);\n\n // send error code to client then terminate\n client.error(e.code, e.message, () => rawClient.close());\n }\n }\n\n protected registerMatchMakeRequest() {\n\n // TODO: DRY with Server.ts\n const matchmakeRoute = 'matchmake';\n const allowedRoomNameChars = /([a-zA-Z_\\-0-9]+)/gi;\n\n const writeHeaders = (req: uWebSockets.HttpRequest, res: uWebSockets.HttpResponse) => {\n // skip if aborted\n if (res.aborted) { return; }\n\n const headers = Object.assign(\n {},\n matchMaker.controller.DEFAULT_CORS_HEADERS,\n matchMaker.controller.getCorsHeaders.call(undefined, req)\n );\n\n for (const header in headers) {\n res.writeHeader(header, headers[header].toString());\n }\n\n return true;\n }\n\n const writeError = (res: uWebSockets.HttpResponse, error: { code: number, error: string }) => {\n // skip if aborted\n if (res.aborted) { return; }\n\n res.writeStatus(\"406 Not Acceptable\");\n res.end(JSON.stringify(error));\n }\n\n const onAborted = (res: uWebSockets.HttpResponse) => {\n res.aborted = true;\n };\n\n this.app.options(\"/matchmake/*\", (res, req) => {\n res.onAborted(() => onAborted(res));\n\n if (writeHeaders(req, res)) {\n res.writeStatus(\"204 No Content\");\n res.end();\n }\n });\n\n\n // @ts-ignore\n this.app.post(\"/matchmake/*\", (res, req) => {\n res.onAborted(() => onAborted(res));\n\n // do not accept matchmaking requests if already shutting down\n if (matchMaker.state === matchMaker.MatchMakerState.SHUTTING_DOWN) {\n return res.close();\n }\n\n writeHeaders(req, res);\n res.writeHeader('Content-Type', 'application/json');\n\n const url = req.getUrl();\n const matchedParams = url.match(allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(matchmakeRoute);\n const authToken = getBearerToken(req.getHeader('authorization'));\n\n // cache all headers\n const headers = {};\n req.forEach((key, value) => headers[key] = value);\n\n // read json body\n this.readJson(res, async (clientOptions) => {\n try {\n if (clientOptions === undefined) {\n throw new Error(\"invalid JSON input\");\n }\n\n const method = matchedParams[matchmakeIndex + 1];\n const roomName = matchedParams[matchmakeIndex + 2] || '';\n\n const response = await matchMaker.controller.invokeMethod(\n method,\n roomName,\n clientOptions,\n { token: authToken, request: { headers } }\n );\n\n if (!res.aborted) {\n res.writeStatus(\"200 OK\");\n res.end(JSON.stringify(response));\n }\n\n } catch (e) {\n debugAndPrintError(e);\n writeError(res, {\n code: e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n error: e.message\n });\n }\n\n });\n });\n\n // this.app.any(\"/*\", (res, req) => {\n // res.onAborted(() => onAborted(req));\n // res.writeStatus(\"200 OK\");\n // });\n\n this.app.get(\"/matchmake/*\", async (res, req) => {\n res.onAborted(() => onAborted(res));\n\n writeHeaders(req, res);\n res.writeHeader('Content-Type', 'application/json');\n\n const url = req.getUrl();\n const matchedParams = url.match(allowedRoomNameChars);\n const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : \"\";\n\n try {\n const response = await matchMaker.controller.getAvailableRooms(roomName || '')\n if (!res.aborted) {\n res.writeStatus(\"200 OK\");\n res.end(JSON.stringify(response));\n }\n\n } catch (e) {\n debugAndPrintError(e);\n writeError(res, {\n code: e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n error: e.message\n });\n }\n });\n }\n\n /* Helper function for reading a posted JSON body */\n /* Extracted from https://github.com/uNetworking/uWebSockets.js/blob/master/examples/JsonPost.js */\n private readJson(res: uWebSockets.HttpResponse, cb: (json: any) => void) {\n let buffer: any;\n /* Register data cb */\n res.onData((ab, isLast) => {\n let chunk = Buffer.from(ab);\n if (isLast) {\n let json;\n if (buffer) {\n try {\n // @ts-ignore\n json = JSON.parse(Buffer.concat([buffer, chunk]));\n } catch (e) {\n /* res.close calls onAborted */\n // res.close();\n cb(undefined);\n return;\n }\n cb(json);\n } else {\n try {\n // @ts-ignore\n json = JSON.parse(chunk);\n } catch (e) {\n /* res.close calls onAborted */\n // res.close();\n cb(undefined);\n return;\n }\n cb(json);\n }\n } else {\n if (buffer) {\n buffer = Buffer.concat([buffer, chunk]);\n } else {\n buffer = Buffer.concat([chunk]);\n }\n }\n });\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import http, { IncomingHttpHeaders } from 'http';\nimport querystring from 'querystring';\nimport uWebSockets from 'uWebSockets.js';\nimport expressify, { Application } from \"uwebsockets-express\";\n\nimport { AuthContext, HttpServerMock, ErrorCode, matchMaker, getBearerToken, Transport, debugAndPrintError, spliceOne } from '@colyseus/core';\nimport { uWebSocketClient, uWebSocketWrapper } from './uWebSocketClient.js';\n\nexport type TransportOptions = Omit<uWebSockets.WebSocketBehavior<any>, \"upgrade\" | \"open\" | \"pong\" | \"close\" | \"message\">;\n\ntype RawWebSocketClient = uWebSockets.WebSocket<any> & {\n url: string,\n query: string,\n context: AuthContext,\n};\n\nexport class uWebSocketsTransport extends Transport {\n public app: uWebSockets.TemplatedApp;\n public expressApp: Application;\n\n protected clients: RawWebSocketClient[] = [];\n protected clientWrappers = new WeakMap<RawWebSocketClient, uWebSocketWrapper>();\n\n private _listeningSocket: any;\n private _originalRawSend: typeof uWebSocketClient.prototype.raw | null = null;\n\n constructor(options: TransportOptions = {}, appOptions: uWebSockets.AppOptions = {}) {\n super();\n\n this.app = (appOptions.cert_file_name && appOptions.key_file_name)\n ? uWebSockets.SSLApp(appOptions)\n : uWebSockets.App(appOptions);\n\n this.expressApp = expressify(this.app);\n\n if (options.maxBackpressure === undefined) {\n options.maxBackpressure = 1024 * 1024;\n }\n\n if (options.compression === undefined) {\n options.compression = uWebSockets.DISABLED;\n }\n\n if (options.maxPayloadLength === undefined) {\n options.maxPayloadLength = 4 * 1024;\n }\n\n if (options.sendPingsAutomatically === undefined) {\n options.sendPingsAutomatically = true;\n }\n\n // https://github.com/colyseus/colyseus/issues/458\n // Adding a mock object for Transport.server\n if(!this.server) {\n // @ts-ignore\n this.server = new HttpServerMock();\n }\n\n this.app.ws('/*', {\n ...options,\n\n upgrade: (res, req, context) => {\n // get all headers\n const headers: {[id: string]: string} = {};\n req.forEach((key, value) => headers[key] = value);\n\n /* This immediately calls open handler, you must not use res after this call */\n /* Spell these correctly */\n res.upgrade(\n {\n url: req.getUrl(),\n query: req.getQuery(),\n context: {\n token: getBearerToken(req.getHeader('authorization')),\n headers,\n ip: Buffer.from(res.getRemoteAddressAsText()).toString(),\n }\n },\n req.getHeader('sec-websocket-key'),\n req.getHeader('sec-websocket-protocol'),\n req.getHeader('sec-websocket-extensions'),\n context\n );\n },\n\n open: async (ws: RawWebSocketClient) => {\n // ws.pingCount = 0;\n await this.onConnection(ws);\n },\n\n // pong: (ws: RawWebSocketClient) => {\n // ws.pingCount = 0;\n // },\n\n close: (ws: RawWebSocketClient, code: number, message: ArrayBuffer) => {\n // remove from client list\n spliceOne(this.clients, this.clients.indexOf(ws));\n\n const clientWrapper = this.clientWrappers.get(ws);\n if (clientWrapper) {\n this.clientWrappers.delete(ws);\n\n // emit 'close' on wrapper\n clientWrapper.emit('close', code);\n }\n },\n\n message: (ws: RawWebSocketClient, message: ArrayBuffer, isBinary: boolean) => {\n // emit 'message' on wrapper\n this.clientWrappers.get(ws)?.emit('message', Buffer.from(message));\n },\n\n });\n\n this.registerMatchMakeRequest();\n }\n\n public listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void) {\n const callback = (listeningSocket: any) => {\n this._listeningSocket = listeningSocket;\n listeningListener?.();\n // @ts-ignore\n this.server.emit(\"listening\"); // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n };\n\n if (typeof(port) === \"string\") {\n // @ts-ignore\n this.app.listen_unix(callback, port);\n\n } else {\n this.app.listen(port, callback);\n\n }\n return this;\n }\n\n public shutdown() {\n if (this._listeningSocket) {\n uWebSockets.us_listen_socket_close(this._listeningSocket);\n // @ts-ignore\n this.server.emit(\"close\"); // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n }\n }\n\n public simulateLatency(milliseconds: number) {\n if (this._originalRawSend == null) {\n this._originalRawSend = uWebSocketClient.prototype.raw;\n }\n\n const originalRawSend = this._originalRawSend;\n uWebSocketClient.prototype.raw = milliseconds <= Number.EPSILON ? originalRawSend : function (...args: any[]) {\n // copy buffer\n let [buf, ...rest] = args;\n buf = Array.from(buf);\n setTimeout(() => originalRawSend.apply(this, [buf, ...rest]), milliseconds);\n };\n }\n\n protected async onConnection(rawClient: RawWebSocketClient) {\n const wrapper = new uWebSocketWrapper(rawClient);\n // keep reference to client and its wrapper\n this.clients.push(rawClient);\n this.clientWrappers.set(rawClient, wrapper);\n\n const query = rawClient.query;\n const url = rawClient.url;\n const searchParams = querystring.parse(query);\n\n const sessionId = searchParams.sessionId as string;\n const processAndRoomId = url.match(/\\/[a-zA-Z0-9_\\-]+\\/([a-zA-Z0-9_\\-]+)$/);\n const roomId = processAndRoomId && processAndRoomId[1];\n\n const room = matchMaker.getLocalRoomById(roomId);\n const client = new uWebSocketClient(sessionId, wrapper);\n\n //\n // TODO: DRY code below with all transports\n //\n\n try {\n if (!room || !room.hasReservedSeat(sessionId, searchParams.reconnectionToken as string)) {\n throw new Error('seat reservation expired.');\n }\n\n await room._onJoin(client, rawClient.context);\n\n } catch (e) {\n debugAndPrintError(e);\n\n // send error code to client then terminate\n client.error(e.code, e.message, () => client.leave());\n }\n }\n\n protected registerMatchMakeRequest() {\n\n // TODO: DRY with Server.ts\n const matchmakeRoute = 'matchmake';\n const allowedRoomNameChars = /([a-zA-Z_\\-0-9]+)/gi;\n\n const writeHeaders = (req: uWebSockets.HttpRequest, res: uWebSockets.HttpResponse) => {\n // skip if aborted\n if (res.aborted) { return; }\n\n const headers = Object.assign(\n {},\n matchMaker.controller.DEFAULT_CORS_HEADERS,\n matchMaker.controller.getCorsHeaders.call(undefined, req)\n );\n\n for (const header in headers) {\n res.writeHeader(header, headers[header].toString());\n }\n\n return true;\n }\n\n const writeError = (res: uWebSockets.HttpResponse, error: { code: number, error: string }) => {\n // skip if aborted\n if (res.aborted) { return; }\n\n res.cork(() => {\n res.writeStatus(\"406 Not Acceptable\");\n res.end(JSON.stringify(error));\n });\n }\n\n const onAborted = (res: uWebSockets.HttpResponse) => {\n res.aborted = true;\n };\n\n this.app.options(\"/matchmake/*\", (res, req) => {\n res.onAborted(() => onAborted(res));\n\n if (writeHeaders(req, res)) {\n res.writeStatus(\"204 No Content\");\n res.end();\n }\n });\n\n\n // @ts-ignore\n this.app.post(\"/matchmake/*\", (res, req) => {\n res.onAborted(() => onAborted(res));\n\n // do not accept matchmaking requests if already shutting down\n if (matchMaker.state === matchMaker.MatchMakerState.SHUTTING_DOWN) {\n return res.close();\n }\n\n writeHeaders(req, res);\n res.writeHeader('Content-Type', 'application/json');\n\n const url = req.getUrl();\n const matchedParams = url.match(allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(matchmakeRoute);\n\n // cache all headers\n const headers: IncomingHttpHeaders = {};\n req.forEach((key, value) => headers[key] = value);\n\n // read json body\n this.readJson(res, async (clientOptions) => {\n try {\n if (clientOptions === undefined) {\n throw new Error(\"invalid JSON input\");\n }\n\n const method = matchedParams[matchmakeIndex + 1];\n const roomName = matchedParams[matchmakeIndex + 2] || '';\n\n const response = await matchMaker.controller.invokeMethod(\n method,\n roomName,\n clientOptions,\n {\n token: getBearerToken(req.getHeader('authorization')),\n headers,\n ip: headers['x-real-ip'] ?? Buffer.from(res.getRemoteAddressAsText()).toString()\n }\n );\n\n if (!res.aborted) {\n res.cork(() => {\n res.writeStatus(\"200 OK\");\n res.end(JSON.stringify(response));\n });\n }\n\n } catch (e) {\n debugAndPrintError(e);\n writeError(res, {\n code: e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n error: e.message\n });\n }\n\n });\n });\n\n // this.app.any(\"/*\", (res, req) => {\n // res.onAborted(() => onAborted(req));\n // res.writeStatus(\"200 OK\");\n // });\n\n this.app.get(\"/matchmake/*\", async (res, req) => {\n res.onAborted(() => onAborted(res));\n\n writeHeaders(req, res);\n res.writeHeader('Content-Type', 'application/json');\n\n const url = req.getUrl();\n const matchedParams = url.match(allowedRoomNameChars);\n const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : \"\";\n\n try {\n const response = await matchMaker.controller.getAvailableRooms(roomName || '')\n if (!res.aborted) {\n res.cork(() => {\n res.writeStatus(\"200 OK\");\n res.end(JSON.stringify(response));\n });\n }\n\n } catch (e) {\n debugAndPrintError(e);\n writeError(res, {\n code: e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n error: e.message\n });\n }\n });\n }\n\n /* Helper function for reading a posted JSON body */\n /* Extracted from https://github.com/uNetworking/uWebSockets.js/blob/master/examples/JsonPost.js */\n private readJson(res: uWebSockets.HttpResponse, cb: (json: any) => void) {\n let buffer: any;\n /* Register data cb */\n res.onData((ab, isLast) => {\n let chunk = Buffer.from(ab);\n if (isLast) {\n let json;\n if (buffer) {\n try {\n // @ts-ignore\n json = JSON.parse(Buffer.concat([buffer, chunk]));\n } catch (e) {\n /* res.close calls onAborted */\n // res.close();\n cb(undefined);\n return;\n }\n cb(json);\n } else {\n try {\n // @ts-ignore\n json = JSON.parse(chunk);\n } catch (e) {\n /* res.close calls onAborted */\n // res.close();\n cb(undefined);\n return;\n }\n cb(json);\n }\n } else {\n if (buffer) {\n buffer = Buffer.concat([buffer, chunk]);\n } else {\n buffer = Buffer.concat([chunk]);\n }\n }\n });\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,yBAAwB;AACxB,yBAAwB;AACxB,iCAAwC;AAExC,kBAA6H;AAC7H,8BAAoD;AAU7C,MAAM,6BAA6B,sBAAU;AAAA,EAUhD,YAAY,UAA4B,CAAC,GAAG,aAAqC,CAAC,GAAG;AACjF,UAAM;AAPV,SAAU,UAAgC,CAAC;AAC3C,SAAU,iBAAiB,oBAAI,QAA+C;AAG9E,SAAQ,mBAAiE;AAKrE,SAAK,MAAO,WAAW,kBAAkB,WAAW,gBAC9C,mBAAAA,QAAY,OAAO,UAAU,IAC7B,mBAAAA,QAAY,IAAI,UAAU;AAEhC,SAAK,iBAAa,2BAAAC,SAAW,KAAK,GAAG;AAErC,QAAI,QAAQ,oBAAoB,QAAW;AACvC,cAAQ,kBAAkB,OAAO;AAAA,IACrC;AAEA,QAAI,QAAQ,gBAAgB,QAAW;AACnC,cAAQ,cAAc,mBAAAD,QAAY;AAAA,IACtC;AAEA,QAAI,QAAQ,qBAAqB,QAAW;AACxC,cAAQ,mBAAmB,IAAI;AAAA,IACnC;AAEA,QAAI,QAAQ,2BAA2B,QAAW;AAC9C,cAAQ,yBAAyB;AAAA,IACrC;AAIA,QAAG,CAAC,KAAK,QAAQ;AAEf,WAAK,SAAS,IAAI,2BAAe;AAAA,IACnC;AAEA,SAAK,IAAI,GAAG,MAAM;AAAA,MACd,GAAG;AAAA,MAEH,SAAS,CAAC,KAAK,KAAK,YAAY;AAE5B,cAAM,UAAkC,CAAC;AACzC,YAAI,QAAQ,CAAC,KAAK,UAAU,QAAQ,GAAG,IAAI,KAAK;AAIhD,YAAI;AAAA,UACA;AAAA,YACI,KAAK,IAAI,OAAO;AAAA,YAChB,OAAO,IAAI,SAAS;AAAA,YACpB,SAAS;AAAA,cACP,WAAO,4BAAe,IAAI,UAAU,eAAe,CAAC;AAAA,cACpD;AAAA,cACA,IAAI,OAAO,KAAK,IAAI,uBAAuB,CAAC,EAAE,SAAS;AAAA,YACzD;AAAA,UACJ;AAAA,UACA,IAAI,UAAU,mBAAmB;AAAA,UACjC,IAAI,UAAU,wBAAwB;AAAA,UACtC,IAAI,UAAU,0BAA0B;AAAA,UACxC;AAAA,QACJ;AAAA,MACJ;AAAA,MAEA,MAAM,OAAO,OAA2B;AAEpC,cAAM,KAAK,aAAa,EAAE;AAAA,MAC9B;AAAA;AAAA;AAAA;AAAA,MAMA,OAAO,CAAC,IAAwB,MAAc,YAAyB;AAEnE,mCAAU,KAAK,SAAS,KAAK,QAAQ,QAAQ,EAAE,CAAC;AAEhD,cAAM,gBAAgB,KAAK,eAAe,IAAI,EAAE;AAChD,YAAI,eAAe;AACjB,eAAK,eAAe,OAAO,EAAE;AAG7B,wBAAc,KAAK,SAAS,IAAI;AAAA,QAClC;AAAA,MACJ;AAAA,MAEA,SAAS,CAAC,IAAwB,SAAsB,aAAsB;AAE1E,aAAK,eAAe,IAAI,EAAE,GAAG,KAAK,WAAW,OAAO,KAAK,OAAO,CAAC;AAAA,MACrE;AAAA,IAEJ,CAAC;AAED,SAAK,yBAAyB;AAAA,EAClC;AAAA,EAEO,OAAO,MAAc,UAAmB,SAAkB,mBAAgC;AAC7F,UAAM,WAAW,CAAC,oBAAyB;AACzC,WAAK,mBAAmB;AACxB,0BAAoB;AAEpB,WAAK,OAAO,KAAK,WAAW;AAAA,IAC9B;AAEA,QAAI,OAAO,SAAU,UAAU;AAE3B,WAAK,IAAI,YAAY,UAAU,IAAI;AAAA,IAEvC,OAAO;AACH,WAAK,IAAI,OAAO,MAAM,QAAQ;AAAA,IAElC;AACA,WAAO;AAAA,EACX;AAAA,EAEO,WAAW;AACd,QAAI,KAAK,kBAAkB;AACzB,yBAAAA,QAAY,uBAAuB,KAAK,gBAAgB;AAExD,WAAK,OAAO,KAAK,OAAO;AAAA,IAC1B;AAAA,EACJ;AAAA,EAEO,gBAAgB,cAAsB;AACzC,QAAI,KAAK,oBAAoB,MAAM;AAC/B,WAAK,mBAAmB,yCAAiB,UAAU;AAAA,IACvD;AAEA,UAAM,kBAAkB,KAAK;AAC7B,6CAAiB,UAAU,MAAM,gBAAgB,OAAO,UAAU,kBAAkB,YAAa,MAAa;AAE1G,UAAI,CAAC,KAAK,GAAG,IAAI,IAAI;AACrB,YAAM,MAAM,KAAK,GAAG;AACpB,iBAAW,MAAM,gBAAgB,MAAM,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,YAAY;AAAA,IAC9E;AAAA,EACJ;AAAA,EAEA,MAAgB,aAAa,WAA+B;AACxD,UAAM,UAAU,IAAI,0CAAkB,SAAS;AAE/C,SAAK,QAAQ,KAAK,SAAS;AAC3B,SAAK,eAAe,IAAI,WAAW,OAAO;AAE1C,UAAM,QAAQ,UAAU;AACxB,UAAM,MAAM,UAAU;AACtB,UAAM,eAAe,mBAAAE,QAAY,MAAM,KAAK;AAE5C,UAAM,YAAY,aAAa;AAC/B,UAAM,mBAAmB,IAAI,MAAM,uCAAuC;AAC1E,UAAM,SAAS,oBAAoB,iBAAiB,CAAC;AAErD,UAAM,OAAO,uBAAW,iBAAiB,MAAM;AAC/C,UAAM,SAAS,IAAI,yCAAiB,WAAW,OAAO;AAMtD,QAAI;AACA,UAAI,CAAC,QAAQ,CAAC,KAAK,gBAAgB,WAAW,aAAa,iBAA2B,GAAG;AACrF,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC/C;AAEA,YAAM,KAAK,QAAQ,QAAQ,UAAU,OAAO;AAAA,IAEhD,SAAS,GAAG;AACR,0CAAmB,CAAC;AAGpB,aAAO,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,OAAO,MAAM,CAAC;AAAA,IACxD;AAAA,EACJ;AAAA,EAEU,2BAA2B;AAGjC,UAAM,iBAAiB;AACvB,UAAM,uBAAuB;AAE7B,UAAM,eAAe,CAAC,KAA8B,QAAkC;AAElF,UAAI,IAAI,SAAS;AAAE;AAAA,MAAQ;AAE3B,YAAM,UAAU,OAAO;AAAA,QACnB,CAAC;AAAA,QACD,uBAAW,WAAW;AAAA,QACtB,uBAAW,WAAW,eAAe,KAAK,QAAW,GAAG;AAAA,MAC5D;AAEA,iBAAW,UAAU,SAAS;AAC1B,YAAI,YAAY,QAAQ,QAAQ,MAAM,EAAE,SAAS,CAAC;AAAA,MACtD;AAEA,aAAO;AAAA,IACX;AAEA,UAAM,aAAa,CAAC,KAA+B,UAA2C;AAE1F,UAAI,IAAI,SAAS;AAAE;AAAA,MAAQ;AAE3B,UAAI,KAAK,MAAM;AACb,YAAI,YAAY,oBAAoB;AACpC,YAAI,IAAI,KAAK,UAAU,KAAK,CAAC;AAAA,MAC/B,CAAC;AAAA,IACL;AAEA,UAAM,YAAY,CAAC,QAAkC;AACnD,UAAI,UAAU;AAAA,IAChB;AAEA,SAAK,IAAI,QAAQ,gBAAgB,CAAC,KAAK,QAAQ;AAC3C,UAAI,UAAU,MAAM,UAAU,GAAG,CAAC;AAElC,UAAI,aAAa,KAAK,GAAG,GAAG;AAC1B,YAAI,YAAY,gBAAgB;AAChC,YAAI,IAAI;AAAA,MACV;AAAA,IACJ,CAAC;AAID,SAAK,IAAI,KAAK,gBAAgB,CAAC,KAAK,QAAQ;AACxC,UAAI,UAAU,MAAM,UAAU,GAAG,CAAC;AAGlC,UAAI,uBAAW,UAAU,uBAAW,gBAAgB,eAAe;AACjE,eAAO,IAAI,MAAM;AAAA,MACnB;AAEA,mBAAa,KAAK,GAAG;AACrB,UAAI,YAAY,gBAAgB,kBAAkB;AAElD,YAAM,MAAM,IAAI,OAAO;AACvB,YAAM,gBAAgB,IAAI,MAAM,oBAAoB;AACpD,YAAM,iBAAiB,cAAc,QAAQ,cAAc;AAG3D,YAAM,UAA+B,CAAC;AACtC,UAAI,QAAQ,CAAC,KAAK,UAAU,QAAQ,GAAG,IAAI,KAAK;AAGhD,WAAK,SAAS,KAAK,OAAO,kBAAkB;AACxC,YAAI;AACA,cAAI,kBAAkB,QAAW;AAC/B,kBAAM,IAAI,MAAM,oBAAoB;AAAA,UACtC;AAEA,gBAAM,SAAS,cAAc,iBAAiB,CAAC;AAC/C,gBAAM,WAAW,cAAc,iBAAiB,CAAC,KAAK;AAEtD,gBAAM,WAAW,MAAM,uBAAW,WAAW;AAAA,YAC3C;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,cACE,WAAO,4BAAe,IAAI,UAAU,eAAe,CAAC;AAAA,cACpD;AAAA,cACA,IAAI,QAAQ,WAAW,KAAK,OAAO,KAAK,IAAI,uBAAuB,CAAC,EAAE,SAAS;AAAA,YACjF;AAAA,UACF;AAEA,cAAI,CAAC,IAAI,SAAS;AAChB,gBAAI,KAAK,MAAM;AACb,kBAAI,YAAY,QAAQ;AACxB,kBAAI,IAAI,KAAK,UAAU,QAAQ,CAAC;AAAA,YAClC,CAAC;AAAA,UACH;AAAA,QAEJ,SAAS,GAAG;AACR,8CAAmB,CAAC;AACpB,qBAAW,KAAK;AAAA,YACZ,MAAM,EAAE,QAAQ,sBAAU;AAAA,YAC1B,OAAO,EAAE;AAAA,UACb,CAAC;AAAA,QACL;AAAA,MAEJ,CAAC;AAAA,IACL,CAAC;AAOD,SAAK,IAAI,IAAI,gBAAgB,OAAO,KAAK,QAAQ;AAC7C,UAAI,UAAU,MAAM,UAAU,GAAG,CAAC;AAElC,mBAAa,KAAK,GAAG;AACrB,UAAI,YAAY,gBAAgB,kBAAkB;AAElD,YAAM,MAAM,IAAI,OAAO;AACvB,YAAM,gBAAgB,IAAI,MAAM,oBAAoB;AACpD,YAAM,WAAW,cAAc,SAAS,IAAI,cAAc,cAAc,SAAS,CAAC,IAAI;AAEtF,UAAI;AACA,cAAM,WAAW,MAAM,uBAAW,WAAW,kBAAkB,YAAY,EAAE;AAC7E,YAAI,CAAC,IAAI,SAAS;AAChB,cAAI,KAAK,MAAM;AACb,gBAAI,YAAY,QAAQ;AACxB,gBAAI,IAAI,KAAK,UAAU,QAAQ,CAAC;AAAA,UAClC,CAAC;AAAA,QACH;AAAA,MAEJ,SAAS,GAAG;AACR,4CAAmB,CAAC;AACpB,mBAAW,KAAK;AAAA,UACZ,MAAM,EAAE,QAAQ,sBAAU;AAAA,UAC1B,OAAO,EAAE;AAAA,QACb,CAAC;AAAA,MACL;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA,EAIQ,SAAS,KAA+B,IAAyB;AACrE,QAAI;AAEJ,QAAI,OAAO,CAAC,IAAI,WAAW;AACvB,UAAI,QAAQ,OAAO,KAAK,EAAE;AAC1B,UAAI,QAAQ;AACR,YAAI;AACJ,YAAI,QAAQ;AACR,cAAI;AAEA,mBAAO,KAAK,MAAM,OAAO,OAAO,CAAC,QAAQ,KAAK,CAAC,CAAC;AAAA,UACpD,SAAS,GAAG;AAGR,eAAG,MAAS;AACZ;AAAA,UACJ;AACA,aAAG,IAAI;AAAA,QACX,OAAO;AACH,cAAI;AAEA,mBAAO,KAAK,MAAM,KAAK;AAAA,UAC3B,SAAS,GAAG;AAGR,eAAG,MAAS;AACZ;AAAA,UACJ;AACA,aAAG,IAAI;AAAA,QACX;AAAA,MACJ,OAAO;AACH,YAAI,QAAQ;AACR,mBAAS,OAAO,OAAO,CAAC,QAAQ,KAAK,CAAC;AAAA,QAC1C,OAAO;AACH,mBAAS,OAAO,OAAO,CAAC,KAAK,CAAC;AAAA,QAClC;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;",
6
6
  "names": ["uWebSockets", "expressify", "querystring"]
7
7
  }
@@ -36,10 +36,10 @@ var uWebSocketsTransport = class extends Transport {
36
36
  {
37
37
  url: req.getUrl(),
38
38
  query: req.getQuery(),
39
- // compatibility with @colyseus/ws-transport
40
- headers,
41
- connection: {
42
- remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString()
39
+ context: {
40
+ token: getBearerToken(req.getHeader("authorization")),
41
+ headers,
42
+ ip: Buffer.from(res.getRemoteAddressAsText()).toString()
43
43
  }
44
44
  },
45
45
  req.getHeader("sec-websocket-key"),
@@ -114,10 +114,10 @@ var uWebSocketsTransport = class extends Transport {
114
114
  if (!room || !room.hasReservedSeat(sessionId, searchParams.reconnectionToken)) {
115
115
  throw new Error("seat reservation expired.");
116
116
  }
117
- await room._onJoin(client, rawClient);
117
+ await room._onJoin(client, rawClient.context);
118
118
  } catch (e) {
119
119
  debugAndPrintError(e);
120
- client.error(e.code, e.message, () => rawClient.close());
120
+ client.error(e.code, e.message, () => client.leave());
121
121
  }
122
122
  }
123
123
  registerMatchMakeRequest() {
@@ -141,8 +141,10 @@ var uWebSocketsTransport = class extends Transport {
141
141
  if (res.aborted) {
142
142
  return;
143
143
  }
144
- res.writeStatus("406 Not Acceptable");
145
- res.end(JSON.stringify(error));
144
+ res.cork(() => {
145
+ res.writeStatus("406 Not Acceptable");
146
+ res.end(JSON.stringify(error));
147
+ });
146
148
  };
147
149
  const onAborted = (res) => {
148
150
  res.aborted = true;
@@ -164,7 +166,6 @@ var uWebSocketsTransport = class extends Transport {
164
166
  const url = req.getUrl();
165
167
  const matchedParams = url.match(allowedRoomNameChars);
166
168
  const matchmakeIndex = matchedParams.indexOf(matchmakeRoute);
167
- const authToken = getBearerToken(req.getHeader("authorization"));
168
169
  const headers = {};
169
170
  req.forEach((key, value) => headers[key] = value);
170
171
  this.readJson(res, async (clientOptions) => {
@@ -178,11 +179,17 @@ var uWebSocketsTransport = class extends Transport {
178
179
  method,
179
180
  roomName,
180
181
  clientOptions,
181
- { token: authToken, request: { headers } }
182
+ {
183
+ token: getBearerToken(req.getHeader("authorization")),
184
+ headers,
185
+ ip: headers["x-real-ip"] ?? Buffer.from(res.getRemoteAddressAsText()).toString()
186
+ }
182
187
  );
183
188
  if (!res.aborted) {
184
- res.writeStatus("200 OK");
185
- res.end(JSON.stringify(response));
189
+ res.cork(() => {
190
+ res.writeStatus("200 OK");
191
+ res.end(JSON.stringify(response));
192
+ });
186
193
  }
187
194
  } catch (e) {
188
195
  debugAndPrintError(e);
@@ -203,8 +210,10 @@ var uWebSocketsTransport = class extends Transport {
203
210
  try {
204
211
  const response = await matchMaker.controller.getAvailableRooms(roomName || "");
205
212
  if (!res.aborted) {
206
- res.writeStatus("200 OK");
207
- res.end(JSON.stringify(response));
213
+ res.cork(() => {
214
+ res.writeStatus("200 OK");
215
+ res.end(JSON.stringify(response));
216
+ });
208
217
  }
209
218
  } catch (e) {
210
219
  debugAndPrintError(e);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/uWebSocketsTransport.ts"],
4
- "sourcesContent": ["import http from 'http';\nimport querystring from 'querystring';\nimport uWebSockets from 'uWebSockets.js';\nimport expressify, { Application } from \"uwebsockets-express\";\n\nimport { HttpServerMock, ErrorCode, matchMaker, getBearerToken, Transport, debugAndPrintError, spliceOne } from '@colyseus/core';\nimport { uWebSocketClient, uWebSocketWrapper } from './uWebSocketClient.js';\n\nexport type TransportOptions = Omit<uWebSockets.WebSocketBehavior<any>, \"upgrade\" | \"open\" | \"pong\" | \"close\" | \"message\">;\n\ntype RawWebSocketClient = uWebSockets.WebSocket<any> & {\n url: string,\n query: string,\n headers: {[key: string]: string},\n connection: { remoteAddress: string },\n};\n\nexport class uWebSocketsTransport extends Transport {\n public app: uWebSockets.TemplatedApp;\n public expressApp: Application;\n\n protected clients: RawWebSocketClient[] = [];\n protected clientWrappers = new WeakMap<RawWebSocketClient, uWebSocketWrapper>();\n\n private _listeningSocket: any;\n private _originalRawSend: typeof uWebSocketClient.prototype.raw | null = null;\n\n constructor(options: TransportOptions = {}, appOptions: uWebSockets.AppOptions = {}) {\n super();\n\n this.app = (appOptions.cert_file_name && appOptions.key_file_name)\n ? uWebSockets.SSLApp(appOptions)\n : uWebSockets.App(appOptions);\n\n this.expressApp = expressify(this.app);\n\n if (options.maxBackpressure === undefined) {\n options.maxBackpressure = 1024 * 1024;\n }\n\n if (options.compression === undefined) {\n options.compression = uWebSockets.DISABLED;\n }\n\n if (options.maxPayloadLength === undefined) {\n options.maxPayloadLength = 4 * 1024;\n }\n\n if (options.sendPingsAutomatically === undefined) {\n options.sendPingsAutomatically = true;\n }\n\n // https://github.com/colyseus/colyseus/issues/458\n // Adding a mock object for Transport.server\n if(!this.server) {\n // @ts-ignore\n this.server = new HttpServerMock();\n }\n\n this.app.ws('/*', {\n ...options,\n\n upgrade: (res, req, context) => {\n // get all headers\n const headers: {[id: string]: string} = {};\n req.forEach((key, value) => headers[key] = value);\n\n /* This immediately calls open handler, you must not use res after this call */\n /* Spell these correctly */\n res.upgrade(\n {\n url: req.getUrl(),\n query: req.getQuery(),\n\n // compatibility with @colyseus/ws-transport\n headers,\n connection: {\n remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString()\n }\n },\n req.getHeader('sec-websocket-key'),\n req.getHeader('sec-websocket-protocol'),\n req.getHeader('sec-websocket-extensions'),\n context\n );\n },\n\n open: async (ws: RawWebSocketClient) => {\n // ws.pingCount = 0;\n await this.onConnection(ws);\n },\n\n // pong: (ws: RawWebSocketClient) => {\n // ws.pingCount = 0;\n // },\n\n close: (ws: RawWebSocketClient, code: number, message: ArrayBuffer) => {\n // remove from client list\n spliceOne(this.clients, this.clients.indexOf(ws));\n\n const clientWrapper = this.clientWrappers.get(ws);\n if (clientWrapper) {\n this.clientWrappers.delete(ws);\n\n // emit 'close' on wrapper\n clientWrapper.emit('close', code);\n }\n },\n\n message: (ws: RawWebSocketClient, message: ArrayBuffer, isBinary: boolean) => {\n // emit 'message' on wrapper\n this.clientWrappers.get(ws)?.emit('message', Buffer.from(message));\n },\n\n });\n\n this.registerMatchMakeRequest();\n }\n\n public listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void) {\n const callback = (listeningSocket: any) => {\n this._listeningSocket = listeningSocket;\n listeningListener?.();\n // @ts-ignore\n this.server.emit(\"listening\"); // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n };\n\n if (typeof(port) === \"string\") {\n // @ts-ignore\n this.app.listen_unix(callback, port);\n\n } else {\n this.app.listen(port, callback);\n\n }\n return this;\n }\n\n public shutdown() {\n if (this._listeningSocket) {\n uWebSockets.us_listen_socket_close(this._listeningSocket);\n // @ts-ignore\n this.server.emit(\"close\"); // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n }\n }\n\n public simulateLatency(milliseconds: number) {\n if (this._originalRawSend == null) {\n this._originalRawSend = uWebSocketClient.prototype.raw;\n }\n\n const originalRawSend = this._originalRawSend;\n uWebSocketClient.prototype.raw = milliseconds <= Number.EPSILON ? originalRawSend : function (...args: any[]) {\n // copy buffer\n let [buf, ...rest] = args;\n buf = Array.from(buf);\n setTimeout(() => originalRawSend.apply(this, [buf, ...rest]), milliseconds);\n };\n }\n\n protected async onConnection(rawClient: RawWebSocketClient) {\n const wrapper = new uWebSocketWrapper(rawClient);\n // keep reference to client and its wrapper\n this.clients.push(rawClient);\n this.clientWrappers.set(rawClient, wrapper);\n\n const query = rawClient.query;\n const url = rawClient.url;\n const searchParams = querystring.parse(query);\n\n const sessionId = searchParams.sessionId as string;\n const processAndRoomId = url.match(/\\/[a-zA-Z0-9_\\-]+\\/([a-zA-Z0-9_\\-]+)$/);\n const roomId = processAndRoomId && processAndRoomId[1];\n\n const room = matchMaker.getLocalRoomById(roomId);\n const client = new uWebSocketClient(sessionId, wrapper);\n\n //\n // TODO: DRY code below with all transports\n //\n\n try {\n if (!room || !room.hasReservedSeat(sessionId, searchParams.reconnectionToken as string)) {\n throw new Error('seat reservation expired.');\n }\n\n await room._onJoin(client, rawClient as unknown as http.IncomingMessage);\n\n } catch (e) {\n debugAndPrintError(e);\n\n // send error code to client then terminate\n client.error(e.code, e.message, () => rawClient.close());\n }\n }\n\n protected registerMatchMakeRequest() {\n\n // TODO: DRY with Server.ts\n const matchmakeRoute = 'matchmake';\n const allowedRoomNameChars = /([a-zA-Z_\\-0-9]+)/gi;\n\n const writeHeaders = (req: uWebSockets.HttpRequest, res: uWebSockets.HttpResponse) => {\n // skip if aborted\n if (res.aborted) { return; }\n\n const headers = Object.assign(\n {},\n matchMaker.controller.DEFAULT_CORS_HEADERS,\n matchMaker.controller.getCorsHeaders.call(undefined, req)\n );\n\n for (const header in headers) {\n res.writeHeader(header, headers[header].toString());\n }\n\n return true;\n }\n\n const writeError = (res: uWebSockets.HttpResponse, error: { code: number, error: string }) => {\n // skip if aborted\n if (res.aborted) { return; }\n\n res.writeStatus(\"406 Not Acceptable\");\n res.end(JSON.stringify(error));\n }\n\n const onAborted = (res: uWebSockets.HttpResponse) => {\n res.aborted = true;\n };\n\n this.app.options(\"/matchmake/*\", (res, req) => {\n res.onAborted(() => onAborted(res));\n\n if (writeHeaders(req, res)) {\n res.writeStatus(\"204 No Content\");\n res.end();\n }\n });\n\n\n // @ts-ignore\n this.app.post(\"/matchmake/*\", (res, req) => {\n res.onAborted(() => onAborted(res));\n\n // do not accept matchmaking requests if already shutting down\n if (matchMaker.state === matchMaker.MatchMakerState.SHUTTING_DOWN) {\n return res.close();\n }\n\n writeHeaders(req, res);\n res.writeHeader('Content-Type', 'application/json');\n\n const url = req.getUrl();\n const matchedParams = url.match(allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(matchmakeRoute);\n const authToken = getBearerToken(req.getHeader('authorization'));\n\n // cache all headers\n const headers = {};\n req.forEach((key, value) => headers[key] = value);\n\n // read json body\n this.readJson(res, async (clientOptions) => {\n try {\n if (clientOptions === undefined) {\n throw new Error(\"invalid JSON input\");\n }\n\n const method = matchedParams[matchmakeIndex + 1];\n const roomName = matchedParams[matchmakeIndex + 2] || '';\n\n const response = await matchMaker.controller.invokeMethod(\n method,\n roomName,\n clientOptions,\n { token: authToken, request: { headers } }\n );\n\n if (!res.aborted) {\n res.writeStatus(\"200 OK\");\n res.end(JSON.stringify(response));\n }\n\n } catch (e) {\n debugAndPrintError(e);\n writeError(res, {\n code: e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n error: e.message\n });\n }\n\n });\n });\n\n // this.app.any(\"/*\", (res, req) => {\n // res.onAborted(() => onAborted(req));\n // res.writeStatus(\"200 OK\");\n // });\n\n this.app.get(\"/matchmake/*\", async (res, req) => {\n res.onAborted(() => onAborted(res));\n\n writeHeaders(req, res);\n res.writeHeader('Content-Type', 'application/json');\n\n const url = req.getUrl();\n const matchedParams = url.match(allowedRoomNameChars);\n const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : \"\";\n\n try {\n const response = await matchMaker.controller.getAvailableRooms(roomName || '')\n if (!res.aborted) {\n res.writeStatus(\"200 OK\");\n res.end(JSON.stringify(response));\n }\n\n } catch (e) {\n debugAndPrintError(e);\n writeError(res, {\n code: e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n error: e.message\n });\n }\n });\n }\n\n /* Helper function for reading a posted JSON body */\n /* Extracted from https://github.com/uNetworking/uWebSockets.js/blob/master/examples/JsonPost.js */\n private readJson(res: uWebSockets.HttpResponse, cb: (json: any) => void) {\n let buffer: any;\n /* Register data cb */\n res.onData((ab, isLast) => {\n let chunk = Buffer.from(ab);\n if (isLast) {\n let json;\n if (buffer) {\n try {\n // @ts-ignore\n json = JSON.parse(Buffer.concat([buffer, chunk]));\n } catch (e) {\n /* res.close calls onAborted */\n // res.close();\n cb(undefined);\n return;\n }\n cb(json);\n } else {\n try {\n // @ts-ignore\n json = JSON.parse(chunk);\n } catch (e) {\n /* res.close calls onAborted */\n // res.close();\n cb(undefined);\n return;\n }\n cb(json);\n }\n } else {\n if (buffer) {\n buffer = Buffer.concat([buffer, chunk]);\n } else {\n buffer = Buffer.concat([chunk]);\n }\n }\n });\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import http, { IncomingHttpHeaders } from 'http';\nimport querystring from 'querystring';\nimport uWebSockets from 'uWebSockets.js';\nimport expressify, { Application } from \"uwebsockets-express\";\n\nimport { AuthContext, HttpServerMock, ErrorCode, matchMaker, getBearerToken, Transport, debugAndPrintError, spliceOne } from '@colyseus/core';\nimport { uWebSocketClient, uWebSocketWrapper } from './uWebSocketClient.js';\n\nexport type TransportOptions = Omit<uWebSockets.WebSocketBehavior<any>, \"upgrade\" | \"open\" | \"pong\" | \"close\" | \"message\">;\n\ntype RawWebSocketClient = uWebSockets.WebSocket<any> & {\n url: string,\n query: string,\n context: AuthContext,\n};\n\nexport class uWebSocketsTransport extends Transport {\n public app: uWebSockets.TemplatedApp;\n public expressApp: Application;\n\n protected clients: RawWebSocketClient[] = [];\n protected clientWrappers = new WeakMap<RawWebSocketClient, uWebSocketWrapper>();\n\n private _listeningSocket: any;\n private _originalRawSend: typeof uWebSocketClient.prototype.raw | null = null;\n\n constructor(options: TransportOptions = {}, appOptions: uWebSockets.AppOptions = {}) {\n super();\n\n this.app = (appOptions.cert_file_name && appOptions.key_file_name)\n ? uWebSockets.SSLApp(appOptions)\n : uWebSockets.App(appOptions);\n\n this.expressApp = expressify(this.app);\n\n if (options.maxBackpressure === undefined) {\n options.maxBackpressure = 1024 * 1024;\n }\n\n if (options.compression === undefined) {\n options.compression = uWebSockets.DISABLED;\n }\n\n if (options.maxPayloadLength === undefined) {\n options.maxPayloadLength = 4 * 1024;\n }\n\n if (options.sendPingsAutomatically === undefined) {\n options.sendPingsAutomatically = true;\n }\n\n // https://github.com/colyseus/colyseus/issues/458\n // Adding a mock object for Transport.server\n if(!this.server) {\n // @ts-ignore\n this.server = new HttpServerMock();\n }\n\n this.app.ws('/*', {\n ...options,\n\n upgrade: (res, req, context) => {\n // get all headers\n const headers: {[id: string]: string} = {};\n req.forEach((key, value) => headers[key] = value);\n\n /* This immediately calls open handler, you must not use res after this call */\n /* Spell these correctly */\n res.upgrade(\n {\n url: req.getUrl(),\n query: req.getQuery(),\n context: {\n token: getBearerToken(req.getHeader('authorization')),\n headers,\n ip: Buffer.from(res.getRemoteAddressAsText()).toString(),\n }\n },\n req.getHeader('sec-websocket-key'),\n req.getHeader('sec-websocket-protocol'),\n req.getHeader('sec-websocket-extensions'),\n context\n );\n },\n\n open: async (ws: RawWebSocketClient) => {\n // ws.pingCount = 0;\n await this.onConnection(ws);\n },\n\n // pong: (ws: RawWebSocketClient) => {\n // ws.pingCount = 0;\n // },\n\n close: (ws: RawWebSocketClient, code: number, message: ArrayBuffer) => {\n // remove from client list\n spliceOne(this.clients, this.clients.indexOf(ws));\n\n const clientWrapper = this.clientWrappers.get(ws);\n if (clientWrapper) {\n this.clientWrappers.delete(ws);\n\n // emit 'close' on wrapper\n clientWrapper.emit('close', code);\n }\n },\n\n message: (ws: RawWebSocketClient, message: ArrayBuffer, isBinary: boolean) => {\n // emit 'message' on wrapper\n this.clientWrappers.get(ws)?.emit('message', Buffer.from(message));\n },\n\n });\n\n this.registerMatchMakeRequest();\n }\n\n public listen(port: number, hostname?: string, backlog?: number, listeningListener?: () => void) {\n const callback = (listeningSocket: any) => {\n this._listeningSocket = listeningSocket;\n listeningListener?.();\n // @ts-ignore\n this.server.emit(\"listening\"); // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n };\n\n if (typeof(port) === \"string\") {\n // @ts-ignore\n this.app.listen_unix(callback, port);\n\n } else {\n this.app.listen(port, callback);\n\n }\n return this;\n }\n\n public shutdown() {\n if (this._listeningSocket) {\n uWebSockets.us_listen_socket_close(this._listeningSocket);\n // @ts-ignore\n this.server.emit(\"close\"); // Mocking Transport.server behaviour, https://github.com/colyseus/colyseus/issues/458\n }\n }\n\n public simulateLatency(milliseconds: number) {\n if (this._originalRawSend == null) {\n this._originalRawSend = uWebSocketClient.prototype.raw;\n }\n\n const originalRawSend = this._originalRawSend;\n uWebSocketClient.prototype.raw = milliseconds <= Number.EPSILON ? originalRawSend : function (...args: any[]) {\n // copy buffer\n let [buf, ...rest] = args;\n buf = Array.from(buf);\n setTimeout(() => originalRawSend.apply(this, [buf, ...rest]), milliseconds);\n };\n }\n\n protected async onConnection(rawClient: RawWebSocketClient) {\n const wrapper = new uWebSocketWrapper(rawClient);\n // keep reference to client and its wrapper\n this.clients.push(rawClient);\n this.clientWrappers.set(rawClient, wrapper);\n\n const query = rawClient.query;\n const url = rawClient.url;\n const searchParams = querystring.parse(query);\n\n const sessionId = searchParams.sessionId as string;\n const processAndRoomId = url.match(/\\/[a-zA-Z0-9_\\-]+\\/([a-zA-Z0-9_\\-]+)$/);\n const roomId = processAndRoomId && processAndRoomId[1];\n\n const room = matchMaker.getLocalRoomById(roomId);\n const client = new uWebSocketClient(sessionId, wrapper);\n\n //\n // TODO: DRY code below with all transports\n //\n\n try {\n if (!room || !room.hasReservedSeat(sessionId, searchParams.reconnectionToken as string)) {\n throw new Error('seat reservation expired.');\n }\n\n await room._onJoin(client, rawClient.context);\n\n } catch (e) {\n debugAndPrintError(e);\n\n // send error code to client then terminate\n client.error(e.code, e.message, () => client.leave());\n }\n }\n\n protected registerMatchMakeRequest() {\n\n // TODO: DRY with Server.ts\n const matchmakeRoute = 'matchmake';\n const allowedRoomNameChars = /([a-zA-Z_\\-0-9]+)/gi;\n\n const writeHeaders = (req: uWebSockets.HttpRequest, res: uWebSockets.HttpResponse) => {\n // skip if aborted\n if (res.aborted) { return; }\n\n const headers = Object.assign(\n {},\n matchMaker.controller.DEFAULT_CORS_HEADERS,\n matchMaker.controller.getCorsHeaders.call(undefined, req)\n );\n\n for (const header in headers) {\n res.writeHeader(header, headers[header].toString());\n }\n\n return true;\n }\n\n const writeError = (res: uWebSockets.HttpResponse, error: { code: number, error: string }) => {\n // skip if aborted\n if (res.aborted) { return; }\n\n res.cork(() => {\n res.writeStatus(\"406 Not Acceptable\");\n res.end(JSON.stringify(error));\n });\n }\n\n const onAborted = (res: uWebSockets.HttpResponse) => {\n res.aborted = true;\n };\n\n this.app.options(\"/matchmake/*\", (res, req) => {\n res.onAborted(() => onAborted(res));\n\n if (writeHeaders(req, res)) {\n res.writeStatus(\"204 No Content\");\n res.end();\n }\n });\n\n\n // @ts-ignore\n this.app.post(\"/matchmake/*\", (res, req) => {\n res.onAborted(() => onAborted(res));\n\n // do not accept matchmaking requests if already shutting down\n if (matchMaker.state === matchMaker.MatchMakerState.SHUTTING_DOWN) {\n return res.close();\n }\n\n writeHeaders(req, res);\n res.writeHeader('Content-Type', 'application/json');\n\n const url = req.getUrl();\n const matchedParams = url.match(allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(matchmakeRoute);\n\n // cache all headers\n const headers: IncomingHttpHeaders = {};\n req.forEach((key, value) => headers[key] = value);\n\n // read json body\n this.readJson(res, async (clientOptions) => {\n try {\n if (clientOptions === undefined) {\n throw new Error(\"invalid JSON input\");\n }\n\n const method = matchedParams[matchmakeIndex + 1];\n const roomName = matchedParams[matchmakeIndex + 2] || '';\n\n const response = await matchMaker.controller.invokeMethod(\n method,\n roomName,\n clientOptions,\n {\n token: getBearerToken(req.getHeader('authorization')),\n headers,\n ip: headers['x-real-ip'] ?? Buffer.from(res.getRemoteAddressAsText()).toString()\n }\n );\n\n if (!res.aborted) {\n res.cork(() => {\n res.writeStatus(\"200 OK\");\n res.end(JSON.stringify(response));\n });\n }\n\n } catch (e) {\n debugAndPrintError(e);\n writeError(res, {\n code: e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n error: e.message\n });\n }\n\n });\n });\n\n // this.app.any(\"/*\", (res, req) => {\n // res.onAborted(() => onAborted(req));\n // res.writeStatus(\"200 OK\");\n // });\n\n this.app.get(\"/matchmake/*\", async (res, req) => {\n res.onAborted(() => onAborted(res));\n\n writeHeaders(req, res);\n res.writeHeader('Content-Type', 'application/json');\n\n const url = req.getUrl();\n const matchedParams = url.match(allowedRoomNameChars);\n const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : \"\";\n\n try {\n const response = await matchMaker.controller.getAvailableRooms(roomName || '')\n if (!res.aborted) {\n res.cork(() => {\n res.writeStatus(\"200 OK\");\n res.end(JSON.stringify(response));\n });\n }\n\n } catch (e) {\n debugAndPrintError(e);\n writeError(res, {\n code: e.code || ErrorCode.MATCHMAKE_UNHANDLED,\n error: e.message\n });\n }\n });\n }\n\n /* Helper function for reading a posted JSON body */\n /* Extracted from https://github.com/uNetworking/uWebSockets.js/blob/master/examples/JsonPost.js */\n private readJson(res: uWebSockets.HttpResponse, cb: (json: any) => void) {\n let buffer: any;\n /* Register data cb */\n res.onData((ab, isLast) => {\n let chunk = Buffer.from(ab);\n if (isLast) {\n let json;\n if (buffer) {\n try {\n // @ts-ignore\n json = JSON.parse(Buffer.concat([buffer, chunk]));\n } catch (e) {\n /* res.close calls onAborted */\n // res.close();\n cb(undefined);\n return;\n }\n cb(json);\n } else {\n try {\n // @ts-ignore\n json = JSON.parse(chunk);\n } catch (e) {\n /* res.close calls onAborted */\n // res.close();\n cb(undefined);\n return;\n }\n cb(json);\n }\n } else {\n if (buffer) {\n buffer = Buffer.concat([buffer, chunk]);\n } else {\n buffer = Buffer.concat([chunk]);\n }\n }\n });\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colyseus/uwebsockets-transport",
3
- "version": "0.16.0-preview.12",
3
+ "version": "0.16.0-preview.14",
4
4
  "input": "./src/index.ts",
5
5
  "main": "./build/index.js",
6
6
  "module": "./build/index.mjs",
@@ -12,9 +12,14 @@
12
12
  }
13
13
  },
14
14
  "dependencies": {
15
- "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.43.0",
16
- "uwebsockets-express": "^1.3.8",
17
- "@colyseus/core": "^0.16.0-preview.30"
15
+ "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.51.0",
16
+ "uwebsockets-express": "^1.3.8"
17
+ },
18
+ "devDependencies": {
19
+ "@colyseus/core": "^0.16.0-preview.36"
20
+ },
21
+ "peerDependencies_TODO": {
22
+ "@colyseus/core": "0.16.x"
18
23
  },
19
24
  "author": "Endel Dreyer",
20
25
  "license": "MIT",