HEAD: an extra unit test for wvbase64 that I forgot to check in a while ago.
[wvapps.git] / wvprint / wvzeroconfbrowser.cc
blobaec4ad9cacb5d10844de69ba876269416c9f90ae
1 /*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 2004 Net Integration Technologies, Inc.
5 * Authors:
6 * Hubert Figuiere <hub@nit.ca>
8 * This is the Zeroconf browser class
9 * Needs Howl http://www.porchdogsoft.com/products/howl/
14 #include "wvstring.h"
15 #include "uniconf.h"
16 #include "wvzeroconfbrowser.h"
18 #include "howl.h"
22 static
23 sw_result my_service_reply(
24 sw_discovery discovery,
25 sw_discovery_oid oid,
26 sw_discovery_publish_status status,
27 sw_opaque extra)
29 return SW_OKAY;
34 sw_result WvZeroconfBrowser::zeroconf_resolver(sw_discovery discovery,
35 sw_discovery_oid oid,
36 sw_uint32 interface_index,
37 sw_const_string name,
38 sw_const_string type,
39 sw_const_string domain,
40 sw_ipv4_address address,
41 sw_port port,
42 sw_octets text_record,
43 sw_uint32 text_record_len,
44 sw_opaque_t extra)
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];
51 sw_uint32 oval_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);
75 exit:
76 return err;
80 sw_result WvZeroconfBrowser::zeroconf_browser(sw_discovery discovery,
81 sw_discovery_oid oid,
82 sw_discovery_browse_status status,
83 sw_uint32 interface_index,
84 sw_const_string name,
85 sw_const_string type,
86 sw_const_string domain,
87 sw_opaque_t extra)
89 WvZeroconfBrowser *watcher = static_cast<WvZeroconfBrowser *>(extra);
91 return watcher->_zeroconf_browser(discovery, oid, status, interface_index,
92 name, type, domain);
96 sw_result WvZeroconfBrowser::_zeroconf_browser(sw_discovery discovery,
97 sw_discovery_oid oid,
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);
107 switch (status)
109 case SW_DISCOVERY_BROWSE_ADD_SERVICE:
110 services.add(new WvZeroconfService(*this, status, name,
111 type, domain, interface_index),
112 false);
114 log(WvLog::Debug1, "ZeroConf browse add service %s %s\n", name, type);
116 break;
117 case SW_DISCOVERY_BROWSE_REMOVE_SERVICE:
118 services.add(new WvZeroconfService(*this, status, name,
119 type, domain, interface_index),
120 false);
121 log(WvLog::Debug1, "ZeroConf browse remove service %s %s\n", name, type);
123 break;
124 default:
125 break;
128 return SW_OKAY;
132 WvZeroconfBrowser::WvZeroconfBrowser(WvStringParm service)
133 : WvFdStream(), log("WvZeroconfBrowser", WvLog::Error),
134 zeroconf_session(NULL)
136 sw_result err;
138 err = sw_discovery_init(&zeroconf_session);
139 if (err != SW_OKAY)
141 log(WvLog::Error, "Unable to init Zeroconf\n");
142 seterr(err);
144 else
146 // This will never work on MacOS X due to howl limitation
147 int socket = sw_discovery_socket(zeroconf_session);
148 assert(zeroconf_session);
149 setfd(socket);
151 sw_discovery_oid oid;
152 err = sw_discovery_browse(zeroconf_session, 0, service, NULL,
153 zeroconf_browser, this, &oid);
154 assert(zeroconf_session);
155 if (err != SW_OKAY)
157 log("sw_discovery_browse() failed\n");
158 seterr(err);
164 WvZeroconfBrowser::~WvZeroconfBrowser()
166 // must delete the services.
167 services.zap(true);
172 void WvZeroconfBrowser::close()
174 if (zeroconf_session)
176 sw_discovery_fina(zeroconf_session);
177 assert(zeroconf_session);
178 zeroconf_session = NULL;
181 WvFdStream::close();
185 void WvZeroconfBrowser::execute(void)
187 WvStream::execute();
189 sw_result err = sw_discovery_read_socket(zeroconf_session);
190 assert(zeroconf_session);
191 if (err != SW_OKAY)
193 log("sw_discovery_read_socket failed (%s)\n", err);
194 seterr(err);
199 WvZeroconfService *WvZeroconfBrowser::pop_first_service(void)
201 WvZeroconfService *service = NULL;
202 if (services.isempty())
204 return NULL;
207 service = services.first();
208 services.unlink_first();
210 return service;
214 bool WvZeroconfBrowser::publish(WvStringParm name, WvStringParm type,
215 WvStringParm port)
217 sw_result result;
218 sw_text_record text_record;
219 sw_discovery_publish_id id;
221 log(WvLog::Debug, "WvZeroconfBrowser::publish(%s %s %s)\n", name, type,
222 port);
224 if (sw_text_record_init(&text_record) != SW_OKAY)
226 log(WvLog::Error, "sw_text_record_init() failed\n");
227 return false;
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");
239 return false;
241 sw_text_record_fina(text_record);
243 return true;
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),
253 &oid) != SW_OKAY)
257 return true;
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,
268 sw_port port,
269 sw_octets text_record,
270 sw_uint32 text_record_len,
271 sw_opaque_t extra)
273 char name_buf[16];
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);
283 delete cfg;
284 return err;