예제 #1
0
        public unsafe void Write(
            UvStreamHandle handle,
            ref ReadableBuffer buffer,
            Action <UvWriteReq, int, Exception, object> callback,
            object state)
        {
            try
            {
                int nBuffers = 0;
                if (buffer.IsSingleSpan)
                {
                    nBuffers = 1;
                }
                else
                {
                    foreach (var span in buffer)
                    {
                        nBuffers++;
                    }
                }

                // add GCHandle to keeps this SafeHandle alive while request processing
                _pins.Add(GCHandle.Alloc(this, GCHandleType.Normal));

                var pBuffers = (Uv.uv_buf_t *)_bufs;
                if (nBuffers > BUFFER_COUNT)
                {
                    // create and pin buffer array when it's larger than the pre-allocated one
                    var bufArray = new Uv.uv_buf_t[nBuffers];
                    var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
                    _pins.Add(gcHandle);
                    pBuffers = (Uv.uv_buf_t *)gcHandle.AddrOfPinnedObject();
                }

                if (nBuffers == 1)
                {
                    var span = buffer.FirstSpan;
                    pBuffers[0] = Libuv.buf_init((IntPtr)span.UnsafePointer, span.Length);
                }
                else
                {
                    int i = 0;
                    foreach (var span in buffer)
                    {
                        pBuffers[i++] = Libuv.buf_init((IntPtr)span.UnsafePointer, span.Length);
                    }
                }

                _callback = callback;
                _state    = state;
                _uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb);
            }
            catch
            {
                _callback = null;
                _state    = null;
                Unpin(this);
                throw;
            }
        }
예제 #2
0
        public async Task SocketCanRead()
        {
            int bytesRead = 0;
            var loop      = new UvLoopHandle();

            loop.Init(_uv);
            var tcp = new UvTcpHandle();

            tcp.Init(loop);
            tcp.Bind(new IPEndPoint(IPAddress.Loopback, 54321));
            tcp.Listen(10, (_, status, error, state) =>
            {
                Console.WriteLine("Connected");
                var tcp2 = new UvTcpHandle();
                tcp2.Init(loop);
                tcp.Accept(tcp2);
                var data = Marshal.AllocCoTaskMem(500);
                tcp2.ReadStart(
                    (a, b, c) => _uv.buf_init(data, 500),
                    (__, nread, error2, state2) =>
                {
                    bytesRead += nread;
                    if (nread == 0)
                    {
                        tcp2.Dispose();
                    }
                },
                    null);
                tcp.Dispose();
            }, null);
            Console.WriteLine("Task.Run");
            var t = Task.Run(async() =>
            {
                var socket = new Socket(
                    AddressFamily.InterNetwork,
                    SocketType.Stream,
                    ProtocolType.Tcp);
                await Task.Factory.FromAsync(
                    socket.BeginConnect,
                    socket.EndConnect,
                    new IPEndPoint(IPAddress.Loopback, 54321),
                    null,
                    TaskCreationOptions.None);
                await Task.Factory.FromAsync(
                    socket.BeginSend,
                    socket.EndSend,
                    new[] { new ArraySegment <byte>(new byte[] { 1, 2, 3, 4, 5 }) },
                    SocketFlags.None,
                    null,
                    TaskCreationOptions.None);
                socket.Dispose();
            });

            loop.Run();
            loop.Dispose();
            await t;
        }
        public async Task SocketCanRead()
        {
            var loop = new UvLoopHandle(_logger);

            loop.Init(_uv);
            var tcp = new UvTcpHandle(_logger);

            tcp.Init(loop, (a, b) => { });
            var address = ServerAddress.FromUrl($"http://127.0.0.1:0/");

            tcp.Bind(address);
            var port = tcp.GetSockIPEndPoint().Port;

            tcp.Listen(10, (_, status, error, state) =>
            {
                var tcp2 = new UvTcpHandle(_logger);
                tcp2.Init(loop, (a, b) => { });
                tcp.Accept(tcp2);
                var data = Marshal.AllocCoTaskMem(500);
                tcp2.ReadStart(
                    (a, b, c) => _uv.buf_init(data, 500),
                    (__, nread, state2) =>
                {
                    if (nread <= 0)
                    {
                        tcp2.Dispose();
                    }
                },
                    null);
                tcp.Dispose();
            }, null);
            var t = Task.Run(async() =>
            {
                var socket = TestConnection.CreateConnectedLoopbackSocket(port);
#if NET451
                await Task.Factory.FromAsync(
                    socket.BeginSend,
                    socket.EndSend,
                    new[] { new ArraySegment <byte>(new byte[] { 1, 2, 3, 4, 5 }) },
                    SocketFlags.None,
                    null,
                    TaskCreationOptions.None);
#else
                await socket.SendAsync(new[] { new ArraySegment <byte>(new byte[] { 1, 2, 3, 4, 5 }) },
                                       SocketFlags.None);
#endif
                socket.Dispose();
            });

            loop.Run();
            loop.Dispose();
            await t;
        }
