예제 #1
0
        public MultipleLoopTests()
        {
            var engine = new KestrelEngine(new TestServiceContext());

            _uv     = engine.Libuv;
            _logger = engine.Log;
        }
예제 #2
0
        internal static void _WriteCallback(IntPtr handle, int status)
        {
            var request = FromIntPtr <UvWriteRequest>(handle);

            foreach (var gcHandle in request._PinnedWriteHandles)
            {
                gcHandle.Free();
            }
            request._PinnedWriteHandles.Clear();

            var callback = request.Callback;

            request.Callback = null;

            var state = request.State;

            request.State = null;

            Exception error;

            Libuv.CheckStatusCode(status, out error);

            if (callback != null)
            {
                callback.Invoke(request, error, state);
            }

            request.Close();
        }
예제 #3
0
        /// <summary>
        /// Executes the request on the base handle.
        /// </summary>
        public void Connect()
        {
            var addr = SockAddr.FromIpEndPoint(this.EndPoint);

            Libuv.EnsureSuccess(Libuv.uv_tcp_connect(this, this.BaseHandle, ref addr, _UvConnectCallback));
            this.EndPoint = null;
        }
예제 #4
0
        /// <summary>
        /// Starts reading data from an incoming stream.
        /// The <paramref name="readCallback"/> will be executed several times until the stream closes or <see cref="ReadStop"/> method is called.
        /// </summary>
        /// <param name="allocCallback">Allocation callback.</param>
        /// <param name="readCallback">Read callback.</param>
        /// <param name="state">State to be passed to the callbacks.</param>
        public void ReadStart(AllocCallbackDelegate allocCallback, ReadCallbackDelegate readCallback, object state = null)
        {
            this.EnsureCallingThread();
            if (this._ReadVitality.IsAllocated)
            {
                throw new InvalidOperationException("ReadStop must be called before ReadStart may be called again.");
            }

            try
            {
                this._ReadVitality      = GCHandle.Alloc(this, GCHandleType.Normal);
                this._UserAllocCallback = allocCallback;
                this._UserReadCallback  = readCallback;
                this._UserReadState     = state;

                Libuv.EnsureSuccess(Libuv.uv_read_start(this, _UvAllocCallback, _UvReadCallback));
            }
            catch (Exception)
            {
                this._UserAllocCallback = null;
                this._UserReadCallback  = null;
                this._UserReadState     = null;
                if (this._ReadVitality.IsAllocated)
                {
                    this._ReadVitality.Free();
                }
                throw;
            }
        }
예제 #5
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;
            }
        }
        public NetworkingTests()
        {
            var engine = new KestrelEngine(new TestServiceContext());

            _uv     = engine.Libuv;
            _logger = engine.Log;
        }
예제 #7
0
        public void Connect(
            UvTcpHandle socket,
            IPEndPoint endpoint,
            Action <UvConnectRequest, int, Exception, object> callback,
            object state)
        {
            _callback = callback;
            _state    = state;

            SockAddr addr;
            var      addressText = endpoint.Address.ToString();

            Exception error1;

            _uv.ip4_addr(addressText, endpoint.Port, out addr, out error1);

            if (error1 != null)
            {
                Exception error2;
                _uv.ip6_addr(addressText, endpoint.Port, out addr, out error2);
                if (error2 != null)
                {
                    throw error1;
                }
            }

            Pin();
            Libuv.tcp_connect(this, socket, ref addr, _uv_connect_cb);
        }
예제 #8
0
        /// <summary>
        /// Start listening for incoming connections.
        /// </summary>
        /// <param name="backlog">Indicates the number of connections the kernel might queue.</param>
        /// <param name="callback">Callback to be called when a new incoming connection is received.</param>
        /// <param name="state">State to be passed to the callback.</param>
        public void Listen(int backlog, ListenCallbackDelegate callback, object state = null)
        {
            this.EnsureCallingThread();
            if (this._ListenVitality.IsAllocated)
            {
                throw new InvalidOperationException("Listen may not be called more than once.");
            }
            try
            {
                this._UserListenCallback = callback;
                this._UserListenState    = state;
                this._ListenVitality     = GCHandle.Alloc(this, GCHandleType.Normal);

                Libuv.EnsureSuccess(Libuv.uv_listen(this, backlog, _UvListenCallback));
            }
            catch
            {
                this._UserListenCallback = null;
                this._UserListenState    = null;
                if (this._ListenVitality.IsAllocated)
                {
                    this._ListenVitality.Free();
                }
                throw;
            }
        }
