diff --git a/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java b/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java index 0e4bcb00c..1d7349b1f 100644 --- a/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/AbstractAgiServer.java @@ -1,15 +1,15 @@ package org.asteriskjava.fastagi; +import org.asteriskjava.fastagi.internal.AgiChannelFactory; +import org.asteriskjava.fastagi.internal.DefaultAgiChannelFactory; import org.asteriskjava.util.DaemonThreadFactory; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -import org.asteriskjava.fastagi.internal.AgiChannelFactory; -import org.asteriskjava.fastagi.internal.DefaultAgiChannelFactory; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import java.util.concurrent.SynchronousQueue; /** * Abstract base class for FastAGI and AsyncAGI servers. @@ -241,6 +241,27 @@ private synchronized ThreadPoolExecutor getPool() return pool; } + + /** + * Returns the approximate number of AgiConnectionHandler threads that are actively executing tasks. + * @see ThreadPoolExecutor#getActiveCount() + * @see #getPoolActiveThreadCount() + * @see org.asteriskjava.fastagi.internal.AgiConnectionHandler#AGI_CONNECTION_HANDLERS + */ + public int getPoolActiveTaskCount () { + if (pool != null) { + return pool.getActiveCount(); + } + return -1; + }//getPoolActiveCount + + public int getPoolActiveThreadCount () { + if (pool != null) { + return pool.getPoolSize(); + } + return -1; + }//getPoolActiveThreadCount + /** * Creates a new ThreadPoolExecutor to serve the AGI requests. The nature of this pool * defines how many concurrent requests can be handled. The default implementation diff --git a/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java b/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java index f695e72b4..16519cea0 100644 --- a/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java +++ b/src/main/java/org/asteriskjava/fastagi/DefaultAgiServer.java @@ -20,7 +20,11 @@ import org.asteriskjava.fastagi.internal.AgiConnectionHandler; import org.asteriskjava.fastagi.internal.DefaultAgiChannelFactory; import org.asteriskjava.fastagi.internal.FastAgiConnectionHandler; -import org.asteriskjava.util.*; +import org.asteriskjava.util.Log; +import org.asteriskjava.util.LogFactory; +import org.asteriskjava.util.ReflectionUtil; +import org.asteriskjava.util.ServerSocketFacade; +import org.asteriskjava.util.SocketConnectionFacade; import org.asteriskjava.util.internal.ServerSocketFacadeImpl; import java.io.IOException; @@ -256,9 +260,12 @@ private void loadConfig() } } + /** Default 50? Windows server max 200? */ + private static final int BACKLOG = 200; + protected ServerSocketFacade createServerSocket() throws IOException { - return new ServerSocketFacadeImpl(port, 0, null); + return new ServerSocketFacadeImpl(port, BACKLOG, null); } public void startup() throws IOException, IllegalStateException @@ -301,7 +308,7 @@ public void startup() throws IOException, IllegalStateException } } - logger.info("Received connection from " + socket.getRemoteAddress()); + logger.debug("Received connection from " + socket.getRemoteAddress()); // execute connection handler final AgiConnectionHandler connectionHandler = new FastAgiConnectionHandler(getMappingStrategy(), socket, this.getAgiChannelFactory()); diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java index 184a91866..af14a6089 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiChannelImpl.java @@ -499,4 +499,7 @@ public void gosub(String context, String extension, String priority, String... a { sendCommand(new GosubCommand(context, extension, priority, arguments)); } + + + public AgiRequest getInternalAgiRequest () { return request;} } diff --git a/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java b/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java index c3d6e85f8..1373b1763 100644 --- a/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java +++ b/src/main/java/org/asteriskjava/fastagi/internal/AgiConnectionHandler.java @@ -21,6 +21,9 @@ import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + /** * An AgiConnectionHandler is created and run by the AgiServer whenever a new * AGI connection from an Asterisk Server is received. @@ -43,6 +46,10 @@ public abstract class AgiConnectionHandler implements Runnable private AgiScript script = null; private AgiChannelFactory agiChannelFactory; + + public static final ConcurrentMap AGI_CONNECTION_HANDLERS = + new ConcurrentHashMap(32); + /** * The strategy to use to determine which script to run. */ @@ -93,8 +100,7 @@ protected AgiScript getScript() */ public abstract void release(); - public void run() - { + @Override public void run() { AgiChannel channel = null; try @@ -126,8 +132,8 @@ public void run() setStatusVariable(channel, AJ_AGISTATUS_NOT_FOUND); logToAsterisk(channel, errorMessage); } - else if (script != null) - { + else if (script != null) { + AGI_CONNECTION_HANDLERS.put(this, channel); runScript(script, request, channel); } } @@ -141,12 +147,12 @@ else if (script != null) setStatusVariable(channel, AJ_AGISTATUS_FAILED); logger.error("Unexpected Exception while handling request", e); } - finally - { + finally { + AGI_CONNECTION_HANDLERS.remove(this); AgiConnectionHandler.channel.set(null); release(); } - } + }//run private void runScript(AgiScript script, AgiRequest request, AgiChannel channel) { diff --git a/src/main/java/org/asteriskjava/live/AsteriskChannel.java b/src/main/java/org/asteriskjava/live/AsteriskChannel.java index e3f86a54b..7618f02b1 100644 --- a/src/main/java/org/asteriskjava/live/AsteriskChannel.java +++ b/src/main/java/org/asteriskjava/live/AsteriskChannel.java @@ -65,6 +65,8 @@ public interface AsteriskChannel extends LiveObject String VARIABLE_MONITOR_EXEC = "MONITOR_EXEC"; String VARIABLE_MONITOR_EXEC_ARGS = "MONITOR_EXEC_ARGS"; + /** Pseudo-variable to store {@link org.asteriskjava.manager.event.DialEvent#getDialStatus()} */ + String VAR_AJ_DIAL_STATUS = "AJ_DIAL_STATUS"; /** * Returns the unique id of this channel, for example "1099015093.165". * diff --git a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java index d87b5a68c..c5183fde7 100644 --- a/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java +++ b/src/main/java/org/asteriskjava/live/internal/AsteriskServerImpl.java @@ -16,17 +16,21 @@ */ package org.asteriskjava.live.internal; +import org.asteriskjava.AsteriskVersion; +import org.asteriskjava.config.ConfigFile; import org.asteriskjava.live.*; -import org.asteriskjava.manager.*; +import org.asteriskjava.manager.ManagerConnection; +import org.asteriskjava.manager.ManagerConnectionState; +import org.asteriskjava.manager.ManagerEventListener; +import org.asteriskjava.manager.ManagerEventListenerProxy; +import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.action.*; import org.asteriskjava.manager.event.*; import org.asteriskjava.manager.response.*; +import org.asteriskjava.util.AstUtil; import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; -import org.asteriskjava.util.AstUtil; -import org.asteriskjava.config.ConfigFile; -import org.asteriskjava.AsteriskVersion; import java.util.*; import java.util.concurrent.atomic.AtomicLong; @@ -58,21 +62,16 @@ public class AsteriskServerImpl implements AsteriskServer, ManagerEventListener */ private ManagerConnection eventConnection; private ManagerEventListener eventListener = null; - private ManagerEventListenerProxy managerEventListenerProxy = null; - - private boolean initialized = false; + ManagerEventListenerProxy managerEventListenerProxy; - /** - * A pool of manager connections to use for sending actions to Asterisk. - */ - private final ManagerConnectionPool connectionPool; + boolean initialized = false; - private final List listeners; + final Set listeners; - private final ChannelManager channelManager; - private final MeetMeManager meetMeManager; - private final QueueManager queueManager; - private final AgentManager agentManager; + final ChannelManager channelManager; + final MeetMeManager meetMeManager; + final QueueManager queueManager; + final AgentManager agentManager; /** * The exact version string of the Asterisk server we are connected to. @@ -117,9 +116,8 @@ public class AsteriskServerImpl implements AsteriskServer, ManagerEventListener */ public AsteriskServerImpl() { - connectionPool = new ManagerConnectionPool(1); idCounter = new AtomicLong(); - listeners = new ArrayList(); + listeners = new LinkedHashSet(); originateCallbacks = new HashMap(); channelManager = new ChannelManager(this); agentManager = new AgentManager(this); @@ -136,7 +134,7 @@ public AsteriskServerImpl() public AsteriskServerImpl(ManagerConnection eventConnection) { this(); - setManagerConnection(eventConnection); //todo: !!! Possible bug !!!: call to overridable method over object construction + setManagerConnection(eventConnection); //todo: !!! Possible bug !!!: call to overridable method over object construction } /** @@ -164,8 +162,6 @@ public void setManagerConnection(ManagerConnection eventConnection) } this.eventConnection = eventConnection; - this.connectionPool.clear(); - this.connectionPool.add(eventConnection); } public ManagerConnection getManagerConnection() @@ -1163,7 +1159,7 @@ private void handleOriginateEvent(OriginateResponseEvent originateEvent) return; } } - + if (channel.wasInState(ChannelState.DOWN)) { cb.onNoAnswer(channel); @@ -1179,19 +1175,31 @@ private void handleOriginateEvent(OriginateResponseEvent originateEvent) } } - public void shutdown() - { - if (eventConnection != null && (eventConnection.getState() == ManagerConnectionState.CONNECTED || eventConnection.getState() == ManagerConnectionState.RECONNECTING)) - { - eventConnection.logoff(); - } - if (managerEventListenerProxy != null) - { + @Override public void shutdown() { + if (eventConnection != null && (eventConnection.getState() == ManagerConnectionState.CONNECTED || eventConnection.getState() == ManagerConnectionState.RECONNECTING)) { + try { + eventConnection.logoff(); + } catch (Exception ignore) {} + } + + if (managerEventListenerProxy != null) { + if (eventConnection != null) { + eventConnection.removeEventListener(managerEventListenerProxy); + } managerEventListenerProxy.shutdown(); } - managerEventListenerProxy = null; + + if (eventConnection != null && eventListener != null) { + eventConnection.removeEventListener(eventListener); + } + + managerEventListenerProxy = null; eventListener = null; - } + + if (initialized) {//incredible, but it happened + handleDisconnectEvent(null); + }//i + }//shutdown public List getPeerEntries() throws ManagerCommunicationException { diff --git a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java index e3334ccb9..327b73604 100644 --- a/src/main/java/org/asteriskjava/live/internal/ChannelManager.java +++ b/src/main/java/org/asteriskjava/live/internal/ChannelManager.java @@ -20,11 +20,14 @@ import org.asteriskjava.manager.ResponseEvents; import org.asteriskjava.manager.action.StatusAction; import org.asteriskjava.manager.event.*; +import org.asteriskjava.util.DaemonThreadFactory; import org.asteriskjava.util.DateUtil; import org.asteriskjava.util.Log; import org.asteriskjava.util.LogFactory; import java.util.*; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * Manages channel events on behalf of an AsteriskServer. @@ -47,7 +50,10 @@ class ChannelManager /** * A map of all active channel by their unique id. */ - private final Set channels; + final LinkedHashMap channels = new LinkedHashMap(); + + + ScheduledThreadPoolExecutor traceScheduledExecutorService; /** * Creates a new instance. @@ -57,7 +63,6 @@ class ChannelManager ChannelManager(AsteriskServerImpl server) { this.server = server; - this.channels = new HashSet(); } void initialize() throws ManagerCommunicationException @@ -70,6 +75,9 @@ void initialize(List variables) throws ManagerCommunicationException ResponseEvents re; disconnected(); + + traceScheduledExecutorService = new ScheduledThreadPoolExecutor(1, new DaemonThreadFactory());//Executors.newSingleThreadScheduledExecutor + StatusAction sa = new StatusAction(); sa.setVariables(variables); re = server.sendEventGeneratingAction(sa); @@ -84,6 +92,9 @@ void initialize(List variables) throws ManagerCommunicationException void disconnected() { + if (traceScheduledExecutorService != null) { + traceScheduledExecutorService.shutdown(); + } synchronized (channels) { channels.clear(); @@ -102,7 +113,7 @@ Collection getChannels() synchronized (channels) { copy = new ArrayList(channels.size() + 2); - for (AsteriskChannel channel : channels) + for (AsteriskChannel channel : channels.values()) { if (channel.getState() != ChannelState.HUNGUP) { @@ -117,7 +128,7 @@ private void addChannel(AsteriskChannelImpl channel) { synchronized (channels) { - channels.add(channel); + channels.put(channel.getId(), channel); } } @@ -130,7 +141,7 @@ private void removeOldChannels() synchronized (channels) { - i = channels.iterator(); + i = channels.values().iterator(); while (i.hasNext()) { final AsteriskChannel channel = i.next(); @@ -147,56 +158,42 @@ private void removeOldChannels() } } - private AsteriskChannelImpl addNewChannel(String uniqueId, String name, + private AsteriskChannelImpl addNewChannel(String uniqueId, final String name, Date dateOfCreation, String callerIdNumber, String callerIdName, ChannelState state, String account) { - final AsteriskChannelImpl channel; - final String traceId; - - channel = new AsteriskChannelImpl(server, name, uniqueId, dateOfCreation); + final AsteriskChannelImpl channel = new AsteriskChannelImpl(server, name, uniqueId, dateOfCreation); channel.setCallerId(new CallerId(callerIdName, callerIdNumber)); channel.setAccount(account); channel.stateChanged(dateOfCreation, state); logger.info("Adding channel " + channel.getName() + "(" + channel.getId() + ")"); + addChannel(channel); - if (SLEEP_TIME_BEFORE_GET_VAR > 0) - { - try - { - Thread.sleep(SLEEP_TIME_BEFORE_GET_VAR); - } - catch (InterruptedException e) - { - Thread.currentThread().interrupt(); - } - } + //todo getChannelImplById -> LinkedHashMap, callbacks order + traceScheduledExecutorService.schedule(new Runnable(){ + @Override public void run () { + final String traceId = getTraceId(channel); + channel.setTraceId(traceId); - traceId = getTraceId(channel); - channel.setTraceId(traceId); + if (traceId != null && (!name.toLowerCase(Locale.ENGLISH).startsWith("local/") || name.endsWith(",1") || name.endsWith(";1"))) { + final OriginateCallbackData callbackData = server.getOriginateCallbackDataByTraceId(traceId); + + if (callbackData != null && callbackData.getChannel() == null) { + callbackData.setChannel(channel); + try { + callbackData.getCallback().onDialing(channel); + } catch (Throwable t) { + logger.warn("Exception dispatching originate progress. "+ channel, t); + }//t + }//i + }//i + }}, SLEEP_TIME_BEFORE_GET_VAR, TimeUnit.MILLISECONDS); - addChannel(channel); - if (traceId != null && (!name.toLowerCase(Locale.ENGLISH).startsWith("local/") || (name.endsWith(",1") || name.endsWith(";1")))) - { - final OriginateCallbackData callbackData; - callbackData = server.getOriginateCallbackDataByTraceId(traceId); - if (callbackData != null && callbackData.getChannel() == null) - { - callbackData.setChannel(channel); - try - { - callbackData.getCallback().onDialing(channel); - } - catch (Throwable t) - { - logger.warn("Exception dispatching originate progress.", t); - } - } - } server.fireNewAsteriskChannel(channel); return channel; - } + }//addNewChannel + void handleStatusEvent(StatusEvent event) { @@ -292,9 +289,9 @@ AsteriskChannelImpl getChannelImplByName(String name) synchronized (channels) { - for (AsteriskChannelImpl tmp : channels) + for (AsteriskChannelImpl tmp : channels.values()) { - if (tmp.getName() != null && tmp.getName().equals(name)) + if (name.equals(tmp.getName())) { // return the most recent channel or when dates are similar, the active one if (dateOfCreation == null || @@ -334,9 +331,9 @@ AsteriskChannelImpl getChannelImplByNameAndActive(String name) synchronized (channels) { - for (AsteriskChannelImpl tmp : channels) + for (AsteriskChannelImpl tmp : channels.values()) { - if (tmp.getName() != null && tmp.getName().equals(name) && tmp.getState() != ChannelState.HUNGUP) + if (name.equals(tmp.getName()) && tmp.getState() != ChannelState.HUNGUP) { channel = tmp; } @@ -345,25 +342,13 @@ AsteriskChannelImpl getChannelImplByNameAndActive(String name) return channel; } - AsteriskChannelImpl getChannelImplById(String id) - { - if (id == null) - { - return null; - } + AsteriskChannelImpl getChannelImplById(String uniqueId) { + if (uniqueId == null) { return null;} - synchronized (channels) - { - for (AsteriskChannelImpl channel : channels) - { - if (id.equals(channel.getId())) - { - return channel; - } - } - } - return null; - } + synchronized (channels) { + return channels.get(uniqueId); + } + }//getChannelImplById /** * Returns the other side of a local channel. @@ -447,7 +432,7 @@ void handleNewExtenEvent(NewExtenEvent event) channel = getChannelImplById(event.getUniqueId()); if (channel == null) { - logger.error("Ignored NewExtenEvent for unknown channel " + event.getChannel()); + logger.warn("handleNewExtenEvent: Ignored NewExtenEvent for unknown channel " + event.getChannel()); return; } @@ -461,6 +446,23 @@ void handleNewExtenEvent(NewExtenEvent event) } } + private void idChanged (AsteriskChannelImpl channel, AbstractChannelEvent event) { + if (channel != null) { + final String oldId = channel.getId(); + final String newId = event.getUniqueId(); + + if (oldId != null && oldId.equals(newId)) { return;} + + logger.info("Changing unique_id for '" + channel.getName() + "' from " + oldId + " to " + newId +" < "+ event); + synchronized(channels) { + channels.remove(oldId); + channels.put(newId, channel); + channel.idChanged(event.getDateReceived(), newId); + } + } + }//idChanged + + void handleNewStateEvent(NewStateEvent event) { AsteriskChannelImpl channel = getChannelImplById(event.getUniqueId()); @@ -469,11 +471,7 @@ void handleNewStateEvent(NewStateEvent event) { // NewStateEvent can occur for an existing channel that now has a different unique id (originate with Local/) channel = getChannelImplByNameAndActive(event.getChannel()); - if (channel != null) - { - logger.info("Changing unique id for '" + channel.getName() + "' from " + channel.getId() + " to " + event.getUniqueId()); - channel.idChanged(event.getDateReceived(), event.getUniqueId()); - } + idChanged(channel, event); if (channel == null) { @@ -544,11 +542,7 @@ void handleNewCallerIdEvent(NewCallerIdEvent event) { // NewCallerIdEvent can occur for an existing channel that now has a different unique id (originate with Local/) channel = getChannelImplByNameAndActive(event.getChannel()); - if (channel != null) - { - logger.info("Changing unique id for '" + channel.getName() + "' from " + channel.getId() + " to " + event.getUniqueId()); - channel.idChanged(event.getDateReceived(), event.getUniqueId()); - } + idChanged(channel, event); if (channel == null) { @@ -573,7 +567,7 @@ void handleHangupEvent(HangupEvent event) if (channel == null) { - logger.error("Ignored HangupEvent for unknown channel " + event.getChannel()); + logger.warn("handleHangupEvent: Ignored HangupEvent for unknown channel " + event.getChannel()); return; } @@ -598,14 +592,18 @@ void handleDialEvent(DialEvent event) if (sourceChannel == null) { - logger.error("Ignored DialEvent for unknown source channel " + event.getChannel() + " with unique id " + event.getUniqueId()); - return; - } - if (destinationChannel == null) - { - logger.error("Ignored DialEvent for unknown destination channel " + event.getDestination() + " with unique id " + event.getDestUniqueId()); + logger.warn("handleDialEvent: Ignored DialEvent for unknown source channel " + event.getChannel() + " with unique id " + event.getUniqueId()); return; } + if (destinationChannel == null) { + if (DialEvent.SUBEVENT_END.equalsIgnoreCase(event.getSubEvent())) { + sourceChannel.updateVariable(AsteriskChannel.VAR_AJ_DIAL_STATUS, event.getDialStatus()); + logger.info("handleDialEvent: Ignored DialEvent for unknown dst channel "+ event.getDestination() +" with unique_id "+ event.getDestUniqueId()); + } else { + logger.warn("handleDialEvent: Ignored DialEvent for unknown dst channel "+ event.getDestination() +" with unique_id "+ event.getDestUniqueId()); + } + return; + }//i logger.info(sourceChannel.getName() + " dialed " + destinationChannel.getName()); getTraceId(sourceChannel); @@ -627,12 +625,12 @@ void handleBridgeEvent(BridgeEvent event) if (channel1 == null) { - logger.error("Ignored BridgeEvent for unknown channel " + event.getChannel1()); + logger.warn("handleBridgeEvent: Ignored BridgeEvent for unknown channel " + event.getChannel1()); return; } if (channel2 == null) { - logger.error("Ignored BridgeEvent for unknown channel " + event.getChannel2()); + logger.warn("handleBridgeEvent: Ignored BridgeEvent for unknown channel " + event.getChannel2()); return; } @@ -671,7 +669,7 @@ void handleRenameEvent(RenameEvent event) if (channel == null) { - logger.error("Ignored RenameEvent for unknown channel with uniqueId " + event.getUniqueId()); + logger.warn("handleRenameEvent: Ignored RenameEvent for unknown channel with uniqueId " + event.getUniqueId()); return; } diff --git a/src/main/java/org/asteriskjava/live/internal/ManagerConnectionPool.java b/src/main/java/org/asteriskjava/live/internal/ManagerConnectionPool.java deleted file mode 100644 index 21612197e..000000000 --- a/src/main/java/org/asteriskjava/live/internal/ManagerConnectionPool.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2005-2006 Stefan Reuter - * - * 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 org.asteriskjava.live.internal; - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; - -import org.asteriskjava.live.ManagerCommunicationException; -import org.asteriskjava.manager.ManagerConnection; -import org.asteriskjava.manager.ResponseEvents; -import org.asteriskjava.manager.action.EventGeneratingAction; -import org.asteriskjava.manager.action.ManagerAction; -import org.asteriskjava.manager.response.ManagerResponse; -import org.asteriskjava.util.Log; -import org.asteriskjava.util.LogFactory; - -class ManagerConnectionPool -{ - private final Log logger = LogFactory.getLog(getClass()); - private final BlockingQueue connections; - - ManagerConnectionPool(int size) - { - this.connections = new ArrayBlockingQueue(size); - } - - void clear() - { - connections.clear(); - } - - void add(ManagerConnection connection) - { - put(connection); - } - - ManagerResponse sendAction(ManagerAction action) throws ManagerCommunicationException - { - ManagerConnection connection; - ManagerResponse response; - - connection = get(); - try - { - response = connection.sendAction(action); - } - catch (Exception e) - { - throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e); - } - finally - { - put(connection); - } - - return response; - } - - ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws ManagerCommunicationException - { - return sendEventGeneratingAction(action, -1); - } - - ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long timeout) - throws ManagerCommunicationException - { - ManagerConnection connection; - ResponseEvents responseEvents; - - connection = get(); - try - { - if (timeout > 0) - { - responseEvents = connection.sendEventGeneratingAction(action, timeout); - } - else - { - responseEvents = connection.sendEventGeneratingAction(action); - } - } - catch (Exception e) - { - throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e); - } - finally - { - put(connection); - } - - return responseEvents; - } - - /** - * Retrieves a connection from the pool. - * - * @return the retrieved connection, or null if interrupted - * while waiting for a connection to become available. - */ - private ManagerConnection get() - { - try - { - return connections.take(); - } - catch (InterruptedException e) - { - logger.error("Interrupted while waiting for ManagerConnection to become available", e); - Thread.currentThread().interrupt(); - return null; - } - } - - private void put(ManagerConnection connection) - { - try - { - connections.put(connection); - } - catch (InterruptedException e) - { - Thread.currentThread().interrupt(); - throw new RuntimeException("Interrupted while trying to add connection to pool"); - } - } -} diff --git a/src/main/java/org/asteriskjava/manager/ManagerEventListenerProxy.java b/src/main/java/org/asteriskjava/manager/ManagerEventListenerProxy.java index b7d39b7a6..4779bace8 100644 --- a/src/main/java/org/asteriskjava/manager/ManagerEventListenerProxy.java +++ b/src/main/java/org/asteriskjava/manager/ManagerEventListenerProxy.java @@ -1,11 +1,14 @@ package org.asteriskjava.manager; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - import org.asteriskjava.manager.event.ManagerEvent; import org.asteriskjava.util.DaemonThreadFactory; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + /** * Proxies a ManagerEventListener and dispatches events asynchronously by using * a single threaded executor.

