/**
* $RCSfile: ,v $
* $Revision: $
* $Date: $
*
* Copyright (C) 2004-2011 Jive Software. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sipmack.sip;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TooManyListenersException;
import javax.sdp.SessionDescription;
import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.DialogTerminatedEvent;
import javax.sip.IOExceptionEvent;
import javax.sip.InvalidArgumentException;
import javax.sip.ListeningPoint;
import javax.sip.ObjectInUseException;
import javax.sip.PeerUnavailableException;
import javax.sip.RequestEvent;
import javax.sip.ResponseEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.SipFactory;
import javax.sip.SipListener;
import javax.sip.SipProvider;
import javax.sip.SipStack;
import javax.sip.TimeoutEvent;
import javax.sip.Transaction;
import javax.sip.TransactionAlreadyExistsException;
import javax.sip.TransactionTerminatedEvent;
import javax.sip.TransactionUnavailableException;
import javax.sip.TransportNotSupportedException;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.ContactHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.HeaderFactory;
import javax.sip.header.MaxForwardsHeader;
import javax.sip.header.ToHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.Message;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import net.java.sipmack.common.Log;
import net.java.sipmack.sip.event.CallEvent;
import net.java.sipmack.sip.event.CallRejectedEvent;
import net.java.sipmack.sip.event.CommunicationsErrorEvent;
import net.java.sipmack.sip.event.CommunicationsListener;
import net.java.sipmack.sip.event.MessageEvent;
import net.java.sipmack.sip.event.RegistrationEvent;
import net.java.sipmack.sip.event.UnknownMessageEvent;
import net.java.sipmack.sip.security.Credentials;
import net.java.sipmack.sip.security.SecurityAuthority;
import net.java.sipmack.sip.security.SipSecurityManager;
import net.java.sipmack.sip.simple.MessageProcessing;
/**
* Title: SIPark
* Description: JAIN-SIP Audio/Video phone application
*
* @author Thiago Rocha Camargo (thiago@jivesoftware.com) The
* <code>SipManager</code> class that Manage SIP Stack
* @version 1.0, 20/07/2006
*/
public class SipManager implements SipListener {
/**
* Specifies the number of retries that should be attempted when deleting a
* sipProvider
*/
protected static final int RETRY_OBJECT_DELETES = 10;
protected static final long REGISTER_TIMEOUT = 20000;
/**
* Specifies the time to wait before retrying delete of a sipProvider.
*/
protected static final long RETRY_OBJECT_DELETES_AFTER = 500;
protected static final String DEFAULT_TRANSPORT = "udp";
// jain-sip objects - package accessibility as they should be
// available for XxxProcessing classes
/**
* The SipFactory instance used to create the SipStack and the Address
* Message and Header Factories.
*/
public SipFactory sipFactory;
/**
* The AddressFactory used to create URLs ans Address objects.
*/
public AddressFactory addressFactory;
/**
* The HeaderFactory used to create SIP message headers.
*/
public HeaderFactory headerFactory;
/**
* The Message Factory used to create SIP messages.
*/
public MessageFactory messageFactory;
private int loginfailed = 0;
/**
* The sipStack instance that handles SIP communications.
*/
SipStack sipStack;
/**
* The busy state of this SIP Manager
*/
public boolean isBusy = false;
/**
* The default (and currently the only) SIP listening point of the
* application.
*/
ListeningPoint listeningPoint;
/**
* The JAIN SIP SipProvider instance.
*/
public SipProvider sipProvider;
/**
* An instance used to provide user credentials
*/
private SecurityAuthority securityAuthority = null;
/**
* Used for the contact header to provide firewall support.
*/
private InetSocketAddress publicIpAddress = null;
// properties
protected String sipStackPath = "gov.nist";
/**
*/
protected String currentlyUsedURI = null;
protected String username = null;
protected String displayName = null;
protected String transport = null;
protected String registrarAddress = null;
protected int localPort = -1;
protected int registrarPort = -1;
protected int registrationsExpiration = -1;
protected String registrarTransport = null;
private int registerRetries = 0;
// mandatory stack properties
protected String stackAddress = null;
protected String stackName = "SIPark";
// Prebuilt Message headers
/**
*/
protected FromHeader fromHeader = null;
/**
*/
protected ContactHeader contactHeader = null;
protected ArrayList<ViaHeader> viaHeaders = null;
protected static final int MAX_FORWARDS = 70;
/**
*/
protected MaxForwardsHeader maxForwardsHeader = null;
protected long registrationTransaction = -1;
protected List<CommunicationsListener> listeners = new ArrayList<CommunicationsListener>();
// Processing managers
/**
* The instance that handles all registration associated activity such as
* registering, unregistering and keeping track of expirations.
*/
RegisterProcessing registerProcessing = null;
/**
* The instance that handles all call associated activity such as
* establishing, managing, and terminating calls.
*/
CallProcessing callProcessing = null;
/**
* The instance that handles incoming/outgoing MESSAGE requests.
*/
public MessageProcessing messageProcessing = null;
/**
* The instance that handles incoming/outgoing REFER requests.
*/
TransferProcessing transferProcessing = null;
/**
* Authentication manager.
*/
public SipSecurityManager sipSecurityManager = null;
/**
*/
protected boolean isStarted = false;
/**
* Constructor. It only creates a SipManager instance without initializing
* the stack itself.
*/
public SipManager() {
registerProcessing = new RegisterProcessing(this);
callProcessing = new CallProcessing(this);
messageProcessing = new MessageProcessing(this);
transferProcessing = new TransferProcessing(this, callProcessing);
sipSecurityManager = new SipSecurityManager();
registerRetries = 0;
}
/**
* Creates and initializes JAIN SIP objects (factories, stack, listening
* point and provider). Once this method is called the application is ready
* to handle (incoming and outgoing) sip messages.
*
* @throws CommunicationsException if an axception should occur during the initialization
* process
*/
public void start() throws CommunicationsException {
try {
initProperties();
SIPConfig.setSystemProperties();
this.sipFactory = SipFactory.getInstance();
sipFactory.setPathName(sipStackPath);
try {
addressFactory = sipFactory.createAddressFactory();
headerFactory = sipFactory.createHeaderFactory();
messageFactory = sipFactory.createMessageFactory();
}
catch (PeerUnavailableException ex) {
Log.error("start", ex);
throw new CommunicationsException(
"Could not create factories!", ex);
}
try {
sipStack = sipFactory.createSipStack(System.getProperties());
((SipCommRouter) sipStack.getRouter())
.setOutboundProxy(SIPConfig.getOutboundProxy());
}
catch (PeerUnavailableException ex) {
Log.error("start", ex);
throw new CommunicationsException(
"Cannot connect!\n"
+ "Please verify your connection.", ex);
}
try {
boolean successfullyBound = false;
int tries = 0;
while (!successfullyBound) {
try {
// try and capture the firewall mapping for this address
// just befre it gets occuppied by the stack
publicIpAddress = NetworkAddressManager
.getPublicAddressFor(localPort);
listeningPoint = sipStack.createListeningPoint(publicIpAddress.getAddress().getHostAddress(),
localPort, transport);
}
catch (InvalidArgumentException ex) {
Log.error("start", ex);
// choose another port between 1024 and 65000
if (tries > 3) {
if (!NetworkAddressManager.nextIndex()) throw new CommunicationsException(
"Cannot connect!\n"
+ "Please verify your connection.", ex);
tries = 0;
}
tries++;
localPort = (int) ((65000 - 1024) * Math.random()) + 1024;
try {
Thread.sleep(1000);
}
catch (Exception e) {
}
continue;
}
successfullyBound = true;
}
}
catch (TransportNotSupportedException ex) {
throw new CommunicationsException(
"Transport "
+ transport
+ " is not suppported by the stack!\n Try specifying another"
+ " transport in Mais property files.\n", ex);
}
try {
sipProvider = sipStack.createSipProvider(listeningPoint);
}
catch (ObjectInUseException ex) {
Log.error("start", ex);
throw new CommunicationsException(
"Could not create factories!\n", ex);
}
try {
sipProvider.addSipListener(this);
}
catch (TooManyListenersException exc) {
throw new CommunicationsException(
"Could not register SipManager as a sip listener!", exc);
}
// we should have a security authority to be able to handle
// authentication
if (sipSecurityManager.getSecurityAuthority() == null) {
throw new CommunicationsException(
"No SecurityAuthority was provided to SipManager!");
}
// we should have also have a SubsciptionAuthority to be able to
// handle
// incoming Subscription requests.
if (sipSecurityManager.getSecurityAuthority() == null) {
throw new CommunicationsException(
"No SubscriptionAuthority was provided to SipManager!");
}
sipSecurityManager.setHeaderFactory(headerFactory);
sipSecurityManager.setTransactionCreator(sipProvider);
sipSecurityManager.setSipManCallback(this);
// Make sure prebuilt headers are nulled so that they get reinited
// if this is a restart
contactHeader = null;
fromHeader = null;
viaHeaders = null;
maxForwardsHeader = null;
isStarted = true;
}
finally {
}
}
/**
* Unregisters listening points, deletes sip providers, and generally
* prepares the stack for a re-start(). This method is meant to be used when
* properties are changed and should be reread by the stack.
*
* @throws CommunicationsException
*/
synchronized public void stop() throws CommunicationsException {
try {
if (registerProcessing != null)
registerProcessing.cancelSchedules();
if (sipStack == null)
return;
sleep(500);
sipProvider.removeSipListener(this);
// Delete SipProvider
int tries = 0;
for (tries = 0; tries < RETRY_OBJECT_DELETES; tries++) {
try {
sipStack.deleteSipProvider(sipProvider);
}
catch (ObjectInUseException ex) {
sleep(RETRY_OBJECT_DELETES_AFTER);
continue;
}
break;
}
if (sipStack == null)
return;
if (tries >= RETRY_OBJECT_DELETES)
throw new CommunicationsException(
"Failed to delete the sipProvider!");
if (sipStack == null)
return;
// Delete RI ListeningPoint
for (tries = 0; tries < RETRY_OBJECT_DELETES; tries++) {
try {
sipStack.deleteListeningPoint(listeningPoint);
}
catch (ObjectInUseException ex) {
// Log.debug("Retrying delete of riListeningPoint!");
sleep(RETRY_OBJECT_DELETES_AFTER);
continue;
}
break;
}
if (sipStack != null) {
for (Iterator<?> it = sipStack.getSipProviders(); it.hasNext();) {
SipProvider element = (SipProvider) it.next();
try {
sipStack.deleteSipProvider(element);
}
catch (Exception e) {
}
}
}
if (tries >= RETRY_OBJECT_DELETES)
throw new CommunicationsException(
"Failed to delete a listeningPoint!");
listeningPoint = null;
addressFactory = null;
messageFactory = null;
headerFactory = null;
sipStack = null;
registrarAddress = null;
securityAuthority = null;
viaHeaders = null;
contactHeader = null;
fromHeader = null;
NetworkAddressManager.shutDown();
}
finally {
isStarted = false;
}
}
/**
* Waits during _no_less_ than sleepFor milliseconds. Had to implement it on
* top of Thread.sleep() to guarantee minimum sleep time.
*
* @param sleepFor the number of miliseconds to wait
*/
protected static void sleep(long sleepFor) {
long startTime = System.currentTimeMillis();
long haveBeenSleeping = 0;
while (haveBeenSleeping < sleepFor) {
try {
Thread.sleep(sleepFor - haveBeenSleeping);
}
catch (InterruptedException ex) {
// we-ll have to wait again!
}
haveBeenSleeping = (System.currentTimeMillis() - startTime);
}
}
/**
* @param uri the currentlyUsedURI to set.
*/
public void setCurrentlyUsedURI(String uri) {
this.currentlyUsedURI = uri;
}
/**
* Get the currently used SIP username
*/
public String getCurrentUsername() {
return this.username;
}
/**
* Causes the RegisterProcessing object to send a registration request to
* the registrar defined in net.java.mais.sip.REGISTRAR_ADDRESS and to
* register with the address defined in the net.java.mais.sip.PUBLIC_ADDRESS
* property
*
* @throws CommunicationsException if an exception is thrown by the underlying stack. The
* exception that caused this CommunicationsException may be
* extracted with CommunicationsException.getCause()
*/
public void register() throws CommunicationsException {
register(currentlyUsedURI);
}
/**
* Registers using the specified public address.
*
* @param sipServerAddress the address of the server.
* @throw CommunicationsException
*/
public void register(String sipServerAddress) throws CommunicationsException {
try {
if (sipServerAddress == null || sipServerAddress.trim().length() == 0) {
Log.debug("PUBLIC NOT FOUND!");
throw new CommunicationsException("Public address NOT FOUND");
}
// Handle default domain name (i.e. transform 1234 -> 1234@sip.com
String defaultDomainName = SIPConfig.getDefaultDomain();
if (sipServerAddress.toLowerCase().indexOf("sipphone.com") != -1
|| (defaultDomainName != null && defaultDomainName
.indexOf("sipphone.com") != -1)) {
StringBuffer buff = new StringBuffer(sipServerAddress);
int nameEnd = sipServerAddress.indexOf('@');
nameEnd = nameEnd == -1 ? Integer.MAX_VALUE : nameEnd;
nameEnd = Math.min(nameEnd, buff.length()) - 1;
int nameStart = sipServerAddress.indexOf("sip:");
nameStart = nameStart == -1 ? 0 : nameStart + "sip:".length();
for (int i = nameEnd; i >= nameStart; i--)
if (!Character.isLetter(buff.charAt(i))
&& !Character.isDigit(buff.charAt(i)))
buff.deleteCharAt(i);
sipServerAddress = buff.toString();
}
// if user didn't provide a domain name in the URL and someone
// has defined the DEFAULT_DOMAIN_NAME property - let's fill in the
// blank.
if (defaultDomainName != null && sipServerAddress.indexOf('@') == -1) {
sipServerAddress = sipServerAddress + "@" + defaultDomainName;
}
if (!sipServerAddress.trim().toLowerCase().startsWith("sip:")) {
sipServerAddress = "sip:" + sipServerAddress;
}
this.currentlyUsedURI = sipServerAddress;
registerProcessing.register(registrarAddress, registrarPort, registrarTransport, registrationsExpiration);
}
catch (Exception e) {
fireRegistrationFailed(registrarAddress, RegistrationEvent.Type.TimeOut);
Log.error("register", e);
}
}
public void startRegisterProcess(String userName, String authUserName,
String password) throws CommunicationsException {
try {
// TODO : Anpassen
//SIPTransaction.setRegisterTimeout(10);
//registerRetries = 0;
checkIfStarted();
// Obtain initial credentials
Credentials defaultCredentials = new Credentials();
this.username = userName;
defaultCredentials.setUserName(userName);
defaultCredentials.setPassword(password.toCharArray());
defaultCredentials
.setAuthUserName(authUserName != null ? authUserName
: userName);
String realm = SIPConfig.getAuthenticationRealm();
realm = realm == null ? "" : realm;
Credentials initialCredentials = securityAuthority
.obtainCredentials(realm, defaultCredentials);
SIPConfig.setUserName(initialCredentials.getUserName());
SIPConfig.setAuthUserName(initialCredentials.getAuthUserName());
register(initialCredentials.getUserName());
// at this point a simple register request has been sent and the
// global
// from header in SipManager has been set to a valid value by the
// RegisterProcesing
// class. Use it to extract the valid user name that needs to be
// cached by
// the security manager together with the user provided password.
//initialCredentials.setUserName(((SipURI) getFromHeader().getAddress().getURI()).getUser());
cacheCredentials(realm, initialCredentials);
}
catch (Exception ee) {
Log.error("startRegisterProcess", ee);
}
}
/**
* Causes the PresenceAgent object to notify all subscribers of our brand
* new offline status and the RegisterProcessing object to send a
* registration request with a 0 "expires" interval to the registrar defined
* in net.java.mais.sip.REGISTRAR_ADDRESS.
*
* @throws CommunicationsException if an exception is thrown by the underlying stack. The
* exception that caused this CommunicationsException may be
* extracted with CommunicationsException.getCause()
*/
public void unregister() throws CommunicationsException {
try {
checkIfStarted();
if (!isRegistered()) {
return;
}
registerProcessing.unregister();
fireUnregistered(registrarAddress == null ? "" : registrarAddress);
}
catch (Exception e) {
Log.error("unregister", e);
}
}
private boolean registrationFailed(RegistrationEvent.Type type) {
try {
//if (RegistrationEvent.Type.TimeOut.equals(type))
if (registerRetries++ < 2) {
stop();
while (isStarted()) ;
start();
while (!isStarted()) ;
register();
return false;
} else {
if (NetworkAddressManager.nextIndex()) {
stop();
start();
registerRetries = 0;
register();
return false;
}
}
}
catch (Exception e) {
Log.error("unregister", e);
}
return true;
}
/**
* Queries the RegisterProcessing object whether the application is
* registered with a registrar.
*
* @return true if the application is registered with a registrar.
*/
public boolean isRegistered() {
return (registerProcessing != null && registerProcessing.isRegistered());
}
/**
* Determines whether the SipManager was started.
*
* @return true if the SipManager was started.
*/
public boolean isStarted() {
return isStarted;
}
// ============================ COMMUNICATION FUNCTIONALITIES =========================
/**
* Causes the CallProcessing object to send an INVITE request to the URI
* specified by <code>callee</code> setting sdpContent as message body.
* The method generates a Call object that will represent the resulting call
* and will be used for later references to the same call.
*
* @param callee the URI to send the INVITE to.
* @param sdpContent the sdp session offer.
* @return the Call object that will represent the call resulting from
* invoking this method.
* @throws CommunicationsException if an exception occurs while sending and parsing.
*/
public Call establishCall(String callee, String sdpContent)
throws CommunicationsException {
checkIfStarted();
if (isBusy()) return null;
return callProcessing.invite(callee, sdpContent);
} // CALL
// ------------------ hang up on
/**
* Causes the CallProcessing object to send a terminating request (CANCEL,
* BUSY_HERE or BYE) and thus terminate that call with id
* <code>callID</code>.
*
* @param callID the id of the call to terminate.
* @throws CommunicationsException if an exception occurs while invoking this method.
*/
public void endCall(int callID) throws CommunicationsException {
fireCallEnded(callProcessing.callDispatcher.getCall(callID));
checkIfStarted();
callProcessing.endCall(callID);
}
public void sendDTMF(int callID, String digit)
throws CommunicationsException {
callProcessing.sendDTMF(callID, digit);
}
public void hold(int callID, SessionDescription sdp, boolean mic, boolean cam)
throws CommunicationsException {
callProcessing.hold(callID, sdp.toString());
callProcessing.callDispatcher.getCall(callID).onHoldMic(mic);
callProcessing.callDispatcher.getCall(callID).onHoldCam(cam);
}
public void transfer(int callID, String callee) {
try {
transferProcessing.transfer(callID, callee);
}
catch (CommunicationsException e) {
e.printStackTrace();
}
}
/**
* Calls endCall for all currently active calls.
*
* @throws CommunicationsException if an exception occurs while
*/
public void endAllCalls() throws CommunicationsException {
try {
checkIfStarted();
if (!isRegistered()) {
return;
}
if (callProcessing == null) {
return;
}
Object[] keys = callProcessing.getCallDispatcher().getAllCalls();
for (int i = 0; i < keys.length; i++) {
endCall(((Integer) keys[i]).intValue());
}
}
finally {
setBusy(false);
}
}
/**
* Causes CallProcessing to send a 200 OK response, with the specified sdp
* description, to the specified call's remote party.
*
* @param callID the id of the call that is to be answered.
* @param sdpContent this party's media description (as defined by SDP).
* @throws CommunicationsException if an axeption occurs while invoking this method.
*/
public void answerCall(int callID, String sdpContent)
throws CommunicationsException {
checkIfStarted();
callProcessing.sayOK(callID, sdpContent);
} // answer to
/**
* Sends a NOT_IMPLEMENTED response through the specified transaction.
*
* @param serverTransaction the transaction to send the response through.
* @param request the request that is being answered.
*/
void sendNotImplemented(ServerTransaction serverTransaction, Request request) {
Response notImplemented = null;
try {
notImplemented = messageFactory.createResponse(
Response.NOT_IMPLEMENTED, request);
attachToTag(notImplemented, serverTransaction.getDialog());
}
catch (ParseException ex) {
fireCommunicationsError(new CommunicationsException(
"Failed to create a NOT_IMPLEMENTED response to a "
+ request.getMethod() + " request!", ex));
return;
}
try {
serverTransaction.sendResponse(notImplemented);
}
catch (SipException ex) {
fireCommunicationsError(new CommunicationsException(
"Failed to create a NOT_IMPLEMENTED response to a "
+ request.getMethod() + " request!", ex));
}
catch (InvalidArgumentException e) {
fireCommunicationsError(new CommunicationsException(
"Failed to create a NOT_IMPLEMENTED response to a "
+ request.getMethod() + " request!", e));
}
}
public void processIOException(IOExceptionEvent ioExceptionEvent) {
}
public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
}
public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
}
// ============================= Utility Methods ==================================
/**
* Initialises SipManager's fromHeader field in accordance with
* net.java.mais.sip.PUBLIC_ADDRESS net.java.mais.sip.DISPLAY_NAME
* net.java.mais.sip.TRANSPORT net.java.mais.sip.PREFERRED_LOCAL_PORT and
* returns a reference to it.
*
* @return a reference to SipManager's fromHeader field.
* @throws CommunicationsException if a ParseException occurs while initially composing the
* FromHeader.
*/
public FromHeader getFromHeader() throws CommunicationsException {
return this.getFromHeader(false);
}
public FromHeader getFromHeader(boolean isNew)
throws CommunicationsException {
if (fromHeader != null && !isNew) {
return fromHeader;
}
try {
SipURI fromURI = (SipURI) addressFactory
.createURI(currentlyUsedURI);
fromURI.setTransportParam(listeningPoint.getTransport());
fromURI.setPort(listeningPoint.getPort());
Address fromAddress = addressFactory.createAddress(fromURI);
if (displayName != null && displayName.trim().length() > 0) {
fromAddress.setDisplayName(displayName);
} else {
fromAddress
.setDisplayName(Credentials.getUserDisplay());
}
fromHeader = headerFactory.createFromHeader(fromAddress,
Integer.toString(hashCode()));
}
catch (ParseException ex) {
throw new CommunicationsException(
"A ParseException occurred while creating From Header!",
ex);
}
return fromHeader;
}
/**
* Same as calling getContactHeader(true)
*
* @return the result of getContactHeader(true)
* @throws CommunicationsException if an exception is thrown while calling
* getContactHeader(false)
* @uml.property name="contactHeader"
*/
public ContactHeader getContactHeader() throws CommunicationsException {
return getContactHeader(true);
}
/**
* Same as calling getContactHeader(true).
*
* @return the result of calling getContactHeader(true).
* @throws CommunicationsException if an exception occurs while executing
* getContactHeader(true).
*/
ContactHeader getRegistrationContactHeader() throws CommunicationsException {
return getContactHeader(true);
}
/**
* Initialises SipManager's contactHeader field in accordance with
* javax.sip.IP_ADDRESS net.java.mais.sip.DISPLAY_NAME
* net.java.mais.sip.TRANSPORT net.java.mais.sip.PREFERRED_LOCAL_PORT and
* returns a reference to it.
*
* @param useLocalHostAddress specifies whether the SipURI in the contact header should
* contain the value of javax.sip.IP_ADDRESS (true) or that of
* net.java.mais.sip.PUBLIC_ADDRESS (false).
* @return a reference to SipManager's contactHeader field.
* @throws CommunicationsException if a ParseException occurs while initially composing the
* FromHeader.
*/
public ContactHeader getContactHeader(boolean useLocalHostAddress)
throws CommunicationsException {
if (contactHeader != null) {
return contactHeader;
}
try {
SipURI contactURI;
if (useLocalHostAddress) {
contactURI = (SipURI) addressFactory.createSipURI(null,
Credentials.getUserDisplay()
+ "@"
+ publicIpAddress.getAddress()
.getHostAddress());
} else {
contactURI = (SipURI) addressFactory
.createURI(currentlyUsedURI);
}
// Forces NAT Traversal
// contactURI = (SipURI)
// addressFactory.createSipURI(null,Credentials.getUser()+
// "@" + publicIpAddress.getAddress().getHostAddress());
// contactURI.setTransportParam(listeningPoint.getTransport());
contactURI.setPort(publicIpAddress.getPort());
Address contactAddress = addressFactory
.createAddress(contactURI);
if (displayName != null && displayName.trim().length() > 0) {
contactAddress.setDisplayName(displayName);
}
contactHeader = headerFactory
.createContactHeader(contactAddress);
}
catch (ParseException ex) {
throw new CommunicationsException(
"A ParseException occurred while creating From Header!",
ex);
}
return contactHeader;
}
/**
* Initializes (if null) and returns an ArrayList with a single ViaHeader
* containing localhost's address. This ArrayList may be used when sending
* requests.
*
* @return ViaHeader-s list to be used when sending requests.
* @throws CommunicationsException if a ParseException is to occur while initializing the array
* list.
*/
public ArrayList<ViaHeader> getLocalViaHeaders() throws CommunicationsException {
ListeningPoint lp = sipProvider.getListeningPoints()[0];
viaHeaders = new ArrayList<ViaHeader>();
try {
ViaHeader viaHeader = headerFactory.createViaHeader(SIPConfig
.getIPAddress(), lp.getPort(), lp.getTransport(), null);
viaHeader.setParameter("rport", null);
viaHeaders.add(viaHeader);
return viaHeaders;
}
catch (ParseException ex) {
throw new CommunicationsException(
"A ParseException occurred while creating Via Headers!");
}
catch (InvalidArgumentException ex) {
throw new CommunicationsException(
"Unable to create a via header for port "
+ lp.getPort(), ex);
}
}
/**
* Initializes and returns SipManager's maxForwardsHeader field using the
* value specified by MAX_FORWARDS.
*
* @return an instance of a MaxForwardsHeader that can be used when sending
* requests
* @throws CommunicationsException if MAX_FORWARDS has an invalid value.
*/
public MaxForwardsHeader getMaxForwardsHeader()
throws CommunicationsException {
if (maxForwardsHeader != null) {
return maxForwardsHeader;
}
try {
maxForwardsHeader = headerFactory
.createMaxForwardsHeader(MAX_FORWARDS);
return maxForwardsHeader;
}
catch (InvalidArgumentException ex) {
throw new CommunicationsException(
"A problem occurred while creating MaxForwardsHeader",
ex);
}
}
/**
* Returns the user used to create the From Header URI.
*
* @return the user used to create the From Header URI.
*/
public String getLocalUser() {
try {
return ((SipURI) getFromHeader().getAddress().getURI()).getUser();
}
catch (CommunicationsException ex) {
return "";
}
}
/**
* Generates a ToTag (the containingDialog's hashCode())and attaches it to
* response's ToHeader.
*
* @param response the response that is to get the ToTag.
* @param containingDialog the Dialog instance that is to extract a unique Tag value
* (containingDialog.hashCode())
*/
public void attachToTag(Response response, Dialog containingDialog) {
ToHeader to = (ToHeader) response.getHeader(ToHeader.NAME);
if (to == null) {
fireCommunicationsError(new CommunicationsException(
"No TO header found in, attaching a to tag is therefore impossible"));
}
try {
if (to.getTag() == null || to.getTag().trim().length() == 0) {
// the containing dialog may be null (e.g. when called by
// sendNotImplemented). Attach sth else in that case.
// Bug Report - Joe Provino - SUN Microsystems
int toTag = containingDialog != null ? containingDialog
.hashCode() : (int) System.currentTimeMillis();
to.setTag(Integer.toString(toTag));
}
}
catch (ParseException ex) {
fireCommunicationsError(new CommunicationsException(
"Failed to attach a TO tag to an outgoing response"));
}
}
// ================================ PROPERTIES ================================
protected void initProperties() {
try {
// ------------------ stack properties --------------
// network address management is handled by
// common.NetworkAddressManager
// stackAddress = Utils.getProperty("javax.sip.IP_ADDRESS");
// if (stackAddress == null) {
stackAddress = getLocalHostAddress();
// Add the host address to the properties that will pass the stack
SIPConfig.setIPAddress(stackAddress);
SIPConfig.setSystemProperties();
// ensure IPv6 address compliance
if (stackAddress.indexOf(':') != stackAddress.lastIndexOf(':')
&& stackAddress.charAt(0) != '[') {
stackAddress = '[' + stackAddress.trim() + ']';
}
stackName = SIPConfig.getStackName();
if (stackName == null) {
stackName = "SIPark@" + Integer.toString(hashCode());
// Add the stack name to the properties that will pass the stack
}
// String retransmissionFilter = SIPConfig.getRetransmissionFilter();
// ------------ application properties --------------
//currentlyUsedURI = SIPConfig.getPublicAddress();
if (currentlyUsedURI == null) {
currentlyUsedURI = SIPConfig.getUserName() + "@" + stackAddress;
}
if (!currentlyUsedURI.trim().toLowerCase().startsWith("sip:")) {
currentlyUsedURI = "sip:" + currentlyUsedURI.trim();
}
// at this point we are sure we have a sip: prefix in the uri
// we construct our pres: uri by replacing that prefix.
// String presenceUri = "pres"
// + currentlyUsedURI.substring(currentlyUsedURI.indexOf(':'));
registrarAddress = SIPConfig.getRegistrarAddress();
try {
registrarPort = SIPConfig.getRegistrarPort();
}
catch (NumberFormatException ex) {
registrarPort = 5060;
}
registrarTransport = SIPConfig.getRegistrarTransport();
if (registrarTransport == null) {
registrarTransport = DEFAULT_TRANSPORT;
}
try {
registrationsExpiration = SIPConfig.getRegistrationExpiration();
}
catch (NumberFormatException ex) {
registrationsExpiration = 3600;
}
sipStackPath = SIPConfig.getStackPath();
if (sipStackPath == null) {
sipStackPath = "gov.nist";
}
// String routerPath = SIPConfig.getRouterPath();
transport = SIPConfig.getTransport();
if (transport.equals("")) {
transport = DEFAULT_TRANSPORT;
}
try {
localPort = SIPConfig.getLocalPort();
}
catch (NumberFormatException exc) {
localPort = 5060;
}
displayName = SIPConfig.getDisplayName();
}
catch (Exception e) {
Log.error("initProperties", e);
}
}
// ============================ SECURITY ================================
/**
* Sets the SecurityAuthority instance that should be consulted later on for
* user credentials.
*
* @param authority the SecurityAuthority instance that should be consulted later
* on for user credentials.
*/
public void setSecurityAuthority(SecurityAuthority authority) {
// keep a copy
this.securityAuthority = authority;
sipSecurityManager.setSecurityAuthority(authority);
}
/**
* Adds the specified credentials to the security manager's credentials
* cache so that they get tried next time they're needed.
*
* @param realm the realm these credentials should apply for.
* @param credentials a set of credentials (username and pass)
*/
public void cacheCredentials(String realm, Credentials credentials) {
sipSecurityManager.cacheCredentials(realm, credentials);
}
// ============================ EVENT DISPATHING ============================
/**
* Adds a CommunicationsListener to SipManager.
*
* @param listener The CommunicationsListener to be added.
*/
public void addCommunicationsListener(CommunicationsListener listener) {
try {
listeners.add(listener);
}
catch (Exception e) {
Log.error("addCommunicationsListener", e);
}
}
// ------------ call received dispatch
void fireCallReceived(Call call) {
try {
CallEvent evt = new CallEvent(call);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i)).callReceived(evt);
}
}
catch (Exception e) {
Log.error("fireCallReceived", e);
}
} // call received
void fireCallEnded(Call call) {
try {
CallEvent evt = new CallEvent(call);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i)).callEnded(evt);
}
}
catch (Exception e) {
Log.error("fireCallEnded", e);
}
} // call received
// ------------ call received dispatch
void fireMessageReceived(Request message) {
MessageEvent evt = new MessageEvent(message);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i))
.messageReceived(evt);
}
} // call received
// ------------ registerred
void fireRegistered(String address) {
// TODO : Anpassen
//SIPTransaction.setRegisterTimeout(64);
try {
registerProcessing.subscribe(registrarAddress, registrarPort, registrarTransport);
} catch (CommunicationsException e) {
Log.error(e);
}
RegistrationEvent evt = new RegistrationEvent(address);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i)).registered(evt);
}
} // call received
// ------------ registering
void fireRegistering(String address) {
RegistrationEvent evt = new RegistrationEvent(address);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i)).registering(evt);
}
} // call received
// ------------ unregistered
public void fireUnregistered(String address) {
RegistrationEvent evt = new RegistrationEvent(address);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i)).unregistered(evt);
}
}
void fireRegistrationFailed(String address, RegistrationEvent.Type type) {
if (registrationFailed(type)) {
RegistrationEvent evt = new RegistrationEvent(address, type);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i)).registrationFailed(evt);
}
}
}
void fireUnregistering(String address) {
RegistrationEvent evt = new RegistrationEvent(address);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i)).unregistering(evt);
}
}
// ---------------- received unknown message
void fireUnknownMessageReceived(Message message) {
UnknownMessageEvent evt = new UnknownMessageEvent(message);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i))
.receivedUnknownMessage(evt);
}
}
// ---------------- rejected a call
public void fireCallRejectedLocally(String reason, Message invite, Call call) {
CallRejectedEvent evt = new CallRejectedEvent(reason, invite, call);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i))
.callRejectedLocally(evt);
}
}
void fireCallRejectedRemotely(String reason, Message invite, Call call) {
CallRejectedEvent evt = new CallRejectedEvent(reason, invite, call);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i))
.callRejectedRemotely(evt);
}
}
// call rejected
// ---------------- error occurred
public void fireCommunicationsError(Throwable throwable) {
try {
CommunicationsErrorEvent evt = new CommunicationsErrorEvent(
throwable);
for (int i = listeners.size() - 1; i >= 0; i--) {
((CommunicationsListener) listeners.get(i)).communicationsErrorOccurred(evt);
}
}
catch (Throwable e) {
Log.error("fireCommunicationsError", e);
}
} // error occurred
// ============================= SIP LISTENER METHODS ==============================
public void processRequest(RequestEvent requestReceivedEvent) {
Log.debug(requestReceivedEvent.getRequest().toString());
ServerTransaction serverTransaction = requestReceivedEvent
.getServerTransaction();
Request request = requestReceivedEvent.getRequest();
if (serverTransaction == null) {
try {
serverTransaction = sipProvider
.getNewServerTransaction(request);
}
catch (TransactionAlreadyExistsException ex) {
return;
}
catch (TransactionUnavailableException ex) {
return;
}
}
Dialog dialog = serverTransaction.getDialog();
if (request.getMethod().equals(Request.NOTIFY)) {
Response ok = null;
try {
ok = messageFactory.createResponse(Response.OK,
request);
}
catch (ParseException ex) {
ex.printStackTrace();
}
ContactHeader contactHeader = null;
try {
contactHeader = getContactHeader();
ok.addHeader(contactHeader);
attachToTag(ok, dialog);
System.err.println(ok.toString());
serverTransaction.sendResponse(ok);
} catch (CommunicationsException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (SipException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
fireMessageReceived(request);
return;
}
//TODO REMOVE
@SuppressWarnings("unused")
Request requestClone = (Request) request.clone();
// INVITE
if (request.getMethod().equals(Request.INVITE)) {
if (serverTransaction.getDialog().getState() == null) {
callProcessing.processInvite(serverTransaction, request);
} else {
callProcessing.processReInvite(serverTransaction, request);
}
}
// ACK
else if (request.getMethod().equals(Request.ACK)) {
if (serverTransaction != null
&& serverTransaction.getDialog().getFirstTransaction()
.getRequest().getMethod()
.equals(Request.INVITE)) {
callProcessing.processAck(serverTransaction, request);
} else {
// just ignore
}
}
// BYE
else if (request.getMethod().equals(Request.BYE)) {
if (dialog.getFirstTransaction().getRequest().getMethod()
.equals(Request.INVITE) || dialog.getFirstTransaction().getRequest().getMethod()
.equals(Request.REFER)) {
callProcessing.processBye(serverTransaction, request);
}
}
// CANCEL
else if (request.getMethod().equals(Request.CANCEL)) {
if (dialog.getFirstTransaction().getRequest().getMethod()
.equals(Request.INVITE)) {
callProcessing.processCancel(serverTransaction, request);
} else {
sendNotImplemented(serverTransaction, request);
fireUnknownMessageReceived(requestReceivedEvent
.getRequest());
}
}
// REFER
else if (request.getMethod().equals(Request.REFER)) {
transferProcessing.processRefer(serverTransaction, request);
} else if (request.getMethod().equals(Request.INFO)) {
/** @todo add proper request handling */
fireMessageReceived(request);
} else if (request.getMethod().equals(Request.MESSAGE)) {
messageProcessing.processMessageRequest(serverTransaction,
request);
fireMessageReceived(request);
} else if (request.getMethod().equals(Request.OPTIONS)) {
/** @todo add proper request handling */
sendNotImplemented(serverTransaction, request);
fireUnknownMessageReceived(requestReceivedEvent.getRequest());
} else if (request.getMethod().equals(Request.PRACK)) {
/** @todo add proper request handling */
sendNotImplemented(serverTransaction, request);
fireUnknownMessageReceived(requestReceivedEvent.getRequest());
} else if (request.getMethod().equals(Request.REGISTER)) {
/** @todo add proper request handling */
sendNotImplemented(serverTransaction, request);
fireUnknownMessageReceived(requestReceivedEvent.getRequest());
} else if (request.getMethod().equals(Request.SUBSCRIBE)) {
} else if (request.getMethod().equals(Request.UPDATE)) {
/** @todo add proper request handling */
sendNotImplemented(serverTransaction, request);
fireUnknownMessageReceived(requestReceivedEvent.getRequest());
} else if (request.getMethod().equals(Request.INFO)) {
sendNotImplemented(serverTransaction, request);
fireUnknownMessageReceived(requestReceivedEvent.getRequest());
} else {
// We couldn't recognise the message
sendNotImplemented(serverTransaction, request);
fireUnknownMessageReceived(requestReceivedEvent.getRequest());
}
}
public void processTimeout(TimeoutEvent transactionTimeOutEvent) {
Transaction transaction;
if (transactionTimeOutEvent.isServerTransaction()) {
transaction = transactionTimeOutEvent.getServerTransaction();
} else {
transaction = transactionTimeOutEvent.getClientTransaction();
}
Request request = transaction.getRequest();
if (request.getMethod().equals(Request.REGISTER)) {
registerProcessing.processTimeout(transaction, request);
} else if (request.getMethod().equals(Request.INVITE)) {
callProcessing.processTimeout(transaction, request);
} else {
// Just show an error for now
}
}
// -------------------- PROCESS RESPONSE
public void processResponse(ResponseEvent responseReceivedEvent) {
Log.debug("<RESPONSE>");
Log.debug("[" + responseReceivedEvent.getResponse().getStatusCode()
+ "]");
Log.debug("</RESPONSE>");
ClientTransaction clientTransaction = responseReceivedEvent
.getClientTransaction();
if (clientTransaction == null) {
return;
}
Response response = responseReceivedEvent.getResponse();
//TODO REMOVE
@SuppressWarnings("unused")
Dialog dialog = clientTransaction.getDialog();
String method = ((CSeqHeader) response.getHeader(CSeqHeader.NAME))
.getMethod();
//TODO REMOVE
@SuppressWarnings("unused")
Response responseClone = (Response) response.clone();
// OK
if (response.getStatusCode() == Response.OK) {
// REGISTER
if (method.equals(Request.REGISTER)) {
registerProcessing.processOK(clientTransaction, response);
}// INVITE
else if (method.equals(Request.INVITE)) {
callProcessing.processInviteOK(clientTransaction, response);
}// BYE
else if (method.equals(Request.BYE)) {
callProcessing.processByeOK(clientTransaction, response);
}// CANCEL
else if (method.equals(Request.CANCEL)) {
callProcessing.processCancelOK(clientTransaction, response);
} else if (method.equals(Request.SUBSCRIBE)) {
}
}
// SESSION PROGRESS
else if (response.getStatusCode() == Response.SESSION_PROGRESS) {
callProcessing.processRingingBack(clientTransaction, response);
}
// ACCEPTED
else if (response.getStatusCode() == Response.ACCEPTED) {
// SUBSCRIBE
if (method.equals(Request.SUBSCRIBE)) {
} else if (method.equals(Request.REFER)) {
Call call = callProcessing.getCallDispatcher().findCall(clientTransaction.getDialog());
try {
callProcessing.endCall(call);
}
catch (CommunicationsException e) {
Log.error("Trasnfer", e);
}
}
}
// RINGING - process RINGING before treating the general case of a
// provisional response (see next "else if")
// report and fix - Asa Karlsson
else if (response.getStatusCode() == Response.RINGING) {
if (method.equals(Request.INVITE)) {
callProcessing.processRinging(clientTransaction, response);
} else {
fireUnknownMessageReceived(response);
}
}
// TRYING
else if (response.getStatusCode() == Response.TRYING
// process all provisional responses here
// reported by Les Roger Davis
|| response.getStatusCode() / 100 == 1) {
if (method.equals(Request.INVITE)) {
callProcessing.processTrying(clientTransaction, response);
}
// We could also receive a TRYING response to a REGISTER req
// bug reports by
// Steven Lass <sltemp at comcast.net>
// Luis Vazquez <luis at teledata.com.uy>
else if (method.equals(Request.REGISTER)) {
// do nothing
} else {
// TODO TRYING // fireUnknownMessageReceived(response);
}
}
// NOT_FOUND
else if (response.getStatusCode() == Response.NOT_FOUND) {
if (method.equals(Request.INVITE)) {
callProcessing.processNotFound(clientTransaction, response);
}
if (method.equals(Request.SUBSCRIBE)) {
} else if (method.equals(Request.REGISTER)) {
fireRegistrationFailed("Invalid username.", RegistrationEvent.Type.NotFound);
Log.debug("REGISTER NOT FOUND");
}
}
// NOT_IMPLEMENTED
else if (response.getStatusCode() == Response.NOT_IMPLEMENTED) {
if (method.equals(Request.REGISTER)) {
// Fixed typo issues - Reported by pizarro
registerProcessing.processNotImplemented(clientTransaction,
response);
} else if (method.equals(Request.INVITE)) {
callProcessing.processNotImplemented(clientTransaction,
response);
} else {
fireUnknownMessageReceived(response);
}
}
// REQUEST_TERMINATED
else if (response.getStatusCode() == Response.REQUEST_TERMINATED) {
callProcessing.processRequestTerminated(clientTransaction,
response);
}
// BUSY_HERE
else if (response.getStatusCode() == Response.BUSY_HERE) {
if (method.equals(Request.INVITE)) {
callProcessing.processBusyHere(clientTransaction, response);
} else {
fireUnknownMessageReceived(response);
}
}
// 401 UNAUTHORIZED
else if (response.getStatusCode() == Response.UNAUTHORIZED
|| response.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED) {
if (method.equals(Request.INVITE)) {
callProcessing.processAuthenticationChallenge(
clientTransaction, response);
} else if (method.equals(Request.REGISTER)) {
//TODO REMOVE
@SuppressWarnings("unused")
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
registerProcessing.processAuthenticationChallenge(
clientTransaction, response);
loginfailed++ ;
if (loginfailed < 3)
Log.debug("Removed");
else
fireRegistrationFailed("Invalid password.", RegistrationEvent.Type.WrongPass);
} else if (method.equals(Request.SUBSCRIBE)) {
} else
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.FORBIDDEN) {
} else if (response.getStatusCode() == 403) {
// Wrong Authorization User
fireRegistrationFailed("Invalid auth user.", RegistrationEvent.Type.WrongAuthUser);
}
// Other Errors
else if ( // We'll handle all errors the same way so no individual
// handling
// is needed
// response.getStatusCode() == Response.NOT_ACCEPTABLE
// || response.getStatusCode() == Response.SESSION_NOT_ACCEPTABLE
response.getStatusCode() / 100 == 4) {
if (method.equals(Request.INVITE)) {
callProcessing
.processCallError(clientTransaction, response);
} else {
fireUnknownMessageReceived(response);
}
} else if (response.getStatusCode() == Response.ACCEPTED) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.ADDRESS_INCOMPLETE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.ALTERNATIVE_SERVICE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.AMBIGUOUS) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.BAD_EVENT) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.BAD_EXTENSION) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.BAD_GATEWAY) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.BAD_REQUEST) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.BUSY_EVERYWHERE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.CALL_IS_BEING_FORWARDED) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST) {
/** @todo add proper request handling */
// fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.DECLINE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.DOES_NOT_EXIST_ANYWHERE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.EXTENSION_REQUIRED) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.GONE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.INTERVAL_TOO_BRIEF) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.LOOP_DETECTED) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.MESSAGE_TOO_LARGE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.METHOD_NOT_ALLOWED) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.MOVED_PERMANENTLY) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.MOVED_TEMPORARILY) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.MULTIPLE_CHOICES) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.NOT_ACCEPTABLE_HERE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.PAYMENT_REQUIRED) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.QUEUED) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.REQUEST_ENTITY_TOO_LARGE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.REQUEST_PENDING) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.REQUEST_TIMEOUT) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.REQUEST_URI_TOO_LONG) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
}
// Thiago Rocha Camargo
// Contorno para falha na plataforma
else if (response.getStatusCode() == Response.SERVER_INTERNAL_ERROR) {
//
} else if (response.getStatusCode() == Response.SERVER_TIMEOUT) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.SERVICE_UNAVAILABLE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.SESSION_NOT_ACCEPTABLE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.SESSION_PROGRESS) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.TEMPORARILY_UNAVAILABLE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.TOO_MANY_HOPS) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.UNDECIPHERABLE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.UNSUPPORTED_MEDIA_TYPE) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.UNSUPPORTED_URI_SCHEME) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.USE_PROXY) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else if (response.getStatusCode() == Response.VERSION_NOT_SUPPORTED) {
/** @todo add proper request handling */
fireUnknownMessageReceived(response);
} else { // We couldn't recognise the message
fireUnknownMessageReceived(response);
}
} // process response
// --------
String getLocalHostAddress() {
// network address management is handled by
// common.NetworkAddressManager
// String hostAddress = Utils.getProperty("javax.sip.IP_ADDRESS");
// if (hostAddress == null) {
InetAddress localhost = NetworkAddressManager.getLocalHost();
String hostAddress = localhost.getHostAddress();
return hostAddress;
}
protected void checkIfStarted() throws CommunicationsException {
if (!isStarted) {
throw new CommunicationsException(
"The underlying SIP Stack had not been"
+ "properly initialised! Impossible to continue");
}
}
public void sendServerInternalError(int callID)
throws CommunicationsException {
checkIfStarted();
callProcessing.sayInternalError(callID);
}
public boolean isBusy() {
return isBusy;
}
public void setBusy(boolean busy) {
isBusy = busy;
}
}