├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── msbuildpath.exe ├── src ├── Libuv.Tests │ ├── Libuv.Tests.csproj │ └── webserver.cs ├── Libuv.sln └── Libuv │ ├── CheckWatcher.cs │ ├── ChildProcess.cs │ ├── IdleWatcher.cs │ ├── Libuv.csproj │ ├── PipeServer.cs │ ├── PipeSocket.cs │ ├── PrepareWatcher.cs │ ├── TcpServer.cs │ ├── TcpSocket.cs │ ├── TimerWatcher.cs │ ├── UV.cs │ ├── UVStream.cs │ └── Watcher.cs └── winbuild.bat /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libuv"] 2 | path = deps/libuv 3 | url = git://github.com/joyent/libuv.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Kerry Snyder 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ##### 2 | uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') 3 | 4 | CSBUILD=xbuild 5 | UVFLAGS=CPPFLAGS="-m32" 6 | CC=$(PREFIX)gcc 7 | 8 | STATIC_LIBRARY=so 9 | 10 | ifeq (Darwin,$(uname_S)) 11 | STATIC_LIBRARY=dylib 12 | endif 13 | 14 | so=-shared 15 | dylib=-dynamiclib -framework CoreServices 16 | ##### 17 | TEST_DIRS = src/Libuv.Tests 18 | TEST_DEPS := $(foreach dir, $(TEST_DIRS), $(wildcard $(dir)/*)) 19 | LIBUV_DIRS = src/Libuv 20 | LIBUV_DEPS := $(foreach dir, $(LIBUV_DIRS), $(wildcard $(dir)/*)) 21 | 22 | all: build/Libuv.Tests.exe 23 | 24 | build/Libuv.dll: build/libuv.$(STATIC_LIBRARY) $(LIBUV_DEPS) 25 | $(CSBUILD) src/Libuv.sln /target:Libuv 26 | 27 | build/Libuv.Tests.exe: build/Libuv.dll $(TEST_DEPS) 28 | $(CSBUILD) src/Libuv.sln 29 | 30 | deps/libuv/uv.a: 31 | mkdir build/ 32 | $(UVFLAGS) $(MAKE) -C deps/libuv 33 | 34 | build/libuv.%: deps/libuv/uv.a 35 | ar -x deps/libuv/uv.a 36 | $(CC) $($(STATIC_LIBRARY)) -m32 -o build/libuv.$(STATIC_LIBRARY) *.o 37 | rm -rf __.SYMDEF\ SORTED *.o 38 | 39 | clean: 40 | $(RM) -r build/ 41 | $(MAKE) -C deps/libuv clean 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | libuv-sharp 2 | ========== 3 | 4 | What 5 | ---- 6 | 7 | C# bindings to [libuv][0]... that's about it. Ultimate goal is to provide really good cross-platform evented sockets for [manos][1]. 8 | 9 | Status 10 | ----- 11 | 12 | Builds and runs on Windows, Mac and Linux. 13 | 14 | Requirements 15 | ------------ 16 | 17 | ### *nixes 18 | 19 | * [Mono][2] (Tested under 2.10.2) 20 | * gcc 21 | 22 | ### Windows 23 | 24 | * MSVC 2010 (Not tested with the express edition, but it should work) 25 | * MSVC# 2010 26 | 27 | Build and Run 28 | ------------- 29 | 30 | ### Get it 31 | 32 | git pull git://github.com/kersny/libuv-csharp.git 33 | git submodule update --init 34 | 35 | ### *nixes 36 | 37 | make 38 | mono build/Libuv.Tests.exe 39 | (to clean) make clean 40 | 41 | ### Windows 42 | 43 | winbuild.bat 44 | cd build 45 | Libuv.Tests.exe 46 | (to clean) winbuild.bat clean 47 | 48 | 49 | 50 | Somewhere else: 51 | 52 | telnet localhost 8080 53 | 54 | 55 | TODO 56 | ---- 57 | 58 | * Test for Memory Leaks 59 | * Fix Child Processes 60 | * Proper test suite to make bumping UV Version easier 61 | * Auto-generated struct sizes for all platforms 62 | 63 | [0]: https://www.github.com/joyent/libuv 64 | [1]: https://www.github.com/jacksonh/manos 65 | [2]: http://www.go-mono.com/mono-downloads/download.html 66 | -------------------------------------------------------------------------------- /msbuildpath.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kersny/libuv-csharp/003229328bc05ce3143c2a20c22f23524efeda5d/msbuildpath.exe -------------------------------------------------------------------------------- /src/Libuv.Tests/Libuv.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E} 9 | Exe 10 | Libuv 11 | Libuv.Tests 12 | v4.0 13 | ../../build/tmp/ 14 | 15 | 16 | true 17 | full 18 | false 19 | ../../build/ 20 | DEBUG 21 | prompt 22 | 4 23 | false 24 | true 25 | 1591 26 | x86 27 | 28 | 29 | none 30 | false 31 | ../../build/ 32 | prompt 33 | 4 34 | false 35 | true 36 | 1591 37 | x86 38 | 39 | 40 | 41 | 42 | Libuv 43 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F} 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/Libuv.Tests/webserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.IO; 4 | using System.Net; 5 | using Libuv; 6 | 7 | namespace Libuv.Tests { 8 | class webserver { 9 | [DllImport ("uv")] 10 | public static extern void uv_init (); 11 | [DllImport ("uv")] 12 | public static extern void uv_run (); 13 | static int clientcount = 0; 14 | static void Main () 15 | { 16 | var endpoint = new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1}), 8081); 17 | uv_init(); 18 | 19 | var watch = new PrepareWatcher(() => { 20 | //Console.WriteLine("Prepare Watcher Called"); 21 | }); 22 | watch.Start(); 23 | var server = new TcpServer((socket) => { 24 | clientcount++; 25 | socket.Stream.Write(System.Text.Encoding.ASCII.GetBytes(clientcount.ToString()), 1); 26 | if (clientcount > 5) { 27 | socket.Close(); 28 | } 29 | Console.WriteLine("Client Connected"); 30 | socket.Stream.OnRead += (data) => { 31 | Console.WriteLine("Data Recieved: {0}", System.Text.Encoding.ASCII.GetString(data, 0, data.Length)); 32 | socket.Stream.Write(data, data.Length); 33 | }; 34 | //socket.OnClose += () => { 35 | // Console.WriteLine("Client Disconnected"); 36 | //}; 37 | }); 38 | server.Listen(endpoint); 39 | var client = new TcpSocket(); 40 | client.Connect(endpoint, () => { 41 | client.Stream.OnRead += (data) => { 42 | Console.WriteLine("Client Recieved: {0}", System.Text.Encoding.ASCII.GetString(data, 0, data.Length)); 43 | watch.Stop(); 44 | watch.Dispose(); 45 | client.Close(); 46 | }; 47 | byte[] message = System.Text.Encoding.ASCII.GetBytes("Hello World\n"); 48 | client.Stream.Write(message, message.Length); 49 | }); 50 | var pipeserver = new PipeServer((socket) => { 51 | clientcount++; 52 | socket.Stream.Write(System.Text.Encoding.ASCII.GetBytes(clientcount.ToString()), 1); 53 | if (clientcount > 5) { 54 | socket.Close(); 55 | } 56 | Console.WriteLine("Pipe Client Connected"); 57 | socket.Stream.OnRead += (data) => { 58 | Console.WriteLine("Pipe Data Recieved: {0}", System.Text.Encoding.ASCII.GetString(data, 0, data.Length)); 59 | socket.Stream.Write(data, data.Length); 60 | }; 61 | //socket.OnClose += () => { 62 | // Console.WriteLine("Client Disconnected"); 63 | //}; 64 | }); 65 | pipeserver.Listen("libuv-csharp"); 66 | var pipeclient = new PipeSocket(); 67 | pipeclient.Connect("libuv-csharp", () => { 68 | pipeclient.Stream.OnRead += (data) => { 69 | Console.WriteLine("Pipe Client Recieved: {0}", System.Text.Encoding.ASCII.GetString(data, 0, data.Length)); 70 | watch.Stop(); 71 | watch.Dispose(); 72 | pipeclient.Close(); 73 | }; 74 | byte[] message = System.Text.Encoding.ASCII.GetBytes("Hello World\n"); 75 | pipeclient.Stream.Write(message, message.Length); 76 | }); 77 | var watch2 = new PrepareWatcher(() => { 78 | //Console.WriteLine("Prepare Watcher 2 Called"); 79 | }); 80 | watch2.Start(); 81 | var check = new CheckWatcher(() => { 82 | //Console.WriteLine("Check Watcher Called"); 83 | }); 84 | check.Start(); 85 | var idle = new IdleWatcher(() => { 86 | //Console.WriteLine("Idle Watcher Called"); 87 | }); 88 | idle.Start(); 89 | var after = new TimerWatcher(new TimeSpan(0,0,5), new TimeSpan(1,0,0), () => { 90 | //Console.WriteLine("After 5 Seconds"); 91 | }); 92 | after.Start(); 93 | var every = new TimerWatcher(new TimeSpan(0,0,5), () => { 94 | //Console.WriteLine("Every 5 Seconds"); 95 | // after.Stop(); 96 | }); 97 | every.Start(); 98 | var cp = new ChildProcess("ls"); 99 | cp.Spawn(); 100 | uv_run(); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Libuv.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2010 3 | Project("{13C31A1D-9AA8-43D7-BAEA-B9F4E9DE202B}") = "Libuv", "Libuv\Libuv.csproj", "{2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}" 4 | EndProject 5 | Project("{966921C3-BDCB-4030-9D41-5BBF59887EC2}") = "Libuv.Tests", "Libuv.Tests\Libuv.Tests.csproj", "{26D063C9-1C31-4D02-87DC-B92C8FA5952E}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Debug|Mixed Platforms = Debug|Mixed Platforms 11 | Debug|Win32 = Debug|Win32 12 | Release|Any CPU = Release|Any CPU 13 | Release|Mixed Platforms = Release|Mixed Platforms 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 18 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}.Debug|Any CPU.Build.0 = Debug|Any CPU 19 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 20 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 21 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}.Debug|Win32.ActiveCfg = Debug|Any CPU 22 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 25 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}.Release|Mixed Platforms.Build.0 = Release|Any CPU 26 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F}.Release|Win32.ActiveCfg = Release|Any CPU 27 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 30 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 31 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E}.Debug|Win32.ActiveCfg = Debug|Any CPU 32 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 35 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E}.Release|Mixed Platforms.Build.0 = Release|Any CPU 36 | {26D063C9-1C31-4D02-87DC-B92C8FA5952E}.Release|Win32.ActiveCfg = Release|Any CPU 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /src/Libuv/CheckWatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Libuv { 5 | public class CheckWatcher : Watcher { 6 | [DllImport("uv")] 7 | internal static extern int uv_check_init(IntPtr check); 8 | [DllImport("uv")] 9 | internal static extern int uv_check_start(IntPtr check, uv_watcher_cb cb); 10 | [DllImport("uv")] 11 | internal static extern int uv_check_stop(IntPtr check); 12 | 13 | public CheckWatcher(Action callback) : base(callback, Sizes.CheckWatcher) {} 14 | 15 | internal override int InitImpl() 16 | { 17 | return uv_check_init(this._handle); 18 | } 19 | internal override int StartImpl() 20 | { 21 | return uv_check_start(this._handle, StaticCallback); 22 | } 23 | internal override int StopImpl() 24 | { 25 | return uv_check_stop(this._handle); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Libuv/ChildProcess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.IO; 4 | using System.Collections.Generic; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace Libuv { 8 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 9 | public delegate void uv_exit_cb(IntPtr handle, int exit_status, int term_signal); 10 | [StructLayout(LayoutKind.Sequential)] 11 | public struct uv_process_options_t { 12 | public uv_exit_cb exit_cb; 13 | public string file; 14 | public IntPtr[] args; 15 | public IntPtr[] env; 16 | public string cwd; 17 | public int windows_verbatim_arguments; 18 | 19 | public IntPtr stdin_stream; 20 | public IntPtr stdout_stream; 21 | public IntPtr stderr_stream; 22 | } 23 | public class ChildProcess { 24 | [DllImport ("uv")] 25 | public static extern int uv_spawn(IntPtr process, uv_process_options_t options); 26 | [DllImport ("uv")] 27 | public static extern int uv_process_kill(IntPtr process, int signum); 28 | [DllImport ("uv")] 29 | public static extern int uv_pipe_init(IntPtr pipe); 30 | [DllImport ("uv")] 31 | public static extern int uv_close(IntPtr process, uv_close_cb cb); 32 | static void static_exit(IntPtr handle, int exit_status, int term_signal) 33 | { 34 | uv_close(handle, static_close); 35 | } 36 | static void static_close(IntPtr handle) 37 | { 38 | Marshal.FreeHGlobal(handle); 39 | } 40 | public string File { get; set; } 41 | public string CurrentWorkingDirectory { get; set; } 42 | public List Environment { get; private set; } 43 | public List Arguments { get; private set; } 44 | private IntPtr _handle; 45 | public UVStream StdOut; 46 | public UVStream StdErr; 47 | private IntPtr _stdout; 48 | private IntPtr _stderr; 49 | //public event Action OnExit; 50 | //private void HandleExit(string stdout, string stderr); 51 | 52 | public ChildProcess(string command) 53 | { 54 | this.File = command; 55 | this.CurrentWorkingDirectory = Directory.GetCurrentDirectory(); 56 | this._stdout = Marshal.AllocHGlobal(Sizes.PipeT); 57 | uv_pipe_init(_stdout); 58 | this.StdOut = new UVStream(_stdout); 59 | this._stderr = Marshal.AllocHGlobal(Sizes.PipeT); 60 | uv_pipe_init(_stdout); 61 | this.StdOut = new UVStream(_stdout); 62 | this._handle = Marshal.AllocHGlobal(Sizes.ProcessT); 63 | } 64 | public void Spawn() 65 | { 66 | var options = new uv_process_options_t(); 67 | options.exit_cb = static_exit; 68 | options.file = this.File; 69 | var args = new IntPtr[Arguments.Count + 3]; 70 | args[0] = Marshal.StringToHGlobalAuto(this.CurrentWorkingDirectory); 71 | args[1] = Marshal.StringToHGlobalAuto(this.File); 72 | args[args.Length - 1] = IntPtr.Zero; 73 | for (int i = 0; i < Arguments.Count; i++) 74 | { 75 | args[i + 2] = Marshal.StringToHGlobalAuto(Arguments[i]); 76 | } 77 | options.args = args; 78 | var env = new IntPtr[Environment.Count + 1]; 79 | env[Environment.Count - 1] = IntPtr.Zero; 80 | for (int i = 0; i < Environment.Count; i++) 81 | { 82 | env[i] = Marshal.StringToHGlobalAuto(Environment[i]); 83 | } 84 | options.env = env; 85 | options.stdout_stream = _stdout; 86 | options.stderr_stream = _stderr; 87 | Util.CheckError(uv_spawn(_handle, options)); 88 | StdOut.ReadStart(); 89 | StdErr.ReadStart(); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Libuv/IdleWatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Libuv { 5 | public class IdleWatcher : Watcher { 6 | [DllImport("uv")] 7 | internal static extern int uv_idle_init(IntPtr idle); 8 | [DllImport("uv")] 9 | internal static extern int uv_idle_start(IntPtr idle, uv_watcher_cb cb); 10 | [DllImport("uv")] 11 | internal static extern int uv_idle_stop(IntPtr idle); 12 | 13 | public IdleWatcher(Action callback) : base(callback, Sizes.IdleWatcher) {} 14 | 15 | internal override int InitImpl() 16 | { 17 | return uv_idle_init(this._handle); 18 | } 19 | internal override int StartImpl() 20 | { 21 | return uv_idle_start(this._handle, StaticCallback); 22 | } 23 | internal override int StopImpl() 24 | { 25 | return uv_idle_stop(this._handle); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Libuv/Libuv.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {2548B25A-2E1F-4E21-BC43-7E39B1F6F23F} 9 | library 10 | Libuv 11 | Libuv 12 | v4.0 13 | ../../build/tmp 14 | 15 | 16 | true 17 | full 18 | false 19 | ../../build 20 | DEBUG 21 | prompt 22 | 4 23 | false 24 | true 25 | 1591 26 | x86 27 | 28 | 29 | none 30 | false 31 | ../../build 32 | prompt 33 | 4 34 | false 35 | true 36 | 1591 37 | x86 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/Libuv/PipeServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace Libuv { 6 | public class PipeServer { 7 | [DllImport("uv")] 8 | internal static extern int uv_pipe_init(IntPtr prepare); 9 | [DllImport("uv")] 10 | internal static extern int uv_pipe_bind(IntPtr prepare, string name); 11 | [DllImport("uv")] 12 | internal static extern int uv_listen(IntPtr stream, int backlog, uv_connection_cb cb); 13 | 14 | private static uv_connection_cb unmanaged_callback; 15 | 16 | static PipeServer() 17 | { 18 | unmanaged_callback = StaticCallback; 19 | } 20 | 21 | private Action callback; 22 | private IntPtr _handle; 23 | private GCHandle me; 24 | 25 | public PipeServer(Action callback) 26 | { 27 | this.callback = callback; 28 | this._handle = Marshal.AllocHGlobal(Sizes.PipeT); 29 | Util.CheckError(uv_pipe_init(this._handle)); 30 | var handle = (uv_handle_t)Marshal.PtrToStructure(this._handle, typeof(uv_handle_t)); 31 | this.me = GCHandle.Alloc(this); 32 | handle.data = GCHandle.ToIntPtr(this.me); 33 | Marshal.StructureToPtr(handle, this._handle, true); 34 | } 35 | public void Listen(string endpoint) 36 | { 37 | Util.CheckError(uv_pipe_bind(this._handle, endpoint)); 38 | Util.CheckError(uv_listen(this._handle, 128, unmanaged_callback)); 39 | } 40 | public static void StaticCallback(IntPtr server_ptr, int status) 41 | { 42 | Util.CheckError(status); 43 | var handle = (uv_handle_t)Marshal.PtrToStructure(server_ptr, typeof(uv_handle_t)); 44 | var instance = GCHandle.FromIntPtr(handle.data); 45 | var server = (PipeServer)instance.Target; 46 | server.callback(new PipeSocket(server._handle)); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Libuv/PipeSocket.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace Libuv { 6 | public class PipeSocket { 7 | public UVStream Stream { get; private set; } 8 | static void unmanaged_connect_cb(IntPtr connection, int status) 9 | { 10 | Util.CheckError(status); 11 | var tmp = (uv_connect_t)Marshal.PtrToStructure(connection, typeof(uv_connect_t)); 12 | var handle = (uv_handle_t)Marshal.PtrToStructure(tmp.handle, typeof(uv_handle_t)); 13 | var instance = GCHandle.FromIntPtr(handle.data); 14 | var socket_instance = (PipeSocket)instance.Target; 15 | socket_instance.Stream = new UVStream(socket_instance._handle); 16 | socket_instance.Stream.ReadStart(); 17 | socket_instance.HandleConnect(); 18 | } 19 | static void on_close(IntPtr socket) 20 | { 21 | /* 22 | var handle = (uv_handle_t)Marshal.PtrToStructure(socket, typeof(uv_handle_t)); 23 | var instance = GCHandle.FromIntPtr(handle.data); 24 | var watcher_instance = (PipeSocket)instance.Target; 25 | //dont think this is what should happen here 26 | watcher_instance.me.Free(); 27 | Marshal.FreeHGlobal(socket); 28 | */ 29 | } 30 | private IntPtr _handle; 31 | public event Action OnConnect; 32 | private GCHandle me; 33 | private IntPtr connection; 34 | public PipeSocket() 35 | { 36 | this._handle = Marshal.AllocHGlobal(Sizes.PipeT); 37 | Util.CheckError(uv_pipe_init(this._handle)); 38 | var handle = (uv_handle_t)Marshal.PtrToStructure(this._handle, typeof(uv_handle_t)); 39 | this.me = GCHandle.Alloc(this); 40 | handle.data = GCHandle.ToIntPtr(this.me); 41 | Marshal.StructureToPtr(handle, this._handle, true); 42 | this.connection = Marshal.AllocHGlobal(Sizes.ConnectT); 43 | //can't attach anything to connect_t, it would get nulled 44 | } 45 | public void Connect(string path, Action OnConnect) 46 | { 47 | Util.CheckError(uv_pipe_connect(this.connection, this._handle, path, unmanaged_connect_cb)); 48 | this.OnConnect += OnConnect; 49 | } 50 | public PipeSocket(IntPtr ServerHandle) 51 | { 52 | this._handle = Marshal.AllocHGlobal(Sizes.PipeT); 53 | Util.CheckError(uv_pipe_init(this._handle)); 54 | Util.CheckError(uv_accept(ServerHandle, this._handle)); 55 | var handle = (uv_handle_t)Marshal.PtrToStructure(this._handle, typeof(uv_handle_t)); 56 | this.me = GCHandle.Alloc(this); 57 | handle.data = GCHandle.ToIntPtr(this.me); 58 | Marshal.StructureToPtr(handle, this._handle, true); 59 | this.Stream = new UVStream(this._handle); 60 | } 61 | private void HandleConnect() 62 | { 63 | if (OnConnect != null) 64 | { 65 | OnConnect(); 66 | } 67 | } 68 | public void Close() 69 | { 70 | uv_close(this._handle, on_close); 71 | } 72 | [DllImport("uv")] 73 | internal static extern int uv_pipe_init(IntPtr prepare); 74 | [DllImport ("uv")] 75 | internal static extern int uv_accept(IntPtr socket, IntPtr stream); 76 | [DllImport ("uv")] 77 | internal static extern int uv_close(IntPtr handle, uv_close_cb cb); 78 | [DllImport ("uv")] 79 | internal static extern int uv_pipe_connect(IntPtr connect, IntPtr tcp_handle, string path, uv_connect_cb cb); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Libuv/PrepareWatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Libuv { 5 | public class PrepareWatcher : Watcher { 6 | [DllImport("uv")] 7 | internal static extern int uv_prepare_init(IntPtr prepare); 8 | [DllImport("uv")] 9 | internal static extern int uv_prepare_start(IntPtr prepare, uv_watcher_cb cb); 10 | [DllImport("uv")] 11 | internal static extern int uv_prepare_stop(IntPtr prepare); 12 | 13 | public PrepareWatcher(Action callback) : base(callback, Sizes.PrepareWatcher) {} 14 | 15 | internal override int InitImpl() 16 | { 17 | return uv_prepare_init(this._handle); 18 | } 19 | internal override int StartImpl() 20 | { 21 | return uv_prepare_start(this._handle, StaticCallback); 22 | } 23 | internal override int StopImpl() 24 | { 25 | return uv_prepare_stop(this._handle); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Libuv/TcpServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace Libuv { 6 | public class TcpServer { 7 | [DllImport("uv")] 8 | internal static extern int uv_tcp_init(IntPtr prepare); 9 | [DllImport("uv")] 10 | internal static extern int uv_tcp_bind(IntPtr prepare, sockaddr_in address); 11 | [DllImport("uv")] 12 | internal static extern int uv_listen(IntPtr stream, int backlog, uv_connection_cb cb); 13 | [DllImport("uv")] 14 | internal static extern sockaddr_in uv_ip4_addr(string ip, int port); 15 | 16 | private static uv_connection_cb unmanaged_callback; 17 | 18 | static TcpServer() 19 | { 20 | unmanaged_callback = StaticCallback; 21 | } 22 | 23 | private Action callback; 24 | private IntPtr _handle; 25 | private GCHandle me; 26 | 27 | public TcpServer(Action callback) 28 | { 29 | this.callback = callback; 30 | this._handle = Marshal.AllocHGlobal(Sizes.TcpT); 31 | Util.CheckError(uv_tcp_init(this._handle)); 32 | var handle = (uv_handle_t)Marshal.PtrToStructure(this._handle, typeof(uv_handle_t)); 33 | this.me = GCHandle.Alloc(this); 34 | handle.data = GCHandle.ToIntPtr(this.me); 35 | Marshal.StructureToPtr(handle, this._handle, true); 36 | } 37 | public void Listen(IPEndPoint endpoint) 38 | { 39 | var info = uv_ip4_addr(endpoint.Address.ToString(), endpoint.Port); 40 | Util.CheckError(uv_tcp_bind(this._handle, info)); 41 | Util.CheckError(uv_listen(this._handle, 128, unmanaged_callback)); 42 | } 43 | public static void StaticCallback(IntPtr server_ptr, int status) 44 | { 45 | Util.CheckError(status); 46 | var handle = (uv_handle_t)Marshal.PtrToStructure(server_ptr, typeof(uv_handle_t)); 47 | var instance = GCHandle.FromIntPtr(handle.data); 48 | var server = (TcpServer)instance.Target; 49 | server.callback(new TcpSocket(server._handle)); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Libuv/TcpSocket.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace Libuv { 6 | public class TcpSocket { 7 | public UVStream Stream { get; private set; } 8 | static void unmanaged_connect_cb(IntPtr connection, int status) 9 | { 10 | Util.CheckError(status); 11 | var tmp = (uv_connect_t)Marshal.PtrToStructure(connection, typeof(uv_connect_t)); 12 | var handle = (uv_handle_t)Marshal.PtrToStructure(tmp.handle, typeof(uv_handle_t)); 13 | var instance = GCHandle.FromIntPtr(handle.data); 14 | var socket_instance = (TcpSocket)instance.Target; 15 | socket_instance.Stream = new UVStream(socket_instance._handle); 16 | socket_instance.Stream.ReadStart(); 17 | socket_instance.HandleConnect(); 18 | } 19 | static void on_close(IntPtr socket) 20 | { 21 | /* 22 | var handle = (uv_handle_t)Marshal.PtrToStructure(socket, typeof(uv_handle_t)); 23 | var instance = GCHandle.FromIntPtr(handle.data); 24 | var watcher_instance = (TcpSocket)instance.Target; 25 | //dont think this is what should happen here 26 | watcher_instance.me.Free(); 27 | Marshal.FreeHGlobal(socket); 28 | */ 29 | } 30 | private IntPtr _handle; 31 | public event Action OnConnect; 32 | private GCHandle me; 33 | private IntPtr connection; 34 | public TcpSocket() 35 | { 36 | this._handle = Marshal.AllocHGlobal(Sizes.TcpT); 37 | Util.CheckError(uv_tcp_init(this._handle)); 38 | var handle = (uv_handle_t)Marshal.PtrToStructure(this._handle, typeof(uv_handle_t)); 39 | this.me = GCHandle.Alloc(this); 40 | handle.data = GCHandle.ToIntPtr(this.me); 41 | Marshal.StructureToPtr(handle, this._handle, true); 42 | this.connection = Marshal.AllocHGlobal(Sizes.ConnectT); 43 | //can't attach anything to connect_t, it would get nulled 44 | } 45 | public void Connect(IPEndPoint endpoint, Action OnConnect) 46 | { 47 | var info = uv_ip4_addr(endpoint.Address.ToString(), endpoint.Port); 48 | Util.CheckError(uv_tcp_connect(this.connection, this._handle, info, unmanaged_connect_cb)); 49 | this.OnConnect += OnConnect; 50 | } 51 | public TcpSocket(IntPtr ServerHandle) 52 | { 53 | this._handle = Marshal.AllocHGlobal(Sizes.TcpT); 54 | Util.CheckError(uv_tcp_init(this._handle)); 55 | Util.CheckError(uv_accept(ServerHandle, this._handle)); 56 | var handle = (uv_handle_t)Marshal.PtrToStructure(this._handle, typeof(uv_handle_t)); 57 | this.me = GCHandle.Alloc(this); 58 | handle.data = GCHandle.ToIntPtr(this.me); 59 | Marshal.StructureToPtr(handle, this._handle, true); 60 | this.Stream = new UVStream(this._handle); 61 | } 62 | private void HandleConnect() 63 | { 64 | if (OnConnect != null) 65 | { 66 | OnConnect(); 67 | } 68 | } 69 | public void Close() 70 | { 71 | uv_close(this._handle, on_close); 72 | } 73 | [DllImport("uv")] 74 | internal static extern int uv_tcp_init(IntPtr prepare); 75 | [DllImport ("uv")] 76 | internal static extern int uv_accept(IntPtr socket, IntPtr stream); 77 | [DllImport ("uv")] 78 | internal static extern int uv_close(IntPtr handle, uv_close_cb cb); 79 | [DllImport ("uv")] 80 | internal static extern int uv_tcp_connect(IntPtr connect, IntPtr tcp_handle, sockaddr_in address, uv_connect_cb cb); 81 | [DllImport ("uv")] 82 | internal static extern sockaddr_in uv_ip4_addr(string ip, int port); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Libuv/TimerWatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Libuv { 5 | public class TimerWatcher : Watcher { 6 | [DllImport("uv")] 7 | internal static extern int uv_timer_init(IntPtr timer); 8 | [DllImport("uv")] 9 | internal static extern int uv_timer_start(IntPtr timer, uv_watcher_cb cb, double after, double repeat); 10 | [DllImport("uv")] 11 | internal static extern int uv_timer_stop(IntPtr timer); 12 | [DllImport("uv")] 13 | internal static extern int uv_timer_again(IntPtr timer); 14 | [DllImport("uv")] 15 | internal static extern int uv_timer_set_repeat(IntPtr timer, double time); 16 | 17 | private TimeSpan delay; 18 | private TimeSpan repeat; 19 | public TimeSpan Repeat { 20 | get { return repeat; } 21 | set { 22 | if (value < TimeSpan.Zero) 23 | throw new ArgumentException("value"); 24 | repeat = value; 25 | Util.CheckError(uv_timer_set_repeat(this._handle, repeat.TotalMilliseconds)); 26 | } 27 | } 28 | public TimerWatcher(TimeSpan repeat, Action callback) 29 | : this (TimeSpan.Zero, repeat, callback) 30 | { 31 | } 32 | public TimerWatcher(TimeSpan after, TimeSpan repeat, Action callback) : base(callback, Sizes.TimerWatcher) 33 | { 34 | this.repeat = repeat; 35 | this.delay = after; 36 | 37 | } 38 | internal override int InitImpl() 39 | { 40 | return uv_timer_init(this._handle); 41 | } 42 | internal override int StartImpl() 43 | { 44 | return uv_timer_start(this._handle, StaticCallback, delay.TotalMilliseconds, repeat.TotalMilliseconds); 45 | } 46 | internal override int StopImpl() 47 | { 48 | return uv_timer_stop(this._handle); 49 | } 50 | public void Again() 51 | { 52 | Util.CheckError(uv_timer_again(this._handle)); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Libuv/UV.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace Libuv { 6 | public static class Util { 7 | public static void CheckError(int code) 8 | { 9 | if (code != 0) throw new Exception(uv_strerror(uv_last_error())); 10 | } 11 | [DllImport ("uv")] 12 | public static extern uv_err_t uv_last_error(); 13 | [DllImport ("uv")] 14 | public static extern string uv_strerror(uv_err_t err); 15 | } 16 | [StructLayout(LayoutKind.Sequential)] 17 | public struct uv_handle_t { 18 | public uv_handle_type type; 19 | public IntPtr close_cb; 20 | public IntPtr data; 21 | } 22 | [StructLayout(LayoutKind.Sequential)] 23 | public struct uv_req_t { 24 | public uv_req_type type; 25 | public IntPtr data; 26 | } 27 | [StructLayout(LayoutKind.Sequential)] 28 | public struct uv_connect_t { 29 | public uv_req_type type; 30 | public IntPtr data; 31 | #if !__MonoCS__ 32 | NativeOverlapped overlapped; 33 | IntPtr queued_bytes; 34 | uv_err_t error; 35 | IntPtr next_req; 36 | #endif 37 | public IntPtr cb; 38 | public IntPtr handle; 39 | } 40 | [StructLayout(LayoutKind.Sequential)] 41 | public struct uv_shutdown_t { 42 | public uv_req_type type; 43 | public IntPtr data; 44 | #if !__MonoCS__ 45 | NativeOverlapped overlapped; 46 | IntPtr queued_bytes; 47 | uv_err_t error; 48 | IntPtr next_req; 49 | #endif 50 | public IntPtr handle; 51 | public IntPtr cb; 52 | } 53 | [StructLayout(LayoutKind.Sequential)] 54 | public struct uv_err_t 55 | { 56 | public uv_err_code code; 57 | int sys_errno_; 58 | } 59 | public enum uv_err_code 60 | { 61 | UV_UNKNOWN = -1, 62 | UV_OK = 0, 63 | UV_EOF, 64 | UV_EACCESS, 65 | UV_EAGAIN, 66 | UV_EADDRINUSE, 67 | UV_EADDRNOTAVAIL, 68 | UV_EAFNOSUPPORT, 69 | UV_EALREADY, 70 | UV_EBADF, 71 | UV_EBUSY, 72 | UV_ECONNABORTED, 73 | UV_ECONNREFUSED, 74 | UV_ECONNRESET, 75 | UV_EDESTADDRREQ, 76 | UV_EFAULT, 77 | UV_EHOSTUNREACH, 78 | UV_EINTR, 79 | UV_EINVAL, 80 | UV_EISCONN, 81 | UV_EMFILE, 82 | UV_ENETDOWN, 83 | UV_ENETUNREACH, 84 | UV_ENFILE, 85 | UV_ENOBUFS, 86 | UV_ENOMEM, 87 | UV_ENONET, 88 | UV_ENOPROTOOPT, 89 | UV_ENOTCONN, 90 | UV_ENOTSOCK, 91 | UV_ENOTSUP, 92 | UV_EPROTO, 93 | UV_EPROTONOSUPPORT, 94 | UV_EPROTOTYPE, 95 | UV_ETIMEDOUT, 96 | UV_ECHARSET, 97 | UV_EAIFAMNOSUPPORT, 98 | UV_EAINONAME, 99 | UV_EAISERVICE, 100 | UV_EAISOCKTYPE, 101 | UV_ESHUTDOWN 102 | } 103 | public enum uv_handle_type { 104 | UV_UNKNOWN_HANDLE = 0, 105 | UV_TCP, 106 | UV_NAMED_PIPE, 107 | UV_TTY, 108 | UV_FILE, 109 | UV_TIMER, 110 | UV_PREPARE, 111 | UV_CHECK, 112 | UV_IDLE, 113 | UV_ASYNC, 114 | UV_ARES_TASK, 115 | UV_ARES_EVENT, 116 | UV_GETADDRINFO, 117 | UV_PROCESS 118 | } 119 | public enum uv_req_type { 120 | UV_UNKNOWN_REQ = 0, 121 | UV_CONNECT, 122 | UV_ACCEPT, 123 | UV_READ, 124 | UV_WRITE, 125 | UV_SHUTDOWN, 126 | UV_WAKEUP, 127 | UV_REQ_TYPE_PRIVATE 128 | } 129 | public static class Sizes { 130 | #if __MonoCS__ 131 | public static readonly int PrepareWatcher = 64; 132 | public static readonly int IdleWatcher = 64; 133 | public static readonly int CheckWatcher = 64; 134 | public static readonly int TimerWatcher = 80; 135 | public static readonly int TcpT = 152; 136 | public static readonly int PipeT = 156; 137 | public static readonly int ShutdownT = 16; 138 | public static readonly int ConnectT = 24; 139 | public static readonly int WriteT = 68; 140 | public static readonly int ProcessT = 88; 141 | #else 142 | public static readonly int PrepareWatcher = 40; 143 | public static readonly int IdleWatcher = 40; 144 | public static readonly int CheckWatcher = 40; 145 | public static readonly int TimerWatcher = 72; 146 | public static readonly int TcpT = 436; 147 | public static readonly int ShutdownT = 52; 148 | public static readonly int ConnectT = 52; 149 | public static readonly int WriteT = 52; 150 | #endif 151 | } 152 | [StructLayout(LayoutKind.Sequential)] 153 | #if __MonoCS__ 154 | public struct uv_buf_t 155 | { 156 | public IntPtr data; 157 | public IntPtr len; 158 | } 159 | #else 160 | public struct uv_buf_t 161 | { 162 | public ulong len; 163 | public IntPtr data; 164 | } 165 | #endif 166 | // From: http://www.elitepvpers.com/forum/co2-programming/159327-advanced-winsock-c.html 167 | [StructLayout(LayoutKind.Sequential, Size=16)] 168 | public struct sockaddr_in 169 | { 170 | public const int Size = 16; 171 | 172 | public short sin_family; 173 | public ushort sin_port; 174 | public struct in_addr 175 | { 176 | public uint S_addr; 177 | public struct _S_un_b 178 | { 179 | public byte s_b1, s_b2, s_b3, s_b4; 180 | } 181 | public _S_un_b S_un_b; 182 | public struct _S_un_w 183 | { 184 | public ushort s_w1, s_w2; 185 | } 186 | public _S_un_w S_un_w; 187 | } 188 | public in_addr sin_addr; 189 | } 190 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 191 | public delegate void uv_shutdown_cb(IntPtr req, int status); 192 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 193 | public delegate uv_buf_t uv_alloc_cb(IntPtr stream, IntPtr suggested_size); 194 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 195 | public delegate void uv_read_cb(IntPtr req, IntPtr nread, uv_buf_t buf); 196 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 197 | public delegate void uv_write_cb(IntPtr req, int status); 198 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 199 | public delegate void uv_connect_cb(IntPtr conn, int status); 200 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 201 | public delegate void uv_close_cb(IntPtr conn); 202 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 203 | public delegate void uv_connection_cb(IntPtr server, int status); 204 | } 205 | -------------------------------------------------------------------------------- /src/Libuv/UVStream.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Libuv { 5 | public class UVStream { 6 | private IntPtr handle; 7 | private GCHandle gchandle; 8 | public event Action OnRead; 9 | public event Action OnClose; 10 | // Pass an already init-ed uv_handle_t subclass to stream from 11 | public UVStream(IntPtr Handle) { 12 | this.gchandle = GCHandle.Alloc(this); 13 | this.handle = Handle; 14 | //attach handle of ourself to the c struct so we can access instance callbacks in static callbacks 15 | //static callbacks are used as to not force the clr to thunk a new one for every callback on every object 16 | var handle = (uv_handle_t)Marshal.PtrToStructure(this.handle, typeof(uv_handle_t)); 17 | this.gchandle = GCHandle.Alloc(this); 18 | handle.data = GCHandle.ToIntPtr(this.gchandle); 19 | Marshal.StructureToPtr(handle, this.handle, true); 20 | } 21 | // Instance Methods 22 | public void ReadStart() 23 | { 24 | Util.CheckError(uv_read_start(this.handle, static_alloc, static_read)); 25 | } 26 | public void ReadStop() 27 | { 28 | Util.CheckError(uv_read_stop(this.handle)); 29 | } 30 | public void Write(byte[] data, int length) 31 | { 32 | IntPtr write_request = Marshal.AllocHGlobal(Sizes.WriteT); 33 | var dataptrhandle = GCHandle.Alloc(data, GCHandleType.Pinned); 34 | // This is not being freed, which needs to be fixed 35 | IntPtr dat = dataptrhandle.AddrOfPinnedObject(); 36 | uv_buf_t[] buf = new uv_buf_t[1]; 37 | buf[0].data = dat; 38 | #if __MonoCS__ 39 | buf[0].len = (IntPtr)length; 40 | #else 41 | buf[0].len = (ulong)length; 42 | #endif 43 | var req = (uv_req_t)Marshal.PtrToStructure(write_request, typeof(uv_req_t)); 44 | req.data = dat; 45 | Marshal.StructureToPtr(req, write_request, true); 46 | Util.CheckError(uv_write(write_request, this.handle, buf, 1, after_write)); 47 | } 48 | private void HandleRead(byte[] data) 49 | { 50 | if (OnRead != null) 51 | { 52 | OnRead(data); 53 | } 54 | } 55 | private void HandleClose() 56 | { 57 | if (OnClose != null) 58 | { 59 | OnClose(); 60 | } 61 | } 62 | // Static Callbacks 63 | static uv_buf_t static_alloc(IntPtr tcp, IntPtr size) 64 | { 65 | uv_buf_t buf; 66 | buf.data = Marshal.AllocHGlobal((int)size); 67 | #if __MonoCS__ 68 | buf.len = size; 69 | #else 70 | buf.len = (ulong)size; 71 | #endif 72 | return buf; 73 | } 74 | static void static_read(IntPtr stream, IntPtr nread, uv_buf_t buf) 75 | { 76 | int size = (int)nread; 77 | if (size < 0) { 78 | if ((int)buf.data != 0) 79 | Marshal.FreeHGlobal(buf.data); 80 | IntPtr shutdown = Marshal.AllocHGlobal(Sizes.ShutdownT); 81 | Util.CheckError(uv_shutdown(shutdown, stream, after_shutdown)); 82 | return; 83 | } 84 | if (size == 0) { 85 | Marshal.FreeHGlobal(buf.data); 86 | return; 87 | } 88 | byte[] data = new byte[size]; 89 | Marshal.Copy(buf.data, data, 0, size); 90 | var handle = (uv_handle_t)Marshal.PtrToStructure(stream, typeof(uv_handle_t)); 91 | var instance_gchandle = GCHandle.FromIntPtr(handle.data); 92 | var stream_instance = (UVStream)instance_gchandle.Target; 93 | stream_instance.HandleRead(data); 94 | Marshal.FreeHGlobal(buf.data); 95 | } 96 | static void after_shutdown(IntPtr shutdown, int status) 97 | { 98 | Util.CheckError(status); 99 | var tmp = (uv_shutdown_t)Marshal.PtrToStructure(shutdown, typeof(uv_shutdown_t)); 100 | var handle = (uv_handle_t)Marshal.PtrToStructure(tmp.handle, typeof(uv_handle_t)); 101 | var instance = GCHandle.FromIntPtr(handle.data); 102 | var watcher_instance = (UVStream)instance.Target; 103 | watcher_instance.HandleClose(); 104 | Marshal.FreeHGlobal(shutdown); 105 | } 106 | static void after_write(IntPtr write_req, int status) 107 | { 108 | Util.CheckError(status); 109 | var req = (uv_req_t)Marshal.PtrToStructure(write_req, typeof(uv_req_t)); 110 | //var handle = GCHandle.FromIntPtr(req.data); 111 | //handle.Free(); 112 | Marshal.FreeHGlobal(write_req); 113 | } 114 | // Externs 115 | [DllImport ("uv")] 116 | internal static extern int uv_read_start(IntPtr stream, uv_alloc_cb alloc_cb, uv_read_cb read); 117 | [DllImport ("uv")] 118 | internal static extern int uv_read_stop(IntPtr stream); 119 | [DllImport ("uv")] 120 | internal static extern int uv_write(IntPtr req, IntPtr handle, uv_buf_t[] bufs, int bufcnt, uv_write_cb cb); 121 | [DllImport ("uv")] 122 | internal static extern int uv_shutdown(IntPtr req, IntPtr handle, uv_shutdown_cb cb); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/Libuv/Watcher.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using System; 3 | 4 | namespace Libuv { 5 | public abstract class Watcher : IDisposable { 6 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 7 | internal delegate void uv_watcher_cb(IntPtr watcher, int status); 8 | 9 | internal Action callback; 10 | internal IntPtr _handle; 11 | internal GCHandle me; 12 | 13 | public Watcher(Action callback, int size) 14 | { 15 | this.callback = callback; 16 | this._handle = Marshal.AllocHGlobal(size); 17 | Util.CheckError(this.InitImpl()); 18 | var handle = (uv_handle_t)Marshal.PtrToStructure(this._handle, typeof(uv_handle_t)); 19 | this.me = GCHandle.Alloc(this); 20 | handle.data = GCHandle.ToIntPtr(this.me); 21 | Marshal.StructureToPtr(handle, this._handle, true); 22 | } 23 | internal static void StaticCallback(IntPtr watcher, int status) 24 | { 25 | Util.CheckError(status); 26 | var handle = (uv_handle_t)Marshal.PtrToStructure(watcher, typeof(uv_handle_t)); 27 | var instance = GCHandle.FromIntPtr(handle.data); 28 | var watcher_instance = (Watcher)instance.Target; 29 | watcher_instance.callback(); 30 | } 31 | public void Start() 32 | { 33 | Util.CheckError(this.StartImpl()); 34 | } 35 | public void Stop() 36 | { 37 | Util.CheckError(this.StopImpl()); 38 | } 39 | 40 | internal abstract int InitImpl(); 41 | internal abstract int StartImpl(); 42 | internal abstract int StopImpl(); 43 | 44 | ~Watcher() 45 | { 46 | Cleanup(); 47 | } 48 | private void Cleanup() 49 | { 50 | me.Free(); 51 | Marshal.FreeHGlobal(this._handle); 52 | } 53 | public void Dispose() 54 | { 55 | Cleanup(); 56 | GC.SuppressFinalize(this); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /winbuild.bat: -------------------------------------------------------------------------------- 1 | echo off 2 | IF %1.==. GOTO Build 3 | IF %1==clean ( 4 | GOTO Clean 5 | ) ELSE ( 6 | GOTO Build 7 | ) 8 | :Build 9 | del uv.def 10 | echo LIBRARY UVWRAP >> uv.def 11 | echo EXPORTS >> uv.def 12 | set count=0 13 | setlocal ENABLEDELAYEDEXPANSION 14 | for /f "tokens=1,2,3,4,5 delims=( " %%a in ('findstr "extern" src\Libuv\*.cs src\Libuv.Tests\*.cs') do ( 15 | set /a count=count+1 16 | echo %%e @!count! >> uv.def 17 | ) 18 | call "deps\libuv\create-msvs-files.bat" 19 | cd ../.. 20 | for /f %%b IN ('msbuildpath.exe') do %%bMSBuild.exe deps\libuv\build\all.sln 21 | call "%VS100COMNTOOLS%vsvars32.bat" 22 | FOR /F %%a IN ('msbuildpath.exe') DO %%aMSBuild.exe src\Libuv.sln 23 | "%VCINSTALLDIR%bin\cl.exe" /o build\uv.dll deps\libuv\build\Debug\obj\uv\*.obj ws2_32.lib advapi32.lib /link /DLL /DEF:uv.def 24 | GOTO Done 25 | :Clean 26 | rmdir /S /Q deps\libuv\build\Debug 27 | rmdir /S /Q build 28 | del /Q uv_wrap.obj 29 | del /Q uv_wrap.def 30 | GOTO Done 31 | :Done 32 | echo on 33 | --------------------------------------------------------------------------------