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); } }
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(); } }