dnssd 1.2 → 1.3

Sign up to get free protection for your applications and to get access to all the features.
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