dnssd 1.2 → 1.3

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.
Files changed (45) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.autotest +14 -0
  3. data/History.txt +22 -3
  4. data/Manifest.txt +15 -0
  5. data/README.txt +27 -3
  6. data/Rakefile +5 -4
  7. data/ext/dnssd/dnssd.c +4 -0
  8. data/ext/dnssd/dnssd.h +13 -18
  9. data/ext/dnssd/errors.c +9 -3
  10. data/ext/dnssd/extconf.rb +51 -44
  11. data/ext/dnssd/flags.c +68 -14
  12. data/ext/dnssd/record.c +218 -0
  13. data/ext/dnssd/service.c +341 -121
  14. data/lib/dnssd.rb +46 -11
  15. data/lib/dnssd/record.rb +97 -0
  16. data/lib/dnssd/reply.rb +39 -92
  17. data/lib/dnssd/reply/addr_info.rb +47 -0
  18. data/lib/dnssd/reply/browse.rb +52 -0
  19. data/lib/dnssd/reply/domain.rb +22 -0
  20. data/lib/dnssd/reply/query_record.rb +183 -0
  21. data/lib/dnssd/reply/register.rb +37 -0
  22. data/lib/dnssd/reply/resolve.rb +105 -0
  23. data/lib/dnssd/service.rb +123 -16
  24. data/lib/dnssd/text_record.rb +28 -19
  25. data/sample/browse.rb +24 -6
  26. data/sample/enumerate_domains.rb +7 -1
  27. data/sample/getaddrinfo.rb +28 -0
  28. data/sample/growl.rb +2 -0
  29. data/sample/query_record.rb +15 -0
  30. data/sample/register.rb +19 -20
  31. data/sample/resolve.rb +31 -7
  32. data/sample/resolve_ichat.rb +5 -6
  33. data/sample/server.rb +2 -0
  34. data/sample/socket.rb +4 -0
  35. data/test/test_dnssd.rb +6 -4
  36. data/test/test_dnssd_flags.rb +1 -15
  37. data/test/test_dnssd_record.rb +92 -0
  38. data/test/test_dnssd_reply.rb +13 -79
  39. data/test/test_dnssd_reply_browse.rb +28 -0
  40. data/test/test_dnssd_reply_query_record.rb +92 -0
  41. data/test/test_dnssd_reply_resolve.rb +47 -0
  42. data/test/test_dnssd_service.rb +12 -0
  43. data/test/test_dnssd_text_record.rb +3 -3
  44. metadata +32 -11
  45. metadata.gz.sig +0 -0
