lib/socket.js
function find() {
      // If there is no remaining URI, fires `error` and `close` event as it means that all
      // tries failed.
      if (uris.length === 0) {
        // Now that `connecting` event is being fired, there is no `error` and `close` event user
        // added. Delays to fire them a little while.
        setTimeout(function() {
          self.emit("error", new Error());
          self.emit("close");
        }, 0);
        return;
      }
      // A temporal variable to be used while finding working one.
      var testTransport;
      // Get the first uri by removing it from `uris`. For example, `[1,2].shift()` returns `1`
      // and make the array `[2]`.
      var uri = uris.shift();
      // Transport handles only the specific types of URIs. It finds which transport factory can
      // handle this `uri` among ones specified by `transports` option.
      for (var i = 0; i < options.transports.length; i++) {
        // A transport factory creates and returns a transport object if it can handle the given
        // URI and nothing if not.
        testTransport = options.transports[i](uri, options);
        // If the factory handles this type of URI,
        if (testTransport) {
          break;
        }
      }
      // If there is no transport matching with the given URI, try with the next URI.
      if (!testTransport) {
        find();
        return;
      }
      // This is to stop the whole process to find a working transport when the `close` method
      // is called before `open` event.
      function stop() {
        testTransport.removeListener("close", find);
        testTransport.close();
      }

      // Until the socket is opened, `close` method should trigger `stop` function as well.
      self.once("close", stop);
      // It establishes a connection.
      testTransport.open();
      // If it fails, it should remove stop listener and try with the next URI. These event handlers
      // will be removed once this transport is recognized as working.
      testTransport.on("close", function() {
        self.removeListener("close", stop);
      });
      testTransport.on("close", find);
      // Node.js kills the process by default when an `error` event is fired if there is no
      // listener for it. However, a user doesn't need to be notified of an error from this
      // transport being tested.
      testTransport.on("error", function() {
      });
      // If it succeeds, it means that the process to find working transport is done. The first
      // transport text message is used to handshake the socket protocol. Note that `once`
      // registers one-time event handler.
      testTransport.once("text", function(text) {
        // The handshake output is in the form of URI. Query params starting with `cettia-`
        // represent protocol header.
        var headers = url.parse(text, true).query;
        // The server prints an id of the socket as a `cettia-id` param, `id` header,
        // every time the transport connects. If the server issues a new id,
        if (id !== headers["cettia-id"]) {
          // That means there was no `id` or the server socket whose id is `id` was deleted in
          // the server due to long-term disconnection.
          id = headers["cettia-id"];
          // Fires a `new` event as a new socket is created.
          self.emit("new");
        }

        // To maintain an alive connection, `heartbeat` is used.
        options.heartbeat = +headers["cettia-heartbeat"];
        // `_heartbeat` is for testing so it should be not passed from the server in production.
        // The default value is `5000`.
        options._heartbeat = +headers["cettia-_heartbeat"] || 5000;
        // Now that the working transport is found and handshaking is completed, it stops
        // a process to find a working transport by removing `close` event handler `find` and
        // associates the working transport with the socket.
        testTransport.removeListener("close", find);
        transport = testTransport;

        // When an event object is created from `text` or `binary` event,
        function onevent(event) {
          // Event should have the following properties:
          // * `id: string`: an event identifier.
          // * `type: string`: an event type.
          // * `data: any`: an event data.
          // * `reply: boolean`: `true` if this event requires the reply.

          // If the server sends a plain event, dispatch it.
          if (!event.reply) {
            self.emit(event.type, event.data);
          } else {
            var latch;
            // A function to create a function.
            function reply(success) {
              // A controller function.
              return function(value) {
                // This latch prevents double reply.
                if (!latch) {
                  latch = true;
                  self.send("reply", {id: event.id, data: value, exception: !success});
                }
              };
            }

            // Here, the controller is passed to the event handler as 2nd argument and
            // allows to call the server's `resolved` or `rejected` callback by sending
            // `reply` event.
            self.emit(event.type, event.data, {resolve: reply(true), reject: reply(false)});
          }
        }

        // When the transport has received a text message from the server,
        // it deserializes a text message into an event object in the JSON format and deals with it.
        transport.on("text", function(text) {
          onevent(JSON.parse(text));
        });
        // When the transport has received a binary message from the server.
        // it deserializes a binary message into an event object in the
        // [MessagePack](http://msgpack.org) format and deals with it.
        transport.on("binary", function(binary) {
          onevent(msgpack.decode(binary));
        });
        // When any error has occurred.
        transport.on("error", function(error) {
          self.emit("error", error);
        });
        // When the transport has been closed for any reason.
        transport.on("close", function() {
          self.emit("close");
        });
        // Now that the working transport is associated and the communication is possible,
        // it removes `close` event handler `stop` and fires `open` event.
        self.removeListener("close", stop);
        self.emit("open");
      });
    }
