Пример #1
0
        public void Dispose()
        {
            try
            {
                InUse = false;
                if (socket != null)
                {
                    if (socket.Connected)
                    {
                        socket.Shutdown(SocketShutdown.Both);
                    }
                    socket.Close();
                }

                if (st != null)
                {
                    st.Close();
                    st.Dispose();
                }

                if (PacketPending != null)
                {
                    PacketPending.Dispose();
                }

                BufferStream.Dispose();
            }
            catch (Exception err)
            {
                Node.LogAppendLine(err);
            }
        }
Пример #2
0
        private static Stream GetStream(string url, IWebProxy proxy)
        {
            BufferManager bufferManager = BufferManager.Instance;

            for (int i = 0; i < 10; i++)
            {
                var bufferStream = new BufferStream(bufferManager);

                try
                {
                    var request = (HttpWebRequest)WebRequest.Create(url);
                    request.AllowAutoRedirect = true;
                    request.Proxy             = proxy;
                    request.Headers.Add("Pragma", "no-cache");
                    request.Headers.Add("Cache-Control", "no-cache");
                    request.Timeout          = 1000 * 60 * 5;
                    request.ReadWriteTimeout = 1000 * 60 * 5;

                    using (WebResponse response = request.GetResponse())
                    {
                        if (response.ContentLength > 1024 * 1024 * 32)
                        {
                            throw new Exception("too large");
                        }

                        using (Stream stream = response.GetResponseStream())
                            using (var safeBuffer = bufferManager.CreateSafeBuffer(1024 * 4))
                            {
                                int length;

                                while ((length = stream.Read(safeBuffer.Value, 0, safeBuffer.Value.Length)) > 0)
                                {
                                    bufferStream.Write(safeBuffer.Value, 0, length);

                                    if (bufferStream.Length > 1024 * 1024 * 32)
                                    {
                                        throw new Exception("too large");
                                    }
                                }
                            }

                        if (response.ContentLength != -1 && bufferStream.Length != response.ContentLength)
                        {
                            continue;
                        }

                        bufferStream.Seek(0, SeekOrigin.Begin);
                        return(bufferStream);
                    }
                }
                catch (Exception)
                {
                    bufferStream.Dispose();
                }
            }

            throw new Exception(string.Format("not found: {0}", url));
        }
Пример #3
0
 public void Dispose()
 {
     if (BufferStream != null)
     {
         BufferStream.Dispose();
         BufferStream = null;
     }
     if (BinaryWriter != null)
     {
         BinaryWriter.Close();
         BinaryWriter = null;
     }
     BlockRecycler    = null;
     _readAheadBuffer = null;
     _writeBuffer     = null;
     //_logger = null;
     HeaderData = null;
 }
Пример #4
0
        private Stream GetStream(string url)
        {
            var bufferStream = new BufferStream(_bufferManager);

            try
            {
                using (var client = new HttpClient())
                {
                    using (var stream = client.GetStreamAsync(url).Result)
                    {
                        if (stream.Length > 1024 * 1024 * 32)
                        {
                            throw new Exception("too large");
                        }

                        using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 4))
                        {
                            int length;

                            while ((length = stream.Read(safeBuffer.Value, 0, safeBuffer.Value.Length)) > 0)
                            {
                                bufferStream.Write(safeBuffer.Value, 0, length);

                                if (bufferStream.Length > 1024 * 1024 * 32)
                                {
                                    throw new Exception("too large");
                                }
                            }
                        }

                        bufferStream.Seek(0, SeekOrigin.Begin);
                        return(bufferStream);
                    }
                }
            }
            catch (Exception)
            {
                bufferStream.Dispose();

                throw;
            }
        }
Пример #5
0
        private (int, WaitQueue <ResponseInfo>) Send <TArgument>(AmoebaRequestType type, TArgument argument)
        {
            int id    = this.CreateId();
            var queue = new WaitQueue <ResponseInfo>();

            _queueMap.Add(id, queue);

            using (var writer = new ItemStreamWriter(_bufferManager))
            {
                writer.Write((uint)type);
                writer.Write((uint)id);

                Stream valueStream = null;

                if (argument != null)
                {
                    try
                    {
                        valueStream = new BufferStream(_bufferManager);
                        JsonUtils.Save(valueStream, argument);
                    }
                    catch (Exception)
                    {
                        if (valueStream != null)
                        {
                            valueStream.Dispose();
                            valueStream = null;
                        }

                        throw;
                    }
                }

                _messagingManager.Send(new UniteStream(writer.GetStream(), valueStream));
            }

            return(id, queue);
        }
Пример #6
0
        public override Stream Receive(TimeSpan timeout, Information options)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (!_connect)
            {
                throw new ConnectionException();
            }

            lock (_receiveLock)
            {
                try
                {
                    _receiveStopwatch.Restart();

                    Restart :;

                    int length = 0;

                    {
                        byte[] lengthbuffer = new byte[4];

                        var time = BaseConnection.CheckTimeout(_receiveStopwatch.Elapsed, timeout);
                        time = (time < _receiveTimeSpan) ? time : _receiveTimeSpan;

                        _cap.Receive(lengthbuffer, time);

                        _receivedByteCount.Add(4);

                        length = NetworkConverter.ToInt32(lengthbuffer);
                    }

                    if (length == 0)
                    {
                        Thread.Sleep(100);
                        goto Restart;
                    }
                    else if (length > _maxReceiveCount)
                    {
                        throw new ConnectionException();
                    }

                    BufferStream bufferStream = null;

                    try
                    {
                        bufferStream = new BufferStream(_bufferManager);
                        byte[] receiveBuffer = null;

                        try
                        {
                            receiveBuffer = _bufferManager.TakeBuffer(1024 * 4);

                            do
                            {
                                int receiveLength = Math.Min(receiveBuffer.Length, length);

                                if (_bandwidthLimit != null)
                                {
                                    receiveLength = _bandwidthLimit.GetInBandwidth(this, receiveLength);
                                    if (receiveLength < 0)
                                    {
                                        throw new ConnectionException();
                                    }
                                }

                                var time = BaseConnection.CheckTimeout(_receiveStopwatch.Elapsed, timeout);
                                time = (time < _receiveTimeSpan) ? time : _receiveTimeSpan;

                                _cap.Receive(receiveBuffer, 0, receiveLength, time);

                                _receivedByteCount.Add(receiveLength);
                                bufferStream.Write(receiveBuffer, 0, receiveLength);

                                length -= receiveLength;
                            } while (length > 0);
                        }
                        finally
                        {
                            _bufferManager.ReturnBuffer(receiveBuffer);
                        }
                    }
                    catch (Exception e)
                    {
                        if (bufferStream != null)
                        {
                            bufferStream.Dispose();
                        }

                        throw e;
                    }

                    bufferStream.Seek(0, SeekOrigin.Begin);
                    return(bufferStream);
                }
                catch (ConnectionException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    throw new ConnectionException(e.Message, e);
                }
            }
        }
