Discord Twitter Youtube
<< Back

Deep dive into WebRTC & the ICE protocol Deep dive into WebRTC & the ICE protocol

WebRTC: An in-depth look at the ICE protocol

If you haven’t already read the introduction to WebRTC & ICE, we highly recommend doing so!

The challenge

WebRTC is a powerful technology that allows real-time audio and video communication directly between browsers, without the need for plugins or additional software. However, establishing a direct connection can be quite challenging. Network address translators (NATs) and firewalls are the main reasons why it is so hard to establish a direct connection between two peers. IPv6 which could, in theory, resolve some of our headaches makes it in practice even harder to establish a direct connection. (NAT46, NAT64, hairpinning, etc.) Fortunately, smart people found a workaround for most of these problems that where outlined, this is where the Interactive Connectivity Establishment (ICE) protocol comes in.(Anderson, 2022)

WebRTC - Introduction

WebRTC is supported by almost all modern browsers and is the best solution available for peer to peer (p2p) connections. (Can I Use, 2023) It is using the ICE protocol to establish a direct connection if possible or relay the data using a Traversal Using Relays around NAT (TURN) server. (Mdn Web Docs, 2023g) It is used by multiple big cooperations and known web applications, for the most part for voice over IP (VOIP). This article was intended for the interested reader how seeks more information about this topic.

After the peer, to which a connection is desired, was identified, the connection must be established before data can be exchanged.

Establish a connection

There are defined steps for WebRTC that must happen to establish a connection. (Mdn Web Docs, 2023b) Some of these steps are specific to WebRTC and not generally needed for ICE, but the concept stays the same.


  • The caller captures local Media via MediaDevices.getUserMedia(...)
  • The caller creates RTCPeerConnection and adds the media stream or the data channels
  • The caller registers to get ice-candidates RTCPeerConnection.onicecandidate = (event) => { //send to receiver }. The caller sends these candidates to the receiver after offers have been exchanged. (Mdn Web Docs, 2023c)
  • The caller calls RTCPeerConnection.createOffer() to create an offer and sets it as the local description with RTCPeerConnection.setLocalDescription().
  • After setLocalDescription(), the caller asks STUN servers to generate the ice candidates.
  • The caller uses the signaling server to transmit the offer to the intended receiver of the call.
  • The recipient receives the offer and calls RTCPeerConnection.setRemoteDescription() to record it as the remote description (the description of the other end of the connection).
  • The receiver registers to get ice-candidates RTCPeerConnection.onicecandidate = (event) => { //send to caller }. The receiver sends these candidates to the caller after offers have been exchanged.
  • The recipient then creates an answer by calling RTCPeerConnection.createAnswer() and sets it as local description using RTCPeerConnection.setLocalDescription().
  • After setLocalDescription(), the caller asks STUN servers to generate the ice candidates.
  • The recipient now knows the configuration of both ends of the connection.
  • The recipient uses the signaling server to send the answer to the caller.
  • The caller calls RTCPeerConnection.setRemoteDescription() to set the answer as the remote description for its end of the call. It now knows the configuration of both peers. Media begins to flow as configured.
  • Now gathered ICE-candidates can be exchanged and added to the connection using RTCPeerConnection.addIceCandidate(); (Mdn Web Docs, 2023h)

In most situations STUN or TURN will be necessary to connect to the desired peer. (Mdn Web Docs, 2023b) To configure these settings add the following object to the constructor of your RTCPeerConnection. (Mdn Web Docs, 2023f)

static ICE_CONFIGURATION_TURN = {
    iceServers: [
        {
            urls: "stun:stun.l.google.com:19302",
        },
        {
            urls: "turn:turn.ddns.net:8442",
            username: "YOUR_USERNAME",
            credential: "YOUR_PASSWORD",
        }
    ]
}

new RTCPeerConnection(RTCPeerConnectionFactory.ICE_CONFIGURATION_TURN)

Think about the lines of code above, found a “security” issue? The password and username of “your” TURN/STUN server are sent, in clear-text, to all clients. So why require a password in the first place? Someone can use your turn server, for which you pay, for their own application. There are workarounds but that’s just a stupid standard. (Uberti, 2013) TURN and STUN were developed before WebRTC but there would have been plenty of time to change that.

Create DataChannels

Even though WebRTC was mainly developed with audio and video transmission in mind, it can be used to transfer data using data channels. (Mdn Web Docs, 2023e) You can open a new data channel using RTCPeerConnection.createDataChannel('label', <any>CHANNEL_OPTIONS);.

The underlying data transport used by the RTCDataChannel can be created in one of two ways (Mdn Web Docs, 2023e):

  • Let WebRTC handle it, this is the easiest way and works for a wide variety of use cases.
  • Do it on your own, write custom signaling and earn flexibility.

Buffering

WebRTC data channels automatically support buffering of outbound data. (Mdn Web Docs, 2023e) Unfortunately there is no way to control the size of the buffer. You can learn how much data is buffered and get notified if the buffer is low. Keep in mind that your website can be used on mobile devices so do not buffer unnecessarily high amounts of outbound data.

Understanding Message-Size

The maximum size of a single message can vary between 16kB and 65kB based on the browser you are using. (Mdn Web Docs, 2023e) So you will have to split larger data into chunks, send the chunks and assemble them on the receiving end. SCTP, the protocol used to transfer data was originally designed for use as a signaling protocol. “Support for messages larger than the network layer’s Maximum Transmission Unit (MTU) was added almost as an afterthought, …” (Mdn Web Docs, 2023e) Different browsers use different libraries for the SCTP protocol resulting in different maximum message sizes.

Stream Control Transmission Protocol (SCTP)

As WebRTC and ICE mainly rely on UDP, a protocol that neither guarantees that messages will be received nor that they are in the right order a further protocol is needed, SCTP. („User Datagram Protocol“, 2023) (Rosenberg et al., 2003)

SCTP is a reliable transport protocol, it offers the following services to its users: (Stewart, 2007)

  • acknowledged error-free non-duplicated transfer of user data (data sent will be received)
  • data fragmentation to conform to discovered path MTU size (messages larger than the MTU can be sent.)
  • sequenced delivery of user messages within multiple streams, an option for order-of-arrival delivery of individual user messages (sent sequence is equal to received sequence)
  • optional bundling of multiple user messages into a single SCTP packet (optimization for small messages)
  • network-level fault tolerance through supporting multi-homing at either or both ends of an association. (Multiple roads lead to Rom.)

Tips & Tricks for WebRTC

  • Try to compress messages before sending them if viable. (e.g. SnappyJS (Jia, 2023))
  • Buffer data in an array before writing them to the disk / download them.
  • For large files, be aware of buffer-overflow. (e.g. StreamSaver.js (Wärting, 2016/2023))
  • Use Multiple Data-Channels

    Using multiple data channels is not as easy as it sounds. Because of the characteristics of UDP, congestion control can only be handled at the endpoints, how well this works depends on the buffering method (buffer-unit) employed by the node at the congestion.(Zhang et al., 2020) This means one or multiple data channels can have a really hard time transmitting packets. For example, channel 1 is sending so much data that all packets from channel 2 are dropped. These packets will be delayed or in the worst case not transmitted. Buffer overflow protection must be set up manually.
  • Always use GetUserMedia();

    If you asked yourself why we are requesting access to your microphone, most browsers require a website to request access to user media. Only if access is granted local connections are possible. It is done to mitigate the risk of websites collecting local IP addresses. You can thank google for that, it proposed these changes in the ietf-draft “WebRTC IP Address Handling Requirements draft-ietf-rtcweb-ip-handling-09”. (Uberti & Shieh, n.d.)

Example

There are many examples and tutorials out there that you can consult if you choose to develop your own WebRTC application. In my experience implementing WebRTC seems to be simple at first but if you want to do anything different from what is commonly done, it has a steep learning curve. That’s why I would recommend, at least, refreshing the basics about network engineering and consulting the documentation instead of following a tutorial or example. If you want to take a look at some examples anyway, I can recommend the official webpage. (GitHub - WebRTC, 2023)

The Interactive Connectivity Establishment (ICE) protocol

As mentioned above, WebRTC relies on ICE to establish a connection between peers. Now we will take a closer look at ICE and summarize how it works.

The ICE protocol tries to determine the best possible connection between two peers, it works with many different network scenarios.(Rosenberg et al., 2003) This may include situation where the peers are:

  • In the same network/subnet
  • Assigned a public IP-Address/Endpoint
  • In different networks, behind different NATs and Firewalls

The process involves several steps and uses a combination of different techniques, such as STUN and TURN to establish a connection between those peers.

It was and is hard for me to understand how WebRTC and ICE works in detail because I had and probably have gaps in my knowledge about network engineering. The following paragraphs try to refresh the memory of the reader about the basics of network engineering.

Network Address Translation (NAT)

We have a problem, it is a result of the need or the idea of saving one or two bytes in an IPv4 header. IPv4 offers a theoretical pool of 4.294.967.296 different addresses. („Address Pool“, 2021) With smartphones, laptops, and other smart devices this is simply not enough. The problem has gotten so bad that even Internet Service Provider use NAT. (see CGNAT)

NAT aims to provide a local pool of IP addresses that are mapped to one external/public IP address, there by extending the maximum of devices that can be connected to the internet.(„Network Address Translation“, 2023) This can be achieved in different ways, the simplest is to map a local address and port (endpoint) to the external endpoint. NAT maps those addresses in a way, that each outgoing packets source address is translated and packets sent to the public endpoint are forwarded to the local endpoint.

There are 4 basic types, the designations may differ. („Network Address Translation“, 2023)

  • Full cone NAT
  • Address Restricted cone NAT
  • Port Restricted cone NAT
  • Symmetric NAT

“Many NAT implementations combine these types, so it is better to refer to specific individual NAT behavior instead of using the Cone/Symmetric terminology.”(„Network Address Translation“, 2023)

Full cone NAT

A local endpoint is mapped to one public endpoint. Whatever is sent to the public endpoint will be forwarded to the local address.

Based on („Network Address Translation“, 2023)

Address Restricted NAT

A local endpoint is mapped to one public endpoint. Whatever is sent to this public endpoint by mapped addresses will be forwarded, other packets from other addresses will be dropped.

Based on („Network Address Translation“, 2023)

Port Restricted NAT

A local endpoint is mapped to one public endpoint. Whatever is sent to this public endpoint by mapped endpoints will be forwarded, other packets from other endpoints will be dropped.

Based on („Network Address Translation“, 2023)

Symmetric NAT

A local endpoint is mapped to multiple public endpoints depending on the destination endpoint. Only packets sent to the mapped endpoint by the mapped destination endpoint are forwarded, others will be dropped.

Based on („Network Address Translation“, 2023)

Multilayer NAT

Sometimes peers are behind multiple layers of NAT. This can be a hard situation to navigate, fortunately ICE does this for us. Hairpinning can resolve this issue but is not always supported, if it is not supported, we will have to resort to using TURN.

Hairpinning

It is also known as NAT loopback, it allows for packets from the LAN, with the destination address set to the WAN address to be routed to the client in the LAN.(„Network Address Translation“, 2023) The destination address is translated and the packet forwarded.

Hairpinning can be extremely useful to achieve a direct connection in multilayer NAT topology. (Ford, 2023) There can be cases where packets are routed within the second level NAT, the public IP address of the second level NAT cannot be learned. That is why we must rely on hairpinning to achieve a direct connection, otherwise we must resort to using a relay connection.

Carrier-grad NAT (CGNAT)

CGNAT reduces the number of public IP-addresses needed by ISP even further.(„Carrier-Grade NAT“, 2023) It also increases the complexity of the network topology of the internet, direct connections between clients are even harder to establish and it does not help that most of them are symmetric.

ICE Connection Establishment

ICE can help us to get a connection to the peer, even if he is hidden behind a NAT and firewall. (Rosenberg et al., 2003) The process of establishing a connection was outlined in Establish a Connection, some WebRTC specific steps are to be excluded. But the core part of creating offer and answer, exchanging these using a signaling server and exchanging candidates remain the same. That is why no specific process for ICE is explained here.

ICE-CandidateTypes

There are 3 major types of ice candidates which will be explained, the last type is irrelevant in most situations.(Mdn Web Docs, 2023d) These candidates are gathered by STUN, TURN or the client. Candidates represent a way of establishing a connection between endpoints, not all candidates will be successful but at most times multiple will. That is why we also need to prioritize the candidates to select the best connection. Theoretically latency, ping or other techniques could be used to define the cost of a route, in practice, at least using WebRTC, only the type of candidate will be considered. Host before srflx before prflx before relay. The candidates can change at any time, e.g. the computer switches from LAN into WLAN and the IP address changes, new candidates are gathered and must be transmitted to the other peer to be considered when trying to reestablish a connection.

  • Host

    The public or local IP address of the peer. It is the true address of the remote peer. To avoid leaking the local IP address MDNS is used which can make it harder to debug issues with the connection. (Fablet et al., n.d.)

  • Server-Reflexive (srflx)

    The srflx candidate defines a route through NAT. The peer can share these candidates with another peer to connect. They can be learned by the STUN server and TURN server to represent the peer anonymously.

  • Relay

    Relay candidates are obtained using the TURN Server, data is relayed from one peer over the TURN server to the second peer. WebRTC encrypts the data sent so no useful information about the data transferred can be obtained. (Mdn Web Docs, 2023e)

  • Peer-Reflexive (preflx)

    Preflx candidates are the most uncommon candidates you will encounter. They are obtained by a peer while connecting using another candidate. Most likely, one of the peers is behind a Symmetric NAT.

Multicast DNS (MDNS)

ICE, by its nature, sends the local endpoint to the peer that tries to connect. This has the effect that local endpoints are leaked to clients that try to connect, this may be a vulnerability, mdns tries to mitigate this risk. “In computer networking, the multicast DNS (mDNS) protocol resolves hostnames to IP addresses within small networks that do not include a local name server.” („Multicast DNS“, 2023)

Session Traversal Utilities for NAT (STUN)

A STUN-Server discovers endpoints for the client connected. STUN is a protocol to get a connection to a client behind NAT. („STUN“, 2023) Although STUN is an incredible technology it has its shortcomings, for example, it does not work with Symmetric NAT.

The STUN protocol is very interesting, I can only recommend taking a closer look at its inner structure. (Rosenberg et al., 2003) One of the main tasks that STUN performs is to detect what kind of NAT you are facing and how to traverse it.

The flow chart for the basic algorithm to detect which kind of NAT you are facing:

(„STUN“, 2023)

Based on the results of the STUN - type detection algorithm, ICE-candidates are generated that can be used to connect to the peer.(„STUN“, 2023)

Traversal Using Relays around NAT (TURN)

If you want to achieve a connection to a client and STUN fails, you turn to TURN. TURN extends STUN and adds a relay candidate that is chosen when all other candidates fail to establish a connection. („STUN“, 2023) It is not limited to TCP or UDP both protocols are supported. For data transfer, if possible, choose TCP, it will reduce overhead and transfer data faster, generally. Because traffic is relayed it needs bandwidth for the host of the server, which may not be cheap. To reduce costs, TURN should be avoided at all costs.

Methods used by ICE & other p2p protocols

ICE uses many different methods for establishing a peer connection. (Rosenberg, 2010) Because of its nature, it cannot rely on all available options. Other protocols may include other types of methods to achieve a peer to peer connection or perhaps the developers used them on top of ICE Some techniques are not used by ICE because they are not available in modern browsers because of security concerns, are bound to certain Operation Systems (OS) or require other special circumstances.

No-NAT

If there is no NAT between the peers, either they are in the same network or port-forwarding is in place, there is really no need for this.(Ford, 2023) If no additional rules for the firewall are defined, we need to send a packet to the peer to open a hole in the firewall, he does the same. One of those packets is dropped but a hole has been established. For the peers it seems like the other peer is responding to a request they sent and the firewall does not interfere. Depending on the firewall configuration we need to send keepalive packets to make sure the connection stays open.

Universal Plug and Play (UPnP)

UPnP is also an option for peer-to-peer applications, although it is not used by ICE, it is one of the best methods to establish a p2p connection. (Rosenberg et al., 2003) UPnP can be used to set up port forwarding automatically. (NordVPN, 2023) This solves most problems, but does, most likely, not work for Enterprise grade NAT. Also, it is not always rational to set up a port forwarding rule for not permanently installed software.

UDP/TCP hole punching

UDP hole punching is a method to connect two clients who are behind NAT or multilayer NAT. („UDP Hole Punching“, 2023) (Ford, 2023)

Consider the following situation, two peers are behind different NATs, at first, they have no way to communicate with each other. (Ford, 2023) To establish a connection between those two peers we need a middleman that helps us communicate. The two peers register with the server, the server shares the perceived source endpoint of the packet he has received from the peer with the other peer. This process happens for both peers. Now that both peers have the mapped public endpoint of the other peer, a connection can be established. For Full cone NAT it works without any additional steps, for Address Restricted and Port Restricted NAT it is almost as simple. Each peer begins sending packets, this opens a hole for the other peer in their NAT (and firewall if necessary). The first packets arriving at the other peer will be dropped, but packets from that peer will be able to find their way to the other peer. After that both NATs have a mapping for the opposite peer, and a p2p connection was established. As you may have noticed Symmetric NAT was not mentioned, that is because hole punching does not work for them. Because each destination endpoint gets its own mapping, the server cannot share the public endpoint with the other peer. Because the public endpoint for the other peer would be different than that for the server. Unfortunately Symmetric NAT are quite common in enterprises or as CGNAT

Before UDP hole punching

Before anything has taken place neither peer knows the others endpoint but both are connected to the server.(Ford, 2023) This server will be used to signal the peers and to discover their public addresses. That is why the server should not be within a NAT, even if you have a public IP address this does not guarantee that the source address of the other peer was translated correctly.

Based on (Ford, 2023)

During UDP hole punching

The first step to establish a connection is for one peer to request a connection to the other. (Ford, 2023) The server will then forward the endpoints (public and local) to both peers, which will start sending packets to all received endpoints. Some endpoints will never establish a working connection, others will, after a few tries. If a packet is received before a packet was sent, there is no mapping for that endpoint, so the packet will be dropped. But as soon as both peers have sent a message to the other a mapping will exist and a connection can be established. For both it will seem that the first packets were lost but then the “server”, in reality the other peer, has responded with a packet. A connection has been established.

Based on (Ford, 2023)

After UDP hole punching

Now that a connection has been established the peers can communicate using the discovered endpoints. (Ford, 2023) Depending on the NAT and the firewall, keepalive message must be exchanged for the connection to remain open, especially for UDP because it is not session oriented. („User Datagram Protocol“, 2023)

Based on (Ford, 2023)

Based on (Ford, 2023)

TCP hole punching

TCP hole punching works like UDP hole punching, but because of the more complicated connection establishment process of TCP it is not as viable.(Ford, 2023) If it is able to establish a connection, it should be prioritized over UDP hole punching for data transfer, for audio and video transmission UDP is king. WebRTC limits WaveNet8//Send in its efficiency because it does not commonly provide TCP candidates. (Mdn Web Docs, 2023a)

UDP is challenging for data transmission because it is not session oriented so more complex congestion control algorithms must be employed. (Zhang et al., 2020)

Relay

On of the most straight forward ways to communicate is to relay once messages through a public server. This is wasteful and only an option if all other methods fail. ICE uses TURN to relay messages to the peers.

Conclusion

Overall, the ICE protocol tries to find the best connection between two endpoints, even if they are behind different NATs or firewalls. It improves the quality of audio and video transmissions, reduces delays and distortions, and enables a seamless experience for users. It works on many platforms and in the web, so there is no need to install an application.

For data transfer many improvements could be made and WaveNet8//Send tries to overcome some of WebRTC and ICEs shortcomings but, because of the restrictiveness of browsers, not much can be done.

Feel free to join our discord if you have any questions or port out where we are wrong, Thanks!

references

Address pool. (2021). In Wikipedia. https://en.wikipedia.org/w/index.php?title=Address_pool&oldid=1038113007

Anderson, D. (2022, Mai 3). How NAT traversal works — Concerning CGNATs. APNIC Blog. https://blog.apnic.net/2022/05/03/how-nat-traversal-works-concerning-cgnats/

Can I Use. (2023, Mai 15). „Webrtc“ | Can I use… Support tables for HTML5, CSS3, etc. https://caniuse.com/?search=Webrtc

Carrier-grade NAT. (2023). In Wikipedia. https://en.wikipedia.org/w/index.php?title=Carrier-grade_NAT&oldid=1137061340

Fablet, Y., Borst, J. D., Uberti, J., & Wang, Q. (n.d.). Using Multicast DNS to protect privacy when exposing ICE candidates (Internet Draft draft-ietf-rtcweb-mdns-ice-candidates-03). Internet Engineering Task Force. https://datatracker.ietf.org/doc/draft-ietf-rtcweb-mdns-ice-candidates-03

Ford, B. (2023, Mai 15). Peer-to-Peer Communication Across Network Address Translators. Peer-to-Peer Communication Across Network Address Translators. https://bford.info/pub/net/p2pnat/

GitHub - WebRTC. (2023, Mai 1). WebRTC samples. https://webrtc.github.io/samples/

Jia, Z. (2023). SnappyJS [JavaScript]. https://github.com/zhipeng-jia/snappyjs

mdn web docs. (2023a, Februar 19). WebRTC API - Web APIs | MDN. https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API

mdn web docs. (2023b, März 15). WebRTC Connectivity - Web APIs | MDN. https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Connectivity

mdn web docs. (2023c, April 7). RTCPeerConnection: Icecandidate Event - Web APIs | MDN. https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/icecandidate_event

mdn web docs. (2023d, April 7). RTCIceCandidate: Type Property - Web APIs | MDN. https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidate/type

mdn web docs. (2023e, April 25). Using WebRTC Data Channels - Web APIs | MDN. https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Using_data_channels

mdn web docs. (2023f, April 28). RTCPeerConnection - Web APIs | MDN. https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection

mdn web docs. (2023g, Mai 4). Introduction to WebRTC Protocols - Web APIs | MDN. https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Protocols

mdn web docs. (2023h, Mai 10). RTCPeerConnection: AddIceCandidate() Method - Web APIs | MDN. https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addIceCandidate

Multicast DNS. (2023). In Wikipedia. https://en.wikipedia.org/w/index.php?title=Multicast_DNS&oldid=1148215350

Network address translation. (2023). In Wikipedia. https://en.wikipedia.org/w/index.php?title=Network_address_translation&oldid=1153500450

NordVPN. (2023, März 27). What is UPnP? | NordVPN. https://nordvpn.com/blog/what-is-upnp/

Reddy.K, T., Johnston, A., Matthews, P., & Rosenberg, J. (2020). Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN) (Request for Comments RFC 8656). Internet Engineering Task Force. https://doi.org/10.17487/RFC8656

Rosenberg, J. (2010). Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols (Request for Comments RFC 5245). Internet Engineering Task Force. https://doi.org/10.17487/RFC5245

Rosenberg, J., Huitema, C., Mahy, R., & Weinberger, J. (2003). STUN - Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs) (Request for Comments RFC 3489). Internet Engineering Task Force. https://doi.org/10.17487/RFC3489

