2 * Worldvisions Weaver Software:
3 * Copyright (C) 2004 Net Integration Technologies, Inc.
6 * Hubert Figuiere <hub@nit.ca>
8 * This is the Zeroconf browser class
9 * Needs Howl http://www.porchdogsoft.com/products/howl/
16 #include "wvzeroconfbrowser.h"
23 sw_result
my_service_reply(
24 sw_discovery discovery
,
26 sw_discovery_publish_status status
,
34 sw_result
WvZeroconfBrowser::zeroconf_resolver(sw_discovery discovery
,
36 sw_uint32 interface_index
,
39 sw_const_string domain
,
40 sw_ipv4_address address
,
42 sw_octets text_record
,
43 sw_uint32 text_record_len
,
46 sw_text_record_iterator it
;
47 // sw_int8 name_buf[16];
48 sw_int8 key
[SW_TEXT_RECORD_MAX_LEN
];
49 // sw_int8 sval[SW_TEXT_RECORD_MAX_LEN];
50 sw_uint8 oval
[SW_TEXT_RECORD_MAX_LEN
];
52 sw_result err
= SW_OKAY
;
54 // WvZeroconfBrowser *watcher = static_cast<WvZeroconfBrowser *>(extra);
56 sw_discovery_cancel(discovery
, oid
);
58 // fprintf(stderr, "resolve reply: 0x%x %s %s %s %s %d\n", interface_index,
59 // (char*)name, type, domain, sw_ipv4_address_name(address, name_buf, 16), port);
61 if ((text_record_len
> 0) && (text_record
) && (*text_record
!= '\0'))
63 err
= sw_text_record_iterator_init(&it
, text_record
, text_record_len
);
64 sw_check_okay(err
, exit
);
66 while (sw_text_record_iterator_next(it
, (char*)key
, oval
,
67 &oval_len
) == SW_OKAY
)
69 // fprintf(stderr, "key = %s, data is %d bytes\n", (char*)key, oval_len);
72 err
= sw_text_record_iterator_fina(it
);
73 sw_check_okay(err
, exit
);
80 sw_result
WvZeroconfBrowser::zeroconf_browser(sw_discovery discovery
,
82 sw_discovery_browse_status status
,
83 sw_uint32 interface_index
,
86 sw_const_string domain
,
89 WvZeroconfBrowser
*watcher
= static_cast<WvZeroconfBrowser
*>(extra
);
91 return watcher
->_zeroconf_browser(discovery
, oid
, status
, interface_index
,
96 sw_result
WvZeroconfBrowser::_zeroconf_browser(sw_discovery discovery
,
98 sw_discovery_browse_status status
,
99 sw_uint32 interface_index
,
100 sw_const_string name
,
101 sw_const_string type
,
102 sw_const_string domain
)
104 // sw_discovery_resolve_id rid;
105 assert(zeroconf_session
== discovery
);
109 case SW_DISCOVERY_BROWSE_ADD_SERVICE
:
110 services
.add(new WvZeroconfService(*this, status
, name
,
111 type
, domain
, interface_index
),
114 log(WvLog::Debug1
, "ZeroConf browse add service %s %s\n", name
, type
);
117 case SW_DISCOVERY_BROWSE_REMOVE_SERVICE
:
118 services
.add(new WvZeroconfService(*this, status
, name
,
119 type
, domain
, interface_index
),
121 log(WvLog::Debug1
, "ZeroConf browse remove service %s %s\n", name
, type
);
132 WvZeroconfBrowser::WvZeroconfBrowser(WvStringParm service
)
133 : WvFdStream(), log("WvZeroconfBrowser", WvLog::Error
),
134 zeroconf_session(NULL
)
138 err
= sw_discovery_init(&zeroconf_session
);
141 log(WvLog::Error
, "Unable to init Zeroconf\n");
146 // This will never work on MacOS X due to howl limitation
147 int socket
= sw_discovery_socket(zeroconf_session
);
148 assert(zeroconf_session
);
151 sw_discovery_oid oid
;
152 err
= sw_discovery_browse(zeroconf_session
, 0, service
, NULL
,
153 zeroconf_browser
, this, &oid
);
154 assert(zeroconf_session
);
157 log("sw_discovery_browse() failed\n");
164 WvZeroconfBrowser::~WvZeroconfBrowser()
166 // must delete the services.
172 void WvZeroconfBrowser::close()
174 if (zeroconf_session
)
176 sw_discovery_fina(zeroconf_session
);
177 assert(zeroconf_session
);
178 zeroconf_session
= NULL
;
185 void WvZeroconfBrowser::execute(void)
189 sw_result err
= sw_discovery_read_socket(zeroconf_session
);
190 assert(zeroconf_session
);
193 log("sw_discovery_read_socket failed (%s)\n", err
);
199 WvZeroconfService
*WvZeroconfBrowser::pop_first_service(void)
201 WvZeroconfService
*service
= NULL
;
202 if (services
.isempty())
207 service
= services
.first();
208 services
.unlink_first();
214 bool WvZeroconfBrowser::publish(WvStringParm name
, WvStringParm type
,
218 sw_text_record text_record
;
219 sw_discovery_publish_id id
;
221 log(WvLog::Debug
, "WvZeroconfBrowser::publish(%s %s %s)\n", name
, type
,
224 if (sw_text_record_init(&text_record
) != SW_OKAY
)
226 log(WvLog::Error
, "sw_text_record_init() failed\n");
229 assert(zeroconf_session
);
230 result
= sw_discovery_publish(zeroconf_session
, 0, name
, type
,
231 NULL
, NULL
, port
.num(),
232 sw_text_record_bytes(text_record
),
233 sw_text_record_len(text_record
),
234 my_service_reply
, NULL
, &id
);
235 assert(zeroconf_session
);
236 if (result
!= SW_OKAY
)
238 log(WvLog::Error
, "sw_discovery_publish() failed\n");
241 sw_text_record_fina(text_record
);
247 bool WvZeroconfService::resolve(UniConf
&cfg
)
249 sw_discovery_oid oid
;
250 if (sw_discovery_resolve(resolver
.session(), interface_index
, name
,
251 type
, domain
, zeroconf_resolver
,
252 (sw_opaque_t
)new UniConf(cfg
),
261 sw_result
WvZeroconfService::zeroconf_resolver(sw_discovery discovery
,
262 sw_discovery_oid oid
,
263 sw_uint32 interface_index
,
264 sw_const_string name
,
265 sw_const_string type
,
266 sw_const_string domain
,
267 sw_ipv4_address address
,
269 sw_octets text_record
,
270 sw_uint32 text_record_len
,
274 sw_result err
= SW_OKAY
;
276 UniConf
*cfg
= static_cast<UniConf
*>(extra
);
278 sw_discovery_cancel(discovery
, oid
);
280 (*cfg
)["ip"].setme((char*)sw_ipv4_address_name(address
, name_buf
, 16));
281 (*cfg
)["port"].setmeint(port
);