dnssd 1.0 → 1.1.0

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,11 +1,3 @@
1
- /*
2
- * Ruby Rendezvous Binding
3
- *
4
- * Copyright (c) 2004 Chad Fowler, Charles Mills, Rich Kilmer
5
- * Licenced under the same terms as Ruby.
6
- * This software has absolutely no warranty.
7
- */
8
-
9
1
  #include "dnssd.h"
10
2
  #include <assert.h>
11
3
 
@@ -14,14 +6,24 @@
14
6
  #define DNSSD_API
15
7
  #endif
16
8
 
9
+ static VALUE cDNSSDReply;
17
10
  static VALUE cDNSSDService;
11
+ static VALUE cDNSSDTextRecord;
12
+
18
13
  static ID dnssd_id_call;
19
- static ID dnssd_id_to_str;
14
+ static ID dnssd_id_encode;
20
15
  static ID dnssd_id_to_i;
16
+ static ID dnssd_id_to_str;
17
+
21
18
  static ID dnssd_iv_block;
22
- static ID dnssd_iv_thread;
19
+ static ID dnssd_iv_domain;
20
+ static ID dnssd_iv_interface;
21
+ static ID dnssd_iv_port;
23
22
  static ID dnssd_iv_result;
24
23
  static ID dnssd_iv_service;
24
+ static ID dnssd_iv_target;
25
+ static ID dnssd_iv_text_record;
26
+ static ID dnssd_iv_thread;
25
27
 
26
28
  #define IsDNSSDService(obj) (rb_obj_is_kind_of(obj,cDNSSDService)==Qtrue)
27
29
  #define GetDNSSDService(obj, var) \
@@ -32,10 +34,131 @@ dnssd_to_flags(VALUE obj) {
32
34
  return (DNSServiceFlags)NUM2ULONG(rb_funcall(obj, dnssd_id_to_i, 0));
33
35
  }
34
36
 
35
- void
37
+ static VALUE
38
+ create_fullname(const char *name, const char *regtype,
39
+ const char *domain) {
40
+ char buffer[kDNSServiceMaxDomainName];
41
+
42
+ if (DNSServiceConstructFullName(buffer, name, regtype, domain)) {
43
+ static const char msg[] = "could not construct full service name";
44
+ rb_raise(rb_eArgError, msg);
45
+ }
46
+
47
+ buffer[kDNSServiceMaxDomainName - 1] = '\000'; /* just in case */
48
+ return rb_str_new2(buffer);
49
+ }
50
+
51
+ /*
52
+ * call-seq:
53
+ * DNSSD::Service.fullname(name, type, domain) => String
54
+ *
55
+ * Concatenate a three-part domain name like DNSSD::Reply#fullname into a
56
+ * properly-escaped full domain name.
57
+ *
58
+ * Any dots or slashes in the +name+ must NOT be escaped.
59
+ *
60
+ * +name+ may be +nil+ (to construct a PTR record name, e.g.
61
+ * "_ftp._tcp.apple.com").
62
+ *
63
+ * The +type+ is the service type followed by the protocol, separated by a dot
64
+ * (e.g. "_ftp._tcp").
65
+ *
66
+ * The +domain+ is the domain name, e.g. "apple.com". Any literal dots or
67
+ * backslashes must be escaped.
68
+ *
69
+ * Raises ArgumentError if the full service name cannot be
70
+ * constructed from the arguments.
71
+ */
72
+
73
+ static VALUE
74
+ dnssd_service_s_fullname(VALUE klass, VALUE name, VALUE type, VALUE domain) {
75
+ return create_fullname(StringValueCStr(name), StringValueCStr(type),
76
+ StringValueCStr(domain));
77
+ }
78
+
79
+ 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
+ }
157
+
158
+ static void
36
159
  dnssd_callback(VALUE service, VALUE reply) {
37
- VALUE result = rb_funcall2( rb_ivar_get(service, dnssd_iv_block),
38
- dnssd_id_call, 1, &reply );
160
+ VALUE result = rb_funcall2(rb_ivar_get(service, dnssd_iv_block),
161
+ dnssd_id_call, 1, &reply);
39
162
  rb_ivar_set(service, dnssd_iv_result, result);
40
163
  }
41
164
 
@@ -58,53 +181,12 @@ dnssd_get_interface_index(VALUE interface) {
58
181
  }
59
182
  }
60
183
 