Пример #7
0
        private static Stream ToStream <T>(ItemBase <T> item)
            where T : ItemBase <T>
        {
            Stream stream = null;

            try
            {
                stream = new RangeStream(item.Export(_bufferManager));

                List <KeyValuePair <byte, Stream> > list = new List <KeyValuePair <byte, Stream> >();

                try
                {
                    stream.Seek(0, SeekOrigin.Begin);

                    BufferStream deflateBufferStream = null;

                    try
                    {
                        deflateBufferStream = new BufferStream(_bufferManager);

                        using (DeflateStream deflateStream = new DeflateStream(deflateBufferStream, CompressionMode.Compress, true))
                        {
                            byte[] compressBuffer = null;

                            try
                            {
                                compressBuffer = _bufferManager.TakeBuffer(1024 * 4);

                                int i = -1;

                                while ((i = stream.Read(compressBuffer, 0, compressBuffer.Length)) > 0)
                                {
                                    deflateStream.Write(compressBuffer, 0, i);
                                }
                            }
                            finally
                            {
                                if (compressBuffer != null)
                                {
                                    _bufferManager.ReturnBuffer(compressBuffer);
                                }
                            }
                        }

                        deflateBufferStream.Seek(0, SeekOrigin.Begin);

                        list.Add(new KeyValuePair <byte, Stream>((byte)ConvertCompressionAlgorithm.Deflate, deflateBufferStream));
                    }
                    catch (Exception)
                    {
                        if (deflateBufferStream != null)
                        {
                            deflateBufferStream.Dispose();
                        }
                    }
                }
                catch (Exception)
                {
                }

                list.Add(new KeyValuePair <byte, Stream>((byte)ConvertCompressionAlgorithm.None, stream));

                list.Sort((x, y) =>
                {
                    int c = x.Value.Length.CompareTo(y.Value.Length);
                    if (c != 0)
                    {
                        return(c);
                    }

                    return(x.Key.CompareTo(y.Key));
                });

#if DEBUG
                if (list[0].Value.Length != stream.Length)
                {
                    Debug.WriteLine("AmoebaConverter ToStream : {0}→{1} {2}",
                                    NetworkConverter.ToSizeString(stream.Length),
                                    NetworkConverter.ToSizeString(list[0].Value.Length),
                                    NetworkConverter.ToSizeString(list[0].Value.Length - stream.Length));
                }
#endif

                for (int i = 1; i < list.Count; i++)
                {
                    list[i].Value.Dispose();
                }

                BufferStream headerStream = new BufferStream(_bufferManager);
                headerStream.WriteByte((byte)list[0].Key);

                var dataStream = new UniteStream(headerStream, list[0].Value);

                MemoryStream crcStream = new MemoryStream(Crc32_Castagnoli.ComputeHash(dataStream));
                return(new UniteStream(dataStream, crcStream));
            }
            catch (Exception ex)
            {
                if (stream != null)
                {
                    stream.Dispose();
                }

                throw new ArgumentException(ex.Message, ex);
            }
        }
Пример #8
0
        protected override int ProcessIncoming(NetContext context, Connection connection, Stream incoming)
        {
            if (incoming.Length < 2)
            {
                return(0);                     // can't read that; frame takes at minimum two bytes
            }
            byte[] buffer = null;
            try
            {
                buffer = context.GetBuffer();
                int read;
                // read as much as possible up to 14 bytes; that gives us space for 2 bytes frame header, 8 bytes length, and 4 bytes mask
                read = NetContext.TryFill(incoming, buffer, 14);

                int headerLength;
                var frame = WebSocketsFrame.TryParseFrameHeader(buffer, read, out headerLength);

                if (frame == null)
                {
                    return(0);
                }
                int payloadLen = frame.PayloadLength;

#if VERBOSE
                Debug.WriteLine("Parsed header from: " + BitConverter.ToString(buffer, 0, headerLength));
#endif

                if (incoming.Length < headerLength + payloadLen)
                {
                    return(0);                                             // not enough data to read the payload
                }
                if (payloadLen != 0)
                {
                    Stream payload = null;
                    try
                    {
                        payload = new BufferStream(context, context.Handler.MaxIncomingQuota);
                        if (read != headerLength)
                        {
                            incoming.Position -= (read - headerLength);                       // we got it wrong...
                        }
                        Copy(incoming, payload, buffer, frame.Mask, payloadLen);

                        if (payloadLen != payload.Length)
                        {
                            throw new InvalidOperationException("I munged the data");
                        }
                        frame.Payload = payload;
                        payload       = null;
                    }
                    finally
                    {
                        if (payload != null)
                        {
                            payload.Dispose();
                        }
                    }
                }
                foreach (var final in ApplyExtensions(context, connection, frame, true))
                {
                    ProcessFrame(context, connection, final);
                }
                return(headerLength + payloadLen);
            }
            finally
            {
                context.Recycle(buffer);
            }
        }
Пример #9
0
        private static Stream Compress(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            try
            {
                var dic = new Dictionary <byte, Stream>();

                try
                {
                    stream.Seek(0, SeekOrigin.Begin);

                    BufferStream deflateBufferStream = null;

                    try
                    {
                        deflateBufferStream = new BufferStream(_bufferManager);

                        using (var deflateStream = new DeflateStream(deflateBufferStream, CompressionMode.Compress, true))
                            using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 4))
                            {
                                int length;

                                while ((length = stream.Read(safeBuffer.Value, 0, safeBuffer.Value.Length)) > 0)
                                {
                                    deflateStream.Write(safeBuffer.Value, 0, length);
                                }
                            }

                        deflateBufferStream.Seek(0, SeekOrigin.Begin);

                        dic.Add((byte)ConvertCompressionAlgorithm.Deflate, deflateBufferStream);
                    }
                    catch (Exception)
                    {
                        if (deflateBufferStream != null)
                        {
                            deflateBufferStream.Dispose();
                        }
                    }
                }
                catch (Exception)
                {
                }

                dic.Add((byte)ConvertCompressionAlgorithm.None, stream);

                var list = dic.ToList();

                list.Sort((x, y) =>
                {
                    int c = x.Value.Length.CompareTo(y.Value.Length);
                    if (c != 0)
                    {
                        return(c);
                    }

                    return(x.Key.CompareTo(y.Key));
                });

                for (int i = 1; i < list.Count; i++)
                {
                    list[i].Value.Dispose();
                }

                var headerStream = new BufferStream(_bufferManager);
                Varint.SetUInt64(headerStream, list[0].Key);

                return(new UniteStream(headerStream, list[0].Value));
            }
            catch (Exception ex)
            {
                if (stream != null)
                {
                    stream.Dispose();
                }

                throw new ArgumentException(ex.Message, ex);
            }
        }
