diff --git a/peers-gui/src/main/java/net/sourceforge/peers/gui/AccountFrame.java b/peers-gui/src/main/java/net/sourceforge/peers/gui/AccountFrame.java
index a44d219e..a2ecf69a 100644
--- a/peers-gui/src/main/java/net/sourceforge/peers/gui/AccountFrame.java
+++ b/peers-gui/src/main/java/net/sourceforge/peers/gui/AccountFrame.java
@@ -244,7 +244,6 @@ public void registering(SipRequest sipRequest) {
public synchronized void registerSuccess(SipResponse sipResponse) {
if (unregistering) {
- userAgent.close();
applyNewConfig();
} else {
registration.registerSuccessful();
@@ -253,7 +252,6 @@ public synchronized void registerSuccess(SipResponse sipResponse) {
public void registerFailed(SipResponse sipResponse) {
if (unregistering) {
- userAgent.close();
applyNewConfig();
} else {
registration.registerFailed();
@@ -280,7 +278,6 @@ public void run() {
runnable = new Runnable() {
@Override
public void run() {
- userAgent.close();
applyNewConfig();
}
};
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/media/MediaManager.java b/peers-lib/src/main/java/net/sourceforge/peers/media/MediaManager.java
index 0c54cb54..430f2ed4 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/media/MediaManager.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/media/MediaManager.java
@@ -19,18 +19,18 @@
package net.sourceforge.peers.media;
-import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.List;
-
import net.sourceforge.peers.Logger;
import net.sourceforge.peers.rtp.RtpPacket;
import net.sourceforge.peers.rtp.RtpSession;
import net.sourceforge.peers.sdp.Codec;
import net.sourceforge.peers.sip.core.useragent.UserAgent;
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+
public class MediaManager {
public static final int DEFAULT_CLOCK = 8000; // Hz
@@ -309,7 +309,9 @@ public void stopSession() {
}
break;
case file:
- fileReader.close();
+ if (fileReader != null) {
+ fileReader.close();
+ }
break;
default:
break;
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/UserAgent.java b/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/UserAgent.java
index 0233ef47..4f5515c8 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/UserAgent.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/UserAgent.java
@@ -19,11 +19,6 @@
package net.sourceforge.peers.sip.core.useragent;
-import java.io.File;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.List;
-
import net.sourceforge.peers.Config;
import net.sourceforge.peers.FileLogger;
import net.sourceforge.peers.Logger;
@@ -50,6 +45,11 @@
import net.sourceforge.peers.sip.transport.SipResponse;
import net.sourceforge.peers.sip.transport.TransportManager;
+import java.io.File;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.List;
+
public class UserAgent {
@@ -74,6 +74,7 @@ public class UserAgent {
private DialogManager dialogManager;
private TransactionManager transactionManager;
private TransportManager transportManager;
+ private InviteHandler inviteHandler;
private int cseqCounter;
private SipListener sipListener;
@@ -143,7 +144,7 @@ private UserAgent(SipListener sipListener, Config config, String peersHome,
//core
- InviteHandler inviteHandler = new InviteHandler(this,
+ inviteHandler = new InviteHandler(this,
dialogManager,
transactionManager,
transportManager,
@@ -232,6 +233,9 @@ private UserAgent(SipListener sipListener, Config config, String peersHome,
public void close() {
transportManager.closeTransports();
+ transactionManager.closeTimers();
+ inviteHandler.closeTimers();
+ mediaManager.stopSession();
config.setPublicInetAddress(null);
}
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/InviteHandler.java b/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/InviteHandler.java
index 5931acc6..25fdd63e 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/InviteHandler.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/InviteHandler.java
@@ -339,6 +339,10 @@ public void rejectCall(SipRequest sipRequest) {
//////////////////////////////////////////////////////////
// UAC methods
//////////////////////////////////////////////////////////
+
+ public void closeTimers() {
+ ackTimer.cancel();
+ }
public ClientTransaction preProcessInvite(SipRequest sipRequest)
throws SipUriSyntaxException {
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/RegisterHandler.java b/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/RegisterHandler.java
index db06e1fc..615e4794 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/RegisterHandler.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/sip/core/useragent/handlers/RegisterHandler.java
@@ -1,298 +1,301 @@
-/*
- This file is part of Peers, a java SIP softphone.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
- Copyright 2007-2013 Yohann Martineau
-*/
-
-package net.sourceforge.peers.sip.core.useragent.handlers;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Hashtable;
-import java.util.Timer;
-import java.util.TimerTask;
-
-import net.sourceforge.peers.Config;
-import net.sourceforge.peers.Logger;
-import net.sourceforge.peers.sip.RFC3261;
-import net.sourceforge.peers.sip.core.useragent.InitialRequestManager;
-import net.sourceforge.peers.sip.core.useragent.RequestManager;
-import net.sourceforge.peers.sip.core.useragent.SipListener;
-import net.sourceforge.peers.sip.core.useragent.UserAgent;
-import net.sourceforge.peers.sip.syntaxencoding.NameAddress;
-import net.sourceforge.peers.sip.syntaxencoding.SipHeaderFieldName;
-import net.sourceforge.peers.sip.syntaxencoding.SipHeaderFieldValue;
-import net.sourceforge.peers.sip.syntaxencoding.SipHeaderParamName;
-import net.sourceforge.peers.sip.syntaxencoding.SipHeaders;
-import net.sourceforge.peers.sip.syntaxencoding.SipURI;
-import net.sourceforge.peers.sip.syntaxencoding.SipUriSyntaxException;
-import net.sourceforge.peers.sip.transaction.ClientTransaction;
-import net.sourceforge.peers.sip.transaction.ClientTransactionUser;
-import net.sourceforge.peers.sip.transaction.NonInviteClientTransaction;
-import net.sourceforge.peers.sip.transaction.Transaction;
-import net.sourceforge.peers.sip.transaction.TransactionManager;
-import net.sourceforge.peers.sip.transport.SipRequest;
-import net.sourceforge.peers.sip.transport.SipResponse;
-import net.sourceforge.peers.sip.transport.TransportManager;
-
-public class RegisterHandler extends MethodHandler
- implements ClientTransactionUser {
-
- public static final int REFRESH_MARGIN = 10; // seconds
-
- private InitialRequestManager initialRequestManager;
-
- private Timer timer;
-
- private String requestUriStr;
- private String profileUriStr;
- private String callIDStr;
-
- //FIXME should be on a profile based context
- private boolean unregisterInvoked;
- private boolean registered;
-
- public RegisterHandler(UserAgent userAgent,
- TransactionManager transactionManager,
- TransportManager transportManager, Logger logger) {
- super(userAgent, transactionManager, transportManager, logger);
- }
-
- //TODO factorize common code here and in invitehandler
- public synchronized ClientTransaction preProcessRegister(SipRequest sipRequest)
- throws SipUriSyntaxException {
- registered = false;
- unregisterInvoked = false;
- SipHeaders sipHeaders = sipRequest.getSipHeaders();
- SipURI destinationUri = RequestManager.getDestinationUri(sipRequest,
- logger);
- int port = destinationUri.getPort();
- if (port == SipURI.DEFAULT_PORT) {
- port = RFC3261.TRANSPORT_DEFAULT_PORT;
- }
- //TODO if header route is present, addrspec = toproute.nameaddress.addrspec
- String transport = RFC3261.TRANSPORT_UDP;
- Hashtable params = destinationUri.getUriParameters();
- if (params != null) {
- String reqUriTransport = params.get(RFC3261.PARAM_TRANSPORT);
- if (reqUriTransport != null) {
- transport = reqUriTransport;
- }
- }
- SipURI sipUri = userAgent.getConfig().getOutboundProxy();
- if (sipUri == null) {
- sipUri = destinationUri;
- }
- InetAddress inetAddress;
- try {
- inetAddress = InetAddress.getByName(sipUri.getHost());
- } catch (UnknownHostException e) {
- throw new SipUriSyntaxException("unknown host: "
- + sipUri.getHost(), e);
- }
- ClientTransaction clientTransaction = transactionManager
- .createClientTransaction(sipRequest, inetAddress, port,
- transport, null, this);
- //TODO 10.2
- SipHeaderFieldValue to = sipHeaders.get(
- new SipHeaderFieldName(RFC3261.HDR_TO));
- SipHeaderFieldValue from = sipHeaders.get(
- new SipHeaderFieldName(RFC3261.HDR_FROM));
- String fromValue = from.getValue();
- to.setValue(fromValue);
- requestUriStr = destinationUri.toString();
- profileUriStr = NameAddress.nameAddressToUri(fromValue);
- callIDStr = sipHeaders.get(new SipHeaderFieldName(RFC3261.HDR_CALLID))
- .toString();
- // added for buggy servers like cirpack which doesn't answer with a
- // default expires value if it doesn't find any expires in request
- sipHeaders.add(new SipHeaderFieldName(RFC3261.HDR_EXPIRES),
- new SipHeaderFieldValue(String.valueOf(
- RFC3261.DEFAULT_EXPIRES)));
- return clientTransaction;
- }
-
- public void unregister() {
- timer.cancel();
- unregisterInvoked = true;
- challenged = false;
- }
-
- //////////////////////////////////////////////////////////
- // ClientTransactionUser methods
- //////////////////////////////////////////////////////////
-
- public void errResponseReceived(SipResponse sipResponse) {
- String password = userAgent.getConfig().getPassword();
- if (password != null && !"".equals(password.trim())) {
- int statusCode = sipResponse.getStatusCode();
- if (statusCode == RFC3261.CODE_401_UNAUTHORIZED
- || statusCode ==
- RFC3261.CODE_407_PROXY_AUTHENTICATION_REQUIRED) {
- if (challenged) {
- notifyListener(sipResponse);
- } else {
- challenged = true;
- NonInviteClientTransaction nonInviteClientTransaction =
- (NonInviteClientTransaction)
- transactionManager.getClientTransaction(sipResponse);
- SipRequest sipRequest =
- nonInviteClientTransaction.getRequest();
- challengeManager.handleChallenge(sipRequest, sipResponse);
- }
- } else { // not 401 nor 407
- SipHeaders sipHeaders = sipResponse.getSipHeaders();
- SipHeaderFieldName viaName = new SipHeaderFieldName(
- RFC3261.HDR_VIA);
- SipHeaderFieldValue via = sipHeaders.get(viaName);
- SipHeaderParamName receivedName = new SipHeaderParamName(
- RFC3261.PARAM_RECEIVED);
- String viaValue = via.getValue();
- int pos = viaValue.indexOf(" ");
- if (pos > -1) {
- viaValue = viaValue.substring(pos + 1);
- pos = viaValue.indexOf(RFC3261.TRANSPORT_PORT_SEP);
- if (pos > -1) {
- viaValue = viaValue.substring(0, pos);
- } else {
- pos = viaValue.indexOf(RFC3261.PARAM_SEPARATOR);
- if (pos > -1) {
- viaValue = viaValue.substring(0, pos);
- }
- }
- }
- String received = via.getParam(receivedName);
- if (received != null && !"".equals(received.trim())) {
- if (viaValue.equals(received)) {
- notifyListener(sipResponse);
- } else { // received != via ip address
- try {
- InetAddress receivedInetAddress =
- InetAddress.getByName(received);
- Config config = userAgent.getConfig();
- config.setPublicInetAddress(receivedInetAddress);
- userAgent.register();
- } catch (UnknownHostException e) {
- notifyListener(sipResponse);
- logger.error(e.getMessage(), e);
- } catch (SipUriSyntaxException e) {
- notifyListener(sipResponse);
- logger.error(e.getMessage(), e);
- }
- }
- } else { // received not provided
- notifyListener(sipResponse);
- }
- }
- } else { // no password configured
- notifyListener(sipResponse);
- }
- }
-
- private void notifyListener(SipResponse sipResponse) {
- SipListener sipListener = userAgent.getSipListener();
- if (sipListener != null) {
- sipListener.registerFailed(sipResponse);
- }
- challenged = false;
- }
-
- public void provResponseReceived(SipResponse sipResponse,
- Transaction transaction) {
- //meaningless
- }
-
- public synchronized void successResponseReceived(SipResponse sipResponse,
- Transaction transaction) {
- // 1. retrieve request corresponding to response
- // 2. if request was not an unregister, extract contact and expires,
- // and start register refresh timer
- // 3. notify sip listener of register success event.
- SipRequest sipRequest = transaction.getRequest();
- SipHeaderFieldName contactName = new SipHeaderFieldName(
- RFC3261.HDR_CONTACT);
- SipHeaderFieldValue requestContact = sipRequest.getSipHeaders()
- .get(contactName);
- SipHeaderParamName expiresParam = new SipHeaderParamName(
- RFC3261.PARAM_EXPIRES);
- String expires = requestContact.getParam(expiresParam);
- challenged = false;
- if (!"0".equals(expires)) {
- // each contact contains an expires parameter giving the expiration
- // in seconds. Thus the binding must be refreshed before it expires.
- SipHeaders sipHeaders = sipResponse.getSipHeaders();
- SipHeaderFieldValue responseContact = sipHeaders.get(contactName);
- if (responseContact == null) {
- return;
- }
- expires = responseContact.getParam(expiresParam);
- // patch mobicents simple application
- registered = true;
- int delay = -1;
- if (expires == null || "".equals(expires.trim())) {
- delay = 3600;
- }
- if (!unregisterInvoked) {
- if (delay == -1) {
- delay = Integer.parseInt(expires) - REFRESH_MARGIN;
- }
- timer = new Timer(getClass().getSimpleName()
- + " refresh timer");
- timer.schedule(new RefreshTimerTask(), delay * 1000);
- }
- }
- SipListener sipListener = userAgent.getSipListener();
- if (sipListener != null) {
- sipListener.registerSuccessful(sipResponse);
- }
- }
-
- public void transactionTimeout(ClientTransaction clientTransaction) {
- SipListener sipListener = userAgent.getSipListener();
- if (sipListener != null) {
- sipListener.registerFailed(null);
- }
- }
-
- public void transactionTransportError() {
- //TODO alert user
- }
-
- public boolean isRegistered() {
- return registered;
- }
-
- //////////////////////////////////////////////////////////
- // TimerTask
- //////////////////////////////////////////////////////////
-
- class RefreshTimerTask extends TimerTask {
- @Override
- public void run() {
- try {
- initialRequestManager.createInitialRequest(requestUriStr,
- RFC3261.METHOD_REGISTER, profileUriStr, callIDStr);
- } catch (SipUriSyntaxException e) {
- logger.error("syntax error", e);
- }
- }
- }
-
- public void setInitialRequestManager(InitialRequestManager initialRequestManager) {
- this.initialRequestManager = initialRequestManager;
- }
-
-}
+/*
+ This file is part of Peers, a java SIP softphone.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+ Copyright 2007-2013 Yohann Martineau
+*/
+
+package net.sourceforge.peers.sip.core.useragent.handlers;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Hashtable;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import net.sourceforge.peers.Config;
+import net.sourceforge.peers.Logger;
+import net.sourceforge.peers.sip.RFC3261;
+import net.sourceforge.peers.sip.core.useragent.InitialRequestManager;
+import net.sourceforge.peers.sip.core.useragent.RequestManager;
+import net.sourceforge.peers.sip.core.useragent.SipListener;
+import net.sourceforge.peers.sip.core.useragent.UserAgent;
+import net.sourceforge.peers.sip.syntaxencoding.NameAddress;
+import net.sourceforge.peers.sip.syntaxencoding.SipHeaderFieldName;
+import net.sourceforge.peers.sip.syntaxencoding.SipHeaderFieldValue;
+import net.sourceforge.peers.sip.syntaxencoding.SipHeaderParamName;
+import net.sourceforge.peers.sip.syntaxencoding.SipHeaders;
+import net.sourceforge.peers.sip.syntaxencoding.SipURI;
+import net.sourceforge.peers.sip.syntaxencoding.SipUriSyntaxException;
+import net.sourceforge.peers.sip.transaction.ClientTransaction;
+import net.sourceforge.peers.sip.transaction.ClientTransactionUser;
+import net.sourceforge.peers.sip.transaction.NonInviteClientTransaction;
+import net.sourceforge.peers.sip.transaction.Transaction;
+import net.sourceforge.peers.sip.transaction.TransactionManager;
+import net.sourceforge.peers.sip.transport.SipRequest;
+import net.sourceforge.peers.sip.transport.SipResponse;
+import net.sourceforge.peers.sip.transport.TransportManager;
+
+public class RegisterHandler extends MethodHandler
+ implements ClientTransactionUser {
+
+ public static final int REFRESH_MARGIN = 10; // seconds
+
+ private InitialRequestManager initialRequestManager;
+
+ private Timer timer;
+
+ private String requestUriStr;
+ private String profileUriStr;
+ private String callIDStr;
+
+ //FIXME should be on a profile based context
+ private boolean unregisterInvoked;
+ private boolean registered;
+
+ public RegisterHandler(UserAgent userAgent,
+ TransactionManager transactionManager,
+ TransportManager transportManager, Logger logger) {
+ super(userAgent, transactionManager, transportManager, logger);
+ }
+
+ //TODO factorize common code here and in invitehandler
+ public synchronized ClientTransaction preProcessRegister(SipRequest sipRequest)
+ throws SipUriSyntaxException {
+ registered = false;
+ unregisterInvoked = false;
+ SipHeaders sipHeaders = sipRequest.getSipHeaders();
+ SipURI destinationUri = RequestManager.getDestinationUri(sipRequest,
+ logger);
+ int port = destinationUri.getPort();
+ if (port == SipURI.DEFAULT_PORT) {
+ port = RFC3261.TRANSPORT_DEFAULT_PORT;
+ }
+ //TODO if header route is present, addrspec = toproute.nameaddress.addrspec
+ String transport = RFC3261.TRANSPORT_UDP;
+ Hashtable params = destinationUri.getUriParameters();
+ if (params != null) {
+ String reqUriTransport = params.get(RFC3261.PARAM_TRANSPORT);
+ if (reqUriTransport != null) {
+ transport = reqUriTransport;
+ }
+ }
+ SipURI sipUri = userAgent.getConfig().getOutboundProxy();
+ if (sipUri == null) {
+ sipUri = destinationUri;
+ }
+ InetAddress inetAddress;
+ try {
+ inetAddress = InetAddress.getByName(sipUri.getHost());
+ } catch (UnknownHostException e) {
+ throw new SipUriSyntaxException("unknown host: "
+ + sipUri.getHost(), e);
+ }
+ ClientTransaction clientTransaction = transactionManager
+ .createClientTransaction(sipRequest, inetAddress, port,
+ transport, null, this);
+ //TODO 10.2
+ SipHeaderFieldValue to = sipHeaders.get(
+ new SipHeaderFieldName(RFC3261.HDR_TO));
+ SipHeaderFieldValue from = sipHeaders.get(
+ new SipHeaderFieldName(RFC3261.HDR_FROM));
+ String fromValue = from.getValue();
+ to.setValue(fromValue);
+ requestUriStr = destinationUri.toString();
+ profileUriStr = NameAddress.nameAddressToUri(fromValue);
+ callIDStr = sipHeaders.get(new SipHeaderFieldName(RFC3261.HDR_CALLID))
+ .toString();
+ // added for buggy servers like cirpack which doesn't answer with a
+ // default expires value if it doesn't find any expires in request
+ sipHeaders.add(new SipHeaderFieldName(RFC3261.HDR_EXPIRES),
+ new SipHeaderFieldValue(String.valueOf(
+ RFC3261.DEFAULT_EXPIRES)));
+ return clientTransaction;
+ }
+
+ public void unregister() {
+ timer.cancel();
+ unregisterInvoked = true;
+ challenged = false;
+ }
+
+ //////////////////////////////////////////////////////////
+ // ClientTransactionUser methods
+ //////////////////////////////////////////////////////////
+
+ public void errResponseReceived(SipResponse sipResponse) {
+ String password = userAgent.getConfig().getPassword();
+ if (password != null && !"".equals(password.trim())) {
+ int statusCode = sipResponse.getStatusCode();
+ if (statusCode == RFC3261.CODE_401_UNAUTHORIZED
+ || statusCode ==
+ RFC3261.CODE_407_PROXY_AUTHENTICATION_REQUIRED) {
+ if (challenged) {
+ notifyListener(sipResponse);
+ } else {
+ challenged = true;
+ NonInviteClientTransaction nonInviteClientTransaction =
+ (NonInviteClientTransaction)
+ transactionManager.getClientTransaction(sipResponse);
+ SipRequest sipRequest =
+ nonInviteClientTransaction.getRequest();
+ challengeManager.handleChallenge(sipRequest, sipResponse);
+ }
+ } else { // not 401 nor 407
+ SipHeaders sipHeaders = sipResponse.getSipHeaders();
+ SipHeaderFieldName viaName = new SipHeaderFieldName(
+ RFC3261.HDR_VIA);
+ SipHeaderFieldValue via = sipHeaders.get(viaName);
+ SipHeaderParamName receivedName = new SipHeaderParamName(
+ RFC3261.PARAM_RECEIVED);
+ String viaValue = via.getValue();
+ int pos = viaValue.indexOf(" ");
+ if (pos > -1) {
+ viaValue = viaValue.substring(pos + 1);
+ pos = viaValue.indexOf(RFC3261.TRANSPORT_PORT_SEP);
+ if (pos > -1) {
+ viaValue = viaValue.substring(0, pos);
+ } else {
+ pos = viaValue.indexOf(RFC3261.PARAM_SEPARATOR);
+ if (pos > -1) {
+ viaValue = viaValue.substring(0, pos);
+ }
+ }
+ }
+ String received = via.getParam(receivedName);
+ if (received != null && !"".equals(received.trim())) {
+ if (viaValue.equals(received)) {
+ notifyListener(sipResponse);
+ } else { // received != via ip address
+ try {
+ InetAddress receivedInetAddress =
+ InetAddress.getByName(received);
+ Config config = userAgent.getConfig();
+ config.setPublicInetAddress(receivedInetAddress);
+ userAgent.register();
+ } catch (UnknownHostException e) {
+ notifyListener(sipResponse);
+ logger.error(e.getMessage(), e);
+ } catch (SipUriSyntaxException e) {
+ notifyListener(sipResponse);
+ logger.error(e.getMessage(), e);
+ }
+ }
+ } else { // received not provided
+ notifyListener(sipResponse);
+ }
+ }
+ } else { // no password configured
+ notifyListener(sipResponse);
+ }
+ }
+
+ private void notifyListener(SipResponse sipResponse) {
+ SipListener sipListener = userAgent.getSipListener();
+ if (sipListener != null) {
+ sipListener.registerFailed(sipResponse);
+ }
+ challenged = false;
+ }
+
+ public void provResponseReceived(SipResponse sipResponse,
+ Transaction transaction) {
+ //meaningless
+ }
+
+ public synchronized void successResponseReceived(SipResponse sipResponse,
+ Transaction transaction) {
+ // 1. retrieve request corresponding to response
+ // 2. if request was not an unregister, extract contact and expires,
+ // and start register refresh timer
+ // 3. notify sip listener of register success event.
+ SipRequest sipRequest = transaction.getRequest();
+ SipHeaderFieldName contactName = new SipHeaderFieldName(
+ RFC3261.HDR_CONTACT);
+ SipHeaderFieldValue requestContact = sipRequest.getSipHeaders()
+ .get(contactName);
+ SipHeaderParamName expiresParam = new SipHeaderParamName(
+ RFC3261.PARAM_EXPIRES);
+ String expires = requestContact.getParam(expiresParam);
+ challenged = false;
+ if (!"0".equals(expires)) {
+ // each contact contains an expires parameter giving the expiration
+ // in seconds. Thus the binding must be refreshed before it expires.
+ SipHeaders sipHeaders = sipResponse.getSipHeaders();
+ SipHeaderFieldValue responseContact = sipHeaders.get(contactName);
+ if (responseContact == null) {
+ return;
+ }
+ expires = responseContact.getParam(expiresParam);
+ // patch mobicents simple application
+ registered = true;
+ int delay = -1;
+ if (expires == null || "".equals(expires.trim())) {
+ delay = 3600;
+ }
+ if (!unregisterInvoked) {
+ if (delay == -1) {
+ delay = Integer.parseInt(expires) - REFRESH_MARGIN;
+ }
+ if (timer != null) {
+ timer.cancel();
+ }
+ timer = new Timer(getClass().getSimpleName()
+ + " refresh timer");
+ timer.schedule(new RefreshTimerTask(), delay * 1000);
+ }
+ }
+ SipListener sipListener = userAgent.getSipListener();
+ if (sipListener != null) {
+ sipListener.registerSuccessful(sipResponse);
+ }
+ }
+
+ public void transactionTimeout(ClientTransaction clientTransaction) {
+ SipListener sipListener = userAgent.getSipListener();
+ if (sipListener != null) {
+ sipListener.registerFailed(null);
+ }
+ }
+
+ public void transactionTransportError() {
+ //TODO alert user
+ }
+
+ public boolean isRegistered() {
+ return registered;
+ }
+
+ //////////////////////////////////////////////////////////
+ // TimerTask
+ //////////////////////////////////////////////////////////
+
+ class RefreshTimerTask extends TimerTask {
+ @Override
+ public void run() {
+ try {
+ initialRequestManager.createInitialRequest(requestUriStr,
+ RFC3261.METHOD_REGISTER, profileUriStr, callIDStr);
+ } catch (SipUriSyntaxException e) {
+ logger.error("syntax error", e);
+ }
+ }
+ }
+
+ public void setInitialRequestManager(InitialRequestManager initialRequestManager) {
+ this.initialRequestManager = initialRequestManager;
+ }
+
+}
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/sip/transaction/TransactionManager.java b/peers-lib/src/main/java/net/sourceforge/peers/sip/transaction/TransactionManager.java
index 96dd0bad..fa536bd0 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/sip/transaction/TransactionManager.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/sip/transaction/TransactionManager.java
@@ -56,6 +56,10 @@ public TransactionManager(Logger logger) {
timer = new Timer(TransactionManager.class.getSimpleName()
+ " " + Timer.class.getSimpleName());
}
+
+ public void closeTimers() {
+ timer.cancel();
+ }
public ClientTransaction createClientTransaction(SipRequest sipRequest,
InetAddress inetAddress, int port, String transport,
diff --git a/peers-lib/src/main/java/net/sourceforge/peers/sip/transport/UdpMessageReceiver.java b/peers-lib/src/main/java/net/sourceforge/peers/sip/transport/UdpMessageReceiver.java
index 69a39e5e..01fa922f 100644
--- a/peers-lib/src/main/java/net/sourceforge/peers/sip/transport/UdpMessageReceiver.java
+++ b/peers-lib/src/main/java/net/sourceforge/peers/sip/transport/UdpMessageReceiver.java
@@ -62,6 +62,11 @@ public Integer run() {
datagramSocket.receive(packet);
} catch (SocketTimeoutException e) {
return socketTimeoutException;
+ } catch(SocketException e) {
+ if (e.getMessage().equals("Socket closed") && ! isListening()) // race condition
+ return noException;
+ else
+ return ioException;
} catch (IOException e) {
logger.error("cannot receive packet", e);
return ioException;