- move things here and there

git-svn-id: http://bigbluebutton.googlecode.com/svn/trunk@3015 af16638f-c34d-0410-8cfa-b39d5352b314
This commit is contained in:
Richard Alam 2009-11-18 19:54:37 +00:00
parent 64089ef8f3
commit 2b01d06621
6 changed files with 716 additions and 543 deletions

View File

@ -5,7 +5,7 @@ import org.red5.server.api.IScope;
import org.red5.server.api.service.IServiceCapableConnection;
import org.slf4j.Logger;
public class RtmpConnection implements ScopeProvider {
public class RtmpConnection implements ScopeProvider, SipUserAgentListener, SipRegisterAgentListener {
private static Logger log = Red5LoggerFactory.getLogger( RtmpConnection.class, "sip" );
private final IServiceCapableConnection connection;
@ -20,57 +20,56 @@ public class RtmpConnection implements ScopeProvider {
return scope;
}
public void onCallIncoming(String source, String sourceName, String destination, String destinationName) {
connection.invoke( "incoming",
new Object[] { source, sourceName, destination, destinationName } );
public void onNewIncomingCall(String source, String sourceName, String destination, String destinationName) {
connection.invoke("incoming", new Object[] {source, sourceName, destination, destinationName});
}
public void onUaCallRinging() {
log.debug( "onUaCallRinging" );
public void onOutgoingCallRemoteRinging() {
log.debug("onOutgoingCallRemoteRinging");
connection.invoke("callState", new Object[] {"onUaCallRinging"});
}
public void onUaCallAccepted() {
log.debug( "onUaCallAccepted" );
public void onOutgoingCallAccepted() {
log.debug("onOutgoingCallAccepted");
connection.invoke("callState", new Object[] {"onUaCallAccepted"});
}
public void onUaCallConnected(String playName, String publishName) {
public void onCallConnected(String playName, String publishName) {
log.debug( "SIP Call Connected" );
connection.invoke("connected", new Object[] {playName, publishName});
}
public void onUaCallTrasferred() {
log.debug( "onUaCallTrasferred");
public void onCallTrasferred() {
log.debug("onCallTrasferred");
connection.invoke("callState", new Object[] {"onUaCallTrasferred"});
}
public void onUaCallCancelled() {
log.debug( "onUaCallCancelled");
public void onIncomingCallCancelled() {
log.debug("onIncomingCallCancelled");
connection.invoke("callState", new Object[] {"onUaCallCancelled"});
}
public void onUaCallFailed() {
log.debug( "onUaCallFailed");
connection.invoke("callState", new Object[] {"onUaCallFailed" });
public void onOutgoingCallFailed() {
log.debug("onOutgoingCallFailed");
connection.invoke("callState", new Object[] {"onUaCallFailed"});
}
public void onUaCallClosed() {
log.debug( "onUaCallClosed");
public void onCallClosed() {
log.debug("onCallClosed");
connection.invoke("callState", new Object[] {"onUaCallClosed"});
}
public void onUaRegistrationSuccess(String result) {
public void onRegistrationSuccess(String result) {
log.debug( "SIP Registration success " + result );
connection.invoke("registrationSucess", new Object[] {result});
}
public void onUaRegistrationFailure(String result) {
public void onRegistrationFailure(String result) {
log.debug( "SIP Registration failure " + result );
connection.invoke("registrationFailure", new Object[] {result});
}
public void onUaUnregistedSuccess() {
public void onUnregistedSuccess() {
// TODO Auto-generated method stub
}
}

View File

@ -0,0 +1,420 @@
package org.red5.app.sip;
import local.net.KeepAliveSip;
import org.zoolu.net.SocketAddress;
import org.zoolu.sip.address.*;
import org.zoolu.sip.provider.SipStack;
import org.zoolu.sip.provider.SipProvider;
import org.zoolu.sip.header.*;
import org.zoolu.sip.message.*;
import org.zoolu.sip.transaction.TransactionClient;
import org.zoolu.sip.transaction.TransactionClientListener;
import org.zoolu.sip.authentication.DigestAuthentication;
import org.slf4j.Logger;
import org.red5.logging.Red5LoggerFactory;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* Register User Agent. It registers (one time or periodically) a contact
* address with a registrar server.
*/
public class SipRegisterAgent implements TransactionClientListener {
private static Logger log = Red5LoggerFactory.getLogger(SipRegisterAgent.class, "sip");
private final Executor exec = Executors.newSingleThreadExecutor();
private Runnable registerProcess;
private volatile boolean continueRegistering = false;
/** The CallerID and CSeq that should be used during REGISTER method */
private CallIdHeader registerCallID;
private int registerCSeq;
private static final int MAX_ATTEMPTS = 3;
private Set<SipRegisterAgentListener> listeners = new HashSet<SipRegisterAgentListener>();
private SipProvider sipProvider;
private NameAddress target; /** User's URI with the fully qualified domain name of the registrar server. */
private String username;
private String realm;
private String passwd;
private String nextNonce; /** Nonce for the next authentication. */
private String qop; /** Qop for the next authentication. */
private NameAddress contact; /** User's contact address. */
private int expireTime; /** Expiration time. */
private int renewTime;
private int origRenewTime; // Change by lior.
private int minRenewTime = 20;
private int regFailRetryTime = 15;
private boolean lastRegFailed = false; // Changed by Lior.
private boolean regInprocess = false;
private int attempts; /** Number of registration attempts. */
private KeepAliveSip keepAlive; /** KeepAliveSip daemon. */
public SipRegisterAgent(SipProvider sipProvider, String targetUrl, String contactUrl) {
init(sipProvider, targetUrl, contactUrl);
}
/**
* Creates a new RegisterAgent with authentication credentials (i.e.
* username, realm, and passwd).
*/
public SipRegisterAgent(SipProvider sipProvider, String targetUrl,
String contactUrl, String username, String realm, String passwd) {
init(sipProvider, targetUrl, contactUrl);
// Authentication.
this.username = username;
this.realm = realm;
this.passwd = passwd;
}
private void init(SipProvider sipProvider, String targetUrl, String contactUrl) {
this.sipProvider = sipProvider;
this.target = new NameAddress(targetUrl);
this.contact = new NameAddress(contactUrl);
// this.expire_time=SipStack.default_expires;
this.expireTime = 600;
// Changed by Lior.
this.renewTime = 600;
this.origRenewTime = this.renewTime;
this.keepAlive = null;
// Authentication.
this.username = null;
this.realm = null;
this.passwd = null;
this.nextNonce = null;
this.qop = null;
this.attempts = 0;
this.minRenewTime = 20;
this.regFailRetryTime = 5;
this.registerCallID = null;
this.registerCSeq = 0;
}
public void addListener(SipRegisterAgentListener listener) {
listeners.add(listener);
}
public void removeListener(SipRegisterAgentListener listener) {
listeners.remove(listener);
}
private boolean isPeriodicallyRegistering() {
return continueRegistering;
}
/** Registers with the registrar server. */
public void register() {
register(expireTime);
}
/** Registers with the registrar server for <i>expire_time</i> seconds. */
public void register(int expireTime) {
attempts = 0;
lastRegFailed = false;
regInprocess = true;
if (expireTime > 0) this.expireTime = expireTime;
Message req = MessageFactory.createRegisterRequest(sipProvider, target, target, contact);
/*
* MY_FIX: registerCallID contains the CallerID randomly generated in
* the first REGISTER method. It will be reused for all successive
* REGISTER invocations
*/
if (this.registerCallID == null)
this.registerCallID = req.getCallIdHeader();
else
req.setCallIdHeader(this.registerCallID);
/*
* MY_FIX: the registerCSeq must be unique for a given CallerID
*/
this.registerCSeq++;
req.setCSeqHeader(new CSeqHeader(this.registerCSeq, SipMethods.REGISTER));
req.setExpiresHeader(new ExpiresHeader(String.valueOf(expireTime)));
if (nextNonce != null) {
AuthorizationHeader authHeader = new AuthorizationHeader("Digest");
authHeader.addUsernameParam(username);
authHeader.addRealmParam(realm);
authHeader.addNonceParam(nextNonce);
authHeader.addUriParam(req.getRequestLine().getAddress().toString());
authHeader.addQopParam(qop);
String response = (new DigestAuthentication(SipMethods.REGISTER,
authHeader, null, passwd)).getResponse();
authHeader.addResponseParam(response);
req.setAuthorizationHeader(authHeader);
}
if (expireTime > 0)
printLog("Registering contact " + contact + " (it expires in " + expireTime + " secs)");
else
printLog("Unregistering contact " + contact);
TransactionClient t = new TransactionClient(sipProvider, req, this);
t.request();
}
public void unregister() {
if (isPeriodicallyRegistering()) {
stopRegistering();
}
register(0);
sipProvider = null;
}
public void unregisterall() {
attempts = 0;
Message req = MessageFactory.createRegisterRequest(sipProvider, target, target, null);
req.setExpiresHeader(new ExpiresHeader(String.valueOf(0)));
printLog("Unregistering all contacts");
TransactionClient t = new TransactionClient(sipProvider, req, this);
t.request();
}
/**
* Periodically registers with the registrar server.
*
* @param expireTime
* expiration time in seconds
* @param renewTime
* renew time in seconds
*/
public void loopRegister(int expireTime, int renewTime) {
this.expireTime = expireTime;
this.renewTime = renewTime;
if (!isPeriodicallyRegistering()) {
registerProcess = new Runnable() {
public void run() {
registerWithServer();
}
};
exec.execute(registerProcess);
}
}
/**
* Periodically registers with the registrar server.
*
* @param expireTime
* expiration time in seconds
* @param renewTime
* renew time in seconds
* @param keepaliveTime
* keep-alive packet rate (inter-arrival time) in milliseconds
*/
public void loopRegister(int expireTime, int renewTime, long keepaliveTime) {
if (isPeriodicallyRegistering()) {
stopRegistering();
}
loopRegister(expireTime, renewTime);
// Keep-alive.
if (keepaliveTime > 0) {
SipURL targetUrl = target.getAddress();
String targetHost = targetUrl.getHost();
int targePort = targetUrl.getPort();
if (targePort < 0) targePort = SipStack.default_port;
SocketAddress socket = new SocketAddress(targetHost, targePort);
keepAlive = new KeepAliveSip(sipProvider, socket, null, keepaliveTime);
}
}
public void stopRegistering() {
continueRegistering = false;
if (keepAlive != null)
keepAlive.halt();
}
// ***************************** run() *****************************
/** Run method */
private void registerWithServer() {
continueRegistering = true;
try {
while (continueRegistering) {
register();
// Changed by Lior.
long waitCnt = 0;
while (regInprocess) {
Thread.sleep(1000);
waitCnt += 1000;
}
if (lastRegFailed) {
printLog("Failed Registration stop try.");
stopRegistering();
} else
Thread.sleep(renewTime * 1000 - waitCnt);
}
} catch (Exception e) {
printException(e);
}
continueRegistering = false;
}
// **************** Transaction callback functions *****************
/** Callback function called when client sends back a failure response. */
/** Callback function called when client sends back a provisional response. */
public void onTransProvisionalResponse(TransactionClient transaction, Message resp) {
// do nothing...
}
/** Callback function called when client sends back a success response. */
public void onTransSuccessResponse(TransactionClient transaction, Message resp) {
if (transaction.getTransactionMethod().equals(SipMethods.REGISTER)) {
if (resp.hasAuthenticationInfoHeader()) {
nextNonce = resp.getAuthenticationInfoHeader().getNextnonceParam();
}
StatusLine status = resp.getStatusLine();
String result = status.getCode() + " " + status.getReason();
// Update the renew_time.
// Changed by Lior.
int expires = 0;
if (resp.hasExpiresHeader()) {
expires = resp.getExpiresHeader().getDeltaSeconds();
} else if (resp.hasContactHeader()) {
// Look for the max expires - should be the latest.
Vector contacts = resp.getContacts().getHeaders();
for (int i = 0; i < contacts.size(); i++) {
int exp_i = (new ContactHeader((Header) contacts.elementAt(i))).getExpires();
if (exp_i / 2 > expires)
expires = exp_i / 2;
}
}
if (expires > 0 && expires < renewTime) {
renewTime = expires;
if (renewTime < minRenewTime) {
printLog("Attempt to set renew time below min renew. Attempted="
+ renewTime + " min=" + minRenewTime + "\r\nResponse=" + resp.toString());
renewTime = minRenewTime;
}
} else if (expires > origRenewTime) {
printLog("Attempt to set renew time above original renew. Attempted="
+ expires + " origrenew=" + origRenewTime + "\r\nResponse=" + resp.toString());
}
printLog("Registration success: ");
regInprocess = false;
notifyListenersOfRegistrationSuccess(result);
}
}
private void notifyListenersOfRegistrationSuccess(String result) {
for (SipRegisterAgentListener listener : listeners) {
listener.onRegistrationSuccess(result);
}
}
/** Callback function called when client sends back a failure response. */
public void onTransFailureResponse(TransactionClient transaction, Message resp) {
printLog("onTransFailureResponse start: ");
if (transaction.getTransactionMethod().equals(SipMethods.REGISTER)) {
StatusLine status = resp.getStatusLine();
int code = status.getCode();
if ((code == 401 && attempts < MAX_ATTEMPTS && resp.hasWwwAuthenticateHeader()
&& resp.getWwwAuthenticateHeader().getRealmParam().equalsIgnoreCase(realm))
|| (code == 407 && attempts < MAX_ATTEMPTS && resp.hasProxyAuthenticateHeader()
&& resp.getProxyAuthenticateHeader().getRealmParam().equalsIgnoreCase(realm)))
{
printLog("onTransFailureResponse 401 or 407: ");
attempts++;
Message req = transaction.getRequestMessage();
req.setCSeqHeader(req.getCSeqHeader().incSequenceNumber());
// * MY_FIX: registerCSeq counter must incremented.
this.registerCSeq++;
WwwAuthenticateHeader wah;
if (code == 401)
wah = resp.getWwwAuthenticateHeader();
else
wah = resp.getProxyAuthenticateHeader();
String qopOptions = wah.getQopOptionsParam();
// qop=(qopOptions!=null)? "auth" : null;
// Select a new branch - rfc3261 says should be new on each
// request.
ViaHeader via = req.getViaHeader();
req.removeViaHeader();
via.setBranch(SipProvider.pickBranch());
req.addViaHeader(via);
qop = (qopOptions != null) ? "auth" : null;
DigestAuthentication digest = new DigestAuthentication(SipMethods.REGISTER,
req.getRequestLine().getAddress().toString(), wah, qop, null, username, passwd);
AuthorizationHeader ah;
if (code == 401)
ah = digest.getAuthorizationHeader();
else
ah = digest.getProxyAuthorizationHeader();
req.setAuthorizationHeader(ah);
TransactionClient t = new TransactionClient(sipProvider, req, this);
t.request();
} else {
String result = code + " " + status.getReason();
lastRegFailed = true;
regInprocess = false;
printLog("Registration failure: " + result);
notifyListenersOfRegistrationFailure(result);
}
}
}
private void notifyListenersOfRegistrationFailure(String result) {
for (SipRegisterAgentListener listener : listeners) {
listener.onRegistrationFailure(result);
}
}
/** Callback function called when client expires timeout. */
public void onTransTimeout(TransactionClient transaction) {
if (transaction.getTransactionMethod().equals(SipMethods.REGISTER)) {
lastRegFailed = true;
regInprocess = false;
printLog("Registration failure: No response from server.");
notifyListenersOfRegistrationFailure( "Timeout");
}
}
// ****************************** Logs *****************************
void printLog(String str) {
System.out.println("RegisterAgent: " + str);
}
void printException(Exception e) {
System.out.println("RegisterAgent Exception: " + e);
}
}

View File

@ -0,0 +1,9 @@
package org.red5.app.sip;
public interface SipRegisterAgentListener {
/** When a UA has been successfully (un)registered. */
public void onRegistrationSuccess(String result);
/** When a UA failed on (un)registering. */
public void onRegistrationFailure(String result);
public void onUnregistedSuccess();
}

View File

@ -1,12 +1,11 @@
package org.red5.app.sip;
import org.zoolu.sip.address.*;
import org.zoolu.sip.provider.*;
import org.zoolu.net.SocketAddress;
import org.slf4j.Logger;
import org.red5.logging.Red5LoggerFactory;
public class SipUser implements SipUserAgentListener, RegisterAgentListener {
public class SipUser {
private static Logger log = Red5LoggerFactory.getLogger(SipUser.class, "sip");
private RtmpConnection rtmpConnection;
@ -16,58 +15,33 @@ public class SipUser implements SipUserAgentListener, RegisterAgentListener {
private SipProvider sipProvider;
private String optOutboundProxy = null;
private SipUserAgent userAgent;
private RegisterAgent registerAgent;
private RTMPUser rtmpUser;
private String username;
private String password;
private String publishName;
private String playName;
private int sipPort;
private int rtpPort;
private SipRegisterAgent registerAgent;
private String proxy;
private String realm;
public SipUser(String userid, RtmpConnection connection, int sipPort, int rtpPort) {
log.debug( "SIPUser Constructor: sip port " + sipPort + " rtp port:" + rtpPort );
this.userid = userid;
this.rtmpConnection = connection;
this.sipPort = sipPort;
this.rtpPort = rtpPort;
initializeSipStack();
initializeSipProvider(sipPort);
initializeUserProfile(rtpPort);
}
/*
public boolean isRunning() {
boolean resp = false;
try {
resp = userAgent.isReceiverRunning();
}
catch ( Exception e ) {
resp = false;
}
return resp;
}
*/
public void login(String obproxy, String phone, String username, String password, String realm, String proxy) {
log.debug( "SIPUser login" );
this.username = username;
this.password = password;
this.proxy = proxy;
this.optOutboundProxy = obproxy;
this.realm = realm;
rtmpUser = new RTMPUser();
initializeSipStack();
initializeSipProvider();
initializeUserProfile(phone);
sipProvider.setOutboundProxy(new SocketAddress(optOutboundProxy));
setupUserProfile(username, password, realm, phone);
initializeUserAgent();
}
private void initializeUserAgent() {
userAgent = new SipUserAgent(sipProvider, userProfile, this, rtmpConnection);
userAgent.waitForIncomingCalls();
userAgent = new SipUserAgent(sipProvider, userProfile, rtmpConnection);
userAgent.addListener(rtmpConnection);
userAgent.initialize();
}
private void initializeSipStack() {
@ -76,23 +50,24 @@ public class SipUser implements SipUserAgentListener, RegisterAgentListener {
SipStack.log_path = "log";
}
private void initializeSipProvider() {
sipProvider = new SipProvider( null, sipPort );
sipProvider.setOutboundProxy(new SocketAddress(optOutboundProxy));
private void initializeSipProvider(int sipPort) {
sipProvider = new SipProvider(null, sipPort);
sipProvider.addSipProviderListener(new OptionMethodListener());
}
private void initializeUserProfile(String phone) {
private void setupUserProfile(String username, String password, String realm, String phone) {
String fromURL = "\"" + phone + "\" <sip:" + phone + "@" + proxy + ">";
userProfile = new SipUserAgentProfile();
userProfile.audioPort = rtpPort;
userProfile.username = username;
userProfile.username = username;
userProfile.passwd = password;
userProfile.realm = realm;
userProfile.fromUrl = fromURL;
userProfile.contactUrl = "sip:" + phone + "@" + sipProvider.getViaAddress();
}
private void initializeUserProfile(int rtpPort) {
userProfile = new SipUserAgentProfile();
userProfile.audioPort = rtpPort;
if ( sipProvider.getPort() != SipStack.default_port ) {
userProfile.contactUrl += ":" + sipProvider.getPort();
}
@ -105,9 +80,10 @@ public class SipUser implements SipUserAgentListener, RegisterAgentListener {
public void register() {
log.debug( "SIPUser register" );
if (sipProvider != null) {
registerAgent = new RegisterAgent( sipProvider, userProfile.fromUrl, userProfile.contactUrl, username,
userProfile.realm, password, this );
loopRegister(userProfile.expires, userProfile.expires / 2, userProfile.keepaliveTime);
registerAgent = new SipRegisterAgent(sipProvider, userProfile.fromUrl, userProfile.contactUrl,
userProfile.username, userProfile.realm, userProfile.passwd);
registerAgent.addListener(rtmpConnection);
loopRegister(userProfile.expires, userProfile.expires/2, userProfile.keepaliveTime);
}
}
@ -148,7 +124,7 @@ public class SipUser implements SipUserAgentListener, RegisterAgentListener {
public void close() {
log.debug("SIPUser close1");
try {
try {
hangup();
unregister();
new Thread().sleep(3000);
@ -156,41 +132,26 @@ public class SipUser implements SipUserAgentListener, RegisterAgentListener {
log.error("close: Exception:>\n" + e);
}
try {
log.debug("SIPUser provider.halt");
sipProvider.halt();
} catch(Exception e) {
log.error("close: Exception:>\n" + e);
}
rtmpConnection = null;
log.debug("Stopping SipProvider");
sipProvider.halt();
}
public void accept() {
log.debug( "SIPUser accept" );
if (userAgent != null) {
try {
userAgent.accept();
}
catch ( Exception e ) {
log.error( "SIPUser: accept - Exception:>\n" + e );
}
userAgent.accept();
}
}
public void hangup() {
log.debug( "SIPUser hangup" );
if ( userAgent != null ) {
if ( userAgent.call_state != UserAgent.UA_IDLE ) {
userAgent.hangup();
userAgent.waitForIncomingCalls();
}
if (userAgent != null) {
userAgent.hangup();
}
closeStreams();
rtmpUser.stopStream();
}
public void streamStatus( String status ) {
@ -204,15 +165,12 @@ public class SipUser implements SipUserAgentListener, RegisterAgentListener {
public void unregister() {
log.debug( "SIPUser unregister" );
if ( registerAgent != null ) {
if ( registerAgent.isRegistering() ) {
registerAgent.halt();
}
if (registerAgent != null) {
registerAgent.unregister();
registerAgent = null;
}
if ( userAgent != null ) {
if (userAgent != null) {
userAgent.hangup();
}
userAgent = null;
@ -247,77 +205,6 @@ public class SipUser implements SipUserAgentListener, RegisterAgentListener {
}
private void loopRegister( int expire_time, int renew_time, long keepalive_time ) {
if ( registerAgent.isRegistering() ) {
registerAgent.halt();
}
registerAgent.loopRegister( expire_time, renew_time, keepalive_time );
}
public void onUaCallIncoming( SipUserAgent ua, NameAddress callee, NameAddress caller ) {
String source = caller.getAddress().toString();
String sourceName = caller.hasDisplayName() ? caller.getDisplayName() : "";
String destination = callee.getAddress().toString();
String destinationName = callee.hasDisplayName() ? callee.getDisplayName() : "";
log.debug( "onUaCallIncoming " + source + " " + destination);
rtmpConnection.onCallIncoming(source, sourceName, destination, destinationName);
}
public void onUaCallRinging( SipUserAgent ua ) {
log.debug( "onUaCallRinging" );
rtmpConnection.onUaCallRinging();
}
public void onUaCallAccepted( SipUserAgent ua ) {
log.debug( "onUaCallAccepted" );
rtmpConnection.onUaCallAccepted();
}
public void onUaCallConnected(SipUserAgent ua, String playName, String publishName) {
log.debug( "SIP Call Connected" );
rtmpConnection.onUaCallConnected(playName, publishName);
}
public void onUaCallTrasferred( SipUserAgent ua ) {
log.debug( "onUaCallTrasferred");
rtmpConnection.onUaCallTrasferred();
}
public void onUaCallCancelled( SipUserAgent ua ) {
log.debug( "onUaCallCancelled");
closeStreams();
rtmpConnection.onUaCallCancelled();
ua.waitForIncomingCalls();
}
public void onUaCallFailed( SipUserAgent ua ) {
log.debug( "onUaCallFailed");
closeStreams();
rtmpConnection.onUaCallFailed();
ua.waitForIncomingCalls();
}
public void onUaCallClosed( SipUserAgent ua ) {
log.debug( "onUaCallClosed");
closeStreams();
rtmpConnection.onUaCallClosed();
ua.waitForIncomingCalls();
}
public void onUaRegistrationSuccess( RegisterAgent ra, NameAddress target, NameAddress contact, String result ) {
log.debug( "SIP Registration success " + result );
rtmpConnection.onUaRegistrationSuccess(result);
}
public void onUaRegistrationFailure( RegisterAgent ra, NameAddress target, NameAddress contact, String result ) {
log.debug( "SIP Registration failure " + result );
rtmpConnection.onUaRegistrationFailure(result);
}
public void onUaUnregistedSuccess() {
// TODO Auto-generated method stub
}
}

View File

@ -12,6 +12,8 @@ import org.slf4j.Logger;
import org.red5.logging.Red5LoggerFactory;
import org.zoolu.tools.Parser;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
public class SipUserAgent extends CallListenerAdapter {
@ -23,136 +25,66 @@ public class SipUserAgent extends CallListenerAdapter {
private ExtendedCall callTransfer;
private CallStream callStream;
private String localSession = null;
private SipUserAgentListener listener = null;
private Codec sipCodec = null;
private final ScopeProvider scopeProvider;
private Set<SipUserAgentListener> listeners = new HashSet<SipUserAgentListener>();
private static final String UA_IDLE = "IDLE"; /** UA_IDLE=0 */
private static final String UA_INCOMING_CALL = "INCOMING_CALL"; /** UA_INCOMING_CALL=1 */
private static final String UA_OUTGOING_CALL = "OUTGOING_CALL"; /** UA_OUTGOING_CALL=2 */
private static final String UA_ONCALL = "ONCALL"; /** UA_ONCALL=3 */
/**
* Call state
* <P>
* UA_IDLE=0, <BR>
* UA_INCOMING_CALL=1, <BR>
* UA_OUTGOING_CALL=2, <BR>
* UA_ONCALL=3
*/
String call_state = UA_IDLE;
protected void changeStatus(String state) {
call_state = state;
private enum CallState {
UA_IDLE(0), UA_INCOMING_CALL(1), UA_OUTGOING_CALL(2), UA_ONCALL(3);
private final int state;
CallState(int state) {this.state = state;}
private int getState() {return state;}
}
protected boolean statusIs(String state) {
return call_state.equals(state);
private CallState callState;
public SipUserAgent(SipProvider sipProvider, SipUserAgentProfile userProfile, ScopeProvider scopeProvider) {
this.scopeProvider = scopeProvider;
this.sipProvider = sipProvider;
this.userProfile = userProfile;
// If no contact_url and/or from_url has been set, create it now.
userProfile.initContactAddress(sipProvider);
// Set local sdp.
initSessionDescriptor();
}
protected String getStatus() {
return call_state;
public void addListener(SipUserAgentListener listener) {
listeners.add(listener);
}
public void removeListener(SipUserAgentListener listener) {
listeners.remove(listener);
}
private void changeStatus(CallState state) {
callState = state;
}
/**
* Sets the automatic answer time (default is -1 that means no auto accept
* mode)
*/
public void setAcceptTime(int accept_time) {
userProfile.acceptTime = accept_time;
public boolean isIdle() {
return callState == CallState.UA_IDLE;
}
/**
* Sets the automatic hangup time (default is 0, that corresponds to manual
* hangup mode)
*/
public void setHangupTime(int time) {
userProfile.hangupTime = time;
}
/** Sets the redirection url (default is null, that is no redircetion) */
public void setRedirection(String url) {
userProfile.redirectTo = url;
}
/** Sets the no offer mode for the invite (default is false) */
public void setNoOfferMode(boolean nooffer) {
userProfile.noOffer = nooffer;
}
public void setAudio(boolean enable) {
userProfile.audio = enable;
}
public void setVideo(boolean enable) {
userProfile.video = enable;
}
public void setReceiveOnlyMode(boolean r_only) {
userProfile.recvOnly = r_only;
}
public void setSendOnlyMode(boolean s_only) {
userProfile.sendOnly = s_only;
}
public void setSendToneMode(boolean s_tone) {
userProfile.sendTone = s_tone;
}
public void setSendFile(String file_name) {
userProfile.sendFile = file_name;
}
public void setRecvFile(String file_name) {
userProfile.recvFile = file_name;
}
public String getSessionDescriptor() {
return localSession;
}
public void setSessionDescriptor(String sdp) {
localSession = sdp;
}
// public boolean isReceiverRunning() {
// return callStream.isReceiverRunning();
// }
public void queueSipDtmfDigits(String digits) {
callStream.queueSipDtmfDigits(digits);
}
public void initialize() {
waitForIncomingCalls();
}
public void initSessionDescriptor() {
log.debug("initSessionDescriptor");
SessionDescriptor newSdp = SdpUtils.createInitialSdp(
userProfile.username, sipProvider.getViaAddress(),
userProfile.audioPort, userProfile.videoPort,
userProfile.audioCodecsPrecedence );
SessionDescriptor newSdp = SdpUtils.createInitialSdp(userProfile.username,
sipProvider.getViaAddress(), userProfile.audioPort,
userProfile.videoPort, userProfile.audioCodecsPrecedence );
localSession = newSdp.toString();
log.debug("localSession Descriptor = " + localSession );
}
public SipUserAgent(SipProvider sipProvider, SipUserAgentProfile userProfile,
SipUserAgentListener listener, ScopeProvider scopeProvider) {
this.scopeProvider = scopeProvider;
this.sipProvider = sipProvider;
this.listener = listener;
this.userProfile = userProfile;
// If no contact_url and/or from_url has been set, create it now.
userProfile.initContactAddress( sipProvider );
// Set local sdp.
initSessionDescriptor();
}
public void call(String targetUrl) {
log.debug( "call", "Init..." );
changeStatus( UA_OUTGOING_CALL );
log.debug( "call", "Init..." );
changeStatus(CallState.UA_OUTGOING_CALL);
call = new ExtendedCall(sipProvider, userProfile.fromUrl,
userProfile.contactUrl, userProfile.username,
@ -165,7 +97,7 @@ public class SipUserAgent extends CallListenerAdapter {
if (userProfile.noOffer) {
call.call(targetUrl);
} else {
call.call( targetUrl, localSession );
call.call(targetUrl, localSession);
}
}
@ -180,9 +112,9 @@ public class SipUserAgent extends CallListenerAdapter {
/** Waits for an incoming call (acting as UAS). */
public void waitForIncomingCalls() {
log.debug("waitForIncomingCalls..." );
changeStatus( UA_IDLE );
private void waitForIncomingCalls() {
log.debug("waitForIncomingCalls..." );
changeStatus(CallState.UA_IDLE);
call = new ExtendedCall(sipProvider, userProfile.fromUrl,
userProfile.contactUrl, userProfile.username,
@ -194,12 +126,13 @@ public class SipUserAgent extends CallListenerAdapter {
/** Closes an ongoing, incoming, or pending call */
public void hangup() {
log.debug("hangup");
closeMediaApplication();
if (call != null) {
call.hangup();
}
changeStatus(UA_IDLE);
if (isIdle()) return;
closeMediaApplication();
if (call != null) call.hangup();
changeStatus(CallState.UA_IDLE);
waitForIncomingCalls();
}
@ -212,8 +145,6 @@ public class SipUserAgent extends CallListenerAdapter {
}
}
/** Redirects an incoming call */
public void redirect(String redirection) {
log.debug( "redirect", "Init..." );
@ -243,9 +174,7 @@ public class SipUserAgent extends CallListenerAdapter {
try {
callStream = new CallStream(sipCodec, connInfo, scopeProvider);
if (listener != null) {
listener.onUaCallConnected(this, callStream.getListenStreamName(), callStream.getTalkStreamName());
}
notifyListenersOnCallConnected(callStream.getListenStreamName(), callStream.getTalkStreamName());
} catch (Exception e) {
log.error("Failed to create Call Stream.");
}
@ -253,9 +182,15 @@ public class SipUserAgent extends CallListenerAdapter {
}
}
private void notifyListenersOnCallConnected(String listenStream, String talkStream) {
for (SipUserAgentListener listener : listeners) {
listener.onCallConnected(listenStream, talkStream);
}
}
private int getLocalAudioPort(SessionDescriptor localSdp) {
int localAudioPort = 0;
int localVideoPort = 0;
//int localVideoPort = 0;
// parse local sdp
for ( Enumeration e = localSdp.getMediaDescriptors().elements(); e.hasMoreElements(); ) {
@ -263,9 +198,9 @@ public class SipUserAgent extends CallListenerAdapter {
if ( media.getMedia().equals( "audio" ) ) {
localAudioPort = media.getPort();
}
if ( media.getMedia().equals( "video" ) ) {
localVideoPort = media.getPort();
}
//if ( media.getMedia().equals( "video" ) ) {
// localVideoPort = media.getPort();
//}
}
return localAudioPort;
@ -273,9 +208,9 @@ public class SipUserAgent extends CallListenerAdapter {
private int getRemoteAudioPort(SessionDescriptor remoteSdp) {
int remoteAudioPort = 0;
int remoteVideoPort = 0;
//int remoteVideoPort = 0;
for ( Enumeration e = remoteSdp.getMediaDescriptors().elements(); e.hasMoreElements(); ) {
for (Enumeration e = remoteSdp.getMediaDescriptors().elements(); e.hasMoreElements();) {
MediaDescriptor descriptor = (MediaDescriptor) e.nextElement();
MediaField media = descriptor.getMedia();
@ -283,9 +218,9 @@ public class SipUserAgent extends CallListenerAdapter {
remoteAudioPort = media.getPort();
}
if ( media.getMedia().equals( "video" ) ) {
remoteVideoPort = media.getPort();
}
// if ( media.getMedia().equals( "video" ) ) {
// remoteVideoPort = media.getPort();
// }
}
return remoteAudioPort;
@ -296,7 +231,7 @@ public class SipUserAgent extends CallListenerAdapter {
}
protected void closeMediaApplication() {
log.debug( "closeMediaApplication", "Init..." );
log.debug("closeMediaApplication" );
if (callStream != null) {
callStream.stopMedia();
@ -307,125 +242,41 @@ public class SipUserAgent extends CallListenerAdapter {
// ********************** Call callback functions **********************
private void createAudioCodec(SessionDescriptor newSdp) {
sipCodec = SdpUtils.getNegotiatedAudioCodec(newSdp);
}
/**
* Callback function called when arriving a new INVITE method (incoming call)
*/
public void onCallIncoming(Call call, NameAddress callee, NameAddress caller, String sdp, Message invite) {
log.debug("onCallIncoming");
if (call != this.call) {
log.debug("NOT the current call.");
return;
}
if (!isCurrentCall(call)) return;
log.debug("Inside SIPUserAgent.onCallIncoming(): sdp=\n" + sdp);
log.debug("IncomingCallIncoming()");
changeStatus(UA_INCOMING_CALL);
changeStatus(CallState.UA_INCOMING_CALL);
call.ring();
if (sdp != null) {
SessionDescriptor remoteSdp = new SessionDescriptor(sdp);
SessionDescriptor localSdp = new SessionDescriptor(localSession);
log.debug("localSdp = " + localSdp.toString() + ".");
log.debug("remoteSdp = " + remoteSdp.toString() + ".");
// First we need to make payloads negotiation so the related
// attributes can be then matched.
SessionDescriptor newSdp = SdpUtils.makeMediaPayloadsNegotiation(localSdp, remoteSdp);
// After we can create the correct audio codec considering
// audio negotiation made above.
sipCodec = SdpUtils.getNegotiatedAudioCodec(newSdp);
// Now we complete the SDP negotiation informing the selected
// codec, so it can be internally updated during the process.
SdpUtils.completeSdpNegotiation(newSdp, localSdp, remoteSdp);
localSession = newSdp.toString();
log.debug("newSdp = " + localSession + "." );
// Finally, we use the "newSdp" and "remoteSdp" to initialize
// the lasting codec informations.
CodecUtils.initSipAudioCodec(sipCodec, userProfile.audioDefaultPacketization,
userProfile.audioDefaultPacketization, newSdp, remoteSdp);
setupSdpAndCodec(sdp);
}
if (listener != null) {
listener.onUaCallIncoming(this, callee, caller);
}
notifyListenersOfNewIncomingCall(callee, caller);
}
/**
* Callback function called when arriving a new Re-INVITE method
* (re-inviting/call modify)
*/
public void onCallModifying(Call call, String sdp, Message invite) {
log.debug("onCallModifying");
if (call != this.call) {
log.debug("NOT the current call.");
return;
}
log.debug("RE-INVITE/MODIFY.");
// to be implemented.
// currently it simply accepts the session changes (see method
// onCallModifying() in CallListenerAdapter)
super.onCallModifying( call, sdp, invite );
}
/**
* Callback function that may be overloaded (extended). Called when arriving
* a 180 Ringing
*/
public void onCallRinging(Call call, Message resp) {
log.debug("onCallRinging");
if (call != this.call && call != callTransfer) {
log.debug("NOT the current call.");
return;
}
log.debug("RINGING." );
// Play "on" sound.
if (listener != null) {
listener.onUaCallRinging(this);
}
}
/** Callback function called when arriving a 2xx (call accepted) */
public void onCallAccepted(Call call, String sdp, Message resp) {
log.debug( "onCallAccepted");
if (call != this.call && call != callTransfer) {
log.debug("NOT the current call." );
return;
}
log.debug("ACCEPTED/CALL.");
changeStatus(UA_ONCALL);
SessionDescriptor remoteSdp = new SessionDescriptor(sdp);
private void setupSdpAndCodec(String sdp) {
SessionDescriptor remoteSdp = new SessionDescriptor(sdp);
SessionDescriptor localSdp = new SessionDescriptor(localSession);
log.debug("localSdp = " + localSdp.toString() + ".");
log.debug("remoteSdp = " + remoteSdp.toString() + ".");
// First we need to make payloads negotiation so the related
// attributes can be then matched.
// First we need to make payloads negotiation so the related attributes can be then matched.
SessionDescriptor newSdp = SdpUtils.makeMediaPayloadsNegotiation(localSdp, remoteSdp);
// After we can create the correct audio codec considering
// audio negotiation made above.
sipCodec = SdpUtils.getNegotiatedAudioCodec(newSdp);
createAudioCodec(newSdp);
// Now we complete the SDP negotiation informing the selected
// codec, so it can be internally updated during the process.
@ -433,12 +284,71 @@ public class SipUserAgent extends CallListenerAdapter {
localSession = newSdp.toString();
log.debug("newSdp = " + localSession + ".");
log.debug("newSdp = " + localSession + "." );
// Finally, we use the "newSdp" and "remoteSdp" to initialize
// the lasting codec informations.
// Finally, we use the "newSdp" and "remoteSdp" to initialize the lasting codec informations.
CodecUtils.initSipAudioCodec(sipCodec, userProfile.audioDefaultPacketization,
userProfile.audioDefaultPacketization, newSdp, remoteSdp);
}
private void notifyListenersOfNewIncomingCall(NameAddress callee, NameAddress caller) {
String source = caller.getAddress().toString();
String sourceName = caller.hasDisplayName() ? caller.getDisplayName() : "";
String destination = callee.getAddress().toString();
String destinationName = callee.hasDisplayName() ? callee.getDisplayName() : "";
for (SipUserAgentListener listener : listeners) {
listener.onNewIncomingCall(source, sourceName, destination, destinationName);
}
}
/**
* Callback function called when arriving a new Re-INVITE method (re-inviting/call modify)
*/
public void onCallModifying(Call call, String sdp, Message invite) {
log.debug("onCallModifying");
if (!isCurrentCall(call)) return;
log.debug("RE-INVITE/MODIFY.");
// to be implemented.
// currently it simply accepts the session changes (see method
// onCallModifying() in CallListenerAdapter)
super.onCallModifying(call, sdp, invite);
}
/**
* Callback function that may be overloaded (extended). Called when arriving a 180 Ringing
*/
public void onCallRinging(Call call, Message resp) {
log.debug("onCallRinging");
if (!isCurrentCallOrCallTransfer(call)) return;
log.debug("RINGING." );
notifyListenersOfOnOutgoingCallRemoteRinging();
}
private void notifyListenersOfOnOutgoingCallRemoteRinging() {
for (SipUserAgentListener listener : listeners) {
listener.onOutgoingCallRemoteRinging();
}
}
/** Callback function called when arriving a 2xx (call accepted) */
public void onCallAccepted(Call call, String sdp, Message resp) {
log.debug( "onCallAccepted");
if (!isCurrentCallOrCallTransfer(call)) return;
log.debug("ACCEPTED/CALL.");
changeStatus(CallState.UA_ONCALL);
setupSdpAndCodec(sdp);
if (userProfile.noOffer) {
// Answer with the local sdp.
@ -454,24 +364,24 @@ public class SipUserAgent extends CallListenerAdapter {
this.call.notify(code, reason);
}
if (listener != null) {
listener.onUaCallAccepted(this);
}
notifyListenersOfOnOutgoingCallAccepted();
}
public void notifyListenersOfOnOutgoingCallAccepted() {
for (SipUserAgentListener listener : listeners) {
listener.onOutgoingCallAccepted();
}
}
/** Callback function called when arriving an ACK method (call confirmed) */
public void onCallConfirmed(Call call, String sdp, Message ack) {
log.debug("onCallConfirmed");
if (call != this.call) {
log.debug("NOT the current call.");
return;
}
if (!isCurrentCall(call)) return;
log.debug("CONFIRMED/CALL.");
changeStatus(UA_ONCALL);
changeStatus(CallState.UA_ONCALL);
launchMediaApplication();
}
@ -480,10 +390,7 @@ public class SipUserAgent extends CallListenerAdapter {
public void onCallReInviteAccepted(Call call, String sdp, Message resp) {
log.debug( "onCallReInviteAccepted");
if (call != this.call) {
log.debug("NOT the current call." );
return;
}
if (!isCurrentCall(call)) return;
log.debug("RE-INVITE-ACCEPTED/CALL." );
}
@ -493,30 +400,22 @@ public class SipUserAgent extends CallListenerAdapter {
public void onCallReInviteRefused(Call call, String reason, Message resp) {
log.debug("onCallReInviteRefused");
if (call != this.call) {
log.debug("NOT the current call");
return;
}
if (!isCurrentCall(call)) return;
log.debug("RE-INVITE-REFUSED (" + reason + ")/CALL.");
if (listener != null) {
listener.onUaCallFailed(this);
}
notifyListenersOnOutgoingCallFailed();
waitForIncomingCalls();
}
/** Callback function called when arriving a 4xx (call failure) */
public void onCallRefused(Call call, String reason, Message resp) {
log.debug("onCallRefused");
if (call != this.call) {
log.debug("NOT the current call.");
return;
}
if (!isCurrentCall(call)) return;
log.debug("REFUSED (" + reason + ").");
changeStatus(UA_IDLE);
changeStatus(CallState.UA_IDLE);
if (call == callTransfer) {
StatusLine status_line = resp.getStatusLine();
@ -526,9 +425,14 @@ public class SipUserAgent extends CallListenerAdapter {
callTransfer = null;
}
if (listener != null) {
listener.onUaCallFailed(this);
}
notifyListenersOnOutgoingCallFailed();
waitForIncomingCalls();
}
private void notifyListenersOnOutgoingCallFailed() {
for (SipUserAgentListener listener : listeners) {
listener.onOutgoingCallFailed();
}
}
@ -536,11 +440,7 @@ public class SipUserAgent extends CallListenerAdapter {
public void onCallRedirection(Call call, String reason, Vector contact_list, Message resp) {
log.debug("onCallRedirection");
if (call != this.call) {
log.debug("NOT the current call.");
return;
}
if (!isCurrentCall(call)) return;
log.debug("REDIRECTION (" + reason + ")." );
call.call(((String) contact_list.elementAt(0)));
@ -548,24 +448,23 @@ public class SipUserAgent extends CallListenerAdapter {
/**
* Callback function that may be overloaded (extended). Called when arriving
* a CANCEL request
* Callback function that may be overloaded (extended). Called when arriving a CANCEL request
*/
public void onCallCanceling(Call call, Message cancel) {
log.debug("onCallCanceling");
if (call != this.call) {
log.debug("NOT the current call.");
return;
}
if (!isCurrentCall(call)) return;
log.debug("CANCEL.");
changeStatus(UA_IDLE);
if (listener != null) {
listener.onUaCallCancelled(this);
}
changeStatus(CallState.UA_IDLE);
notifyListenersOfOnIncomingCallCancelled();
waitForIncomingCalls();
}
private void notifyListenersOfOnIncomingCallCancelled() {
for (SipUserAgentListener listener : listeners) {
listener.onIncomingCallCancelled();
}
}
@ -573,10 +472,7 @@ public class SipUserAgent extends CallListenerAdapter {
public void onCallClosing(Call call, Message bye) {
log.debug("onCallClosing");
if (call != this.call && call != callTransfer) {
log.debug("NOT the current call.");
return;
}
if (!isCurrentCallOrCallTransfer(call)) return;
if (call != callTransfer && callTransfer != null) {
log.debug("CLOSE PREVIOUS CALL.");
@ -589,16 +485,19 @@ public class SipUserAgent extends CallListenerAdapter {
closeMediaApplication();
if (listener != null) {
listener.onUaCallClosed(this);
}
changeStatus(UA_IDLE);
notifyListenersOfOnCallClosed();
changeStatus(CallState.UA_IDLE);
// Reset local sdp for next call.
initSessionDescriptor();
waitForIncomingCalls();
}
private void notifyListenersOfOnCallClosed() {
for (SipUserAgentListener listener : listeners) {
listener.onCallClosed();
}
}
/**
* Callback function called when arriving a response after a BYE request
@ -607,18 +506,13 @@ public class SipUserAgent extends CallListenerAdapter {
public void onCallClosed(Call call, Message resp) {
log.debug("onCallClosed");
if (call != this.call) {
log.debug("NOT the current call." );
return;
}
if (!isCurrentCall(call)) return;
log.debug("CLOSE/OK.");
if (listener != null) {
listener.onUaCallClosed(this);
}
changeStatus(UA_IDLE);
notifyListenersOfOnCallClosed();
changeStatus(CallState.UA_IDLE);
waitForIncomingCalls();
}
@ -626,40 +520,31 @@ public class SipUserAgent extends CallListenerAdapter {
public void onCallTimeout(Call call) {
log.debug("onCallTimeout");
if (call != this.call) {
log.debug("NOT the current call.");
return;
}
if (!isCurrentCall(call)) return;
log.debug("NOT FOUND/TIMEOUT.");
changeStatus(UA_IDLE);
changeStatus(CallState.UA_IDLE);
if (call == callTransfer) {
int code = 408;
String reason = "Request Timeout";
this.call.notify( code, reason );
this.call.notify(code, reason);
callTransfer = null;
}
if (listener != null) {
listener.onUaCallFailed(this);
}
notifyListenersOnOutgoingCallFailed();
waitForIncomingCalls();
}
// ****************** ExtendedCall callback functions ******************
/**
* Callback function called when arriving a new REFER method (transfer request)
*/
public void onCallTransfer(ExtendedCall call, NameAddress refer_to, NameAddress refered_by, Message refer) {
log.debug("onCallTransfer");
if (call != this.call) {
log.debug("NOT the current call.");
return;
}
if (!isCurrentCall(call)) return;
log.debug("Transfer to " + refer_to.toString() + ".");
@ -674,10 +559,7 @@ public class SipUserAgent extends CallListenerAdapter {
public void onCallTransferAccepted(ExtendedCall call, Message resp) {
log.debug("onCallTransferAccepted");
if (call != this.call) {
log.debug("NOT the current call.");
return;
}
if (!isCurrentCall(call)) return;
log.debug("Transfer accepted.");
}
@ -685,48 +567,45 @@ public class SipUserAgent extends CallListenerAdapter {
/** Callback function called when a call transfer is refused. */
public void onCallTransferRefused(ExtendedCall call, String reason, Message resp) {
log.debug("onCallTransferRefused");
if (call != this.call) {
log.debug("NOT the current call.");
return;
}
log.debug( "onCallTransferRefused", "Transfer refused." );
log.debug("onCallTransferRefused");
if (!isCurrentCall(call)) return;
log.debug("Transfer refused.");
}
/** Callback function called when a call transfer is successfully completed */
public void onCallTransferSuccess(ExtendedCall call, Message notify) {
log.debug( "onCallTransferSuccess", "Init..." );
log.debug("onCallTransferSuccess");
if (!isCurrentCall(call)) return;
if (call != this.call) {
log.debug("onCallTransferSuccess", "NOT the current call.");
return;
}
log.debug( "onCallTransferSuccess", "Transfer successed." );
log.debug("Transfer succeeded.");
call.hangup();
if ( listener != null ) {
listener.onUaCallTrasferred( this );
}
notifyListenersOfOnCallTransferred();
}
private void notifyListenersOfOnCallTransferred() {
for (SipUserAgentListener listener : listeners) {
listener.onCallTrasferred();
}
}
/**
* Callback function called when a call transfer is NOT sucessfully
* completed
* Callback function called when a call transfer is NOT successfully completed
*/
public void onCallTransferFailure(ExtendedCall call, String reason, Message notify) {
log.debug( "onCallTransferFailure", "Init..." );
log.debug("onCallTransferFailure");
if (!isCurrentCall(call)) return;
if ( call != this.call ) {
log.debug( "onCallTransferFailure", "NOT the current call." );
return;
}
log.debug( "onCallTransferFailure", "Transfer failed." );
log.info("Transfer failed.");
}
private boolean isCurrentCallOrCallTransfer(Call call) {
return (call == this.call) || (call != callTransfer);
}
private boolean isCurrentCall(Call call) {
return this.call == call;
}
}

View File

@ -1,33 +1,12 @@
package org.red5.app.sip;
import org.zoolu.sip.address.NameAddress;
/** Listener of SIPUserAgent */
public interface SipUserAgentListener {
/** When a new call is incoming */
public void onUaCallIncoming( SipUserAgent ua, NameAddress callee, NameAddress caller );
/** When an incoming call is cancelled */
public void onUaCallCancelled( SipUserAgent ua );
/** When an ougoing call is remotly ringing */
public void onUaCallRinging( SipUserAgent ua );
/** When an ougoing call has been accepted */
public void onUaCallAccepted( SipUserAgent ua );
/** When a call has been trasferred */
public void onUaCallTrasferred( SipUserAgent ua );
/** When an ougoing call has been refused or timeout */
public void onUaCallFailed( SipUserAgent ua );
/** When a call has been locally or remotely closed */
public void onUaCallClosed(SipUserAgent ua);
/** When a call has media connected */
public void onUaCallConnected(SipUserAgent ua, String talkStreamName, String listenStreamName);
public void onCallConnected(String talkStreamName, String listenStreamName);
public void onNewIncomingCall(String source, String sourceName, String destination, String destinationName);
public void onOutgoingCallRemoteRinging();
public void onOutgoingCallAccepted();
public void onCallTrasferred();
public void onIncomingCallCancelled();
public void onOutgoingCallFailed();
public void onCallClosed();
}