예제 #9
0
        /// <summary>
        /// Executes the write request on the base handle.
        /// </summary>
        public void Write()
        {
            this.EnsureCallingThread();
            try
            {
                // Build UvBuffers to write
                var buffers   = this.Buffers;
                var count     = buffers.Count;
                var uvBuffers = new UvBuffer[count];
                for (int i = 0; i < count; i++)
                {
                    var buffer             = buffers[i];
                    var pinnedBufferHandle = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
                    this._PinnedWriteHandles.Add(pinnedBufferHandle);

                    uvBuffers[i] = Libuv.uv_buf_init(Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset), buffer.Count);
                }

                this.Write(uvBuffers);
            }
            catch (Exception)
            {
                foreach (var gcHandle in this._PinnedWriteHandles)
                {
                    gcHandle.Free();
                }
                this._PinnedWriteHandles.Clear();
                throw;
            }
        }
예제 #10
0
파일: UvTcp.cs 프로젝트: codecopy/NLibuv
        /// <summary>
        /// Binds the handle to the specified end point.
        /// </summary>
        /// <param name="endPoint"></param>
        public void Bind(IPEndPoint endPoint)
        {
            this.EnsureCallingThread();

            var addr = SockAddr.FromIpEndPoint(endPoint);

            Libuv.EnsureSuccess(Libuv.uv_tcp_bind(this, ref addr, 0));
        }
예제 #11
0
        private static void _ListenCallback(IntPtr serverPtr, int status)
        {
            var stream = FromIntPtr <UvNetworkStream>(serverPtr);

            Exception error;

            Libuv.CheckStatusCode(status, out error);

            stream._UserListenCallback.Invoke(stream, error, stream._UserListenState);
        }
예제 #12
0
        public void Connect(
            UvPipeHandle pipe,
            string name,
            Action <UvConnectRequest, int, UvException, object> callback,
            object state)
        {
            _callback = callback;
            _state    = state;

            Libuv.pipe_connect(this, pipe, name, _uv_connect_cb);
        }
예제 #13
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;
            }
        }
예제 #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UvPrepare"/> handle.
        /// </summary>
        /// <param name="loop">Loop, on which this handle will be initialized.</param>
        /// <param name="callback">Callback, which will be invoked every loop iteration.</param>
        /// <param name="state">A state object to be stored in the handle for later use inside the callback.</param>
        public UvPrepare(UvLoop loop, Action <UvPrepare> callback, object state)
            : base(loop, UvHandleType.Prepare)
        {
            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            this._Callback = callback;
            this._State    = state;
            Libuv.EnsureSuccess(Libuv.uv_prepare_init(loop, this));
            this.NeedsToBeClosed = true;
        }
예제 #15
0
파일: UvAsync.cs 프로젝트: codecopy/NLibuv
        /// <summary>
        /// Initializes a new instance of the <see cref="UvAsync"/> handle.
        /// </summary>
        /// <param name="loop">Loop, on which this handle will be initialized.</param>
        /// <param name="callback">A callback, which will be executed after a loop will receive an async signal from this handle.</param>
        /// <param name="state">A state object to be stored in the handle for later use inside the callback.</param>
        public UvAsync(UvLoop loop, Action <UvAsync> callback, object state = null)
            : base(loop, UvHandleType.Async)
        {
            if (callback == null)
            {
                throw new ArgumentNullException(nameof(callback));
            }

            this._Callback = callback;
            this._State    = state;
            Libuv.EnsureSuccess(Libuv.uv_async_init(loop, this, _UvAsyncCallback));
            this.NeedsToBeClosed = true;
        }
예제 #16
0
        /// <inheritdoc/>
        protected override void CloseHandle()
        {
            this.EnsureCallingThread();

            // Protect the managed object from being collected by GC during closing inside the libuv logic
            if (!this._ClosingHandle.IsAllocated)
            {
                this._ClosingHandle = GCHandle.Alloc(this, GCHandleType.Normal);
            }

            // Object disposing will be performed inside a callback
            Libuv.uv_close(this, _UvCloseCallback);
        }
