tries a rescue of my git repository after a network loss

cusax-fix
Emil Ivov 16 years ago
parent f4df77d8e2
commit 2437a95d8e

@ -1,96 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.jabber;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* Keeps a list of all calls currently active and maintained by this protocol
* provider. Offers methods for finding a call by its ID, peer session
* and others.
*
* @author Emil Ivov
* @author Symphorien Wanko
*/
public class ActiveCallsRepository
extends CallChangeAdapter
{
/**
* logger of this class
*/
private static final Logger logger
= Logger.getLogger(ActiveCallsRepository.class);
/**
* The operation set that created us. Instance is mainly used for firing
* events when necessary.
*/
private OperationSetBasicTelephonyJabberImpl parentOperationSet = null;
/**
* A table mapping call ids against call instances.
*/
private Hashtable<String, CallJabberImpl> activeCalls
= new Hashtable<String, CallJabberImpl>();
/**
* It's where we store all active calls
* @param opSet the <tt>OperationSetBasicTelphony</tt> instance which has
* been used to create calls in this repository
*/
public ActiveCallsRepository(OperationSetBasicTelephonyJabberImpl opSet)
{
this.parentOperationSet = opSet;
}
/**
* Adds the specified call to the list of calls tracked by this repository.
* @param call CallJabberImpl
*/
public void addCall(CallJabberImpl call)
{
activeCalls.put(call.getCallID(), call);
call.addCallChangeListener(this);
}
/**
* If <tt>evt</tt> indicates that the call has been ended we remove it from
* the repository.
* @param evt the <tt>CallChangeEvent</tt> instance containing the source
* calls and its old and new state.
*/
public void callStateChanged(CallChangeEvent evt)
{
if(evt.getEventType().equals(CallChangeEvent.CALL_STATE_CHANGE)
&& ((CallState)evt.getNewValue()).equals(CallState.CALL_ENDED))
{
CallJabberImpl sourceCall = this.activeCalls
.remove(evt.getSourceCall().getCallID());
if (logger.isTraceEnabled())
logger.trace( "Removing call " + sourceCall + " from the list of "
+ "active calls because it entered an ENDED state");
this.parentOperationSet.fireCallEvent(
CallEvent.CALL_ENDED, sourceCall);
}
}
/**
* Returns an iterator over all currently active (non-ended) calls.
*
* @return an iterator over all currently active (non-ended) calls.
*/
public Iterator<CallJabberImpl> getActiveCalls()
{
return new LinkedList<CallJabberImpl>(activeCalls.values()).iterator();
}
}

@ -6,8 +6,7 @@
*/
package net.java.sip.communicator.impl.protocol.jabber;
import java.util.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
@ -20,37 +19,42 @@
* @author Symphorien Wanko
*/
public class CallJabberImpl
extends Call
extends AbstractCall<CallPeerJabberImpl, ProtocolProviderServiceJabberImpl>
implements CallPeerListener
{
/**
* Logger of this class
*/
private static final Logger logger = Logger.getLogger(CallJabberImpl.class);
/**
* A list containing all <tt>CallPeer</tt>s of this call.
*/
private Vector<CallPeerJabberImpl> callPeers
= new Vector<CallPeerJabberImpl>();
/**
* The <tt>CallSession</tt> that the media service has created for this
* call.
* The operation set that created us.
*/
// private CallSession mediaCallSession = null;
private final OperationSetBasicTelephonyJabberImpl parentOpSet;
/**
* Crates a CallJabberImpl instance belonging to <tt>sourceProvider</tt> and
* initiated by <tt>CallCreator</tt>.
* associated with the jingle session with the specified <tt>jingleSID</tt>.
* If this call corresponds to an incoming jingle session then the jingleSID
* would come from there. Otherwise one could generate one using {@link
* JingleIQ#generateSID()}
*
* @param sourceProvider the ProtocolProviderServiceJabberImpl instance in the
* context of which this call has been created.
* @param parentOpSet the {@link OperationSetBasicTelephonyJabberImpl}
* instance in the context of which this call has been created.
*/
protected CallJabberImpl(ProtocolProviderServiceJabberImpl sourceProvider)
protected CallJabberImpl(
OperationSetBasicTelephonyJabberImpl parentOpSet)
{
super(sourceProvider);
super(parentOpSet.getProtocolProvider());
this.parentOpSet = parentOpSet;
//let's add ourselves to the calls repo. we are doing it ourselves just
//to make sure that no one ever forgets.
parentOpSet.getActiveCallsRepository().addCall(this);
}
////////// legacy methods ///////////////
/**
* Adds <tt>callPeer</tt> to the list of peers in this call.
* If the call peer is already included in the call, the method has
@ -60,12 +64,12 @@ protected CallJabberImpl(ProtocolProviderServiceJabberImpl sourceProvider)
*/
public void addCallPeer(CallPeerJabberImpl callPeer)
{
if(callPeers.contains(callPeer))
if(getCallPeersVector().contains(callPeer))
return;
callPeer.addCallPeerListener(this);
this.callPeers.add(callPeer);
getCallPeersVector().add(callPeer);
fireCallPeerEvent( callPeer, CallPeerEvent.CALL_PEER_ADDED);
}
@ -78,39 +82,20 @@ public void addCallPeer(CallPeerJabberImpl callPeer)
*/
public void removeCallPeer(CallPeerJabberImpl callPeer)
{
if(!callPeers.contains(callPeer))
if(!getCallPeersVector().contains(callPeer))
return;
this.callPeers.remove(callPeer);
getCallPeersVector().remove(callPeer);
callPeer.setCall(null);
callPeer.removeCallPeerListener(this);
fireCallPeerEvent(
callPeer, CallPeerEvent.CALL_PEER_REMOVED);
if(callPeers.size() == 0)
if(getCallPeersVector().size() == 0)
setCallState(CallState.CALL_ENDED);
}
/**
* Returns an iterator over all call peers.
* @return an Iterator over all peers currently involved in the call.
*/
public Iterator<CallPeer> getCallPeers()
{
return new LinkedList<CallPeer>(callPeers).iterator();
}
/**
* Returns the number of peers currently associated with this call.
* @return an <tt>int</tt> indicating the number of peers currently
* associated with this call.
*/
public int getCallPeerCount()
{
return callPeers.size();
}
/**
* Dummy implementation of a method (inherited from CallPeerListener)
* that we don't need.
@ -210,4 +195,104 @@ public void removeLocalUserSoundLevelListener(
{
}
////////////////////////////////////// NEW METHODS ///////////////////////////////////////////////////////
/**
* Creates a new call peer and sends a RINGING response.
*
* @param jingleIQ the {@link JingleIQ} that created the session.
*
* @return the newly created {@link CallPeerJabberImpl} (the one that sent
* the INVITE).
*/
public CallPeerJabberImpl processSessionInitiate(JingleIQ jingleIQ)
{
String remoteParty = jingleIQ.getInitiator();
//according to the Jingle spec initiator may be null.
if (remoteParty == null)
remoteParty = jingleIQ.getFrom();
CallPeerJabberImpl peer = createCallPeerFor(
remoteParty, true, jingleIQ.getSID());
//send a ringing response
try
{
if (logger.isTraceEnabled())
logger.trace("will send ringing response: ");
JingleIQ response = JinglePacketFactory.createRinging(jingleIQ);
parentOpSet.getProtocolProvider().getConnection()
.sendPacket(response);
}
catch (Exception ex)
{
logger.error("Error while trying to send a request", ex);
peer.setState(CallPeerState.FAILED,
"Internal Error: " + ex.getMessage());
return peer;
}
return peer;
}
/**
* Creates a new call peer associated with <tt>jingleIQ</tt>
*
* @param remoteParty the full jid of the remote party that the new peer
* will be representing.
* @param isIncoming indicates whether this is an incoming call (as opposed
* to a call that we've initiated locally).
* @param jingleSID the ID of the session that the new peer belongs to.
*
* @return a new instance of a <tt>CallPeerJabberImpl</tt>.
*/
private CallPeerJabberImpl createCallPeerFor(String remoteParty,
boolean isIncoming,
String jingleSID)
{
CallPeerJabberImpl callPeer = new CallPeerJabberImpl(
remoteParty, this, jingleSID);
addCallPeer(callPeer);
callPeer.setState( isIncoming
? CallPeerState.INCOMING_CALL
: CallPeerState.INITIATING_CALL);
// if this was the first peer we added in this call then the call is
// new and we also need to notify everyone of its creation.
if(this.getCallPeerCount() == 1)
{
parentOpSet.fireCallEvent( (isIncoming
? CallEvent.CALL_RECEIVED
: CallEvent.CALL_INITIATED),
this);
}
return callPeer;
}
/**
* Determines if this call contains a peer whose corresponding session has
* the specified <tt>sid</tt>.
*
* @param sid the ID of the session whose peer we are looking for.
*
* @return <tt>true</tt> if this call contains a peer with the specified
* jingle <tt>sid</tt> and false otherwise.
*/
public boolean containsJingleSID(String sid)
{
for(CallPeerJabberImpl peer : getCallPeersVector())
{
if (peer.getJingleSID().equals(sid))
return true;
}
return false;
}
}

