blob: 6428d97e2a94d47cdaa7a3ed186fc7dc14ef203a [file] [log] [blame]
Alexandre Lision8af73cb2013-12-10 14:11:20 -05001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pjnath/stun_msg.h>
21#include <pjnath/errno.h>
22#include <pj/assert.h>
23#include <pj/os.h>
24#include <pj/string.h>
25
26#if PJ_LOG_MAX_LEVEL > 0
27
28
29#define APPLY() if (len < 1 || len >= (end-p)) \
30 goto on_return; \
31 p += len
32
33static int print_binary(char *buffer, unsigned length,
34 const pj_uint8_t *data, unsigned data_len)
35{
36 unsigned i;
37
38 if (length < data_len * 2 + 8)
39 return -1;
40
41 pj_ansi_sprintf(buffer, ", data=");
42 buffer += 7;
43
44 for (i=0; i<data_len; ++i) {
45 pj_ansi_sprintf(buffer, "%02x", (*data) & 0xFF);
46 buffer += 2;
47 data++;
48 }
49
50 pj_ansi_sprintf(buffer, "\n");
51 buffer++;
52
53 return data_len * 2 + 8;
54}
55
56static int print_attr(char *buffer, unsigned length,
57 const pj_stun_attr_hdr *ahdr)
58{
59 char *p = buffer, *end = buffer + length;
60 const char *attr_name = pj_stun_get_attr_name(ahdr->type);
61 char attr_buf[32];
62 int len;
63
64 if (*attr_name == '?') {
65 pj_ansi_snprintf(attr_buf, sizeof(attr_buf), "Attr 0x%x",
66 ahdr->type);
67 attr_name = attr_buf;
68 }
69
70 len = pj_ansi_snprintf(p, end-p,
71 " %s: length=%d",
72 attr_name,
73 (int)ahdr->length);
74 APPLY();
75
76
77 switch (ahdr->type) {
78 case PJ_STUN_ATTR_MAPPED_ADDR:
79 case PJ_STUN_ATTR_RESPONSE_ADDR:
80 case PJ_STUN_ATTR_SOURCE_ADDR:
81 case PJ_STUN_ATTR_CHANGED_ADDR:
82 case PJ_STUN_ATTR_REFLECTED_FROM:
83 case PJ_STUN_ATTR_XOR_PEER_ADDR:
84 case PJ_STUN_ATTR_XOR_RELAYED_ADDR:
85 case PJ_STUN_ATTR_XOR_MAPPED_ADDR:
86 case PJ_STUN_ATTR_XOR_REFLECTED_FROM:
87 case PJ_STUN_ATTR_ALTERNATE_SERVER:
88 {
89 const pj_stun_sockaddr_attr *attr;
90
91 attr = (const pj_stun_sockaddr_attr*)ahdr;
92
93 if (attr->sockaddr.addr.sa_family == pj_AF_INET()) {
94 len = pj_ansi_snprintf(p, end-p,
95 ", IPv4 addr=%s:%d\n",
96 pj_inet_ntoa(attr->sockaddr.ipv4.sin_addr),
97 pj_ntohs(attr->sockaddr.ipv4.sin_port));
98
99 } else if (attr->sockaddr.addr.sa_family == pj_AF_INET6()) {
100 len = pj_ansi_snprintf(p, end-p,
101 ", IPv6 addr present\n");
102 } else {
103 len = pj_ansi_snprintf(p, end-p,
104 ", INVALID ADDRESS FAMILY!\n");
105 }
106 APPLY();
107 }
108 break;
109
110 case PJ_STUN_ATTR_CHANNEL_NUMBER:
111 {
112 const pj_stun_uint_attr *attr;
113
114 attr = (const pj_stun_uint_attr*)ahdr;
115 len = pj_ansi_snprintf(p, end-p,
116 ", chnum=%u (0x%x)\n",
117 (int)PJ_STUN_GET_CH_NB(attr->value),
118 (int)PJ_STUN_GET_CH_NB(attr->value));
119 APPLY();
120 }
121 break;
122
123 case PJ_STUN_ATTR_CHANGE_REQUEST:
124 case PJ_STUN_ATTR_LIFETIME:
125 case PJ_STUN_ATTR_BANDWIDTH:
126 case PJ_STUN_ATTR_REQ_ADDR_TYPE:
127 case PJ_STUN_ATTR_EVEN_PORT:
128 case PJ_STUN_ATTR_REQ_TRANSPORT:
129 case PJ_STUN_ATTR_TIMER_VAL:
130 case PJ_STUN_ATTR_PRIORITY:
131 case PJ_STUN_ATTR_FINGERPRINT:
132 case PJ_STUN_ATTR_REFRESH_INTERVAL:
133 case PJ_STUN_ATTR_ICMP:
134 {
135 const pj_stun_uint_attr *attr;
136
137 attr = (const pj_stun_uint_attr*)ahdr;
138 len = pj_ansi_snprintf(p, end-p,
139 ", value=%u (0x%x)\n",
140 (pj_uint32_t)attr->value,
141 (pj_uint32_t)attr->value);
142 APPLY();
143 }
144 break;
145
146 case PJ_STUN_ATTR_USERNAME:
147 case PJ_STUN_ATTR_PASSWORD:
148 case PJ_STUN_ATTR_REALM:
149 case PJ_STUN_ATTR_NONCE:
150 case PJ_STUN_ATTR_SOFTWARE:
151 {
152 const pj_stun_string_attr *attr;
153
154 attr = (pj_stun_string_attr*)ahdr;
155 len = pj_ansi_snprintf(p, end-p,
156 ", value=\"%.*s\"\n",
157 (int)attr->value.slen,
158 attr->value.ptr);
159 APPLY();
160 }
161 break;
162
163 case PJ_STUN_ATTR_ERROR_CODE:
164 {
165 const pj_stun_errcode_attr *attr;
166
167 attr = (const pj_stun_errcode_attr*) ahdr;
168 len = pj_ansi_snprintf(p, end-p,
169 ", err_code=%d, reason=\"%.*s\"\n",
170 attr->err_code,
171 (int)attr->reason.slen,
172 attr->reason.ptr);
173 APPLY();
174 }
175 break;
176
177 case PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES:
178 {
179 const pj_stun_unknown_attr *attr;
180 unsigned j;
181
182 attr = (const pj_stun_unknown_attr*) ahdr;
183
184 len = pj_ansi_snprintf(p, end-p,
185 ", unknown list:");
186 APPLY();
187
188 for (j=0; j<attr->attr_count; ++j) {
189 len = pj_ansi_snprintf(p, end-p,
190 " %d",
191 (int)attr->attrs[j]);
192 APPLY();
193 }
194 }
195 break;
196
197 case PJ_STUN_ATTR_MESSAGE_INTEGRITY:
198 {
199 const pj_stun_msgint_attr *attr;
200
201 attr = (const pj_stun_msgint_attr*) ahdr;
202 len = print_binary(p, (unsigned)(end-p), attr->hmac, 20);
203 APPLY();
204 }
205 break;
206
207 case PJ_STUN_ATTR_DATA:
208 {
209 const pj_stun_binary_attr *attr;
210
211 attr = (const pj_stun_binary_attr*) ahdr;
212 len = print_binary(p, (unsigned)(end-p), attr->data, attr->length);
213 APPLY();
214 }
215 break;
216 case PJ_STUN_ATTR_ICE_CONTROLLED:
217 case PJ_STUN_ATTR_ICE_CONTROLLING:
218 case PJ_STUN_ATTR_RESERVATION_TOKEN:
219 {
220 const pj_stun_uint64_attr *attr;
221 pj_uint8_t data[8];
222 int i;
223
224 attr = (const pj_stun_uint64_attr*) ahdr;
225
226 for (i=0; i<8; ++i)
227 data[i] = ((const pj_uint8_t*)&attr->value)[7-i];
228
229 len = print_binary(p, (unsigned)(end-p), data, 8);
230 APPLY();
231 }
232 break;
233 case PJ_STUN_ATTR_USE_CANDIDATE:
234 case PJ_STUN_ATTR_DONT_FRAGMENT:
235 default:
236 len = pj_ansi_snprintf(p, end-p, "\n");
237 APPLY();
238 break;
239 }
240
241 return (int)(p-buffer);
242
243on_return:
244 return len;
245}
246
247
248/*
249 * Dump STUN message to a printable string output.
250 */
251PJ_DEF(char*) pj_stun_msg_dump(const pj_stun_msg *msg,
252 char *buffer,
253 unsigned length,
254 unsigned *printed_len)
255{
256 char *p, *end;
257 int len;
258 unsigned i;
259
260 PJ_ASSERT_RETURN(msg && buffer && length, NULL);
261
262 PJ_CHECK_STACK();
263
264 p = buffer;
265 end = buffer + length;
266
267 len = pj_ansi_snprintf(p, end-p, "STUN %s %s\n",
268 pj_stun_get_method_name(msg->hdr.type),
269 pj_stun_get_class_name(msg->hdr.type));
270 APPLY();
271
272 len = pj_ansi_snprintf(p, end-p,
273 " Hdr: length=%d, magic=%08x, tsx_id=%08x%08x%08x\n"
274 " Attributes:\n",
275 msg->hdr.length,
276 msg->hdr.magic,
277 *(pj_uint32_t*)&msg->hdr.tsx_id[0],
278 *(pj_uint32_t*)&msg->hdr.tsx_id[4],
279 *(pj_uint32_t*)&msg->hdr.tsx_id[8]);
280 APPLY();
281
282 for (i=0; i<msg->attr_count; ++i) {
283 len = print_attr(p, (unsigned)(end-p), msg->attr[i]);
284 APPLY();
285 }
286
287on_return:
288 *p = '\0';
289 if (printed_len)
290 *printed_len = (unsigned)(p-buffer);
291 return buffer;
292
293#undef APPLY
294}
295
296
297#endif /* PJ_LOG_MAX_LEVEL > 0 */
298