89
90
[MonoNativeFunctionWrapper]
90
91
delegate IntPtr RetainDelegate (IntPtr info);
91
93
static IntPtr CFReadStreamRef_InvokeRetain (IntPtr retain, IntPtr info)
93
return ((RetainDelegate) Marshal.GetDelegateForFunctionPointer (retain, typeof (RetainDelegate))) (info);
95
return ((RetainDelegate)Marshal.GetDelegateForFunctionPointer (retain, typeof (RetainDelegate))) (info);
96
98
[MonoNativeFunctionWrapper]
97
99
delegate void ReleaseDelegate (IntPtr info);
98
101
static void CFReadStreamRef_InvokeRelease (IntPtr release, IntPtr info)
100
((ReleaseDelegate) Marshal.GetDelegateForFunctionPointer (release, typeof (ReleaseDelegate))) (info);
103
((ReleaseDelegate)Marshal.GetDelegateForFunctionPointer (release, typeof (ReleaseDelegate))) (info);
103
106
[MonoNativeFunctionWrapper]
104
107
delegate IntPtr CopyDescriptionDelegate (IntPtr info);
105
109
static IntPtr CFReadStreamRef_InvokeCopyDescription (IntPtr copyDescription, IntPtr info)
107
return ((CopyDescriptionDelegate) Marshal.GetDelegateForFunctionPointer (copyDescription, typeof (CopyDescriptionDelegate))) (info);
111
return ((CopyDescriptionDelegate)Marshal.GetDelegateForFunctionPointer (copyDescription, typeof (CopyDescriptionDelegate))) (info);
110
114
[MonoNativeFunctionWrapper]
111
115
delegate void CallbackDelegate (IntPtr stream, CFStreamEventType eventType, IntPtr info);
112
117
static void CFReadStreamRef_InvokeCallback (IntPtr callback, IntPtr stream, CFStreamEventType eventType, IntPtr info)
114
((CallbackDelegate) Marshal.GetDelegateForFunctionPointer (callback, typeof (CallbackDelegate))) (stream, eventType, info);
119
((CallbackDelegate)Marshal.GetDelegateForFunctionPointer (callback, typeof (CallbackDelegate))) (stream, eventType, info);
123
public enum CFStreamStatus {
134
public abstract class CFStream : CFType, INativeObject, IDisposable {
141
#region Stream Constructors
143
[DllImport (Constants.CoreFoundationLibrary)]
144
extern static void CFStreamCreatePairWithSocket (IntPtr allocator, CFSocketNativeHandle socket,
145
out IntPtr read, out IntPtr write);
147
public static void CreatePairWithSocket (CFSocket socket, out CFReadStream readStream,
148
out CFWriteStream writeStream)
151
CFStreamCreatePairWithSocket (IntPtr.Zero, socket.GetNative (), out read, out write);
152
readStream = new CFReadStream (read);
153
writeStream = new CFWriteStream (write);
156
[DllImport (Constants.CFNetworkLibrary)]
157
extern static void CFStreamCreatePairWithPeerSocketSignature (IntPtr allocator, ref CFSocketSignature sig, out IntPtr read, out IntPtr write);
159
public static void CreatePairWithPeerSocketSignature (AddressFamily family, SocketType type,
160
ProtocolType proto, IPEndPoint endpoint,
161
out CFReadStream readStream,
162
out CFWriteStream writeStream)
164
using (var address = new CFSocketAddress (endpoint)) {
165
var sig = new CFSocketSignature (family, type, proto, address);
167
CFStreamCreatePairWithPeerSocketSignature (IntPtr.Zero, ref sig, out read, out write);
168
readStream = new CFReadStream (read);
169
writeStream = new CFWriteStream (write);
173
[DllImport (Constants.CFNetworkLibrary)]
174
extern static void CFStreamCreatePairWithSocketToCFHost (IntPtr allocator, IntPtr host, int port,
175
out IntPtr read, out IntPtr write);
177
public static void CreatePairWithSocketToHost (IPEndPoint endpoint,
178
out CFReadStream readStream,
179
out CFWriteStream writeStream)
181
using (var host = CFHost.Create (endpoint)) {
183
CFStreamCreatePairWithSocketToCFHost (
184
IntPtr.Zero, host.Handle, endpoint.Port, out read, out write);
185
readStream = new CFReadStream (read);
186
writeStream = new CFWriteStream (write);
190
[DllImport (Constants.CFNetworkLibrary)]
191
extern static void CFStreamCreatePairWithSocketToHost (IntPtr allocator, IntPtr host, int port,
192
out IntPtr read, out IntPtr write);
194
public static void CreatePairWithSocketToHost (string host, int port,
195
out CFReadStream readStream,
196
out CFWriteStream writeStream)
198
using (var str = new CFString (host)) {
200
CFStreamCreatePairWithSocketToHost (
201
IntPtr.Zero, str.Handle, port, out read, out write);
202
readStream = new CFReadStream (read);
203
writeStream = new CFWriteStream (write);
207
[DllImport (Constants.CFNetworkLibrary)]
208
extern static IntPtr CFReadStreamCreateForHTTPRequest (IntPtr alloc, IntPtr request);
210
public static CFHTTPStream CreateForHTTPRequest (CFHTTPMessage request)
212
var handle = CFReadStreamCreateForHTTPRequest (IntPtr.Zero, request.Handle);
213
if (handle == IntPtr.Zero)
216
return new CFHTTPStream (handle);
219
[DllImport (Constants.CFNetworkLibrary)]
220
extern static IntPtr CFReadStreamCreateForStreamedHTTPRequest (IntPtr alloc, IntPtr request, IntPtr body);
222
public static CFHTTPStream CreateForStreamedHTTPRequest (CFHTTPMessage request, CFReadStream body)
224
var handle = CFReadStreamCreateForStreamedHTTPRequest (IntPtr.Zero, request.Handle, body.Handle);
225
if (handle == IntPtr.Zero)
228
return new CFHTTPStream (handle);
231
[DllImport (Constants.CFNetworkLibrary)]
232
extern static void CFStreamCreateBoundPair (IntPtr alloc, out IntPtr readStream, out IntPtr writeStream, CFIndex transferBufferSize);
234
public static void CreateBoundPair (out CFReadStream readStream, out CFWriteStream writeStream, int bufferSize)
237
CFStreamCreateBoundPair (IntPtr.Zero, out read, out write, bufferSize);
238
readStream = new CFReadStream (read);
239
writeStream = new CFWriteStream (write);
246
public abstract CFException GetError ();
248
protected void CheckError ()
250
var exc = GetError ();
258
throw new InvalidOperationException ();
262
throw new InvalidOperationException ();
267
protected abstract bool DoOpen ();
275
DoSetClient (null, 0, IntPtr.Zero);
276
UnscheduleFromRunLoop (loop, loopMode);
288
protected abstract void DoClose ();
290
public CFStreamStatus GetStatus ()
293
return DoGetStatus ();
296
protected abstract CFStreamStatus DoGetStatus ();
298
internal IntPtr GetProperty (NSString name)
301
return DoGetProperty (name);
304
protected abstract IntPtr DoGetProperty (NSString name);
306
protected abstract bool DoSetProperty (NSString name, INativeObject value);
308
internal void SetProperty (NSString name, INativeObject value)
311
if (DoSetProperty (name, value))
313
throw new InvalidOperationException (string.Format (
314
"Cannot set property '{0}' on {1}.", name, GetType ().Name)
322
public class StreamEventArgs : EventArgs {
323
public CFStreamEventType EventType {
328
public StreamEventArgs (CFStreamEventType type)
330
this.EventType = type;
333
public override string ToString ()
335
return string.Format ("[StreamEventArgs: EventType={0}]", EventType);
339
public event EventHandler<StreamEventArgs> OpenCompletedEvent;
340
public event EventHandler<StreamEventArgs> HasBytesAvailableEvent;
341
public event EventHandler<StreamEventArgs> CanAcceptBytesEvent;
342
public event EventHandler<StreamEventArgs> ErrorEvent;
343
public event EventHandler<StreamEventArgs> ClosedEvent;
345
protected virtual void OnOpenCompleted (StreamEventArgs args)
347
if (OpenCompletedEvent != null)
348
OpenCompletedEvent (this, args);
351
protected virtual void OnHasBytesAvailableEvent (StreamEventArgs args)
353
if (HasBytesAvailableEvent != null)
354
HasBytesAvailableEvent (this, args);
357
protected virtual void OnCanAcceptBytesEvent (StreamEventArgs args)
359
if (CanAcceptBytesEvent != null)
360
CanAcceptBytesEvent (this, args);
363
protected virtual void OnErrorEvent (StreamEventArgs args)
365
if (ErrorEvent != null)
366
ErrorEvent (this, args);
369
protected virtual void OnClosedEvent (StreamEventArgs args)
371
if (ClosedEvent != null)
372
ClosedEvent (this, args);
377
protected abstract void ScheduleWithRunLoop (CFRunLoop loop, NSString mode);
379
protected abstract void UnscheduleFromRunLoop (CFRunLoop loop, NSString mode);
381
protected delegate void CFStreamCallback (IntPtr s, CFStreamEventType type, IntPtr info);
383
[MonoPInvokeCallback (typeof(CFStreamCallback))]
384
static void OnCallback (IntPtr s, CFStreamEventType type, IntPtr info)
386
var stream = GCHandle.FromIntPtr (info).Target as CFStream;
387
stream.OnCallback (type);
390
protected virtual void OnCallback (CFStreamEventType type)
392
var args = new StreamEventArgs (type);
394
case CFStreamEventType.OpenCompleted:
395
OnOpenCompleted (args);
397
case CFStreamEventType.CanAcceptBytes:
398
OnCanAcceptBytesEvent (args);
400
case CFStreamEventType.HasBytesAvailable:
401
OnHasBytesAvailableEvent (args);
403
case CFStreamEventType.ErrorOccurred:
406
case CFStreamEventType.EndEncountered:
407
OnClosedEvent (args);
412
public void EnableEvents (CFRunLoop runLoop, NSString runLoopMode)
414
if (open || closed || (loop != null))
415
throw new InvalidOperationException ();
419
loopMode = runLoopMode;
421
var ctx = new CFStreamClientContext ();
422
ctx.Info = GCHandle.ToIntPtr (gch);
424
var args = CFStreamEventType.OpenCompleted |
425
CFStreamEventType.CanAcceptBytes | CFStreamEventType.HasBytesAvailable |
426
CFStreamEventType.CanAcceptBytes | CFStreamEventType.ErrorOccurred |
427
CFStreamEventType.EndEncountered;
429
var ptr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (CFStreamClientContext)));
431
Marshal.StructureToPtr (ctx, ptr, false);
432
if (!DoSetClient (OnCallback, (int)args, ptr))
433
throw new InvalidOperationException ("Stream does not support async events.");
435
Marshal.FreeHGlobal (ptr);
438
ScheduleWithRunLoop (runLoop, runLoopMode);
441
protected abstract bool DoSetClient (CFStreamCallback callback, CFIndex eventTypes,
444
protected CFStream (IntPtr handle)
446
this.handle = handle;
447
gch = GCHandle.Alloc (this);
450
protected void CheckHandle ()
452
if (handle == IntPtr.Zero)
453
throw new ObjectDisposedException (GetType ().Name);
461
public void Dispose ()
464
GC.SuppressFinalize (this);
467
public IntPtr Handle {
468
get { return handle; }
471
protected virtual void Dispose (bool disposing)
478
if (handle != IntPtr.Zero) {
479
CFObject.CFRelease (handle);
480
handle = IntPtr.Zero;