@@ -0,0 +1,218 @@
1
+ #include "dnssd.h"
2
+
3
+ static VALUE cDNSSDRecord;
4
+
5
+ static void
6
+ dnssd_record_free(void *ptr) {
7
+ DNSRecordRef *record = (DNSRecordRef *)ptr;
8
+
9
+ /* TODO */
10
+
11
+ free(record);
12
+ }
13
+
14
+ static VALUE
15
+ dnssd_record_s_allocate(VALUE klass) {
16
+ DNSRecordRef *record = ALLOC(DNSRecordRef);
17
+
18
+ *record = NULL;
19
+
20
+ return Data_Wrap_Struct(klass, 0, dnssd_record_free, record);
21
+ }
22
+
23
+ void
24
+ Init_DNSSD_Record(void) {
25
+ VALUE mDNSSD = rb_define_module("DNSSD");
26
+
27
+ cDNSSDRecord = rb_define_class_under(mDNSSD, "Record", rb_cObject);
28
+
29
+ rb_define_alloc_func(cDNSSDRecord, dnssd_record_s_allocate);
30
+
31
+ /* Internet service class */
32
+ rb_define_const(cDNSSDRecord, "IN", UINT2NUM(kDNSServiceClass_IN));
33
+
34
+ /* Wildcard match. */
35
+ rb_define_const(cDNSSDRecord, "ANY", UINT2NUM(kDNSServiceType_ANY));
36
+
37
+ /* Host address. */
38
+ rb_define_const(cDNSSDRecord, "A", UINT2NUM(kDNSServiceType_A));
39
+
40
+ /* IPv6 Address (deprecated) */
41
+ rb_define_const(cDNSSDRecord, "A6", UINT2NUM(kDNSServiceType_A6));
42
+
43
+ /* IPv6 Address. */
44
+ rb_define_const(cDNSSDRecord, "AAAA", UINT2NUM(kDNSServiceType_AAAA));
45
+
46
+ #ifdef kDNSServiceType_APL
47
+ /* Address Prefix List */
48
+ rb_define_const(cDNSSDRecord, "APL", UINT2NUM(kDNSServiceType_APL));
49
+ #endif
50
+
51
+ /* AFS cell database. */
52
+ rb_define_const(cDNSSDRecord, "AFSDB", UINT2NUM(kDNSServiceType_AFSDB));
53
+
54
+ /* ATM Address */
55
+ rb_define_const(cDNSSDRecord, "ATMA", UINT2NUM(kDNSServiceType_ATMA));
56
+
57
+ /* Transfer zone of authority. */
58
+ rb_define_const(cDNSSDRecord, "AXFR", UINT2NUM(kDNSServiceType_AXFR));
59
+
60
+ /* Certification record */
61
+ rb_define_const(cDNSSDRecord, "CERT", UINT2NUM(kDNSServiceType_CERT));
62
+
63
+ /* Canonical name. */
64
+ rb_define_const(cDNSSDRecord, "CNAME", UINT2NUM(kDNSServiceType_CNAME));
65
+
66
+ #ifdef kDNSServiceType_DHCID
67
+ /* DHCID */
68
+ rb_define_const(cDNSSDRecord, "DHCID", UINT2NUM(kDNSServiceType_DHCID));
69
+ #endif
70
+
71
+ /* Non-terminal DNAME (for IPv6) */
72
+ rb_define_const(cDNSSDRecord, "DNAME", UINT2NUM(kDNSServiceType_DNAME));
73
+
74
+ #ifdef kDNSServiceType_DNSKEY
75
+ /* DNSKEY */
76
+ rb_define_const(cDNSSDRecord, "DNSKEY", UINT2NUM(kDNSServiceType_DNSKEY));
77
+ #endif
78
+
79
+ #ifdef kDNSServiceType_DS
80
+ /* Delegation Signer */
81
+ rb_define_const(cDNSSDRecord, "DS", UINT2NUM(kDNSServiceType_DS));
82
+ #endif
83
+
84
+ /* Endpoint identifier. */
85
+ rb_define_const(cDNSSDRecord, "EID", UINT2NUM(kDNSServiceType_EID));
86
+
87
+ /* Geographical position (withdrawn). */
88
+ rb_define_const(cDNSSDRecord, "GPOS", UINT2NUM(kDNSServiceType_GPOS));
89
+
90
+ /* Host information. */
91
+ rb_define_const(cDNSSDRecord, "HINFO", UINT2NUM(kDNSServiceType_HINFO));
92
+
93
+ #ifdef kDNSServiceType_IPSECKEY
94
+ /* IPSECKEY */
95
+ rb_define_const(cDNSSDRecord, "IPSECKEY", UINT2NUM(kDNSServiceType_IPSECKEY));
96
+ #endif
97
+
98
+ /* ISDN calling address. */
99
+ rb_define_const(cDNSSDRecord, "ISDN", UINT2NUM(kDNSServiceType_ISDN));
100
+
101
+ /* Incremental zone transfer. */
102
+ rb_define_const(cDNSSDRecord, "IXFR", UINT2NUM(kDNSServiceType_IXFR));
103
+
104
+ /* Security key. */
105
+ rb_define_const(cDNSSDRecord, "KEY", UINT2NUM(kDNSServiceType_KEY));
106
+
107
+ /* Key Exchange */
108
+ rb_define_const(cDNSSDRecord, "KX", UINT2NUM(kDNSServiceType_KX));
109
+
110
+ /* Location Information. */
111
+ rb_define_const(cDNSSDRecord, "LOC", UINT2NUM(kDNSServiceType_LOC));
112
+
113
+ /* Transfer mail agent records. */
114
+ rb_define_const(cDNSSDRecord, "MAILA", UINT2NUM(kDNSServiceType_MAILA));
115
+
116
+ /* Transfer mailbox records. */
117
+ rb_define_const(cDNSSDRecord, "MAILB", UINT2NUM(kDNSServiceType_MAILB));
118
+
119
+ /* Mailbox domain name. */
120
+ rb_define_const(cDNSSDRecord, "MB", UINT2NUM(kDNSServiceType_MB));
121
+
122
+ /* Mail destination. */
123
+ rb_define_const(cDNSSDRecord, "MD", UINT2NUM(kDNSServiceType_MD));
124
+
125
+ /* Mail forwarder. */
126
+ rb_define_const(cDNSSDRecord, "MF", UINT2NUM(kDNSServiceType_MF));
127
+
128
+ /* Mail group member. */
129
+ rb_define_const(cDNSSDRecord, "MG", UINT2NUM(kDNSServiceType_MG));
130
+
131
+ /* Mailbox information. */
132
+ rb_define_const(cDNSSDRecord, "MINFO", UINT2NUM(kDNSServiceType_MINFO));
133
+
134
+ /* Mail rename name. */
135
+ rb_define_const(cDNSSDRecord, "MR", UINT2NUM(kDNSServiceType_MR));
136
+
137
+ /* Mail routing information. */
138
+ rb_define_const(cDNSSDRecord, "MX", UINT2NUM(kDNSServiceType_MX));
139
+
140
+ /* Naming Authority PoinTeR */
141
+ rb_define_const(cDNSSDRecord, "NAPTR", UINT2NUM(kDNSServiceType_NAPTR));
142
+
143
+ /* Nimrod Locator. */
144
+ rb_define_const(cDNSSDRecord, "NIMLOC", UINT2NUM(kDNSServiceType_NIMLOC));
145
+
146
+ /* Authoritative server. */
147
+ rb_define_const(cDNSSDRecord, "NS", UINT2NUM(kDNSServiceType_NS));
148
+
149
+ /* NSAP address. */
150
+ rb_define_const(cDNSSDRecord, "NSAP", UINT2NUM(kDNSServiceType_NSAP));
151
+
152
+ /* Reverse NSAP lookup (deprecated). */
153
+ rb_define_const(cDNSSDRecord, "NSAP_PTR", UINT2NUM(kDNSServiceType_NSAP_PTR));
154
+
155
+ #ifdef kDNSServiceType_NSEC
156
+ /* NSEC */
157
+ rb_define_const(cDNSSDRecord, "NSEC", UINT2NUM(kDNSServiceType_NSEC));
158
+ #endif
159
+
160
+ /* Null resource record. */
161
+ rb_define_const(cDNSSDRecord, "NULL", UINT2NUM(kDNSServiceType_NULL));
162
+
163
+ /* Next domain (security). */
164
+ rb_define_const(cDNSSDRecord, "NXT", UINT2NUM(kDNSServiceType_NXT));
165
+
166
+ /* EDNS0 option (meta-RR) */
167
+ rb_define_const(cDNSSDRecord, "OPT", UINT2NUM(kDNSServiceType_OPT));
168
+
169
+ /* Domain name pointer. */
170
+ rb_define_const(cDNSSDRecord, "PTR", UINT2NUM(kDNSServiceType_PTR));
171
+
172
+ /* X.400 mail mapping. */
173
+ rb_define_const(cDNSSDRecord, "PX", UINT2NUM(kDNSServiceType_PX));
174
+
175
+ /* Responsible person. */
176
+ rb_define_const(cDNSSDRecord, "RP", UINT2NUM(kDNSServiceType_RP));
177
+
178
+ #ifdef kDNSServiceType_RRSIG
179
+ /* RRSIG */
180
+ rb_define_const(cDNSSDRecord, "RRSIG", UINT2NUM(kDNSServiceType_RRSIG));
181
+ #endif
182
+
183
+ /* Router. */
184
+ rb_define_const(cDNSSDRecord, "RT", UINT2NUM(kDNSServiceType_RT));
185
+
186
+ /* Security signature. */
187
+ rb_define_const(cDNSSDRecord, "SIG", UINT2NUM(kDNSServiceType_SIG));
188
+
189
+ /* Kitchen sink (experimental) */
190
+ rb_define_const(cDNSSDRecord, "SINK", UINT2NUM(kDNSServiceType_SINK));
191
+
192
+ /* Start of authority zone. */
193
+ rb_define_const(cDNSSDRecord, "SOA", UINT2NUM(kDNSServiceType_SOA));
194
+
195
+ /* Server Selection. */
196
+ rb_define_const(cDNSSDRecord, "SRV", UINT2NUM(kDNSServiceType_SRV));
197
+
198
+ #ifdef kDNSServiceType_SSHFP
199
+ /* SSH Key Fingerprint */
200
+ rb_define_const(cDNSSDRecord, "SSHFP", UINT2NUM(kDNSServiceType_SSHFP));
201
+ #endif
202
+
203
+ /* Transaction key */
204
+ rb_define_const(cDNSSDRecord, "TKEY", UINT2NUM(kDNSServiceType_TKEY));
205
+
206
+ /* Transaction signature. */
207
+ rb_define_const(cDNSSDRecord, "TSIG", UINT2NUM(kDNSServiceType_TSIG));
208
+
209
+ /* One or more text strings (NOT "zero or more..."). */
210
+ rb_define_const(cDNSSDRecord, "TXT", UINT2NUM(kDNSServiceType_TXT));
211
+
212
+ /* Well known service. */
213
+ rb_define_const(cDNSSDRecord, "WKS", UINT2NUM(kDNSServiceType_WKS));
214
+
215
+ /* X_25 calling address. */
216
+ rb_define_const(cDNSSDRecord, "X25", UINT2NUM(kDNSServiceType_X25));
217
+ }
218
+
@@ -1,35 +1,36 @@
1
1
  #include "dnssd.h"
