Go to the documentation of this file.00001 package ros.zeroconf.jmdns;
00002 
00003 import java.io.IOException;
00004 import java.lang.Thread;
00005 import java.lang.Boolean;
00006 import java.net.InetAddress;
00007 import java.net.Inet4Address;
00008 import java.net.Inet6Address;
00009 import java.net.NetworkInterface;
00010 import java.util.Arrays;
00011 import java.util.Iterator;
00012 import java.util.HashMap;
00013 import java.util.HashSet;
00014 import java.util.List;
00015 import java.util.ArrayList;
00016 import java.util.Map;
00017 import java.util.Set;
00018 import javax.jmdns.JmmDNS;
00019 import javax.jmdns.NetworkTopologyEvent;
00020 import javax.jmdns.NetworkTopologyListener;
00021 import javax.jmdns.ServiceEvent;
00022 import javax.jmdns.ServiceInfo;
00023 import javax.jmdns.ServiceListener;
00024 import javax.jmdns.ServiceTypeListener;
00025 import org.ros.message.zeroconf_comms.DiscoveredService;
00026 
00041 public class Zeroconf implements ServiceListener, ServiceTypeListener, NetworkTopologyListener {
00042 
00043         private class DefaultLogger implements ZeroconfLogger {
00044                 public void println(String msg) {}
00045         }
00046         
00047     JmmDNS jmmdns;
00048     Set<String> listeners;
00049     Set<ServiceInfo> services;
00050     ZeroconfLogger logger;
00051     Map<String, ZeroconfDiscoveryHandler> listener_callbacks;
00052     ZeroconfDiscoveryHandler default_listener_callback;
00053 
00054     public Zeroconf() {
00055         
00056 
00057 
00058         this.jmmdns = JmmDNS.Factory.getInstance();
00059         this.listeners = new HashSet<String>();
00060         this.services = new HashSet<ServiceInfo>();
00061         this.logger = new DefaultLogger();
00062         this.listener_callbacks = new HashMap<String, ZeroconfDiscoveryHandler>();
00063         this.default_listener_callback = null;
00064 
00065         
00066 
00067 
00068         
00069         this.jmmdns.addNetworkTopologyListener(this);
00070     }
00071 
00072     public Zeroconf(ZeroconfLogger logger) {
00073         
00074 
00075 
00076         this.jmmdns = JmmDNS.Factory.getInstance();
00077         this.listeners = new HashSet<String>();
00078         this.services = new HashSet<ServiceInfo>();
00079         this.logger = logger;
00080         this.listener_callbacks = new HashMap<String, ZeroconfDiscoveryHandler>();
00081         this.default_listener_callback = null;
00082 
00083         
00084 
00085 
00086         
00087         this.jmmdns.addNetworkTopologyListener(this);
00088     }
00089 
00090         
00091 
00092 
00093     public void setDefaultDiscoveryCallback(ZeroconfDiscoveryHandler listener_callback) {
00094         this.default_listener_callback = listener_callback;
00095     }
00096     public void addListener(String service_type, String domain) {
00097         addListener(service_type, domain, this.default_listener_callback);
00098     }
00105     public void addListener(String service_type, String domain, ZeroconfDiscoveryHandler listener_callback) {
00106         String service = service_type + "." + domain + ".";
00107         logger.println("Activating listener: " + service);
00108         listeners.add(service);
00109         if ( listener_callback != null ) { 
00110                 listener_callbacks.put(service, listener_callback);
00111         }
00112         
00113         jmmdns.addServiceListener(service, this);
00114     }
00115     
00119     public void removeListener(String service_type, String domain) {
00120         String listener_to_remove = service_type + "." + domain + ".";
00121         for ( Iterator<String> listener = listeners.iterator(); listener.hasNext(); ) {
00122                 String this_listener = listener.next().toString();
00123                 if ( this_listener.equals(listener_to_remove) ) { 
00124                         logger.println("Deactivating listener: " + this_listener);
00125                 listener.remove();
00126                 
00127                                 jmmdns.removeServiceListener(listener_to_remove, this);
00128                                 break;
00129                 }
00130         }
00131         listener_callbacks.remove(listener_to_remove);
00132     }
00145     public void addService(String name, String type, String domain, int port, String description) {
00146         String full_service_type = type + "." + domain + ".";
00147         logger.println("Registering service: " + full_service_type);
00148         String service_key = "description"; 
00149         HashMap<String, byte[]> properties = new HashMap<String, byte[]>();
00150         properties.put(service_key,description.getBytes());
00151         ServiceInfo service_info = ServiceInfo.create(full_service_type, name, port, 0, 0, true, properties);
00152         
00153         if ( services.add(service_info) ) {
00154                 try {
00155                         jmmdns.registerService(service_info);
00156             } catch (IOException e) {
00157                 e.printStackTrace();
00158             }
00159         }
00160         
00161         
00162         
00163         
00164     }
00165 
00172     public List<DiscoveredService> listDiscoveredServices() {
00173         List<ServiceInfo> service_infos = new ArrayList<ServiceInfo>();
00174         for(String service : listeners ) {
00175                 service_infos.addAll(Arrays.asList(this.jmmdns.list(service)));
00176         }
00177         
00178         
00179         
00180         
00181         List<DiscoveredService> discovered_services = new ArrayList<DiscoveredService>();
00182         for(ServiceInfo service_info : service_infos ) {
00183                 Boolean service_found = false;
00184                 for ( DiscoveredService discovered_service : discovered_services ) {
00185                         if ( service_info.getQualifiedName().equals(discovered_service.name+"."+discovered_service.type+"."+discovered_service.domain+".") ) {
00186                                 for ( InetAddress inet_address : service_info.getInetAddresses() ) {
00187                                         if ( inet_address instanceof Inet4Address) {
00188                                                 Boolean address_found = false;
00189                                         for ( String unique_address : discovered_service.ipv4_addresses ) {
00190                                                 if ( inet_address.getHostAddress().equals(unique_address) ) {
00191                                                         address_found = true;
00192                                                         break;
00193                                                 }
00194                                         }
00195                                         if ( !address_found ) {
00196                                                 discovered_service.ipv4_addresses.add(inet_address.getHostAddress());
00197                                         }
00198                                         } else { 
00199                                                 Boolean address_found = false;
00200                                         for ( String unique_address : discovered_service.ipv6_addresses ) {
00201                                                 if ( inet_address.getHostAddress().equals(unique_address) ) {
00202                                                         address_found = true;
00203                                                         break;
00204                                                 }
00205                                         }
00206                                         if ( !address_found ) {
00207                                                 discovered_service.ipv6_addresses.add(inet_address.getHostAddress());
00208                                         }
00209                                         }
00210                                 }
00211                                 service_found = true;
00212                                 break;
00213                         }
00214                 }
00215                 if ( !service_found ) {
00216                         discovered_services.add(toDiscoveredService(service_info));
00217                 }
00218                 
00219         }
00220         return discovered_services;
00221     }
00222 
00227     public void removeAllServices() {
00228         logger.println("Removing all services");
00229         jmmdns.unregisterAllServices();
00230         services.clear();
00231     }
00232     
00233     public void shutdown() throws IOException {
00234         removeAllServices();
00235         logger.println("Shutdown");
00236         jmmdns.close();
00237     }
00238     
00239         
00240 
00241 
00242     @Override
00243     public void serviceAdded(ServiceEvent event) {
00244         final ServiceInfo service_info = event.getInfo();
00245         
00246         
00247         jmmdns.getServiceInfos(service_info.getType(), service_info.getName(), true);
00248         ZeroconfDiscoveryHandler callback = listener_callbacks.get(service_info.getType());
00249         if ( callback != null ) {
00250                 callback.serviceAdded(toDiscoveredService(service_info));
00251         } else {
00252             logger.println("[+] Service         : " + service_info.getQualifiedName());
00253         }
00254     }
00255 
00256     @Override
00257     public void serviceRemoved(ServiceEvent event) {
00258         final String name = event.getName();
00259         final ServiceInfo service_info = event.getInfo();
00260         ZeroconfDiscoveryHandler callback = listener_callbacks.get(service_info.getType());
00261         if ( callback != null ) {
00262                 callback.serviceRemoved(toDiscoveredService(service_info));
00263         } else {
00264             logger.println("[-] Service         : " + name);
00265         }
00266     }
00267 
00268     @Override
00277     public void serviceResolved(ServiceEvent event) {
00278         final ServiceInfo service_info = event.getInfo();
00279         ZeroconfDiscoveryHandler callback = listener_callbacks.get(service_info.getType());
00280         if ( callback != null ) {
00281                 callback.serviceResolved(toDiscoveredService(service_info));
00282         } else {
00283             logger.println("[=] Resolved        : " + service_info.getQualifiedName());
00284                 logger.println("      Port          : " + service_info.getPort() );
00285                 for ( int i = 0; i < service_info.getInetAddresses().length; ++i ) {
00286                 logger.println("      Address       : " + service_info.getInetAddresses()[i].getHostAddress() );
00287                 }
00288         }
00289     }
00290 
00291     @Override
00292     public void serviceTypeAdded(ServiceEvent event) {
00293 
00294 
00295     }
00296 
00297     @Override
00298     public void subTypeForServiceTypeAdded(ServiceEvent event) {
00299 
00300     }
00301 
00302         
00303 
00304 
00305     @Override
00306         public void inetAddressAdded(NetworkTopologyEvent event) {
00307                 try {
00308                         logger.println("[+] NetworkInterface: " + event.getInetAddress().getHostAddress() + " [" + NetworkInterface.getByInetAddress(event.getInetAddress()).getDisplayName() + "]");
00309                 } catch (IOException e) {
00310                 e.printStackTrace();
00311         }
00312         try {
00313                 event.getDNS().addServiceTypeListener(this);
00314                 for(String listener : listeners ) {
00315                         logger.println("      Adding service listener '" + listener + "'");
00316                 event.getDNS().addServiceListener(listener, this);
00317                 }
00318                 for (ServiceInfo service : services ) {
00319                         logger.println("Publishing Service on " + event.getInetAddress().getHostAddress());
00320                         logger.println("  Name   : " + service.getName() );
00321                         logger.println("  Type   : " + service.getType() );
00322                         logger.println("  Port   : " + service.getPort() );
00323                 event.getDNS().registerService(service.clone()); 
00324                 }
00325         } catch (IOException e) {
00326                 e.printStackTrace();
00327         }
00328         }
00329         
00330     @Override
00331     public void inetAddressRemoved(NetworkTopologyEvent event) {
00332         String event_address_str = event.getInetAddress().getHostAddress();
00333         
00334         
00335         
00336                 logger.println("[-] NetworkInterface: " + event_address_str);
00337                 
00338                 
00339                 
00340                 
00341 
00342                 event.getDNS().removeServiceTypeListener(this);
00343         for(String listener : listeners ) {
00344                 logger.println("      Removing service listener '" + listener + "'");
00345                 event.getDNS().removeServiceListener(listener, this);
00346         }
00347         for (ServiceInfo service : services ) {
00348                 logger.println("Unpublishing Service:");
00349                 logger.println("  Name   : " + service.getName() );
00350                 logger.println("  Type   : " + service.getType() );
00351                 logger.println("  Port   : " + service.getPort() );
00352                 event.getDNS().unregisterService(service); 
00353         }
00354         }
00355 
00356     
00357 
00358 
00359     public void display(DiscoveredService discovered_service) {
00360         logger.println("Discovered Service:");
00361         logger.println("  Name   : " + discovered_service.name );
00362         logger.println("  Type   : " + discovered_service.type );
00363         logger.println("  Port   : " + discovered_service.port );
00364         for ( String address : discovered_service.ipv4_addresses ) {
00365                 logger.println("  Address: " + address );
00366         }
00367         for ( String address : discovered_service.ipv6_addresses ) {
00368                 logger.println("  Address: " + address );
00369         }
00370     }
00371 
00372     public String toString(DiscoveredService discovered_service) {
00373         String result = "Service Info:\n";
00374         result += "  Name   : " + discovered_service.name + "\n";
00375         result += "  Type   : " + discovered_service.type + "\n";
00376         result += "  Port   : " + discovered_service.port + "\n";
00377         for ( String address : discovered_service.ipv4_addresses ) {
00378                 result += "  Address: " + address + "\n";
00379         }
00380         for ( String address : discovered_service.ipv6_addresses ) {
00381                 result += "  Address: " + address + "\n";
00382         }
00383         return result;
00384     }
00385 
00386     
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410     
00411 
00412 
00413     private DiscoveredService toDiscoveredService(ServiceInfo service_info) {
00414         DiscoveredService discovered_service = new DiscoveredService();
00415                 discovered_service.name = service_info.getName();
00416                 String[] type_domain_str = service_info.getType().split("\\.");
00417                 discovered_service.type = type_domain_str[0] + "." + type_domain_str[1];
00418                 discovered_service.domain = service_info.getDomain();
00419                 discovered_service.hostname = service_info.getServer();
00420                 discovered_service.port = service_info.getPort();
00421                 for ( InetAddress inet_address : service_info.getInetAddresses() ) {
00422                         if ( inet_address instanceof Inet4Address) {
00423                                 discovered_service.ipv4_addresses.add(inet_address.getHostAddress());
00424                         } else { 
00425                                 discovered_service.ipv6_addresses.add(inet_address.getHostAddress());
00426                         }
00427                 }
00428         return discovered_service;
00429     }
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 }