AbstractProtocol (Apache Tomcat 11.0.23 API Documentation)
Description: declaration: package: org.apache.coyote, class: AbstractProtocol

# Class AbstractProtocol<S>

java.lang.Object
org.apache.coyote.AbstractProtocol<S>

Type Parameters:
  `S` - the type of the socket

All Implemented Interfaces:
  `MBeanRegistration, ProtocolHandler`

Direct Known Subclasses:
  `AbstractAjpProtocol, AbstractHttp11Protocol`

public abstract class AbstractProtocol<S> extends Object implements ProtocolHandler, MBeanRegistration
Abstract base class for protocol handlers.

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `protected static class`
  `AbstractProtocol.ConnectionHandler<S>`
  Connection handler base class.
  `protected static class`
  `AbstractProtocol.RecycledProcessors`
  Pool of recycled processors.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected Adapter`
  `adapter`
  The adapter provides the link between the ProtocolHandler and the connector.
  `protected String`
  `domain`
  The domain for JMX.
  `protected MBeanServer`
  `mserver`
  The MBean server.
  `protected ObjectName`
  `oname`
  The JMX object name.
  `protected int`
  `processorCache`
  The maximum number of idle processors that will be retained in the cache and re-used with a subsequent request.
  `protected ObjectName`
  `rgOname`
  Name of MBean for the Global Request Processor.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `AbstractProtocol(AbstractEndpoint<S,?> endpoint)`
  Creates a new protocol handler.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `addWaitingProcessor(Processor processor)`
  Adds a processor to the waiting processors set.
  `long`
  `awaitConnectionsClose(long waitMillis)`
  Awaits for connections to close.
  `void`
  `closeServerSocketGraceful()`
  Closes the server socket gracefully.
  `protected abstract Processor`
  `createProcessor()`
  Create and configure a new Processor instance for the current protocol implementation.
  `protected abstract Processor`
  `createUpgradeProcessor(SocketWrapperBase<?> socket, UpgradeToken upgradeToken)`
  Create and configure a new Processor instance for upgrade connections.
  `void`
  `destroy()`
  Destroys the protocol handler.
  `int`
  `getAcceptCount()`
  Gets the accept count.
  `int`
  `getAcceptorThreadPriority()`
  Gets the acceptor thread priority.
  `Adapter`
  `getAdapter()`
  Gets the adapter.
  `InetAddress`
  `getAddress()`
  Gets the address.
  `String`
  `getClientCertProvider()`
  When client certificate information is presented in a form other than instances of `X509Certificate` it needs to be converted before it can be used and this property controls which JSSE provider is used to perform the conversion.
  `long`
  `getConnectionCount()`
  Gets the connection count.
  `int`
  `getConnectionLinger()`
  Gets the connection linger time.
  `int`
  `getConnectionTimeout()`
  Gets the connection timeout.
  `String`
  `getDomain()`
  Gets the domain.
  `protected AbstractEndpoint<S,?>`
  `getEndpoint()`
  Gets the endpoint.
  `Executor`
  `getExecutor()`
  Gets the executor for this protocol handler.
  `ObjectName`
  `getGlobalRequestProcessorMBeanName()`
  Gets the MBean name for the Global Request Processor.
  `AbstractEndpoint.Handler<S>`
  `getHandler()`
  Gets the handler.
  `String`
  `getId()`
  Gets the protocol ID.
  `int`
  `getKeepAliveTimeout()`
  The time Tomcat will wait for a subsequent request before closing the connection.
  `int`
  `getLocalPort()`
  Gets the local port.
  `protected abstract Log`
  `getLog()`
  Concrete implementations need to provide access to their logger to be used by the abstract classes.
  `int`
  `getMaxConnections()`
  Gets the maximum number of connections.
  `int`
  `getMaxHeaderCount()`
  Gets the maximum header count.
  `int`
  `getMaxQueueSize()`
  Gets the maximum queue size.
  `int`
  `getMaxThreads()`
  Gets the maximum number of threads.
  `int`
  `getMinSpareThreads()`
  Gets the minimum number of spare threads.
  `String`
  `getName()`
  Gets the name of this protocol instance.
  `int`
  `getNameIndex()`
  Gets the name index for this protocol.
  `protected abstract String`
  `getNamePrefix()`
  Obtain the prefix to be used when construction a name for this protocol handler.
  `protected abstract UpgradeProtocol`
  `getNegotiatedProtocol(String name)`
  Find a suitable handler for the protocol negotiated at the network layer.
  `ObjectName`
  `getObjectName()`
  Gets the object name.
  `int`
  `getPort()`
  Gets the port.
  `int`
  `getPortOffset()`
  Gets the port offset.
  `int`
  `getPortWithOffset()`
  Gets the port with offset applied.
  `int`
  `getProcessorCache()`
  Gets the processor cache size.
  `String`
  `getProperty(String name)`
  Generic property getter used by the digester.
  `protected abstract String`
  `getProtocolName()`
  Obtain the name of the protocol, (Http, Ajp, etc.).
  `boolean`
  `getTcpNoDelay()`
  Gets whether TCP no-delay is enabled.
  `int`
  `getThreadPriority()`
  Gets the thread priority.
  `protected abstract UpgradeProtocol`
  `getUpgradeProtocol(String name)`
  Find a suitable handler for the protocol upgraded name specified.
  `ScheduledExecutorService`
  `getUtilityExecutor()`
  Gets the utility executor for this protocol handler.
  `int`
  `getWaitingProcessorCount()`
  Gets the count of waiting processors.
  `void`
  `init()`
  Initializes the protocol handler.
  `boolean`
  `isPaused()`
  Checks if the protocol handler is paused.
  `boolean`
  `isSendfileSupported()`
  Checks if sendfile is supported.
  `void`
  `pause()`
  Pauses the protocol handler.
  `void`
  `postDeregister()`
  Post-deregisters this MBean.
  `void`
  `postRegister(Boolean registrationDone)`
  Post-registers this MBean.
  `void`
  `preDeregister()`
  Pre-deregisters this MBean.
  `ObjectName`
  `preRegister(MBeanServer server, ObjectName name)`
  Pre-registers this MBean.
  `void`
  `removeWaitingProcessor(Processor processor)`
  Removes a processor from the waiting processors set.
  `void`
  `resume()`
  Resumes the protocol handler.
  `void`
  `setAcceptCount(int acceptCount)`
  Sets the accept count.
  `void`
  `setAcceptorThreadPriority(int threadPriority)`
  Sets the acceptor thread priority.
  `void`
  `setAdapter(Adapter adapter)`
  Sets the adapter.
  `void`
  `setAddress(InetAddress ia)`
  Sets the address.
  `void`
  `setClientCertProvider(String s)`
  Sets the JSSE provider to use for client certificate conversion.
  `void`
  `setConnectionLinger(int connectionLinger)`
  Sets the connection linger time.
  `void`
  `setConnectionTimeout(int timeout)`
  Sets the connection timeout.
  `void`
  `setExecutor(Executor executor)`
  Sets the executor for this protocol handler.
  `protected void`
  `setHandler(AbstractEndpoint.Handler<S> handler)`
  Sets the handler.
  `void`
  `setKeepAliveTimeout(int keepAliveTimeout)`
  Sets the keep-alive timeout.
  `void`
  `setMaxConnections(int maxConnections)`
  Sets the maximum number of connections.
  `void`
  `setMaxHeaderCount(int maxHeaderCount)`
  Sets the maximum header count.
  `void`
  `setMaxQueueSize(int maxQueueSize)`
  Sets the maximum queue size.
  `void`
  `setMaxThreads(int maxThreads)`
  Sets the maximum number of threads.
  `void`
  `setMinSpareThreads(int minSpareThreads)`
  Sets the minimum number of spare threads.
  `void`
  `setPort(int port)`
  Sets the port.
  `void`
  `setPortOffset(int portOffset)`
  Sets the port offset.
  `void`
  `setProcessorCache(int processorCache)`
  Sets the maximum number of idle processors to cache.
  `boolean`
  `setProperty(String name, String value)`
  Generic property setter used by the digester.
  `void`
  `setTcpNoDelay(boolean tcpNoDelay)`
  Sets whether TCP no-delay is enabled.
  `void`
  `setThreadPriority(int threadPriority)`
  Sets the thread priority.
  `void`
  `setUtilityExecutor(ScheduledExecutorService utilityExecutor)`
  Sets the utility executor for this protocol handler.
  `void`
  `start()`
  Starts the protocol handler.
  `protected void`
  `startAsyncTimeout()`
  Note: The name of this method originated with the Servlet 3.0 asynchronous processing but evolved over time to represent a timeout that is triggered independently of the socket read/write timeouts.
  `void`
  `stop()`
  Stops the protocol handler.
  `protected void`
  `stopAsyncTimeout()`
  Stops the async timeout scheduler.

  ### Methods inherited from class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

  ### Methods inherited from interface ProtocolHandler

  `addSslHostConfig, addSslHostConfig, addUpgradeProtocol, findSslHostConfigs, findUpgradeProtocols, getDesiredBufferSize`

- ## Field Details

  - ### rgOname

    protected ObjectName rgOname
    Name of MBean for the Global Request Processor.

  - ### adapter

    protected Adapter adapter
    The adapter provides the link between the ProtocolHandler and the connector.

  - ### processorCache

    protected int processorCache
    The maximum number of idle processors that will be retained in the cache and re-used with a subsequent request. The default is 200. A value of -1 means unlimited. In the unlimited case, the theoretical maximum number of cached Processor objects is `getMaxConnections()` although it will usually be closer to `getMaxThreads()`.

  - ### domain

    protected String domain
    The domain for JMX.

  - ### oname

    protected ObjectName oname
    The JMX object name.

  - ### mserver

    protected MBeanServer mserver
    The MBean server.

- ## Constructor Details

  - ### AbstractProtocol

    public AbstractProtocol(AbstractEndpoint<S,?> endpoint)
    Creates a new protocol handler.
    Parameters:
      `endpoint` - The endpoint for low-level network I/O

- ## Method Details

  - ### setProperty

    public boolean setProperty(String name, String value)
    Generic property setter used by the digester. Other code should not need to use this. The digester will only use this method if it can't find a more specific setter. That means the property belongs to the Endpoint, the ServerSocketFactory or some other lower level component. This method ensures that it is visible to both.
    Parameters:
      `name` - The name of the property to set
      `value` - The value, in string form, to set for the property
    Returns:
      `true` if the property was set successfully, otherwise `false`

  - ### getProperty

    public String getProperty(String name)
    Generic property getter used by the digester. Other code should not need to use this.
    Parameters:
      `name` - The name of the property to get
    Returns:
      The value of the property converted to a string

  - ### getGlobalRequestProcessorMBeanName

    public ObjectName getGlobalRequestProcessorMBeanName()
    Gets the MBean name for the Global Request Processor.
    Returns:
      the MBean name

  - ### setAdapter

    public void setAdapter(Adapter adapter)
    Sets the adapter.
    Specified by:
      `setAdapter` in interface `ProtocolHandler`
    Parameters:
      `adapter` - The adapter

  - ### getAdapter

    public Adapter getAdapter()
    Gets the adapter.
    Specified by:
      `getAdapter` in interface `ProtocolHandler`
    Returns:
      the adapter

  - ### getProcessorCache

    public int getProcessorCache()
    Gets the processor cache size.
    Returns:
      the processor cache size

  - ### setProcessorCache

    public void setProcessorCache(int processorCache)
    Sets the maximum number of idle processors to cache.
    Parameters:
      `processorCache` - The processor cache size (-1 for unlimited)

  - ### getClientCertProvider

    public String getClientCertProvider()
    When client certificate information is presented in a form other than instances of `X509Certificate` it needs to be converted before it can be used and this property controls which JSSE provider is used to perform the conversion. For example it is used with the AJP connectors and with the `SSLValve`. If not specified, the default provider will be used.
    Returns:
      The name of the JSSE provider to use

  - ### setClientCertProvider

    public void setClientCertProvider(String s)
    Sets the JSSE provider to use for client certificate conversion.
    Parameters:
      `s` - The provider name

  - ### getMaxHeaderCount

    public int getMaxHeaderCount()
    Gets the maximum header count.
    Returns:
      the maximum header count

  - ### setMaxHeaderCount

    public void setMaxHeaderCount(int maxHeaderCount)
    Sets the maximum header count.
    Parameters:
      `maxHeaderCount` - The maximum header count

  - ### isSendfileSupported

    public boolean isSendfileSupported()
    Checks if sendfile is supported.
    Specified by:
      `isSendfileSupported` in interface `ProtocolHandler`
    Returns:
      `true` if sendfile is supported

  - ### getId

    public String getId()
    Gets the protocol ID.
    Specified by:
      `getId` in interface `ProtocolHandler`
    Returns:
      the protocol ID

  - ### getExecutor

    public Executor getExecutor()
    Gets the executor for this protocol handler.
    Specified by:
      `getExecutor` in interface `ProtocolHandler`
    Returns:
      the executor

  - ### setExecutor

    public void setExecutor(Executor executor)
    Sets the executor for this protocol handler.
    Specified by:
      `setExecutor` in interface `ProtocolHandler`
    Parameters:
      `executor` - The executor

  - ### getUtilityExecutor

    public ScheduledExecutorService getUtilityExecutor()
    Gets the utility executor for this protocol handler.
    Specified by:
      `getUtilityExecutor` in interface `ProtocolHandler`
    Returns:
      The utility executor

  - ### setUtilityExecutor

    public void setUtilityExecutor(ScheduledExecutorService utilityExecutor)
    Sets the utility executor for this protocol handler.
    Specified by:
      `setUtilityExecutor` in interface `ProtocolHandler`
    Parameters:
      `utilityExecutor` - The utility executor

  - ### getMaxThreads

    public int getMaxThreads()
    Gets the maximum number of threads.
    Returns:
      the maximum number of threads

  - ### setMaxThreads

    public void setMaxThreads(int maxThreads)
    Sets the maximum number of threads.
    Parameters:
      `maxThreads` - The maximum number of threads

  - ### getMaxConnections

    public int getMaxConnections()
    Gets the maximum number of connections.
    Returns:
      the maximum number of connections

  - ### setMaxConnections

    public void setMaxConnections(int maxConnections)
    Sets the maximum number of connections.
    Parameters:
      `maxConnections` - The maximum number of connections

  - ### getMinSpareThreads

    public int getMinSpareThreads()
    Gets the minimum number of spare threads.
    Returns:
      the minimum spare threads

  - ### setMinSpareThreads

    public void setMinSpareThreads(int minSpareThreads)
    Sets the minimum number of spare threads.
    Parameters:
      `minSpareThreads` - The minimum spare threads

  - ### getThreadPriority

    public int getThreadPriority()
    Gets the thread priority.
    Returns:
      the thread priority

  - ### setThreadPriority

    public void setThreadPriority(int threadPriority)
    Sets the thread priority.
    Parameters:
      `threadPriority` - The thread priority

  - ### getMaxQueueSize

    public int getMaxQueueSize()
    Gets the maximum queue size.
    Returns:
      the maximum queue size

  - ### setMaxQueueSize

    public void setMaxQueueSize(int maxQueueSize)
    Sets the maximum queue size.
    Parameters:
      `maxQueueSize` - The maximum queue size

  - ### getAcceptCount

    public int getAcceptCount()
    Gets the accept count.
    Returns:
      the accept count

  - ### setAcceptCount

    public void setAcceptCount(int acceptCount)
    Sets the accept count.
    Parameters:
      `acceptCount` - The accept count

  - ### getTcpNoDelay

    public boolean getTcpNoDelay()
    Gets whether TCP no-delay is enabled.
    Returns:
      `true` if TCP no-delay is enabled

  - ### setTcpNoDelay

    public void setTcpNoDelay(boolean tcpNoDelay)
    Sets whether TCP no-delay is enabled.
    Parameters:
      `tcpNoDelay` - `true` to enable TCP no-delay

  - ### getConnectionLinger

    public int getConnectionLinger()
    Gets the connection linger time.
    Returns:
      the connection linger time

  - ### setConnectionLinger

    public void setConnectionLinger(int connectionLinger)
    Sets the connection linger time.
    Parameters:
      `connectionLinger` - The connection linger time

  - ### getKeepAliveTimeout

    public int getKeepAliveTimeout()
    The time Tomcat will wait for a subsequent request before closing the connection. The default is `getConnectionTimeout()`.
    Returns:
      The timeout in milliseconds

  - ### setKeepAliveTimeout

    public void setKeepAliveTimeout(int keepAliveTimeout)
    Sets the keep-alive timeout.
    Parameters:
      `keepAliveTimeout` - The keep-alive timeout in milliseconds

  - ### getAddress

    public InetAddress getAddress()
    Gets the address.
    Returns:
      the address

  - ### setAddress

    public void setAddress(InetAddress ia)
    Sets the address.
    Parameters:
      `ia` - The address

  - ### getPort

    public int getPort()
    Gets the port.
    Returns:
      the port

  - ### setPort

    public void setPort(int port)
    Sets the port.
    Parameters:
      `port` - The port

  - ### getPortOffset

    public int getPortOffset()
    Gets the port offset.
    Returns:
      the port offset

  - ### setPortOffset

    public void setPortOffset(int portOffset)
    Sets the port offset.
    Parameters:
      `portOffset` - The port offset

  - ### getPortWithOffset

    public int getPortWithOffset()
    Gets the port with offset applied.
    Returns:
      the port with offset

  - ### getLocalPort

    public int getLocalPort()
    Gets the local port.
    Returns:
      the local port

  - ### getConnectionTimeout

    public int getConnectionTimeout()
    Gets the connection timeout. When Tomcat expects data from the client, this is the time Tomcat will wait for that data to arrive before closing the connection.
    Returns:
      the connection timeout

  - ### setConnectionTimeout

    public void setConnectionTimeout(int timeout)
    Sets the connection timeout.
    Parameters:
      `timeout` - The connection timeout in milliseconds

  - ### getConnectionCount

    public long getConnectionCount()
    Gets the connection count.
    Returns:
      the connection count

  - ### setAcceptorThreadPriority

    public void setAcceptorThreadPriority(int threadPriority)
    Sets the acceptor thread priority.
    Parameters:
      `threadPriority` - The thread priority

  - ### getAcceptorThreadPriority

    public int getAcceptorThreadPriority()
    Gets the acceptor thread priority.
    Returns:
      the acceptor thread priority

  - ### getNameIndex

    public int getNameIndex()
    Gets the name index for this protocol.
    Returns:
      the name index

  - ### getName

    public String getName()
    Gets the name of this protocol instance. The name will be prefix-address-port if address is non-null and prefix-port if the address is null.
    Returns:
      A name for this protocol instance that is appropriately quoted for use in an ObjectName.

  - ### addWaitingProcessor

    public void addWaitingProcessor(Processor processor)
    Adds a processor to the waiting processors set.
    Parameters:
      `processor` - The processor

  - ### removeWaitingProcessor

    public void removeWaitingProcessor(Processor processor)
    Removes a processor from the waiting processors set.
    Parameters:
      `processor` - The processor

  - ### getWaitingProcessorCount

    public int getWaitingProcessorCount()
    Gets the count of waiting processors.
    Returns:
      the waiting processor count

  - ### getEndpoint

    protected AbstractEndpoint<S,?> getEndpoint()
    Gets the endpoint.
    Returns:
      the endpoint

  - ### getHandler

    public AbstractEndpoint.Handler<S> getHandler()
    Gets the handler.
    Returns:
      the handler

  - ### setHandler

    protected void setHandler(AbstractEndpoint.Handler<S> handler)
    Sets the handler.
    Parameters:
      `handler` - The handler

  - ### getLog

    protected abstract Log getLog()
    Concrete implementations need to provide access to their logger to be used by the abstract classes.
    Returns:
      the logger

  - ### getNamePrefix

    protected abstract String getNamePrefix()
    Obtain the prefix to be used when construction a name for this protocol handler. The name will be prefix-address-port.
    Returns:
      the prefix

  - ### getProtocolName

    protected abstract String getProtocolName()
    Obtain the name of the protocol, (Http, Ajp, etc.). Used with JMX.
    Returns:
      the protocol name

  - ### getNegotiatedProtocol

    protected abstract UpgradeProtocol getNegotiatedProtocol(String name)
    Find a suitable handler for the protocol negotiated at the network layer.
    Parameters:
      `name` - The name of the requested negotiated protocol.
    Returns:
      The instance where `UpgradeProtocol.getAlpnName()` matches the requested protocol

  - ### getUpgradeProtocol

    protected abstract UpgradeProtocol getUpgradeProtocol(String name)
    Find a suitable handler for the protocol upgraded name specified. This is used for direct connection protocol selection.
    Parameters:
      `name` - The name of the requested negotiated protocol.
    Returns:
      The instance where `UpgradeProtocol.getAlpnName()` matches the requested protocol

  - ### createProcessor

    protected abstract Processor createProcessor()
    Create and configure a new Processor instance for the current protocol implementation.
    Returns:
      A fully configured Processor instance that is ready to use

  - ### createUpgradeProcessor

    protected abstract Processor createUpgradeProcessor(SocketWrapperBase<?> socket, UpgradeToken upgradeToken)
    Create and configure a new Processor instance for upgrade connections.
    Parameters:
      `socket` - The socket for the upgrade connection
      `upgradeToken` - The upgrade token containing upgrade information
    Returns:
      A fully configured Processor instance that is ready to use

  - ### getObjectName

    public ObjectName getObjectName()
    Gets the object name.
    Returns:
      the object name

  - ### getDomain

    public String getDomain()
    Gets the domain.
    Returns:
      the domain

  - ### preRegister

    public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception
    Pre-registers this MBean.
    Specified by:
      `preRegister` in interface `MBeanRegistration`
    Parameters:
      `server` - The MBean server
      `name` - The object name
    Returns:
      the object name
    Throws:
      `Exception` - if registration fails

  - ### postRegister

    public void postRegister(Boolean registrationDone)
    Post-registers this MBean.
    Specified by:
      `postRegister` in interface `MBeanRegistration`
    Parameters:
      `registrationDone` - The registration status

  - ### preDeregister

    public void preDeregister() throws Exception
    Pre-deregisters this MBean.
    Specified by:
      `preDeregister` in interface `MBeanRegistration`
    Throws:
      `Exception` - if deregistration fails

  - ### postDeregister

    public void postDeregister()
    Post-deregisters this MBean.
    Specified by:
      `postDeregister` in interface `MBeanRegistration`

  - ### init

    public void init() throws Exception
    Initializes the protocol handler.
    Specified by:
      `init` in interface `ProtocolHandler`
    Throws:
      `Exception` - if initialization fails

  - ### start

    public void start() throws Exception
    Starts the protocol handler.
    Specified by:
      `start` in interface `ProtocolHandler`
    Throws:
      `Exception` - if start fails

  - ### startAsyncTimeout

    protected void startAsyncTimeout()
    Note: The name of this method originated with the Servlet 3.0 asynchronous processing but evolved over time to represent a timeout that is triggered independently of the socket read/write timeouts.

  - ### stopAsyncTimeout

    protected void stopAsyncTimeout()
    Stops the async timeout scheduler.

  - ### pause

    public void pause() throws Exception
    Pauses the protocol handler.
    Specified by:
      `pause` in interface `ProtocolHandler`
    Throws:
      `Exception` - if pause fails

  - ### isPaused

    public boolean isPaused()
    Checks if the protocol handler is paused.
    Returns:
      `true` if paused

  - ### resume

    public void resume() throws Exception
    Resumes the protocol handler.
    Specified by:
      `resume` in interface `ProtocolHandler`
    Throws:
      `Exception` - if resume fails

  - ### stop

    public void stop() throws Exception
    Stops the protocol handler.
    Specified by:
      `stop` in interface `ProtocolHandler`
    Throws:
      `Exception` - if stop fails

  - ### destroy

    public void destroy() throws Exception
    Destroys the protocol handler.
    Specified by:
      `destroy` in interface `ProtocolHandler`
    Throws:
      `Exception` - if destroy fails

  - ### closeServerSocketGraceful

    public void closeServerSocketGraceful()
    Closes the server socket gracefully.
    Specified by:
      `closeServerSocketGraceful` in interface `ProtocolHandler`

  - ### awaitConnectionsClose

    public long awaitConnectionsClose(long waitMillis)
    Awaits for connections to close.
    Specified by:
      `awaitConnectionsClose` in interface `ProtocolHandler`
    Parameters:
      `waitMillis` - The maximum time to wait in milliseconds
    Returns:
      the number of connections remaining after the wait