61
- /*
62
- * call-seq:
63
- * DNSSD::Service.fullname(name, type, domain) => string
64
- *
65
- * Concatenate a three-part domain name (as seen in DNSSD::Reply#fullname())
66
- * into a properly-escaped full domain name.
67
- *
68
- * Any dots or slashes in the _name_ must NOT be escaped.
69
- * May be <code>nil</code> (to construct a PTR record name, e.g. "_ftp._tcp.apple.com").
70
- *
71
- * The _type_ is the service type followed by the protocol, separated by a dot (e.g. "_ftp._tcp").
72
- *
73
- * The _domain_ is the domain name, e.g. "apple.com". Any literal dots or backslashes
74
- * must be escaped.
75
- *
76
- * Raises a <code>ArgumentError</code> if the full service name cannot be constructed from
77
- * the arguments.
78
- */
79
-
80
- static VALUE
81
- dnssd_service_s_fullname(VALUE klass, VALUE name, VALUE type, VALUE domain) {
82
- return dnssd_create_fullname( StringValueCStr(name), StringValueCStr(type),
83
- StringValueCStr(domain), 1 );
84
- }
85
-
86
- /*
87
- * call-seq:
88
- * DNSSD::Service.split(fullname) => array
89
- * DNSSD::Service.split_fullname(fullname) => array
90
- *
91
- * Split a properly escaped multi-part domain name (as seen in DNSSD::Reply#fullname())
92
- * into an array of names.
93
- *
94
- * DNSSD::Service.split('_http._tcp.local.') #=> ["_http.", "_tcp.", "local."]
95
- */
96
-
97
- static VALUE
98
- dnssd_service_s_split(VALUE klass, VALUE fullname) {
99
- return dnssd_split_fullname(fullname);
100
- }
101
-
102
184
  /*
103
185
  * call-seq:
104
186
  * DNSSD::Service.new() => raises a RuntimeError
105
187
  *
106
- * Services can only be instantiated using DNSSD.enumerate_domains(),
107
- * DNSSD.browse(), DNSSD.register(), and DNSSD.resolve().
188
+ * Services can only be instantiated using ::enumerate_domains, ::browse,
189
+ * ::register, and ::resolve.
108
190
  */
109
191
 
110
192
  static VALUE