Пример #10
0
        private static Stream Decrypt(Stream stream, IExchangeDecrypt privateKey)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (privateKey == null)
            {
                throw new ArgumentNullException("privateKey");
            }

            try
            {
                byte type = (byte)stream.ReadByte();

                if (type == (byte)ConvertCryptoAlgorithm.Aes256)
                {
                    byte[] cryptoKey;

                    {
                        byte[] lengthBuffer = new byte[4];
                        if (stream.Read(lengthBuffer, 0, lengthBuffer.Length) != lengthBuffer.Length)
                        {
                            throw new ArgumentException();
                        }
                        int length = NetworkConverter.ToInt32(lengthBuffer);

                        byte[] encryptedBuffer = new byte[length];
                        if (stream.Read(encryptedBuffer, 0, encryptedBuffer.Length) != encryptedBuffer.Length)
                        {
                            throw new ArgumentException();
                        }

                        cryptoKey = Exchange.Decrypt(privateKey, encryptedBuffer);
                    }

                    BufferStream outStream = null;

                    try
                    {
                        outStream = new BufferStream(_bufferManager);

                        using (Stream dataStream = new WrapperStream(stream, true))
                        {
                            var iv = new byte[32];
                            dataStream.Read(iv, 0, iv.Length);

                            using (var rijndael = new RijndaelManaged()
                            {
                                KeySize = 256, BlockSize = 256, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7
                            })
                                using (var inStream = new RangeStream(dataStream, dataStream.Position, dataStream.Length - dataStream.Position))
                                    using (CryptoStream cs = new CryptoStream(inStream, rijndael.CreateDecryptor(cryptoKey, iv), CryptoStreamMode.Read))
                                    {
                                        byte[] buffer = null;

                                        try
                                        {
                                            buffer = _bufferManager.TakeBuffer(1024 * 4);

                                            int i = -1;

                                            while ((i = cs.Read(buffer, 0, buffer.Length)) > 0)
                                            {
                                                outStream.Write(buffer, 0, i);
                                            }
                                        }
                                        finally
                                        {
                                            _bufferManager.ReturnBuffer(buffer);
                                        }
                                    }
                        }

                        outStream.Seek(0, SeekOrigin.Begin);
                    }
                    catch (Exception)
                    {
                        if (outStream != null)
                        {
                            outStream.Dispose();
                        }

                        throw;
                    }

                    return(outStream);
                }

                throw new NotSupportedException();
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }
Пример #11
0
        private static Stream Encrypt(Stream stream, IExchangeEncrypt publicKey)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (publicKey == null)
            {
                throw new ArgumentNullException("publicKey");
            }

            try
            {
                BufferStream outStream = null;

                try
                {
                    outStream = new BufferStream(_bufferManager);
                    outStream.WriteByte((byte)ConvertCryptoAlgorithm.Aes256);

                    byte[] cryptoKey = new byte[32];
                    _random.GetBytes(cryptoKey);

                    {
                        var encryptedBuffer = Exchange.Encrypt(publicKey, cryptoKey);
                        outStream.Write(NetworkConverter.GetBytes((int)encryptedBuffer.Length), 0, 4);
                        outStream.Write(encryptedBuffer, 0, encryptedBuffer.Length);
                    }

                    byte[] iv = new byte[32];
                    _random.GetBytes(iv);
                    outStream.Write(iv, 0, iv.Length);

                    using (Stream inStream = new WrapperStream(stream, true))
                    {
                        using (var rijndael = new RijndaelManaged()
                        {
                            KeySize = 256, BlockSize = 256, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7
                        })
                            using (CryptoStream cs = new CryptoStream(inStream, rijndael.CreateEncryptor(cryptoKey, iv), CryptoStreamMode.Read))
                            {
                                byte[] buffer = null;

                                try
                                {
                                    buffer = _bufferManager.TakeBuffer(1024 * 4);

                                    int i = -1;

                                    while ((i = cs.Read(buffer, 0, buffer.Length)) > 0)
                                    {
                                        outStream.Write(buffer, 0, i);
                                    }
                                }
                                finally
                                {
                                    if (buffer != null)
                                    {
                                        _bufferManager.ReturnBuffer(buffer);
                                    }
                                }
                            }
                    }

                    outStream.Seek(0, SeekOrigin.Begin);
                }
                catch (Exception)
                {
                    if (outStream != null)
                    {
                        outStream.Dispose();
                    }

                    throw;
                }

                return(outStream);
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }
Пример #12
0
        private static Stream Decrypt(Stream stream, ExchangePrivateKey privateKey)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            if (privateKey == null)
            {
                throw new ArgumentNullException(nameof(privateKey));
            }

            try
            {
                int type = (int)Varint.GetUInt64(stream);

                if (type == (int)ConvertCryptoAlgorithm.Aes256)
                {
                    byte[] cryptoKey;

                    {
                        int length = (int)Varint.GetUInt64(stream);

                        var encryptedBuffer = new byte[length];
                        if (stream.Read(encryptedBuffer, 0, encryptedBuffer.Length) != encryptedBuffer.Length)
                        {
                            throw new ArgumentException();
                        }

                        cryptoKey = Exchange.Decrypt(privateKey, encryptedBuffer);
                    }

                    var iv = new byte[32];
                    stream.Read(iv, 0, iv.Length);

                    BufferStream outStream = null;

                    try
                    {
                        outStream = new BufferStream(_bufferManager);

                        using (var aes = Aes.Create())
                        {
                            aes.KeySize = 256;
                            aes.Mode    = CipherMode.CBC;
                            aes.Padding = PaddingMode.PKCS7;

                            using (var inStream = new RangeStream(stream, stream.Position, stream.Length - stream.Position, true))
                                using (var cs = new CryptoStream(inStream, aes.CreateDecryptor(cryptoKey, iv), CryptoStreamMode.Read))
                                    using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 4))
                                    {
                                        int length;

                                        while ((length = cs.Read(safeBuffer.Value, 0, safeBuffer.Value.Length)) > 0)
                                        {
                                            outStream.Write(safeBuffer.Value, 0, length);
                                        }
                                    }
                        }

                        outStream.Seek(0, SeekOrigin.Begin);
                    }
                    catch (Exception)
                    {
                        if (outStream != null)
                        {
                            outStream.Dispose();
                        }

                        throw;
                    }

                    return(outStream);
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Dispose();
                }
            }
        }
