Phoenix Channel을 사용하여 WebRTC를 시그널링하는 메모 #beamlangtokyo

Elixir 초보자용 핸즈온 vol2 에서 배운 것을 되돌아 보면서 메모를 쓰고 있습니다.

전에 WebRTC 시그널링 서버에 Milkcocoa를 사용하여 보기 메모 #webrtcjp #mlkcca 라고 하는 기사를 썼습니다만, 이것의 Phoenix.channel판을 해 보겠습니다.

내용적으로는 WebRTC측의 요소가 많을지도

만든 것



화상 채팅 - Phoenix Channel에서 시그널링을 하고 있습니다.



Elixir 핸즈온에서 한 이와 함께


WebRTC 핸즈온에서 한 이거

두 가지 조합입니다. Phoenix Channel 핸즈온 자료 를 참조.

Phoenix는 WebSocket을 그대로 사용하는 것이 아니라, WebSocket상에 만들어진 복수의 Channel(PhoenixChannel)을 사용해 클라이언트와 서버의 양방향 통신을 실시합니다.
  • WebSocket에 가상 레이어를 만들어 통신하는 메커니즘
  • Socket.io의 룸 기능과 같은 것을 구현합니다
  • JS 이외에도 Swift 등의 클라이언트가 존재한다

  • WebRTC 시그널링 수정



    기본은 이 기사의 단계 으로 진행한 후의 이야기가 됩니다.

    이벤트 추가


    lib/demo_web/channels/chat_channel.exsignaling 이벤트 추가

    lib/demo_web/channels/chat_channel.ex
    
    (省略)
    
        def handle_in("signaling", payload, socket) do
            broadcast! socket, "signaling", payload
            {:reply, {:ok, payload}, socket}
        end
    
    (省略)
    
    

    서버 측은 이것뿐.

    UUID 생성



    이번에는 demo라는 Phoenix 응용 프로그램을 만들고 assets/js/demo.js에 추가했습니다.

    Milkcocoa 버전 때와 동일하지만 SDP를 보낼 때 자신에게 정보가 보내지면 Failed to set remote answer sdp: Called in wrong state: STATE_INPROGRESS 등의 오류가 나오므로 자신에게는 정보가 보내지지 않도록해야합니다.

    각 액세스에 대해 UUID를 부여하여 자신감에 대한 정보를 생략합니다.

    Phoenix Channel에서 그런 기능이없는 것일까 (있을 것)

    assets/js/demo.js
    
    'use strict';
    
    import {Socket} from "phoenix"
    
    const UUID = uuid();
    
    function uuid() {
      let uuid = "", i, random;
      for (i = 0; i < 32; i++) {
        random = Math.random() * 16 | 0;
    
        if (i == 8 || i == 12 || i == 16 || i == 20) {
          uuid += "-"
        }
        uuid += (i == 12 ? 4 : (i == 16 ? (random & 3 | 8) : random)).toString(16);
      }
      return uuid;
    }
    
    
    
    (省略)
    
    
    

    sdp 및 IceCandidate 보내기



    둘 다 chan.push() 를 사용하여 보내도록 합니다.

    assets/js/demo.js
    
    
    (省略)
    
    
    function sendSdp(sessionDescription) {
            console.log('---sending sdp ---');
            $textForSendSdp.value = sessionDescription.sdp;
            const message = JSON.stringify(sessionDescription);
            console.log('sending SDP=' + message);
            //ws.send(message);
            chan.push('signaling', {body: message, uuid:UUID})
    }
    
    
    (省略)
    
    
     function sendIceCandidate(candidate) {
            console.log('---sending ICE candidate ---');
            const message = JSON.stringify({ type: 'candidate', ice: candidate });
            console.log('sending candidate=' + message);
            // ws.send(message);
            chan.push('signaling', {body: message, uuid:UUID})
        }
    
    
    (省略)
    
    

    signaling 이벤트를 받는 처리 추가



    SDP 정보가 전송되었을 때의 처리입니다.
    if(msg.uuid === UUID) return; 에서는 방금전의 UUID 이야기로 보내져 온 UUID가 자신의 것이었던 경우는 아무것도 하지 않게 하고 있습니다.

    assets/js/demo.js
    
    
    (省略)
    
        chan.on("signaling", msg => {
    
          const message = JSON.parse(msg.body);
          if(msg.uuid === UUID) return; //送られてきたUUIDが自分のものだった場合は何もしない
    
          if (message.type === 'offer') {
            // offer 受信時
            console.log('Received offer ...');
            $textToReceiveSdp.value = message.sdp;
            const offer = new RTCSessionDescription(message);
            setOffer(offer);
          }
          else if (message.type === 'answer') {
              // answer 受信時
              console.log('Received answer ...');
              $textToReceiveSdp.value = message.sdp;
              const answer = new RTCSessionDescription(message);
              setAnswer(answer);
          }
          else if (message.type === 'candidate') {
              // ICE candidate 受信時
              console.log('Received ICE candidate ...');
              const candidate = new RTCIceCandidate(message.ice);
              console.log(candidate);
              addIceCandidate(candidate);
          }
        })
    
    (省略)
    
    

    이제 Phoenix Channel을 통해 시그널링을 할 수 있습니다.

    소감



    Phoenix 자체 오늘 처음 만졌는데 편리하게 Erlang VM을 이용할 수 있는 구조는 대단하네요. (작은 느낌

    Socket.io등의 기존 시스템과 잘 연계할 수 있는 구조가 있으면 과거의 시스템의 환승 허드가 내려 좋을 것 같다. (브릿지하는 구조 있을 것 같은 생각이 든다)

    좋은 웹페이지 즐겨찾기