public override void message(ref IceInternal.ThreadPoolCurrent current) { StartCallback startCB = null; Queue<OutgoingMessage> sentCBs = null; MessageInfo info = new MessageInfo(); int dispatchCount = 0; IceInternal.ThreadPoolMessage msg = new IceInternal.ThreadPoolMessage(this); try { lock(this) { if(!msg.startIOScope(ref current)) { return; } if(_state >= StateClosed) { return; } int readyOp = current.operation; try { unscheduleTimeout(current.operation); int writeOp = IceInternal.SocketOperation.None; int readOp = IceInternal.SocketOperation.None; if((readyOp & IceInternal.SocketOperation.Write) != 0) { if(_observer != null) { observerStartWrite(_writeStream.getBuffer()); } writeOp = write(_writeStream.getBuffer()); if(_observer != null && (writeOp & IceInternal.SocketOperation.Write) == 0) { observerFinishWrite(_writeStream.getBuffer()); } } while((readyOp & IceInternal.SocketOperation.Read) != 0) { IceInternal.Buffer buf = _readStream.getBuffer(); if(_observer != null && !_readHeader) { observerStartRead(buf); } readOp = read(buf); if((readOp & IceInternal.SocketOperation.Read) != 0) { break; } if(_observer != null && !_readHeader) { Debug.Assert(!buf.b.hasRemaining()); observerFinishRead(buf); } if(_readHeader) // Read header if necessary. { _readHeader = false; if(_observer != null) { _observer.receivedBytes(IceInternal.Protocol.headerSize); } int pos = _readStream.pos(); if(pos < IceInternal.Protocol.headerSize) { // // This situation is possible for small UDP packets. // throw new Ice.IllegalMessageSizeException(); } _readStream.pos(0); byte[] m = new byte[4]; m[0] = _readStream.readByte(); m[1] = _readStream.readByte(); m[2] = _readStream.readByte(); m[3] = _readStream.readByte(); if(m[0] != IceInternal.Protocol.magic[0] || m[1] != IceInternal.Protocol.magic[1] || m[2] != IceInternal.Protocol.magic[2] || m[3] != IceInternal.Protocol.magic[3]) { Ice.BadMagicException ex = new Ice.BadMagicException(); ex.badMagic = m; throw ex; } ProtocolVersion pv = new ProtocolVersion(); pv.read__(_readStream); IceInternal.Protocol.checkSupportedProtocol(pv); EncodingVersion ev = new EncodingVersion(); ev.read__(_readStream); IceInternal.Protocol.checkSupportedProtocolEncoding(ev); _readStream.readByte(); // messageType _readStream.readByte(); // compress int size = _readStream.readInt(); if(size < IceInternal.Protocol.headerSize) { throw new Ice.IllegalMessageSizeException(); } if(size > _messageSizeMax) { IceInternal.Ex.throwMemoryLimitException(size, _messageSizeMax); } if(size > _readStream.size()) { _readStream.resize(size, true); } _readStream.pos(pos); } if(buf.b.hasRemaining()) { if(_endpoint.datagram()) { throw new Ice.DatagramLimitException(); // The message was truncated. } continue; } break; } int newOp = readOp | writeOp; readyOp &= ~newOp; Debug.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; } _threadPool.unregister(this, current.operation); // // We start out in holding state. // setState(StateHolding); if(_startCallback != null) { startCB = _startCallback; _startCallback = null; if(startCB != null) { ++dispatchCount; } } } else { Debug.Assert(_state <= StateClosingPending); // // We parse messages first, if we receive a close // connection message we won't send more messages. // if((readyOp & IceInternal.SocketOperation.Read) != 0) { newOp |= parseMessage(ref info); dispatchCount += info.messageDispatchCount; } if((readyOp & IceInternal.SocketOperation.Write) != 0) { newOp |= sendNextMessage(out sentCBs); if(sentCBs != null) { ++dispatchCount; } } if(_state < StateClosed) { scheduleTimeout(newOp); _threadPool.update(this, current.operation, newOp); } } if(_acmLastActivity > -1) { _acmLastActivity = IceInternal.Time.currentMonotonicTimeMillis(); } if(dispatchCount == 0) { return; // Nothing to dispatch we're done! } _dispatchCount += dispatchCount; msg.completed(ref current); } catch(DatagramLimitException) // Expected. { if(_warnUdp) { _logger.warning("maximum datagram size of " + _readStream.pos() + " exceeded"); } _readStream.resize(IceInternal.Protocol.headerSize, true); _readStream.pos(0); _readHeader = true; return; } catch(SocketException ex) { setState(StateClosed, ex); return; } catch(LocalException ex) { if(_endpoint.datagram()) { if(_warn) { String s = "datagram connection exception:\n" + ex + '\n' + _desc; _logger.warning(s); } _readStream.resize(IceInternal.Protocol.headerSize, true); _readStream.pos(0); _readHeader = true; } else { setState(StateClosed, ex); } return; } IceInternal.ThreadPoolCurrent c = current; _threadPool.dispatch(() => { dispatch(startCB, sentCBs, info); msg.destroy(ref c); }, this); } } finally { msg.finishIOScope(ref current); } }
private bool validate(int operation) { if(!_endpoint.datagram()) // Datagram connections are always implicitly validated. { if(_adapter != null) // The server side has the active role for connection validation. { if(_writeStream.size() == 0) { _writeStream.writeBlob(IceInternal.Protocol.magic); Ice.Util.currentProtocol.write__(_writeStream); Ice.Util.currentProtocolEncoding.write__(_writeStream); _writeStream.writeByte(IceInternal.Protocol.validateConnectionMsg); _writeStream.writeByte((byte)0); // Compression status (always zero for validate connection). _writeStream.writeInt(IceInternal.Protocol.headerSize); // Message size. IceInternal.TraceUtil.traceSend(_writeStream, _logger, _traceLevels); _writeStream.prepareWrite(); } if(_observer != null) { observerStartWrite(_writeStream.pos()); } if(_writeStream.pos() != _writeStream.size() && !_transceiver.write(_writeStream.getBuffer())) { scheduleTimeout(IceInternal.SocketOperation.Write, connectTimeout()); _threadPool.update(this, operation, IceInternal.SocketOperation.Write); return false; } if(_observer != null) { observerFinishWrite(_writeStream.pos()); } } else // The client side has the passive role for connection validation. { if(_readStream.size() == 0) { _readStream.resize(IceInternal.Protocol.headerSize, true); _readStream.pos(0); } if(_observer != null) { observerStartRead(_readStream.pos()); } if(_readStream.pos() != _readStream.size() && !_transceiver.read(_readStream.getBuffer())) { scheduleTimeout(IceInternal.SocketOperation.Read, connectTimeout()); _threadPool.update(this, operation, IceInternal.SocketOperation.Read); return false; } if(_observer != null) { observerFinishRead(_readStream.pos()); } Debug.Assert(_readStream.pos() == IceInternal.Protocol.headerSize); _readStream.pos(0); byte[] m = _readStream.readBlob(4); if(m[0] != IceInternal.Protocol.magic[0] || m[1] != IceInternal.Protocol.magic[1] || m[2] != IceInternal.Protocol.magic[2] || m[3] != IceInternal.Protocol.magic[3]) { BadMagicException ex = new BadMagicException(); ex.badMagic = m; throw ex; } ProtocolVersion pv = new ProtocolVersion(); pv.read__(_readStream); IceInternal.Protocol.checkSupportedProtocol(pv); EncodingVersion ev = new EncodingVersion(); ev.read__(_readStream); IceInternal.Protocol.checkSupportedProtocolEncoding(ev); byte messageType = _readStream.readByte(); if(messageType != IceInternal.Protocol.validateConnectionMsg) { throw new ConnectionNotValidatedException(); } _readStream.readByte(); // Ignore compression status for validate connection. int size = _readStream.readInt(); if(size != IceInternal.Protocol.headerSize) { throw new IllegalMessageSizeException(); } IceInternal.TraceUtil.traceRecv(_readStream, _logger, _traceLevels); _validated = true; } } _writeStream.resize(0, false); _writeStream.pos(0); _readStream.resize(IceInternal.Protocol.headerSize, true); _readStream.pos(0); _readHeader = true; return true; }
private bool validate(int operation) { if(!_endpoint.datagram()) // Datagram connections are always implicitly validated. { if(_adapter != null) // The server side has the active role for connection validation. { if(_writeStream.size() == 0) { _writeStream.writeBlob(IceInternal.Protocol.magic); Ice.Util.currentProtocol.write__(_writeStream); Ice.Util.currentProtocolEncoding.write__(_writeStream); _writeStream.writeByte(IceInternal.Protocol.validateConnectionMsg); _writeStream.writeByte((byte)0); // Compression status (always zero for validate connection). _writeStream.writeInt(IceInternal.Protocol.headerSize); // Message size. IceInternal.TraceUtil.traceSend(_writeStream, _logger, _traceLevels); _writeStream.prepareWrite(); } if(_observer != null) { observerStartWrite(_writeStream.getBuffer()); } if(_writeStream.pos() != _writeStream.size()) { int op = write(_writeStream.getBuffer()); if(op != 0) { scheduleTimeout(op); _threadPool.update(this, operation, op); return false; } } if(_observer != null) { observerFinishWrite(_writeStream.getBuffer()); } } else // The client side has the passive role for connection validation. { if(_readStream.size() == 0) { _readStream.resize(IceInternal.Protocol.headerSize, true); _readStream.pos(0); } if(_observer != null) { observerStartRead(_readStream.getBuffer()); } if(_readStream.pos() != _readStream.size()) { int op = read(_readStream.getBuffer()); if(op != 0) { scheduleTimeout(op); _threadPool.update(this, operation, op); return false; } } if(_observer != null) { observerFinishRead(_readStream.getBuffer()); } Debug.Assert(_readStream.pos() == IceInternal.Protocol.headerSize); _readStream.pos(0); byte[] m = _readStream.readBlob(4); if(m[0] != IceInternal.Protocol.magic[0] || m[1] != IceInternal.Protocol.magic[1] || m[2] != IceInternal.Protocol.magic[2] || m[3] != IceInternal.Protocol.magic[3]) { BadMagicException ex = new BadMagicException(); ex.badMagic = m; throw ex; } ProtocolVersion pv = new ProtocolVersion(); pv.read__(_readStream); IceInternal.Protocol.checkSupportedProtocol(pv); EncodingVersion ev = new EncodingVersion(); ev.read__(_readStream); IceInternal.Protocol.checkSupportedProtocolEncoding(ev); byte messageType = _readStream.readByte(); if(messageType != IceInternal.Protocol.validateConnectionMsg) { throw new ConnectionNotValidatedException(); } _readStream.readByte(); // Ignore compression status for validate connection. int size = _readStream.readInt(); if(size != IceInternal.Protocol.headerSize) { throw new IllegalMessageSizeException(); } IceInternal.TraceUtil.traceRecv(_readStream, _logger, _traceLevels); _validated = true; } } _writeStream.resize(0, false); _writeStream.pos(0); _readStream.resize(IceInternal.Protocol.headerSize, true); _readStream.pos(0); _readHeader = true; if(_instance.traceLevels().network >= 1) { StringBuilder s = new StringBuilder(); if(_endpoint.datagram()) { s.Append("starting to "); s.Append(_connector != null ? "send" : "receive"); s.Append(" "); s.Append(_endpoint.protocol()); s.Append(" messages\n"); s.Append(_transceiver.toDetailedString()); } else { s.Append(_connector != null ? "established" : "accepted"); s.Append(" "); s.Append(_endpoint.protocol()); s.Append(" connection\n"); s.Append(ToString()); } _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.ToString()); } return true; }
public override void message(ref IceInternal.ThreadPoolCurrent current) { StartCallback startCB = null; Queue<OutgoingMessage> sentCBs = null; MessageInfo info = new MessageInfo(); IceInternal.ThreadPoolMessage msg = new IceInternal.ThreadPoolMessage(_m); _m.Lock(); try { if(!msg.startIOScope(ref current)) { return; } if(_state >= StateClosed) { return; } try { unscheduleTimeout(current.operation); if((current.operation & IceInternal.SocketOperation.Write) != 0 && !_writeStream.isEmpty()) { if(_observer != null) { observerStartWrite(_writeStream.pos()); } if(_writeStream.getBuffer().b.hasRemaining() && !_transceiver.write(_writeStream.getBuffer())) { Debug.Assert(!_writeStream.isEmpty()); scheduleTimeout(IceInternal.SocketOperation.Write, _endpoint.timeout()); return; } if(_observer != null) { observerFinishWrite(_writeStream.pos()); } Debug.Assert(!_writeStream.getBuffer().b.hasRemaining()); } if((current.operation & IceInternal.SocketOperation.Read) != 0 && !_readStream.isEmpty()) { if(_readHeader) // Read header if necessary. { if(_readStream.getBuffer().b.hasRemaining() && !_transceiver.read(_readStream.getBuffer())) { return; } Debug.Assert(!_readStream.getBuffer().b.hasRemaining()); _readHeader = false; if(_observer != null) { _observer.receivedBytes(IceInternal.Protocol.headerSize); } int pos = _readStream.pos(); if(pos < IceInternal.Protocol.headerSize) { // // This situation is possible for small UDP packets. // throw new Ice.IllegalMessageSizeException(); } _readStream.pos(0); byte[] m = new byte[4]; m[0] = _readStream.readByte(); m[1] = _readStream.readByte(); m[2] = _readStream.readByte(); m[3] = _readStream.readByte(); if(m[0] != IceInternal.Protocol.magic[0] || m[1] != IceInternal.Protocol.magic[1] || m[2] != IceInternal.Protocol.magic[2] || m[3] != IceInternal.Protocol.magic[3]) { Ice.BadMagicException ex = new Ice.BadMagicException(); ex.badMagic = m; throw ex; } ProtocolVersion pv = new ProtocolVersion(); pv.read__(_readStream); IceInternal.Protocol.checkSupportedProtocol(pv); EncodingVersion ev = new EncodingVersion(); ev.read__(_readStream); IceInternal.Protocol.checkSupportedProtocolEncoding(ev); _readStream.readByte(); // messageType _readStream.readByte(); // compress int size = _readStream.readInt(); if(size < IceInternal.Protocol.headerSize) { throw new Ice.IllegalMessageSizeException(); } if(size > _instance.messageSizeMax()) { IceInternal.Ex.throwMemoryLimitException(size, _instance.messageSizeMax()); } if(size > _readStream.size()) { _readStream.resize(size, true); } _readStream.pos(pos); } if(_readStream.getBuffer().b.hasRemaining()) { if(_endpoint.datagram()) { throw new Ice.DatagramLimitException(); // The message was truncated. } else { if(_observer != null) { observerStartRead(_readStream.pos()); } if(!_transceiver.read(_readStream.getBuffer())) { Debug.Assert(!_readStream.isEmpty()); scheduleTimeout(IceInternal.SocketOperation.Read, _endpoint.timeout()); return; } if(_observer != null) { observerFinishRead(_readStream.pos()); } Debug.Assert(!_readStream.getBuffer().b.hasRemaining()); } } } if(_state <= StateNotValidated) { if(_state == StateNotInitialized && !initialize(current.operation)) { return; } if(_state <= StateNotValidated && !validate(current.operation)) { return; } _threadPool.unregister(this, current.operation); // // We start out in holding state. // setState(StateHolding); startCB = _startCallback; _startCallback = null; } else { Debug.Assert(_state <= StateClosing); // // We parse messages first, if we receive a close // connection message we won't send more messages. // if((current.operation & IceInternal.SocketOperation.Read) != 0) { parseMessage(ref info); } if((current.operation & IceInternal.SocketOperation.Write) != 0) { sentCBs = sendNextMessage(); } } // // We increment the dispatch count to prevent the // communicator destruction during the callback. // if(sentCBs != null || info.outAsync != null) { ++_dispatchCount; } if(_acmTimeout > 0) { _acmAbsoluteTimeoutMillis = IceInternal.Time.currentMonotonicTimeMillis() + _acmTimeout * 1000; } if(startCB == null && sentCBs == null && info.invokeNum == 0 && info.outAsync == null) { return; // Nothing to dispatch. } msg.completed(ref current); } catch(DatagramLimitException) // Expected. { if(_warnUdp) { _logger.warning("maximum datagram size of " + _readStream.pos() + " exceeded"); } _readStream.resize(IceInternal.Protocol.headerSize, true); _readStream.pos(0); _readHeader = true; return; } catch(SocketException ex) { setState(StateClosed, ex); return; } catch(LocalException ex) { if(_endpoint.datagram()) { if(_warn) { String s = "datagram connection exception:\n" + ex + '\n' + _desc; _logger.warning(s); } _readStream.resize(IceInternal.Protocol.headerSize, true); _readStream.pos(0); _readHeader = true; } else { setState(StateClosed, ex); } return; } finally { msg.finishIOScope(ref current); } // // Unlike C++/Java, this method is called from an IO thread of the .NET thread // pool or from the communicator async IO thread. While it's fine to handle the // non-blocking activity of the connection from these threads, the dispatching // of the message must be taken care of by the Ice thread pool. // IceInternal.ThreadPoolCurrent c = current; _threadPool.execute( delegate() { if(_dispatcher != null) { try { _dispatcher(delegate() { dispatch(startCB, sentCBs, info); }, this); } catch(System.Exception ex) { if(_instance.initializationData().properties.getPropertyAsIntWithDefault( "Ice.Warn.Dispatch", 1) > 1) { warning("dispatch exception", ex); } } } else { dispatch(startCB, sentCBs, info); } msg.destroy(ref c); }); } finally { _m.Unlock(); } }