Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import * as WebSocket from 'ws'
- // -------------------------------------------------------
- //
- // Binding
- //
- // Message sent immediately on socket connection. The
- // binding message contains the client sockets address
- // (or socket identifier) and webrtc connection info.
- //
- // -------------------------------------------------------
- export interface Binding {
- type: 'binding'
- address: string
- configuration: RTCConfiguration
- }
- // -------------------------------------------------------
- //
- // Forward
- //
- // Message sent from one user to another through via the
- // server. The forwarded message is the primary exchange
- // type for webrtc negotiation where data T is understood
- // by negotiating clients.
- //
- // -------------------------------------------------------
- export interface Forward<T = any> {
- type: 'forward'
- from: string
- to: string
- data: T
- }
- // -------------------------------------------------------
- //
- // Address
- //
- // Simple address allocator. Fakes IPv4 looking
- // addresses. Is used by the server to allocate
- // unique addresses to sockets on connection.
- //
- // -------------------------------------------------------
- export class Address {
- private index: number = 0
- public next(): string {
- this.index += 1
- const bounds = [256, 256, 256, 256]
- const address = bounds.reduce<[number[], number]>(
- (state, rank, index) => {
- state[0][index] = Math.floor((this.index / state[1]) % rank)
- state[1] *= rank
- return state
- },
- [Array.from({ length: bounds.length }), 1]
- )[0]
- return address.join('.')
- }
- }
- // -------------------------------------------------------
- //
- // Server
- //
- // Simple smoke webrtc signalling server. Implements the
- // smoke signalling protocol for connecting clients in a
- // smoke network.
- //
- // -------------------------------------------------------
- export class Server {
- private server!: WebSocket.Server
- private sockets: Map<string, WebSocket>
- private address: Address
- constructor(private configuration: RTCConfiguration) {
- this.sockets = new Map<string, WebSocket>()
- this.address = new Address()
- }
- /** Handles incoming connections */
- private onConnection(socket: WebSocket) {
- const configuration = this.configuration
- const address = this.address.next()
- const type = 'binding'
- socket.send(JSON.stringify({ type, address, configuration } as Binding))
- socket.on('message', data => this.onMessage(address, data))
- socket.on('error', error => this.onError(address, error))
- socket.on('close', () => this.onClose(address))
- this.sockets.set(address, socket)
- }
- /** Handles an incoming message from the given address. */
- private onMessage(address: string, data: WebSocket.Data) {
- try {
- const message = JSON.parse(data as string) as Forward
- if (message.type === 'forward') {
- this.onForward(address, message)
- }
- } catch (error) {
- const socket = this.sockets.get(address)!
- socket.close(1003, 'protocol violation')
- this.sockets.delete(address)
- }
- }
- /** Handles an incoming forward request. */
- private onForward(address: string, forward: Forward) {
- if (!this.sockets.has(forward.to)) {
- return
- }
- const socket = this.sockets.get(forward.to)!
- const type = 'forward'
- const from = address
- const to = forward.to
- const data = forward.data
- socket.send(JSON.stringify({ type, from, to, data } as Forward))
- }
- /** Handles the socket keepalive. */
- private onKeepAlive() {
- for (const key in this.sockets.keys()) {
- const socket = this.sockets.get(key)!
- socket.ping()
- }
- }
- /** Handles socket on error events. */
- private onError(address: string, error: Error) {
- console.error(address, error)
- }
- /** Handles socket on close events. */
- private onClose(address: string) {
- this.sockets.delete(address)
- }
- /** Starts this server listening on the given port. */
- public listen(port: number) {
- this.server = new WebSocket.Server({ port })
- this.server.on('connection', socket => this.onConnection(socket))
- setInterval(() => this.onKeepAlive(), 16000)
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement