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.
@@ -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 dnssd_id_call;
14
- static ID dnssd_id_encode;
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 dnssd_iv_block;
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 dnssd_iv_result;
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
- #define IsDNSSDService(obj) (rb_obj_is_kind_of(obj,cDNSSDService)==Qtrue)
24
+ /* HACK why is this a macro */
29
25
  #define GetDNSSDService(obj, var) \
30
- do { assert(IsDNSSDService(obj)); Data_Get_Struct(obj, DNSServiceRef, var); } while (0)
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 DNSServiceFlags
33
- dnssd_to_flags(VALUE obj) {
34
- return (DNSServiceFlags)NUM2ULONG(rb_funcall(obj, dnssd_id_to_i, 0));
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
- text_record_new(VALUE text_record) {
81
- return rb_funcall(cDNSSDTextRecord, rb_intern("new"), 1, text_record);
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
- static void
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
- static const char *
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
- * DNSSD::Service.new() => raises a RuntimeError
133
+ * service.started? => true or false
187
134
  *
188
- * Services can only be instantiated using ::enumerate_domains, ::browse,
189
- * ::register, and ::resolve.
135
+ * Returns true if the service has been started.
190
136
  */
191
137
 
192
138
  static VALUE
193
- dnssd_service_new(int argc, VALUE *argv, VALUE klass) {
194
- dnssd_instantiation_error(rb_class2name(klass));
195
- return Qnil;
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
- static VALUE
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
- return client == NULL ? Qtrue : Qfalse;
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 service) {
181
+ dnssd_service_stop(VALUE self) {
254
182
  VALUE thread;
255
- DNSServiceRef *client = (DNSServiceRef*)RDATA(service)->data;
183
+ DNSServiceRef *client = (DNSServiceRef*)RDATA(self)->data;
256
184
 
257
185
  /* set to null right away for a bit more thread safety */
258
- RDATA(service)->data = NULL;
186
+ RDATA(self)->data = NULL;
259
187
 
260
188
  if (client == NULL)
261
189
  rb_raise(eDNSSDError, "service is already stopped");
262
190
 
263
- dnssd_service_free_client(client);
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
- /* will raise error if thread is not a Ruby Thread */
271
- rb_thread_kill(thread);
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
- return service;
275
- }
276
-
277
- /* stop the service only if it is still running */
199
+ dnssd_service_free_client(client);
278
200
 
279
- static VALUE
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 service) {
289
- int dns_sd_fd, nfds, result;
290
- fd_set readfds;
291
-
205
+ dnssd_service_process(VALUE self) {
292
206
  DNSServiceRef *client;
293
- GetDNSSDService(service, client);
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
- dns_sd_fd = DNSServiceRefSockFD(*client);
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
- VALUE thread = rb_thread_create(dnssd_service_process, (void *)service);
336
- rb_ivar_set(service, dnssd_iv_thread, thread);
217
+ if (rb_ivar_get(self, dnssd_iv_continue) == Qfalse)
218
+ return Qnil;
337
219
 
338
- /* !! IMPORTANT: prevents premature garbage collection of the service, this
339
- * way the thread holds a reference to the service and the service gets
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
- rb_ivar_set(thread, dnssd_iv_service, service);
344
- return service;
223
+ return self;
345
224
  }
346
225
 
347
226
  static void DNSSD_API
348
- dnssd_domain_enum_reply(DNSServiceRef sdRef, DNSServiceFlags flags,
349
- uint32_t interface_index, DNSServiceErrorType e,
350
- const char *domain, void *context) {
351
- VALUE service;
352
- /* other parameters are undefined if errorCode != 0 */
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
- dnssd_callback(service,
356
- reply_from_domain_enum(service, flags, interface_index, domain));
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
- static VALUE
360
- sd_enumerate_domains(int argc, VALUE *argv, VALUE service) {
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 interface_index = 0;
253
+ uint32_t interface = 0;
365
254
 
366
255
  DNSServiceErrorType e;
367
256
  DNSServiceRef *client;
368
257
 
369
- rb_scan_args(argc, argv, "02", &tmp_flags, &interface);
258
+ type = StringValueCStr(_type);
370
259
 
371
- /* optional parameters */
372
- if (!NIL_P(tmp_flags))
373
- flags = dnssd_to_flags(tmp_flags);
260
+ if (!NIL_P(_domain))
261
+ domain = StringValueCStr(_domain);
374
262
 
375
- if (!NIL_P(interface))
376
- interface_index = dnssd_get_interface_index(interface);
263
+ if (!NIL_P(_flags))
264
+ flags = (DNSServiceFlags)NUM2ULONG(_flags);
377
265
 
378
- GetDNSSDService(service, client);
379
- e = DNSServiceEnumerateDomains(client, flags, interface_index,
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
- static VALUE
405
- dnssd_enumerate_domains_bang(int argc, VALUE * argv, VALUE self) {
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
- static VALUE
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
- dnssd_browse_reply(DNSServiceRef client, DNSServiceFlags flags,
438
- uint32_t interface_index, DNSServiceErrorType e,
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
- /* other parameters are undefined if errorCode != 0 */
283
+ VALUE service, reply;
284
+
443
285
  dnssd_check_error_code(e);
286
+
444
287
  service = (VALUE)context;
445
- dnssd_callback(service,
446
- reply_from_browse(service, flags, interface_index, name, type, domain));
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
- static VALUE
450
- sd_browse(int argc, VALUE *argv, VALUE service) {
451
- VALUE type, domain, tmp_flags, interface;
296
+ /* Binding to DNSServiceEnumerateDomains
297
+ */
452
298
 
453
- const char *type_str;
454
- const char *domain_str = NULL;
299
+ static VALUE
300
+ dnssd_service_enumerate_domains(VALUE self, VALUE _flags, VALUE _interface) {
455
301
  DNSServiceFlags flags = 0;
456
- uint32_t interface_index = 0;
302
+ uint32_t interface = 0;
457
303
 
458
304
  DNSServiceErrorType e;
459
305
  DNSServiceRef *client;
460
306
 
461
- rb_scan_args(argc, argv, "13", &type, &domain, &tmp_flags, &interface);
462
- type_str = StringValueCStr(type);
307
+ if (!NIL_P(_flags))
308
+ flags = (DNSServiceFlags)NUM2ULONG(_flags);
463
309
 
464
- /* optional parameters */
465
- if (!NIL_P(domain))
466
- domain_str = dnssd_get_domain(domain);
310
+ if (!NIL_P(_interface))
311
+ interface = NUM2ULONG(_interface);
467
312
 
468
- if (!NIL_P(tmp_flags))
469
- flags = dnssd_to_flags(tmp_flags);
313
+ GetDNSSDService(self, client);
470
314
 
471
- if (!NIL_P(interface))
472
- interface_index = dnssd_get_interface_index(interface);
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
- dnssd_register_reply(DNSServiceRef client, DNSServiceFlags flags,
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
- /* other parameters are undefined if errorCode != 0 */
327
+ VALUE service, reply;
328
+
547
329
  dnssd_check_error_code(e);
330
+
548
331
  service = (VALUE)context;
549
- dnssd_callback(service,
550
- reply_from_register(service, flags, name, regtype, domain));
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
- static VALUE
554
- sd_register(int argc, VALUE *argv, VALUE service) {
555
- VALUE name, type, domain, port, text_record, tmp_flags, interface;
340
+ /* Binding to DNSServiceRegister
341
+ */
556
342
 
557
- const char *name_str, *type_str, *domain_str = NULL;
558
- uint16_t opaqueport;
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 interface_index = 0;
352
+ uint32_t interface = 0;
563
353
 
564
354
  DNSServiceErrorType e;
565
355
  DNSServiceRef *client;
566
356
 
567
- rb_scan_args(argc, argv, "43", &name, &type, &domain, &port,
568
- &text_record, &tmp_flags, &interface);
357
+ name = StringValueCStr(_name);
358
+ type = StringValueCStr(_type);
569
359
 
570
- /* required parameters */
571
- name_str = StringValueCStr(name);
572
- type_str = StringValueCStr(type);
360
+ if (!NIL_P(_host))
361
+ host = StringValueCStr(_host);
573
362
 
574
- if (!NIL_P(domain))
575
- domain_str = dnssd_get_domain(domain);
363
+ if (!NIL_P(_domain))
364
+ domain = StringValueCStr(_domain);
576
365
 
577
- /* convert from host to net byte order */
578
- opaqueport = htons((uint16_t)NUM2UINT(port));
366
+ port = htons((uint16_t)NUM2UINT(_port));
579
367
 
580
- /* optional parameters */
581
- if (!NIL_P(text_record)) {
582
- text_record = rb_funcall(text_record, dnssd_id_encode, 0);
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(tmp_flags))
588
- flags = dnssd_to_flags(tmp_flags);
373
+ if (!NIL_P(_flags))
374
+ flags = (DNSServiceFlags)NUM2ULONG(_flags);
589
375
 
590
- if(!NIL_P(interface))
591
- interface_index = dnssd_get_interface_index(interface);
376
+ if (!NIL_P(_interface))
377
+ interface = NUM2ULONG(_interface);
592
378
 
593
- GetDNSSDService(service, client);
379
+ GetDNSSDService(self, client);
594
380
 
595
- /* HACK */
596
- rb_iv_set(service, "@interface", interface);
597
- rb_iv_set(service, "@port", port);
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
- * call-seq:
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 VALUE
621
- dnssd_register_bang(int argc, VALUE * argv, VALUE self) {
622
- VALUE block = Qnil;
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
- if (rb_block_given_p())
625
- block = rb_block_proc();
397
+ dnssd_check_error_code(e);
626
398
 
627
- return dnssd_service_start(
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
- static VALUE
654
- dnssd_register(int argc, VALUE * argv, VALUE self) {
655
- VALUE block = Qnil;
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
- if (rb_block_given_p())
658
- block = rb_block_proc();
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
- return dnssd_service_start_in_thread(
661
- sd_register(argc, argv, dnssd_service_alloc(block)));
412
+ dnssd_service_callback(service, reply);
662
413
  }
663
414
 
664
- static void DNSSD_API
665
- dnssd_resolve_reply(DNSServiceRef client, DNSServiceFlags flags,
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
- sd_resolve(int argc, VALUE *argv, VALUE service) {
681
- VALUE name, type, domain, tmp_flags, interface;
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 interface_index = 0;
423
+ uint32_t interface = 0;
686
424
 
687
- DNSServiceErrorType err;
425
+ DNSServiceErrorType e;
688
426
  DNSServiceRef *client;
689
427
 
690
- rb_scan_args(argc, argv, "32", &name, &type, &domain, &tmp_flags, &interface);
691
-
692
- /* required parameters */
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
- /* optional parameters */
698
- if (!NIL_P(tmp_flags))
699
- flags = dnssd_to_flags(tmp_flags);
432
+ if (!NIL_P(_flags))
433
+ flags = NUM2ULONG(_flags);
700
434
 
701
- if (!NIL_P(interface))
702
- interface_index = dnssd_get_interface_index(interface);
435
+ if (!NIL_P(_interface))
436
+ interface = NUM2ULONG(_interface);
703
437
 
704
- GetDNSSDService(service, client);
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
- static VALUE
729
- dnssd_resolve_bang(int argc, VALUE * argv, VALUE self) {
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
- static VALUE
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
- dnssd_id_call = rb_intern("call");
764
- dnssd_id_encode = rb_intern("encode");
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
- dnssd_iv_block = rb_intern("@block");
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
- dnssd_iv_result = rb_intern("@result");
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
- rb_define_singleton_method(cDNSSDService, "new", dnssd_service_new, -1);
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
- rb_define_module_function(mDNSSD, "browse", dnssd_browse, -1);
789
- rb_define_module_function(mDNSSD, "browse!", dnssd_browse_bang, -1);
790
-
791
- rb_define_module_function(mDNSSD, "enumerate_domains", dnssd_enumerate_domains, -1);
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
- rb_define_module_function(mDNSSD, "resolve", dnssd_resolve, -1);
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