Change all stun_XXX_t enums/structs into StunXxx to have a common naming convention
[sipe-libnice.git] / stun / utils.c
blobe139a96a3da56af4eb2c9bd2ff7178924087b6d9
1 /*
2 * This file is part of the Nice GLib ICE library.
4 * (C) 2007 Nokia Corporation. All rights reserved.
5 * Contact: Rémi Denis-Courmont
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/
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.
17 * The Original Code is the Nice GLib ICE library.
19 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
20 * Corporation. All Rights Reserved.
22 * Contributors:
23 * Rémi Denis-Courmont, Nokia
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.
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
40 #include <string.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <stdarg.h>
45 #include "utils.h"
47 /** Compares two socket addresses
48 * @return 0 if the addresses are equal, non-zero otherwise
50 int sockaddrcmp (const struct sockaddr *a, const struct sockaddr *b)
52 int res;
54 res = a->sa_family - b->sa_family;
55 if (res)
56 return res;
58 switch (a->sa_family)
60 case AF_INET:
62 const struct sockaddr_in *a4 = (const struct sockaddr_in *)a;
63 const struct sockaddr_in *b4 = (const struct sockaddr_in *)b;
64 res = memcmp (&a4->sin_addr, &b4->sin_addr, 4);
65 if (res == 0)
66 res = memcmp (&a4->sin_port, &b4->sin_port, 2);
67 break;
70 case AF_INET6:
72 const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)a;
73 const struct sockaddr_in6 *b6 = (const struct sockaddr_in6 *)b;
74 res = memcmp (&a6->sin6_addr, &b6->sin6_addr, 16);
75 if (res == 0)
76 res = a6->sin6_scope_id - b6->sin6_scope_id;
77 if (res == 0)
78 res = memcmp (&a6->sin6_port, &b6->sin6_port, 2);
79 break;
83 return res;
88 bool stun_optional (uint16_t t)
90 return (t >> 15) == 1;
94 /**
95 * @return complement to the next multiple of 4.
97 size_t stun_padding (size_t l)
99 return (4 - (l & 3)) & 3;
104 * Rounds up an integer to the next multiple of 4.
106 size_t stun_align (size_t l)
108 return (l + 3) & ~3;
113 * Reads a word from a non-aligned buffer.
114 * @return host byte order word value.
116 uint16_t stun_getw (const uint8_t *ptr)
118 return ((ptr)[0] << 8) | ptr[1];
123 /* /\** */
124 /* * @param msg valid STUN message */
125 /* * @return true if there is at least one unknown mandatory attribute. */
126 /* *\/ */
127 /* bool stun_has_unknown (const void *msg) */
128 /* { */
129 /* uint16_t dummy; */
130 /* return stun_find_unknown (msg, &dummy, 1); */
131 /* } */
133 static int debug_enabled = 1;
135 void stun_debug_enable (void) {
136 debug_enabled = 1;
138 void stun_debug_disable (void) {
139 debug_enabled = 0;
142 void stun_debug (const char *fmt, ...)
144 va_list ap;
145 if (debug_enabled) {
146 va_start (ap, fmt);
147 vfprintf (stderr, fmt, ap);
148 va_end (ap);
152 void stun_debug_bytes (const void *data, size_t len)
154 size_t i;
156 stun_debug ("0x");
157 for (i = 0; i < len; i++)
158 stun_debug ("%02x", ((const unsigned char *)data)[i]);
161 StunMessageReturn stun_xor_address (const StunMessage *msg,
162 struct sockaddr *addr, socklen_t addrlen,
163 uint32_t magic_cookie)
165 switch (addr->sa_family)
167 case AF_INET:
169 struct sockaddr_in *ip4 = (struct sockaddr_in *)addr;
170 if ((size_t) addrlen < sizeof (*ip4))
171 return STUN_MESSAGE_RETURN_INVALID;
173 ip4->sin_port ^= htons (magic_cookie >> 16);
174 ip4->sin_addr.s_addr ^= htonl (magic_cookie);
175 return STUN_MESSAGE_RETURN_SUCCESS;
178 case AF_INET6:
180 struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)addr;
181 unsigned short i;
183 if ((size_t) addrlen < sizeof (*ip6))
184 return STUN_MESSAGE_RETURN_INVALID;
186 ip6->sin6_port ^= htons (magic_cookie >> 16);
187 for (i = 0; i < 16; i++)
188 ip6->sin6_addr.s6_addr[i] ^= msg->buffer[4 + i];
189 return STUN_MESSAGE_RETURN_SUCCESS;
192 return STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS;
195 void *stun_setw (uint8_t *ptr, uint16_t value)
197 *ptr++ = value >> 8;
198 *ptr++ = value & 0xff;
199 return ptr;
203 void stun_set_type (uint8_t *h, StunClass c, StunMethod m)
205 /* assert (c < 4); */
206 /* assert (m < (1 << 12)); */
208 h[0] = (c >> 1) | ((m >> 6) & 0x3e);
209 h[1] = ((c << 4) & 0x10) | ((m << 1) & 0xe0) | (m & 0x0f);
211 /* assert (stun_getw (h) < (1 << 14)); */
212 /* assert (stun_get_class (h) == c); */
213 /* assert (stun_get_method (h) == m); */
218 * @param code host-byte order error code
219 * @return a static pointer to a nul-terminated error message string.
221 const char *stun_strerror (StunError code)
223 static const struct
225 StunError code;
226 char phrase[32];
227 } tab[] =
229 { STUN_ERROR_TRY_ALTERNATE, "Try alternate server" },
230 { STUN_ERROR_BAD_REQUEST, "Bad request" },
231 { STUN_ERROR_UNAUTHORIZED, "Unauthorized" },
232 { STUN_ERROR_UNKNOWN_ATTRIBUTE, "Unknown Attribute" },
233 { STUN_ERROR_ALLOCATION_MISMATCH, "Allocation Mismatch" },
234 { STUN_ERROR_STALE_NONCE, "Stale Nonce" },
235 { STUN_ERROR_ACT_DST_ALREADY, "Active Destination Already Set" },
236 { STUN_ERROR_UNSUPPORTED_FAMILY, "Address Family not Supported" },
237 { STUN_ERROR_UNSUPPORTED_TRANSPORT, "Unsupported Transport Protocol" },
238 { STUN_ERROR_INVALID_IP, "Invalid IP Address" },
239 { STUN_ERROR_INVALID_PORT, "Invalid Port" },
240 { STUN_ERROR_OP_TCP_ONLY, "Operation for TCP Only" },
241 { STUN_ERROR_CONN_ALREADY, "Connection Already Exists" },
242 { STUN_ERROR_ALLOCATION_QUOTA_REACHED, "Allocation Quota Reached" },
243 { STUN_ERROR_ROLE_CONFLICT, "Role conflict" },
244 { STUN_ERROR_SERVER_ERROR, "Server Error" },
245 { STUN_ERROR_SERVER_CAPACITY, "Insufficient Capacity" },
246 { STUN_ERROR_INSUFFICIENT_CAPACITY, "Insufficient Capacity" },
248 const char *str = "Unknown error";
249 size_t i;
251 for (i = 0; i < (sizeof (tab) / sizeof (tab[0])); i++)
253 if (tab[i].code == code)
255 str = tab[i].phrase;
256 break;
260 /* Maximum allowed error message length */
261 // assert (strlen (str) < 128);
262 return str;