protected void destroy() { search_destroyed = true; if (twc != null) { twc.destroy(); twc = null; } if (timer_event != null) { timer_event.cancel(); timer_event = null; } if (control_socket != null) { try { control_socket.close(); } catch (Throwable e) { } control_socket = null; } }
protected Searcher(boolean _persistent, boolean _async) throws DeviceManagerException { try { int last_port = COConfigurationManager.getIntParameter("devices.tivo.net.tcp.port", 0); if (last_port > 0) { try { ServerSocket ss = new ServerSocket(last_port); ss.setReuseAddress(true); ss.close(); } catch (Throwable e) { last_port = 0; } } twc = plugin_interface.getTracker().createWebContext(last_port, Tracker.PR_HTTP); tcp_port = twc.getURLs()[0].getPort(); COConfigurationManager.setParameter("devices.tivo.net.tcp.port", tcp_port); twc.addPageGenerator( new TrackerWebPageGenerator() { public boolean generate( TrackerWebPageRequest request, TrackerWebPageResponse response) throws IOException { String id = (String) request.getHeaders().get("tsn"); if (id == null) { id = (String) request.getHeaders().get("tivo_tcd_id"); } if (id != null && is_enabled) { persistent = true; DeviceTivo tivo = foundTiVo(request.getClientAddress2().getAddress(), id, null, null); return (tivo.generate(request, response)); } return (false); } }); control_socket = new DatagramSocket(null); control_socket.setReuseAddress(true); try { control_socket.setSoTimeout(60 * 1000); } catch (Throwable e) { } InetAddress bind = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress(); control_socket.bind(new InetSocketAddress(bind, CONTROL_PORT)); timer_event = SimpleTimer.addPeriodicEvent( "Tivo:Beacon", 60 * 1000, new TimerEventPerformer() { public void perform(TimerEvent event) { if (!(manager_destroyed || search_destroyed)) { sendBeacon(); } // see if time to auto-shutdown searching if (!persistent) { synchronized (DeviceTivoManager.this) { if (SystemTime.getMonotonousTime() - start >= LIFE_MILLIS) { log("Terminating search, no devices found"); current_search = null; destroy(); } } } } }); final AESemaphore start_sem = new AESemaphore("TiVo:CtrlListener"); new AEThread2("TiVo:CtrlListener", true) { public void run() { start_sem.release(); long successful_accepts = 0; long failed_accepts = 0; while (!(manager_destroyed || search_destroyed)) { try { byte[] buf = new byte[8192]; DatagramPacket packet = new DatagramPacket(buf, buf.length); control_socket.receive(packet); successful_accepts++; failed_accepts = 0; if (receiveBeacon(packet.getAddress(), packet.getData(), packet.getLength())) { persistent = true; } } catch (SocketTimeoutException e) { } catch (Throwable e) { if (control_socket != null && !search_destroyed && !manager_destroyed) { failed_accepts++; log("UDP receive on port " + CONTROL_PORT + " failed", e); } if ((failed_accepts > 100 && successful_accepts == 0) || failed_accepts > 1000) { log(" too many failures, abandoning"); break; } } } } }.start(); if (_async) { new DelayedEvent( "search:delay", 5000, new AERunnable() { public void runSupport() { sendBeacon(); } }); } else { start_sem.reserve(5000); sendBeacon(); } log("Initiated device search"); } catch (Throwable e) { log("Failed to initialise search", e); destroy(); throw (new DeviceManagerException("Creation failed", e)); } }