function find() {
      // If there is no remaining URI, fires `error` and `close` event as it means that all
      // tries failed.
      if (uris.length === 0) {
        // Now that `connecting` event is being fired, there is no `error` and `close` event user
        // added. Delays to fire them a little while.
        setTimeout(function() {
          self.emit("error", new Error());
          self.emit("close");
        }, 0);
        return;
      }
      // A temporal variable to be used while finding working one.
      var testTransport;
      // Get the first uri by removing it from `uris`. For example, `[1,2].shift()` returns `1`
      // and make the array `[2]`.
      var uri = uris.shift();
      // Transport handles only the specific types of URIs. It finds which transport factory can
      // handle this `uri` among ones specified by `transports` option.
      for (var i = 0; i < options.transports.length; i++) {
        // A transport factory creates and returns a transport object if it can handle the given
        // URI and nothing if not.
        testTransport = options.transports[i](uri, options);
        // If the factory handles this type of URI,
        if (testTransport) {
          break;
        }
      }
      // If there is no transport matching with the given URI, try with the next URI.
      if (!testTransport) {
        find();
        return;
      }
      // This is to stop the whole process to find a working transport when the `close` method
      // is called before `open` event.
      function stop() {
        testTransport.removeListener("close", find);
        testTransport.close();
      }

      // Until the socket is opened, `close` method should trigger `stop` function as well.
      self.once("close", stop);
      // It establishes a connection.
      testTransport.open();
      // If it fails, it should remove stop listener and try with the next URI. These event handlers
      // will be removed once this transport is recognized as working.
      testTransport.on("close", function() {
        self.removeListener("close", stop);
      });
      testTransport.on("close", find);
      // Node.js kills the process by default when an `error` event is fired if there is no
      // listener for it. However, a user doesn't need to be notified of an error from this
      // transport being tested.
      testTransport.on("error", function() {
      });
      // If it succeeds, it means that the process to find working transport is done. The first
      // transport text message is used to handshake the socket protocol. Note that `once`
      // registers one-time event handler.
      testTransport.once("text", function(text) {
        // The handshake output is in the form of URI. Query params starting with `cettia-`
        // represent protocol header.
        var headers = url.parse(text, true).query;
        // The server prints an id of the socket as a `cettia-id` param, `id` header,
        // every time the transport connects. If the server issues a new id,
        if (id !== headers["cettia-id"]) {
          // That means there was no `id` or the server socket whose id is `id` was deleted in
          // the server due to long-term disconnection.
          id = headers["cettia-id"];
          // Fires a `new` event as a new socket is created.
          self.emit("new");
        }

        // To maintain an alive connection, `heartbeat` is used.
        options.heartbeat = +headers["cettia-heartbeat"];
        // `_heartbeat` is for testing so it should be not passed from the server in production.
        // The default value is `5000`.
        options._heartbeat = +headers["cettia-_heartbeat"] || 5000;
        // Now that the working transport is found and handshaking is completed, it stops
        // a process to find a working transport by removing `close` event handler `find` and
        // associates the working transport with the socket.
        testTransport.removeListener("close", find);
        transport = testTransport;

        // When an event object is created from `text` or `binary` event,
        function onevent(event) {
          // Event should have the following properties:
          // * `id: string`: an event identifier.
          // * `type: string`: an event type.
          // * `data: any`: an event data.
          // * `reply: boolean`: `true` if this event requires the reply.

          // If the server sends a plain event, dispatch it.
          if (!event.reply) {
            self.emit(event.type, event.data);
          } else {
            var latch;
            // A function to create a function.
            function reply(success) {
              // A controller function.
              return function(value) {
                // This latch prevents double reply.
                if (!latch) {
                  latch = true;
                  self.send("reply", {id: event.id, data: value, exception: !success});
                }
              };
            }

            // Here, the controller is passed to the event handler as 2nd argument and
            // allows to call the server's `resolved` or `rejected` callback by sending
            // `reply` event.
            self.emit(event.type, event.data, {resolve: reply(true), reject: reply(false)});
          }
        }

        // When the transport has received a text message from the server,
        // it deserializes a text message into an event object in the JSON format and deals with it.
        transport.on("text", function(text) {
          onevent(JSON.parse(text));
        });
        // When the transport has received a binary message from the server.
        // it deserializes a binary message into an event object in the
        // [MessagePack](http://msgpack.org) format and deals with it.
        transport.on("binary", function(binary) {
          onevent(msgpack.decode(binary));
        });
        // When any error has occurred.
        transport.on("error", function(error) {
          self.emit("error", error);
        });
        // When the transport has been closed for any reason.
        transport.on("close", function() {
          self.emit("close");
        });
        // Now that the working transport is associated and the communication is possible,
        // it removes `close` event handler `stop` and fires `open` event.
        self.removeListener("close", stop);
        self.emit("open");
      });
    }
