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;