/** * Closes given {@link #transportManagers} of this <tt>Conference</tt> and removes corresponding * channel bundle. */ void closeTransportManager(TransportManager transportManager) { synchronized (transportManagers) { for (Iterator<IceUdpTransportManager> i = transportManagers.values().iterator(); i.hasNext(); ) { if (i.next() == transportManager) { i.remove(); // Presumably, we have a single association for // transportManager. break; } } // Close manager try { transportManager.close(); } catch (Throwable t) { logger.warn( "Failed to close an IceUdpTransportManager of" + " conference " + getID() + "!", t); // The whole point of explicitly closing the // transportManagers of this Conference is to prevent memory // leaks. Hence, it does not make sense to possibly leave // TransportManagers open because a TransportManager has // failed to close. if (t instanceof InterruptedException) Thread.currentThread().interrupt(); else if (t instanceof ThreadDeath) throw (ThreadDeath) t; } } }
/** * Runs in {@link #sendKeepAliveMessageThread} to notify this instance that * <tt>sendKeepAliveMessageThread</tt> is about to exit. */ private void exitSendKeepAliveMessageThread() { synchronized (sendKeepAliveMessageSyncRoot) { if (sendKeepAliveMessageThread == Thread.currentThread()) sendKeepAliveMessageThread = null; /* * Well, if the currentThread is finishing and this instance is * still to send keep-alive messages, we'd better start another * Thread for the purpose to continue the work that the * currentThread was supposed to carry out. */ if ((sendKeepAliveMessageThread == null) && (sendKeepAliveMessageInterval != SEND_KEEP_ALIVE_MESSAGE_INTERVAL_NOT_SPECIFIED)) { createSendKeepAliveMessageThread(); } } }
/** * Expires this <tt>Conference</tt>, its <tt>Content</tt>s and their respective <tt>Channel</tt>s. * Releases the resources acquired by this instance throughout its life time and prepares it to be * garbage collected. */ public void expire() { synchronized (this) { if (expired) return; else expired = true; } EventAdmin eventAdmin = videobridge.getEventAdmin(); if (eventAdmin != null) eventAdmin.sendEvent(EventFactory.conferenceExpired(this)); setRecording(false); if (recorderEventHandler != null) { recorderEventHandler.close(); recorderEventHandler = null; } Videobridge videobridge = getVideobridge(); try { videobridge.expireConference(this); } finally { // Expire the Contents of this Conference. for (Content content : getContents()) { try { content.expire(); } catch (Throwable t) { logger.warn( "Failed to expire content " + content.getName() + " of conference " + getID() + "!", t); if (t instanceof InterruptedException) Thread.currentThread().interrupt(); else if (t instanceof ThreadDeath) throw (ThreadDeath) t; } } // Close the transportManagers of this Conference. Normally, there // will be no TransportManager left to close at this point because // all Channels have expired and the last Channel to be removed from // a TransportManager closes the TransportManager. However, a // Channel may have expired before it has learned of its // TransportManager and then the TransportManager will not close. closeTransportManagers(); if (logger.isInfoEnabled()) { logger.info( "Expired conference " + getID() + ". " + videobridge.getConferenceCountString()); } } }
/** * Runs in {@link #sendKeepAliveMessageThread} and sends STUN keep-alive <tt>Message</tt>s to the * STUN server associated with the <tt>StunCandidateHarvester</tt> of this instance. * * @return <tt>true</tt> if the method is to be invoked again; otherwise, <tt>false</tt> */ private boolean runInSendKeepAliveMessageThread() { synchronized (sendKeepAliveMessageSyncRoot) { // Since we're going to #wait, make sure we're not canceled yet. if (sendKeepAliveMessageThread != Thread.currentThread()) return false; if (sendKeepAliveMessageInterval == SEND_KEEP_ALIVE_MESSAGE_INTERVAL_NOT_SPECIFIED) { return false; } // Determine the amount of milliseconds that we'll have to #wait. long timeout; if (sendKeepAliveMessageTime == -1) { /* * If we're just starting, don't just go and send a new STUN * keep-alive message but rather wait for the whole interval. */ timeout = sendKeepAliveMessageInterval; } else { timeout = sendKeepAliveMessageTime + sendKeepAliveMessageInterval - System.currentTimeMillis(); } // At long last, #wait if necessary. if (timeout > 0) { try { sendKeepAliveMessageSyncRoot.wait(timeout); } catch (InterruptedException iex) { } /* * Apart from being the time to send the STUN keep-alive * message, it could be that we've experienced a spurious * wake-up or that we've been canceled. */ return true; } } sendKeepAliveMessageTime = System.currentTimeMillis(); try { sendKeepAliveMessage(); } catch (StunException sex) { logger.log(Level.INFO, "Failed to send STUN keep-alive message.", sex); } return true; }