Пример #13
0
        public override System.IO.Stream Receive(TimeSpan timeout, Information options)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (!_connect)
            {
                throw new ConnectionException();
            }

            lock (_receiveLock)
            {
                Stream stream = null;

                try
                {
                    stream = _connection.Receive(timeout, options);

                    byte version = (byte)stream.ReadByte();

                    Stream dataStream = null;

                    try
                    {
                        dataStream = new RangeStream(stream, stream.Position, stream.Length - stream.Position);

                        if (version == (byte)0)
                        {
                            return(dataStream);
                        }
                        else if (version == (byte)1)
                        {
                            BufferStream deflateBufferStream = null;

                            try
                            {
                                deflateBufferStream = new BufferStream(_bufferManager);

                                using (DeflateStream deflateStream = new DeflateStream(dataStream, CompressionMode.Decompress, true))
                                {
                                    byte[] decompressBuffer = null;

                                    try
                                    {
                                        decompressBuffer = _bufferManager.TakeBuffer(1024 * 4);

                                        int i = -1;

                                        while ((i = deflateStream.Read(decompressBuffer, 0, decompressBuffer.Length)) > 0)
                                        {
                                            deflateBufferStream.Write(decompressBuffer, 0, i);

                                            if (deflateBufferStream.Length > _maxReceiveCount)
                                            {
                                                throw new ConnectionException();
                                            }
                                        }
                                    }
                                    finally
                                    {
                                        if (decompressBuffer != null)
                                        {
                                            _bufferManager.ReturnBuffer(decompressBuffer);
                                        }
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                if (deflateBufferStream != null)
                                {
                                    deflateBufferStream.Dispose();
                                }

                                throw e;
                            }

#if DEBUG
                            Debug.WriteLine("Receive : {0}→{1} {2}",
                                            NetworkConverter.ToSizeString(stream.Length),
                                            NetworkConverter.ToSizeString(deflateBufferStream.Length),
                                            NetworkConverter.ToSizeString(stream.Length - deflateBufferStream.Length));
#endif

                            deflateBufferStream.Seek(0, SeekOrigin.Begin);
                            dataStream.Dispose();

                            return(deflateBufferStream);
                        }
                        else
                        {
                            throw new ArgumentException("ArgumentException");
                        }
                    }
                    catch (ConnectionException e)
                    {
                        if (dataStream != null)
                        {
                            dataStream.Dispose();
                        }

                        throw e;
                    }
                    catch (Exception e)
                    {
                        if (dataStream != null)
                        {
                            dataStream.Dispose();
                        }

                        throw new ConnectionException(e.Message, e);
                    }
                }
                catch (ConnectionException e)
                {
                    if (stream != null)
                    {
                        stream.Dispose();
                    }

                    throw e;
                }
                catch (Exception e)
                {
                    if (stream != null)
                    {
                        stream.Dispose();
                    }

                    throw new ConnectionException(e.Message, e);
                }
            }
        }
Пример #14
0
            IEnumerable<WebSocketsFrame> IExtension.ApplyOutgoing(NetContext context, WebSocketConnection connection, WebSocketsFrame frame)
            {
                if (!frame.IsControlFrame && frame.PayloadLength > parent.compressMessagesLargerThanBytes)
                {
                    if (frame.Reserved1)
                    {
                        throw new InvalidOperationException("Reserved1 flag is already set; extension conflict?");
                    }

                    int headerBytes = 0;
                    if (outbound == null)
                    {
                        outbound = new ZStream();
                        const int BITS = 12; // 4096 byte outbound buffer (instead of full 32k=15)
                        outbound.deflateInit(zlibConst.Z_BEST_COMPRESSION, BITS);
                        headerBytes = 2;
                    }
                    BufferStream tmp = null;
                    var payload = frame.Payload;
                    payload.Position = 0;
                    byte[] inBuffer = null, outBuffer = null;
                    try
                    {
                        inBuffer = context.GetBuffer();
                        outBuffer = context.GetBuffer();
                        tmp = new BufferStream(context, 0);

                        outbound.next_out = outBuffer;
                        outbound.next_in = inBuffer;

                        int remaining = frame.PayloadLength;
                        while (remaining > 0)
                        {
                            int readCount = payload.Read(inBuffer, 0, inBuffer.Length);
                            if (readCount <= 0) break;
                            remaining -= readCount;

                            outbound.next_in_index = 0;
                            outbound.avail_in = readCount;

                            do
                            {
                                outbound.next_out_index = 0;
                                outbound.avail_out = outBuffer.Length;
                                long priorOut = outbound.total_out;
                                int err = outbound.deflate(remaining == 0 ? zlibConst.Z_SYNC_FLUSH : zlibConst.Z_NO_FLUSH);
                                if (err != zlibConst.Z_OK && err != zlibConst.Z_STREAM_END)
                                    throw new ZStreamException("deflating: " + outbound.msg);

                                int outCount = (int)(outbound.total_out - priorOut);
                                if (outCount > 0)
                                {
                                    if (headerBytes == 0)
                                    {
                                        tmp.Write(outBuffer, 0, outCount);
                                    }
                                    else
                                    {
                                        if (outCount < headerBytes)
                                        {
                                            throw new InvalidOperationException("Failed to write entire header");
                                        }
                                        // check the generated header meets our expectations
                                        // CMF is very specific - CM must be 8, and CINFO must be <=7 (for 32k window)
                                        if ((outBuffer[0] & 15) != 8)
                                        {
                                            throw new InvalidOperationException("Zlib CM header was incorrect");
                                        }
                                        if ((outBuffer[0] & 128) != 0) // if msb set, is > 7 - invalid
                                        {
                                            throw new InvalidOperationException("Zlib CINFO header was incorrect");
                                        }

                                        // FLG is less important; FCHECK is irrelevent, FLEVEL doesn't matter; but
                                        // FDICT must be zero, to ensure that we aren't expecting a an initialization dictionary
                                        if ((outBuffer[1] & 32) != 0)
                                        {
                                            throw new InvalidOperationException("Zlib FLG.FDICT header was set (must not be)");
                                        }

                                        // skip the header, and write anything else
                                        outCount -= headerBytes;
                                        if (outCount > 0)
                                        {
                                            tmp.Write(outBuffer, headerBytes, outCount);
                                        }
                                        headerBytes = 0; // all written now
                                    }
                                }
                            } while (outbound.avail_in > 0 || outbound.avail_out == 0);
                        }
                        if (remaining != 0) throw new EndOfStreamException();
                        if (headerBytes != 0) throw new InvalidOperationException("Zlib header was not written");

                        // verify the last 4 bytes, then drop them
                        tmp.Position = tmp.Length - 4;
                        NetContext.Fill(tmp, outBuffer, 4);
                        if (!(outBuffer[0] == 0x00 && outBuffer[1] == 0x00 && outBuffer[2] == 0xFF && outBuffer[3] == 0xFF))
                        {
                            throw new InvalidOperationException("expectation failed: 0000FFFF in the tail");
                        }

                        if (parent.disableContextTakeover && tmp.Length >= frame.PayloadLength)
                        { // compressing it didn't do anything useful; since we're going to discard
                          // the compression context, we might as well stick with the original data
                            payload.Position = 0;
                            payload = null; // so that it doesn't get disposed
                        }
                        else
                        {
                            // set our final output
                            tmp.Position = 0;
                            tmp.SetLength(tmp.Length - 4);
                            long bytesSaved = frame.PayloadLength - tmp.Length;
                            frame.Payload = tmp;
                            frame.PayloadLength = (int)tmp.Length;
                            frame.Reserved1 = true;
                            tmp = payload as BufferStream;
                            parent.RegisterOutboundBytesSaved(bytesSaved);
                        }
                    }
#if DEBUG
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex);
                        throw;
                    }
#endif
                    finally
                    {
                        if (outbound != null)
                        {
                            outbound.next_out = null;
                            outbound.next_in = null;
                        }
                        if (tmp != null) tmp.Dispose();
                        if (inBuffer != null) context.Recycle(inBuffer);
                        if (outBuffer != null) context.Recycle(outBuffer);
                        if (parent.disableContextTakeover) ClearContext(false, true);
                    }
                }
                yield return frame;
            }
Пример #15
0
        private static Stream ToStream <T>(int version, ItemBase <T> item)
            where T : ItemBase <T>
        {
            Stream stream = null;

            try
            {
                stream = new RangeStream(item.Export(_bufferManager));

                var dic = new Dictionary <byte, Stream>();

                try
                {
                    stream.Seek(0, SeekOrigin.Begin);

                    BufferStream deflateBufferStream = null;

                    try
                    {
                        deflateBufferStream = new BufferStream(_bufferManager);

                        using (var deflateStream = new DeflateStream(deflateBufferStream, CompressionMode.Compress, true))
                            using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 4))
                            {
                                int length;

                                while ((length = stream.Read(safeBuffer.Value, 0, safeBuffer.Value.Length)) > 0)
                                {
                                    deflateStream.Write(safeBuffer.Value, 0, length);
                                }
                            }

                        deflateBufferStream.Seek(0, SeekOrigin.Begin);

                        dic.Add((byte)ConvertCompressionAlgorithm.Deflate, deflateBufferStream);
                    }
                    catch (Exception)
                    {
                        if (deflateBufferStream != null)
                        {
                            deflateBufferStream.Dispose();
                        }
                    }
                }
                catch (Exception)
                {
                }

                dic.Add((byte)ConvertCompressionAlgorithm.None, stream);

                var list = dic.ToList();

                list.Sort((x, y) =>
                {
                    int c = x.Value.Length.CompareTo(y.Value.Length);
                    if (c != 0)
                    {
                        return(c);
                    }

                    return(x.Key.CompareTo(y.Key));
                });

                for (int i = 1; i < list.Count; i++)
                {
                    list[i].Value.Dispose();
                }

                var headerStream = new BufferStream(_bufferManager);
                VintUtils.SetUInt64(headerStream, (uint)version);
                VintUtils.SetUInt64(headerStream, list[0].Key);

                var dataStream = new UniteStream(headerStream, list[0].Value);

                var crcStream = new MemoryStream(Crc32_Castagnoli.ComputeHash(new WrapperStream(dataStream, true)));
                return(new UniteStream(dataStream, crcStream));
            }
            catch (Exception ex)
            {
                if (stream != null)
                {
                    stream.Dispose();
                }

                throw new ArgumentException(ex.Message, ex);
            }
        }