2
2
 
3
- #ifndef DNSSD_API
4
- /* define as nothing if not defined in Apple's "dns_sd.h" header */
5
- #define DNSSD_API
6
- #endif
7
-
8
- static VALUE cDNSSDReply;
3
+ static VALUE mDNSSD;
4
+ static VALUE cDNSSDFlags;
5
+ static VALUE cDNSSDRecord;
6
+ static VALUE cDNSSDReplyAddrInfo;
7
+ static VALUE cDNSSDReplyBrowse;
8
+ static VALUE cDNSSDReplyDomain;
9
+ static VALUE cDNSSDReplyQueryRecord;
10
+ static VALUE cDNSSDReplyRegister;
11
+ static VALUE cDNSSDReplyResolve;
9
12
  static VALUE cDNSSDService;
10
13
  static VALUE cDNSSDTextRecord;
14
+ static VALUE rb_cSocket;
11
15
 
12
16
  static ID dnssd_id_join;
13
17
  static ID dnssd_id_push;
14
18
 
15
19
  static ID dnssd_iv_continue;
16
- static ID dnssd_iv_domain;
17
- static ID dnssd_iv_interface;
18
- static ID dnssd_iv_port;
20
+ static ID dnssd_iv_records;
19
21
  static ID dnssd_iv_replies;
20
- static ID dnssd_iv_target;
21
- static ID dnssd_iv_text_record;
22
+ static ID dnssd_iv_service;
22
23
  static ID dnssd_iv_thread;
24
+ static ID dnssd_iv_type;
23
25
 
24
- /* HACK why is this a macro */
25
- #define GetDNSSDService(obj, var) \
26
+ #define get(klass, obj, type, var) \
26
27
  do {\
27
28
  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);\
29
+ if (rb_obj_is_kind_of(obj, klass) != Qtrue)\
30
+ rb_raise(rb_eTypeError,\
31
+ "wrong argument type %s",\
32
+ rb_class2name(CLASS_OF(obj)));\
33
+ Data_Get_Struct(obj, type, var);\
33
34
  } while (0)
34
35
 
35
36
  static void
@@ -71,29 +72,9 @@ create_fullname(const char *name, const char *regtype,
71
72
  return rb_str_new2(buffer);
72
73
  }
