summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2014-11-13 11:47:10 +0100
committerBenoit Foucher <benoit@zeroc.com>2014-11-13 11:47:10 +0100
commit9cb2519efe1c9e56c25f2dcdcdb8aaa26ddf2969 (patch)
treefb419cfcaab0d8aff7ef211db4a6eddbac31f8d0
parentremove timeout.jar from git (diff)
downloadice-9cb2519efe1c9e56c25f2dcdcdb8aaa26ddf2969.tar.bz2
ice-9cb2519efe1c9e56c25f2dcdcdb8aaa26ddf2969.tar.xz
ice-9cb2519efe1c9e56c25f2dcdcdb8aaa26ddf2969.zip
Fixed ICE-5852: added support for WS continuation frames
-rw-r--r--cpp/src/Ice/ConnectionI.cpp14
-rw-r--r--cpp/src/Ice/WSTransceiver.cpp44
-rw-r--r--cpp/src/Ice/WSTransceiver.h1
-rw-r--r--cs/src/Ice/ConnectionI.cs14
-rw-r--r--cs/src/Ice/WSTransceiver.cs64
-rw-r--r--java/src/Ice/src/main/java/Ice/ConnectionI.java13
-rw-r--r--java/src/Ice/src/main/java/IceInternal/WSTransceiver.java52
-rw-r--r--js/src/Ice/ConnectionI.js24
8 files changed, 166 insertions, 60 deletions
diff --git a/cpp/src/Ice/ConnectionI.cpp b/cpp/src/Ice/ConnectionI.cpp
index 2a3077aa7b8..ae7f9d37c36 100644
--- a/cpp/src/Ice/ConnectionI.cpp
+++ b/cpp/src/Ice/ConnectionI.cpp
@@ -2174,7 +2174,7 @@ Ice::ConnectionI::finish(bool close)
{
string verb = _connector ? "establish" : "accept";
Trace out(_instance->initializationData().logger, _instance->traceLevels()->networkCat);
- out << "failed to " << verb << " " << _endpoint->protocol() << " connection\n" << toString()
+ out << "failed to " << verb << " " << _endpoint->protocol() << " connection\n" << toString()
<< "\n" << *_exception.get();
}
}
@@ -2184,6 +2184,18 @@ Ice::ConnectionI::finish(bool close)
{
Trace out(_instance->initializationData().logger, _instance->traceLevels()->networkCat);
out << "closed " << _endpoint->protocol() << " connection\n" << toString();
+
+ //
+ // Trace the cause of unexpected connection closures
+ //
+ if(!(dynamic_cast<const CloseConnectionException*>(_exception.get()) ||
+ dynamic_cast<const ForcedCloseConnectionException*>(_exception.get()) ||
+ dynamic_cast<const ConnectionTimeoutException*>(_exception.get()) ||
+ dynamic_cast<const CommunicatorDestroyedException*>(_exception.get()) ||
+ dynamic_cast<const ObjectAdapterDeactivatedException*>(_exception.get())))
+ {
+ out << "\n" << *_exception.get();
+ }
}
}
diff --git a/cpp/src/Ice/WSTransceiver.cpp b/cpp/src/Ice/WSTransceiver.cpp
index 2e97aa219b4..3f5c3a83f43 100644
--- a/cpp/src/Ice/WSTransceiver.cpp
+++ b/cpp/src/Ice/WSTransceiver.cpp
@@ -579,7 +579,6 @@ IceInternal::WSTransceiver::read(Buffer& buf, bool& hasMoreData)
{
s = _delegate->read(buf, hasMoreData);
}
-
}
else
{
@@ -817,7 +816,7 @@ IceInternal::WSTransceiver::WSTransceiver(const ProtocolInstancePtr& instance, c
_parser(new HttpParser),
_readState(ReadStateOpcode),
_readBufferSize(1024),
- _readLastFrame(false),
+ _readLastFrame(true),
_readOpCode(0),
_readHeaderLength(0),
_readPayloadLength(0),
@@ -851,7 +850,7 @@ IceInternal::WSTransceiver::WSTransceiver(const ProtocolInstancePtr& instance, c
_parser(new HttpParser),
_readState(ReadStateOpcode),
_readBufferSize(1024),
- _readLastFrame(false),
+ _readLastFrame(true),
_readOpCode(0),
_readHeaderLength(0),
_readPayloadLength(0),
@@ -1119,9 +1118,30 @@ IceInternal::WSTransceiver::preRead(Buffer& buf)
// opcode.
//
unsigned char ch = static_cast<unsigned char>(*_readI++);
- _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
_readOpCode = ch & 0xf;
+ //
+ // Remember if last frame if we're going to read a data or
+ // continuation frame, this is only for protocol
+ // correctness checking purpose.
+ //
+ if(_readOpCode == OP_DATA)
+ {
+ if(!_readLastFrame)
+ {
+ throw ProtocolException(__FILE__, __LINE__, "invalid data frame, no FIN on previous frame");
+ }
+ _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
+ }
+ else if(_readOpCode == OP_CONT)
+ {
+ if(_readLastFrame)
+ {
+ throw ProtocolException(__FILE__, __LINE__, "invalid continuation frame, previous frame FIN set");
+ }
+ _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
+ }
+
ch = static_cast<unsigned char>(*_readI++);
//
@@ -1203,33 +1223,27 @@ IceInternal::WSTransceiver::preRead(Buffer& buf)
switch(_readOpCode)
{
- case OP_CONT: // Continuation frame
- {
- // TODO: Add support for continuation frames?
- throw ProtocolException(__FILE__, __LINE__, "continuation frames not supported");
- }
case OP_TEXT: // Text frame
{
throw ProtocolException(__FILE__, __LINE__, "text frames not supported");
}
case OP_DATA: // Data frame
+ case OP_CONT: // Continuation frame
{
if(_instance->traceLevel() >= 2)
{
Trace out(_instance->logger(), _instance->traceCategory());
- out << "received " << protocol() << " data frame with payload length of " << _readPayloadLength;
+ out << "received " << protocol() << (_readOpCode == OP_DATA ? " data" : " continuation");
+ out << " frame with payload length of " << _readPayloadLength;
out << " bytes\n" << toString();
}
- if(!_readLastFrame)
- {
- throw ProtocolException(__FILE__, __LINE__, "continuation frames not supported");
- }
if(_readPayloadLength <= 0)
{
throw ProtocolException(__FILE__, __LINE__, "payload length is 0");
}
_readState = ReadStatePayload;
+ _readFrameStart = buf.i;
break;
}
case OP_CLOSE: // Connection close
@@ -1384,7 +1398,7 @@ IceInternal::WSTransceiver::postRead(Buffer& buf)
// Unmask the data we just read.
//
IceInternal::Buffer::Container::iterator p = _readStart;
- for(size_t n = _readStart - buf.b.begin(); p < buf.i; ++p, ++n)
+ for(size_t n = _readStart - _readFrameStart; p < buf.i; ++p, ++n)
{
*p ^= _readMask[n % 4];
}
diff --git a/cpp/src/Ice/WSTransceiver.h b/cpp/src/Ice/WSTransceiver.h
index c67ac7721d6..0a2a7dbc93d 100644
--- a/cpp/src/Ice/WSTransceiver.h
+++ b/cpp/src/Ice/WSTransceiver.h
@@ -118,6 +118,7 @@ private:
size_t _readHeaderLength;
size_t _readPayloadLength;
Buffer::Container::iterator _readStart;
+ Buffer::Container::iterator _readFrameStart;
unsigned char _readMask[4];
enum WriteState
diff --git a/cs/src/Ice/ConnectionI.cs b/cs/src/Ice/ConnectionI.cs
index 5a5b02bd6ed..938898e7528 100644
--- a/cs/src/Ice/ConnectionI.cs
+++ b/cs/src/Ice/ConnectionI.cs
@@ -1585,6 +1585,20 @@ namespace Ice
s.Append(_endpoint.protocol());
s.Append(" connection\n");
s.Append(ToString());
+
+ //
+ // Trace the cause of unexpected connection closures
+ //
+ if(!(_exception is CloseConnectionException ||
+ _exception is ForcedCloseConnectionException ||
+ _exception is ConnectionTimeoutException ||
+ _exception is CommunicatorDestroyedException ||
+ _exception is ObjectAdapterDeactivatedException))
+ {
+ s.Append("\n");
+ s.Append(_exception);
+ }
+
_instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.ToString());
}
}
diff --git a/cs/src/Ice/WSTransceiver.cs b/cs/src/Ice/WSTransceiver.cs
index 76883b4d898..07dbdfe8d75 100644
--- a/cs/src/Ice/WSTransceiver.cs
+++ b/cs/src/Ice/WSTransceiver.cs
@@ -418,7 +418,7 @@ namespace IceInternal
if(buf.b.remaining() > readSz)
{
int size = buf.size();
- buf.resize(readSz, true);
+ buf.resize(buf.b.position() + readSz, true);
s = _delegate.read(buf, ref hasMoreData);
buf.resize(size, true);
}
@@ -440,10 +440,17 @@ namespace IceInternal
}
}
while(postRead(buf));
-
- hasMoreData |= _readBufferPos < _readBuffer.b.position();
-
- s = !buf.b.hasRemaining() ? IceInternal.SocketOperation.None : IceInternal.SocketOperation.Read;
+
+ if(!buf.b.hasRemaining())
+ {
+ hasMoreData |= _readBufferPos < _readBuffer.b.position();
+ s = SocketOperation.None;
+ }
+ else
+ {
+ hasMoreData = false;
+ s = SocketOperation.Read;
+ }
if(((_state == StateClosingRequestPending && !_closingInitiator) ||
(_state == StateClosingResponsePending && _closingInitiator) ||
@@ -691,7 +698,7 @@ namespace IceInternal
_readState = ReadStateOpcode;
_readBuffer = new IceInternal.Buffer(IceInternal.ByteBuffer.ByteOrder.BIG_ENDIAN); // Network byte order
_readBufferSize = 1024;
- _readLastFrame = false;
+ _readLastFrame = true;
_readOpCode = 0;
_readHeaderLength = 0;
_readPayloadLength = 0;
@@ -968,9 +975,30 @@ namespace IceInternal
// opcode.
//
int ch = _readBuffer.b.get(_readBufferPos++);
- _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
_readOpCode = ch & 0xf;
+ //
+ // Remember if last frame if we're going to read a data or
+ // continuation frame, this is only for protocol
+ // correctness checking purpose.
+ //
+ if(_readOpCode == OP_DATA)
+ {
+ if(!_readLastFrame)
+ {
+ throw new Ice.ProtocolException("invalid data frame, no FIN on previous frame");
+ }
+ _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
+ }
+ else if(_readOpCode == OP_CONT)
+ {
+ if(_readLastFrame)
+ {
+ throw new Ice.ProtocolException("invalid continuation frame, previous frame FIN set");
+ }
+ _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
+ }
+
ch = _readBuffer.b.get(_readBufferPos++);
//
@@ -1058,34 +1086,27 @@ namespace IceInternal
switch(_readOpCode)
{
- case OP_CONT: // Continuation frame
- {
- // TODO: Add support for continuation frames?
- throw new Ice.ProtocolException("continuation frames not supported");
- }
case OP_TEXT: // Text frame
{
throw new Ice.ProtocolException("text frames not supported");
}
case OP_DATA: // Data frame
+ case OP_CONT: // Continuation frame
{
if(_instance.traceLevel() >= 2)
{
- _instance.logger().trace(
- _instance.traceCategory(),
- "received " + protocol() + " data frame with payload length of " + _readPayloadLength +
- " bytes\n" + ToString());
+ _instance.logger().trace(_instance.traceCategory(), "received " + protocol() +
+ (_readOpCode == OP_DATA ? " data" : " continuation") +
+ " frame with payload length of " + _readPayloadLength +
+ " bytes\n" + ToString());
}
- if(!_readLastFrame)
- {
- throw new Ice.ProtocolException("continuation frames not supported");
- }
if(_readPayloadLength <= 0)
{
throw new Ice.ProtocolException("payload length is 0");
}
_readState = ReadStatePayload;
+ _readFrameStart = buf.b.position();
break;
}
case OP_CLOSE: // Connection close
@@ -1240,7 +1261,7 @@ namespace IceInternal
byte[] arr = buf.b.rawBytes();
for(int n = _readStart; n < pos; ++n)
{
- arr[n] = (byte)(arr[n] ^ _readMask[n % 4]);
+ arr[n] = (byte)(arr[n] ^ _readMask[(n - _readFrameStart) % 4]);
}
}
@@ -1600,6 +1621,7 @@ namespace IceInternal
private int _readHeaderLength;
private int _readPayloadLength;
private int _readStart;
+ private int _readFrameStart;
private byte[] _readMask;
private const int WriteStateHeader = 0;
diff --git a/java/src/Ice/src/main/java/Ice/ConnectionI.java b/java/src/Ice/src/main/java/Ice/ConnectionI.java
index 9e465d33e2f..ae274cbc1a6 100644
--- a/java/src/Ice/src/main/java/Ice/ConnectionI.java
+++ b/java/src/Ice/src/main/java/Ice/ConnectionI.java
@@ -1458,6 +1458,19 @@ public final class ConnectionI extends IceInternal.EventHandler
s.append(_endpoint.protocol());
s.append(" connection\n");
s.append(toString());
+
+ //
+ // Trace the cause of unexpected connection closures
+ //
+ if(!(_exception instanceof CloseConnectionException ||
+ _exception instanceof ForcedCloseConnectionException ||
+ _exception instanceof ConnectionTimeoutException ||
+ _exception instanceof CommunicatorDestroyedException ||
+ _exception instanceof ObjectAdapterDeactivatedException))
+ {
+ s.append("\n");
+ s.append(_exception);
+ }
_instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.toString());
}
}
diff --git a/java/src/Ice/src/main/java/IceInternal/WSTransceiver.java b/java/src/Ice/src/main/java/IceInternal/WSTransceiver.java
index 7451d818389..81c29a3916e 100644
--- a/java/src/Ice/src/main/java/IceInternal/WSTransceiver.java
+++ b/java/src/Ice/src/main/java/IceInternal/WSTransceiver.java
@@ -404,7 +404,7 @@ final class WSTransceiver implements Transceiver
if(buf.b.remaining() > readSz)
{
int size = buf.size();
- buf.resize(readSz, true);
+ buf.resize(buf.b.position() + readSz, true);
s = _delegate.read(buf, moreData);
buf.resize(size, true);
}
@@ -534,7 +534,7 @@ final class WSTransceiver implements Transceiver
_readState = ReadStateOpcode;
_readBuffer = new Buffer(false, java.nio.ByteOrder.BIG_ENDIAN); // Use network byte order.
_readBufferSize = 1024;
- _readLastFrame = false;
+ _readLastFrame = true;
_readOpCode = 0;
_readHeaderLength = 0;
_readPayloadLength = 0;
@@ -819,9 +819,30 @@ final class WSTransceiver implements Transceiver
{
ch += 256;
}
- _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
_readOpCode = ch & 0xf;
+ //
+ // Remember if last frame if we're going to read a data or
+ // continuation frame, this is only for protocol
+ // correctness checking purpose.
+ //
+ if(_readOpCode == OP_DATA)
+ {
+ if(!_readLastFrame)
+ {
+ throw new Ice.ProtocolException("invalid data frame, no FIN on previous frame");
+ }
+ _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
+ }
+ else if(_readOpCode == OP_CONT)
+ {
+ if(_readLastFrame)
+ {
+ throw new Ice.ProtocolException("invalid continuation frame, previous frame FIN set");
+ }
+ _readLastFrame = (ch & FLAG_FINAL) == FLAG_FINAL;
+ }
+
ch = _readBuffer.b.get(_readBufferPos++);
if(ch < 0)
{
@@ -910,34 +931,27 @@ final class WSTransceiver implements Transceiver
switch(_readOpCode)
{
- case OP_CONT: // Continuation frame
- {
- // TODO: Add support for continuation frames?
- throw new Ice.ProtocolException("continuation frames not supported");
- }
case OP_TEXT: // Text frame
{
throw new Ice.ProtocolException("text frames not supported");
}
+ case OP_CONT: // Continuation frame
case OP_DATA: // Data frame
{
if(_instance.traceLevel() >= 2)
{
- _instance.logger().trace(
- _instance.traceCategory(),
- "received " + protocol() + " data frame with payload length of " + _readPayloadLength +
- " bytes\n" + toString());
+ _instance.logger().trace(_instance.traceCategory(), "received " + protocol() +
+ (_readOpCode == OP_DATA ? " data" : " continuation") +
+ " frame with payload length of " + _readPayloadLength + " bytes\n" +
+ toString());
}
- if(!_readLastFrame)
- {
- throw new Ice.ProtocolException("continuation frames not supported");
- }
if(_readPayloadLength <= 0)
{
throw new Ice.ProtocolException("payload length is 0");
}
_readState = ReadStatePayload;
+ _readFrameStart = buf.b.position();
break;
}
case OP_CLOSE: // Connection close
@@ -1111,16 +1125,17 @@ final class WSTransceiver implements Transceiver
if(buf.b.hasArray())
{
byte[] arr = buf.b.array();
+ int offset = buf.b.arrayOffset();
for(int n = _readStart; n < pos; ++n)
{
- arr[n] = (byte)(arr[n] ^ _readMask[n % 4]);
+ arr[n + offset] = (byte)(arr[n + offset] ^ _readMask[(n - _readFrameStart) % 4]);
}
}
else
{
for(int n = _readStart; n < pos; ++n)
{
- final byte b = (byte)(buf.b.get(n) ^ _readMask[n % 4]);
+ final byte b = (byte)(buf.b.get(n) ^ _readMask[(n - _readFrameStart) % 4]);
buf.b.put(n, b);
}
}
@@ -1495,6 +1510,7 @@ final class WSTransceiver implements Transceiver
private int _readHeaderLength;
private int _readPayloadLength;
private int _readStart;
+ private int _readFrameStart;
private byte[] _readMask;
private static final int WriteStateHeader = 0;
diff --git a/js/src/Ice/ConnectionI.js b/js/src/Ice/ConnectionI.js
index e98c9d2c4c6..6f6a5d14320 100644
--- a/js/src/Ice/ConnectionI.js
+++ b/js/src/Ice/ConnectionI.js
@@ -1230,6 +1230,20 @@ var ConnectionI = Class({
s.push(this._endpoint.protocol());
s.push(" connection\n");
s.push(this.toString());
+
+ //
+ // Trace the cause of unexpected connection closures
+ //
+ if(!(this._exception instanceof CloseConnectionException ||
+ this._exception instanceof ForcedCloseConnectionException ||
+ this._exception instanceof ConnectionTimeoutException ||
+ this._exception instanceof CommunicatorDestroyedException ||
+ this._exception instanceof ObjectAdapterDeactivatedException))
+ {
+ s.push("\n");
+ s.push(this._exception.toString());
+ }
+
this._instance.initializationData().logger.trace(traceLevels.networkCat, s.join(""));
}
}
@@ -1395,11 +1409,11 @@ var ConnectionI = Class({
// Don't warn about certain expected exceptions.
//
if(!(this._exception instanceof Ice.CloseConnectionException ||
- this._exception instanceof Ice.ForcedCloseConnectionException ||
- this._exception instanceof Ice.ConnectionTimeoutException ||
- this._exception instanceof Ice.CommunicatorDestroyedException ||
- this._exception instanceof Ice.ObjectAdapterDeactivatedException ||
- (this._exception instanceof Ice.ConnectionLostException && this._state === StateClosing)))
+ this._exception instanceof Ice.ForcedCloseConnectionException ||
+ this._exception instanceof Ice.ConnectionTimeoutException ||
+ this._exception instanceof Ice.CommunicatorDestroyedException ||
+ this._exception instanceof Ice.ObjectAdapterDeactivatedException ||
+ (this._exception instanceof Ice.ConnectionLostException && this._state === StateClosing)))
{
this.warning("connection exception", this._exception);
}