Пример #16
0
        private static Stream Compress(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            var targetStream = new RangeStream(stream, true);

            List <KeyValuePair <byte, Stream> > list = new List <KeyValuePair <byte, Stream> >();

            try
            {
                targetStream.Seek(0, SeekOrigin.Begin);

                BufferStream deflateBufferStream = null;

                try
                {
                    deflateBufferStream = new BufferStream(_bufferManager);

                    using (DeflateStream deflateStream = new DeflateStream(deflateBufferStream, CompressionMode.Compress, true))
                    {
                        byte[] compressBuffer = null;

                        try
                        {
                            compressBuffer = _bufferManager.TakeBuffer(1024 * 4);

                            int i = -1;

                            while ((i = targetStream.Read(compressBuffer, 0, compressBuffer.Length)) > 0)
                            {
                                deflateStream.Write(compressBuffer, 0, i);
                            }
                        }
                        finally
                        {
                            if (compressBuffer != null)
                            {
                                _bufferManager.ReturnBuffer(compressBuffer);
                            }
                        }
                    }

                    deflateBufferStream.Seek(0, SeekOrigin.Begin);

                    list.Add(new KeyValuePair <byte, Stream>((byte)ConvertCompressionAlgorithm.Deflate, deflateBufferStream));
                }
                catch (Exception)
                {
                    if (deflateBufferStream != null)
                    {
                        deflateBufferStream.Dispose();
                    }
                }
            }
            catch (Exception)
            {
            }

            list.Add(new KeyValuePair <byte, Stream>((byte)ConvertCompressionAlgorithm.None, targetStream));

            list.Sort((x, y) =>
            {
                int c = x.Value.Length.CompareTo(y.Value.Length);
                if (c != 0)
                {
                    return(c);
                }

                return(x.Key.CompareTo(y.Key));
            });

#if DEBUG
            if (list[0].Value.Length != targetStream.Length)
            {
                Debug.WriteLine("ContentConverter Compress {3} : {0}→{1} {2}",
                                NetworkConverter.ToSizeString(targetStream.Length),
                                NetworkConverter.ToSizeString(list[0].Value.Length),
                                NetworkConverter.ToSizeString(list[0].Value.Length - targetStream.Length),
                                (ConvertCompressionAlgorithm)list[0].Key);
            }
#endif

            for (int i = 1; i < list.Count; i++)
            {
                list[i].Value.Dispose();
            }

            BufferStream metadataStream = new BufferStream(_bufferManager);
            metadataStream.WriteByte((byte)list[0].Key);

            return(new UniteStream(metadataStream, list[0].Value));
        }
Пример #17
0
            IEnumerable <WebSocketsFrame> IExtension.ApplyIncoming(NetContext context, WebSocketConnection connection, WebSocketsFrame frame)
            {
                if (frame.Reserved1 && !frame.IsControlFrame)
                {
                    BufferStream tmp     = null;
                    var          payload = frame.Payload;
                    payload.Position = 0;
                    byte[] inBuffer = null, outBuffer = null;

                    try
                    {
                        outBuffer = context.GetBuffer();
                        inBuffer  = context.GetBuffer();
                        tmp       = new BufferStream(context, 0);

                        if (inbound == null)
                        {
                            inbound = new ZStream();
                            inbound.inflateInit();

                            // fake a zlib header with:
                            // CMF:
                            //   CM = 8 (deflate)
                            //   CINFO = 7 (32k window)
                            // FLG:
                            //   FCHECK: 26 (checksum of other bits)
                            //   FDICT: 0 (no dictionary)
                            //   FLEVEL: 3 (maximum)
                            inBuffer[0]     = 120;
                            inBuffer[1]     = 218;
                            inbound.next_in = inBuffer;
                            int chk = Inflate(tmp, outBuffer, 2);
                            if (chk != 0)
                            {
                                throw new InvalidOperationException("Spoofed zlib header suggested data");
                            }
                        }

                        inbound.next_in = inBuffer;
                        int remaining = frame.PayloadLength;
                        //bool first = true;
                        while (remaining > 0)
                        {
                            int readCount = payload.Read(inBuffer, 0, inBuffer.Length);
                            if (readCount <= 0)
                            {
                                break;
                            }
                            remaining -= readCount;

                            //if (first)
                            //{   // kill the BFINAL flag from the first block, if set; we don't want zlib
                            //    // trying to verify the ADLER checksum; unfortunately, a frame can contain
                            //    // multiple blocks, and a *later* block could have BFINAL set. That sucks.
                            //    inBuffer[0] &= 254;
                            //    first = false;
                            //}
                            Inflate(tmp, outBuffer, readCount);
                        }
                        if (remaining != 0)
                        {
                            throw new EndOfStreamException();
                        }

                        // spoof the missing 4 bytes from the tail
                        inBuffer[0] = inBuffer[1] = 0x00;
                        inBuffer[2] = inBuffer[3] = 0xFF;
                        Inflate(tmp, outBuffer, 4);

                        // set our final output
                        tmp.Position  = 0;
                        frame.Payload = tmp;
                        long bytesSaved = tmp.Length - frame.PayloadLength;
                        frame.PayloadLength = (int)tmp.Length;
                        frame.Reserved1     = false;
                        tmp = payload as BufferStream;
                        parent.RegisterInboundBytesSaved(bytesSaved);
                    }
#if DEBUG
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex);
                        throw;
                    }
#endif
                    finally
                    {
                        if (inbound != null)
                        {
                            inbound.next_out = null;
                            inbound.next_in  = null;
                        }
                        if (tmp != null)
                        {
                            tmp.Dispose();
                        }
                        if (inBuffer != null)
                        {
                            context.Recycle(inBuffer);
                        }
                        if (outBuffer != null)
                        {
                            context.Recycle(outBuffer);
                        }
                        if (parent.disableContextTakeover)
                        {
                            ClearContext(true, false);
                        }
                    }
                }
                yield return(frame);
            }
Пример #18
0
            IEnumerable <WebSocketsFrame> IExtension.ApplyOutgoing(NetContext context, WebSocketConnection connection, WebSocketsFrame frame)
            {
                if (!frame.IsControlFrame && frame.PayloadLength > parent.compressMessagesLargerThanBytes)
                {
                    if (frame.Reserved1)
                    {
                        throw new InvalidOperationException("Reserved1 flag is already set; extension conflict?");
                    }

                    int headerBytes = 0;
                    if (outbound == null)
                    {
                        outbound = new ZStream();
                        const int BITS = 12; // 4096 byte outbound buffer (instead of full 32k=15)
                        outbound.deflateInit(zlibConst.Z_BEST_COMPRESSION, BITS);
                        headerBytes = 2;
                    }
                    BufferStream tmp     = null;
                    var          payload = frame.Payload;
                    payload.Position = 0;
                    byte[] inBuffer = null, outBuffer = null;
                    try
                    {
                        inBuffer  = context.GetBuffer();
                        outBuffer = context.GetBuffer();
                        tmp       = new BufferStream(context, 0);

                        outbound.next_out = outBuffer;
                        outbound.next_in  = inBuffer;

                        int remaining = frame.PayloadLength;
                        while (remaining > 0)
                        {
                            int readCount = payload.Read(inBuffer, 0, inBuffer.Length);
                            if (readCount <= 0)
                            {
                                break;
                            }
                            remaining -= readCount;

                            outbound.next_in_index = 0;
                            outbound.avail_in      = readCount;

                            do
                            {
                                outbound.next_out_index = 0;
                                outbound.avail_out      = outBuffer.Length;
                                long priorOut = outbound.total_out;
                                int  err      = outbound.deflate(remaining == 0 ? zlibConst.Z_SYNC_FLUSH : zlibConst.Z_NO_FLUSH);
                                if (err != zlibConst.Z_OK && err != zlibConst.Z_STREAM_END)
                                {
                                    throw new ZStreamException("deflating: " + outbound.msg);
                                }

                                int outCount = (int)(outbound.total_out - priorOut);
                                if (outCount > 0)
                                {
                                    if (headerBytes == 0)
                                    {
                                        tmp.Write(outBuffer, 0, outCount);
                                    }
                                    else
                                    {
                                        if (outCount < headerBytes)
                                        {
                                            throw new InvalidOperationException("Failed to write entire header");
                                        }
                                        // check the generated header meets our expectations
                                        // CMF is very specific - CM must be 8, and CINFO must be <=7 (for 32k window)
                                        if ((outBuffer[0] & 15) != 8)
                                        {
                                            throw new InvalidOperationException("Zlib CM header was incorrect");
                                        }
                                        if ((outBuffer[0] & 128) != 0) // if msb set, is > 7 - invalid
                                        {
                                            throw new InvalidOperationException("Zlib CINFO header was incorrect");
                                        }

                                        // FLG is less important; FCHECK is irrelevent, FLEVEL doesn't matter; but
                                        // FDICT must be zero, to ensure that we aren't expecting a an initialization dictionary
                                        if ((outBuffer[1] & 32) != 0)
                                        {
                                            throw new InvalidOperationException("Zlib FLG.FDICT header was set (must not be)");
                                        }

                                        // skip the header, and write anything else
                                        outCount -= headerBytes;
                                        if (outCount > 0)
                                        {
                                            tmp.Write(outBuffer, headerBytes, outCount);
                                        }
                                        headerBytes = 0; // all written now
                                    }
                                }
                            } while (outbound.avail_in > 0 || outbound.avail_out == 0);
                        }
                        if (remaining != 0)
                        {
                            throw new EndOfStreamException();
                        }
                        if (headerBytes != 0)
                        {
                            throw new InvalidOperationException("Zlib header was not written");
                        }

                        // verify the last 4 bytes, then drop them
                        tmp.Position = tmp.Length - 4;
                        NetContext.Fill(tmp, outBuffer, 4);
                        if (!(outBuffer[0] == 0x00 && outBuffer[1] == 0x00 && outBuffer[2] == 0xFF && outBuffer[3] == 0xFF))
                        {
                            throw new InvalidOperationException("expectation failed: 0000FFFF in the tail");
                        }

                        if (parent.disableContextTakeover && tmp.Length >= frame.PayloadLength)
                        { // compressing it didn't do anything useful; since we're going to discard
                          // the compression context, we might as well stick with the original data
                            payload.Position = 0;
                            payload          = null; // so that it doesn't get disposed
                        }
                        else
                        {
                            // set our final output
                            tmp.Position = 0;
                            tmp.SetLength(tmp.Length - 4);
                            long bytesSaved = frame.PayloadLength - tmp.Length;
                            frame.Payload       = tmp;
                            frame.PayloadLength = (int)tmp.Length;
                            frame.Reserved1     = true;
                            tmp = payload as BufferStream;
                            parent.RegisterOutboundBytesSaved(bytesSaved);
                        }
                    }
#if DEBUG
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex);
                        throw;
                    }