73
74
 
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
-
94
75
  /*
95
76
  * call-seq:
96
- * DNSSD::Service.fullname(name, type, domain) => String
77
+ * DNSSD::Service.fullname(name, type, domain)
97
78
  *
98
79
  * Concatenate a three-part domain name like DNSSD::Reply#fullname into a
99
80
  * properly-escaped full domain name.
@@ -119,6 +100,29 @@ dnssd_service_s_fullname(VALUE klass, VALUE name, VALUE type, VALUE domain) {
119
100
  StringValueCStr(domain));
120
101
  }
121
102
 
103
+ #ifdef HAVE_DNSSERVICEGETPROPERTY
104
+ /*
105
+ * call-seq:
106
+ * service.get_property(property)
107
+ *
108
+ * Binding for DNSServiceGetProperty. The only property currently supported in
109
+ * DNSSD is DaemonVersion
110
+ */
111
+ static VALUE
112
+ dnssd_service_s_get_property(VALUE klass, VALUE property) {
113
+ uint32_t result = 0;
114
+ uint32_t size = sizeof(result);
115
+ DNSServiceErrorType e;
116
+
117
+ e = DNSServiceGetProperty(StringValueCStr(property), (void *)&result, &size);
118
+
119
+ dnssd_check_error_code(e);
120
+
121
+ /* as of this writing only a uint32_t will be returned */
122
+ return ULONG2NUM(result);
123
+ }
124
+ #endif
125
+
122
126
  static VALUE