예제 #17
0
        /// <summary>
        /// Stops data reading for the stream. The <see cref="ReadCallbackDelegate"/> callback will no longer be called.
        /// </summary>
        public void ReadStop()
        {
            this.EnsureCallingThread();
            if (!this._ReadVitality.IsAllocated)
            {
                throw new InvalidOperationException("ReadStart must be called before ReadStop may be called.");
            }
            this._UserAllocCallback = null;
            this._UserReadCallback  = null;
            this._UserReadState     = null;
            this._ReadVitality.Free();

            Libuv.EnsureSuccess(Libuv.uv_read_stop(this));
        }
예제 #18
0
파일: UvTcp.cs 프로젝트: codecopy/NLibuv
        /// <summary>
        /// Get the address of the peer connected to the handle.
        /// </summary>
        /// <returns></returns>
        public IPEndPoint GetSockEndPoint()
        {
            this.EnsureCallingThread();

            SockAddr socketAddress;

#if DOTNET_CORE
            int namelen = Marshal.SizeOf <SockAddr>();
#else
            int namelen = Marshal.SizeOf(typeof(SockAddr));
#endif
            Libuv.EnsureSuccess(Libuv.uv_tcp_getsockname(this, out socketAddress, ref namelen));

            return(socketAddress.ToIpEndPoint());
        }
예제 #19
0
        private static void _ReadCallback(IntPtr streamPtr, int nread, ref UvBuffer buf)
        {
            var stream = FromIntPtr <UvStream>(streamPtr);

            foreach (var gcHandle in stream._PinnedReadHandles)
            {
                gcHandle.Free();
            }
            stream._PinnedReadHandles.Clear();

            Exception error;

            Libuv.CheckStatusCode(nread, out error);

            stream._UserReadCallback.Invoke(stream, nread, error, stream._UserReadState);
        }
예제 #20
0
        public KestrelEngine(ILibraryManager libraryManager, IApplicationShutdown appShutdownService)
        {
            AppShutdown = appShutdownService;
            Threads     = new List <KestrelThread>();
            Listeners   = new List <Listener>();
            Memory      = new MemoryPool();
            Libuv       = new Libuv();

            var libraryPath = default(string);

            if (libraryManager != null)
            {
                var library = libraryManager.GetLibraryInformation("Microsoft.AspNet.Server.Kestrel");
                libraryPath = library.Path;
                if (library.Type == "Project")
                {
                    libraryPath = Path.GetDirectoryName(libraryPath);
                }
                if (Libuv.IsWindows)
                {
                    var architecture = IntPtr.Size == 4
                        ? "x86"
                        : "amd64";

                    libraryPath = Path.Combine(
                        libraryPath,
                        "native",
                        "windows",
                        architecture,
                        "libuv.dll");
                }
                else if (Libuv.IsDarwin)
                {
                    libraryPath = Path.Combine(
                        libraryPath,
                        "native",
                        "darwin",
                        "universal",
                        "libuv.dylib");
                }
                else
                {
                    libraryPath = "libuv.so.1";
                }
            }
            Libuv.Load(libraryPath);
        }
예제 #21
0
        public KestrelEngine(ILibraryManager libraryManager, ServiceContext context)
            : this(context)
        {
            Libuv = new Libuv();

            var libraryPath = default(string);

            if (libraryManager != null)
            {
                var library = libraryManager.GetLibrary("Microsoft.AspNet.Server.Kestrel");
                libraryPath = library.Path;
                if (library.Type == "Project")
                {
                    libraryPath = Path.GetDirectoryName(libraryPath);
                }
                if (Libuv.IsWindows)
                {
                    var architecture = IntPtr.Size == 4
                        ? "x86"
                        : "x64";

                    libraryPath = Path.Combine(
                        libraryPath,
                        "runtimes",
                        "win7-" + architecture,
                        "native",
                        "libuv.dll");
                }
                else if (Libuv.IsDarwin)
                {
                    libraryPath = Path.Combine(
                        libraryPath,
                        "runtimes",
                        "osx",
                        "native",
                        "libuv.dylib");
                }
                else
                {
                    libraryPath = "libuv.so.1";
                }
            }
            Libuv.Load(libraryPath);
        }
