2 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 Copyright (c) 2000-2014, Apple Inc. All rights reserved.
28 #if !defined(__COREFOUNDATION_CFSTREAM__)
29 #define __COREFOUNDATION_CFSTREAM__ 1
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>
40 CF_IMPLICIT_BRIDGING_ENABLED
43 typedef CF_ENUM(CFIndex
, CFStreamStatus
) {
44 kCFStreamStatusNotOpen
= 0,
45 kCFStreamStatusOpening
, /* open is in-progress */
47 kCFStreamStatusReading
,
48 kCFStreamStatusWriting
,
49 kCFStreamStatusAtEnd
, /* no further bytes can be read/written */
50 kCFStreamStatusClosed
,
54 typedef CF_OPTIONS(CFOptionFlags
, CFStreamEventType
) {
55 kCFStreamEventNone
= 0,
56 kCFStreamEventOpenCompleted
= 1,
57 kCFStreamEventHasBytesAvailable
= 2,
58 kCFStreamEventCanAcceptBytes
= 4,
59 kCFStreamEventErrorOccurred
= 8,
60 kCFStreamEventEndEncountered
= 16
66 void *(*retain
)(void *info
);
67 void (*release
)(void *info
);
68 CFStringRef (*copyDescription
)(void *info
);
69 } CFStreamClientContext
;
71 typedef struct CF_BRIDGED_MUTABLE_TYPE(NSInputStream
) __CFReadStream
* CFReadStreamRef
;
72 typedef struct CF_BRIDGED_MUTABLE_TYPE(NSOutputStream
) __CFWriteStream
* CFWriteStreamRef
;
74 typedef void (*CFReadStreamClientCallBack
)(CFReadStreamRef stream
, CFStreamEventType type
, void *clientCallBackInfo
);
75 typedef void (*CFWriteStreamClientCallBack
)(CFWriteStreamRef stream
, CFStreamEventType type
, void *clientCallBackInfo
);
78 CFTypeID
CFReadStreamGetTypeID(void);
80 CFTypeID
CFWriteStreamGetTypeID(void);
84 /* Value will be a CFData containing all bytes thusfar written; used to recover the data written to a memory write stream. */
86 const CFStringRef kCFStreamPropertyDataWritten
;
88 /* Pass kCFAllocatorNull for bytesDeallocator to prevent CFReadStream from deallocating bytes; otherwise, CFReadStream will deallocate bytes when the stream is destroyed */
90 CFReadStreamRef
CFReadStreamCreateWithBytesNoCopy(CFAllocatorRef alloc
, const UInt8
*bytes
, CFIndex length
, CFAllocatorRef bytesDeallocator
);
92 /* The stream writes into the buffer given; when bufferCapacity is exhausted, the stream is exhausted (status becomes kCFStreamStatusAtEnd) */
94 CFWriteStreamRef
CFWriteStreamCreateWithBuffer(CFAllocatorRef alloc
, UInt8
*buffer
, CFIndex bufferCapacity
);
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 */
98 CFWriteStreamRef
CFWriteStreamCreateWithAllocatedBuffers(CFAllocatorRef alloc
, CFAllocatorRef bufferAllocator
);
102 CFReadStreamRef
CFReadStreamCreateWithFile(CFAllocatorRef alloc
, CFURLRef fileURL
);
104 CFWriteStreamRef
CFWriteStreamCreateWithFile(CFAllocatorRef alloc
, CFURLRef fileURL
);
105 CF_IMPLICIT_BRIDGING_DISABLED
107 void CFStreamCreateBoundPair(CFAllocatorRef alloc
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
, CFIndex transferBufferSize
);
108 CF_IMPLICIT_BRIDGING_ENABLED
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 */
112 const CFStringRef kCFStreamPropertyAppendToFile
;
115 const CFStringRef kCFStreamPropertyFileCurrentOffset
; // Value is a CFNumber
118 /* Socket stream properties */
120 /* Value will be a CFData containing the native handle */
122 const CFStringRef kCFStreamPropertySocketNativeHandle
;
124 /* Value will be a CFString, or NULL if unknown */
126 const CFStringRef kCFStreamPropertySocketRemoteHostName
;
128 /* Value will be a CFNumber, or NULL if unknown */
130 const CFStringRef kCFStreamPropertySocketRemotePortNumber
;
132 CF_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 */
135 void CFStreamCreatePairWithSocket(CFAllocatorRef alloc
, CFSocketNativeHandle sock
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
);
137 void CFStreamCreatePairWithSocketToHost(CFAllocatorRef alloc
, CFStringRef host
, UInt32 port
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
);
139 void CFStreamCreatePairWithPeerSocketSignature(CFAllocatorRef alloc
, const CFSocketSignature
*signature
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
);
140 CF_IMPLICIT_BRIDGING_ENABLED
143 /* Returns the current state of the stream */
145 CFStreamStatus
CFReadStreamGetStatus(CFReadStreamRef stream
);
147 CFStreamStatus
CFWriteStreamGetStatus(CFWriteStreamRef stream
);
149 /* Returns NULL if no error has occurred; otherwise returns the error. */
151 CFErrorRef
CFReadStreamCopyError(CFReadStreamRef stream
) CF_AVAILABLE(10_5
, 2_0
);
153 CFErrorRef
CFWriteStreamCopyError(CFWriteStreamRef stream
) CF_AVAILABLE(10_5
, 2_0
);
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. */
161 Boolean
CFReadStreamOpen(CFReadStreamRef stream
);
163 Boolean
CFWriteStreamOpen(CFWriteStreamRef stream
);
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. */
169 void CFReadStreamClose(CFReadStreamRef stream
);
171 void CFWriteStreamClose(CFWriteStreamRef stream
);
173 /* Whether there is data currently available for reading; returns TRUE if it's
174 impossible to tell without trying */
176 Boolean
CFReadStreamHasBytesAvailable(CFReadStreamRef stream
);
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. */
186 CFIndex
CFReadStreamRead(CFReadStreamRef stream
, UInt8
*buffer
, CFIndex bufferLength
);
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. */
198 const UInt8
*CFReadStreamGetBuffer(CFReadStreamRef stream
, CFIndex maxBytesToRead
, CFIndex
*numBytesRead
);
200 /* Whether the stream can currently be written to without blocking;
201 returns TRUE if it's impossible to tell without trying */
203 Boolean
CFWriteStreamCanAcceptBytes(CFWriteStreamRef stream
);
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. */
211 CFIndex
CFWriteStreamWrite(CFWriteStreamRef stream
, const UInt8
*buffer
, CFIndex bufferLength
);
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. */
222 CFTypeRef
CFReadStreamCopyProperty(CFReadStreamRef stream
, CFStringRef propertyName
);
224 CFTypeRef
CFWriteStreamCopyProperty(CFWriteStreamRef stream
, CFStringRef propertyName
);
226 /* Returns TRUE if the stream recognizes and accepts the given property-value pair;
229 Boolean
CFReadStreamSetProperty(CFReadStreamRef stream
, CFStringRef propertyName
, CFTypeRef propertyValue
);
231 Boolean
CFWriteStreamSetProperty(CFWriteStreamRef stream
, CFStringRef propertyName
, CFTypeRef propertyValue
);
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.
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.
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
250 Boolean
CFReadStreamSetClient(CFReadStreamRef stream
, CFOptionFlags streamEvents
, CFReadStreamClientCallBack clientCB
, CFStreamClientContext
*clientContext
);
252 Boolean
CFWriteStreamSetClient(CFWriteStreamRef stream
, CFOptionFlags streamEvents
, CFWriteStreamClientCallBack clientCB
, CFStreamClientContext
*clientContext
);
255 void CFReadStreamScheduleWithRunLoop(CFReadStreamRef stream
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
);
257 void CFWriteStreamScheduleWithRunLoop(CFWriteStreamRef stream
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
);
260 void CFReadStreamUnscheduleFromRunLoop(CFReadStreamRef stream
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
);
262 void CFWriteStreamUnscheduleFromRunLoop(CFWriteStreamRef stream
, CFRunLoopRef runLoop
, CFStringRef runLoopMode
);
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.
272 void CFReadStreamSetDispatchQueue(CFReadStreamRef stream
, dispatch_queue_t q
) CF_AVAILABLE(10_9
, 7_0
);
275 void CFWriteStreamSetDispatchQueue(CFWriteStreamRef stream
, dispatch_queue_t q
) CF_AVAILABLE(10_9
, 7_0
);
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.
283 dispatch_queue_t
CFReadStreamCopyDispatchQueue(CFReadStreamRef stream
) CF_AVAILABLE(10_9
, 7_0
);
286 dispatch_queue_t
CFWriteStreamCopyDispatchQueue(CFWriteStreamRef stream
) CF_AVAILABLE(10_9
, 7_0
);
288 /* The following API is deprecated starting in 10.5; please use CFRead/WriteStreamCopyError(), above, instead */
289 typedef 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> */
300 CFStreamError
CFReadStreamGetError(CFReadStreamRef stream
);
302 CFStreamError
CFWriteStreamGetError(CFWriteStreamRef stream
);
306 CF_IMPLICIT_BRIDGING_DISABLED
308 #endif /* ! __COREFOUNDATION_CFSTREAM__ */