123
127
  dnssd_service_s_allocate(VALUE klass) {
124
128
  DNSServiceRef *client = ALLOC(DNSServiceRef);
@@ -128,32 +132,14 @@ dnssd_service_s_allocate(VALUE klass) {
128
132
  return Data_Wrap_Struct(klass, 0, dnssd_service_free, client);
129
133
  }
130
134
 
131
- /*
132
- * call-seq:
133
- * service.started? => true or false
134
- *
135
- * Returns true if the service has been started.
135
+ /* Returns true if the service has been stopped.
136
136
  */
137
137
 
138
138
  static VALUE
139
- dnssd_service_started_p(VALUE service) {
140
- DNSServiceRef *client = (DNSServiceRef*)RDATA(service)->data;
141
- if (client)
142
- return (*client) == NULL ? Qfalse : Qtrue;
143
-
144
- return Qtrue;
145
- }
146
-
147
- /*
148
- * call-seq:
149
- * service.stopped? => true or false
150
- *
151
- * Returns true if the service has been stopped.
152
- */
139
+ dnssd_service_stopped_p(VALUE self) {
140
+ DNSServiceRef *client;
153
141
 
154
- static VALUE
155
- dnssd_service_stopped_p(VALUE service) {
156
- DNSServiceRef *client = (DNSServiceRef*)RDATA(service)->data;
142
+ get(cDNSSDService, self, DNSServiceRef, client);
157
143
 
158
144
  if (client)
159
145
  return (*client) == NULL ? Qtrue : Qfalse;
@@ -161,11 +147,7 @@ dnssd_service_stopped_p(VALUE service) {
161
147
  return Qtrue;
162
148
  }
163
149
 
164
- /*
165
- * call-seq:
166
- * service.stop => service
167
- *
168
- * Stops the service, closing the underlying socket and killing the underlying
150
+ /* Stops the service, closing the underlying socket and killing the underlying
169
151
  * thread.
170
152
  *
171
153
  * It is good practice to all stop running services before exit.
@@ -180,9 +162,10 @@ dnssd_service_stopped_p(VALUE service) {
180
162
  static VALUE
181
163
  dnssd_service_stop(VALUE self) {
182
164
  VALUE thread;
183
- DNSServiceRef *client = (DNSServiceRef*)RDATA(self)->data;
165
+ DNSServiceRef *client;
166
+
167
+ get(cDNSSDService, self, DNSServiceRef, client);
184
168
 
185
- /* set to null right away for a bit more thread safety */
186
169
  RDATA(self)->data = NULL;
187
170
 
188
171
  if (client == NULL)
@@ -198,14 +181,25 @@ dnssd_service_stop(VALUE self) {
198
181
 
199
182
  dnssd_service_free_client(client);
200
183
 
184
+ rb_ivar_set(self, dnssd_iv_type, Qnil);
185
+
201
186
  return self;
202
187
  }
203
188
 
189
+ /* Binding to DNSServiceProcessResult
190
+ *
191
+ * When run with a single thread _process will block.
192
+ *
193
+ * _process works intelligently with threads. If a service is waiting on data
194
+ * from the daemon in a thread you can force _process to abort by setting
195
+ * @continue to false and running the thread.
196
+ */
197
+
204
198
  static VALUE
205
199
  dnssd_service_process(VALUE self) {
206
200
  DNSServiceRef *client;
207
201
 
208
- GetDNSSDService(self, client);
202
+ get(cDNSSDService, self, DNSServiceRef, client);
209
203
 
210
204
  if (client == NULL) {
211
205
  /* looks like this thread has already been stopped */
@@ -223,30 +217,80 @@ dnssd_service_process(VALUE self) {
223
217
  return self;
224
218
  }
225
219
 
220
+ /* call-seq:
221
+ * service._add_record(flags, type, data, ttl)
222
+ *
223
+ * Binding to DNSServiceAddRecord
224
+ */
225
+
226
+ static VALUE
227
+ dnssd_service_add_record(VALUE self, VALUE _flags, VALUE _rrtype, VALUE _rdata,
228
+ VALUE _ttl) {
229
+ VALUE _record = Qnil;
230
+ DNSServiceRef *client;
231
+ DNSRecordRef *record;
232
+ DNSServiceFlags flags;
233
+ DNSServiceErrorType e;
234
+ uint16_t rrtype;
235
+ uint16_t rdlen;
236
+ const void *rdata;
237
+ uint32_t ttl;
238
+
239
+ _rdata = rb_str_to_str(_rdata);
240
+ flags = (DNSServiceFlags)NUM2ULONG(_flags);
241
+ rrtype = NUM2UINT(_rrtype);
242
+ rdlen = RSTRING_LEN(_rdata);
243
+ rdata = (void *)RSTRING_PTR(_rdata);
244
+ ttl = NUM2ULONG(_ttl);
245
+
246
+ get(cDNSSDService, self, DNSServiceRef, client);
247
+
248
+ _record = rb_class_new_instance(0, NULL, cDNSSDRecord);
249
+
250
+ get(cDNSSDRecord, _record, DNSRecordRef, record);
251
+
252
+ e = DNSServiceAddRecord(*client, record, flags, rrtype, rdlen, rdata, ttl);
253
+
254
+ dnssd_check_error_code(e);
255
+
256
+ /* record will become invalid when this service is destroyed */
257
+ rb_ivar_set(_record, dnssd_iv_service, self);
258
+ rb_ary_push(rb_ivar_get(self, dnssd_iv_records), _record);
259
+
260
+ return _record;
261
+ }
262
+
226
263
  static void DNSSD_API
227
264
  dnssd_service_browse_reply(DNSServiceRef client, DNSServiceFlags flags,
228
265
  uint32_t interface, DNSServiceErrorType e, const char *name,
229
266
  const char *type, const char *domain, void *context) {
230
- VALUE service, reply;
267
+ VALUE service, reply, argv[6];
231
268
 
232
269
  dnssd_check_error_code(e);
233
270
 
234
271
  service = (VALUE)context;
235
272
 
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));
273
+ argv[0] = service;
274
+ argv[1] = ULONG2NUM(flags);
275
+ argv[2] = ULONG2NUM(interface);
276
+ argv[3] = rb_str_new2(name);
277
+ argv[4] = rb_str_new2(type);
278
+ argv[5] = rb_str_new2(domain);
279
+
280
+ reply = rb_class_new_instance(6, argv, cDNSSDReplyBrowse);
240
281
 
241
282
  dnssd_service_callback(service, reply);
242
283
  }
243
284
 
244
- /* Binding to DNSServiceBrowse
285
+ /* call-seq:
286
+ * service._browse(flags, interface, type, domain)
287
+ *
288
+ * Binding to DNSServiceBrowse
245
289
  */
246
290
 
247
291
  static VALUE
248
- dnssd_service_browse(VALUE self, VALUE _type, VALUE _domain, VALUE _flags,
249
- VALUE _interface) {
292
+ dnssd_service_browse(VALUE self, VALUE _flags, VALUE _interface, VALUE _type,
293
+ VALUE _domain) {
250
294
  const char *type;
251
295
  const char *domain = NULL;
252
296
  DNSServiceFlags flags = 0;
@@ -266,7 +310,7 @@ dnssd_service_browse(VALUE self, VALUE _type, VALUE _domain, VALUE _flags,
266
310
  if (!NIL_P(_interface))
267
311
  interface = NUM2ULONG(_interface);
268
312
 
269
- GetDNSSDService(self, client);
313
+ get(cDNSSDService, self, DNSServiceRef, client);
270
314
 
271
315
  e = DNSServiceBrowse(client, flags, interface, type, domain,
272
316
  dnssd_service_browse_reply, (void *)self);
@@ -280,20 +324,26 @@ static void DNSSD_API
280
324
  dnssd_service_enumerate_domains_reply(DNSServiceRef client,
281
325
  DNSServiceFlags flags, uint32_t interface, DNSServiceErrorType e,
282
326
  const char *domain, void *context) {
283
- VALUE service, reply;
327
+ VALUE service, reply, argv[4];
284
328
 
285
329
  dnssd_check_error_code(e);
286
330
 
287
331
  service = (VALUE)context;
288
332
 
289
- reply = reply_new(service, flags);
290
- reply_set_interface(reply, interface);
291
- rb_ivar_set(reply, dnssd_iv_domain, rb_str_new2(domain));
333
+ argv[0] = service;
334
+ argv[1] = ULONG2NUM(flags);
335
+ argv[2] = ULONG2NUM(interface);
336
+ argv[3] = rb_str_new2(domain);
337
+
338
+ reply = rb_class_new_instance(4, argv, cDNSSDReplyDomain);
292
339
 
293
340
  dnssd_service_callback(service, reply);
294
341
  }
295
342
 
296
- /* Binding to DNSServiceEnumerateDomains
343
+ /* call-seq:
344
+ * service._enumerate_domains(flags, interface)
345
+ *
346
+ * Binding to DNSServiceEnumerateDomains
297
347
  */
298
348
 
299
349
  static VALUE
@@ -310,7 +360,7 @@ dnssd_service_enumerate_domains(VALUE self, VALUE _flags, VALUE _interface) {
310
360
  if (!NIL_P(_interface))
311
361
  interface = NUM2ULONG(_interface);
312
362
 
313
- GetDNSSDService(self, client);
363
+ get(cDNSSDService, self, DNSServiceRef, client);
314
364
 
315
365
  e = DNSServiceEnumerateDomains(client, flags, interface,
316
366
  dnssd_service_enumerate_domains_reply, (void *)self);
@@ -320,36 +370,162 @@ dnssd_service_enumerate_domains(VALUE self, VALUE _flags, VALUE _interface) {
320
370
  return self;
321
371
  }
322
372
 
373
+ #ifdef HAVE_DNSSERVICEGETADDRINFO
374
+ static void DNSSD_API
375
+ dnssd_service_getaddrinfo_reply(DNSServiceRef client, DNSServiceFlags flags,
376
+ uint32_t interface, DNSServiceErrorType e, const char *host,
377
+ const struct sockaddr *address, uint32_t ttl, void *context) {
378
+ VALUE service, reply, argv[6];
379
+
380
+ dnssd_check_error_code(e);
381
+
382
+ service = (VALUE)context;
383
+
384
+ argv[0] = service;
385
+ argv[1] = ULONG2NUM(flags);
386
+ argv[2] = ULONG2NUM(interface);
387
+ argv[3] = rb_str_new2(host);
388
+ argv[4] = rb_str_new((char *)address, SIN_LEN((struct sockaddr_in*)address));
389
+ argv[5] = ULONG2NUM(ttl);
390
+
391
+ reply = rb_class_new_instance(6, argv, cDNSSDReplyAddrInfo);
392
+
393
+ dnssd_service_callback(service, reply);
394
+ }
395
+
396
+ /* call-seq:
397
+ * service._getaddrinfo(flags, interface, host, protocol)
398
+ *
399
+ * Binding to DNSServiceGetAddrInfo
400
+ */
401
+
402
+ static VALUE
403
+ dnssd_service_getaddrinfo(VALUE self, VALUE _flags, VALUE _interface,
404
+ VALUE _protocol, VALUE _host) {
405
+ DNSServiceFlags flags = 0;
406
+ uint32_t interface = 0;
407
+ DNSServiceProtocol protocol = 0;
408
+ const char *host;
409
+
410
+ DNSServiceErrorType e;
411
+ DNSServiceRef *client;
412
+
413
+ host = StringValueCStr(_host);
414
+
415
+ protocol = (DNSServiceProtocol)NUM2ULONG(_protocol);
416
+
417
+ if (!NIL_P(_flags))
418
+ flags = (DNSServiceFlags)NUM2ULONG(_flags);
419
+
420
+ if (!NIL_P(_interface))
421
+ interface = NUM2ULONG(_interface);
422
+
423
+ get(cDNSSDService, self, DNSServiceRef, client);
424
+
425
+ e = DNSServiceGetAddrInfo(client, flags, interface, protocol, host,
426
+ dnssd_service_getaddrinfo_reply, (void *)self);
427
+
428
+ dnssd_check_error_code(e);
429
+
430
+ return self;
431
+ }
432
+ #endif
433
+
434
+ static void DNSSD_API
435
+ dnssd_service_query_record_reply(DNSServiceRef client, DNSServiceFlags flags,
436
+ uint32_t interface, DNSServiceErrorType e, const char *fullname,
437
+ uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata,
438
+ uint32_t ttl, void *context) {
439
+ VALUE service, reply, argv[8];
440
+
441
+ dnssd_check_error_code(e);
442
+
443
+ service = (VALUE)context;
444
+
445
+ argv[0] = service;
446
+ argv[1] = ULONG2NUM(flags);
447
+ argv[2] = ULONG2NUM(interface);
448
+ argv[3] = rb_str_new2(fullname);
449
+ argv[4] = UINT2NUM(rrtype);
450
+ argv[5] = UINT2NUM(rrclass);
451
+ argv[6] = rb_str_new((char *)rdata, rdlen);
452
+ argv[7] = ULONG2NUM(ttl);
453
+
454
+ reply = rb_class_new_instance(8, argv, cDNSSDReplyQueryRecord);
455
+
456
+ dnssd_service_callback(service, reply);
457
+ }
458
+
459
+ /* call-seq:
460
+ * service._query_record(flags, interface, fullname, record_type, record_class)
461
+ *
462
+ * Binding to DNSServiceQueryRecord
463
+ */
464
+
465
+ static VALUE
466
+ dnssd_service_query_record(VALUE self, VALUE _flags, VALUE _interface,
467
+ VALUE _fullname, VALUE _rrtype, VALUE _rrclass) {
468
+ DNSServiceRef *client;
469
+ DNSServiceFlags flags;
470
+ DNSServiceErrorType e;
471
+ char *fullname;
472
+ uint32_t interface;
473
+ uint16_t rrtype;
474
+ uint16_t rrclass;
475
+
476
+ flags = (DNSServiceFlags)NUM2ULONG(_flags);
477
+ interface = NUM2ULONG(_interface);
478
+ fullname = StringValueCStr(_fullname);
479
+ rrtype = NUM2UINT(_rrtype);
480
+ rrclass = NUM2UINT(_rrclass);
481
+
482
+ get(cDNSSDService, self, DNSServiceRef, client);
483
+
484
+ e = DNSServiceQueryRecord(client, flags, interface, fullname, rrtype,
485
+ rrclass, dnssd_service_query_record_reply, (void *)self);
486
+
487
+ dnssd_check_error_code(e);
488
+
489
+ return self;
490
+ }
491
+
323
492
  static void DNSSD_API
324
493
  dnssd_service_register_reply(DNSServiceRef client, DNSServiceFlags flags,
325
494
  DNSServiceErrorType e, const char *name, const char *type,
326
495
  const char *domain, void *context) {
327
- VALUE service, reply;
496
+ VALUE service, reply, argv[5];
328
497
 
329
498
  dnssd_check_error_code(e);
330
499
 
331
500
  service = (VALUE)context;
332
501
 
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));
502
+ argv[0] = service;
503
+ argv[1] = ULONG2NUM(flags);
504
+ argv[2] = rb_str_new2(name);
505
+ argv[3] = rb_str_new2(type);
506
+ argv[4] = rb_str_new2(domain);
507
+
508
+ reply = rb_class_new_instance(5, argv, cDNSSDReplyRegister);
336
509
 
337
510
  dnssd_service_callback(service, reply);
338
511
  }
339
512
 
340
- /* Binding to DNSServiceRegister
513
+ /* call-seq:
514
+ * service._register(flags, interface, name, type, domain, host, port, text_record)
515
+ *
516
+ * Binding to DNSServiceRegister
341
517
  */
342
518
 
343
519
  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) {
520
+ dnssd_service_register(VALUE self, VALUE _flags, VALUE _interface, VALUE _name,
521
+ VALUE _type, VALUE _domain, VALUE _host, VALUE _port, VALUE _text_record) {
347
522
  const char *name, *type, *host = NULL, *domain = NULL;
348
523
  uint16_t port;
349
524
  uint16_t txt_len = 0;
350
525
  char *txt_rec = NULL;
351
526
  DNSServiceFlags flags = 0;
352
527
  uint32_t interface = 0;
528
+ DNSServiceRegisterReply callback = NULL;
353
529
 
354
530
  DNSServiceErrorType e;
355
531
  DNSServiceRef *client;
@@ -376,11 +552,13 @@ dnssd_service_register(VALUE self, VALUE _name, VALUE _type, VALUE _domain,
376
552
  if (!NIL_P(_interface))
377
553
  interface = NUM2ULONG(_interface);
378
554
 
379
- GetDNSSDService(self, client);
555
+ if (rb_block_given_p())
556
+ callback = dnssd_service_register_reply;
557
+
558
+ get(cDNSSDService, self, DNSServiceRef, client);
380
559
 
381
560
  e = DNSServiceRegister(client, flags, interface, name, type,
382
- domain, host, port, txt_len, txt_rec, dnssd_service_register_reply,
383
- (void*)self);
561
+ domain, host, port, txt_len, txt_rec, callback, (void*)self);
384
562
 
385
563
  dnssd_check_error_code(e);
386
564
 
@@ -392,32 +570,34 @@ dnssd_service_resolve_reply(DNSServiceRef client, DNSServiceFlags flags,
392
570
  uint32_t interface, DNSServiceErrorType e, const char *name,
393
571
  const char *target, uint16_t port, uint16_t txt_len,
394
572
  const unsigned char *txt_rec, void *context) {
395
- VALUE service, reply, text_record, text_record_str;
573
+ VALUE service, reply, argv[7];
396
574
 
397
575
  dnssd_check_error_code(e);
398
576
 
399
577
  service = (VALUE)context;
400
578
 
401
- reply = reply_new(service, flags);
579
+ argv[0] = service;
580
+ argv[1] = ULONG2NUM(flags);
581
+ argv[2] = ULONG2NUM(interface);
582
+ argv[3] = rb_str_new2(name);
583
+ argv[4] = rb_str_new2(target);
584
+ argv[5] = UINT2NUM(ntohs(port));
585
+ argv[6] = rb_str_new((char *)txt_rec, txt_len);
402
586
 
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)));
407
-
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);
587
+ reply = rb_class_new_instance(7, argv, cDNSSDReplyResolve);
411
588
 
412
589
  dnssd_service_callback(service, reply);
413
590
  }
414
591
 
415
- /* Binding to DNSServiceResolve
592
+ /* call-seq:
593
+ * service._resolve(flags, interface, name, type, domain)
594
+ *
595
+ * Binding to DNSServiceResolve
416
596
  */
417
597
 
418
598
  static VALUE
419
- dnssd_service_resolve(VALUE self, VALUE _name, VALUE _type, VALUE _domain,
420
- VALUE _flags, VALUE _interface) {
599
+ dnssd_service_resolve(VALUE self, VALUE _flags, VALUE _interface, VALUE _name,
600
+ VALUE _type, VALUE _domain) {
421
601
  const char *name, *type, *domain;
422
602
  DNSServiceFlags flags = 0;
423
603
  uint32_t interface = 0;
@@ -435,7 +615,7 @@ dnssd_service_resolve(VALUE self, VALUE _name, VALUE _type, VALUE _domain,
435
615
  if (!NIL_P(_interface))
436
616
  interface = NUM2ULONG(_interface);
437
617
 
438
- GetDNSSDService(self, client);
618
+ get(cDNSSDService, self, DNSServiceRef, client);
439
619
 
440
620
  e = DNSServiceResolve(client, flags, interface, name, type, domain,
441
621
  dnssd_service_resolve_reply, (void *)self);
@@ -447,40 +627,80 @@ dnssd_service_resolve(VALUE self, VALUE _name, VALUE _type, VALUE _domain,
447
627
 
448
628
  void
449
629
  Init_DNSSD_Service(void) {
450
- VALUE mDNSSD = rb_define_module("DNSSD");
630
+ mDNSSD = rb_define_module("DNSSD");
451
631
 
452
- dnssd_id_join = rb_intern("join");
453
- dnssd_id_push = rb_intern("push");
632
+ dnssd_id_join = rb_intern("join");
633
+ dnssd_id_push = rb_intern("push");
454
634
 
455
635
  dnssd_iv_continue = rb_intern("@continue");
456
- dnssd_iv_domain = rb_intern("@domain");
457
- dnssd_iv_interface = rb_intern("@interface");
458
- dnssd_iv_port = rb_intern("@port");
636
+ dnssd_iv_records = rb_intern("@records");
459
637
  dnssd_iv_replies = rb_intern("@replies");
460
- dnssd_iv_target = rb_intern("@target");
461
- dnssd_iv_text_record = rb_intern("@text_record");
638
+ dnssd_iv_service = rb_intern("@service");
462
639
  dnssd_iv_thread = rb_intern("@thread");
640
+ dnssd_iv_type = rb_intern("@type");
463
641
 
464
- cDNSSDReply = rb_define_class_under(mDNSSD, "Reply", rb_cObject);
465
- cDNSSDService = rb_define_class_under(mDNSSD, "Service", rb_cObject);
466
- cDNSSDTextRecord = rb_define_class_under(mDNSSD, "TextRecord", rb_cObject);
642
+ cDNSSDFlags = rb_define_class_under(mDNSSD, "Flags", rb_cObject);
643
+ cDNSSDRecord = rb_define_class_under(mDNSSD, "Record", rb_cObject);
644
+ cDNSSDService = rb_define_class_under(mDNSSD, "Service", rb_cObject);
645
+ cDNSSDTextRecord = rb_path2class("DNSSD::TextRecord");
467
646
 
647
+ cDNSSDReplyAddrInfo = rb_path2class("DNSSD::Reply::AddrInfo");
648
+ cDNSSDReplyBrowse = rb_path2class("DNSSD::Reply::Browse");
649
+ cDNSSDReplyDomain = rb_path2class("DNSSD::Reply::Domain");
650
+ cDNSSDReplyQueryRecord = rb_path2class("DNSSD::Reply::QueryRecord");
651
+ cDNSSDReplyRegister = rb_path2class("DNSSD::Reply::Register");
652
+ cDNSSDReplyResolve = rb_path2class("DNSSD::Reply::Resolve");
653
+
654
+ rb_cSocket = rb_path2class("Socket");
655
+
656
+
657
+ /* Maximum length for a domain name */
468
658
  rb_define_const(cDNSSDService, "MAX_DOMAIN_NAME",
469
659
  ULONG2NUM(kDNSServiceMaxDomainName));
660
+
661
+ /* Maximum length for a service name */
470
662
  rb_define_const(cDNSSDService, "MAX_SERVICE_NAME",
471
663
  ULONG2NUM(kDNSServiceMaxServiceName));
472
664
 
665
+ #ifdef kDNSServiceProperty_DaemonVersion
666
+ /* DaemonVersion property value */
667
+ rb_define_const(cDNSSDService, "DaemonVersion",
668
+ rb_str_new2(kDNSServiceProperty_DaemonVersion));
669
+ #endif
670
+
671
+ #ifdef HAVE_DNSSERVICEGETPROPERTY
672
+ /* IPv4 protocol for #getaddrinfo */
673
+ rb_define_const(cDNSSDService, "IPv4", ULONG2NUM(kDNSServiceProtocol_IPv4));
674
+
675
+ /* IPv6 protocol for #getaddrinfo */
676
+ rb_define_const(cDNSSDService, "IPv6", ULONG2NUM(kDNSServiceProtocol_IPv6));
677
+
678
+ /* HACK the below are only used by NAT, fix with proper HAVE_ */
679
+
680
+ /* TCP protocol for creating NAT port mappings */
681
+ rb_define_const(cDNSSDService, "TCP", ULONG2NUM(kDNSServiceProtocol_TCP));
682
+
683
+ /* UDP protocol for creating NAT port mappings */
684
+ rb_define_const(cDNSSDService, "UDP", ULONG2NUM(kDNSServiceProtocol_UDP));
685
+ #endif
473
686
 
474
687
  rb_define_alloc_func(cDNSSDService, dnssd_service_s_allocate);
475
688
  rb_define_singleton_method(cDNSSDService, "fullname", dnssd_service_s_fullname, 3);
476
689
 
477
- rb_define_method(cDNSSDService, "started?", dnssd_service_started_p, 0);
690
+ #ifdef HAVE_DNSSERVICEGETPROPERTY
691
+ rb_define_singleton_method(cDNSSDService, "get_property", dnssd_service_s_get_property, 1);
692
+ #endif
478
693
 
479
694
  rb_define_method(cDNSSDService, "stop", dnssd_service_stop, 0);
480
695
  rb_define_method(cDNSSDService, "stopped?", dnssd_service_stopped_p, 0);
481
696
 
697
+ rb_define_method(cDNSSDService, "_add_record", dnssd_service_add_record, 4);
482
698
  rb_define_method(cDNSSDService, "_browse", dnssd_service_browse, 4);
483
699
  rb_define_method(cDNSSDService, "_enumerate_domains", dnssd_service_enumerate_domains, 2);
700
+ #ifdef HAVE_DNSSERVICEGETADDRINFO
701
+ rb_define_method(cDNSSDService, "_getaddrinfo", dnssd_service_getaddrinfo, 4);
702
+ #endif
703
+ rb_define_method(cDNSSDService, "_query_record", dnssd_service_query_record, 5);
484
704
  rb_define_method(cDNSSDService, "_register", dnssd_service_register, 8);
485
705
  rb_define_method(cDNSSDService, "_resolve", dnssd_service_resolve, 5);
486
706