@vworlds/dgram-server 1.0.0
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/dgram-common/src/constants.d.ts +18 -0
- package/dgram-common/src/constants.js +19 -0
- package/dgram-common/src/constants.js.map +1 -0
- package/dgram-common/src/events.d.ts +26 -0
- package/dgram-common/src/events.js +42 -0
- package/dgram-common/src/events.js.map +1 -0
- package/dgram-common/src/index.d.ts +5 -0
- package/dgram-common/src/index.js +4 -0
- package/dgram-common/src/index.js.map +1 -0
- package/dgram-common/src/socket.d.ts +27 -0
- package/dgram-common/src/socket.js +5 -0
- package/dgram-common/src/socket.js.map +1 -0
- package/dgram-server/src/index.d.ts +4 -0
- package/dgram-server/src/index.js +4 -0
- package/dgram-server/src/index.js.map +1 -0
- package/dgram-server/src/server/server-options.d.ts +35 -0
- package/dgram-server/src/server/server-options.js +9 -0
- package/dgram-server/src/server/server-options.js.map +1 -0
- package/dgram-server/src/server/server-socket.d.ts +18 -0
- package/dgram-server/src/server/server-socket.js +36 -0
- package/dgram-server/src/server/server-socket.js.map +1 -0
- package/dgram-server/src/server/socket-listener.d.ts +24 -0
- package/dgram-server/src/server/socket-listener.js +32 -0
- package/dgram-server/src/server/socket-listener.js.map +1 -0
- package/dgram-server/src/webrtc/datachannel/connections-manager.d.ts +19 -0
- package/dgram-server/src/webrtc/datachannel/connections-manager.js +94 -0
- package/dgram-server/src/webrtc/datachannel/connections-manager.js.map +1 -0
- package/dgram-server/src/webrtc/datachannel/webrtc-connection.d.ts +46 -0
- package/dgram-server/src/webrtc/datachannel/webrtc-connection.js +111 -0
- package/dgram-server/src/webrtc/datachannel/webrtc-connection.js.map +1 -0
- package/dgram-server/src/webrtc/http/helpers.d.ts +5 -0
- package/dgram-server/src/webrtc/http/helpers.js +13 -0
- package/dgram-server/src/webrtc/http/helpers.js.map +1 -0
- package/dgram-server/src/webrtc/http/http-server.d.ts +20 -0
- package/dgram-server/src/webrtc/http/http-server.js +30 -0
- package/dgram-server/src/webrtc/http/http-server.js.map +1 -0
- package/dgram-server/src/webrtc/http/routes.d.ts +10 -0
- package/dgram-server/src/webrtc/http/routes.js +78 -0
- package/dgram-server/src/webrtc/http/routes.js.map +1 -0
- package/package.json +19 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare const EVENTS: {
|
|
2
|
+
CONNECT: string;
|
|
3
|
+
CONNECTION: string;
|
|
4
|
+
DATA_CHANNEL_IS_OPEN: string;
|
|
5
|
+
DISCONNECTED: string;
|
|
6
|
+
ERROR: string;
|
|
7
|
+
MESSAGE: string;
|
|
8
|
+
};
|
|
9
|
+
declare const ERRORS: {
|
|
10
|
+
BROWSER_NOT_SUPPORTED: string;
|
|
11
|
+
COULD_NOT_PARSE_MESSAGE: string;
|
|
12
|
+
DROPPED_FROM_BUFFERING: string;
|
|
13
|
+
MAX_MESSAGE_SIZE_EXCEEDED: string;
|
|
14
|
+
PEER_CONNECTION_NOT_CREATED: string;
|
|
15
|
+
DATA_CHANNEL_NOT_CREATED: string;
|
|
16
|
+
CONNECTION_CLOSED: string;
|
|
17
|
+
};
|
|
18
|
+
export { EVENTS, ERRORS };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const EVENTS = {
|
|
2
|
+
CONNECT: 'connect',
|
|
3
|
+
CONNECTION: 'connection',
|
|
4
|
+
DATA_CHANNEL_IS_OPEN: 'dataChannelIsOpen',
|
|
5
|
+
DISCONNECTED: 'disconnected',
|
|
6
|
+
ERROR: 'error',
|
|
7
|
+
MESSAGE: 'rawMessage',
|
|
8
|
+
};
|
|
9
|
+
const ERRORS = {
|
|
10
|
+
BROWSER_NOT_SUPPORTED: 'BROWSER_NOT_SUPPORTED',
|
|
11
|
+
COULD_NOT_PARSE_MESSAGE: 'COULD_NOT_PARSE_MESSAGE',
|
|
12
|
+
DROPPED_FROM_BUFFERING: 'DROPPED_FROM_BUFFERING',
|
|
13
|
+
MAX_MESSAGE_SIZE_EXCEEDED: 'MAX_MESSAGE_SIZE_EXCEEDED',
|
|
14
|
+
PEER_CONNECTION_NOT_CREATED: 'PEER_CONNECTION_NOT_CREATED',
|
|
15
|
+
DATA_CHANNEL_NOT_CREATED: 'DATA_CHANNEL_NOT_CREATED',
|
|
16
|
+
CONNECTION_CLOSED: 'CONNECTION_CLOSED',
|
|
17
|
+
};
|
|
18
|
+
export { EVENTS, ERRORS };
|
|
19
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../dgram-common/src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG;IACb,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,YAAY;IACxB,oBAAoB,EAAE,mBAAmB;IACzC,YAAY,EAAE,cAAc;IAC5B,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,YAAY;CACtB,CAAC;AAEF,MAAM,MAAM,GAAG;IACb,qBAAqB,EAAE,uBAAuB;IAC9C,uBAAuB,EAAE,yBAAyB;IAClD,sBAAsB,EAAE,wBAAwB;IAChD,yBAAyB,EAAE,2BAA2B;IACtD,2BAA2B,EAAE,6BAA6B;IAC1D,wBAAwB,EAAE,0BAA0B;IACpD,iBAAiB,EAAE,mBAAmB;CACvC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed eventemitter3 wrapper used by dgram sockets and listener classes.
|
|
3
|
+
* Inspired by @yandeu/events: https://github.com/yandeu/events
|
|
4
|
+
*/
|
|
5
|
+
type ValidEventMap<T = any> = T extends {
|
|
6
|
+
[P in keyof T]: (...args: any[]) => void;
|
|
7
|
+
} ? T : never;
|
|
8
|
+
type Handler<T extends any | ((...args: any[]) => R), R = any> = T;
|
|
9
|
+
export type EventListener<T extends ValidEventMap, K extends EventNames<T>> = T extends string | symbol ? (...args: any[]) => void : K extends keyof T ? Handler<T[K], void> : never;
|
|
10
|
+
type EventArgs<T extends ValidEventMap, K extends EventNames<T>> = Parameters<EventListener<T, K>>;
|
|
11
|
+
export type EventNames<T extends ValidEventMap> = T extends string | symbol ? T : keyof T;
|
|
12
|
+
declare class events<EventMap extends ValidEventMap = any> {
|
|
13
|
+
on<T extends EventNames<EventMap>>(event: T, fn: EventListener<EventMap, T>, context?: any): events<EventMap>;
|
|
14
|
+
emit<T extends EventNames<EventMap>>(event: T, ...args: EventArgs<EventMap, T>): boolean;
|
|
15
|
+
once<T extends EventNames<EventMap>>(event: T, fn: EventListener<EventMap, T>, context?: any): events<EventMap>;
|
|
16
|
+
eventNames(): EventNames<EventMap>[];
|
|
17
|
+
listeners(event: EventNames<EventMap>): any[];
|
|
18
|
+
listenerCount(event: EventNames<EventMap>): any;
|
|
19
|
+
removeListener<T extends EventNames<EventMap>>(event: T, fn?: EventListener<EventMap, T>, context?: any, once?: boolean): this;
|
|
20
|
+
removeAllListeners(event?: EventNames<EventMap>): this;
|
|
21
|
+
off<T extends EventNames<EventMap>>(event: T, fn?: EventListener<EventMap, T> | undefined, context?: any, once?: boolean | undefined): events<EventMap>;
|
|
22
|
+
addListener<T extends EventNames<EventMap>>(event: T, fn: EventListener<EventMap, T>, context?: any): events<EventMap>;
|
|
23
|
+
}
|
|
24
|
+
export declare class Events<EventMap extends ValidEventMap = any> extends events<EventMap> {
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed eventemitter3 wrapper used by dgram sockets and listener classes.
|
|
3
|
+
* Inspired by @yandeu/events: https://github.com/yandeu/events
|
|
4
|
+
*/
|
|
5
|
+
import eventEmitter3 from 'eventemitter3';
|
|
6
|
+
const { EventEmitter } = eventEmitter3;
|
|
7
|
+
class events {
|
|
8
|
+
on(event, fn, context) {
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
|
11
|
+
emit(event, ...args) {
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
once(event, fn, context) {
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
eventNames() {
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
listeners(event) {
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
listenerCount(event) {
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
removeListener(event, fn, context, once) {
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
removeAllListeners(event) {
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
off(event, fn, context, once) {
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
addListener(event, fn, context) {
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
events = EventEmitter;
|
|
40
|
+
export class Events extends events {
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../../../dgram-common/src/events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,aAAa,MAAM,eAAe,CAAC;AAE1C,MAAM,EAAE,YAAY,EAAE,GAAG,aAAa,CAAC;AA2BvC,MAAM,MAAM;IACH,EAAE,CACP,KAAQ,EACR,EAA8B,EAC9B,OAAa;QAEb,OAAO,CAAQ,CAAC;IAClB,CAAC;IAEM,IAAI,CACT,KAAQ,EACR,GAAG,IAA4B;QAE/B,OAAO,CAAQ,CAAC;IAClB,CAAC;IAEM,IAAI,CACT,KAAQ,EACR,EAA8B,EAC9B,OAAa;QAEb,OAAO,CAAQ,CAAC;IAClB,CAAC;IAEM,UAAU;QACf,OAAO,CAAQ,CAAC;IAClB,CAAC;IAEM,SAAS,CAAC,KAA2B;QAC1C,OAAO,CAAQ,CAAC;IAClB,CAAC;IAEM,aAAa,CAAC,KAA2B;QAC9C,OAAO,CAAQ,CAAC;IAClB,CAAC;IAEM,cAAc,CACnB,KAAQ,EACR,EAA+B,EAC/B,OAAa,EACb,IAAc;QAEd,OAAO,CAAQ,CAAC;IAClB,CAAC;IAED,kBAAkB,CAAC,KAA4B;QAC7C,OAAO,CAAQ,CAAC;IAClB,CAAC;IAEM,GAAG,CACR,KAAQ,EACR,EAA2C,EAC3C,OAAa,EACb,IAA0B;QAE1B,OAAO,CAAQ,CAAC;IAClB,CAAC;IAEM,WAAW,CAChB,KAAQ,EACR,EAA8B,EAC9B,OAAa;QAEb,OAAO,CAAQ,CAAC;IAClB,CAAC;CACF;AAEA,MAAc,GAAG,YAAY,CAAC;AAE/B,MAAM,OAAO,MAEX,SAAQ,MAAgB;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../dgram-common/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Events } from './events.js';
|
|
2
|
+
/** Describes a connection failure reported through the socket `connect` event. */
|
|
3
|
+
export interface ConnectionError extends Error {
|
|
4
|
+
/** Numeric status code for the failure. Browser support failures use `-1`. */
|
|
5
|
+
status: number;
|
|
6
|
+
/** Human-readable status text suitable for logs or UI. */
|
|
7
|
+
statusText: string;
|
|
8
|
+
}
|
|
9
|
+
/** Events emitted by dgram socket implementations. */
|
|
10
|
+
interface SocketEvents {
|
|
11
|
+
/** Fired after the peer connection or data channel closes. */
|
|
12
|
+
disconnect: () => void;
|
|
13
|
+
/** Fired when binary payload data arrives from the remote peer. */
|
|
14
|
+
receive: (data: Uint8Array) => void;
|
|
15
|
+
/** Fired when the socket connects, or with an error when setup fails. */
|
|
16
|
+
connect: (err?: ConnectionError) => void;
|
|
17
|
+
}
|
|
18
|
+
/** Common socket-shaped interface implemented by browser and server dgram sockets. */
|
|
19
|
+
export declare abstract class Socket extends Events<SocketEvents> {
|
|
20
|
+
/** Stable connection id assigned by the signaling server. */
|
|
21
|
+
abstract get id(): string;
|
|
22
|
+
/** Sends one binary datagram-like payload over the underlying WebRTC data channel. */
|
|
23
|
+
abstract send(data: Uint8Array): void;
|
|
24
|
+
/** Closes the underlying WebRTC connection and releases resources. */
|
|
25
|
+
abstract close(): void;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket.js","sourceRoot":"","sources":["../../../../dgram-common/src/socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAoBrC,sFAAsF;AACtF,MAAM,OAAgB,MAAO,SAAQ,MAAoB;CAOxD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Reliability mode used when configuring the server-created data channel. */
|
|
2
|
+
export declare enum ReliabilityType {
|
|
3
|
+
/** Retransmit dropped packets up to `maxRetransmits`. */
|
|
4
|
+
Rexmit = "rexmit",
|
|
5
|
+
/** Retry delivery for at most `maxPacketLifeTime` milliseconds. */
|
|
6
|
+
Timed = "timed"
|
|
7
|
+
}
|
|
8
|
+
/** Options used by `SocketListener` when creating WebRTC server peers. */
|
|
9
|
+
export interface ServerOptions {
|
|
10
|
+
/** Base path for the HTTP signaling API. Defaults to `/rtc/v1`. */
|
|
11
|
+
apiBasePath?: string;
|
|
12
|
+
/** ICE/STUN/TURN servers shared with node-datachannel. */
|
|
13
|
+
iceServers?: RTCIceServer[];
|
|
14
|
+
/** ICE transport policy. Use `relay` to force TURN-only connectivity. */
|
|
15
|
+
iceTransportPolicy?: RTCIceTransportPolicy;
|
|
16
|
+
/** Data channel label expected by the client. Use `dgram` with `ClientSocket`. */
|
|
17
|
+
label: string;
|
|
18
|
+
/** Enables node-datachannel's UDP mux support when available. */
|
|
19
|
+
enableIceUdpMux?: boolean;
|
|
20
|
+
/** The maximum number of milliseconds that attempts to transfer a message may take in unreliable mode. While this value is a 16-bit unsigned number, each user agent may clamp it to whatever maximum it deems appropriate. Default: undefined. */
|
|
21
|
+
maxPacketLifeTime?: number;
|
|
22
|
+
/** options.maxRetransmits The maximum number of times the user agent should attempt to retransmit a message which fails the first time in unreliable mode. While this value is a16-bit unsigned number, each user agent may clamp it to whatever maximum it deems appropriate. Default: 0. */
|
|
23
|
+
maxRetransmits?: number;
|
|
24
|
+
/** Indicates whether or not messages sent on the RTCDataChannel are required to arrive at their destination. Default: false. */
|
|
25
|
+
reliabilityType?: ReliabilityType;
|
|
26
|
+
/** Indicates whether or not messages sent on the RTCDataChannel are required to arrive at their destination in the same order in which they were sent (true), or if they're allowed to arrive out-of-order (false). Default: false. */
|
|
27
|
+
ordered?: boolean;
|
|
28
|
+
/** Set a custom port range for the WebRTC connection. */
|
|
29
|
+
portRange?: {
|
|
30
|
+
/** Minimum port range (defaults to 0) */
|
|
31
|
+
min: number;
|
|
32
|
+
/** Minimum port range (defaults to 65535) */
|
|
33
|
+
max: number;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Reliability mode used when configuring the server-created data channel. */
|
|
2
|
+
export var ReliabilityType;
|
|
3
|
+
(function (ReliabilityType) {
|
|
4
|
+
/** Retransmit dropped packets up to `maxRetransmits`. */
|
|
5
|
+
ReliabilityType["Rexmit"] = "rexmit";
|
|
6
|
+
/** Retry delivery for at most `maxPacketLifeTime` milliseconds. */
|
|
7
|
+
ReliabilityType["Timed"] = "timed";
|
|
8
|
+
})(ReliabilityType || (ReliabilityType = {}));
|
|
9
|
+
//# sourceMappingURL=server-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-options.js","sourceRoot":"","sources":["../../../../src/server/server-options.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,yDAAyD;IACzD,oCAAiB,CAAA;IACjB,mEAAmE;IACnE,kCAAe,CAAA;AACjB,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import WebRTCConnection from '../webrtc/datachannel/webrtc-connection.js';
|
|
2
|
+
import { Socket } from '../../../dgram-common/src/index.js';
|
|
3
|
+
/** Server-side dgram socket for one connected WebRTC client. */
|
|
4
|
+
export declare class ServerSocket extends Socket {
|
|
5
|
+
connection: WebRTCConnection;
|
|
6
|
+
/**
|
|
7
|
+
* Wraps a low-level server WebRTC connection in the common socket API.
|
|
8
|
+
*
|
|
9
|
+
* @param connection Active server-side WebRTC connection.
|
|
10
|
+
*/
|
|
11
|
+
constructor(connection: WebRTCConnection);
|
|
12
|
+
/** Connection id assigned by the server connection manager. */
|
|
13
|
+
get id(): string;
|
|
14
|
+
/** Sends one binary payload to the connected browser peer. */
|
|
15
|
+
send(data: Uint8Array): void;
|
|
16
|
+
/** Closes the server-side data channel and peer connection. */
|
|
17
|
+
close(): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { EVENTS, Socket, } from '../../../dgram-common/src/index.js';
|
|
2
|
+
/** Server-side dgram socket for one connected WebRTC client. */
|
|
3
|
+
export class ServerSocket extends Socket {
|
|
4
|
+
connection;
|
|
5
|
+
/**
|
|
6
|
+
* Wraps a low-level server WebRTC connection in the common socket API.
|
|
7
|
+
*
|
|
8
|
+
* @param connection Active server-side WebRTC connection.
|
|
9
|
+
*/
|
|
10
|
+
constructor(connection) {
|
|
11
|
+
super();
|
|
12
|
+
this.connection = connection;
|
|
13
|
+
this.connection.on(EVENTS.DATA_CHANNEL_IS_OPEN, (err) => {
|
|
14
|
+
this.emit('connect', err);
|
|
15
|
+
});
|
|
16
|
+
this.connection.on(EVENTS.MESSAGE, (data) => {
|
|
17
|
+
this.emit('receive', data);
|
|
18
|
+
});
|
|
19
|
+
this.connection.on(EVENTS.DISCONNECTED, () => {
|
|
20
|
+
this.emit('disconnect');
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** Connection id assigned by the server connection manager. */
|
|
24
|
+
get id() {
|
|
25
|
+
return this.connection.id;
|
|
26
|
+
}
|
|
27
|
+
/** Sends one binary payload to the connected browser peer. */
|
|
28
|
+
send(data) {
|
|
29
|
+
this.connection.sendMessage(data);
|
|
30
|
+
}
|
|
31
|
+
/** Closes the server-side data channel and peer connection. */
|
|
32
|
+
close() {
|
|
33
|
+
this.connection.close();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=server-socket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-socket.js","sourceRoot":"","sources":["../../../../src/server/server-socket.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,MAAM,EACN,MAAM,GACP,MAAM,oCAAoC,CAAC;AAE5C,gEAAgE;AAChE,MAAM,OAAO,YAAa,SAAQ,MAAM;IAMnB;IALnB;;;;OAIG;IACH,YAAmB,UAA4B;QAC7C,KAAK,EAAE,CAAC;QADS,eAAU,GAAV,UAAU,CAAkB;QAG7C,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC,GAAoB,EAAE,EAAE;YACvE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,IAAgB,EAAE,EAAE;YACtD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,GAAG,EAAE;YAC3C,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,+DAA+D;IAC/D,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;IAC5B,CAAC;IAED,8DAA8D;IAC9D,IAAI,CAAC,IAAgB;QACnB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,+DAA+D;IAC/D,KAAK;QACH,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Events, Socket } from '../../../dgram-common/src/index.js';
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import { ServerOptions } from './server-options.js';
|
|
4
|
+
/** Events emitted by `SocketListener`. */
|
|
5
|
+
interface SocketListenerEvents {
|
|
6
|
+
/** Fired after a new peer's data channel opens and is ready to send/receive. */
|
|
7
|
+
new: (s: Socket) => void;
|
|
8
|
+
}
|
|
9
|
+
/** Installs dgram signaling routes on an Express app and emits connected sockets. */
|
|
10
|
+
export declare class SocketListener extends Events<SocketListenerEvents> {
|
|
11
|
+
options: ServerOptions;
|
|
12
|
+
/** HTTP signaling route installer. */
|
|
13
|
+
private apiServer;
|
|
14
|
+
/** Creates and tracks server-side WebRTC connections. */
|
|
15
|
+
private connectionsManager;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a listener and mounts signaling routes on the provided Express app.
|
|
18
|
+
*
|
|
19
|
+
* @param app Express app that should host the signaling API.
|
|
20
|
+
* @param options WebRTC and signaling options for every new connection.
|
|
21
|
+
*/
|
|
22
|
+
constructor(app: express.Application, options: ServerOptions);
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { EVENTS, Events } from '../../../dgram-common/src/index.js';
|
|
2
|
+
import ConnectionsManager from '../webrtc/datachannel/connections-manager.js';
|
|
3
|
+
import HttpServer from '../webrtc/http/http-server.js';
|
|
4
|
+
import { ServerSocket } from './server-socket.js';
|
|
5
|
+
/** Installs dgram signaling routes on an Express app and emits connected sockets. */
|
|
6
|
+
export class SocketListener extends Events {
|
|
7
|
+
options;
|
|
8
|
+
/** HTTP signaling route installer. */
|
|
9
|
+
apiServer;
|
|
10
|
+
/** Creates and tracks server-side WebRTC connections. */
|
|
11
|
+
connectionsManager;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a listener and mounts signaling routes on the provided Express app.
|
|
14
|
+
*
|
|
15
|
+
* @param app Express app that should host the signaling API.
|
|
16
|
+
* @param options WebRTC and signaling options for every new connection.
|
|
17
|
+
*/
|
|
18
|
+
constructor(app, options) {
|
|
19
|
+
super();
|
|
20
|
+
this.options = options;
|
|
21
|
+
this.connectionsManager = new ConnectionsManager(options);
|
|
22
|
+
this.apiServer = new HttpServer(app, this.connectionsManager, this.options);
|
|
23
|
+
this.apiServer.setupRoutes();
|
|
24
|
+
this.connectionsManager.on(EVENTS.CONNECTION, (conn) => {
|
|
25
|
+
const ss = new ServerSocket(conn);
|
|
26
|
+
ss.on('connect', () => {
|
|
27
|
+
this.emit('new', ss);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=socket-listener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket-listener.js","sourceRoot":"","sources":["../../../../src/server/socket-listener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAU,MAAM,oCAAoC,CAAC;AAE5E,OAAO,kBAAkB,MAAM,8CAA8C,CAAC;AAE9E,OAAO,UAAU,MAAM,+BAA+B,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQlD,qFAAqF;AACrF,MAAM,OAAO,cAAe,SAAQ,MAA4B;IAcrD;IAbT,sCAAsC;IAC9B,SAAS,CAAa;IAC9B,yDAAyD;IACjD,kBAAkB,CAAqB;IAE/C;;;;;OAKG;IACH,YACE,GAAwB,EACjB,OAAsB;QAE7B,KAAK,EAAE,CAAC;QAFD,YAAO,GAAP,OAAO,CAAe;QAG7B,IAAI,CAAC,kBAAkB,GAAG,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,SAAS,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5E,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;QAE7B,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,IAAsB,EAAE,EAAE;YACvE,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;YAClC,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;gBACpB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ServerOptions } from '../../server/server-options.js';
|
|
2
|
+
import WebRTCConnection from './webrtc-connection.js';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
/** Creates, stores, and deletes server-side WebRTC connections. */
|
|
5
|
+
export default class ConnectionsManager extends EventEmitter {
|
|
6
|
+
options: ServerOptions;
|
|
7
|
+
/** Active server-side WebRTC connections keyed by connection id. */
|
|
8
|
+
private connections;
|
|
9
|
+
/** @param options WebRTC and data channel settings applied to new connections. */
|
|
10
|
+
constructor(options: ServerOptions);
|
|
11
|
+
/** Creates a random connection id used by signaling routes. */
|
|
12
|
+
private createId;
|
|
13
|
+
/** Looks up an active server connection by id. */
|
|
14
|
+
getConnection(id: string): WebRTCConnection | undefined;
|
|
15
|
+
/** Creates a server peer, data channel, and offer for a browser client. */
|
|
16
|
+
createConnection(): Promise<WebRTCConnection | undefined>;
|
|
17
|
+
/** Closes and removes a server connection. */
|
|
18
|
+
deleteConnection(connection: WebRTCConnection): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { ReliabilityType, } from '../../server/server-options.js';
|
|
2
|
+
import WebRTCConnection from './webrtc-connection.js';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
import { EVENTS } from '../../../../dgram-common/src/index.js';
|
|
5
|
+
/** Creates, stores, and deletes server-side WebRTC connections. */
|
|
6
|
+
export default class ConnectionsManager extends EventEmitter {
|
|
7
|
+
options;
|
|
8
|
+
/** Active server-side WebRTC connections keyed by connection id. */
|
|
9
|
+
connections = new Map();
|
|
10
|
+
/** @param options WebRTC and data channel settings applied to new connections. */
|
|
11
|
+
constructor(options) {
|
|
12
|
+
super();
|
|
13
|
+
this.options = options;
|
|
14
|
+
}
|
|
15
|
+
/** Creates a random connection id used by signaling routes. */
|
|
16
|
+
createId() {
|
|
17
|
+
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
18
|
+
let id = '';
|
|
19
|
+
for (let i = 0; i < 24; i++) {
|
|
20
|
+
id += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
21
|
+
}
|
|
22
|
+
return id;
|
|
23
|
+
}
|
|
24
|
+
/** Looks up an active server connection by id. */
|
|
25
|
+
getConnection(id) {
|
|
26
|
+
return this.connections.get(id);
|
|
27
|
+
}
|
|
28
|
+
/** Creates a server peer, data channel, and offer for a browser client. */
|
|
29
|
+
async createConnection() {
|
|
30
|
+
return new Promise(async (resolve, reject) => {
|
|
31
|
+
const { ordered = false, reliabilityType = ReliabilityType.Rexmit, enableIceUdpMux, label = 'dgram', iceServers = [], portRange, iceTransportPolicy = 'all', maxPacketLifeTime = undefined, maxRetransmits = 2, } = this.options;
|
|
32
|
+
const dcConfig = {
|
|
33
|
+
ordered,
|
|
34
|
+
};
|
|
35
|
+
if (reliabilityType === ReliabilityType.Timed &&
|
|
36
|
+
maxPacketLifeTime !== undefined) {
|
|
37
|
+
dcConfig.maxPacketLifeTime = maxPacketLifeTime;
|
|
38
|
+
}
|
|
39
|
+
else if (maxRetransmits !== undefined) {
|
|
40
|
+
dcConfig.maxRetransmits = maxRetransmits;
|
|
41
|
+
}
|
|
42
|
+
// WebRTC connection config
|
|
43
|
+
let rtcConfig = {
|
|
44
|
+
iceTransportPolicy: iceTransportPolicy,
|
|
45
|
+
iceServers: iceServers.map((ice) => ice.urls),
|
|
46
|
+
};
|
|
47
|
+
if (enableIceUdpMux !== undefined) {
|
|
48
|
+
rtcConfig.enableIceUdpMux = enableIceUdpMux;
|
|
49
|
+
}
|
|
50
|
+
// portRange is a nonstandard API
|
|
51
|
+
if (portRange?.min && portRange?.max) {
|
|
52
|
+
rtcConfig = {
|
|
53
|
+
...rtcConfig,
|
|
54
|
+
portRangeBegin: portRange.min,
|
|
55
|
+
portRangeEnd: portRange.max,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const newId = this.createId();
|
|
59
|
+
const connection = new WebRTCConnection(newId, rtcConfig, this.connections);
|
|
60
|
+
const pc = await connection.init();
|
|
61
|
+
if (!pc) {
|
|
62
|
+
reject(undefined);
|
|
63
|
+
}
|
|
64
|
+
this.connections.set(connection.id, connection);
|
|
65
|
+
pc.onDataChannel((dc) => {
|
|
66
|
+
// do nothing
|
|
67
|
+
});
|
|
68
|
+
pc.onStateChange(async (state) => {
|
|
69
|
+
if (state === 'disconnected' ||
|
|
70
|
+
state === 'failed' ||
|
|
71
|
+
state === 'closed') {
|
|
72
|
+
await this.deleteConnection(connection);
|
|
73
|
+
}
|
|
74
|
+
connection.setState(state);
|
|
75
|
+
});
|
|
76
|
+
pc.onGatheringStateChange((state) => { });
|
|
77
|
+
pc.onLocalDescription((sdp, type) => {
|
|
78
|
+
connection.localDescription = { sdp, type };
|
|
79
|
+
resolve(connection);
|
|
80
|
+
});
|
|
81
|
+
pc.onLocalCandidate((candidate, mid) => {
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
connection.iceCandidates.push({ candidate, sdpMid: mid });
|
|
84
|
+
});
|
|
85
|
+
await connection.setupDataChannel(label, dcConfig);
|
|
86
|
+
this.emit(EVENTS.CONNECTION, connection);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** Closes and removes a server connection. */
|
|
90
|
+
async deleteConnection(connection) {
|
|
91
|
+
await connection.close();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=connections-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections-manager.js","sourceRoot":"","sources":["../../../../../src/webrtc/datachannel/connections-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { PeerConnection } from 'node-datachannel';
|
|
3
|
+
import type { DataChannel, DataChannelInitConfig, RtcConfig } from 'node-datachannel';
|
|
4
|
+
/** SDP offer generated by node-datachannel for the browser peer. */
|
|
5
|
+
export interface LocalDescription {
|
|
6
|
+
/** Session description protocol body. */
|
|
7
|
+
sdp: string;
|
|
8
|
+
/** SDP description type, usually `offer`. */
|
|
9
|
+
type: string;
|
|
10
|
+
}
|
|
11
|
+
/** Low-level server-side WebRTC peer and data channel wrapper. */
|
|
12
|
+
export default class WebRTCConnection extends EventEmitter {
|
|
13
|
+
id: string;
|
|
14
|
+
config: RtcConfig;
|
|
15
|
+
connections: Map<string, WebRTCConnection>;
|
|
16
|
+
/** Last observed peer connection state. */
|
|
17
|
+
state: string;
|
|
18
|
+
/** node-datachannel peer connection for this client. */
|
|
19
|
+
peerConnection: PeerConnection | undefined;
|
|
20
|
+
/** Server-created data channel used for binary messages. */
|
|
21
|
+
dataChannel: DataChannel | undefined;
|
|
22
|
+
/** Current local SDP description sent to the browser during signaling. */
|
|
23
|
+
localDescription: LocalDescription;
|
|
24
|
+
/** ICE candidates gathered since the browser last polled the signaling API. */
|
|
25
|
+
iceCandidates: RTCIceCandidate[];
|
|
26
|
+
/**
|
|
27
|
+
* Creates a low-level server WebRTC connection wrapper.
|
|
28
|
+
*
|
|
29
|
+
* @param id Connection id assigned by `ConnectionsManager`.
|
|
30
|
+
* @param config node-datachannel peer connection configuration.
|
|
31
|
+
* @param connections Shared connection map used for self-removal on close.
|
|
32
|
+
*/
|
|
33
|
+
constructor(id: string, config: RtcConfig, connections: Map<string, WebRTCConnection>);
|
|
34
|
+
/** Records a peer state change and emits the matching dgram lifecycle event. */
|
|
35
|
+
setState(state: string): void;
|
|
36
|
+
/** Creates the underlying node-datachannel peer connection. */
|
|
37
|
+
init(): Promise<PeerConnection>;
|
|
38
|
+
/** Creates or returns the server data channel and attaches message/open handlers. */
|
|
39
|
+
setupDataChannel(label: string, config: DataChannelInitConfig): Promise<DataChannel>;
|
|
40
|
+
/** Sends one binary payload to the browser peer. */
|
|
41
|
+
sendMessage(data: any): Promise<void>;
|
|
42
|
+
/** Returns true when node-datachannel has buffered outbound data. */
|
|
43
|
+
isBuffering(): boolean;
|
|
44
|
+
/** Closes the data channel, peer connection, and removes this connection from the map. */
|
|
45
|
+
close(): Promise<void>;
|
|
46
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { PeerConnection } from 'node-datachannel';
|
|
3
|
+
import { EVENTS, ERRORS } from '../../../../dgram-common/src/index.js';
|
|
4
|
+
/** Low-level server-side WebRTC peer and data channel wrapper. */
|
|
5
|
+
export default class WebRTCConnection extends EventEmitter {
|
|
6
|
+
id;
|
|
7
|
+
config;
|
|
8
|
+
connections;
|
|
9
|
+
/** Last observed peer connection state. */
|
|
10
|
+
state;
|
|
11
|
+
/** node-datachannel peer connection for this client. */
|
|
12
|
+
peerConnection;
|
|
13
|
+
/** Server-created data channel used for binary messages. */
|
|
14
|
+
dataChannel;
|
|
15
|
+
/** Current local SDP description sent to the browser during signaling. */
|
|
16
|
+
localDescription;
|
|
17
|
+
/** ICE candidates gathered since the browser last polled the signaling API. */
|
|
18
|
+
iceCandidates = [];
|
|
19
|
+
/**
|
|
20
|
+
* Creates a low-level server WebRTC connection wrapper.
|
|
21
|
+
*
|
|
22
|
+
* @param id Connection id assigned by `ConnectionsManager`.
|
|
23
|
+
* @param config node-datachannel peer connection configuration.
|
|
24
|
+
* @param connections Shared connection map used for self-removal on close.
|
|
25
|
+
*/
|
|
26
|
+
constructor(id, config, connections) {
|
|
27
|
+
super();
|
|
28
|
+
this.id = id;
|
|
29
|
+
this.config = config;
|
|
30
|
+
this.connections = connections;
|
|
31
|
+
this.state = '';
|
|
32
|
+
this.localDescription = { sdp: '', type: '' };
|
|
33
|
+
}
|
|
34
|
+
/** Records a peer state change and emits the matching dgram lifecycle event. */
|
|
35
|
+
setState(state) {
|
|
36
|
+
if (this.state === state) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.state = state;
|
|
40
|
+
if (state === 'open') {
|
|
41
|
+
this.emit(EVENTS.CONNECT);
|
|
42
|
+
}
|
|
43
|
+
else if (state === 'failed') {
|
|
44
|
+
this.emit(EVENTS.ERROR);
|
|
45
|
+
}
|
|
46
|
+
else if (state === 'closed') {
|
|
47
|
+
this.emit(EVENTS.DISCONNECTED);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Creates the underlying node-datachannel peer connection. */
|
|
51
|
+
async init() {
|
|
52
|
+
this.peerConnection = new PeerConnection(this.id, this.config);
|
|
53
|
+
return this.peerConnection;
|
|
54
|
+
}
|
|
55
|
+
/** Creates or returns the server data channel and attaches message/open handlers. */
|
|
56
|
+
async setupDataChannel(label, config) {
|
|
57
|
+
if (!this.peerConnection) {
|
|
58
|
+
throw new Error(ERRORS.PEER_CONNECTION_NOT_CREATED);
|
|
59
|
+
}
|
|
60
|
+
if (this.dataChannel) {
|
|
61
|
+
return this.dataChannel;
|
|
62
|
+
}
|
|
63
|
+
this.dataChannel = this.peerConnection.createDataChannel(label, config);
|
|
64
|
+
this.dataChannel.onOpen(() => {
|
|
65
|
+
this.dataChannel?.onMessage((msg) => {
|
|
66
|
+
this.emit(EVENTS.MESSAGE, msg);
|
|
67
|
+
});
|
|
68
|
+
this.emit(EVENTS.DATA_CHANNEL_IS_OPEN);
|
|
69
|
+
});
|
|
70
|
+
return this.dataChannel;
|
|
71
|
+
}
|
|
72
|
+
/** Sends one binary payload to the browser peer. */
|
|
73
|
+
async sendMessage(data) {
|
|
74
|
+
if (!this.dataChannel) {
|
|
75
|
+
throw new Error(ERRORS.DATA_CHANNEL_NOT_CREATED);
|
|
76
|
+
}
|
|
77
|
+
if (this.dataChannel.isOpen()) {
|
|
78
|
+
try {
|
|
79
|
+
this.dataChannel.sendMessageBinary(data);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.log(error);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
throw new Error(ERRORS.CONNECTION_CLOSED);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Returns true when node-datachannel has buffered outbound data. */
|
|
90
|
+
isBuffering() {
|
|
91
|
+
if (this.dataChannel) {
|
|
92
|
+
return this.dataChannel.bufferedAmount() > 0;
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
/** Closes the data channel, peer connection, and removes this connection from the map. */
|
|
97
|
+
async close() {
|
|
98
|
+
if (this.dataChannel?.isOpen()) {
|
|
99
|
+
this.dataChannel.close();
|
|
100
|
+
this.dataChannel = undefined;
|
|
101
|
+
}
|
|
102
|
+
if (this.peerConnection) {
|
|
103
|
+
this.peerConnection.close();
|
|
104
|
+
this.peerConnection = undefined;
|
|
105
|
+
}
|
|
106
|
+
if (this.connections.has(this.id)) {
|
|
107
|
+
this.connections.delete(this.id);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=webrtc-connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webrtc-connection.js","sourceRoot":"","sources":["../../../../../src/webrtc/datachannel/webrtc-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAMlD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAUvE,kEAAkE;AAClE,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,YAAY;IAsB/C;IACA;IACA;IAvBT,2CAA2C;IACpC,KAAK,CAAS;IAErB,wDAAwD;IACjD,cAAc,CAA8B;IACnD,4DAA4D;IACrD,WAAW,CAA2B;IAC7C,0EAA0E;IACnE,gBAAgB,CAAmB;IAE1C,+EAA+E;IACxE,aAAa,GAAsB,EAAE,CAAC;IAE7C;;;;;;OAMG;IACH,YACS,EAAU,EACV,MAAiB,EACjB,WAA0C;QAEjD,KAAK,EAAE,CAAC;QAJD,OAAE,GAAF,EAAE,CAAQ;QACV,WAAM,GAAN,MAAM,CAAW;QACjB,gBAAW,GAAX,WAAW,CAA+B;QAGjD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,gBAAgB,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAChD,CAAC;IAED,gFAAgF;IACzE,QAAQ,CAAC,KAAa;QAC3B,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,+DAA+D;IACxD,KAAK,CAAC,IAAI;QACf,IAAI,CAAC,cAAc,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,qFAAqF;IAC9E,KAAK,CAAC,gBAAgB,CAC3B,KAAa,EACb,MAA6B;QAE7B,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAExE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE;YAC3B,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE;gBAClC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACjC,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,oDAAoD;IAC7C,KAAK,CAAC,WAAW,CAAC,IAAS;QAChC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC3C,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,qEAAqE;IAC9D,WAAW;QAChB,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QAC/C,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,0FAA0F;IAC1F,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC;YAC/B,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC/B,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAClC,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
/** Sends a plain text HTTP response with the provided status code. */
|
|
3
|
+
export declare function sendStatus(res: express.Response, code: number, msg: string): void;
|
|
4
|
+
/** Sends an object as a JSON HTTP 200 response. */
|
|
5
|
+
export declare function sendJson(res: express.Response, obj: object): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Sends a plain text HTTP response with the provided status code. */
|
|
2
|
+
export function sendStatus(res, code, msg) {
|
|
3
|
+
res.status(code);
|
|
4
|
+
res.setHeader('Content-Type', 'text/plain');
|
|
5
|
+
res.end(msg);
|
|
6
|
+
}
|
|
7
|
+
/** Sends an object as a JSON HTTP 200 response. */
|
|
8
|
+
export function sendJson(res, obj) {
|
|
9
|
+
res.status(200);
|
|
10
|
+
res.setHeader('Content-Type', 'application/json');
|
|
11
|
+
res.end(JSON.stringify(obj));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../../../src/webrtc/http/helpers.ts"],"names":[],"mappings":"AAEA,sEAAsE;AACtE,MAAM,UAAU,UAAU,CAAC,GAAqB,EAAE,IAAY,EAAE,GAAW;IACzE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;IAC5C,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,QAAQ,CAAC,GAAqB,EAAE,GAAW;IACzD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;IAClD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { ServerOptions } from '../../server/server-options.js';
|
|
3
|
+
import ConnectionsManager from '../datachannel/connections-manager.js';
|
|
4
|
+
/** Mounts the HTTP signaling routes needed by the browser client. */
|
|
5
|
+
export default class HttpServer {
|
|
6
|
+
app: express.Application;
|
|
7
|
+
connectionsManager: ConnectionsManager;
|
|
8
|
+
/** URL prefix where signaling routes are installed. */
|
|
9
|
+
private apiBasePath;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a signaling route installer.
|
|
12
|
+
*
|
|
13
|
+
* @param app Express app to receive signaling routes.
|
|
14
|
+
* @param connectionsManager Connection manager used by route handlers.
|
|
15
|
+
* @param options Server options containing the optional API base path.
|
|
16
|
+
*/
|
|
17
|
+
constructor(app: express.Application, connectionsManager: ConnectionsManager, options: ServerOptions);
|
|
18
|
+
/** Registers connection, answer, candidate, and close routes on the Express app. */
|
|
19
|
+
setupRoutes(): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { closeConnection, createConnection, getIceCandidates, setRemoteDesc, } from './routes.js';
|
|
2
|
+
/** Default URL prefix used by the dgram signaling API. */
|
|
3
|
+
const DEFAULT_API_BASE_PATH = '/rtc/v1';
|
|
4
|
+
/** Mounts the HTTP signaling routes needed by the browser client. */
|
|
5
|
+
export default class HttpServer {
|
|
6
|
+
app;
|
|
7
|
+
connectionsManager;
|
|
8
|
+
/** URL prefix where signaling routes are installed. */
|
|
9
|
+
apiBasePath;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a signaling route installer.
|
|
12
|
+
*
|
|
13
|
+
* @param app Express app to receive signaling routes.
|
|
14
|
+
* @param connectionsManager Connection manager used by route handlers.
|
|
15
|
+
* @param options Server options containing the optional API base path.
|
|
16
|
+
*/
|
|
17
|
+
constructor(app, connectionsManager, options) {
|
|
18
|
+
this.app = app;
|
|
19
|
+
this.connectionsManager = connectionsManager;
|
|
20
|
+
this.apiBasePath = options.apiBasePath || DEFAULT_API_BASE_PATH;
|
|
21
|
+
}
|
|
22
|
+
/** Registers connection, answer, candidate, and close routes on the Express app. */
|
|
23
|
+
setupRoutes() {
|
|
24
|
+
this.app.post(`${this.apiBasePath}/connection`, createConnection.bind(null, this.connectionsManager));
|
|
25
|
+
this.app.post(`${this.apiBasePath}/connection/:id/remote-desc`, setRemoteDesc.bind(null, this.connectionsManager));
|
|
26
|
+
this.app.get(`${this.apiBasePath}/connection/:id/candidates`, getIceCandidates.bind(null, this.connectionsManager));
|
|
27
|
+
this.app.post(`${this.apiBasePath}/connection/:id/close`, closeConnection.bind(null, this.connectionsManager));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=http-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.js","sourceRoot":"","sources":["../../../../../src/webrtc/http/http-server.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,GACd,MAAM,aAAa,CAAC;AAErB,0DAA0D;AAC1D,MAAM,qBAAqB,GAAG,SAAS,CAAC;AAExC,qEAAqE;AACrE,MAAM,CAAC,OAAO,OAAO,UAAU;IAYpB;IACA;IAZT,uDAAuD;IAC/C,WAAW,CAAC;IAEpB;;;;;;OAMG;IACH,YACS,GAAwB,EACxB,kBAAsC,EAC7C,OAAsB;QAFf,QAAG,GAAH,GAAG,CAAqB;QACxB,uBAAkB,GAAlB,kBAAkB,CAAoB;QAG7C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,qBAAqB,CAAC;IAClE,CAAC;IAED,oFAAoF;IAC7E,WAAW;QAChB,IAAI,CAAC,GAAG,CAAC,IAAI,CACX,GAAG,IAAI,CAAC,WAAW,aAAa,EAChC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,CACrD,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,IAAI,CACX,GAAG,IAAI,CAAC,WAAW,6BAA6B,EAChD,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAClD,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,GAAG,CACV,GAAG,IAAI,CAAC,WAAW,4BAA4B,EAC/C,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,CACrD,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,IAAI,CACX,GAAG,IAAI,CAAC,WAAW,uBAAuB,EAC1C,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,CACpD,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import ConnectionsManager from '../datachannel/connections-manager.js';
|
|
3
|
+
/** Creates a server WebRTC peer and returns its id plus local SDP offer. */
|
|
4
|
+
export declare function createConnection(connectionMgr: ConnectionsManager, req: express.Request, res: express.Response): Promise<void>;
|
|
5
|
+
/** Stores the browser SDP answer on an existing server peer. */
|
|
6
|
+
export declare function setRemoteDesc(connectionMgr: ConnectionsManager, req: express.Request, res: express.Response): void;
|
|
7
|
+
/** Closes an existing server peer connection. */
|
|
8
|
+
export declare function closeConnection(connectionMgr: ConnectionsManager, req: express.Request, res: express.Response): void;
|
|
9
|
+
/** Returns pending server ICE candidates and clears the candidate queue. */
|
|
10
|
+
export declare function getIceCandidates(connectionMgr: ConnectionsManager, req: express.Request, res: express.Response): void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { sendJson, sendStatus } from './helpers.js';
|
|
2
|
+
/** Creates a server WebRTC peer and returns its id plus local SDP offer. */
|
|
3
|
+
export async function createConnection(connectionMgr, req, res) {
|
|
4
|
+
const conn = await connectionMgr.createConnection();
|
|
5
|
+
if (!conn) {
|
|
6
|
+
sendStatus(res, 500, 'There was a problem creating the datachannel connection');
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
sendJson(res, {
|
|
10
|
+
id: conn.id,
|
|
11
|
+
localDescription: conn.localDescription,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
/** Stores the browser SDP answer on an existing server peer. */
|
|
15
|
+
export function setRemoteDesc(connectionMgr, req, res) {
|
|
16
|
+
const connId = req.params.id;
|
|
17
|
+
if (!connId) {
|
|
18
|
+
sendStatus(res, 400, 'Connection id is empty');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const conn = connectionMgr.getConnection(connId);
|
|
23
|
+
if (!conn || !conn.peerConnection) {
|
|
24
|
+
sendStatus(res, 404, 'Connection not found');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
conn.peerConnection.setRemoteDescription(req.body.sdp, req.body.type);
|
|
28
|
+
sendStatus(res, 200, '');
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
console.log(err);
|
|
32
|
+
sendStatus(res, 500, '');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Closes an existing server peer connection. */
|
|
36
|
+
export function closeConnection(connectionMgr, req, res) {
|
|
37
|
+
const connId = req.params.id;
|
|
38
|
+
if (!connId) {
|
|
39
|
+
sendStatus(res, 400, 'Connection id is empty');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const conn = connectionMgr.getConnection(connId);
|
|
44
|
+
if (!conn || !conn.peerConnection) {
|
|
45
|
+
sendStatus(res, 404, 'Connection not found');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
conn.peerConnection.close();
|
|
49
|
+
sendStatus(res, 200, '');
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
console.log(err);
|
|
53
|
+
sendStatus(res, 500, '');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Returns pending server ICE candidates and clears the candidate queue. */
|
|
57
|
+
export function getIceCandidates(connectionMgr, req, res) {
|
|
58
|
+
const connId = req.params.id;
|
|
59
|
+
if (!connId) {
|
|
60
|
+
sendStatus(res, 400, 'Connection id is empty');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const conn = connectionMgr.getConnection(connId);
|
|
65
|
+
if (!conn || !conn.peerConnection) {
|
|
66
|
+
sendStatus(res, 404, 'Connection not found');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const iceCandidates = [...conn.iceCandidates];
|
|
70
|
+
conn.iceCandidates = [];
|
|
71
|
+
sendJson(res, iceCandidates);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
console.log(err);
|
|
75
|
+
sendStatus(res, 500, '');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../../../src/webrtc/http/routes.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vworlds/dgram-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dgram-server/src/index.js",
|
|
6
|
+
"types": "./dgram-server/src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dgram-server/src/index.d.ts",
|
|
10
|
+
"default": "./dgram-server/src/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"eventemitter3": "^4.0.7",
|
|
15
|
+
"express": "^4.18.2",
|
|
16
|
+
"node-datachannel": "^0.32.3"
|
|
17
|
+
},
|
|
18
|
+
"license": "UNLICENSED"
|
|
19
|
+
}
|