1/*
2 * Copyright (c) 2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*	CFStream.h
25	Copyright (c) 2000-2013, Apple Inc. All rights reserved.
26*/
27
28#if !defined(__COREFOUNDATION_CFSTREAM__)
29#define __COREFOUNDATION_CFSTREAM__ 1
30
31#include <CoreFoundation/CFBase.h>
32#include <CoreFoundation/CFString.h>
33#include <CoreFoundation/CFDictionary.h>
34#include <CoreFoundation/CFURL.h>
35#include <CoreFoundation/CFRunLoop.h>
36#include <CoreFoundation/CFSocket.h>
37#include <CoreFoundation/CFError.h>
38#include <dispatch/dispatch.h>
39
40CF_IMPLICIT_BRIDGING_ENABLED
41CF_EXTERN_C_BEGIN
42
43typedef CF_ENUM(CFIndex, CFStreamStatus) {
44    kCFStreamStatusNotOpen = 0,
45    kCFStreamStatusOpening,  /* open is in-progress */
46    kCFStreamStatusOpen,
47    kCFStreamStatusReading,
48    kCFStreamStatusWriting,
49    kCFStreamStatusAtEnd,    /* no further bytes can be read/written */
50    kCFStreamStatusClosed,
51    kCFStreamStatusError
52};
53
54typedef CF_OPTIONS(CFOptionFlags, CFStreamEventType) {
55    kCFStreamEventNone = 0,
56    kCFStreamEventOpenCompleted = 1,
57    kCFStreamEventHasBytesAvailable = 2,
58    kCFStreamEventCanAcceptBytes = 4,
59    kCFStreamEventErrorOccurred = 8,
60    kCFStreamEventEndEncountered = 16
61};
62
63typedef struct {
64    CFIndex version;
65    void *info;
66    void *(*retain)(void *info);
67    void (*release)(void *info);
68    CFStringRef (*copyDescription)(void *info);
69} CFStreamClientContext;
70
71typedef struct __CFReadStream * CFReadStreamRef;
72typedef struct __CFWriteStream * CFWriteStreamRef;
73
74typedef void (*CFReadStreamClientCallBack)(CFReadStreamRef stream, CFStreamEventType type, void *clientCallBackInfo);
75typedef void (*CFWriteStreamClientCallBack)(CFWriteStreamRef stream, CFStreamEventType type, void *clientCallBackInfo);
76
77CF_EXPORT
78CFTypeID CFReadStreamGetTypeID(void);
79CF_EXPORT
80CFTypeID CFWriteStreamGetTypeID(void);
81
82/* Memory streams */
83
84/* Value will be a CFData containing all bytes thusfar written; used to recover the data written to a memory write stream. */
85CF_EXPORT
86const CFStringRef kCFStreamPropertyDataWritten;
87
88/* Pass kCFAllocatorNull for bytesDeallocator to prevent CFReadStream from deallocating bytes; otherwise, CFReadStream will deallocate bytes when the stream is destroyed */
89CF_EXPORT
90CFReadStreamRef CFReadStreamCreateWithBytesNoCopy(CFAllocatorRef alloc, const UInt8 *bytes, CFIndex length, CFAllocatorRef bytesDeallocator);
91
92/* The stream writes into the buffer given; when bufferCapacity is exhausted, the stream is exhausted (status becomes kCFStreamStatusAtEnd) */
93CF_EXPORT
94CFWriteStreamRef CFWriteStreamCreateWithBuffer(CFAllocatorRef alloc, UInt8 *buffer, CFIndex bufferCapacity);
95
96/* New buffers are allocated from bufferAllocator as bytes are written to the stream.  At any point, you can recover the bytes thusfar written by asking for the property kCFStreamPropertyDataWritten, above */
97CF_EXPORT
98CFWriteStreamRef CFWriteStreamCreateWithAllocatedBuffers(CFAllocatorRef alloc, CFAllocatorRef bufferAllocator);
99
100/* File streams */
101CF_EXPORT
102CFReadStreamRef CFReadStreamCreateWithFile(CFAllocatorRef alloc, CFURLRef fileURL);
103CF_EXPORT
104CFWriteStreamRef CFWriteStreamCreateWithFile(CFAllocatorRef alloc, CFURLRef fileURL);
105CF_IMPLICIT_BRIDGING_DISABLED
106CF_EXPORT
107void CFStreamCreateBoundPair(CFAllocatorRef alloc, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream, CFIndex transferBufferSize);
108CF_IMPLICIT_BRIDGING_ENABLED
109
110/* Property for file write streams; value should be a CFBoolean.  Set to TRUE to append to a file, rather than to replace its contents */
111CF_EXPORT
112const CFStringRef kCFStreamPropertyAppendToFile;
113
114CF_EXPORT
115const CFStringRef kCFStreamPropertyFileCurrentOffset;   // Value is a CFNumber
116
117
118/* Socket stream properties */
119
120/* Value will be a CFData containing the native handle */
121CF_EXPORT
122const CFStringRef kCFStreamPropertySocketNativeHandle;
123
124/* Value will be a CFString, or NULL if unknown */
125CF_EXPORT
126const CFStringRef kCFStreamPropertySocketRemoteHostName;
127
128/* Value will be a CFNumber, or NULL if unknown */
129CF_EXPORT
130const CFStringRef kCFStreamPropertySocketRemotePortNumber;
131
132CF_IMPLICIT_BRIDGING_DISABLED
133/* Socket streams; the returned streams are paired such that they use the same socket; pass NULL if you want only the read stream or the write stream */
134CF_EXPORT
135void CFStreamCreatePairWithSocket(CFAllocatorRef alloc, CFSocketNativeHandle sock, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream);
136CF_EXPORT
137void CFStreamCreatePairWithSocketToHost(CFAllocatorRef alloc, CFStringRef host, UInt32 port, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream);
138CF_EXPORT
139void CFStreamCreatePairWithPeerSocketSignature(CFAllocatorRef alloc, const CFSocketSignature *signature, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream);
140CF_IMPLICIT_BRIDGING_ENABLED
141
142
143/* Returns the current state of the stream */
144CF_EXPORT
145CFStreamStatus CFReadStreamGetStatus(CFReadStreamRef stream);
146CF_EXPORT
147CFStreamStatus CFWriteStreamGetStatus(CFWriteStreamRef stream);
148
149/* Returns NULL if no error has occurred; otherwise returns the error. */
150CF_EXPORT
151CFErrorRef CFReadStreamCopyError(CFReadStreamRef stream) CF_AVAILABLE(10_5, 2_0);
152CF_EXPORT
153CFErrorRef CFWriteStreamCopyError(CFWriteStreamRef stream) CF_AVAILABLE(10_5, 2_0);
154
155/* Returns success/failure.  Opening a stream causes it to reserve all the system
156   resources it requires.  If the stream can open non-blocking, this will always
157   return TRUE; listen to the run loop source to find out when the open completes
158   and whether it was successful, or poll using CFRead/WriteStreamGetStatus(), waiting
159   for a status of kCFStreamStatusOpen or kCFStreamStatusError.  */
160CF_EXPORT
161Boolean CFReadStreamOpen(CFReadStreamRef stream);
162CF_EXPORT
163Boolean CFWriteStreamOpen(CFWriteStreamRef stream);
164
165/* Terminates the flow of bytes; releases any system resources required by the
166   stream.  The stream may not fail to close.  You may call CFStreamClose() to
167   effectively abort a stream. */
168CF_EXPORT
169void CFReadStreamClose(CFReadStreamRef stream);
170CF_EXPORT
171void CFWriteStreamClose(CFWriteStreamRef stream);
172
173/* Whether there is data currently available for reading; returns TRUE if it's
174   impossible to tell without trying */
175CF_EXPORT
176Boolean CFReadStreamHasBytesAvailable(CFReadStreamRef stream);
177
178/* Returns the number of bytes read, or -1 if an error occurs preventing any
179   bytes from being read, or 0 if the stream's end was encountered.
180   It is an error to try and read from a stream that hasn't been opened first.
181   This call will block until at least one byte is available; it will NOT block
182   until the entire buffer can be filled.  To avoid blocking, either poll using
183   CFReadStreamHasBytesAvailable() or use the run loop and listen for the
184   kCFStreamCanRead event for notification of data available. */
185CF_EXPORT
186CFIndex CFReadStreamRead(CFReadStreamRef stream, UInt8 *buffer, CFIndex bufferLength);
187
188/* Returns a pointer to an internal buffer if possible (setting *numBytesRead
189   to the length of the returned buffer), otherwise returns NULL; guaranteed
190   to return in O(1).  Bytes returned in the buffer are considered read from
191   the stream; if maxBytesToRead is greater than 0, not more than maxBytesToRead
192   will be returned.  If maxBytesToRead is less than or equal to zero, as many bytes
193   as are readily available will be returned.  The returned buffer is good only
194   until the next stream operation called on the stream.  Caller should neither
195   change the contents of the returned buffer nor attempt to deallocate the buffer;
196   it is still owned by the stream. */
197CF_EXPORT
198const UInt8 *CFReadStreamGetBuffer(CFReadStreamRef stream, CFIndex maxBytesToRead, CFIndex *numBytesRead);
199
200/* Whether the stream can currently be written to without blocking;
201   returns TRUE if it's impossible to tell without trying */
202CF_EXPORT
203Boolean CFWriteStreamCanAcceptBytes(CFWriteStreamRef stream);
204
205/* Returns the number of bytes successfully written, -1 if an error has
206   occurred, or 0 if the stream has been filled to capacity (for fixed-length
207   streams).  If the stream is not full, this call will block until at least
208   one byte is written.  To avoid blocking, either poll via CFWriteStreamCanAcceptBytes
209   or use the run loop and listen for the kCFStreamCanWrite event. */
210CF_EXPORT
211CFIndex CFWriteStreamWrite(CFWriteStreamRef stream, const UInt8 *buffer, CFIndex bufferLength);
212
213/* Particular streams can name properties and assign meanings to them; you
214   access these properties through the following calls.  A property is any interesting
215   information about the stream other than the data being transmitted itself.
216   Examples include the headers from an HTTP transmission, or the expected
217   number of bytes, or permission information, etc.  Properties that can be set
218   configure the behavior of the stream, and may only be settable at particular times
219   (like before the stream has been opened).  See the documentation for particular
220   properties to determine their get- and set-ability. */
221CF_EXPORT
222CFTypeRef CFReadStreamCopyProperty(CFReadStreamRef stream, CFStringRef propertyName);
223CF_EXPORT
224CFTypeRef CFWriteStreamCopyProperty(CFWriteStreamRef stream, CFStringRef propertyName);
225
226/* Returns TRUE if the stream recognizes and accepts the given property-value pair;
227   FALSE otherwise. */
228CF_EXPORT
229Boolean CFReadStreamSetProperty(CFReadStreamRef stream, CFStringRef propertyName, CFTypeRef propertyValue);
230CF_EXPORT
231Boolean CFWriteStreamSetProperty(CFWriteStreamRef stream, CFStringRef propertyName, CFTypeRef propertyValue);
232
233/* Asynchronous processing - If you wish to neither poll nor block, you may register
234   a client to hear about interesting events that occur on a stream.  Only one client
235   per stream is allowed; registering a new client replaces the previous one.
236
237   Once you have set a client, the stream must be scheduled to provide the context in
238   which the client will be called.  Streams may be scheduled on a single dispatch queue
239   or on one or more run loops.  If scheduled on a run loop, it is the caller's responsibility
240   to ensure that at least one of the scheduled run loops is being run.
241
242   NOTE: Unlike other CoreFoundation APIs, pasing a NULL clientContext here will remove
243   the client.  If you do not care about the client context (i.e. your only concern
244   is that your callback be called), you should pass in a valid context where every
245   entry is 0 or NULL.
246
247*/
248
249CF_EXPORT
250Boolean CFReadStreamSetClient(CFReadStreamRef stream, CFOptionFlags streamEvents, CFReadStreamClientCallBack clientCB, CFStreamClientContext *clientContext);
251CF_EXPORT
252Boolean CFWriteStreamSetClient(CFWriteStreamRef stream, CFOptionFlags streamEvents, CFWriteStreamClientCallBack clientCB, CFStreamClientContext *clientContext);
253
254CF_EXPORT
255void CFReadStreamScheduleWithRunLoop(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode);
256CF_EXPORT
257void CFWriteStreamScheduleWithRunLoop(CFWriteStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode);
258
259CF_EXPORT
260void CFReadStreamUnscheduleFromRunLoop(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode);
261CF_EXPORT
262void CFWriteStreamUnscheduleFromRunLoop(CFWriteStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode);
263
264/*
265 * Specify the dispatch queue upon which the client callbacks will be invoked.
266 * Passing NULL for the queue will prevent future callbacks from being invoked.
267 * Specifying a dispatch queue using this API will unschedule the stream from
268 * any run loops it had previously been scheduled upon - similarly, scheduling
269 * with a runloop will disassociate the stream from any existing dispatch queue.
270 */
271CF_EXPORT
272void CFReadStreamSetDispatchQueue(CFReadStreamRef stream, dispatch_queue_t q) CF_AVAILABLE(10_9, 7_0);
273
274CF_EXPORT
275void CFWriteStreamSetDispatchQueue(CFWriteStreamRef stream, dispatch_queue_t q) CF_AVAILABLE(10_9, 7_0);
276
277/*
278 * Returns the previously set dispatch queue with an incremented retain count.
279 * Note that the stream's queue may have been set to NULL if the stream was
280 * scheduled on a runloop subsequent to it having had a dispatch queue set.
281 */
282CF_EXPORT
283dispatch_queue_t CFReadStreamCopyDispatchQueue(CFReadStreamRef stream) CF_AVAILABLE(10_9, 7_0);
284
285CF_EXPORT
286dispatch_queue_t CFWriteStreamCopyDispatchQueue(CFWriteStreamRef stream) CF_AVAILABLE(10_9, 7_0);
287
288/* The following API is deprecated starting in 10.5; please use CFRead/WriteStreamCopyError(), above, instead */
289typedef CF_ENUM(CFIndex, CFStreamErrorDomain) {
290    kCFStreamErrorDomainCustom = -1L,      /* custom to the kind of stream in question */
291    kCFStreamErrorDomainPOSIX = 1,        /* POSIX errno; interpret using <sys/errno.h> */
292    kCFStreamErrorDomainMacOSStatus      /* OSStatus type from Carbon APIs; interpret using <MacTypes.h> */
293};
294
295typedef struct {
296    CFIndex domain;
297    SInt32 error;
298} CFStreamError;
299CF_EXPORT
300CFStreamError CFReadStreamGetError(CFReadStreamRef stream);
301CF_EXPORT
302CFStreamError CFWriteStreamGetError(CFWriteStreamRef stream);
303
304
305CF_EXTERN_C_END
306CF_IMPLICIT_BRIDGING_DISABLED
307
308#endif /* ! __COREFOUNDATION_CFSTREAM__ */
309