#endif
                    finally
                    {
                        if (outbound != null)
                        {
                            outbound.next_out = null;
                            outbound.next_in  = null;
                        }
                        if (tmp != null)
                        {
                            tmp.Dispose();
                        }
                        if (inBuffer != null)
                        {
                            context.Recycle(inBuffer);
                        }
                        if (outBuffer != null)
                        {
                            context.Recycle(outBuffer);
                        }
                        if (parent.disableContextTakeover)
                        {
                            ClearContext(false, true);
                        }
                    }
                }
                yield return(frame);
            }
Пример #19
0
        private void MessagingManager_ReceiveEvent <TService>(TService serviceManager, Stream requestStream, Action <Stream> sendAction, Action exitAction)
            where TService : StateManagerBase, IService
        {
            using (var reader = new ItemStreamReader(new WrapperStream(requestStream, true), _bufferManager))
            {
                var type = (AmoebaRequestType)reader.GetUInt32();
                int id   = (int)reader.GetUInt32();

                if (type == AmoebaRequestType.Exit)
                {
                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                    exitAction();
                }
                else if (type == AmoebaRequestType.Cancel)
                {
                    if (_tasks.TryGetValue(id, out var responseTask))
                    {
                        responseTask.Stop();
                    }
                }
                else
                {
                    var responseTask = ResponseTask.Create((token) =>
                    {
                        try
                        {
                            switch (type)
                            {
                            case AmoebaRequestType.GetState:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.State);
                                    break;
                                }

                            case AmoebaRequestType.Start:
                                {
                                    serviceManager.Start();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.Stop:
                                {
                                    serviceManager.Stop();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.GetReport:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.Report);
                                    break;
                                }

                            case AmoebaRequestType.GetNetworkConnectionReports:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.GetNetworkConnectionReports());
                                    break;
                                }

                            case AmoebaRequestType.GetCacheContentReports:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.GetCacheContentReports());
                                    break;
                                }

                            case AmoebaRequestType.GetDownloadContentReports:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.GetDownloadContentReports());
                                    break;
                                }

                            case AmoebaRequestType.GetConfig:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.Config);
                                    break;
                                }

                            case AmoebaRequestType.SetConfig:
                                {
                                    var config = JsonUtils.Load <ServiceConfig>(requestStream);
                                    serviceManager.SetConfig(config);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.SetCloudLocations:
                                {
                                    var cloudLocations = JsonUtils.Load <Location[]>(requestStream);
                                    serviceManager.SetCloudLocations(cloudLocations);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.GetSize:
                                {
                                    SendResponse(AmoebaResponseType.Result, id, serviceManager.Size);
                                    break;
                                }

                            case AmoebaRequestType.Resize:
                                {
                                    long size = JsonUtils.Load <long>(requestStream);
                                    serviceManager.Resize(size);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.CheckBlocks:
                                {
                                    try
                                    {
                                        serviceManager.CheckBlocks(new Progress <CheckBlocksProgressReport>((report) =>
                                        {
                                            SendResponse(AmoebaResponseType.Output, id, report);
                                        }), token).Wait();
                                    }
                                    catch (Exception)
                                    {
                                    }

                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.AddContent:
                                {
                                    var arguments = JsonUtils.Load <(string, DateTime)>(requestStream);
                                    var result    = serviceManager.AddContent(arguments.Item1, arguments.Item2, token).Result;
                                    SendResponse(AmoebaResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaRequestType.RemoveContent:
                                {
                                    string path = JsonUtils.Load <string>(requestStream);
                                    serviceManager.RemoveContent(path);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.Diffusion:
                                {
                                    string path = JsonUtils.Load <string>(requestStream);
                                    serviceManager.Diffusion(path);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.AddDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string, long)>(requestStream);
                                    serviceManager.AddDownload(arguments.Item1, arguments.Item2, arguments.Item3);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.RemoveDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string)>(requestStream);
                                    serviceManager.RemoveDownload(arguments.Item1, arguments.Item2);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.ResetDownload:
                                {
                                    var arguments = JsonUtils.Load <(Metadata, string)>(requestStream);
                                    serviceManager.ResetDownload(arguments.Item1, arguments.Item2);
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.SetProfile:
                                {
                                    var arguments = JsonUtils.Load <(Profile, DigitalSignature)>(requestStream);
                                    serviceManager.SetProfile(arguments.Item1, arguments.Item2, token).Wait();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.SetStore:
                                {
                                    var arguments = JsonUtils.Load <(Store, DigitalSignature)>(requestStream);
                                    serviceManager.SetStore(arguments.Item1, arguments.Item2, token).Wait();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.SetMailMessage:
                                {
                                    var arguments = JsonUtils.Load <(Signature, MailMessage, ExchangePublicKey, DigitalSignature)>(requestStream);
                                    serviceManager.SetMailMessage(arguments.Item1, arguments.Item2, arguments.Item3, arguments.Item4, token).Wait();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.SetChatMessage:
                                {
                                    var arguments = JsonUtils.Load <(Tag, ChatMessage, DigitalSignature, TimeSpan)>(requestStream);
                                    serviceManager.SetChatMessage(arguments.Item1, arguments.Item2, arguments.Item3, arguments.Item4, token).Wait();
                                    SendResponse(AmoebaResponseType.Result, id, (object)null);
                                    break;
                                }

                            case AmoebaRequestType.GetProfile:
                                {
                                    var signature = JsonUtils.Load <Signature>(requestStream);
                                    var result    = serviceManager.GetProfile(signature, token).Result;
                                    SendResponse(AmoebaResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaRequestType.GetStore:
                                {
                                    var signature = JsonUtils.Load <Signature>(requestStream);
                                    var result    = serviceManager.GetStore(signature, token).Result;
                                    SendResponse(AmoebaResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaRequestType.GetMailMessages:
                                {
                                    var arguments = JsonUtils.Load <(Signature, ExchangePrivateKey)>(requestStream);
                                    var result    = serviceManager.GetMailMessages(arguments.Item1, arguments.Item2, token).Result;
                                    SendResponse(AmoebaResponseType.Result, id, result);
                                    break;
                                }

                            case AmoebaRequestType.GetChatMessages:
                                {
                                    var tag    = JsonUtils.Load <Tag>(requestStream);
                                    var result = serviceManager.GetChatMessages(tag, token).Result;
                                    SendResponse(AmoebaResponseType.Result, id, result);
                                    break;
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            SendResponse(AmoebaResponseType.Error, id, e.Message);
                        }
                        finally
                        {
                            _tasks.Remove(id);
                        }
                    });

                    _tasks.Add(id, responseTask);
                    responseTask.Start();
                }
            }

            void SendResponse <T>(AmoebaResponseType type, int id, T value)
            {
                using (var writer = new ItemStreamWriter(_bufferManager))
                {
                    writer.Write((uint)type);
                    writer.Write((uint)id);

                    Stream valueStream = null;

                    if (value != null)
                    {
                        try
                        {
                            valueStream = new BufferStream(_bufferManager);
                            JsonUtils.Save(valueStream, value);
                        }
                        catch (Exception)
                        {
                            if (valueStream != null)
                            {
                                valueStream.Dispose();
                                valueStream = null;
                            }

                            return;
                        }
                    }

                    sendAction(new UniteStream(writer.GetStream(), valueStream));
                }
            }
        }
        protected override int ProcessIncoming(NetContext context, Connection connection, Stream incoming)
        {
            if (incoming.Length < 2) return 0; // can't read that; frame takes at minimum two bytes

            

            byte[] buffer = null;
            try
            {
                buffer = context.GetBuffer();
                int read;
                // read as much as possible up to 14 bytes; that gives us space for 2 bytes frame header, 8 bytes length, and 4 bytes mask
                read = NetContext.TryFill(incoming, buffer, 14);

                int headerLength;
                var frame = WebSocketsFrame.TryParseFrameHeader(buffer, read, out headerLength);

                if (frame == null) return 0;
                int payloadLen = frame.PayloadLength;

#if VERBOSE
                Debug.WriteLine("Parsed header from: " + BitConverter.ToString(buffer, 0, headerLength));
#endif

                if (incoming.Length < headerLength + payloadLen) return 0; // not enough data to read the payload

                if (payloadLen != 0)
                {
                    Stream payload = null;
                    try
                    {
                        payload = new BufferStream(context, context.Handler.MaxIncomingQuota);
                        if (read != headerLength) incoming.Position -= (read - headerLength); // we got it wrong...

                        Copy(incoming, payload, buffer, frame.Mask, payloadLen);

                        if (payloadLen != payload.Length)
                        {
                            throw new InvalidOperationException("I munged the data");
                        }
                        frame.Payload = payload;
                        payload = null;
                    }
                    finally
                    {
                        if (payload != null) payload.Dispose();
                    }
                }
                foreach (var final in ApplyExtensions(context, connection, frame, true))
                {
                    ProcessFrame(context, connection, final);
                }
                return headerLength + payloadLen;
            }
            finally
            {
                context.Recycle(buffer);
            }
        }
Пример #21
0
        private static Stream Decompress(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            try
            {
                stream.Seek(0, SeekOrigin.Begin);

                int type = (int)Varint.GetUInt64(stream);

                if (type == (int)ConvertCompressionAlgorithm.None)
                {
                    return(new RangeStream(stream));
                }
                else if (type == (int)ConvertCompressionAlgorithm.Deflate)
                {
                    BufferStream deflateBufferStream = null;

                    try
                    {
                        deflateBufferStream = new BufferStream(_bufferManager);

                        using (var deflateStream = new DeflateStream(stream, CompressionMode.Decompress))
                            using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 4))
                            {
                                int length;

                                while ((length = deflateStream.Read(safeBuffer.Value, 0, safeBuffer.Value.Length)) > 0)
                                {
                                    deflateBufferStream.Write(safeBuffer.Value, 0, length);

                                    if (deflateBufferStream.Length > 1024 * 1024 * 256)
                                    {
                                        throw new Exception("too large");
                                    }
                                }
                            }

                        deflateBufferStream.Seek(0, SeekOrigin.Begin);

                        return(deflateBufferStream);
                    }
                    catch (Exception)
                    {
                        if (deflateBufferStream != null)
                        {
                            deflateBufferStream.Dispose();
                        }

                        throw;
                    }
                }
                else
                {
                    throw new ArgumentException("ArgumentException");
                }
            }
            catch (Exception e)
            {
                if (stream != null)
                {
                    stream.Dispose();
                }

                throw new ArgumentException(e.Message, e);
            }
        }
Пример #22
0
        public override void Send(System.IO.Stream stream, TimeSpan timeout, Information options)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (!_connect)
            {
                throw new ConnectionException();
            }
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (stream.Length == 0)
            {
                throw new ArgumentOutOfRangeException("stream");
            }

            bool isCompress = true;

            if (options != null)
            {
                if (options.Contains("IsCompress"))
                {
                    isCompress = (bool)options["IsCompress"];
                }
            }

            lock (_sendLock)
            {
                using (RangeStream targetStream = new RangeStream(stream, stream.Position, stream.Length - stream.Position, true))
                {
                    try
                    {
                        List <KeyValuePair <byte, Stream> > list = new List <KeyValuePair <byte, Stream> >();

                        if (isCompress)
                        {
                            if (_otherCompressAlgorithm.HasFlag(CompressAlgorithm.Deflate))
                            {
                                BufferStream deflateBufferStream = null;

                                try
                                {
                                    deflateBufferStream = new BufferStream(_bufferManager);

                                    using (DeflateStream deflateStream = new DeflateStream(deflateBufferStream, CompressionMode.Compress, true))
                                    {
                                        byte[] compressBuffer = null;

                                        try
                                        {
                                            compressBuffer = _bufferManager.TakeBuffer(1024 * 4);

                                            int i = -1;

                                            while ((i = targetStream.Read(compressBuffer, 0, compressBuffer.Length)) > 0)
                                            {
                                                deflateStream.Write(compressBuffer, 0, i);
                                            }
                                        }
                                        finally
                                        {
                                            if (compressBuffer != null)
                                            {
                                                _bufferManager.ReturnBuffer(compressBuffer);
                                            }
                                        }
                                    }

                                    deflateBufferStream.Seek(0, SeekOrigin.Begin);

                                    list.Add(new KeyValuePair <byte, Stream>((byte)1, deflateBufferStream));
                                }
                                catch (Exception e)
                                {
                                    if (deflateBufferStream != null)
                                    {
                                        deflateBufferStream.Dispose();
                                    }

                                    throw e;
                                }
                            }
                        }

                        list.Add(new KeyValuePair <byte, Stream>((byte)0, new WrapperStream(targetStream, true)));

                        list.Sort((x, y) =>
                        {
                            int c = x.Value.Length.CompareTo(y.Value.Length);
                            if (c != 0)
                            {
                                return(c);
                            }

                            return(x.Key.CompareTo(y.Key));
                        });

#if DEBUG
                        if (list[0].Value.Length != targetStream.Length)
                        {
                            Debug.WriteLine("Send : {0}→{1} {2}",
                                            NetworkConverter.ToSizeString(targetStream.Length),
                                            NetworkConverter.ToSizeString(list[0].Value.Length),
                                            NetworkConverter.ToSizeString(list[0].Value.Length - targetStream.Length));
                        }
#endif

                        for (int i = 1; i < list.Count; i++)
                        {
                            list[i].Value.Dispose();
                        }

                        BufferStream headerStream = new BufferStream(_bufferManager);
                        headerStream.WriteByte((byte)list[0].Key);

                        using (var dataStream = new UniteStream(headerStream, list[0].Value))
                        {
                            _connection.Send(dataStream, timeout, options);
                        }
                    }
                    catch (ConnectionException e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        throw new ConnectionException(e.Message, e);
                    }
                }
            }
        }
Пример #23
0
        private static Stream Encrypt(Stream stream, ExchangePublicKey publicKey)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            if (publicKey == null)
            {
                throw new ArgumentNullException(nameof(publicKey));
            }

            try
            {
                BufferStream outStream = null;

                try
                {
                    outStream = new BufferStream(_bufferManager);
                    Varint.SetUInt64(outStream, (uint)ConvertCryptoAlgorithm.Aes256);

                    var cryptoKey = new byte[32];
                    var iv        = new byte[32];

                    using (var random = RandomNumberGenerator.Create())
                    {
                        random.GetBytes(cryptoKey);
                        random.GetBytes(iv);
                    }

                    {
                        var encryptedBuffer = Exchange.Encrypt(publicKey, cryptoKey);
                        Varint.SetUInt64(outStream, (uint)encryptedBuffer.Length);
                        outStream.Write(encryptedBuffer, 0, encryptedBuffer.Length);
                    }

                    outStream.Write(iv, 0, iv.Length);

                    using (var aes = Aes.Create())
                    {
                        aes.KeySize = 256;
                        aes.Mode    = CipherMode.CBC;
                        aes.Padding = PaddingMode.PKCS7;

                        using (var inStream = new WrapperStream(stream, true))
                            using (var cs = new CryptoStream(inStream, aes.CreateEncryptor(cryptoKey, iv), CryptoStreamMode.Read))
                                using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 4))
                                {
                                    int length;

                                    while ((length = cs.Read(safeBuffer.Value, 0, safeBuffer.Value.Length)) > 0)
                                    {
                                        outStream.Write(safeBuffer.Value, 0, length);
                                    }
                                }
                    }

                    outStream.Seek(0, SeekOrigin.Begin);
                }
                catch (Exception)
                {
                    if (outStream != null)
                    {
                        outStream.Dispose();
                    }

                    throw;
                }

                return(outStream);
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Dispose();
                }
            }
        }
Пример #24
0
            IEnumerable<WebSocketsFrame> IExtension.ApplyIncoming(NetContext context, WebSocketConnection connection, WebSocketsFrame frame)
            {
                if (frame.Reserved1 && !frame.IsControlFrame)
                {
                    BufferStream tmp = null;
                    var payload = frame.Payload;
                    payload.Position = 0;
                    byte[] inBuffer = null, outBuffer = null;

                    try
                    {
                        outBuffer = context.GetBuffer();
                        inBuffer = context.GetBuffer();
                        tmp = new BufferStream(context, 0);

                        if (inbound == null)
                        {
                            inbound = new ZStream();
                            inbound.inflateInit();

                            // fake a zlib header with:
                            // CMF:
                            //   CM = 8 (deflate)
                            //   CINFO = 7 (32k window)
                            // FLG:
                            //   FCHECK: 26 (checksum of other bits)
                            //   FDICT: 0 (no dictionary)
                            //   FLEVEL: 3 (maximum)
                            inBuffer[0] = 120;
                            inBuffer[1] = 218;
                            inbound.next_in = inBuffer;
                            int chk = Inflate(tmp, outBuffer, 2);
                            if (chk != 0) throw new InvalidOperationException("Spoofed zlib header suggested data");
                        }   
                        
                        inbound.next_in = inBuffer;
                        int remaining = frame.PayloadLength;
                        //bool first = true;
                        while (remaining > 0)
                        {
                            int readCount = payload.Read(inBuffer, 0, inBuffer.Length);
                            if (readCount <= 0) break;
                            remaining -= readCount;

                            //if (first)
                            //{   // kill the BFINAL flag from the first block, if set; we don't want zlib
                            //    // trying to verify the ADLER checksum; unfortunately, a frame can contain
                            //    // multiple blocks, and a *later* block could have BFINAL set. That sucks.
                            //    inBuffer[0] &= 254;
                            //    first = false;
                            //}
                            Inflate(tmp, outBuffer, readCount);                          
                        }
                        if (remaining != 0) throw new EndOfStreamException();

                        // spoof the missing 4 bytes from the tail
                        inBuffer[0] = inBuffer[1] = 0x00;
                        inBuffer[2] = inBuffer[3] = 0xFF;
                        Inflate(tmp, outBuffer, 4);

                        // set our final output
                        tmp.Position = 0;
                        frame.Payload = tmp;
                        long bytesSaved = tmp.Length - frame.PayloadLength;
                        frame.PayloadLength = (int)tmp.Length;
                        frame.Reserved1 = false;
                        tmp = payload as BufferStream;
                        parent.RegisterInboundBytesSaved(bytesSaved);
                    }
#if DEBUG
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex);
                        throw;
                    }
#endif
                    finally
                    {
                        if (inbound != null)
                        {
                            inbound.next_out = null;
                            inbound.next_in = null;
                        }
                        if (tmp != null) tmp.Dispose();
                        if (inBuffer != null) context.Recycle(inBuffer);
                        if (outBuffer != null) context.Recycle(outBuffer);
                        if (parent.disableContextTakeover) ClearContext(true, false);
                    }

                }
                yield return frame;
            }
