// **********************************************************************
//
// Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
package IceInternal;
class TcpAcceptor implements Acceptor
{
public java.nio.channels.ServerSocketChannel
fd()
{
return _fd;
}
public void
close()
{
if(_traceLevels.network >= 1)
{
String s = "stopping to accept tcp connections at " + toString();
_logger.trace(_traceLevels.networkCat, s);
}
assert(_fd != null);
Network.closeSocketNoThrow(_fd);
_fd = null;
}
public void
listen()
{
// Nothing to do.
if(_traceLevels.network >= 1)
{
StringBuffer s = new StringBuffer("accepting tcp connections at ");
s.append(toString());
java.util.List<String> interfaces =
Network.getHostsForEndpointExpand(_addr.getAddress().getHostAddress(), _instance.protocolSupport(),
true);
if(!interfaces.isEmpty())
{
s.append("\nlocal interfaces: ");
s.append(IceUtilInternal.StringUtil.joinString(interfaces, ", "));
}
_logger.trace(_traceLevels.networkCat, s.toString());
}
}
public Transceiver
accept()
{
java.nio.channels.SocketChannel fd = Network.doAccept(_fd);
Network.setBlock(fd, false);
Network.setTcpBufSize(fd, _instance.initializationData().properties, _logger);
if(_traceLevels.network >= 1)
{
String s = "accepted tcp connection\n" + Network.fdToString(fd);
_logger.trace(_traceLevels.networkCat, s);
}
return new TcpTransceiver(_instance, fd, true);
}
public String
toString()
{
return Network.addrToString(_addr);
}
int
effectivePort()
{
return _addr.getPort();
}
TcpAcceptor(Instance instance, String host, int port)
{
_instance = instance;
_traceLevels = instance.traceLevels();
_logger = instance.initializationData().logger;
_backlog = instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.TCP.Backlog", 511);
try
{
_fd = Network.createTcpServerSocket();
Network.setBlock(_fd, false);
Network.setTcpBufSize(_fd, _instance.initializationData().properties, _logger);
if(!System.getProperty("os.name").startsWith("Windows"))
{
//
// Enable SO_REUSEADDR on Unix platforms to allow
// re-using the socket even if it's in the TIME_WAIT
// state. On Windows, this doesn't appear to be
// necessary and enabling SO_REUSEADDR would actually
// not be a good thing since it allows a second
// process to bind to an address even it's already
// bound by another process.
//
// TODO: using SO_EXCLUSIVEADDRUSE on Windows would
// probably be better but it's only supported by recent
// Windows versions (XP SP2, Windows Server 2003).
//
Network.setReuseAddress(_fd, true);
}
_addr = Network.getAddressForServer(host, port, _instance.protocolSupport());
if(_traceLevels.network >= 2)
{
String s = "attempting to bind to tcp socket " + toString();
_logger.trace(_traceLevels.networkCat, s);
}
_addr = Network.doBind(_fd, _addr, _backlog);
}
catch(RuntimeException ex)
{
_fd = null;
throw ex;
}
}
protected synchronized void
finalize()
throws Throwable
{
IceUtilInternal.Assert.FinalizerAssert(_fd == null);
super.finalize();
}
private Instance _instance;
private TraceLevels _traceLevels;
private Ice.Logger _logger;
private java.nio.channels.ServerSocketChannel _fd;
private int _backlog;
private java.net.InetSocketAddress _addr;
}