Relay or no relay, that was the question
The miracle of the blogosphere happened again. My little rant about Jingle media relaying produced the expected effect, and I now have the answer: Google is effectively using media relaying in GTalk to cater for the 8% of NAT traversal cases not covered by their implementation of ICE. According to the information source,
the client discovers the relay's host, port and other information using a proprietary XMPP extension. The client communicates with the relay service to allocate ports.
It's a proprietary protocol. The team would like to replace the proprietary protocol with TURN.
Earlier today I conducted a simple experience of placing a call between two GTalk clients, with diagnostic logging enabled. Then I looked for an indication of media relaying in the resulting log, and here are my findings.
Immediately after initializing the XMPP session, the client goes on sending the following stanzas before any IM application requests :
[007:201] [8a8] SEND >>>>>>>>>>>>>>>>>>>>>>>>> : Mon Nov 06 10:48:29 2006
[007:201] [8a8] <presence type="unavailable"/>
[007:201] [8a8] SEND >>>>>>>>>>>>>>>>>>>>>>>>> : Mon Nov 06 10:48:29 2006
[007:211] [8a8] <iq type="get" id="7">
[007:211] [8a8] <query xmlns="google:relay"/>
[007:211] [8a8] </iq>
The client eventually gets an answer from the server:
[007:581] [8a8] RECV <<<<<<<<<<<<<<<<<<<<<<<<< : Mon Nov 06 10:48:30 2006
[007:581] [8a8] <iq to="email@example.com/Talk.v98734E454A" id="7" type="result">
[007:581] [8a8] <query xmlns="google:relay">
[007:581] [8a8] <token>
[007:581] [8a8] CAESHgoVamxzZWd1aW5lYXVAZ21haWwuY29tEIO2uPPrIRoQEWhSGqW0sC45unw91a8uNg==
[007:581] [8a8] </token>
[007:581] [8a8] </query>
[007:581] [8a8] </iq>
Later on during the exchange, it appears that the client is attempting a connection through HTTP to a relay.l.google.com host:
[138:820] [8a8] HTTPPortAllocator: starting request 1
[138:820] [8a8] HTTPPortAllocator: sending to host relay.l.google.com
[138:840] [8a8] HtmlWindow::GetHostInfo
[138:910] [38c] ReuseSocketPool - Creating new socket
[138:910] [38c] Resolving addr in PhysicalSocket::Connect
[138:910] [38c] === DNS RESOLUTION (relay.l.google.com) ===
[139:080] [38c] relay.l.google.com resolved to 22.214.171.124
[139:090] [38c] ReuseSocketPool - Opening connection to: relay.l.google.com:80
[139:391] [8a8] HTTPPortAllocator: HTTP request 1 succeeded with code 200
At this stage we enter the Google's Jingle transports candidates' negotiation. The client prepares the various candidates and then goes on trying them in sequence:
[139:401] [c8c] Jingle:Net[0:192.168.254.100]: Allocation Phase=Udp (Step=0)
[139:401] [c8c] Jingle:Port[rtp:local:Net[0:192.168.254.100]]: Added port to allocator
[139:401] [c8c] Jingle:Port[rtp:stun:Net[0:192.168.254.100]]: Added port to allocator
[139:401] [8a8] SEND >>>>>>>>>>>>>>>>>>>>>>>>> : Mon Nov 06 10:50:41 2006
[139:401] [8a8] <iq to="firstname.lastname@example.org/Talk.v100C3349241" type="set" id="37">
[139:401] [8a8] <session xmlns="http://www.google.com/session" type="transport-info"
[139:401] [8a8] <transport xmlns="http://www.google.com/transport/p2p">
[139:401] [8a8] <candidate name="rtp" address="192.168.254.100"
[139:401] [8a8] </transport>
[139:401] [8a8] </session>
[139:401] [8a8] </iq>
Following the specification the client determine the best connection from the candidates:
[140:462] [c8c] Jingle:Channel[rtp|__]: New best connection: Conn[0:rtp:local:192.168.254.100:1780->rtp:local:192.168.254.101:1237|C-w]
[140:462] [8a8] SEND >>>>>>>>>>>>>>>>>>>>>>>>> : Mon Nov 06 10:50:42 2006
[140:462] [8a8] <iq to="email@example.com/Talk.v100C3349241" id="83" type="result"/>
At this point, the client has established a preferred connection for direct RTP, but it nevertheless goes on and prepare a further connection through the relay, but as my call was local, it did not issued the corresponding candidate, instead connecting point-to-point through the local UDP candidate:
[141:464] [c8c] Jingle:Net[0:192.168.254.100]: Allocation Phase=Relay (Step=1)
[141:464] [c8c] Jingle:Port[rtp:relay:Net[0:192.168.254.100]]: Added port to allocator
[141:464] [c8c] Connecting to relay via udp @ 126.96.36.199:19295
[142:525] [c8c] Jingle:Net[0:192.168.254.100]: Allocation Phase=Tcp (Step=2)
[142:525] [c8c] Jingle:Port[rtp:local:Net[0:192.168.254.100]]: Added port to allocator
[142:535] [c8c] Jingle:Conn[0:rtp:local:192.168.254.100:1783->rtp:local:192.168.254.101:1240|--w]: set_connected
From this scenario, I can hazard a hypothesis about the way a GTalk client negotiates media relaying.
- The client uses a proprietary XMPP extension to query the relay service and receives an opaque token if the request is successful. I believe the token is destined to authorize a later use of the media relay to the client who made the request.
- The client then retrieves the appropriate relay parameters though HTTP, probably presenting the previous token as an authorization reference, and not through an XMPP interface as my source stated.
- The client then creates a transport candidate from the received parameters, and assign it a lower priority than the UDP and TCP candidates. It uses this candidate in the transport negotiation sequence.
Although I am missing the proper test environment to verify my hypothesis, my first finding concens the inaccuracies in the description of an otherwise rather standard and expected technical solution. I leave you to decide why the mechanism has been described as XMPP, where in fact it appears to be a mix of HTTP and XMPP. I personally find this disturbing, as it can be leading to more inaccuracies of the sort finding their way into the Jingle specification. I am ready to accept that Google is concerned, but I do not believe disclosing this mechanism will ever put that company at risk.
But, when I reflect on the position taken publicly by the authors of the XMPP Jingle specification in favor of using TURN to deal with media relaying negotiation, I am worried of the possible impact of their stand on the specification completion time and on the ensuing implementation by developers.
As I stated earlier, ICE and TURN are "work in progress" drafts, which have already been lingering at the IETF for over a year since Google announced the GTalk service. During that past year, the activity around the XMPP Jingle specification has been very slow to take up.
- On one hand, the specification has only recently been published toward a last call before JSF council approval.
- On the other hand, I believe the inherent complexity of media support libraries slows down the implementation of Jingle at the client level because developers need to master these new and unfamiliar concepts.
Apart from notable support in open source IPBX, implemented by developers well versed in the intricacies of media communication programming, I only know of the the Jabbin project as a tentative implementation of a free Jingle client...
I believe it would not be realistic to push at all cost a Jingle specification highly dependent on forthcoming RFCs without any foreseeable time of publication of the said standards. The community would benefit more from an interim specification, leveraging instead existing RFCs, such as raw RTP, STUN and media relaying for NAT traversal, to be later updated when the ICE draft is made into an RFC. This approach would have the added advantage of being less complex from a programming stand-point, and would provide a more gradual learning curve for the developers to get accustomed to the subtleties of multi-media communication.Technorati Tags: XMPP, Jabber, Jingle, VoIP, Session signaling, NAT, TURN, Antecipate