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
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.
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.
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
)
54 res
= a
->sa_family
- b
->sa_family
;
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);
66 res
= memcmp (&a4
->sin_port
, &b4
->sin_port
, 2);
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);
76 res
= a6
->sin6_scope_id
- b6
->sin6_scope_id
;
78 res
= memcmp (&a6
->sin6_port
, &b6
->sin6_port
, 2);
88 bool stun_optional (uint16_t t
)
90 return (t
>> 15) == 1;
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
)
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];
124 /* * @param msg valid STUN message */
125 /* * @return true if there is at least one unknown mandatory attribute. */
127 /* bool stun_has_unknown (const void *msg) */
129 /* uint16_t dummy; */
130 /* return stun_find_unknown (msg, &dummy, 1); */
133 static int debug_enabled
= 1;
135 void stun_debug_enable (void) {
138 void stun_debug_disable (void) {
142 void stun_debug (const char *fmt
, ...)
147 vfprintf (stderr
, fmt
, ap
);
152 void stun_debug_bytes (const void *data
, size_t len
)
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
)
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
;
180 struct sockaddr_in6
*ip6
= (struct sockaddr_in6
*)addr
;
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
)
198 *ptr
++ = value
& 0xff;
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
)
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";
251 for (i
= 0; i
< (sizeof (tab
) / sizeof (tab
[0])); i
++)
253 if (tab
[i
].code
== code
)
260 /* Maximum allowed error message length */
261 // assert (strlen (str) < 128);