aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java')
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java38
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java59
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallPeerMediaHandlerJabberGTalkImpl.java37
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java82
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java93
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java148
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java4
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java202
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java39
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java213
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/P2PTransportManager.java96
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/RawUdpTransportManager.java7
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java13
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/cobri/CobriConferenceIQ.java163
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/cobri/CobriIQProvider.java27
-rw-r--r--src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java3
-rw-r--r--src/net/java/sip/communicator/service/protocol/AccountID.java51
-rw-r--r--src/net/java/sip/communicator/service/protocol/ActiveCallsRepository.java7
-rw-r--r--src/net/java/sip/communicator/service/protocol/event/RegistrationStateChangeListener.java12
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java76
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java16
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/DynamicRTPExtensionsRegistry.java2
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java13
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/MediaHandler.java13
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/TransportManager.java1
25 files changed, 1008 insertions, 407 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
index f1d3466..e79b01b 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
@@ -320,7 +320,7 @@ public class CallPanel
this.callConference = callConference;
this.callWindow = callWindow;
- uiVideoHandler = new UIVideoHandler2(callConference);
+ uiVideoHandler = new UIVideoHandler2(this.callConference);
callDurationTimer
= new Timer(
@@ -345,9 +345,10 @@ public class CallPanel
* Adds the listeners which will observe the model and will trigger the
* updates of this view from it.
*/
- callConference.addCallChangeListener(callConferenceListener);
- callConference.addCallPeerConferenceListener(callConferenceListener);
- callConference.addPropertyChangeListener(callConferenceListener);
+ this.callConference.addCallChangeListener(callConferenceListener);
+ this.callConference.addCallPeerConferenceListener(
+ callConferenceListener);
+ this.callConference.addPropertyChangeListener(callConferenceListener);
uiVideoHandler.addObserver(uiVideoHandlerObserver);
updateViewFromModel();
@@ -400,12 +401,16 @@ public class CallPanel
else if (buttonName.equals(CONFERENCE_BUTTON))
{
ConferenceInviteDialog inviteDialog;
+
if (callConference.isJitsiVideoBridge())
- inviteDialog = new ConferenceInviteDialog(
- callConference,
- callConference.getCalls()
- .get(0).getProtocolProvider(),
- true);
+ {
+ inviteDialog
+ = new ConferenceInviteDialog(
+ callConference,
+ callConference.getCalls().get(0)
+ .getProtocolProvider(),
+ true);
+ }
else
inviteDialog = new ConferenceInviteDialog(callConference);
@@ -437,18 +442,11 @@ public class CallPanel
{
if (callInfoFrame == null)
{
- this.callInfoFrame = new CallInfoFrame(callConference);
- this.addCallTitleListener(callInfoFrame);
- }
-
- if (callInfoFrame.hasCallInfo())
- {
- callInfoFrame.setVisible(!callInfoFrame.isVisible());
- }
- else
- {
- callInfoFrame.setVisible(false);
+ callInfoFrame = new CallInfoFrame(callConference);
+ addCallTitleListener(callInfoFrame);
}
+ callInfoFrame.setVisible(
+ callInfoFrame.hasCallInfo() && !callInfoFrame.isVisible());
}
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
index d04411b..4897908 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
@@ -292,14 +292,17 @@ public class OneToOneCallPeerPanel
= new TransparentPanel(new BorderLayout(5, 0));
TransparentPanel remoteLevelPanel
= new TransparentPanel(new BorderLayout(5, 0));
-
- localLevel = new InputVolumeControlButton(
- callPeer.getCall(),
- ImageLoader.MICROPHONE,
- ImageLoader.MUTE_BUTTON,
- false, false, false);
- remoteLevel = new OutputVolumeControlButton(
- ImageLoader.HEADPHONE, false, false).getComponent();
+ Call call = callPeer.getCall();
+
+ localLevel
+ = new InputVolumeControlButton(
+ call,
+ ImageLoader.MICROPHONE,
+ ImageLoader.MUTE_BUTTON,
+ false, false, false);
+ remoteLevel
+ = new OutputVolumeControlButton(ImageLoader.HEADPHONE, false, false)
+ .getComponent();
final SoundLevelIndicator localLevelIndicator
= new SoundLevelIndicator(
@@ -339,7 +342,7 @@ public class OneToOneCallPeerPanel
+ "DISABLE_SOUND_LEVEL_INDICATORS",
false))
{
- this.callPeer.addStreamSoundLevelListener(
+ callPeer.addStreamSoundLevelListener(
new SoundLevelListener()
{
public void soundLevelChanged(Object source, int level)
@@ -347,15 +350,26 @@ public class OneToOneCallPeerPanel
remoteLevelIndicator.updateSoundLevel(level);
}
});
-
- this.callPeer.getCall().addLocalUserSoundLevelListener(
- new SoundLevelListener()
- {
- public void soundLevelChanged(Object source, int level)
+ /*
+ * By the time the UI gets to be initialized, the callPeer may have
+ * been removed from its Call. As far as the UI is concerned, the
+ * callPeer will never have a Call again and there will be no audio
+ * levels to display anyway so there is no point in throwing a
+ * NullPointerException here.
+ */
+ if (call != null)
+ {
+ call.addLocalUserSoundLevelListener(
+ new SoundLevelListener()
{
- localLevelIndicator.updateSoundLevel(level);
- }
- });
+ public void soundLevelChanged(
+ Object source,
+ int level)
+ {
+ localLevelIndicator.updateSoundLevel(level);
+ }
+ });
+ }
}
}
@@ -502,11 +516,8 @@ public class OneToOneCallPeerPanel
CallPeerSecurityStatusEvent securityEvent
= callPeer.getCurrentSecuritySettings();
- if (securityEvent != null
- && securityEvent instanceof CallPeerSecurityOnEvent)
- {
+ if (securityEvent instanceof CallPeerSecurityOnEvent)
securityOn((CallPeerSecurityOnEvent) securityEvent);
- }
}
/**
@@ -733,8 +744,10 @@ public class OneToOneCallPeerPanel
SrtpControl srtpControl = evt.getSecurityController();
if ((srtpControl.requiresSecureSignalingTransport()
- && callPeer.getProtocolProvider().isSignalingTransportSecure())
- || !srtpControl.requiresSecureSignalingTransport())
+ && callPeer
+ .getProtocolProvider()
+ .isSignalingTransportSecure())
+ || !srtpControl.requiresSecureSignalingTransport())
{
if (srtpControl instanceof ZrtpControl)
{
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallPeerMediaHandlerJabberGTalkImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallPeerMediaHandlerJabberGTalkImpl.java
index 8dfee62..0e535b0 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallPeerMediaHandlerJabberGTalkImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallPeerMediaHandlerJabberGTalkImpl.java
@@ -245,26 +245,23 @@ public abstract class AbstractCallPeerMediaHandlerJabberGTalkImpl
{
List<CryptoPacketExtension> cryptoPacketExtensions
= encryptionPacketExtension.getCryptoList();
- Vector<SrtpCryptoAttribute> peerAttributes
- = new Vector<SrtpCryptoAttribute>(cryptoPacketExtensions.size());
+ List<SrtpCryptoAttribute> peerAttributes
+ = new ArrayList<SrtpCryptoAttribute>(cryptoPacketExtensions.size());
for (CryptoPacketExtension cpe : cryptoPacketExtensions)
peerAttributes.add(cpe.toSrtpCryptoAttribute());
- if (peerAttributes == null)
- return null;
-
- if (isInitiator)
- return sDesControl.initiatorSelectAttribute(peerAttributes);
- else
- return sDesControl.responderSelectAttribute(peerAttributes);
+ return
+ isInitiator
+ ? sDesControl.initiatorSelectAttribute(peerAttributes)
+ : sDesControl.responderSelectAttribute(peerAttributes);
}
/**
* Returns if the remote peer supports ZRTP.
*
* @param encryptionPacketExtension The ENCRYPTION element received from
- * the remote peer. This may contain the ZRTP acket element for the remote
+ * the remote peer. This may contain the ZRTP packet element for the remote
* peer.
*
* @return True if the remote peer supports ZRTP. False, otherwise.
@@ -513,15 +510,16 @@ public abstract class AbstractCallPeerMediaHandlerJabberGTalkImpl
RtpDescriptionPacketExtension remoteDescription)
{
// Sets ZRTP or SDES, depending on the preferences for this account.
- List<String> preferredEncryptionProtocols = getPeer()
- .getProtocolProvider()
- .getAccountID()
- .getSortedEnabledEncryptionProtocolList();
+ List<String> preferredEncryptionProtocols
+ = getPeer()
+ .getProtocolProvider()
+ .getAccountID()
+ .getSortedEnabledEncryptionProtocolList();
- for(int i = 0; i < preferredEncryptionProtocols.size(); ++i)
+ for(String preferredEncryptionProtocol : preferredEncryptionProtocols)
{
// ZRTP
- if(preferredEncryptionProtocols.get(i).equals(
+ if(preferredEncryptionProtocol.equals(
ProtocolProviderFactory.ENCRYPTION_PROTOCOL + ".ZRTP"))
{
boolean isZRTPAddedToDescription
@@ -529,18 +527,19 @@ public abstract class AbstractCallPeerMediaHandlerJabberGTalkImpl
mediaType,
localDescription,
remoteDescription);
+
if(isZRTPAddedToDescription)
{
addZRTPAdvertisedEncryptions(
false,
remoteDescription,
mediaType);
- // Stops once an encryption advertisement has been choosen.
+ // Stops once an encryption advertisement has been chosen.
return;
}
}
// SDES
- else if(preferredEncryptionProtocols.get(i).equals(
+ else if(preferredEncryptionProtocol.equals(
ProtocolProviderFactory.ENCRYPTION_PROTOCOL + ".SDES"))
{
addSDESAdvertisedEncryptions(
@@ -552,7 +551,7 @@ public abstract class AbstractCallPeerMediaHandlerJabberGTalkImpl
localDescription,
remoteDescription))
{
- // Stops once an encryption advertisement has been choosen.
+ // Stops once an encryption advertisement has been chosen.
return;
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java
index 213bf29..a7995f5 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java
@@ -605,6 +605,88 @@ public class CallJabberImpl
}
/**
+ * Notifies this instance that a specific <tt>CobriConferenceIQ</tt> has
+ * been received.
+ *
+ * @param conferenceIQ the <tt>CobriConferenceIQ</tt> which has been
+ * received
+ * @return <tt>true</tt> if the specified <tt>conferenceIQ</tt> was
+ * processed by this instance and no further processing is to be performed
+ * by other possible processors of <tt>CobriConferenceIQ</tt>s; otherwise,
+ * <tt>false</tt>. Because a <tt>CobriConferenceIQ</tt> request sent from
+ * the Jitsi VideoBridge server to the application as its client concerns a
+ * specific <tt>CallJabberImpl</tt> implementation, no further processing by
+ * other <tt>CallJabberImpl</tt> instances is necessary once the
+ * <tt>CobriConferenceIQ</tt> is processed by the associated
+ * <tt>CallJabberImpl</tt> instance.
+ */
+ boolean processCobriConferenceIQ(CobriConferenceIQ conferenceIQ)
+ {
+ if (cobri == null)
+ {
+ /*
+ * This instance has not set up any conference using the Jitsi
+ * VideoBridge server-side technology yet so it cannot be bothered
+ * with related requests.
+ */
+ return false;
+ }
+ else if (conferenceIQ.getID().equals(cobri.getID()))
+ {
+ /*
+ * Remove the local Channels (from the specified conferenceIQ) i.e.
+ * the Channels on which the local peer/user is sending to the Jitsi
+ * VideoBridge server because they concern this Call only and not
+ * its CallPeers.
+ */
+ for (MediaType mediaType : MediaType.values())
+ {
+ String contentName = mediaType.toString();
+ CobriConferenceIQ.Content content
+ = conferenceIQ.getContent(contentName);
+
+ if (content != null)
+ {
+ CobriConferenceIQ.Content thisContent
+ = cobri.getContent(contentName);
+
+ if ((thisContent != null)
+ && (thisContent.getChannelCount() > 0))
+ {
+ CobriConferenceIQ.Channel thisChannel
+ = thisContent.getChannel(0);
+ CobriConferenceIQ.Channel channel
+ = content.getChannel(thisChannel.getID());
+
+ if (channel != null)
+ content.removeChannel(channel);
+ }
+ }
+ }
+
+ for (CallPeerJabberImpl callPeer : getCallPeerList())
+ callPeer.processCobriConferenceIQ(conferenceIQ);
+
+ /*
+ * We have removed the local Channels from the specified
+ * conferenceIQ. Consequently, it is no longer the same and fit for
+ * processing by other CallJabberImpl instances.
+ */
+ return true;
+ }
+ else
+ {
+ /*
+ * This instance has set up a conference using the Jitsi VideoBridge
+ * server-side technology but it is not the one referred to by the
+ * specified conferenceIQ i.e. the specified conferenceIQ does not
+ * concern this instance.
+ */
+ return false;
+ }
+ }
+
+ /**
* Creates a new call peer and sends a RINGING response.
*
* @param jingleIQ the {@link JingleIQ} that created the session.
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java
index 4ec4dd0..b2632fc 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java
@@ -9,6 +9,7 @@ package net.java.sip.communicator.impl.protocol.jabber;
import java.lang.reflect.*;
import java.util.*;
+import net.java.sip.communicator.impl.protocol.jabber.extensions.cobri.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.ContentPacketExtension.SendersEnum;
import net.java.sip.communicator.impl.protocol.jabber.jinglesdp.*;
@@ -114,9 +115,11 @@ public class CallPeerJabberImpl
try
{
- getMediaHandler().getTransportManager().
- wrapupConnectivityEstablishment();
- answer = getMediaHandler().generateSessionAccept();
+ CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler();
+
+ mediaHandler
+ .getTransportManager().wrapupConnectivityEstablishment();
+ answer = mediaHandler.generateSessionAccept();
}
catch(Exception exc)
{
@@ -362,6 +365,26 @@ public class CallPeerJabberImpl
}
/**
+ * Notifies this instance that a specific <tt>CobriConferenceIQ</tt> has
+ * been received. This <tt>CallPeerJabberImpl</tt> uses the part of the
+ * information provided in the specified <tt>conferenceIQ</tt> which
+ * concerns it only.
+ *
+ * @param conferenceIQ the <tt>CobriConferenceIQ</tt> which has been
+ * received
+ */
+ void processCobriConferenceIQ(CobriConferenceIQ conferenceIQ)
+ {
+ /*
+ * CallPeerJabberImpl does not itself/directly know the specifics
+ * related to the channels allocated on the Jitsi VideoBridge server.
+ * The channels contain transport and media-related information so
+ * forward the notification to CallPeerMediaHandlerJabberImpl.
+ */
+ getMediaHandler().processCobriConferenceIQ(conferenceIQ);
+ }
+
+ /**
* Processes the content-accept {@link JingleIQ}.
*
* @param content The {@link JingleIQ} that contains content that remote
@@ -373,20 +396,27 @@ public class CallPeerJabberImpl
try
{
- getMediaHandler().getTransportManager().
- wrapupConnectivityEstablishment();
- getMediaHandler().processAnswer(contents);
+ CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler();
+
+ mediaHandler
+ .getTransportManager().wrapupConnectivityEstablishment();
+ mediaHandler.processAnswer(contents);
}
- catch(Exception exc)
+ catch (Exception e)
{
- logger.warn("Failed to process a content-accept", exc);
- //send an error response;
- JingleIQ errResp = JinglePacketFactory.createSessionTerminate(
- sessionInitIQ.getTo(), sessionInitIQ.getFrom(),
- sessionInitIQ.getSID(), Reason.INCOMPATIBLE_PARAMETERS,
- "Error: " + exc.getMessage());
+ logger.warn("Failed to process a content-accept", e);
- setState(CallPeerState.FAILED, "Error: " + exc.getMessage());
+ // Send an error response.
+ String reason = "Error: " + e.getMessage();
+ JingleIQ errResp
+ = JinglePacketFactory.createSessionTerminate(
+ sessionInitIQ.getTo(),
+ sessionInitIQ.getFrom(),
+ sessionInitIQ.getSID(),
+ Reason.INCOMPATIBLE_PARAMETERS,
+ reason);
+
+ setState(CallPeerState.FAILED, reason);
getProtocolProvider().getConnection().sendPacket(errResp);
return;
}
@@ -446,6 +476,7 @@ public class CallPeerJabberImpl
{
new Thread()
{
+ @Override
public void run()
{
try
@@ -537,25 +568,27 @@ public class CallPeerJabberImpl
try
{
- boolean modify = false;
- if(ext.getFirstChildOfType(RtpDescriptionPacketExtension.class)
- != null)
- {
- modify = true;
- }
+ boolean modify
+ = (ext.getFirstChildOfType(RtpDescriptionPacketExtension.class)
+ != null);
+
getMediaHandler().reinitContent(ext.getName(), ext, modify);
}
- catch(Exception exc)
+ catch(Exception e)
{
- logger.info("Failed to process an incoming content-modify", exc);
+ logger.info("Failed to process an incoming content-modify", e);
- //send an error response;
- JingleIQ errResp = JinglePacketFactory.createSessionTerminate(
- sessionInitIQ.getTo(), sessionInitIQ.getFrom(),
- sessionInitIQ.getSID(), Reason.INCOMPATIBLE_PARAMETERS,
- "Error: " + exc.getMessage());
+ // Send an error response.
+ String reason = "Error: " + e.getMessage();
+ JingleIQ errResp
+ = JinglePacketFactory.createSessionTerminate(
+ sessionInitIQ.getTo(),
+ sessionInitIQ.getFrom(),
+ sessionInitIQ.getSID(),
+ Reason.INCOMPATIBLE_PARAMETERS,
+ reason);
- setState(CallPeerState.FAILED, "Error: " + exc.getMessage());
+ setState(CallPeerState.FAILED, reason);
getProtocolProvider().getConnection().sendPacket(errResp);
return;
}
@@ -626,8 +659,8 @@ public class CallPeerJabberImpl
try
{
- mediaHandler.getTransportManager().
- wrapupConnectivityEstablishment();
+ mediaHandler
+ .getTransportManager().wrapupConnectivityEstablishment();
mediaHandler.processAnswer(answer);
}
catch(Exception exc)
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java
index 6af49cb..eaa5563 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java
@@ -9,6 +9,7 @@ package net.java.sip.communicator.impl.protocol.jabber;
import java.lang.reflect.*;
import java.util.*;
+import net.java.sip.communicator.impl.protocol.jabber.extensions.cobri.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*;
import net.java.sip.communicator.impl.protocol.jabber.jinglesdp.*;
import net.java.sip.communicator.service.protocol.*;
@@ -18,7 +19,7 @@ import net.java.sip.communicator.util.*;
import org.jitsi.service.neomedia.*;
import org.jitsi.service.neomedia.device.*;
import org.jitsi.service.neomedia.format.*;
-import org.jivesoftware.smack.util.StringUtils;
+import org.jivesoftware.smack.util.*;
import org.jivesoftware.smackx.packet.*;
/**
@@ -143,6 +144,61 @@ public class CallPeerMediaHandlerJabberImpl
}
/**
+ * {@inheritDoc}
+ *
+ * In the case of a telephony conference organized by the local peer/user
+ * via the Jitsi VideoBridge server-side technology, returns an SSRC
+ * reported by the server as received on the channel allocated by the local
+ * peer/user for the purposes of communicating with the <tt>CallPeer</tt>
+ * associated with this instance.
+ */
+ @Override
+ public long getRemoteSSRC(MediaType mediaType)
+ {
+ /*
+ * If the Jitsi VideoBridge server-side technology is utilized, a single
+ * MediaStream (per MediaType) is shared among the participating
+ * CallPeers and, consequently, the remote SSRCs cannot be associated
+ * with the CallPeers from which they are actually being sent. That's
+ * why the server will report them to the conference focus.
+ */
+ TransportManagerJabberImpl transportManager = this.transportManager;
+
+ if (transportManager instanceof RawUdpTransportManager)
+ {
+ RawUdpTransportManager rawUdpTransportManager
+ = (RawUdpTransportManager) transportManager;
+ CobriConferenceIQ.Channel channel
+ = rawUdpTransportManager.getCobriChannel(
+ mediaType,
+ false /* remote */);
+
+ if (channel != null)
+ {
+ long[] ssrcs = channel.getSSRCs();
+
+ /*
+ * A peer (regardless of whether it is local or remote) may send
+ * multiple RTP streams at any time. In such a case, it is not
+ * clear which one of their SSRCs is to be returned. Anyway, the
+ * super says that the returned is the last known and we will
+ * presume that the last known in the list reported by the Jitsi
+ * VideoBridge server is the last.
+ */
+ for (int i = ssrcs.length - 1; i >= 0; i--)
+ {
+ long remoteSSRC = ssrcs[i];
+
+ if (remoteSSRC != -1)
+ return remoteSSRC;
+ }
+ }
+ }
+
+ return super.getRemoteSSRC(mediaType);
+ }
+
+ /**
* Get the local content of a specific content type (like audio or video).
*
* @param contentType content type name
@@ -977,6 +1033,86 @@ public class CallPeerMediaHandlerJabberImpl
}
/**
+ * Notifies this instance that a specific <tt>CobriConferenceIQ</tt> has
+ * been received. This <tt>CallPeerMediaHandler</tt> uses the part of the
+ * information provided in the specified <tt>conferenceIQ</tt> which
+ * concerns it only.
+ *
+ * @param conferenceIQ the <tt>CobriConferenceIQ</tt> which has been
+ * received
+ */
+ void processCobriConferenceIQ(CobriConferenceIQ conferenceIQ)
+ {
+ /*
+ * This CallPeerMediaHandler stores the media information but it does
+ * not store the cobri Channels (which contain both media and transport
+ * information). The TransportManager associated with this instance
+ * stores the cobri Channels but does not store media information (such
+ * as the remote SSRCs). An design/implementation choice has to be made
+ * though and the present one is to have this CallPeerMediaHandler
+ * transparently (with respect to the TransportManager) store the media
+ * information inside the TransportManager.
+ */
+ TransportManagerJabberImpl transportManager = this.transportManager;
+
+ if (transportManager instanceof RawUdpTransportManager)
+ {
+ RawUdpTransportManager rawUdpTransportManager
+ = (RawUdpTransportManager) transportManager;
+ long oldAudioRemoteSSRC = getRemoteSSRC(MediaType.AUDIO);
+ long oldVideoRemoteSSRC = getRemoteSSRC(MediaType.VIDEO);
+
+ for (MediaType mediaType : MediaType.values())
+ {
+ CobriConferenceIQ.Channel dst
+ = rawUdpTransportManager.getCobriChannel(
+ mediaType,
+ false /* remote */);
+
+ if (dst != null)
+ {
+ CobriConferenceIQ.Content content
+ = conferenceIQ.getContent(mediaType.toString());
+
+ if (content != null)
+ {
+ CobriConferenceIQ.Channel src
+ = content.getChannel(dst.getID());
+
+ if (src != null)
+ {
+ long[] ssrcs = src.getSSRCs();
+
+ if (!Arrays.equals(dst.getSSRCs(), ssrcs))
+ dst.setSSRCs(src.getSSRCs());
+ }
+ }
+ }
+ }
+
+ /*
+ * Do fire new PropertyChangeEvents for the properties
+ * AUDIO_REMOTE_SSRC and VIDEO_REMOTE_SSRC if necessary.
+ */
+ long newAudioRemoteSSRC = getRemoteSSRC(MediaType.AUDIO);
+ long newVideoRemoteSSRC = getRemoteSSRC(MediaType.VIDEO);
+
+ if (oldAudioRemoteSSRC != newAudioRemoteSSRC)
+ {
+ firePropertyChange(
+ AUDIO_REMOTE_SSRC,
+ oldAudioRemoteSSRC, newAudioRemoteSSRC);
+ }
+ if (oldVideoRemoteSSRC != newVideoRemoteSSRC)
+ {
+ firePropertyChange(
+ VIDEO_REMOTE_SSRC,
+ oldVideoRemoteSSRC, newVideoRemoteSSRC);
+ }
+ }
+ }
+
+ /**
* Process a <tt>ContentPacketExtension</tt> and initialize its
* corresponding <tt>MediaStream</tt>.
*
@@ -986,7 +1122,7 @@ public class CallPeerMediaHandlerJabberImpl
* @throws OperationFailedException if we fail to handle <tt>content</tt>
* for reasons like failing to initialize media devices or streams.
* @throws IllegalArgumentException if there's a problem with the syntax or
- * the semantics of <tt>content</tt>. Method is synchronized in order to
+ * the semantics of <tt>content</tt>. The method is synchronized in order to
* avoid closing mediaHandler when we are currently in process of
* initializing, configuring and starting streams and anybody interested
* in this operation can synchronize to the mediaHandler instance to wait
@@ -1676,6 +1812,7 @@ public class CallPeerMediaHandlerJabberImpl
/**
* Returns the quality control for video calls if any.
+ *
* @return the implemented quality control.
*/
public QualityControl getQualityControl()
@@ -1695,6 +1832,7 @@ public class CallPeerMediaHandlerJabberImpl
/**
* Sometimes as initing a call with custom preset can set and we force
* that quality controls is supported.
+ *
* @param value whether quality controls is supported..
*/
public void setSupportQualityControls(boolean value)
@@ -1705,6 +1843,7 @@ public class CallPeerMediaHandlerJabberImpl
/**
* Closes the <tt>CallPeerMediaHandler</tt>.
*/
+ @Override
public synchronized void close()
{
super.close();
@@ -1721,16 +1860,17 @@ public class CallPeerMediaHandlerJabberImpl
/**
* Overrides to give access to the transport manager to send events
* about ICE state changes.
+ *
* @param property the name of the property of this
* <tt>PropertyChangeNotifier</tt> which had its value changed
* @param oldValue the value of the property with the specified name before
* the change
* @param newValue the value of the property with the specified name after
*/
+ @Override
protected void firePropertyChange(
String property,
- Object oldValue,
- Object newValue)
+ Object oldValue, Object newValue)
{
super.firePropertyChange(property, oldValue, newValue);
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java
index b2c9c46..8501831 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java
@@ -668,7 +668,7 @@ public class IceUdpTransportManager
for(Component component : stream.getComponents())
{
- for(Candidate candidate : component.getLocalCandidates())
+ for(Candidate<?> candidate : component.getLocalCandidates())
trans.addCandidate(createCandidate(candidate));
}
@@ -685,7 +685,7 @@ public class IceUdpTransportManager
* @return a new {@link CandidatePacketExtension} corresponding to the state
* of the <tt>candidate</tt> candidate.
*/
- private CandidatePacketExtension createCandidate(Candidate candidate)
+ private CandidatePacketExtension createCandidate(Candidate<?> candidate)
{
CandidatePacketExtension packet = new CandidatePacketExtension();
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
index 053e51e..0e5ae0d 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
@@ -117,7 +117,6 @@ public class OperationSetBasicTelephonyJabberImpl
}
else if (registrationState == RegistrationState.UNREGISTERED)
{
- // plug jingle unregistration
unsubscribeForJinglePackets();
if (logger.isInfoEnabled())
@@ -751,14 +750,14 @@ public class OperationSetBasicTelephonyJabberImpl
}
/**
- * Unsubscribes us to notifications about incoming jingle packets.
+ * Unsubscribes us from notifications about incoming jingle packets.
*/
private void unsubscribeForJinglePackets()
{
- if(protocolProvider.getConnection() != null)
- {
- protocolProvider.getConnection().removePacketListener(this);
- }
+ XMPPConnection connection = protocolProvider.getConnection();
+
+ if(connection != null)
+ connection.removePacketListener(this);
}
/**
@@ -773,19 +772,19 @@ public class OperationSetBasicTelephonyJabberImpl
*/
public boolean accept(Packet packet)
{
- String sid = null;
-
- //we only handle JingleIQ-s
- if( ! (packet instanceof JingleIQ) && !(packet instanceof SessionIQ))
+ // We handle JingleIQ and SessionIQ.
+ if(!(packet instanceof JingleIQ) && !(packet instanceof SessionIQ))
{
- AbstractCallPeer<?, ?> callPeer =
- activeCallsRepository.findCallPeerBySessInitPacketID(
- packet.getPacketID());
+ String packetID = packet.getPacketID();
+ AbstractCallPeer<?, ?> callPeer
+ = activeCallsRepository.findCallPeerBySessInitPacketID(
+ packetID);
if(callPeer == null)
{
- callPeer = activeGTalkCallsRepository.
- findCallPeerBySessInitPacketID(packet.getPacketID());
+ callPeer
+ = activeGTalkCallsRepository.findCallPeerBySessInitPacketID(
+ packetID);
}
if(callPeer != null)
@@ -798,20 +797,30 @@ public class OperationSetBasicTelephonyJabberImpl
if (error != null)
{
- logger.error("Received an error: code=" + error.getCode()
- + " message=" + error.getMessage());
- String message = "Service unavailable";
- Roster roster = getProtocolProvider().getConnection().
- getRoster();
+ String errorMessage = error.getMessage();
- if(!roster.contains(packet.getFrom()))
+ logger.error(
+ "Received an error: code=" + error.getCode()
+ + " message=" + errorMessage);
+
+ String message;
+
+ if (errorMessage == null)
{
- message += ": try adding the contact to your contact " +
- "list first.";
- }
+ Roster roster
+ = getProtocolProvider().getConnection().getRoster();
+ String packetFrom = packet.getFrom();
- if (error.getMessage() != null)
- message = error.getMessage();
+ message = "Service unavailable";
+ if(!roster.contains(packetFrom))
+ {
+ message
+ += ": try adding the contact " + packetFrom
+ + " to your contact list first.";
+ }
+ }
+ else
+ message = errorMessage;
callPeer.setState(CallPeerState.FAILED, message);
}
@@ -831,7 +840,7 @@ public class OperationSetBasicTelephonyJabberImpl
RtpDescriptionPacketExtension.class);
}
- sid = jingleIQ.getSID();
+ String sid = jingleIQ.getSID();
//if this is not a session-initiate we'll only take it if we've
//already seen its session ID.
@@ -845,12 +854,14 @@ public class OperationSetBasicTelephonyJabberImpl
{
return true;
}
+ else
+ {
+ String sid = sessionIQ.getID();
- sid = sessionIQ.getID();
-
- //if this is not a session's initiate we'll only take it if we've
- //already seen its session ID.
- return (activeGTalkCallsRepository.findSID(sid) != null);
+ // If this is not a session's initiate, we'll take it only if
+ // we've seen its session ID already.
+ return (activeGTalkCallsRepository.findSID(sid) != null);
+ }
}
return false;
}
@@ -863,66 +874,56 @@ public class OperationSetBasicTelephonyJabberImpl
*/
public void processPacket(Packet packet)
{
- if(packet instanceof JingleIQ)
- {
- JingleIQ jingleIQ = (JingleIQ)packet;
+ IQ iq = (IQ) packet;
- //to prevent hijacking sessions from other jingle based features
- //like file transfer for example, we should only send the
- //ack if this is a session-initiate with rtp content or if we are
- //the owners of this packet's sid
+ /*
+ * To prevent hijacking sessions from other Jingle-based features such
+ * as file transfer, we should send the ack only if this is a
+ * session-initiate with RTP content or if we are the owners of the
+ * packet's SID.
+ */
- //first ack all "set" requests.
- if(jingleIQ.getType() == IQ.Type.SET)
- {
- IQ ack = IQ.createResultIQ(jingleIQ);
- protocolProvider.getConnection().sendPacket(ack);
- }
+ //first ack all "set" requests.
+ if(iq.getType() == IQ.Type.SET)
+ {
+ IQ ack = IQ.createResultIQ(iq);
- try
- {
- processJingleIQ(jingleIQ);
- }
- catch(Throwable t)
- {
- logger.info("Error while handling incoming Jingle packet: ", t);
+ protocolProvider.getConnection().sendPacket(ack);
+ }
- /*
- * The Javadoc on ThreadDeath says: If ThreadDeath is caught by
- * a method, it is important that it be rethrown so that the
- * thread actually dies.
- */
- if (t instanceof ThreadDeath)
- throw (ThreadDeath) t;
- }
+ try
+ {
+ if (iq instanceof JingleIQ)
+ processJingleIQ((JingleIQ) iq);
+ else if (iq instanceof SessionIQ)
+ processSessionIQ((SessionIQ) iq);
}
- else if(packet instanceof SessionIQ)
+ catch(Throwable t)
{
- SessionIQ sessionIQ = (SessionIQ)packet;
-
- //first ack all "set" requests.
- if(sessionIQ.getType() == IQ.Type.SET)
+ if (logger.isInfoEnabled())
{
- IQ ack = IQ.createResultIQ(sessionIQ);
- protocolProvider.getConnection().sendPacket(ack);
- }
+ String packetClass;
- try
- {
- processSessionIQ(sessionIQ);
- }
- catch(Throwable t)
- {
- logger.info("Error while handling incoming GTalk packet: ", t);
+ if (iq instanceof JingleIQ)
+ packetClass = "Jingle";
+ else if (iq instanceof SessionIQ)
+ packetClass = "Gtalk";
+ else
+ packetClass = packet.getClass().getSimpleName();
- /*
- * The Javadoc on ThreadDeath says: If ThreadDeath is caught by
- * a method, it is important that it be rethrown so that the
- * thread actually dies.
- */
- if (t instanceof ThreadDeath)
- throw (ThreadDeath) t;
+ logger.info(
+ "Error while handling incoming " + packetClass
+ + " packet: ",
+ t);
}
+
+ /*
+ * The Javadoc on ThreadDeath says: If ThreadDeath is caught by
+ * a method, it is important that it be rethrown so that the
+ * thread actually dies.
+ */
+ if (t instanceof ThreadDeath)
+ throw (ThreadDeath) t;
}
}
@@ -948,10 +949,12 @@ public class OperationSetBasicTelephonyJabberImpl
if(error != null)
{
- message += "\ncode=" + error.getCode()
- + " message=" + error.getMessage();
- logger.error(" code=" + error.getCode()
- + " message=" + error.getMessage());
+ String errorStr
+ = "code=" + error.getCode()
+ + " message=" + error.getMessage();
+
+ message += "\n" + errorStr;
+ logger.error(" " + errorStr);
}
if (callPeer != null)
@@ -964,13 +967,12 @@ public class OperationSetBasicTelephonyJabberImpl
if(action == JingleAction.SESSION_INITIATE)
{
- CallJabberImpl call = null;
-
TransferPacketExtension transfer
= (TransferPacketExtension)
jingleIQ.getExtension(
- TransferPacketExtension.ELEMENT_NAME,
- TransferPacketExtension.NAMESPACE);
+ TransferPacketExtension.ELEMENT_NAME,
+ TransferPacketExtension.NAMESPACE);
+ CallJabberImpl call = null;
if (transfer != null)
{
@@ -992,7 +994,7 @@ public class OperationSetBasicTelephonyJabberImpl
&& protocolProvider.getOurJID().equals(
transfer.getTo()))
{
- // OK transfer correspond to us
+ // OK, we are legally involved in the transfer.
call = attendantCall;
}
}
@@ -1000,18 +1002,16 @@ public class OperationSetBasicTelephonyJabberImpl
}
if(call == null)
- {
call = new CallJabberImpl(this);
- }
- final CallJabberImpl callThread = call;
+ final CallJabberImpl finalCall = call;
new Thread()
{
@Override
public void run()
{
- callThread.processSessionInitiate(jingleIQ);
+ finalCall.processSessionInitiate(jingleIQ);
}
}.start();
@@ -1076,11 +1076,14 @@ public class OperationSetBasicTelephonyJabberImpl
if (packetExtension instanceof CoinPacketExtension)
{
- CoinPacketExtension coinExt =
- (CoinPacketExtension)packetExtension;
+ CoinPacketExtension coinExt
+ = (CoinPacketExtension)packetExtension;
+
callPeer.setConferenceFocus(
- Boolean.parseBoolean(coinExt.getAttributeAsString(
- CoinPacketExtension.ISFOCUS_ATTR_NAME)));
+ Boolean.parseBoolean(
+ coinExt.getAttributeAsString(
+ CoinPacketExtension
+ .ISFOCUS_ATTR_NAME)));
}
}
}
@@ -1164,6 +1167,7 @@ public class OperationSetBasicTelephonyJabberImpl
// smack processor
new Thread()
{
+ @Override
public void run()
{
try
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java
index 511cc43..3931c14 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java
@@ -341,26 +341,23 @@ public class OperationSetTelephonyConferencingJabberImpl
*
* @param evt the event received
*/
+ @Override
public void registrationStateChanged(RegistrationStateChangeEvent evt)
{
super.registrationStateChanged(evt);
RegistrationState registrationState = evt.getNewState();
- if (registrationState == RegistrationState.REGISTERED)
+ if (RegistrationState.REGISTERED.equals(registrationState))
{
if(logger.isDebugEnabled())
- {
logger.debug("Subscribes to Coin packets");
- }
subscribeForCoinPackets();
}
- else if (registrationState == RegistrationState.UNREGISTERED)
+ else if (RegistrationState.UNREGISTERED.equals(registrationState))
{
if(logger.isDebugEnabled())
- {
logger.debug("Unsubscribes to Coin packets");
- }
unsubscribeForCoinPackets();
}
}
@@ -432,14 +429,14 @@ public class OperationSetTelephonyConferencingJabberImpl
}
/**
- * Unsubscribes us to notifications about incoming Coin packets.
+ * Unsubscribes us from notifications about incoming Coin packets.
*/
private void unsubscribeForCoinPackets()
{
- if(parentProvider.getConnection() != null)
- {
- parentProvider.getConnection().removePacketListener(this);
- }
+ XMPPConnection connection = parentProvider.getConnection();
+
+ if (connection != null)
+ connection.removePacketListener(this);
}
/**
@@ -452,12 +449,7 @@ public class OperationSetTelephonyConferencingJabberImpl
*/
public boolean accept(Packet packet)
{
- if(!(packet instanceof CoinIQ))
- {
- return false;
- }
-
- return true;
+ return (packet instanceof CoinIQ);
}
/**
@@ -487,17 +479,20 @@ public class OperationSetTelephonyConferencingJabberImpl
sid);
if (callPeer != null)
- handleCoin(coinIQ, callPeer);
+ handleCoin(callPeer, coinIQ);
}
}
/**
- * Handle Coin IQ.
+ * Handles a specific <tt>CoinIQ</tt> sent from a specific
+ * <tt>CallPeer</tt>.
*
- * @param coinIQ Coin IQ
- * @param callPeer a <tt>CallPeer</tt>
+ * @param callPeer the <tt>CallPeer</tt> from which the specified
+ * <tt>CoinIQ</tt> was sent
+ * @param coinIQ the <tt>CoinIQ</tt> which was sent from the specified
+ * <tt>callPeer</tt>
*/
- private void handleCoin(CoinIQ coinIQ, CallPeerJabberImpl callPeer)
+ private void handleCoin(CallPeerJabberImpl callPeer, CoinIQ coinIQ)
{
setConferenceInfoXML(callPeer, -1, coinIQ.getChildElementXML());
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java
index 2408cd7..f4ff56b 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java
@@ -8,23 +8,38 @@ package net.java.sip.communicator.impl.protocol.jabber;
import java.util.*;
-import org.jivesoftware.smack.*;
-import org.jivesoftware.smackx.packet.*;
-
import net.java.sip.communicator.impl.protocol.jabber.extensions.cobri.*;
import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.service.protocol.media.*;
+import net.java.sip.communicator.util.*;
+
+import org.jivesoftware.smack.*;
+import org.jivesoftware.smack.filter.*;
+import org.jivesoftware.smack.packet.*;
/**
* Implements <tt>OperationSetVideoBridge</tt> for Jabber.
*
* @author Yana Stamcheva
+ * @author Lyubomir Marinov
*/
public class OperationSetVideoBridgeImpl
- implements OperationSetVideoBridge
+ implements OperationSetVideoBridge,
+ PacketFilter,
+ PacketListener,
+ RegistrationStateChangeListener
{
/**
- * The parent protocol provider.
+ * The <tt>Logger</tt> used by the <tt>OperationSetVideoBridgeImpl</tt>
+ * class and its instances for logging output.
+ */
+ private static final Logger logger
+ = Logger.getLogger(OperationSetVideoBridgeImpl.class);
+
+ /**
+ * The <tt>ProtocolProviderService</tt> implementation which initialized
+ * this instance, owns it and is often referred to as its parent.
*/
private final ProtocolProviderServiceJabberImpl protocolProvider;
@@ -35,10 +50,28 @@ public class OperationSetVideoBridgeImpl
*
* @param protocolProvider the parent Jabber protocol provider
*/
- public OperationSetVideoBridgeImpl(ProtocolProviderServiceJabberImpl
- protocolProvider)
+ public OperationSetVideoBridgeImpl(
+ ProtocolProviderServiceJabberImpl protocolProvider)
{
this.protocolProvider = protocolProvider;
+ this.protocolProvider.addRegistrationStateChangeListener(this);
+ }
+
+ /**
+ * Implements {@link PacketFilter}. Determines whether this instance is
+ * interested in a specific {@link Packet}.
+ * <tt>OperationSetVideoBridgeImpl</tt> returns <tt>true</tt> if the
+ * specified <tt>packet</tt> is a {@link CobriConferenceIQ}; otherwise,
+ * <tt>false</tt>.
+ *
+ * @param packet the <tt>Packet</tt> to be determined whether this instance
+ * is interested in it
+ * @return <tt>true</tt> if the specified <tt>packet</tt> is a
+ * <tt>CobriConferenceIQ</tt>; otherwise, <tt>false</tt>
+ */
+ public boolean accept(Packet packet)
+ {
+ return (packet instanceof CobriConferenceIQ);
}
/**
@@ -54,12 +87,14 @@ public class OperationSetVideoBridgeImpl
*/
public Call createConfCall(String[] callees)
throws OperationFailedException,
- OperationNotSupportedException
+ OperationNotSupportedException
{
- return protocolProvider
+ return
+ protocolProvider
.getOperationSet(OperationSetTelephonyConferencing.class)
- .createConfCall(callees,
- new MediaAwareCallConference(true));
+ .createConfCall(
+ callees,
+ new MediaAwareCallConference(true));
}
/**
@@ -82,10 +117,10 @@ public class OperationSetVideoBridgeImpl
throws OperationFailedException,
OperationNotSupportedException
{
- return protocolProvider.getOperationSet(
- OperationSetTelephonyConferencing.class).inviteCalleeToCall(
- uri,
- call);
+ return
+ protocolProvider
+ .getOperationSet(OperationSetTelephonyConferencing.class)
+ .inviteCalleeToCall(uri, call);
}
/**
@@ -100,7 +135,151 @@ public class OperationSetVideoBridgeImpl
{
String jitsiVideoBridge = protocolProvider.getJitsiVideoBridge();
- return (jitsiVideoBridge != null
- && jitsiVideoBridge.length() > 0);
+ return ((jitsiVideoBridge != null) && (jitsiVideoBridge.length() > 0));
+ }
+
+ /**
+ * Notifies this instance that a specific <tt>CobriConferenceIQ</tt> has
+ * been received.
+ *
+ * @param conferenceIQ the <tt>CobriConferenceIQ</tt> which has been
+ * received
+ */
+ private void processCobriConferenceIQ(CobriConferenceIQ conferenceIQ)
+ {
+ /*
+ * The application is not a Jitsi VideoBridge server, it is a client.
+ * Consequently, the specified CobriConferenceIQ is sent to it in
+ * relation to the part of the application's functionality which makes
+ * requests to a Jitsi VideoBridge server i.e. CallJabberImpl.
+ *
+ * Additionally, the method processCobriConferenceIQ is presently tasked
+ * with processing CobriConferenceIQ requests only. They are SET IQs
+ * sent by the Jitsi VideoBridge server to notify the application about
+ * updates in the states of (cobri) conferences organized by the
+ * application.
+ */
+ if (IQ.Type.SET.equals(conferenceIQ.getType())
+ && conferenceIQ.getID() != null)
+ {
+ OperationSetBasicTelephony<?> basicTelephony
+ = protocolProvider.getOperationSet(
+ OperationSetBasicTelephony.class);
+
+ if (basicTelephony != null)
+ {
+ Iterator<? extends Call> i = basicTelephony.getActiveCalls();
+
+ while (i.hasNext())
+ {
+ Call call = i.next();
+
+ if (call instanceof CallJabberImpl)
+ {
+ CallJabberImpl callJabberImpl = (CallJabberImpl) call;
+ MediaAwareCallConference conference
+ = callJabberImpl.getConference();
+
+ if ((conference != null)
+ && conference.isJitsiVideoBridge())
+ {
+ /*
+ * TODO We may want to disallow rogue CallJabberImpl
+ * instances which may throw an exception to prevent
+ * the conferenceIQ from reaching the CallJabberImpl
+ * instance which it was meant for.
+ */
+ callJabberImpl.processCobriConferenceIQ(
+ conferenceIQ);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Implements {@link PacketListener}. Notifies this instance that a specific
+ * {@link Packet} (which this instance has already expressed interest into
+ * by returning <tt>true</tt> from {@link #accept(Packet)}) has been
+ * received.
+ *
+ * @param packet the <tt>Packet</tt> which has been received and which this
+ * instance is given a chance to process
+ */
+ public void processPacket(Packet packet)
+ {
+ /*
+ * As we do elsewhere, acknowledge the receipt of the Packet first and
+ * then go about our business with it.
+ */
+ IQ iq = (IQ) packet;
+
+ if (iq.getType() == IQ.Type.SET)
+ protocolProvider.getConnection().sendPacket(IQ.createResultIQ(iq));
+
+ /*
+ * Now that the acknowledging is out of the way, do go about our
+ * business with the Packet.
+ */
+ CobriConferenceIQ conferenceIQ = (CobriConferenceIQ) iq;
+ boolean interrupted = false;
+
+ try
+ {
+ processCobriConferenceIQ(conferenceIQ);
+ }
+ catch (Throwable t)
+ {
+ logger.error(
+ "An error occurred during the processing of a "
+ + packet.getClass().getName() + " packet",
+ t);
+
+ if (t instanceof InterruptedException)
+ {
+ /*
+ * We cleared the interrupted state of the current Thread by
+ * catching the InterruptedException. However, we do not really
+ * care whether the current Thread has been interrupted - we
+ * caught the InterruptedException because we want to swallow
+ * any Throwable. Consequently, we should better restore the
+ * interrupted state.
+ */
+ interrupted = true;
+ }
+ else if (t instanceof ThreadDeath)
+ throw (ThreadDeath) t;
+ }
+ if (interrupted)
+ Thread.currentThread().interrupt();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Implements {@link RegistrationStateChangeListener}. Notifies this
+ * instance that there has been a change in the <tt>RegistrationState</tt>
+ * of {@link #protocolProvider}. Subscribes this instance to
+ * {@link CobriConferenceIQ}s as soon as <tt>protocolProvider</tt> is
+ * registered and unsubscribes it as soon as <tt>protocolProvider</tt> is
+ * unregistered.
+ */
+ public void registrationStateChanged(RegistrationStateChangeEvent ev)
+ {
+ RegistrationState registrationState = ev.getNewState();
+
+ if (RegistrationState.REGISTERED.equals(registrationState))
+ {
+ protocolProvider.getConnection().addPacketListener(this, this);
+ }
+ else if (RegistrationState.UNREGISTERED.equals(registrationState))
+ {
+ XMPPConnection connection = protocolProvider.getConnection();
+
+ if (connection != null)
+ connection.removePacketListener(this);
+ }
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/P2PTransportManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/P2PTransportManager.java
index d56660e..f8f0289 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/P2PTransportManager.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/P2PTransportManager.java
@@ -21,6 +21,7 @@ import org.jivesoftware.smack.packet.*;
* Google P2P TransportManager.
*
* @author Sebastien Vincent
+ * @author Lyubomir Marinov
*/
public class P2PTransportManager
extends IceUdpTransportManager
@@ -61,13 +62,16 @@ public class P2PTransportManager
* @return the ICE agent to use for all the ICE negotiation that this
* transport manager would be going through
*/
+ @Override
protected Agent createIceAgent()
{
CallPeerJabberImpl peer = getCallPeer();
ProtocolProviderServiceJabberImpl provider = peer.getProtocolProvider();
- Agent iceAgent = TransportManagerGTalkImpl.createAgent(provider,
- !peer.isInitiator());
+ Agent iceAgent
+ = TransportManagerGTalkImpl.createAgent(
+ provider,
+ !peer.isInitiator());
/* We use a custom strategy that will wait a little bit before choosing
* to go through a relay. In fact Empathy will begin to send first the
@@ -76,7 +80,7 @@ public class P2PTransportManager
* checks will start earlier for relay.
*/
iceAgent.setNominationStrategy(
- NominationStrategy.NOMINATE_FIRST_HOST_OR_REFLEXIVE_VALID);
+ NominationStrategy.NOMINATE_FIRST_HOST_OR_REFLEXIVE_VALID);
return iceAgent;
}
@@ -89,6 +93,7 @@ public class P2PTransportManager
* <tt>TransportManagerJabberImpl</tt>
* @see TransportManagerJabberImpl#getXmlNamespace()
*/
+ @Override
public String getXmlNamespace()
{
return "http://www.google.com/transport/p2p";
@@ -99,6 +104,7 @@ public class P2PTransportManager
*
* @return <tt>PacketExtension</tt>
*/
+ @Override
protected PacketExtension getTransportPacketExtension()
{
return new GTalkTransportPacketExtension();
@@ -113,37 +119,46 @@ public class P2PTransportManager
*
* @return the {@link GTalkTransportPacketExtension}
*/
+ @Override
public PacketExtension createTransport(IceMediaStream stream)
{
GTalkTransportPacketExtension trans
= new GTalkTransportPacketExtension();
if(stream != null)
+ {
for(Component component : stream.getComponents())
{
- List<LocalCandidate> candToRemove =
- new ArrayList<LocalCandidate>();
- List<LocalCandidate> candidates =
- component.getLocalCandidates();
+ /* Remove the bases of the UPNP candidates. */
+ List<LocalCandidate> candidates
+ = component.getLocalCandidates();
+ List<LocalCandidate> candidatesToRemove = null;
- for(LocalCandidate candidate : component.getLocalCandidates())
+ for(LocalCandidate candidate : candidates)
{
if(candidate instanceof UPNPCandidate)
{
LocalCandidate base = candidate.getBase();
- candToRemove.add(base);
+
+ if (candidatesToRemove == null)
+ {
+ candidatesToRemove
+ = new ArrayList<LocalCandidate>(
+ candidates.size());
+ }
+ candidatesToRemove.add(base);
}
}
-
- for(Candidate candidate : candToRemove)
+ if (candidatesToRemove != null)
{
- candidates.remove(candidate);
+ for(Candidate<?> candidateToRemove : candidatesToRemove)
+ candidates.remove(candidateToRemove);
}
- for(Candidate candidate : candidates)
+ for(Candidate<?> candidate : candidates)
trans.addCandidate(createCandidate(candidate));
}
-
+ }
return trans;
}
@@ -157,19 +172,13 @@ public class P2PTransportManager
* @return a new {@link CandidatePacketExtension} corresponding to the state
* of the <tt>candidate</tt> candidate.
*/
- private GTalkCandidatePacketExtension createCandidate(Candidate candidate)
+ private GTalkCandidatePacketExtension createCandidate(
+ Candidate<?> candidate)
{
- String name =
- candidate.getParentComponent().getParentStream().getName();
-
- if(candidate.getParentComponent().getComponentID() == Component.RTP)
- {
- name = "rtp";
- }
- else
- {
- name = "rtcp";
- }
+ String name
+ = (candidate.getParentComponent().getComponentID() == Component.RTP)
+ ? "rtp"
+ : "rtcp";
return GTalkPacketFactory.createCandidate(candidate, name);
}
@@ -194,9 +203,10 @@ public class P2PTransportManager
* {@link #wrapupCandidateHarvest()}.
* @throws OperationFailedException in case we fail allocating ports
*/
+ @Override
public void startCandidateHarvest(
- List<ContentPacketExtension> ourOffer,
- final TransportInfoSender transportInfoSender)
+ List<ContentPacketExtension> ourOffer,
+ final TransportInfoSender transportInfoSender)
throws OperationFailedException
{
final List<ContentPacketExtension> offer = ourOffer;
@@ -224,13 +234,11 @@ public class P2PTransportManager
}
for(ContentPacketExtension ourContent : offer)
- {
- ourContent.addChildExtension(
- getTransportPacketExtension());
- }
+ ourContent.addChildExtension(getTransportPacketExtension());
new Thread()
{
+ @Override
public void run()
{
Collection<ContentPacketExtension> transportInfoContents
@@ -246,7 +254,8 @@ public class P2PTransportManager
= ourContent.getFirstChildOfType(
RtpDescriptionPacketExtension.class);
- ourContent.addChildExtension(getTransportPacketExtension());
+ ourContent.addChildExtension(
+ getTransportPacketExtension());
IceMediaStream stream = null;
try
@@ -275,7 +284,7 @@ public class P2PTransportManager
transportInfoContents.add(transportInfoContent);
transportInfoSender.sendTransportInfo(
- transportInfoContents);
+ transportInfoContents);
}
}
}
@@ -303,28 +312,23 @@ public class P2PTransportManager
if (IceProcessingState.RUNNING.equals(iceAgent.getState()))
{
if(logger.isInfoEnabled())
- {
logger.info("Update ICE remote candidates");
- }
for (ContentPacketExtension content : remote)
{
GTalkTransportPacketExtension transport
= content.getFirstChildOfType(
GTalkTransportPacketExtension.class);
-
List<GTalkCandidatePacketExtension> candidates
= transport.getChildExtensionsOfType(
- GTalkCandidatePacketExtension.class);
+ GTalkCandidatePacketExtension.class);
- if(candidates == null || candidates.size() == 0)
- {
+ if((candidates == null) || (candidates.size() == 0))
return false;
- }
RtpDescriptionPacketExtension description
= content.getFirstChildOfType(
- RtpDescriptionPacketExtension.class);
+ RtpDescriptionPacketExtension.class);
if (description == null)
{
@@ -371,7 +375,7 @@ public class P2PTransportManager
candidate.getType().toString()),
"0",
(long)(candidate.getPreference() * 1000),
- // Gingle does not send rel-addr/rel-port infromation.
+ // Gingle does not send rel-addr/rel-port information.
null,
ufrag);
@@ -383,9 +387,7 @@ public class P2PTransportManager
for(IceMediaStream stream : iceAgent.getStreams())
{
for(Component component : stream.getComponents())
- {
component.updateRemoteCandidate();
- }
}
return false;
@@ -399,7 +401,6 @@ public class P2PTransportManager
GTalkTransportPacketExtension transport
= content.getFirstChildOfType(
GTalkTransportPacketExtension.class);
-
List<GTalkCandidatePacketExtension> candidates
= transport.getChildExtensionsOfType(
GTalkCandidatePacketExtension.class);
@@ -440,7 +441,6 @@ public class P2PTransportManager
*/
if (candidate.getGeneration() != generation)
continue;
-
if(candidate.getProtocol().equalsIgnoreCase("ssltcp"))
continue;
@@ -462,7 +462,7 @@ public class P2PTransportManager
candidate.getType().toString()),
"0",
(long)(candidate.getPreference() * 1000),
- // Gingle does not send rel-addr/rel-port infromation.
+ // Gingle does not send rel-addr/rel-port information.
null,
ufrag);
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/RawUdpTransportManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/RawUdpTransportManager.java
index dea5306..6af0f58 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/RawUdpTransportManager.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/RawUdpTransportManager.java
@@ -337,6 +337,11 @@ public class RawUdpTransportManager
* Gets the {@link CobriConferenceIQ.Channel} which belongs to a content
* associated with a specific <tt>MediaType</tt> and is to be either locally
* or remotely used.
+ * <p>
+ * <b>Note</b>: Modifications to the <tt>CobriConferenceIQ.Channel</tt>
+ * instance returned by the method propagate to (the state of) this
+ * instance.
+ * </p>
*
* @param mediaType the <tt>MediaType</tt> associated with the content which
* contains the <tt>CobriConferenceIQ.Channel</tt> to get
@@ -348,7 +353,7 @@ public class RawUdpTransportManager
* in accord with the specified <tt>local</tt> indicator if such a channel
* exists; otherwise, <tt>null</tt>
*/
- private CobriConferenceIQ.Channel getCobriChannel(
+ CobriConferenceIQ.Channel getCobriChannel(
MediaType mediaType,
boolean local)
{
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java
index b8e9bf0..301d4fd 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java
@@ -27,7 +27,6 @@ import org.jivesoftware.smackx.*;
import org.jivesoftware.smackx.packet.*;
import org.xmlpull.mxp1.*;
import org.xmlpull.v1.*;
-// disambiguation
/**
* Keeps track of entity capabilities.
@@ -35,7 +34,7 @@ import org.xmlpull.v1.*;
* This work is based on Jonas Adahl's smack fork.
*
* @author Emil Ivov
- * @author Lubomir Marinov
+ * @author Lyubomir Marinov
*/
public class EntityCapsManager
{
@@ -885,18 +884,16 @@ public class EntityCapsManager
/* Google Talk web does not set hash but we need it to be cached */
if(hash == null)
- {
hash = "";
- }
if (hash != null)
{
// Check it the packet indicates that the user is online. We
// will use this information to decide if we're going to send
// the discover info request.
- boolean online = false;
- if (packet instanceof Presence)
- online = ((Presence) packet).isAvailable();
+ boolean online
+ = (packet instanceof Presence)
+ && ((Presence) packet).isAvailable();
if(online)
{
@@ -917,7 +914,7 @@ public class EntityCapsManager
* Implements an immutable value which stands for a specific node, a
* specific hash (algorithm) and a specific ver.
*
- * @author Lubomir Marinov
+ * @author Lyubomir Marinov
*/
public static class Caps
{
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/cobri/CobriConferenceIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/cobri/CobriConferenceIQ.java
index d44c6ca..db23b3a 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/cobri/CobriConferenceIQ.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/cobri/CobriConferenceIQ.java
@@ -39,6 +39,13 @@ public class CobriConferenceIQ
= "http://jitsi.org/protocol/videobridge#conference";
/**
+ * An array of <tt>long</tt>s which represents the lack of any (RTP) SSRCs
+ * seen/received on a <tt>Channel</tt>. Explicitly defined to reduce
+ * unnecessary allocations.
+ */
+ public static final long[] NO_SSRCS = new long[0];
+
+ /**
* The list of {@link Content}s included into this <tt>conference</tt> IQ.
*/
private final List<Content> contents = new LinkedList<Content>();
@@ -234,6 +241,13 @@ public class CobriConferenceIQ
public static final String RTP_PORT_ATTR_NAME = "rtpport";
/**
+ * The name of the XML element which is a child of the &lt;channel&gt;
+ * element and which identifies/specifies an (RTP) SSRC which has been
+ * seen/received on the respective <tt>Channel</tt>.
+ */
+ public static final String SSRC_ELEMENT_NAME = "ssrc";
+
+ /**
* The number of seconds of inactivity after which the <tt>channel</tt>
* represented by this instance expires.
*/
@@ -267,6 +281,13 @@ public class CobriConferenceIQ
private int rtpPort;
/**
+ * The list of (RTP) SSRCs which have been seen/received on this
+ * <tt>Channel</tt> by now. These may exclude SSRCs which are no longer
+ * active. Set by the Jitsi VideoBridge server, not its clients.
+ */
+ private long[] ssrcs = NO_SSRCS;
+
+ /**
* Adds a <tt>payload-type</tt> element defined by XEP-0167: Jingle RTP
* Sessions to this <tt>channel</tt>.
*
@@ -290,6 +311,33 @@ public class CobriConferenceIQ
}
/**
+ * Adds a specific (RTP) SSRC to the list of SSRCs seen/received on this
+ * <tt>Channel</tt>. Invoked by the Jitsi VideoBridge server, not its
+ * clients.
+ *
+ * @param ssrc the (RTP) SSRC to be added to the list of SSRCs
+ * seen/received on this <tt>Channel</tt>
+ * @return <tt>true</tt> if the list of SSRCs seen/received on this
+ * <tt>Channel</tt> has been modified as part of the method call;
+ * otherwise, <tt>false</tt>
+ */
+ public synchronized boolean addSSRC(long ssrc)
+ {
+ // contains
+ for (long element : ssrcs)
+ if (element == ssrc)
+ return false;
+
+ // add
+ long[] newSSRCs = new long[ssrcs.length + 1];
+
+ System.arraycopy(ssrcs, 0, newSSRCs, 0, ssrcs.length);
+ newSSRCs[ssrcs.length] = ssrc;
+ ssrcs = newSSRCs;
+ return true;
+ }
+
+ /**
* Gets the number of seconds of inactivity after which the
* <tt>channel</tt> represented by this instance expires.
*
@@ -332,6 +380,18 @@ public class CobriConferenceIQ
}
/**
+ * Gets (a copy of) the list of (RTP) SSRCs seen/received on this
+ * <tt>Channel</tt>.
+ *
+ * @return an array of <tt>long</tt>s which represents (a copy of) the
+ * list of (RTP) SSRCs seen/received on this <tt>Channel</tt>
+ */
+ public synchronized long[] getSSRCs()
+ {
+ return (ssrcs.length == 0) ? NO_SSRCS : ssrcs.clone();
+ }
+
+ /**
* Removes a <tt>payload-type</tt> element defined by XEP-0167: Jingle
* RTP Sessions from this <tt>channel</tt>.
*
@@ -347,6 +407,54 @@ public class CobriConferenceIQ
}
/**
+ * Removes a specific (RTP) SSRC from the list of SSRCs seen/received on
+ * this <tt>Channel</tt>. Invoked by the Jitsi VideoBridge server, not
+ * its clients.
+ *
+ * @param ssrc the (RTP) SSRC to be removed from the list of SSRCs
+ * seen/received on this <tt>Channel</tt>
+ * @return <tt>true</tt> if the list of SSRCs seen/received on this
+ * <tt>Channel</tt> has been modified as part of the method call;
+ * otherwise, <tt>false</tt>
+ */
+ public synchronized boolean removeSSRC(long ssrc)
+ {
+ if (ssrcs.length == 1)
+ {
+ if (ssrcs[0] == ssrc)
+ {
+ ssrcs = NO_SSRCS;
+ return true;
+ }
+ else
+ return false;
+ }
+ else
+ {
+ for (int i = 0; i < ssrcs.length; i++)
+ {
+ if (ssrcs[i] == ssrc)
+ {
+ long[] newSSRCs = new long[ssrcs.length - 1];
+
+ if (i != 0)
+ System.arraycopy(ssrcs, 0, newSSRCs, 0, i);
+ if (i != newSSRCs.length)
+ {
+ System.arraycopy(
+ ssrcs, i + 1,
+ newSSRCs, i,
+ newSSRCs.length - i);
+ }
+ ssrcs = newSSRCs;
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
* Sets the number of seconds of inactivity after which the
* <tt>channel</tt> represented by this instance expires.
*
@@ -389,6 +497,24 @@ public class CobriConferenceIQ
this.rtpPort = rtpPort;
}
+ /**
+ * Sets the list of (RTP) SSRCs seen/received on this <tt>Channel</tt>.
+ *
+ * @param ssrcs the list of (RTP) SSRCs to be set as seen/received on
+ * this <tt>Channel</tt>
+ */
+ public void setSSRCs(long[] ssrcs)
+ {
+ /*
+ * TODO Make sure that the SSRCs set on this instance do not contain
+ * duplicates.
+ */
+ this.ssrcs
+ = ((ssrcs == null) || (ssrcs.length == 0))
+ ? NO_SSRCS
+ : ssrcs.clone();
+ }
+
public void toXML(StringBuilder xml)
{
xml.append('<').append(ELEMENT_NAME);
@@ -396,45 +522,70 @@ public class CobriConferenceIQ
String id = getID();
if (id != null)
+ {
xml.append(' ').append(ID_ATTR_NAME).append("='").append(id)
.append('\'');
+ }
String host = getHost();
if (host != null)
+ {
xml.append(' ').append(HOST_ATTR_NAME).append("='").append(host)
.append('\'');
+ }
int rtpPort = getRTPPort();
if (rtpPort > 0)
+ {
xml.append(' ').append(RTP_PORT_ATTR_NAME).append("='")
.append(rtpPort).append('\'');
+ }
int rtcpPort = getRTCPPort();
if (rtcpPort > 0)
+ {
xml.append(' ').append(RTCP_PORT_ATTR_NAME).append("='")
.append(rtcpPort).append('\'');
+ }
int expire = getExpire();
if (expire >= 0)
+ {
xml.append(' ').append(EXPIRE_ATTR_NAME).append("='")
.append(expire).append('\'');
+ }
List<PayloadTypePacketExtension> payloadTypes = getPayloadTypes();
+ boolean hasPayloadTypes = (payloadTypes.size() != 0);
+ long[] ssrcs = getSSRCs();
+ boolean hasSSRCs = (ssrcs.length != 0);
- if (payloadTypes.size() == 0)
+ if (hasPayloadTypes || hasSSRCs)
{
- xml.append(" />");
+ xml.append('>');
+ if (hasPayloadTypes)
+ {
+ for (PayloadTypePacketExtension payloadType : payloadTypes)
+ xml.append(payloadType.toXML());
+ }
+ if (hasSSRCs)
+ {
+ for (long ssrc : ssrcs)
+ {
+ xml.append('<').append(SSRC_ELEMENT_NAME).append('>')
+ .append(ssrc).append("</")
+ .append(SSRC_ELEMENT_NAME).append('>');
+ }
+ }
+ xml.append("</").append(ELEMENT_NAME).append('>');
}
else
{
- xml.append('>');
- for (PayloadTypePacketExtension payloadType : payloadTypes)
- xml.append(payloadType.toXML());
- xml.append("</").append(ELEMENT_NAME).append('>');
+ xml.append(" />");
}
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/cobri/CobriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/cobri/CobriIQProvider.java
index aab8ad3..54d4ccf 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/cobri/CobriIQProvider.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/cobri/CobriIQProvider.java
@@ -51,6 +51,7 @@ public class CobriIQProvider
CobriConferenceIQ.Channel channel = null;
CobriConferenceIQ.Content content = null;
PacketExtensionProvider payloadTypePacketExtensionProvider = null;
+ StringBuilder ssrc = null;
while (!done)
{
@@ -64,15 +65,21 @@ public class CobriIQProvider
{
done = true;
}
- else if (CobriConferenceIQ.Channel.ELEMENT_NAME
- .equals(name))
+ else if (CobriConferenceIQ.Channel.ELEMENT_NAME.equals(
+ name))
{
content.addChannel(channel);
channel = null;
}
- else if (CobriConferenceIQ.Content.ELEMENT_NAME
+ else if (CobriConferenceIQ.Channel.SSRC_ELEMENT_NAME
.equals(name))
{
+ channel.addSSRC(Long.parseLong(ssrc.toString().trim()));
+ ssrc = null;
+ }
+ else if (CobriConferenceIQ.Content.ELEMENT_NAME.equals(
+ name))
+ {
conference.addContent(content);
content = null;
}
@@ -129,9 +136,14 @@ public class CobriIQProvider
if ((expire != null) && (expire.length() != 0))
channel.setExpire(Integer.parseInt(expire));
}
- else if (CobriConferenceIQ.Content.ELEMENT_NAME
+ else if (CobriConferenceIQ.Channel.SSRC_ELEMENT_NAME
.equals(name))
{
+ ssrc = new StringBuilder();
+ }
+ else if (CobriConferenceIQ.Content.ELEMENT_NAME.equals(
+ name))
+ {
content = new CobriConferenceIQ.Content();
String contentName
@@ -181,6 +193,13 @@ public class CobriIQProvider
}
break;
}
+
+ case XmlPullParser.TEXT:
+ {
+ if (ssrc != null)
+ ssrc.append(parser.getText());
+ break;
+ }
}
}
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java b/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java
index e490dd1..44f4a68 100644
--- a/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java
+++ b/src/net/java/sip/communicator/service/protocol/AbstractCallPeer.java
@@ -253,9 +253,8 @@ public abstract class AbstractCallPeer<T extends Call,
protected ConferenceMember findConferenceMember(long ssrc)
{
List<ConferenceMember> members = getConferenceMembers();
- int memberCount = members.size();
- for (int i = 0; i < memberCount; i++)
+ for (int i = 0, memberCount = members.size(); i < memberCount; i++)
{
ConferenceMember member = members.get(i);
diff --git a/src/net/java/sip/communicator/service/protocol/AccountID.java b/src/net/java/sip/communicator/service/protocol/AccountID.java
index ba1cf86..c373120 100644
--- a/src/net/java/sip/communicator/service/protocol/AccountID.java
+++ b/src/net/java/sip/communicator/service/protocol/AccountID.java
@@ -463,14 +463,15 @@ public abstract class AccountID
public List<String> getSortedEnabledEncryptionProtocolList()
{
Map<String, Integer> encryptionProtocols
- = this.getIntegerPropertiesByPrefix(
+ = getIntegerPropertiesByPrefix(
ProtocolProviderFactory.ENCRYPTION_PROTOCOL,
true);
Map<String, Boolean> encryptionProtocolStatus
- = this.getBooleanPropertiesByPrefix(
+ = getBooleanPropertiesByPrefix(
ProtocolProviderFactory.ENCRYPTION_PROTOCOL_STATUS,
true,
false);
+
// If the account is not yet configured, then ZRTP is activated by
// default.
if(encryptionProtocols.size() == 0)
@@ -484,49 +485,45 @@ public abstract class AccountID
true);
}
- List<String> sortedEncryptionProtocolList
+ List<String> sortedEncryptionProtocols
= new ArrayList<String>(encryptionProtocols.size());
- Iterator<String> names = encryptionProtocols.keySet().iterator();
- String name;
- int index;
+
// First: add all protocol in the right order.
- while(names.hasNext())
+ for (Map.Entry<String, Integer> e : encryptionProtocols.entrySet())
{
- name = names.next();
- index = encryptionProtocols.get(name);
+ int index = e.getValue();
// If the key is set.
- if(index != -1)
+ if (index != -1)
{
- if(index > sortedEncryptionProtocolList.size())
- {
- index = sortedEncryptionProtocolList.size();
- }
- sortedEncryptionProtocolList.add(index, name);
+ if (index > sortedEncryptionProtocols.size())
+ index = sortedEncryptionProtocols.size();
+
+ String name = e.getKey();
+
+ sortedEncryptionProtocols.add(index, name);
}
}
// Second: remove all disabled protocol.
- String encryptionProtocolPropertyName;
- int prefixeLength
+ int namePrefixLength
= ProtocolProviderFactory.ENCRYPTION_PROTOCOL.length() + 1;
- names = encryptionProtocols.keySet().iterator();
- while(names.hasNext())
+
+ for (Iterator<String> i = sortedEncryptionProtocols.iterator();
+ i.hasNext();)
{
- encryptionProtocolPropertyName = names.next();
- index = encryptionProtocols.get(encryptionProtocolPropertyName);
- name = encryptionProtocolPropertyName.substring(prefixeLength);
- // If the key is set.
- if(index != -1 && !encryptionProtocolStatus.get(
- ProtocolProviderFactory.ENCRYPTION_PROTOCOL_STATUS
+ String name = i.next().substring(namePrefixLength);
+
+ if (!encryptionProtocolStatus.get(
+ ProtocolProviderFactory.ENCRYPTION_PROTOCOL_STATUS
+ "."
+ name))
{
- sortedEncryptionProtocolList.remove(index);
+ i.remove();
}
}
- return sortedEncryptionProtocolList;
+ return sortedEncryptionProtocols;
}
/**
diff --git a/src/net/java/sip/communicator/service/protocol/ActiveCallsRepository.java b/src/net/java/sip/communicator/service/protocol/ActiveCallsRepository.java
index e1ceeb4..ebe4008 100644
--- a/src/net/java/sip/communicator/service/protocol/ActiveCallsRepository.java
+++ b/src/net/java/sip/communicator/service/protocol/ActiveCallsRepository.java
@@ -100,7 +100,12 @@ public abstract class ActiveCallsRepository<T extends Call,
{
synchronized(activeCalls)
{
- return new LinkedList<T>(activeCalls.values()).iterator();
+ /*
+ * Given that we know the elements that will go into the new List,
+ * it is more optimal in terms of memory and execution time to use
+ * ArrayList rather than LinkedList.
+ */
+ return new ArrayList<T>(activeCalls.values()).iterator();
}
}
diff --git a/src/net/java/sip/communicator/service/protocol/event/RegistrationStateChangeListener.java b/src/net/java/sip/communicator/service/protocol/event/RegistrationStateChangeListener.java
index aba6456..3b4d56d 100644
--- a/src/net/java/sip/communicator/service/protocol/event/RegistrationStateChangeListener.java
+++ b/src/net/java/sip/communicator/service/protocol/event/RegistrationStateChangeListener.java
@@ -10,8 +10,7 @@ import java.util.*;
/**
* An event listener that should be implemented by parties interested in changes
- * that occur in the registration state of a
- * <code>ProtocolProviderService</code>.
+ * that occur in the registration state of a <tt>ProtocolProviderService</tt>.
*
* @author Emil Ivov
*/
@@ -19,12 +18,11 @@ public interface RegistrationStateChangeListener
extends EventListener
{
/**
- * The method is called by a <code>ProtocolProviderService</code>
- * implementation whenever a change in the registration state of the
- * corresponding provider had occurred.
+ * The method is called by a <tt>ProtocolProviderService</tt> implementation
+ * whenever a change in its registration state has occurred.
*
- * @param evt
- * the event describing the status change.
+ * @param evt a <tt>RegistrationStateChangeEvent</tt> which describes the
+ * registration state change.
*/
public void registrationStateChanged(RegistrationStateChangeEvent evt);
}
diff --git a/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java b/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java
index 3b31144..9d6812c 100644
--- a/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java
+++ b/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java
@@ -526,63 +526,38 @@ public abstract class AbstractOperationSetTelephonyConferencing<
MediaAwareCallPeer<?,?,?> callPeer,
MediaType mediaType)
{
- MediaStream stream = callPeer.getMediaHandler().getStream(mediaType);
- long remoteSourceID;
+ long remoteSourceID
+ = callPeer.getMediaHandler().getRemoteSSRC(mediaType);
- if (stream != null)
+ if (remoteSourceID != -1)
{
- remoteSourceID = stream.getRemoteSourceID();
- if (remoteSourceID != -1)
- {
- /*
- * TODO Technically, we are detecting conflicts within a Call
- * while we should be detecting them within the whole
- * CallConference.
- */
- MediaAwareCall<?,?,?> call = callPeer.getCall();
+ /*
+ * TODO Technically, we are detecting conflicts within a Call
+ * while we should be detecting them within the whole
+ * CallConference.
+ */
+ MediaAwareCall<?,?,?> call = callPeer.getCall();
- if (call != null)
+ if (call != null)
+ {
+ for (MediaAwareCallPeer<?,?,?> aCallPeer
+ : call.getCallPeerList())
{
- for (MediaAwareCallPeer<?,?,?> aCallPeer
- : call.getCallPeerList())
+ if (aCallPeer != callPeer)
{
- if (aCallPeer != callPeer)
+ long aRemoteSourceID
+ = aCallPeer.getMediaHandler().getRemoteSSRC(
+ mediaType);
+
+ if (aRemoteSourceID == remoteSourceID)
{
- MediaStream aStream
- = aCallPeer.getMediaHandler().getStream(
- mediaType);
-
- /*
- * When the Jitsi VideoBridge server-side technology
- * is utilized by the local peer/user to host a
- * telephony conference, one and the same
- * MediaStream instance will be shared by the
- * CallPeers. This will definitely lead to a
- * conflict.
- */
- if (aStream == stream)
- {
- remoteSourceID = -1;
- break;
- }
- else
- {
- long aRemoteSourceID
- = stream.getRemoteSourceID();
-
- if (aRemoteSourceID == remoteSourceID)
- {
- remoteSourceID = -1;
- break;
- }
- }
+ remoteSourceID = -1;
+ break;
}
}
}
}
}
- else
- remoteSourceID = -1;
return remoteSourceID;
}
@@ -706,15 +681,15 @@ public abstract class AbstractOperationSetTelephonyConferencing<
* Notifies this <tt>PropertyChangeListener</tt> that the value of a
* specific property of the notifier it is registered with has changed.
*
- * @param event a <tt>PropertyChangeEvent</tt> which describes the source of
+ * @param ev a <tt>PropertyChangeEvent</tt> which describes the source of
* the event, the name of the property which has changed its value and the
* old and new values of the property
* @see PropertyChangeListener#propertyChange(PropertyChangeEvent)
*/
@SuppressWarnings("unchecked")
- public void propertyChange(PropertyChangeEvent event)
+ public void propertyChange(PropertyChangeEvent ev)
{
- String propertyName = event.getPropertyName();
+ String propertyName = ev.getPropertyName();
if (CallPeerMediaHandler.AUDIO_LOCAL_SSRC.equals(
propertyName)
@@ -726,8 +701,7 @@ public abstract class AbstractOperationSetTelephonyConferencing<
propertyName))
{
Call call
- = ((CallPeerMediaHandler<MediaAwareCallPeerT>)
- event.getSource())
+ = ((CallPeerMediaHandler<MediaAwareCallPeerT>) ev.getSource())
.getPeer()
.getCall();
diff --git a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
index f5c4c98..7702c42 100644
--- a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
+++ b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
@@ -606,15 +606,15 @@ public abstract class CallPeerMediaHandler
}
/**
- * Gets the last-known remote SSRC of the audio <tt>MediaStream</tt> of this
- * instance.
+ * Gets the last-known SSRC of an RTP stream with a specific
+ * <tt>MediaType</tt> received by a <tt>MediaStream</tt> of this instance.
*
- * @return the last-known remote SSRC of the audio <tt>MediaStream</tt> of
- * this instance
+ * @return the last-known SSRC of an RTP stream with a specific
+ * <tt>MediaType</tt> received by a <tt>MediaStream</tt> of this instance
*/
- public long getAudioRemoteSSRC()
+ public long getRemoteSSRC(MediaType mediaType)
{
- return mediaHandler.getRemoteSSRC(this, MediaType.AUDIO);
+ return mediaHandler.getRemoteSSRC(this, mediaType);
}
/**
@@ -1032,14 +1032,18 @@ public abstract class CallPeerMediaHandler
synchronized (localAudioLevelListenerLock)
{
if (localAudioLevelListener != null)
+ {
audioStream.setLocalUserAudioLevelListener(
localAudioLevelListener);
+ }
}
synchronized (streamAudioLevelListenerLock)
{
if (streamAudioLevelListener != null)
+ {
audioStream.setStreamAudioLevelListener(
streamAudioLevelListener);
+ }
}
synchronized (csrcAudioLevelListenerLock)
{
diff --git a/src/net/java/sip/communicator/service/protocol/media/DynamicRTPExtensionsRegistry.java b/src/net/java/sip/communicator/service/protocol/media/DynamicRTPExtensionsRegistry.java
index 9a9e654..5c03c0c 100644
--- a/src/net/java/sip/communicator/service/protocol/media/DynamicRTPExtensionsRegistry.java
+++ b/src/net/java/sip/communicator/service/protocol/media/DynamicRTPExtensionsRegistry.java
@@ -192,7 +192,7 @@ public class DynamicRTPExtensionsRegistry
{
throw new IllegalStateException(
"Impossible to map more than the 255 already mapped "
- +" RTP extensions");
+ +" RTP extensions");
}
byte extID = nextExtensionMapping++;
diff --git a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java
index 92b2b25..55054ea 100644
--- a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java
+++ b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java
@@ -773,10 +773,10 @@ public abstract class MediaAwareCallPeer
if (getConferenceMemberCount() > 2)
{
// this peer is now a conference focus with more than three
- // participants. This means that the this peer is mixing and sending
- // us audio for at least two separate participants. We therefore
- // need to remove the stream level listeners and switch to CSRC
- // level listening
+ // participants. This means that this peer is mixing and sending us
+ // audio for at least two separate participants. We therefore need
+ // to remove the stream level listeners and switch to CSRC level
+ // listening
CallPeerMediaHandler<?> mediaHandler = getMediaHandler();
mediaHandler.setStreamAudioLevelListener(null);
@@ -839,7 +839,8 @@ public abstract class MediaAwareCallPeer
&& ((conferenceMemberCount = getConferenceMemberCount()) > 0)
&& (conferenceMemberCount < 3))
{
- long audioRemoteSSRC = getMediaHandler().getAudioRemoteSSRC();
+ long audioRemoteSSRC
+ = getMediaHandler().getRemoteSSRC(MediaType.AUDIO);
if (audioRemoteSSRC != CallPeerMediaHandler.SSRC_UNKNOWN)
{
@@ -873,9 +874,11 @@ public abstract class MediaAwareCallPeer
= streamAudioLevelListeners.size();
for(int i = 0; i < streamAudioLevelListenerCount; i++)
+ {
streamAudioLevelListeners.get(i).soundLevelChanged(
this,
newLevel);
+ }
}
}
diff --git a/src/net/java/sip/communicator/service/protocol/media/MediaHandler.java b/src/net/java/sip/communicator/service/protocol/media/MediaHandler.java
index 5211d80..c5e2632 100644
--- a/src/net/java/sip/communicator/service/protocol/media/MediaHandler.java
+++ b/src/net/java/sip/communicator/service/protocol/media/MediaHandler.java
@@ -149,26 +149,34 @@ public class MediaHandler
Object source = evt.getSource();
if (source == audioStream)
+ {
setLocalSSRC(
MediaType.AUDIO,
audioStream.getLocalSourceID());
+ }
else if (source == videoStream)
+ {
setLocalSSRC(
MediaType.VIDEO,
videoStream.getLocalSourceID());
+ }
}
else if (MediaStream.PNAME_REMOTE_SSRC.equals(propertyName))
{
Object source = evt.getSource();
if (source == audioStream)
+ {
setRemoteSSRC(
MediaType.AUDIO,
audioStream.getRemoteSourceID());
+ }
else if (source == videoStream)
+ {
setRemoteSSRC(
MediaType.VIDEO,
videoStream.getRemoteSourceID());
+ }
}
}
};
@@ -817,8 +825,7 @@ public class MediaHandler
{
this.audioStream
.removePropertyChangeListener(
- streamPropertyChangeListener);
-
+ streamPropertyChangeListener);
this.audioStream.close();
}
@@ -831,7 +838,7 @@ public class MediaHandler
{
this.audioStream
.addPropertyChangeListener(
- streamPropertyChangeListener);
+ streamPropertyChangeListener);
audioLocalSSRC = this.audioStream.getLocalSourceID();
audioRemoteSSRC = this.audioStream.getRemoteSourceID();
}
diff --git a/src/net/java/sip/communicator/service/protocol/media/TransportManager.java b/src/net/java/sip/communicator/service/protocol/media/TransportManager.java
index 6106360..ede1b3a 100644
--- a/src/net/java/sip/communicator/service/protocol/media/TransportManager.java
+++ b/src/net/java/sip/communicator/service/protocol/media/TransportManager.java
@@ -7,7 +7,6 @@
package net.java.sip.communicator.service.protocol.media;
import java.net.*;
-import java.util.*;
import net.java.sip.communicator.service.netaddr.*;
import net.java.sip.communicator.service.protocol.*;