├── .gitignore ├── README.md ├── _config.yml ├── demo-multicast-receive-api.html └── explainer.md /.gitignore: -------------------------------------------------------------------------------- 1 | .*.sw? 2 | *~ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MulticastReceiver 2 | 3 | An API that allows web applications to join a multicast (S,G) and receive 4 | authenticated, congestion-safe multicast IP traffic from services that 5 | offer it. 6 | 7 | It provides: 8 | 9 | * per-packet authentication 10 | * an origin-based security model 11 | * protection against over-subscription 12 | 13 | This lets browsers join in subscribing to popular live media events or 14 | file downloads (software or pre-recorded media) that make use of multicast 15 | IP to enable the efficient use of network and server resources. 16 | 17 | See the [explainer](explainer.md) for more info. 18 | 19 | Visit the [demo page](https://grumpyoldtroll.github.io/wicg-multicast-receiver-api/demo-multicast-receive-api.html) with a [browser that implements the API](https://github.com/GrumpyOldTroll/chromium_fork) to experiment with trying to receive traffic. (You may need some extra steps to receive external traffic, see the [getting started](https://github.com/w3c/multicast-cg/blob/main/primers/01-getting-started.md) primer for help, and please open issues if you encounter trouble.) 20 | 21 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | title: Multicast Receive API Proposal 2 | description: proposal to add a generic multicast receive API to web browsers. 3 | remote_theme: pmarsceill/just-the-docs 4 | color_scheme: dark 5 | -------------------------------------------------------------------------------- /demo-multicast-receive-api.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | MulticastReceive API Demo 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 34 | 45 | 46 | 47 |
20 |

21 |

22 | 23 |
24 | 25 |
26 | 27 |
28 | 29 |
30 | 31 |
32 |

33 |
35 |

36 |

37 |

38 |

39 |
40 |
41 | 42 |
43 |

44 |
48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
#Multicast Stream: (S->G):P/DORMSStatusStatsAction
63 |
64 |
65 | 66 | 67 | 68 | 69 | 70 | 71 | 314 | 315 | 316 | 317 | -------------------------------------------------------------------------------- /explainer.md: -------------------------------------------------------------------------------- 1 | # MulticastReceiver Explainer 2 | 3 | ## Problem and Motivation 4 | 5 | The capacity of CDNs and others to deliver popular content at 6 | scale is not keeping up with demand. 7 | 8 | ### Scaling Problem Examples 9 | 10 | A few different presentations have addressed the scaling problem that can be solved by multiast, but we'll refer here to some real-world numbers presented at NANOG 79: 11 | 12 | * [video](https://www.youtube.com/watch?v=2aihLUb1elg&t=4m56s) 13 | * [slides](https://storage.googleapis.com/site-media-prod/meetings/NANOG79/2209/20200530_Holland_Ip_Multicast_Next_v1.pdf#page=5) 14 | 15 | NB: The presentation used [mistaken numbers](https://github.com/GrumpyOldTroll/wicg-multicast-receiver-api/issues/2) for video bitrate estimates, corrected below, but the overall point still holds. The arithmetic is simple. 16 | 17 | * `167 tbps`: new record peak traffic delivery to end users, announced [April 2020](https://news.mit.edu/2020/3-questions-tom-leighton-managing-covid-19-internet-traffic-surge-0427) by Akamai. 18 | 19 | #### Linear Media Delivery 20 | 21 | Using these values: 22 | 23 | * **20 mbps**: bit-rate for 4k video 24 | * **5 mbps**: bit-rate for 1080p video 25 | 26 | Example reachable audience sizes: 27 | 28 | * **8.35m users** = 167 tbps / (20mbps / end user) 29 | * **33.5m users** = 167 tbps / (5mbps / end user) 30 | 31 | For comparison, audience sizes of popular events: 32 | 33 | Overall viewership: 34 | 35 | * 500m = Fifa World Cup Finals, 2018 36 | * 200m-300m = Cricket World Cup 2015 (whenever India is playing) 37 | * 100m = Super Bowl 2019 38 | 39 | Online Viewership: 40 | 41 | * 6m viewers = Twitch concurrent viewers [all time peak](https://twitchtracker.com/statistics) in June 2020 (as of December 2020) 42 | * 9m viewers = 2018 World Cup [peak concurrent online viewers](https://www.conviva.com/peak-concurrent-plays-broke-records-world-cup-finals/) 43 | 44 | What *is* achievable in 4k as a maximum upper bound?: 45 | 46 | * Most popular 2017-2018 Nielsen show with \<8.3m viewers is ranked **#43** ("Scorpion") 47 | 48 | When one of the largest providers on the Internet can only handle the 49 | 43rd-most popular TV show with no extra capacity before setting a 50 | new record for traffic because of the Internet's unicast delivery model, 51 | the Internet is really not living up to its potential. 52 | 53 | #### Downloads 54 | 55 | Consider a 2GB OS upgrade that has to be delivered to 1b devices. What's 56 | the average delivery time at a high-end peak delivery rate? 57 | 58 | * **1.1 days** = 2GB * 1b devices / 167 Tbps 59 | 60 | Consider also that some OS or app updates are over **10GB**, and therefore 61 | would take over **11 days** to deliver to 1b users, at a record-setting 62 | aggregate delivery rate, doing nothing else. (Sure hope there's no urgent 63 | security updates!) 64 | 65 | ### Conclusion 66 | 67 | We think these problems of scale are addressable with IP Multicast. 68 | 69 | If web pages were able to subscribe to this kind of popular content and 70 | have traffic replicated to many end users as part of delivery through the 71 | network, it would have a transformative effect on the capability of the 72 | Internet to handle these scaling issues, and would provide dramatic network 73 | efficiency gains, even for much less popular content than the extreme 74 | cases. 75 | 76 | (The extreme cases simply can't be done satisfactorily on the 77 | Internet by any means today, regardless of the real-world need to do 78 | them sometimes.) 79 | 80 | ## Goals 81 | 82 | * Provide a way to subscribe to one-to-many multicast streams. 83 | 84 | * Provide an API that can be used by many use cases. There are lots 85 | of protocols, some of them proprietary. As long as they can live 86 | within the safety rules, they're all welcome. 87 | 88 | * Authenticate the traffic cryptographically. An app can only receive 89 | data from a packet with cryptographic proof that it was sent by the 90 | correct sender, with a server-controlled origin policy. 91 | 92 | * Ensure network safety. Using the API cannot blow out the network 93 | by signing up for too much traffic, because that will get noticed 94 | and the group will be pruned at the browser (and also probably in 95 | the network, if it succeeds at the browser). 96 | 97 | ## Non-goals 98 | 99 | * Sending. This API does not do any outbound data traffic. The functions in this API invoke a few outbound packets with IGMP or MLD, plus some other signaling protocols defined in the IETF's RFC series, but provides no capability to create app-controllable outbound traffic, outside of the specific narrow signaling to join multicast groups and process their traffic. 100 | 101 | * ASM (Any-Source Multicast). This proposal only permits use of 102 | [SSM](https://tools.ietf.org/html/rfc4607) (Source Specific Multicast). 103 | (NB: [RFC 8815](https://tools.ietf.org/html/rfc8815) deprecated interdomain multicast using ASM) 104 | 105 | * Privacy and Secrecy within your local network. 106 | 107 | As a receiver, your IGMP or MLD membership report goes on the LAN, to a local 108 | network that can see your machine's IP and MAC address. 109 | 110 | The network is replicating the packets, and they know the global IP 111 | for source and group. If they want to, they can probably find out 112 | what content it contains. 113 | 114 | This API is mainly for content that's so popular it's expected that 115 | lots of people will consume it, but if you can't let your local 116 | network know you're consuming it, you'll have to tunnel it in as 117 | secured unicast from somewhere else that can know. It's NOT just you 118 | and the sender, and it cannot be, because the network is involved in 119 | replicating the packets. You need to have a trust relationship with 120 | someone downstream of that packet replication, because they can find 121 | out what you're consuming. 122 | 123 | Upstream of your local network it gets more private--they'll only 124 | know that at least one machine inside your network is subscribed, 125 | without knowing who it was. But you can assume your next-hop router 126 | will know that your machine has asked to receive a specific piece of 127 | content. 128 | 129 | * Encrypting the data. 130 | 131 | Although the sender MAY encrypt the data, it is not required, 132 | nor is it effective at providing privacy or secrecy in the intended 133 | use case of a scalable one-to-many distribution. The contents of the 134 | packets are sent to many receivers, and some of them will not be 135 | trustworthy. Any key that allows a receiver to decrypt it will also be 136 | available to the receiver's adversaries, perhaps because they are a 137 | legitimate customer to the sender and paid for it. 138 | 139 | That said, the data could for example be built out of encrypted 140 | segments, and the receiver could construct those segments and feed them 141 | into a player that provides its own guarantees about key control, as many existing DRM systems do. 142 | 143 | Nothing prevents the data from being encrypted, it is entirely possible and likely for some use cases. 144 | But nothing in this architecture provides or requires encryption for the transported data. 145 | This spec provides authenticated UDP payloads to the web app, and a different layer would have to understand the content of those payloads (including whether they hold encrypted data). 146 | 147 | ## Proposed Solution 148 | 149 | ### Overview 150 | 151 | The API subscribes to a Source Specific Multicast (S,G) with a UDP port 152 | number and a domain name for the authentication metadata. After that, 153 | it receives UDP payloads if the join is successful (and may of course 154 | leave). 155 | 156 | If the loss rate is high enough or if the total bandwidth would go above 157 | a system-managed threshold, the join will fail with an error. 158 | 159 | If the loss rate is above a safety threshold but below an emergency 160 | disconnect threshold, there's a signal and grace period for the application 161 | to gracefully transition to a state that maintains a lower loss level. 162 | 163 | ### Specifications 164 | 165 | This API will build upon an ongoing set of efforts within the IETF. The 166 | basic idea is to provide a standardized and secure method for the browser 167 | to discover and process metadata about the traffic streams, which it can 168 | use to ensure safe operation. (The network MAY also use the same 169 | metadata to ensure network safety.) 170 | 171 | * DORMS (Discovery Of RESTCONF Metadata for SSM): 172 | 173 | [draft-ietf-mboned-dorms](https://datatracker.ietf.org/doc/draft-ietf-mboned-dorms/) 174 | 175 | This defines a mechanism for the metadata to get discovered and 176 | delivered to the browser and the network. (It uses 177 | [RESTCONF](https://tools.ietf.org/html/rfc8040) and a 178 | [YANG](https://tools.ietf.org/html/rfc7950) model.) The other 2 179 | (AMBI and CBACC, below), extend that data with the info they need to 180 | operate. 181 | 182 | * AMBI (Asymmetric Manifest-Based Integrity): 183 | 184 | [draft-ietf-mboned-ambi](https://datatracker.ietf.org/doc/draft-ietf-mboned-ambi/) 185 | 186 | This is how the browser verifies the integrity of the data received 187 | and gets the information to monitor packet loss, without needing to 188 | understand the payload of the protocol being delivered. It sends 189 | packet hashes out of band in an authenticated stream, so the 190 | receiver knows whether it received what the sender sent. 191 | 192 | * CBACC (Circuit Breaker Assisted Congestion Control): 193 | 194 | [draft-ietf-mboned-cbacc](https://datatracker.ietf.org/doc/draft-ietf-mboned-cbacc/) 195 | 196 | This is how the browser (and the network) ensure that capacity 197 | limits are not exceeded. This defines the behavior both for a 198 | policy-based limit, and for responding to loss by using the 199 | loss detection provided by AMBI. It notices and cuts off 200 | multicast streams whenever someone has over-subscribed. 201 | 202 | Note: other relevant extensions may be forthcoming. In particular, some 203 | work is ongoing to define a transport for AMBI that can live inside the 204 | same multicast channel as the data using 205 | [ALTA](https://datatracker.ietf.org/doc/draft-krose-mboned-alta/) to 206 | authenticate the packet manifests. (We hope this will make for 207 | some improvements in achievable latency targets.) 208 | However, the components listed here are intended to be sufficient to 209 | provide a safe core architecture, and to be adequate on their own for 210 | solutions to scalability problems where network support for multicast is 211 | enabled, and for use cases where the achievable latency is acceptable. 212 | 213 | ### JavaScript API 214 | 215 | Here is an example that joins a multicast flow for 20 seconds. 216 | 217 | ```javascript 218 | // Multicast flow to join: 219 | 220 | let multicastFlow = { 221 | source: '198.51.100.10', 222 | group: '232.10.10.1', 223 | port: 5001, 224 | dorms: 'dorms.example.com' 225 | }; 226 | 227 | // Construct MulticastReceiver and subscribe to the multicast flow on the 228 | // network: 229 | 230 | let multicastReceiver=new MulticastReceiver(multicastFlow); 231 | 232 | // Read multicast UDP packets: 233 | 234 | let multicastReader=multicastReceiver.readable.getReader(); 235 | 236 | async function readMulticastData() { 237 | for(;;) { 238 | let { done, value } = await multicastReader.read(); 239 | if(done) { 240 | return; 241 | } else { 242 | // value is an UInt8Array with the payload of one UDP packet. 243 | console.log("Got multicast packet with size "+value.length); 244 | } 245 | } 246 | } 247 | 248 | readMulticastData().then( () => { 249 | console.log("Cancel was called."); 250 | }).catch( error => { 251 | console.log(error,"Error. Closecode is "+multicastReader.closecode); 252 | }); 253 | 254 | // Cancel after 20 seconds: 255 | 256 | setTimeout( () => { 257 | console.log("Canceling multicast"); 258 | multicastReader.cancel(); 259 | },20000); 260 | ``` 261 | 262 | The browser will try to join the multicast flow on the network as soon as MulticastReceiver is constructed. The browser will leave the multicast flow on the network whenever there is an event that will trigger either a) a promise returned by `read()` to be rejected or b) the `done` value to become true. After such an event, no more multicast data can be read from that MulticastReceiver. So if JavaScript wants to receive the same or another multicast flow later, it will need to construct a new MulticastReceiver. 263 | 264 | In case the promise returned by `read()` is rejected, it will be rejected with an informative text which may be useful for debugging and which is logged to the console in the example above. In addition to this, the closecode will be set to one of several well-known values such as: 265 | 266 | * `MulticastReceiver.FLOW_PROBLEM`: There was a problem with the multicast flow itself. For example: 267 | * DORMS could not identify a multicast flow on the given source and group. 268 | * The multicast flow had a higher bandwidth than announced by DORMS. 269 | * Multicast packets were received but could not be authenticated. 270 | * `MulticastReceiver.LOCAL_PROBLEM`: There was a problem on the local device that prevented reception of the multicast flow. For example: 271 | * A socket to receive multicast on could not be created or was closed. 272 | * `MulticastReceiver.OVERSUBSCRIBED`: A CBACC oversubscription threshold (see below) was reached so the left the multicast flow or did not join it at all. 273 | 274 | ### Getting DORMS metadata 275 | 276 | Consider the subscription to the multicast flow from the example in the previous section: 277 | 278 | ```javascript 279 | { 280 | source: '198.51.100.10', 281 | group: '232.10.10.1', 282 | port: 5001, 283 | dorms: 'dorms.example.com' 284 | }; 285 | ``` 286 | 287 | Here `dorms.example.com` is a domain name and an optional port (default is 443) where the browser will try to get metadata for the multicast flow with HTTPS as described in the DORMS specification. Among other things, this metadata must include the trust anchor used by AMBI to perform integrity checks on the multicast flow. When downloading the metadata, the browser will verify that the server presents a valid certificate for `dorms.example.com`. This ensures that a chain of trust is established from the JavaScript that subscribes to a multicast flow and to the integrity checks the browser performs using AMBI. 288 | 289 | We also want to ensure that the browser only subscribes to a multicast flow which wants to be subscribed to by a browser. This is to prevent for example: 290 | 291 | * A malicious website to subscribe to a multicast flow private to a network. 292 | * A pirate website to subscribe to a multicast flow from a normal website. 293 | 294 | There are two mechanisms in place to prevent this: 295 | 296 | * When downloading DORMS metadata with HTTPS, the browser will perform [CORS](https://fetch.spec.whatwg.org/#http-cors-protocol) checks. 297 | * The DORMS server provided by JavaScript needs to be the same identified by the DORMS reverse-DNS scheme described in the DORMS specification (see next paragraph). 298 | 299 | The second bullet ensures that JavaScript can only subscribe to a multicast flow from a given source IP if the reverse DNS of that source IP has been setup to allow it. More precisely, when receiving the multicast subscription in our example, the browser will make a reverse-DNS lookup for a `SRV` record for the domain `_dorms._tcp.10.100.51.198.in-addr.arpa`. In order for the subscription to succeed, this must give a `SRV` record with the hostname `dorms.example.com` and port 443. A different port can be used if provided in the JavaScript API as well. Obviously, DNS is usually not considered secure, so in some cases it may be possible to hack DNS to circumvent this check. This problem may need further considerations. 300 | 301 | ### TBDs 302 | 303 | TBD: In the current API, one packet is delivered at a time to JavaScript. This is similar to how datagrams work in [WebTransport](https://github.com/WICG/web-transport). We may want to deliver multiple packets at a time for performance reasons. We are currently working on profiling this in Chromium. 304 | 305 | TBD: It would be nice if JavaScript had access to precise timestamps for when packets are received by the OS or at least by the browser from the OS. This could allow JavaScript to implement protocols for detecting the amount of available bandwidth using mechanisms such as [pathchirp](http://www.spin.rice.edu/Software/pathChirp/) and/or [pathrate](https://www.cc.gatech.edu/~dovrolis/bw-est/pathrate.html). Do we want to support this? And if we do, what should the API look like? It seems like an extra field in the object returned by `read()` would be an obvious place. But this may not be compatible with the ReadableStream system. So we may need to wrap the UInt8Array with the packet content in an extra object? 306 | 307 | TBD: Define the CBACC oversubscription threshold model for the browser. 308 | The rough initial idea is to start with a threshold at ~1mbps, grow if it's 309 | succeeding without loss, and shrink if loss goes persistently high. 310 | 311 | TBD: add api extensions for loss rate reporting ahead of cbacc+ambi-based cutoff. need some kind of early warning from stats. 312 | 313 | TBD: We may want to extend the API such that the browser can inform JavaScript that a CBACC oversubscription threshold is about to be reached. This may allow JavaScript to decide which multicast flows to unsubscribe from rather than relying on the browser to select one or more flows and close them with an `MulticastReceiver.OVERSUBSCRIBED` closecode. 314 | 315 | TBD: If JavaScript is not reading any packets, should the browser close the multicast flow with a specific closecode? Related to this, should there be an API where JavaScript can set the maximum number of packets that can be queued up internally in the ReadableStream? 316 | 317 | TBD: Should the browser unsubscribe automatically from a multicast flow on which no data is received from the network? Most likely the answer is *no* as subscription to a multicast flow without data can be used to signal to the network that it may consider creating the flow. 318 | 319 | TBD: AMBI may give information about dropped packets. Do we want that information to be available in the API? Perhaps by the reading of a special packet that indicates one or more dropped packets. 320 | 321 | TBD: Detailed design. This early draft is intended to solicit community 322 | feedback about whether this general approach is doomed for reasons not 323 | addressed in the IETF drafts, or whether attempting an implementation and 324 | filling out all the details will actually be deployable, once it all works. 325 | 326 | ## Alternative designs considered 327 | 328 | ### Specific Protocols 329 | 330 | It's reasonable to question why we wouldn't solve the scaling problem by 331 | defining an API for a specific transport protocol, such as 332 | [FLUTE](https://tools.ietf.org/html/rfc6726) or 333 | [NORM](https://tools.ietf.org/html/rfc5740), 334 | or by adding support for [RTP](https://tools.ietf.org/html/rfc3550) with [RAMS](https://tools.ietf.org/html/rfc6285) or other 335 | [multicast-enabling features](https://tools.ietf.org/html/rfc5760). 336 | 337 | Part of the problem is that many existing applications (such as IPTV 338 | systems currently deployed by some ISPs) don't use these protocols, 339 | and we hope not to exclude their use cases, even though some of the 340 | deployments use proprietary protocols with no publicly available 341 | implementations. 342 | 343 | Multicast IP also is an area of ongoing research with new protocols 344 | still being developed, for example 345 | [draft-pardue-quic-http-mcast](https://datatracker.ietf.org/doc/draft-pardue-quic-http-mcast/). We believe enabling this kind of experimentation 346 | with web apps will be extremely valuable. 347 | 348 | Additionally, a number of gaming or communication protocols exist 349 | that are built directly on top of unreliable UDP transport, and are 350 | specific to the application itself. These applications are also often 351 | proprietary or least non-standard (but still sometimes deployed and 352 | useful and could benefit from scalability). 353 | 354 | The intent of the proposed architecture is to provide all the necessary 355 | guard rails to ensure safety for the network and receiver so that 356 | interdomain multicast can be delivered approximately as safely as other 357 | kinds of traffic, while permitting experimentation that can realize the 358 | untapped potential for a wide variety of uni-directional one-to-many 359 | protocol designs. 360 | 361 | ### WebTransport 362 | 363 | It has been suggested that this might fit as a unidirectional protocol 364 | definition within [WebTransport](https://github.com/WICG/web-transport). 365 | 366 | As it stands today, this proposal is not compatible with the WebTransport 367 | goal of "Ensure the same security properties as WebSockets", because the 368 | one-to-many nature of this proposal makes it impossible to provide the 369 | same security guarantees as TLS. 370 | 371 | After discussion with some of the WebTransport contributors, the advice 372 | was to open this as an independent proposal. 373 | 374 | If there's enough consensus that it's worthwhile, perhaps it's possible 375 | to make the goals compatible in some way and to fold this proposal into 376 | a subset of WebTransport. But as of today the idea has been (very 377 | tentatively) considered, and sits somewhere between 'rejected' and 378 | 'deferred'. 379 | 380 | --------------------------------------------------------------------------------