2
* This file is part of the Nice GLib ICE library.
4
* (C) 2006-2008 Collabora Ltd.
5
* Contact: Dafydd Harries
6
* Contact: Olivier Crete
7
* (C) 2006, 2007 Nokia Corporation. All rights reserved.
8
* Contact: Kai Vehmanen
10
* The contents of this file are subject to the Mozilla Public License Version
11
* 1.1 (the "License"); you may not use this file except in compliance with
12
* the License. You may obtain a copy of the License at
13
* http://www.mozilla.org/MPL/
15
* Software distributed under the License is distributed on an "AS IS" basis,
16
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17
* for the specific language governing rights and limitations under the
20
* The Original Code is the Nice GLib ICE library.
22
* The Initial Developers of the Original Code are Collabora Ltd and Nokia
23
* Corporation. All Rights Reserved.
26
* Dafydd Harries, Collabora Ltd.
27
* Olivier Crete, Collabora Ltd.
28
* Rémi Denis-Courmont, Nokia
31
* Alternatively, the contents of this file may be used under the terms of the
32
* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
33
* case the provisions of LGPL are applicable instead of those above. If you
34
* wish to allow use of your version of this file only under the terms of the
35
* LGPL and not to allow others to use your version of this file under the
36
* MPL, indicate your decision by deleting the provisions above and replace
37
* them with the notice and other provisions required by the LGPL. If you do
38
* not delete the provisions above, a recipient may use your version of this
39
* file under either the MPL or the LGPL.
43
* Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
44
* http://en.wikipedia.org/wiki/Berkeley_sockets.)
61
NiceTurnSocketCompatibility compatibility;
62
gchar recv_buf[65536];
65
NiceSocket *base_socket;
69
static void socket_close (NiceSocket *sock);
70
static gint socket_recv (NiceSocket *sock, NiceAddress *from,
71
guint len, gchar *buf);
72
static gboolean socket_send (NiceSocket *sock, const NiceAddress *to,
73
guint len, const gchar *buf);
74
static gboolean socket_is_reliable (NiceSocket *sock);
77
nice_tcp_turn_socket_new (NiceAgent *agent, NiceSocket *base_socket,
78
NiceTurnSocketCompatibility compatibility)
81
NiceSocket *sock = g_slice_new0 (NiceSocket);
82
sock->priv = priv = g_slice_new0 (TurnTcpPriv);
84
priv->compatibility = compatibility;
85
priv->base_socket = base_socket;
87
sock->fileno = priv->base_socket->fileno;
88
sock->addr = priv->base_socket->addr;
89
sock->send = socket_send;
90
sock->recv = socket_recv;
91
sock->is_reliable = socket_is_reliable;
92
sock->close = socket_close;
99
socket_close (NiceSocket *sock)
101
TurnTcpPriv *priv = sock->priv;
103
if (priv->base_socket)
104
nice_socket_free (priv->base_socket);
106
g_slice_free(TurnTcpPriv, sock->priv);
111
socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
113
TurnTcpPriv *priv = sock->priv;
117
if (priv->expecting_len == 0) {
120
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9)
122
else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE)
127
ret = nice_socket_recv (priv->base_socket, from,
128
headerlen - priv->recv_buf_len, priv->recv_buf + priv->recv_buf_len);
132
priv->recv_buf_len += ret;
134
if (priv->recv_buf_len < headerlen)
137
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9) {
138
guint16 magic = ntohs (*(guint16*)priv->recv_buf);
139
guint16 packetlen = ntohs (*(guint16*)(priv->recv_buf + 2));
141
if (magic < 0x4000) {
143
priv->expecting_len = 20 + packetlen;
146
priv->expecting_len = 4 + packetlen;
149
else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
150
guint len = ntohs (*(guint16*)priv->recv_buf);
151
priv->expecting_len = len;
152
priv->recv_buf_len = 0;
156
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9)
157
padlen = (priv->expecting_len % 4) ? 4 - (priv->expecting_len % 4) : 0;
161
ret = nice_socket_recv (priv->base_socket, from,
162
priv->expecting_len + padlen - priv->recv_buf_len,
163
priv->recv_buf + priv->recv_buf_len);
168
priv->recv_buf_len += ret;
170
if (priv->recv_buf_len == priv->expecting_len + padlen) {
171
guint copy_len = MIN (len, priv->recv_buf_len);
172
memcpy (buf, priv->recv_buf, copy_len);
173
priv->expecting_len = 0;
174
priv->recv_buf_len = 0;
183
socket_send (NiceSocket *sock, const NiceAddress *to,
184
guint len, const gchar *buf)
187
TurnTcpPriv *priv = sock->priv;
188
gchar padbuf[3] = {0, 0, 0};
189
int padlen = (len%4) ? 4 - (len%4) : 0;
191
if (priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9)
194
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
195
guint16 tmpbuf = htons (len);
196
ret = nice_socket_send (priv->base_socket, to,
197
sizeof(guint16), (gchar *)&tmpbuf);
203
ret = nice_socket_send (priv->base_socket, to, len, buf);
208
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9)
209
ret = nice_socket_send (priv->base_socket, to, padlen, padbuf);
216
socket_is_reliable (NiceSocket *sock)