summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpp/config/TestUtil.py4
-rw-r--r--cpp/slice/Ice/LocalException.ice11
-rw-r--r--cpp/src/Ice/Connection.cpp84
-rw-r--r--cpp/src/Ice/Connection.h1
-rw-r--r--cpp/src/Ice/ConnectionFactory.cpp21
-rw-r--r--cpp/src/Ice/ConnectionFactory.h2
-rw-r--r--cpp/src/Ice/Exception.cpp7
-rw-r--r--cpp/src/Ice/Protocol.h9
-rw-r--r--cpp/src/Ice/TraceUtil.cpp5
-rw-r--r--java/src/IceInternal/Connection.java84
-rw-r--r--java/src/IceInternal/IncomingConnectionFactory.java6
-rw-r--r--java/src/IceInternal/Protocol.java9
-rw-r--r--java/src/IceInternal/TraceUtil.java5
13 files changed, 216 insertions, 32 deletions
diff --git a/cpp/config/TestUtil.py b/cpp/config/TestUtil.py
index fb9a3a78ad7..2ee25fc35e6 100644
--- a/cpp/config/TestUtil.py
+++ b/cpp/config/TestUtil.py
@@ -16,8 +16,8 @@ import sys, os
# protocol. Otherwise TCP is used.
#
-protocol = "ssl"
-#protocol = ""
+#protocol = "ssl"
+protocol = ""
#
# Set compressed to 1 in case you want to run the tests with
diff --git a/cpp/slice/Ice/LocalException.ice b/cpp/slice/Ice/LocalException.ice
index 733a1113aa9..49902fcedac 100644
--- a/cpp/slice/Ice/LocalException.ice
+++ b/cpp/slice/Ice/LocalException.ice
@@ -305,6 +305,17 @@ local exception UnknownMessageException extends ProtocolException
/**
*
+ * This exception is a specialization of [ProtocolException], that is
+ * raised if a message is received over a connection that is not yet
+ * validated.
+ *
+ **/
+local exception ConnectionNotValidatedException extends ProtocolException
+{
+};
+
+/**
+ *
* This exception is a specialization of [ProtocolException],
* indicating that a response for an unknown request id has been
* received.
diff --git a/cpp/src/Ice/Connection.cpp b/cpp/src/Ice/Connection.cpp
index e25f1c98fb3..f30bd36759c 100644
--- a/cpp/src/Ice/Connection.cpp
+++ b/cpp/src/Ice/Connection.cpp
@@ -414,6 +414,25 @@ IceInternal::Connection::message(BasicStream& stream, const ThreadPoolPtr& threa
assert(stream.i == stream.b.end());
stream.i = stream.b.begin() + 2;
stream.read(messageType);
+
+ //
+ // Check whether the connection is validated.
+ //
+ if(!_connectionValidated && messageType != validateConnectionMsg)
+ {
+ //
+ // Yes, we must set _connectionValidated to true
+ // here. The connection gets implicitly validated by
+ // any kind of message. However, it's still a protocol
+ // error like any other if no explicit connection
+ // validation message was sent first. Also, if I
+ // wouldn't set _connecitonValidated to true here,
+ // then the ConnectionValidatedException would be
+ // translated int a CloseConnectionException.
+ //
+ _connectionValidated = true;
+ throw ConnectionNotValidatedException(__FILE__, __LINE__);
+ }
//
// Uncompress if necessary.
@@ -548,6 +567,25 @@ IceInternal::Connection::message(BasicStream& stream, const ThreadPoolPtr& threa
break;
}
+ case validateConnectionMsg:
+ {
+ traceHeader("received validate connection", stream, _logger, _traceLevels);
+ if(_endpoint->datagram())
+ {
+ if(_warn)
+ {
+ Warning out(_logger);
+ out << "ignoring validate connection message for datagram connection:\n"
+ << _transceiver->toString();
+ }
+ }
+ else
+ {
+ _connectionValidated = true;
+ }
+ break;
+ }
+
case closeConnectionMsg:
{
traceHeader("received close connection", stream, _logger, _traceLevels);
@@ -782,22 +820,33 @@ IceInternal::Connection::Connection(const InstancePtr& instance,
{
_warn = _instance->properties()->getPropertyAsInt("Ice.ConnectionWarnings") > 0;
- if(_adapter)
+ if(_endpoint->datagram())
{
//
- // Incoming connections are always implicitly validated.
+ // Datagram connections are always implicitly validated.
//
_connectionValidated = true;
}
else
{
- //
- // Outoging datagram connections are always validated
- // implicitly. Outgoing non-datagram connections must receive a
- // message from the server for connection validation.
- //
- //_connectionValidated = _endpoint->datagram();
- _connectionValidated = true; // TODO: Not finished yet.
+ if(_adapter)
+ {
+ //
+ // Incoming connections play the active role with respect
+ // to connection validation.
+ //
+ _connectionValidated = true;
+ validateConnection();
+ }
+ else
+ {
+ //
+ // Outgoing connections are passive with respect to
+ // validation, i.e., they wait until they get a validate
+ // connection message from the server.
+ //
+ _connectionValidated = false;
+ }
}
}
@@ -959,6 +1008,19 @@ IceInternal::Connection::setState(State state)
}
void
+IceInternal::Connection::validateConnection()
+{
+ BasicStream os(_instance);
+ os.write(protocolVersion);
+ os.write(encodingVersion);
+ os.write(validateConnectionMsg);
+ os.write(headerSize); // Message size.
+ os.i = os.b.begin();
+ traceHeader("sending validate connection", os, _logger, _traceLevels);
+ _transceiver->write(os, _endpoint->timeout());
+}
+
+void
IceInternal::Connection::closeConnection()
{
BasicStream os(_instance);
@@ -969,6 +1031,10 @@ IceInternal::Connection::closeConnection()
os.i = os.b.begin();
traceHeader("sending close connection", os, _logger, _traceLevels);
_transceiver->write(os, _endpoint->timeout());
+
+ //
+ // A close connection is always followed by a connection shutdown.
+ //
_transceiver->shutdown();
}
diff --git a/cpp/src/Ice/Connection.h b/cpp/src/Ice/Connection.h
index 102012f6378..50fc13f30f5 100644
--- a/cpp/src/Ice/Connection.h
+++ b/cpp/src/Ice/Connection.h
@@ -90,6 +90,7 @@ private:
void setState(State, const ::Ice::LocalException&);
void setState(State);
+ void validateConnection();
void closeConnection();
void registerWithPool();
void unregisterWithPool();
diff --git a/cpp/src/Ice/ConnectionFactory.cpp b/cpp/src/Ice/ConnectionFactory.cpp
index 4cfe1b2f95f..0645e0dee39 100644
--- a/cpp/src/Ice/ConnectionFactory.cpp
+++ b/cpp/src/Ice/ConnectionFactory.cpp
@@ -334,9 +334,18 @@ IceInternal::IncomingConnectionFactory::message(BasicStream&, const ThreadPoolPt
try
{
TransceiverPtr transceiver = _acceptor->accept(0);
- ConnectionPtr connection = new Connection(_instance, transceiver, _endpoint, _adapter);
- connection->activate();
- _connections.push_back(connection);
+ // Test code: We drop every 2nd connection we accept.
+/*
+ if(++_testCount % 2)
+ {
+ transceiver->close();
+ }
+ else
+*/ {
+ ConnectionPtr connection = new Connection(_instance, transceiver, _endpoint, _adapter);
+ connection->activate();
+ _connections.push_back(connection);
+ }
}
catch(const SocketException&)
{
@@ -371,6 +380,11 @@ IceInternal::IncomingConnectionFactory::finished(const ThreadPoolPtr& threadPool
}
else if(_state == StateClosed)
{
+//
+// With the new connection validation, this code is not needed
+// anymore.
+//
+/*
try
{
//
@@ -399,6 +413,7 @@ IceInternal::IncomingConnectionFactory::finished(const ThreadPoolPtr& threadPool
out << "connection exception:\n" << ex << '\n' << _acceptor->toString();
}
}
+*/
_acceptor->close();
diff --git a/cpp/src/Ice/ConnectionFactory.h b/cpp/src/Ice/ConnectionFactory.h
index 15fadcf3ca8..72fe7c4508d 100644
--- a/cpp/src/Ice/ConnectionFactory.h
+++ b/cpp/src/Ice/ConnectionFactory.h
@@ -101,6 +101,8 @@ private:
State _state;
bool _warn;
bool _registeredWithPool;
+
+ int _testCount; // TODO: For test only.
};
}
diff --git a/cpp/src/Ice/Exception.cpp b/cpp/src/Ice/Exception.cpp
index daa6ee8b3fe..3d6d3bd8733 100644
--- a/cpp/src/Ice/Exception.cpp
+++ b/cpp/src/Ice/Exception.cpp
@@ -212,6 +212,13 @@ Ice::UnknownMessageException::ice_print(ostream& out) const
}
void
+Ice::ConnectionNotValidatedException::ice_print(ostream& out) const
+{
+ Exception::ice_print(out);
+ out << ":\nprotocol error: received message over unvalidated connection";
+}
+
+void
Ice::UnknownRequestIdException::ice_print(ostream& out) const
{
Exception::ice_print(out);
diff --git a/cpp/src/Ice/Protocol.h b/cpp/src/Ice/Protocol.h
index 4d9c879b3b6..d79f08bfa2c 100644
--- a/cpp/src/Ice/Protocol.h
+++ b/cpp/src/Ice/Protocol.h
@@ -38,10 +38,11 @@ const ::Ice::Byte encodingVersion = 0;
const ::Ice::Byte requestMsg = 0;
const ::Ice::Byte requestBatchMsg = 1;
const ::Ice::Byte replyMsg = 2;
-const ::Ice::Byte closeConnectionMsg = 3;
-const ::Ice::Byte compressedRequestMsg = 4;
-const ::Ice::Byte compressedRequestBatchMsg = 5;
-const ::Ice::Byte compressedReplyMsg = 6;
+const ::Ice::Byte validateConnectionMsg = 3;
+const ::Ice::Byte closeConnectionMsg = 4;
+const ::Ice::Byte compressedRequestMsg = 5;
+const ::Ice::Byte compressedRequestBatchMsg = 6;
+const ::Ice::Byte compressedReplyMsg = 7;
}
diff --git a/cpp/src/Ice/TraceUtil.cpp b/cpp/src/Ice/TraceUtil.cpp
index ac4069fc36f..1a9d2889dbe 100644
--- a/cpp/src/Ice/TraceUtil.cpp
+++ b/cpp/src/Ice/TraceUtil.cpp
@@ -71,6 +71,11 @@ printHeader(ostream& s, BasicStream& stream)
s << "(close connection)";
break;
}
+ case validateConnectionMsg:
+ {
+ s << "(validate connection)";
+ break;
+ }
default:
{
s << "(unknown)";
diff --git a/java/src/IceInternal/Connection.java b/java/src/IceInternal/Connection.java
index f3bb30097e1..33ec2527665 100644
--- a/java/src/IceInternal/Connection.java
+++ b/java/src/IceInternal/Connection.java
@@ -387,6 +387,26 @@ public final class Connection extends EventHandler
byte messageType = stream.readByte();
stream.pos(Protocol.headerSize);
+ //
+ // Check whether the connection is validated.
+ //
+ if(!_connectionValidated && messageType != Protocol.validateConnectionMsg)
+ {
+ //
+ // Yes, we must set _connectionValidated to true
+ // here. The connection gets implicitly validated
+ // by any kind of message. However, it's still a
+ // protocol error like any other if no explicit
+ // connection validation message was sent
+ // first. Also, if I wouldn't set
+ // _connecitonValidated to true here, then the
+ // ConnectionValidatedException would be
+ // translated int a CloseConnectionException.
+ //
+ _connectionValidated = true;
+ throw new Ice.ConnectionNotValidatedException();
+ }
+
switch(messageType)
{
case Protocol.compressedRequestMsg:
@@ -442,6 +462,24 @@ public final class Connection extends EventHandler
break;
}
+ case Protocol.validateConnectionMsg:
+ {
+ TraceUtil.traceHeader("received validate connection", stream, _logger, _traceLevels);
+ if(_endpoint.datagram())
+ {
+ if(_warn)
+ {
+ _logger.warning("ignoring validate connection message for datagram connection:\n" +
+ _transceiver.toString());
+ }
+ }
+ else
+ {
+ _connectionValidated = true;
+ }
+ break;
+ }
+
case Protocol.closeConnectionMsg:
{
TraceUtil.traceHeader("received close connection", stream, _logger, _traceLevels);
@@ -702,24 +740,34 @@ public final class Connection extends EventHandler
_warn = _instance.properties().getPropertyAsInt("Ice.ConnectionWarnings") > 0 ? true : false;
_registeredWithPool = false;
- if(_adapter != null)
+ if(_endpoint.datagram())
{
//
- // Incoming connections are always implicitly validated.
+ // Datagram connections are always implicitly validated.
//
_connectionValidated = true;
}
else
{
- //
- // Outoging datagram connections are always validated
- // implicitly. Outgoing non-datagram connections must receive a
- // message from the server for connection validation.
- //
- //_connectionValidated = _endpoint.datagram();
- _connectionValidated = true; // TODO: Not finished yet.
+ if(_adapter != null)
+ {
+ //
+ // Incoming connections play the active role with
+ // respect to connection validation.
+ //
+ _connectionValidated = true;
+ validateConnection();
+ }
+ else
+ {
+ //
+ // Outgoing connections are passive with respect to
+ // validation, i.e., they wait until they get a
+ // validate connection message from the server.
+ //
+ _connectionValidated = false;
+ }
}
-
}
protected void
@@ -908,6 +956,17 @@ public final class Connection extends EventHandler
}
private void
+ validateConnection()
+ {
+ BasicStream os = new BasicStream(_instance);
+ os.writeByte(Protocol.protocolVersion);
+ os.writeByte(Protocol.encodingVersion);
+ os.writeByte(Protocol.validateConnectionMsg);
+ os.writeInt(Protocol.headerSize); // Message size.
+ _transceiver.write(os, _endpoint.timeout());
+ }
+
+ private void
closeConnection()
{
BasicStream os = new BasicStream(_instance);
@@ -916,6 +975,11 @@ public final class Connection extends EventHandler
os.writeByte(Protocol.closeConnectionMsg);
os.writeInt(Protocol.headerSize); // Message size.
_transceiver.write(os, _endpoint.timeout());
+
+ //
+ // A close connection is always followed by a connection
+ // shutdown.
+ //
_transceiver.shutdown();
}
diff --git a/java/src/IceInternal/IncomingConnectionFactory.java b/java/src/IceInternal/IncomingConnectionFactory.java
index f1f27db86c1..83538c6f09a 100644
--- a/java/src/IceInternal/IncomingConnectionFactory.java
+++ b/java/src/IceInternal/IncomingConnectionFactory.java
@@ -145,6 +145,11 @@ public class IncomingConnectionFactory extends EventHandler
}
else if(_state == StateClosed)
{
+//
+// With the new connection validation, this code is not needed
+// anymore.
+//
+/*
try
{
//
@@ -172,6 +177,7 @@ public class IncomingConnectionFactory extends EventHandler
warning(ex);
}
}
+*/
_acceptor.close();
diff --git a/java/src/IceInternal/Protocol.java b/java/src/IceInternal/Protocol.java
index 1b34b22840c..fa6cc04575d 100644
--- a/java/src/IceInternal/Protocol.java
+++ b/java/src/IceInternal/Protocol.java
@@ -34,8 +34,9 @@ final class Protocol
final static byte requestMsg = 0;
final static byte requestBatchMsg = 1;
final static byte replyMsg = 2;
- final static byte closeConnectionMsg = 3;
- final static byte compressedRequestMsg = 4;
- final static byte compressedRequestBatchMsg = 5;
- final static byte compressedReplyMsg = 6;
+ final static byte validateConnectionMsg = 3;
+ final static byte closeConnectionMsg = 4;
+ final static byte compressedRequestMsg = 5;
+ final static byte compressedRequestBatchMsg = 6;
+ final static byte compressedReplyMsg = 7;
}
diff --git a/java/src/IceInternal/TraceUtil.java b/java/src/IceInternal/TraceUtil.java
index 71e94e582bd..d40b2fa2bfa 100644
--- a/java/src/IceInternal/TraceUtil.java
+++ b/java/src/IceInternal/TraceUtil.java
@@ -236,6 +236,11 @@ final class TraceUtil
out.write("(close connection)");
break;
}
+ case Protocol.validateConnectionMsg:
+ {
+ out.write("(validate connection)");
+ break;
+ }
default:
{
out.write("(unknown)");