@ -6,8 +6,12 @@
*/
package net.java.sip.communicator.impl.protocol.jabber;
import org.jivesoftware.smack.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* Our Jabber implementation of the default CallPeer;
@ -16,13 +20,19 @@
* @author Symphorien Wanko
*/
public class CallPeerJabberImpl
extends AbstractCallPeer
extends AbstractCallPeer<CallJabberImpl, ProtocolProviderServiceJabberImpl>
{
/**
* The <tt>Logger</tt> used by the <tt>CallPeerJabberImpl</tt>
* class and its instances for logging output.
*/
private static final Logger logger = Logger
.getLogger(CallPeerJabberImpl.class.getName());
/**
* The jabber address of this peer
*/
private String peerAddress = null;
private String peerJID = null;
/**
* A byte array containing the image/photo representing the call peer.
@ -30,7 +40,9 @@ public class CallPeerJabberImpl
private byte[] image;
/**
* A string uniquely identifying the peer.
* A string uniquely identifying the peer. The reason we are keeping an ID
* of our own rather than using the Jingle session id is that we can't
* guarantee uniqueness of of jingle SIDs from one client to the next.
*/
private String peerID;
@ -39,17 +51,27 @@ public class CallPeerJabberImpl
*/
private CallJabberImpl call;
/**
* The session ID of the Jingle session associated with this call.
*/
private final String jingleSID;
/**
* Creates a new call peer with address <tt>peerAddress</tt>.
*
* @param peerAddress the Jabber address of the new call peer.
* @param owningCall the call that contains this call peer.
* @param jingleSID the ID of the session that we are maintaining with this
* peer.
*/
public CallPeerJabberImpl(String peerAddress,
CallJabberImpl owningCall)
public CallPeerJabberImpl(String peerAddress,
CallJabberImpl owningCall,
String jingleSID)
{
this.peerAddress = peerAddress;
this.peerJID = peerAddress;
this.call = owningCall;
this.jingleSID = jingleSID;
call.addCallPeer(this);
//create the uid
@ -64,7 +86,7 @@ public CallPeerJabberImpl(String peerAddress,
*/
public String getAddress()
{
return peerAddress;
return peerJID;
}
/**
@ -78,10 +100,10 @@ public void setAddress(String address)
{
String oldAddress = getAddress();
if(peerAddress.equals(address))
if(peerJID.equals(address))
return;
this.peerAddress = address;
this.peerJID = address;
//Fire the Event
fireCallPeerChangeEvent(
CallPeerChangeEvent.CALL_PEER_ADDRESS_CHANGE,
@ -108,7 +130,7 @@ public String getDisplayName()
return cont.getDisplayName();
}
}
return peerAddress;
return peerJID;
}
/**
@ -176,15 +198,15 @@ protected void setPeerID(String peerID)
*
* @return a reference to the call containing this peer.
*/
public Call getCall()
public CallJabberImpl getCall()
{
return call;
}
/**
* Sets the call containing this peer.
* @param call the call that this call peer is
* partdicipating in.
*
* @param call the call that this call peer is participating in.
*/
protected void setCall(CallJabberImpl call)
{
@ -196,7 +218,7 @@ protected void setCall(CallJabberImpl call)
* @return a reference to the ProtocolProviderService that this peer
* belongs to.
*/
public ProtocolProviderService getProtocolProvider()
public ProtocolProviderServiceJabberImpl getProtocolProvider()
{
return this.getCall().getProtocolProvider();
}
@ -269,4 +291,78 @@ public void removeConferenceMembersSoundLevelListener(
{
}
////////////////////////////// OK CODE starts here ////////////////////////
/**
* Ends the call with for this <tt>CallPeer</tt>. Depending on the state
* of the peer the method would send a CANCEL, BYE, or BUSY_HERE message
* and set the new state to DISCONNECTED.
*
* @throws OperationFailedException if we fail to terminate the call.
*/
public void hangup()
throws OperationFailedException
{
// do nothing if the call is already ended
if (CallPeerState.DISCONNECTED.equals(getState())
|| CallPeerState.FAILED.equals(getState()))
{
if (logger.isDebugEnabled())
logger.debug("Ignoring a request to hangup a call peer "
+ "that is already DISCONNECTED");
return;
}
//get a reference to the provider before we change the state to
//DISCONNECTED because at that point we may lose our Call reference
ProtocolProviderServiceJabberImpl provider = getProtocolProvider();
CallPeerState prevPeerState = getState();
setState(CallPeerState.DISCONNECTED);
JingleIQ responseIQ = null;
if (prevPeerState.equals(CallPeerState.CONNECTED)
|| CallPeerState.isOnHold(prevPeerState))
{
responseIQ = JinglePacketFactory.createBye(
provider.getOurJID(), peerJID, jingleSID);
}
else if (CallPeerState.CONNECTING.equals(getState())
|| CallPeerState.CONNECTING_WITH_EARLY_MEDIA.equals(getState())
|| CallPeerState.ALERTING_REMOTE_SIDE.equals(getState()))
{
responseIQ = JinglePacketFactory.createCancel(
provider.getOurJID(), peerJID, jingleSID);
}
else if (prevPeerState.equals(CallPeerState.INCOMING_CALL))
{
responseIQ = JinglePacketFactory.createBusy(
provider.getOurJID(), peerJID, jingleSID);
}
else if (prevPeerState.equals(CallPeerState.BUSY)
|| prevPeerState.equals(CallPeerState.FAILED))
{
// For FAILED and BUSY we only need to update CALL_STATUS
// as everything else has been done already.
}
else
{
logger.info("Could not determine call peer state!");
}
if (responseIQ != null)
provider.getConnection().sendPacket(responseIQ);
}
/**
* Returns the session ID of the Jingle session associated with this call.
*
* @return the session ID of the Jingle session associated with this call.
*/
public String getJingleSID()
{
return jingleSID;
}
}

@ -8,20 +8,15 @@
import java.util.*;
import net.java.sip.communicator.impl.protocol.jabber.OperationSetBasicInstantMessagingJabberImpl.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.mailnotification.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.service.protocol.jabberconstants.*;
import net.java.sip.communicator.util.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.filter.*;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.provider.*;
import org.jivesoftware.smackx.*;
import org.jivesoftware.smackx.packet.*;
/**
@ -33,7 +28,9 @@
*/
public class OperationSetBasicTelephonyJabberImpl
extends AbstractOperationSetBasicTelephony
implements RegistrationStateChangeListener
implements RegistrationStateChangeListener,
PacketListener,
PacketFilter
{
/**
@ -51,8 +48,8 @@ public class OperationSetBasicTelephonyJabberImpl
/**
* Contains references for all currently active (non ended) calls.
*/
private ActiveCallsRepository activeCallsRepository
= new ActiveCallsRepository(this);
private ActiveCallsRepositoryJabberImpl activeCallsRepository
= new ActiveCallsRepositoryJabberImpl(this);
/**
* Creates a new instance.
@ -185,8 +182,7 @@ private CallJabberImpl createOutgoingCall(String calleeAddress)
try
{
// check if the remote client supports telephony.
DiscoverInfo di = ServiceDiscoveryManager
.getInstanceFor(protocolProvider.getConnection())
DiscoverInfo di = protocolProvider.getDiscoveryManager()
.discoverInfo(fullCalleeURI);
if (di.containsFeature(ProtocolProviderServiceJabberImpl
.URN_XMPP_JINGLE))
@ -228,43 +224,72 @@ public Iterator<CallJabberImpl> getActiveCalls()
* Resumes communication with a call peer previously put on hold.
*
* @param peer the call peer to put on hold.
*
* @throws OperationFailedException if we fail to send the "hold" message.
*/
public void putOffHold(CallPeer peer)
public synchronized void putOffHold(CallPeer peer)
throws OperationFailedException
{
/** @todo implement putOffHold() */
putOnHold(peer, false);
}
/**
* Puts the specified CallPeer "on hold".
*
* @param peer the peer that we'd like to put on hold.
*
* @throws OperationFailedException if we fail to send the "hold" message.
*/
public synchronized void putOnHold(CallPeer peer)
throws OperationFailedException
{
putOnHold(peer, true);
}
/**
* Puts the specified <tt>CallPeer</tt> on or off hold.
*
* @param peer the <tt>CallPeer</tt> to be put on or off hold
* @param on <tt>true</tt> to have the specified <tt>CallPeer</tt>
* put on hold; <tt>false</tt>, otherwise
*
* @throws OperationFailedException if we fail to send the "hold" message.
*/
public void putOnHold(CallPeer peer)
private void putOnHold(CallPeer peer, boolean on)
throws OperationFailedException
{
CallPeerJabberImpl jabberPeer = (CallPeerJabberImpl) peer;
//jabberPeer.putOnHold(on);
}
/**
* Sets the mute state of the <tt>CallJabberImpl</tt>.
*
* @param call the <tt>CallJabberImpl</tt> whose mute state is set
* @param mute <tt>true</tt> to mute the call streams being sent to
* <tt>peers</tt>; otherwise, <tt>false</tt>
*/
@Override
public void setMute(Call call, boolean mute)
{
/** @todo implement putOnHold() */
}
/**
* Implements method <tt>hangupCallPeer</tt>
* from <tt>OperationSetBasicTelephony</tt>.
* Ends the call with the specified <tt>peer</tt>.
*
* @param peer the peer that we'd like to hang up on.
* @throws ClassCastException if peer is not an instance of
* CallPeerJabberImpl.
*
* @throws ClassCastException if peer is not an instance of this
* CallPeerSipImpl.
* @throws OperationFailedException if we fail to terminate the call.
*
* // TODO: ask for suppression of OperationFailedException from the interface.
* // what happens if hangup fails ? are we forced to continue to talk ? :o)
*/
public void hangupCallPeer(CallPeer peer)
throws ClassCastException, OperationFailedException
public synchronized void hangupCallPeer(CallPeer peer)
throws ClassCastException,
OperationFailedException
{
CallPeerJabberImpl callPeer
= (CallPeerJabberImpl)peer;
/**
* @todo implement hangupCallPeer
*/
CallPeerJabberImpl peerJabberImpl = (CallPeerJabberImpl)peer;
peerJabberImpl.hangup();
}
@ -304,7 +329,7 @@ public void shutdown()
while(activeCalls.hasNext())
{
CallJabberImpl call = activeCalls.next();
Iterator<CallPeer> callPeers = call.getCallPeers();
Iterator<CallPeerJabberImpl> callPeers = call.getCallPeers();
//go through all call peers and say bye to every one.
while (callPeers.hasNext())
@ -329,25 +354,121 @@ public void shutdown()
*/
private void subscribeForJinglePackets()
{
protocolProvider.getConnection().addPacketListener(
new JingleListener(), new PacketTypeFilter( JingleIQ.class));
protocolProvider.getConnection().addPacketListener(this, this);
}
/**
* The listener that we use to retrieve inbound jingle related packets.
* Tests whether or not the specified packet should be handled by this
* operation set. This method is called by smack prior to packet delivery
* and it would only accept <tt>JingleIQ</tt>s that are either session
* initiations with RTP content or belong to sessions that are already
* handled by this operation set.
*
* @param packet the packet to test.
* @return true if and only if <tt>packet</tt> passes the filter.
*/
private class JingleListener implements PacketListener
public boolean accept(Packet packet)
{
/**
* Handles incoming jingle packets and passes them to the corresponding
* methods in this operation set.
*
* @param packet the packet to process.
*/
public void processPacket(Packet packet)
//we only handle JingleIQ-s
if( ! (packet instanceof JingleIQ) )
return false;
JingleIQ jingleIQ = (JingleIQ)packet;
if( jingleIQ.getAction() == JingleAction.SESSION_INITIATE)
{
System.out.println("here's the packet : " + packet);
//we only accept session-initiate-s dealing RTP
if( jingleIQ.containsContentChildOfType(
RtpDescriptionPacketExtension.class))
return true;
else
return false;
}
//if this is not a session-initiate we'll only take it if we've
//already seen its session ID.
if( activeCallsRepository.findJingleSID(jingleIQ.getSID()) != null )
return true;
else
return false;
}
}
/**
* Handles incoming jingle packets and passes them to the corresponding
* method based on their action.
*
* @param packet the packet to process.
*/
public void processPacket(Packet packet)
{
//this is not supposed to happen because of the filter ... but still
if (! (packet instanceof JingleIQ) )
return;
JingleIQ jingleIQ = (JingleIQ)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
//first ack all "set" requests.
if(jingleIQ.getType() == IQ.Type.SET)
{
IQ ack = IQ.createResultIQ(jingleIQ);
protocolProvider.getConnection().sendPacket(ack);
}
processJinglePacket(jingleIQ);
}
/**
* Analyzes the <tt>jingleIQ</tt>'s action and passes it to the
* corresponding handler.
*
* @param jingleIQ the {@link JingleIQ} packet we need to be analyzing.
*/
private void processJinglePacket(JingleIQ jingleIQ)
{
JingleAction action = jingleIQ.getAction();
if(action == JingleAction.SESSION_INITIATE)
{
CallJabberImpl call = new CallJabberImpl(this);
call.processSessionInitiate(jingleIQ);
}
else if(action == JingleAction.SESSION_TERMINATE)
{
}
else if(action == JingleAction.SESSION_ACCEPT)
{
}
}
/**
* Returns a reference to the {@link ActiveCallsRepositoryJabberImpl} that we are
* currently using.
*
* @return a reference to the {@link ActiveCallsRepositoryJabberImpl} that we are
* currently using.
*/
protected ActiveCallsRepositoryJabberImpl getActiveCallsRepository()
{
return activeCallsRepository;
}
/**
* Returns the protocol provider that this operation set belongs to.
*
* @return a reference to the <tt>ProtocolProviderService</tt> that created
* this operation set.
*/
public ProtocolProviderServiceJabberImpl getProtocolProvider()
{
return protocolProvider;
}
}

@ -1240,7 +1240,7 @@ public boolean isFeatureSupported(String jid, String feature)
* @param contact the contact, for which we're looking for a jid
* @return the jid of the specified contact;
*/
String getFullJid(Contact contact)
public String getFullJid(Contact contact)
{
Roster roster = getConnection().getRoster();
Presence presence = roster.getPresence(contact.getAddress());
@ -1345,4 +1345,41 @@ public void run()
}
}
}
/**
* Returns the currently valid {@link ScServiceDiscoveryManager}.
*
* @return the currently valid {@link ScServiceDiscoveryManager}.
*/
public ScServiceDiscoveryManager getDiscoveryManager()
{
return discoveryManager;
}
/**
* Returns our own Jabber ID.
*
* @return our own Jabber ID.
*/
public String getOurJID()
{
String jid = null;
if( connection != null )
connection.getUser();
if (jid == null)
{
//seems like the connection is not yet initialized so lets try
//to construct our jid ourselves.
String userID =
StringUtils.parseName(getAccountID().getUserID());
String serviceName =
StringUtils.parseServer(getAccountID().getUserID());
jid = userID + "@" + serviceName;
}
return jid;
}
}

@ -16,6 +16,7 @@
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smackx.*;
import org.jivesoftware.smackx.packet.*;
import net.java.sip.communicator.util.*;
/**
* An wrapper to smack's default {@link ServiceDiscoveryManager} that adds
@ -29,6 +30,13 @@ public class ScServiceDiscoveryManager
implements PacketInterceptor,
NodeInformationProvider
{
/**
* The <tt>Logger</tt> used by the <tt>ScServiceDiscoveryManager</tt>
* class and its instances for logging output.
*/
private static final Logger logger = Logger
.getLogger(ScServiceDiscoveryManager.class.getName());
/**
* A flag that indicates whether we are currently storing non-caps
*/
@ -344,4 +352,102 @@ private void initFeatures()
}
}
}
/**
* Returns the discovered information of a given XMPP entity addressed by
* its JID.
*
* @param entityID the address of the XMPP entity.
*
* @return the discovered information.
*
* @throws XMPPException if the operation failed for some reason.
*/
public DiscoverInfo discoverInfo(String entityID)
throws XMPPException
{
return discoveryManager.discoverInfo(entityID, entityID);
}
/**
* Returns the discovered information of a given XMPP entity addressed by
* its JID and note attribute. Use this message only when trying to query
* information which is not directly addressable.
*
* @param entityID the address of the XMPP entity.
* @param node the attribute that supplements the 'jid' attribute.
*
* @return the discovered information.
*
* @throws XMPPException if the operation failed for some reason.
*/
public DiscoverInfo discoverInfo(String entityID, String node)
throws XMPPException
{
return discoveryManager.discoverInfo(entityID, node);
}
/**
* Returns the discovered items of a given XMPP entity addressed by its JID.
*
* @param entityID the address of the XMPP entity.
*
* @return the discovered information.
*
* @throws XMPPException if the operation failed for some reason.
*/
public DiscoverItems discoverItems(String entityID) throws XMPPException
{
return discoveryManager.discoverItems(entityID);
}
/**
* Returns the discovered items of a given XMPP entity addressed by its JID
* and note attribute. Use this message only when trying to query
* information which is not directly addressable.
*
* @param entityID the address of the XMPP entity.
* @param node the attribute that supplements the 'jid' attribute.
*
* @return the discovered items.
*
* @throws XMPPException if the operation failed for some reason.
*/
public DiscoverItems discoverItems(String entityID, String node)
throws XMPPException
{
return discoveryManager.discoverItems(entityID, node);
}
/**
* Returns <tt>true</tt> if <tt>jid</tt> supports the specified
* <tt>feature</tt> and <tt>false</tt> otherwise. The method may check the
* information locally if we've already cached this <tt>jid</tt>'s disco
* info, or retrieve it from the network.
*
* @param jid the jabber ID we'd like to test for support
* @param feature the URN feature we are interested in
*
* @return true if <tt>jid</tt> is discovered to support <tt>feature</tt>
* and <tt>false</tt> otherwise.
*/
public boolean supportsFeature(String jid, String feature)
{
DiscoverInfo info = null;
try
{
info = this.discoverInfo(jid);
}
catch(XMPPException ex)
{
logger.info("failed to retrieve disco info for " + jid
+ " feature " + feature, ex);
return false;
}
if(info != null && info .containsFeature(feature))
return true;
else
return false;
}
}

