summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpp/src/Ice/ConnectionI.cpp2
-rw-r--r--java/src/Ice/ConnectionI.java612
-rw-r--r--java/src/IceInternal/Acceptor.java1
-rw-r--r--java/src/IceInternal/EndpointFactory.java4
-rw-r--r--java/src/IceInternal/EndpointFactoryManager.java145
-rw-r--r--java/src/IceInternal/EndpointHostResolver.java25
-rw-r--r--java/src/IceInternal/EndpointI.java105
-rw-r--r--java/src/IceInternal/EventHandler.java17
-rw-r--r--java/src/IceInternal/EventHandlerOpPair.java22
-rw-r--r--java/src/IceInternal/IPEndpointI.java327
-rw-r--r--java/src/IceInternal/IncomingConnectionFactory.java7
-rw-r--r--java/src/IceInternal/Instance.java6
-rw-r--r--java/src/IceInternal/OpaqueEndpointI.java331
-rw-r--r--java/src/IceInternal/OutgoingConnectionFactory.java15
-rw-r--r--java/src/IceInternal/ProtocolInstance.java114
-rw-r--r--java/src/IceInternal/ProtocolPluginFacade.java36
-rw-r--r--java/src/IceInternal/ProtocolPluginFacadeI.java80
-rw-r--r--java/src/IceInternal/RoutableReference.java1
-rw-r--r--java/src/IceInternal/Selector.java316
-rw-r--r--java/src/IceInternal/TcpAcceptor.java38
-rw-r--r--java/src/IceInternal/TcpConnector.java39
-rw-r--r--java/src/IceInternal/TcpEndpointFactory.java34
-rw-r--r--java/src/IceInternal/TcpEndpointI.java486
-rw-r--r--java/src/IceInternal/TcpTransceiver.java127
-rw-r--r--java/src/IceInternal/ThreadPool.java152
-rw-r--r--java/src/IceInternal/ThreadPoolWorkQueue.java6
-rw-r--r--java/src/IceInternal/Transceiver.java31
-rw-r--r--java/src/IceInternal/UdpConnector.java26
-rw-r--r--java/src/IceInternal/UdpEndpointFactory.java34
-rw-r--r--java/src/IceInternal/UdpEndpointI.java607
-rw-r--r--java/src/IceInternal/UdpTransceiver.java394
-rw-r--r--java/src/IceSSL/AcceptorI.java58
-rw-r--r--java/src/IceSSL/ConnectorI.java33
-rw-r--r--java/src/IceSSL/EndpointFactoryI.java28
-rw-r--r--java/src/IceSSL/EndpointI.java476
-rw-r--r--java/src/IceSSL/Instance.java1184
-rw-r--r--java/src/IceSSL/PluginI.java70
-rw-r--r--java/src/IceSSL/SharedInstance.java1140
-rw-r--r--java/src/IceSSL/TransceiverI.java187
-rw-r--r--java/src/IceSSL/X509TrustManagerI.java4
-rw-r--r--java/test/Ice/background/Acceptor.java6
-rw-r--r--java/test/Ice/background/Configuration.java13
-rw-r--r--java/test/Ice/background/EndpointFactory.java19
-rw-r--r--java/test/Ice/background/EndpointI.java81
-rw-r--r--java/test/Ice/background/Transceiver.java89
-rw-r--r--java/test/Ice/hold/HoldI.java2
46 files changed, 3568 insertions, 3962 deletions
diff --git a/cpp/src/Ice/ConnectionI.cpp b/cpp/src/Ice/ConnectionI.cpp
index 9dc3ff4efa5..f36c83f62fa 100644
--- a/cpp/src/Ice/ConnectionI.cpp
+++ b/cpp/src/Ice/ConnectionI.cpp
@@ -3263,6 +3263,7 @@ Ice::ConnectionI::parseMessage(BasicStream& stream, Int& invokeNum, Int& request
}
setState(StateClosed);
}
+ break;
}
case requestMsg:
@@ -3416,7 +3417,6 @@ Ice::ConnectionI::parseMessage(BasicStream& stream, Int& invokeNum, Int& request
{
trace("received unknown message\n(invalid, closing connection)", stream, _logger, _traceLevels);
throw UnknownMessageException(__FILE__, __LINE__);
- break;
}
}
}
diff --git a/java/src/Ice/ConnectionI.java b/java/src/Ice/ConnectionI.java
index c001462c960..fb2c0ce8a33 100644
--- a/java/src/Ice/ConnectionI.java
+++ b/java/src/Ice/ConnectionI.java
@@ -341,7 +341,6 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
sendRequest(IceInternal.Outgoing out, boolean compress, boolean response)
throws IceInternal.LocalExceptionWrapper
{
- int requestId = 0;
final IceInternal.BasicStream os = out.os();
if(_exception != null)
@@ -363,6 +362,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
//
_transceiver.checkSendSize(os.getBuffer(), _instance.messageSizeMax());
+ int requestId = 0;
if(response)
{
//
@@ -382,7 +382,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
os.writeInt(requestId);
}
- out.attachRemoteObserver(initConnectionInfo(), _endpoint, requestId,
+ out.attachRemoteObserver(initConnectionInfo(), _endpoint, requestId,
os.size() - IceInternal.Protocol.headerSize - 4);
//
@@ -418,7 +418,6 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
sendAsyncRequest(IceInternal.OutgoingAsync out, boolean compress, boolean response)
throws IceInternal.LocalExceptionWrapper
{
- int requestId = 0;
final IceInternal.BasicStream os = out.__getOs();
if(_exception != null)
@@ -440,6 +439,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
//
_transceiver.checkSendSize(os.getBuffer(), _instance.messageSizeMax());
+ int requestId = 0;
if(response)
{
//
@@ -459,13 +459,13 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
os.writeInt(requestId);
}
- out.__attachRemoteObserver(initConnectionInfo(), _endpoint, requestId,
+ out.__attachRemoteObserver(initConnectionInfo(), _endpoint, requestId,
os.size() - IceInternal.Protocol.headerSize - 4);
int status;
try
{
- status = sendMessage(new OutgoingMessage(out, out.__getOs(), compress, requestId));
+ status = sendMessage(new OutgoingMessage(out, os, compress, requestId));
}
catch(Ice.LocalException ex)
{
@@ -505,8 +505,8 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
if(_exception != null)
{
//
- // If there were no batch requests queued when the connection failed, we can safely
- // retry with a new connection. Otherwise, we must throw to notify the caller that
+ // If there were no batch requests queued when the connection failed, we can safely
+ // retry with a new connection. Otherwise, we must throw to notify the caller that
// some previous batch requests were not sent.
//
if(_batchStream.isEmpty())
@@ -597,6 +597,9 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
buffer.b.get(lastRequest);
_batchStream.resize(_batchMarker, false);
+ //
+ // Send the batch stream without the last request.
+ //
try
{
//
@@ -673,7 +676,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
public synchronized void
abortBatchRequest()
{
- _batchStream = new IceInternal.BasicStream(_instance, IceInternal.Protocol.currentProtocolEncoding,
+ _batchStream = new IceInternal.BasicStream(_instance, IceInternal.Protocol.currentProtocolEncoding,
_batchAutoFlush);
_batchRequestNum = 0;
_batchRequestCompress = false;
@@ -711,7 +714,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
{
return begin_flushBatchRequestsInternal(cb);
}
-
+
public AsyncResult
begin_flushBatchRequests(IceInternal.Functional_VoidCallback __responseCb,
IceInternal.Functional_GenericCallback1<Ice.LocalException> __localExceptionCb,
@@ -793,6 +796,9 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_batchStream.swap(out.os());
+ //
+ // Send the batch stream.
+ //
boolean sent = false;
try
{
@@ -809,7 +815,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
//
// Reset the batch stream.
//
- _batchStream = new IceInternal.BasicStream(_instance, IceInternal.Protocol.currentProtocolEncoding,
+ _batchStream = new IceInternal.BasicStream(_instance, IceInternal.Protocol.currentProtocolEncoding,
_batchAutoFlush);
_batchRequestNum = 0;
_batchRequestCompress = false;
@@ -857,6 +863,9 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_batchStream.swap(outAsync.__getOs());
+ //
+ // Send the batch stream.
+ //
int status;
try
{
@@ -873,7 +882,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
//
// Reset the batch stream.
//
- _batchStream = new IceInternal.BasicStream(_instance, IceInternal.Protocol.currentProtocolEncoding,
+ _batchStream = new IceInternal.BasicStream(_instance, IceInternal.Protocol.currentProtocolEncoding,
_batchAutoFlush);
_batchRequestNum = 0;
_batchRequestCompress = false;
@@ -1103,7 +1112,6 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
{
return;
}
- assert(_state < StateClosing);
_adapter = adapter;
@@ -1166,36 +1174,49 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
return;
}
+ int readyOp = current.operation;
try
{
unscheduleTimeout(current.operation);
- if((current.operation & IceInternal.SocketOperation.Write) != 0 && !_writeStream.isEmpty())
+
+ int writeOp = IceInternal.SocketOperation.None;
+ int readOp = IceInternal.SocketOperation.None;
+
+ if((readyOp & IceInternal.SocketOperation.Write) != 0)
{
+ final IceInternal.Buffer buf = _writeStream.getBuffer();
if(_observer != null)
{
- observerStartWrite(_writeStream.pos());
+ observerStartWrite(buf);
}
- if(!_transceiver.write(_writeStream.getBuffer()))
+ writeOp = _transceiver.write(buf);
+ if(_observer != null && (writeOp & IceInternal.SocketOperation.Write) == 0)
{
- assert(!_writeStream.isEmpty());
- scheduleTimeout(IceInternal.SocketOperation.Write, _endpoint.timeout());
- return;
- }
- if(_observer != null)
- {
- observerFinishWrite(_writeStream.pos());
+ observerFinishWrite(buf);
}
- assert(!_writeStream.getBuffer().b.hasRemaining());
}
- if((current.operation & IceInternal.SocketOperation.Read) != 0 && !_readStream.isEmpty())
+
+ while((readyOp & IceInternal.SocketOperation.Read) != 0)
{
+ final IceInternal.Buffer buf = _readStream.getBuffer();
+ if(_observer != null && !_readHeader)
+ {
+ observerStartRead(buf);
+ }
+
+ readOp = _transceiver.read(buf, _hasMoreData);
+ if((readOp & IceInternal.SocketOperation.Read) != 0)
+ {
+ break;
+ }
+ if(_observer != null && !_readHeader)
+ {
+ assert(!buf.b.hasRemaining());
+ observerFinishRead(buf);
+ }
+
if(_readHeader) // Read header if necessary.
{
- if(!_transceiver.read(_readStream.getBuffer(), _hasMoreData))
- {
- return;
- }
- assert(!_readStream.getBuffer().b.hasRemaining());
_readHeader = false;
if(_observer != null)
@@ -1256,34 +1277,33 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
{
throw new Ice.DatagramLimitException(); // The message was truncated.
}
- else
- {
- if(_observer != null)
- {
- observerStartRead(_readStream.pos());
- }
- if(!_transceiver.read(_readStream.getBuffer(), _hasMoreData))
- {
- assert(!_readStream.isEmpty());
- scheduleTimeout(IceInternal.SocketOperation.Read, _endpoint.timeout());
- return;
- }
- if(_observer != null)
- {
- observerFinishRead(_readStream.pos());
- }
- assert(!_readStream.getBuffer().b.hasRemaining());
- }
+ continue;
}
+ break;
}
-
+
+ int newOp = readOp | writeOp;
+ readyOp = readyOp & ~newOp;
+ assert(readyOp != 0 || newOp != 0);
+
if(_state <= StateNotValidated)
{
+ if(newOp != 0)
+ {
+ //
+ // Wait for all the transceiver conditions to be
+ // satisfied before continuing.
+ //
+ scheduleTimeout(newOp);
+ _threadPool.update(this, current.operation, newOp);
+ return;
+ }
+
if(_state == StateNotInitialized && !initialize(current.operation))
{
return;
}
-
+
if(_state <= StateNotValidated && !validate(current.operation))
{
return;
@@ -1307,24 +1327,41 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
else
{
- assert(_state <= StateClosing);
-
+ assert(_state <= StateClosingPending);
+
//
// We parse messages first, if we receive a close
// connection message we won't send more messages.
- //
- if((current.operation & IceInternal.SocketOperation.Read) != 0)
+ //
+ if((readyOp & IceInternal.SocketOperation.Read) != 0)
{
- info = parseMessage(current.stream); // Optimization: use the thread's stream.
+ info = new MessageInfo(current.stream); // Optimization: use the thread's stream.
+ newOp |= parseMessage(info);
}
- if((current.operation & IceInternal.SocketOperation.Write) != 0)
+ if((readyOp & IceInternal.SocketOperation.Write) != 0)
{
- sentCBs = sendNextMessage();
- if(sentCBs != null)
+ sentCBs = new java.util.LinkedList<OutgoingMessage>();
+ newOp |= sendNextMessage(sentCBs);
+ if(!sentCBs.isEmpty())
{
++_dispatchCount;
}
+ else
+ {
+ sentCBs = null;
+ }
+ }
+
+ if(_state < StateClosed)
+ {
+ scheduleTimeout(newOp);
+ _threadPool.update(this, current.operation, newOp);
+ }
+
+ if(readyOp == 0)
+ {
+ return;
}
}
}
@@ -1368,9 +1405,10 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
{
_acmLastActivity = IceInternal.Time.currentMonotonicTimeMillis();
}
+
current.ioCompleted();
}
-
+
if(_dispatcher != null)
{
if(info != null && info.heartbeatCallback == null) // No need for the stream if heartbeat callback
@@ -1452,22 +1490,6 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
++count;
}
- if(info.invokeNum > 0)
- {
- //
- // Method invocation (or multiple invocations for batch messages)
- // must be done outside the thread synchronization, so that nested
- // calls are possible.
- //
- invokeAll(info.stream, info.invokeNum, info.requestId, info.compress, info.servantManager,
- info.adapter);
-
- //
- // Don't increase count, the dispatch count is
- // decreased when the incoming reply is sent.
- //
- }
-
if(info.heartbeatCallback != null)
{
try
@@ -1480,8 +1502,24 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
++count;
}
+
+ //
+ // Method invocation (or multiple invocations for batch messages)
+ // must be done outside the thread synchronization, so that nested
+ // calls are possible.
+ //
+ if(info.invokeNum > 0)
+ {
+ invokeAll(info.stream, info.invokeNum, info.requestId, info.compress, info.servantManager,
+ info.adapter);
+
+ //
+ // Don't increase count, the dispatch count is
+ // decreased when the incoming reply is sent.
+ //
+ }
}
-
+
//
// Decrease dispatch count.
//
@@ -1493,13 +1531,12 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
if(_dispatchCount == 0)
{
//
- // Only initiate shutdown if not already done. It
- // might have already been done if the sent
- // callback or AMI callback was dispatched when
- // the connection was already in the closing
- // state.
+ // Only initiate shutdown if not already done. It might
+ // have already been done if the sent callback or AMI
+ // callback was dispatched when the connection was already
+ // in the closing state.
//
- if(_state == StateClosing && !_shutdownInitiated)
+ if(_state == StateClosing)
{
try
{
@@ -1523,11 +1560,16 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
public void
finished(IceInternal.ThreadPoolCurrent current)
{
+ synchronized(this)
+ {
+ assert(_state == StateClosed);
+ unscheduleTimeout(IceInternal.SocketOperation.Read | IceInternal.SocketOperation.Write);
+ }
+
//
- // Check if the connection needs to call user callbacks. If it doesn't, we
- // can safely run finish() from this "IO thread". Otherwise, we either run
- // finish() with the dispatcher if one is set, or we promote another IO
- // thread first before calling finish().
+ // If there are no callbacks to call, we don't call ioCompleted() since we're not going
+ // to call code that will potentially block (this avoids promoting a new leader and
+ // unecessary thread creation, especially if this is called on shutdown).
//
if(_startCallback == null && _sendStreams.isEmpty() && _asyncRequests.isEmpty() && _callback == null)
{
@@ -1551,7 +1593,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
{
finish();
}
- },
+ },
this);
}
catch(java.lang.Exception ex)
@@ -1567,43 +1609,30 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
public void
finish()
{
- synchronized(this)
- {
- assert(_state == StateClosed);
- unscheduleTimeout(IceInternal.SocketOperation.Read |
- IceInternal.SocketOperation.Write |
- IceInternal.SocketOperation.Connect);
- }
-
if(_startCallback != null)
{
_startCallback.connectionStartFailed(this, _exception);
_startCallback = null;
}
-
+
if(!_sendStreams.isEmpty())
{
if(!_writeStream.isEmpty())
{
//
- // Return the stream to the outgoing call. This is important for
+ // Return the stream to the outgoing call. This is important for
// retriable AMI calls which are not marshalled again.
//
OutgoingMessage message = _sendStreams.getFirst();
_writeStream.swap(message.stream);
}
-
- //
- // NOTE: for twoway requests which are not sent, finished can be called twice: the
- // first time because the outgoing is in the _sendStreams set and the second time
- // because it's either in the _requests/_asyncRequests set. This is fine, only the
- // first call should be taken into account by the implementation of finished.
- //
+
for(OutgoingMessage p : _sendStreams)
{
- if(p.requestId > 0)
+ p.finished(_exception);
+ if(p.requestId > 0) // Make sure finished isn't called twice.
{
- if(p.out != null) // Make sure finished isn't called twice.
+ if(p.out != null)
{
_requests.remove(p.requestId);
}
@@ -1612,11 +1641,10 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_asyncRequests.remove(p.requestId);
}
}
- p.finished(_exception);
}
_sendStreams.clear();
}
-
+
for(IceInternal.Outgoing p : _requests.values())
{
p.finished(_exception, true);
@@ -1628,7 +1656,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
p.__finished(_exception, true);
}
_asyncRequests.clear();
-
+
if(_callback != null)
{
try
@@ -1662,18 +1690,12 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
return _toString();
}
- public java.nio.channels.SelectableChannel
+ public java.nio.channels.SelectableChannel
fd()
{
return _transceiver.fd();
}
- public boolean
- hasMoreData()
- {
- return _hasMoreData.value;
- }
-
public synchronized void
timedOut()
{
@@ -1685,7 +1707,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
{
setState(StateClosed, new TimeoutException());
}
- else if(_state == StateClosing)
+ else if(_state < StateClosed)
{
setState(StateClosed, new CloseTimeoutException());
}
@@ -1760,7 +1782,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_monitor = monitor;
_transceiver = transceiver;
_desc = transceiver.toString();
- _type = transceiver.type();
+ _type = transceiver.protocol();
_connector = connector;
_endpoint = endpoint;
_adapter = adapter;
@@ -1786,7 +1808,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
_nextRequestId = 1;
_batchAutoFlush = initData.properties.getPropertyAsIntWithDefault("Ice.BatchAutoFlush", 1) > 0 ? true : false;
- _batchStream = new IceInternal.BasicStream(instance, IceInternal.Protocol.currentProtocolEncoding,
+ _batchStream = new IceInternal.BasicStream(instance, IceInternal.Protocol.currentProtocolEncoding,
_batchAutoFlush);
_batchStreamInUse = false;
_batchRequestNum = 0;
@@ -1869,8 +1891,9 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
private static final int StateActive = 2;
private static final int StateHolding = 3;
private static final int StateClosing = 4;
- private static final int StateClosed = 5;
- private static final int StateFinished = 6;
+ private static final int StateClosingPending = 5;
+ private static final int StateClosed = 6;
+ private static final int StateFinished = 7;
private void
setState(int state, LocalException ex)
@@ -1888,6 +1911,11 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
if(_exception == null)
{
+ //
+ // If we are in closed state, an exception must be set.
+ //
+ assert(_state != StateClosed);
+
_exception = ex;
//
@@ -1903,7 +1931,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_exception instanceof ConnectionTimeoutException ||
_exception instanceof CommunicatorDestroyedException ||
_exception instanceof ObjectAdapterDeactivatedException ||
- (_exception instanceof ConnectionLostException && _state == StateClosing)))
+ (_exception instanceof ConnectionLostException && _state >= StateClosing)))
{
warning("connection exception", _exception);
}
@@ -1995,19 +2023,15 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
case StateClosing:
+ case StateClosingPending:
{
//
- // Can't change back from closed.
+ // Can't change back from closing pending.
//
- if(_state >= StateClosed)
+ if(_state >= StateClosingPending)
{
return;
}
- if(_state == StateHolding)
- {
- // We need to continue to read in closing state.
- _threadPool.register(this, IceInternal.SocketOperation.Read);
- }
break;
}
@@ -2020,7 +2044,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_threadPool.finish(this);
break;
}
-
+
case StateFinished:
{
assert(_state == StateClosed);
@@ -2069,7 +2093,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
if(oldState != newState)
{
_observer = _instance.getObserver().getConnectionObserver(initConnectionInfo(),
- _endpoint,
+ _endpoint,
newState,
_observer);
if(_observer != null)
@@ -2089,7 +2113,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_exception instanceof ConnectionTimeoutException ||
_exception instanceof CommunicatorDestroyedException ||
_exception instanceof ObjectAdapterDeactivatedException ||
- (_exception instanceof ConnectionLostException && _state == StateClosing)))
+ (_exception instanceof ConnectionLostException && _state >= StateClosing)))
{
_observer.failed(_exception.ice_name());
}
@@ -2117,17 +2141,19 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
{
assert(_state == StateClosing);
assert(_dispatchCount == 0);
- assert(!_shutdownInitiated);
+ if(_shutdownInitiated)
+ {
+ return;
+ }
_shutdownInitiated = true;
if(!_endpoint.datagram())
{
//
- // Before we shut down, we send a close connection
- // message.
+ // Before we shut down, we send a close connection message.
//
- IceInternal.BasicStream os = new IceInternal.BasicStream(_instance,
+ IceInternal.BasicStream os = new IceInternal.BasicStream(_instance,
IceInternal.Protocol.currentProtocolEncoding);
os.writeBlob(IceInternal.Protocol.magic);
IceInternal.Protocol.currentProtocol.__write(os);
@@ -2138,23 +2164,18 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
if((sendMessage(new OutgoingMessage(os, false, false)) & IceInternal.AsyncStatus.Sent) > 0)
{
+ setState(StateClosingPending);
+
//
- // Schedule the close timeout to wait for the peer to close the connection. If
- // the message was queued for sending, sendNextMessage will schedule the timeout
- // once all messages were sent.
+ // Notify the the transceiver of the graceful connection closure.
//
- scheduleTimeout(IceInternal.SocketOperation.Write, closeTimeout());
+ int op = _transceiver.closing(true, _exception);
+ if(op != 0)
+ {
+ scheduleTimeout(op);
+ _threadPool.register(this, op);
+ }
}
-
- //
- // The CloseConnection message should be sufficient. Closing the write
- // end of the socket is probably an artifact of how things were done
- // in IIOP. In fact, shutting down the write end of the socket causes
- // problems on Windows by preventing the peer from using the socket.
- // For example, the peer is no longer able to continue writing a large
- // message after the socket is shutdown.
- //
- //_transceiver.shutdownWrite();
}
}
@@ -2190,10 +2211,10 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
private boolean
initialize(int operation)
{
- int s = _transceiver.initialize(_readStream.getBuffer(), _writeStream.getBuffer());
+ int s = _transceiver.initialize(_readStream.getBuffer(), _writeStream.getBuffer(), _hasMoreData);
if(s != IceInternal.SocketOperation.None)
{
- scheduleTimeout(s, connectTimeout());
+ scheduleTimeout(s);
_threadPool.update(this, operation, s);
return false;
}
@@ -2203,6 +2224,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
//
_desc = _transceiver.toString();
setState(StateNotValidated);
+
return true;
}
@@ -2213,7 +2235,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
{
if(_adapter != null) // The server side has the active role for connection validation.
{
- if(_writeStream.size() == 0)
+ if(_writeStream.isEmpty())
{
_writeStream.writeBlob(IceInternal.Protocol.magic);
IceInternal.Protocol.currentProtocol.__write(_writeStream);
@@ -2227,22 +2249,28 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
if(_observer != null)
{
- observerStartWrite(_writeStream.pos());
+ observerStartWrite(_writeStream.getBuffer());
}
- if(_writeStream.pos() != _writeStream.size() && !_transceiver.write(_writeStream.getBuffer()))
+
+ if(_writeStream.pos() != _writeStream.size())
{
- scheduleTimeout(IceInternal.SocketOperation.Write, connectTimeout());
- _threadPool.update(this, operation, IceInternal.SocketOperation.Write);
- return false;
+ int op = _transceiver.write(_writeStream.getBuffer());
+ if(op != 0)
+ {
+ scheduleTimeout(op);
+ _threadPool.update(this, operation, op);
+ return false;
+ }
}
+
if(_observer != null)
{
- observerFinishWrite(_writeStream.pos());
+ observerFinishWrite(_writeStream.getBuffer());
}
}
else // The client side has the passive role for connection validation.
{
- if(_readStream.size() == 0)
+ if(_readStream.isEmpty())
{
_readStream.resize(IceInternal.Protocol.headerSize, true);
_readStream.pos(0);
@@ -2250,17 +2278,23 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
if(_observer != null)
{
- observerStartRead(_readStream.pos());
+ observerStartRead(_readStream.getBuffer());
}
- if(_readStream.pos() != _readStream.size() && !_transceiver.read(_readStream.getBuffer(), _hasMoreData))
+
+ if(_readStream.pos() != _readStream.size())
{
- scheduleTimeout(IceInternal.SocketOperation.Read, connectTimeout());
- _threadPool.update(this, operation, IceInternal.SocketOperation.Read);
- return false;
+ int op = _transceiver.read(_readStream.getBuffer(), _hasMoreData);
+ if(op != 0)
+ {
+ scheduleTimeout(op);
+ _threadPool.update(this, operation, op);
+ return false;
+ }
}
+
if(_observer != null)
{
- observerFinishRead(_readStream.pos());
+ observerFinishRead(_readStream.getBuffer());
}
assert(_readStream.pos() == IceInternal.Protocol.headerSize);
@@ -2276,10 +2310,10 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_readProtocol.__read(_readStream);
IceInternal.Protocol.checkSupportedProtocol(_readProtocol);
-
+
_readProtocolEncoding.__read(_readStream);
IceInternal.Protocol.checkSupportedProtocolEncoding(_readProtocolEncoding);
-
+
byte messageType = _readStream.readByte();
if(messageType != IceInternal.Protocol.validateConnectionMsg)
{
@@ -2301,19 +2335,28 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_writeStream.pos(0);
_readStream.resize(IceInternal.Protocol.headerSize, true);
- _readHeader = true;
_readStream.pos(0);
-
+ _readHeader = true;
+
return true;
}
- private java.util.List<OutgoingMessage>
- sendNextMessage()
+ private int
+ sendNextMessage(java.util.List<OutgoingMessage> callbacks)
{
- assert(!_sendStreams.isEmpty());
- assert(!_writeStream.isEmpty() && _writeStream.pos() == _writeStream.size());
+ if(_sendStreams.isEmpty())
+ {
+ return IceInternal.SocketOperation.None;
+ }
+ else if(_state == StateClosingPending && _writeStream.pos() == _writeStream.size())
+ {
+ // Message wasn't sent, empty the _writeStream, we're not going to send more data.
+ OutgoingMessage message = _sendStreams.getFirst();
+ _writeStream.swap(message.stream);
+ return IceInternal.SocketOperation.None;
+ }
- java.util.List<OutgoingMessage> callbacks = new java.util.LinkedList<OutgoingMessage>();
+ assert(!_writeStream.isEmpty() && _writeStream.pos() == _writeStream.size());
try
{
while(true)
@@ -2338,17 +2381,17 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
//
- // If we are in the closed state, don't continue sending.
+ // If we are in the closed state or if the close is
+ // pending, don't continue sending.
+ //
+ // This can occur if parseMessage (called before
+ // sendNextMessage by message()) closes the connection.
//
- // The connection can be in the closed state if parseMessage
- // (called before sendNextMessage by message()) closes the
- // connection.
- //
- if(_state >= StateClosed)
+ if(_state >= StateClosingPending)
{
- return callbacks;
+ return IceInternal.SocketOperation.None;
}
-
+
//
// Otherwise, prepare the next message stream for writing.
//
@@ -2375,45 +2418,50 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
//
if(_observer != null)
{
- observerStartWrite(_writeStream.pos());
+ observerStartWrite(_writeStream.getBuffer());
}
- if(_writeStream.pos() != _writeStream.size() && !_transceiver.write(_writeStream.getBuffer()))
+ if(_writeStream.pos() != _writeStream.size())
{
- assert(!_writeStream.isEmpty());
- scheduleTimeout(IceInternal.SocketOperation.Write, _endpoint.timeout());
- return callbacks;
+ int op = _transceiver.write(_writeStream.getBuffer());
+ if(op != 0)
+ {
+ return op;
+ }
}
if(_observer != null)
{
- observerFinishWrite(_writeStream.pos());
+ observerFinishWrite(_writeStream.getBuffer());
}
}
}
catch(Ice.LocalException ex)
{
setState(StateClosed, ex);
- return callbacks;
+ return IceInternal.SocketOperation.None;
}
- assert(_writeStream.isEmpty());
- _threadPool.unregister(this, IceInternal.SocketOperation.Write);
-
//
- // If all the messages were sent and we are in the closing state, we schedule
+ // If all the messages were sent and we are in the closing state, we schedule
// the close timeout to wait for the peer to close the connection.
//
if(_state == StateClosing)
{
- scheduleTimeout(IceInternal.SocketOperation.Write, closeTimeout());
+ setState(StateClosingPending);
+ int op = _transceiver.closing(true, _exception);
+ if(op != 0)
+ {
+ return op;
+ }
}
- return callbacks;
+ return IceInternal.SocketOperation.None;
}
private int
sendMessage(OutgoingMessage message)
{
assert(_state < StateClosed);
+
if(!_sendStreams.isEmpty())
{
message.adopt();
@@ -2423,8 +2471,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
//
// Attempt to send the message without blocking. If the send blocks, we register
- // the connection with the selector thread or we request the caller to call
- // finishSendMessage() outside the synchronization.
+ // the connection with the selector thread.
//
assert(!message.prepared);
@@ -2434,6 +2481,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
message.stream = doCompress(stream, message.compress);
message.stream.prepareWrite();
message.prepared = true;
+ int op;
if(message.outAsync != null)
{
@@ -2444,16 +2492,21 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
IceInternal.TraceUtil.traceSend(stream, _logger, _traceLevels);
}
+ //
+ // Send the message without blocking.
+ //
if(_observer != null)
{
- observerStartWrite(message.stream.pos());
+ observerStartWrite(message.stream.getBuffer());
}
- if(_transceiver.write(message.stream.getBuffer()))
+ op = _transceiver.write(message.stream.getBuffer());
+ if(op == 0)
{
if(_observer != null)
{
- observerFinishWrite(message.stream.pos());
+ observerFinishWrite(message.stream.getBuffer());
}
+
int status = IceInternal.AsyncStatus.Sent;
if(message.sent())
{
@@ -2466,12 +2519,13 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
return status;
}
+
message.adopt();
_writeStream.swap(message.stream);
_sendStreams.addLast(message);
- scheduleTimeout(IceInternal.SocketOperation.Write, _endpoint.timeout());
- _threadPool.register(this, IceInternal.SocketOperation.Write);
+ scheduleTimeout(op);
+ _threadPool.register(this, op);
return IceInternal.AsyncStatus.Queued;
}
@@ -2549,18 +2603,18 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
ConnectionCallback heartbeatCallback;
}
- private MessageInfo
- parseMessage(IceInternal.BasicStream stream)
+ private int
+ parseMessage(MessageInfo info)
{
assert(_state > StateNotValidated && _state < StateClosed);
- MessageInfo info = new MessageInfo(stream);
-
_readStream.swap(info.stream);
_readStream.resize(IceInternal.Protocol.headerSize, true);
_readStream.pos(0);
_readHeader = true;
+ assert(info.stream.pos() == info.stream.size());
+
//
// Connection is validated on first message. This is only used by
// setState() to check wether or not we can print a connection
@@ -2569,15 +2623,12 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
//
_validated = true;
- assert(info.stream.pos() == info.stream.size());
-
try
{
//
// We don't need to check magic and version here. This has already
// been done by the ThreadPool which provides us with the stream.
//
- assert(info.stream.pos() == info.stream.size());
info.stream.pos(8);
byte messageType = info.stream.readByte();
info.compress = info.stream.readByte();
@@ -2611,14 +2662,24 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
else
{
- setState(StateClosed, new CloseConnectionException());
+ setState(StateClosingPending, new CloseConnectionException());
+
+ //
+ // Notify the the transceiver of the graceful connection closure.
+ //
+ int op = _transceiver.closing(false, _exception);
+ if(op != 0)
+ {
+ return op;
+ }
+ setState(StateClosed);
}
break;
}
case IceInternal.Protocol.requestMsg:
{
- if(_state == StateClosing)
+ if(_state >= StateClosing)
{
IceInternal.TraceUtil.trace("received request during closing\n" +
"(ignored by server, client will retry)",
@@ -2638,7 +2699,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
case IceInternal.Protocol.requestBatchMsg:
{
- if(_state == StateClosing)
+ if(_state >= StateClosing)
{
IceInternal.TraceUtil.trace("received batch request during closing\n" +
"(ignored by server, client will retry)",
@@ -2715,7 +2776,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
}
- return info;
+ return _state == StateHolding ? IceInternal.SocketOperation.None : IceInternal.SocketOperation.Read;
}
private void
@@ -2787,23 +2848,72 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
}
- private void
- scheduleTimeout(int status, int timeout)
+ private void
+ scheduleTimeout(int status)
{
+ int timeout;
+ if(_state < StateActive)
+ {
+ IceInternal.DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideConnectTimeout)
+ {
+ timeout = defaultsAndOverrides.overrideConnectTimeoutValue;
+ }
+ else
+ {
+ timeout = _endpoint.timeout();
+ }
+ }
+ else if(_state < StateClosingPending)
+ {
+ if(_readHeader) // No timeout for reading the header.
+ {
+ status &= ~IceInternal.SocketOperation.Read;
+ }
+ timeout = _endpoint.timeout();
+ }
+ else
+ {
+ IceInternal.DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
+ if(defaultsAndOverrides.overrideCloseTimeout)
+ {
+ timeout = defaultsAndOverrides.overrideCloseTimeoutValue;
+ }
+ else
+ {
+ timeout = _endpoint.timeout();
+ }
+ }
+
if(timeout < 0)
{
return;
}
- if((status & IceInternal.SocketOperation.Read) != 0)
+ try
{
- _timer.schedule(_readTimeout, timeout);
- _readTimeoutScheduled = true;
+ if((status & IceInternal.SocketOperation.Read) != 0)
+ {
+ if(_readTimeoutScheduled)
+ {
+ _timer.cancel(_readTimeout);
+ }
+ _timer.schedule(_readTimeout, timeout);
+ _readTimeoutScheduled = true;
+ }
+ if((status & (IceInternal.SocketOperation.Write | IceInternal.SocketOperation.Connect)) != 0)
+ {
+ if(_writeTimeoutScheduled)
+ {
+ _timer.cancel(_writeTimeout);
+ }
+ _timer.schedule(_writeTimeout, timeout);
+ _writeTimeoutScheduled = true;
+ }
}
- if((status & (IceInternal.SocketOperation.Write | IceInternal.SocketOperation.Connect)) != 0)
+ catch(Throwable ex)
{
- _timer.schedule(_writeTimeout, timeout);
- _writeTimeoutScheduled = true;
+ assert(false);
}
}
@@ -2823,34 +2933,6 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
}
- private int
- connectTimeout()
- {
- IceInternal.DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
- if(defaultsAndOverrides.overrideConnectTimeout)
- {
- return defaultsAndOverrides.overrideConnectTimeoutValue;
- }
- else
- {
- return _endpoint.timeout();
- }
- }
-
- private int
- closeTimeout()
- {
- IceInternal.DefaultsAndOverrides defaultsAndOverrides = _instance.defaultsAndOverrides();
- if(defaultsAndOverrides.overrideCloseTimeout)
- {
- return defaultsAndOverrides.overrideCloseTimeoutValue;
- }
- else
- {
- return _endpoint.timeout();
- }
- }
-
private ConnectionInfo
initConnectionInfo()
{
@@ -2875,7 +2957,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
{
return connectionStateMap[state];
}
-
+
private void
warning(String msg, Exception ex)
{
@@ -2888,46 +2970,50 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
private void
- observerStartRead(int pos)
+ observerStartRead(IceInternal.Buffer buf)
{
if(_readStreamPos >= 0)
{
- _observer.receivedBytes(pos - _readStreamPos);
+ assert(!buf.empty());
+ _observer.receivedBytes(buf.b.position() - _readStreamPos);
}
- _readStreamPos = pos;
+ _readStreamPos = buf.empty() ? -1 : buf.b.position();
}
private void
- observerFinishRead(int pos)
+ observerFinishRead(IceInternal.Buffer buf)
{
if(_readStreamPos == -1)
{
return;
}
- assert(pos >= _readStreamPos);
- _observer.receivedBytes(pos - _readStreamPos);
+ assert(buf.b.position() >= _readStreamPos);
+ _observer.receivedBytes(buf.b.position() - _readStreamPos);
_readStreamPos = -1;
}
private void
- observerStartWrite(int pos)
+ observerStartWrite(IceInternal.Buffer buf)
{
if(_writeStreamPos >= 0)
{
- _observer.sentBytes(pos - _writeStreamPos);
+ assert(!buf.empty());
+ _observer.sentBytes(buf.b.position() - _writeStreamPos);
}
- _writeStreamPos = pos;
+ _writeStreamPos = buf.empty() ? -1 : buf.b.position();
}
private void
- observerFinishWrite(int pos)
+ observerFinishWrite(IceInternal.Buffer buf)
{
if(_writeStreamPos == -1)
{
return;
}
- assert(pos >= _writeStreamPos);
- _observer.sentBytes(pos - _writeStreamPos);
+ if(buf.b.position() > _writeStreamPos)
+ {
+ _observer.sentBytes(buf.b.position() - _writeStreamPos);
+ }
_writeStreamPos = -1;
}
@@ -3160,7 +3246,6 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
private boolean _readTimeoutScheduled;
private StartCallback _startCallback = null;
- private Ice.BooleanHolder _hasMoreData = new Ice.BooleanHolder(false);
private final boolean _warn;
private final boolean _warnUdp;
@@ -3222,6 +3307,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
Ice.Instrumentation.ConnectionState.ConnectionStateActive, // StateActive
Ice.Instrumentation.ConnectionState.ConnectionStateHolding, // StateHolding
Ice.Instrumentation.ConnectionState.ConnectionStateClosing, // StateClosing
+ Ice.Instrumentation.ConnectionState.ConnectionStateClosing, // StateClosingPending
Ice.Instrumentation.ConnectionState.ConnectionStateClosed, // StateClosed
Ice.Instrumentation.ConnectionState.ConnectionStateClosed, // StateFinished
};
diff --git a/java/src/IceInternal/Acceptor.java b/java/src/IceInternal/Acceptor.java
index fb1f9f24b3d..0d883d6ef8b 100644
--- a/java/src/IceInternal/Acceptor.java
+++ b/java/src/IceInternal/Acceptor.java
@@ -15,5 +15,6 @@ public interface Acceptor
void close();
void listen();
Transceiver accept();
+ String protocol();
String toString();
}
diff --git a/java/src/IceInternal/EndpointFactory.java b/java/src/IceInternal/EndpointFactory.java
index aabdec78581..61425287f5c 100644
--- a/java/src/IceInternal/EndpointFactory.java
+++ b/java/src/IceInternal/EndpointFactory.java
@@ -13,7 +13,9 @@ public interface EndpointFactory
{
short type();
String protocol();
- EndpointI create(String str, boolean oaEndpoint);
+ EndpointI create(java.util.ArrayList<String> args, boolean oaEndpoint);
EndpointI read(BasicStream s);
void destroy();
+
+ EndpointFactory clone(ProtocolInstance instance);
}
diff --git a/java/src/IceInternal/EndpointFactoryManager.java b/java/src/IceInternal/EndpointFactoryManager.java
index 94f61fbb873..64fd927c771 100644
--- a/java/src/IceInternal/EndpointFactoryManager.java
+++ b/java/src/IceInternal/EndpointFactoryManager.java
@@ -16,8 +16,7 @@ public final class EndpointFactoryManager
_instance = instance;
}
- public synchronized void
- add(EndpointFactory factory)
+ public synchronized void add(EndpointFactory factory)
{
for(int i = 0; i < _factories.size(); i++)
{
@@ -30,8 +29,7 @@ public final class EndpointFactoryManager
_factories.add(factory);
}
- public synchronized EndpointFactory
- get(short type)
+ public synchronized EndpointFactory get(short type)
{
for(int i = 0; i < _factories.size(); i++)
{
@@ -44,77 +42,101 @@ public final class EndpointFactoryManager
return null;
}
- public synchronized EndpointI
- create(String str, boolean oaEndpoint)
+ public synchronized EndpointI create(String str, boolean oaEndpoint)
{
- String s = str.trim();
- if(s.length() == 0)
+ String[] arr = IceUtilInternal.StringUtil.splitString(str, " \t\r\n");
+ if(arr == null)
{
Ice.EndpointParseException e = new Ice.EndpointParseException();
- e.str = "value has no non-whitespace characters";
+ e.str = "mismatched quote";
throw e;
}
- java.util.regex.Pattern p = java.util.regex.Pattern.compile("([ \t\n\r]+)|$");
- java.util.regex.Matcher m = p.matcher(s);
- boolean b = m.find();
- assert(b);
+ if(arr.length == 0)
+ {
+ Ice.EndpointParseException e = new Ice.EndpointParseException();
+ e.str = "value has no non-whitespace characters";
+ throw e;
+ }
- String protocol = s.substring(0, m.start());
+ java.util.ArrayList<String> v = new java.util.ArrayList<String>(java.util.Arrays.asList(arr));
+ String protocol = v.get(0);
+ v.remove(0);
if(protocol.equals("default"))
{
protocol = _instance.defaultsAndOverrides().defaultProtocol;
}
+ EndpointFactory factory = null;
+
for(int i = 0; i < _factories.size(); i++)
{
EndpointFactory f = _factories.get(i);
if(f.protocol().equals(protocol))
{
- return f.create(s.substring(m.end()), oaEndpoint);
-
- // Code below left in place for debugging.
-
- /*
- EndpointI e = f.create(s.substring(m.end()), oaEndpoint);
- BasicStream bs = new BasicStream(_instance, true, false);
- e.streamWrite(bs);
- java.nio.ByteBuffer buf = bs.getBuffer();
- buf.position(0);
- short type = bs.readShort();
- EndpointI ue = new IceInternal.OpaqueEndpointI(type, bs);
- System.err.println("Normal: " + e);
- System.err.println("Opaque: " + ue);
- return e;
- */
+ factory = f;
}
}
+ if(factory != null)
+ {
+ EndpointI e = factory.create(v, oaEndpoint);
+ if(!v.isEmpty())
+ {
+ Ice.EndpointParseException ex = new Ice.EndpointParseException();
+ ex.str = "unrecognized argument `" + v.get(0) + "' in endpoint `" + str + "'";
+ throw ex;
+ }
+ return e;
+
+ // Code below left in place for debugging.
+
+ /*
+ EndpointI e = f.create(s.substring(m.end()), oaEndpoint);
+ BasicStream bs = new BasicStream(_instance, true, false);
+ e.streamWrite(bs);
+ java.nio.ByteBuffer buf = bs.getBuffer();
+ buf.position(0);
+ short type = bs.readShort();
+ EndpointI ue = new IceInternal.OpaqueEndpointI(type, bs);
+ System.err.println("Normal: " + e);
+ System.err.println("Opaque: " + ue);
+ return e;
+ */
+ }
+
//
// If the stringified endpoint is opaque, create an unknown endpoint,
// then see whether the type matches one of the known endpoints.
//
if(protocol.equals("opaque"))
{
- EndpointI ue = new OpaqueEndpointI(s.substring(m.end()));
- for(int i = 0; i < _factories.size(); i++)
+ EndpointI ue = new OpaqueEndpointI(v);
+ if(!v.isEmpty())
+ {
+ Ice.EndpointParseException ex = new Ice.EndpointParseException();
+ ex.str = "unrecognized argument `" + v.get(0) + "' in endpoint `" + str + "'";
+ throw ex;
+ }
+ factory = get(ue.type());
+ if(factory != null)
{
- EndpointFactory f = _factories.get(i);
- if(f.type() == ue.type())
- {
- //
- // Make a temporary stream, write the opaque endpoint data into the stream,
- // and ask the factory to read the endpoint data from that stream to create
- // the actual endpoint.
- //
- BasicStream bs = new BasicStream(_instance, Protocol.currentProtocolEncoding, true, false);
- ue.streamWrite(bs);
- Buffer buf = bs.getBuffer();
- buf.b.position(0);
- bs.readShort(); // type
- return f.read(bs);
- }
+ //
+ // Make a temporary stream, write the opaque endpoint data into the stream,
+ // and ask the factory to read the endpoint data from that stream to create
+ // the actual endpoint.
+ //
+ BasicStream bs = new BasicStream(_instance, Protocol.currentProtocolEncoding, true, false);
+ bs.writeShort(ue.type());
+ ue.streamWrite(bs);
+ Buffer buf = bs.getBuffer();
+ buf.b.position(0);
+ bs.readShort(); // type
+ bs.startReadEncaps();
+ EndpointI e = factory.read(bs);
+ bs.endReadEncaps();
+ return e;
}
return ue; // Endpoint is opaque, but we don't have a factory for its type.
}
@@ -122,23 +144,30 @@ public final class EndpointFactoryManager
return null;
}
- public synchronized EndpointI
- read(BasicStream s)
+ public synchronized EndpointI read(BasicStream s)
{
short type = s.readShort();
- for(int i = 0; i < _factories.size(); i++)
+
+ EndpointFactory factory = get(type);
+ EndpointI e = null;
+
+ s.startReadEncaps();
+
+ if(factory != null)
{
- EndpointFactory f = _factories.get(i);
- if(f.type() == type)
- {
- return f.read(s);
- }
+ e = factory.read(s);
}
- return new OpaqueEndpointI(type, s);
+ else
+ {
+ e = new OpaqueEndpointI(type, s);
+ }
+
+ s.endReadEncaps();
+
+ return e;
}
- void
- destroy()
+ void destroy()
{
for(int i = 0; i < _factories.size(); i++)
{
diff --git a/java/src/IceInternal/EndpointHostResolver.java b/java/src/IceInternal/EndpointHostResolver.java
index 43d646c6fb9..898055c102b 100644
--- a/java/src/IceInternal/EndpointHostResolver.java
+++ b/java/src/IceInternal/EndpointHostResolver.java
@@ -34,8 +34,8 @@ public class EndpointHostResolver
}
}
- public java.util.List<Connector>
- resolve(String host, int port, Ice.EndpointSelectionType selType, EndpointI endpoint)
+ public java.util.List<Connector> resolve(String host, int port, Ice.EndpointSelectionType selType,
+ IPEndpointI endpoint)
{
//
// Try to get the addresses without DNS lookup. If this doesn't
@@ -92,8 +92,8 @@ public class EndpointHostResolver
return connectors;
}
- synchronized public void
- resolve(String host, int port, Ice.EndpointSelectionType selType, EndpointI endpoint, EndpointI_connectors callback)
+ synchronized public void resolve(String host, int port, Ice.EndpointSelectionType selType, IPEndpointI endpoint,
+ EndpointI_connectors callback)
{
//
// TODO: Optimize to avoid the lookup if the given host is a textual IPv4 or IPv6
@@ -124,16 +124,14 @@ public class EndpointHostResolver
notify();
}
- synchronized public void
- destroy()
+ synchronized public void destroy()
{
assert(!_destroyed);
_destroyed = true;
notify();
}
- public void
- joinWithThread()
+ public void joinWithThread()
{
if(_thread != null)
{
@@ -151,8 +149,7 @@ public class EndpointHostResolver
}
}
- public void
- run()
+ public void run()
{
while(true)
{
@@ -236,8 +233,7 @@ public class EndpointHostResolver
_queue.clear();
}
- synchronized public void
- updateObserver()
+ synchronized public void updateObserver()
{
Ice.Instrumentation.CommunicatorObserver obsv = _instance.getObserver();
if(obsv != null)
@@ -258,7 +254,7 @@ public class EndpointHostResolver
String host;
int port;
Ice.EndpointSelectionType selType;
- EndpointI endpoint;
+ IPEndpointI endpoint;
EndpointI_connectors callback;
Ice.Instrumentation.Observer observer;
}
@@ -282,8 +278,7 @@ public class EndpointHostResolver
setName(threadName + "Ice.HostResolver");
}
- public void
- run()
+ public void run()
{
try
{
diff --git a/java/src/IceInternal/EndpointI.java b/java/src/IceInternal/EndpointI.java
index 99888b7ec85..6d91760b570 100644
--- a/java/src/IceInternal/EndpointI.java
+++ b/java/src/IceInternal/EndpointI.java
@@ -11,19 +11,21 @@ package IceInternal;
abstract public class EndpointI implements Ice.Endpoint, java.lang.Comparable<EndpointI>
{
- public EndpointI(String connectionId)
- {
- _connectionId = connectionId;
- }
-
- public EndpointI()
+ public String toString()
{
+ return _toString();
}
- public String
- toString()
+ public String _toString()
{
- return _toString();
+ //
+ // WARNING: Certain features, such as proxy validation in Glacier2,
+ // depend on the format of proxy strings. Changes to toString() and
+ // methods called to generate parts of the reference string could break
+ // these features. Please review for all features that depend on the
+ // format of proxyToString() before changing this and related code.
+ //
+ return protocol() + options();
}
//
@@ -35,12 +37,12 @@ abstract public class EndpointI implements Ice.Endpoint, java.lang.Comparable<En
// Return the endpoint type.
//
public abstract short type();
-
+
//
// Return the protocol name.
//
public abstract String protocol();
-
+
//
// Return the timeout for the endpoint in milliseconds. 0 means
// non-blocking, -1 means no timeout.
@@ -55,6 +57,11 @@ abstract public class EndpointI implements Ice.Endpoint, java.lang.Comparable<En
public abstract EndpointI timeout(int t);
//
+ // Return the connection ID
+ //
+ public abstract String connectionId();
+
+ //
// Return a new endpoint with a different connection id.
//
public abstract EndpointI connectionId(String connectionId);
@@ -64,7 +71,7 @@ abstract public class EndpointI implements Ice.Endpoint, java.lang.Comparable<En
// otherwise.
//
public abstract boolean compress();
-
+
//
// Return a new endpoint with a different compression value,
// provided that compression is supported by the
@@ -83,14 +90,6 @@ abstract public class EndpointI implements Ice.Endpoint, java.lang.Comparable<En
public abstract boolean secure();
//
- // Return the connection ID
- //
- public String connectionId()
- {
- return _connectionId;
- }
-
- //
// Return a server side transceiver for this endpoint, or null if a
// transceiver can only be created by an acceptor. In case a
// transceiver is created, this operation also returns a new
@@ -126,15 +125,53 @@ abstract public class EndpointI implements Ice.Endpoint, java.lang.Comparable<En
//
public abstract boolean equivalent(EndpointI endpoint);
- public java.util.List<Connector>
- connectors(java.util.List<java.net.InetSocketAddress> addresses, NetworkProxy proxy)
+ public abstract String options();
+
+ public void initWithOptions(java.util.ArrayList<String> args)
{
- //
- // This method must be extended by endpoints which use the EndpointHostResolver to create
- // connectors from IP addresses.
- //
- assert(false);
- return null;
+ java.util.ArrayList<String> unknown = new java.util.ArrayList<String>();
+
+ String str = "`" + protocol() + " ";
+ for(String p : args)
+ {
+ if(IceUtilInternal.StringUtil.findFirstOf(p, " \t\n\r") != -1)
+ {
+ str += " \"" + p + "\"";
+ }
+ else
+ {
+ str += " " + p;
+ }
+ }
+ str += "'";
+
+ for(int n = 0; n < args.size(); ++n)
+ {
+ String option = args.get(n);
+ if(option.length() < 2 || option.charAt(0) != '-')
+ {
+ unknown.add(option);
+ continue;
+ }
+
+ String argument = null;
+ if(n + 1 < args.size() && args.get(n + 1).charAt(0) != '-')
+ {
+ argument = args.get(++n);
+ }
+
+ if(!checkOption(option, argument, str))
+ {
+ unknown.add(option);
+ if(argument != null)
+ {
+ unknown.add(argument);
+ }
+ }
+ }
+
+ args.clear();
+ args.addAll(unknown);
}
//
@@ -149,15 +186,9 @@ abstract public class EndpointI implements Ice.Endpoint, java.lang.Comparable<En
return compareTo((EndpointI)obj) == 0;
}
- public int compareTo(EndpointI p) // From java.lang.Comparable.
+ protected boolean checkOption(String option, String argument, String endpoint)
{
- if(!_connectionId.equals(p._connectionId))
- {
- return _connectionId.compareTo(p._connectionId);
- }
-
- return 0;
+ // Must be overridden to check for options.
+ return false;
}
-
- protected String _connectionId = "";
}
diff --git a/java/src/IceInternal/EventHandler.java b/java/src/IceInternal/EventHandler.java
index 0b8b0efaef8..5dc747b2118 100644
--- a/java/src/IceInternal/EventHandler.java
+++ b/java/src/IceInternal/EventHandler.java
@@ -31,17 +31,8 @@ public abstract class EventHandler
//
abstract public java.nio.channels.SelectableChannel fd();
- //
- // In Java, it's possible that the transceiver reads more data than what was
- // really asked. If this is the case, hasMoreData() returns true and the handler
- // read() method should be called again (without doing a select()). This is
- // handled by the Selector class (it adds the handler to a separate list of
- // handlers if this method returns true.)
- //
- abstract public boolean hasMoreData();
-
- int _disabled = 0;
- int _registered = 0;
- int _ready = 0;
- java.nio.channels.SelectionKey _key = null;
+ public int _disabled = 0;
+ public Ice.BooleanHolder _hasMoreData = new Ice.BooleanHolder(false);
+ public int _registered = 0;
+ public java.nio.channels.SelectionKey _key = null;
}
diff --git a/java/src/IceInternal/EventHandlerOpPair.java b/java/src/IceInternal/EventHandlerOpPair.java
new file mode 100644
index 00000000000..43325ecb4f5
--- /dev/null
+++ b/java/src/IceInternal/EventHandlerOpPair.java
@@ -0,0 +1,22 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 EventHandlerOpPair
+{
+ EventHandlerOpPair(EventHandler handler, int op)
+ {
+ this.handler = handler;
+ this.op = op;
+ }
+
+ EventHandler handler;
+ int op;
+}
diff --git a/java/src/IceInternal/IPEndpointI.java b/java/src/IceInternal/IPEndpointI.java
new file mode 100644
index 00000000000..7c860106754
--- /dev/null
+++ b/java/src/IceInternal/IPEndpointI.java
@@ -0,0 +1,327 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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;
+
+public abstract class IPEndpointI extends EndpointI
+{
+ protected IPEndpointI(ProtocolInstance instance, String host, int port, String connectionId)
+ {
+ _instance = instance;
+ _host = host;
+ _port = port;
+ _connectionId = connectionId;
+ _hashInitialized = false;
+ }
+
+ protected IPEndpointI(ProtocolInstance instance)
+ {
+ _instance = instance;
+ _host = null;
+ _port = 0;
+ _connectionId = "";
+ _hashInitialized = false;
+ }
+
+ protected IPEndpointI(ProtocolInstance instance, BasicStream s)
+ {
+ _instance = instance;
+ _host = s.readString();
+ _port = s.readInt();
+ _connectionId = "";
+ _hashInitialized = false;
+ }
+
+ public void streamWrite(BasicStream s)
+ {
+ s.startWriteEncaps();
+ streamWriteImpl(s);
+ s.endWriteEncaps();
+ }
+
+ public Ice.EndpointInfo getInfo()
+ {
+ Ice.IPEndpointInfo info = new Ice.IPEndpointInfo()
+ {
+ public short type()
+ {
+ return IPEndpointI.this.type();
+ }
+
+ public boolean datagram()
+ {
+ return IPEndpointI.this.datagram();
+ }
+
+ public boolean secure()
+ {
+ return IPEndpointI.this.secure();
+ }
+ };
+ fillEndpointInfo(info);
+ return info;
+ }
+
+ public short type()
+ {
+ return _instance.type();
+ }
+
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ public String connectionId()
+ {
+ return _connectionId;
+ }
+
+ public EndpointI connectionId(String connectionId)
+ {
+ if(connectionId.equals(_connectionId))
+ {
+ return this;
+ }
+ else
+ {
+ return createEndpoint(_host, _port, connectionId);
+ }
+ }
+
+ public java.util.List<Connector> connectors(Ice.EndpointSelectionType selType)
+ {
+ return _instance.resolve(_host, _port, selType, this);
+ }
+
+ public void connectors_async(Ice.EndpointSelectionType selType, EndpointI_connectors callback)
+ {
+ _instance.resolve(_host, _port, selType, this, callback);
+ }
+
+ public java.util.List<EndpointI> expand()
+ {
+ java.util.List<EndpointI> endps = new java.util.ArrayList<EndpointI>();
+ java.util.List<String> hosts = Network.getHostsForEndpointExpand(_host, _instance.protocolSupport(), false);
+ if(hosts == null || hosts.isEmpty())
+ {
+ endps.add(this);
+ }
+ else
+ {
+ for(String h : hosts)
+ {
+ endps.add(createEndpoint(h, _port, _connectionId));
+ }
+ }
+ return endps;
+ }
+
+ public boolean equivalent(EndpointI endpoint)
+ {
+ if(!(endpoint instanceof IPEndpointI))
+ {
+ return false;
+ }
+ IPEndpointI ipEndpointI = (IPEndpointI)endpoint;
+ return ipEndpointI.type() == type() && ipEndpointI._host.equals(_host) && ipEndpointI._port == _port;
+ }
+
+ public java.util.List<Connector> connectors(java.util.List<java.net.InetSocketAddress> addresses,
+ NetworkProxy proxy)
+ {
+ java.util.List<Connector> connectors = new java.util.ArrayList<Connector>();
+ for(java.net.InetSocketAddress p : addresses)
+ {
+ connectors.add(createConnector(p, proxy));
+ }
+ return connectors;
+ }
+
+ synchronized public int hashCode()
+ {
+ if(!_hashInitialized)
+ {
+ _hashValue = 5381;
+ _hashValue = HashUtil.hashAdd(_hashValue, type());
+ _hashValue = hashInit(_hashValue);
+ }
+ return _hashValue;
+ }
+
+ public String options()
+ {
+ //
+ // WARNING: Certain features, such as proxy validation in Glacier2,
+ // depend on the format of proxy strings. Changes to toString() and
+ // methods called to generate parts of the reference string could break
+ // these features. Please review for all features that depend on the
+ // format of proxyToString() before changing this and related code.
+ //
+ String s = "";
+
+ if(_host != null && _host.length() > 0)
+ {
+ s += " -h ";
+ boolean addQuote = _host.indexOf(':') != -1;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ s += _host;
+ if(addQuote)
+ {
+ s += "\"";
+ }
+ }
+
+ s += " -p " + _port;
+
+ return s;
+ }
+
+ public int compareTo(EndpointI obj) // From java.lang.Comparable
+ {
+ if(!(obj instanceof IPEndpointI))
+ {
+ return type() < obj.type() ? -1 : 1;
+ }
+
+ IPEndpointI p = (IPEndpointI)obj;
+ if(this == p)
+ {
+ return 0;
+ }
+
+ int v = _host.compareTo(p._host);
+ if(v != 0)
+ {
+ return v;
+ }
+
+ if(_port < p._port)
+ {
+ return -1;
+ }
+ else if(p._port < _port)
+ {
+ return 1;
+ }
+
+ return _connectionId.compareTo(p._connectionId);
+ }
+
+ public String host()
+ {
+ return _host;
+ }
+
+ public int port()
+ {
+ return _port;
+ }
+
+ protected void streamWriteImpl(BasicStream s)
+ {
+ s.writeString(_host);
+ s.writeInt(_port);
+ }
+
+ protected int hashInit(int h)
+ {
+ h = HashUtil.hashAdd(h, _host);
+ h = HashUtil.hashAdd(h, _port);
+ h = HashUtil.hashAdd(h, _connectionId);
+ return h;
+ }
+
+ protected void fillEndpointInfo(Ice.IPEndpointInfo info)
+ {
+ info.host = _host;
+ info.port = _port;
+ }
+
+ public void initWithOptions(java.util.ArrayList<String> args, boolean oaEndpoint)
+ {
+ super.initWithOptions(args);
+
+ if(_host == null || _host.length() == 0)
+ {
+ _host = _instance.defaultHost();
+ }
+ else if(_host.equals("*"))
+ {
+ if(oaEndpoint)
+ {
+ _host = "";
+ }
+ else
+ {
+ throw new Ice.EndpointParseException("`-h *' not valid for proxy endpoint `" + toString() + "'");
+ }
+ }
+ }
+
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ switch(option.charAt(1))
+ {
+ case 'h':
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -h option in endpoint " + endpoint);
+ }
+ _host = argument;
+ return true;
+ }
+
+ case 'p':
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -p option in endpoint " + endpoint);
+ }
+
+ try
+ {
+ _port = Integer.parseInt(argument);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid port value `" + argument +
+ "' in endpoint " + endpoint);
+ }
+
+ if(_port < 0 || _port > 65535)
+ {
+ throw new Ice.EndpointParseException("port value `" + argument +
+ "' out of range in endpoint " + endpoint);
+ }
+
+ return true;
+ }
+
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+ protected abstract Connector createConnector(java.net.InetSocketAddress addr, NetworkProxy proxy);
+ protected abstract IPEndpointI createEndpoint(String host, int port, String connectionId);
+
+ protected ProtocolInstance _instance;
+ protected String _host;
+ protected int _port;
+ protected String _connectionId;
+ private boolean _hashInitialized;
+ private int _hashValue;
+}
diff --git a/java/src/IceInternal/IncomingConnectionFactory.java b/java/src/IceInternal/IncomingConnectionFactory.java
index 54a9076fde7..59c63fb3b2a 100644
--- a/java/src/IceInternal/IncomingConnectionFactory.java
+++ b/java/src/IceInternal/IncomingConnectionFactory.java
@@ -308,13 +308,6 @@ public final class IncomingConnectionFactory extends EventHandler implements Ice
return _acceptor.fd();
}
- public boolean
- hasMoreData()
- {
- assert(_acceptor != null);
- return false;
- }
-
//
// Operations from ConnectionI.StartCallback
//
diff --git a/java/src/IceInternal/Instance.java b/java/src/IceInternal/Instance.java
index be091ba60e7..0fa8d7e4422 100644
--- a/java/src/IceInternal/Instance.java
+++ b/java/src/IceInternal/Instance.java
@@ -782,9 +782,11 @@ public final class Instance
}
_endpointFactoryManager = new EndpointFactoryManager(this);
- EndpointFactory tcpEndpointFactory = new TcpEndpointFactory(this);
+ ProtocolInstance tcpProtocolInstance = new ProtocolInstance(this, Ice.TCPEndpointType.value, "tcp");
+ EndpointFactory tcpEndpointFactory = new TcpEndpointFactory(tcpProtocolInstance);
_endpointFactoryManager.add(tcpEndpointFactory);
- EndpointFactory udpEndpointFactory = new UdpEndpointFactory(this);
+ ProtocolInstance udpProtocolInstance = new ProtocolInstance(this, Ice.UDPEndpointType.value, "udp");
+ EndpointFactory udpEndpointFactory = new UdpEndpointFactory(udpProtocolInstance);
_endpointFactoryManager.add(udpEndpointFactory);
_pluginManager = new Ice.PluginManagerI(communicator, this);
diff --git a/java/src/IceInternal/OpaqueEndpointI.java b/java/src/IceInternal/OpaqueEndpointI.java
index 89c4305cbd0..70e3559a82b 100644
--- a/java/src/IceInternal/OpaqueEndpointI.java
+++ b/java/src/IceInternal/OpaqueEndpointI.java
@@ -11,179 +11,50 @@ package IceInternal;
final class OpaqueEndpointI extends EndpointI
{
- public
- OpaqueEndpointI(String str)
+ public OpaqueEndpointI(java.util.ArrayList<String> args)
{
- super("");
-
+ _type = -1;
_rawEncoding = Ice.Util.Encoding_1_0;
+ _rawBytes = new byte[0];
- int topt = 0;
- int vopt = 0;
+ initWithOptions(args);
- String[] arr = str.split("[ \t\n\r]+");
- int i = 0;
- while(i < arr.length)
+ if(_type < 0)
{
- if(arr[i].length() == 0)
- {
- i++;
- continue;
- }
-
- String option = arr[i++];
- if(option.length() != 2 || option.charAt(0) != '-')
- {
- throw new Ice.EndpointParseException("expected an endpoint option but found `" + option +
- "' in endpoint `opaque " + str + "'");
- }
-
- String argument = null;
- if(i < arr.length && arr[i].charAt(0) != '-')
- {
- argument = arr[i++];
- }
-
- switch(option.charAt(1))
- {
- case 't':
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -t option in endpoint `opaque "
- + str + "'");
- }
-
- int t;
- try
- {
- t = Integer.parseInt(argument);
- }
- catch(NumberFormatException ex)
- {
- throw new Ice.EndpointParseException("invalid type value `" + argument +
- "' in endpoint `opaque " + str + "'");
- }
-
- if(t < 0 || t > 65535)
- {
- throw new Ice.EndpointParseException("type value `" + argument +
- "' out of range in endpoint `opaque " + str + "'");
- }
-
- _type = (short)t;
- ++topt;
- if(topt > 1)
- {
- throw new Ice.EndpointParseException("multiple -t options in endpoint `opaque " + str + "'");
- }
- break;
- }
-
- case 'e':
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -e option in endpoint `opaque "
- + str + "'");
- }
-
- try
- {
- _rawEncoding = Ice.Util.stringToEncodingVersion(argument);
- }
- catch(Ice.VersionParseException e)
- {
- throw new Ice.EndpointParseException("invalid encoding version `" + argument +
- "' in endpoint `opaque " + str + "':\n" + e.str);
- }
- break;
- }
-
- case 'v':
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -v option in endpoint `opaque "
- + str + "'");
- }
-
- for(int j = 0; j < argument.length(); ++j)
- {
- if(!IceUtilInternal.Base64.isBase64(argument.charAt(j)))
- {
- throw new Ice.EndpointParseException("invalid base64 character `" + argument.charAt(j) +
- "' (ordinal " + ((int)argument.charAt(j)) +
- ") in endpoint `opaque " + str + "'");
- }
- }
- _rawBytes = IceUtilInternal.Base64.decode(argument);
- ++vopt;
- if(vopt > 1)
- {
- throw new Ice.EndpointParseException("multiple -v options in endpoint `opaque " + str + "'");
- }
- break;
- }
-
- default:
- {
- throw new Ice.EndpointParseException("invalid option `" + option + "' in endpoint `opaque " +
- str + "'");
- }
- }
+ throw new Ice.EndpointParseException("no -t option in endpoint " + toString());
}
-
- if(topt != 1)
+ if(_rawBytes.length == 0)
{
- throw new Ice.EndpointParseException("no -t option in endpoint `opaque " + str + "'");
- }
- if(vopt != 1)
- {
- throw new Ice.EndpointParseException("no -v option in endpoint `opaque " + str + "'");
+ throw new Ice.EndpointParseException("no -v option in endpoint " + toString());
}
+
calcHashValue();
}
- public
- OpaqueEndpointI(short type, BasicStream s)
+ public OpaqueEndpointI(short type, BasicStream s)
{
- super("");
_type = type;
- _rawEncoding = s.startReadEncaps();
+ _rawEncoding = s.getReadEncoding();
int sz = s.getReadEncapsSize();
_rawBytes = s.readBlob(sz);
- s.endReadEncaps();
+
calcHashValue();
}
//
// Marshal the endpoint
//
- public void
- streamWrite(BasicStream s)
+ public void streamWrite(BasicStream s)
{
- s.writeShort(_type);
s.startWriteEncaps(_rawEncoding, Ice.FormatType.DefaultFormat);
s.writeBlob(_rawBytes);
s.endWriteEncaps();
}
//
- // Convert the endpoint to its string form
- //
- public String
- _toString()
- {
- String val = IceUtilInternal.Base64.encode(_rawBytes);
- return "opaque -t " + _type + " -e " + Ice.Util.encodingVersionToString(_rawEncoding) + " -v " + val;
- }
-
- //
// Return the endpoint information.
//
- public Ice.EndpointInfo
- getInfo()
+ public Ice.EndpointInfo getInfo()
{
return new Ice.OpaqueEndpointInfo(-1, false, _rawEncoding, _rawBytes)
{
@@ -191,12 +62,12 @@ final class OpaqueEndpointI extends EndpointI
{
return _type;
}
-
+
public boolean datagram()
{
return false;
}
-
+
public boolean secure()
{
return false;
@@ -207,8 +78,7 @@ final class OpaqueEndpointI extends EndpointI
//
// Return the endpoint type
//
- public short
- type()
+ public short type()
{
return _type;
}
@@ -216,8 +86,7 @@ final class OpaqueEndpointI extends EndpointI
//
// Return the protocol name
//
- public String
- protocol()
+ public String protocol()
{
return "opaque";
}
@@ -226,38 +95,39 @@ final class OpaqueEndpointI extends EndpointI
// Return the timeout for the endpoint in milliseconds. 0 means
// non-blocking, -1 means no timeout.
//
- public int
- timeout()
+ public int timeout()
{
return -1;
}
-
+
//
// Return a new endpoint with a different timeout value, provided
// that timeouts are supported by the endpoint. Otherwise the same
// endpoint is returned.
//
- public EndpointI
- timeout(int t)
+ public EndpointI timeout(int t)
{
return this;
}
+ public String connectionId()
+ {
+ return "";
+ }
+
//
// Return a new endpoint with a different connection id.
//
- public EndpointI
- connectionId(String connectionId)
+ public EndpointI connectionId(String connectionId)
{
return this;
}
-
+
//
// Return true if the endpoints support bzip2 compress, or false
// otherwise.
//
- public boolean
- compress()
+ public boolean compress()
{
return false;
}
@@ -267,8 +137,7 @@ final class OpaqueEndpointI extends EndpointI
// provided that compression is supported by the
// endpoint. Otherwise the same endpoint is returned.
//
- public EndpointI
- compress(boolean compress)
+ public EndpointI compress(boolean compress)
{
return this;
}
@@ -276,17 +145,15 @@ final class OpaqueEndpointI extends EndpointI
//
// Return true if the endpoint is datagram-based.
//
- public boolean
- datagram()
+ public boolean datagram()
{
return false;
}
-
+
//
// Return true if the endpoint is secure.
//
- public boolean
- secure()
+ public boolean secure()
{
return false;
}
@@ -294,8 +161,7 @@ final class OpaqueEndpointI extends EndpointI
//
// Get the encoded endpoint.
//
- public byte[]
- rawBytes()
+ public byte[] rawBytes()
{
return _rawBytes;
}
@@ -307,8 +173,7 @@ final class OpaqueEndpointI extends EndpointI
// "effective" endpoint, which might differ from this endpoint,
// for example, if a dynamic port number is assigned.
//
- public Transceiver
- transceiver(EndpointIHolder endpoint)
+ public Transceiver transceiver(EndpointIHolder endpoint)
{
endpoint.value = null;
return null;
@@ -318,14 +183,12 @@ final class OpaqueEndpointI extends EndpointI
// Return connectors for this endpoint, or empty list if no connector
// is available.
//
- public java.util.List<Connector>
- connectors(Ice.EndpointSelectionType selType)
+ public java.util.List<Connector> connectors(Ice.EndpointSelectionType selType)
{
return new java.util.ArrayList<Connector>();
}
- public void
- connectors_async(Ice.EndpointSelectionType selType, EndpointI_connectors callback)
+ public void connectors_async(Ice.EndpointSelectionType selType, EndpointI_connectors callback)
{
callback.connectors(new java.util.ArrayList<Connector>());
}
@@ -337,8 +200,7 @@ final class OpaqueEndpointI extends EndpointI
// from this endpoint, for example, if a dynamic port number is
// assigned.
//
- public Acceptor
- acceptor(EndpointIHolder endpoint, String adapterName)
+ public Acceptor acceptor(EndpointIHolder endpoint, String adapterName)
{
endpoint.value = null;
return null;
@@ -349,8 +211,7 @@ final class OpaqueEndpointI extends EndpointI
// host if listening on INADDR_ANY on server side or if no host
// was specified on client side.
//
- public java.util.List<EndpointI>
- expand()
+ public java.util.List<EndpointI> expand()
{
java.util.List<EndpointI> endps = new java.util.ArrayList<EndpointI>();
endps.add(this);
@@ -360,23 +221,35 @@ final class OpaqueEndpointI extends EndpointI
//
// Check whether the endpoint is equivalent to another one.
//
- public boolean
- equivalent(EndpointI endpoint)
+ public boolean equivalent(EndpointI endpoint)
{
return false;
}
- public int
- hashCode()
+ public int hashCode()
{
return _hashCode;
}
-
+
+ public String options()
+ {
+ String s = "";
+ if(_type > -1)
+ {
+ s += " -t " + _type;
+ }
+ s += " -e " + Ice.Util.encodingVersionToString(_rawEncoding);
+ if(_rawBytes.length > 0)
+ {
+ s += " -v " + IceUtilInternal.Base64.encode(_rawBytes);
+ }
+ return s;
+ }
+
//
// Compare endpoints for sorting purposes
//
- public int
- compareTo(EndpointI obj) // From java.lang.Comparable
+ public int compareTo(EndpointI obj) // From java.lang.Comparable
{
if(!(obj instanceof OpaqueEndpointI))
{
@@ -439,8 +312,92 @@ final class OpaqueEndpointI extends EndpointI
return 0;
}
- private void
- calcHashValue()
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ switch(option.charAt(1))
+ {
+ case 't':
+ {
+ if(_type > -1)
+ {
+ throw new Ice.EndpointParseException("multiple -t options in endpoint " + endpoint);
+ }
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -t option in endpoint " + endpoint);
+ }
+
+ int t;
+ try
+ {
+ t = Integer.parseInt(argument);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid type value `" + argument + "' in endpoint " + endpoint);
+ }
+
+ if(t < 0 || t > 65535)
+ {
+ throw new Ice.EndpointParseException("type value `" + argument + "' out of range in endpoint " +
+ endpoint);
+ }
+
+ _type = (short)t;
+ return true;
+ }
+
+ case 'v':
+ {
+ if(_rawBytes.length > 0)
+ {
+ throw new Ice.EndpointParseException("multiple -v options in endpoint " + endpoint);
+ }
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -v option in endpoint " + endpoint);
+ }
+
+ for(int j = 0; j < argument.length(); ++j)
+ {
+ if(!IceUtilInternal.Base64.isBase64(argument.charAt(j)))
+ {
+ throw new Ice.EndpointParseException("invalid base64 character `" + argument.charAt(j) +
+ "' (ordinal " + ((int)argument.charAt(j)) +
+ ") in endpoint " + endpoint);
+ }
+ }
+ _rawBytes = IceUtilInternal.Base64.decode(argument);
+ return true;
+ }
+
+ case 'e':
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -e option in endpoint " + endpoint);
+ }
+
+ try
+ {
+ _rawEncoding = Ice.Util.stringToEncodingVersion(argument);
+ }
+ catch(Ice.VersionParseException e)
+ {
+ throw new Ice.EndpointParseException("invalid encoding version `" + argument +
+ "' in endpoint " + endpoint + ":\n" + e.str);
+ }
+ return true;
+ }
+
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+ private void calcHashValue()
{
int h = 5381;
h = IceInternal.HashUtil.hashAdd(h, _type);
diff --git a/java/src/IceInternal/OutgoingConnectionFactory.java b/java/src/IceInternal/OutgoingConnectionFactory.java
index f4822753730..53a1abbfc90 100644
--- a/java/src/IceInternal/OutgoingConnectionFactory.java
+++ b/java/src/IceInternal/OutgoingConnectionFactory.java
@@ -28,6 +28,7 @@ public final class OutgoingConnectionFactory
list.add(value);
}
+ /*
public void
removeElementWithValue(K key, V value)
{
@@ -39,6 +40,20 @@ public final class OutgoingConnectionFactory
this.remove(key);
}
}
+ */
+
+ public boolean
+ removeElementWithValue(K key, V value)
+ {
+ java.util.List<V> list = this.get(key);
+ assert(list != null);
+ boolean v = list.remove(value);
+ if(list.isEmpty())
+ {
+ this.remove(key);
+ }
+ return v;
+ }
};
interface CreateConnectionCallback
diff --git a/java/src/IceInternal/ProtocolInstance.java b/java/src/IceInternal/ProtocolInstance.java
new file mode 100644
index 00000000000..ee0b9074277
--- /dev/null
+++ b/java/src/IceInternal/ProtocolInstance.java
@@ -0,0 +1,114 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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;
+
+public class ProtocolInstance
+{
+ public ProtocolInstance(Ice.Communicator communicator, short type, String protocol)
+ {
+ _instance = Util.getInstance(communicator);
+ _traceLevel = _instance.traceLevels().network;
+ _traceCategory = _instance.traceLevels().networkCat;
+ _logger = _instance.initializationData().logger;
+ _properties = _instance.initializationData().properties;
+ _type = type;
+ _protocol = protocol;
+ }
+
+ public int traceLevel()
+ {
+ return _traceLevel;
+ }
+
+ public String traceCategory()
+ {
+ return _traceCategory;
+ }
+
+ public Ice.Logger logger()
+ {
+ return _logger;
+ }
+
+ public String protocol()
+ {
+ return _protocol;
+ }
+
+ public short type()
+ {
+ return _type;
+ }
+
+ public Ice.Properties properties()
+ {
+ return _properties;
+ }
+
+ public boolean preferIPv6()
+ {
+ return _instance.preferIPv6();
+ }
+
+ public int protocolSupport()
+ {
+ return _instance.protocolSupport();
+ }
+
+ public String defaultHost()
+ {
+ return _instance.defaultsAndOverrides().defaultHost;
+ }
+
+ public Ice.EncodingVersion defaultEncoding()
+ {
+ return _instance.defaultsAndOverrides().defaultEncoding;
+ }
+
+ public NetworkProxy networkProxy()
+ {
+ return _instance.networkProxy();
+ }
+
+ public int messageSizeMax()
+ {
+ return _instance.messageSizeMax();
+ }
+
+ public java.util.List<Connector> resolve(String host, int port, Ice.EndpointSelectionType type, IPEndpointI endpt)
+ {
+ return _instance.endpointHostResolver().resolve(host, port, type, endpt);
+ }
+
+ public void resolve(String host, int port, Ice.EndpointSelectionType type, IPEndpointI endpt,
+ EndpointI_connectors callback)
+ {
+ _instance.endpointHostResolver().resolve(host, port, type, endpt, callback);
+ }
+
+ ProtocolInstance(Instance instance, short type, String protocol)
+ {
+ _instance = instance;
+ _traceLevel = _instance.traceLevels().network;
+ _traceCategory = _instance.traceLevels().networkCat;
+ _logger = _instance.initializationData().logger;
+ _properties = _instance.initializationData().properties;
+ _type = type;
+ _protocol = protocol;
+ }
+
+ protected Instance _instance;
+ protected int _traceLevel;
+ protected String _traceCategory;
+ protected Ice.Logger _logger;
+ protected Ice.Properties _properties;
+ protected String _protocol;
+ protected short _type;
+}
diff --git a/java/src/IceInternal/ProtocolPluginFacade.java b/java/src/IceInternal/ProtocolPluginFacade.java
index c1834c1ae92..07080ea383e 100644
--- a/java/src/IceInternal/ProtocolPluginFacade.java
+++ b/java/src/IceInternal/ProtocolPluginFacade.java
@@ -18,42 +18,6 @@ public interface ProtocolPluginFacade
Ice.Communicator getCommunicator();
//
- // Get the endpoint host resolver.
- //
- IceInternal.EndpointHostResolver getEndpointHostResolver();
-
- //
- // Get the protocol support.
- //
- int getProtocolSupport();
-
- //
- // Get the protocol support.
- //
- boolean getPreferIPv6();
-
- //
- // Get the network proxy.
- //
- NetworkProxy getNetworkProxy();
-
- //
- // Get the default encoding to be used in endpoints.
- //
- Ice.EncodingVersion getDefaultEncoding();
-
- //
- // Get the default hostname to be used in endpoints.
- //
- String getDefaultHost();
-
- //
- // Get the network trace level and category name.
- //
- int getNetworkTraceLevel();
- String getNetworkTraceCategory();
-
- //
// Register an EndpointFactory.
//
void addEndpointFactory(EndpointFactory factory);
diff --git a/java/src/IceInternal/ProtocolPluginFacadeI.java b/java/src/IceInternal/ProtocolPluginFacadeI.java
index 0c51675b1e0..d4213bba8b8 100644
--- a/java/src/IceInternal/ProtocolPluginFacadeI.java
+++ b/java/src/IceInternal/ProtocolPluginFacadeI.java
@@ -11,8 +11,7 @@ package IceInternal;
public class ProtocolPluginFacadeI implements ProtocolPluginFacade
{
- public
- ProtocolPluginFacadeI(Ice.Communicator communicator)
+ public ProtocolPluginFacadeI(Ice.Communicator communicator)
{
_communicator = communicator;
_instance = Util.getInstance(communicator);
@@ -22,82 +21,15 @@ public class ProtocolPluginFacadeI implements ProtocolPluginFacade
// Get the Communicator instance with which this facade is
// associated.
//
- public Ice.Communicator
- getCommunicator()
+ public Ice.Communicator getCommunicator()
{
return _communicator;
}
//
- // Get the endpoint host resolver.
- //
- public EndpointHostResolver
- getEndpointHostResolver()
- {
- return _instance.endpointHostResolver();
- }
-
- //
- // Get the protocol support.
- //
- public int
- getProtocolSupport()
- {
- return _instance.protocolSupport();
- }
-
- public boolean
- getPreferIPv6()
- {
- return _instance.preferIPv6();
- }
-
- //
- // Get the network proxy.
- //
- public NetworkProxy getNetworkProxy()
- {
- return _instance.networkProxy();
- }
-
- //
- // Get the default encoding to be used in endpoints.
- //
- public Ice.EncodingVersion
- getDefaultEncoding()
- {
- return _instance.defaultsAndOverrides().defaultEncoding;
- }
-
- //
- // Get the default hostname to be used in endpoints.
- //
- public String
- getDefaultHost()
- {
- return _instance.defaultsAndOverrides().defaultHost;
- }
-
- //
- // Get the network trace level and category name.
- //
- public int
- getNetworkTraceLevel()
- {
- return _instance.traceLevels().network;
- }
-
- public String
- getNetworkTraceCategory()
- {
- return _instance.traceLevels().networkCat;
- }
-
- //
// Register an EndpointFactory.
//
- public void
- addEndpointFactory(EndpointFactory factory)
+ public void addEndpointFactory(EndpointFactory factory)
{
_instance.endpointFactoryManager().add(factory);
}
@@ -105,8 +37,7 @@ public class ProtocolPluginFacadeI implements ProtocolPluginFacade
//
// Register an EndpointFactory.
//
- public EndpointFactory
- getEndpointFactory(short type)
+ public EndpointFactory getEndpointFactory(short type)
{
return _instance.endpointFactoryManager().get(type);
}
@@ -114,8 +45,7 @@ public class ProtocolPluginFacadeI implements ProtocolPluginFacade
//
// Look up a Java class by name.
//
- public Class<?>
- findClass(String className)
+ public Class<?> findClass(String className)
{
return _instance.findClass(className);
}
diff --git a/java/src/IceInternal/RoutableReference.java b/java/src/IceInternal/RoutableReference.java
index 563cbb90297..de9d002f8b4 100644
--- a/java/src/IceInternal/RoutableReference.java
+++ b/java/src/IceInternal/RoutableReference.java
@@ -283,6 +283,7 @@ public class RoutableReference extends Reference
assert(_adapterId.length() == 0);
for(EndpointI endpoint : _endpoints)
{
+ s.writeShort(endpoint.type());
endpoint.streamWrite(s);
}
}
diff --git a/java/src/IceInternal/Selector.java b/java/src/IceInternal/Selector.java
index 2ab11238b66..b23fbacb1b1 100644
--- a/java/src/IceInternal/Selector.java
+++ b/java/src/IceInternal/Selector.java
@@ -15,10 +15,11 @@ public final class Selector
{
}
- public
- Selector(Instance instance)
+ public Selector(Instance instance)
{
_instance = instance;
+ _selecting = false;
+ _interrupted = false;
try
{
@@ -36,8 +37,7 @@ public final class Selector
_keys = _selector.selectedKeys();
}
- public void
- destroy()
+ public void destroy()
{
try
{
@@ -49,14 +49,12 @@ public final class Selector
_selector = null;
}
- public void
- initialize(EventHandler handler)
+ public void initialize(EventHandler handler)
{
updateImpl(handler);
}
- public void
- update(EventHandler handler, int remove, int add)
+ public void update(EventHandler handler, int remove, int add)
{
int previous = handler._registered;
handler._registered = handler._registered & ~remove;
@@ -65,23 +63,11 @@ public final class Selector
{
return;
}
- updateImpl(handler);
- if(handler.hasMoreData() && (handler._disabled & SocketOperation.Read) == 0)
- {
- if((add & SocketOperation.Read) != 0)
- {
- _pendingHandlers.add(handler);
- }
- if((remove & SocketOperation.Read) != 0)
- {
- _pendingHandlers.remove(handler);
- }
- }
+ updateImpl(handler);
}
- public void
- enable(EventHandler handler, int status)
+ public void enable(EventHandler handler, int status)
{
if((handler._disabled & status) == 0)
{
@@ -92,180 +78,85 @@ public final class Selector
if((handler._registered & status) != 0)
{
updateImpl(handler);
-
- if((status & SocketOperation.Read) != 0 && handler.hasMoreData())
- {
- // Add back the pending handler if reads are enabled.
- _pendingHandlers.add(handler);
- }
}
}
- public void
- disable(EventHandler handler, int status)
+ public void disable(EventHandler handler, int status)
{
if((handler._disabled & status) != 0)
{
return;
}
handler._disabled = handler._disabled | status;
-
+
if((handler._registered & status) != 0)
{
updateImpl(handler);
-
- if((status & SocketOperation.Read) != 0 && handler.hasMoreData())
- {
- // Remove the pending handler if reads are disabled.
- _pendingHandlers.remove(handler);
- }
}
}
- public void
- finish(EventHandler handler)
+ public void finish(EventHandler handler)
{
- handler._registered = 0;
-
- if(handler._key != null)
+ if(handler._registered != 0)
{
- handler._key.cancel();
- handler._key = null;
- }
-
- _changes.remove(handler);
- _pendingHandlers.remove(handler);
- }
+ if(handler._key != null)
+ {
+ handler._key.cancel();
+ handler._key = null;
+ }
- public void
- startSelect()
- {
- assert(_changes.isEmpty());
+ _changes.remove(handler);
- //
- // Don't set _selecting = true if there are pending handlers, select() won't block
- // and will just call selectNow().
- //
- if(_pendingHandlers.isEmpty())
- {
- _selecting = true;
+ update(handler, handler._registered, SocketOperation.None);
}
}
- public void
- finishSelect(java.util.List<EventHandler> handlers, long timeout)
+ public void startSelect()
{
- _selecting = false;
- handlers.clear();
-
- if(!_changes.isEmpty())
- {
- for(EventHandler h : _changes)
- {
- updateImpl(h);
- }
- _changes.clear();
- }
- else if(_keys.isEmpty() && _pendingHandlers.isEmpty() && timeout <= 0)
+ if(_interrupted)
{
- //
- // This is necessary to prevent a busy loop in case of a spurious wake-up which
- // sometime occurs in the client thread pool when the communicator is destroyed.
- // If there are too many successive spurious wake-ups, we log an error.
- //
- try
- {
- Thread.sleep(1);
- }
- catch(java.lang.InterruptedException ex)
- {
- }
-
- if(++_spuriousWakeUp > 100)
- {
- _spuriousWakeUp = 0;
- _instance.initializationData().logger.warning("spurious selector wake up");
- }
- return;
- }
-
- _spuriousWakeUp = 0;
+ _interrupted = false;
- for(java.nio.channels.SelectionKey key : _keys)
- {
- EventHandler handler = (EventHandler)key.attachment();
- try
- {
- //
- // It's important to check for interestOps here because the event handler
- // registration might have changed above when _changes was processed. We
- // don't want to return event handlers which aren't interested anymore in
- // a given operation.
- //
- handler._ready = fromJavaOps(key.readyOps() & key.interestOps());
- if(handler.hasMoreData() && _pendingHandlers.remove(handler))
- {
- handler._ready |= SocketOperation.Read;
- }
- handlers.add(handler);
- }
- catch(java.nio.channels.CancelledKeyException ex)
+ if(!_changes.isEmpty())
{
- assert(handler._registered == 0);
+ updateSelector();
}
}
- _keys.clear();
+ _selecting = true;
+ }
- for(EventHandler handler : _pendingHandlers)
- {
- if(handler.hasMoreData())
- {
- handler._ready = SocketOperation.Read;
- handlers.add(handler);
- }
- }
- _pendingHandlers.clear();
+ public void finishSelect()
+ {
+ _selecting = false;
}
- public void
- select(long timeout)
+ public void select(java.util.List<EventHandlerOpPair> handlers, long timeout)
throws TimeoutException
{
while(true)
{
try
{
- //
- // Only block if _selecting = true, otherwise we call selectNow() to retrieve new
- // ready handlers and process handlers from _pendingHandlers.
- //
- if(_selecting)
+ if(timeout > 0)
{
- if(timeout > 0)
+ //
+ // NOTE: On some platforms, select() sometime returns slightly before
+ // the timeout (at least according to our monotonic time). To make sure
+ // timeouts are correctly detected, we wait for a little longer than
+ // the configured timeout (10ms).
+ //
+ long before = IceInternal.Time.currentMonotonicTimeMillis();
+ if(_selector.select(timeout * 1000 + 10) == 0)
{
- //
- // NOTE: On some platforms, select() sometime returns slightly before
- // the timeout (at least according to our monotonic time). To make sure
- // timeouts are correctly detected, we wait for a little longer than
- // the configured timeout (10ms).
- //
- long before = IceInternal.Time.currentMonotonicTimeMillis();
- if(_selector.select(timeout * 1000 + 10) == 0)
+ if(IceInternal.Time.currentMonotonicTimeMillis() - before >= timeout * 1000)
{
- if(IceInternal.Time.currentMonotonicTimeMillis() - before >= timeout * 1000)
- {
- throw new TimeoutException();
- }
+ throw new TimeoutException();
}
}
- else
- {
- _selector.select();
- }
}
else
{
- _selector.selectNow();
+ _selector.select();
}
}
catch(java.nio.channels.CancelledKeyException ex)
@@ -299,63 +190,111 @@ public final class Selector
break;
}
- }
- public void
- hasMoreData(EventHandler handler)
- {
- assert(!_selecting && handler.hasMoreData());
+ handlers.clear();
- //
- // Only add the handler if read is still registered and enabled.
- //
- if((handler._registered & ~handler._disabled & SocketOperation.Read) != 0)
+ if(_interrupted) // Interrupted, we have to process the interrupt before returning any handlers
+ {
+ return;
+ }
+
+ if(_keys.isEmpty() && timeout <= 0)
+ {
+ //
+ // This is necessary to prevent a busy loop in case of a spurious wake-up which
+ // sometime occurs in the client thread pool when the communicator is destroyed.
+ // If there are too many successive spurious wake-ups, we log an error.
+ //
+ try
+ {
+ Thread.sleep(1);
+ }
+ catch(java.lang.InterruptedException ex)
+ {
+ }
+
+ if(++_spuriousWakeUp > 100)
+ {
+ _spuriousWakeUp = 0;
+ _instance.initializationData().logger.warning("spurious selector wake up");
+ }
+ return;
+ }
+
+ _spuriousWakeUp = 0;
+
+ for(java.nio.channels.SelectionKey key : _keys)
{
- _pendingHandlers.add(handler);
+ EventHandler handler = (EventHandler)key.attachment();
+ try
+ {
+ //
+ // Use the intersection of readyOps and interestOps because we only want to
+ // report the operations in which the handler is still interested.
+ //
+ final int op = fromJavaOps(key.readyOps() & key.interestOps());
+ handlers.add(new EventHandlerOpPair(handler, op));
+ }
+ catch(java.nio.channels.CancelledKeyException ex)
+ {
+ assert(handler._registered == 0);
+ }
}
+ _keys.clear();
}
- private void
- updateImpl(EventHandler handler)
+ private void updateImpl(EventHandler handler)
{
+ _changes.add(handler);
if(_selecting)
{
- //
- // Queue the change since we can't change the selection key interest ops while a select
- // operation is in progress (it could block depending on the underlying implementaiton
- // of the Java selector).
- //
- if(_changes.isEmpty())
+ if(!_interrupted)
{
+ //
+ // We can't change the selection key interest ops while a select operation is in progress
+ // (it could block depending on the underlying implementation of the Java selector).
+ //
+ // Wake up the selector if necessary.
+ //
_selector.wakeup();
+ _interrupted = true;
}
- _changes.add(handler);
- return;
}
+ else
+ {
+ updateSelector();
+ }
+ }
- int ops = toJavaOps(handler, handler._registered & ~handler._disabled);
- if(handler._key == null)
+ private void updateSelector()
+ {
+ for(EventHandler handler : _changes)
{
- if(handler._registered != 0)
+ int status = handler._registered & ~handler._disabled;
+ int ops = toJavaOps(handler, status);
+ if(handler._key == null)
{
- try
+ if(handler._registered != 0)
{
- handler._key = handler.fd().register(_selector, ops, handler);
- }
- catch(java.nio.channels.ClosedChannelException ex)
- {
- assert(false);
+ try
+ {
+ handler._key = handler.fd().register(_selector, ops, handler);
+ }
+ catch(java.nio.channels.ClosedChannelException ex)
+ {
+ assert(false);
+ }
}
}
+ else
+ {
+ handler._key.interestOps(ops);
+ }
}
- else
- {
- handler._key.interestOps(ops);
- }
+ _changes.clear();
}
- int
- toJavaOps(EventHandler handler, int o)
+ int toJavaOps(EventHandler handler, int o)
{
int op = 0;
if((o & SocketOperation.Read) != 0)
@@ -380,8 +319,7 @@ public final class Selector
return op;
}
- int
- fromJavaOps(int o)
+ int fromJavaOps(int o)
{
int op = 0;
if((o & (java.nio.channels.SelectionKey.OP_READ | java.nio.channels.SelectionKey.OP_ACCEPT)) != 0)
@@ -399,7 +337,6 @@ public final class Selector
return op;
}
-
final private Instance _instance;
private java.nio.channels.Selector _selector;
@@ -408,5 +345,6 @@ public final class Selector
private java.util.HashSet<EventHandler> _changes = new java.util.HashSet<EventHandler>();
private java.util.HashSet<EventHandler> _pendingHandlers = new java.util.HashSet<EventHandler>();
private boolean _selecting;
+ private boolean _interrupted;
private int _spuriousWakeUp;
}
diff --git a/java/src/IceInternal/TcpAcceptor.java b/java/src/IceInternal/TcpAcceptor.java
index 301577f3286..d8f35bb625a 100644
--- a/java/src/IceInternal/TcpAcceptor.java
+++ b/java/src/IceInternal/TcpAcceptor.java
@@ -20,10 +20,10 @@ class TcpAcceptor implements Acceptor
public void
close()
{
- if(_traceLevels.network >= 1)
+ if(_instance.traceLevel() >= 1)
{
String s = "stopping to accept tcp connections at " + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ _instance.logger().trace(_instance.traceCategory(), s);
}
assert(_fd != null);
@@ -36,7 +36,7 @@ class TcpAcceptor implements Acceptor
{
// Nothing to do.
- if(_traceLevels.network >= 1)
+ if(_instance.traceLevel() >= 1)
{
StringBuffer s = new StringBuffer("listening for tcp connections at ");
s.append(toString());
@@ -49,7 +49,7 @@ class TcpAcceptor implements Acceptor
s.append("\nlocal interfaces: ");
s.append(IceUtilInternal.StringUtil.joinString(interfaces, ", "));
}
- _logger.trace(_traceLevels.networkCat, s.toString());
+ _instance.logger().trace(_instance.traceCategory(), s.toString());
}
}
@@ -58,18 +58,24 @@ class TcpAcceptor implements Acceptor
{
java.nio.channels.SocketChannel fd = Network.doAccept(_fd);
Network.setBlock(fd, false);
- Network.setTcpBufSize(fd, _instance.initializationData().properties, _logger);
+ Network.setTcpBufSize(fd, _instance.properties(), _instance.logger());
- if(_traceLevels.network >= 1)
+ if(_instance.traceLevel() >= 1)
{
String s = "accepted tcp connection\n" + Network.fdToString(fd);
- _logger.trace(_traceLevels.networkCat, s);
+ _instance.logger().trace(_instance.traceCategory(), s);
}
return new TcpTransceiver(_instance, fd);
}
public String
+ protocol()
+ {
+ return _instance.protocol();
+ }
+
+ public String
toString()
{
return Network.addrToString(_addr);
@@ -81,18 +87,16 @@ class TcpAcceptor implements Acceptor
return _addr.getPort();
}
- TcpAcceptor(Instance instance, String host, int port)
+ TcpAcceptor(ProtocolInstance instance, String host, int port)
{
_instance = instance;
- _traceLevels = instance.traceLevels();
- _logger = instance.initializationData().logger;
- _backlog = instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.TCP.Backlog", 511);
+ _backlog = instance.properties().getPropertyAsIntWithDefault("Ice.TCP.Backlog", 511);
try
{
_fd = Network.createTcpServerSocket();
Network.setBlock(_fd, false);
- Network.setTcpBufSize(_fd, _instance.initializationData().properties, _logger);
+ Network.setTcpBufSize(_fd, instance.properties(), _instance.logger());
if(!System.getProperty("os.name").startsWith("Windows"))
{
//
@@ -110,11 +114,11 @@ class TcpAcceptor implements Acceptor
//
Network.setReuseAddress(_fd, true);
}
- _addr = Network.getAddressForServer(host, port, _instance.protocolSupport(), _instance.preferIPv6());
- if(_traceLevels.network >= 2)
+ _addr = Network.getAddressForServer(host, port, instance.protocolSupport(), instance.preferIPv6());
+ if(instance.traceLevel() >= 2)
{
String s = "attempting to bind to tcp socket " + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ instance.logger().trace(instance.traceCategory(), s);
}
_addr = Network.doBind(_fd, _addr, _backlog);
}
@@ -142,9 +146,7 @@ class TcpAcceptor implements Acceptor
}
}
- private Instance _instance;
- private TraceLevels _traceLevels;
- private Ice.Logger _logger;
+ private ProtocolInstance _instance;
private java.nio.channels.ServerSocketChannel _fd;
private int _backlog;
private java.net.InetSocketAddress _addr;
diff --git a/java/src/IceInternal/TcpConnector.java b/java/src/IceInternal/TcpConnector.java
index e4289f27a17..4e1ff9ff5e1 100644
--- a/java/src/IceInternal/TcpConnector.java
+++ b/java/src/IceInternal/TcpConnector.java
@@ -11,49 +11,45 @@ package IceInternal;
final class TcpConnector implements Connector
{
- public Transceiver
- connect()
+ public Transceiver connect()
{
- if(_traceLevels.network >= 2)
+ if(_instance.traceLevel() >= 2)
{
- String s = "trying to establish tcp connection to " + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "trying to establish " + _instance.protocol() + " connection to " + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
try
{
java.nio.channels.SocketChannel fd = Network.createTcpSocket();
Network.setBlock(fd, false);
- Network.setTcpBufSize(fd, _instance.initializationData().properties, _logger);
+ Network.setTcpBufSize(fd, _instance.properties(), _instance.logger());
final java.net.InetSocketAddress addr = _proxy != null ? _proxy.getAddress() : _addr;
Network.doConnect(fd, addr);
return new TcpTransceiver(_instance, fd, _proxy, _addr);
}
catch(Ice.LocalException ex)
{
- if(_traceLevels.network >= 2)
+ if(_instance.traceLevel() >= 2)
{
- String s = "failed to establish tcp connection to " + toString() + "\n" + ex;
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "failed to establish " + _instance.protocol() + " connection to " + toString() + "\n" + ex;
+ _instance.logger().trace(_instance.traceCategory(), s);
}
throw ex;
}
}
- public short
- type()
+ public short type()
{
- return Ice.TCPEndpointType.value;
+ return _instance.type();
}
- public String
- toString()
+ public String toString()
{
return Network.addrToString(_proxy == null ? _addr : _proxy.getAddress());
}
- public int
- hashCode()
+ public int hashCode()
{
return _hashCode;
}
@@ -61,12 +57,10 @@ final class TcpConnector implements Connector
//
// Only for use by TcpEndpoint
//
- TcpConnector(Instance instance, java.net.InetSocketAddress addr, NetworkProxy proxy, int timeout,
+ TcpConnector(ProtocolInstance instance, java.net.InetSocketAddress addr, NetworkProxy proxy, int timeout,
String connectionId)
{
_instance = instance;
- _traceLevels = instance.traceLevels();
- _logger = instance.initializationData().logger;
_addr = addr;
_proxy = proxy;
_timeout = timeout;
@@ -79,8 +73,7 @@ final class TcpConnector implements Connector
_hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _connectionId);
}
- public boolean
- equals(java.lang.Object obj)
+ public boolean equals(java.lang.Object obj)
{
if(!(obj instanceof TcpConnector))
{
@@ -106,9 +99,7 @@ final class TcpConnector implements Connector
return Network.compareAddress(_addr, p._addr) == 0;
}
- private Instance _instance;
- private TraceLevels _traceLevels;
- private Ice.Logger _logger;
+ private ProtocolInstance _instance;
private java.net.InetSocketAddress _addr;
private NetworkProxy _proxy;
private int _timeout;
diff --git a/java/src/IceInternal/TcpEndpointFactory.java b/java/src/IceInternal/TcpEndpointFactory.java
index 6d0df0e77c3..d50fb5c37c7 100644
--- a/java/src/IceInternal/TcpEndpointFactory.java
+++ b/java/src/IceInternal/TcpEndpointFactory.java
@@ -11,40 +11,42 @@ package IceInternal;
final class TcpEndpointFactory implements EndpointFactory
{
- TcpEndpointFactory(Instance instance)
+ TcpEndpointFactory(ProtocolInstance instance)
{
_instance = instance;
}
- public short
- type()
+ public short type()
{
- return Ice.TCPEndpointType.value;
+ return _instance.type();
}
- public String
- protocol()
+ public String protocol()
{
- return "tcp";
+ return _instance.protocol();
}
- public EndpointI
- create(String str, boolean oaEndpoint)
+ public EndpointI create(java.util.ArrayList<String> args, boolean oaEndpoint)
{
- return new TcpEndpointI(_instance, str, oaEndpoint);
+ IPEndpointI endpt = new TcpEndpointI(_instance);
+ endpt.initWithOptions(args, oaEndpoint);
+ return endpt;
}
- public EndpointI
- read(BasicStream s)
+ public EndpointI read(BasicStream s)
{
- return new TcpEndpointI(s);
+ return new TcpEndpointI(_instance, s);
}
- public void
- destroy()
+ public void destroy()
{
_instance = null;
}
- private Instance _instance;
+ public EndpointFactory clone(ProtocolInstance instance)
+ {
+ return new TcpEndpointFactory(instance);
+ }
+
+ private ProtocolInstance _instance;
}
diff --git a/java/src/IceInternal/TcpEndpointI.java b/java/src/IceInternal/TcpEndpointI.java
index 9e6594b20ad..6fb7a7e9ce1 100644
--- a/java/src/IceInternal/TcpEndpointI.java
+++ b/java/src/IceInternal/TcpEndpointI.java
@@ -9,284 +9,61 @@
package IceInternal;
-final class TcpEndpointI extends EndpointI
+final class TcpEndpointI extends IPEndpointI
{
- public
- TcpEndpointI(Instance instance, String ho, int po, int ti, String conId, boolean co)
+ public TcpEndpointI(ProtocolInstance instance, String ho, int po, int ti, String conId, boolean co)
{
- super(conId);
- _instance = instance;
- _host = ho;
- _port = po;
+ super(instance, ho, po, conId);
_timeout = ti;
_compress = co;
- calcHashValue();
}
- public
- TcpEndpointI(Instance instance, String str, boolean oaEndpoint)
+ public TcpEndpointI(ProtocolInstance instance)
{
- super("");
- _instance = instance;
- _host = null;
- _port = 0;
+ super(instance);
_timeout = -1;
_compress = false;
-
- String[] arr = str.split("[ \t\n\r]+");
-
- int i = 0;
- while(i < arr.length)
- {
- if(arr[i].length() == 0)
- {
- i++;
- continue;
- }
-
- String option = arr[i++];
- if(option.length() != 2 || option.charAt(0) != '-')
- {
- throw new Ice.EndpointParseException("expected an endpoint option but found `" + option +
- "' in endpoint `tcp " + str + "'");
- }
-
- String argument = null;
- if(i < arr.length && arr[i].charAt(0) != '-')
- {
- argument = arr[i++];
- if(argument.charAt(0) == '\"' && argument.charAt(argument.length() - 1) == '\"')
- {
- argument = argument.substring(1, argument.length() - 1);
- }
- }
-
- switch(option.charAt(1))
- {
- case 'h':
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -h option in endpoint `tcp "
- + str + "'");
- }
-
- _host = argument;
- break;
- }
-
- case 'p':
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -p option in endpoint `tcp "
- + str + "'");
- }
-
- try
- {
- _port = Integer.parseInt(argument);
- }
- catch(NumberFormatException ex)
- {
- throw new Ice.EndpointParseException("invalid port value `" + argument +
- "' in endpoint `tcp " + str + "'");
- }
-
- if(_port < 0 || _port > 65535)
- {
- throw new Ice.EndpointParseException("port value `" + argument +
- "' out of range in endpoint `tcp " + str + "'");
- }
-
- break;
- }
-
- case 't':
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -t option in endpoint `tcp "
- + str + "'");
- }
-
- try
- {
- _timeout = Integer.parseInt(argument);
- }
- catch(NumberFormatException ex)
- {
- throw new Ice.EndpointParseException("invalid timeout value `" + argument +
- "' in endpoint `tcp " + str + "'");
- }
-
- break;
- }
-
- case 'z':
- {
- if(argument != null)
- {
- throw new Ice.EndpointParseException("unexpected argument `" + argument +
- "' provided for -z option in `tcp " + str + "'");
- }
-
- _compress = true;
- break;
- }
-
- default:
- {
- throw new Ice.EndpointParseException("unknown option `" + option + "' in `tcp " + str + "'");
- }
- }
- }
-
- if(_host == null)
- {
- _host = _instance.defaultsAndOverrides().defaultHost;
- }
- else if(_host.equals("*"))
- {
- if(oaEndpoint)
- {
- _host = null;
- }
- else
- {
- throw new Ice.EndpointParseException("`-h *' not valid for proxy endpoint `tcp " + str + "'");
- }
- }
-
- if(_host == null)
- {
- _host = "";
- }
-
- calcHashValue();
}
- public
- TcpEndpointI(BasicStream s)
+ public TcpEndpointI(ProtocolInstance instance, BasicStream s)
{
- super("");
- _instance = s.instance();
- s.startReadEncaps();
- _host = s.readString();
- _port = s.readInt();
+ super(instance, s);
_timeout = s.readInt();
_compress = s.readBool();
- s.endReadEncaps();
- calcHashValue();
- }
-
- //
- // Marshal the endpoint
- //
- public void
- streamWrite(BasicStream s)
- {
- s.writeShort(Ice.TCPEndpointType.value);
- s.startWriteEncaps();
- s.writeString(_host);
- s.writeInt(_port);
- s.writeInt(_timeout);
- s.writeBool(_compress);
- s.endWriteEncaps();
- }
-
- //
- // Convert the endpoint to its string form
- //
- public String
- _toString()
- {
- //
- // WARNING: Certain features, such as proxy validation in Glacier2,
- // depend on the format of proxy strings. Changes to toString() and
- // methods called to generate parts of the reference string could break
- // these features. Please review for all features that depend on the
- // format of proxyToString() before changing this and related code.
- //
- String s = "tcp";
-
- if(_host != null && _host.length() > 0)
- {
- s += " -h ";
- boolean addQuote = _host.indexOf(':') != -1;
- if(addQuote)
- {
- s += "\"";
- }
- s += _host;
- if(addQuote)
- {
- s += "\"";
- }
- }
-
- s += " -p " + _port;
-
- if(_timeout != -1)
- {
- s += " -t " + _timeout;
- }
- if(_compress)
- {
- s += " -z";
- }
- return s;
}
//
// Return the endpoint information.
//
- public Ice.EndpointInfo
- getInfo()
+ public Ice.EndpointInfo getInfo()
{
- return new Ice.TCPEndpointInfo(_timeout, _compress, _host, _port)
+ Ice.TCPEndpointInfo info = new Ice.TCPEndpointInfo()
{
public short type()
{
- return Ice.TCPEndpointType.value;
+ return TcpEndpointI.this.type();
}
-
+
public boolean datagram()
{
- return false;
+ return TcpEndpointI.this.datagram();
}
-
+
public boolean secure()
{
- return false;
+ return TcpEndpointI.this.secure();
}
- };
- }
-
- //
- // Return the endpoint type
- //
- public short
- type()
- {
- return Ice.TCPEndpointType.value;
- }
+ };
- //
- // Return the protocol name
- //
- public String
- protocol()
- {
- return "tcp";
+ fillEndpointInfo(info);
+ return info;
}
//
// Return the timeout for the endpoint in milliseconds. 0 means
// non-blocking, -1 means no timeout.
//
- public int
- timeout()
+ public int timeout()
{
return _timeout;
}
@@ -296,8 +73,7 @@ final class TcpEndpointI extends EndpointI
// that timeouts are supported by the endpoint. Otherwise the same
// endpoint is returned.
//
- public EndpointI
- timeout(int timeout)
+ public EndpointI timeout(int timeout)
{
if(timeout == _timeout)
{
@@ -310,27 +86,10 @@ final class TcpEndpointI extends EndpointI
}
//
- // Return a new endpoint with a different connection id.
- //
- public EndpointI
- connectionId(String connectionId)
- {
- if(connectionId.equals(_connectionId))
- {
- return this;
- }
- else
- {
- return new TcpEndpointI(_instance, _host, _port, _timeout, connectionId, _compress);
- }
- }
-
- //
// Return true if the endpoints support bzip2 compress, or false
// otherwise.
//
- public boolean
- compress()
+ public boolean compress()
{
return _compress;
}
@@ -340,8 +99,7 @@ final class TcpEndpointI extends EndpointI
// provided that compression is supported by the
// endpoint. Otherwise the same endpoint is returned.
//
- public EndpointI
- compress(boolean compress)
+ public EndpointI compress(boolean compress)
{
if(compress == _compress)
{
@@ -356,8 +114,7 @@ final class TcpEndpointI extends EndpointI
//
// Return true if the endpoint is datagram-based.
//
- public boolean
- datagram()
+ public boolean datagram()
{
return false;
}
@@ -365,8 +122,7 @@ final class TcpEndpointI extends EndpointI
//
// Return true if the endpoint is secure.
//
- public boolean
- secure()
+ public boolean secure()
{
return false;
}
@@ -378,103 +134,54 @@ final class TcpEndpointI extends EndpointI
// "effective" endpoint, which might differ from this endpoint,
// for example, if a dynamic port number is assigned.
//
- public Transceiver
- transceiver(EndpointIHolder endpoint)
+ public Transceiver transceiver(EndpointIHolder endpoint)
{
endpoint.value = this;
return null;
}
//
- // Return connectors for this endpoint, or empty list if no connector
- // is available.
- //
- public java.util.List<Connector>
- connectors(Ice.EndpointSelectionType selType)
- {
- return _instance.endpointHostResolver().resolve(_host, _port, selType, this);
- }
-
- public void
- connectors_async(Ice.EndpointSelectionType selType, EndpointI_connectors callback)
- {
- _instance.endpointHostResolver().resolve(_host, _port, selType, this, callback);
- }
-
- //
// Return an acceptor for this endpoint, or null if no acceptors
// is available. In case an acceptor is created, this operation
// also returns a new "effective" endpoint, which might differ
// from this endpoint, for example, if a dynamic port number is
// assigned.
//
- public Acceptor
- acceptor(EndpointIHolder endpoint, String adapterName)
+ public Acceptor acceptor(EndpointIHolder endpoint, String adapterName)
{
TcpAcceptor p = new TcpAcceptor(_instance, _host, _port);
- endpoint.value = new TcpEndpointI(_instance, _host, p.effectivePort(), _timeout, _connectionId, _compress);
+ endpoint.value = createEndpoint(_host, p.effectivePort(), _connectionId);
return p;
}
- //
- // Expand endpoint out in to separate endpoints for each local
- // host if listening on INADDR_ANY.
- //
- public java.util.List<EndpointI>
- expand()
+ public String options()
{
- java.util.List<EndpointI> endps = new java.util.ArrayList<EndpointI>();
- java.util.List<String> hosts = Network.getHostsForEndpointExpand(_host, _instance.protocolSupport(), false);
- if(hosts == null || hosts.isEmpty())
- {
- endps.add(this);
- }
- else
- {
- for(String h : hosts)
- {
- endps.add(new TcpEndpointI(_instance, h, _port, _timeout, _connectionId, _compress));
- }
- }
- return endps;
- }
+ //
+ // WARNING: Certain features, such as proxy validation in Glacier2,
+ // depend on the format of proxy strings. Changes to toString() and
+ // methods called to generate parts of the reference string could break
+ // these features. Please review for all features that depend on the
+ // format of proxyToString() before changing this and related code.
+ //
+ String s = super.options();
- //
- // Check whether the endpoint is equivalent to another one.
- //
- public boolean
- equivalent(EndpointI endpoint)
- {
- if(!(endpoint instanceof TcpEndpointI))
+ if(_timeout != -1)
{
- return false;
+ s += " -t " + _timeout;
}
- TcpEndpointI tcpEndpointI = (TcpEndpointI)endpoint;
- return tcpEndpointI._host.equals(_host) && tcpEndpointI._port == _port;
- }
- public java.util.List<Connector>
- connectors(java.util.List<java.net.InetSocketAddress> addresses, NetworkProxy proxy)
- {
- java.util.List<Connector> connectors = new java.util.ArrayList<Connector>();
- for(java.net.InetSocketAddress p : addresses)
+ if(_compress)
{
- connectors.add(new TcpConnector(_instance, p, proxy, _timeout, _connectionId));
+ s += " -z";
}
- return connectors;
- }
- public int
- hashCode()
- {
- return _hashCode;
+ return s;
}
//
// Compare endpoints for sorting purposes
//
- public int
- compareTo(EndpointI obj) // From java.lang.Comparable
+ public int compareTo(EndpointI obj) // From java.lang.Comparable
{
if(!(obj instanceof TcpEndpointI))
{
@@ -486,23 +193,6 @@ final class TcpEndpointI extends EndpointI
{
return 0;
}
- else
- {
- int r = super.compareTo(p);
- if(r != 0)
- {
- return r;
- }
- }
-
- if(_port < p._port)
- {
- return -1;
- }
- else if(p._port < _port)
- {
- return 1;
- }
if(_timeout < p._timeout)
{
@@ -522,26 +212,94 @@ final class TcpEndpointI extends EndpointI
return 1;
}
- return _host.compareTo(p._host);
+ return super.compareTo(obj);
}
- private void
- calcHashValue()
+ protected void streamWriteImpl(BasicStream s)
{
- int h = 5381;
- h = IceInternal.HashUtil.hashAdd(h, Ice.TCPEndpointType.value);
- h = IceInternal.HashUtil.hashAdd(h, _host);
- h = IceInternal.HashUtil.hashAdd(h, _port);
+ super.streamWriteImpl(s);
+ s.writeInt(_timeout);
+ s.writeBool(_compress);
+ }
+
+ protected int hashInit(int h)
+ {
+ h = super.hashInit(h);
h = IceInternal.HashUtil.hashAdd(h, _timeout);
- h = IceInternal.HashUtil.hashAdd(h, _connectionId);
h = IceInternal.HashUtil.hashAdd(h, _compress);
- _hashCode = h;
+ return h;
+ }
+
+ protected void fillEndpointInfo(Ice.IPEndpointInfo info)
+ {
+ super.fillEndpointInfo(info);
+ if(info instanceof Ice.TCPEndpointInfo)
+ {
+ Ice.TCPEndpointInfo tcpInfo = (Ice.TCPEndpointInfo)info;
+ tcpInfo.timeout = _timeout;
+ tcpInfo.compress = _compress;
+ }
+ }
+
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ if(super.checkOption(option, argument, endpoint))
+ {
+ return true;
+ }
+
+ switch(option.charAt(1))
+ {
+ case 't':
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -t option in endpoint " + endpoint);
+ }
+
+ try
+ {
+ _timeout = Integer.parseInt(argument);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid timeout value `" + argument +
+ "' in endpoint " + endpoint);
+ }
+
+ return true;
+ }
+
+ case 'z':
+ {
+ if(argument != null)
+ {
+ throw new Ice.EndpointParseException("unexpected argument `" + argument +
+ "' provided for -z option in " + endpoint);
+ }
+
+ _compress = true;
+
+ return true;
+ }
+
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+ protected Connector createConnector(java.net.InetSocketAddress addr, NetworkProxy proxy)
+ {
+ return new TcpConnector(_instance, addr, proxy, _timeout, _connectionId);
+ }
+
+ protected IPEndpointI createEndpoint(String host, int port, String connectionId)
+ {
+ return new TcpEndpointI(_instance, host, port, _timeout, connectionId, _compress);
}
- private Instance _instance;
- private String _host;
- private int _port;
private int _timeout;
private boolean _compress;
- private int _hashCode;
}
diff --git a/java/src/IceInternal/TcpTransceiver.java b/java/src/IceInternal/TcpTransceiver.java
index 7122f8ff7cf..fd8bcc9ba54 100644
--- a/java/src/IceInternal/TcpTransceiver.java
+++ b/java/src/IceInternal/TcpTransceiver.java
@@ -11,15 +11,13 @@ package IceInternal;
final class TcpTransceiver implements Transceiver
{
- public java.nio.channels.SelectableChannel
- fd()
+ public java.nio.channels.SelectableChannel fd()
{
assert(_fd != null);
return _fd;
}
- public int
- initialize(Buffer readBuffer, Buffer writeBuffer)
+ public int initialize(Buffer readBuffer, Buffer writeBuffer, Ice.BooleanHolder moreData)
{
try
{
@@ -28,7 +26,7 @@ final class TcpTransceiver implements Transceiver
_state = StateConnectPending;
return SocketOperation.Connect;
}
- else if(_state == StateConnectPending)
+ else if(_state <= StateConnectPending)
{
Network.doFinishConnect(_fd);
_desc = Network.fdToString(_fd, _proxy, _addr);
@@ -44,7 +42,7 @@ final class TcpTransceiver implements Transceiver
//
// Write the proxy connection message.
//
- if(write(writeBuffer))
+ if(write(writeBuffer) == SocketOperation.None)
{
//
// Write completed without blocking.
@@ -54,8 +52,7 @@ final class TcpTransceiver implements Transceiver
//
// Try to read the response.
//
- Ice.BooleanHolder dummy = new Ice.BooleanHolder();
- if(read(readBuffer, dummy))
+ if(read(readBuffer, moreData) == SocketOperation.None)
{
//
// Read completed without blocking - fall through.
@@ -103,32 +100,38 @@ final class TcpTransceiver implements Transceiver
}
catch(Ice.LocalException ex)
{
- if(_traceLevels.network >= 2)
+ if(_instance.traceLevel() >= 2)
{
StringBuilder s = new StringBuilder(128);
- s.append("failed to establish tcp connection\n");
+ s.append("failed to establish " + _instance.protocol() + " connection\n");
s.append(Network.fdToString(_fd, _proxy, _addr));
- _logger.trace(_traceLevels.networkCat, s.toString());
+ _instance.logger().trace(_instance.traceCategory(), s.toString());
}
throw ex;
}
assert(_state == StateConnected);
- if(_traceLevels.network >= 1)
+ if(_instance.traceLevel() >= 1)
{
- String s = "tcp connection established\n" + _desc;
- _logger.trace(_traceLevels.networkCat, s);
+ String s = _instance.protocol() + " connection established\n" + _desc;
+ _instance.logger().trace(_instance.traceCategory(), s);
}
return SocketOperation.None;
}
- public void
- close()
+ public int closing(boolean initiator, Ice.LocalException ex)
{
- if(_state == StateConnected && _traceLevels.network >= 1)
+ // If we are initiating the connection closure, wait for the peer
+ // to close the TCP/IP connection. Otherwise, close immediately.
+ return initiator ? SocketOperation.Read : SocketOperation.None;
+ }
+
+ public void close()
+ {
+ if(_state == StateConnected && _instance.traceLevel() >= 1)
{
- String s = "closing tcp connection\n" + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "closing " + _instance.protocol() + " connection\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
assert(_fd != null);
@@ -147,22 +150,26 @@ final class TcpTransceiver implements Transceiver
}
@SuppressWarnings("deprecation")
- public boolean
- write(Buffer buf)
+ public int write(Buffer buf)
{
+ final int size = buf.b.limit();
+ int packetSize = size - buf.b.position();
+
+ if(packetSize == 0)
+ {
+ return SocketOperation.None;
+ }
+
//
- // We don't want write to be called on android main thread as this will cause
- // NetworkOnMainThreadException to be thrown. If that is the android main thread
- // we return false and this method will be later called from the thread pool.
+ // We don't want write to be called on Android's main thread as this will cause
+ // NetworkOnMainThreadException to be thrown. If this is the Android main thread
+ // we return false and this method will be called later from the thread pool.
//
if(Util.isAndroidMainThread(Thread.currentThread()))
{
- return false;
+ return SocketOperation.Write;
}
- final int size = buf.b.limit();
- int packetSize = size - buf.b.position();
-
//
// Limit packet size to avoid performance problems on WIN32
//
@@ -177,8 +184,8 @@ final class TcpTransceiver implements Transceiver
try
{
assert(_fd != null);
- int ret = _fd.write(buf.b);
+ int ret = _fd.write(buf.b);
if(ret == -1)
{
throw new Ice.ConnectionLostException();
@@ -186,20 +193,21 @@ final class TcpTransceiver implements Transceiver
else if(ret == 0)
{
//
- // Writing would block, so we reset the limit (if necessary) and return false to indicate
+ // Writing would block, so we reset the limit (if necessary) and indicate
// that more data must be sent.
//
if(packetSize == _maxSendPacketSize)
{
buf.b.limit(size);
}
- return false;
+ return SocketOperation.Write;
}
- if(_traceLevels.network >= 3)
+ if(_instance.traceLevel() >= 3)
{
- String s = "sent " + ret + " of " + packetSize + " bytes via tcp\n" + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "sent " + ret + " of " + packetSize + " bytes via " + _instance.protocol() + "\n" +
+ toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
if(packetSize == _maxSendPacketSize)
@@ -222,15 +230,18 @@ final class TcpTransceiver implements Transceiver
throw new Ice.SocketException(ex);
}
}
- return true;
+
+ return SocketOperation.None;
}
@SuppressWarnings("deprecation")
- public boolean
- read(Buffer buf, Ice.BooleanHolder moreData)
+ public int read(Buffer buf, Ice.BooleanHolder moreData)
{
int packetSize = buf.b.remaining();
- moreData.value = false;
+ if(packetSize == 0)
+ {
+ return SocketOperation.None;
+ }
while(buf.b.hasRemaining())
{
@@ -246,15 +257,16 @@ final class TcpTransceiver implements Transceiver
if(ret == 0)
{
- return false;
+ return SocketOperation.Read;
}
if(ret > 0)
{
- if(_traceLevels.network >= 3)
+ if(_instance.traceLevel() >= 3)
{
- String s = "received " + ret + " of " + packetSize + " bytes via tcp\n" + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "received " + ret + " of " + packetSize + " bytes via " + _instance.protocol() +
+ "\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
}
@@ -270,23 +282,20 @@ final class TcpTransceiver implements Transceiver
}
}
- return true;
+ return SocketOperation.None;
}
- public String
- type()
+ public String protocol()
{
- return "tcp";
+ return _instance.protocol();
}
- public String
- toString()
+ public String toString()
{
return _desc;
}
- public Ice.ConnectionInfo
- getInfo()
+ public Ice.ConnectionInfo getInfo()
{
Ice.TCPConnectionInfo info = new Ice.TCPConnectionInfo();
if(_fd != null)
@@ -303,8 +312,7 @@ final class TcpTransceiver implements Transceiver
return info;
}
- public void
- checkSendSize(Buffer buf, int messageSizeMax)
+ public void checkSendSize(Buffer buf, int messageSizeMax)
{
if(buf.size() > messageSizeMax)
{
@@ -313,14 +321,13 @@ final class TcpTransceiver implements Transceiver
}
@SuppressWarnings("deprecation")
- TcpTransceiver(Instance instance, java.nio.channels.SocketChannel fd, NetworkProxy proxy,
+ TcpTransceiver(ProtocolInstance instance, java.nio.channels.SocketChannel fd, NetworkProxy proxy,
java.net.InetSocketAddress addr)
{
+ _instance = instance;
_fd = fd;
_proxy = proxy;
_addr = addr;
- _traceLevels = instance.traceLevels();
- _logger = instance.initializationData().logger;
_state = StateNeedConnect;
_desc = "";
@@ -341,11 +348,10 @@ final class TcpTransceiver implements Transceiver
}
@SuppressWarnings("deprecation")
- TcpTransceiver(Instance instance, java.nio.channels.SocketChannel fd)
+ TcpTransceiver(ProtocolInstance instance, java.nio.channels.SocketChannel fd)
{
+ _instance = instance;
_fd = fd;
- _traceLevels = instance.traceLevels();
- _logger = instance.initializationData().logger;
_state = StateConnected;
_desc = Network.fdToString(_fd);
@@ -382,14 +388,13 @@ final class TcpTransceiver implements Transceiver
}
}
+ private ProtocolInstance _instance;
private java.nio.channels.SocketChannel _fd;
private NetworkProxy _proxy;
private java.net.InetSocketAddress _addr;
- private TraceLevels _traceLevels;
- private Ice.Logger _logger;
- private String _desc;
private int _state;
+ private String _desc;
private int _maxSendPacketSize;
private static final int StateNeedConnect = 0;
diff --git a/java/src/IceInternal/ThreadPool.java b/java/src/IceInternal/ThreadPool.java
index 03e3713fe93..8ab584e9623 100644
--- a/java/src/IceInternal/ThreadPool.java
+++ b/java/src/IceInternal/ThreadPool.java
@@ -25,7 +25,7 @@ public final class ThreadPool
}
}
}
-
+
static final class FinishedWorkItem implements ThreadPoolWorkItem
{
public
@@ -60,6 +60,16 @@ public final class ThreadPool
private final EventHandlerThread _thread;
}
+ static final class InterruptWorkItem implements ThreadPoolWorkItem
+ {
+ public void execute(ThreadPoolCurrent current)
+ {
+ // Nothing to do, this is just used to interrupt the thread pool selector.
+ }
+ }
+
+ private static ThreadPoolWorkItem _interruptWorkItem = new InterruptWorkItem();
+
//
// Exception raised by the thread pool work queue when the thread pool
// is destroyed.
@@ -257,7 +267,33 @@ public final class ThreadPool
update(EventHandler handler, int remove, int add)
{
assert(!_destroyed);
+
+ // Don't remove what needs to be added
+ remove &= ~add;
+
+ // Don't remove/add if already un-registered or registered
+ remove = handler._registered & remove;
+ add = ~handler._registered & add;
+ if(remove == add)
+ {
+ return;
+ }
+
_selector.update(handler, remove, add);
+
+ if((add & SocketOperation.Read) != 0 && handler._hasMoreData.value &&
+ (handler._disabled & SocketOperation.Read) == 0)
+ {
+ if(_pendingHandlers.isEmpty())
+ {
+ _workQueue.queue(_interruptWorkItem); // Interrupt select()
+ }
+ _pendingHandlers.add(handler);
+ }
+ else if((remove & SocketOperation.Read) != 0)
+ {
+ _pendingHandlers.remove(handler);
+ }
}
public void
@@ -312,6 +348,8 @@ public final class ThreadPool
{
ThreadPoolCurrent current = new ThreadPoolCurrent(_instance, this, thread);
boolean select = false;
+ java.util.List<EventHandlerOpPair> handlers = new java.util.ArrayList<EventHandlerOpPair>();
+
while(true)
{
if(current._handler != null)
@@ -335,7 +373,7 @@ public final class ThreadPool
{
try
{
- _selector.select(_serverIdleTime);
+ _selector.select(handlers, _serverIdleTime);
}
catch(Selector.TimeoutException ex)
{
@@ -356,8 +394,25 @@ public final class ThreadPool
{
if(select)
{
- _selector.finishSelect(_handlers, _serverIdleTime);
+ java.util.List<EventHandlerOpPair> tmp = _handlers;
+ _handlers = handlers;
+ handlers = tmp;
+
+ if(!_pendingHandlers.isEmpty())
+ {
+ for(EventHandlerOpPair pair : _handlers)
+ {
+ _pendingHandlers.remove(pair.handler);
+ }
+ for(EventHandler p : _pendingHandlers)
+ {
+ _handlers.add(new EventHandlerOpPair(p, SocketOperation.Read));
+ }
+ _pendingHandlers.clear();
+ }
+
_nextHandler = _handlers.iterator();
+ _selector.finishSelect();
select = false;
}
else if(!current._leader && followerWait(current))
@@ -375,9 +430,14 @@ public final class ThreadPool
//
--_inUseIO;
- if((current.operation & SocketOperation.Read) != 0 && current._handler.hasMoreData())
+ if(current._handler._hasMoreData.value &&
+ (current._handler._registered & SocketOperation.Read) != 0)
{
- _selector.hasMoreData(current._handler);
+ if(_pendingHandlers.isEmpty())
+ {
+ _workQueue.queue(_interruptWorkItem);
+ }
+ _pendingHandlers.add(current._handler);
}
}
else
@@ -386,7 +446,19 @@ public final class ThreadPool
// If the handler called ioCompleted(), we re-enable the handler in
// case it was disabled and we decrease the number of thread in use.
//
- _selector.enable(current._handler, current.operation);
+ if(_serialize)
+ {
+ _selector.enable(current._handler, current.operation);
+ if(current._handler._hasMoreData.value &&
+ (current._handler._registered & SocketOperation.Read) != 0)
+ {
+ if(_pendingHandlers.isEmpty())
+ {
+ _workQueue.queue(_interruptWorkItem); // Interrupt select()
+ }
+ _pendingHandlers.add(current._handler);
+ }
+ }
assert(_inUse > 0);
--_inUse;
}
@@ -396,20 +468,34 @@ public final class ThreadPool
return; // Wait timed-out.
}
}
- else if(!current._ioCompleted &&
- (current.operation & SocketOperation.Read) != 0 && current._handler.hasMoreData())
+ else if(current._handler._hasMoreData.value &&
+ (current._handler._registered & SocketOperation.Read) != 0)
{
- _selector.hasMoreData(current._handler);
+ if(_pendingHandlers.isEmpty())
+ {
+ _workQueue.queue(_interruptWorkItem); // Interrupt select()
+ }
+ _pendingHandlers.add(current._handler);
}
//
// Get the next ready handler.
//
- if(_nextHandler.hasNext())
+ EventHandlerOpPair next = null;
+ while(_nextHandler.hasNext())
+ {
+ EventHandlerOpPair n = _nextHandler.next();
+ if((n.op & n.handler._registered) != 0)
+ {
+ next = n;
+ break;
+ }
+ }
+ if(next != null)
{
current._ioCompleted = false;
- current._handler = _nextHandler.next();
- current.operation = current._handler._ready;
+ current._handler = next.handler;
+ current.operation = next.op;
thread.setState(Ice.Instrumentation.ThreadState.ThreadStateInUseForIO);
}
else
@@ -431,6 +517,7 @@ public final class ThreadPool
}
else
{
+ _handlers.clear();
_selector.startSelect();
select = true;
thread.setState(Ice.Instrumentation.ThreadState.ThreadStateIdle);
@@ -462,17 +549,29 @@ public final class ThreadPool
if(_sizeMax > 1)
{
--_inUseIO;
-
- if((current.operation & SocketOperation.Read) != 0 && current._handler.hasMoreData())
+
+ if(!_destroyed)
{
- _selector.hasMoreData(current._handler);
+ if(_serialize)
+ {
+ _selector.disable(current._handler, current.operation);
+
+ // Make sure the handler isn't in the set of pending handlers (this can
+ // for example occur if the handler is has more data and its added by
+ // ThreadPool::update while we were processing IO).
+ _pendingHandlers.remove(current._handler);
+ }
+ else if(current._handler._hasMoreData.value &&
+ (current._handler._registered & SocketOperation.Read) != 0)
+ {
+ if(_pendingHandlers.isEmpty())
+ {
+ _workQueue.queue(_interruptWorkItem); // Interrupt select()
+ }
+ _pendingHandlers.add(current._handler);
+ }
}
-
- if(_serialize && !_destroyed)
- {
- _selector.disable(current._handler, current.operation);
- }
-
+
if(current._leader)
{
//
@@ -527,10 +626,6 @@ public final class ThreadPool
}
}
}
- else if((current.operation & SocketOperation.Read) != 0 && current._handler.hasMoreData())
- {
- _selector.hasMoreData(current._handler);
- }
}
private synchronized void
@@ -563,7 +658,7 @@ public final class ThreadPool
//
// Wait to be promoted and for all the IO threads to be done.
//
- while(!_promote || _inUseIO == _sizeIO || !_nextHandler.hasNext() && _inUseIO > 0)
+ while(!_promote || _inUseIO == _sizeIO || (!_nextHandler.hasNext() && _inUseIO > 0))
{
try
{
@@ -740,8 +835,9 @@ public final class ThreadPool
private int _inUse; // Number of threads that are currently in use.
private int _inUseIO; // Number of threads that are currently performing IO.
- private java.util.List<EventHandler> _handlers = new java.util.ArrayList<EventHandler>();
- private java.util.Iterator<EventHandler> _nextHandler;
+ private java.util.List<EventHandlerOpPair> _handlers = new java.util.ArrayList<EventHandlerOpPair>();
+ private java.util.Iterator<EventHandlerOpPair> _nextHandler;
+ private java.util.HashSet<EventHandler> _pendingHandlers = new java.util.HashSet<EventHandler>();
private boolean _promote;
}
diff --git a/java/src/IceInternal/ThreadPoolWorkQueue.java b/java/src/IceInternal/ThreadPoolWorkQueue.java
index eab2b4d2b88..ba3c19eaea8 100644
--- a/java/src/IceInternal/ThreadPoolWorkQueue.java
+++ b/java/src/IceInternal/ThreadPoolWorkQueue.java
@@ -149,12 +149,6 @@ final class ThreadPoolWorkQueue extends EventHandler
{
return (java.nio.channels.SelectableChannel)_fdIntrRead;
}
-
- public boolean
- hasMoreData()
- {
- return false;
- }
public void
postMessage()
diff --git a/java/src/IceInternal/Transceiver.java b/java/src/IceInternal/Transceiver.java
index 329ff3e1386..ad372615208 100644
--- a/java/src/IceInternal/Transceiver.java
+++ b/java/src/IceInternal/Transceiver.java
@@ -13,35 +13,14 @@ public interface Transceiver
{
java.nio.channels.SelectableChannel fd();
- //
- // Initialize the transceiver.
- //
- // Returns the status if the initialize operation.
- //
- int initialize(Buffer readBuffer, Buffer writeBuffer);
-
+ int initialize(Buffer readBuffer, Buffer writeBuffer, Ice.BooleanHolder moreData);
+ int closing(boolean initiator, Ice.LocalException ex);
void close();
- //
- // Write data.
- //
- // Returns true if all the data was written, false otherwise.
- //
- boolean write(Buffer buf);
-
- //
- // Read data.
- //
- // Returns true if all the requested data was read, false otherwise.
- //
- // NOTE: In Java, read() returns a boolean in moreData to indicate
- // whether the transceiver has read more data than requested.
- // If moreData is true, read should be called again without
- // calling select on the FD.
- //
- boolean read(Buffer buf, Ice.BooleanHolder moreData);
+ int write(Buffer buf);
+ int read(Buffer buf, Ice.BooleanHolder moreData);
- String type();
+ String protocol();
String toString();
Ice.ConnectionInfo getInfo();
void checkSendSize(Buffer buf, int messageSizeMax);
diff --git a/java/src/IceInternal/UdpConnector.java b/java/src/IceInternal/UdpConnector.java
index b70e1b4c8ec..054014efc2c 100644
--- a/java/src/IceInternal/UdpConnector.java
+++ b/java/src/IceInternal/UdpConnector.java
@@ -11,33 +11,28 @@ package IceInternal;
final class UdpConnector implements Connector
{
- public Transceiver
- connect()
+ public Transceiver connect()
{
return new UdpTransceiver(_instance, _addr, _mcastInterface, _mcastTtl);
}
- public java.nio.channels.SelectableChannel
- fd()
+ public java.nio.channels.SelectableChannel fd()
{
assert(false); // Shouldn't be called, startConnect always completes immediately.
return null;
}
- public short
- type()
+ public short type()
{
- return Ice.UDPEndpointType.value;
+ return _instance.type();
}
- public String
- toString()
+ public String toString()
{
return Network.addrToString(_addr);
}
- public int
- hashCode()
+ public int hashCode()
{
return _hashCode;
}
@@ -45,7 +40,7 @@ final class UdpConnector implements Connector
//
// Only for use by TcpEndpoint
//
- UdpConnector(Instance instance, java.net.InetSocketAddress addr, String mcastInterface, int mcastTtl,
+ UdpConnector(ProtocolInstance instance, java.net.InetSocketAddress addr, String mcastInterface, int mcastTtl,
String connectionId)
{
_instance = instance;
@@ -62,8 +57,7 @@ final class UdpConnector implements Connector
_hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _connectionId);
}
- public boolean
- equals(java.lang.Object obj)
+ public boolean equals(java.lang.Object obj)
{
if(!(obj instanceof UdpConnector))
{
@@ -92,9 +86,9 @@ final class UdpConnector implements Connector
}
return Network.compareAddress(_addr, p._addr) == 0;
- }
+ }
- private Instance _instance;
+ private ProtocolInstance _instance;
private java.net.InetSocketAddress _addr;
private String _mcastInterface;
private int _mcastTtl;
diff --git a/java/src/IceInternal/UdpEndpointFactory.java b/java/src/IceInternal/UdpEndpointFactory.java
index e45e12d2ea6..8e4301d358b 100644
--- a/java/src/IceInternal/UdpEndpointFactory.java
+++ b/java/src/IceInternal/UdpEndpointFactory.java
@@ -11,40 +11,42 @@ package IceInternal;
final class UdpEndpointFactory implements EndpointFactory
{
- UdpEndpointFactory(Instance instance)
+ UdpEndpointFactory(ProtocolInstance instance)
{
_instance = instance;
}
- public short
- type()
+ public short type()
{
- return Ice.UDPEndpointType.value;
+ return _instance.type();
}
- public String
- protocol()
+ public String protocol()
{
- return "udp";
+ return _instance.protocol();
}
- public EndpointI
- create(String str, boolean oaEndpoint)
+ public EndpointI create(java.util.ArrayList<String> args, boolean oaEndpoint)
{
- return new UdpEndpointI(_instance, str, oaEndpoint);
+ IPEndpointI endpt = new UdpEndpointI(_instance);
+ endpt.initWithOptions(args, oaEndpoint);
+ return endpt;
}
- public EndpointI
- read(BasicStream s)
+ public EndpointI read(BasicStream s)
{
- return new UdpEndpointI(s);
+ return new UdpEndpointI(_instance, s);
}
- public void
- destroy()
+ public void destroy()
{
_instance = null;
}
- private Instance _instance;
+ public EndpointFactory clone(ProtocolInstance instance)
+ {
+ return new UdpEndpointFactory(instance);
+ }
+
+ private ProtocolInstance _instance;
}
diff --git a/java/src/IceInternal/UdpEndpointI.java b/java/src/IceInternal/UdpEndpointI.java
index 24a0fcaf29f..43b5ba48d50 100644
--- a/java/src/IceInternal/UdpEndpointI.java
+++ b/java/src/IceInternal/UdpEndpointI.java
@@ -9,208 +9,28 @@
package IceInternal;
-final class UdpEndpointI extends EndpointI
+final class UdpEndpointI extends IPEndpointI
{
- public
- UdpEndpointI(Instance instance, String ho, int po, String mif, int mttl, boolean conn, String conId, boolean co)
+ public UdpEndpointI(ProtocolInstance instance, String ho, int po, String mif, int mttl, boolean conn, String conId,
+ boolean co)
{
- super(conId);
- _instance = instance;
- _host = ho;
- _port = po;
+ super(instance, ho, po, conId);
_mcastInterface = mif;
_mcastTtl = mttl;
_connect = conn;
_compress = co;
- calcHashValue();
}
- public
- UdpEndpointI(Instance instance, String str, boolean oaEndpoint)
+ public UdpEndpointI(ProtocolInstance instance)
{
- super("");
- _instance = instance;
- _host = null;
- _port = 0;
+ super(instance);
_connect = false;
_compress = false;
-
- String[] arr = str.split("[ \t\n\r]+");
-
- int i = 0;
- while(i < arr.length)
- {
- if(arr[i].length() == 0)
- {
- i++;
- continue;
- }
-
- String option = arr[i++];
- if(option.charAt(0) != '-')
- {
- throw new Ice.EndpointParseException("expected an endpoint option but found `" + option +
- "' in endpoint `udp " + str + "'");
- }
-
- String argument = null;
- if(i < arr.length && arr[i].charAt(0) != '-')
- {
- argument = arr[i++];
- if(argument.charAt(0) == '\"' && argument.charAt(argument.length() - 1) == '\"')
- {
- argument = argument.substring(1, argument.length() - 1);
- }
- }
-
- if(option.equals("-h"))
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -h option in endpoint `udp "
- + str + "'");
- }
-
- _host = argument;
- }
- else if(option.equals("-p"))
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -p option in endpoint `udp "
- + str + "'");
- }
-
- try
- {
- _port = Integer.parseInt(argument);
- }
- catch(NumberFormatException ex)
- {
- throw new Ice.EndpointParseException("invalid port value `" + argument + "' in endpoint `udp " +
- str + "'");
- }
-
- if(_port < 0 || _port > 65535)
- {
- throw new Ice.EndpointParseException("port value `" + argument +
- "' out of range in endpoint `udp " + str + "'");
- }
- }
- else if(option.equals("-c"))
- {
- if(argument != null)
- {
- throw new Ice.EndpointParseException("unexpected argument `" + argument +
- "' provided for -c option in `udp " + str + "'");
- }
-
- _connect = true;
- }
- else if(option.equals("-z"))
- {
- if(argument != null)
- {
- throw new Ice.EndpointParseException("unexpected argument `" + argument +
- "' provided for -z option in `udp " + str + "'");
- }
-
- _compress = true;
- }
- else if(option.equals("-v") || option.equals("-e"))
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for " + option + " option in endpoint " +
- "`udp " + str + "'");
- }
-
- try
- {
- Ice.EncodingVersion v = Ice.Util.stringToEncodingVersion(argument);
- if(v.major != 1 || v.minor != 0)
- {
- _instance.initializationData().logger.warning("deprecated udp endpoint option: " + option);
- }
- }
- catch(Ice.VersionParseException e)
- {
- throw new Ice.EndpointParseException("invalid version `" + argument + "' in endpoint `udp " +
- str + "':\n" + e.str);
- }
- }
- else if(option.equals("--interface"))
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for --interface option in endpoint `udp "
- + str + "'");
- }
-
- _mcastInterface = argument;
- }
- else if(option.equals("--ttl"))
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for --ttl option in endpoint `udp "
- + str + "'");
- }
-
- try
- {
- _mcastTtl = Integer.parseInt(argument);
- }
- catch(NumberFormatException ex)
- {
- throw new Ice.EndpointParseException("invalid TTL value `" + argument + "' in endpoint `udp " +
- str + "'");
- }
-
- if(_mcastTtl < 0)
- {
- throw new Ice.EndpointParseException("TTL value `" + argument +
- "' out of range in endpoint `udp " + str + "'");
- }
- }
- else
- {
- throw new Ice.EndpointParseException("unknown option `" + option + "' in `udp " + str + "'");
- }
- }
-
- if(_host == null)
- {
- _host = _instance.defaultsAndOverrides().defaultHost;
- }
- else if(_host.equals("*"))
- {
- if(oaEndpoint)
- {
- _host = null;
- }
- else
- {
- throw new Ice.EndpointParseException("`-h *' not valid for proxy endpoint `udp " + str + "'");
- }
- }
-
- if(_host == null)
- {
- _host = "";
- }
-
- calcHashValue();
}
- public
- UdpEndpointI(BasicStream s)
+ public UdpEndpointI(ProtocolInstance instance, BasicStream s)
{
- super("");
- _instance = s.instance();
- s.startReadEncaps();
- _host = s.readString();
- _port = s.readInt();
+ super(instance, s);
if(s.getReadEncoding().equals(Ice.Util.Encoding_1_0))
{
s.readByte();
@@ -222,145 +42,59 @@ final class UdpEndpointI extends EndpointI
//_connect = s.readBool();
_connect = false;
_compress = s.readBool();
- s.endReadEncaps();
- calcHashValue();
- }
-
- //
- // Marshal the endpoint
- //
- public void
- streamWrite(BasicStream s)
- {
- s.writeShort(Ice.UDPEndpointType.value);
- s.startWriteEncaps();
- s.writeString(_host);
- s.writeInt(_port);
- if(s.getWriteEncoding().equals(Ice.Util.Encoding_1_0))
- {
- Ice.Util.Protocol_1_0.__write(s);
- Ice.Util.Encoding_1_0.__write(s);
- }
- // Not transmitted.
- //s.writeBool(_connect);
- s.writeBool(_compress);
- s.endWriteEncaps();
- }
-
- //
- // Convert the endpoint to its string form
- //
- public String
- _toString()
- {
- //
- // WARNING: Certain features, such as proxy validation in Glacier2,
- // depend on the format of proxy strings. Changes to toString() and
- // methods called to generate parts of the reference string could break
- // these features. Please review for all features that depend on the
- // format of proxyToString() before changing this and related code.
- //
- String s = "udp";
-
- if(_host != null && _host.length() > 0)
- {
- s += " -h ";
- boolean addQuote = _host.indexOf(':') != -1;
- if(addQuote)
- {
- s += "\"";
- }
- s += _host;
- if(addQuote)
- {
- s += "\"";
- }
- }
-
- s += " -p " + _port;
-
- if(_mcastInterface.length() != 0)
- {
- s += " --interface " + _mcastInterface;
- }
-
- if(_mcastTtl != -1)
- {
- s += " --ttl " + _mcastTtl;
- }
-
- if(_connect)
- {
- s += " -c";
- }
-
- if(_compress)
- {
- s += " -z";
- }
-
- return s;
}
//
// Return the endpoint information.
//
- public Ice.EndpointInfo
- getInfo()
+ public Ice.EndpointInfo getInfo()
{
- return new Ice.UDPEndpointInfo(-1, _compress, _host, _port, _mcastInterface, _mcastTtl)
+ Ice.UDPEndpointInfo info = new Ice.UDPEndpointInfo()
{
public short type()
{
- return Ice.UDPEndpointType.value;
+ return UdpEndpointI.this.type();
}
-
+
public boolean datagram()
{
- return true;
+ return UdpEndpointI.this.datagram();
}
-
+
public boolean secure()
{
- return false;
+ return UdpEndpointI.this.secure();
}
};
- }
- //
- // Return the endpoint type
- //
- public short
- type()
- {
- return Ice.UDPEndpointType.value;
+ fillEndpointInfo(info);
+ return info;
}
//
- // Return the protocol name
+ // Return the timeout for the endpoint in milliseconds. 0 means
+ // non-blocking, -1 means no timeout.
//
- public String
- protocol()
+ public int timeout()
{
- return "udp";
+ return -1;
}
//
- // Return the timeout for the endpoint in milliseconds. 0 means
- // non-blocking, -1 means no timeout.
+ // Return a new endpoint with a different timeout value, provided
+ // that timeouts are supported by the endpoint. Otherwise the same
+ // endpoint is returned.
//
- public int
- timeout()
+ public EndpointI timeout(int timeout)
{
- return -1;
+ return this;
}
//
// Return true if the endpoints support bzip2 compress, or false
// otherwise.
//
- public boolean
- compress()
+ public boolean compress()
{
return _compress;
}
@@ -370,8 +104,7 @@ final class UdpEndpointI extends EndpointI
// provided that compression is supported by the
// endpoint. Otherwise the same endpoint is returned.
//
- public EndpointI
- compress(boolean compress)
+ public EndpointI compress(boolean compress)
{
if(compress == _compress)
{
@@ -385,38 +118,9 @@ final class UdpEndpointI extends EndpointI
}
//
- // Return a new endpoint with a different connection id.
- //
- public EndpointI
- connectionId(String connectionId)
- {
- if(connectionId.equals(_connectionId))
- {
- return this;
- }
- else
- {
- return new UdpEndpointI(_instance, _host, _port, _mcastInterface, _mcastTtl, _connect, connectionId,
- _compress);
- }
- }
-
- //
- // Return a new endpoint with a different timeout value, provided
- // that timeouts are supported by the endpoint. Otherwise the same
- // endpoint is returned.
- //
- public EndpointI
- timeout(int timeout)
- {
- return this;
- }
-
- //
// Return true if the endpoint is datagram-based.
//
- public boolean
- datagram()
+ public boolean datagram()
{
return true;
}
@@ -424,8 +128,7 @@ final class UdpEndpointI extends EndpointI
//
// Return true if the endpoint is secure.
//
- public boolean
- secure()
+ public boolean secure()
{
return false;
}
@@ -437,103 +140,64 @@ final class UdpEndpointI extends EndpointI
// "effective" endpoint, which might differ from this endpoint,
// for example, if a dynamic port number is assigned.
//
- public Transceiver
- transceiver(EndpointIHolder endpoint)
+ public Transceiver transceiver(EndpointIHolder endpoint)
{
UdpTransceiver p = new UdpTransceiver(_instance, _host, _port, _mcastInterface, _connect);
- endpoint.value = new UdpEndpointI(_instance, _host, p.effectivePort(), _mcastInterface, _mcastTtl,
- _connect, _connectionId, _compress);
+ endpoint.value = createEndpoint(_host, p.effectivePort(), _connectionId);
return p;
}
//
- // Return connectors for this endpoint, or empty list if no connector
- // is available.
- //
- public java.util.List<Connector>
- connectors(Ice.EndpointSelectionType selType)
- {
- return _instance.endpointHostResolver().resolve(_host, _port, selType, this);
- }
-
- public void
- connectors_async(Ice.EndpointSelectionType selType, EndpointI_connectors callback)
- {
- _instance.endpointHostResolver().resolve(_host, _port, selType, this, callback);
- }
-
- //
// Return an acceptor for this endpoint, or null if no acceptors
// is available. In case an acceptor is created, this operation
// also returns a new "effective" endpoint, which might differ
// from this endpoint, for example, if a dynamic port number is
// assigned.
//
- public Acceptor
- acceptor(EndpointIHolder endpoint, String adapterName)
+ public Acceptor acceptor(EndpointIHolder endpoint, String adapterName)
{
endpoint.value = this;
return null;
}
//
- // Expand endpoint out in to separate endpoints for each local
- // host if listening on INADDR_ANY.
+ // Convert the endpoint to its string form
//
- public java.util.List<EndpointI>
- expand()
+ public String options()
{
- java.util.ArrayList<EndpointI> endps = new java.util.ArrayList<EndpointI>();
- java.util.ArrayList<String> hosts =
- Network.getHostsForEndpointExpand(_host, _instance.protocolSupport(), false);
- if(hosts == null || hosts.isEmpty())
+ //
+ // WARNING: Certain features, such as proxy validation in Glacier2,
+ // depend on the format of proxy strings. Changes to toString() and
+ // methods called to generate parts of the reference string could break
+ // these features. Please review for all features that depend on the
+ // format of proxyToString() before changing this and related code.
+ //
+ String s = super.options();
+
+ if(_mcastInterface.length() != 0)
{
- endps.add(this);
+ s += " --interface " + _mcastInterface;
}
- else
+
+ if(_mcastTtl != -1)
{
- for(String host : hosts)
- {
- endps.add(new UdpEndpointI(_instance, host, _port, _mcastInterface, _mcastTtl, _connect, _connectionId,
- _compress));
- }
+ s += " --ttl " + _mcastTtl;
}
- return endps;
- }
- //
- // Check whether the endpoint is equivalent to another one.
- //
- public boolean
- equivalent(EndpointI endpoint)
- {
- if(!(endpoint instanceof UdpEndpointI))
+ if(_connect)
{
- return false;
+ s += " -c";
}
- UdpEndpointI udpEndpointI = (UdpEndpointI)endpoint;
- return udpEndpointI._host.equals(_host) && udpEndpointI._port == _port;
- }
- public java.util.List<Connector>
- connectors(java.util.List<java.net.InetSocketAddress> addresses, NetworkProxy proxy)
- {
- java.util.ArrayList<Connector> connectors = new java.util.ArrayList<Connector>();
- for(java.net.InetSocketAddress p : addresses)
+ if(_compress)
{
- connectors.add(new UdpConnector(_instance, p, _mcastInterface, _mcastTtl, _connectionId));
+ s += " -z";
}
- return connectors;
- }
- public int
- hashCode()
- {
- return _hashCode;
+ return s;
}
- public int
- compareTo(EndpointI obj) // From java.lang.Comparable
+ public int compareTo(EndpointI obj) // From java.lang.Comparable
{
if(!(obj instanceof UdpEndpointI))
{
@@ -545,23 +209,6 @@ final class UdpEndpointI extends EndpointI
{
return 0;
}
- else
- {
- int r = super.compareTo(p);
- if(r != 0)
- {
- return r;
- }
- }
-
- if(_port < p._port)
- {
- return -1;
- }
- else if(p._port < _port)
- {
- return 1;
- }
if(!_connect && p._connect)
{
@@ -596,30 +243,148 @@ final class UdpEndpointI extends EndpointI
return rc;
}
- return _host.compareTo(p._host);
+ return super.compareTo(obj);
}
- private void
- calcHashValue()
+ //
+ // Marshal the endpoint
+ //
+ protected void streamWriteImpl(BasicStream s)
{
- int h = 5381;
- h = IceInternal.HashUtil.hashAdd(h, Ice.UDPEndpointType.value);
- h = IceInternal.HashUtil.hashAdd(h, _host);
- h = IceInternal.HashUtil.hashAdd(h, _port);
+ super.streamWriteImpl(s);
+ if(s.getWriteEncoding().equals(Ice.Util.Encoding_1_0))
+ {
+ Ice.Util.Protocol_1_0.__write(s);
+ Ice.Util.Encoding_1_0.__write(s);
+ }
+ // Not transmitted.
+ //s.writeBool(_connect);
+ s.writeBool(_compress);
+ }
+
+ protected int hashInit(int h)
+ {
+ h = super.hashInit(h);
h = IceInternal.HashUtil.hashAdd(h, _mcastInterface);
h = IceInternal.HashUtil.hashAdd(h, _mcastTtl);
h = IceInternal.HashUtil.hashAdd(h, _connect);
- h = IceInternal.HashUtil.hashAdd(h, _connectionId);
h = IceInternal.HashUtil.hashAdd(h, _compress);
- _hashCode = h;
+ return h;
+ }
+
+ protected void fillEndpointInfo(Ice.IPEndpointInfo info)
+ {
+ super.fillEndpointInfo(info);
+ if(info instanceof Ice.UDPEndpointInfo)
+ {
+ Ice.UDPEndpointInfo udpInfo = (Ice.UDPEndpointInfo)info;
+ udpInfo.timeout = -1;
+ udpInfo.compress = _compress;
+ udpInfo.mcastInterface = _mcastInterface;
+ udpInfo.mcastTtl = _mcastTtl;
+ }
+ }
+
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ if(super.checkOption(option, argument, endpoint))
+ {
+ return true;
+ }
+
+ if(option.equals("-c"))
+ {
+ if(argument != null)
+ {
+ throw new Ice.EndpointParseException("unexpected argument `" + argument +
+ "' provided for -c option in " + endpoint);
+ }
+
+ _connect = true;
+ }
+ else if(option.equals("-z"))
+ {
+ if(argument != null)
+ {
+ throw new Ice.EndpointParseException("unexpected argument `" + argument +
+ "' provided for -z option in " + endpoint);
+ }
+
+ _compress = true;
+ }
+ else if(option.equals("-v") || option.equals("-e"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for " + option + " option in endpoint " +
+ endpoint);
+ }
+
+ try
+ {
+ Ice.EncodingVersion v = Ice.Util.stringToEncodingVersion(argument);
+ if(v.major != 1 || v.minor != 0)
+ {
+ _instance.logger().warning("deprecated udp endpoint option: " + option);
+ }
+ }
+ catch(Ice.VersionParseException e)
+ {
+ throw new Ice.EndpointParseException("invalid version `" + argument + "' in endpoint " +
+ endpoint + ":\n" + e.str);
+ }
+ }
+ else if(option.equals("--interface"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for --interface option in endpoint "
+ + endpoint);
+ }
+
+ _mcastInterface = argument;
+ }
+ else if(option.equals("--ttl"))
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for --ttl option in endpoint " + endpoint);
+ }
+
+ try
+ {
+ _mcastTtl = Integer.parseInt(argument);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid TTL value `" + argument + "' in endpoint " + endpoint);
+ }
+
+ if(_mcastTtl < 0)
+ {
+ throw new Ice.EndpointParseException("TTL value `" + argument + "' out of range in endpoint " +
+ endpoint);
+ }
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+ }
+
+ protected Connector createConnector(java.net.InetSocketAddress addr, NetworkProxy proxy)
+ {
+ return new UdpConnector(_instance, addr, _mcastInterface, _mcastTtl, _connectionId);
+ }
+
+ protected IPEndpointI createEndpoint(String host, int port, String connectionId)
+ {
+ return new UdpEndpointI(_instance, host, port, _mcastInterface, _mcastTtl, _connect, connectionId, _compress);
}
- private Instance _instance;
- private String _host;
- private int _port;
private String _mcastInterface = "";
private int _mcastTtl = -1;
private boolean _connect;
private boolean _compress;
- private int _hashCode;
}
diff --git a/java/src/IceInternal/UdpTransceiver.java b/java/src/IceInternal/UdpTransceiver.java
index 96174b95c26..15f1683cf4e 100644
--- a/java/src/IceInternal/UdpTransceiver.java
+++ b/java/src/IceInternal/UdpTransceiver.java
@@ -11,15 +11,13 @@ package IceInternal;
final class UdpTransceiver implements Transceiver
{
- public java.nio.channels.SelectableChannel
- fd()
+ public java.nio.channels.SelectableChannel fd()
{
assert(_fd != null);
return _fd;
}
- public int
- initialize(Buffer readBuffer, Buffer writeBuffer)
+ public int initialize(Buffer readBuffer, Buffer writeBuffer, Ice.BooleanHolder moreData)
{
//
// Nothing to do.
@@ -27,17 +25,24 @@ final class UdpTransceiver implements Transceiver
return SocketOperation.None;
}
- public void
- close()
+ public int closing(boolean initiator, Ice.LocalException ex)
+ {
+ //
+ // Nothing to do.
+ //
+ return SocketOperation.None;
+ }
+
+ public void close()
{
assert(_fd != null);
-
- if(_state >= StateConnected && _traceLevels.network >= 1)
+
+ if(_state >= StateConnected && _instance.traceLevel() >= 1)
{
- String s = "closing udp connection\n" + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "closing " + _instance.protocol() + " connection\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
-
+
try
{
_fd.close();
@@ -48,9 +53,8 @@ final class UdpTransceiver implements Transceiver
_fd = null;
}
- @SuppressWarnings("deprecation")
- public boolean
- write(Buffer buf)
+ @SuppressWarnings("deprecation")
+ public int write(Buffer buf)
{
//
// We don't want write or send to be called on android main thread as this will cause
@@ -59,12 +63,12 @@ final class UdpTransceiver implements Transceiver
//
if(Util.isAndroidMainThread(Thread.currentThread()))
{
- return false;
+ return SocketOperation.Write;
}
assert(buf.b.position() == 0);
assert(_fd != null && _state >= StateConnected);
-
+
// The caller is supposed to check the send size before by calling checkSendSize
assert(java.lang.Math.min(_maxPacketSize, _sndSize - _udpOverhead) >= buf.size());
@@ -107,25 +111,23 @@ final class UdpTransceiver implements Transceiver
if(ret == 0)
{
- return false;
+ return SocketOperation.Write;
}
- if(_traceLevels.network >= 3)
+ if(_instance.traceLevel() >= 3)
{
- String s = "sent " + ret + " bytes via udp\n" + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "sent " + ret + " bytes via " + _instance.protocol() + "\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
assert(ret == buf.b.limit());
- return true;
+ return SocketOperation.None;
}
-
+
@SuppressWarnings("deprecation")
- public boolean
- read(Buffer buf, Ice.BooleanHolder moreData)
+ public int read(Buffer buf, Ice.BooleanHolder moreData)
{
assert(buf.b.position() == 0);
- moreData.value = false;
final int packetSize = java.lang.Math.min(_maxPacketSize, _rcvSize - _udpOverhead);
buf.resize(packetSize, true);
@@ -139,7 +141,7 @@ final class UdpTransceiver implements Transceiver
java.net.SocketAddress peerAddr = _fd.receive(buf.b);
if(peerAddr == null || buf.b.position() == 0)
{
- return false;
+ return SocketOperation.Read;
}
_peerAddr = (java.net.InetSocketAddress)peerAddr;
@@ -172,33 +174,31 @@ final class UdpTransceiver implements Transceiver
Network.doConnect(_fd, _peerAddr);
_state = StateConnected;
- if(_traceLevels.network >= 1)
+ if(_instance.traceLevel() >= 1)
{
- String s = "connected udp socket\n" + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "connected " + _instance.protocol() + " socket\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
}
- if(_traceLevels.network >= 3)
+ if(_instance.traceLevel() >= 3)
{
- String s = "received " + ret + " bytes via udp\n" + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "received " + ret + " bytes via " + _instance.protocol() + "\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
buf.resize(ret, true);
buf.b.position(ret);
- return true;
+ return SocketOperation.None;
}
- public String
- type()
+ public String protocol()
{
- return "udp";
+ return _instance.protocol();
}
- public String
- toString()
+ public String toString()
{
if(_fd == null)
{
@@ -227,8 +227,7 @@ final class UdpTransceiver implements Transceiver
return s;
}
- public Ice.ConnectionInfo
- getInfo()
+ public Ice.ConnectionInfo getInfo()
{
Ice.UDPConnectionInfo info = new Ice.UDPConnectionInfo();
if(_fd != null)
@@ -261,16 +260,15 @@ final class UdpTransceiver implements Transceiver
return info;
}
- public void
- checkSendSize(Buffer buf, int messageSizeMax)
+ public void checkSendSize(Buffer buf, int messageSizeMax)
{
if(buf.size() > messageSizeMax)
{
Ex.throwMemoryLimitException(buf.size(), messageSizeMax);
}
-
+
//
- // The maximum packetSize is either the maximum allowable UDP packet size, or
+ // The maximum packetSize is either the maximum allowable UDP packet size, or
// the UDP send buffer size (which ever is smaller).
//
final int packetSize = java.lang.Math.min(_maxPacketSize, _sndSize - _udpOverhead);
@@ -280,8 +278,7 @@ final class UdpTransceiver implements Transceiver
}
}
- public final int
- effectivePort()
+ public final int effectivePort()
{
return _addr.getPort();
}
@@ -290,17 +287,16 @@ final class UdpTransceiver implements Transceiver
// Only for use by UdpEndpoint
//
@SuppressWarnings("deprecation")
- UdpTransceiver(Instance instance, java.net.InetSocketAddress addr, String mcastInterface, int mcastTtl)
+ UdpTransceiver(ProtocolInstance instance, java.net.InetSocketAddress addr, String mcastInterface, int mcastTtl)
{
- _traceLevels = instance.traceLevels();
- _logger = instance.initializationData().logger;
+ _instance = instance;
_state = StateNeedConnect;
_addr = addr;
try
{
_fd = Network.createUdpSocket(_addr);
- setBufSize(instance);
+ setBufSize(instance.properties());
Network.setBlock(_fd, false);
//
// NOTE: setting the multicast interface before performing the
@@ -313,10 +309,10 @@ final class UdpTransceiver implements Transceiver
Network.doConnect(_fd, _addr);
_state = StateConnected; // We're connected now
- if(_traceLevels.network >= 1)
+ if(_instance.traceLevel() >= 1)
{
- String s = "starting to send udp packets\n" + toString();
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "starting to send " + _instance.protocol() + " packets\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
}
catch(Ice.LocalException ex)
@@ -330,22 +326,21 @@ final class UdpTransceiver implements Transceiver
// Only for use by UdpEndpoint
//
@SuppressWarnings("deprecation")
- UdpTransceiver(Instance instance, String host, int port, String mcastInterface, boolean connect)
+ UdpTransceiver(ProtocolInstance instance, String host, int port, String mcastInterface, boolean connect)
{
- _traceLevels = instance.traceLevels();
- _logger = instance.initializationData().logger;
+ _instance = instance;
_state = connect ? StateNeedConnect : StateNotConnected;
try
{
_addr = Network.getAddressForServer(host, port, instance.protocolSupport(), instance.preferIPv6());
_fd = Network.createUdpSocket(_addr);
- setBufSize(instance);
+ setBufSize(instance.properties());
Network.setBlock(_fd, false);
- if(_traceLevels.network >= 2)
+ if(_instance.traceLevel() >= 2)
{
- String s = "attempting to bind to udp socket " + Network.addrToString(_addr);
- _logger.trace(_traceLevels.networkCat, s);
+ String s = "attempting to bind to " + _instance.protocol() + " socket " + Network.addrToString(_addr);
+ _instance.logger().trace(_instance.traceCategory(), s);
}
if(_addr.getAddress().isMulticastAddress())
{
@@ -357,11 +352,11 @@ final class UdpTransceiver implements Transceiver
//
// Windows does not allow binding to the mcast address itself
// so we bind to INADDR_ANY (0.0.0.0) instead. As a result,
- // bi-directional connection won't work because the source
+ // bi-directional connection won't work because the source
// address won't be the multicast address and the client will
// therefore reject the datagram.
//
- int protocol =
+ int protocol =
_mcastAddr.getAddress().getAddress().length == 4 ? Network.EnableIPv4 : Network.EnableIPv6;
_addr = Network.getAddressForServer("", port, protocol, instance.preferIPv6());
}
@@ -395,12 +390,12 @@ final class UdpTransceiver implements Transceiver
_addr = Network.doBind(_fd, _addr);
}
- if(_traceLevels.network >= 1)
+ if(_instance.traceLevel() >= 1)
{
- StringBuffer s = new StringBuffer("starting to receive udp packets\n");
+ StringBuffer s = new StringBuffer("starting to receive " + _instance.protocol() + " packets\n");
s.append(toString());
- java.util.List<String> interfaces =
+ java.util.List<String> interfaces =
Network.getHostsForEndpointExpand(_addr.getAddress().getHostAddress(), instance.protocolSupport(),
true);
if(!interfaces.isEmpty())
@@ -408,7 +403,7 @@ final class UdpTransceiver implements Transceiver
s.append("\nlocal interfaces: ");
s.append(IceUtilInternal.StringUtil.joinString(interfaces, ", "));
}
- _logger.trace(_traceLevels.networkCat, s.toString());
+ _instance.logger().trace(_instance.traceCategory(), s.toString());
}
}
catch(Ice.LocalException ex)
@@ -418,8 +413,7 @@ final class UdpTransceiver implements Transceiver
}
}
- private synchronized void
- setBufSize(Instance instance)
+ private synchronized void setBufSize(Ice.Properties properties)
{
assert(_fd != null);
@@ -446,13 +440,14 @@ final class UdpTransceiver implements Transceiver
//
// Get property for buffer size and check for sanity.
//
- int sizeRequested = instance.initializationData().properties.getPropertyAsIntWithDefault(prop, dfltSize);
+ int sizeRequested = properties.getPropertyAsIntWithDefault(prop, dfltSize);
if(sizeRequested < (_udpOverhead + IceInternal.Protocol.headerSize))
{
- _logger.warning("Invalid " + prop + " value of " + sizeRequested + " adjusted to " + dfltSize);
+ _instance.logger().warning("Invalid " + prop + " value of " + sizeRequested + " adjusted to " +
+ dfltSize);
sizeRequested = dfltSize;
}
-
+
if(sizeRequested != dfltSize)
{
//
@@ -479,233 +474,106 @@ final class UdpTransceiver implements Transceiver
//
if(sizeSet < sizeRequested)
{
- _logger.warning("UDP " + direction + " buffer size: requested size of "
+ _instance.logger().warning("UDP " + direction + " buffer size: requested size of "
+ sizeRequested + " adjusted to " + sizeSet);
}
}
}
}
- //
- // The NIO classes before JDK 1.7 do not support multicast, at least not directly.
- // This method works around that limitation by using reflection to configure the
- // file descriptor of a DatagramChannel for multicast operation. Specifically, an
- // instance of java.net.PlainDatagramSocketImpl is use to (temporarily) wrap the
- // channel's file descriptor.
- //
- // If using JDK >= 1.7 we use the new added MulticastChannel via reflection to allow
- // compilation with older JDK versions.
- //
- private void
- configureMulticast(java.net.InetSocketAddress group, String interfaceAddr, int ttl)
+ private void configureMulticast(java.net.InetSocketAddress group, String interfaceAddr, int ttl)
{
try
{
- Class<?> cls = Util.findClass("java.nio.channels.MulticastChannel", null);
- java.lang.reflect.Method m = null;
- java.net.DatagramSocketImpl socketImpl = null;
- java.lang.reflect.Field socketFd = null;
java.net.NetworkInterface intf = null;
- if(cls == null || !cls.isAssignableFrom(_fd.getClass()))
+
+ if(interfaceAddr.length() != 0)
{
- cls = Util.findClass("java.net.PlainDatagramSocketImpl", null);
- if(cls == null)
+ intf = java.net.NetworkInterface.getByName(interfaceAddr);
+ if(intf == null)
{
- throw new Ice.SocketException();
+ try
+ {
+ intf = java.net.NetworkInterface.getByInetAddress(
+ java.net.InetAddress.getByName(interfaceAddr));
+ }
+ catch(Exception ex)
+ {
+ }
}
- java.lang.reflect.Constructor<?> c = cls.getDeclaredConstructor((Class<?>[])null);
- c.setAccessible(true);
- socketImpl = (java.net.DatagramSocketImpl)c.newInstance((Object[])null);
+ }
+ if(group != null)
+ {
//
- // We have to invoke the protected create() method on the PlainDatagramSocketImpl object so
- // that this hack works properly when IPv6 is enabled on Windows.
+ // Join multicast group.
//
- try
- {
- m = cls.getDeclaredMethod("create", (Class<?>[])null);
- m.setAccessible(true);
- m.invoke(socketImpl);
- }
- catch(java.lang.NoSuchMethodException ex) // OpenJDK
+ boolean join = false;
+ if(intf != null)
{
+ _fd.join(group.getAddress(), intf);
+ join = true;
}
-
- cls = Util.findClass("sun.nio.ch.DatagramChannelImpl", null);
- if(cls == null)
+ else
{
- throw new Ice.SocketException();
- }
- java.lang.reflect.Field channelFd = cls.getDeclaredField("fd");
- channelFd.setAccessible(true);
-
- socketFd = java.net.DatagramSocketImpl.class.getDeclaredField("fd");
- socketFd.setAccessible(true);
- socketFd.set(socketImpl, channelFd.get(_fd));
- }
+ //
+ // If the user doesn't specify an interface, we join to the multicast group with every
+ // interface that supports multicast and has a configured address with the same protocol
+ // as the group address protocol.
+ //
+ int protocol = group.getAddress().getAddress().length == 4 ? Network.EnableIPv4 :
+ Network.EnableIPv6;
- try
- {
- if(interfaceAddr.length() != 0)
- {
- intf = java.net.NetworkInterface.getByName(interfaceAddr);
- if(intf == null)
+ java.util.List<java.net.NetworkInterface> interfaces =
+ java.util.Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
+ for(java.net.NetworkInterface iface : interfaces)
{
- try
- {
- intf = java.net.NetworkInterface.getByInetAddress(
- java.net.InetAddress.getByName(interfaceAddr));
- }
- catch(Exception ex)
+ if(!iface.supportsMulticast())
{
+ continue;
}
- }
- }
- if(group != null)
- {
- //
- // Join multicast group.
- //
- Class<?>[] types;
- Object[] args;
- if(socketImpl == null)
- {
- types = new Class<?>[]{ java.net.InetAddress.class, java.net.NetworkInterface.class };
- m = _fd.getClass().getDeclaredMethod("join", types);
- m.setAccessible(true);
- boolean join = false;
- if(intf != null)
+ boolean hasProtocolAddress = false;
+ java.util.List<java.net.InetAddress> addresses =
+ java.util.Collections.list(iface.getInetAddresses());
+ for(java.net.InetAddress address : addresses)
{
- m.invoke(_fd, new Object[] { group.getAddress(), intf });
- join = true;
- }
- else
- {
- //
- // If the user doesn't specify an interface, we join to the multicast group with all the
- // interfaces that support multicast and has a configured address with the same protocol
- // as the group address protocol.
- //
- int protocol = group.getAddress().getAddress().length == 4 ? Network.EnableIPv4 :
- Network.EnableIPv6;
-
- java.util.List<java.net.NetworkInterface> interfaces =
- java.util.Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
- for(java.net.NetworkInterface iface : interfaces)
+ if(address.getAddress().length == 4 && protocol == Network.EnableIPv4 ||
+ address.getAddress().length != 4 && protocol == Network.EnableIPv6)
{
- if(!iface.supportsMulticast())
- {
- continue;
- }
- boolean hasProtocolAddress = false;
- java.util.List<java.net.InetAddress> addresses =
- java.util.Collections.list(iface.getInetAddresses());
- for(java.net.InetAddress address : addresses)
- {
- if(address.getAddress().length == 4 && protocol == Network.EnableIPv4 ||
- address.getAddress().length != 4 && protocol == Network.EnableIPv6)
- {
- hasProtocolAddress = true;
- break;
- }
- }
-
- if(hasProtocolAddress)
- {
- m.invoke(_fd, new Object[] { group.getAddress(), iface });
- join = true;
- }
+ hasProtocolAddress = true;
+ break;
}
-
- if(!join)
- {
- throw new Ice.SocketException(new IllegalArgumentException(
- "There aren't any interfaces that support multicast, " +
- "or the interfaces that support it\n" +
- "are not configured for the group protocol. " +
- "Cannot join the mulitcast group."));
- }
- }
- }
- else
- {
- try
- {
- types = new Class<?>[]{ java.net.SocketAddress.class, java.net.NetworkInterface.class };
- m = socketImpl.getClass().getDeclaredMethod("joinGroup", types);
- args = new Object[]{ group, intf };
}
- catch(java.lang.NoSuchMethodException ex) // OpenJDK
- {
- types = new Class<?>[]{ java.net.InetAddress.class, java.net.NetworkInterface.class };
- m = socketImpl.getClass().getDeclaredMethod("join", types);
- args = new Object[]{ group.getAddress(), intf };
- }
- m.setAccessible(true);
- m.invoke(socketImpl, args);
- }
- }
- else if(intf != null)
- {
- //
- // Otherwise, set the multicast interface if specified.
- //
- Class<?>[] types = new Class<?>[]{ Integer.TYPE, Object.class };
- if(socketImpl == null)
- {
- Class<?> socketOption = Util.findClass("java.net.SocketOption", null);
- Class<?> standardSocketOptions = Util.findClass("java.net.StandardSocketOptions", null);
- m = _fd.getClass().getDeclaredMethod("setOption", new Class<?>[]{socketOption, Object.class});
- m.setAccessible(true);
- java.lang.reflect.Field ipMcastIf = standardSocketOptions.getDeclaredField("IP_MULTICAST_IF");
- ipMcastIf.setAccessible(true);
- m.invoke(_fd, new Object[]{ ipMcastIf.get(null), intf });
- }
- else
- {
- try
+ if(hasProtocolAddress)
{
- m = socketImpl.getClass().getDeclaredMethod("setOption", types);
- }
- catch(java.lang.NoSuchMethodException ex) // OpenJDK
- {
- m = socketImpl.getClass().getDeclaredMethod("socketSetOption", types);
+ _fd.join(group.getAddress(), iface);
+ join = true;
}
- m.setAccessible(true);
- Object[] args = new Object[]{ Integer.valueOf(java.net.SocketOptions.IP_MULTICAST_IF2), intf };
- m.invoke(socketImpl, args);
}
- }
- if(ttl != -1)
- {
- if(socketImpl == null)
+ if(!join)
{
- Class<?> socketOption = Util.findClass("java.net.SocketOption", null);
- Class<?> standardSocketOptions = Util.findClass("java.net.StandardSocketOptions", null);
- m = _fd.getClass().getDeclaredMethod("setOption", new Class<?>[]{socketOption, Object.class});
- m.setAccessible(true);
- java.lang.reflect.Field ipMcastTtl = standardSocketOptions.getDeclaredField("IP_MULTICAST_TTL");
- ipMcastTtl.setAccessible(true);
- m.invoke(_fd, new Object[]{ ipMcastTtl.get(null), ttl });
- }
- else
- {
- Class<?>[] types = new Class<?>[]{ Integer.TYPE };
- m = java.net.DatagramSocketImpl.class.getDeclaredMethod("setTimeToLive", types);
- m.setAccessible(true);
- m.invoke(socketImpl, new Object[]{ Integer.valueOf(ttl) });
+ throw new Ice.SocketException(new IllegalArgumentException(
+ "There aren't any interfaces that support multicast, " +
+ "or the interfaces that support it\n" +
+ "are not configured for the group protocol. " +
+ "Cannot join the mulitcast group."));
}
}
}
- finally
+ else if(intf != null)
{
- if(socketFd != null && socketImpl != null)
- {
- socketFd.set(socketImpl, null);
- }
+ //
+ // Otherwise, set the multicast interface if specified.
+ //
+ _fd.setOption(java.net.StandardSocketOptions.IP_MULTICAST_IF, intf);
+ }
+
+ if(ttl != -1)
+ {
+ _fd.setOption(java.net.StandardSocketOptions.IP_MULTICAST_TTL, ttl);
}
}
catch(Exception ex)
@@ -714,8 +582,7 @@ final class UdpTransceiver implements Transceiver
}
}
- protected synchronized void
- finalize()
+ protected synchronized void finalize()
throws Throwable
{
try
@@ -731,8 +598,7 @@ final class UdpTransceiver implements Transceiver
}
}
- private TraceLevels _traceLevels;
- private Ice.Logger _logger;
+ private ProtocolInstance _instance;
private int _state;
private int _rcvSize;
diff --git a/java/src/IceSSL/AcceptorI.java b/java/src/IceSSL/AcceptorI.java
index 42a4e336cb2..804f72b12ef 100644
--- a/java/src/IceSSL/AcceptorI.java
+++ b/java/src/IceSSL/AcceptorI.java
@@ -11,19 +11,17 @@ package IceSSL;
final class AcceptorI implements IceInternal.Acceptor
{
- public java.nio.channels.ServerSocketChannel
- fd()
+ public java.nio.channels.ServerSocketChannel fd()
{
return _fd;
}
- public void
- close()
+ public void close()
{
- if(_instance.networkTraceLevel() >= 1)
+ if(_instance.traceLevel() >= 1)
{
- String s = "stopping to accept ssl connections at " + toString();
- _logger.trace(_instance.networkTraceCategory(), s);
+ String s = "stopping to accept " + _instance.protocol() + " connections at " + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
assert(_fd != null);
@@ -31,14 +29,13 @@ final class AcceptorI implements IceInternal.Acceptor
_fd = null;
}
- public void
- listen()
+ public void listen()
{
// Nothing to do.
- if(_instance.networkTraceLevel() >= 1)
+ if(_instance.traceLevel() >= 1)
{
- StringBuffer s = new StringBuffer("listening for ssl connections at ");
+ StringBuffer s = new StringBuffer("listening for " + _instance.protocol() + " connections at ");
s.append(toString());
java.util.List<String> interfaces =
@@ -49,12 +46,11 @@ final class AcceptorI implements IceInternal.Acceptor
s.append("\nlocal interfaces: ");
s.append(IceUtilInternal.StringUtil.joinString(interfaces, ", "));
}
- _logger.trace(_instance.networkTraceCategory(), s.toString());
+ _instance.logger().trace(_instance.traceCategory(), s.toString());
}
}
- public IceInternal.Transceiver
- accept()
+ public IceInternal.Transceiver accept()
{
//
// The plug-in may not be fully initialized.
@@ -72,7 +68,7 @@ final class AcceptorI implements IceInternal.Acceptor
try
{
IceInternal.Network.setBlock(fd, false);
- IceInternal.Network.setTcpBufSize(fd, _instance.communicator().getProperties(), _logger);
+ IceInternal.Network.setTcpBufSize(fd, _instance.properties(), _instance.logger());
java.net.InetSocketAddress peerAddr = (java.net.InetSocketAddress)fd.socket().getRemoteSocketAddress();
engine = _instance.createSSLEngine(true, peerAddr);
@@ -83,23 +79,26 @@ final class AcceptorI implements IceInternal.Acceptor
throw ex;
}
- if(_instance.networkTraceLevel() >= 1)
+ if(_instance.traceLevel() >= 1)
{
- _logger.trace(_instance.networkTraceCategory(), "accepting ssl connection\n" +
- IceInternal.Network.fdToString(fd));
+ _instance.logger().trace(_instance.traceCategory(), "accepting " + _instance.protocol() + " connection\n" +
+ IceInternal.Network.fdToString(fd));
}
return new TransceiverI(_instance, engine, fd, _adapterName);
}
- public String
- toString()
+ public String protocol()
+ {
+ return _instance.protocol();
+ }
+
+ public String toString()
{
return IceInternal.Network.addrToString(_addr);
}
- int
- effectivePort()
+ int effectivePort()
{
return _addr.getPort();
}
@@ -108,14 +107,13 @@ final class AcceptorI implements IceInternal.Acceptor
{
_instance = instance;
_adapterName = adapterName;
- _logger = instance.communicator().getLogger();
- _backlog = instance.communicator().getProperties().getPropertyAsIntWithDefault("Ice.TCP.Backlog", 511);
+ _backlog = instance.properties().getPropertyAsIntWithDefault("Ice.TCP.Backlog", 511);
try
{
_fd = IceInternal.Network.createTcpServerSocket();
IceInternal.Network.setBlock(_fd, false);
- IceInternal.Network.setTcpBufSize(_fd, _instance.communicator().getProperties(), _logger);
+ IceInternal.Network.setTcpBufSize(_fd, _instance.properties(), _instance.logger());
if(!System.getProperty("os.name").startsWith("Windows"))
{
//
@@ -135,10 +133,10 @@ final class AcceptorI implements IceInternal.Acceptor
}
_addr = IceInternal.Network.getAddressForServer(host, port, _instance.protocolSupport(),
_instance.preferIPv6());
- if(_instance.networkTraceLevel() >= 2)
+ if(_instance.traceLevel() >= 2)
{
- String s = "attempting to bind to ssl socket " + toString();
- _logger.trace(_instance.networkTraceCategory(), s);
+ String s = "attempting to bind to " + _instance.protocol() + " socket " + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
_addr = IceInternal.Network.doBind(_fd, _addr, _backlog);
}
@@ -149,8 +147,7 @@ final class AcceptorI implements IceInternal.Acceptor
}
}
- protected synchronized void
- finalize()
+ protected synchronized void finalize()
throws Throwable
{
try
@@ -168,7 +165,6 @@ final class AcceptorI implements IceInternal.Acceptor
private Instance _instance;
private String _adapterName;
- private Ice.Logger _logger;
private java.nio.channels.ServerSocketChannel _fd;
private int _backlog;
private java.net.InetSocketAddress _addr;
diff --git a/java/src/IceSSL/ConnectorI.java b/java/src/IceSSL/ConnectorI.java
index aae35bb55c2..a373c8e5084 100644
--- a/java/src/IceSSL/ConnectorI.java
+++ b/java/src/IceSSL/ConnectorI.java
@@ -11,8 +11,7 @@ package IceSSL;
final class ConnectorI implements IceInternal.Connector
{
- public IceInternal.Transceiver
- connect()
+ public IceInternal.Transceiver connect()
{
//
// The plug-in may not be fully initialized.
@@ -24,17 +23,17 @@ final class ConnectorI implements IceInternal.Connector
throw ex;
}
- if(_instance.networkTraceLevel() >= 2)
+ if(_instance.traceLevel() >= 2)
{
- String s = "trying to establish ssl connection to " + toString();
- _logger.trace(_instance.networkTraceCategory(), s);
+ String s = "trying to establish " + _instance.protocol() + " connection to " + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
try
{
java.nio.channels.SocketChannel fd = IceInternal.Network.createTcpSocket();
IceInternal.Network.setBlock(fd, false);
- IceInternal.Network.setTcpBufSize(fd, _instance.communicator().getProperties(), _logger);
+ IceInternal.Network.setTcpBufSize(fd, _instance.properties(), _instance.logger());
final java.net.InetSocketAddress addr = _proxy != null ? _proxy.getAddress() : _addr;
IceInternal.Network.doConnect(fd, addr);
try
@@ -50,29 +49,26 @@ final class ConnectorI implements IceInternal.Connector
}
catch(Ice.LocalException ex)
{
- if(_instance.networkTraceLevel() >= 2)
+ if(_instance.traceLevel() >= 2)
{
- String s = "failed to establish ssl connection to " + toString() + "\n" + ex;
- _logger.trace(_instance.networkTraceCategory(), s);
+ String s = "failed to establish " + _instance.protocol() + " connection to " + toString() + "\n" + ex;
+ _instance.logger().trace(_instance.traceCategory(), s);
}
throw ex;
}
}
- public short
- type()
+ public short type()
{
- return EndpointType.value;
+ return _instance.type();
}
- public String
- toString()
+ public String toString()
{
return IceInternal.Network.addrToString(_proxy == null ? _addr : _proxy.getAddress());
}
- public int
- hashCode()
+ public int hashCode()
{
return _hashCode;
}
@@ -84,7 +80,6 @@ final class ConnectorI implements IceInternal.Connector
int timeout, String connectionId)
{
_instance = instance;
- _logger = instance.communicator().getLogger();
_host = host;
_addr = addr;
_proxy = proxy;
@@ -98,8 +93,7 @@ final class ConnectorI implements IceInternal.Connector
_hashCode = IceInternal.HashUtil.hashAdd(_hashCode , _connectionId);
}
- public boolean
- equals(java.lang.Object obj)
+ public boolean equals(java.lang.Object obj)
{
if(!(obj instanceof ConnectorI))
{
@@ -126,7 +120,6 @@ final class ConnectorI implements IceInternal.Connector
}
private Instance _instance;
- private Ice.Logger _logger;
private String _host;
private java.net.InetSocketAddress _addr;
private IceInternal.NetworkProxy _proxy;
diff --git a/java/src/IceSSL/EndpointFactoryI.java b/java/src/IceSSL/EndpointFactoryI.java
index f573d9f6410..e566049db7d 100644
--- a/java/src/IceSSL/EndpointFactoryI.java
+++ b/java/src/IceSSL/EndpointFactoryI.java
@@ -16,35 +16,37 @@ final class EndpointFactoryI implements IceInternal.EndpointFactory
_instance = instance;
}
- public short
- type()
+ public short type()
{
- return EndpointType.value;
+ return _instance.type();
}
- public String
- protocol()
+ public String protocol()
{
- return "ssl";
+ return _instance.protocol();
}
- public IceInternal.EndpointI
- create(String str, boolean oaEndpoint)
+ public IceInternal.EndpointI create(java.util.ArrayList<String> args, boolean oaEndpoint)
{
- return new EndpointI(_instance, str, oaEndpoint);
+ IceInternal.IPEndpointI endpt = new EndpointI(_instance);
+ endpt.initWithOptions(args, oaEndpoint);
+ return endpt;
}
- public IceInternal.EndpointI
- read(IceInternal.BasicStream s)
+ public IceInternal.EndpointI read(IceInternal.BasicStream s)
{
return new EndpointI(_instance, s);
}
- public void
- destroy()
+ public void destroy()
{
_instance = null;
}
+ public IceInternal.EndpointFactory clone(IceInternal.ProtocolInstance instance)
+ {
+ return new EndpointFactoryI(new Instance(_instance.sharedInstance(), instance.type(), instance.protocol()));
+ }
+
private Instance _instance;
}
diff --git a/java/src/IceSSL/EndpointI.java b/java/src/IceSSL/EndpointI.java
index 8d57be9e157..c2d297a9e85 100644
--- a/java/src/IceSSL/EndpointI.java
+++ b/java/src/IceSSL/EndpointI.java
@@ -9,284 +9,64 @@
package IceSSL;
-final class EndpointI extends IceInternal.EndpointI
+final class EndpointI extends IceInternal.IPEndpointI
{
- public
- EndpointI(Instance instance, String ho, int po, int ti, String conId, boolean co)
+ public EndpointI(Instance instance, String ho, int po, int ti, String conId, boolean co)
{
- super(conId);
+ super(instance, ho, po, conId);
_instance = instance;
- _host = ho;
- _port = po;
_timeout = ti;
_compress = co;
- calcHashValue();
}
- public
- EndpointI(Instance instance, String str, boolean oaEndpoint)
+ public EndpointI(Instance instance)
{
- super("");
+ super(instance);
_instance = instance;
- _host = null;
- _port = 0;
_timeout = -1;
_compress = false;
-
- String[] arr = str.split("[ \t\n\r]+");
-
- int i = 0;
- while(i < arr.length)
- {
- if(arr[i].length() == 0)
- {
- i++;
- continue;
- }
-
- String option = arr[i++];
- if(option.length() != 2 || option.charAt(0) != '-')
- {
- throw new Ice.EndpointParseException("expected an endpoint option but found `" + option +
- "' in endpoint `ssl " + str + "'");
- }
-
- String argument = null;
- if(i < arr.length && arr[i].charAt(0) != '-')
- {
- argument = arr[i++];
- if(argument.charAt(0) == '\"' && argument.charAt(argument.length() - 1) == '\"')
- {
- argument = argument.substring(1, argument.length() - 1);
- }
- }
-
- switch(option.charAt(1))
- {
- case 'h':
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -h option in endpoint `ssl "
- + str + "'");
- }
-
- _host = argument;
- break;
- }
-
- case 'p':
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -p option in endpoint `ssl "
- + str + "'");
- }
-
- try
- {
- _port = Integer.parseInt(argument);
- }
- catch(NumberFormatException ex)
- {
- throw new Ice.EndpointParseException("invalid port value `" + argument +
- "' in endpoint `ssl " + str + "'");
- }
-
- if(_port < 0 || _port > 65535)
- {
- throw new Ice.EndpointParseException("port value `" + argument +
- "' out of range in endpoint `ssl " + str + "'");
- }
-
- break;
- }
-
- case 't':
- {
- if(argument == null)
- {
- throw new Ice.EndpointParseException("no argument provided for -t option in endpoint `ssl "
- + str + "'");
- }
-
- try
- {
- _timeout = Integer.parseInt(argument);
- }
- catch(NumberFormatException ex)
- {
- throw new Ice.EndpointParseException("invalid timeout value `" + argument +
- "' in endpoint `ssl " + str + "'");
- }
-
- break;
- }
-
- case 'z':
- {
- if(argument != null)
- {
- throw new Ice.EndpointParseException("unexpected argument `" + argument +
- "' provided for -z option in `ssl " + str + "'");
- }
-
- _compress = true;
- break;
- }
-
- default:
- {
- throw new Ice.EndpointParseException("unknown option `" + option + "' in `ssl " + str + "'");
- }
- }
- }
-
- if(_host == null)
- {
- _host = _instance.defaultHost();
- }
- else if(_host.equals("*"))
- {
- if(oaEndpoint)
- {
- _host = null;
- }
- else
- {
- throw new Ice.EndpointParseException("`-h *' not valid for proxy endpoint `ssl " + str + "'");
- }
- }
-
- if(_host == null)
- {
- _host = "";
- }
-
- calcHashValue();
}
- public
- EndpointI(Instance instance, IceInternal.BasicStream s)
+ public EndpointI(Instance instance, IceInternal.BasicStream s)
{
- super("");
+ super(instance, s);
_instance = instance;
- s.startReadEncaps();
- _host = s.readString();
- _port = s.readInt();
_timeout = s.readInt();
_compress = s.readBool();
- s.endReadEncaps();
- calcHashValue();
- }
-
- //
- // Marshal the endpoint
- //
- public void
- streamWrite(IceInternal.BasicStream s)
- {
- s.writeShort(EndpointType.value);
- s.startWriteEncaps();
- s.writeString(_host);
- s.writeInt(_port);
- s.writeInt(_timeout);
- s.writeBool(_compress);
- s.endWriteEncaps();
- }
-
- //
- // Convert the endpoint to its string form
- //
- public String
- _toString()
- {
- //
- // WARNING: Certain features, such as proxy validation in Glacier2,
- // depend on the format of proxy strings. Changes to toString() and
- // methods called to generate parts of the reference string could break
- // these features. Please review for all features that depend on the
- // format of proxyToString() before changing this and related code.
- //
- String s = "ssl";
-
- if(_host != null && _host.length() > 0)
- {
- s += " -h ";
- boolean addQuote = _host.indexOf(':') != -1;
- if(addQuote)
- {
- s += "\"";
- }
- s += _host;
- if(addQuote)
- {
- s += "\"";
- }
- }
-
- s += " -p " + _port;
-
- if(_timeout != -1)
- {
- s += " -t " + _timeout;
- }
- if(_compress)
- {
- s += " -z";
- }
- return s;
}
//
// Return the endpoint information.
//
- public Ice.EndpointInfo
- getInfo()
+ public Ice.EndpointInfo getInfo()
{
- return new IceSSL.EndpointInfo(_timeout, _compress, _host, _port)
+ Ice.IPEndpointInfo info = new IceSSL.EndpointInfo()
{
public short type()
{
- return EndpointType.value;
+ return EndpointI.this.type();
}
public boolean datagram()
{
- return false;
+ return EndpointI.this.datagram();
}
public boolean secure()
{
- return true;
+ return EndpointI.this.secure();
}
- };
- }
-
- //
- // Return the endpoint type
- //
- public short
- type()
- {
- return EndpointType.value;
- }
+ };
- //
- // Return the protocol name
- //
- public String
- protocol()
- {
- return "ssl";
+ fillEndpointInfo(info);
+ return info;
}
//
// Return the timeout for the endpoint in milliseconds. 0 means
// non-blocking, -1 means no timeout.
//
- public int
- timeout()
+ public int timeout()
{
return _timeout;
}
@@ -296,8 +76,7 @@ final class EndpointI extends IceInternal.EndpointI
// that timeouts are supported by the endpoint. Otherwise the same
// endpoint is returned.
//
- public IceInternal.EndpointI
- timeout(int timeout)
+ public IceInternal.EndpointI timeout(int timeout)
{
if(timeout == _timeout)
{
@@ -310,27 +89,10 @@ final class EndpointI extends IceInternal.EndpointI
}
//
- // Return a new endpoint with a different connection id.
- //
- public IceInternal.EndpointI
- connectionId(String connectionId)
- {
- if(connectionId.equals(_connectionId))
- {
- return this;
- }
- else
- {
- return new EndpointI(_instance, _host, _port, _timeout, connectionId, _compress);
- }
- }
-
- //
// Return true if the endpoints support bzip2 compress, or false
// otherwise.
//
- public boolean
- compress()
+ public boolean compress()
{
return _compress;
}
@@ -340,8 +102,7 @@ final class EndpointI extends IceInternal.EndpointI
// provided that compression is supported by the
// endpoint. Otherwise the same endpoint is returned.
//
- public IceInternal.EndpointI
- compress(boolean compress)
+ public IceInternal.EndpointI compress(boolean compress)
{
if(compress == _compress)
{
@@ -356,8 +117,7 @@ final class EndpointI extends IceInternal.EndpointI
//
// Return true if the endpoint is datagram-based.
//
- public boolean
- datagram()
+ public boolean datagram()
{
return false;
}
@@ -365,8 +125,7 @@ final class EndpointI extends IceInternal.EndpointI
//
// Return true if the endpoint is secure.
//
- public boolean
- secure()
+ public boolean secure()
{
return true;
}
@@ -378,104 +137,54 @@ final class EndpointI extends IceInternal.EndpointI
// "effective" endpoint, which might differ from this endpoint,
// for example, if a dynamic port number is assigned.
//
- public IceInternal.Transceiver
- transceiver(IceInternal.EndpointIHolder endpoint)
+ public IceInternal.Transceiver transceiver(IceInternal.EndpointIHolder endpoint)
{
endpoint.value = this;
return null;
}
//
- // Return connectors for this endpoint, or empty list if no connector
- // is available.
- //
- public java.util.List<IceInternal.Connector>
- connectors(Ice.EndpointSelectionType selType)
- {
- return _instance.endpointHostResolver().resolve(_host, _port, selType, this);
- }
-
- public void
- connectors_async(Ice.EndpointSelectionType selType, IceInternal.EndpointI_connectors callback)
- {
- _instance.endpointHostResolver().resolve(_host, _port, selType, this, callback);
- }
-
- //
// Return an acceptor for this endpoint, or null if no acceptors
// is available. In case an acceptor is created, this operation
// also returns a new "effective" endpoint, which might differ
// from this endpoint, for example, if a dynamic port number is
// assigned.
//
- public IceInternal.Acceptor
- acceptor(IceInternal.EndpointIHolder endpoint, String adapterName)
+ public IceInternal.Acceptor acceptor(IceInternal.EndpointIHolder endpoint, String adapterName)
{
AcceptorI p = new AcceptorI(_instance, adapterName, _host, _port);
endpoint.value = new EndpointI(_instance, _host, p.effectivePort(), _timeout, _connectionId, _compress);
return p;
}
- //
- // Expand endpoint out in to separate endpoints for each local
- // host if listening on INADDR_ANY.
- //
- public java.util.List<IceInternal.EndpointI>
- expand()
+ public String options()
{
- java.util.ArrayList<IceInternal.EndpointI> endps = new java.util.ArrayList<IceInternal.EndpointI>();
- java.util.ArrayList<String> hosts =
- IceInternal.Network.getHostsForEndpointExpand(_host, _instance.protocolSupport(), false);
- if(hosts == null || hosts.isEmpty())
- {
- endps.add(this);
- }
- else
- {
- for(String host : hosts)
- {
- endps.add(new EndpointI(_instance, host, _port, _timeout, _connectionId, _compress));
- }
- }
- return endps;
- }
+ //
+ // WARNING: Certain features, such as proxy validation in Glacier2,
+ // depend on the format of proxy strings. Changes to toString() and
+ // methods called to generate parts of the reference string could break
+ // these features. Please review for all features that depend on the
+ // format of proxyToString() before changing this and related code.
+ //
+ String s = super.options();
- //
- // Check whether the endpoint is equivalent to a specific Connector.
- //
- public boolean
- equivalent(IceInternal.EndpointI endpoint)
- {
- if(!(endpoint instanceof EndpointI))
+ if(_timeout != -1)
{
- return false;
+ s += " -t " + _timeout;
}
- EndpointI sslEndpointI = (EndpointI)endpoint;
- return sslEndpointI._host.equals(_host) && sslEndpointI._port == _port;
- }
- public java.util.List<IceInternal.Connector>
- connectors(java.util.List<java.net.InetSocketAddress> addresses, IceInternal.NetworkProxy proxy)
- {
- java.util.List<IceInternal.Connector> connectors = new java.util.ArrayList<IceInternal.Connector>();
- for(java.net.InetSocketAddress p : addresses)
+ if(_compress)
{
- connectors.add(new ConnectorI(_instance, _host, p, proxy, _timeout, _connectionId));
+ s += " -z";
}
- return connectors;
- }
- public int
- hashCode()
- {
- return _hashCode;
+ return s;
}
//
// Compare endpoints for sorting purposes
//
- public int
- compareTo(IceInternal.EndpointI obj) // From java.lang.Comparable
+ public int compareTo(IceInternal.EndpointI obj) // From java.lang.Comparable
{
if(!(obj instanceof EndpointI))
{
@@ -487,23 +196,6 @@ final class EndpointI extends IceInternal.EndpointI
{
return 0;
}
- else
- {
- int r = super.compareTo(p);
- if(r != 0)
- {
- return r;
- }
- }
-
- if(_port < p._port)
- {
- return -1;
- }
- else if(p._port < _port)
- {
- return 1;
- }
if(_timeout < p._timeout)
{
@@ -523,26 +215,94 @@ final class EndpointI extends IceInternal.EndpointI
return 1;
}
- return _host.compareTo(p._host);
+ return super.compareTo(obj);
+ }
+
+ protected void streamWriteImpl(IceInternal.BasicStream s)
+ {
+ super.streamWriteImpl(s);
+ s.writeInt(_timeout);
+ s.writeBool(_compress);
}
- private void
- calcHashValue()
+ protected int hashInit(int h)
{
- int h = 5381;
- h = IceInternal.HashUtil.hashAdd(h, EndpointType.value);
- h = IceInternal.HashUtil.hashAdd(h, _host);
- h = IceInternal.HashUtil.hashAdd(h, _port);
+ h = super.hashInit(h);
h = IceInternal.HashUtil.hashAdd(h, _timeout);
- h = IceInternal.HashUtil.hashAdd(h, _connectionId);
h = IceInternal.HashUtil.hashAdd(h, _compress);
- _hashCode = h;
+ return h;
+ }
+
+ protected void fillEndpointInfo(Ice.IPEndpointInfo info)
+ {
+ super.fillEndpointInfo(info);
+ if(info instanceof IceSSL.EndpointInfo)
+ {
+ IceSSL.EndpointInfo sslInfo = (IceSSL.EndpointInfo)info;
+ sslInfo.timeout = _timeout;
+ sslInfo.compress = _compress;
+ }
+ }
+
+ protected boolean checkOption(String option, String argument, String endpoint)
+ {
+ if(super.checkOption(option, argument, endpoint))
+ {
+ return true;
+ }
+
+ switch(option.charAt(1))
+ {
+ case 't':
+ {
+ if(argument == null)
+ {
+ throw new Ice.EndpointParseException("no argument provided for -t option in endpoint " + endpoint);
+ }
+
+ try
+ {
+ _timeout = Integer.parseInt(argument);
+ }
+ catch(NumberFormatException ex)
+ {
+ throw new Ice.EndpointParseException("invalid timeout value `" + argument + "' in endpoint " +
+ endpoint);
+ }
+
+ return true;
+ }
+
+ case 'z':
+ {
+ if(argument != null)
+ {
+ throw new Ice.EndpointParseException("unexpected argument `" + argument +
+ "' provided for -z option in " + endpoint);
+ }
+
+ _compress = true;
+ return true;
+ }
+
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+ protected IceInternal.Connector createConnector(java.net.InetSocketAddress addr, IceInternal.NetworkProxy proxy)
+ {
+ return new ConnectorI(_instance, _host, addr, proxy, _timeout, _connectionId);
+ }
+
+ protected IceInternal.IPEndpointI createEndpoint(String host, int port, String connectionId)
+ {
+ return new EndpointI(_instance, host, port, _timeout, connectionId, _compress);
}
private Instance _instance;
- private String _host;
- private int _port;
private int _timeout;
private boolean _compress;
- private int _hashCode;
}
diff --git a/java/src/IceSSL/Instance.java b/java/src/IceSSL/Instance.java
index 741199480b5..944d6d95074 100644
--- a/java/src/IceSSL/Instance.java
+++ b/java/src/IceSSL/Instance.java
@@ -13,1196 +13,54 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
-class Instance
+class Instance extends IceInternal.ProtocolInstance
{
- Instance(Ice.Communicator communicator)
+ Instance(SharedInstance sharedInstance, short type, String protocol)
{
- _logger = communicator.getLogger();
- _facade = IceInternal.Util.getProtocolPluginFacade(communicator);
- _securityTraceLevel = communicator.getProperties().getPropertyAsIntWithDefault("IceSSL.Trace.Security", 0);
- _securityTraceCategory = "Security";
- _trustManager = new TrustManager(communicator);
-
- //
- // Register the endpoint factory. We have to do this now, rather than
- // in initialize, because the communicator may need to interpret
- // proxies before the plug-in is fully initialized.
- //
- _facade.addEndpointFactory(new EndpointFactoryI(this));
- }
-
- void
- initialize()
- {
- if(_initialized)
- {
- return;
- }
-
- final String prefix = "IceSSL.";
- Ice.Properties properties = communicator().getProperties();
-
- //
- // Parse the cipher list.
- //
- String ciphers = properties.getProperty(prefix + "Ciphers");
- if(ciphers.length() > 0)
- {
- parseCiphers(ciphers);
- }
-
- //
- // Select protocols.
- //
- String[] protocols = properties.getPropertyAsList(prefix + "Protocols");
- if(protocols.length != 0)
- {
- java.util.ArrayList<String> l = new java.util.ArrayList<String>();
- for(String prot : protocols)
- {
- String s = prot.toLowerCase();
- if(s.equals("ssl3") || s.equals("sslv3"))
- {
- l.add("SSLv3");
- }
- else if(s.equals("tls") || s.equals("tls1") || s.equals("tlsv1") || s.equals("tls1_0") ||
- s.equals("tlsv1_0"))
- {
- l.add("TLSv1");
- }
- else if(s.equals("tls1_1") || s.equals("tlsv1_1"))
- {
- l.add("TLSv1.1");
- }
- else if(s.equals("tls1_2") || s.equals("tlsv1_2"))
- {
- l.add("TLSv1.2");
- }
- else
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: unrecognized protocol `" + prot + "'";
- throw e;
- }
- }
- _protocols = new String[l.size()];
- l.toArray(_protocols);
- }
-
- //
- // CheckCertName determines whether we compare the name in a peer's
- // certificate against its hostname.
- //
- _checkCertName = properties.getPropertyAsIntWithDefault(prefix + "CheckCertName", 0) > 0;
-
- //
- // VerifyDepthMax establishes the maximum length of a peer's certificate
- // chain, including the peer's certificate. A value of 0 means there is
- // no maximum.
- //
- _verifyDepthMax = properties.getPropertyAsIntWithDefault(prefix + "VerifyDepthMax", 2);
-
- //
- // VerifyPeer determines whether certificate validation failures abort a connection.
- //
- _verifyPeer = communicator().getProperties().getPropertyAsIntWithDefault("IceSSL.VerifyPeer", 2);
-
- //
- // Check for a certificate verifier.
- //
- final String certVerifierClass = properties.getProperty(prefix + "CertVerifier");
- if(certVerifierClass.length() > 0)
- {
- if(_verifier != null)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: certificate verifier already installed";
- throw e;
- }
-
- Class<?> cls = null;
- try
- {
- cls = _facade.findClass(certVerifierClass);
- }
- catch(Throwable ex)
- {
- throw new Ice.PluginInitializationException(
- "IceSSL: unable to load certificate verifier class " + certVerifierClass, ex);
- }
-
- try
- {
- _verifier = (CertificateVerifier)cls.newInstance();
- }
- catch(Throwable ex)
- {
- throw new Ice.PluginInitializationException(
- "IceSSL: unable to instantiate certificate verifier class " + certVerifierClass, ex);
- }
- }
-
- //
- // Check for a password callback.
- //
- final String passwordCallbackClass = properties.getProperty(prefix + "PasswordCallback");
- if(passwordCallbackClass.length() > 0)
- {
- if(_passwordCallback != null)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: password callback already installed";
- throw e;
- }
-
- Class<?> cls = null;
- try
- {
- cls = _facade.findClass(passwordCallbackClass);
- }
- catch(Throwable ex)
- {
- throw new Ice.PluginInitializationException(
- "IceSSL: unable to load password callback class " + passwordCallbackClass, ex);
- }
-
- try
- {
- _passwordCallback = (PasswordCallback)cls.newInstance();
- }
- catch(Throwable ex)
- {
- throw new Ice.PluginInitializationException(
- "IceSSL: unable to instantiate password callback class " + passwordCallbackClass, ex);
- }
- }
-
- //
- // If the user doesn't supply an SSLContext, we need to create one based
- // on property settings.
- //
- if(_context == null)
- {
- try
- {
- //
- // Check for a default directory. We look in this directory for
- // files mentioned in the configuration.
- //
- _defaultDir = properties.getProperty(prefix + "DefaultDir");
-
- //
- // We need a SecureRandom object.
- //
- // NOTE: The JDK recommends obtaining a SecureRandom object like this:
- //
- // java.security.SecureRandom rand = java.security.SecureRandom.getInstance("SHA1PRNG");
- //
- // However, there is a bug (6202721) which causes it to always use /dev/random,
- // which can lead to long delays at program startup. The workaround is to use
- // the default constructor.
- //
- java.security.SecureRandom rand = new java.security.SecureRandom();
-
- //
- // Check for seed data for the random number generator.
- //
- final String seedFiles = properties.getProperty(prefix + "Random");
- if(seedFiles.length() > 0)
- {
- final String[] arr = seedFiles.split(java.io.File.pathSeparator);
- for(String file : arr)
- {
- try
- {
- java.io.InputStream seedStream = openResource(file);
- if(seedStream == null)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: random seed file not found:\n" + file;
- throw e;
- }
-
- _seeds.add(seedStream);
- }
- catch(java.io.IOException ex)
- {
- throw new Ice.PluginInitializationException(
- "IceSSL: unable to access random seed file:\n" + file, ex);
- }
- }
- }
-
- if(!_seeds.isEmpty())
- {
- byte[] seed = null;
- int start = 0;
- for(InputStream in : _seeds)
- {
- try
- {
- int num = in.available();
- if(seed == null)
- {
- seed = new byte[num];
- }
- else
- {
- byte[] tmp = new byte[seed.length + num];
- System.arraycopy(seed, 0, tmp, 0, seed.length);
- start = seed.length;
- seed = tmp;
- }
- in.read(seed, start, num);
- }
- catch(java.io.IOException ex)
- {
- throw new Ice.PluginInitializationException("IceSSL: error while reading random seed", ex);
- }
- finally
- {
- try
- {
- in.close();
- }
- catch(java.io.IOException e)
- {
- // Ignore.
- }
- }
- }
- rand.setSeed(seed);
- }
- _seeds.clear();
-
- //
- // We call nextInt() in order to force the object to perform any time-consuming
- // initialization tasks now.
- //
- rand.nextInt();
-
- //
- // The keystore holds private keys and associated certificates.
- //
- String keystorePath = properties.getProperty(prefix + "Keystore");
-
- //
- // The password for the keys.
- //
- String password = properties.getProperty(prefix + "Password");
-
- //
- // The password for the keystore.
- //
- String keystorePassword = properties.getProperty(prefix + "KeystorePassword");
-
- //
- // The default keystore type is usually "JKS", but the legal values are determined
- // by the JVM implementation. Other possibilities include "PKCS12" and "BKS".
- //
- final String defaultType = java.security.KeyStore.getDefaultType();
- final String keystoreType = properties.getPropertyWithDefault(prefix + "KeystoreType", defaultType);
-
- //
- // The alias of the key to use in authentication.
- //
- final String alias = properties.getProperty(prefix + "Alias");
-
- //
- // The truststore holds the certificates of trusted CAs.
- //
- String truststorePath = properties.getProperty(prefix + "Truststore");
-
- //
- // The password for the truststore.
- //
- String truststorePassword = properties.getProperty(prefix + "TruststorePassword");
-
- //
- // The default truststore type is usually "JKS", but the legal values are determined
- // by the JVM implementation. Other possibilities include "PKCS12" and "BKS".
- //
- final String truststoreType =
- properties.getPropertyWithDefault(prefix + "TruststoreType",
- java.security.KeyStore.getDefaultType());
-
- //
- // Collect the key managers.
- //
- javax.net.ssl.KeyManager[] keyManagers = null;
- java.security.KeyStore keys = null;
- if(_keystoreStream != null || keystorePath.length() > 0)
- {
- java.io.InputStream keystoreStream = null;
- try
- {
- if(_keystoreStream != null)
- {
- keystoreStream = _keystoreStream;
- }
- else
- {
- keystoreStream = openResource(keystorePath);
- if(keystoreStream == null)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: keystore not found:\n" + keystorePath;
- throw e;
- }
- }
-
- keys = java.security.KeyStore.getInstance(keystoreType);
- char[] passwordChars = null;
- if(keystorePassword.length() > 0)
- {
- passwordChars = keystorePassword.toCharArray();
- }
- else if(_passwordCallback != null)
- {
- passwordChars = _passwordCallback.getKeystorePassword();
- }
- else if(keystoreType.equals("BKS"))
- {
- // Bouncy Castle does not permit null passwords.
- passwordChars = new char[0];
- }
-
- keys.load(keystoreStream, passwordChars);
-
- if(passwordChars != null)
- {
- java.util.Arrays.fill(passwordChars, '\0');
- }
- keystorePassword = null;
- }
- catch(java.io.IOException ex)
- {
- throw new Ice.PluginInitializationException(
- "IceSSL: unable to load keystore:\n" + keystorePath, ex);
- }
- finally
- {
- if(keystoreStream != null)
- {
- try
- {
- keystoreStream.close();
- }
- catch(java.io.IOException e)
- {
- // Ignore.
- }
- }
- }
-
- String algorithm = javax.net.ssl.KeyManagerFactory.getDefaultAlgorithm();
- javax.net.ssl.KeyManagerFactory kmf = javax.net.ssl.KeyManagerFactory.getInstance(algorithm);
- char[] passwordChars = new char[0]; // This password cannot be null.
- if(password.length() > 0)
- {
- passwordChars = password.toCharArray();
- }
- else if(_passwordCallback != null)
- {
- passwordChars = _passwordCallback.getPassword(alias);
- }
- kmf.init(keys, passwordChars);
- if(passwordChars.length > 0)
- {
- java.util.Arrays.fill(passwordChars, '\0');
- }
- password = null;
- keyManagers = kmf.getKeyManagers();
-
- //
- // If the user selected a specific alias, we need to wrap the key managers
- // in order to return the desired alias.
- //
- if(alias.length() > 0)
- {
- if(!keys.isKeyEntry(alias))
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: keystore does not contain an entry with alias `" + alias + "'";
- throw e;
- }
-
- for(int i = 0; i < keyManagers.length; ++i)
- {
- keyManagers[i] = new X509KeyManagerI((javax.net.ssl.X509KeyManager)keyManagers[i], alias);
- }
- }
- }
-
- //
- // Load the truststore.
- //
- java.security.KeyStore ts = null;
- if(_truststoreStream != null || truststorePath.length() > 0)
- {
- //
- // If the trust store and the key store are the same input
- // stream or file, don't create another key store.
- //
- if((_truststoreStream != null && _truststoreStream == _keystoreStream) ||
- (truststorePath.length() > 0 && truststorePath.equals(keystorePath)))
- {
- assert keys != null;
- ts = keys;
- }
- else
- {
- java.io.InputStream truststoreStream = null;
- try
- {
- if(_truststoreStream != null)
- {
- truststoreStream = _truststoreStream;
- }
- else
- {
- truststoreStream = openResource(truststorePath);
- if(truststoreStream == null)
- {
- Ice.PluginInitializationException e = new Ice.PluginInitializationException();
- e.reason = "IceSSL: truststore not found:\n" + truststorePath;
- throw e;
- }
- }
-
- ts = java.security.KeyStore.getInstance(truststoreType);
-
- char[] passwordChars = null;
- if(truststorePassword.length() > 0)
- {
- passwordChars = truststorePassword.toCharArray();
- }
- else if(_passwordCallback != null)
- {
- passwordChars = _passwordCallback.getTruststorePassword();
- }
- else if(truststoreType.equals("BKS"))
- {
- // Bouncy Castle does not permit null passwords.
- passwordChars = new char[0];
- }
-
- ts.load(truststoreStream, passwordChars);
-
- if(passwordChars != null)
- {
- java.util.Arrays.fill(passwordChars, '\0');
- }
- truststorePassword = null;
- }
- catch(java.io.IOException ex)
- {
- throw new Ice.PluginInitializationException(
- "IceSSL: unable to load truststore:\n" + truststorePath, ex);
- }
- finally
- {
- if(truststoreStream != null)
- {
- try
- {
- truststoreStream.close();
- }
- catch(java.io.IOException e)
- {
- // Ignore.
- }
- }
- }
- }
- }
- else
- {
- ts = keys;
- }
-
- //
- // Collect the trust managers.
- //
- javax.net.ssl.TrustManager[] trustManagers = null;
- {
- String algorithm = javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm();
- javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance(algorithm);
- tmf.init(ts);
- trustManagers = tmf.getTrustManagers();
- assert(trustManagers != null);
- }
-
- //
- // Wrap each trust manager.
- //
- for(int i = 0; i < trustManagers.length; ++i)
- {
- trustManagers[i] = new X509TrustManagerI(this, (javax.net.ssl.X509TrustManager)trustManagers[i]);
- }
-
- //
- // Initialize the SSL context.
- //
- _context = javax.net.ssl.SSLContext.getInstance("TLS");
- _context.init(keyManagers, trustManagers, rand);
- }
- catch(java.security.GeneralSecurityException ex)
- {
- throw new Ice.PluginInitializationException("IceSSL: unable to initialize context", ex);
- }
- }
-
- //
- // Clear cached input streams.
- //
- _seeds.clear();
- _keystoreStream = null;
- _truststoreStream = null;
-
- _initialized = true;
- }
-
- void
- context(javax.net.ssl.SSLContext context)
- {
- if(_initialized)
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: plug-in is already initialized";
- throw ex;
- }
-
- _context = context;
- }
-
- javax.net.ssl.SSLContext
- context()
- {
- return _context;
- }
-
- void
- setCertificateVerifier(CertificateVerifier verifier)
- {
- _verifier = verifier;
- }
-
- CertificateVerifier
- getCertificateVerifier()
- {
- return _verifier;
- }
-
- void
- setPasswordCallback(PasswordCallback callback)
- {
- _passwordCallback = callback;
- }
-
- PasswordCallback
- getPasswordCallback()
- {
- return _passwordCallback;
- }
-
- void
- setKeystoreStream(java.io.InputStream stream)
- {
- if(_initialized)
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: plugin is already initialized";
- throw ex;
- }
-
- _keystoreStream = stream;
- }
-
- void
- setTruststoreStream(java.io.InputStream stream)
- {
- if(_initialized)
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: plugin is already initialized";
- throw ex;
- }
-
- _truststoreStream = stream;
- }
-
- void
- addSeedStream(java.io.InputStream stream)
- {
- _seeds.add(stream);
- }
-
- Ice.Communicator
- communicator()
- {
- return _facade.getCommunicator();
- }
-
- IceInternal.EndpointHostResolver
- endpointHostResolver()
- {
- return _facade.getEndpointHostResolver();
- }
-
- int
- protocolSupport()
- {
- return _facade.getProtocolSupport();
- }
-
- boolean
- preferIPv6()
- {
- return _facade.getPreferIPv6();
+ super(sharedInstance.communicator(), type, protocol);
+ _sharedInstance = sharedInstance;
}
- Ice.EncodingVersion
- defaultEncoding()
+ SharedInstance sharedInstance()
{
- return _facade.getDefaultEncoding();
+ return _sharedInstance;
}
- String
- defaultHost()
+ int securityTraceLevel()
{
- return _facade.getDefaultHost();
+ return _sharedInstance.securityTraceLevel();
}
- int
- networkTraceLevel()
+ String securityTraceCategory()
{
- return _facade.getNetworkTraceLevel();
+ return _sharedInstance.securityTraceCategory();
}
- String
- networkTraceCategory()
+ boolean initialized()
{
- return _facade.getNetworkTraceCategory();
+ return _sharedInstance.initialized();
}
- int
- securityTraceLevel()
+ javax.net.ssl.SSLEngine createSSLEngine(boolean incoming, java.net.InetSocketAddress peerAddr)
{
- return _securityTraceLevel;
+ return _sharedInstance.createSSLEngine(incoming, peerAddr);
}
- String
- securityTraceCategory()
+ void traceConnection(java.nio.channels.SocketChannel fd, javax.net.ssl.SSLEngine engine, boolean incoming)
{
- return _securityTraceCategory;
+ _sharedInstance.traceConnection(fd, engine, incoming);
}
- boolean
- initialized()
+ void verifyPeer(NativeConnectionInfo info, java.nio.channels.SelectableChannel fd, String address)
{
- return _initialized;
+ _sharedInstance.verifyPeer(info, fd, address);
}
- javax.net.ssl.SSLEngine
- createSSLEngine(boolean incoming, java.net.InetSocketAddress peerAddr)
- {
- javax.net.ssl.SSLEngine engine;
- if(peerAddr != null)
- {
- engine = _context.createSSLEngine(peerAddr.getAddress().getHostAddress(), peerAddr.getPort());
- }
- else
- {
- engine = _context.createSSLEngine();
- }
- engine.setUseClientMode(!incoming);
-
- String[] cipherSuites = filterCiphers(engine.getSupportedCipherSuites(), engine.getEnabledCipherSuites());
- try
- {
- engine.setEnabledCipherSuites(cipherSuites);
- }
- catch(IllegalArgumentException ex)
- {
- throw new Ice.SecurityException("IceSSL: invalid ciphersuite", ex);
- }
-
- if(_securityTraceLevel >= 1)
- {
- StringBuilder s = new StringBuilder(128);
- s.append("enabling SSL ciphersuites:");
- for(String suite : cipherSuites)
- {
- s.append("\n ");
- s.append(suite);
- }
- _logger.trace(_securityTraceCategory, s.toString());
- }
-
- if(_protocols != null)
- {
- try
- {
- engine.setEnabledProtocols(_protocols);
- }
- catch(IllegalArgumentException ex)
- {
- throw new Ice.SecurityException("IceSSL: invalid protocol", ex);
- }
- }
-
- if(incoming)
- {
- if(_verifyPeer == 0)
- {
- engine.setWantClientAuth(false);
- engine.setNeedClientAuth(false);
- }
- else if(_verifyPeer == 1)
- {
- engine.setWantClientAuth(true);
- }
- else
- {
- engine.setNeedClientAuth(true);
- }
- }
-
- try
- {
- engine.beginHandshake();
- }
- catch(javax.net.ssl.SSLException ex)
- {
- throw new Ice.SecurityException("IceSSL: handshake error", ex);
- }
-
- return engine;
- }
-
- String[]
- filterCiphers(String[] supportedCiphers, String[] defaultCiphers)
- {
- java.util.LinkedList<String> result = new java.util.LinkedList<String>();
- if(_allCiphers)
- {
- for(String cipher : supportedCiphers)
- {
- result.add(cipher);
- }
- }
- else if(!_noCiphers)
- {
- for(String cipher : defaultCiphers)
- {
- result.add(cipher);
- }
- }
-
- if(_ciphers != null)
- {
- for(CipherExpression ce : _ciphers)
- {
- if(ce.not)
- {
- java.util.Iterator<String> e = result.iterator();
- while(e.hasNext())
- {
- String cipher = e.next();
- if(ce.cipher != null)
- {
- if(ce.cipher.equals(cipher))
- {
- e.remove();
- }
- }
- else
- {
- assert(ce.re != null);
- java.util.regex.Matcher m = ce.re.matcher(cipher);
- if(m.find())
- {
- e.remove();
- }
- }
- }
- }
- else
- {
- if(ce.cipher != null)
- {
- result.add(0, ce.cipher);
- }
- else
- {
- assert(ce.re != null);
- for(String cipher : supportedCiphers)
- {
- java.util.regex.Matcher m = ce.re.matcher(cipher);
- if(m.find())
- {
- result.add(0, cipher);
- }
- }
- }
- }
- }
- }
-
- String[] arr = new String[result.size()];
- result.toArray(arr);
- return arr;
- }
-
- String[]
- protocols()
- {
- return _protocols;
- }
-
- void
- traceConnection(java.nio.channels.SocketChannel fd, javax.net.ssl.SSLEngine engine, boolean incoming)
- {
- javax.net.ssl.SSLSession session = engine.getSession();
- String msg = "SSL summary for " + (incoming ? "incoming" : "outgoing") + " connection\n" +
- "cipher = " + session.getCipherSuite() + "\n" +
- "protocol = " + session.getProtocol() + "\n" +
- IceInternal.Network.fdToString(fd);
- _logger.trace(_securityTraceCategory, msg);
- }
-
- void
- verifyPeer(NativeConnectionInfo info, java.nio.channels.SelectableChannel fd, String address)
- {
- //
- // For an outgoing connection, we compare the proxy address (if any) against
- // fields in the server's certificate (if any).
- //
- if(info.nativeCerts != null && info.nativeCerts.length > 0 && address.length() > 0)
- {
- java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate)info.nativeCerts[0];
-
- //
- // Extract the IP addresses and the DNS names from the subject
- // alternative names.
- //
- java.util.ArrayList<String> ipAddresses = new java.util.ArrayList<String>();
- java.util.ArrayList<String> dnsNames = new java.util.ArrayList<String>();
- try
- {
- java.util.Collection<java.util.List<?> > subjectAltNames = cert.getSubjectAlternativeNames();
- if(subjectAltNames != null)
- {
- for(java.util.List<?> l : subjectAltNames)
- {
- assert(!l.isEmpty());
- Integer n = (Integer)l.get(0);
- if(n.intValue() == 7)
- {
- ipAddresses.add((String)l.get(1));
- }
- else if(n.intValue() == 2)
- {
- dnsNames.add(((String)l.get(1)).toLowerCase());
- }
- }
- }
- }
- catch(java.security.cert.CertificateParsingException ex)
- {
- assert(false);
- }
-
- //
- // Compare the peer's address against the common name as well as
- // the dnsName and ipAddress values in the subject alternative name.
- //
- boolean certNameOK = false;
- String dn = "";
- String addrLower = address.toLowerCase();
- {
- javax.security.auth.x500.X500Principal principal = cert.getSubjectX500Principal();
- dn = principal.getName(javax.security.auth.x500.X500Principal.CANONICAL);
- //
- // Canonical format is already in lower case.
- //
- String cn = "cn=" + addrLower;
- int pos = dn.indexOf(cn);
- if(pos >= 0)
- {
- //
- // Ensure we match the entire common name.
- //
- certNameOK = (pos + cn.length() == dn.length()) || (dn.charAt(pos + cn.length()) == ',');
- }
- }
-
- //
- // Compare the peer's address against the dnsName and ipAddress
- // values in the subject alternative name.
- //
- if(!certNameOK)
- {
- certNameOK = ipAddresses.contains(addrLower);
- }
- if(!certNameOK)
- {
- certNameOK = dnsNames.contains(addrLower);
- }
-
- //
- // Log a message if the name comparison fails. If CheckCertName is defined,
- // we also raise an exception to abort the connection. Don't log a message if
- // CheckCertName is not defined and a verifier is present.
- //
- if(!certNameOK && (_checkCertName || (_securityTraceLevel >= 1 && _verifier == null)))
- {
- StringBuilder sb = new StringBuilder(128);
- sb.append("IceSSL: ");
- if(!_checkCertName)
- {
- sb.append("ignoring ");
- }
- sb.append("certificate validation failure:\npeer certificate does not have `");
- sb.append(address);
- sb.append("' as its commonName or in its subjectAltName extension");
- if(dn.length() > 0)
- {
- sb.append("\nSubject DN: ");
- sb.append(dn);
- }
- if(!dnsNames.isEmpty())
- {
- sb.append("\nDNS names found in certificate: ");
- for(int j = 0; j < dnsNames.size(); ++j)
- {
- if(j > 0)
- {
- sb.append(", ");
- }
- sb.append(dnsNames.get(j));
- }
- }
- if(!ipAddresses.isEmpty())
- {
- sb.append("\nIP addresses found in certificate: ");
- for(int j = 0; j < ipAddresses.size(); ++j)
- {
- if(j > 0)
- {
- sb.append(", ");
- }
- sb.append(ipAddresses.get(j));
- }
- }
- if(_securityTraceLevel >= 1)
- {
- _logger.trace(_securityTraceCategory, sb.toString());
- }
- if(_checkCertName)
- {
- Ice.SecurityException ex = new Ice.SecurityException();
- ex.reason = sb.toString();
- throw ex;
- }
- }
- }
-
- if(_verifyDepthMax > 0 && info.nativeCerts != null && info.nativeCerts.length > _verifyDepthMax)
- {
- String msg = (info.incoming ? "incoming" : "outgoing") + " connection rejected:\n" +
- "length of peer's certificate chain (" + info.nativeCerts.length + ") exceeds maximum of " +
- _verifyDepthMax + "\n" +
- IceInternal.Network.fdToString(fd);
- if(_securityTraceLevel >= 1)
- {
- _logger.trace(_securityTraceCategory, msg);
- }
- Ice.SecurityException ex = new Ice.SecurityException();
- ex.reason = msg;
- throw ex;
- }
-
- if(!_trustManager.verify(info))
- {
- String msg = (info.incoming ? "incoming" : "outgoing") + " connection rejected by trust manager\n" +
- IceInternal.Network.fdToString(fd);
- if(_securityTraceLevel >= 1)
- {
- _logger.trace(_securityTraceCategory, msg);
- }
- Ice.SecurityException ex = new Ice.SecurityException();
- ex.reason = msg;
- throw ex;
- }
-
- if(_verifier != null && !_verifier.verify(info))
- {
- String msg = (info.incoming ? "incoming" : "outgoing") + " connection rejected by certificate verifier\n" +
- IceInternal.Network.fdToString(fd);
- if(_securityTraceLevel >= 1)
- {
- _logger.trace(_securityTraceCategory, msg);
- }
- Ice.SecurityException ex = new Ice.SecurityException();
- ex.reason = msg;
- throw ex;
- }
- }
-
- void
- trustManagerFailure(boolean incoming, java.security.cert.CertificateException ex)
+ void trustManagerFailure(boolean incoming, java.security.cert.CertificateException ex)
throws java.security.cert.CertificateException
{
- if(_verifyPeer == 0)
- {
- if(_securityTraceLevel >= 1)
- {
- String msg = "ignoring peer verification failure";
- if(_securityTraceLevel > 1)
- {
- java.io.StringWriter sw = new java.io.StringWriter();
- java.io.PrintWriter pw = new java.io.PrintWriter(sw);
- ex.printStackTrace(pw);
- pw.flush();
- msg += ":\n" + sw.toString();
- }
- _logger.trace(_securityTraceCategory, msg);
- }
- }
- else
- {
- throw ex;
- }
- }
-
- private void
- parseCiphers(String ciphers)
- {
- java.util.ArrayList<CipherExpression> cipherList = new java.util.ArrayList<CipherExpression>();
- String[] expr = ciphers.split("[ \t]+");
- for(int i = 0; i < expr.length; ++i)
- {
- if(expr[i].equals("ALL"))
- {
- if(i != 0)
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: `ALL' must be first in cipher list `" + ciphers + "'";
- throw ex;
- }
- _allCiphers = true;
- }
- else if(expr[i].equals("NONE"))
- {
- if(i != 0)
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: `NONE' must be first in cipher list `" + ciphers + "'";
- throw ex;
- }
- _noCiphers = true;
- }
- else
- {
- CipherExpression ce = new CipherExpression();
- String exp = expr[i];
- if(exp.charAt(0) == '!')
- {
- ce.not = true;
- if(exp.length() > 1)
- {
- exp = exp.substring(1);
- }
- else
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: invalid cipher expression `" + exp + "'";
- throw ex;
- }
- }
-
- if(exp.charAt(0) == '(')
- {
- if(!exp.endsWith(")"))
- {
- Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
- ex.reason = "IceSSL: invalid cipher expression `" + exp + "'";
- throw ex;
- }
-
- try
- {
- ce.re = java.util.regex.Pattern.compile(exp.substring(1, exp.length() - 2));
- }
- catch(java.util.regex.PatternSyntaxException ex)
- {
- throw new Ice.PluginInitializationException(
- "IceSSL: invalid cipher expression `" + exp + "'", ex);
- }
- }
- else
- {
- ce.cipher = exp;
- }
-
- cipherList.add(ce);
- }
- }
- _ciphers = new CipherExpression[cipherList.size()];
- cipherList.toArray(_ciphers);
- }
-
- private java.io.InputStream
- openResource(String path)
- throws java.io.IOException
- {
- //
- // This method wraps a call to IceInternal.Util.openResource. If the first call fails and
- // IceSSL.DefaultDir is defined, prepend the default directory and try again.
- //
- java.io.InputStream stream = IceInternal.Util.openResource(getClass().getClassLoader(), path);
- if(stream == null && _defaultDir.length() > 0)
- {
- stream = IceInternal.Util.openResource(getClass().getClassLoader(),
- _defaultDir + java.io.File.separator + path);
- }
-
- if(stream != null)
- {
- stream = new java.io.BufferedInputStream(stream);
- }
-
- return stream;
- }
-
- private static class CipherExpression
- {
- boolean not;
- String cipher;
- java.util.regex.Pattern re;
+ _sharedInstance.trustManagerFailure(incoming, ex);
}
- private Ice.Logger _logger;
- private IceInternal.ProtocolPluginFacade _facade;
- private int _securityTraceLevel;
- private String _securityTraceCategory;
- private boolean _initialized;
- private javax.net.ssl.SSLContext _context;
- private String _defaultDir;
- private CipherExpression[] _ciphers;
- private boolean _allCiphers;
- private boolean _noCiphers;
- private String[] _protocols;
- private boolean _checkCertName;
- private int _verifyDepthMax;
- private int _verifyPeer;
- private CertificateVerifier _verifier;
- private PasswordCallback _passwordCallback;
- private TrustManager _trustManager;
-
- private InputStream _keystoreStream;
- private InputStream _truststoreStream;
- private List<InputStream> _seeds = new ArrayList<InputStream>();
+ private SharedInstance _sharedInstance;
}
diff --git a/java/src/IceSSL/PluginI.java b/java/src/IceSSL/PluginI.java
index 9f19809aa54..ba714104582 100644
--- a/java/src/IceSSL/PluginI.java
+++ b/java/src/IceSSL/PluginI.java
@@ -11,76 +11,74 @@ package IceSSL;
class PluginI implements Plugin
{
- public
- PluginI(Ice.Communicator communicator)
+ public PluginI(Ice.Communicator communicator)
{
- _instance = new Instance(communicator);
+ IceInternal.ProtocolPluginFacade facade = IceInternal.Util.getProtocolPluginFacade(communicator);
+
+ _sharedInstance = new SharedInstance(facade);
+
+ //
+ // Register the endpoint factory. We have to do this now, rather than
+ // in initialize, because the communicator may need to interpret
+ // proxies before the plug-in is fully initialized.
+ //
+ facade.addEndpointFactory(
+ new EndpointFactoryI(new Instance(_sharedInstance, IceSSL.EndpointType.value, "ssl")));
}
- public void
- initialize()
+ public void initialize()
{
- _instance.initialize();
+ _sharedInstance.initialize();
}
- public void
- destroy()
+ public void destroy()
{
}
- public void
- setContext(javax.net.ssl.SSLContext context)
+ public void setContext(javax.net.ssl.SSLContext context)
{
- _instance.context(context);
+ _sharedInstance.context(context);
}
- public javax.net.ssl.SSLContext
- getContext()
+ public javax.net.ssl.SSLContext getContext()
{
- return _instance.context();
+ return _sharedInstance.context();
}
- public void
- setCertificateVerifier(CertificateVerifier verifier)
+ public void setCertificateVerifier(CertificateVerifier verifier)
{
- _instance.setCertificateVerifier(verifier);
+ _sharedInstance.setCertificateVerifier(verifier);
}
- public CertificateVerifier
- getCertificateVerifier()
+ public CertificateVerifier getCertificateVerifier()
{
- return _instance.getCertificateVerifier();
+ return _sharedInstance.getCertificateVerifier();
}
- public void
- setPasswordCallback(PasswordCallback callback)
+ public void setPasswordCallback(PasswordCallback callback)
{
- _instance.setPasswordCallback(callback);
+ _sharedInstance.setPasswordCallback(callback);
}
- public PasswordCallback
- getPasswordCallback()
+ public PasswordCallback getPasswordCallback()
{
- return _instance.getPasswordCallback();
+ return _sharedInstance.getPasswordCallback();
}
- public void
- setKeystoreStream(java.io.InputStream stream)
+ public void setKeystoreStream(java.io.InputStream stream)
{
- _instance.setKeystoreStream(stream);
+ _sharedInstance.setKeystoreStream(stream);
}
- public void
- setTruststoreStream(java.io.InputStream stream)
+ public void setTruststoreStream(java.io.InputStream stream)
{
- _instance.setTruststoreStream(stream);
+ _sharedInstance.setTruststoreStream(stream);
}
- public void
- addSeedStream(java.io.InputStream stream)
+ public void addSeedStream(java.io.InputStream stream)
{
- _instance.addSeedStream(stream);
+ _sharedInstance.addSeedStream(stream);
}
- private Instance _instance;
+ private SharedInstance _sharedInstance;
}
diff --git a/java/src/IceSSL/SharedInstance.java b/java/src/IceSSL/SharedInstance.java
new file mode 100644
index 00000000000..842dfe4b157
--- /dev/null
+++ b/java/src/IceSSL/SharedInstance.java
@@ -0,0 +1,1140 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 IceSSL;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+class SharedInstance
+{
+ SharedInstance(IceInternal.ProtocolPluginFacade facade)
+ {
+ _communicator = facade.getCommunicator();
+ _logger = _communicator.getLogger();
+ _facade = facade;
+ _securityTraceLevel = _communicator.getProperties().getPropertyAsIntWithDefault("IceSSL.Trace.Security", 0);
+ _securityTraceCategory = "Security";
+ _trustManager = new TrustManager(_communicator);
+ }
+
+ void initialize()
+ {
+ if(_initialized)
+ {
+ return;
+ }
+
+ final String prefix = "IceSSL.";
+ Ice.Properties properties = communicator().getProperties();
+
+ //
+ // Parse the cipher list.
+ //
+ String ciphers = properties.getProperty(prefix + "Ciphers");
+ if(ciphers.length() > 0)
+ {
+ parseCiphers(ciphers);
+ }
+
+ //
+ // Select protocols.
+ //
+ String[] protocols = properties.getPropertyAsList(prefix + "Protocols");
+ if(protocols.length != 0)
+ {
+ java.util.ArrayList<String> l = new java.util.ArrayList<String>();
+ for(String prot : protocols)
+ {
+ String s = prot.toLowerCase();
+ if(s.equals("ssl3") || s.equals("sslv3"))
+ {
+ l.add("SSLv3");
+ }
+ else if(s.equals("tls") || s.equals("tls1") || s.equals("tlsv1") || s.equals("tls1_0") ||
+ s.equals("tlsv1_0"))
+ {
+ l.add("TLSv1");
+ }
+ else if(s.equals("tls1_1") || s.equals("tlsv1_1"))
+ {
+ l.add("TLSv1.1");
+ }
+ else if(s.equals("tls1_2") || s.equals("tlsv1_2"))
+ {
+ l.add("TLSv1.2");
+ }
+ else
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: unrecognized protocol `" + prot + "'";
+ throw e;
+ }
+ }
+ _protocols = new String[l.size()];
+ l.toArray(_protocols);
+ }
+
+ //
+ // CheckCertName determines whether we compare the name in a peer's
+ // certificate against its hostname.
+ //
+ _checkCertName = properties.getPropertyAsIntWithDefault(prefix + "CheckCertName", 0) > 0;
+
+ //
+ // VerifyDepthMax establishes the maximum length of a peer's certificate
+ // chain, including the peer's certificate. A value of 0 means there is
+ // no maximum.
+ //
+ _verifyDepthMax = properties.getPropertyAsIntWithDefault(prefix + "VerifyDepthMax", 2);
+
+ //
+ // VerifyPeer determines whether certificate validation failures abort a connection.
+ //
+ _verifyPeer = properties.getPropertyAsIntWithDefault("IceSSL.VerifyPeer", 2);
+
+ //
+ // Check for a certificate verifier.
+ //
+ final String certVerifierClass = properties.getProperty(prefix + "CertVerifier");
+ if(certVerifierClass.length() > 0)
+ {
+ if(_verifier != null)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: certificate verifier already installed";
+ throw e;
+ }
+
+ Class<?> cls = null;
+ try
+ {
+ cls = _facade.findClass(certVerifierClass);
+ }
+ catch(Throwable ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to load certificate verifier class " + certVerifierClass, ex);
+ }
+
+ try
+ {
+ _verifier = (CertificateVerifier)cls.newInstance();
+ }
+ catch(Throwable ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to instantiate certificate verifier class " + certVerifierClass, ex);
+ }
+ }
+
+ //
+ // Check for a password callback.
+ //
+ final String passwordCallbackClass = properties.getProperty(prefix + "PasswordCallback");
+ if(passwordCallbackClass.length() > 0)
+ {
+ if(_passwordCallback != null)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: password callback already installed";
+ throw e;
+ }
+
+ Class<?> cls = null;
+ try
+ {
+ cls = _facade.findClass(passwordCallbackClass);
+ }
+ catch(Throwable ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to load password callback class " + passwordCallbackClass, ex);
+ }
+
+ try
+ {
+ _passwordCallback = (PasswordCallback)cls.newInstance();
+ }
+ catch(Throwable ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to instantiate password callback class " + passwordCallbackClass, ex);
+ }
+ }
+
+ //
+ // If the user doesn't supply an SSLContext, we need to create one based
+ // on property settings.
+ //
+ if(_context == null)
+ {
+ try
+ {
+ //
+ // Check for a default directory. We look in this directory for
+ // files mentioned in the configuration.
+ //
+ _defaultDir = properties.getProperty(prefix + "DefaultDir");
+
+ //
+ // We need a SecureRandom object.
+ //
+ // NOTE: The JDK recommends obtaining a SecureRandom object like this:
+ //
+ // java.security.SecureRandom rand = java.security.SecureRandom.getInstance("SHA1PRNG");
+ //
+ // However, there is a bug (6202721) which causes it to always use /dev/random,
+ // which can lead to long delays at program startup. The workaround is to use
+ // the default constructor.
+ //
+ java.security.SecureRandom rand = new java.security.SecureRandom();
+
+ //
+ // Check for seed data for the random number generator.
+ //
+ final String seedFiles = properties.getProperty(prefix + "Random");
+ if(seedFiles.length() > 0)
+ {
+ final String[] arr = seedFiles.split(java.io.File.pathSeparator);
+ for(String file : arr)
+ {
+ try
+ {
+ java.io.InputStream seedStream = openResource(file);
+ if(seedStream == null)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: random seed file not found:\n" + file;
+ throw e;
+ }
+
+ _seeds.add(seedStream);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to access random seed file:\n" + file, ex);
+ }
+ }
+ }
+
+ if(!_seeds.isEmpty())
+ {
+ byte[] seed = null;
+ int start = 0;
+ for(InputStream in : _seeds)
+ {
+ try
+ {
+ int num = in.available();
+ if(seed == null)
+ {
+ seed = new byte[num];
+ }
+ else
+ {
+ byte[] tmp = new byte[seed.length + num];
+ System.arraycopy(seed, 0, tmp, 0, seed.length);
+ start = seed.length;
+ seed = tmp;
+ }
+ in.read(seed, start, num);
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.PluginInitializationException("IceSSL: error while reading random seed", ex);
+ }
+ finally
+ {
+ try
+ {
+ in.close();
+ }
+ catch(java.io.IOException e)
+ {
+ // Ignore.
+ }
+ }
+ }
+ rand.setSeed(seed);
+ }
+ _seeds.clear();
+
+ //
+ // We call nextInt() in order to force the object to perform any time-consuming
+ // initialization tasks now.
+ //
+ rand.nextInt();
+
+ //
+ // The keystore holds private keys and associated certificates.
+ //
+ String keystorePath = properties.getProperty(prefix + "Keystore");
+
+ //
+ // The password for the keys.
+ //
+ String password = properties.getProperty(prefix + "Password");
+
+ //
+ // The password for the keystore.
+ //
+ String keystorePassword = properties.getProperty(prefix + "KeystorePassword");
+
+ //
+ // The default keystore type is usually "JKS", but the legal values are determined
+ // by the JVM implementation. Other possibilities include "PKCS12" and "BKS".
+ //
+ final String defaultType = java.security.KeyStore.getDefaultType();
+ final String keystoreType = properties.getPropertyWithDefault(prefix + "KeystoreType", defaultType);
+
+ //
+ // The alias of the key to use in authentication.
+ //
+ final String alias = properties.getProperty(prefix + "Alias");
+
+ //
+ // The truststore holds the certificates of trusted CAs.
+ //
+ String truststorePath = properties.getProperty(prefix + "Truststore");
+
+ //
+ // The password for the truststore.
+ //
+ String truststorePassword = properties.getProperty(prefix + "TruststorePassword");
+
+ //
+ // The default truststore type is usually "JKS", but the legal values are determined
+ // by the JVM implementation. Other possibilities include "PKCS12" and "BKS".
+ //
+ final String truststoreType =
+ properties.getPropertyWithDefault(prefix + "TruststoreType",
+ java.security.KeyStore.getDefaultType());
+
+ //
+ // Collect the key managers.
+ //
+ javax.net.ssl.KeyManager[] keyManagers = null;
+ java.security.KeyStore keys = null;
+ if(_keystoreStream != null || keystorePath.length() > 0)
+ {
+ java.io.InputStream keystoreStream = null;
+ try
+ {
+ if(_keystoreStream != null)
+ {
+ keystoreStream = _keystoreStream;
+ }
+ else
+ {
+ keystoreStream = openResource(keystorePath);
+ if(keystoreStream == null)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: keystore not found:\n" + keystorePath;
+ throw e;
+ }
+ }
+
+ keys = java.security.KeyStore.getInstance(keystoreType);
+ char[] passwordChars = null;
+ if(keystorePassword.length() > 0)
+ {
+ passwordChars = keystorePassword.toCharArray();
+ }
+ else if(_passwordCallback != null)
+ {
+ passwordChars = _passwordCallback.getKeystorePassword();
+ }
+ else if(keystoreType.equals("BKS"))
+ {
+ // Bouncy Castle does not permit null passwords.
+ passwordChars = new char[0];
+ }
+
+ keys.load(keystoreStream, passwordChars);
+
+ if(passwordChars != null)
+ {
+ java.util.Arrays.fill(passwordChars, '\0');
+ }
+ keystorePassword = null;
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to load keystore:\n" + keystorePath, ex);
+ }
+ finally
+ {
+ if(keystoreStream != null)
+ {
+ try
+ {
+ keystoreStream.close();
+ }
+ catch(java.io.IOException e)
+ {
+ // Ignore.
+ }
+ }
+ }
+
+ String algorithm = javax.net.ssl.KeyManagerFactory.getDefaultAlgorithm();
+ javax.net.ssl.KeyManagerFactory kmf = javax.net.ssl.KeyManagerFactory.getInstance(algorithm);
+ char[] passwordChars = new char[0]; // This password cannot be null.
+ if(password.length() > 0)
+ {
+ passwordChars = password.toCharArray();
+ }
+ else if(_passwordCallback != null)
+ {
+ passwordChars = _passwordCallback.getPassword(alias);
+ }
+ kmf.init(keys, passwordChars);
+ if(passwordChars.length > 0)
+ {
+ java.util.Arrays.fill(passwordChars, '\0');
+ }
+ password = null;
+ keyManagers = kmf.getKeyManagers();
+
+ //
+ // If the user selected a specific alias, we need to wrap the key managers
+ // in order to return the desired alias.
+ //
+ if(alias.length() > 0)
+ {
+ if(!keys.isKeyEntry(alias))
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: keystore does not contain an entry with alias `" + alias + "'";
+ throw e;
+ }
+
+ for(int i = 0; i < keyManagers.length; ++i)
+ {
+ keyManagers[i] = new X509KeyManagerI((javax.net.ssl.X509KeyManager)keyManagers[i], alias);
+ }
+ }
+ }
+
+ //
+ // Load the truststore.
+ //
+ java.security.KeyStore ts = null;
+ if(_truststoreStream != null || truststorePath.length() > 0)
+ {
+ //
+ // If the trust store and the key store are the same input
+ // stream or file, don't create another key store.
+ //
+ if((_truststoreStream != null && _truststoreStream == _keystoreStream) ||
+ (truststorePath.length() > 0 && truststorePath.equals(keystorePath)))
+ {
+ assert keys != null;
+ ts = keys;
+ }
+ else
+ {
+ java.io.InputStream truststoreStream = null;
+ try
+ {
+ if(_truststoreStream != null)
+ {
+ truststoreStream = _truststoreStream;
+ }
+ else
+ {
+ truststoreStream = openResource(truststorePath);
+ if(truststoreStream == null)
+ {
+ Ice.PluginInitializationException e = new Ice.PluginInitializationException();
+ e.reason = "IceSSL: truststore not found:\n" + truststorePath;
+ throw e;
+ }
+ }
+
+ ts = java.security.KeyStore.getInstance(truststoreType);
+
+ char[] passwordChars = null;
+ if(truststorePassword.length() > 0)
+ {
+ passwordChars = truststorePassword.toCharArray();
+ }
+ else if(_passwordCallback != null)
+ {
+ passwordChars = _passwordCallback.getTruststorePassword();
+ }
+ else if(truststoreType.equals("BKS"))
+ {
+ // Bouncy Castle does not permit null passwords.
+ passwordChars = new char[0];
+ }
+
+ ts.load(truststoreStream, passwordChars);
+
+ if(passwordChars != null)
+ {
+ java.util.Arrays.fill(passwordChars, '\0');
+ }
+ truststorePassword = null;
+ }
+ catch(java.io.IOException ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: unable to load truststore:\n" + truststorePath, ex);
+ }
+ finally
+ {
+ if(truststoreStream != null)
+ {
+ try
+ {
+ truststoreStream.close();
+ }
+ catch(java.io.IOException e)
+ {
+ // Ignore.
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ ts = keys;
+ }
+
+ //
+ // Collect the trust managers.
+ //
+ javax.net.ssl.TrustManager[] trustManagers = null;
+ {
+ String algorithm = javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm();
+ javax.net.ssl.TrustManagerFactory tmf = javax.net.ssl.TrustManagerFactory.getInstance(algorithm);
+ tmf.init(ts);
+ trustManagers = tmf.getTrustManagers();
+ assert(trustManagers != null);
+ }
+
+ //
+ // Wrap each trust manager.
+ //
+ for(int i = 0; i < trustManagers.length; ++i)
+ {
+ trustManagers[i] = new X509TrustManagerI(this, (javax.net.ssl.X509TrustManager)trustManagers[i]);
+ }
+
+ //
+ // Initialize the SSL context.
+ //
+ _context = javax.net.ssl.SSLContext.getInstance("TLS");
+ _context.init(keyManagers, trustManagers, rand);
+ }
+ catch(java.security.GeneralSecurityException ex)
+ {
+ throw new Ice.PluginInitializationException("IceSSL: unable to initialize context", ex);
+ }
+ }
+
+ //
+ // Clear cached input streams.
+ //
+ _seeds.clear();
+ _keystoreStream = null;
+ _truststoreStream = null;
+
+ _initialized = true;
+ }
+
+ void context(javax.net.ssl.SSLContext context)
+ {
+ if(_initialized)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plug-in is already initialized";
+ throw ex;
+ }
+
+ assert(_context == null);
+ _context = context;
+ }
+
+ javax.net.ssl.SSLContext context()
+ {
+ return _context;
+ }
+
+ void setCertificateVerifier(CertificateVerifier verifier)
+ {
+ _verifier = verifier;
+ }
+
+ CertificateVerifier getCertificateVerifier()
+ {
+ return _verifier;
+ }
+
+ void setPasswordCallback(PasswordCallback callback)
+ {
+ _passwordCallback = callback;
+ }
+
+ PasswordCallback getPasswordCallback()
+ {
+ return _passwordCallback;
+ }
+
+ void setKeystoreStream(java.io.InputStream stream)
+ {
+ if(_initialized)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plugin is already initialized";
+ throw ex;
+ }
+
+ _keystoreStream = stream;
+ }
+
+ void setTruststoreStream(java.io.InputStream stream)
+ {
+ if(_initialized)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: plugin is already initialized";
+ throw ex;
+ }
+
+ _truststoreStream = stream;
+ }
+
+ void addSeedStream(java.io.InputStream stream)
+ {
+ _seeds.add(stream);
+ }
+
+ int securityTraceLevel()
+ {
+ return _securityTraceLevel;
+ }
+
+ String securityTraceCategory()
+ {
+ return _securityTraceCategory;
+ }
+
+ boolean initialized()
+ {
+ return _initialized;
+ }
+
+ javax.net.ssl.SSLEngine createSSLEngine(boolean incoming, java.net.InetSocketAddress peerAddr)
+ {
+ javax.net.ssl.SSLEngine engine;
+ if(peerAddr != null)
+ {
+ engine = _context.createSSLEngine(peerAddr.getAddress().getHostAddress(), peerAddr.getPort());
+ }
+ else
+ {
+ engine = _context.createSSLEngine();
+ }
+ engine.setUseClientMode(!incoming);
+
+ String[] cipherSuites = filterCiphers(engine.getSupportedCipherSuites(), engine.getEnabledCipherSuites());
+ try
+ {
+ engine.setEnabledCipherSuites(cipherSuites);
+ }
+ catch(IllegalArgumentException ex)
+ {
+ throw new Ice.SecurityException("IceSSL: invalid ciphersuite", ex);
+ }
+
+ if(_securityTraceLevel >= 1)
+ {
+ StringBuilder s = new StringBuilder(128);
+ s.append("enabling SSL ciphersuites:");
+ for(String suite : cipherSuites)
+ {
+ s.append("\n ");
+ s.append(suite);
+ }
+ _logger.trace(_securityTraceCategory, s.toString());
+ }
+
+ if(_protocols != null)
+ {
+ try
+ {
+ engine.setEnabledProtocols(_protocols);
+ }
+ catch(IllegalArgumentException ex)
+ {
+ throw new Ice.SecurityException("IceSSL: invalid protocol", ex);
+ }
+ }
+
+ if(incoming)
+ {
+ if(_verifyPeer == 0)
+ {
+ engine.setWantClientAuth(false);
+ engine.setNeedClientAuth(false);
+ }
+ else if(_verifyPeer == 1)
+ {
+ engine.setWantClientAuth(true);
+ }
+ else
+ {
+ engine.setNeedClientAuth(true);
+ }
+ }
+
+ try
+ {
+ engine.beginHandshake();
+ }
+ catch(javax.net.ssl.SSLException ex)
+ {
+ throw new Ice.SecurityException("IceSSL: handshake error", ex);
+ }
+
+ return engine;
+ }
+
+ String[] filterCiphers(String[] supportedCiphers, String[] defaultCiphers)
+ {
+ java.util.LinkedList<String> result = new java.util.LinkedList<String>();
+ if(_allCiphers)
+ {
+ for(String cipher : supportedCiphers)
+ {
+ result.add(cipher);
+ }
+ }
+ else if(!_noCiphers)
+ {
+ for(String cipher : defaultCiphers)
+ {
+ result.add(cipher);
+ }
+ }
+
+ if(_ciphers != null)
+ {
+ for(CipherExpression ce : _ciphers)
+ {
+ if(ce.not)
+ {
+ java.util.Iterator<String> e = result.iterator();
+ while(e.hasNext())
+ {
+ String cipher = e.next();
+ if(ce.cipher != null)
+ {
+ if(ce.cipher.equals(cipher))
+ {
+ e.remove();
+ }
+ }
+ else
+ {
+ assert(ce.re != null);
+ java.util.regex.Matcher m = ce.re.matcher(cipher);
+ if(m.find())
+ {
+ e.remove();
+ }
+ }
+ }
+ }
+ else
+ {
+ if(ce.cipher != null)
+ {
+ result.add(0, ce.cipher);
+ }
+ else
+ {
+ assert(ce.re != null);
+ for(String cipher : supportedCiphers)
+ {
+ java.util.regex.Matcher m = ce.re.matcher(cipher);
+ if(m.find())
+ {
+ result.add(0, cipher);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ String[] arr = new String[result.size()];
+ result.toArray(arr);
+ return arr;
+ }
+
+ String[] protocols()
+ {
+ return _protocols;
+ }
+
+ void traceConnection(java.nio.channels.SocketChannel fd, javax.net.ssl.SSLEngine engine, boolean incoming)
+ {
+ javax.net.ssl.SSLSession session = engine.getSession();
+ String msg = "SSL summary for " + (incoming ? "incoming" : "outgoing") + " connection\n" +
+ "cipher = " + session.getCipherSuite() + "\n" +
+ "protocol = " + session.getProtocol() + "\n" +
+ IceInternal.Network.fdToString(fd);
+ _logger.trace(_securityTraceCategory, msg);
+ }
+
+ Ice.Communicator communicator()
+ {
+ return _communicator;
+ }
+
+ void verifyPeer(NativeConnectionInfo info, java.nio.channels.SelectableChannel fd, String address)
+ {
+ //
+ // For an outgoing connection, we compare the proxy address (if any) against
+ // fields in the server's certificate (if any).
+ //
+ if(info.nativeCerts != null && info.nativeCerts.length > 0 && address.length() > 0)
+ {
+ java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate)info.nativeCerts[0];
+
+ //
+ // Extract the IP addresses and the DNS names from the subject
+ // alternative names.
+ //
+ java.util.ArrayList<String> ipAddresses = new java.util.ArrayList<String>();
+ java.util.ArrayList<String> dnsNames = new java.util.ArrayList<String>();
+ try
+ {
+ java.util.Collection<java.util.List<?> > subjectAltNames = cert.getSubjectAlternativeNames();
+ if(subjectAltNames != null)
+ {
+ for(java.util.List<?> l : subjectAltNames)
+ {
+ assert(!l.isEmpty());
+ Integer n = (Integer)l.get(0);
+ if(n.intValue() == 7)
+ {
+ ipAddresses.add((String)l.get(1));
+ }
+ else if(n.intValue() == 2)
+ {
+ dnsNames.add(((String)l.get(1)).toLowerCase());
+ }
+ }
+ }
+ }
+ catch(java.security.cert.CertificateParsingException ex)
+ {
+ assert(false);
+ }
+
+ //
+ // Compare the peer's address against the common name as well as
+ // the dnsName and ipAddress values in the subject alternative name.
+ //
+ boolean certNameOK = false;
+ String dn = "";
+ String addrLower = address.toLowerCase();
+ {
+ javax.security.auth.x500.X500Principal principal = cert.getSubjectX500Principal();
+ dn = principal.getName(javax.security.auth.x500.X500Principal.CANONICAL);
+ //
+ // Canonical format is already in lower case.
+ //
+ String cn = "cn=" + addrLower;
+ int pos = dn.indexOf(cn);
+ if(pos >= 0)
+ {
+ //
+ // Ensure we match the entire common name.
+ //
+ certNameOK = (pos + cn.length() == dn.length()) || (dn.charAt(pos + cn.length()) == ',');
+ }
+ }
+
+ //
+ // Compare the peer's address against the dnsName and ipAddress
+ // values in the subject alternative name.
+ //
+ if(!certNameOK)
+ {
+ certNameOK = ipAddresses.contains(addrLower);
+ }
+ if(!certNameOK)
+ {
+ certNameOK = dnsNames.contains(addrLower);
+ }
+
+ //
+ // Log a message if the name comparison fails. If CheckCertName is defined,
+ // we also raise an exception to abort the connection. Don't log a message if
+ // CheckCertName is not defined and a verifier is present.
+ //
+ if(!certNameOK && (_checkCertName || (_securityTraceLevel >= 1 && _verifier == null)))
+ {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("IceSSL: ");
+ if(!_checkCertName)
+ {
+ sb.append("ignoring ");
+ }
+ sb.append("certificate validation failure:\npeer certificate does not have `");
+ sb.append(address);
+ sb.append("' as its commonName or in its subjectAltName extension");
+ if(dn.length() > 0)
+ {
+ sb.append("\nSubject DN: ");
+ sb.append(dn);
+ }
+ if(!dnsNames.isEmpty())
+ {
+ sb.append("\nDNS names found in certificate: ");
+ for(int j = 0; j < dnsNames.size(); ++j)
+ {
+ if(j > 0)
+ {
+ sb.append(", ");
+ }
+ sb.append(dnsNames.get(j));
+ }
+ }
+ if(!ipAddresses.isEmpty())
+ {
+ sb.append("\nIP addresses found in certificate: ");
+ for(int j = 0; j < ipAddresses.size(); ++j)
+ {
+ if(j > 0)
+ {
+ sb.append(", ");
+ }
+ sb.append(ipAddresses.get(j));
+ }
+ }
+ if(_securityTraceLevel >= 1)
+ {
+ _logger.trace(_securityTraceCategory, sb.toString());
+ }
+ if(_checkCertName)
+ {
+ Ice.SecurityException ex = new Ice.SecurityException();
+ ex.reason = sb.toString();
+ throw ex;
+ }
+ }
+ }
+
+ if(_verifyDepthMax > 0 && info.nativeCerts != null && info.nativeCerts.length > _verifyDepthMax)
+ {
+ String msg = (info.incoming ? "incoming" : "outgoing") + " connection rejected:\n" +
+ "length of peer's certificate chain (" + info.nativeCerts.length + ") exceeds maximum of " +
+ _verifyDepthMax + "\n" +
+ IceInternal.Network.fdToString(fd);
+ if(_securityTraceLevel >= 1)
+ {
+ _logger.trace(_securityTraceCategory, msg);
+ }
+ Ice.SecurityException ex = new Ice.SecurityException();
+ ex.reason = msg;
+ throw ex;
+ }
+
+ if(!_trustManager.verify(info))
+ {
+ String msg = (info.incoming ? "incoming" : "outgoing") + " connection rejected by trust manager\n" +
+ IceInternal.Network.fdToString(fd);
+ if(_securityTraceLevel >= 1)
+ {
+ _logger.trace(_securityTraceCategory, msg);
+ }
+ Ice.SecurityException ex = new Ice.SecurityException();
+ ex.reason = msg;
+ throw ex;
+ }
+
+ if(_verifier != null && !_verifier.verify(info))
+ {
+ String msg = (info.incoming ? "incoming" : "outgoing") + " connection rejected by certificate verifier\n" +
+ IceInternal.Network.fdToString(fd);
+ if(_securityTraceLevel >= 1)
+ {
+ _logger.trace(_securityTraceCategory, msg);
+ }
+ Ice.SecurityException ex = new Ice.SecurityException();
+ ex.reason = msg;
+ throw ex;
+ }
+ }
+
+ void trustManagerFailure(boolean incoming, java.security.cert.CertificateException ex)
+ throws java.security.cert.CertificateException
+ {
+ if(_verifyPeer == 0)
+ {
+ if(_securityTraceLevel >= 1)
+ {
+ String msg = "ignoring peer verification failure";
+ if(_securityTraceLevel > 1)
+ {
+ java.io.StringWriter sw = new java.io.StringWriter();
+ java.io.PrintWriter pw = new java.io.PrintWriter(sw);
+ ex.printStackTrace(pw);
+ pw.flush();
+ msg += ":\n" + sw.toString();
+ }
+ _logger.trace(_securityTraceCategory, msg);
+ }
+ }
+ else
+ {
+ throw ex;
+ }
+ }
+
+ private void parseCiphers(String ciphers)
+ {
+ java.util.ArrayList<CipherExpression> cipherList = new java.util.ArrayList<CipherExpression>();
+ String[] expr = ciphers.split("[ \t]+");
+ for(int i = 0; i < expr.length; ++i)
+ {
+ if(expr[i].equals("ALL"))
+ {
+ if(i != 0)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: `ALL' must be first in cipher list `" + ciphers + "'";
+ throw ex;
+ }
+ _allCiphers = true;
+ }
+ else if(expr[i].equals("NONE"))
+ {
+ if(i != 0)
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: `NONE' must be first in cipher list `" + ciphers + "'";
+ throw ex;
+ }
+ _noCiphers = true;
+ }
+ else
+ {
+ CipherExpression ce = new CipherExpression();
+ String exp = expr[i];
+ if(exp.charAt(0) == '!')
+ {
+ ce.not = true;
+ if(exp.length() > 1)
+ {
+ exp = exp.substring(1);
+ }
+ else
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: invalid cipher expression `" + exp + "'";
+ throw ex;
+ }
+ }
+
+ if(exp.charAt(0) == '(')
+ {
+ if(!exp.endsWith(")"))
+ {
+ Ice.PluginInitializationException ex = new Ice.PluginInitializationException();
+ ex.reason = "IceSSL: invalid cipher expression `" + exp + "'";
+ throw ex;
+ }
+
+ try
+ {
+ ce.re = java.util.regex.Pattern.compile(exp.substring(1, exp.length() - 2));
+ }
+ catch(java.util.regex.PatternSyntaxException ex)
+ {
+ throw new Ice.PluginInitializationException(
+ "IceSSL: invalid cipher expression `" + exp + "'", ex);
+ }
+ }
+ else
+ {
+ ce.cipher = exp;
+ }
+
+ cipherList.add(ce);
+ }
+ }
+ _ciphers = new CipherExpression[cipherList.size()];
+ cipherList.toArray(_ciphers);
+ }
+
+ private java.io.InputStream openResource(String path)
+ throws java.io.IOException
+ {
+ //
+ // This method wraps a call to IceInternal.Util.openResource. If the first call fails and
+ // IceSSL.DefaultDir is defined, prepend the default directory and try again.
+ //
+ java.io.InputStream stream = IceInternal.Util.openResource(getClass().getClassLoader(), path);
+ if(stream == null && _defaultDir.length() > 0)
+ {
+ stream = IceInternal.Util.openResource(getClass().getClassLoader(),
+ _defaultDir + java.io.File.separator + path);
+ }
+
+ if(stream != null)
+ {
+ stream = new java.io.BufferedInputStream(stream);
+ }
+
+ return stream;
+ }
+
+ private static class CipherExpression
+ {
+ boolean not;
+ String cipher;
+ java.util.regex.Pattern re;
+ }
+
+ private Ice.Communicator _communicator;
+ private Ice.Logger _logger;
+ private IceInternal.ProtocolPluginFacade _facade;
+ private int _securityTraceLevel;
+ private String _securityTraceCategory;
+ private boolean _initialized;
+ private javax.net.ssl.SSLContext _context;
+ private String _defaultDir;
+ private CipherExpression[] _ciphers;
+ private boolean _allCiphers;
+ private boolean _noCiphers;
+ private String[] _protocols;
+ private boolean _checkCertName;
+ private int _verifyDepthMax;
+ private int _verifyPeer;
+ private CertificateVerifier _verifier;
+ private PasswordCallback _passwordCallback;
+ private TrustManager _trustManager;
+
+ private InputStream _keystoreStream;
+ private InputStream _truststoreStream;
+ private List<InputStream> _seeds = new ArrayList<InputStream>();
+}
diff --git a/java/src/IceSSL/TransceiverI.java b/java/src/IceSSL/TransceiverI.java
index 560b278dfdf..51c30138872 100644
--- a/java/src/IceSSL/TransceiverI.java
+++ b/java/src/IceSSL/TransceiverI.java
@@ -15,15 +15,13 @@ import javax.net.ssl.SSLEngineResult.*;
final class TransceiverI implements IceInternal.Transceiver
{
- public java.nio.channels.SelectableChannel
- fd()
+ public java.nio.channels.SelectableChannel fd()
{
assert(_fd != null);
return _fd;
}
- public int
- initialize(IceInternal.Buffer readBuffer, IceInternal.Buffer writeBuffer)
+ public int initialize(IceInternal.Buffer readBuffer, IceInternal.Buffer writeBuffer, Ice.BooleanHolder moreData)
{
try
{
@@ -32,7 +30,7 @@ final class TransceiverI implements IceInternal.Transceiver
_state = StateConnectPending;
return IceInternal.SocketOperation.Connect;
}
- else if(_state == StateConnectPending)
+ else if(_state <= StateConnectPending)
{
IceInternal.Network.doFinishConnect(_fd);
_desc = IceInternal.Network.fdToString(_fd, _proxy, _addr);
@@ -104,33 +102,36 @@ final class TransceiverI implements IceInternal.Transceiver
_state = StateConnected;
}
- if(_state == StateConnected)
- {
- return handshakeNonBlocking();
- }
+ assert(_state == StateConnected);
+
+ return handshakeNonBlocking();
}
catch(Ice.LocalException ex)
{
- if(_instance.networkTraceLevel() >= 2)
+ if(_instance.traceLevel() >= 2)
{
StringBuilder s = new StringBuilder(128);
- s.append("failed to establish ssl connection\n");
+ s.append("failed to establish " + protocol() + " connection\n");
s.append(IceInternal.Network.fdToString(_fd, _proxy, _addr));
- _logger.trace(_instance.networkTraceCategory(), s.toString());
+ _instance.logger().trace(_instance.traceCategory(), s.toString());
}
throw ex;
}
+ }
- return IceInternal.SocketOperation.None;
+ public int closing(boolean initiator, Ice.LocalException ex)
+ {
+ // If we are initiating the connection closure, wait for the peer
+ // to close the TCP/IP connection. Otherwise, close immediately.
+ return initiator ? IceInternal.SocketOperation.Read : IceInternal.SocketOperation.None;
}
- public void
- close()
+ public void close()
{
- if(_state == StateHandshakeComplete && _instance.networkTraceLevel() >= 1)
+ if(_state == StateHandshakeComplete && _instance.traceLevel() >= 1)
{
- String s = "closing ssl connection\n" + toString();
- _logger.trace(_instance.networkTraceCategory(), s);
+ String s = "closing " + protocol() + " connection\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
assert(_fd != null);
@@ -151,7 +152,7 @@ final class TransceiverI implements IceInternal.Transceiver
{
//
// Note: we can't block to send the close_notify message. In some cases, the
- // close_notify message might therefore not be receieved by the peer. This is
+ // close_notify message might therefore not be received by the peer. This is
// not a big issue since the Ice protocol isn't subject to truncation attacks.
//
flushNonBlocking();
@@ -186,7 +187,7 @@ final class TransceiverI implements IceInternal.Transceiver
// We would probably need to wait for a response in shutdown() to avoid this.
// For now, we'll ignore this exception.
//
- //_logger.error("IceSSL: error during close\n" + ex.getMessage());
+ //_instance.logger().error("IceSSL: error during close\n" + ex.getMessage());
}
}
@@ -200,47 +201,33 @@ final class TransceiverI implements IceInternal.Transceiver
}
}
- public boolean
- write(IceInternal.Buffer buf)
+ public int write(IceInternal.Buffer buf)
{
if(_state == StateProxyConnectRequest)
{
//
// We need to write the proxy message, but we have to use TCP and not SSL.
//
- return writeRaw(buf);
- }
-
- //
- // If the handshake isn't completed yet, we shouldn't be writing.
- //
- if(_state < StateHandshakeComplete)
- {
- throw new Ice.ConnectionLostException();
+ return writeRaw(buf) ? IceInternal.SocketOperation.None : IceInternal.SocketOperation.Write;
}
//
- // We don't want write to be called on android main thread as this will cause
- // NetworkOnMainThreadException to be thrown. If that is the android main thread
- // we return false and this method will be later called from the thread pool.
+ // We don't want write to be called on Android's main thread as this will cause
+ // NetworkOnMainThreadException to be thrown. If this is the Android main thread
+ // we return false and this method will be called later from the thread pool.
//
if(IceInternal.Util.isAndroidMainThread(Thread.currentThread()))
{
- return false;
+ return IceInternal.SocketOperation.Write;
}
int status = writeNonBlocking(buf.b);
- if(status != IceInternal.SocketOperation.None)
- {
- assert(status == IceInternal.SocketOperation.Write);
- return false;
- }
- return true;
+ assert(status == IceInternal.SocketOperation.None || status == IceInternal.SocketOperation.Write);
+ return status;
}
@SuppressWarnings("deprecation")
- public boolean
- read(IceInternal.Buffer buf, Ice.BooleanHolder moreData)
+ public int read(IceInternal.Buffer buf, Ice.BooleanHolder moreData)
{
moreData.value = false;
@@ -249,21 +236,11 @@ final class TransceiverI implements IceInternal.Transceiver
//
// We need to read the proxy reply, but we have to use TCP and not SSL.
//
- return readRaw(buf);
- }
-
- //
- // If the handshake isn't completed yet, we shouldn't be reading (read can be
- // called by the thread pool when the connection is registered/unregistered
- // with the pool to be closed).
- //
- if(_state < StateHandshakeComplete)
- {
- throw new Ice.ConnectionLostException();
+ return readRaw(buf) ? IceInternal.SocketOperation.None : IceInternal.SocketOperation.Read;
}
int rem = 0;
- if(_instance.networkTraceLevel() >= 3)
+ if(_instance.traceLevel() >= 3)
{
rem = buf.b.remaining();
}
@@ -274,10 +251,11 @@ final class TransceiverI implements IceInternal.Transceiver
int pos = buf.b.position();
fill(buf.b);
- if(_instance.networkTraceLevel() >= 3 && buf.b.position() > pos)
+ if(_instance.traceLevel() >= 3 && buf.b.position() > pos)
{
- String s = "received " + (buf.b.position() - pos) + " of " + rem + " bytes via ssl\n" + toString();
- _logger.trace(_instance.networkTraceCategory(), s);
+ String s = "received " + (buf.b.position() - pos) + " of " + rem + " bytes via " + protocol() +
+ "\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
//
@@ -305,7 +283,7 @@ final class TransceiverI implements IceInternal.Transceiver
if(status != IceInternal.SocketOperation.None)
{
assert(status == IceInternal.SocketOperation.Read);
- return false;
+ return status;
}
continue;
}
@@ -322,10 +300,11 @@ final class TransceiverI implements IceInternal.Transceiver
pos = buf.b.position();
fill(buf.b);
- if(_instance.networkTraceLevel() >= 3 && buf.b.position() > pos)
+ if(_instance.traceLevel() >= 3 && buf.b.position() > pos)
{
- String s = "received " + (buf.b.position() - pos) + " of " + rem + " bytes via ssl\n" + toString();
- _logger.trace(_instance.networkTraceCategory(), s);
+ String s = "received " + (buf.b.position() - pos) + " of " + rem + " bytes via " + protocol() +
+ "\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
}
}
@@ -338,29 +317,25 @@ final class TransceiverI implements IceInternal.Transceiver
// Return a boolean to indicate whether more data is available.
//
moreData.value = _netInput.position() > 0;
- return true;
+ return IceInternal.SocketOperation.None;
}
- public String
- type()
+ public String protocol()
{
- return "ssl";
+ return _instance.protocol();
}
- public String
- toString()
+ public String toString()
{
return _desc;
}
- public Ice.ConnectionInfo
- getInfo()
+ public Ice.ConnectionInfo getInfo()
{
return getNativeConnectionInfo();
}
- public void
- checkSendSize(IceInternal.Buffer buf, int messageSizeMax)
+ public void checkSendSize(IceInternal.Buffer buf, int messageSizeMax)
{
if(buf.size() > messageSizeMax)
{
@@ -397,7 +372,6 @@ final class TransceiverI implements IceInternal.Transceiver
_instance = instance;
_engine = engine;
_fd = fd;
- _logger = instance.communicator().getLogger();
_maxPacketSize = 0;
if(System.getProperty("os.name").startsWith("Windows"))
{
@@ -418,8 +392,7 @@ final class TransceiverI implements IceInternal.Transceiver
_netOutput = ByteBuffer.allocateDirect(engine.getSession().getPacketBufferSize() * 2);
}
- protected void
- finalize()
+ protected void finalize()
throws Throwable
{
try
@@ -435,8 +408,7 @@ final class TransceiverI implements IceInternal.Transceiver
}
}
- private NativeConnectionInfo
- getNativeConnectionInfo()
+ private NativeConnectionInfo getNativeConnectionInfo()
{
//
// This can only be called on an open transceiver.
@@ -454,7 +426,7 @@ final class TransceiverI implements IceInternal.Transceiver
info.localAddress = socket.getLocalAddress().getHostAddress();
info.localPort = socket.getLocalPort();
}
-
+
if(socket.getInetAddress() != null)
{
info.remoteAddress = socket.getInetAddress().getHostAddress();
@@ -489,8 +461,7 @@ final class TransceiverI implements IceInternal.Transceiver
return info;
}
- private int
- handshakeNonBlocking()
+ private int handshakeNonBlocking()
{
try
{
@@ -599,8 +570,7 @@ final class TransceiverI implements IceInternal.Transceiver
return IceInternal.SocketOperation.None;
}
- private void
- handshakeCompleted()
+ private void handshakeCompleted()
{
_state = StateHandshakeComplete;
@@ -610,8 +580,7 @@ final class TransceiverI implements IceInternal.Transceiver
//
if(!_incoming)
{
- int verifyPeer =
- _instance.communicator().getProperties().getPropertyAsIntWithDefault("IceSSL.VerifyPeer", 2);
+ int verifyPeer = _instance.properties().getPropertyAsIntWithDefault("IceSSL.VerifyPeer", 2);
if(verifyPeer > 0)
{
try
@@ -630,18 +599,18 @@ final class TransceiverI implements IceInternal.Transceiver
//
_instance.verifyPeer(getNativeConnectionInfo(), _fd, _host);
- if(_instance.networkTraceLevel() >= 1)
+ if(_instance.traceLevel() >= 1)
{
String s;
if(_incoming)
{
- s = "accepted ssl connection\n" + _desc;
+ s = "accepted " + protocol() + " connection\n" + _desc;
}
else
{
- s = "ssl connection established\n" + _desc;
+ s = protocol() + " connection established\n" + _desc;
}
- _logger.trace(_instance.networkTraceCategory(), s);
+ _instance.logger().trace(_instance.traceCategory(), s);
}
if(_instance.securityTraceLevel() >= 1)
@@ -651,8 +620,7 @@ final class TransceiverI implements IceInternal.Transceiver
}
@SuppressWarnings("deprecation")
- private int
- writeNonBlocking(ByteBuffer buf)
+ private int writeNonBlocking(ByteBuffer buf)
{
//
// This method has two purposes: encrypt the application's message buffer into our
@@ -693,11 +661,11 @@ final class TransceiverI implements IceInternal.Transceiver
//
if(result.bytesConsumed() > 0)
{
- if(_instance.networkTraceLevel() >= 3)
+ if(_instance.traceLevel() >= 3)
{
- String s = "sent " + result.bytesConsumed() + " of " + rem + " bytes via ssl\n" +
- toString();
- _logger.trace(_instance.networkTraceCategory(), s);
+ String s = "sent " + result.bytesConsumed() + " of " + rem + " bytes via " +
+ protocol() + "\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
}
}
@@ -705,7 +673,7 @@ final class TransceiverI implements IceInternal.Transceiver
//
// Write the encrypted data to the socket. We continue writing until we've written
// all of _netOutput, or until flushNonBlocking indicates that it cannot write
- // (i.e., by returning NeedWrite).
+ // (i.e., by returning SocketOperation.Write).
//
if(_netOutput.position() > 0)
{
@@ -727,8 +695,7 @@ final class TransceiverI implements IceInternal.Transceiver
return IceInternal.SocketOperation.None;
}
- private int
- flushNonBlocking()
+ private int flushNonBlocking()
{
_netOutput.flip();
@@ -792,8 +759,7 @@ final class TransceiverI implements IceInternal.Transceiver
return status;
}
- private int
- readNonBlocking()
+ private int readNonBlocking()
{
while(true)
{
@@ -826,8 +792,7 @@ final class TransceiverI implements IceInternal.Transceiver
return IceInternal.SocketOperation.None;
}
- private void
- fill(ByteBuffer buf)
+ private void fill(ByteBuffer buf)
{
_appInput.flip();
if(_appInput.hasRemaining())
@@ -872,8 +837,7 @@ final class TransceiverI implements IceInternal.Transceiver
}
@SuppressWarnings("deprecation")
- private boolean
- writeRaw(IceInternal.Buffer buf)
+ private boolean writeRaw(IceInternal.Buffer buf)
{
//
// We don't want write to be called on android main thread as this will cause
@@ -904,10 +868,10 @@ final class TransceiverI implements IceInternal.Transceiver
return false;
}
- if(_instance.networkTraceLevel() >= 3)
+ if(_instance.traceLevel() >= 3)
{
- String s = "sent " + ret + " of " + packetSize + " bytes via tcp\n" + toString();
- _logger.trace(_instance.networkTraceCategory(), s);
+ String s = "sent " + ret + " of " + packetSize + " bytes via " + protocol() + "\n" + toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
}
catch(java.io.InterruptedIOException ex)
@@ -923,8 +887,7 @@ final class TransceiverI implements IceInternal.Transceiver
}
@SuppressWarnings("deprecation")
- private boolean
- readRaw(IceInternal.Buffer buf)
+ private boolean readRaw(IceInternal.Buffer buf)
{
int packetSize = buf.b.remaining();
@@ -947,10 +910,11 @@ final class TransceiverI implements IceInternal.Transceiver
if(ret > 0)
{
- if(_instance.networkTraceLevel() >= 3)
+ if(_instance.traceLevel() >= 3)
{
- String s = "received " + ret + " of " + packetSize + " bytes via tcp\n" + toString();
- _logger.trace(_instance.networkTraceCategory(), s);
+ String s = "received " + ret + " of " + packetSize + " bytes via " + protocol() + "\n" +
+ toString();
+ _instance.logger().trace(_instance.traceCategory(), s);
}
}
@@ -978,7 +942,6 @@ final class TransceiverI implements IceInternal.Transceiver
private String _adapterName;
private java.net.InetSocketAddress _addr;
private int _state;
- private Ice.Logger _logger;
private String _desc;
private int _maxPacketSize;
diff --git a/java/src/IceSSL/X509TrustManagerI.java b/java/src/IceSSL/X509TrustManagerI.java
index 39e5b7cd24f..9a1f22cb470 100644
--- a/java/src/IceSSL/X509TrustManagerI.java
+++ b/java/src/IceSSL/X509TrustManagerI.java
@@ -11,7 +11,7 @@ package IceSSL;
final class X509TrustManagerI implements javax.net.ssl.X509TrustManager
{
- X509TrustManagerI(Instance instance, javax.net.ssl.X509TrustManager delegate)
+ X509TrustManagerI(SharedInstance instance, javax.net.ssl.X509TrustManager delegate)
{
_instance = instance;
_delegate = delegate;
@@ -67,6 +67,6 @@ final class X509TrustManagerI implements javax.net.ssl.X509TrustManager
return _delegate.getAcceptedIssuers();
}
- private Instance _instance;
+ private SharedInstance _instance;
private javax.net.ssl.X509TrustManager _delegate;
}
diff --git a/java/test/Ice/background/Acceptor.java b/java/test/Ice/background/Acceptor.java
index 5833012a313..02a33c49506 100644
--- a/java/test/Ice/background/Acceptor.java
+++ b/java/test/Ice/background/Acceptor.java
@@ -36,6 +36,12 @@ class Acceptor implements IceInternal.Acceptor
}
public String
+ protocol()
+ {
+ return _acceptor.protocol();
+ }
+
+ public String
toString()
{
return _acceptor.toString();
diff --git a/java/test/Ice/background/Configuration.java b/java/test/Ice/background/Configuration.java
index 15e7b37e58c..befe01738fc 100644
--- a/java/test/Ice/background/Configuration.java
+++ b/java/test/Ice/background/Configuration.java
@@ -143,6 +143,18 @@ public final class Configuration
}
}
+ public synchronized void
+ buffered(boolean b)
+ {
+ _buffered = b;
+ }
+
+ public synchronized boolean
+ buffered()
+ {
+ return _buffered;
+ }
+
private Ice.LocalException _connectorsException;
private Ice.LocalException _connectException;
private int _initializeSocketStatus;
@@ -152,4 +164,5 @@ public final class Configuration
private Ice.LocalException _readException;
private int _writeReadyCount;
private Ice.LocalException _writeException;
+ private boolean _buffered;
}
diff --git a/java/test/Ice/background/EndpointFactory.java b/java/test/Ice/background/EndpointFactory.java
index b611e5bf911..55aba553082 100644
--- a/java/test/Ice/background/EndpointFactory.java
+++ b/java/test/Ice/background/EndpointFactory.java
@@ -29,16 +29,21 @@ final class EndpointFactory implements IceInternal.EndpointFactory
}
public IceInternal.EndpointI
- create(String str, boolean server)
+ create(java.util.ArrayList<String> args, boolean server)
{
- return new EndpointI(_configuration, _factory.create(str, server));
+ return new EndpointI(_configuration, _factory.create(args, server));
}
public IceInternal.EndpointI
read(IceInternal.BasicStream s)
{
- s.readShort();
- return new EndpointI(_configuration, _factory.read(s));
+ short type = s.readShort();
+ assert(type == _factory.type());
+
+ s.startReadEncaps();
+ IceInternal.EndpointI endpoint = new EndpointI(_configuration, _factory.read(s));
+ s.endReadEncaps();
+ return endpoint;
}
public void
@@ -46,6 +51,12 @@ final class EndpointFactory implements IceInternal.EndpointFactory
{
}
+ public IceInternal.EndpointFactory
+ clone(IceInternal.ProtocolInstance instance)
+ {
+ return this;
+ }
+
private Configuration _configuration;
private IceInternal.EndpointFactory _factory;
}
diff --git a/java/test/Ice/background/EndpointI.java b/java/test/Ice/background/EndpointI.java
index 575123e4978..d364e0b32a8 100644
--- a/java/test/Ice/background/EndpointI.java
+++ b/java/test/Ice/background/EndpointI.java
@@ -19,67 +19,45 @@ final class EndpointI extends IceInternal.EndpointI
_configuration = configuration;
}
- //
- // Marshal the endpoint
- //
- public void
- streamWrite(IceInternal.BasicStream s)
- {
- s.writeShort(type());
- _endpoint.streamWrite(s);
- }
-
- //
- // Convert the endpoint to its string form
- //
public String
_toString()
{
return "test-" + _endpoint.toString();
}
- //
- // Return the endpoint information/
- //
public Ice.EndpointInfo
getInfo()
{
return _endpoint.getInfo();
}
- //
- // Return the endpoint type
- //
+ public void
+ streamWrite(IceInternal.BasicStream s)
+ {
+ s.startWriteEncaps();
+ s.writeShort(_endpoint.type());
+ _endpoint.streamWrite(s);
+ s.endWriteEncaps();
+ }
+
public short
type()
{
return (short)(TYPE_BASE + _endpoint.type());
}
- //
- // Return the protocol name
- //
public String
protocol()
{
return _endpoint.protocol();
}
- //
- // Return the timeout for the endpoint in milliseconds. 0 means
- // non-blocking, -1 means no timeout.
- //
public int
timeout()
{
return _endpoint.timeout();
}
- //
- // Return a new endpoint with a different timeout value, provided
- // that timeouts are supported by the endpoint. Otherwise the same
- // endpoint is returned.
- //
public IceInternal.EndpointI
timeout(int timeout)
{
@@ -94,9 +72,12 @@ final class EndpointI extends IceInternal.EndpointI
}
}
- //
- // Return a new endpoint with a different connection id.
- //
+ public String
+ connectionId()
+ {
+ return _endpoint.connectionId();
+ }
+
public IceInternal.EndpointI
connectionId(String connectionId)
{
@@ -111,21 +92,12 @@ final class EndpointI extends IceInternal.EndpointI
}
}
- //
- // Return true if the endpoints support bzip2 compress, or false
- // otherwise.
- //
public boolean
compress()
{
return _endpoint.compress();
}
- //
- // Return a new endpoint with a different compression value,
- // provided that compression is supported by the
- // endpoint. Otherwise the same endpoint is returned.
- //
public IceInternal.EndpointI
compress(boolean compress)
{
@@ -140,31 +112,18 @@ final class EndpointI extends IceInternal.EndpointI
}
}
- //
- // Return true if the endpoint is datagram-based.
- //
public boolean
datagram()
{
return _endpoint.datagram();
}
- //
- // Return true if the endpoint is secure.
- //
public boolean
secure()
{
return _endpoint.secure();
}
- //
- // Return a server side transceiver for this endpoint, or null if a
- // transceiver can only be created by an acceptor. In case a
- // transceiver is created, this operation also returns a new
- // "effective" endpoint, which might differ from this endpoint,
- // for example, if a dynamic port number is assigned.
- //
public IceInternal.Transceiver
transceiver(IceInternal.EndpointIHolder endpoint)
{
@@ -188,10 +147,6 @@ final class EndpointI extends IceInternal.EndpointI
}
}
- //
- // Return connectors for this endpoint, or empty list if no connector
- // is available.
- //
public java.util.List<IceInternal.Connector>
connectors(Ice.EndpointSelectionType selType)
{
@@ -272,6 +227,12 @@ final class EndpointI extends IceInternal.EndpointI
return testEndpoint._endpoint.equivalent(_endpoint);
}
+ public String
+ options()
+ {
+ return _endpoint.options();
+ }
+
public int
hashCode()
{
diff --git a/java/test/Ice/background/Transceiver.java b/java/test/Ice/background/Transceiver.java
index 8209e90a600..36a0b85a6d2 100644
--- a/java/test/Ice/background/Transceiver.java
+++ b/java/test/Ice/background/Transceiver.java
@@ -18,14 +18,18 @@ final class Transceiver implements IceInternal.Transceiver
}
public int
- initialize(IceInternal.Buffer readBuffer, IceInternal.Buffer writeBuffer)
+ initialize(IceInternal.Buffer readBuffer, IceInternal.Buffer writeBuffer, Ice.BooleanHolder moreData)
{
int status = _configuration.initializeSocketStatus();
- if(status == IceInternal.SocketOperation.Connect || status == IceInternal.SocketOperation.Write)
+ if(status == IceInternal.SocketOperation.Connect)
+ {
+ return status;
+ }
+ else if(status == IceInternal.SocketOperation.Write)
{
if(!_initialized)
{
- status = _transceiver.initialize(readBuffer, writeBuffer);
+ status = _transceiver.initialize(readBuffer, writeBuffer, moreData);
if(status != IceInternal.SocketOperation.None)
{
return status;
@@ -42,7 +46,7 @@ final class Transceiver implements IceInternal.Transceiver
_configuration.checkInitializeException();
if(!_initialized)
{
- status = _transceiver.initialize(readBuffer, writeBuffer);
+ status = _transceiver.initialize(readBuffer, writeBuffer, moreData);
if(status != IceInternal.SocketOperation.None)
{
return status;
@@ -52,41 +56,82 @@ final class Transceiver implements IceInternal.Transceiver
return IceInternal.SocketOperation.None;
}
+ public int
+ closing(boolean initiator, Ice.LocalException ex)
+ {
+ return _transceiver.closing(initiator, ex);
+ }
+
public void
close()
{
_transceiver.close();
}
- public boolean
+ public int
write(IceInternal.Buffer buf)
{
- if(!_configuration.writeReady())
+ if(!_configuration.writeReady() && buf.b.hasRemaining())
{
- return false;
+ return IceInternal.SocketOperation.Write;
}
+
_configuration.checkWriteException();
return _transceiver.write(buf);
}
- public boolean
+ public int
read(IceInternal.Buffer buf, Ice.BooleanHolder moreData)
{
- if(!moreData.value)
+ if(!_configuration.readReady() && buf.b.hasRemaining())
+ {
+ return IceInternal.SocketOperation.Read;
+ }
+
+ _configuration.checkReadException();
+
+ if(_buffered)
{
- if(!_configuration.readReady())
+ while(buf.b.hasRemaining())
{
- return false;
+ if(_readBufferPos == _readBuffer.b.position())
+ {
+ _readBufferPos = 0;
+ _readBuffer.b.position(0);
+ _transceiver.read(_readBuffer, moreData);
+ if(_readBufferPos == _readBuffer.b.position())
+ {
+ moreData.value = false;
+ return IceInternal.SocketOperation.Read;
+ }
+ }
+ assert(_readBuffer.b.position() > _readBufferPos);
+ int requested = buf.b.remaining();
+ int available = _readBuffer.b.position() - _readBufferPos;
+ assert(available > 0);
+ if(available >= requested)
+ {
+ available = requested;
+ }
+
+ byte[] arr = new byte[available];
+ _readBuffer.b.get(arr);
+ buf.b.put(arr);
+ _readBufferPos += available;
}
+ moreData.value = _readBufferPos < _readBuffer.b.position();
+ return IceInternal.SocketOperation.None;
+ }
+ else
+ {
+ return _transceiver.read(buf, moreData);
}
- _configuration.checkReadException();
- return _transceiver.read(buf, moreData);
}
public String
- type()
+ protocol()
{
- return "test-" + _transceiver.type();
+ return "test-" + _transceiver.protocol();
}
public String
@@ -114,9 +159,17 @@ final class Transceiver implements IceInternal.Transceiver
{
_transceiver = transceiver;
_configuration = configuration;
+ _initialized = false;
+ _buffered = _configuration.buffered();
+ _readBuffer = new IceInternal.Buffer(100 * 1024, false);
+ _readBuffer.resize(1024 * 8, true); // 8KB buffer
+ _readBufferPos = 0;
}
- final private IceInternal.Transceiver _transceiver;
- final private Configuration _configuration;
- private boolean _initialized = false;
+ private final IceInternal.Transceiver _transceiver;
+ private final Configuration _configuration;
+ private boolean _initialized;
+ private final boolean _buffered;
+ private IceInternal.Buffer _readBuffer;
+ private int _readBufferPos;
}
diff --git a/java/test/Ice/hold/HoldI.java b/java/test/Ice/hold/HoldI.java
index 2a2cddfc726..00a80469bbc 100644
--- a/java/test/Ice/hold/HoldI.java
+++ b/java/test/Ice/hold/HoldI.java
@@ -111,7 +111,7 @@ public final class HoldI extends _HoldDisp
{
if(_last != expected)
{
- System.err.println("_last = " + _last + " expected = " + expected);
+ System.err.println("_last = " + _last + " expected = " + expected + " value = " + value);
_adapter.getCommunicator().shutdown();
test(false);
}