cb52768374c4226fc022cdf21fae0d21f4b243bc
[platform/upstream/libnice.git] / stun / tests / test-turn.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2007 Nokia Corporation. All rights reserved.
5  *  Contact: Rémi Denis-Courmont
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is the Nice GLib ICE library.
18  *
19  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
20  * Corporation. All Rights Reserved.
21  *
22  * Contributors:
23  *   Rémi Denis-Courmont, Nokia
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
27  * case the provisions of LGPL are applicable instead of those above. If you
28  * wish to allow use of your version of this file only under the terms of the
29  * LGPL and not to allow others to use your version of this file under the
30  * MPL, indicate your decision by deleting the provisions above and replace
31  * them with the notice and other provisions required by the LGPL. If you do
32  * not delete the provisions above, a recipient may use your version of this
33  * file under either the MPL or the LGPL.
34  */
35
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
39
40 #include <sys/types.h>
41 #include "stun/stunagent.h"
42 #include "stun/usages/turn.h"
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <unistd.h>
47 #include <string.h>
48
49 #ifdef _WIN32
50 #include <winsock2.h>
51 #include <ws2tcpip.h>
52
53 #define MSG_DONTWAIT 0
54 #define MSG_NOSIGNAL 0
55
56 #define alarm(...)
57 #define close closesocket
58 #else
59 #include <sys/types.h>
60 #include <sys/socket.h>
61 #include <arpa/inet.h>
62 #include <netdb.h>
63 #include <errno.h>
64 #endif
65
66 #undef NDEBUG /* ensure assertions are built-in */
67 #include <assert.h>
68
69
70 static int listen_dgram (void)
71 {
72   struct addrinfo hints, *res;
73   int val = -1;
74
75   memset (&hints, 0, sizeof (hints));
76   hints.ai_socktype = SOCK_DGRAM;
77
78   if (getaddrinfo (NULL, "0", &hints, &res))
79     return -1;
80
81   for (const struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
82   {
83     int fd = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
84     if (fd == -1)
85       continue;
86
87     if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
88     {
89       close (fd);
90       continue;
91     }
92
93     val = fd;
94     break;
95   }
96
97   freeaddrinfo (res);
98   return val;
99 }
100
101
102 static void
103 printaddr (const char *str, const struct sockaddr *addr, socklen_t addrlen)
104 {
105   char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
106
107   int val = getnameinfo (addr, addrlen, hostbuf, sizeof (hostbuf),
108                          servbuf, sizeof (servbuf),
109                          NI_NUMERICHOST | NI_NUMERICSERV);
110   if (val)
111     printf ("%s: %s\n", str, gai_strerror (val));
112   else
113     printf ("%s: %s port %s\n", str, hostbuf, servbuf);
114 }
115
116
117 /** Various responses test */
118 static void test_turn (char *username, char *password, char *hostname, int port)
119 {
120   struct sockaddr_storage addr;
121   socklen_t addrlen = sizeof (addr);
122   struct sockaddr_storage alternate_addr;
123   socklen_t alternate_addrlen = sizeof (alternate_addr);
124   struct sockaddr_storage relay_addr;
125   socklen_t relay_addrlen = sizeof (relay_addr);
126   ssize_t val;
127   size_t len;
128   int fd;
129   uint8_t buf[STUN_MAX_MESSAGE_SIZE];
130   uint8_t req[STUN_MAX_MESSAGE_SIZE];
131   uint8_t refresh[STUN_MAX_MESSAGE_SIZE];
132   size_t req_len;
133   StunAgent agent;
134   StunMessage msg;
135   StunMessage req_msg;
136   StunMessage refresh_msg;
137   uint32_t bandwidth, lifetime;
138   struct addrinfo hints, *res;
139   int ret = -1;
140
141   memset (&hints, 0, sizeof (hints));
142   hints.ai_family = AF_UNSPEC;
143   hints.ai_socktype = SOCK_DGRAM;
144   hints.ai_flags = 0;
145
146   ret = getaddrinfo (hostname, port, &hints, &res);
147   assert (ret == 0);
148
149   stun_agent_init (&agent, STUN_ALL_KNOWN_ATTRIBUTES,
150       STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS);
151
152   /* Allocate a client socket and connect to server */
153   fd = socket (AF_INET, SOCK_DGRAM, 0);
154   assert (fd != -1);
155
156   val = connect (fd,res->ai_addr, res->ai_addrlen);
157 #ifdef G_OS_WIN32
158   assert (val == 0 || (WSAGetLastError () == WSAEINPROGRESS));
159 #else
160   assert (val == 0 || (errno == EINPROGRESS));
161 #endif
162
163   freeaddrinfo (res);
164
165
166   /* Send old-style response */
167   req_len = stun_usage_turn_create (&agent, &req_msg, req, sizeof(req),
168       NULL,
169       STUN_USAGE_TURN_REQUEST_PORT_NORMAL,
170       -1, -1,
171       username, strlen (username), password, strlen(password),
172       STUN_USAGE_TURN_COMPATIBILITY_DRAFT9);
173   assert (req_len > 0);
174
175   val = send (fd, req, req_len, MSG_NOSIGNAL);
176   assert (val >= 0);
177
178   val = recv (fd, buf, 1000, 0);
179   assert (val >= 0);
180
181   assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
182       == STUN_VALIDATION_SUCCESS);
183
184   val = stun_usage_turn_process (&msg,
185       (struct sockaddr *)&relay_addr, &relay_addrlen,
186       (struct sockaddr *)&addr, &addrlen,
187       (struct sockaddr *)&alternate_addr, &alternate_addrlen,
188       &bandwidth, &lifetime,
189       STUN_USAGE_TURN_COMPATIBILITY_DRAFT9);
190   assert (val == STUN_USAGE_TURN_RETURN_ERROR);
191
192   req_len = stun_usage_turn_create (&agent, &req_msg, req, sizeof(req),
193       &msg,
194       STUN_USAGE_TURN_REQUEST_PORT_NORMAL,
195       -1, -1,
196       username, strlen (username), password, strlen(password),
197       STUN_USAGE_TURN_COMPATIBILITY_DRAFT9);
198   assert (req_len > 0);
199
200   val = send (fd, req, req_len, MSG_NOSIGNAL);
201   assert (val >= 0);
202
203   val = recv (fd, buf, 1000, 0);
204   assert (val >= 0);
205
206   assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
207       == STUN_VALIDATION_SUCCESS);
208
209   val = stun_usage_turn_process (&msg,
210       (struct sockaddr *)&relay_addr, &relay_addrlen,
211       (struct sockaddr *)&addr, &addrlen,
212       (struct sockaddr *)&alternate_addr, &alternate_addrlen,
213       &bandwidth, &lifetime,
214       STUN_USAGE_TURN_COMPATIBILITY_DRAFT9);
215   assert (val == STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS);
216
217   printaddr ("Relay address found : ", (struct sockaddr *)&relay_addr, relay_addrlen);
218   printaddr ("Mapped address found : ",(struct sockaddr *) &addr, addrlen);
219
220
221   req_len = stun_usage_turn_create_refresh (&agent, &refresh_msg, refresh,
222       sizeof(refresh),  &req_msg, 0, username, strlen (username),
223       password, strlen(password),STUN_USAGE_TURN_COMPATIBILITY_DRAFT9);
224   assert (req_len > 0);
225
226   val = send (fd, refresh, req_len, MSG_NOSIGNAL);
227   assert (val >= 0);
228
229   val = recv (fd, buf, 1000, 0);
230   assert (val >= 0);
231
232   assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
233       == STUN_VALIDATION_SUCCESS);
234
235   val = close (fd);
236   assert (val == 0);
237 }
238
239 static void turnserver (void)
240 {
241   test_turn ("toto", "password", "127.0.0.1", "3478");
242 }
243
244 static void numb (void)
245 {
246   test_turn ("youness.alaoui@collabora.co.uk", "badger", "numb.viagenie.ca", "3478");
247 }
248
249 static void test (void (*func) (void), const char *name)
250 {
251   alarm (10);
252
253   printf ("%s test... ", name);
254   func ();
255   puts ("OK");
256 }
257
258
259 int main (void)
260 {
261   test (turnserver, "Testing TURN");
262   test (numb, "Testing numb");
263   return 0;
264 }