Пример #25
0
        private static Stream Decompress(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            try
            {
                var targetStream = new RangeStream(stream, true);

                byte type = (byte)targetStream.ReadByte();

                if (type == (byte)ConvertCompressionAlgorithm.None)
                {
                    return(new RangeStream(targetStream));
                }
                else if (type == (byte)ConvertCompressionAlgorithm.Deflate)
                {
                    using (Stream dataStream = new WrapperStream(targetStream, true))
                    {
                        BufferStream deflateBufferStream = null;

                        try
                        {
                            deflateBufferStream = new BufferStream(_bufferManager);

                            using (DeflateStream deflateStream = new DeflateStream(dataStream, CompressionMode.Decompress, true))
                            {
                                byte[] decompressBuffer = null;

                                try
                                {
                                    decompressBuffer = _bufferManager.TakeBuffer(1024 * 4);

                                    int i = -1;

                                    while ((i = deflateStream.Read(decompressBuffer, 0, decompressBuffer.Length)) > 0)
                                    {
                                        deflateBufferStream.Write(decompressBuffer, 0, i);
                                    }
                                }
                                finally
                                {
                                    if (decompressBuffer != null)
                                    {
                                        _bufferManager.ReturnBuffer(decompressBuffer);
                                    }
                                }
                            }

                            deflateBufferStream.Seek(0, SeekOrigin.Begin);

#if DEBUG
                            Debug.WriteLine("ContentConverter Decompress {3} : {0}→{1} {2}",
                                            NetworkConverter.ToSizeString(dataStream.Length),
                                            NetworkConverter.ToSizeString(deflateBufferStream.Length),
                                            NetworkConverter.ToSizeString(dataStream.Length - deflateBufferStream.Length),
                                            ConvertCompressionAlgorithm.Deflate);
#endif

                            return(deflateBufferStream);
                        }
                        catch (Exception)
                        {
                            if (deflateBufferStream != null)
                            {
                                deflateBufferStream.Dispose();
                            }
                        }
                    }
                }

                throw new ArgumentException("ArgumentException");
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }