Esempio n. 1
0
        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);
            }

        }
Esempio n. 2
0
        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();
            }
        }