diff options
author | Benoit Foucher <benoit@zeroc.com> | 2014-11-13 11:47:10 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2014-11-13 11:47:10 +0100 |
commit | 9cb2519efe1c9e56c25f2dcdcdb8aaa26ddf2969 (patch) | |
tree | fb419cfcaab0d8aff7ef211db4a6eddbac31f8d0 | |
parent | remove timeout.jar from git (diff) | |
download | ice-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.cpp | 14 | ||||
-rw-r--r-- | cpp/src/Ice/WSTransceiver.cpp | 44 | ||||
-rw-r--r-- | cpp/src/Ice/WSTransceiver.h | 1 | ||||
-rw-r--r-- | cs/src/Ice/ConnectionI.cs | 14 | ||||
-rw-r--r-- | cs/src/Ice/WSTransceiver.cs | 64 | ||||
-rw-r--r-- | java/src/Ice/src/main/java/Ice/ConnectionI.java | 13 | ||||
-rw-r--r-- | java/src/Ice/src/main/java/IceInternal/WSTransceiver.java | 52 | ||||
-rw-r--r-- | js/src/Ice/ConnectionI.js | 24 |
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); } |