2014-03-27 13 views
9

Ich muss die Frage heute noch einmal stellen.Peer-to-Peer-Nacharbeit für Konferenz, WebRTC

Ich bin im Verlauf der Verarbeitung eines Codes, um eine Verbindung mit dem Code für eine Gruppenunterhaltung zu verbinden. Ohne Umschweife, ich diesen Code haben:

CallToUsers = function(connection) { 
    var connection = connection; 
    var isChannelReady; 
    var isInitiator = false; 
    var isStarted = false; 
    var servers = null; 
    var localStream = connection.getStream(); 
    var localStreams = []; 
    var localConnection; 
    var turnReady; 
    var remoteStreams = []; 
    var remoteStream; 
    var pcConfig = { 
     'iceServers': [{ 
      'url': 'stun:stun.l.google.com:19302' 
      }] 
     }; 
    var pcConstraints = { 
     'optional': [{ 
      'DtlsSrtpKeyAgreement': true 
      }] 
     }; 
    var sdpConstraints = { 
     'mandatory': { 
      'OfferToReceiveAudio': true, 
      'OfferToReceiveVideo': true 
     } 
    }; 
    var room; 
    var socket = io.connect(); 
    var divElement = document.createElement('div'); 
    divElement.setAttribute('id', 'remotesVideo'); 
    document.body.appendChild(divElement); 

    var createRoom = function(room) { 
     room = room; 
     if(room !== '') { 
      console.log('Create or join to room', room); 
      socket.emit('create or join', room); 
     } 

     socket.on('created', function(room) { 
      console.log('Created room ' + room); 
      isInitiator = true; 
     }); 

     /*socket.on('full', function(room) { 
      console.log('Room' + room + ' is full'); 
     });*/ 

     socket.on('join', function(room) { 
      console.log('Another peer made request to join ' + room); 
      isChannelReady = true; 
     }); 

     socket.on('joined', function(room) { 
      console.log('User joined to room ' + room); 
      isChannelReady = true; 
     }); 

     socket.on('log', function(array) { 
      console.log.apply(console, array); 
     }); 
    }; 

    var sendMessage = function(message) { 
     console.log('Client sending a message: ', message); 
     socket.emit('message', message); 
    }; 

    window.onbeforeunload = function(e){ 
     sendMessage('bye'); 
    }; 

    var startCall = function() { 
     sendMessage('got user media'); 

     if(isInitiator) { 
      maybeStart(); 
     } 

     socket.on('message', function(message) { 
      console.log('Client received a message: ' + message); 
      if(message === 'got user media') { 
       maybeStart(); 
      } else if(message.type === 'offer') { 
       if(!isInitiator && !isStarted) { 
        maybeStart(); 
       } 

       for(var i = 0; i < localStreams.length; i++) { 
        localStreams[i].setRemoteDescription(new RTCSessionDescription(message)); 
       } 

       doAnswer(); 
      } else if(message.type === 'answer' && isStarted) { 
       for(var i = 0; i < localStreams.length; i++) { 
        localStreams[i].setRemoteDescription(new RTCSessionDescription(message)); 
       } 
      } else if(message.type === 'candidate' && isStarted) { 
       var candidate = new RTCIceCandidate({ 
        sdpMLineIndex: message.label, 
        candidate: message.candidate 
       }); 

       for(var i = 0; i < localStreams.length; i++) { 
        localStreams[i].addIceCandidate(candidate); 
       } 
      } else if(message === 'bye' && isStarted) { 
       handleRemoteEndCall(); 
      } 
     }); 

     //if(location.hostname != 'localhost') { 
      //requestTurn('https://computeengineondemand.appspot.com/turn?username=41784574&key=4080218913'); 
     //} 
    }; 

    var maybeStart = function() { 
     if(!isStarted && typeof localStream != 'undefined' && isChannelReady) { 
      createPeerConnection(); 
      for(var i = 0; i < localStreams.length; i++) { 
       localStreams[i].addStream(localStream); 
      } 
      isStarted = true; 

      if(isInitiator) { 
       doCall(); 
      } 
     } 
    }; 

    var createPeerConnection = function() { 
     try { 
       localConnection = new RTCPeerConnection(pcConfig, pcConstraints); 
       localConnection.onicecandidate = handleIceCandidate; 
       localConnection.onaddstream = handleRemoteStreamAdded; 
       localConnection.onremovestream = handleRemoteStreamRemoved; 
       localStreams.push(localConnection); 
      console.log('Created RTCPeerConnection'); 
     } catch(e) { 
      console.log('exception ' + e.message); 
      return; 
     } 
    }; 

    var handleIceCandidate = function(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'); 
     } 
    }; 

    var handleRemoteStreamAdded = function(event) { 
     console.log('Remote stream added'); 
     var newVideo = document.createElement('video'); 
     newVideo.setAttribute('id', Math.floor((Math.random() * 1000) + 1)); 
     newVideo.muted = false; 
     divElement.appendChild(newVideo); 
     attachMediaStream(newVideo, event.stream); 
     remoteStream = event.stream; 
     remoteStreams.push(remoteStream); 
    }; 

    var handleRemoteStreamRemoved = function(event) { 
     console.log('Delete'); 
    }; 

    var handleCreateOfferError = function(event) { 
     console.log('createOffer() error: ' + e); 
    } 

    var setLocalAndSendMessage = function(sessionDescription) { 
     sessionDescription.sdp = preferOpus(sessionDescription.sdp); 
     for(var i = 0; i < localStreams.length; i++) { 
      localStreams[i].setLocalDescription(sessionDescription); 
     } 
     sendMessage(sessionDescription); 
    }; 

    var doCall = function() { 
     console.log('Start call'); 
     for(var i = 0; i < localStreams.length; i++) { 
      localStreams[i].createOffer(setLocalAndSendMessage, handleCreateOfferError); 
     } 
    }; 

    var doAnswer = function() { 
     console.log('Sending answer'); 
     for(var i = 0; i < localStreams.length; i++) { 
      localStreams[i].createAnswer(setLocalAndSendMessage, null, sdpConstraints); 
     } 
    }; 

    var endCall = function() { 
     console.log('Hanging up'); 
     isStarted = false; 
     for(var i = 0; i < localStreams.length; i++) { 
      localStreams[i].close(); 
      localStreams[i] = null; 
     } 
     sendMessage('bye'); 
    }; 

    var handleRemoteEndCall = function() { 
    }; 

    var requestTurn = function(turnUrl) { 
     var turnExists = false; 

     for(var i in pcConfig.iceServers) { 
      if(pcConfig.iceServers[i].url.substr(0, 5) === 'turn:') { 
       turnExists = true; 
       turnReady = true; 
       break; 
      } 
     } 

     if(!turnExists) { 
      console.log('Getting TURN server from ', turnUrl); 

      var xhr = new XMLHttpRequest(); 
      xhr.onreadystatechange = function() { 
       if(xhr.readyState === 4 && xhr.status === 200) { 
        var turnServer = JSON.parse(xhr.responseText); 
        console.log('Got TURN server: ', turnServer); 
        pc_config.iceServers.push({ 
         'url': 'turn:' + turnServer.username + '@' + turnServer.turn, 
         'credential': turnServer.password 
        }); 
        turnReady = true; 
       } 
      }; 

      xhr.open('GET', turnUrl, true); 
      xhr.send(); 
     } 
    }; 

    var preferOpus = function(sdp) { 
     var sdpLines = sdp.split('\r\n'); 
     var mLineIndex; 

     for(var i = 0; i < sdpLines.length; i++) { 
      if(sdpLines[i].search('m=audio') !== -1) { 
       mLineIndex = i; 
       break; 
      } 
     } 

     if(mLineIndex === null) { 
      return sdp; 
     } 

     for(i = 0; i < sdpLines.length; i++) { 
      if(sdpLines[i].search('opus/48000') !== -1) { 
       var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i); 

       if(opusPayload) { 
        sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], opusPayload); 
       } 

       break; 
      } 
     } 

     sdpLines = removeCN(sdpLines, mLineIndex); 

     sdp = sdpLines.join('\r\n'); 

     return sdp; 
    }; 

    var extractSdp = function(sdpLine, pattern) { 
     var result = sdpLine.match(pattern); 

     return result && result.length === 2 ? result[1] : null; 
    }; 

    var setDefaultCodec = function(mLine, payload) { 
     var elements = mLine.split(' '); 
     var newLine = []; 
     var index = 0; 

     for(var i = 0; i < elements.length; i++) { 
      if(index === 3) { 
       newLine[index++] = payload; 
      } 
      if(elements[i] !== payload) { 
       newLine[index++] = elements[i]; 
      } 
     } 

     return newLine.join(' '); 
    }; 

    var removeCN = function(sdpLines, mLineIndex) { 
     var mLineElements = sdpLines[mLineIndex].split(' '); 

     for(var i = sdpLines.length - 1; i >= 0; i--) { 
      var payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i); 

      if(payload) { 
       var cnPos = mLineElements.indexOf(payload); 

       if(cnPos !== -1) { 
        mLineElements.splice(cnPos, 1); 
       } 

       sdpLines.splice(i, 1); 
      } 
     } 

     sdpLines[mLineIndex] = mLineElements.join(' '); 

     return sdpLines; 
    }; 

    return { 
     startCall: startCall, 
     endCall: endCall, 
     createRoom: createRoom 
    }; 
}; 

Während das Gespräch zwischen zwei Benutzern gut arbeiten, dann, wenn ein anderes Mitglied hinzufügen, es keine Verbindung mehr zu den beiden anderen Kollegen, obwohl sie eindeutig die Protokolle sehe ich, dass hängt im selben Raum.

In der Konsole keine Fehler.

Ist jemand nett zu helfen?

@edit

Ich füge auch Server-Code bei Bedarf:

var static = require('node-static'); 
var http = require('http'); 
var file = new(static.Server)(); 
var app = http.createServer(function (req, res) { 
    file.serve(req, res); 
}).listen(2017); 


var io = require('socket.io').listen(app); 
io.sockets.on('connection', function (socket){ 

    function log(){ 
     var array = [">>> "]; 
     for (var i = 0; i < arguments.length; i++) { 
     array.push(arguments[i]); 
     } 
     socket.emit('log', array); 
    } 

    socket.on('message', function (message) { 
     log('Got message: ', message); 
     socket.broadcast.emit('message', message); // should be room only 
    }); 

    socket.on('create or join', function (room) { 
     var numClients = io.sockets.clients(room).length; 

     log('Room ' + room + ' has ' + numClients + ' client(s)'); 
     log('Request to create or join room', room); 

     if (numClients == 0){ 
      socket.join(room); 
      socket.emit('created', room); 
     } else { 
      io.sockets.in(room).emit('join', room); 
      socket.join(room); 
      socket.emit('joined', room); 
     } 
     socket.emit('emit(): client ' + socket.id + ' joined room ' + room); 
     socket.broadcast.emit('broadcast(): client ' + socket.id + ' joined room ' + room); 

    }); 

}); 
+3

Aber wo erstellen Sie eine zweite Peerverbindung? Was ich in MaybeStart sehe, ist, wenn (! IsStarted && typeof localStream! = 'Undefiniert' && isChannelReady), Sie keine weitere Peer-Verbindung erstellen. Wenn die dritte Person kommt, denke ich nicht, dass das wahr wird. –

Antwort

1

gelöst schließlich das Problem. Die allgemeine Regel des Schreibens von Konferenzen, an die alle Peers angeschlossen sind, ist dies: jeder neue Incoming spielt die Rolle des Beantworters, und nachdem er eine Verbindung mit allen Angeboten hergestellt hat, die ihm ein Angebot senden, beginnt er als Anbieter zu agieren. das ist immer das Angebot). @Mert Koksal, danke für dein Interesse Thread.