Exemple #1
0
        public static Buffer?Compress(Buffer buf, int headerSize, int compressionLevel)
        {
            Debug.Assert(Supported());
            //
            // Compress the message body, but not the header.
            //
            int uncompressedLen = buf.Size() - headerSize;

            byte[] data          = buf.B.RawBytes(headerSize, uncompressedLen);
            int    compressedLen = (int)((uncompressedLen * 1.01) + 600);

            byte[] compressed = new byte[compressedLen];

            int rc = _compressBuffer(compressed, ref compressedLen, data, uncompressedLen, compressionLevel, 0, 0);

            if (rc == BZ_OUTBUFF_FULL)
            {
                return(null);
            }
            else if (rc < 0)
            {
                var ex = new Ice.CompressionException("BZ2_bzBuffToBuffCompress failed");
                ex.Reason = GetBZ2Error(rc);
                throw ex;
            }

            //
            // Don't bother if the compressed data is larger than the
            // uncompressed data.
            //
            if (compressedLen >= uncompressedLen)
            {
                return(null);
            }

            var r = new Buffer();

            r.Resize(headerSize + 4 + compressedLen, false);
            r.B.Position(0);

            //
            // Copy the header from the uncompressed stream to the
            // compressed one.
            //
            r.B.Put(buf.B.RawBytes(0, headerSize));

            //
            // Add the size of the uncompressed stream before the
            // message body.
            //
            r.B.PutInt(buf.Size());

            //
            // Add the compressed message body.
            //
            r.B.Put(compressed, 0, compressedLen);

            return(r);
        }
Exemple #2
0
        public void FinishWrite(Buffer buf)
        {
            Debug.Assert(_writeEventArgs != null);
            if (_fd == null)
            {
                buf.B.Position(buf.Size()); // Assume all the data was sent for at-most-once semantics.
                _writeEventArgs = null;
                return;
            }

            if (!_incoming && _state < StateConnected)
            {
                if (_writeEventArgs.SocketError != SocketError.Success)
                {
                    var ex = new SocketException((int)_writeEventArgs.SocketError);
                    if (Network.ConnectionRefused(ex))
                    {
                        throw new Ice.ConnectionRefusedException(ex);
                    }
                    else
                    {
                        throw new Ice.ConnectFailedException(ex);
                    }
                }
                return;
            }

            int ret;

            try
            {
                if (_writeEventArgs.SocketError != SocketError.Success)
                {
                    throw new SocketException((int)_writeEventArgs.SocketError);
                }
                ret = _writeEventArgs.BytesTransferred;
            }
            catch (SocketException ex)
            {
                if (Network.ConnectionLost(ex))
                {
                    throw new Ice.ConnectionLostException(ex);
                }
                else
                {
                    throw new Ice.SocketException(ex);
                }
            }

            if (ret == 0)
            {
                throw new Ice.ConnectionLostException();
            }

            Debug.Assert(ret > 0);
            Debug.Assert(ret == buf.B.Limit());
            buf.B.Position(buf.B.Position() + ret);
        }
Exemple #3
0
        public void FinishWrite(Buffer buf)
        {
            if (_fd == null) // Transceiver was closed
            {
                if (buf.Size() - buf.B.Position() < _maxSendPacketSize)
                {
                    buf.B.Position(buf.B.Limit()); // Assume all the data was sent for at-most-once semantics.
                }
                return;
            }

            Debug.Assert(_fd != null && _writeEventArgs != null);

            if (_state < StateConnected && _state != StateProxyWrite)
            {
                return;
            }

            try
            {
                if (_writeEventArgs.SocketError != SocketError.Success)
                {
                    throw new SocketException((int)_writeEventArgs.SocketError);
                }
                int ret = _writeEventArgs.BytesTransferred;
                _writeEventArgs.SetBuffer(null, 0, 0);
                if (ret == 0)
                {
                    throw new Ice.ConnectionLostException();
                }

                Debug.Assert(ret > 0);
                buf.B.Position(buf.B.Position() + ret);

                if (_state == StateProxyWrite)
                {
                    Debug.Assert(_proxy != null);
                    _state = ToState(_proxy.EndWrite(buf));
                }
            }
            catch (SocketException ex)
            {
                if (Network.ConnectionLost(ex))
                {
                    throw new Ice.ConnectionLostException(ex);
                }

                throw new Ice.SocketException(ex);
            }
            catch (ObjectDisposedException ex)
            {
                throw new Ice.ConnectionLostException(ex);
            }
        }
Exemple #4
0
        public void CheckSendSize(Buffer buf)
        {
            //
            // The maximum packetSize is either the maximum allowable UDP packet size, or
            // the UDP send buffer size (which ever is smaller).
            //
            int packetSize = Math.Min(MaxPacketSize, _sndSize - UdpOverhead);

            if (packetSize < buf.Size())
            {
                throw new Ice.DatagramLimitException();
            }
        }