예제 #22
0
        private void RunLoop()
        {
            Uv  = new Libuv();
            Log = new KestrelTrace(new LoggerFactory().CreateLogger <UvTcpListener>());

            Loop = new UvLoopHandle(Log);
            Loop.Init(Uv);

            _shutdownPostHandle = new UvAsyncHandle(Log);
            _shutdownPostHandle.Init(Loop, OnPost, _queueCloseCallback);

            _listenSocket = new UvTcpHandle(Log);
            _listenSocket.Init(Loop, _queueCloseCallback);
            _listenSocket.NoDelay(true);

            string host = null;

            if (_ip == IPAddress.Any)
            {
                host = "*";
            }
            else if (_ip == IPAddress.Loopback)
            {
                host = "localhost";
            }
            else
            {
                host = _ip.ToString();
            }

            var url     = $"http://{host}:{_port}";
            var address = Microsoft.AspNetCore.Server.Kestrel.ServerAddress.FromUrl(url);

            _listenSocket.Bind(address);

            _listenSocket.Listen(10, _onConnectionCallback, this);

            Uv.run(Loop, 0);
        }
예제 #23
0
        private static void _AllocCallback(IntPtr streamPtr, int suggestedSize, out UvBuffer buf)
        {
            var stream = FromIntPtr <UvStream>(streamPtr);

            try
            {
                var buffer             = stream._UserAllocCallback.Invoke(stream, suggestedSize, stream._UserReadState);
                var pinnedBufferHandle = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
                stream._PinnedReadHandles.Add(pinnedBufferHandle);

                buf = Libuv.uv_buf_init(Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset), buffer.Count);
            }
            catch (Exception)
            {
                foreach (var gcHandle in stream._PinnedReadHandles)
                {
                    gcHandle.Free();
                }
                stream._PinnedReadHandles.Clear();
                buf = Libuv.uv_buf_init(IntPtr.Zero, 0);
                throw;
            }
        }
예제 #24
0
        private static void _ConnectCallback(IntPtr handle, int status)
        {
            var request = FromIntPtr <UvTcpConnectRequest>(handle);

            var callback = request.Callback;

            request.Callback = null;

            var state = request.State;

            request.State = null;

            Exception error;

            Libuv.CheckStatusCode(status, out error);

            if (callback != null)
            {
                callback.Invoke(request, error, state);
            }

            request.Close();
        }
예제 #25
0
 private static int _CalculateSize(UvHandleType handleType)
 {
     return(Libuv.uv_handle_size(handleType).ToInt32());
 }
예제 #26
0
 /// <summary>
 /// This call is used in conjunction with <see cref="Listen"/> to accept incoming connections.
 /// Call this function after receiving a <see cref="ListenCallbackDelegate"/> to accept the connection.
 /// </summary>
 /// <param name="client"></param>
 public void Accept(UvStream client)
 {
     this.EnsureCallingThread();
     Libuv.EnsureSuccess(Libuv.uv_accept(this, client));
 }
예제 #27
0
        /// <summary>
        /// Set the number of pending pipe instance handles when the pipe server is waiting for connections.
        /// </summary>
        /// <param name="count"></param>
        public void SetPendingInstances(int count)
        {
            this.EnsureCallingThread();

            Libuv.uv_pipe_pending_instances(this, count);
        }
예제 #28
0
파일: UvTcp.cs 프로젝트: codecopy/NLibuv
 /// <summary>
 /// Enables / disables Nagle’s algorithm.
 /// </summary>
 /// <param name="enable"></param>
 public void NoDelay(bool enable)
 {
     this.EnsureCallingThread();
     Libuv.EnsureSuccess(Libuv.uv_tcp_nodelay(this, enable ? 1 : 0));
 }
예제 #29
0
파일: UvTcp.cs 프로젝트: codecopy/NLibuv
 /// <summary>
 /// Opens an existing file descriptor or SOCKET as a TCP handle.
 /// </summary>
 /// <param name="hSocket"></param>
 public void Open(IntPtr hSocket)
 {
     this.EnsureCallingThread();
     Libuv.EnsureSuccess(Libuv.uv_tcp_open(this, hSocket));
 }
예제 #30
0
파일: UvTcp.cs 프로젝트: codecopy/NLibuv
 /// <summary>
 /// Initializes a new instance of <see cref="UvTcp"/> handle on the given event loop.
 /// </summary>
 /// <param name="loop"></param>
 public UvTcp(UvLoop loop) : base(loop, UvHandleType.Tcp)
 {
     Libuv.EnsureSuccess(Libuv.uv_tcp_init(loop, this));
     this.NeedsToBeClosed = true;
 }