@@ -26,62 +29,46 @@ * * * @author srt + * @author fink * @since 0.3 - * @version $Id$ */ -public class ManagerEventListenerProxy implements ManagerEventListener -{ - private final ExecutorService executor; - private ManagerEventListener target; +public class ManagerEventListenerProxy implements ManagerEventListener { + private final ThreadPoolExecutor executor; + private final ManagerEventListener target; - /** - * Creates a new ManagerEventListenerProxy.

- * You must set the target by calling {@link #setTarget(ManagerEventListener)}. - */ - public ManagerEventListenerProxy() - { - this.executor = Executors.newSingleThreadExecutor(new DaemonThreadFactory()); - } /** * Creates a new ManagerEventListenerProxy that notifies the given target * asynchronously when new events are received. * * @param target the target listener to invoke. + * @see Executors#newSingleThreadExecutor(ThreadFactory) */ - public ManagerEventListenerProxy(ManagerEventListener target) - { - this(); - this.target = target; - } + public ManagerEventListenerProxy(ManagerEventListener target) { + executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new DaemonThreadFactory()); + this.target = target; + if (target == null) { + throw new NullPointerException("ManagerEventListener target is null!"); + } + }//new + + + @Override public void onManagerEvent(final ManagerEvent event) { + executor.execute(new Runnable() { + @Override public void run() { + target.onManagerEvent(event); + } + }); + }//onManagerEvent - /** - * Sets the target listener that is notified asynchronously when new events - * are received. - * c - * @param target the target listener to invoke. - */ - public synchronized void setTarget(ManagerEventListener target) - { - this.target = target; - } - public synchronized void onManagerEvent(final ManagerEvent event) - { - if (target != null) - { - executor.execute(new Runnable() - { - public void run() - { - target.onManagerEvent(event); - } - }); - } - } - public void shutdown() { - executor.shutdown(); } + + public static class Access { + public static int getThreadQueueSize (ManagerEventListenerProxy proxy) { + return proxy.executor.getQueue().size(); + } + }//Access } diff --git a/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java b/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java index 3f43b0023..8c72c8321 100644 --- a/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AbstractChannelEvent.java @@ -49,7 +49,11 @@ public abstract class AbstractChannelEvent extends ManagerEvent */ private String uniqueId; - protected AbstractChannelEvent(Object source) + private String connectedLineNum; + private String connectedLineName; + + + protected AbstractChannelEvent(Object source) { super(source); } @@ -137,4 +141,14 @@ public final void setCallerIdName(String callerIdName) { this.callerIdName = callerIdName; } + + + public String getConnectedLineNum () { return connectedLineNum;} + + public void setConnectedLineNum (String connectedLineNum) { this.connectedLineNum = connectedLineNum;} + + + public String getConnectedLineName () { return connectedLineName;} + + public void setConnectedLineName (String connectedLineName) { this.connectedLineName = connectedLineName;} } diff --git a/src/main/java/org/asteriskjava/manager/event/AgentCalledEvent.java b/src/main/java/org/asteriskjava/manager/event/AgentCalledEvent.java index 43ff9e108..0bcd1ed81 100644 --- a/src/main/java/org/asteriskjava/manager/event/AgentCalledEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/AgentCalledEvent.java @@ -42,6 +42,8 @@ public class AgentCalledEvent extends ManagerEvent private String destinationChannel; private String callerIdNum; private String callerIdName; + private String connectedLineNum; + private String connectedLineName; private String context; private String extension; private String priority; @@ -281,4 +283,14 @@ public void setVariables(Map variables) { this.variables = variables; } + + public String getConnectedLineNum () { return connectedLineNum;} + + public void setConnectedLineNum (String connectedLineNum) { this.connectedLineNum = connectedLineNum;} + + + public String getConnectedLineName () { return connectedLineName;} + + public void setConnectedLineName (String connectedLineName) { this.connectedLineName = connectedLineName;} + } diff --git a/src/main/java/org/asteriskjava/manager/event/DialEvent.java b/src/main/java/org/asteriskjava/manager/event/DialEvent.java index 8d95c9405..19cf54b11 100644 --- a/src/main/java/org/asteriskjava/manager/event/DialEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/DialEvent.java @@ -67,7 +67,11 @@ public class DialEvent extends ManagerEvent */ private String callerIdName; - /** + private String connectedLineNum; + private String connectedLineName; + + + /** * The unique id of the source channel. */ private String uniqueId; @@ -343,4 +347,15 @@ public void setDialStatus(String dialStatus) { this.dialStatus = dialStatus; } + + + public String getConnectedLineNum () { return connectedLineNum;} + + public void setConnectedLineNum (String connectedLineNum) { this.connectedLineNum = connectedLineNum;} + + + public String getConnectedLineName () { return connectedLineName;} + + public void setConnectedLineName (String connectedLineName) { this.connectedLineName = connectedLineName;} + } diff --git a/src/main/java/org/asteriskjava/manager/event/JoinEvent.java b/src/main/java/org/asteriskjava/manager/event/JoinEvent.java index 231ddd5d8..84d4e7dc6 100644 --- a/src/main/java/org/asteriskjava/manager/event/JoinEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/JoinEvent.java @@ -32,6 +32,8 @@ public class JoinEvent extends QueueEvent protected String callerIdNum; protected String callerIdName; + private String connectedLineNum; + private String connectedLineName; protected Integer position; public JoinEvent(Object source) @@ -119,4 +121,14 @@ public void setPosition(Integer position) { this.position = position; } + + public String getConnectedLineNum () { return connectedLineNum;} + + public void setConnectedLineNum (String connectedLineNum) { this.connectedLineNum = connectedLineNum;} + + + public String getConnectedLineName () { return connectedLineName;} + + public void setConnectedLineName (String connectedLineName) { this.connectedLineName = connectedLineName;} + } diff --git a/src/main/java/org/asteriskjava/manager/event/LeaveEvent.java b/src/main/java/org/asteriskjava/manager/event/LeaveEvent.java index 39864b855..6c2aeab52 100644 --- a/src/main/java/org/asteriskjava/manager/event/LeaveEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/LeaveEvent.java @@ -30,11 +30,18 @@ public class LeaveEvent extends QueueEvent */ static final long serialVersionUID = -7450401017732634240L; - /** + protected Integer position; + + /** * @param source */ public LeaveEvent(Object source) { super(source); } + + + public Integer getPosition () { return position;} + public void setPosition (Integer position) { this.position = position;} + } diff --git a/src/main/java/org/asteriskjava/manager/event/MeetMeLeaveEvent.java b/src/main/java/org/asteriskjava/manager/event/MeetMeLeaveEvent.java index 022bc99ed..19fad8bc3 100644 --- a/src/main/java/org/asteriskjava/manager/event/MeetMeLeaveEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MeetMeLeaveEvent.java @@ -33,7 +33,9 @@ public class MeetMeLeaveEvent extends AbstractMeetMeEvent private String callerIdNum; private String callerIdName; - private Long duration; + private String connectedLineNum; + private String connectedLineName; + private Long duration; /** * @param source @@ -105,4 +107,14 @@ public void setDuration(Long duration) { this.duration = duration; } + + public String getConnectedLineNum () { return connectedLineNum;} + + public void setConnectedLineNum (String connectedLineNum) { this.connectedLineNum = connectedLineNum;} + + + public String getConnectedLineName () { return connectedLineName;} + + public void setConnectedLineName (String connectedLineName) { this.connectedLineName = connectedLineName;} + } diff --git a/src/main/java/org/asteriskjava/manager/event/MusicOnHoldEvent.java b/src/main/java/org/asteriskjava/manager/event/MusicOnHoldEvent.java index eb7791bcd..c0f8cea63 100644 --- a/src/main/java/org/asteriskjava/manager/event/MusicOnHoldEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/MusicOnHoldEvent.java @@ -33,9 +33,10 @@ public class MusicOnHoldEvent extends ManagerEvent public static final String STATE_STOP = "Stop"; private String channel; + private String clazz; private String uniqueId; private String state; - + public MusicOnHoldEvent(Object source) { super(source); @@ -61,6 +62,16 @@ public void setChannel(String channel) this.channel = channel; } + public String getClazz() + { + return this.clazz; + } + + public void setClazz(String clazz) + { + this.clazz = clazz; + } + /** * Returns the unique id of the channel. * @@ -120,4 +131,4 @@ public boolean isStop() { return STATE_STOP.equals(state); } -} \ No newline at end of file +} diff --git a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java index 5a67336e0..8a673be55 100644 --- a/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/PeerEntryEvent.java @@ -44,6 +44,7 @@ public class PeerEntryEvent extends ResponseEvent private Integer port; private Boolean dynamic; private Boolean natSupport; + private Boolean forceRport; private Boolean videoSupport; private Boolean textSupport; private Boolean acl; @@ -190,6 +191,17 @@ public void setNatSupport(Boolean natSupport) this.natSupport = natSupport; } + /** + * Returns whether the nat option is set to force_rport.
+ * Available since Asterisk 1.8 + * + * @return true if the nat option is set to force_rport, + * false otherwise or null if not supported by Asterisk. + */ + public Boolean getForceRport() { return forceRport;} + + public void setForceRport(Boolean forceRport) { this.forceRport = forceRport;} + /** * Available since Asterisk 1.4. * diff --git a/src/main/java/org/asteriskjava/manager/event/PickupEvent.java b/src/main/java/org/asteriskjava/manager/event/PickupEvent.java new file mode 100644 index 000000000..ff1cb6e67 --- /dev/null +++ b/src/main/java/org/asteriskjava/manager/event/PickupEvent.java @@ -0,0 +1,33 @@ +package org.asteriskjava.manager.event; + +public class PickupEvent extends ManagerEvent { + private String channel; + private String targetChannel; + + + public PickupEvent (Object source) { + super(source); + } + + + /** + * + */ + private static final long serialVersionUID = 1L; + + + public String getChannel () { + return channel; + } + + + public void setChannel (String channel) { + this.channel = channel; + } + + + public String getTargetChannel () { return targetChannel;} + + public void setTargetChannel (String tch) { targetChannel = tch;} + +} \ No newline at end of file diff --git a/src/main/java/org/asteriskjava/manager/event/QueueEntryEvent.java b/src/main/java/org/asteriskjava/manager/event/QueueEntryEvent.java index a9543ab1e..cfe404d2d 100644 --- a/src/main/java/org/asteriskjava/manager/event/QueueEntryEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/QueueEntryEvent.java @@ -38,6 +38,8 @@ public class QueueEntryEvent extends ResponseEvent private String callerId; private String callerIdName; private String callerIdNum; + private String connectedLineNum; + private String connectedLineName; private Long wait; /** @@ -194,4 +196,14 @@ public void setWait(Long wait) { this.wait = wait; } + + public String getConnectedLineNum () { return connectedLineNum;} + + public void setConnectedLineNum (String connectedLineNum) { this.connectedLineNum = connectedLineNum;} + + + public String getConnectedLineName () { return connectedLineName;} + + public void setConnectedLineName (String connectedLineName) { this.connectedLineName = connectedLineName;} + } diff --git a/src/main/java/org/asteriskjava/manager/event/StatusEvent.java b/src/main/java/org/asteriskjava/manager/event/StatusEvent.java index 9f3f6606f..b5e34e44b 100644 --- a/src/main/java/org/asteriskjava/manager/event/StatusEvent.java +++ b/src/main/java/org/asteriskjava/manager/event/StatusEvent.java @@ -36,6 +36,8 @@ public class StatusEvent extends ResponseEvent private String channel; private String callerIdNum; private String callerIdName; + private String connectedLineNum; + private String connectedLineName; private String accountCode; private Integer channelState; private String channelStateDesc; @@ -400,4 +402,14 @@ public void setVariables(Map variables) { this.variables = variables; } + + public String getConnectedLineNum () { return connectedLineNum;} + + public void setConnectedLineNum (String connectedLineNum) { this.connectedLineNum = connectedLineNum;} + + + public String getConnectedLineName () { return connectedLineName;} + + public void setConnectedLineName (String connectedLineName) { this.connectedLineName = connectedLineName;} + } diff --git a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java index 94295d16e..90e715ad7 100644 --- a/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java +++ b/src/main/java/org/asteriskjava/manager/internal/AbstractBuilder.java @@ -47,6 +47,10 @@ protected void setAttributes(Object target, Map attributes, Set< if ("source".equals(setterName)) { setterName = "src"; + } + else if ("class".equals(setterName)) + { + setterName = "clazz"; } setter = setters.get(setterName); diff --git a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java index 22e7d1ae8..c38b44389 100644 --- a/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java +++ b/src/main/java/org/asteriskjava/manager/internal/EventBuilderImpl.java @@ -32,15 +32,18 @@ class EventBuilderImpl extends AbstractBuilder implements EventBuilder { private static final Set ignoredAttributes = new HashSet(Arrays.asList("event")); - private Map> registeredEventClasses; + private Map> registeredEventClasses; - EventBuilderImpl() + private static final Class[] OBJECT_ARG = {Object.class}; + + + EventBuilderImpl() { - this.registeredEventClasses = new HashMap>(); + registeredEventClasses = new HashMap>(); registerBuiltinEventClasses(); } - @SuppressWarnings({"deprecation"}) + @SuppressWarnings("deprecation") private void registerBuiltinEventClasses() { // please add new event classes alphabetically @@ -124,6 +127,7 @@ private void registerBuiltinEventClasses() registerEventClass(PeerEntryEvent.class); registerEventClass(PeerlistCompleteEvent.class); registerEventClass(PeerStatusEvent.class); + registerEventClass(PickupEvent.class); registerEventClass(PriEventEvent.class); registerEventClass(QueueCallerAbandonEvent.class); registerEventClass(QueueEntryEvent.class); @@ -173,7 +177,7 @@ private void registerBuiltinEventClasses() } - public final void registerEventClass(Class clazz) throws IllegalArgumentException + @Override public final void registerEventClass(Class clazz) throws IllegalArgumentException { String className; String eventType; @@ -205,9 +209,9 @@ public final void registerEventClass(Class clazz) throws */ public final void registerEventClass(String eventType, Class clazz) throws IllegalArgumentException { - Constructor defaultConstructor; + Constructor defaultConstructor; - if (!ManagerEvent.class.isAssignableFrom(clazz)) + if (!ManagerEvent.class.isAssignableFrom(clazz)) { throw new IllegalArgumentException(clazz + " is not a ManagerEvent"); } @@ -219,7 +223,7 @@ public final void registerEventClass(String eventType, Class attributes) - { - ManagerEvent event; - String eventType; - Class eventClass; - Constructor constructor; + @Override public ManagerEvent buildEvent(Object source, Map attributes) { - if (attributes.get("event") == null) + if (attributes.get("event") == null) { logger.error("No event type in properties"); return null; @@ -254,7 +253,7 @@ public ManagerEvent buildEvent(Object source, Map attributes) return null; } - eventType = ((String) attributes.get("event")).toLowerCase(Locale.US); + String eventType = attributes.get("event").toString().toLowerCase(Locale.US); // Change in Asterisk 1.4 where the name of the UserEvent is sent as property instead // of the event name (AJ-48) @@ -277,7 +276,7 @@ public ManagerEvent buildEvent(Object source, Map attributes) eventType = eventType + userEventType; } - eventClass = registeredEventClasses.get(eventType); + Class eventClass = registeredEventClasses.get(eventType); if (eventClass == null) { logger.info("No event class registered for event type '" + eventType + "', attributes: " + attributes @@ -285,9 +284,10 @@ public ManagerEvent buildEvent(Object source, Map attributes) return null; } + final Constructor constructor; try { - constructor = eventClass.getConstructor(new Class[]{Object.class}); + constructor = eventClass.getConstructor(OBJECT_ARG); } catch (NoSuchMethodException ex) { @@ -295,9 +295,10 @@ public ManagerEvent buildEvent(Object source, Map attributes) return null; } + final ManagerEvent event; try { - event = (ManagerEvent) constructor.newInstance(source); + event = constructor.newInstance(source); } catch (Exception ex) { diff --git a/src/main/java/org/asteriskjava/manager/response/PingResponse.java b/src/main/java/org/asteriskjava/manager/response/PingResponse.java index c0b77282c..211c70b25 100644 --- a/src/main/java/org/asteriskjava/manager/response/PingResponse.java +++ b/src/main/java/org/asteriskjava/manager/response/PingResponse.java @@ -28,6 +28,7 @@ public class PingResponse extends ManagerResponse private static final long serialVersionUID = 0L; private String ping; + private Double timestamp; /** * Returns always "Pong". @@ -43,4 +44,16 @@ public void setPing(String ping) { this.ping = ping; } + + /** + * Returns the timestamp for this response. + * In contains the time the response was generated in seconds since the epoch. + *

+ * Example: 1300978224.745639 + * + * @return the timestamp for this response. + */ + public Double getTimestamp() { return timestamp;} + public void setTimestamp(Double timestamp) { this.timestamp = timestamp;} + } \ No newline at end of file diff --git a/src/main/java/org/asteriskjava/tools/HtmlEventTracer.java b/src/main/java/org/asteriskjava/tools/HtmlEventTracer.java index 875411246..3f2a9aa16 100644 --- a/src/main/java/org/asteriskjava/tools/HtmlEventTracer.java +++ b/src/main/java/org/asteriskjava/tools/HtmlEventTracer.java @@ -133,7 +133,7 @@ public void write() StringBuilder line = new StringBuilder(); line.append(""); - line.append(getLocalName(event.getClass())); + line.append(event.getClass().getSimpleName()); line.append("
"); line.append(event.getDateReceived()); line.append(""); @@ -187,7 +187,8 @@ protected String getProperty(Object obj, String property) continue; } - return propertyDescriptor.getReadMethod().invoke(obj).toString(); + final Object o = propertyDescriptor.getReadMethod().invoke(obj); + return o != null ? o.toString() : null; } } catch (Exception e) @@ -199,14 +200,6 @@ protected String getProperty(Object obj, String property) return null; } - protected String getLocalName(Class c) - { - String s; - - s = c.getName(); - return s.substring(s.lastIndexOf(".") + 1, s.length()); - } - protected String getText(String uniqueId, ManagerEvent event) { String format = null; diff --git a/src/main/java/org/asteriskjava/util/DaemonThreadFactory.java b/src/main/java/org/asteriskjava/util/DaemonThreadFactory.java index 490a7b563..c54139b6c 100644 --- a/src/main/java/org/asteriskjava/util/DaemonThreadFactory.java +++ b/src/main/java/org/asteriskjava/util/DaemonThreadFactory.java @@ -20,19 +20,16 @@ public class DaemonThreadFactory implements ThreadFactory /** * Creates a new instance. */ - public DaemonThreadFactory() - { - namePrefix = "Asterisk-Java DaemonPool-" + poolNumber.getAndIncrement() + "-thread-"; - } + public DaemonThreadFactory() { + namePrefix = "AJ DaemonPool-"+ poolNumber.getAndIncrement() +'.'; + }//new - public Thread newThread(Runnable r) - { - final Thread thread; - thread = new Thread(r); + @Override public Thread newThread (Runnable r) { + final Thread thread = new Thread(r); thread.setDaemon(true); thread.setName(namePrefix + threadNumber.getAndIncrement()); return thread; } -} +} \ No newline at end of file diff --git a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java index 1f395ff6a..54a877adf 100644 --- a/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java +++ b/src/main/java/org/asteriskjava/util/internal/SocketConnectionFacadeImpl.java @@ -16,25 +16,18 @@ */ package org.asteriskjava.util.internal; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; +import org.asteriskjava.util.SocketConnectionFacade; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; +import java.io.*; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; -import java.util.Scanner; import java.util.NoSuchElementException; +import java.util.Scanner; import java.util.regex.Pattern; -import javax.net.SocketFactory; -import javax.net.ssl.SSLSocketFactory; - -import org.asteriskjava.util.SocketConnectionFacade; - /** * Default implementation of the SocketConnectionFacade interface using java.io. @@ -65,7 +58,7 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou { this(host, port, ssl, timeout, readTimeout, CRNL_PATTERN); } - + /** * Creates a new instance for use with the Manager API that uses the given line delimiter. * @@ -105,11 +98,15 @@ public SocketConnectionFacadeImpl(String host, int port, boolean ssl, int timeou * @param socket the underlying socket. * @throws IOException if the connection cannot be initialized. */ - SocketConnectionFacadeImpl(Socket socket) throws IOException - { - initialize(socket, NL_PATTERN); + SocketConnectionFacadeImpl(Socket socket) throws IOException { + socket.setSoTimeout(MAX_SOCKET_READ_TIMEOUT_MILLIS); + initialize(socket, NL_PATTERN); } + /** 70 mi = 70 * 60 * 1000 */ + private static final int MAX_SOCKET_READ_TIMEOUT_MILLIS = 4200000; + + private void initialize(Socket socket, Pattern pattern) throws IOException { this.socket = socket;