2b91f92f4887649dbf77bd6987de31bb63fc0444
[platform/upstream/libnice.git] / socket / udp-turn-over-tcp.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2008-2009 Collabora Ltd.
5  *  Contact: Youness Alaoui
6  * (C) 2008-2009 Nokia Corporation. All rights reserved.
7  *
8  * The contents of this file are subject to the Mozilla Public License Version
9  * 1.1 (the "License"); you may not use this file except in compliance with
10  * the License. You may obtain a copy of the License at
11  * http://www.mozilla.org/MPL/
12  *
13  * Software distributed under the License is distributed on an "AS IS" basis,
14  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
15  * for the specific language governing rights and limitations under the
16  * License.
17  *
18  * The Original Code is the Nice GLib ICE library.
19  *
20  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
21  * Corporation. All Rights Reserved.
22  *
23  * Contributors:
24  *   Youness Alaoui, Collabora Ltd.
25  *
26  * Alternatively, the contents of this file may be used under the terms of the
27  * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
28  * case the provisions of LGPL are applicable instead of those above. If you
29  * wish to allow use of your version of this file only under the terms of the
30  * LGPL and not to allow others to use your version of this file under the
31  * MPL, indicate your decision by deleting the provisions above and replace
32  * them with the notice and other provisions required by the LGPL. If you do
33  * not delete the provisions above, a recipient may use your version of this
34  * file under either the MPL or the LGPL.
35  */
36
37 /*
38  * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
39  * http://en.wikipedia.org/wiki/Berkeley_sockets.)
40  */
41 #ifdef HAVE_CONFIG_H
42 # include "config.h"
43 #endif
44
45 #include "udp-turn-over-tcp.h"
46 #include "agent-priv.h"
47
48 #include <string.h>
49 #include <errno.h>
50 #include <fcntl.h>
51
52 #ifndef G_OS_WIN32
53 #include <unistd.h>
54 #endif
55
56 typedef struct {
57   NiceTurnSocketCompatibility compatibility;
58   union {
59     guint8 u8[65536];
60     guint16 u16[32768];
61   } recv_buf;
62   gsize recv_buf_len;  /* in bytes */
63   guint expecting_len;
64   NiceSocket *base_socket;
65 } TurnTcpPriv;
66
67 typedef enum {
68   MS_TURN_CONTROL_MESSAGE = 2,
69   MS_TURN_END_TO_END_DATA = 3
70 } MsTurnPayloadType;
71
72 #define MAX_UDP_MESSAGE_SIZE 65535
73
74 #define MAGIC_COOKIE_OFFSET \
75   STUN_MESSAGE_HEADER_LENGTH + STUN_MESSAGE_TYPE_LEN + \
76   STUN_MESSAGE_LENGTH_LEN + sizeof(guint16)
77
78 static void socket_close (NiceSocket *sock);
79 static gint socket_recv_messages (NiceSocket *sock,
80     NiceInputMessage *recv_messages, guint n_recv_messages);
81 static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
82     const NiceOutputMessage *messages, guint n_messages);
83 static gint socket_send_messages_reliable (NiceSocket *sock,
84     const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
85 static gboolean socket_is_reliable (NiceSocket *sock);
86 static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
87 static void socket_set_writable_callback (NiceSocket *sock,
88     NiceSocketWritableCb callback, gpointer user_data);
89 static gboolean socket_is_based_on (NiceSocket *sock, NiceSocket *other);
90
91 NiceSocket *
92 nice_udp_turn_over_tcp_socket_new (NiceSocket *base_socket,
93     NiceTurnSocketCompatibility compatibility)
94 {
95   TurnTcpPriv *priv;
96   NiceSocket *sock = g_slice_new0 (NiceSocket);
97   sock->priv = priv = g_slice_new0 (TurnTcpPriv);
98
99   priv->compatibility = compatibility;
100   priv->base_socket = base_socket;
101
102   sock->type = NICE_SOCKET_TYPE_UDP_TURN_OVER_TCP;
103   sock->fileno = priv->base_socket->fileno;
104   sock->addr = priv->base_socket->addr;
105   sock->send_messages = socket_send_messages;
106   sock->send_messages_reliable = socket_send_messages_reliable;
107   sock->recv_messages = socket_recv_messages;
108   sock->is_reliable = socket_is_reliable;
109   sock->can_send = socket_can_send;
110   sock->set_writable_callback = socket_set_writable_callback;
111   sock->is_based_on = socket_is_based_on;
112   sock->close = socket_close;
113
114   return sock;
115 }
116
117
118 static void
119 socket_close (NiceSocket *sock)
120 {
121   TurnTcpPriv *priv = sock->priv;
122
123   if (priv->base_socket)
124     nice_socket_free (priv->base_socket);
125
126   g_slice_free(TurnTcpPriv, sock->priv);
127   sock->priv = NULL;
128 }
129
130 static gssize
131 socket_recv_message (NiceSocket *sock, NiceInputMessage *recv_message)
132 {
133   TurnTcpPriv *priv = sock->priv;
134   gssize ret;
135   guint padlen;
136   GInputVector local_recv_buf;
137   NiceInputMessage local_recv_message;
138
139   /* Make sure socket has not been freed: */
140   g_assert (sock->priv != NULL);
141
142   if (priv->expecting_len == 0) {
143     guint headerlen = 0;
144
145     if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
146         priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 ||
147         priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007)
148       headerlen = 4;
149     else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE)
150       headerlen = 2;
151     else
152       return -1;
153
154     local_recv_buf.buffer = priv->recv_buf.u8 + priv->recv_buf_len;
155     local_recv_buf.size = headerlen - priv->recv_buf_len;
156     local_recv_message.buffers = &local_recv_buf;
157     local_recv_message.n_buffers = 1;
158     local_recv_message.from = recv_message->from;
159     local_recv_message.length = 0;
160
161     ret = nice_socket_recv_messages (priv->base_socket, &local_recv_message, 1);
162     if (ret < 0)
163         return ret;
164
165     priv->recv_buf_len += local_recv_message.length;
166
167     if (priv->recv_buf_len < headerlen)
168       return 0;
169
170     if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
171         priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
172       guint16 magic = ntohs (*priv->recv_buf.u16);
173       guint16 packetlen = ntohs (*(priv->recv_buf.u16 + 1));
174
175       if (magic < 0x4000) {
176         /* Its STUN */
177         priv->expecting_len = 20 + packetlen;
178       } else {
179         /* Channel data */
180         priv->expecting_len = 4 + packetlen;
181       }
182     }
183     else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
184       guint compat_len = ntohs (*priv->recv_buf.u16);
185       priv->expecting_len = compat_len;
186       priv->recv_buf_len = 0;
187     }
188     else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) {
189       guint8 pt = *priv->recv_buf.u8;
190       guint16 packetlen = ntohs (priv->recv_buf.u16[1]);
191
192       if (pt != MS_TURN_CONTROL_MESSAGE &&
193           pt != MS_TURN_END_TO_END_DATA) {
194         /* Unexpected data, error in stream */
195         return -1;
196       }
197
198       /* Keep the RFC4571 framing for the NiceAgent to unframe */
199       priv->expecting_len = packetlen + sizeof(guint16);
200       priv->recv_buf_len = sizeof(guint16);
201       priv->recv_buf.u16[0] = priv->recv_buf.u16[1];
202     }
203   }
204
205   if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
206       priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766)
207     padlen = (priv->expecting_len % 4) ?  4 - (priv->expecting_len % 4) : 0;
208   else
209     padlen = 0;
210
211   local_recv_buf.buffer = priv->recv_buf.u8 + priv->recv_buf_len;
212   local_recv_buf.size = priv->expecting_len + padlen - priv->recv_buf_len;
213   local_recv_message.buffers = &local_recv_buf;
214   local_recv_message.n_buffers = 1;
215   local_recv_message.from = recv_message->from;
216   local_recv_message.length = 0;
217
218   ret = nice_socket_recv_messages (priv->base_socket, &local_recv_message, 1);
219   if (ret < 0)
220       return ret;
221
222   priv->recv_buf_len += local_recv_message.length;
223
224   if (priv->recv_buf_len == priv->expecting_len + padlen) {
225     /* FIXME: Eliminate this memcpy(). */
226     ret = memcpy_buffer_to_input_message (recv_message,
227         priv->recv_buf.u8, priv->recv_buf_len);
228
229     priv->expecting_len = 0;
230     priv->recv_buf_len = 0;
231
232     return ret;
233   }
234
235   return 0;
236 }
237
238 static gint
239 socket_recv_messages (NiceSocket *nicesock,
240     NiceInputMessage *recv_messages, guint n_recv_messages)
241 {
242   guint i;
243   gboolean error = FALSE;
244
245   /* Make sure socket has not been freed: */
246   g_assert (nicesock->priv != NULL);
247
248   for (i = 0; i < n_recv_messages; i++) {
249     gssize len;
250
251     len = socket_recv_message (nicesock, &recv_messages[i]);
252     recv_messages[i].length = MAX (len, 0);
253
254     if (len < 0)
255       error = TRUE;
256
257     if (len <= 0)
258       break;
259   }
260
261   /* Was there an error processing the first message? */
262   if (error && i == 0)
263     return -1;
264
265   return i;
266 }
267
268 static gssize
269 socket_send_message (NiceSocket *sock, const NiceAddress *to,
270     const NiceOutputMessage *message, gboolean reliable)
271 {
272   TurnTcpPriv *priv = sock->priv;
273   guint8 padbuf[3] = {0, 0, 0};
274   GOutputVector *local_bufs;
275   NiceOutputMessage local_message;
276   guint j;
277   gint ret;
278   guint n_bufs;
279   union {
280     guint16 google_len;
281     struct {
282       guint8 pt;
283       guint8 zero;
284     } msoc;
285   } header_buf;
286   guint offset = 0;
287
288   /* Make sure socket has not been freed: */
289   g_assert (sock->priv != NULL);
290
291   /* Count the number of buffers. */
292   if (message->n_buffers == -1) {
293     n_bufs = 0;
294
295     for (j = 0; message->buffers[j].buffer != NULL; j++)
296       n_bufs++;
297   } else {
298     n_bufs = message->n_buffers;
299   }
300
301   /* Allocate a new array of buffers, covering all the buffers in the input
302    * @message, but with an additional one for a header and one for a footer. */
303   local_bufs = g_alloca ((n_bufs + 1) * sizeof (GOutputVector));
304   local_message.buffers = local_bufs;
305   local_message.n_buffers = n_bufs + 1;
306
307   if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
308     header_buf.google_len = htons (output_message_get_size (message));
309     local_bufs[0].buffer = &header_buf;
310     local_bufs[0].size = sizeof (guint16);
311     offset = 1;
312   } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
313       priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
314     gsize message_len = output_message_get_size (message);
315     gsize padlen = (message_len % 4) ? 4 - (message_len % 4) : 0;
316
317     local_bufs[n_bufs].buffer = &padbuf;
318     local_bufs[n_bufs].size = padlen;
319   } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) {
320     union {
321       guint32 u32;
322       guint8 u8[4];
323     } cookie;
324     guint16 len = output_message_get_size (message);
325
326     /* Copy the cookie from possibly split messages */
327     cookie.u32 = 0;
328     if (len > sizeof (TURN_MAGIC_COOKIE) + MAGIC_COOKIE_OFFSET) {
329       guint16 buf_offset = 0;
330       guint i;
331
332       for (i = 0; i < n_bufs; i++) {
333         if (message->buffers[i].size >
334             (gsize) (MAGIC_COOKIE_OFFSET - buf_offset)) {
335           /* If the cookie is split, we assume it's data */
336           if (message->buffers[i].size > sizeof (TURN_MAGIC_COOKIE) +
337               MAGIC_COOKIE_OFFSET - buf_offset) {
338             const guint8 *buf = message->buffers[i].buffer;
339             memcpy (&cookie.u8, buf + MAGIC_COOKIE_OFFSET - buf_offset,
340                 sizeof (TURN_MAGIC_COOKIE));
341           }
342           break;
343         } else {
344           buf_offset += message->buffers[i].size;
345         }
346       }
347     }
348
349     cookie.u32 = ntohl(cookie.u32);
350     header_buf.msoc.zero = 0;
351     if (cookie.u32 == TURN_MAGIC_COOKIE)
352       header_buf.msoc.pt = MS_TURN_CONTROL_MESSAGE;
353     else
354       header_buf.msoc.pt = MS_TURN_END_TO_END_DATA;
355
356     local_bufs[0].buffer = &header_buf;
357     local_bufs[0].size = sizeof(header_buf.msoc);
358     offset = 1;
359   } else {
360     local_message.n_buffers = n_bufs;
361   }
362
363   /* Copy the existing buffers across. */
364   for (j = 0; j < n_bufs; j++) {
365     local_bufs[j + offset].buffer = message->buffers[j].buffer;
366     local_bufs[j + offset].size = message->buffers[j].size;
367   }
368
369
370   if (reliable)
371     ret = nice_socket_send_messages_reliable (priv->base_socket, to,
372         &local_message, 1);
373   else
374     ret = nice_socket_send_messages (priv->base_socket, to, &local_message, 1);
375
376   if (ret == 1)
377     ret = output_message_get_size (&local_message);
378
379   return ret;
380 }
381
382 static gint
383 socket_send_messages (NiceSocket *sock, const NiceAddress *to,
384     const NiceOutputMessage *messages, guint n_messages)
385 {
386   guint i;
387
388   /* Make sure socket has not been freed: */
389   g_assert (sock->priv != NULL);
390
391   for (i = 0; i < n_messages; i++) {
392     const NiceOutputMessage *message = &messages[i];
393     gssize len;
394
395     len = socket_send_message (sock, to, message, FALSE);
396
397     if (len < 0) {
398       /* Error. */
399       if (i > 0)
400         break;
401       return len;
402     } else if (len == 0) {
403       /* EWOULDBLOCK. */
404       break;
405     }
406   }
407
408   return i;
409 }
410
411 static gint
412 socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
413     const NiceOutputMessage *messages, guint n_messages)
414 {
415   guint i;
416
417   for (i = 0; i < n_messages; i++) {
418     const NiceOutputMessage *message = &messages[i];
419     gssize len;
420
421     len = socket_send_message (sock, to, message, TRUE);
422
423     if (len < 0) {
424       /* Error. */
425       return len;
426     }
427   }
428
429   return i;
430 }
431
432
433 static gboolean
434 socket_is_reliable (NiceSocket *sock)
435 {
436   TurnTcpPriv *priv = sock->priv;
437
438   return nice_socket_is_reliable (priv->base_socket);
439 }
440
441 static gboolean
442 socket_can_send (NiceSocket *sock, NiceAddress *addr)
443 {
444   TurnTcpPriv *priv = sock->priv;
445
446   return nice_socket_can_send (priv->base_socket, addr);
447 }
448
449 static void
450 socket_set_writable_callback (NiceSocket *sock,
451     NiceSocketWritableCb callback, gpointer user_data)
452 {
453   TurnTcpPriv *priv = sock->priv;
454
455   nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
456 }
457
458 static gboolean
459 socket_is_based_on (NiceSocket *sock, NiceSocket *other)
460 {
461   TurnTcpPriv *priv = sock->priv;
462
463   return (sock == other) ||
464       (priv && nice_socket_is_based_on (priv->base_socket, other));
465 }