Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2017
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { Flow } from "./async"
  2.  
  3. export type WebSocketConnectFunction    = ()           => void
  4. export type WebSocketMessageFunction    = (data : any) => void
  5. export type WebSocketErrorFunction      = (error: any) => void
  6. export type WebSocketDisconnectFunction = ()           => void
  7.  
  8. export class Socket {
  9.   private _connect    : WebSocketConnectFunction    = function() {}
  10.   private _message    : WebSocketMessageFunction    = function() {}
  11.   private _error      : WebSocketErrorFunction      = function() {}
  12.   private _disconnect : WebSocketDisconnectFunction = function() {}
  13.   private _connected  : boolean                     = false
  14.   private _flow       : Flow                        = undefined
  15.   private _socket     : WebSocket                   = undefined
  16.  
  17.   /**
  18.    * creates a new web socket connection
  19.    * @param {SocketOptions} options the web socket options.
  20.    * @returns {Socket}
  21.    */
  22.   constructor(private endpoint: string) {
  23.     this._flow             = new Flow()
  24.     this._socket           = new WebSocket(endpoint)
  25.     this._socket.onopen    = ()      => this.handle_connect   ()
  26.     this._socket.onmessage = (data)  => this.handle_message   (data)
  27.     this._socket.onerror   = (error) => this.handle_error     (error)
  28.     this._socket.onclose   = ()      => this.handle_disconnect()
  29.   }
  30.  
  31.   /**
  32.    * subscribes to the socket connect event.
  33.    * @param {WebSocketConnectFunction} func the listener function.
  34.    * @returns {void}
  35.    */
  36.   public connect    (func: WebSocketConnectFunction):    void { this._connect    = func }
  37.  
  38.   /**
  39.    * subscribes to the socket message event.
  40.    * @param {WebSocketMessageFunction} func the listener function.
  41.    * @returns {void}
  42.    */
  43.   public message    (func: WebSocketMessageFunction):    void { this._message    = func }
  44.  
  45.   /**
  46.    * subscribes to the socket error event.
  47.    * @param {WebSocketErrorFunction} func the listener function.
  48.    * @returns {void}
  49.    */
  50.   public error    (func: WebSocketErrorFunction):    void { this._error    = func }
  51.  
  52.   /**
  53.    * subscribes to the socket disconnect event.
  54.    * @param {WebSocketDisconnectFunction} func the listener function.
  55.    * @returns {void}
  56.    */
  57.   public disconnect (func: WebSocketDisconnectFunction): void { this._disconnect = func }
  58.  
  59.   /**
  60.    * sends a message to the server.
  61.    * @param {any} data the data to send.
  62.    * @returns {Promise<any>}
  63.    */
  64.   public send       (data: any): Promise<any> {
  65.     return this._flow.run(() => this._socket.send(JSON.stringify(data)))
  66.   }
  67.  
  68.   /**
  69.    * handles the connect event.
  70.    * @returns {void}
  71.    */
  72.   private handle_connect(): void {
  73.     this._connect()
  74.     this._connected = true
  75.     this._flow.resume()
  76.   }
  77.  
  78.   /**
  79.    * handles incoming messages
  80.    * @param {any} data the data being received.
  81.    * @returns {void}
  82.    */
  83.   private handle_message(data: MessageEvent): void {
  84.     try {
  85.       const message = JSON.parse(data.data)
  86.       this._message(message)
  87.     } catch(error) {
  88.       this.handle_error(error)
  89.     }
  90.   }
  91.  
  92.   /**
  93.    * handles error events on this socket.
  94.    * @param {any} error the error.
  95.    * @returns {void}
  96.    */
  97.   private handle_error(error: any): void {
  98.     this._error(error)
  99.   }
  100.  
  101.   /**
  102.    * handles the socket disconnect event.
  103.    * @returns {void}
  104.    */
  105.   private handle_disconnect(): void {
  106.     this._disconnect()
  107.   }
  108. }
  109.  
  110.  
  111. export type Address   = { type: "address",   id?: string, address?: string }
  112. export type Offer     = { type: "offer",     id?: string, from: string, to: string, data: any }
  113. export type Answer    = { type: "answer",    id?: string, from: string, to: string, data: any }
  114. export type Candidate = { type: "candidate", id?: string, from: string, to: string, data: any }
  115. export type Message   = Address | Offer | Answer | Candidate
  116.  
  117. export type OfferFunction     = (offer    : Offer)     => void
  118. export type AnswerFunction    = (answer   : Answer)    => void
  119. export type CandidateFunction = (candidate: Candidate) => void
  120.  
  121. /**
  122.  * Hub
  123.  *
  124.  * Represents a clients connection to the network. The hub
  125.  * faciliates webrtc offer/answer/candidate exchange, and
  126.  * also provides the ability for the client to request
  127.  * their network address.
  128.  */
  129. export class Hub {
  130.  
  131.   private _socket   : Socket
  132.   private _offer    : OfferFunction       = function() {}
  133.   private _answer   : AnswerFunction      = function() {}
  134.   private _candidate: CandidateFunction   = function() {}
  135.   private _address  : string              = ""
  136.   private _flow     : Flow                = undefined
  137.  
  138.   /**
  139.    * creates a new hub connection.
  140.    * @param {string} endpoint the hub endpoint to connect to.
  141.    * @returns {Hub}
  142.    */
  143.   constructor(private endpoint: string) {
  144.     this._flow   = new Flow()
  145.     this._socket = new Socket(endpoint)
  146.     this._socket.connect(this.connect.bind(this))
  147.     this._socket.message(this.message.bind(this))
  148.     this._socket.disconnect(this.disconnect.bind(this))
  149.   }
  150.  
  151.   /**
  152.    * returns this hubs address within the wider network.
  153.    * @returns {Promise<string>}
  154.    */
  155.   public address  (): Promise<string> {
  156.     return this._flow.run(() => this._address)
  157.   }
  158.   /**
  159.    * subscribes to incoming offers.
  160.    * @param {OfferFunction} func the offer listening function.
  161.    * @returns {void}
  162.    */
  163.   public onOffer     (func: OfferFunction): void { this._offer = func }
  164.  
  165.   /**
  166.    * subscribes to incoming answers.
  167.    * @param {OfferFunction} func the answer listening function.
  168.    * @returns {void}
  169.    */
  170.   public onAnswer    (func: AnswerFunction): void { this._answer = func }
  171.  
  172.   /**
  173.    * subscribes to incoming candidates.
  174.    * @param {OfferFunction} func the candidate listening function.
  175.    * @returns {void}
  176.    */
  177.   public onCandidate (func: CandidateFunction): void { this._candidate = func }
  178.  
  179.   /**
  180.    * sends an offer to the network.
  181.    * @param {Offer} offer the offer to send.
  182.    * @returns {Promise<any>}
  183.    */
  184.   public sendOffer(offer: Offer): Promise<any> {
  185.     return this._flow.run(() => this._socket.send(offer))
  186.   }
  187.  
  188.   /**
  189.    * sends an answer to the network.
  190.    * @param {Answer} answer the answer to send.
  191.    * @returns {Promise<any>}
  192.    */
  193.   public sendAnswer(answer: Answer): Promise<any> {
  194.     return this._flow.run(() => this._socket.send(answer))
  195.   }
  196.  
  197.   /**
  198.    * sends a candidate to the network.
  199.    * @param {Candidate} candidate the candidate to send.
  200.    * @returns {Promise<any>}
  201.    */
  202.   public sendCandidate(candidate: Candidate): Promise<any> {
  203.     return this._flow.run(() => this._socket.send(candidate))
  204.   }
  205.  
  206.   /**
  207.    * handles socket connection events.
  208.    * @returns {void}
  209.    */
  210.   private connect   () : void { }
  211.  
  212.   /**
  213.    * handles socket disconnect events.
  214.    * @returns {void}
  215.    */
  216.   private disconnect() : void { }
  217.  
  218.   /**
  219.    * handles incoming network messages
  220.    * @param {Message} message the incoming message.
  221.    * @returns {void}
  222.    */
  223.   private message(message: Message): void {
  224.     switch(message.type) {
  225.       case "address": {
  226.         this._address = message.address
  227.         this._flow.resume()
  228.         break;
  229.       }
  230.       case "offer":      this._offer(message);     break;
  231.       case "answer":     this._answer(message);    break;
  232.       case "candidate":  this._candidate(message); break;
  233.     }
  234.   }
  235. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement