dongliao2011
2013-01-20 14:17 阅读 94
已采纳

WebRTC候选人信息结尾处的这些数据是什么?

I set up a basic video chat app using the WebRTC APIs in Chrome along with a WebSocket script I wrote myself following the W3C specs and other questions here on SO.

Sometimes though, when one PC sends ICE candidate info to the other PC via the WebSocket connection, a bunch of garbled text is attached to the end of the JSON-stringified candidate info. This problem only happens sometimes though, and it never happens with the SDP info sent via the createOffer and createAnswer methods.

Please see the following link for an example of what I'm talking about: http://s1290.beta.photobucket.com/user/HartleySan83/media/NGdata_zps0a7203e7.png.html?sort=3&o=0

Because the JSON-stringified candidate info always ends with '}}', by adding an if condition to the WebSocket server script, I was able to circumvent this problem and get the video chat app to work. Unfortunately, this is a hack that I'd like to avoid. Plus, I'd like to know why this is happening in the first place.

It's worth noting that when I either alert or echo the candidate info to the console on the client side before it's sent to the WebSocket server script, none of the extra garbled text is present, so I'm not sure why it's present with the candidate info on the server side and only sometimes.

The following is a code snippet of the client-side code where the candidate info is sent to the server-side script:

function startPeerConnection() {

  navigator.webkitGetUserMedia({ audio: true, video: true }, function (stream) {

    document.getElementById('vid1').src = webkitURL.createObjectURL(stream);

    pc = new webkitRTCPeerConnection(null);

    pc.onicecandidate = function (evt) {

      if (evt.candidate) {

        socket.send(JSON.stringify({ candidate: evt.candidate }));

      }

    };

    pc.onaddstream = function (evt) {

      document.getElementById('vid2').src = webkitURL.createObjectURL(evt.stream);

    };

    pc.addStream(stream);

  }, function () {});

}

And the following is the server-side code that unmasks the received WebSocket data:

$len = ord($buffer[1]) & 127;

if ($len === 126) {

  $masks_start = 4;

} else if ($len === 127) {

  $masks_start = 10;

} else {

  $masks_start = 2;

}

$masks = substr($buffer, $masks_start, 4);

$data = substr($buffer, $masks_start + 4);

$len = strlen($data);

$text = '';

for ($i = 0; $i < $len; $i++) {

  $text .= $data[$i] ^ $masks[$i % 4];

}

if (($end = strpos($text, '}}')) !== false) {
// This if condition eliminates the garbled text.
// Without it, a "Could not decode a text frame as UTF-8"
// error is output to the Chrome console.

  $text = substr($text, 0, $end + 2);

  $len = strlen($text);

}

if ($len <= 125) {

  $header = pack('C*', 129, $len);

} else if (($len > 125) && ($len < 65536)) {

  $header = pack('C*', 129, 126, ($len >> 8) & 255, $len & 255);

} else if ($len >= 65536) {

  $header = pack('C*', 129, 127, ($len >> 56) & 255, ($len >> 48) & 255, ($len >> 40) & 255, ($len >> 32) & 255, ($len >> 24) & 255, ($len >> 16) & 255, ($len >> 8) & 255, $len & 255);

}

$server_response = $header . $text;

foreach ($users as $user) {

  if ($user !== $users[$user_idx]) {

    @socket_write($user['socket'], $server_response, strlen($server_response));

  }

}

I've searched high and low on the Internet for anyone else with the same problem, but I can't find anyone or anything in the specs that talks about this, so I imagine it's some problem with my code.

Any guidance that anyone can offer as to the source of the problem would be much appreciated. Thank you.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

2条回答 默认 最新

  • 已采纳
    duandian2725 duandian2725 2013-01-23 13:46

    Well, I finally found the problem. My server-side WebSocket code was indeed wrong. The problem was that I was miscalculating the length. I, unfortunately, was relying on some page I found about WebSockets in PHP, and as it turns out, the page had a number of errors in its code, which I slowly started to realize more and more. Anyway, here's the proper way to calculate the length of messages sent from a client to the server:

    $len = ord($buffer[1]) & 127; // This is the default payload length.
    
    if ($len === 126) { // If 126, then need to use the payload length at the 3rd and 4th bytes.
    
      $masks_start = 4;
    
      $len = (ord($buffer[2]) << 8) + ord($buffer[3]);
    
    } else if ($len === 127) { // If 127, then need to use the next 8 bytes to calculate the length.
    
      $masks_start = 10;
    
      $len = (ord($buffer[2]) << 56) + (ord($buffer[3]) << 48) + (ord($buffer[4]) << 40) + (ord($buffer[5]) << 32) + (ord($buffer[6]) << 24) + (ord($buffer[7]) << 16) + (ord($buffer[8]) << 8) + ord($buffer[9]);
    
    } else { // Otherwise, the default payload length is correct.
    
      $masks_start = 2;
    
    }
    

    After doing that, everything worked great. Well, I'm still haven't figured out how to properly close a WebSocket connection, but other than that, the WebRTC video is working great.

    点赞 评论 复制链接分享
  • douhui8025 douhui8025 2013-01-22 04:40

    Is the garbled binary data being added by client1 before it sends it to the Websocket server? Or are you only seeing it on the client2 after it's been processed by the websocket server? I ask because I ran into a similar problem where my signaling server (SignalR in this case) had a bug that corrupted the SDP I was sending in-between PeerConnections.

    点赞 评论 复制链接分享

相关推荐