Exemple #5
0
        public static Buffer Uncompress(Buffer buf, int headerSize, int messageSizeMax)
        {
            Debug.Assert(Supported());

            buf.B.Position(headerSize);
            int uncompressedSize = buf.B.GetInt();

            if (uncompressedSize <= headerSize)
            {
                throw new Ice.IllegalMessageSizeException("compressed size <= header size");
            }
            if (uncompressedSize > messageSizeMax)
            {
                Ex.ThrowMemoryLimitException(uncompressedSize, messageSizeMax);
            }

            int compressedLen = buf.Size() - headerSize - 4;

            byte[] compressed      = buf.B.RawBytes(headerSize + 4, compressedLen);
            int    uncompressedLen = uncompressedSize - headerSize;

            byte[] uncompressed = new byte[uncompressedLen];
            int    rc           = _decompressBuffer(uncompressed, ref uncompressedLen, compressed, compressedLen, 0, 0);

            if (rc < 0)
            {
                throw new Ice.CompressionException($"BZ2_bzBuffToBuffDecompress failed\n{GetBZ2Error(rc)}");
            }

            var r = new Buffer();

            r.Resize(uncompressedSize, false);

            //
            // Copy the header from the compressed buffer to the uncompressed one.
            //
            r.B.Position(0);
            r.B.Put(buf.B.RawBytes(), 0, headerSize);
            r.B.Put(uncompressed);

            return(r);
        }
Exemple #6
0
        public bool StartWrite(Buffer buf, AsyncCallback callback, object state, out bool completed)
        {
            Debug.Assert(_fd != null);
            Debug.Assert(_writeEventArgs != null);

            if (!_incoming && _state < StateConnected)
            {
                Debug.Assert(_addr != null);
                completed = false;
                if (_sourceAddr != null)
                {
                    _fd.Bind(_sourceAddr);
                }
                _writeEventArgs.UserToken = state;
                return(!_fd.ConnectAsync(_writeEventArgs));
            }

            // The caller is supposed to check the send size before by calling checkSendSize
            Debug.Assert(Math.Min(MaxPacketSize, _sndSize - UdpOverhead) >= buf.Size());

            Debug.Assert(buf.B.Position() == 0);

            bool completedSynchronously;

            try
            {
                _writeCallback = callback;

                if (_state == StateConnected)
                {
                    _writeEventArgs.UserToken = state;
                    _writeEventArgs.SetBuffer(buf.B.RawBytes(), 0, buf.B.Limit());
                    completedSynchronously = !_fd.SendAsync(_writeEventArgs);
                }
                else
                {
                    if (_peerAddr == null)
                    {
                        throw new Ice.SocketException();
                    }
                    _writeEventArgs.RemoteEndPoint = _peerAddr;
                    _writeEventArgs.UserToken      = state;
                    _writeEventArgs.SetBuffer(buf.B.RawBytes(), 0, buf.B.Limit());
                    completedSynchronously = !_fd.SendToAsync(_writeEventArgs);
                }
            }
            catch (SocketException ex)
            {
                if (Network.ConnectionLost(ex))
                {
                    throw new Ice.ConnectionLostException(ex);
                }
                else
                {
                    throw new Ice.SocketException(ex);
                }
            }

            completed = true;
            return(completedSynchronously);
        }
Exemple #7
0
        public void FinishRead(Buffer buf)
        {
            if (_fd == null)
            {
                return;
            }

            int ret;

            try
            {
                if (_readEventArgs.SocketError != SocketError.Success)
                {
                    throw new SocketException((int)_readEventArgs.SocketError);
                }
                ret = _readEventArgs.BytesTransferred;
                // TODO: Workaround for https://github.com/dotnet/corefx/issues/31182
                if (_state != StateConnected &&
                    !(AssemblyUtil.IsMacOS && _fd.AddressFamily == AddressFamily.InterNetworkV6 && _fd.DualMode))
                {
                    _peerAddr = _readEventArgs.RemoteEndPoint;
                }
            }
            catch (SocketException ex)
            {
                if (Network.RecvTruncated(ex))
                {
                    // The message was truncated and the whole buffer is filled. We ignore
                    // this error here, it will be detected at the connection level when
                    // the Ice message size is checked against the buffer size.
                    ret = buf.Size();
                }
                else
                {
                    if (Network.ConnectionLost(ex))
                    {
                        throw new Ice.ConnectionLostException(ex);
                    }

                    if (Network.ConnectionRefused(ex))
                    {
                        throw new Ice.ConnectionRefusedException(ex);
                    }
                    else
                    {
                        throw new Ice.SocketException(ex);
                    }
                }
            }

            if (ret == 0)
            {
                throw new Ice.ConnectionLostException();
            }

            Debug.Assert(ret > 0);

            if (_state == StateNeedConnect)
            {
                Debug.Assert(_incoming);

                //
                // If we must connect, then we connect to the first peer that
                // sends us a packet.
                //
                bool connected = !_fd.ConnectAsync(_readEventArgs);
                Debug.Assert(connected);
                _state = StateConnected; // We're connected now

                if (_instance.TraceLevel >= 1)
                {
                    _instance.Logger.Trace(_instance.TraceCategory, $"connected {Transport()} socket\n{this}");
                }
            }

            buf.Resize(ret, true);
            buf.B.Position(ret);
        }
