Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 package com.github.rosjava.zeroconf_jmdns_suite.jmdns;
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.Iterator;
00026 import java.util.HashMap;
00027 import java.util.HashSet;
00028 import java.util.List;
00029 import java.util.ArrayList;
00030 import java.util.Map;
00031 import java.util.Set;
00032 import javax.jmdns.JmmDNS;
00033 import javax.jmdns.NetworkTopologyEvent;
00034 import javax.jmdns.NetworkTopologyListener;
00035 import javax.jmdns.ServiceEvent;
00036 import javax.jmdns.ServiceInfo;
00037 import javax.jmdns.ServiceListener;
00038 import javax.jmdns.ServiceTypeListener;
00039 
00040 import com.github.rosjava.zeroconf_jmdns_suite.jmdns.DiscoveredService;
00041 
00042 
00057 public class Zeroconf implements ServiceListener, ServiceTypeListener, NetworkTopologyListener {
00058 
00059         private class DefaultLogger implements ZeroconfLogger {
00060                 public void println(String msg) {}
00061         }
00062         
00063     JmmDNS jmmdns;
00064     Set<String> listeners;
00065     Set<ServiceInfo> services;
00066     ZeroconfLogger logger;
00067     Map<String, ZeroconfDiscoveryHandler> listener_callbacks;
00068     ZeroconfDiscoveryHandler default_listener_callback;
00069 
00070     public Zeroconf() {
00071         
00072 
00073 
00074         this.jmmdns = JmmDNS.Factory.getInstance();
00075         this.listeners = new HashSet<String>();
00076         this.services = new HashSet<ServiceInfo>();
00077         this.logger = new DefaultLogger();
00078         this.listener_callbacks = new HashMap<String, ZeroconfDiscoveryHandler>();
00079         this.default_listener_callback = null;
00080 
00081         
00082 
00083 
00084         
00085         this.jmmdns.addNetworkTopologyListener(this);
00086     }
00087 
00088     public Zeroconf(ZeroconfLogger logger) {
00089         
00090 
00091 
00092         this.jmmdns = JmmDNS.Factory.getInstance();
00093         this.listeners = new HashSet<String>();
00094         this.services = new HashSet<ServiceInfo>();
00095         this.logger = logger;
00096         this.listener_callbacks = new HashMap<String, ZeroconfDiscoveryHandler>();
00097         this.default_listener_callback = null;
00098 
00099         
00100 
00101 
00102         
00103         this.jmmdns.addNetworkTopologyListener(this);
00104     }
00105 
00106         
00107 
00108 
00109     public void setDefaultDiscoveryCallback(ZeroconfDiscoveryHandler listener_callback) {
00110         this.default_listener_callback = listener_callback;
00111     }
00112     public void addListener(String service_type, String domain) {
00113         addListener(service_type, domain, this.default_listener_callback);
00114     }
00121     public void addListener(String service_type, String domain, ZeroconfDiscoveryHandler listener_callback) {
00122         String service = service_type + "." + domain + ".";
00123         logger.println("Activating listener: " + service);
00124         listeners.add(service);
00125         if ( listener_callback != null ) { 
00126                 listener_callbacks.put(service, listener_callback);
00127         }
00128         
00129         jmmdns.addServiceListener(service, this);
00130     }
00131     
00135     public void removeListener(String service_type, String domain) {
00136         String listener_to_remove = service_type + "." + domain + ".";
00137         for ( Iterator<String> listener = listeners.iterator(); listener.hasNext(); ) {
00138                 String this_listener = listener.next().toString();
00139                 if ( this_listener.equals(listener_to_remove) ) { 
00140                         logger.println("Deactivating listener: " + this_listener);
00141                 listener.remove();
00142                 
00143                                 jmmdns.removeServiceListener(listener_to_remove, this);
00144                                 break;
00145                 }
00146         }
00147         listener_callbacks.remove(listener_to_remove);
00148     }
00161     public void addService(String name, String type, String domain, int port, String description) {
00162         String full_service_type = type + "." + domain + ".";
00163         logger.println("Registering service: " + full_service_type);
00164         String service_key = "description"; 
00165         HashMap<String, byte[]> properties = new HashMap<String, byte[]>();
00166         properties.put(service_key,description.getBytes());
00167         ServiceInfo service_info = ServiceInfo.create(full_service_type, name, port, 0, 0, true, properties);
00168         
00169         if ( services.add(service_info) ) {
00170                 try {
00171                         jmmdns.registerService(service_info);
00172             } catch (IOException e) {
00173                 e.printStackTrace();
00174             }
00175         }
00176         
00177         
00178         
00179         
00180     }
00181 
00188     public List<DiscoveredService> listDiscoveredServices() {
00189         List<ServiceInfo> service_infos = new ArrayList<ServiceInfo>();
00190         for(String service : listeners ) {
00191                 service_infos.addAll(Arrays.asList(this.jmmdns.list(service)));
00192         }
00193         
00194         
00195         
00196         
00197         List<DiscoveredService> discovered_services = new ArrayList<DiscoveredService>();
00198         for(ServiceInfo service_info : service_infos ) {
00199                 Boolean service_found = false;
00200                 for ( DiscoveredService discovered_service : discovered_services ) {
00201                         if ( service_info.getQualifiedName().equals(discovered_service.name+"."+discovered_service.type+"."+discovered_service.domain+".") ) {
00202                                 for ( InetAddress inet_address : service_info.getInetAddresses() ) {
00203                                         if ( inet_address instanceof Inet4Address) {
00204                                                 Boolean address_found = false;
00205                                         for ( String unique_address : discovered_service.ipv4_addresses ) {
00206                                                 if ( inet_address.getHostAddress().equals(unique_address) ) {
00207                                                         address_found = true;
00208                                                         break;
00209                                                 }
00210                                         }
00211                                         if ( !address_found ) {
00212                                                 discovered_service.ipv4_addresses.add(inet_address.getHostAddress());
00213                                         }
00214                                         } else { 
00215                                                 Boolean address_found = false;
00216                                         for ( String unique_address : discovered_service.ipv6_addresses ) {
00217                                                 if ( inet_address.getHostAddress().equals(unique_address) ) {
00218                                                         address_found = true;
00219                                                         break;
00220                                                 }
00221                                         }
00222                                         if ( !address_found ) {
00223                                                 discovered_service.ipv6_addresses.add(inet_address.getHostAddress());
00224                                         }
00225                                         }
00226                                 }
00227                                 service_found = true;
00228                                 break;
00229                         }
00230                 }
00231                 if ( !service_found ) {
00232                         discovered_services.add(toDiscoveredService(service_info));
00233                 }
00234                 
00235         }
00236         return discovered_services;
00237     }
00238 
00243     public void removeAllServices() {
00244         logger.println("Removing all services");
00245         jmmdns.unregisterAllServices();
00246         services.clear();
00247     }
00248     
00249     public void shutdown() throws IOException {
00250         removeAllServices();
00251         logger.println("Shutdown");
00252         jmmdns.close();
00253     }
00254     
00255         
00256 
00257 
00258     @Override
00259     public void serviceAdded(ServiceEvent event) {
00260         final ServiceInfo service_info = event.getInfo();
00261         
00262         
00263         jmmdns.getServiceInfos(service_info.getType(), service_info.getName(), true);
00264         ZeroconfDiscoveryHandler callback = listener_callbacks.get(service_info.getType());
00265         if ( callback != null ) {
00266                 callback.serviceAdded(toDiscoveredService(service_info));
00267         } else {
00268             logger.println("[+] Service         : " + service_info.getQualifiedName());
00269         }
00270     }
00271 
00272     @Override
00273     public void serviceRemoved(ServiceEvent event) {
00274         final String name = event.getName();
00275         final ServiceInfo service_info = event.getInfo();
00276         ZeroconfDiscoveryHandler callback = listener_callbacks.get(service_info.getType());
00277         if ( callback != null ) {
00278                 callback.serviceRemoved(toDiscoveredService(service_info));
00279         } else {
00280             logger.println("[-] Service         : " + name);
00281         }
00282     }
00283 
00284     @Override
00293     public void serviceResolved(ServiceEvent event) {
00294         final ServiceInfo service_info = event.getInfo();
00295         ZeroconfDiscoveryHandler callback = listener_callbacks.get(service_info.getType());
00296         if ( callback != null ) {
00297                 callback.serviceResolved(toDiscoveredService(service_info));
00298         } else {
00299             logger.println("[=] Resolved        : " + service_info.getQualifiedName());
00300                 logger.println("      Port          : " + service_info.getPort() );
00301                 for ( int i = 0; i < service_info.getInetAddresses().length; ++i ) {
00302                 logger.println("      Address       : " + service_info.getInetAddresses()[i].getHostAddress() );
00303                 }
00304         }
00305     }
00306 
00307     @Override
00308     public void serviceTypeAdded(ServiceEvent event) {
00309 
00310 
00311     }
00312 
00313     @Override
00314     public void subTypeForServiceTypeAdded(ServiceEvent event) {
00315 
00316     }
00317 
00318         
00319 
00320 
00321     @Override
00322         public void inetAddressAdded(NetworkTopologyEvent event) {
00323                 try {
00324                         logger.println("[+] NetworkInterface: " + event.getInetAddress().getHostAddress() + " [" + NetworkInterface.getByInetAddress(event.getInetAddress()).getDisplayName() + "]");
00325                 } catch (IOException e) {
00326                 e.printStackTrace();
00327         }
00328         try {
00329                 event.getDNS().addServiceTypeListener(this);
00330                 for(String listener : listeners ) {
00331                         logger.println("      Adding service listener '" + listener + "'");
00332                 event.getDNS().addServiceListener(listener, this);
00333                 }
00334                 for (ServiceInfo service : services ) {
00335                         logger.println("Publishing Service on " + event.getInetAddress().getHostAddress());
00336                         logger.println("  Name   : " + service.getName() );
00337                         logger.println("  Type   : " + service.getType() );
00338                         logger.println("  Port   : " + service.getPort() );
00339                 event.getDNS().registerService(service.clone()); 
00340                 }
00341         } catch (IOException e) {
00342                 e.printStackTrace();
00343         }
00344         }
00345         
00346     @Override
00347     public void inetAddressRemoved(NetworkTopologyEvent event) {
00348         String event_address_str = event.getInetAddress().getHostAddress();
00349         
00350         
00351         
00352                 logger.println("[-] NetworkInterface: " + event_address_str);
00353                 
00354                 
00355                 
00356                 
00357 
00358                 event.getDNS().removeServiceTypeListener(this);
00359         for(String listener : listeners ) {
00360                 logger.println("      Removing service listener '" + listener + "'");
00361                 event.getDNS().removeServiceListener(listener, this);
00362         }
00363         for (ServiceInfo service : services ) {
00364                 logger.println("Unpublishing Service:");
00365                 logger.println("  Name   : " + service.getName() );
00366                 logger.println("  Type   : " + service.getType() );
00367                 logger.println("  Port   : " + service.getPort() );
00368                 event.getDNS().unregisterService(service); 
00369         }
00370         }
00371 
00372     
00373 
00374 
00375     public void display(DiscoveredService discovered_service) {
00376         logger.println("Discovered Service:");
00377         logger.println("  Name   : " + discovered_service.name );
00378         logger.println("  Type   : " + discovered_service.type );
00379         logger.println("  Port   : " + discovered_service.port );
00380         for ( String address : discovered_service.ipv4_addresses ) {
00381                 logger.println("  Address: " + address );
00382         }
00383         for ( String address : discovered_service.ipv6_addresses ) {
00384                 logger.println("  Address: " + address );
00385         }
00386     }
00387 
00388     public String toString(DiscoveredService discovered_service) {
00389         String result = "Service Info:\n";
00390         result += "  Name   : " + discovered_service.name + "\n";
00391         result += "  Type   : " + discovered_service.type + "\n";
00392         result += "  Port   : " + discovered_service.port + "\n";
00393         for ( String address : discovered_service.ipv4_addresses ) {
00394                 result += "  Address: " + address + "\n";
00395         }
00396         for ( String address : discovered_service.ipv6_addresses ) {
00397                 result += "  Address: " + address + "\n";
00398         }
00399         return result;
00400     }
00401 
00402     
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426     
00427 
00428 
00429     private DiscoveredService toDiscoveredService(ServiceInfo service_info) {
00430         DiscoveredService discovered_service = new DiscoveredService();
00431                 discovered_service.name = service_info.getName();
00432                 String[] type_domain_str = service_info.getType().split("\\.");
00433                 discovered_service.type = type_domain_str[0] + "." + type_domain_str[1];
00434                 discovered_service.domain = service_info.getDomain();
00435                 discovered_service.hostname = service_info.getServer();
00436                 discovered_service.port = service_info.getPort();
00437                 for ( InetAddress inet_address : service_info.getInetAddresses() ) {
00438                         if ( inet_address instanceof Inet4Address) {
00439                                 discovered_service.ipv4_addresses.add(inet_address.getHostAddress());
00440                         } else { 
00441                                 discovered_service.ipv6_addresses.add(inet_address.getHostAddress());
00442                         }
00443                 }
00444         return discovered_service;
00445     }
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00459 
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467 
00468 }