mirror of https://github.com/sipwise/jitsi.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
453 lines
16 KiB
453 lines
16 KiB
/*
|
|
* 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.service.protocol;
|
|
|
|
import java.net.*;
|
|
import java.util.*;
|
|
|
|
import net.java.sip.communicator.service.protocol.event.*;
|
|
import net.java.sip.communicator.util.*;
|
|
|
|
/**
|
|
* Provides a default implementation for most of the
|
|
* <code>CallParticipant</code> methods with the purpose of only leaving custom
|
|
* protocol development to clients using the PhoneUI service.
|
|
*
|
|
* @author Emil Ivov
|
|
*/
|
|
public abstract class AbstractCallParticipant
|
|
implements CallParticipant
|
|
{
|
|
private static final Logger logger
|
|
= Logger.getLogger(AbstractCallParticipant.class);
|
|
|
|
/**
|
|
* All the CallParticipant listeners registered with this CallParticipant.
|
|
*/
|
|
protected final List<CallParticipantListener> callParticipantListeners
|
|
= new ArrayList<CallParticipantListener>();
|
|
|
|
/**
|
|
* All the CallParticipantSecurityListener-s registered with this
|
|
* CallParticipant.
|
|
*/
|
|
protected final List<CallParticipantSecurityListener>
|
|
callParticipantSecurityListeners
|
|
= new ArrayList<CallParticipantSecurityListener>();
|
|
|
|
/**
|
|
* The state of the call participant.
|
|
*/
|
|
private CallParticipantState state = CallParticipantState.UNKNOWN;
|
|
|
|
private long callDurationStartTime = CALL_DURATION_START_TIME_UNKNOWN;
|
|
|
|
/**
|
|
* Registers the <tt>listener</tt> to the list of listeners that would be
|
|
* receiving CallParticipantEvents
|
|
* @param listener a listener instance to register with this participant.
|
|
*/
|
|
public void addCallParticipantListener(CallParticipantListener listener)
|
|
{
|
|
synchronized(callParticipantListeners)
|
|
{
|
|
if (!callParticipantListeners.contains(listener))
|
|
callParticipantListeners.add(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unregisters the specified listener.
|
|
* @param listener the listener to unregister.
|
|
*/
|
|
public void removeCallParticipantListener(CallParticipantListener listener)
|
|
{
|
|
if (listener == null)
|
|
return;
|
|
synchronized(callParticipantListeners)
|
|
{
|
|
callParticipantListeners.remove(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Registers the <tt>listener</tt> to the list of listeners that would be
|
|
* receiving CallParticipantSecurityEvents
|
|
*
|
|
* @param listener a listener instance to register with this participant.
|
|
*/
|
|
public void addCallParticipantSecurityListener(
|
|
CallParticipantSecurityListener listener)
|
|
{
|
|
synchronized(callParticipantSecurityListeners)
|
|
{
|
|
if (!callParticipantSecurityListeners.contains(listener))
|
|
callParticipantSecurityListeners.add(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unregisters the specified listener.
|
|
*
|
|
* @param listener the listener to unregister.
|
|
*/
|
|
public void removeCallParticipantSecurityListener(
|
|
CallParticipantSecurityListener listener)
|
|
{
|
|
if (listener == null)
|
|
return;
|
|
synchronized(callParticipantSecurityListeners)
|
|
{
|
|
callParticipantSecurityListeners.remove(listener);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a <tt>CallParticipantChangeEvent</tt> using this call
|
|
* participant as source, setting it to be of type <tt>eventType</tt> and
|
|
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
|
|
*
|
|
* @param eventType the type of the event to create and dispatch.
|
|
* @param oldValue the value of the source property before it changed.
|
|
* @param newValue the current value of the source property.
|
|
*/
|
|
protected void fireCallParticipantChangeEvent(String eventType,
|
|
Object oldValue,
|
|
Object newValue)
|
|
{
|
|
this.fireCallParticipantChangeEvent(
|
|
eventType, oldValue, newValue, null);
|
|
}
|
|
|
|
|
|
/**
|
|
* Constructs a <tt>CallParticipantChangeEvent</tt> using this call
|
|
* participant as source, setting it to be of type <tt>eventType</tt> and
|
|
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
|
|
*
|
|
* @param eventType the type of the event to create and dispatch.
|
|
* @param oldValue the value of the source property before it changed.
|
|
* @param newValue the current value of the source property.
|
|
* @param reason a string that could be set to contain a human readable
|
|
* explanation for the transition (particularly handy when moving into a
|
|
* FAILED state).
|
|
*/
|
|
protected void fireCallParticipantChangeEvent(String eventType,
|
|
Object oldValue,
|
|
Object newValue,
|
|
String reason)
|
|
{
|
|
CallParticipantChangeEvent evt = new CallParticipantChangeEvent(
|
|
this, eventType, oldValue, newValue, reason);
|
|
|
|
logger.debug("Dispatching a CallParticipantChangeEvent event to "
|
|
+ callParticipantListeners.size()
|
|
+" listeners. event is: " + evt.toString());
|
|
|
|
Iterator<CallParticipantListener> listeners = null;
|
|
synchronized (callParticipantListeners)
|
|
{
|
|
listeners = new ArrayList<CallParticipantListener>(
|
|
callParticipantListeners).iterator();
|
|
}
|
|
|
|
while (listeners.hasNext())
|
|
{
|
|
CallParticipantListener listener
|
|
= (CallParticipantListener) listeners.next();
|
|
|
|
if(eventType.equals(CallParticipantChangeEvent
|
|
.CALL_PARTICIPANT_ADDRESS_CHANGE))
|
|
{
|
|
listener.participantAddressChanged(evt);
|
|
} else if(eventType.equals(CallParticipantChangeEvent
|
|
.CALL_PARTICIPANT_DISPLAY_NAME_CHANGE))
|
|
{
|
|
listener.participantDisplayNameChanged(evt);
|
|
} else if(eventType.equals(CallParticipantChangeEvent
|
|
.CALL_PARTICIPANT_IMAGE_CHANGE))
|
|
{
|
|
listener.participantImageChanged(evt);
|
|
} else if(eventType.equals(CallParticipantChangeEvent
|
|
.CALL_PARTICIPANT_STATE_CHANGE))
|
|
{
|
|
listener.participantStateChanged(evt);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a <tt>CallParticipantSecurityStatusEvent</tt> using this call
|
|
* participant as source, setting it to be of type <tt>eventType</tt> and
|
|
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
|
|
*
|
|
* @param sessionType the type of the session - audio or video
|
|
* @param eventID the identifier of the event
|
|
*/
|
|
protected void fireCallParticipantSecurityOnEvent(
|
|
String sessionType,
|
|
String cipher,
|
|
String securityString,
|
|
boolean isVerified)
|
|
{
|
|
CallParticipantSecurityOnEvent evt
|
|
= new CallParticipantSecurityOnEvent( this,
|
|
sessionType,
|
|
cipher,
|
|
securityString,
|
|
isVerified);
|
|
|
|
logger.debug("Dispatching a CallParticipantSecurityStatusEvent event to "
|
|
+ callParticipantSecurityListeners.size()
|
|
+" listeners. event is: " + evt.toString());
|
|
|
|
Iterator<CallParticipantSecurityListener> listeners = null;
|
|
synchronized (callParticipantSecurityListeners)
|
|
{
|
|
listeners = new ArrayList<CallParticipantSecurityListener>(
|
|
callParticipantSecurityListeners).iterator();
|
|
}
|
|
|
|
while (listeners.hasNext())
|
|
{
|
|
CallParticipantSecurityListener listener
|
|
= (CallParticipantSecurityListener) listeners.next();
|
|
|
|
listener.securityOn(evt);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a <tt>CallParticipantSecurityStatusEvent</tt> using this call
|
|
* participant as source, setting it to be of type <tt>eventType</tt> and
|
|
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
|
|
*
|
|
* @param sessionType the type of the session - audio or video
|
|
* @param eventID the identifier of the event
|
|
*/
|
|
protected void fireCallParticipantSecurityOffEvent(String sessionType)
|
|
{
|
|
CallParticipantSecurityOffEvent event
|
|
= new CallParticipantSecurityOffEvent( this,
|
|
sessionType);
|
|
|
|
logger.debug(
|
|
"Dispatching a CallParticipantSecurityAuthenticationEvent event to "
|
|
+ callParticipantSecurityListeners.size()
|
|
+" listeners. event is: " + event.toString());
|
|
|
|
Iterator<CallParticipantSecurityListener> listeners = null;
|
|
synchronized (callParticipantSecurityListeners)
|
|
{
|
|
listeners = new ArrayList<CallParticipantSecurityListener>(
|
|
callParticipantSecurityListeners).iterator();
|
|
}
|
|
|
|
while (listeners.hasNext())
|
|
{
|
|
CallParticipantSecurityListener listener
|
|
= (CallParticipantSecurityListener) listeners.next();
|
|
|
|
listener.securityOff(event);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a <tt>CallParticipantSecurityStatusEvent</tt> using this call
|
|
* participant as source, setting it to be of type <tt>eventType</tt> and
|
|
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
|
|
*
|
|
* @param sessionType the type of the session - audio or video
|
|
* @param eventID the identifier of the event
|
|
*/
|
|
protected void fireCallParticipantSecurityMessageEvent(
|
|
String messageType,
|
|
String message,
|
|
String i18nMessage)
|
|
{
|
|
CallParticipantSecurityMessageEvent evt
|
|
= new CallParticipantSecurityMessageEvent( this,
|
|
messageType,
|
|
message,
|
|
i18nMessage);
|
|
|
|
logger.debug("Dispatching a CallParticipantSecurityFailedEvent event to "
|
|
+ callParticipantSecurityListeners.size()
|
|
+" listeners. event is: " + evt.toString());
|
|
|
|
Iterator<CallParticipantSecurityListener> listeners = null;
|
|
synchronized (callParticipantSecurityListeners)
|
|
{
|
|
listeners = new ArrayList<CallParticipantSecurityListener>(
|
|
callParticipantSecurityListeners).iterator();
|
|
}
|
|
|
|
while (listeners.hasNext())
|
|
{
|
|
CallParticipantSecurityListener listener
|
|
= (CallParticipantSecurityListener) listeners.next();
|
|
|
|
listener.securityMessageRecieved(evt);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation of the participant in the form of
|
|
* <br/>
|
|
* Display Name <address>;status=CallParticipantStatus
|
|
* @return a string representation of the participant and its state.
|
|
*/
|
|
public String toString()
|
|
{
|
|
return getDisplayName() + " <" + getAddress()
|
|
+ ">;status=" + getState().getStateString();
|
|
}
|
|
|
|
/**
|
|
* Returns a URL pointing ta a location with call control information for
|
|
* this participant or <tt>null</tt> if no such URL is available for this
|
|
* call participant.
|
|
*
|
|
* @return a URL link to a location with call information or a call control
|
|
* web interface related to this participant or <tt>null</tt> if no such URL
|
|
* is available.
|
|
*/
|
|
public URL getCallInfoURL()
|
|
{
|
|
//if signaling protocols (such as SIP) know where to get this URL from
|
|
//they should override this method
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns an object representing the current state of that participant.
|
|
*
|
|
* @return a CallParticipantState instance representin the participant's
|
|
* state.
|
|
*/
|
|
public CallParticipantState getState()
|
|
{
|
|
return state;
|
|
}
|
|
|
|
/**
|
|
* Causes this CallParticipant to enter the specified state. The method also
|
|
* sets the currentStateStartDate field and fires a
|
|
* CallParticipantChangeEvent.
|
|
*
|
|
* @param newState the state this call participant should enter.
|
|
* @param reason a string that could be set to contain a human readable
|
|
* explanation for the transition (particularly handy when moving into a
|
|
* FAILED state).
|
|
*/
|
|
public void setState(CallParticipantState newState, String reason)
|
|
{
|
|
CallParticipantState oldState = getState();
|
|
|
|
if(oldState == newState)
|
|
return;
|
|
|
|
this.state = newState;
|
|
|
|
if (CallParticipantState.CONNECTED.equals(newState)
|
|
&& !CallParticipantState.isOnHold(oldState))
|
|
{
|
|
callDurationStartTime = System.currentTimeMillis();
|
|
}
|
|
|
|
fireCallParticipantChangeEvent(
|
|
CallParticipantChangeEvent.CALL_PARTICIPANT_STATE_CHANGE,
|
|
oldState,
|
|
newState);
|
|
}
|
|
|
|
/**
|
|
* Causes this CallParticipant to enter the specified state. The method also
|
|
* sets the currentStateStartDate field and fires a
|
|
* CallParticipantChangeEvent.
|
|
*
|
|
* @param newState the state this call participant should enter.
|
|
*/
|
|
public void setState(CallParticipantState newState)
|
|
{
|
|
setState(newState, null);
|
|
}
|
|
|
|
/**
|
|
* Gets the time at which this <code>CallParticipant</code> transitioned
|
|
* into a state (likely {@link CallParticipantState#CONNECTED}) marking the
|
|
* start of the duration of the participation in a <code>Call</code>.
|
|
*
|
|
* @return the time at which this <code>CallParticipant</code> transitioned
|
|
* into a state marking the start of the duration of the
|
|
* participation in a <code>Call</code> or
|
|
* {@link CallParticipant#CALL_DURATION_START_TIME_UNKNOWN} if such
|
|
* a transition has not been performed
|
|
*/
|
|
public long getCallDurationStartTime()
|
|
{
|
|
return callDurationStartTime;
|
|
}
|
|
|
|
/**
|
|
* Determines whether the audio stream (if any) being sent to this
|
|
* participant is mute.
|
|
* <p>
|
|
* The default implementation returns <tt>false</tt>.
|
|
* </p>
|
|
*
|
|
* @return <tt>true</tt> if an audio stream is being sent to this
|
|
* participant and it is currently mute; <tt>false</tt>, otherwise
|
|
*/
|
|
public boolean isMute()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Sets the security status for this call participant.
|
|
*
|
|
* @param isSecurityOn <code>true</code> to indicate that the security is
|
|
* turned on and <code>false</code> - otherwise.
|
|
* @param sessionType the type of the call session - audio or video.
|
|
*/
|
|
public void setSecurityOn( boolean isSecurityOn,
|
|
String sessionType,
|
|
String cipher,
|
|
String securityString,
|
|
boolean isVerified)
|
|
{
|
|
if (isSecurityOn)
|
|
fireCallParticipantSecurityOnEvent(
|
|
sessionType,
|
|
cipher,
|
|
securityString,
|
|
isVerified);
|
|
}
|
|
|
|
public void setSecurityOff(String sessionType)
|
|
{
|
|
fireCallParticipantSecurityOffEvent(sessionType);
|
|
}
|
|
|
|
/**
|
|
* Sets the security message associated with a failure/warning or
|
|
* information coming from the encryption protocol.
|
|
*
|
|
* @param messageType the type of the message.
|
|
* @param message the message
|
|
*/
|
|
public void setSecurityMessage( String messageType,
|
|
String message,
|
|
String i18nMessage)
|
|
{
|
|
fireCallParticipantSecurityMessageEvent(messageType,
|
|
message,
|
|
i18nMessage);
|
|
}
|
|
}
|