Exemple #8
0
        public int Read(Buffer buf, ref bool hasMoreData)
        {
            if (!buf.B.HasRemaining())
            {
                return(SocketOperation.None);
            }

            Debug.Assert(buf.B.Position() == 0);
            Debug.Assert(_fd != null);

            int packetSize = Math.Min(MaxPacketSize, _rcvSize - UdpOverhead);

            buf.Resize(packetSize, true);
            buf.B.Position(0);

            int ret;

            while (true)
            {
                try
                {
                    EndPoint?peerAddr = _peerAddr;
                    if (peerAddr == null)
                    {
                        if (_addr.AddressFamily == AddressFamily.InterNetwork)
                        {
                            peerAddr = new IPEndPoint(IPAddress.Any, 0);
                        }
                        else
                        {
                            Debug.Assert(_addr.AddressFamily == AddressFamily.InterNetworkV6);
                            peerAddr = new IPEndPoint(IPAddress.IPv6Any, 0);
                        }
                    }

                    // TODO: Workaround for https://github.com/dotnet/corefx/issues/31182
                    if (_state == StateConnected ||
                        (AssemblyUtil.IsMacOS && _fd.AddressFamily == AddressFamily.InterNetworkV6 && _fd.DualMode))
                    {
                        ret = _fd.Receive(buf.B.RawBytes(), 0, buf.B.Limit(), SocketFlags.None);
                    }
                    else
                    {
                        ret       = _fd.ReceiveFrom(buf.B.RawBytes(), 0, buf.B.Limit(), SocketFlags.None, ref peerAddr);
                        _peerAddr = (IPEndPoint)peerAddr;
                    }
                    break;
                }
                catch (SocketException e)
                {
                    if (Network.RecvTruncated(e))
                    {
                        // The message was truncated and the whole buffer is filled. We ignore
                        // this error here, it will be detected at the connection level when
                        // the Ice message size is checked against the buffer size.
                        ret = buf.Size();
                        break;
                    }

                    if (Network.Interrupted(e))
                    {
                        continue;
                    }

                    if (Network.WouldBlock(e))
                    {
                        return(SocketOperation.Read);
                    }

                    if (Network.ConnectionLost(e))
                    {
                        throw new Ice.ConnectionLostException();
                    }
                    else
                    {
                        throw new Ice.SocketException(e);
                    }
                }
                catch (Exception e)
                {
                    throw new Ice.SyscallException(e);
                }
            }

            if (ret == 0)
            {
                throw new Ice.ConnectionLostException();
            }

            if (_state == StateNeedConnect)
            {
                Debug.Assert(_incoming);

                //
                // If we must connect, then we connect to the first peer that sends us a packet.
                //
                Debug.Assert(_peerAddr != null);
                bool connected = Network.DoConnect(_fd, _peerAddr, null);
                Debug.Assert(connected);
                _state = StateConnected; // We're connected now

                if (_instance.TraceLevel >= 1)
                {
                    _instance.Logger.Trace(_instance.TraceCategory, $"connected {Transport()} socket\n{this}");
                }
            }

            buf.Resize(ret, true);
            buf.B.Position(ret);

            return(SocketOperation.None);
        }
Exemple #9
0
        public int Write(Buffer buf)
        {
            if (!buf.B.HasRemaining())
            {
                return(SocketOperation.None);
            }

            Debug.Assert(buf.B.Position() == 0);
            Debug.Assert(_fd != null && _state >= StateConnected);

            // The caller is supposed to check the send size before by calling checkSendSize
            Debug.Assert(Math.Min(MaxPacketSize, _sndSize - UdpOverhead) >= buf.Size());

            int ret;

            while (true)
            {
                try
                {
                    if (_state == StateConnected)
                    {
                        ret = _fd.Send(buf.B.RawBytes(), 0, buf.Size(), SocketFlags.None);
                    }
                    else
                    {
                        if (_peerAddr == null)
                        {
                            throw new Ice.SocketException();
                        }
                        ret = _fd.SendTo(buf.B.RawBytes(), 0, buf.Size(), SocketFlags.None, _peerAddr);
                    }
                    break;
                }
                catch (SocketException ex)
                {
                    if (Network.Interrupted(ex))
                    {
                        continue;
                    }

                    if (Network.WouldBlock(ex))
                    {
                        return(SocketOperation.Write);
                    }

                    if (Network.ConnectionLost(ex))
                    {
                        throw new Ice.ConnectionLostException(ex);
                    }
                    else
                    {
                        throw new Ice.SocketException(ex);
                    }
                }
                catch (Exception e)
                {
                    throw new Ice.SyscallException(e);
                }
            }

            Debug.Assert(ret > 0);
            Debug.Assert(ret == buf.B.Limit());
            buf.B.Position(buf.B.Limit());
            return(SocketOperation.None);
        }