yong-stropheruby 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.autotest +9 -0
- data/History.txt +4 -0
- data/Manifest.txt +39 -0
- data/PostInstall.txt +4 -0
- data/README.rdoc +143 -0
- data/Rakefile +21 -0
- data/ext/auth.c +990 -0
- data/ext/common.h +287 -0
- data/ext/conn.c +609 -0
- data/ext/ctx.c +416 -0
- data/ext/event.c +345 -0
- data/ext/extconf.rb +6 -0
- data/ext/handler.c +592 -0
- data/ext/hash.c +278 -0
- data/ext/hash.h +64 -0
- data/ext/jid.c +177 -0
- data/ext/md5.c +289 -0
- data/ext/md5.h +41 -0
- data/ext/ostypes.h +27 -0
- data/ext/parser.c +206 -0
- data/ext/sasl.c +614 -0
- data/ext/sasl.h +44 -0
- data/ext/sha1.c +389 -0
- data/ext/sha1.h +31 -0
- data/ext/snprintf.c +839 -0
- data/ext/sock.c +911 -0
- data/ext/sock.h +51 -0
- data/ext/stanza.c +908 -0
- data/ext/strophe.h +372 -0
- data/ext/strophe_ruby.c +687 -0
- data/ext/thread.c +119 -0
- data/ext/thread.h +43 -0
- data/ext/tls.h +46 -0
- data/ext/tls_dummy.c +89 -0
- data/ext/util.c +107 -0
- data/ext/util.h +32 -0
- data/lib/strophe_ruby.rb +6 -0
- data/test/test_helper.rb +3 -0
- data/test/test_strophe_ruby.rb +11 -0
- data/test/test_strophe_ruby_extn.rb +9 -0
- metadata +108 -0
data/ext/sock.c
ADDED
@@ -0,0 +1,911 @@
|
|
1
|
+
/* sock.c
|
2
|
+
** strophe XMPP client library -- socket abstraction implementation
|
3
|
+
**
|
4
|
+
** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
|
5
|
+
**
|
6
|
+
** This software is provided AS-IS with no warranty, either express
|
7
|
+
** or implied.
|
8
|
+
**
|
9
|
+
** This software is distributed under license and may not be copied,
|
10
|
+
** modified or distributed except as expressly authorized under the
|
11
|
+
** terms of the license contained in the file LICENSE.txt in this
|
12
|
+
** distribution.
|
13
|
+
*/
|
14
|
+
|
15
|
+
/** @file
|
16
|
+
* Socket abstraction.
|
17
|
+
*/
|
18
|
+
|
19
|
+
#include <stdio.h>
|
20
|
+
#include <stdlib.h>
|
21
|
+
#include <string.h>
|
22
|
+
#include <sys/types.h>
|
23
|
+
|
24
|
+
#ifdef _WIN32
|
25
|
+
#include <winsock2.h>
|
26
|
+
#include <ws2tcpip.h>
|
27
|
+
#include <windns.h>
|
28
|
+
#include <Iphlpapi.h>
|
29
|
+
#define snprintf _snprintf
|
30
|
+
#else
|
31
|
+
#include <errno.h>
|
32
|
+
#include <unistd.h>
|
33
|
+
#include <sys/socket.h>
|
34
|
+
#include <netinet/in.h>
|
35
|
+
#include <netdb.h>
|
36
|
+
#include <fcntl.h>
|
37
|
+
#include <arpa/nameser.h>
|
38
|
+
#include <arpa/nameser_compat.h>
|
39
|
+
#include <resolv.h>
|
40
|
+
#endif
|
41
|
+
|
42
|
+
#include "sock.h"
|
43
|
+
|
44
|
+
void sock_initialize(void)
|
45
|
+
{
|
46
|
+
#ifdef _WIN32
|
47
|
+
WSADATA wsad;
|
48
|
+
WSAStartup(0x0101, &wsad);
|
49
|
+
#endif
|
50
|
+
}
|
51
|
+
|
52
|
+
void sock_shutdown(void)
|
53
|
+
{
|
54
|
+
#ifdef _WIN32
|
55
|
+
WSACleanup();
|
56
|
+
#endif
|
57
|
+
}
|
58
|
+
|
59
|
+
int sock_error(void)
|
60
|
+
{
|
61
|
+
#ifdef _WIN32
|
62
|
+
return WSAGetLastError();
|
63
|
+
#else
|
64
|
+
return errno;
|
65
|
+
#endif
|
66
|
+
}
|
67
|
+
|
68
|
+
static int _in_progress(int error)
|
69
|
+
{
|
70
|
+
#ifdef _WIN32
|
71
|
+
return (error == WSAEWOULDBLOCK || error == WSAEINPROGRESS);
|
72
|
+
#else
|
73
|
+
return (errno == EINPROGRESS);
|
74
|
+
#endif
|
75
|
+
}
|
76
|
+
|
77
|
+
sock_t sock_connect(const char * const host, const unsigned int port)
|
78
|
+
{
|
79
|
+
sock_t sock;
|
80
|
+
char service[6];
|
81
|
+
struct addrinfo *res, *ainfo, hints;
|
82
|
+
int err;
|
83
|
+
|
84
|
+
sock = -1;
|
85
|
+
|
86
|
+
snprintf(service, 6, "%u", port);
|
87
|
+
|
88
|
+
memset(&hints, 0, sizeof(struct addrinfo));
|
89
|
+
hints.ai_family = AF_INET;
|
90
|
+
hints.ai_protocol = IPPROTO_TCP;
|
91
|
+
hints.ai_socktype = SOCK_STREAM;
|
92
|
+
|
93
|
+
if ((err = getaddrinfo(host, service, &hints, &res)) != 0)
|
94
|
+
return -1;
|
95
|
+
|
96
|
+
ainfo = res;
|
97
|
+
while (ainfo) {
|
98
|
+
if ((sock = socket(ainfo->ai_family, ainfo->ai_socktype,
|
99
|
+
ainfo->ai_protocol)) >= 0) {
|
100
|
+
sock_set_nonblocking(sock);
|
101
|
+
|
102
|
+
err = connect(sock, ainfo->ai_addr, ainfo->ai_addrlen);
|
103
|
+
|
104
|
+
if ((err == 0) || (err < 0 && _in_progress(sock_error())))
|
105
|
+
break;
|
106
|
+
}
|
107
|
+
|
108
|
+
ainfo = ainfo->ai_next;
|
109
|
+
}
|
110
|
+
|
111
|
+
if (res) freeaddrinfo(res);
|
112
|
+
|
113
|
+
return sock;
|
114
|
+
}
|
115
|
+
|
116
|
+
int sock_close(const sock_t sock)
|
117
|
+
{
|
118
|
+
#ifdef _WIN32
|
119
|
+
return closesocket(sock);
|
120
|
+
#else
|
121
|
+
return close(sock);
|
122
|
+
#endif
|
123
|
+
}
|
124
|
+
|
125
|
+
int sock_set_blocking(const sock_t sock)
|
126
|
+
{
|
127
|
+
#ifdef _WIN32
|
128
|
+
u_long block = 0;
|
129
|
+
return ioctlsocket(sock, FIONBIO, &block);
|
130
|
+
#else
|
131
|
+
return fcntl(sock, F_SETFL, 0);
|
132
|
+
#endif
|
133
|
+
}
|
134
|
+
|
135
|
+
int sock_set_nonblocking(const sock_t sock)
|
136
|
+
{
|
137
|
+
#ifdef _WIN32
|
138
|
+
u_long nonblock = 1;
|
139
|
+
return ioctlsocket(sock, FIONBIO, &nonblock);
|
140
|
+
#else
|
141
|
+
return fcntl(sock, F_SETFL, O_NONBLOCK);
|
142
|
+
#endif
|
143
|
+
}
|
144
|
+
|
145
|
+
int sock_read(const sock_t sock, void * const buff, const size_t len)
|
146
|
+
{
|
147
|
+
return recv(sock, buff, len, 0);
|
148
|
+
}
|
149
|
+
|
150
|
+
int sock_write(const sock_t sock, const void * const buff, const size_t len)
|
151
|
+
{
|
152
|
+
return send(sock, buff, len, 0);
|
153
|
+
}
|
154
|
+
|
155
|
+
int sock_is_recoverable(const int error)
|
156
|
+
{
|
157
|
+
#ifdef _WIN32
|
158
|
+
return (error == WSAEINTR || error == WSAEWOULDBLOCK ||
|
159
|
+
error == WSAEINPROGRESS);
|
160
|
+
#else
|
161
|
+
return (error == EAGAIN || error == EINTR);
|
162
|
+
#endif
|
163
|
+
}
|
164
|
+
|
165
|
+
int sock_connect_error(const sock_t sock)
|
166
|
+
{
|
167
|
+
struct sockaddr sa;
|
168
|
+
unsigned len;
|
169
|
+
char temp;
|
170
|
+
|
171
|
+
sa.sa_family = AF_INET;
|
172
|
+
|
173
|
+
len = sizeof(sa);
|
174
|
+
|
175
|
+
/* we don't actually care about the peer name, we're just checking if
|
176
|
+
* we're connected or not */
|
177
|
+
if (getpeername(sock, &sa, &len) == 0)
|
178
|
+
{
|
179
|
+
return 0;
|
180
|
+
}
|
181
|
+
|
182
|
+
/* it's possible that the error wasn't ENOTCONN, so if it wasn't,
|
183
|
+
* return that */
|
184
|
+
#ifdef _WIN32
|
185
|
+
if (sock_error() != WSAENOTCONN) return sock_error();
|
186
|
+
#else
|
187
|
+
if (sock_error() != ENOTCONN) return sock_error();
|
188
|
+
#endif
|
189
|
+
|
190
|
+
/* load the correct error into errno through error slippage */
|
191
|
+
recv(sock, &temp, 1, 0);
|
192
|
+
|
193
|
+
return sock_error();
|
194
|
+
}
|
195
|
+
|
196
|
+
struct dnsquery_header
|
197
|
+
{
|
198
|
+
unsigned short id;
|
199
|
+
unsigned char qr;
|
200
|
+
unsigned char opcode;
|
201
|
+
unsigned char aa;
|
202
|
+
unsigned char tc;
|
203
|
+
unsigned char rd;
|
204
|
+
unsigned char ra;
|
205
|
+
unsigned char z;
|
206
|
+
unsigned char rcode;
|
207
|
+
unsigned short qdcount;
|
208
|
+
unsigned short ancount;
|
209
|
+
unsigned short nscount;
|
210
|
+
unsigned short arcount;
|
211
|
+
};
|
212
|
+
|
213
|
+
struct dnsquery_question
|
214
|
+
{
|
215
|
+
char qname[1024];
|
216
|
+
unsigned short qtype;
|
217
|
+
unsigned short qclass;
|
218
|
+
};
|
219
|
+
|
220
|
+
struct dnsquery_srvrdata
|
221
|
+
{
|
222
|
+
unsigned short priority;
|
223
|
+
unsigned short weight;
|
224
|
+
unsigned short port;
|
225
|
+
char target[1024];
|
226
|
+
};
|
227
|
+
|
228
|
+
struct dnsquery_resourcerecord
|
229
|
+
{
|
230
|
+
char name[1024];
|
231
|
+
unsigned short type;
|
232
|
+
unsigned short _class;
|
233
|
+
unsigned int ttl;
|
234
|
+
unsigned short rdlength;
|
235
|
+
struct dnsquery_srvrdata rdata;
|
236
|
+
};
|
237
|
+
|
238
|
+
|
239
|
+
void netbuf_add_32bitnum(unsigned char *buf, int buflen, int *offset, unsigned int num)
|
240
|
+
{
|
241
|
+
unsigned char *start = buf + *offset;
|
242
|
+
unsigned char *p = start;
|
243
|
+
|
244
|
+
/* assuming big endian */
|
245
|
+
*p++ = (num >> 24) & 0xff;
|
246
|
+
*p++ = (num >> 16) & 0xff;
|
247
|
+
*p++ = (num >> 8) & 0xff;
|
248
|
+
*p++ = (num) & 0xff;
|
249
|
+
|
250
|
+
*offset += 4;
|
251
|
+
}
|
252
|
+
|
253
|
+
void netbuf_get_32bitnum(unsigned char *buf, int buflen, int *offset, unsigned int *num)
|
254
|
+
{
|
255
|
+
unsigned char *start = buf + *offset;
|
256
|
+
unsigned char *p = start;
|
257
|
+
*num = 0;
|
258
|
+
|
259
|
+
/* assuming big endian */
|
260
|
+
*num |= (*p++) << 24;
|
261
|
+
*num |= (*p++) << 16;
|
262
|
+
*num |= (*p++) << 8;
|
263
|
+
*num |= (*p++);
|
264
|
+
|
265
|
+
*offset += 4;
|
266
|
+
}
|
267
|
+
|
268
|
+
void netbuf_add_16bitnum(unsigned char *buf, int buflen, int *offset, unsigned short num)
|
269
|
+
{
|
270
|
+
unsigned char *start = buf + *offset;
|
271
|
+
unsigned char *p = start;
|
272
|
+
|
273
|
+
/* assuming big endian */
|
274
|
+
*p++ = (num >> 8) & 0xff;
|
275
|
+
*p++ = (num) & 0xff;
|
276
|
+
|
277
|
+
*offset += 2;
|
278
|
+
}
|
279
|
+
|
280
|
+
void netbuf_get_16bitnum(unsigned char *buf, int buflen, int *offset, unsigned short *num)
|
281
|
+
{
|
282
|
+
unsigned char *start = buf + *offset;
|
283
|
+
unsigned char *p = start;
|
284
|
+
*num = 0;
|
285
|
+
|
286
|
+
/* assuming big endian */
|
287
|
+
*num |= (*p++) << 8;
|
288
|
+
*num |= (*p++);
|
289
|
+
|
290
|
+
*offset += 2;
|
291
|
+
}
|
292
|
+
|
293
|
+
void netbuf_add_domain_name(unsigned char *buf, int buflen, int *offset,
|
294
|
+
char *name)
|
295
|
+
{
|
296
|
+
unsigned char *start = buf + *offset;
|
297
|
+
unsigned char *p = start;
|
298
|
+
unsigned char *wordstart, *wordend;
|
299
|
+
|
300
|
+
wordstart = (unsigned char *)name;
|
301
|
+
|
302
|
+
while (*wordstart)
|
303
|
+
{
|
304
|
+
int len;
|
305
|
+
wordend = wordstart;
|
306
|
+
while (*wordend && *wordend != '.')
|
307
|
+
{
|
308
|
+
wordend++;
|
309
|
+
}
|
310
|
+
|
311
|
+
len = (int)(wordend - wordstart);
|
312
|
+
|
313
|
+
if (len > 0x3F)
|
314
|
+
{
|
315
|
+
len = 0x3F;
|
316
|
+
}
|
317
|
+
|
318
|
+
*p++ = len;
|
319
|
+
|
320
|
+
while (wordstart != wordend)
|
321
|
+
{
|
322
|
+
*p++ = *wordstart++;
|
323
|
+
}
|
324
|
+
|
325
|
+
if (*wordstart == '.')
|
326
|
+
{
|
327
|
+
wordstart++;
|
328
|
+
}
|
329
|
+
}
|
330
|
+
|
331
|
+
*p++ = '\0';
|
332
|
+
|
333
|
+
*offset += p - start;
|
334
|
+
}
|
335
|
+
|
336
|
+
int calc_domain_name_size(unsigned char *buf, int buflen, int offset)
|
337
|
+
{
|
338
|
+
unsigned char *p = buf + offset;
|
339
|
+
int len = 0;
|
340
|
+
|
341
|
+
while (*p)
|
342
|
+
{
|
343
|
+
if ((*p & 0xC0) == 0xC0)
|
344
|
+
{
|
345
|
+
int newoffset = 0;
|
346
|
+
newoffset |= (*p++ & 0x3F) << 8;
|
347
|
+
newoffset |= *p;
|
348
|
+
|
349
|
+
p = buf + newoffset;
|
350
|
+
}
|
351
|
+
else
|
352
|
+
{
|
353
|
+
if (len)
|
354
|
+
{
|
355
|
+
len += 1;
|
356
|
+
}
|
357
|
+
len += *p;
|
358
|
+
p += *p + 1;
|
359
|
+
}
|
360
|
+
}
|
361
|
+
|
362
|
+
return len;
|
363
|
+
}
|
364
|
+
|
365
|
+
int netbuf_get_domain_name(unsigned char *buf, int buflen, int *offset, char *namebuf, int namebuflen)
|
366
|
+
{
|
367
|
+
unsigned char *start = buf + *offset;
|
368
|
+
unsigned char *p, *p2;
|
369
|
+
int *curroffset = offset;
|
370
|
+
int len = 0;
|
371
|
+
|
372
|
+
*namebuf = '\0';
|
373
|
+
|
374
|
+
/* measure length */
|
375
|
+
p = start;
|
376
|
+
while (*p)
|
377
|
+
{
|
378
|
+
if ((*p & 0xC0) == 0xC0)
|
379
|
+
{
|
380
|
+
int newoffset = 0;
|
381
|
+
newoffset |= (*p++ & 0x3F) << 8;
|
382
|
+
newoffset |= *p++;
|
383
|
+
|
384
|
+
p = buf + newoffset;
|
385
|
+
}
|
386
|
+
else
|
387
|
+
{
|
388
|
+
len += *p;
|
389
|
+
p += *p + 1;
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
if (namebuflen < len)
|
394
|
+
{
|
395
|
+
return len;
|
396
|
+
}
|
397
|
+
|
398
|
+
/* actually copy in name */
|
399
|
+
p = start;
|
400
|
+
p2 = (unsigned char *)namebuf;
|
401
|
+
while (*p)
|
402
|
+
{
|
403
|
+
if ((*p & 0xC0) == 0xC0)
|
404
|
+
{
|
405
|
+
int newoffset = 0;
|
406
|
+
newoffset |= (*p++ & 0x3F) << 8;
|
407
|
+
newoffset |= *p++;
|
408
|
+
|
409
|
+
if (curroffset)
|
410
|
+
{
|
411
|
+
*curroffset += (int)(p - start);
|
412
|
+
curroffset = NULL;
|
413
|
+
}
|
414
|
+
|
415
|
+
p = buf + newoffset;
|
416
|
+
}
|
417
|
+
else
|
418
|
+
{
|
419
|
+
int i, partlen;
|
420
|
+
|
421
|
+
if (*namebuf != '\0')
|
422
|
+
{
|
423
|
+
*p2++ = '.';
|
424
|
+
}
|
425
|
+
|
426
|
+
partlen = *p++;
|
427
|
+
|
428
|
+
for (i=0; i < partlen; i++)
|
429
|
+
{
|
430
|
+
*p2++ = *p++;
|
431
|
+
}
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
if (curroffset)
|
436
|
+
{
|
437
|
+
p++;
|
438
|
+
*curroffset += (int)(p - start);
|
439
|
+
curroffset = NULL;
|
440
|
+
}
|
441
|
+
|
442
|
+
*p2 = '\0';
|
443
|
+
|
444
|
+
return 0;
|
445
|
+
}
|
446
|
+
|
447
|
+
void netbuf_add_dnsquery_header(unsigned char *buf, int buflen, int *offset, struct dnsquery_header *header)
|
448
|
+
{
|
449
|
+
unsigned char *p;
|
450
|
+
|
451
|
+
netbuf_add_16bitnum(buf, buflen, offset, header->id);
|
452
|
+
|
453
|
+
p = buf + *offset;
|
454
|
+
*p++ = ((header->qr & 0x01) << 7)
|
455
|
+
| ((header->opcode & 0x0F) << 3)
|
456
|
+
| ((header->aa & 0x01) << 2)
|
457
|
+
| ((header->tc & 0x01) << 1)
|
458
|
+
| ((header->rd & 0x01));
|
459
|
+
*p++ = ((header->ra & 0x01) << 7)
|
460
|
+
| ((header->z & 0x07) << 4)
|
461
|
+
| ((header->rcode & 0x0F));
|
462
|
+
*offset += 2;
|
463
|
+
|
464
|
+
netbuf_add_16bitnum(buf, buflen, offset, header->qdcount);
|
465
|
+
netbuf_add_16bitnum(buf, buflen, offset, header->ancount);
|
466
|
+
netbuf_add_16bitnum(buf, buflen, offset, header->nscount);
|
467
|
+
netbuf_add_16bitnum(buf, buflen, offset, header->arcount);
|
468
|
+
}
|
469
|
+
|
470
|
+
void netbuf_get_dnsquery_header(unsigned char *buf, int buflen, int *offset, struct dnsquery_header *header)
|
471
|
+
{
|
472
|
+
unsigned char *p;
|
473
|
+
|
474
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(header->id));
|
475
|
+
|
476
|
+
p = buf + *offset;
|
477
|
+
header->qr = (*p >> 7) & 0x01;
|
478
|
+
header->opcode = (*p >> 3) & 0x0F;
|
479
|
+
header->aa = (*p >> 2) & 0x01;
|
480
|
+
header->tc = (*p >> 1) & 0x01;
|
481
|
+
header->rd = (*p) & 0x01;
|
482
|
+
p++;
|
483
|
+
header->ra = (*p >> 7) & 0x01;
|
484
|
+
header->z = (*p >> 4) & 0x07;
|
485
|
+
header->rcode = (*p) & 0x0F;
|
486
|
+
p++;
|
487
|
+
*offset += 2;
|
488
|
+
|
489
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(header->qdcount));
|
490
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(header->ancount));
|
491
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(header->nscount));
|
492
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(header->arcount));
|
493
|
+
}
|
494
|
+
|
495
|
+
void netbuf_add_dnsquery_question(unsigned char *buf, int buflen, int *offset, struct dnsquery_question *question)
|
496
|
+
{
|
497
|
+
netbuf_add_domain_name(buf, buflen, offset, question->qname);
|
498
|
+
netbuf_add_16bitnum(buf, buflen, offset, question->qtype);
|
499
|
+
netbuf_add_16bitnum(buf, buflen, offset, question->qclass);
|
500
|
+
}
|
501
|
+
|
502
|
+
void netbuf_get_dnsquery_question(unsigned char *buf, int buflen, int *offset, struct dnsquery_question *question)
|
503
|
+
{
|
504
|
+
netbuf_get_domain_name(buf, buflen, offset, question->qname, 1024);
|
505
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(question->qtype));
|
506
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(question->qclass));
|
507
|
+
}
|
508
|
+
|
509
|
+
void netbuf_get_dnsquery_srvrdata(unsigned char *buf, int buflen, int *offset, struct dnsquery_srvrdata *srvrdata)
|
510
|
+
{
|
511
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(srvrdata->priority));
|
512
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(srvrdata->weight));
|
513
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(srvrdata->port));
|
514
|
+
netbuf_get_domain_name(buf, buflen, offset, srvrdata->target, 1024);
|
515
|
+
}
|
516
|
+
|
517
|
+
void netbuf_get_dnsquery_resourcerecord(unsigned char *buf, int buflen, int *offset, struct dnsquery_resourcerecord *rr)
|
518
|
+
{
|
519
|
+
netbuf_get_domain_name(buf, buflen, offset, rr->name, 1024);
|
520
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(rr->type));
|
521
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(rr->_class));
|
522
|
+
netbuf_get_32bitnum(buf, buflen, offset, &(rr->ttl));
|
523
|
+
netbuf_get_16bitnum(buf, buflen, offset, &(rr->rdlength));
|
524
|
+
if (rr->type == 33) /* SRV */
|
525
|
+
{
|
526
|
+
int newoffset = *offset;
|
527
|
+
netbuf_get_dnsquery_srvrdata(buf, buflen, &newoffset, &(rr->rdata));
|
528
|
+
}
|
529
|
+
*offset += rr->rdlength;
|
530
|
+
}
|
531
|
+
|
532
|
+
|
533
|
+
int sock_srv_lookup(const char *service, const char *proto, const char *domain, char *resulttarget, int resulttargetlength, int *resultport)
|
534
|
+
{
|
535
|
+
int set = 0;
|
536
|
+
char fulldomain[2048];
|
537
|
+
|
538
|
+
snprintf(fulldomain, 2048, "_%s._%s.%s", service, proto, domain);
|
539
|
+
#ifdef _WIN32
|
540
|
+
|
541
|
+
/* try using dnsapi first */
|
542
|
+
if (!set)
|
543
|
+
{
|
544
|
+
HINSTANCE hdnsapi = NULL;
|
545
|
+
|
546
|
+
DNS_STATUS (WINAPI * pDnsQuery_A)(PCSTR, WORD, DWORD, PIP4_ARRAY, PDNS_RECORD*, PVOID*);
|
547
|
+
void (WINAPI * pDnsRecordListFree)(PDNS_RECORD, DNS_FREE_TYPE);
|
548
|
+
|
549
|
+
if (hdnsapi = LoadLibrary("dnsapi.dll")) {
|
550
|
+
|
551
|
+
pDnsQuery_A = (void *)GetProcAddress(hdnsapi, "DnsQuery_A");
|
552
|
+
pDnsRecordListFree = (void *)GetProcAddress(hdnsapi, "DnsRecordListFree");
|
553
|
+
|
554
|
+
if (pDnsQuery_A && pDnsRecordListFree) {
|
555
|
+
PDNS_RECORD dnsrecords = NULL;
|
556
|
+
DNS_STATUS error;
|
557
|
+
|
558
|
+
error = pDnsQuery_A(fulldomain, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &dnsrecords, NULL);
|
559
|
+
|
560
|
+
if (error == 0) {
|
561
|
+
PDNS_RECORD current = dnsrecords;
|
562
|
+
|
563
|
+
while (current) {
|
564
|
+
if (current->wType == DNS_TYPE_SRV) {
|
565
|
+
snprintf(resulttarget, resulttargetlength, current->Data.Srv.pNameTarget);
|
566
|
+
*resultport = current->Data.Srv.wPort;
|
567
|
+
set = 1;
|
568
|
+
|
569
|
+
current = NULL;
|
570
|
+
} else {
|
571
|
+
current = current->pNext;
|
572
|
+
}
|
573
|
+
}
|
574
|
+
}
|
575
|
+
|
576
|
+
pDnsRecordListFree(dnsrecords, DnsFreeRecordList);
|
577
|
+
}
|
578
|
+
|
579
|
+
FreeLibrary(hdnsapi);
|
580
|
+
}
|
581
|
+
}
|
582
|
+
|
583
|
+
/* if dnsapi didn't work/isn't there, try querying the dns server manually */
|
584
|
+
if (!set)
|
585
|
+
{
|
586
|
+
unsigned char buf[65536];
|
587
|
+
struct dnsquery_header header;
|
588
|
+
struct dnsquery_question question;
|
589
|
+
int offset = 0;
|
590
|
+
int addrlen;
|
591
|
+
sock_t sock;
|
592
|
+
struct sockaddr_in dnsaddr;
|
593
|
+
char dnsserverips[16][256];
|
594
|
+
int numdnsservers = 0;
|
595
|
+
int j;
|
596
|
+
|
597
|
+
/* Try getting the DNS server ips from GetNetworkParams() in iphlpapi first */
|
598
|
+
if (!numdnsservers)
|
599
|
+
{
|
600
|
+
HINSTANCE hiphlpapi = NULL;
|
601
|
+
DWORD (WINAPI * pGetNetworkParams)(PFIXED_INFO, PULONG);
|
602
|
+
|
603
|
+
if (hiphlpapi = LoadLibrary("Iphlpapi.dll"))
|
604
|
+
{
|
605
|
+
pGetNetworkParams = (void *)GetProcAddress(hiphlpapi, "GetNetworkParams");
|
606
|
+
|
607
|
+
if (pGetNetworkParams)
|
608
|
+
{
|
609
|
+
FIXED_INFO *fi;
|
610
|
+
ULONG len;
|
611
|
+
DWORD error;
|
612
|
+
char buffer[65535];
|
613
|
+
|
614
|
+
len = 65535;
|
615
|
+
fi = buffer;
|
616
|
+
|
617
|
+
if ((error = pGetNetworkParams(fi, &len)) == ERROR_SUCCESS)
|
618
|
+
{
|
619
|
+
IP_ADDR_STRING *pias = &(fi->DnsServerList);
|
620
|
+
|
621
|
+
while (pias && numdnsservers < 16)
|
622
|
+
{
|
623
|
+
strcpy(dnsserverips[numdnsservers++], pias->IpAddress.String);
|
624
|
+
pias = pias->Next;
|
625
|
+
}
|
626
|
+
}
|
627
|
+
}
|
628
|
+
}
|
629
|
+
FreeLibrary(hiphlpapi);
|
630
|
+
}
|
631
|
+
|
632
|
+
/* Next, try getting the DNS server ips from the registry */
|
633
|
+
if (!numdnsservers)
|
634
|
+
{
|
635
|
+
HKEY search;
|
636
|
+
LONG error;
|
637
|
+
|
638
|
+
error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_READ, &search);
|
639
|
+
|
640
|
+
if (error != ERROR_SUCCESS)
|
641
|
+
{
|
642
|
+
error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &search);
|
643
|
+
}
|
644
|
+
|
645
|
+
if (error == ERROR_SUCCESS)
|
646
|
+
{
|
647
|
+
char name[512];
|
648
|
+
DWORD len = 512;
|
649
|
+
|
650
|
+
error = RegQueryValueEx(search, "NameServer", NULL, NULL, (LPBYTE)name, &len);
|
651
|
+
|
652
|
+
if (error != ERROR_SUCCESS)
|
653
|
+
{
|
654
|
+
error = RegQueryValueEx(search, "DhcpNameServer", NULL, NULL, (LPBYTE)name, &len);
|
655
|
+
}
|
656
|
+
|
657
|
+
if (error == ERROR_SUCCESS)
|
658
|
+
{
|
659
|
+
char *parse = "0123456789.", *start, *end;
|
660
|
+
start = name;
|
661
|
+
end = name;
|
662
|
+
name[len] = '\0';
|
663
|
+
|
664
|
+
while (*start && numdnsservers < 16)
|
665
|
+
{
|
666
|
+
while (strchr(parse, *end))
|
667
|
+
{
|
668
|
+
end++;
|
669
|
+
}
|
670
|
+
|
671
|
+
strncpy(dnsserverips[numdnsservers++], start, end - start);
|
672
|
+
|
673
|
+
while (*end && !strchr(parse, *end))
|
674
|
+
{
|
675
|
+
end++;
|
676
|
+
}
|
677
|
+
|
678
|
+
start = end;
|
679
|
+
}
|
680
|
+
}
|
681
|
+
}
|
682
|
+
|
683
|
+
RegCloseKey(search);
|
684
|
+
}
|
685
|
+
|
686
|
+
if (!numdnsservers)
|
687
|
+
{
|
688
|
+
HKEY searchlist;
|
689
|
+
LONG error;
|
690
|
+
|
691
|
+
error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", 0, KEY_READ, &searchlist);
|
692
|
+
|
693
|
+
if (error == ERROR_SUCCESS)
|
694
|
+
{
|
695
|
+
unsigned int i;
|
696
|
+
DWORD numinterfaces = 0;
|
697
|
+
|
698
|
+
RegQueryInfoKey(searchlist, NULL, NULL, NULL, &numinterfaces, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
699
|
+
|
700
|
+
for (i = 0; i < numinterfaces; i++)
|
701
|
+
{
|
702
|
+
char name[512];
|
703
|
+
DWORD len = 512;
|
704
|
+
HKEY searchentry;
|
705
|
+
|
706
|
+
RegEnumKeyEx(searchlist, i, (LPTSTR)name, &len, NULL, NULL, NULL, NULL);
|
707
|
+
|
708
|
+
if (RegOpenKeyEx(searchlist, name, 0, KEY_READ, &searchentry) == ERROR_SUCCESS)
|
709
|
+
{
|
710
|
+
if (RegQueryValueEx(searchentry, "DhcpNameServer", NULL, NULL, (LPBYTE)name, &len) == ERROR_SUCCESS)
|
711
|
+
{
|
712
|
+
char *parse = "0123456789.", *start, *end;
|
713
|
+
start = name;
|
714
|
+
end = name;
|
715
|
+
name[len] = '\0';
|
716
|
+
|
717
|
+
while (*start && numdnsservers < 16)
|
718
|
+
{
|
719
|
+
while (strchr(parse, *end))
|
720
|
+
{
|
721
|
+
end++;
|
722
|
+
}
|
723
|
+
|
724
|
+
strncpy(dnsserverips[numdnsservers++], start, end - start);
|
725
|
+
|
726
|
+
while (*end && !strchr(parse, *end))
|
727
|
+
{
|
728
|
+
end++;
|
729
|
+
}
|
730
|
+
|
731
|
+
start = end;
|
732
|
+
}
|
733
|
+
}
|
734
|
+
else if (RegQueryValueEx(searchentry, "NameServer", NULL, NULL, (LPBYTE)name, &len) == ERROR_SUCCESS)
|
735
|
+
{
|
736
|
+
char *parse = "0123456789.", *start, *end;
|
737
|
+
start = name;
|
738
|
+
end = name;
|
739
|
+
name[len] = '\0';
|
740
|
+
|
741
|
+
while (*start && numdnsservers < 16)
|
742
|
+
{
|
743
|
+
while (strchr(parse, *end))
|
744
|
+
{
|
745
|
+
end++;
|
746
|
+
}
|
747
|
+
|
748
|
+
strncpy(dnsserverips[numdnsservers++], start, end - start);
|
749
|
+
|
750
|
+
while (*end && !strchr(parse, *end))
|
751
|
+
{
|
752
|
+
end++;
|
753
|
+
}
|
754
|
+
|
755
|
+
start = end;
|
756
|
+
}
|
757
|
+
}
|
758
|
+
RegCloseKey(searchentry);
|
759
|
+
}
|
760
|
+
}
|
761
|
+
RegCloseKey(searchlist);
|
762
|
+
}
|
763
|
+
}
|
764
|
+
|
765
|
+
/* If we have a DNS server, use it */
|
766
|
+
if (numdnsservers)
|
767
|
+
{
|
768
|
+
ULONG nonblocking = 1;
|
769
|
+
int i;
|
770
|
+
int insize;
|
771
|
+
|
772
|
+
memset(&header, 0, sizeof(header));
|
773
|
+
header.id = 12345; /* FIXME: Get a better id here */
|
774
|
+
header.rd = 1;
|
775
|
+
header.qdcount = 1;
|
776
|
+
|
777
|
+
netbuf_add_dnsquery_header(buf, 65536, &offset, &header);
|
778
|
+
|
779
|
+
memset(&question, 0, sizeof(question));
|
780
|
+
strncpy(question.qname, fulldomain, 1024);
|
781
|
+
question.qtype = 33; /* SRV */
|
782
|
+
question.qclass = 1; /* INTERNET! */
|
783
|
+
|
784
|
+
netbuf_add_dnsquery_question(buf, 65536, &offset, &question);
|
785
|
+
|
786
|
+
insize = 0;
|
787
|
+
for (i = 0; i < numdnsservers && insize <= 0; i++)
|
788
|
+
{
|
789
|
+
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
790
|
+
ioctlsocket(sock, FIONBIO, &nonblocking);
|
791
|
+
|
792
|
+
memset(&dnsaddr, 0, sizeof(dnsaddr));
|
793
|
+
|
794
|
+
dnsaddr.sin_family = AF_INET;
|
795
|
+
dnsaddr.sin_port = htons(53);
|
796
|
+
dnsaddr.sin_addr.s_addr = inet_addr(dnsserverips[i]);
|
797
|
+
|
798
|
+
addrlen = sizeof(dnsaddr);
|
799
|
+
sendto(sock, (char *)buf, offset, 0, (struct sockaddr *)&dnsaddr, addrlen);
|
800
|
+
for (j = 0; j < 50; j++)
|
801
|
+
{
|
802
|
+
insize = recvfrom(sock, (char *)buf, 65536, 0, (struct sockaddr *)&dnsaddr, &addrlen);
|
803
|
+
if (insize == SOCKET_ERROR)
|
804
|
+
{
|
805
|
+
if (sock_error() == WSAEWOULDBLOCK)
|
806
|
+
{
|
807
|
+
Sleep(100);
|
808
|
+
}
|
809
|
+
else
|
810
|
+
{
|
811
|
+
break;
|
812
|
+
}
|
813
|
+
}
|
814
|
+
else
|
815
|
+
{
|
816
|
+
break;
|
817
|
+
}
|
818
|
+
}
|
819
|
+
|
820
|
+
closesocket(sock);
|
821
|
+
}
|
822
|
+
|
823
|
+
offset = insize;
|
824
|
+
|
825
|
+
if (offset > 0)
|
826
|
+
{
|
827
|
+
int len = offset;
|
828
|
+
int i;
|
829
|
+
struct dnsquery_header header;
|
830
|
+
struct dnsquery_question question;
|
831
|
+
struct dnsquery_resourcerecord rr;
|
832
|
+
|
833
|
+
offset = 0;
|
834
|
+
netbuf_get_dnsquery_header(buf, 65536, &offset, &header);
|
835
|
+
|
836
|
+
for (i = 0; i < header.qdcount; i++)
|
837
|
+
{
|
838
|
+
netbuf_get_dnsquery_question(buf, 65536, &offset, &question);
|
839
|
+
}
|
840
|
+
|
841
|
+
for (i = 0; i < header.ancount; i++)
|
842
|
+
{
|
843
|
+
netbuf_get_dnsquery_resourcerecord(buf, 65536, &offset, &rr);
|
844
|
+
|
845
|
+
if (rr.type == 33)
|
846
|
+
{
|
847
|
+
struct dnsquery_srvrdata *srvrdata = &(rr.rdata);
|
848
|
+
|
849
|
+
snprintf(resulttarget, resulttargetlength, srvrdata->target);
|
850
|
+
*resultport = srvrdata->port;
|
851
|
+
set = 1;
|
852
|
+
}
|
853
|
+
}
|
854
|
+
|
855
|
+
for (i = 0; i < header.ancount; i++)
|
856
|
+
{
|
857
|
+
netbuf_get_dnsquery_resourcerecord(buf, 65536, &offset, &rr);
|
858
|
+
}
|
859
|
+
}
|
860
|
+
}
|
861
|
+
|
862
|
+
}
|
863
|
+
|
864
|
+
#else
|
865
|
+
if (!set) {
|
866
|
+
unsigned char buf[65535];
|
867
|
+
int len;
|
868
|
+
|
869
|
+
if ((len = res_query(fulldomain, C_IN, T_SRV, buf, 65535)) > 0) {
|
870
|
+
int offset;
|
871
|
+
int i;
|
872
|
+
struct dnsquery_header header;
|
873
|
+
struct dnsquery_question question;
|
874
|
+
struct dnsquery_resourcerecord rr;
|
875
|
+
|
876
|
+
offset = 0;
|
877
|
+
netbuf_get_dnsquery_header(buf, 65536, &offset, &header);
|
878
|
+
|
879
|
+
for (i = 0; i < header.qdcount; i++) {
|
880
|
+
netbuf_get_dnsquery_question(buf, 65536, &offset, &question);
|
881
|
+
}
|
882
|
+
|
883
|
+
for (i = 0; i < header.ancount; i++) {
|
884
|
+
netbuf_get_dnsquery_resourcerecord(buf, 65536, &offset, &rr);
|
885
|
+
|
886
|
+
if (rr.type == 33) {
|
887
|
+
struct dnsquery_srvrdata *srvrdata = &(rr.rdata);
|
888
|
+
|
889
|
+
snprintf(resulttarget, resulttargetlength,
|
890
|
+
srvrdata->target);
|
891
|
+
*resultport = srvrdata->port;
|
892
|
+
set = 1;
|
893
|
+
}
|
894
|
+
}
|
895
|
+
|
896
|
+
for (i = 0; i < header.ancount; i++) {
|
897
|
+
netbuf_get_dnsquery_resourcerecord(buf, 65536, &offset, &rr);
|
898
|
+
}
|
899
|
+
}
|
900
|
+
}
|
901
|
+
#endif
|
902
|
+
|
903
|
+
if (!set)
|
904
|
+
{
|
905
|
+
snprintf(resulttarget, resulttargetlength, domain);
|
906
|
+
*resultport = 5222;
|
907
|
+
return 0;
|
908
|
+
}
|
909
|
+
|
910
|
+
return 1;
|
911
|
+
}
|