- From: Robin Raymond <robin@hookflash.com>
- Date: Fri, 6 Feb 2015 11:32:53 -0500
- To: "public-ortc@w3.org" <public-ortc@w3.org>
- Message-ID: <etPan.54d4ecb6.74b0dc51.191@Robins-iMac.local>
Issue: What do we do about DTLS packets that can arrive before there's a DTLS transport to receive the DTLS packets? How this can happen: 1) Alice sends an offer containing ICE candidates (i.e. Alice has an IceGatherer but has not called IceTransport.start() because remote ufrag/password is not yet known) 2) Bob sends his response ufrag / password via signalling channel and starts ICE connectivity checks (i.e. he has called IceTransport.start() method) 3) Alice receives connectivity checks and responds (aka as agreed in last ORTC CG meeting re: issue #170 ) and she sends an ICE consent reply back to Bob (but she still has not received ufrag/password via signalling yet so she cannot call IceTransport.start() yet) 4) Bob receives ICE connectivity consent reply and therefor believes a channel is open to send the DtlsTransport client "hello" packet 5) Alice receives DtlsTransport client hello packet but does not have any IceTransport or DtlsTransport started to receive the DTLS client "hello" packets. While eventually Alice will receive the signalling necessary to setup an IceTransport and DtlsTransport, she may receive DTLS packets prematurely. Possible options: 1) Drop DTLS packets incoming, force DTLS client re-transmit (i.e. consequence is a slow started or disrupted connections); 2) Buffer DTLS packets incoming for a period of time and deliver packets to eventual IceTransport.start() which specifies a matching remote ufrag/password (i.e. consequence is insufficient buffering, over-buffering (DOS attack), or timeouts that drop packets pre-maturely before signalling arrives). 3) Put IceTransport into a .listen() mode of operation with a pre-wired DTLS transport (i.e. consequence is a larger / more complex ORTC API surface and one that must handle forking scenarios). This idea was briefly mentioned in last ORTC CG meeting. I personally favour option 2 or 3 options but not 1. If we are going to respond to connectivity checks (as per issue #170 ) then we are giving consent to the remote side to send data. To incorrectly drop incoming data despite giving consent seems wrong. If we do 3, then we need to be concerned with forking. If Alice sends out a set of offer candidates but multiple answers come back then a single IceTransport in .listen() mode will not be sufficient. We may want to consider having the gatherer in a .listen() mode [where an event is fired to tell of an unknown incoming connectivity consent check from an unknown remote ufrag never seen before) and thus having an IceTransport.accept() to specify where the incoming ICE connectivity checks must be processed. E.g. partial interface IceGatherer { void listen(); attribute EventHandler onunhandledice; } dictionary IceUnhandledEventInit : EventInit { DOMString remoteUFrag; }; partial interface IceTransport { //... void accept(DOMString remoteUFrag); } This API could handle forked replies too. This could also allow the connectivity checks to be replied from a particular IceTransport rather than from the IceGatherer (so long as there's a short buffering of incoming ICE connectivity checks exists for unhandled remote ufrag packets). This would also allow for wiring of a DTLS transport to handle the transport before the consent was given to the remote side (although replying to the incoming DTLS client "hello" would not be possible since no reverse ice consent would be granted). In other words, incoming connectivity checks are handled but outgoing connectivity checks are still not possible since the remote password would remain unknown until signalling arrived but at least the DTLS transport could be wired up before any DTLS packets would / could arrive. So IMHO, it's either buffer all packets until signalling arrives, or do a listen()/accept() scenario modelled after TCP listen()/accept(). -Robin
Received on Friday, 6 February 2015 16:33:28 UTC