@@ -142,11 +224,11 @@ dnssd_service_alloc(VALUE block) {
142
224
  * call-seq:
143
225
  * service.stopped? => true or false
144
226
  *
145
- * Returns <code>true</code> if _service_ has been stopped, <code>false</code> otherwise.
227
+ * Returns true if the service has been stopped.
146
228
  */
147
229
 
148
230
  static VALUE
149
- dnssd_service_is_stopped(VALUE service) {
231
+ dnssd_service_stopped_p(VALUE service) {
150
232
  DNSServiceRef *client = (DNSServiceRef*)RDATA(service)->data;
151
233
  return client == NULL ? Qtrue : Qfalse;
152
234
  }
@@ -155,27 +237,31 @@ dnssd_service_is_stopped(VALUE service) {
155
237
  * call-seq:
156
238
  * service.stop => service
157
239
  *
158
- * Stops _service_ closing the underlying socket and killing
159
- * the underlying thread.
160
- *
161
- * It is good practice to all stop running services before exit.
240
+ * Stops the service, closing the underlying socket and killing the underlying
241
+ * thread.
162
242
  *
163
- * service = DNSSD.browse('_http._tcp') do |r|
164
- * # found a service ...
165
- * end
166
- * sleep(2)
167
- * service.stop
243
+ * It is good practice to all stop running services before exit.
168
244
  *
245
+ * service = DNSSD.browse('_http._tcp') do |r|
246
+ * puts "Found #{r.name}"
247
+ * end
248
+ * sleep(2)
249
+ * service.stop
169
250
  */
170
251
 
171
252
  static VALUE
172
253
  dnssd_service_stop(VALUE service) {
173
254
  VALUE thread;
174
255
  DNSServiceRef *client = (DNSServiceRef*)RDATA(service)->data;
256
+
175
257
  /* set to null right away for a bit more thread safety */
176
258
  RDATA(service)->data = NULL;
177
- if (client == NULL) rb_raise(eDNSSDError, "service is already stopped");
259
+
260
+ if (client == NULL)
261
+ rb_raise(eDNSSDError, "service is already stopped");
262
+
178
263
  dnssd_service_free_client(client);
264
+
179
265
  thread = rb_ivar_get(service, dnssd_iv_thread);
180
266
  rb_ivar_set(service, dnssd_iv_block, Qnil);
181
267
  rb_ivar_set(service, dnssd_iv_thread, Qnil);
@@ -184,9 +270,20 @@ dnssd_service_stop(VALUE service) {
184
270
  /* will raise error if thread is not a Ruby Thread */
185
271
  rb_thread_kill(thread);
186
272
  }
273
+
187
274
  return service;
188
275
  }
189
276
 
277
+ /* stop the service only if it is still running */
278
+
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);
285
+ }
286
+
190
287
  static VALUE
191
288
  dnssd_service_process(VALUE service) {
192
289
  int dns_sd_fd, nfds, result;
@@ -195,6 +292,11 @@ dnssd_service_process(VALUE service) {
195
292
  DNSServiceRef *client;
196
293
  GetDNSSDService(service, client);
197
294
 
295
+ if (client == NULL) {
296
+ /* looks like this thread has already been stopped */
297
+ return Qnil;
298
+ }
299
+
198
300
  dns_sd_fd = DNSServiceRefSockFD(*client);
199
301
  nfds = dns_sd_fd + 1;
200
302
  for ( ;; ) {
@@ -205,7 +307,7 @@ dnssd_service_process(VALUE service) {
205
307
  (fd_set *) NULL,
206
308
  (struct timeval *) NULL);
207
309
  if (result > 0) {
208
- if ( FD_ISSET(dns_sd_fd, &readfds) ) {
310
+ if (FD_ISSET(dns_sd_fd, &readfds)) {
209
311
  DNSServiceErrorType e = DNSServiceProcessResult(*client);
210
312
  dnssd_check_error_code(e);
211
313
  }
@@ -213,56 +315,33 @@ dnssd_service_process(VALUE service) {
213
315
  break;
214
316
  }
215
317
  }
318
+
216
319
  /* return the result from the processing */
217
320
  return rb_ivar_get(service, dnssd_iv_result);
218
321
  }
219
322
 
220
- /* stop the service only if it is still running */
221
-
222
- static VALUE
223
- dnssd_service_stop2(VALUE service) {
224
- if (dnssd_service_is_stopped(service)) {
225
- return service;
226
- }
227
- return dnssd_service_stop(service);
228
- }
229
-
230
323
  static VALUE
231
324
  dnssd_service_start(VALUE service) {
232
- return rb_ensure(dnssd_service_process, service, dnssd_service_stop2, service);
325
+ return rb_ensure(dnssd_service_process, service, dnssd_service_stop2,
326
+ service);
233
327
  }
234
328
 
235
329
  static VALUE
236
330
  dnssd_service_start_in_thread(VALUE service) {
237
- /* race condition - service.@block could be called before the service.@thread
238
- * is set and if the block calls service.stop() will raise an error, even though
239
- * the service has been started and is running. */
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. */
334
+
240
335
  VALUE thread = rb_thread_create(dnssd_service_process, (void *)service);
241
336
  rb_ivar_set(service, dnssd_iv_thread, thread);
242
- /* !! IMPORTANT: prevents premature garbage collection of the service,
243
- * this way the thread holds a reference to the service and
244
- * the service gets marked as long as the thread is running.
245
- * Running threads are always marked by Ruby. !! */
246
- rb_ivar_set(thread, dnssd_iv_service, service);
247
- return service;
248
- }
249
337
 
250
- /*
251
- * call-seq:
252
- * service.inspect => string
253
- *
254
- */
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. !! */
255
342
 
256
- static VALUE
257
- dnssd_service_inspect(VALUE self) {
258
- VALUE buf = rb_str_buf_new(32);
259
- rb_str_buf_cat2(buf, "<#");
260
- rb_str_buf_cat2(buf, rb_obj_classname(self));
261
- if (dnssd_service_is_stopped(self)) {
262
- rb_str_buf_cat2(buf, " (stopped)");
263
- }
264
- rb_str_buf_cat2(buf, ">");
265
- return buf;
343
+ rb_ivar_set(thread, dnssd_iv_service, service);
344
+ return service;
266
345
  }
267
346
 
268
347
  static void DNSSD_API
@@ -273,7 +352,8 @@ dnssd_domain_enum_reply(DNSServiceRef sdRef, DNSServiceFlags flags,
273
352
  /* other parameters are undefined if errorCode != 0 */
274
353
  dnssd_check_error_code(e);
275
354
  service = (VALUE)context;
276
- dnssd_callback(service, dnssd_domain_enum_new(service, flags, interface_index, domain));
355
+ dnssd_callback(service,
356
+ reply_from_domain_enum(service, flags, interface_index, domain));
277
357
  }
278
358
 
279
359
  static VALUE
@@ -286,16 +366,17 @@ sd_enumerate_domains(int argc, VALUE *argv, VALUE service) {
286
366
  DNSServiceErrorType e;
287
367
  DNSServiceRef *client;
288
368
 
289
- rb_scan_args (argc, argv, "02", &tmp_flags, &interface);
369
+ rb_scan_args(argc, argv, "02", &tmp_flags, &interface);
290
370
 
291
371
  /* optional parameters */
292
372
  if (!NIL_P(tmp_flags))
293
373
  flags = dnssd_to_flags(tmp_flags);
374
+
294
375
  if (!NIL_P(interface))
295
376
  interface_index = dnssd_get_interface_index(interface);
296
377
 
297
378
  GetDNSSDService(service, client);
298
- e = DNSServiceEnumerateDomains (client, flags, interface_index,
379
+ e = DNSServiceEnumerateDomains(client, flags, interface_index,
299
380
  dnssd_domain_enum_reply, (void *)service);
300
381
  dnssd_check_error_code(e);
301
382
  return service;
@@ -303,7 +384,7 @@ sd_enumerate_domains(int argc, VALUE *argv, VALUE service) {
303
384
 
304
385
  /*
305
386
  * call-seq:
306
- * DNSSD.enumerate_domains!(flags, interface) { |reply| } => obj
387
+ * DNSSD.enumerate_domains!(flags, interface) { |reply| } => service
307
388
  *
308
389
  * Synchronously enumerate domains available for browsing and registration.
309
390
  * For each domain found a DNSSD::Reply object is passed to block with #domain
@@ -321,40 +402,39 @@ sd_enumerate_domains(int argc, VALUE *argv, VALUE service) {
321
402
  */
322
403
 
323
404
  static VALUE
324
- dnssd_enumerate_domains_bang (int argc, VALUE * argv, VALUE self) {
405
+ dnssd_enumerate_domains_bang(int argc, VALUE * argv, VALUE self) {
325
406
  return dnssd_service_start(
326
- sd_enumerate_domains(argc, argv, dnssd_service_alloc(rb_block_proc()))
327
- );
407
+ sd_enumerate_domains(argc, argv, dnssd_service_alloc(rb_block_proc())));
328
408
  }
329
409
 
330
410
  /*
331
411
  * call-seq:
332
- * DNSSD.enumerate_domains(flags=0, interface=DNSSD::InterfaceAny) {|reply| bloc } => serivce_handle
412
+ * DNSSD.enumerate_domains(flags, interface) {|reply| } => serivce
333
413
  *
334
414
  * Asynchronously enumerate domains available for browsing and registration.
335
415
  * For each domain found a DNSSD::DomainEnumReply object is passed to block.
336
- * The returned _service_handle_ can be used to control when to
337
- * stop enumerating domains (see DNSSD::Service#stop).
338
- *
339
- * available_domains = []
340
- * s = DNSSD.enumerate_domains do |d|
341
- * available_domains << d.domain
342
- * end
343
- * sleep(0.2)
344
- * s.stop
345
- * puts available_domains.inspect
346
- *
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
347
428
  */
348
429
 
349
430
  static VALUE
350
431
  dnssd_enumerate_domains(int argc, VALUE * argv, VALUE self) {
351
432
  return dnssd_service_start_in_thread(
352
- sd_enumerate_domains(argc, argv, dnssd_service_alloc(rb_block_proc()))
353
- );
433
+ sd_enumerate_domains(argc, argv, dnssd_service_alloc(rb_block_proc())));
354
434
  }
355
435
 
356
436
  static void DNSSD_API
357
- dnssd_browse_reply (DNSServiceRef client, DNSServiceFlags flags,
437
+ dnssd_browse_reply(DNSServiceRef client, DNSServiceFlags flags,
358
438
  uint32_t interface_index, DNSServiceErrorType e,
359
439
  const char *name, const char *type,
360
440
  const char *domain, void *context) {
@@ -363,8 +443,7 @@ dnssd_browse_reply (DNSServiceRef client, DNSServiceFlags flags,
363
443
  dnssd_check_error_code(e);
364
444
  service = (VALUE)context;
365
445
  dnssd_callback(service,
366
- dnssd_browse_new (service, flags, interface_index, name, type, domain)
367
- );
446
+ reply_from_browse(service, flags, interface_index, name, type, domain));
368
447
  }
369
448
 
370
449
  static VALUE
@@ -379,21 +458,21 @@ sd_browse(int argc, VALUE *argv, VALUE service) {
379
458
  DNSServiceErrorType e;
380
459
  DNSServiceRef *client;
381
460
 
382
- rb_scan_args (argc, argv, "13", &type,
383
- &domain, &tmp_flags, &interface);
461
+ rb_scan_args(argc, argv, "13", &type, &domain, &tmp_flags, &interface);
384
462
  type_str = StringValueCStr(type);
385
463
 
386
464
  /* optional parameters */
387
465
  if (!NIL_P(domain))
388
466
  domain_str = dnssd_get_domain(domain);
467
+
389
468
  if (!NIL_P(tmp_flags))
390
469
  flags = dnssd_to_flags(tmp_flags);
470
+
391
471
  if (!NIL_P(interface))
392
472
  interface_index = dnssd_get_interface_index(interface);
393
473
 
394
474
  GetDNSSDService(service, client);
395
- e = DNSServiceBrowse (client, flags, interface_index,
396
- type_str, domain_str,
475
+ e = DNSServiceBrowse(client, flags, interface_index, type_str, domain_str,
397
476
  dnssd_browse_reply, (void *)service);
398
477
  dnssd_check_error_code(e);
399
478
  return service;
@@ -401,51 +480,65 @@ sd_browse(int argc, VALUE *argv, VALUE service) {
401
480
 
402
481
  /*
403
482
  * call-seq:
404
- * DNSSD.browse!(type, domain=nil, flags=0, interface=DNSSD::InterfaceAny) {|reply| block } => obj
483
+ * DNSSD.browse!(type, domain, flags, interface) {|reply| } => service
405
484
  *
406
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
+ *
407
493
  * For each service found a DNSSD::Reply object is passed to block.
408
494
  *
409
- * timeout(6) do
410
- * DNSSD.browse!('_http._tcp') do |r|
411
- * puts "found: #{r.inspect}"
412
- * end
413
- * rescue TimeoutError
414
- * end
495
+ * timeout 6 do
496
+ * DNSSD.browse! '_http._tcp' do |r|
497
+ * puts "found: #{r.name}"
498
+ * end
499
+ * rescue TimeoutError
500
+ * end
415
501
  *
416
502
  */
417
503
 
418
504
  static VALUE
419
505
  dnssd_browse_bang(int argc, VALUE * argv, VALUE self) {
420
506
  return dnssd_service_start(
421
- sd_browse(argc, argv, dnssd_service_alloc(rb_block_proc()))
422
- );
507
+ sd_browse(argc, argv, dnssd_service_alloc(rb_block_proc())));
423
508
  }
424
509
 
425
510
  /*
426
511
  * call-seq:
427
- * DNSSD.browse(type, domain=nil, flags=0, interface=DNSSD::InterfaceAny) {|reply| block } => service_handle
512
+ * DNSSD.browse(type, domain, flags, interface) {|reply| } => service
428
513
  *
429
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
+ *
430
522
  * For each service found a DNSSD::BrowseReply object is passed to block.
431
- * The returned _service_handle_ can be used to control when to
432
- * stop browsing for services (see DNSSD::Service#stop).
433
523
  *
434
- * s = DNSSD.browse('_http._tcp') do |b|
435
- * puts "found: #{b.inspect}"
436
- * end
524
+ * The returned service can be used to control when to stop browsing for
525
+ * services (see DNSSD::Service#stop).
437
526
  *
527
+ * s = DNSSD.browse '_http._tcp' do |b|
528
+ * puts "found: #{b.name}"
529
+ * end
530
+ *
531
+ * s.stop
438
532
  */
439
533
 
440
534
  static VALUE
441
535
  dnssd_browse(int argc, VALUE * argv, VALUE self) {
442
536
  return dnssd_service_start_in_thread(
443
- sd_browse(argc, argv, dnssd_service_alloc(rb_block_proc()))
444
- );
537
+ sd_browse(argc, argv, dnssd_service_alloc(rb_block_proc())));
445
538
  }
446
539
 
447
540
  static void DNSSD_API
448
- dnssd_register_reply (DNSServiceRef client, DNSServiceFlags flags,
541
+ dnssd_register_reply(DNSServiceRef client, DNSServiceFlags flags,
449
542
  DNSServiceErrorType e,
450
543
  const char *name, const char *regtype,
451
544
  const char *domain, void *context) {
@@ -453,13 +546,13 @@ dnssd_register_reply (DNSServiceRef client, DNSServiceFlags flags,
453
546
  /* other parameters are undefined if errorCode != 0 */
454
547
  dnssd_check_error_code(e);
455
548
  service = (VALUE)context;
456
- dnssd_callback(service, dnssd_register_new(service, flags, name, regtype, domain));
549
+ dnssd_callback(service,
550
+ reply_from_register(service, flags, name, regtype, domain));
457
551
  }
458
552
 
459
553
  static VALUE
460
554
  sd_register(int argc, VALUE *argv, VALUE service) {
461
- VALUE name, type, domain, port,
462
- text_record, tmp_flags, interface;
555
+ VALUE name, type, domain, port, text_record, tmp_flags, interface;
463
556
 
464
557
  const char *name_str, *type_str, *domain_str = NULL;
465
558
  uint16_t opaqueport;
@@ -471,8 +564,7 @@ sd_register(int argc, VALUE *argv, VALUE service) {
471
564
  DNSServiceErrorType e;
472
565
  DNSServiceRef *client;
473
566
 
474
- rb_scan_args (argc, argv, "43",
475
- &name, &type, &domain, &port,
567
+ rb_scan_args(argc, argv, "43", &name, &type, &domain, &port,
476
568
  &text_record, &tmp_flags, &interface);
477
569
 
478
570
  /* required parameters */
@@ -481,17 +573,20 @@ sd_register(int argc, VALUE *argv, VALUE service) {
481
573
 
482
574
  if (!NIL_P(domain))
483
575
  domain_str = dnssd_get_domain(domain);
576
+
484
577
  /* convert from host to net byte order */
485
578
  opaqueport = htons((uint16_t)NUM2UINT(port));
486
579
 
487
580
  /* optional parameters */
488
581
  if (!NIL_P(text_record)) {
489
- text_record = dnssd_tr_to_encoded_str(text_record);
582
+ text_record = rb_funcall(text_record, dnssd_id_encode, 0);
490
583
  txt_rec = RSTRING_PTR(text_record);
491
584
  txt_len = RSTRING_LEN(text_record);
492
585
  }
586
+
493
587
  if (!NIL_P(tmp_flags))
494
588
  flags = dnssd_to_flags(tmp_flags);
589
+
495
590
  if(!NIL_P(interface))
496
591
  interface_index = dnssd_get_interface_index(interface);
497
592
 
@@ -502,10 +597,10 @@ sd_register(int argc, VALUE *argv, VALUE service) {
502
597
  rb_iv_set(service, "@port", port);
503
598
  rb_iv_set(service, "@text_record", text_record);
504
599
  /********/
505
- e = DNSServiceRegister (client, flags, interface_index,
506
- name_str, type_str, domain_str,
507
- NULL, opaqueport, txt_len, txt_rec,
508
- dnssd_register_reply, (void*)service );
600
+
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);
509
604
  dnssd_check_error_code(e);
510
605
  return service;
511
606
  }
@@ -514,54 +609,60 @@ sd_register(int argc, VALUE *argv, VALUE service) {
514
609
  * call-seq:
515
610
  * DNSSD.register!(name, type, domain, port, text_record=nil, flags=0, interface=DNSSD::InterfaceAny) {|reply| block } => obj
516
611
  *
517
- * Synchronously register a service. A DNSSD::Reply object is passed
518
- * to the block when the registration completes.
519
- *
520
- * DNSSD.register!("My Files", "_http._tcp", nil, 8080) do |r|
521
- * warn("successfully registered: #{r.inspect}")
522
- * end
612
+ * Synchronously register a service. A DNSSD::Reply object is passed to the
613
+ * optional block when the registration completes.
523
614
  *
615
+ * DNSSD.register! "My Files", "_http._tcp", nil, 8080 do |r|
616
+ * puts "successfully registered: #{r.inspect}"
617
+ * end
524
618
  */
525
619
 
526
620
  static VALUE
527
621
  dnssd_register_bang(int argc, VALUE * argv, VALUE self) {
622
+ VALUE block = Qnil;
623
+
624
+ if (rb_block_given_p())
625
+ block = rb_block_proc();
626
+
528
627
  return dnssd_service_start(
529
- sd_register(argc, argv, dnssd_service_alloc(rb_block_proc()))
530
- );
628
+ sd_register(argc, argv, dnssd_service_alloc(block)));
531
629
  }
532
630
 
533
631
  /*
534
632
  * call-seq:
535
- * DNSSD.register(name, type, domain, port, text_record=nil, flags=0, interface=DNSSD::InterfaceAny) {|reply| block } => service_handle
536
- *
537
- * Asynchronously register a service. A DNSSD::Reply object is
538
- * passed to the block when the registration completes.
539
- * The returned _service_handle_ can be used to control when to
540
- * stop the service (see DNSSD::Service#stop).
541
- *
542
- * # Start a webserver and register it using DNS Service Discovery
543
- * require 'dnssd'
544
- * require 'webrick'
545
- *
546
- * web_s = WEBrick::HTTPServer.new(:Port=>8080, :DocumentRoot=>Dir::pwd)
547
- * dns_s = DNSSD.register("My Files", "_http._tcp", nil, 8080) do |r|
548
- * warn("successfully registered: #{r.inspect}")
549
- * end
550
- *
551
- * trap("INT"){ dns_s.stop; web_s.shutdown }
552
- * web_s.start
553
- *
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
554
651
  */
555
652
 
556
653
  static VALUE
557
654
  dnssd_register(int argc, VALUE * argv, VALUE self) {
655
+ VALUE block = Qnil;
656
+
657
+ if (rb_block_given_p())
658
+ block = rb_block_proc();
659
+
558
660
  return dnssd_service_start_in_thread(
559
- sd_register(argc, argv, dnssd_service_alloc(rb_block_proc()))
560
- );
661
+ sd_register(argc, argv, dnssd_service_alloc(block)));
561
662
  }
562
663
 
563
664
  static void DNSSD_API
564
- dnssd_resolve_reply (DNSServiceRef client, DNSServiceFlags flags,
665
+ dnssd_resolve_reply(DNSServiceRef client, DNSServiceFlags flags,
565
666
  uint32_t interface_index, DNSServiceErrorType e,
566
667
  const char *fullname, const char *host_target,
567
668
  uint16_t opaqueport, uint16_t txt_len,
@@ -571,9 +672,8 @@ dnssd_resolve_reply (DNSServiceRef client, DNSServiceFlags flags,
571
672
  dnssd_check_error_code(e);
572
673
  service = (VALUE)context;
573
674
  dnssd_callback(service,
574
- dnssd_resolve_new(service, flags, interface_index, fullname,
575
- host_target, opaqueport, txt_len, txt_rec)
576
- );
675
+ reply_from_resolve(service, flags, interface_index, fullname,
676
+ host_target, opaqueport, txt_len, txt_rec));
577
677
  }
578
678
 
579
679
  static VALUE
@@ -590,18 +690,19 @@ sd_resolve(int argc, VALUE *argv, VALUE service) {
590
690
  rb_scan_args(argc, argv, "32", &name, &type, &domain, &tmp_flags, &interface);
591
691
 
592
692
  /* required parameters */
593
- name_str = StringValueCStr(name),
594
- type_str = StringValueCStr(type),
595
- domain_str = dnssd_get_domain(domain);
693
+ name_str = StringValueCStr(name);
694
+ type_str = StringValueCStr(type);
695
+ domain_str = dnssd_get_domain(domain);
596
696
 
597
697
  /* optional parameters */
598
698
  if (!NIL_P(tmp_flags))
599
699
  flags = dnssd_to_flags(tmp_flags);
700
+
600
701
  if (!NIL_P(interface))
601
702
  interface_index = dnssd_get_interface_index(interface);
602
703
 
603
704
  GetDNSSDService(service, client);
604
- err = DNSServiceResolve (client, flags, interface_index, name_str, type_str,
705
+ err = DNSServiceResolve(client, flags, interface_index, name_str, type_str,
605
706
  domain_str, dnssd_resolve_reply, (void *)service);
606
707
  dnssd_check_error_code(err);
607
708
  return service;
@@ -609,90 +710,91 @@ sd_resolve(int argc, VALUE *argv, VALUE service) {
609
710
 
610
711
  /*
611
712
  * call-seq:
612
- * DNSSD.resolve!(name, type, domain, flags=0, interface=DNSSD::InterfaceAny) {|reply| block } => obj
713
+ * DNSSD.resolve!(name, type, domain, flags=0, interface=DNSSD::InterfaceAny) {|reply| block } => service
613
714
  *
614
715
  * Synchronously resolve a service discovered via DNSSD.browse().
615
- * The service is resolved to a target host name, port number, and
616
- * text record - all contained in the DNSSD::Reply object
617
- * passed to the required block.
618
716
  *
619
- * timeout(2) do
620
- * DNSSD.resolve!("foo bar", "_http._tcp", "local") do |r|
621
- * puts r.inspect
622
- * end
623
- * rescue TimeoutError
624
- * end
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.
625
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
626
726
  */
627
727
 
628
728
  static VALUE
629
729
  dnssd_resolve_bang(int argc, VALUE * argv, VALUE self) {
630
730
  return dnssd_service_start(
631
- sd_resolve(argc, argv, dnssd_service_alloc(rb_block_proc()))
632
- );
731
+ sd_resolve(argc, argv, dnssd_service_alloc(rb_block_proc())));
633
732
  }
634
733
 
635
734
  /*
636
735
  * call-seq:
637
- * DNSSD.resolve(name, type, domain, flags=0, interface=DNSSD::InterfaceAny) {|reply| block } => service_handle
736
+ * DNSSD.resolve(name, type, domain, flags=0, interface=DNSSD::InterfaceAny) {|reply| } => service
638
737
  *
639
738
  * Asynchronously resolve a service discovered via DNSSD.browse().
640
- * The service is resolved to a target host name, port number, and
641
- * text record - all contained in the DNSSD::Reply object
642
- * passed to the required block.
643
- * The returned _service_handle_ can be used to control when to
644
- * stop resolving the service (see DNSSD::Service#stop).
645
- *
646
- * s = DNSSD.resolve("foo bar", "_http._tcp", "local") do |r|
647
- * puts r.inspect
648
- * end
649
- * sleep(2)
650
- * s.stop
651
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
652
751
  */
653
752
 
654
753
  static VALUE
655
754
  dnssd_resolve(int argc, VALUE * argv, VALUE self) {
656
755
  return dnssd_service_start_in_thread(
657
- sd_resolve(argc, argv, dnssd_service_alloc(rb_block_proc()))
658
- );
756
+ sd_resolve(argc, argv, dnssd_service_alloc(rb_block_proc())));
659
757
  }
660
758
 
661
759
  void
662
760
  Init_DNSSD_Service(void) {
663
- /* hack so rdoc documents the project correctly */
664
- #ifdef mDNSSD_RDOC_HACK
665
- mDNSSD = rb_define_module("DNSSD");
666
- #endif
667
- dnssd_id_call = rb_intern("call");
668
- dnssd_id_to_str = rb_intern("to_str");
669
- dnssd_id_to_i = rb_intern("to_i");
670
- dnssd_iv_block = rb_intern("@block");
671
- dnssd_iv_thread = rb_intern("@thread");
672
- dnssd_iv_result = rb_intern("@result");
673
- dnssd_iv_service = rb_intern("@service");
674
-
675
- cDNSSDService = rb_define_class_under(mDNSSD, "Service", rb_cObject);
761
+ VALUE mDNSSD = rb_define_module("DNSSD");
762
+
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");
767
+
768
+ dnssd_iv_block = rb_intern("@block");
769
+ dnssd_iv_domain = rb_intern("@domain");
770
+ dnssd_iv_interface = rb_intern("@interface");
771
+ dnssd_iv_port = rb_intern("@port");
772
+ dnssd_iv_result = rb_intern("@result");
773
+ dnssd_iv_service = rb_intern("@service");
774
+ dnssd_iv_target = rb_intern("@target");
775
+ dnssd_iv_text_record = rb_intern("@text_record");
776
+ dnssd_iv_thread = rb_intern("@thread");
777
+
778
+ cDNSSDReply = rb_define_class_under(mDNSSD, "Reply", rb_cObject);
779
+ cDNSSDService = rb_define_class_under(mDNSSD, "Service", rb_cObject);
780
+ cDNSSDTextRecord = rb_define_class_under(mDNSSD, "TextRecord", rb_cObject);
676
781
 
677
782
  rb_define_singleton_method(cDNSSDService, "new", dnssd_service_new, -1);
678
783
  rb_define_singleton_method(cDNSSDService, "fullname", dnssd_service_s_fullname, 3);
679
- rb_define_singleton_method(cDNSSDService, "split_fullname", dnssd_service_s_split, 1);
680
- rb_define_singleton_method(cDNSSDService, "split", dnssd_service_s_split, 1);
681
-
682
- /* Access the services underlying thread. Returns nil if the service is synchronous. */
683
- rb_define_attr(cDNSSDService, "thread", 1, 0);
684
784
 
685
785
  rb_define_method(cDNSSDService, "stop", dnssd_service_stop, 0);
686
- rb_define_method(cDNSSDService, "stopped?", dnssd_service_is_stopped, 0);
687
- rb_define_method(cDNSSDService, "inspect", dnssd_service_inspect, 0);
786
+ rb_define_method(cDNSSDService, "stopped?", dnssd_service_stopped_p, 0);
688
787
 
689
- rb_define_module_function(mDNSSD, "enumerate_domains", dnssd_enumerate_domains, -1);
690
- rb_define_module_function(mDNSSD, "enumerate_domains!", dnssd_enumerate_domains_bang, -1);
691
788
  rb_define_module_function(mDNSSD, "browse", dnssd_browse, -1);
692
789
  rb_define_module_function(mDNSSD, "browse!", dnssd_browse_bang, -1);
693
- rb_define_module_function(mDNSSD, "resolve", dnssd_resolve, -1);
694
- rb_define_module_function(mDNSSD, "resolve!", dnssd_resolve_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
+
695
794
  rb_define_module_function(mDNSSD, "register", dnssd_register, -1);
696
795
  rb_define_module_function(mDNSSD, "register!", dnssd_register_bang, -1);
796
+
797
+ rb_define_module_function(mDNSSD, "resolve", dnssd_resolve, -1);
798
+ rb_define_module_function(mDNSSD, "resolve!", dnssd_resolve_bang, -1);
697
799
  }
698
800