Imported Upstream version 0.1.17
[platform/upstream/libnice.git] / tests / test-udp-turn-fragmentation.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2018 Jakub Adam <jakub.adam@ktknet.cz>
5  *
6  * The contents of this file are subject to the Mozilla Public License Version
7  * 1.1 (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  * http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is the Nice GLib ICE library.
17  *
18  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
19  * Corporation. All Rights Reserved.
20  *
21  * Alternatively, the contents of this file may be used under the terms of the
22  * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
23  * case the provisions of LGPL are applicable instead of those above. If you
24  * wish to allow use of your version of this file only under the terms of the
25  * LGPL and not to allow others to use your version of this file under the
26  * MPL, indicate your decision by deleting the provisions above and replace
27  * them with the notice and other provisions required by the LGPL. If you do
28  * not delete the provisions above, a recipient may use your version of this
29  * file under either the MPL or the LGPL.
30  */
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <gio/gnetworking.h>
36
37 #include "agent-priv.h"
38 #include "socket.h"
39
40 static GRand *randg;
41
42 static GSList *
43 generate_test_messages(void)
44 {
45   guint i;
46   GSList *result = NULL;
47
48   for (i = 0; i != 100; ++i) {
49     GInputVector *msg_data = g_new (GInputVector, 1);
50     gsize msg_size = g_rand_int_range (randg, 0, G_MAXUINT16);
51     gsize j;
52
53     msg_data->size = msg_size + sizeof (guint16);
54     msg_data->buffer = g_malloc (msg_data->size);
55     *(guint16 *)(msg_data->buffer) = htons (msg_size);
56
57     for (j = 2; j != msg_data->size; ++j) {
58       ((guint8 *)msg_data->buffer)[j] = g_rand_int(randg);
59     }
60
61     result = g_slist_append(result, msg_data);
62   }
63
64   return result;
65 }
66
67 typedef struct {
68   GSList *msg_data;
69   GSList *current_msg;
70   gsize offset;
71   guint8 send_buffer[G_MAXUINT16 + sizeof (guint16)];
72 } TestSocketPriv;
73
74 static gint
75 test_socket_recv_messages (NiceSocket *sock, NiceInputMessage *recv_messages,
76     guint n_recv_messages) {
77   TestSocketPriv *priv = sock->priv;
78   guint i;
79
80   for (i = 0; priv->current_msg && i != n_recv_messages; ++i) {
81     gsize msg_size = g_rand_int_range (randg, 0, G_MAXUINT16) + sizeof (guint16);
82     gsize j;
83
84     j = sizeof (guint16);
85     while (priv->current_msg && j < msg_size) {
86       GInputVector *msg = priv->current_msg->data;
87       gsize cpylen = MIN (msg->size - priv->offset, msg_size - j);
88       memcpy (priv->send_buffer + j, (guint8 *)msg->buffer + priv->offset,
89           cpylen);
90       priv->offset += cpylen;
91       j += cpylen;
92
93       if (priv->offset == msg->size) {
94         priv->current_msg = priv->current_msg->next;
95         priv->offset = 0;
96       }
97     }
98
99     msg_size = j;
100     *(guint16 *)(priv->send_buffer) = htons (msg_size - sizeof (guint16));
101
102     memcpy_buffer_to_input_message (&recv_messages[i], priv->send_buffer, msg_size);
103     nice_address_set_from_string (recv_messages[i].from, "127.0.0.1");
104   }
105
106   return i;
107 }
108
109 static gboolean
110 test_socket_is_reliable (NiceSocket *sock) {
111   return TRUE;
112 }
113
114 static void
115 test_socket_close (NiceSocket *sock) {
116   g_free (sock->priv);
117 }
118
119 static NiceSocket *
120 test_socket_new (GSList *msg_data)
121 {
122   NiceSocket *sock = g_slice_new0 (NiceSocket);
123   TestSocketPriv *priv = g_new0 (TestSocketPriv, 1);
124   priv->msg_data = msg_data;
125   priv->current_msg = msg_data;
126   priv->offset = 0;
127
128   sock->type = NICE_SOCKET_TYPE_UDP_TURN_OVER_TCP;
129   sock->recv_messages = test_socket_recv_messages;
130   sock->is_reliable = test_socket_is_reliable;
131   sock->close = test_socket_close;
132   sock->priv = (void *) priv;
133
134   return sock;
135 }
136
137 #define N_RECV_MESSAGES 7
138
139 static void
140 tcp_turn_fragmentation (void)
141 {
142   /* Generate some RFC4571-framed test messages. A dummy base socket will split
143    * them randomly into TCP-TURN messages. Test that tcp-turn socket can
144    * correctly extract and reassemble the original test data out of the TURN
145    * messages. */
146   GSList *test_messages = generate_test_messages ();
147   NiceAddress addr;
148   NiceSocket *turnsock;
149   NiceSocket *testsock;
150
151   NiceInputMessage recv_messages[N_RECV_MESSAGES];
152   GInputVector recv_vectors[N_RECV_MESSAGES];
153   NiceAddress recv_addr[N_RECV_MESSAGES];
154   guint8 recv_buffers[N_RECV_MESSAGES][G_MAXUINT16 + sizeof (guint16)];
155
156   gint n_messages;
157   guint i;
158   GSList *li;
159
160   for (i = 0; i != N_RECV_MESSAGES; ++i) {
161     recv_messages[i].buffers = &recv_vectors[i];
162     recv_messages[i].from = &recv_addr[i];
163     recv_messages[i].n_buffers = 1;
164     recv_messages[i].length = 0;
165     recv_vectors[i].buffer = &recv_buffers[i];
166     recv_vectors[i].size = sizeof (recv_buffers[i]);
167   }
168
169   nice_address_set_from_string (&addr, "127.0.0.1");
170
171   testsock = test_socket_new (test_messages);
172
173   turnsock = nice_udp_turn_socket_new (NULL, &addr,
174       testsock, &addr, "", "",
175       NICE_TURN_SOCKET_COMPATIBILITY_OC2007);
176
177   li = test_messages;
178   while (li) {
179     n_messages = nice_socket_recv_messages (turnsock, recv_messages,
180         N_RECV_MESSAGES);
181
182     for (i = 0; i != (guint)n_messages; ++i) {
183       NiceInputMessage *message = &recv_messages[i];
184       GInputVector *vec = li->data;
185       if (message->length == 0) {
186         continue;
187       }
188       g_assert_cmpint (message->length, ==, vec->size);
189       g_assert_cmpmem (message->buffers->buffer, message->length,
190           vec->buffer,  message->length);
191
192       li = li->next;
193     }
194   }
195
196   for (li = test_messages; li; li = li->next) {
197     GInputVector *v = li->data;
198     g_free (v->buffer);
199     g_free (v);
200   }
201   g_slist_free (test_messages);
202
203   nice_socket_free (turnsock);
204   nice_socket_free (testsock);
205 }
206
207 int
208 main (int argc, char *argv[])
209 {
210   GMainLoop *mainloop;
211
212   g_networking_init ();
213
214   randg = g_rand_new();
215   g_test_init (&argc, &argv, NULL);
216
217   mainloop = g_main_loop_new (NULL, TRUE);
218
219   g_test_add_func ("/udp-turn/tcp-fragmentation", tcp_turn_fragmentation);
220
221   g_test_run ();
222
223   g_rand_free(randg);
224
225   g_main_loop_unref (mainloop);
226
227   return 0;
228 }