예제 #4
0
        private unsafe void WriteArraySegmentInternal(
            UvStreamHandle handle,
            ArraySegment <ArraySegment <byte> > bufs,
            UvStreamHandle sendHandle,
            Action <UvWriteReq, int, UvException, object> callback,
            object state)
        {
            try
            {
                var pBuffers = (Uv.uv_buf_t *)_bufs;
                var nBuffers = bufs.Count;
                if (nBuffers > BUFFER_COUNT)
                {
                    // create and pin buffer array when it's larger than the pre-allocated one
                    var bufArray = new Uv.uv_buf_t[nBuffers];
                    var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
                    _pins.Add(gcHandle);
                    pBuffers = (Uv.uv_buf_t *)gcHandle.AddrOfPinnedObject();
                }

                for (var index = 0; index < nBuffers; index++)
                {
                    // create and pin each segment being written
                    var buf = bufs.Array[bufs.Offset + index];

                    var gcHandle = GCHandle.Alloc(buf.Array, GCHandleType.Pinned);
                    _pins.Add(gcHandle);
                    pBuffers[index] = Libuv.buf_init(
                        gcHandle.AddrOfPinnedObject() + buf.Offset,
                        buf.Count);
                }

                _callback = callback;
                _state    = state;

                if (sendHandle == null)
                {
                    _uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb);
                }
                else
                {
                    _uv.write2(this, handle, pBuffers, nBuffers, sendHandle, _uv_write_cb);
                }
            }
            catch
            {
                _callback = null;
                _state    = null;
                UnpinGcHandles();
                throw;
            }
        }
예제 #5
0
        private unsafe void Write(
            UvStreamHandle handle,
            ReadOnlySequence <byte> buffer,
            Action <UvWriteReq, int, UvException, object> callback,
            object state)
        {
            try
            {
                var nBuffers = 0;
                if (buffer.IsSingleSegment)
                {
                    nBuffers = 1;
                }
                else
                {
                    foreach (var _ in buffer)
                    {
                        nBuffers++;
                    }
                }

                var pBuffers = (Uv.uv_buf_t *)_bufs;
                if (nBuffers > BUFFER_COUNT)
                {
                    // create and pin buffer array when it's larger than the pre-allocated one
                    var bufArray = new Uv.uv_buf_t[nBuffers];
                    var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
                    _pins.Add(gcHandle);
                    pBuffers = (Uv.uv_buf_t *)gcHandle.AddrOfPinnedObject();
                }

                if (nBuffers == 1)
                {
                    var memory       = buffer.First;
                    var memoryHandle = memory.Pin();
                    _handles.Add(memoryHandle);

                    // Fast path for single buffer
                    pBuffers[0] = Libuv.buf_init(
                        (IntPtr)memoryHandle.Pointer,
                        memory.Length);
                }
                else
                {
                    var index = 0;
                    foreach (var memory in buffer)
                    {
                        // This won't actually pin the buffer since we're already using pinned memory
                        var memoryHandle = memory.Pin();
                        _handles.Add(memoryHandle);

                        // create and pin each segment being written
                        pBuffers[index] = Libuv.buf_init(
                            (IntPtr)memoryHandle.Pointer,
                            memory.Length);
                        index++;
                    }
                }

                _callback = callback;
                _state    = state;
                _uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb);
            }
            catch
            {
                _callback = null;
                _state    = null;
                UnpinGcHandles();
                throw;
            }
        }