@ -278,5 +278,30 @@ public String getText()
return textContent;
}
/**
* Returns this packet's first direct child extension that matches the
* specified of this packet that matches the specified <tt>type</tt>.
*
* @param type the <tt>Class</tt> of the extension we are looking for.
*
* @return this packet's first direct child extension that matches the
* specified of this packet that matches the specified <tt>type</tt> or
* <tt>null</tt> if no such child extension was found.
*/
public PacketExtension getFirstChildOfType(
Class<? extends PacketExtension> type)
{
List<? extends PacketExtension> childExtensions = getChildExtensions();
synchronized (childExtensions)
{
for(PacketExtension extension : childExtensions)
{
if(type.isAssignableFrom(extension.getClass()))
return extension;
}
}
return null;
}
}

@ -58,8 +58,7 @@ public static JingleIQ createRinging(JingleIQ sessionInitiate)
*/
public static JingleIQ createBusy(String from, String to, String sid)
{
return createSessionTerminate(from, to, sid,
Reason.BUSY, null);
return createSessionTerminate(from, to, sid, Reason.BUSY, null);
}
/**
@ -95,8 +94,7 @@ public static JingleIQ createBye(String from, String to, String sid)
*/
public static JingleIQ createCancel(String from, String to, String sid)
{
return createSessionTerminate(from, to, sid, Reason.CANCEL,
"Oops!");
return createSessionTerminate(from, to, sid, Reason.CANCEL, "Oops!");
}
/**

@ -1,329 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.sip;
import java.util.*;
import javax.sip.*;
import javax.sip.header.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* Keeps a list of all calls currently active and maintained by this protocol
* povider. Offers methods for finding a call by its ID, peer dialog
* and others.
*
* @author Emil Ivov
*/
public class ActiveCallsRepository
extends CallChangeAdapter
{
/**
* Our class logger.
*/
private static final Logger logger
= Logger.getLogger(ActiveCallsRepository.class);
/**
* The operation set that created us. Instance is mainly used for firing
* events when necessary.
*/
private final OperationSetBasicTelephonySipImpl parentOperationSet;
/**
* A table mapping call ids against call instances.
*/
private Hashtable<String, CallSipImpl> activeCalls
= new Hashtable<String, CallSipImpl>();
/**
* Creates a new instance of this repository.
*
* @param opSet a reference to the
* <tt>OperationSetBasicTelephonySipImpl</tt> that craeted us.
*/
public ActiveCallsRepository(OperationSetBasicTelephonySipImpl opSet)
{
this.parentOperationSet = opSet;
}
/**
* Adds the specified call to the list of calls tracked by this repository.
* @param call CallSipImpl
*/
public void addCall(CallSipImpl call)
{
activeCalls.put(call.getCallID(), call);
call.addCallChangeListener(this);
}
/**
* If <tt>evt</tt> indicates that the call has been ended we remove it from
* the repository.
* @param evt the <tt>CallChangeEvent</tt> instance containing the source
* calls and its old and new state.
*/
public void callStateChanged(CallChangeEvent evt)
{
if(evt.getEventType().equals(CallChangeEvent.CALL_STATE_CHANGE)
&& evt.getNewValue().equals(CallState.CALL_ENDED))
{
CallSipImpl sourceCall =
this.activeCalls.remove(evt.getSourceCall().getCallID());
if (logger.isTraceEnabled())
logger.trace("Removing call " + sourceCall + " from the list of "
+ "active calls because it entered an ENDED state");
this.parentOperationSet.fireCallEvent(
CallEvent.CALL_ENDED, sourceCall);
}
}
/**
* Returns an iterator over all currently active (non-ended) calls.
*
* @return an iterator over all currently active (non-ended) calls.
*/
public Iterator<CallSipImpl> getActiveCalls()
{
return new LinkedList<CallSipImpl>(activeCalls.values()).iterator();
}
/**
* Returns the call that contains the specified dialog (i.e. it is
* established between us and one of the other call peers).
* <p>
* @param dialog the jain sip <tt>Dialog</tt> whose containing call we're
* looking for.
* @return the <tt>CallSipImpl</tt> containing <tt>dialog</tt> or null
* if no call contains the specified dialog.
*/
public CallSipImpl findCall(Dialog dialog)
{
Iterator<CallSipImpl> activeCalls = getActiveCalls();
if(dialog == null)
{
if (logger.isDebugEnabled())
logger.debug("Cannot find a peer with a null dialog. "
+ "Returning null");
return null;
}
if(logger.isTraceEnabled())
{
logger.trace("Looking for peer with dialog: " + dialog
+ " among " + this.activeCalls.size() + " calls");
}
while(activeCalls.hasNext())
{
CallSipImpl call = activeCalls.next();
if(call.contains(dialog))
return call;
}
return null;
}
/**
* Returns the call peer whose associated jain sip dialog matches
* <tt>dialog</tt>.
*
* @param dialog the jain sip dialog whose corresponding peer we're
* looking for.
* @return the call peer whose jain sip dialog is the same as the
* specified or null if no such call peer was found.
*/
public CallPeerSipImpl findCallPeer(Dialog dialog)
{
if(dialog == null)
{
if (logger.isDebugEnabled())
logger.debug("Cannot find a peer with a null dialog. "
+ "Returning null");
return null;
}
if(logger.isTraceEnabled())
{
logger.trace("Looking for peer with dialog: " + dialog
+ " among " + this.activeCalls.size() + " calls");
}
for (Iterator<CallSipImpl> activeCalls = getActiveCalls();
activeCalls.hasNext();)
{
CallSipImpl call = activeCalls.next();
CallPeerSipImpl callPeer
= call.findCallPeer(dialog);
if(callPeer != null)
{
if (logger.isTraceEnabled())
logger.trace("Returning peer " + callPeer);
return callPeer;
}
}
return null;
}
/**
* Returns the <tt>CallPeerSipImpl</tt> instance with a <tt>Dialog</tt>
* matching CallID, local and remote tags.
*
* @param callID the <tt>Call-ID</tt> of the dialog we are looking for.
* @param localTag the local tag of the dialog we are looking for.
* @param remoteTag the remote tag of the dialog we are looking for.
*
* @return the <tt>CallPeerSipImpl</tt> matching specified dialog ID or
* <tt>null</tt> if no such peer is known to this repository.
*/
public CallPeerSipImpl findCallPeer(String callID,
String localTag, String remoteTag)
{
if (logger.isTraceEnabled())
{
logger.trace("Looking for call peer with callID " + callID
+ ", localTag " + localTag + ", and remoteTag " + remoteTag
+ " among " + this.activeCalls.size() + " calls.");
}
for (Iterator<CallSipImpl> activeCalls = getActiveCalls();
activeCalls.hasNext();)
{
CallSipImpl call = activeCalls.next();
if (!callID.equals(call.getCallID()))
continue;
for (Iterator<? extends CallPeer> callPeerIter
= call.getCallPeers();
callPeerIter.hasNext();)
{
CallPeerSipImpl callPeer =
(CallPeerSipImpl) callPeerIter.next();
Dialog dialog = callPeer.getDialog();
if (dialog != null)
{
String dialogLocalTag = dialog.getLocalTag();
if (((localTag == null) || "0".equals(localTag)) ?
((dialogLocalTag == null) || "0".equals(dialogLocalTag)) :
localTag.equals(dialogLocalTag))
{
String dialogRemoteTag = dialog.getRemoteTag();
if (((remoteTag == null) || "0".equals(remoteTag))
? ((dialogRemoteTag == null)
|| "0".equals(dialogRemoteTag))
: remoteTag.equals(dialogRemoteTag))
{
return callPeer;
}
}
}
}
}
return null;
}
/**
* Returns the <tt>CallPeerSipImpl</tt> whose INVITE transaction has the
* specified <tt>branchID</tt> and whose corresponding INVITE request
* contains the specified <tt>callID</tt>.
*
* @param callID the <tt>Call-ID</tt> of the dialog we are looking for.
* @param branchID a <tt>String</tt> corresponding to the branch id of the
* latest INVITE transaction that was associated with the peer we are
* looking for.
*
* @return the <tt>CallPeerSipImpl</tt> matching specified call and branch
* id-s or <tt>null</tt> if no such peer is known to this repository.
*/
public CallPeerSipImpl findCallPeer(String branchID, String callID)
{
Iterator<CallSipImpl> activeCallsIter = getActiveCalls();
while (activeCallsIter.hasNext())
{
CallSipImpl activeCall = activeCallsIter.next();
Iterator<CallPeerSipImpl> callPeersIter = activeCall.getCallPeers();
while (callPeersIter.hasNext())
{
CallPeerSipImpl cp = callPeersIter.next();
Dialog cpDialog = cp.getDialog();
Transaction cpTran = cp.getLatestInviteTransaction();
if( cpDialog == null
|| cpDialog.getCallId() == null
|| cpTran == null)
continue;
if ( cp.getLatestInviteTransaction() != null
&& cpDialog.getCallId().getCallId().equals(callID)
&& branchID.equals(cpTran.getBranchId()))
{
return cp;
}
}
}
return null;
}
/**
* Returns the <tt>CallPeerSipImpl</tt> whose INVITE transaction has the
* specified <tt>branchID</tt> and whose corresponding INVITE request
* contains the specified <tt>callID</tt>.
*
* @param cidHeader the <tt>Call-ID</tt> of the dialog we are looking for.
* @param branchID a <tt>String</tt> corresponding to the branch id of the
* latest INVITE transaction that was associated with the peer we are
* looking for.
*
* @return the <tt>CallPeerSipImpl</tt> matching specified call and branch
* id-s or <tt>null</tt> if no such peer is known to this repository.
*/
public CallPeerSipImpl findCallPeer(String branchID, Header cidHeader)
{
if(cidHeader == null || ! (cidHeader instanceof CallIdHeader))
return null;
return findCallPeer(branchID, (((CallIdHeader)cidHeader).getCallId()));
}
/**
* Returns the <tt>CallSipImpl</tt> instance with a <tt>Dialog</tt>
* matching the specified <tt>Call-ID</tt>, local and remote tags.
*
* @param callID the <tt>Call-ID</tt> of the dialog we are looking for.
* @param localTag the local tag of the dialog we are looking for.
* @param remoteTag the remote tag of the dialog we are looking for.
*
* @return the <tt>CallSipImpl</tt> responsible for handling the
* <tt>Dialog</tt> with the matching ID or <tt>null</tt> if no such call was
* found.
*/
public CallSipImpl findCall(String callID,
String localTag,
String remoteTag)
{
CallPeerSipImpl peer = findCallPeer(callID, localTag, remoteTag);
return (peer == null)? null : peer.getCall();
}
}

