00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 package org.rosbuilding.zeroconf;
00017
00018 import java.io.IOException;
00019 import java.lang.Boolean;
00020 import java.net.InetAddress;
00021 import java.net.Inet4Address;
00022
00023 import java.net.NetworkInterface;
00024 import java.util.Arrays;
00025 import java.util.Collections;
00026 import java.util.Enumeration;
00027 import java.util.Iterator;
00028 import java.util.HashMap;
00029 import java.util.HashSet;
00030 import java.util.List;
00031 import java.util.ArrayList;
00032 import java.util.Map;
00033 import java.util.Set;
00034
00035 import javax.jmdns.JmmDNS;
00036 import javax.jmdns.NetworkTopologyEvent;
00037 import javax.jmdns.NetworkTopologyListener;
00038 import javax.jmdns.ServiceEvent;
00039 import javax.jmdns.ServiceInfo;
00040 import javax.jmdns.ServiceListener;
00041 import javax.jmdns.ServiceTypeListener;
00042
00043 import com.github.rosjava.zeroconf_jmdns_suite.jmdns.ZeroconfDiscoveryHandler;
00044 import com.github.rosjava.zeroconf_jmdns_suite.jmdns.ZeroconfLogger;
00045
00046
00061 public class Zeroconf implements ServiceListener, ServiceTypeListener, NetworkTopologyListener {
00062
00063 private class DefaultLogger implements ZeroconfLogger {
00064 public void println(String msg) {}
00065 }
00066
00067 JmmDNS jmmdns;
00068 Set<String> listeners;
00069 Set<ServiceInfo> services;
00070 ZeroconfLogger logger;
00071 Map<String, ZeroconfDiscoveryHandler> listener_callbacks;
00072 ZeroconfDiscoveryHandler default_listener_callback;
00073
00074 public Zeroconf() {
00075
00076
00077
00078 this.jmmdns = JmmDNS.Factory.getInstance();
00079 this.listeners = new HashSet<String>();
00080 this.services = new HashSet<ServiceInfo>();
00081 this.logger = new DefaultLogger();
00082 this.listener_callbacks = new HashMap<String, ZeroconfDiscoveryHandler>();
00083 this.default_listener_callback = null;
00084
00085
00086
00087
00088
00089 this.jmmdns.addNetworkTopologyListener(this);
00090 }
00091
00092 public Zeroconf(ZeroconfLogger logger) {
00093
00094
00095
00096 this.jmmdns = JmmDNS.Factory.getInstance();
00097 this.listeners = new HashSet<String>();
00098 this.services = new HashSet<ServiceInfo>();
00099 this.logger = logger;
00100 this.listener_callbacks = new HashMap<String, ZeroconfDiscoveryHandler>();
00101 this.default_listener_callback = null;
00102
00103
00104
00105
00106
00107 this.jmmdns.addNetworkTopologyListener(this);
00108 }
00109
00110
00111
00112
00113 public void setDefaultDiscoveryCallback(ZeroconfDiscoveryHandler listener_callback) {
00114 this.default_listener_callback = listener_callback;
00115 }
00116 public void addListener(String service_type, String domain) {
00117 addListener(service_type, domain, this.default_listener_callback);
00118 }
00125 public void addListener(String service_type, String domain, ZeroconfDiscoveryHandler listener_callback) {
00126 String service = service_type + "." + domain + ".";
00127 logger.println("Activating listener: " + service);
00128 listeners.add(service);
00129 if ( listener_callback != null ) {
00130 listener_callbacks.put(service, listener_callback);
00131 }
00132
00133 jmmdns.addServiceListener(service, this);
00134 }
00135
00139 public void removeListener(String service_type, String domain) {
00140 String listener_to_remove = service_type + "." + domain + ".";
00141 for ( Iterator<String> listener = listeners.iterator(); listener.hasNext(); ) {
00142 String this_listener = listener.next().toString();
00143 if ( this_listener.equals(listener_to_remove) ) {
00144 logger.println("Deactivating listener: " + this_listener);
00145 listener.remove();
00146
00147 jmmdns.removeServiceListener(listener_to_remove, this);
00148 break;
00149 }
00150 }
00151 listener_callbacks.remove(listener_to_remove);
00152 }
00165 public void addService(String name, String type, String domain, int port, String description) {
00166 String full_service_type = type + "." + domain + ".";
00167 logger.println("Registering service: " + full_service_type);
00168 String service_key = "description";
00169 HashMap<String, byte[]> properties = new HashMap<String, byte[]>();
00170 properties.put(service_key,description.getBytes());
00171 ServiceInfo service_info = ServiceInfo.create(full_service_type, name, port, 0, 0, true, properties);
00172
00173 if ( services.add(service_info) ) {
00174 try {
00175 jmmdns.registerService(service_info);
00176 } catch (IOException e) {
00177 e.printStackTrace();
00178 }
00179 }
00180
00181
00182
00183
00184 }
00185
00186 public void addService(String name, String type, String domain, int port, HashMap<String, byte[]> properties) {
00187 String full_service_type = type + "." + domain + ".";
00188 logger.println("Registering service: " + full_service_type);
00189 ServiceInfo service_info = ServiceInfo.create(full_service_type, name, port, 0, 0, true, properties);
00190
00191 if ( services.add(service_info) ) {
00192 try {
00193 jmmdns.registerService(service_info);
00194 } catch (IOException e) {
00195 e.printStackTrace();
00196 }
00197 }
00198
00199
00200
00201
00202 }
00203
00204 public void addService(DiscoveredService service) {
00205 String full_service_type = service.type + "." + service.domain + ".";
00206 logger.println("Registering service: " + full_service_type);
00207 ServiceInfo service_info = ServiceInfo.create(full_service_type, service.name, service.port, 0, 0, true, service.properties);
00208
00209 if ( services.add(service_info) ) {
00210 try {
00211 jmmdns.registerService(service_info);
00212 } catch (IOException e) {
00213 e.printStackTrace();
00214 }
00215 }
00216
00217
00218
00219
00220 }
00221
00228 public List<DiscoveredService> listDiscoveredServices() {
00229 List<ServiceInfo> service_infos = new ArrayList<ServiceInfo>();
00230 for(String service : listeners ) {
00231 service_infos.addAll(Arrays.asList(this.jmmdns.list(service)));
00232 }
00233
00234
00235
00236
00237 List<DiscoveredService> discovered_services = new ArrayList<DiscoveredService>();
00238 for(ServiceInfo service_info : service_infos ) {
00239 Boolean service_found = false;
00240 for ( DiscoveredService discovered_service : discovered_services ) {
00241 if ( service_info.getQualifiedName().equals(discovered_service.name+"."+discovered_service.type+"."+discovered_service.domain+".") ) {
00242 for ( InetAddress inet_address : service_info.getInetAddresses() ) {
00243 if ( inet_address instanceof Inet4Address) {
00244 Boolean address_found = false;
00245 for ( String unique_address : discovered_service.ipv4_addresses ) {
00246 if ( inet_address.getHostAddress().equals(unique_address) ) {
00247 address_found = true;
00248 break;
00249 }
00250 }
00251 if ( !address_found ) {
00252 discovered_service.ipv4_addresses.add(inet_address.getHostAddress());
00253 }
00254 } else {
00255 Boolean address_found = false;
00256 for ( String unique_address : discovered_service.ipv6_addresses ) {
00257 if ( inet_address.getHostAddress().equals(unique_address) ) {
00258 address_found = true;
00259 break;
00260 }
00261 }
00262 if ( !address_found ) {
00263 discovered_service.ipv6_addresses.add(inet_address.getHostAddress());
00264 }
00265 }
00266 }
00267 service_found = true;
00268 break;
00269 }
00270 }
00271 if ( !service_found ) {
00272 discovered_services.add(toDiscoveredService(service_info));
00273 }
00274
00275 }
00276 return discovered_services;
00277 }
00278
00283 public void removeAllServices() {
00284 logger.println("Removing all services");
00285 jmmdns.unregisterAllServices();
00286 services.clear();
00287 }
00288
00289 public void shutdown() throws IOException {
00290 removeAllServices();
00291 logger.println("Shutdown");
00292 jmmdns.close();
00293 }
00294
00295
00296
00297
00298 @Override
00299 public void serviceAdded(ServiceEvent event) {
00300 final ServiceInfo service_info = event.getInfo();
00301
00302
00303 jmmdns.getServiceInfos(service_info.getType(), service_info.getName(), true);
00304 ZeroconfDiscoveryHandler callback = listener_callbacks.get(service_info.getType());
00305 if ( callback != null ) {
00306 callback.serviceAdded(toDiscoveredService(service_info));
00307 } else {
00308 logger.println("[+] Service : " + service_info.getQualifiedName());
00309 }
00310 }
00311
00312 @Override
00313 public void serviceRemoved(ServiceEvent event) {
00314 final String name = event.getName();
00315 final ServiceInfo service_info = event.getInfo();
00316 ZeroconfDiscoveryHandler callback = listener_callbacks.get(service_info.getType());
00317 if ( callback != null ) {
00318 callback.serviceRemoved(toDiscoveredService(service_info));
00319 } else {
00320 logger.println("[-] Service : " + name);
00321 }
00322 }
00323
00324 @Override
00333 public void serviceResolved(ServiceEvent event) {
00334 final ServiceInfo service_info = event.getInfo();
00335 ZeroconfDiscoveryHandler callback = listener_callbacks.get(service_info.getType());
00336 if ( callback != null ) {
00337 callback.serviceResolved(toDiscoveredService(service_info));
00338 } else {
00339 logger.println("[=] Resolved : " + service_info.getQualifiedName());
00340 logger.println(" Port : " + service_info.getPort() );
00341 for ( int i = 0; i < service_info.getInetAddresses().length; ++i ) {
00342 logger.println(" Address : " + service_info.getInetAddresses()[i].getHostAddress() );
00343 }
00344 }
00345 }
00346
00347 @Override
00348 public void serviceTypeAdded(ServiceEvent event) {
00349
00350
00351 }
00352
00353 @Override
00354 public void subTypeForServiceTypeAdded(ServiceEvent event) {
00355
00356 }
00357
00358
00359
00360
00361 @Override
00362 public void inetAddressAdded(NetworkTopologyEvent event) {
00363 try {
00364 logger.println("[+] NetworkInterface: " + event.getInetAddress().getHostAddress() + " [" + NetworkInterface.getByInetAddress(event.getInetAddress()).getDisplayName() + "]");
00365 } catch (IOException e) {
00366 e.printStackTrace();
00367 }
00368 try {
00369 event.getDNS().addServiceTypeListener(this);
00370 for(String listener : listeners ) {
00371 logger.println(" Adding service listener '" + listener + "'");
00372 event.getDNS().addServiceListener(listener, this);
00373 }
00374 for (ServiceInfo service : services ) {
00375 logger.println("Publishing Service on " + event.getInetAddress().getHostAddress());
00376 logger.println(" Name : " + service.getName() );
00377 logger.println(" Type : " + service.getType() );
00378 logger.println(" Port : " + service.getPort() );
00379 event.getDNS().registerService(service.clone());
00380 }
00381 } catch (IOException e) {
00382 e.printStackTrace();
00383 }
00384 }
00385
00386 @Override
00387 public void inetAddressRemoved(NetworkTopologyEvent event) {
00388 String event_address_str = event.getInetAddress().getHostAddress();
00389
00390
00391
00392 logger.println("[-] NetworkInterface: " + event_address_str);
00393
00394
00395
00396
00397
00398 event.getDNS().removeServiceTypeListener(this);
00399 for(String listener : listeners ) {
00400 logger.println(" Removing service listener '" + listener + "'");
00401 event.getDNS().removeServiceListener(listener, this);
00402 }
00403 for (ServiceInfo service : services ) {
00404 logger.println("Unpublishing Service:");
00405 logger.println(" Name : " + service.getName() );
00406 logger.println(" Type : " + service.getType() );
00407 logger.println(" Port : " + service.getPort() );
00408 event.getDNS().unregisterService(service);
00409 }
00410 }
00411
00412
00413
00414
00415 public void display(DiscoveredService discovered_service) {
00416 logger.println("Discovered Service:");
00417 logger.println(" Name : " + discovered_service.name );
00418 logger.println(" Type : " + discovered_service.type );
00419 logger.println(" Port : " + discovered_service.port );
00420 for ( String address : discovered_service.ipv4_addresses ) {
00421 logger.println(" Address: " + address );
00422 }
00423 for ( String address : discovered_service.ipv6_addresses ) {
00424 logger.println(" Address: " + address );
00425 }
00426 }
00427
00428 public String toString(DiscoveredService discovered_service) {
00429 String result = "Service Info:\n";
00430 result += " Name : " + discovered_service.name + "\n";
00431 result += " Type : " + discovered_service.type + "\n";
00432 result += " Port : " + discovered_service.port + "\n";
00433 for ( String address : discovered_service.ipv4_addresses ) {
00434 result += " Address: " + address + "\n";
00435 }
00436 for ( String address : discovered_service.ipv6_addresses ) {
00437 result += " Address: " + address + "\n";
00438 }
00439 return result;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 private DiscoveredService toDiscoveredService(ServiceInfo service_info) {
00470 DiscoveredService discovered_service = new DiscoveredService();
00471 discovered_service.name = service_info.getName();
00472 String[] type_domain_str = service_info.getType().split("\\.");
00473 discovered_service.type = type_domain_str[0] + "." + type_domain_str[1];
00474 discovered_service.domain = service_info.getDomain();
00475 discovered_service.hostname = service_info.getServer();
00476 discovered_service.port = service_info.getPort();
00477 for ( InetAddress inet_address : service_info.getInetAddresses() ) {
00478 if ( inet_address instanceof Inet4Address) {
00479 discovered_service.ipv4_addresses.add(inet_address.getHostAddress());
00480 } else {
00481 discovered_service.ipv6_addresses.add(inet_address.getHostAddress());
00482 }
00483 }
00484
00485 Enumeration<String> propertyNames = service_info.getPropertyNames();
00486 if (propertyNames != null) {
00487 ArrayList<String> properties = Collections.list(propertyNames);
00488
00489 for (String name : properties) {
00490 String property = service_info.getPropertyString(name);
00491
00492
00493
00494
00495 if (property != null) {
00496 discovered_service.properties.put(name, property);
00497 }
00498 }
00499 }
00500
00501 return discovered_service;
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 }