예제 #6
0
        public unsafe void Write(
            UvStreamHandle handle,
            ReadableBuffer buffer,
            Action <UvWriteReq, int, object> callback,
            object state)
        {
            try
            {
                // Preserve the buffer for the async call
                _buffer = buffer.Preserve();
                buffer  = _buffer.Buffer;

                int nBuffers = 0;
                if (buffer.IsSingleSpan)
                {
                    nBuffers = 1;
                }
                else
                {
                    foreach (var span in buffer)
                    {
                        nBuffers++;
                    }
                }

                // add GCHandle to keeps this SafeHandle alive while request processing
                _pins.Add(GCHandle.Alloc(this, GCHandleType.Normal));

                var pBuffers = (Uv.uv_buf_t *)_bufs;
                if (nBuffers > BUFFER_COUNT)
                {
                    // create and pin buffer array when it's larger than the pre-allocated one
                    var bufArray = new Uv.uv_buf_t[nBuffers];
                    var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
                    _pins.Add(gcHandle);
                    pBuffers = (Uv.uv_buf_t *)gcHandle.AddrOfPinnedObject();
                }

                if (nBuffers == 1)
                {
                    var   memory = buffer.First;
                    void *pointer;
                    if (memory.TryGetPointer(out pointer))
                    {
                        pBuffers[0] = Libuv.buf_init((IntPtr)pointer, memory.Length);
                    }
                    else
                    {
                        throw new InvalidOperationException("Memory needs to be pinned");
                    }
                }
                else
                {
                    int   i = 0;
                    void *pointer;
                    foreach (var memory in buffer)
                    {
                        if (memory.TryGetPointer(out pointer))
                        {
                            pBuffers[i++] = Libuv.buf_init((IntPtr)pointer, memory.Length);
                        }
                        else
                        {
                            throw new InvalidOperationException("Memory needs to be pinned");
                        }
                    }
                }

                _callback = callback;
                _state    = state;
                _uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb);
            }
            catch
            {
                _callback = null;
                _state    = null;
                _buffer.Dispose();
                Unpin(this);
                throw;
            }
        }
예제 #7
0
        private unsafe void Write(
            UvStreamHandle handle,
            ReadOnlySequence <byte> buffer,
            Action <UvWriteReq, int, object> callback,
            object state)
        {
            try
            {
                int nBuffers = 0;
                if (buffer.IsSingleSegment)
                {
                    nBuffers = 1;
                }
                else
                {
                    foreach (var span in buffer)
                    {
                        nBuffers++;
                    }
                }

                // add GCHandle to keeps this SafeHandle alive while request processing
                _pins.Add(GCHandle.Alloc(this, GCHandleType.Normal));

                var pBuffers = (Uv.uv_buf_t *)_bufs;
                if (nBuffers > BUFFER_COUNT)
                {
                    // create and pin buffer array when it's larger than the pre-allocated one
                    var bufArray = new Uv.uv_buf_t[nBuffers];
                    var gcHandle = GCHandle.Alloc(bufArray, GCHandleType.Pinned);
                    _pins.Add(gcHandle);
                    pBuffers = (Uv.uv_buf_t *)gcHandle.AddrOfPinnedObject();
                }

                if (nBuffers == 1)
                {
                    var memory       = buffer.First;
                    var memoryHandle = memory.Retain(pin: true);
                    _handles.Add(memoryHandle);
                    pBuffers[0] = Libuv.buf_init((IntPtr)memoryHandle.Pointer, memory.Length);
                }
                else
                {
                    int i = 0;
                    foreach (var memory in buffer)
                    {
                        var memoryHandle = memory.Retain(pin: true);
                        _handles.Add(memoryHandle);
                        pBuffers[i++] = Libuv.buf_init((IntPtr)memoryHandle.Pointer, memory.Length);
                    }
                }

                _callback = callback;
                _state    = state;
                _uv.write(this, handle, pBuffers, nBuffers, _uv_write_cb);
            }
            catch
            {
                _callback = null;
                _state    = null;
                Unpin(this);
                throw;
            }
        }