@ -20,6 +20,7 @@
import net.java.sip.communicator.service.neomedia.event.*;
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.*;
/**
@ -29,7 +30,7 @@
* @author Lubomir Marinov
*/
public class CallPeerSipImpl
extends AbstractCallPeer
extends AbstractCallPeer<CallSipImpl, ProtocolProviderServiceSipImpl>
implements SimpleAudioLevelListener,
CallPeerConferenceListener,
CsrcAudioLevelListener,
@ -94,7 +95,7 @@ public class CallPeerSipImpl
* corresponds to exactly one instance of <tt>CallPeerMediaHandler</tt> and
* both classes are only separated for reasons of readability.
*/
private final CallPeerMediaHandler mediaHandler;
private final CallPeerMediaHandlerSipImpl mediaHandler;
/**
* The <tt>PropertyChangeListener</tt> which listens to
@ -157,7 +158,7 @@ public CallPeerSipImpl(Address peerAddress,
this.call = owningCall;
this.messageFactory = getProtocolProvider().getMessageFactory();
this.mediaHandler = new CallPeerMediaHandler(this);
this.mediaHandler = new CallPeerMediaHandlerSipImpl(this);
setDialog(containingTransaction.getDialog());
setLatestInviteTransaction(containingTransaction);
@ -1289,7 +1290,7 @@ public synchronized void answer()
public void putOnHold(boolean onHold)
throws OperationFailedException
{
CallPeerMediaHandler mediaHandler = getMediaHandler();
CallPeerMediaHandlerSipImpl mediaHandler = getMediaHandler();
mediaHandler.setLocallyOnHold(onHold);
@ -1450,7 +1451,7 @@ private void reflectConferenceFocus(javax.sip.message.Message message)
public void setLocalVideoAllowed(boolean allowed)
throws OperationFailedException
{
CallPeerMediaHandler mediaHandler = getMediaHandler();
CallPeerMediaHandlerSipImpl mediaHandler = getMediaHandler();
if(mediaHandler.isLocalVideoTransmissionEnabled() == allowed)
return;
@ -1689,7 +1690,7 @@ public void handleAuthenticationChallenge(ClientTransaction retryTran)
* @return a reference to the <tt>CallPeerMediaHandler</tt> instance that
* this peer uses for media related tips and tricks.
*/
public CallPeerMediaHandler getMediaHandler()
public CallPeerMediaHandlerSipImpl getMediaHandler()
{
return mediaHandler;
}
@ -1955,7 +1956,7 @@ public void conferenceMemberAdded(CallPeerConferenceEvent conferenceEvent)
// 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();
CallPeerMediaHandlerSipImpl mediaHandler = getMediaHandler();
mediaHandler.setStreamAudioLevelListener(null);
mediaHandler.setCsrcAudioLevelListener(this);
@ -1980,7 +1981,7 @@ public void conferenceMemberRemoved(CallPeerConferenceEvent conferenceEvent)
// since there's only us and her in the call. Lets stop being a CSRC
// listener and move back to listening the audio level of the
// stream itself.
CallPeerMediaHandler mediaHandler = getMediaHandler();
CallPeerMediaHandlerSipImpl mediaHandler = getMediaHandler();
mediaHandler.setStreamAudioLevelListener(this);
mediaHandler.setCsrcAudioLevelListener(null);

@ -26,7 +26,7 @@
* @author Emil Ivov
*/
public class CallSipImpl
extends Call
extends AbstractCall<CallPeerSipImpl, ProtocolProviderServiceSipImpl>
implements CallPeerListener
{
/**
@ -34,12 +34,6 @@ public class CallSipImpl
*/
private static final Logger logger = Logger.getLogger(CallSipImpl.class);
/**
* A list containing all <tt>CallPeer</tt>s of this call.
*/
private final List<CallPeerSipImpl> callPeers =
new Vector<CallPeerSipImpl>();
/**
* The <tt>MediaDevice</tt> which performs audio mixing for this
* <tt>Call</tt> and its <tt>CallPeer</tt>s when the local peer represented
@ -132,7 +126,7 @@ protected CallSipImpl(OperationSetBasicTelephonySipImpl parentOpSet)
*/
private void addCallPeer(CallPeerSipImpl callPeer)
{
if (callPeers.contains(callPeer))
if (getCallPeersVector().contains(callPeer))
return;
callPeer.addCallPeerListener(this);
@ -141,14 +135,14 @@ private void addCallPeer(CallPeerSipImpl callPeer)
{
// if there's someone listening for audio level events then they'd
// also like to know about the new peer.
if(callPeers.size() == 0)
if(getCallPeersVector().size() == 0)
{
callPeer.getMediaHandler().setLocalUserAudioLevelListener(
localAudioLevelDelegator);
}
}
this.callPeers.add(callPeer);
getCallPeersVector().add(callPeer);
fireCallPeerEvent(callPeer, CallPeerEvent.CALL_PEER_ADDED);
}
@ -161,15 +155,15 @@ private void addCallPeer(CallPeerSipImpl callPeer)
*/
private void removeCallPeer(CallPeerSipImpl callPeer)
{
if (!callPeers.contains(callPeer))
if (!getCallPeersVector().contains(callPeer))
return;
this.callPeers.remove(callPeer);
getCallPeersVector().remove(callPeer);
callPeer.removeCallPeerListener(this);
synchronized(localUserAudioLevelListeners)
{
// remove sound levevel listeners from the peer
// remove sound level listeners from the peer
callPeer.getMediaHandler().setLocalUserAudioLevelListener(null);
}
@ -188,31 +182,10 @@ private void removeCallPeer(CallPeerSipImpl callPeer)
callPeer.setCall(null);
}
if (callPeers.size() == 0)
if (getCallPeersVector().size() == 0)
setCallState(CallState.CALL_ENDED);
}
/**
* Returns an iterator over all call peers.
*
* @return an Iterator over all peers currently involved in the call.
*/
public Iterator<CallPeerSipImpl> getCallPeers()
{
return new LinkedList<CallPeerSipImpl>(callPeers).iterator();
}
/**
* Returns the number of peers currently associated with this call.
*
* @return an <tt>int</tt> indicating the number of peers currently
* associated with this call.
*/
public int getCallPeerCount()
{
return callPeers.size();
}
/**
* Dummy implementation of a method (inherited from CallPeerListener)
* that we don't need.
@ -314,7 +287,7 @@ public CallPeerSipImpl findCallPeer(Dialog dialog)
if (logger.isTraceEnabled())
{
logger.trace("Looking for peer with dialog: " + dialog
+ "among " + this.callPeers.size() + " calls");
+ "among " + getCallPeerCount() + " calls");
}
while (callPeers.hasNext())

@ -58,8 +58,8 @@ public class OperationSetBasicTelephonySipImpl
/**
* Contains references for all currently active (non ended) calls.
*/
private final ActiveCallsRepository activeCallsRepository =
new ActiveCallsRepository(this);
private final ActiveCallsRepositorySipImpl activeCallsRepository =
new ActiveCallsRepositorySipImpl(this);
/**
* Creates a new instance and adds itself as an <tt>INVITE</tt> method
@ -201,13 +201,13 @@ public Iterator<CallSipImpl> getActiveCalls()
}
/**
* Returns a reference to the {@link ActiveCallsRepository} that we are
* Returns a reference to the {@link ActiveCallsRepositorySipImpl} that we are
* currently using.
*
* @return a reference to the {@link ActiveCallsRepository} that we are
* @return a reference to the {@link ActiveCallsRepositorySipImpl} that we are
* currently using.
*/
protected ActiveCallsRepository getActiveCallsRepository()
protected ActiveCallsRepositorySipImpl getActiveCallsRepository()
{
return activeCallsRepository;
}
@ -1100,7 +1100,7 @@ private void processRefer(ServerTransaction serverTransaction,
* Regardless of whether the Accepted, NOTIFY, etc. succeeded, try to
* transfer the call because it's the most important goal.
*/
Call referToCall;
CallSipImpl referToCall;
try
{
referToCall = createOutgoingCall(referToAddress, referRequest);
@ -1118,7 +1118,7 @@ private void processRefer(ServerTransaction serverTransaction,
* subscription-terminating NOTIFY with the final result of the REFER is
* to be sent.
*/
final Call referToCallListenerSource = referToCall;
final CallSipImpl referToCallListenerSource = referToCall;
final boolean sendNotifyRequest = (accepted != null);
final Object subscription = (removeSubscription ? referRequest : null);
CallChangeListener referToCallListener = new CallChangeAdapter()
@ -1288,7 +1288,7 @@ private boolean processNotify(ServerTransaction serverTransaction,
* request and the tracking of the state of <tt>referToCall</tt> should
* continue
*/
private boolean referToCallStateChanged(Call referToCall,
private boolean referToCallStateChanged(CallSipImpl referToCall,
boolean sendNotifyRequest, Dialog dialog, SipProvider sipProvider,
Object subscription)
{

@ -14,7 +14,6 @@
import net.java.sip.communicator.service.neomedia.format.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.DTMFTone;
import net.java.sip.communicator.util.*;
/**
* Class responsible for sending a DTMF Tone using SIP INFO or using rfc4733.
@ -88,7 +87,8 @@ public synchronized void startSendingDTMF(CallPeer callPeer, DTMFTone tone)
/**
* Stops sending DTMF.
* @param callPeer
*
* @param callPeer the call peer that we'd like to stop sending DTMF to.
*/
public synchronized void stopSendingDTMF(CallPeer callPeer)
{

@ -660,7 +660,7 @@ private void getMediaXML(
boolean remote,
StringBuffer xml)
{
CallPeerMediaHandler mediaHandler = callPeer.getMediaHandler();
CallPeerMediaHandlerSipImpl mediaHandler = callPeer.getMediaHandler();
for (MediaType mediaType : MediaType.values())
{
@ -1004,12 +1004,12 @@ public void propertyChange(PropertyChangeEvent event)
{
String propertyName = event.getPropertyName();
if (CallPeerMediaHandler.AUDIO_LOCAL_SSRC.equals(propertyName)
|| CallPeerMediaHandler.AUDIO_REMOTE_SSRC.equals(propertyName)
|| CallPeerMediaHandler.VIDEO_LOCAL_SSRC.equals(propertyName)
|| CallPeerMediaHandler.VIDEO_REMOTE_SSRC.equals(propertyName))
if (CallPeerMediaHandlerSipImpl.AUDIO_LOCAL_SSRC.equals(propertyName)
|| CallPeerMediaHandlerSipImpl.AUDIO_REMOTE_SSRC.equals(propertyName)
|| CallPeerMediaHandlerSipImpl.VIDEO_LOCAL_SSRC.equals(propertyName)
|| CallPeerMediaHandlerSipImpl.VIDEO_REMOTE_SSRC.equals(propertyName))
{
Call call = ((CallPeerMediaHandler) event.getSource()).peer.getCall();
Call call = ((CallPeerMediaHandlerSipImpl) event.getSource()).peer.getCall();
if (call != null)
notifyAll(call);

@ -113,7 +113,7 @@ public Component createLocalVisualComponent(
VideoListener listener)
throws OperationFailedException
{
CallPeerMediaHandler mediaHandler = ((CallPeerSipImpl) peer).getMediaHandler();
CallPeerMediaHandlerSipImpl mediaHandler = ((CallPeerSipImpl) peer).getMediaHandler();
return mediaHandler.createLocalVisualComponent();
}
@ -128,7 +128,7 @@ public Component createLocalVisualComponent(
*/
public void disposeLocalVisualComponent(CallPeer peer, Component component)
{
CallPeerMediaHandler mediaHandler = ((CallPeerSipImpl) peer).getMediaHandler();
CallPeerMediaHandlerSipImpl mediaHandler = ((CallPeerSipImpl) peer).getMediaHandler();
mediaHandler.disposeLocalVisualComponent();
}

@ -32,6 +32,7 @@
* <tt>Message</tt>-s will be easy to route or dispatch.
*
* @author Sebastien Mazy
* @author Emil Ivov
*/
public class SipMessageFactory
implements MessageFactory

@ -1,197 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.sip.sdp;
import java.util.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.neomedia.format.*;
/**
* The RTP Audio/Video Profile [RFC 3551] specifies a number of static payload
* types for use with RTP and reserves the 96-127 field for use with dynamic
* payload types.
* <p>
* Mappings of dynamic payload types are handled with SDP. They are created for
* a particular session and remain the same for its entire lifetime. They may
* however change in following sessions.
* </p>
* <p>
* We use this class as a utility for easily creating and tracking dynamic
* payload mappings for the lifetime of a particular session. One instance of
* this registry is supposed to be mapped to one media session. They should
* have pretty much the same life cycle.
* </p>
* @author Emil Ivov
*/
public class DynamicPayloadTypeRegistry
{
/**
* A field that we use to track dynamic payload numbers that we allocate.
*/
private byte nextDynamicPayloadType = MediaFormat.MIN_DYNAMIC_PAYLOAD_TYPE;
/**
* A table mapping <tt>MediaFormat</tt> instances to the dynamic payload
* type number they have obtained for the lifetime of this registry.
*/
private Map<MediaFormat, Byte> payloadTypeMappings
= new Hashtable<MediaFormat, Byte>();
/**
* Returns the dynamic payload type that has been allocated for
* <tt>format</tt>. A mapping for the specified <tt>format</tt> would be
* created even if it did not previously exist. The method is meant for use
* primarily during generation of SDP descriptions.
*
* @param format the <tt>MediaFormat</tt> instance that we'd like to obtain
* a payload type number for..
*
* @return the (possibly newly allocated) payload type number corresponding
* to the specified <tt>format</tt> instance for the lifetime of the media
* session.
*
* @throws IllegalStateException if we have already registered more dynamic
* formats than allowed for by RTP.
*/
public byte obtainPayloadTypeNumber(MediaFormat format)
throws IllegalStateException
{
MediaType mediaType = format.getMediaType();
String encoding = format.getEncoding();
double clockRate = format.getClockRate();
int channels
= MediaType.AUDIO.equals(mediaType)
? ((AudioMediaFormat) format).getChannels()
: MediaFormatFactory.CHANNELS_NOT_SPECIFIED;
Byte payloadType = null;
for (Map.Entry<MediaFormat, Byte> payloadTypeMapping
: payloadTypeMappings.entrySet())
{
if (AbstractMediaStream.matches(
payloadTypeMapping.getKey(),
mediaType, encoding, clockRate, channels))
{
payloadType = payloadTypeMapping.getValue();
break;
}
}
//hey, we already had this one, let's return it ;)
if (payloadType == null)
{
payloadType = nextPayloadTypeNumber();
payloadTypeMappings.put(format, payloadType);
}
return payloadType;
}
/**
* Adds the specified <tt>format</tt> to <tt>payloadType</tt> mapping to
* the list of mappings known to this registry. The method is meant for
* use primarily when handling incoming media descriptions, methods
* generating local SDP should use the <tt>obtainPayloadTypeNumber</tt>
* instead.
*
* @param payloadType the payload type number that we'd like to allocated
* to <tt>format</tt>.
* @param format the <tt>MediaFormat</tt> that we'd like to create a
* dynamic mapping for.
*
* @throws IllegalArgumentException in case <tt>payloadType</tt> has
* already been assigned to another format.
*/
public void addMapping(MediaFormat format, byte payloadType)
throws IllegalArgumentException
{
MediaFormat alreadyMappedFmt = findFormat(payloadType);
if(alreadyMappedFmt != null)
{
throw new IllegalArgumentException(payloadType
+ " has already been allocated to " + alreadyMappedFmt);
}
if( payloadType < MediaFormat.MIN_DYNAMIC_PAYLOAD_TYPE)
{
throw new IllegalArgumentException(payloadType
+ " is not a valid dynamic payload type number."
+ " (must be between " + MediaFormat.MIN_DYNAMIC_PAYLOAD_TYPE
+ " and " + MediaFormat.MAX_DYNAMIC_PAYLOAD_TYPE);
}
payloadTypeMappings.put(format, Byte.valueOf(payloadType));
}
/**
* Returns a reference to the <tt>MediaFormat</tt> with the specified
* mapping or <tt>null</tt> if the number specified by <tt>payloadType</tt>
* has not been allocated yet.
*
* @param payloadType the number of the payload type that we are trying to
* get a format for.
*
* @return the <tt>MediaFormat</tt> that has been mapped to
* <tt>payloadType</tt> in this registry or <tt>null</tt> if it hasn't been
* allocated yet.
*/
public MediaFormat findFormat(byte payloadType)
{
for (Map.Entry<MediaFormat, Byte> entry
: payloadTypeMappings.entrySet())
{
byte fmtPayloadType = entry.getValue();
if(fmtPayloadType == payloadType)
return entry.getKey();
}
return null;
}
/**
* Returns the first non-allocated dynamic payload type number.
*
* @return the first non-allocated dynamic payload type number.
*
* @throws IllegalStateException if we have already registered more dynamic
* formats than allowed for by RTP.
*/
private byte nextPayloadTypeNumber()
throws IllegalStateException
{
while (true)
{
if (nextDynamicPayloadType < 0)
{
throw new IllegalStateException(
"Impossible to allocate more than the already 32 mapped "
+"dynamic payload type numbers");
}
byte payloadType = nextDynamicPayloadType++;
if(findFormat(payloadType) == null)
return payloadType;
//if we get here then that means that the number we obtained by
//incrementing our PT counter was already occupied (probably by an
//incoming SDP). continue bravely and get the next free one.
}
}
/**
* Returns a copy of all mappings currently registered in this registry.
*
* @return a copy of all mappings currently registered in this registry.
*/
public Map<MediaFormat, Byte> getMappings()
{
return new Hashtable<MediaFormat, Byte>(payloadTypeMappings);
}
}

@ -1,218 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.sip.sdp;
import java.util.*;
import net.java.sip.communicator.service.neomedia.*;
/**
* RFC [RFC 5285] defines a mechanism for attaching multiple extensions to
* RTP packets. Part of this mechanism consists in negotiating their
* identifiers using <tt>extmap</tt> attributes pretty much the same way one
* would negotiate payload types with <tt>rtpmap</tt> attributes.
* <p>
* Mappings of extension IDs are handled with SDP. They are created for
* a particular session and remain the same for its entire lifetime. They may
* however change in following sessions.
* </p>
* <p>
* We use this class as a utility for easily creating and tracking extension
* mappings for the lifetime of a particular session. One instance of this
* registry is supposed to be mapped to one media session and they should
* have the same life cycle.
* </p>
* @author Emil Ivov
*/
public class DynamicRTPExtensionsRegistry
{
/**
* The minimum integer that is allowed for use when mapping extensions using
* the one-byte header.
*/
public static final int MIN_HEADER_ID = 1;
/**
* The maximum integer that is allowed for use when mapping extensions using
* the one-byte header. Note that 15 is reserved for future use by 5285
*/
public static final int MAX_ONE_BYTE_HEADER_ID = 14;
/**
* The maximum integer that is allowed for use when mapping extensions using
* the two-byte header.
*/
public static final int MAX_TWO_BYTE_HEADER_ID = 255;
/**
* A field that we use to track mapping IDs.
*/
private byte nextExtensionMapping = MIN_HEADER_ID;
/**
* A table mapping <tt>RTPExtension</tt> instances to the dynamically
* allocated ID they have obtained for the lifetime of this registry.
*/
private Map<RTPExtension, Byte> extMap
= new Hashtable<RTPExtension, Byte>();
/**
* Returns the ID that has been allocated for <tt>extension</tt>. A mapping
* for the specified <tt>extension</tt> would be created even if it did not
* previously exist. The method is meant for use primarily during generation
* of SDP descriptions.
*
* @param extension the <tt>RTPExtension</tt> instance that we'd like to
* obtain a dynamic ID for.
*
* @return the (possibly newly allocated) ID corresponding to the specified
* <tt>extension</tt> and valid for the lifetime of the media session.
*
* @throws IllegalStateException if we have already registered more RTP
* extensions than allowed for by RTP.
*/
public byte obtainExtensionMapping(RTPExtension extension)
throws IllegalStateException
{
Byte extID = extMap.get(extension);
//hey, we already had this one, let's return it ;)
if( extID == null)
{
extID = nextExtensionID();
extMap.put(extension, extID);
}
return extID;
}
/**
* Returns the ID that has been allocated for <tt>extension</tt> or
* <tt>-1</tt> if no extension exists.
*
* @param extension the <tt>RTPExtension</tt> instance whose ID we'd like to
* find.
*
* @return the ID corresponding to the specified <tt>extension</tt> or
* <tt>-1</tt> if <tt>extension</tt> is not registered with this registry.
*/
public byte getExtensionMapping(RTPExtension extension)
{
Byte extID = extMap.get(extension);
//hey, we already had this one, let's return it ;)
if( extID == null)
{
return -1;
}
return extID;
}
/**
* Adds the specified <tt>extension</tt> to <tt>extID</tt> mapping to
* the list of mappings known to this registry. The method is meant for
* use primarily when handling incoming media descriptions, methods
* generating local SDP should use the <tt>obtainExtensionMapping</tt>
* instead.
*
* @param extID the extension ID that we'd like to allocated to
* <tt>extension</tt>.
* @param extension the <tt>RTPExtension</tt> that we'd like to create a
* dynamic mapping for.
*
* @throws IllegalArgumentException in case <tt>extID</tt> has already been
* assigned to another <tt>RTPExtension</tt>.
*/
public void addMapping(RTPExtension extension, byte extID)
throws IllegalArgumentException
{
RTPExtension alreadyMappedExt = findExtension(extID);
if(alreadyMappedExt != null)
{
throw new IllegalArgumentException(extID
+ " has already been allocated to " + alreadyMappedExt);
}
if( extID < MIN_HEADER_ID)
{
throw new IllegalArgumentException(extID
+ " is not a valid RTP extensino header ID."
+ " (must be between " + MIN_HEADER_ID
+ " and " + MAX_TWO_BYTE_HEADER_ID);
}
extMap.put(extension, Byte.valueOf(extID));
}
/**
* Returns a reference to the <tt>RTPExtension</tt> with the specified
* mapping or <tt>null</tt> if the number specified by <tt>extID</tt>
* has not been allocated yet.
*
* @param extID the ID whose <tt>RTPExtension</tt> we are trying to
* discover.
*
* @return the <tt>RTPExtension</tt> that has been mapped to
* <tt>extID</tt> in this registry or <tt>null</tt> if it hasn't been
* allocated yet.
*/
public RTPExtension findExtension(byte extID)
{
for (Map.Entry<RTPExtension, Byte> entry
: extMap.entrySet())
{
byte currentExtensionID = entry.getValue();
if(currentExtensionID == extID)
return entry.getKey();
}
return null;
}
/**
* Returns the first non-allocated dynamic extension ID number.
*
* @return the first non-allocated dynamic extension ID number..
*
* @throws IllegalStateException if we have already registered more RTP
* extension headers than allowed for by RTP.
*/
private byte nextExtensionID()
throws IllegalStateException
{
while (true)
{
if (nextExtensionMapping < 0)
{
throw new IllegalStateException(
"Impossible to map more than the 255 already mapped "
+" RTP extensions");
}
byte extID = nextExtensionMapping++;
if(findExtension(extID) == null)
return extID;
//if we get here then that means that the number we obtained by
//incrementing our ID counter was already occupied (probably by an
//incoming SDP). continue bravely and get the next free one.
}
}
/**
* Returns a copy of all mappings currently registered in this registry.
*
* @return a copy of all mappings currently registered in this registry.
*/
public Map<RTPExtension, Byte> getMappings()
{
return new Hashtable<RTPExtension, Byte>(extMap);
}
}

@ -18,6 +18,7 @@
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.neomedia.format.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.media.*;
import net.java.sip.communicator.util.*;
/**

@ -19,6 +19,7 @@ Import-Package: org.apache.log4j,
net.java.sip.communicator.service.netaddr,
net.java.sip.communicator.service.protocol,
net.java.sip.communicator.service.protocol.event,
net.java.sip.communicator.service.protocol.media,
net.java.sip.communicator.service.resources,
net.java.sip.communicator.service.version,
net.java.sip.communicator.util,

Loading…
Cancel
Save