public void stop() { if (jmdns != null) { for (Iterator<ServiceInfo> iter = serviceInfos.iterator(); iter.hasNext(); ) { ServiceInfo si = iter.next(); jmdns.unregisterService(si); } // Close it down async since this could block for a while. final JmDNS closeTarget = jmdns; Thread thread = new Thread() { public void run() { try { if (JmDNSFactory.onClose(getLocalAddress())) { closeTarget.close(); } ; } catch (IOException e) { LOG.debug( "Error closing JmDNS " + getLocalhost() + ". This exception will be ignored.", e); } } }; thread.setDaemon(true); thread.start(); jmdns = null; } }
/** Shuts the AirReceiver down gracefully */ public static void onShutdown() { /* Close channels */ final ChannelGroupFuture allChannelsClosed = s_allChannels.close(); /* Stop all mDNS responders */ synchronized (s_jmDNSInstances) { for (final JmDNS jmDNS : s_jmDNSInstances) { try { jmDNS.unregisterAllServices(); s_logger.info("Unregistered all services on " + jmDNS.getInterface()); } catch (final IOException e) { s_logger.info("Failed to unregister some services"); } } } /* Wait for all channels to finish closing */ allChannelsClosed.awaitUninterruptibly(); /* Stop the ExecutorService */ ExecutorService.shutdown(); /* Release the OrderedMemoryAwareThreadPoolExecutor */ ChannelExecutionHandler.releaseExternalResources(); }
private void stopMDNS() throws IOException { if (jmdns != null) { for (JmDNS mdns : jmdns) { if (mdns == null) { continue; } Log.i(TAG, "Stopping GameClient discovery " + mdns.getName()); mdns.removeServiceListener(SERVICE_TYPE, GameClient.this); mdns.close(); mdns = null; } } }
@Override public void inetAddressAdded(InetAddress address) { if (this.mappedJmDNSs.containsKey(address)) { return; } try (JmDNS jmDNS = JmDNS.create(address); ) { jmDNS.addServiceListener("_arduino._tcp.local.", this); // $NON-NLS-1$ this.mappedJmDNSs.put(address, jmDNS); } catch (Exception e) { e.printStackTrace(); } }
// @Test // not working by 22/09/2013 public void testRegisterDevice() { try { JmDNS jmdns = JmDNS.create( InetAddress.getByName( PropertiesLoader.getInstance() .getProperties() .getProperty("iotsys.gateway.authNsAddr6", "fe80::acbc:b659:71db:5cb7%20"))); jmdns.addServiceListener( "_obix._coap." + PropertiesLoader.getInstance() .getProperties() .getProperty("iotsys.gateway.authDomain", "local."), new ServiceListener() { @Override public void serviceAdded(ServiceEvent event) {} @Override public void serviceRemoved(ServiceEvent event) {} @Override public void serviceResolved(ServiceEvent event) { resolvedEvents.add(event); } }); lock.await(20000, TimeUnit.MILLISECONDS); ArrayList<String> eventNames = new ArrayList<String>(); for (ServiceEvent e : resolvedEvents) { eventNames.add(e.getName()); } // test all elements in testDeviceNames are returned in eventNames for (String qName : testDeviceNames) { // if eventNames not contain qName -> fail String fk = qName.split("\\.")[0].toLowerCase(); if (!eventNames.contains(fk)) fail(); } } catch (UnknownHostException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
public Bonjour() { try { jmdns = JmDNS.create(); jmdns.addServiceListener( type, listener = new ServiceListener() { @Override public void serviceResolved(ServiceEvent ev) { System.out.println( "Service resolved: " + ev.getInfo().getQualifiedName() + " port:" + ev.getInfo().getPort()); String jsString = "javascript:destinationManager.addDestination('" + ev.getInfo().getHostAddress() + "'," + ev.getInfo().getPort() + ", 0, 0);"; System.out.println(jsString); webView.loadUrl(jsString); } @Override public void serviceRemoved(ServiceEvent ev) { System.out.println("Service removed: " + ev.getName()); String jsString = "javascript:destinationManager.removeDestinationWithIPAndPort('" + ev.getInfo().getHostAddress() + "'," + ev.getInfo().getPort() + ");"; System.out.println(jsString); webView.loadUrl(jsString); } @Override public void serviceAdded(ServiceEvent event) { // Required to force serviceResolved to be called again // (after the first search) jmdns.requestServiceInfo(event.getType(), event.getName(), 1); } }); } catch (Exception e) { System.out.println("error starting Bonjour"); } }
@Override public void inetAddressRemoved(InetAddress address) { try (JmDNS jmDNS = this.mappedJmDNSs.remove(address)) { if (jmDNS != null) { try { jmDNS.close(); } catch (IOException e) { e.printStackTrace(); } } } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } }
@Override public void serviceAdded(ServiceEvent serviceEvent) { String type = serviceEvent.getType(); String name = serviceEvent.getName(); try (JmDNS dns = serviceEvent.getDNS()) { dns.requestServiceInfo(type, name); ServiceInfo serviceInfo = dns.getServiceInfo(type, name); if (serviceInfo != null) { dns.requestServiceInfo(type, name); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
/** * List published node(s) configuration in the network via multicast * * @param serviceName name of service published. (e.g. release version for installation) * @return node(s) configuration list */ public Map<String, Map<String, String>> list(String serviceName) { Map<String, Map<String, String>> results = new HashMap<String, Map<String, String>>(); ServiceInfo[] infos = jmdns.list("_" + serviceName + "._tcp.local."); for (ServiceInfo info : infos) { _log.info("ServiceInfo:{}", info); // Construct the key final String[] hostAddrs = info.getHostAddresses(); final StringBuffer buf = new StringBuffer(); for (String hostAddr : hostAddrs) { buf.append(hostAddr); buf.append(';'); } final String key = buf.toString(); _log.info("\tkey:{}", key); // Construct the values final Map<String, String> values = new HashMap<String, String>(); for (Enumeration<String> e = info.getPropertyNames(); e.hasMoreElements(); ) { final String prop = e.nextElement(); final String value = new String(info.getPropertyBytes(prop)); _log.info("\tprop:{}, value:{}", prop, value); values.put(prop, value); } // Put <key,values> into the results if (values.isEmpty()) { _log.warn("values are empty for key: {}", key); } results.put(key, values.isEmpty() ? null : values); } return results; }
public DNSMultiCast(Jenkins hudson) { if (disabled) return; // escape hatch try { this.jmdns = JmDNS.create(); Map<String, String> props = new HashMap<String, String>(); String rootURL = hudson.getRootUrl(); if (rootURL != null) props.put("url", rootURL); try { props.put("version", String.valueOf(Jenkins.getVersion())); } catch (IllegalArgumentException e) { // failed to parse the version number } TcpSlaveAgentListener tal = hudson.getTcpSlaveAgentListener(); if (tal != null) props.put("slave-port", String.valueOf(tal.getPort())); props.put("server-id", Util.getDigestOf(hudson.getSecretKey())); URL jenkins_url = new URL(rootURL); int jenkins_port = jenkins_url.getPort(); if (jenkins_port == -1) { jenkins_port = 80; } if (jenkins_url.getPath().length() > 0) { props.put("path", jenkins_url.getPath()); } jmdns.registerService( ServiceInfo.create( "_hudson._tcp.local.", "hudson", jenkins_port, 0, 0, props)); // for backward compatibility jmdns.registerService( ServiceInfo.create("_jenkins._tcp.local.", "jenkins", jenkins_port, 0, 0, props)); // Make Jenkins appear in Safari's Bonjour bookmarks jmdns.registerService( ServiceInfo.create("_http._tcp.local.", "Jenkins", jenkins_port, 0, 0, props)); } catch (IOException e) { LOGGER.log(Level.WARNING, "Failed to advertise the service to DNS multi-cast", e); } }
private void unListenService(String type, boolean notify) { if (null != mDiscoverListener && notify) { mDiscoverListener.onDiscoverStopped(type); } if (null != mJmDNS) { mJmDNS.removeServiceListener(mType, mJmDNSListener); } }
public void activate() { try { jmdns = JmDNS.create(); logger.debug("mDNS service has been started"); } catch (IOException e) { logger.error(e.getMessage()); } }
// ServiceListener interface // ------------------------------------------------------------------------- public void addService(JmDNS jmDNS, String type, String name) { if (LOG.isDebugEnabled()) { LOG.debug("addService with type: " + type + " name: " + name); } if (listener != null) { listener.onServiceAdd(new DiscoveryEvent(name)); } jmDNS.requestServiceInfo(type, name); }
public void deactivate() { unregisterAllServices(); try { jmdns.close(); logger.debug("mDNS service has been stopped"); } catch (IOException e) { logger.error(e.getMessage()); } }
@Override public void createService(String name, String type, int port) { if (!type.contains(TYPE_PADDING)) { type = type + TYPE_PADDING; } mType = type; acquireMulticastLock(); try { if (null != mJmDNS) { destroyService(null, false); } if (mHost) { mJmDNS = JmDNS.create(mWifiEnable); } else { if (null != mAddress) { mJmDNS = JmDNS.create(mAddress, name); } else { mJmDNS = JmDNS.create(mWifiEnable); } } } catch (Exception e) { Log.e(TAG, "failed to create the service", e); if (null != mServiceListener) { mServiceListener.onServiceRegisteredFailed(new ZeroServiceInfo(null, null)); } } if (null != mJmDNS) { try { ServiceInfo si = ServiceInfo.create( mType, name, port, LOCAL_SERVER_WEIGHT, LOCAL_SERVER_PROIORITY, true, "android_jmdns_service"); mJmDNS.registerService(si); } catch (Exception e) { Log.e(TAG, "failed to cast the service", e); } } }
public void close() { if (jmdns != null) { // try { jmdns.abort(); jmdns = null; // } catch (final IOException e) { // LOGGER.log(Level.WARNING,"Failed to close down JmDNS instance!",e); // } } }
private static void stopServicesMDNS() { synchronized (lock) { if (jmdns != null) { for (JmDNS mdns : jmdns) { if (mdns != null) { try { mdns.unregisterAllServices(); mdns.close(); mdns = null; } catch (IOException ex) { Log.e(TAG, "", ex); } } } } waiter.release(); Log.i(TAG, "mDNS released"); } }
@SuppressWarnings("boxing") public void backgroundInit() { // (Ralf:) zomfg, this is one of the worst hacks i've done the last years. Deep within jmdns we // placed a variable to // override a check if it is already safe to transmit something. jmDNS usually takes 5 seconds // to reach that state, but that's // too long for us. If you set this variable the check will be skipped and the request should // take place much faster. // Appears to work(tm). ServiceResolver.ANNOUNCE_OVERRIDE = true; this.logger.status("backgroundinit/start"); final PluginConfigurationUtil pcu = new PluginConfigurationUtil(this.pluginConfiguration); this.startupLock = pcu.getInt(RemoteDiscovery.class, "startup.locktime", 1000); this.lockMode = pcu.getString(RemoteDiscovery.class, "startup.lockmode", "onepass"); try { this.logger.status("backgroundinit/lock"); this.jmdnsLock.lock(); this.jmdns = JmDNS .create(); // Maybe init with local loopback in case no other network card is present, // otherwise returns null this.timeOfStartup = System.currentTimeMillis(); final int port = RemoteDiscoveryImpl.getFreePort(); final ServiceInfo service = ServiceInfo.create(TYPE, NAME + " @" + this.timeOfStartup, port, 0, 0, EXPORT_NAME); this.logger.status("backgroundinit/export", "port", port); this.localManagerExportServer = Proxies.newServer(EXPORT_NAME, port, (DiscoveryManager) this.localTCPIPManager); this.logger.status("backgroundinit/announce", "port", port); this.jmdns.registerService(service); // Set it again, this time for the lock below this.timeOfStartup = System.currentTimeMillis(); } catch (final IOException e) { e.printStackTrace(); } catch (final IllegalStateException e) { this.logger.status("backgroundinit/exception/illegalstate", "message", e.getMessage()); } finally { this.logger.status("backgroundinit/unlock"); this.startupLatch.countDown(); this.jmdnsLock.unlock(); } this.logger.status("backgroundinit/end"); }
@SuppressWarnings("boxing") @Thread(isDaemonic = true) public void backgroundInit() { // (Ralf:) zomfg, this is one of the worst hacks i've done the last // couple of months. Deep within jmdns we placed a variable to // override a check if it is already save to transmit something. jmDNS // usually takes 5 seconds to reach that state, but that's // too long for us. If you set this variable the check will be skipped // and the request should take place much faster. // Appears to work(tm). ServiceResolver.ANNOUNCE_OVERRIDE = true; final PluginConfigurationUtil pcu = new PluginConfigurationUtil(this.pluginConfiguration); this.startupLock = pcu.getInt(RemoteDiscovery.class, "startup.locktime", 1000); this.lockMode = pcu.getString(RemoteDiscovery.class, "startup.lockmode", "onepass"); // TODO put this in a thread this.checkCache.loadCache(); try { this.jmdnsLock.lock(); this.jmdns = JmDNS .create(); // Maybe init with local loopback in case no other network card is present, // otherwise returns null this.timeOfStartup = System.currentTimeMillis(); final int port = getFreePort(); final ServiceInfo service = ServiceInfo.create(TYPE, NAME + " @" + this.timeOfStartup, port, 0, 0, EXPORT_NAME); this.localManagerExportServer = Proxies.newServer(EXPORT_NAME, port, (DiscoveryManager) this.localManager); this.jmdns.registerService(service); // Set it again, this time for the lock below this.timeOfStartup = System.currentTimeMillis(); } catch (IOException e) { e.printStackTrace(); } catch (IllegalStateException e) { this.logger.warning("Error starting discovery."); } finally { this.startupLatch.countDown(); this.jmdnsLock.unlock(); } // and load our cache... // todo make this configurable... // this.checkCache.loadCache(fileName) }
private void destroyService(ZeroServiceInfo zsi, boolean notify) { if (null == mJmDNS) { if (notify) { mServiceListener.onServiceUnregistered(zsi); } return; } try { releaseMulticastLock(); mJmDNS.removeServiceListener(mType, mJmDNSListener); mJmDNS.unregisterAllServices(); mJmDNS.close(); mJmDNS = null; if (null != mServiceListener && notify) { mServiceListener.onServiceUnregistered(zsi); } } catch (Exception e) { Log.e(TAG, "failed to close the JmDNS service"); if (null != mServiceListener && notify) { mServiceListener.onServiceUnregisteredFailed(zsi); } } }
@Override public PluginResult execute(String action, JSONArray data, String callbackId) { // Log.d("OSCManager", "executing something " + action); PluginResult result = null; try { System.out.println("EXECUTING BONJOUR ********************************************"); if (action.equals("start") || action.equals("browse")) { System.out.println("STARTING BONJOUR ********************************************"); ServiceInfo[] infos = jmdns.list("_osc._udp.local."); for (int i = 0; i < infos.length; i++) { String jsString = "javascript:destinationManager.addDestination('" + infos[i].getHostAddress() + "'," + infos[i].getPort() + ", 0, 0);"; System.out.println(jsString); webView.loadUrl(jsString); System.out.println("after sending to js"); } if (action.equals("start")) { ServiceInfo serviceInfo = ServiceInfo.create( "_osc._udp.local.", "Control_" + (Math.round(Math.random() * 100000)), 8080, "OSC reception for device running Control"); jmdns.registerService(serviceInfo); } } } catch (Exception e) { System.out.println("after sending to js"); } return result; }
/** @{inheritDoc} */ public void unregisterService(ServiceDescription description) { ServiceInfo serviceInfo = ServiceInfo.create( description.serviceType, description.serviceName, description.servicePort, 0, 0, description.serviceProperties); logger.debug( "Unregistering service " + description.serviceType + " at port " + String.valueOf(description.servicePort)); jmdns.unregisterService(serviceInfo); }
private void listenService(String type, boolean notify) { if (null != mDiscoverListener && notify) { mDiscoverListener.onDiscoveryStarted(type); } if (null == mJmDNS) { if (null != mDiscoverListener && notify) { mDiscoverListener.onStartDiscoveryFailed(type, "empty service."); } return; } try { mJmDNS.addServiceListener(mType, mJmDNSListener); } catch (Exception e) { Log.e(TAG, "failed to listen the service", e); if (null != mDiscoverListener) { mDiscoverListener.onStartDiscoveryFailed(type, e.getMessage()); } } }
/** * The list of JmDNS handlers. * * @return a {@link java.util.HashMap} of {@link javax.jmdns.JmDNS} objects, accessible by {@link * java.net.InetAddress} keys. */ public static synchronized HashMap<InetAddress, JmDNS> netServices() { if (ZeroConfService.netServices.isEmpty()) { log.debug("JmDNS version: {}", JmDNS.VERSION); try { for (InetAddress address : hostAddresses()) { // explicitly passing null since newer versions of JmDNS use passed in host // as hostname instead of using passed in host as fallback if real hostname // cannot be determined log.debug("Calling JmDNS.create({}, null)", address.getHostAddress()); ZeroConfService.netServices.put(address, JmDNS.create(address, null)); } } catch (IOException ex) { log.warn("Unable to create JmDNS with error: {}", ex.getMessage(), ex); } if (InstanceManager.shutDownManagerInstance() != null) { InstanceManager.shutDownManagerInstance().register(ZeroConfService.shutDownTask); } } return new HashMap<>(ZeroConfService.netServices); }
// DiscoveryAgent interface // ------------------------------------------------------------------------- public void start() throws Exception { if (group == null) { throw new IOException("You must specify a group to discover"); } String type = getType(); if (!type.endsWith(".")) { LOG.warn("The type '" + type + "' should end with '.' to be a valid Rendezvous type"); type += "."; } try { // force lazy construction getJmdns(); if (listener != null) { LOG.info("Discovering service of type: " + type); jmdns.addServiceListener(type, this); } } catch (IOException e) { JMSExceptionSupport.create("Failed to start JmDNS service: " + e, e); } }
@Override public PluginResult execute(String action, JSONArray data, String callbackId) { // Log.d("OSCManager", "executing something " + action); System.out.println("EXECUTING ********************************************"); PluginResult result = null; if (action.equals("start")) { System.out.println("STARTING ********************************************"); ServiceInfo[] infos = jmdns.list("_osc._udp.local."); for (int i = 0; i < infos.length; i++) { String jsString = "javascript:destinationManager.addDestination('" + infos[i].getHostAddress() + "'," + infos[i].getPort() + ", 0, 0);"; System.out.println(jsString); webView.loadUrl(jsString); System.out.println("after sending to js"); } } return result; }
/** Start advertising the service. */ public void publish() { if (!isPublished()) { ZeroConfService.services.put(this.key(), this); this.listeners .stream() .forEach( (listener) -> { listener.serviceQueued(new ZeroConfServiceEvent(this, null)); }); boolean useIPv4 = ProfileUtils.getPreferences( ProfileManager.getDefault().getActiveProfile(), ZeroConfService.class, false) .getBoolean(ZeroConfService.IPv4, true); boolean useIPv6 = ProfileUtils.getPreferences( ProfileManager.getDefault().getActiveProfile(), ZeroConfService.class, false) .getBoolean(ZeroConfService.IPv6, true); for (JmDNS netService : ZeroConfService.netServices().values()) { ZeroConfServiceEvent event; ServiceInfo info; try { if (netService.getInetAddress() instanceof Inet6Address && !useIPv6) { // Skip if address is IPv6 and should not be advertised on log.debug("Ignoring IPv6 address {}", netService.getInetAddress().getHostAddress()); continue; } if (netService.getInetAddress() instanceof Inet4Address && !useIPv4) { // Skip if address is IPv4 and should not be advertised on log.debug("Ignoring IPv4 address {}", netService.getInetAddress().getHostAddress()); continue; } try { log.debug( "Publishing ZeroConfService for '{}' on {}", key(), netService.getInetAddress().getHostAddress()); } catch (IOException ex) { log.debug( "Publishing ZeroConfService for '{}' with IOException {}", key(), ex.getLocalizedMessage(), ex); } // JmDNS requires a 1-to-1 mapping of serviceInfo to InetAddress if (!this.serviceInfos.containsKey(netService.getInetAddress())) { try { info = this.serviceInfo(); netService.registerService(info); log.debug( "Register service '{}' on {} successful.", this.key(), netService.getInetAddress().getHostAddress()); } catch (IllegalStateException ex) { // thrown if the reference serviceInfo object is in use try { log.debug( "Initial attempt to register '{}' on {} failed.", this.key(), netService.getInetAddress().getHostAddress()); info = this.addServiceInfo(netService); log.debug( "Retrying register '{}' on {}.", this.key(), netService.getInetAddress().getHostAddress()); netService.registerService(info); } catch (IllegalStateException ex1) { // thrown if service gets registered on interface by // the networkListener before this loop on interfaces // completes, so we only ensure a later notification // is not posted continuing to next interface in list log.debug( "'{}' is already registered on {}.", this.key(), netService.getInetAddress().getHostAddress()); continue; } } } else { log.debug( "skipping '{}' on {}, already in serviceInfos.", this.key(), netService.getInetAddress().getHostAddress()); } event = new ZeroConfServiceEvent(this, netService); } catch (IOException ex) { log.error("Unable to publish service for '{}': {}", key(), ex.getMessage()); continue; } this.listeners .stream() .forEach( (listener) -> { listener.servicePublished(event); }); } } }
public static MulticastUtil create(String networkInterfaceName) throws IOException { JmDNS jmdns = JmDNS.create(MulticastUtil.getLinkLocalAddress(networkInterfaceName)); return new MulticastUtil(jmdns); }
@Override public void run() { try { final JmDNS jmdns = JmDNS.create(); jmdns.addServiceListener(TOUCH_ABLE_TYPE, this); jmdns.addServiceListener(DACP_TYPE, this); final HashMap<String, String> values = new HashMap<String, String>(); byte[] number = new byte[4]; random.nextBytes(number); values.put("DvNm", "Android-" + toHex(number)); values.put("RemV", "10000"); values.put("DvTy", "iPod"); values.put("RemN", "Remote"); values.put("txtvers", "1"); byte[] pair = new byte[8]; random.nextBytes(pair); values.put("Pair", toHex(pair)); while (_running) { ServerSocket server = new ServerSocket(0); byte[] name = new byte[20]; random.nextBytes(name); System.out.println("Requesting pairing for " + toHex(name)); ServiceInfo pairservice = ServiceInfo.create(REMOTE_TYPE, toHex(name), server.getLocalPort(), 0, 0, values); jmdns.registerService(pairservice); System.out.println("Waiting for pass code"); final Socket socket = server.accept(); OutputStream output = null; try { output = socket.getOutputStream(); // output the contents for debugging final BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); while (br.ready()) { String line = br.readLine(); System.out.println(line); } // edit our local PAIRING_RAW to return the correct guid byte[] code = new byte[8]; random.nextBytes(code); System.out.println("Device guid: " + toHex(code)); System.arraycopy(code, 0, PAIRING_RAW, 16, 8); byte[] header = String.format( "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n", new Integer(PAIRING_RAW.length)) .getBytes(); byte[] reply = new byte[header.length + PAIRING_RAW.length]; System.arraycopy(header, 0, reply, 0, header.length); System.arraycopy(PAIRING_RAW, 0, reply, header.length, PAIRING_RAW.length); System.out.println("Response: " + new String(reply)); output.write(reply); output.flush(); System.out.println("someone paired with me!"); jmdns.unregisterService(pairservice); } finally { if (output != null) { output.close(); } System.out.println("Closing Socket"); if (!server.isClosed()) { server.close(); } _running = false; } } Thread.sleep(6000); System.out.println("Closing JmDNS"); jmdns.close(); } catch (Exception e) { e.printStackTrace(); } }
public static void main(final String[] args) throws Exception { /* Make sure AirReceiver shuts down gracefully */ Runtime.getRuntime() .addShutdownHook( new Thread( new Runnable() { @Override public void run() { onShutdown(); } })); /* Create about dialog */ final Dialog aboutDialog = new Dialog((Dialog) null); final GridBagLayout aboutLayout = new GridBagLayout(); aboutDialog.setLayout(aboutLayout); aboutDialog.setVisible(false); aboutDialog.setTitle("About AirReceiver"); aboutDialog.setResizable(false); { /* Message */ final TextArea title = new TextArea(AboutMessage.split("\n").length + 1, 64); title.setText(AboutMessage); title.setEditable(false); final GridBagConstraints titleConstraints = new GridBagConstraints(); titleConstraints.gridx = 1; titleConstraints.gridy = 1; titleConstraints.fill = GridBagConstraints.HORIZONTAL; titleConstraints.insets = new Insets(0, 0, 0, 0); aboutLayout.setConstraints(title, titleConstraints); aboutDialog.add(title); } { /* Done button */ final Button aboutDoneButton = new Button("Done"); aboutDoneButton.addActionListener( new ActionListener() { @Override public void actionPerformed(final ActionEvent evt) { aboutDialog.setVisible(false); } }); final GridBagConstraints aboutDoneConstraints = new GridBagConstraints(); aboutDoneConstraints.gridx = 1; aboutDoneConstraints.gridy = 2; aboutDoneConstraints.anchor = GridBagConstraints.PAGE_END; aboutDoneConstraints.fill = GridBagConstraints.NONE; aboutDoneConstraints.insets = new Insets(0, 0, 0, 0); aboutLayout.setConstraints(aboutDoneButton, aboutDoneConstraints); aboutDialog.add(aboutDoneButton); } aboutDialog.setVisible(false); aboutDialog.setLocationByPlatform(true); aboutDialog.pack(); /* Create tray icon */ final URL trayIconUrl = AirReceiver.class.getClassLoader().getResource("icon_32.png"); final TrayIcon trayIcon = new TrayIcon((new ImageIcon(trayIconUrl, "AirReceiver").getImage())); trayIcon.setToolTip("AirReceiver"); trayIcon.setImageAutoSize(true); final PopupMenu popupMenu = new PopupMenu(); final MenuItem aboutMenuItem = new MenuItem("About"); aboutMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed(final ActionEvent evt) { aboutDialog.setLocationByPlatform(true); aboutDialog.setVisible(true); } }); popupMenu.add(aboutMenuItem); final MenuItem exitMenuItem = new MenuItem("Quit"); exitMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed(final ActionEvent evt) { onShutdown(); System.exit(0); } }); popupMenu.add(exitMenuItem); trayIcon.setPopupMenu(popupMenu); SystemTray.getSystemTray().add(trayIcon); /* Create AirTunes RTSP server */ final ServerBootstrap airTunesRtspBootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(ExecutorService, ExecutorService)); airTunesRtspBootstrap.setPipelineFactory(new RaopRtspPipelineFactory()); airTunesRtspBootstrap.setOption("reuseAddress", true); airTunesRtspBootstrap.setOption("child.tcpNoDelay", true); airTunesRtspBootstrap.setOption("child.keepAlive", true); s_allChannels.add( airTunesRtspBootstrap.bind( new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), AirtunesServiceRTSPPort))); s_logger.info("Launched RTSP service on port " + AirtunesServiceRTSPPort); /* Create mDNS responders. */ synchronized (s_jmDNSInstances) { for (final NetworkInterface iface : Collections.list(NetworkInterface.getNetworkInterfaces())) { if (iface.isLoopback()) continue; if (iface.isPointToPoint()) continue; if (!iface.isUp()) continue; for (final InetAddress addr : Collections.list(iface.getInetAddresses())) { if (!(addr instanceof Inet4Address) && !(addr instanceof Inet6Address)) continue; try { /* Create mDNS responder for address */ final JmDNS jmDNS = JmDNS.create(addr, HostName + "-jmdns"); s_jmDNSInstances.add(jmDNS); /* Publish RAOP service */ final ServiceInfo airTunesServiceInfo = ServiceInfo.create( AirtunesServiceType, HardwareAddressString + "@" + HostName + " (" + iface.getName() + ")", AirtunesServiceRTSPPort, 0 /* weight */, 0 /* priority */, AirtunesServiceProperties); jmDNS.registerService(airTunesServiceInfo); s_logger.info( "Registered AirTunes service '" + airTunesServiceInfo.getName() + "' on " + addr); } catch (final Throwable e) { s_logger.log(Level.SEVERE, "Failed to publish service on " + addr, e); } } } } }