Stewart, R. R. (2007). Stream Control Transmission Protocol (Request for Comments RFC 4960). Internet Engineering Task Force. https://doi.org/10.17487/RFC4960

STUN. (2023). In Wikipedia. https://en.wikipedia.org/w/index.php?title=STUN&oldid=1152282467

Uberti, J. (2013). A REST API For Access To TURN Services (Internet Draft draft-uberti-behave-turn-rest-00). Internet Engineering Task Force. https://datatracker.ietf.org/doc/draft-uberti-behave-turn-rest-00

Uberti, J., & Shieh, G. (n.d.). WebRTC IP Address Handling Requirements (Internet Draft draft-ietf-rtcweb-ip-handling-09). Internet Engineering Task Force. https://datatracker.ietf.org/doc/draft-ietf-rtcweb-ip-handling-09

UDP hole punching. (2023). In Wikipedia. https://en.wikipedia.org/w/index.php?title=UDP_hole_punching&oldid=1141472485

Universal Plug and Play. (2023). In Wikipedia. https://de.wikipedia.org/w/index.php?title=Universal_Plug_and_Play&oldid=232271164

User Datagram Protocol. (2023). In Wikipedia. https://en.wikipedia.org/w/index.php?title=User_Datagram_Protocol&oldid=1153848688

Wärting, J. (2023). StreamSaver.js (legacy-ish) [JavaScript]. https://github.com/jimmywarting/StreamSaver.js (Original work published 2016)

Zhang, B., Li, Q., & Yan, J. (2020). The unfairness of UDP traffic in routers with different buffer units. Journal of Ambient Intelligence and Humanized Computing, 11(11), 4307-4307–4319. Springer Nature Journals. https://doi.org/10.1007/s12652-018-1024-8

 

© WaveNet8 2023-05-12

<< Back