title: TypeError: fn.bind is not a function
body: <p>I am trying to implement webRTC from the RealTime communication with WebRTC book and I am getting the below errors. I am using socket.io 1.7.3 version</p>
  
  <pre><code>***Server.js***
  
  C:\Users\raghav\node_modules\socket.io-adapter\index.js:196
    if (fn) process.nextTick(fn.bind(null, null, sids));
                                ^
  
  TypeError: fn.bind is not a function
      at Adapter.clients (C:\Users\raghav\node_modules\socket.io-adapter\index.js:196:31)
      at Namespace.clients (C:\Users\raghav\node_modules\socket.io\lib\namespace.js:256:16)
      at Socket.&lt;anonymous&gt; (C:\Users\raghav\WebstormProjects\NewsRoom\js\server.js:22:37)
      at emitOne (events.js:96:13)
      at Socket.emit (events.js:188:7)
      at C:\Users\raghav\node_modules\socket.io\lib\socket.js:503:12
      at _combinedTickCallback (internal/process/next_tick.js:73:7)
      at process._tickCallback (internal/process/next_tick.js:104:9)
  
  Process finished with exit code 1
  
  **webRTc.HTML**
  
  Failed to load resource: net::ERR_CONNECTION_REFUSED
  GET http://localhost:8181/socket.io/?EIO=3&amp;transport=polling&amp;t=LkCudeu net::ERR_CONNECTION_REFUSED
  </code></pre>
  
  <p>Below is the code i used </p>
  
  <p>webRTC.html</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;rag
  &lt;head&gt;
      &lt;title&gt;Very simple WebRTC application with a Node.js signaling server&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
  &lt;div id='mainDiv'&gt;
      &lt;table border="1" width="100%"&gt;
          &lt;tr&gt;
              &lt;th&gt;
                  Local video
              &lt;/th&gt;
              &lt;th&gt;
                  Remote video
              &lt;/th&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td&gt;
                  &lt;video id="localVideo" autoplay&gt;&lt;/video&gt;
              &lt;/td&gt;
              &lt;td&gt;
                  &lt;video id="remoteVideo" autoplay&gt;&lt;/video&gt;
              &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td align="center"&gt;
  &lt;textarea rows="4" cols="60"
            id="dataChannelSend" disabled
            placeholder="This will be enabled once
  the data channel is up..."&gt;
  &lt;/textarea&gt;
              &lt;/td&gt;
              &lt;td align="center"&gt;
  &lt;textarea rows="4" cols="60"
            id="dataChannelReceive" disabled&gt;
  &lt;/textarea&gt;
              &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
              &lt;td align="center"&gt;
                  &lt;button id="sendButton" disabled&gt;Send&lt;/button&gt;
              &lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/table&gt;
  &lt;/div&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"&gt;&lt;/script&gt;
  
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/adapterjs/0.14.1/adapter.min.js"&gt;&lt;/script&gt;
  &lt;script src='js/completeNodeClientWithDataChannel.js'&gt;&lt;/script&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>completeNodeClientWithDataChannel.js</p>
  
  <pre><code>'use strict';
  // Look after different browser vendors' ways of calling the getUserMedia()
  // API method:
  // Opera --&gt; getUserMedia
  // Chrome --&gt; webkitGetUserMedia
  // Firefox --&gt; mozGetUserMedia
  navigator.getUserMedia = navigator.getUserMedia ||
      navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
  // Clean-up function:
  // collect garbage before unloading browser's window
  window.onbeforeunload = function(e){
      hangup();
  }
  // Data channel information
  var sendChannel, receiveChannel;
  var sendButton = document.getElementById("sendButton");
  var sendTextarea = document.getElementById("dataChannelSend");
  var receiveTextarea = document.getElementById("dataChannelReceive");
  // HTML5 &lt;video&gt; elements
  var localVideo = document.querySelector('#localVideo');
  var remoteVideo = document.querySelector('#remoteVideo');
  // Handler associated with Send button
  sendButton.onclick = sendData;
  // Flags...
  var isChannelReady = false;
  var isInitiator = false;
  var isStarted = false;
  // WebRTC data structures
  // Streams
  var localStream;
  var remoteStream;
  // PeerConnection
  var pc;
  // PeerConnection ICE protocol configuration (either Firefox or Chrome)
  var pc_config = webrtcDetectedBrowser === 'firefox' ?
      {'iceServers':[{'url':'stun:23.21.150.121'}]} : // IP address
      {'iceServers': [{'url': 'stun:stun.l.google.com:19302'}]};
  var pc_constraints = {
      'optional': [
          {'DtlsSrtpKeyAgreement': true}
      ]};
  var sdpConstraints = {};
  // Let's get started: prompt user for input (room name)
  var room = prompt('Enter room name:');
  // Connect to signaling server
  var socket = io.connect("http://131.95.31.179:8181");
  // Send 'Create or join' message to singnaling server
  if (room !== '') {
      console.log('Create or join room', room);
      socket.emit('create or join', room);
  }
  // Set getUserMedia constraints
  var constraints = {video: true, audio: true};
  // From this point on, execution proceeds based on asynchronous events...
  // getUserMedia() handlers...
  function handleUserMedia(stream) {
      localStream = stream;
      attachMediaStream(localVideo, stream);
      console.log('Adding local stream.');
      sendMessage('got user media');
  }
  function handleUserMediaError(error){
      console.log('navigator.getUserMedia error: ', error);
  }
  // Server-mediated message exchanging...
  // 1. Server--&gt;Client...
  // Handle 'created' message coming back from server:
  // this peer is the initiator
  socket.on('created', function (room){
      console.log('Created room ' + room);
      isInitiator = true;
  // Call getUserMedia()
      navigator.getUserMedia(constraints, handleUserMedia, handleUserMediaError);
      console.log('Getting user media with constraints', constraints);
      checkAndStart();
  });
  // Handle 'full' message coming back from server:
  // this peer arrived too late :-(
  socket.on('full', function (room){
      console.log('Room ' + room + ' is full');
  });
  // Handle 'join' message coming back from server:
  // another peer is joining the channel
  socket.on('join', function (room){
      console.log('Another peer made a request to join room ' + room);
      console.log('This peer is the initiator of room ' + room + '!');
      isChannelReady = true;
  });
  // Handle 'joined' message coming back from server:
  // this is the second peer joining the channel
  socket.on('joined', function (room){
      console.log('This peer has joined room ' + room);
      isChannelReady = true;
  // Call getUserMedia()
      navigator.getUserMedia(constraints, handleUserMedia, handleUserMediaError);
      console.log('Getting user media with constraints', constraints);
  });
  // Server-sent log message...
  socket.on('log', function (array){
      console.log.apply(console, array);
  });
  // Receive message from the other peer via the signaling server
  socket.on('message', function (message){
      console.log('Received message:', message);
      if (message === 'got user media') {
          checkAndStart();
      } else if (message.type === 'offer') {
          if (!isInitiator &amp;&amp; !isStarted) {
              checkAndStart();
          }
          pc.setRemoteDescription(new RTCSessionDescription(message));
          doAnswer();
      } else if (message.type === 'answer' &amp;&amp; isStarted) {
          pc.setRemoteDescription(new RTCSessionDescription(message));
      } else if (message.type === 'candidate' &amp;&amp; isStarted) {
          var candidate = new RTCIceCandidate({sdpMLineIndex:message.label,
              candidate:message.candidate});
          pc.addIceCandidate(candidate);
      } else if (message === 'bye' &amp;&amp; isStarted) {
          handleRemoteHangup();
      }
  });
  // 2. Client--&gt;Server
  // Send message to the other peer via the signaling server
  function sendMessage(message){
      console.log('Sending message: ', message);
      socket.emit('message', message);
  }
  // Channel negotiation trigger function
  function checkAndStart() {
      if (!isStarted &amp;&amp; typeof localStream != 'undefined' &amp;&amp; isChannelReady) {
          createPeerConnection();
          isStarted = true;
          if (isInitiator) {
              doCall();
          }
      }
  }
  // PeerConnection management...
  function createPeerConnection() {
      try {
          pc = new RTCPeerConnection(pc_config, pc_constraints);
          pc.addStream(localStream);
          pc.onicecandidate = handleIceCandidate;
          console.log('Created RTCPeerConnnection with:\n' +
              ' config: \'' + JSON.stringify(pc_config) + '\';\n' +
              ' constraints: \'' + JSON.stringify(pc_constraints) + '\'.');
      } catch (e) {
          console.log('Failed to create PeerConnection, exception: ' + e.message);
          alert('Cannot create RTCPeerConnection object.');
          return;
      }
      pc.onaddstream = handleRemoteStreamAdded;
      pc.onremovestream = handleRemoteStreamRemoved;
      if (isInitiator) {
          try {
  // Create a reliable data channel
              sendChannel = pc.createDataChannel("sendDataChannel",
                  {reliable: true});
              trace('Created send data channel');
          } catch (e) {
              alert('Failed to create data channel. ');
              trace('createDataChannel() failed with exception: ' + e.message);
          }
          sendChannel.onopen = handleSendChannelStateChange;
          sendChannel.onmessage = handleMessage;
          sendChannel.onclose = handleSendChannelStateChange;
      } else { // Joiner
          pc.ondatachannel = gotReceiveChannel;
      }
  }
  // Data channel management
  function sendData() {
      var data = sendTextarea.value;
      if(isInitiator) sendChannel.send(data);
      else receiveChannel.send(data);
      trace('Sent data: ' + data);
  }
  // Handlers...
  function gotReceiveChannel(event) {
      trace('Receive Channel Callback');
      receiveChannel = event.channel;
      receiveChannel.onmessage = handleMessage;
      receiveChannel.onopen = handleReceiveChannelStateChange;
      receiveChannel.onclose = handleReceiveChannelStateChange;
  }
  function handleMessage(event) {
      trace('Received message: ' + event.data);
      receiveTextarea.value += event.data + '\n';
  }
  function handleSendChannelStateChange() {
      var readyState = sendChannel.readyState;
      trace('Send channel state is: ' + readyState);
  // If channel ready, enable user's input
      if (readyState == "open") {
          dataChannelSend.disabled = false;
          dataChannelSend.focus();
          dataChannelSend.placeholder = "";
          sendButton.disabled = false;
      } else {
          dataChannelSend.disabled = true;
          sendButton.disabled = true;
      }
  }
  function handleReceiveChannelStateChange() {
      var readyState = receiveChannel.readyState;
      trace('Receive channel state is: ' + readyState);
  // If channel ready, enable user's input
      if (readyState == "open") {
          dataChannelSend.disabled = false;
          dataChannelSend.focus();
          dataChannelSend.placeholder = "";
          sendButton.disabled = false;
      } else {
          dataChannelSend.disabled = true;
          sendButton.disabled = true;
      }
  }
  // ICE candidates management
  function handleIceCandidate(event) {
      console.log('handleIceCandidate event: ', event);
      if (event.candidate) {
          sendMessage({
              type: 'candidate',
              label: event.candidate.sdpMLineIndex,
              id: event.candidate.sdpMid,
              candidate: event.candidate.candidate});
      } else {
          console.log('End of candidates.');
      }
  }
  // Create Offer
  function doCall() {
      console.log('Creating Offer...');
      pc.createOffer(setLocalAndSendMessage, onSignalingError, sdpConstraints);
  }
  // Signaling error handler
  function onSignalingError(error) {
      console.log('Failed to create signaling message : ' + error.name);
  }
  // Create Answer
  function doAnswer() {
      console.log('Sending answer to peer.');
      pc.createAnswer(setLocalAndSendMessage, onSignalingError, sdpConstraints);
  }
  // Success handler for both createOffer()
  // and createAnswer()
  function setLocalAndSendMessage(sessionDescription) {
      pc.setLocalDescription(sessionDescription);
      sendMessage(sessionDescription);
  }
  // Remote stream handlers...
  function handleRemoteStreamAdded(event) {
      console.log('Remote stream added.');
      attachMediaStream(remoteVideo, event.stream);
      console.log('Remote stream attached!!.');
      remoteStream = event.stream;
  }
  function handleRemoteStreamRemoved(event) {
      console.log('Remote stream removed. Event: ', event);
  }
  // Clean-up functions...
  function hangup() {
      console.log('Hanging up.');
      stop();
      sendMessage('bye');
  }
  function handleRemoteHangup() {
      console.log('Session terminated.');
      stop();
      isInitiator = false;
  }
  function stop() {
      isStarted = false;
      if (sendChannel) sendChannel.close();
      if (receiveChannel) receiveChannel.close();
      if (pc) pc.close();
      pc = null;
      sendButton.disabled=true;
  }
  </code></pre>
  
  <p>server.js</p>
  
  <pre><code>var static = require('node-static');
  var http = require('http');
  // Create a node-static server instance
  var file = new(static.Server)();
  // We use the http module’s createServer function and
  // rely on our instance of node-static to serve the files
  var app = http.createServer(function (req, res) {
      file.serve(req, res);
  }).listen(8181);
  // Use socket.io JavaScript library for real-time web applications
  var io = require('socket.io').listen(app);
  // Let's start managing connections...
  io.sockets.on('connection', function (socket){
  // Handle 'message' messages
      socket.on('message', function (message) {
          log('S --&gt; got message: ', message);
  // channel-only broadcast...
          socket.broadcast.to(message.channel).emit('message', message);
      });
  // Handle 'create or join' messages
      socket.on('create or join', function (room) {
          var numClients = io.sockets.clients(room).length;
          log('S --&gt; Room ' + room + ' has ' + numClients + ' client(s)');
          log('S --&gt; Request to create or join room', room);
  // First client joining...
          if (numClients == 0){
              socket.join(room);
              socket.emit('created', room);
          } else if (numClients == 1) {
  // Second client joining...
              io.sockets.in(room).emit('join', room);
              socket.join(room);
              socket.emit('joined', room);
          } else { // max two clients
              socket.emit('full', room);
          }
      });
      function log(){
          var array = ["&gt;&gt;&gt; "];
          for (var i = 0; i &lt; arguments.length; i++) {
              array.push(arguments[i]);
          }
          socket.emit('log', array);
      }
  });
  </code></pre>