internal CFSocket(CFSocketNativeHandle sock) { var cbTypes = CFSocketCallBackType.DataCallBack | CFSocketCallBackType.WriteCallBack; gch = GCHandle.Alloc(this); var ctx = new CFStreamClientContext(); ctx.Info = GCHandle.ToIntPtr(gch); var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CFStreamClientContext))); try { Marshal.StructureToPtr(ctx, ptr, false); handle = CFSocketCreateWithNative( IntPtr.Zero, sock, (nuint)(ulong)cbTypes, OnCallback, ptr); } finally { Marshal.FreeHGlobal(ptr); } if (handle == IntPtr.Zero) { throw new CFSocketException(CFSocketError.Error); } var source = new CFRunLoopSource(CFSocketCreateRunLoopSource(IntPtr.Zero, handle, 0)); var loop = CFRunLoop.Current; loop.AddSource(source, CFRunLoop.ModeDefault); }
static void OnCallback(IntPtr s, nuint type, IntPtr address, IntPtr data, IntPtr info) { var socket = GCHandle.FromIntPtr(info).Target as CFSocket; if (socket is null) { return; } CFSocketCallBackType cbType = (CFSocketCallBackType)(ulong)type; if (cbType == CFSocketCallBackType.AcceptCallBack) { var ep = CFSocketAddress.EndPointFromAddressPtr(address); var handle = new CFSocketNativeHandle(Marshal.ReadInt32(data)); socket.OnAccepted(new CFSocketAcceptEventArgs(handle, ep)); } else if (cbType == CFSocketCallBackType.ConnectCallBack) { CFSocketError result; if (data == IntPtr.Zero) { result = CFSocketError.Success; } else { // Note that we read a 32bit value even if CFSocketError is a nint: // 'or a pointer to an SInt32 error code if the connect failed.' result = (CFSocketError)Marshal.ReadInt32(data); } socket.OnConnect(new CFSocketConnectEventArgs(result)); } else if (cbType == CFSocketCallBackType.DataCallBack) { var ep = CFSocketAddress.EndPointFromAddressPtr(address); using (var cfdata = new CFData(data, false)) socket.OnData(new CFSocketDataEventArgs(ep, cfdata.GetBuffer())); } else if (cbType == CFSocketCallBackType.NoCallBack) { // nothing to do } else if (cbType == CFSocketCallBackType.ReadCallBack) { socket.OnRead(new CFSocketReadEventArgs()); } else if (cbType == CFSocketCallBackType.WriteCallBack) { socket.OnWrite(new CFSocketWriteEventArgs()); } }
CFSocket(CFSocketNativeHandle sock) { var cbTypes = CFSocketCallBackType.DataCallBack | CFSocketCallBackType.WriteCallBack; gch = GCHandle.Alloc(this); try { var ctx = new CFStreamClientContext(); ctx.Info = GCHandle.ToIntPtr(gch); var handle = CFSocketCreateWithNative(IntPtr.Zero, sock, (nuint)(ulong)cbTypes, OnCallback, ref ctx); InitializeHandle(handle); var source = new CFRunLoopSource(CFSocketCreateRunLoopSource(IntPtr.Zero, handle, 0), true); var loop = CFRunLoop.Current; loop.AddSource(source, CFRunLoop.ModeDefault); } catch { gch.Free(); throw; } }
public CFSocketAcceptEventArgs(CFSocketNativeHandle handle, IPEndPoint remote) { this.SocketHandle = handle; this.RemoteEndPoint = remote; }
extern static IntPtr CFSocketCreateWithNative(IntPtr allocator, CFSocketNativeHandle sock, nuint /*CFOptionFlags*/ callBackTypes, CFSocketCallBack callout, ref CFStreamClientContext ctx);
internal extern static void CFStreamCreatePairWithSocket(/* CFAllocatorRef */ IntPtr allocator, CFSocketNativeHandle sock, /* CFReadStreamRef* */ out IntPtr readStream, /* CFWriteStreamRef* */ out IntPtr writeStream);