dnssd 1.1.0 → 1.2
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.tar.gz.sig +0 -0
- data/.autotest +10 -11
- data/History.txt +28 -3
- data/Manifest.txt +4 -2
- data/README.txt +10 -8
- data/ext/dnssd/dnssd.c +81 -4
- data/ext/dnssd/dnssd.h +3 -1
- data/ext/dnssd/errors.c +61 -39
- data/ext/dnssd/extconf.rb +4 -1
- data/ext/dnssd/flags.c +84 -22
- data/ext/dnssd/service.c +242 -553
- data/lib/dnssd.rb +138 -109
- data/lib/dnssd/flags.rb +13 -1
- data/lib/dnssd/reply.rb +71 -2
- data/lib/dnssd/service.rb +147 -4
- data/sample/enumerate_domains.rb +13 -0
- data/sample/resolve.rb +2 -2
- data/sample/server.rb +19 -0
- data/sample/socket.rb +18 -0
- data/test/test_dnssd.rb +75 -0
- data/test/test_dnssd_flags.rb +6 -1
- data/test/test_dnssd_reply.rb +67 -0
- metadata +30 -6
- metadata.gz.sig +0 -0
- data/ext/dnssd/dns_sd.h +0 -1493
- data/sample/highlevel_api.rb +0 -30
data/ext/dnssd/service.c
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
#include "dnssd.h"
|
2
|
-
#include <assert.h>
|
3
2
|
|
4
3
|
#ifndef DNSSD_API
|
5
4
|
/* define as nothing if not defined in Apple's "dns_sd.h" header */
|
@@ -10,28 +9,52 @@ static VALUE cDNSSDReply;
|
|
10
9
|
static VALUE cDNSSDService;
|
11
10
|
static VALUE cDNSSDTextRecord;
|
12
11
|
|
13
|
-
static ID
|
14
|
-
static ID
|
15
|
-
static ID dnssd_id_to_i;
|
16
|
-
static ID dnssd_id_to_str;
|
12
|
+
static ID dnssd_id_join;
|
13
|
+
static ID dnssd_id_push;
|
17
14
|
|
18
|
-
static ID
|
15
|
+
static ID dnssd_iv_continue;
|
19
16
|
static ID dnssd_iv_domain;
|
20
17
|
static ID dnssd_iv_interface;
|
21
18
|
static ID dnssd_iv_port;
|
22
|
-
static ID
|
23
|
-
static ID dnssd_iv_service;
|
19
|
+
static ID dnssd_iv_replies;
|
24
20
|
static ID dnssd_iv_target;
|
25
21
|
static ID dnssd_iv_text_record;
|
26
22
|
static ID dnssd_iv_thread;
|
27
23
|
|
28
|
-
|
24
|
+
/* HACK why is this a macro */
|
29
25
|
#define GetDNSSDService(obj, var) \
|
30
|
-
do {
|
26
|
+
do {\
|
27
|
+
Check_Type(obj, T_DATA);\
|
28
|
+
if (rb_obj_is_kind_of(obj, cDNSSDService) != Qtrue)\
|
29
|
+
rb_raise(rb_eTypeError,\
|
30
|
+
"wrong argument type %s (expected DNSSD::Service)",\
|
31
|
+
rb_class2name(CLASS_OF(obj)));\
|
32
|
+
Data_Get_Struct(obj, DNSServiceRef, var);\
|
33
|
+
} while (0)
|
31
34
|
|
32
|
-
static
|
33
|
-
|
34
|
-
|
35
|
+
static void
|
36
|
+
dnssd_service_callback(VALUE self, VALUE reply) {
|
37
|
+
VALUE replies = rb_ivar_get(self, dnssd_iv_replies);
|
38
|
+
|
39
|
+
rb_funcall(replies, dnssd_id_push, 1, reply);
|
40
|
+
}
|
41
|
+
|
42
|
+
static void
|
43
|
+
dnssd_service_free_client(DNSServiceRef *client) {
|
44
|
+
if (*client) {
|
45
|
+
DNSServiceRefDeallocate(*client);
|
46
|
+
*client = NULL;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
static void
|
51
|
+
dnssd_service_free(void *ptr) {
|
52
|
+
DNSServiceRef *client = (DNSServiceRef*)ptr;
|
53
|
+
|
54
|
+
if (client)
|
55
|
+
dnssd_service_free_client(client);
|
56
|
+
|
57
|
+
free(client);
|
35
58
|
}
|
36
59
|
|
37
60
|
static VALUE
|
@@ -48,6 +71,26 @@ create_fullname(const char *name, const char *regtype,
|
|
48
71
|
return rb_str_new2(buffer);
|
49
72
|
}
|
50
73
|
|
74
|
+
static VALUE
|
75
|
+
reply_new(VALUE service, DNSServiceFlags flags) {
|
76
|
+
return rb_funcall(cDNSSDReply, rb_intern("from_service"), 2, service,
|
77
|
+
UINT2NUM(flags));
|
78
|
+
}
|
79
|
+
|
80
|
+
static void
|
81
|
+
reply_set_interface(VALUE self, uint32_t interface) {
|
82
|
+
VALUE if_value;
|
83
|
+
char buffer[IF_NAMESIZE];
|
84
|
+
|
85
|
+
if (if_indextoname(interface, buffer)) {
|
86
|
+
if_value = rb_str_new2(buffer);
|
87
|
+
} else {
|
88
|
+
if_value = ULONG2NUM(interface);
|
89
|
+
}
|
90
|
+
|
91
|
+
rb_ivar_set(self, dnssd_iv_interface, if_value);
|
92
|
+
}
|
93
|
+
|
51
94
|
/*
|
52
95
|
* call-seq:
|
53
96
|
* DNSSD::Service.fullname(name, type, domain) => String
|
@@ -77,147 +120,28 @@ dnssd_service_s_fullname(VALUE klass, VALUE name, VALUE type, VALUE domain) {
|
|
77
120
|
}
|
78
121
|
|
79
122
|
static VALUE
|
80
|
-
|
81
|
-
|
82
|
-
}
|
83
|
-
|
84
|
-
static VALUE
|
85
|
-
reply_new(VALUE service, DNSServiceFlags flags) {
|
86
|
-
return rb_funcall(cDNSSDReply, rb_intern("from_service"), 2, service,
|
87
|
-
UINT2NUM(flags));
|
88
|
-
}
|
89
|
-
|
90
|
-
static void
|
91
|
-
reply_set_interface(VALUE self, uint32_t interface) {
|
92
|
-
VALUE if_value;
|
93
|
-
char buffer[IF_NAMESIZE];
|
94
|
-
|
95
|
-
if (if_indextoname(interface, buffer)) {
|
96
|
-
if_value = rb_str_new2(buffer);
|
97
|
-
} else {
|
98
|
-
if_value = ULONG2NUM(interface);
|
99
|
-
}
|
100
|
-
|
101
|
-
rb_ivar_set(self, dnssd_iv_interface, if_value);
|
102
|
-
}
|
103
|
-
|
104
|
-
static VALUE
|
105
|
-
reply_from_browse(VALUE service, DNSServiceFlags flags,
|
106
|
-
uint32_t interface, const char *name, const char *regtype,
|
107
|
-
const char *domain) {
|
108
|
-
VALUE self = reply_new(service, flags);
|
109
|
-
reply_set_interface(self, interface);
|
110
|
-
rb_funcall(self, rb_intern("set_names"), 3, rb_str_new2(name),
|
111
|
-
rb_str_new2(regtype), rb_str_new2(domain));
|
112
|
-
return self;
|
113
|
-
}
|
114
|
-
|
115
|
-
static VALUE
|
116
|
-
reply_from_domain_enum(VALUE service, DNSServiceFlags flags,
|
117
|
-
uint32_t interface, const char *domain) {
|
118
|
-
VALUE self = reply_new(service, flags);
|
119
|
-
reply_set_interface(self, interface);
|
120
|
-
rb_ivar_set(self, dnssd_iv_domain, rb_str_new2(domain));
|
121
|
-
return self;
|
122
|
-
}
|
123
|
-
|
124
|
-
static VALUE
|
125
|
-
reply_from_register(VALUE service, DNSServiceFlags flags,
|
126
|
-
const char *name, const char *regtype, const char *domain) {
|
127
|
-
VALUE self = reply_new(service, flags);
|
128
|
-
rb_funcall(self, rb_intern("set_names"), 3, rb_str_new2(name),
|
129
|
-
rb_str_new2(regtype), rb_str_new2(domain));
|
130
|
-
/* HACK */
|
131
|
-
/* See HACK in dnssd_service.c */
|
132
|
-
rb_ivar_set(self, dnssd_iv_interface,
|
133
|
-
rb_ivar_get(service, dnssd_iv_interface));
|
134
|
-
rb_ivar_set(self, dnssd_iv_port, rb_ivar_get(service, dnssd_iv_port));
|
135
|
-
rb_ivar_set(self, dnssd_iv_text_record,
|
136
|
-
rb_ivar_get(service, dnssd_iv_text_record));
|
137
|
-
/********/
|
138
|
-
return self;
|
139
|
-
}
|
140
|
-
|
141
|
-
static VALUE
|
142
|
-
reply_from_resolve(VALUE service, DNSServiceFlags flags, uint32_t
|
143
|
-
interface, const char *fullname, const char *host_target, uint16_t
|
144
|
-
opaqueport, uint16_t txt_len, const char *txt_rec) {
|
145
|
-
uint16_t port = ntohs(opaqueport);
|
146
|
-
VALUE self = reply_new(service, flags);
|
147
|
-
|
148
|
-
reply_set_interface(self, interface);
|
149
|
-
rb_funcall(self, rb_intern("set_fullname"), 1, rb_str_new2(fullname));
|
150
|
-
rb_ivar_set(self, dnssd_iv_target, rb_str_new2(host_target));
|
151
|
-
rb_ivar_set(self, dnssd_iv_port, UINT2NUM(port));
|
152
|
-
rb_ivar_set(self, dnssd_iv_text_record,
|
153
|
-
text_record_new(rb_str_new(txt_rec, txt_len)));
|
154
|
-
|
155
|
-
return self;
|
156
|
-
}
|
123
|
+
dnssd_service_s_allocate(VALUE klass) {
|
124
|
+
DNSServiceRef *client = ALLOC(DNSServiceRef);
|
157
125
|
|
158
|
-
|
159
|
-
dnssd_callback(VALUE service, VALUE reply) {
|
160
|
-
VALUE result = rb_funcall2(rb_ivar_get(service, dnssd_iv_block),
|
161
|
-
dnssd_id_call, 1, &reply);
|
162
|
-
rb_ivar_set(service, dnssd_iv_result, result);
|
163
|
-
}
|
126
|
+
*client = NULL;
|
164
127
|
|
165
|
-
|
166
|
-
dnssd_get_domain(VALUE service_domain) {
|
167
|
-
const char *domain = StringValueCStr(service_domain);
|
168
|
-
/* max len including the null terminator and trailing '.' */
|
169
|
-
if (RSTRING_LEN(service_domain) >= kDNSServiceMaxDomainName - 1)
|
170
|
-
rb_raise(rb_eArgError, "domain name string too large");
|
171
|
-
return domain;
|
172
|
-
}
|
173
|
-
|
174
|
-
static uint32_t
|
175
|
-
dnssd_get_interface_index(VALUE interface) {
|
176
|
-
/* if the interface is a string then convert it to the interface index */
|
177
|
-
if (rb_respond_to(interface, dnssd_id_to_str)) {
|
178
|
-
return if_nametoindex(StringValueCStr(interface));
|
179
|
-
} else {
|
180
|
-
return (uint32_t)NUM2ULONG(interface);
|
181
|
-
}
|
128
|
+
return Data_Wrap_Struct(klass, 0, dnssd_service_free, client);
|
182
129
|
}
|
183
130
|
|
184
131
|
/*
|
185
132
|
* call-seq:
|
186
|
-
*
|
133
|
+
* service.started? => true or false
|
187
134
|
*
|
188
|
-
*
|
189
|
-
* ::register, and ::resolve.
|
135
|
+
* Returns true if the service has been started.
|
190
136
|
*/
|
191
137
|
|
192
138
|
static VALUE
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
static void
|
199
|
-
dnssd_service_free_client(DNSServiceRef *client) {
|
200
|
-
DNSServiceRefDeallocate(*client);
|
201
|
-
free(client); /* free the pointer */
|
202
|
-
}
|
203
|
-
|
204
|
-
static void
|
205
|
-
dnssd_service_free(void *ptr) {
|
206
|
-
DNSServiceRef *client = (DNSServiceRef*)ptr;
|
207
|
-
if (client) {
|
208
|
-
/* client will be non-null only if client has not been deallocated */
|
209
|
-
dnssd_service_free_client(client);
|
210
|
-
}
|
211
|
-
}
|
139
|
+
dnssd_service_started_p(VALUE service) {
|
140
|
+
DNSServiceRef *client = (DNSServiceRef*)RDATA(service)->data;
|
141
|
+
if (client)
|
142
|
+
return (*client) == NULL ? Qfalse : Qtrue;
|
212
143
|
|
213
|
-
|
214
|
-
dnssd_service_alloc(VALUE block) {
|
215
|
-
DNSServiceRef *client = ALLOC(DNSServiceRef);
|
216
|
-
VALUE service = Data_Wrap_Struct(cDNSSDService, 0, dnssd_service_free, client);
|
217
|
-
rb_ivar_set(service, dnssd_iv_block, block);
|
218
|
-
rb_ivar_set(service, dnssd_iv_thread, Qnil);
|
219
|
-
rb_ivar_set(service, dnssd_iv_result, Qnil);
|
220
|
-
return service;
|
144
|
+
return Qtrue;
|
221
145
|
}
|
222
146
|
|
223
147
|
/*
|
@@ -230,7 +154,11 @@ dnssd_service_alloc(VALUE block) {
|
|
230
154
|
static VALUE
|
231
155
|
dnssd_service_stopped_p(VALUE service) {
|
232
156
|
DNSServiceRef *client = (DNSServiceRef*)RDATA(service)->data;
|
233
|
-
|
157
|
+
|
158
|
+
if (client)
|
159
|
+
return (*client) == NULL ? Qtrue : Qfalse;
|
160
|
+
|
161
|
+
return Qtrue;
|
234
162
|
}
|
235
163
|
|
236
164
|
/*
|
@@ -250,527 +178,285 @@ dnssd_service_stopped_p(VALUE service) {
|
|
250
178
|
*/
|
251
179
|
|
252
180
|
static VALUE
|
253
|
-
dnssd_service_stop(VALUE
|
181
|
+
dnssd_service_stop(VALUE self) {
|
254
182
|
VALUE thread;
|
255
|
-
DNSServiceRef *client = (DNSServiceRef*)RDATA(
|
183
|
+
DNSServiceRef *client = (DNSServiceRef*)RDATA(self)->data;
|
256
184
|
|
257
185
|
/* set to null right away for a bit more thread safety */
|
258
|
-
RDATA(
|
186
|
+
RDATA(self)->data = NULL;
|
259
187
|
|
260
188
|
if (client == NULL)
|
261
189
|
rb_raise(eDNSSDError, "service is already stopped");
|
262
190
|
|
263
|
-
|
264
|
-
|
265
|
-
thread = rb_ivar_get(service, dnssd_iv_thread);
|
266
|
-
rb_ivar_set(service, dnssd_iv_block, Qnil);
|
267
|
-
rb_ivar_set(service, dnssd_iv_thread, Qnil);
|
191
|
+
thread = rb_ivar_get(self, dnssd_iv_thread);
|
192
|
+
rb_ivar_set(self, dnssd_iv_continue, Qfalse);
|
268
193
|
|
269
|
-
if (!NIL_P(thread)) {
|
270
|
-
|
271
|
-
|
194
|
+
if (!NIL_P(thread) && thread != rb_thread_current()) {
|
195
|
+
rb_thread_run(thread);
|
196
|
+
rb_funcall(thread, dnssd_id_join, 0);
|
272
197
|
}
|
273
198
|
|
274
|
-
|
275
|
-
}
|
276
|
-
|
277
|
-
/* stop the service only if it is still running */
|
199
|
+
dnssd_service_free_client(client);
|
278
200
|
|
279
|
-
|
280
|
-
dnssd_service_stop2(VALUE service) {
|
281
|
-
if (RTEST(dnssd_service_stopped_p(service))) {
|
282
|
-
return service;
|
283
|
-
}
|
284
|
-
return dnssd_service_stop(service);
|
201
|
+
return self;
|
285
202
|
}
|
286
203
|
|
287
204
|
static VALUE
|
288
|
-
dnssd_service_process(VALUE
|
289
|
-
int dns_sd_fd, nfds, result;
|
290
|
-
fd_set readfds;
|
291
|
-
|
205
|
+
dnssd_service_process(VALUE self) {
|
292
206
|
DNSServiceRef *client;
|
293
|
-
|
207
|
+
|
208
|
+
GetDNSSDService(self, client);
|
294
209
|
|
295
210
|
if (client == NULL) {
|
296
211
|
/* looks like this thread has already been stopped */
|
297
212
|
return Qnil;
|
298
213
|
}
|
299
214
|
|
300
|
-
|
301
|
-
nfds = dns_sd_fd + 1;
|
302
|
-
for ( ;; ) {
|
303
|
-
FD_ZERO(&readfds);
|
304
|
-
FD_SET(dns_sd_fd, &readfds);
|
305
|
-
result = rb_thread_select(nfds, &readfds,
|
306
|
-
(fd_set *) NULL,
|
307
|
-
(fd_set *) NULL,
|
308
|
-
(struct timeval *) NULL);
|
309
|
-
if (result > 0) {
|
310
|
-
if (FD_ISSET(dns_sd_fd, &readfds)) {
|
311
|
-
DNSServiceErrorType e = DNSServiceProcessResult(*client);
|
312
|
-
dnssd_check_error_code(e);
|
313
|
-
}
|
314
|
-
} else {
|
315
|
-
break;
|
316
|
-
}
|
317
|
-
}
|
318
|
-
|
319
|
-
/* return the result from the processing */
|
320
|
-
return rb_ivar_get(service, dnssd_iv_result);
|
321
|
-
}
|
322
|
-
|
323
|
-
static VALUE
|
324
|
-
dnssd_service_start(VALUE service) {
|
325
|
-
return rb_ensure(dnssd_service_process, service, dnssd_service_stop2,
|
326
|
-
service);
|
327
|
-
}
|
328
|
-
|
329
|
-
static VALUE
|
330
|
-
dnssd_service_start_in_thread(VALUE service) {
|
331
|
-
/* race condition - service.@block could be called before the service's
|
332
|
-
* @thread is set and if the block calls #stop will raise an error, even
|
333
|
-
* though the service has been started and is running. */
|
215
|
+
rb_thread_wait_fd(DNSServiceRefSockFD(*client));
|
334
216
|
|
335
|
-
|
336
|
-
|
217
|
+
if (rb_ivar_get(self, dnssd_iv_continue) == Qfalse)
|
218
|
+
return Qnil;
|
337
219
|
|
338
|
-
|
339
|
-
|
340
|
-
* marked as long as the thread is running. Running threads are always
|
341
|
-
* marked by Ruby. !! */
|
220
|
+
DNSServiceErrorType e = DNSServiceProcessResult(*client);
|
221
|
+
dnssd_check_error_code(e);
|
342
222
|
|
343
|
-
|
344
|
-
return service;
|
223
|
+
return self;
|
345
224
|
}
|
346
225
|
|
347
226
|
static void DNSSD_API
|
348
|
-
|
349
|
-
uint32_t
|
350
|
-
const char *domain, void *context) {
|
351
|
-
VALUE service;
|
352
|
-
|
227
|
+
dnssd_service_browse_reply(DNSServiceRef client, DNSServiceFlags flags,
|
228
|
+
uint32_t interface, DNSServiceErrorType e, const char *name,
|
229
|
+
const char *type, const char *domain, void *context) {
|
230
|
+
VALUE service, reply;
|
231
|
+
|
353
232
|
dnssd_check_error_code(e);
|
233
|
+
|
354
234
|
service = (VALUE)context;
|
355
|
-
|
356
|
-
|
235
|
+
|
236
|
+
reply = reply_new(service, flags);
|
237
|
+
reply_set_interface(reply, interface);
|
238
|
+
rb_funcall(reply, rb_intern("set_names"), 3, rb_str_new2(name),
|
239
|
+
rb_str_new2(type), rb_str_new2(domain));
|
240
|
+
|
241
|
+
dnssd_service_callback(service, reply);
|
357
242
|
}
|
358
243
|
|
359
|
-
|
360
|
-
|
361
|
-
VALUE tmp_flags, interface;
|
244
|
+
/* Binding to DNSServiceBrowse
|
245
|
+
*/
|
362
246
|
|
247
|
+
static VALUE
|
248
|
+
dnssd_service_browse(VALUE self, VALUE _type, VALUE _domain, VALUE _flags,
|
249
|
+
VALUE _interface) {
|
250
|
+
const char *type;
|
251
|
+
const char *domain = NULL;
|
363
252
|
DNSServiceFlags flags = 0;
|
364
|
-
uint32_t
|
253
|
+
uint32_t interface = 0;
|
365
254
|
|
366
255
|
DNSServiceErrorType e;
|
367
256
|
DNSServiceRef *client;
|
368
257
|
|
369
|
-
|
258
|
+
type = StringValueCStr(_type);
|
370
259
|
|
371
|
-
|
372
|
-
|
373
|
-
flags = dnssd_to_flags(tmp_flags);
|
260
|
+
if (!NIL_P(_domain))
|
261
|
+
domain = StringValueCStr(_domain);
|
374
262
|
|
375
|
-
if (!NIL_P(
|
376
|
-
|
263
|
+
if (!NIL_P(_flags))
|
264
|
+
flags = (DNSServiceFlags)NUM2ULONG(_flags);
|
377
265
|
|
378
|
-
|
379
|
-
|
380
|
-
dnssd_domain_enum_reply, (void *)service);
|
381
|
-
dnssd_check_error_code(e);
|
382
|
-
return service;
|
383
|
-
}
|
266
|
+
if (!NIL_P(_interface))
|
267
|
+
interface = NUM2ULONG(_interface);
|
384
268
|
|
385
|
-
|
386
|
-
* call-seq:
|
387
|
-
* DNSSD.enumerate_domains!(flags, interface) { |reply| } => service
|
388
|
-
*
|
389
|
-
* Synchronously enumerate domains available for browsing and registration.
|
390
|
-
* For each domain found a DNSSD::Reply object is passed to block with #domain
|
391
|
-
* set to the enumerated domain.
|
392
|
-
*
|
393
|
-
* available_domains = []
|
394
|
-
* timeout(2) do
|
395
|
-
* DNSSD.enumerate_domains! do |r|
|
396
|
-
* available_domains << r.domain
|
397
|
-
* end
|
398
|
-
* rescue TimeoutError
|
399
|
-
* end
|
400
|
-
* puts available_domains.inspect
|
401
|
-
*
|
402
|
-
*/
|
269
|
+
GetDNSSDService(self, client);
|
403
270
|
|
404
|
-
|
405
|
-
|
406
|
-
return dnssd_service_start(
|
407
|
-
sd_enumerate_domains(argc, argv, dnssd_service_alloc(rb_block_proc())));
|
408
|
-
}
|
271
|
+
e = DNSServiceBrowse(client, flags, interface, type, domain,
|
272
|
+
dnssd_service_browse_reply, (void *)self);
|
409
273
|
|
410
|
-
|
411
|
-
* call-seq:
|
412
|
-
* DNSSD.enumerate_domains(flags, interface) {|reply| } => serivce
|
413
|
-
*
|
414
|
-
* Asynchronously enumerate domains available for browsing and registration.
|
415
|
-
* For each domain found a DNSSD::DomainEnumReply object is passed to block.
|
416
|
-
* The returned _service_handle_ can be used to control when to stop
|
417
|
-
* enumerating domains (see DNSSD::Service#stop).
|
418
|
-
*
|
419
|
-
* domains = []
|
420
|
-
*
|
421
|
-
* s = DNSSD.enumerate_domains do |d|
|
422
|
-
* domains << d.domain
|
423
|
-
* end
|
424
|
-
*
|
425
|
-
* sleep(0.2)
|
426
|
-
* s.stop
|
427
|
-
* p domains
|
428
|
-
*/
|
274
|
+
dnssd_check_error_code(e);
|
429
275
|
|
430
|
-
|
431
|
-
dnssd_enumerate_domains(int argc, VALUE * argv, VALUE self) {
|
432
|
-
return dnssd_service_start_in_thread(
|
433
|
-
sd_enumerate_domains(argc, argv, dnssd_service_alloc(rb_block_proc())));
|
276
|
+
return self;
|
434
277
|
}
|
435
278
|
|
436
279
|
static void DNSSD_API
|
437
|
-
|
438
|
-
uint32_t
|
439
|
-
const char *name, const char *type,
|
280
|
+
dnssd_service_enumerate_domains_reply(DNSServiceRef client,
|
281
|
+
DNSServiceFlags flags, uint32_t interface, DNSServiceErrorType e,
|
440
282
|
const char *domain, void *context) {
|
441
|
-
VALUE service;
|
442
|
-
|
283
|
+
VALUE service, reply;
|
284
|
+
|
443
285
|
dnssd_check_error_code(e);
|
286
|
+
|
444
287
|
service = (VALUE)context;
|
445
|
-
|
446
|
-
|
288
|
+
|
289
|
+
reply = reply_new(service, flags);
|
290
|
+
reply_set_interface(reply, interface);
|
291
|
+
rb_ivar_set(reply, dnssd_iv_domain, rb_str_new2(domain));
|
292
|
+
|
293
|
+
dnssd_service_callback(service, reply);
|
447
294
|
}
|
448
295
|
|
449
|
-
|
450
|
-
|
451
|
-
VALUE type, domain, tmp_flags, interface;
|
296
|
+
/* Binding to DNSServiceEnumerateDomains
|
297
|
+
*/
|
452
298
|
|
453
|
-
|
454
|
-
|
299
|
+
static VALUE
|
300
|
+
dnssd_service_enumerate_domains(VALUE self, VALUE _flags, VALUE _interface) {
|
455
301
|
DNSServiceFlags flags = 0;
|
456
|
-
uint32_t
|
302
|
+
uint32_t interface = 0;
|
457
303
|
|
458
304
|
DNSServiceErrorType e;
|
459
305
|
DNSServiceRef *client;
|
460
306
|
|
461
|
-
|
462
|
-
|
307
|
+
if (!NIL_P(_flags))
|
308
|
+
flags = (DNSServiceFlags)NUM2ULONG(_flags);
|
463
309
|
|
464
|
-
|
465
|
-
|
466
|
-
domain_str = dnssd_get_domain(domain);
|
310
|
+
if (!NIL_P(_interface))
|
311
|
+
interface = NUM2ULONG(_interface);
|
467
312
|
|
468
|
-
|
469
|
-
flags = dnssd_to_flags(tmp_flags);
|
313
|
+
GetDNSSDService(self, client);
|
470
314
|
|
471
|
-
|
472
|
-
|
315
|
+
e = DNSServiceEnumerateDomains(client, flags, interface,
|
316
|
+
dnssd_service_enumerate_domains_reply, (void *)self);
|
473
317
|
|
474
|
-
GetDNSSDService(service, client);
|
475
|
-
e = DNSServiceBrowse(client, flags, interface_index, type_str, domain_str,
|
476
|
-
dnssd_browse_reply, (void *)service);
|
477
318
|
dnssd_check_error_code(e);
|
478
|
-
return service;
|
479
|
-
}
|
480
319
|
|
481
|
-
|
482
|
-
* call-seq:
|
483
|
-
* DNSSD.browse!(type, domain, flags, interface) {|reply| } => service
|
484
|
-
*
|
485
|
-
* Synchronously browse for services.
|
486
|
-
*
|
487
|
-
* +domain+ is optional
|
488
|
-
*
|
489
|
-
* +flags+ is 0 by default
|
490
|
-
*
|
491
|
-
* +interface+ is DNSSD::InterfaceAny by default
|
492
|
-
*
|
493
|
-
* For each service found a DNSSD::Reply object is passed to block.
|
494
|
-
*
|
495
|
-
* timeout 6 do
|
496
|
-
* DNSSD.browse! '_http._tcp' do |r|
|
497
|
-
* puts "found: #{r.name}"
|
498
|
-
* end
|
499
|
-
* rescue TimeoutError
|
500
|
-
* end
|
501
|
-
*
|
502
|
-
*/
|
503
|
-
|
504
|
-
static VALUE
|
505
|
-
dnssd_browse_bang(int argc, VALUE * argv, VALUE self) {
|
506
|
-
return dnssd_service_start(
|
507
|
-
sd_browse(argc, argv, dnssd_service_alloc(rb_block_proc())));
|
508
|
-
}
|
509
|
-
|
510
|
-
/*
|
511
|
-
* call-seq:
|
512
|
-
* DNSSD.browse(type, domain, flags, interface) {|reply| } => service
|
513
|
-
*
|
514
|
-
* Asynchronously browse for services.
|
515
|
-
*
|
516
|
-
* +domain+ is optional
|
517
|
-
*
|
518
|
-
* +flags+ is 0 by default
|
519
|
-
*
|
520
|
-
* +interface+ is DNSSD::InterfaceAny by default
|
521
|
-
*
|
522
|
-
* For each service found a DNSSD::BrowseReply object is passed to block.
|
523
|
-
*
|
524
|
-
* The returned service can be used to control when to stop browsing for
|
525
|
-
* services (see DNSSD::Service#stop).
|
526
|
-
*
|
527
|
-
* s = DNSSD.browse '_http._tcp' do |b|
|
528
|
-
* puts "found: #{b.name}"
|
529
|
-
* end
|
530
|
-
*
|
531
|
-
* s.stop
|
532
|
-
*/
|
533
|
-
|
534
|
-
static VALUE
|
535
|
-
dnssd_browse(int argc, VALUE * argv, VALUE self) {
|
536
|
-
return dnssd_service_start_in_thread(
|
537
|
-
sd_browse(argc, argv, dnssd_service_alloc(rb_block_proc())));
|
320
|
+
return self;
|
538
321
|
}
|
539
322
|
|
540
323
|
static void DNSSD_API
|
541
|
-
|
542
|
-
DNSServiceErrorType e,
|
543
|
-
const char *name, const char *regtype,
|
324
|
+
dnssd_service_register_reply(DNSServiceRef client, DNSServiceFlags flags,
|
325
|
+
DNSServiceErrorType e, const char *name, const char *type,
|
544
326
|
const char *domain, void *context) {
|
545
|
-
VALUE service;
|
546
|
-
|
327
|
+
VALUE service, reply;
|
328
|
+
|
547
329
|
dnssd_check_error_code(e);
|
330
|
+
|
548
331
|
service = (VALUE)context;
|
549
|
-
|
550
|
-
|
332
|
+
|
333
|
+
reply = reply_new(service, flags);
|
334
|
+
rb_funcall(reply, rb_intern("set_names"), 3, rb_str_new2(name),
|
335
|
+
rb_str_new2(type), rb_str_new2(domain));
|
336
|
+
|
337
|
+
dnssd_service_callback(service, reply);
|
551
338
|
}
|
552
339
|
|
553
|
-
|
554
|
-
|
555
|
-
VALUE name, type, domain, port, text_record, tmp_flags, interface;
|
340
|
+
/* Binding to DNSServiceRegister
|
341
|
+
*/
|
556
342
|
|
557
|
-
|
558
|
-
|
343
|
+
static VALUE
|
344
|
+
dnssd_service_register(VALUE self, VALUE _name, VALUE _type, VALUE _domain,
|
345
|
+
VALUE _host, VALUE _port, VALUE _text_record, VALUE _flags,
|
346
|
+
VALUE _interface) {
|
347
|
+
const char *name, *type, *host = NULL, *domain = NULL;
|
348
|
+
uint16_t port;
|
559
349
|
uint16_t txt_len = 0;
|
560
350
|
char *txt_rec = NULL;
|
561
351
|
DNSServiceFlags flags = 0;
|
562
|
-
uint32_t
|
352
|
+
uint32_t interface = 0;
|
563
353
|
|
564
354
|
DNSServiceErrorType e;
|
565
355
|
DNSServiceRef *client;
|
566
356
|
|
567
|
-
|
568
|
-
|
357
|
+
name = StringValueCStr(_name);
|
358
|
+
type = StringValueCStr(_type);
|
569
359
|
|
570
|
-
|
571
|
-
|
572
|
-
type_str = StringValueCStr(type);
|
360
|
+
if (!NIL_P(_host))
|
361
|
+
host = StringValueCStr(_host);
|
573
362
|
|
574
|
-
if (!NIL_P(
|
575
|
-
|
363
|
+
if (!NIL_P(_domain))
|
364
|
+
domain = StringValueCStr(_domain);
|
576
365
|
|
577
|
-
|
578
|
-
opaqueport = htons((uint16_t)NUM2UINT(port));
|
366
|
+
port = htons((uint16_t)NUM2UINT(_port));
|
579
367
|
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
txt_rec = RSTRING_PTR(text_record);
|
584
|
-
txt_len = RSTRING_LEN(text_record);
|
368
|
+
if (!NIL_P(_text_record)) {
|
369
|
+
txt_rec = RSTRING_PTR(_text_record);
|
370
|
+
txt_len = RSTRING_LEN(_text_record);
|
585
371
|
}
|
586
372
|
|
587
|
-
if (!NIL_P(
|
588
|
-
flags =
|
373
|
+
if (!NIL_P(_flags))
|
374
|
+
flags = (DNSServiceFlags)NUM2ULONG(_flags);
|
589
375
|
|
590
|
-
if(!NIL_P(
|
591
|
-
|
376
|
+
if (!NIL_P(_interface))
|
377
|
+
interface = NUM2ULONG(_interface);
|
592
378
|
|
593
|
-
GetDNSSDService(
|
379
|
+
GetDNSSDService(self, client);
|
594
380
|
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
rb_iv_set(service, "@text_record", text_record);
|
599
|
-
/********/
|
381
|
+
e = DNSServiceRegister(client, flags, interface, name, type,
|
382
|
+
domain, host, port, txt_len, txt_rec, dnssd_service_register_reply,
|
383
|
+
(void*)self);
|
600
384
|
|
601
|
-
e = DNSServiceRegister(client, flags, interface_index, name_str, type_str,
|
602
|
-
domain_str, NULL, opaqueport, txt_len, txt_rec, dnssd_register_reply,
|
603
|
-
(void*)service);
|
604
385
|
dnssd_check_error_code(e);
|
605
|
-
return service;
|
606
|
-
}
|
607
386
|
|
608
|
-
|
609
|
-
|
610
|
-
* DNSSD.register!(name, type, domain, port, text_record=nil, flags=0, interface=DNSSD::InterfaceAny) {|reply| block } => obj
|
611
|
-
*
|
612
|
-
* Synchronously register a service. A DNSSD::Reply object is passed to the
|
613
|
-
* optional block when the registration completes.
|
614
|
-
*
|
615
|
-
* DNSSD.register! "My Files", "_http._tcp", nil, 8080 do |r|
|
616
|
-
* puts "successfully registered: #{r.inspect}"
|
617
|
-
* end
|
618
|
-
*/
|
387
|
+
return self;
|
388
|
+
}
|
619
389
|
|
620
|
-
static
|
621
|
-
|
622
|
-
|
390
|
+
static void DNSSD_API
|
391
|
+
dnssd_service_resolve_reply(DNSServiceRef client, DNSServiceFlags flags,
|
392
|
+
uint32_t interface, DNSServiceErrorType e, const char *name,
|
393
|
+
const char *target, uint16_t port, uint16_t txt_len,
|
394
|
+
const unsigned char *txt_rec, void *context) {
|
395
|
+
VALUE service, reply, text_record, text_record_str;
|
623
396
|
|
624
|
-
|
625
|
-
block = rb_block_proc();
|
397
|
+
dnssd_check_error_code(e);
|
626
398
|
|
627
|
-
|
628
|
-
sd_register(argc, argv, dnssd_service_alloc(block)));
|
629
|
-
}
|
399
|
+
service = (VALUE)context;
|
630
400
|
|
631
|
-
|
632
|
-
* call-seq:
|
633
|
-
* DNSSD.register(name, type, domain, port, text_record=nil, flags=0, interface=DNSSD::InterfaceAny) { |reply| } => service
|
634
|
-
*
|
635
|
-
* Asynchronously register a service. A DNSSD::Reply object is passed to the
|
636
|
-
* optional block when the registration completes.
|
637
|
-
*
|
638
|
-
* The returned service can be used to control when to stop the service.
|
639
|
-
*
|
640
|
-
* # Start a webserver and register it using DNS Service Discovery
|
641
|
-
* require 'dnssd'
|
642
|
-
* require 'webrick'
|
643
|
-
*
|
644
|
-
* web_s = WEBrick::HTTPServer.new :Port => 8080, :DocumentRoot => Dir.pwd
|
645
|
-
* dns_s = DNSSD.register "My Files", "_http._tcp", nil, 8080 do |r|
|
646
|
-
* warn "successfully registered: #{r.inspect}"
|
647
|
-
* end
|
648
|
-
*
|
649
|
-
* trap "INT" do dns_s.stop; web_s.shutdown end
|
650
|
-
* web_s.start
|
651
|
-
*/
|
401
|
+
reply = reply_new(service, flags);
|
652
402
|
|
653
|
-
|
654
|
-
|
655
|
-
|
403
|
+
reply_set_interface(reply, interface);
|
404
|
+
rb_funcall(reply, rb_intern("set_fullname"), 1, rb_str_new2(name));
|
405
|
+
rb_ivar_set(reply, dnssd_iv_target, rb_str_new2(target));
|
406
|
+
rb_ivar_set(reply, dnssd_iv_port, UINT2NUM(ntohs(port)));
|
656
407
|
|
657
|
-
|
658
|
-
|
408
|
+
text_record_str = rb_str_new((char *)txt_rec, txt_len);
|
409
|
+
text_record = rb_class_new_instance(1, &text_record_str, cDNSSDTextRecord);
|
410
|
+
rb_ivar_set(reply, dnssd_iv_text_record, text_record);
|
659
411
|
|
660
|
-
|
661
|
-
sd_register(argc, argv, dnssd_service_alloc(block)));
|
412
|
+
dnssd_service_callback(service, reply);
|
662
413
|
}
|
663
414
|
|
664
|
-
|
665
|
-
|
666
|
-
uint32_t interface_index, DNSServiceErrorType e,
|
667
|
-
const char *fullname, const char *host_target,
|
668
|
-
uint16_t opaqueport, uint16_t txt_len,
|
669
|
-
const char *txt_rec, void *context) {
|
670
|
-
VALUE service;
|
671
|
-
/* other parameters are undefined if errorCode != 0 */
|
672
|
-
dnssd_check_error_code(e);
|
673
|
-
service = (VALUE)context;
|
674
|
-
dnssd_callback(service,
|
675
|
-
reply_from_resolve(service, flags, interface_index, fullname,
|
676
|
-
host_target, opaqueport, txt_len, txt_rec));
|
677
|
-
}
|
415
|
+
/* Binding to DNSServiceResolve
|
416
|
+
*/
|
678
417
|
|
679
418
|
static VALUE
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
const char *name_str, *type_str, *domain_str;
|
419
|
+
dnssd_service_resolve(VALUE self, VALUE _name, VALUE _type, VALUE _domain,
|
420
|
+
VALUE _flags, VALUE _interface) {
|
421
|
+
const char *name, *type, *domain;
|
684
422
|
DNSServiceFlags flags = 0;
|
685
|
-
uint32_t
|
423
|
+
uint32_t interface = 0;
|
686
424
|
|
687
|
-
DNSServiceErrorType
|
425
|
+
DNSServiceErrorType e;
|
688
426
|
DNSServiceRef *client;
|
689
427
|
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
name_str = StringValueCStr(name);
|
694
|
-
type_str = StringValueCStr(type);
|
695
|
-
domain_str = dnssd_get_domain(domain);
|
428
|
+
name = StringValueCStr(_name);
|
429
|
+
type = StringValueCStr(_type);
|
430
|
+
domain = StringValueCStr(_domain);
|
696
431
|
|
697
|
-
|
698
|
-
|
699
|
-
flags = dnssd_to_flags(tmp_flags);
|
432
|
+
if (!NIL_P(_flags))
|
433
|
+
flags = NUM2ULONG(_flags);
|
700
434
|
|
701
|
-
if (!NIL_P(
|
702
|
-
|
435
|
+
if (!NIL_P(_interface))
|
436
|
+
interface = NUM2ULONG(_interface);
|
703
437
|
|
704
|
-
GetDNSSDService(
|
705
|
-
err = DNSServiceResolve(client, flags, interface_index, name_str, type_str,
|
706
|
-
domain_str, dnssd_resolve_reply, (void *)service);
|
707
|
-
dnssd_check_error_code(err);
|
708
|
-
return service;
|
709
|
-
}
|
710
|
-
|
711
|
-
/*
|
712
|
-
* call-seq:
|
713
|
-
* DNSSD.resolve!(name, type, domain, flags=0, interface=DNSSD::InterfaceAny) {|reply| block } => service
|
714
|
-
*
|
715
|
-
* Synchronously resolve a service discovered via DNSSD.browse().
|
716
|
-
*
|
717
|
-
* The service is resolved to a target host name, port number, and text record
|
718
|
-
* - all contained in the DNSSD::Reply object passed to the required block.
|
719
|
-
*
|
720
|
-
* timeout 2 do
|
721
|
-
* DNSSD.resolve! "foo bar", "_http._tcp", "local" do |r|
|
722
|
-
* p r
|
723
|
-
* end
|
724
|
-
* rescue TimeoutError
|
725
|
-
* end
|
726
|
-
*/
|
438
|
+
GetDNSSDService(self, client);
|
727
439
|
|
728
|
-
|
729
|
-
|
730
|
-
return dnssd_service_start(
|
731
|
-
sd_resolve(argc, argv, dnssd_service_alloc(rb_block_proc())));
|
732
|
-
}
|
440
|
+
e = DNSServiceResolve(client, flags, interface, name, type, domain,
|
441
|
+
dnssd_service_resolve_reply, (void *)self);
|
733
442
|
|
734
|
-
|
735
|
-
* call-seq:
|
736
|
-
* DNSSD.resolve(name, type, domain, flags=0, interface=DNSSD::InterfaceAny) {|reply| } => service
|
737
|
-
*
|
738
|
-
* Asynchronously resolve a service discovered via DNSSD.browse().
|
739
|
-
*
|
740
|
-
* The service is resolved to a target host name, port number, and text record
|
741
|
-
* - all contained in the DNSSD::Reply object passed to the required block.
|
742
|
-
*
|
743
|
-
* The returned service can be used to control when to stop resolving the
|
744
|
-
* service (see DNSSD::Service#stop).
|
745
|
-
*
|
746
|
-
* s = DNSSD.resolve "foo bar", "_http._tcp", "local" do |r|
|
747
|
-
* p r
|
748
|
-
* end
|
749
|
-
* sleep 2
|
750
|
-
* s.stop
|
751
|
-
*/
|
443
|
+
dnssd_check_error_code(e);
|
752
444
|
|
753
|
-
|
754
|
-
dnssd_resolve(int argc, VALUE * argv, VALUE self) {
|
755
|
-
return dnssd_service_start_in_thread(
|
756
|
-
sd_resolve(argc, argv, dnssd_service_alloc(rb_block_proc())));
|
445
|
+
return self;
|
757
446
|
}
|
758
447
|
|
759
448
|
void
|
760
449
|
Init_DNSSD_Service(void) {
|
761
450
|
VALUE mDNSSD = rb_define_module("DNSSD");
|
762
451
|
|
763
|
-
|
764
|
-
|
765
|
-
dnssd_id_to_i = rb_intern("to_i");
|
766
|
-
dnssd_id_to_str = rb_intern("to_str");
|
452
|
+
dnssd_id_join = rb_intern("join");
|
453
|
+
dnssd_id_push = rb_intern("push");
|
767
454
|
|
768
|
-
|
455
|
+
dnssd_iv_continue = rb_intern("@continue");
|
769
456
|
dnssd_iv_domain = rb_intern("@domain");
|
770
457
|
dnssd_iv_interface = rb_intern("@interface");
|
771
458
|
dnssd_iv_port = rb_intern("@port");
|
772
|
-
|
773
|
-
dnssd_iv_service = rb_intern("@service");
|
459
|
+
dnssd_iv_replies = rb_intern("@replies");
|
774
460
|
dnssd_iv_target = rb_intern("@target");
|
775
461
|
dnssd_iv_text_record = rb_intern("@text_record");
|
776
462
|
dnssd_iv_thread = rb_intern("@thread");
|
@@ -779,22 +465,25 @@ Init_DNSSD_Service(void) {
|
|
779
465
|
cDNSSDService = rb_define_class_under(mDNSSD, "Service", rb_cObject);
|
780
466
|
cDNSSDTextRecord = rb_define_class_under(mDNSSD, "TextRecord", rb_cObject);
|
781
467
|
|
782
|
-
|
468
|
+
rb_define_const(cDNSSDService, "MAX_DOMAIN_NAME",
|
469
|
+
ULONG2NUM(kDNSServiceMaxDomainName));
|
470
|
+
rb_define_const(cDNSSDService, "MAX_SERVICE_NAME",
|
471
|
+
ULONG2NUM(kDNSServiceMaxServiceName));
|
472
|
+
|
473
|
+
|
474
|
+
rb_define_alloc_func(cDNSSDService, dnssd_service_s_allocate);
|
783
475
|
rb_define_singleton_method(cDNSSDService, "fullname", dnssd_service_s_fullname, 3);
|
784
476
|
|
477
|
+
rb_define_method(cDNSSDService, "started?", dnssd_service_started_p, 0);
|
478
|
+
|
785
479
|
rb_define_method(cDNSSDService, "stop", dnssd_service_stop, 0);
|
786
480
|
rb_define_method(cDNSSDService, "stopped?", dnssd_service_stopped_p, 0);
|
787
481
|
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
rb_define_module_function(mDNSSD, "enumerate_domains!", dnssd_enumerate_domains_bang, -1);
|
793
|
-
|
794
|
-
rb_define_module_function(mDNSSD, "register", dnssd_register, -1);
|
795
|
-
rb_define_module_function(mDNSSD, "register!", dnssd_register_bang, -1);
|
482
|
+
rb_define_method(cDNSSDService, "_browse", dnssd_service_browse, 4);
|
483
|
+
rb_define_method(cDNSSDService, "_enumerate_domains", dnssd_service_enumerate_domains, 2);
|
484
|
+
rb_define_method(cDNSSDService, "_register", dnssd_service_register, 8);
|
485
|
+
rb_define_method(cDNSSDService, "_resolve", dnssd_service_resolve, 5);
|
796
486
|
|
797
|
-
|
798
|
-
rb_define_module_function(mDNSSD, "resolve!", dnssd_resolve_bang, -1);
|
487
|
+
rb_define_method(cDNSSDService, "_process", dnssd_service_process, 0);
|
799
488
|
}
|
800
489
|
|