radar-dnssd 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,711 @@
1
+ /*
2
+ * Copyright (c) 2004 Chad Fowler, Charles Mills, Rich Kilmer
3
+ * Licensed under the same terms as Ruby.
4
+ * This software has absolutely no warranty.
5
+ */
6
+ #include "rdnssd.h"
7
+
8
+ static VALUE cDNSSDFlags;
9
+ static VALUE cDNSSDReply;
10
+
11
+ static ID dnssd_iv_flags;
12
+ static ID dnssd_iv_interface;
13
+ static ID dnssd_iv_fullname;
14
+ static ID dnssd_iv_target;
15
+ static ID dnssd_iv_port;
16
+ static ID dnssd_iv_text_record;
17
+ static ID dnssd_iv_name;
18
+ static ID dnssd_iv_type;
19
+ static ID dnssd_iv_domain;
20
+ static ID dnssd_iv_service;
21
+
22
+ #define IsDNSSDFlags(obj) (rb_obj_is_kind_of(obj,cDNSSDFlags)==Qtrue)
23
+ #define VerifyDNSSDFlags(obj) \
24
+ do { \
25
+ if(!IsDNSSDFlags(obj)) rb_fatal(__FILE__":%d: bug in DNSSD",__LINE__); \
26
+ } while (0)
27
+
28
+ /* dns sd flags, flag ID's, flag names */
29
+ #define DNSSD_MAX_FLAGS 9
30
+
31
+ static const DNSServiceFlags dnssd_flag[DNSSD_MAX_FLAGS] = {
32
+ kDNSServiceFlagsMoreComing,
33
+
34
+ kDNSServiceFlagsAdd,
35
+ kDNSServiceFlagsDefault,
36
+
37
+ kDNSServiceFlagsNoAutoRename,
38
+
39
+ kDNSServiceFlagsShared,
40
+ kDNSServiceFlagsUnique,
41
+
42
+ kDNSServiceFlagsBrowseDomains,
43
+ kDNSServiceFlagsRegistrationDomains,
44
+
45
+ kDNSServiceFlagsLongLivedQuery
46
+ };
47
+
48
+ /* used to make sure only valid bits are set in a flag. */
49
+ #define DNSSD_FLAGS_MASK(f) \
50
+ ( (f) & (kDNSServiceFlagsMoreComing | \
51
+ kDNSServiceFlagsAdd | kDNSServiceFlagsDefault | \
52
+ kDNSServiceFlagsNoAutoRename | kDNSServiceFlagsShared | \
53
+ kDNSServiceFlagsUnique | kDNSServiceFlagsBrowseDomains | \
54
+ kDNSServiceFlagsRegistrationDomains | kDNSServiceFlagsLongLivedQuery) )
55
+
56
+ static const char *dnssd_flag_name[DNSSD_MAX_FLAGS] = {
57
+ "more_coming",
58
+ "add",
59
+ "default",
60
+ "no_auto_rename",
61
+ "shared",
62
+ "unique",
63
+ "browse_domains",
64
+ "registration_domains",
65
+ "long_lived_query"
66
+ };
67
+
68
+ static void
69
+ dnssd_init_flags_methods(VALUE klass)
70
+ {
71
+ char buffer[128];
72
+ int i;
73
+ for (i=0; i<DNSSD_MAX_FLAGS; i++) {
74
+ unsigned long flag = (unsigned long)dnssd_flag[i];
75
+ const char *flag_name = dnssd_flag_name[i];
76
+ VALUE str;
77
+ size_t len;
78
+ len = snprintf(buffer, sizeof(buffer),
79
+ "def %s?; self & %lu end",
80
+ flag_name, flag);
81
+ str = rb_str_new(buffer, (long)len);
82
+ rb_mod_module_eval(1, &str, klass);
83
+
84
+ /* similar to attr_writer method for each flag */
85
+ len = snprintf(buffer, sizeof(buffer),
86
+ "def %s=(val); "
87
+ "if val then self.set_flag(%lu) else self.clear_flag(%lu) end; "
88
+ "val end", /* return val */
89
+ flag_name, flag, flag);
90
+ str = rb_str_new(buffer, (long)len);
91
+ rb_mod_module_eval(1, &str, klass);
92
+ }
93
+ }
94
+
95
+ static VALUE
96
+ dnssd_flags_alloc(VALUE klass)
97
+ {
98
+ /* no free function or mark function, initialize flags/data to 0 */
99
+ return Data_Wrap_Struct(klass, 0, 0, 0);
100
+ }
101
+
102
+ static VALUE
103
+ dnssd_flags_init(VALUE self, DNSServiceFlags flags)
104
+ {
105
+ VerifyDNSSDFlags(self);
106
+ /* note DNSSD_FLAGS_MASK() here */
107
+ RDATA(self)->data = (void*)DNSSD_FLAGS_MASK(flags);
108
+ return self;
109
+ }
110
+
111
+ static DNSServiceFlags
112
+ dnssd_get_flags(VALUE self)
113
+ {
114
+ VerifyDNSSDFlags(self);
115
+ return (DNSServiceFlags)RDATA(self)->data;
116
+ }
117
+
118
+ DNSServiceFlags
119
+ dnssd_to_flags(VALUE obj)
120
+ {
121
+ DNSServiceFlags flags = 0;
122
+ if (IsDNSSDFlags(obj)) {
123
+ flags = dnssd_get_flags(obj);
124
+ } else {
125
+ /* don't want to include any bits that aren't flags */
126
+ flags = DNSSD_FLAGS_MASK((DNSServiceFlags)NUM2ULONG(obj));
127
+ }
128
+ return flags;
129
+ }
130
+
131
+ /*
132
+ * call-seq:
133
+ * DNSSD::Flags.new() => flags
134
+ * DNSSD::Flags.new(flag1, flag2, ...) => union_of_flags
135
+ *
136
+ * Returns a new set of flags.
137
+ * In the first form an empty set of flags is created.
138
+ * In the second a set of flags containing the union of
139
+ * each flag (or set of flags) given is created.
140
+ *
141
+ * flags = Flags.new()
142
+ * flags.more_coming = true
143
+ * flags.to_i #=> DNSSD::Flags::MoreComing
144
+ * f.shared = true
145
+ * flags.to_i #=> Flags::MoreComing | Flags::Shared
146
+ *
147
+ * same_flags = Flags.new(Flags::MoreComing | Flags::Shared)
148
+ * flags == same_flags #=> true
149
+ *
150
+ * same_flags_again = Flags.new(Flags::MoreComing, Flags::Shared)
151
+ * flags == same_flags_again #=> true
152
+ *
153
+ */
154
+
155
+ static VALUE
156
+ dnssd_flags_initialize(int argc, VALUE *argv, VALUE self)
157
+ {
158
+ int i;
159
+ DNSServiceFlags flags = 0;
160
+
161
+ for (i=0; i<argc; i++) {
162
+ flags |= dnssd_to_flags(argv[i]);
163
+ }
164
+ return dnssd_flags_init(self, flags);
165
+ }
166
+
167
+ static VALUE
168
+ dnssd_flags_new2(VALUE klass, DNSServiceFlags flags)
169
+ {
170
+ return dnssd_flags_init(dnssd_flags_alloc(klass), flags);
171
+ }
172
+
173
+ static VALUE
174
+ dnssd_flags_new(DNSServiceFlags flags)
175
+ {
176
+ return dnssd_flags_new2(cDNSSDFlags, flags);
177
+ }
178
+
179
+ /*
180
+ * call-seq:
181
+ * flags.set_flag(f)
182
+ *
183
+ * Set the flag _f_ in _flags_.
184
+ *
185
+ * flags = Flags.new() #=> #<DNSSD::Flags>
186
+ * flags.set_flag(Flags::MoreComing) #=> #<DNSSD::Flags more_coming>
187
+ *
188
+ */
189
+
190
+ static VALUE
191
+ dnssd_flags_set(VALUE self, VALUE num)
192
+ {
193
+ DNSServiceFlags flags;
194
+ VerifyDNSSDFlags(self);
195
+ flags = (DNSServiceFlags)RDATA(self)->data;
196
+ flags |= dnssd_to_flags(num);
197
+ RDATA(self)->data = (void*)flags;
198
+ return self;
199
+ }
200
+
201
+ /*
202
+ * call-seq:
203
+ * flags.clear_flag(f)
204
+ *
205
+ * Clear the flag _f_ in _flags_.
206
+ *
207
+ * flags = Flags.new(Flags::MoreComing) #=> #<DNSSD::Flags more_coming>
208
+ * flags.clear_flag(Flags::MoreComing) #=> #<DNSSD::Flags>
209
+ *
210
+ */
211
+
212
+ static VALUE
213
+ dnssd_flags_clear(VALUE self, VALUE num)
214
+ {
215
+ DNSServiceFlags flags;
216
+ VerifyDNSSDFlags(self);
217
+ /* flags should stay masked here (see DNSSD_FLAGS_MASK() macro) */
218
+ flags = (DNSServiceFlags)RDATA(self)->data;
219
+ flags &= ~dnssd_to_flags(num);
220
+ RDATA(self)->data = (void*)flags;
221
+ return self;
222
+ }
223
+
224
+ /*
225
+ * call-seq:
226
+ * flags1 & flags2 => flags
227
+ *
228
+ * Returns the set of flags included in <i>flags1</i> and <i>flags2</i>.
229
+ *
230
+ */
231
+
232
+ static VALUE
233
+ dnssd_flags_and(VALUE self, VALUE num)
234
+ {
235
+ return dnssd_flags_new2(CLASS_OF(self), dnssd_get_flags(self) & dnssd_to_flags(num));
236
+ }
237
+
238
+ /*
239
+ * call-seq:
240
+ * flags1 | flags2 => flags
241
+ *
242
+ * Returns the set of flags included in <i>flags1</i> or <i>flags2</i>.
243
+ *
244
+ */
245
+
246
+ static VALUE
247
+ dnssd_flags_or(VALUE self, VALUE num)
248
+ {
249
+ return dnssd_flags_new2(CLASS_OF(self), dnssd_get_flags(self) | dnssd_to_flags(num));
250
+ }
251
+
252
+ /*
253
+ * call-seq:
254
+ * ~flags => unset_flags
255
+ *
256
+ * Returns the set of flags not included in _flags_.
257
+ *
258
+ */
259
+
260
+ static VALUE
261
+ dnssd_flags_not(VALUE self)
262
+ {
263
+ /* doesn't totally make sence to return a set of flags here... */
264
+ return dnssd_flags_new2(CLASS_OF(self), ~dnssd_get_flags(self));
265
+ }
266
+
267
+ /*
268
+ * call-seq:
269
+ * flags.to_i => an_integer
270
+ *
271
+ * Get the integer representation of _flags_ by bitwise or'ing
272
+ * each of the set flags.
273
+ *
274
+ */
275
+
276
+ static VALUE
277
+ dnssd_flags_to_i(VALUE self)
278
+ {
279
+ return ULONG2NUM(dnssd_get_flags(self));
280
+ }
281
+
282
+ static VALUE
283
+ dnssd_flags_list(VALUE self)
284
+ {
285
+ DNSServiceFlags flags = dnssd_get_flags(self);
286
+ VALUE buf = rb_str_buf_new(0);
287
+ int i;
288
+ for (i=0; i<DNSSD_MAX_FLAGS; i++) {
289
+ if (flags & dnssd_flag[i]) {
290
+ rb_str_buf_cat2(buf, dnssd_flag_name[i]);
291
+ rb_str_buf_cat2(buf, ",");
292
+ }
293
+ }
294
+ /* get rid of trailing comma */
295
+ if (RSTRING(buf)->len > 0) {
296
+ long len = RSTRING(buf)->len;
297
+ len--;
298
+ RSTRING(buf)->ptr[len] = '\000';
299
+ }
300
+ return buf;
301
+ }
302
+
303
+ static VALUE
304
+ dnssd_struct_inspect(VALUE self, VALUE data)
305
+ {
306
+ VALUE buf = rb_str_buf_new(20 + RSTRING(data)->len);
307
+ rb_str_buf_cat2(buf, "#<");
308
+ rb_str_buf_cat2(buf, rb_obj_classname(self));
309
+ if (RSTRING(data)->len > 0) {
310
+ rb_str_buf_cat2(buf, " ");
311
+ rb_str_buf_append(buf, data);
312
+ }
313
+ rb_str_buf_cat2(buf, ">");
314
+ return buf;
315
+ }
316
+
317
+ /*
318
+ * call-seq:
319
+ * flags.inspect => string
320
+ *
321
+ * Create a printable version of _flags_.
322
+ *
323
+ * flags = DNSSD::Flags.new
324
+ * flags.add = true
325
+ * flags.default = true
326
+ * flags.inspect # => "#<DNSSD::Flags add,default>"
327
+ *
328
+ */
329
+
330
+ static VALUE
331
+ dnssd_flags_inspect(VALUE self)
332
+ {
333
+ return dnssd_struct_inspect(self, dnssd_flags_list(self));
334
+ }
335
+
336
+ /*
337
+ * call-seq:
338
+ * flags == obj => true or false
339
+ *
340
+ * Equality--Two sets of flags are equal if they contain the same flags.
341
+ *
342
+ * flags = Flags.new()
343
+ * flags.more_coming = true
344
+ * flags.shared = true
345
+ * flags == Flags::MoreComing | Flags::Shared #=> true
346
+ * flags == Flags.new(Flags::MoreComing | Flags::Shared) #=> true
347
+ */
348
+
349
+ static VALUE
350
+ dnssd_flags_equal(VALUE self, VALUE obj)
351
+ {
352
+ DNSServiceFlags flags = dnssd_get_flags(self);
353
+ DNSServiceFlags obj_flags = dnssd_to_flags(obj);
354
+
355
+ return flags == obj_flags ? Qtrue : Qfalse;
356
+ }
357
+
358
+ VALUE
359
+ dnssd_create_fullname(const char *name, const char *regtype, const char *domain, int err_flag)
360
+ {
361
+ char buffer[kDNSServiceMaxDomainName];
362
+ if ( DNSServiceConstructFullName(buffer, name, regtype, domain) ) {
363
+ static const char msg[] = "could not construct full service name";
364
+ if (err_flag) {
365
+ rb_raise(rb_eArgError, msg);
366
+ } else {
367
+ VALUE buf;
368
+ rb_warn(msg);
369
+ /* just join them all */
370
+ buf = rb_str_buf_new2(name);
371
+ rb_str_buf_cat2(buf, regtype);
372
+ rb_str_buf_cat2(buf, domain);
373
+ return buf;
374
+ }
375
+ }
376
+ buffer[kDNSServiceMaxDomainName - 1] = '\000'; /* just in case */
377
+ return rb_str_new2(buffer);
378
+ }
379
+
380
+ VALUE
381
+ dnssd_split_fullname(VALUE fullname)
382
+ {
383
+ static const char re[] = "(?:\\\\.|[^\\.])+\\.";
384
+ VALUE regexp = rb_reg_new(re, sizeof(re)-1, 0);
385
+ return rb_funcall2(fullname, rb_intern("scan"), 1, &regexp);
386
+ }
387
+
388
+ #if 0
389
+ static void
390
+ quote_and_append(VALUE buf, VALUE str)
391
+ {
392
+ const char *ptr;
393
+ long i, last_mark, len;
394
+
395
+ ptr = RSTRING(str)->ptr;
396
+ len = RSTRING(str)->len;
397
+ last_mark = 0;
398
+ /* last character should be '.' */
399
+ for (i=0; i<len-1; i++) {
400
+ if (ptr[i] == '.') {
401
+ /* write 1 extra character and replace it with '\\' */
402
+ rb_str_buf_cat(buf, ptr + last_mark, i + 1 - last_mark);
403
+ RSTRING(buf)->ptr[i] = '\\';
404
+ last_mark = i;
405
+ }
406
+ }
407
+ rb_str_buf_cat(buf, ptr + last_mark, len - last_mark);
408
+ }
409
+ #endif
410
+
411
+ static VALUE
412
+ dnssd_join_names(int argc, VALUE *argv)
413
+ {
414
+ int i;
415
+ VALUE buf;
416
+ long len = 0;
417
+
418
+ for (i=0; i<argc; i++) {
419
+ argv[i] = StringValue(argv[i]);
420
+ len += RSTRING(argv[i])->len;
421
+ }
422
+ buf = rb_str_buf_new(len);
423
+ for (i=0; i<argc; i++) {
424
+ rb_str_buf_append(buf, argv[i]);
425
+ }
426
+ return buf;
427
+ }
428
+
429
+ static void
430
+ reply_add_names(VALUE self, const char *name,
431
+ const char *regtype, const char *domain)
432
+ {
433
+ rb_ivar_set(self, dnssd_iv_name, rb_str_new2(name));
434
+ rb_ivar_set(self, dnssd_iv_type, rb_str_new2(regtype));
435
+ rb_ivar_set(self, dnssd_iv_domain, rb_str_new2(domain));
436
+ rb_ivar_set(self, dnssd_iv_fullname, dnssd_create_fullname(name, regtype, domain, 0));
437
+ }
438
+
439
+ static void
440
+ reply_add_names2(VALUE self, const char *fullname)
441
+ {
442
+ VALUE fn = rb_str_new2(fullname);
443
+ VALUE ary = dnssd_split_fullname(fn);
444
+ VALUE type[2] = { rb_ary_entry(ary, 1), rb_ary_entry(ary, 2) };
445
+
446
+ rb_ivar_set(self, dnssd_iv_name, rb_ary_entry(ary, 0));
447
+ rb_ivar_set(self, dnssd_iv_type, dnssd_join_names(2, type));
448
+ rb_ivar_set(self, dnssd_iv_domain, rb_ary_entry(ary, -1));
449
+ rb_ivar_set(self, dnssd_iv_fullname, fn);
450
+ }
451
+
452
+
453
+ static void
454
+ reply_set_interface(VALUE self, uint32_t interface)
455
+ {
456
+ VALUE if_value;
457
+ char buffer[IF_NAMESIZE];
458
+ if (if_indextoname(interface, buffer)) {
459
+ if_value = rb_str_new2(buffer);
460
+ } else {
461
+ if_value = ULONG2NUM(interface);
462
+ }
463
+ rb_ivar_set(self, dnssd_iv_interface, if_value);
464
+ }
465
+
466
+ static void
467
+ reply_set_tr(VALUE self, uint16_t txt_len, const char *txt_rec)
468
+ {
469
+ rb_ivar_set(self, dnssd_iv_text_record, dnssd_tr_new((long)txt_len, txt_rec));
470
+ }
471
+
472
+ static VALUE
473
+ reply_new(VALUE service, DNSServiceFlags flags)
474
+ {
475
+ VALUE self = rb_obj_alloc(cDNSSDReply);
476
+ rb_ivar_set(self, dnssd_iv_service, service);
477
+ rb_ivar_set(self, dnssd_iv_flags, dnssd_flags_new(flags));
478
+ return self;
479
+ }
480
+
481
+ VALUE
482
+ dnssd_domain_enum_new(VALUE service, DNSServiceFlags flags,
483
+ uint32_t interface, const char *domain)
484
+ {
485
+ VALUE d, self = reply_new(service, flags);
486
+ reply_set_interface(self, interface);
487
+ d = rb_str_new2(domain);
488
+ rb_ivar_set(self, dnssd_iv_domain, d);
489
+ rb_ivar_set(self, dnssd_iv_fullname, d);
490
+ return self;
491
+ }
492
+
493
+ VALUE
494
+ dnssd_browse_new(VALUE service, DNSServiceFlags flags, uint32_t interface,
495
+ const char *name, const char *regtype, const char *domain)
496
+ {
497
+ VALUE self = reply_new(service, flags);
498
+ reply_set_interface(self, interface);
499
+ reply_add_names(self, name, regtype, domain);
500
+ return self;
501
+ }
502
+
503
+ #if 0
504
+ static VALUE
505
+ dnssd_gethostname(void)
506
+ {
507
+ #if HAVE_GETHOSTNAME
508
+ #ifndef MAXHOSTNAMELEN
509
+ #define MAXHOSTNAMELEN 256
510
+ #endif
511
+ char buffer[MAXHOSTNAMELEN + 1];
512
+ if (gethostname(buffer, MAXHOSTNAMELEN))
513
+ return Qnil;
514
+ buffer[MAXHOSTNAMELEN] = '\000';
515
+ return rb_str_new2(buffer);
516
+ #else
517
+ return Qnil;
518
+ #endif
519
+ }
520
+ #endif
521
+
522
+ VALUE
523
+ dnssd_register_new(VALUE service, DNSServiceFlags flags, const char *name,
524
+ const char *regtype, const char *domain )
525
+ {
526
+ VALUE self = reply_new(service, flags);
527
+ reply_add_names(self, name, regtype, domain);
528
+ /* HACK */
529
+ /* See HACK in rdnssd_service.c */
530
+ rb_ivar_set(self, dnssd_iv_interface, rb_ivar_get(service, dnssd_iv_interface));
531
+ rb_ivar_set(self, dnssd_iv_port, rb_ivar_get(service, dnssd_iv_port));
532
+ rb_ivar_set(self, dnssd_iv_text_record, rb_ivar_get(service, dnssd_iv_text_record));
533
+ /********/
534
+ return self;
535
+ }
536
+
537
+ VALUE
538
+ dnssd_resolve_new(VALUE service, DNSServiceFlags flags, uint32_t interface,
539
+ const char *fullname, const char *host_target,
540
+ uint16_t opaqueport, uint16_t txt_len, const char *txt_rec)
541
+ {
542
+ uint16_t port = ntohs(opaqueport);
543
+ VALUE self = reply_new(service, flags);
544
+ reply_set_interface(self, interface);
545
+ reply_add_names2(self, fullname);
546
+ rb_ivar_set(self, dnssd_iv_target, rb_str_new2(host_target));
547
+ rb_ivar_set(self, dnssd_iv_port, UINT2NUM(port));
548
+ reply_set_tr(self, txt_len, txt_rec);
549
+ return self;
550
+ }
551
+
552
+ /*
553
+ * call-seq:
554
+ * reply.inspect => string
555
+ *
556
+ */
557
+ static VALUE
558
+ reply_inspect(VALUE self)
559
+ {
560
+ VALUE fullname = rb_ivar_get(self, dnssd_iv_fullname);
561
+ return dnssd_struct_inspect(self, StringValue(fullname));
562
+ }
563
+
564
+ /*
565
+ * call-seq:
566
+ * DNSSD::Reply.new() => raises a RuntimeError
567
+ *
568
+ */
569
+ static VALUE
570
+ reply_initialize(int argc, VALUE *argv, VALUE reply)
571
+ {
572
+ dnssd_instantiation_error(rb_obj_classname(reply));
573
+ return Qnil;
574
+ }
575
+
576
+ void
577
+ Init_DNSSD_Replies(void)
578
+ {
579
+ /* hack so rdoc documents the project correctly */
580
+ #ifdef mDNSSD_RDOC_HACK
581
+ mDNSSD = rb_define_module("DNSSD");
582
+ #endif
583
+
584
+ dnssd_iv_flags = rb_intern("@flags");
585
+ dnssd_iv_interface = rb_intern("@interface");
586
+ dnssd_iv_fullname = rb_intern("@fullname");
587
+ dnssd_iv_target = rb_intern("@target");
588
+ dnssd_iv_port = rb_intern("@port");
589
+ dnssd_iv_text_record = rb_intern("@text_record");
590
+ dnssd_iv_name = rb_intern("@name");
591
+ dnssd_iv_type = rb_intern("@type");
592
+ dnssd_iv_domain = rb_intern("@domain");
593
+ dnssd_iv_service = rb_intern("@service");
594
+
595
+ cDNSSDFlags = rb_define_class_under(mDNSSD, "Flags", rb_cObject);
596
+ rb_define_alloc_func(cDNSSDFlags, dnssd_flags_alloc);
597
+ rb_define_method(cDNSSDFlags, "initialize", dnssd_flags_initialize, -1);
598
+ /* this creates all the attr_writer and flag? methods */
599
+ dnssd_init_flags_methods(cDNSSDFlags);
600
+ rb_define_method(cDNSSDFlags, "inspect", dnssd_flags_inspect, 0);
601
+ rb_define_method(cDNSSDFlags, "to_i", dnssd_flags_to_i, 0);
602
+ rb_define_method(cDNSSDFlags, "==", dnssd_flags_equal, 1);
603
+
604
+ rb_define_method(cDNSSDFlags, "&", dnssd_flags_and, 1);
605
+ rb_define_method(cDNSSDFlags, "|", dnssd_flags_or, 1);
606
+ rb_define_method(cDNSSDFlags, "~", dnssd_flags_not, 0);
607
+
608
+ rb_define_method(cDNSSDFlags, "set_flag", dnssd_flags_set, 1);
609
+ rb_define_method(cDNSSDFlags, "clear_flag", dnssd_flags_clear, 1);
610
+
611
+ cDNSSDReply = rb_define_class_under(mDNSSD, "Reply", rb_cObject);
612
+ /* DNSSD::Reply objects can only be instantiated by
613
+ * DNSSD.browse(), DNSSD.register(), DNSSD.resolve(), DNSSD.enumerate_domains(). */
614
+ rb_define_method(cDNSSDReply, "initialize", reply_initialize, -1);
615
+ /* The service associated with the reply. See DNSSD::Service for more information. */
616
+ rb_define_attr(cDNSSDReply, "service", 1, 0);
617
+ /* Flags describing the reply. See DNSSD::Flags for more information. */
618
+ rb_define_attr(cDNSSDReply, "flags", 1, 0);
619
+ /* The service name. (Not used by DNSSD.enumerate_domains().) */
620
+ rb_define_attr(cDNSSDReply, "name", 1, 0);
621
+ /* The service type. (Not used by DNSSD.enumerate_domains().) */
622
+ rb_define_attr(cDNSSDReply, "type", 1, 0);
623
+ /* The service domain. */
624
+ rb_define_attr(cDNSSDReply, "domain", 1, 0);
625
+ /* The interface on which the service is available. (Used only by DNSSSD.resolve().) */
626
+ rb_define_attr(cDNSSDReply, "interface", 1, 0);
627
+ /* The full service domain name, in the form "<servicename>.<protocol>.<domain>.".
628
+ * (Any literal dots (".") are escaped with a backslash ("\."), and literal
629
+ * backslashes are escaped with a second backslash ("\\"), e.g. a web server
630
+ * named "Dr. Pepper" would have the fullname "Dr\.\032Pepper._http._tcp.local.".)
631
+ * See DNSSD::Service.fullname() for more information. */
632
+ rb_define_attr(cDNSSDReply, "fullname", 1, 0);
633
+ /* The service's primary text record, see DNSSD::TextRecord for more information. */
634
+ rb_define_attr(cDNSSDReply, "text_record", 1, 0);
635
+ /* The target hostname of the machine providing the service.
636
+ * This name can be passed to functions like Socket.gethostbyname()
637
+ * to identify the host's IP address. */
638
+ rb_define_attr(cDNSSDReply, "target", 1, 0);
639
+ /* The port on which connections are accepted for this service. */
640
+ rb_define_attr(cDNSSDReply, "port", 1, 0);
641
+
642
+ rb_define_method(cDNSSDReply, "inspect", reply_inspect, 0);
643
+
644
+ /* flag constants */
645
+ #if DNSSD_MAX_FLAGS != 9
646
+ #error The code below needs to be updated.
647
+ #endif
648
+ /* MoreComing indicates that at least one more result is queued and will be delivered following immediately after this one.
649
+ * Applications should not update their UI to display browse
650
+ * results when the MoreComing flag is set, because this would
651
+ * result in a great deal of ugly flickering on the screen.
652
+ * Applications should instead wait until until MoreComing is not set,
653
+ * and then update their UI.
654
+ * When MoreComing is not set, that doesn't mean there will be no more
655
+ * answers EVER, just that there are no more answers immediately
656
+ * available right now at this instant. If more answers become available
657
+ * in the future they will be delivered as usual.
658
+ */
659
+ rb_define_const(cDNSSDFlags, "MoreComing", ULONG2NUM(kDNSServiceFlagsMoreComing));
660
+
661
+
662
+ /* Flags for domain enumeration and DNSSD.browse() reply callbacks.
663
+ * DNSSD::Flags::Default applies only to enumeration and is only valid in
664
+ * conjuction with DNSSD::Flags::Add. An enumeration callback with the DNSSD::Flags::Add
665
+ * flag NOT set indicates a DNSSD::Flags::Remove, i.e. the domain is no longer valid.
666
+ */
667
+ rb_define_const(cDNSSDFlags, "Add", ULONG2NUM(kDNSServiceFlagsAdd));
668
+ rb_define_const(cDNSSDFlags, "Default", ULONG2NUM(kDNSServiceFlagsDefault));
669
+
670
+ /* Flag for specifying renaming behavior on name conflict when registering non-shared records.
671
+ * By default, name conflicts are automatically handled by renaming the service.
672
+ * DNSSD::Flags::NoAutoRename overrides this behavior - with this
673
+ * flag set, name conflicts will result in a callback. The NoAutoRename flag
674
+ * is only valid if a name is explicitly specified when registering a service
675
+ * (ie the default name is not used.)
676
+ */
677
+ rb_define_const(cDNSSDFlags, "NoAutoRename", ULONG2NUM(kDNSServiceFlagsNoAutoRename));
678
+
679
+ /* Flag for registering individual records on a connected DNSServiceRef.
680
+ * DNSSD::Flags::Shared indicates that there may be multiple records
681
+ * with this name on the network (e.g. PTR records). DNSSD::Flags::Unique indicates that the
682
+ * record's name is to be unique on the network (e.g. SRV records).
683
+ * (DNSSD::Flags::Shared and DNSSD::Flags::Unique are currently not used by the Ruby API.)
684
+ */
685
+ rb_define_const(cDNSSDFlags, "Shared", ULONG2NUM(kDNSServiceFlagsShared));
686
+ rb_define_const(cDNSSDFlags, "Unique", ULONG2NUM(kDNSServiceFlagsUnique));
687
+
688
+ /* Flags for specifying domain enumeration type in DNSSD.enumerate_domains()
689
+ * (currently not part of the Ruby API).
690
+ * DNSSD::Flags::BrowseDomains enumerates domains recommended for browsing,
691
+ * DNSSD::Flags::RegistrationDomains enumerates domains recommended for registration.
692
+ */
693
+ rb_define_const(cDNSSDFlags, "BrowseDomains", ULONG2NUM(kDNSServiceFlagsBrowseDomains));
694
+ rb_define_const(cDNSSDFlags, "RegistrationDomains", ULONG2NUM(kDNSServiceFlagsRegistrationDomains));
695
+
696
+ /* Flag for creating a long-lived unicast query for the DNSDS.query_record()
697
+ * (currently not part of the Ruby API). */
698
+ rb_define_const(cDNSSDFlags, "LongLivedQuery", ULONG2NUM(kDNSServiceFlagsLongLivedQuery));
699
+ }
700
+
701
+ /* Document-class: DNSSD::Reply
702
+ *
703
+ * DNSSD::Reply is used to return information
704
+ *
705
+ */
706
+
707
+ /* Document-class: DNSSD::Flags
708
+ *
709
+ * Flags used in DNSSD Ruby API.
710
+ */
711
+