function find ( ) { // If there is no remaining URI, fires `error` and `close` event as it means that all // tries failed. if ( uris . length === 0 ) { // Now that `connecting` event is being fired, there is no `error` and `close` event user // added. Delays to fire them a little while. setTimeout ( function ( ) { self . emit ( "error" , new Error ( ) ) ; self . emit ( "close" ) ; } , 0 ) ; return ; } // A temporal variable to be used while finding working one. var testTransport ; // Get the first uri by removing it from `uris`. For example, `[1,2].shift()` returns `1` // and make the array `[2]`. var uri = uris . shift ( ) ; // Transport handles only the specific types of URIs. It finds which transport factory can // handle this `uri` among ones specified by `transports` option. for ( var i = 0 ; i < options . transports . length ; i ++ ) { // A transport factory creates and returns a transport object if it can handle the given // URI and nothing if not. testTransport = options . transports [ i ] ( uri , options ) ; // If the factory handles this type of URI, if ( testTransport ) { break ; } } // If there is no transport matching with the given URI, try with the next URI. if ( ! testTransport ) { find ( ) ; return ; } // This is to stop the whole process to find a working transport when the `close` method // is called before `open` event. function stop ( ) { testTransport . removeListener ( "close" , find ) ; testTransport . close ( ) ; } // Until the socket is opened, `close` method should trigger `stop` function as well. self . once ( "close" , stop ) ; // It establishes a connection. testTransport . open ( ) ; // If it fails, it should remove stop listener and try with the next URI. These event handlers // will be removed once this transport is recognized as working. testTransport . on ( "close" , function ( ) { self . removeListener ( "close" , stop ) ; } ) ; testTransport . on ( "close" , find ) ; // Node.js kills the process by default when an `error` event is fired if there is no // listener for it. However, a user doesn't need to be notified of an error from this // transport being tested. testTransport . on ( "error" , function ( ) { } ) ; // If it succeeds, it means that the process to find working transport is done. The first // transport text message is used to handshake the socket protocol. Note that `once` // registers one-time event handler. testTransport . once ( "text" , function ( text ) { // The handshake output is in the form of URI. Query params starting with `cettia-` // represent protocol header. var headers = url . parse ( text , true ) . query ; // The server prints an id of the socket as a `cettia-id` param, `id` header, // every time the transport connects. If the server issues a new id, if ( id !== headers [ "cettia-id" ] ) { // That means there was no `id` or the server socket whose id is `id` was deleted in // the server due to long-term disconnection. id = headers [ "cettia-id" ] ; // Fires a `new` event as a new socket is created. self . emit ( "new" ) ; } // To maintain an alive connection, `heartbeat` is used. options . heartbeat = + headers [ "cettia-heartbeat" ] ; // `_heartbeat` is for testing so it should be not passed from the server in production. // The default value is `5000`. options . _heartbeat = + headers [ "cettia-_heartbeat" ] || 5000 ; // Now that the working transport is found and handshaking is completed, it stops // a process to find a working transport by removing `close` event handler `find` and // associates the working transport with the socket. testTransport . removeListener ( "close" , find ) ; transport = testTransport ; // When an event object is created from `text` or `binary` event, function onevent ( event ) { // Event should have the following properties: // * `id: string`: an event identifier. // * `type: string`: an event type. // * `data: any`: an event data. // * `reply: boolean`: `true` if this event requires the reply. // If the server sends a plain event, dispatch it. if ( ! event . reply ) { self . emit ( event . type , event . data ) ; } else { var latch ; // A function to create a function. function reply ( success ) { // A controller function. return function ( value ) { // This latch prevents double reply. if ( ! latch ) { latch = true ; self . send ( "reply" , { id : event . id , data : value , exception : ! success } ) ; } } ; } // Here, the controller is passed to the event handler as 2nd argument and // allows to call the server's `resolved` or `rejected` callback by sending // `reply` event. self . emit ( event . type , event . data , { resolve : reply ( true ) , reject : reply ( false ) } ) ; } } // When the transport has received a text message from the server, // it deserializes a text message into an event object in the JSON format and deals with it. transport . on ( "text" , function ( text ) { onevent ( JSON . parse ( text ) ) ; } ) ; // When the transport has received a binary message from the server. // it deserializes a binary message into an event object in the // [MessagePack](http://msgpack.org) format and deals with it. transport . on ( "binary" , function ( binary ) { onevent ( msgpack . decode ( binary ) ) ; } ) ; // When any error has occurred. transport . on ( "error" , function ( error ) { self . emit ( "error" , error ) ; } ) ; // When the transport has been closed for any reason. transport . on ( "close" , function ( ) { self . emit ( "close" ) ; } ) ; // Now that the working transport is associated and the communication is possible, // it removes `close` event handler `stop` and fires `open` event. self . removeListener ( "close" , stop ) ; self . emit ( "open" ) ; } ) ; }
Starts a process to find a working transport.
Starts a process to find a working transport .