Skip to main content
Triggered when a WebRTC ICE candidate is received through the unified WebSocket connection. ICE candidates are used to establish the optimal network path for WebRTC media streaming.

Event Properties

type
string
Event type. Always "webrtc.signaling.iceCandidate" for this event.
data
object
Event data object containing ICE candidate information.
data.candidate
object
The RTCIceCandidate object containing candidate information for network path discovery.Example:
{
  "candidate": "candidate:1 1 UDP 2130706431 192.168.1.1 54321 typ host",
  "sdpMLineIndex": 0,
  "sdpMid": "0"
}
{
  "type": "webrtc.signaling.iceCandidate",
  "data": {
    "candidate": {
      "candidate": "candidate:1 1 UDP 2130706431 192.168.1.1 54321 typ host",
      "sdpMLineIndex": 0,
      "sdpMid": "0"
    }
  }
}

Sending ICE Candidate

When ICE candidates are generated by your RTCPeerConnection, you need to send them immediately. Here’s how to send ICE candidates:
const NavTalkMessageType = Object.freeze({
    WEB_RTC_ICE_CANDIDATE: "webrtc.signaling.iceCandidate",
    // ... other event types
});

// Function to send ICE candidate
function sendIceMessage(candidate) {
    const message = {
        type: NavTalkMessageType.WEB_RTC_ICE_CANDIDATE,
        data: { candidate: candidate }
    };
    socket.send(JSON.stringify(message));
    console.log('Sent ICE candidate:', message);
}

// Set up ICE candidate handler - send candidates as they're generated
peerConnection.onicecandidate = (event) => {
    console.log('onicecandidate:', event.candidate ? 'new candidate' : 'gathering complete');
    if (event.candidate) {
        // event.candidate is an RTCIceCandidate object
        sendIceMessage(event.candidate);
    }
};
Message Structure: When sending an ICE candidate, the message structure should be:
{
  "type": "webrtc.signaling.iceCandidate",
  "data": {
    "candidate": {
      "candidate": "candidate:1666409998 1 udp 2122129151 192.168.1.81 64301 typ host generation 0 ufrag lwyK network-id 1",
      "sdpMid": "0",
      "sdpMLineIndex": 0,
      "usernameFragment": "lwyK"
    }
  }
}
RTCIceCandidate Object Properties: The candidate object should have the following properties:
  • candidate (string): The candidate string, e.g., "candidate:1666409998 1 udp 2122129151 192.168.1.81 64301 typ host generation 0 ufrag lwyK network-id 1"
  • sdpMLineIndex (number, optional): The SDP media line index, typically 0 for video or 1 for audio
  • sdpMid (string, optional): The SDP media identification tag, typically "0" for video or "1" for audio
  • usernameFragment (string, optional): The ICE username fragment (ufrag)
Key Points:
  • The candidate parameter in data.candidate should be an RTCIceCandidate object (or equivalent plain object)
  • Send ICE candidates immediately when they’re generated in the onicecandidate event handler
  • Only send candidates when event.candidate is not null (when it’s null, ICE gathering is complete)
  • You may receive multiple ICE candidates - send each one as it’s generated

Receiving ICE Candidate

When you receive an ICE candidate, handle it like this:
async function handleReceivedMessage(data) {
    const nav_data = data.data;
    
    switch (data.type) {
        case NavTalkMessageType.WEB_RTC_ICE_CANDIDATE:
            const candidate = new RTCIceCandidate(nav_data.candidate);
            await peerConnection.addIceCandidate(candidate);
            console.log('ICE candidate added');
            break;
    }
}
Complete Example:
// Set up peer connection
const peerConnection = new RTCPeerConnection(configuration);

// Send ICE candidates as they're generated
peerConnection.onicecandidate = (event) => {
    console.log('onicecandidate:', event.candidate ? 'new candidate' : 'gathering complete');
    if (event.candidate) {
        sendIceMessage(event.candidate);
    }
};

// Handle received ICE candidates
async function handleReceivedMessage(data) {
    const nav_data = data.data;
    
    switch (data.type) {
        case NavTalkMessageType.WEB_RTC_ICE_CANDIDATE:
            const candidate = new RTCIceCandidate(nav_data.candidate);
            await peerConnection.addIceCandidate(candidate);
            console.log('ICE candidate added');
            break;
    }
}
  • When to send: Send ICE candidates immediately when they’re generated in the peerConnection.onicecandidate event handler
  • What to send: Send event.candidate (which is an RTCIceCandidate object) as the candidate value
  • Multiple candidates: You may receive multiple ICE candidates - send each one as it’s generated
  • ICE candidates are sent through the unified WebSocket connection