]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_transform/lib/StreamSource.cpp
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / libsecurity_transform / lib / StreamSource.cpp
1 #include "StreamSource.h"
2 #include <string>
3 #include "misc.h"
4 #include "SecCFRelease.h"
5
6 using namespace std;
7
8 CFStringRef gStreamSourceName = CFSTR("StreamSource");
9
10 const CFIndex kMaximumSize = 2048;
11
12 StreamSource::StreamSource(CFReadStreamRef input, Transform* transform, CFStringRef name)
13 : Source(gStreamSourceName, transform, name),
14 mReadStream(input),
15 mReading(dispatch_group_create())
16 {
17 dispatch_group_enter(mReading);
18 CFRetainSafe(mReadStream);
19 }
20
21 void StreamSource::BackgroundActivate()
22 {
23 CFIndex result = 0;
24
25 do
26 {
27 // make a buffer big enough to handle the object
28 // NOTE: allocating this on the stack and letting CFDataCreate copy it is _faster_ then malloc and CFDataCreateWithBytes(..., kCFAllactorMalloc) by a fair margin. At least for 2K chunks. Retest if changing the size.
29 UInt8 buffer[kMaximumSize];
30
31 result = CFReadStreamRead(mReadStream, buffer, kMaximumSize);
32
33 if (result > 0) // was data returned?
34 {
35 // make the data and send it to the transform
36 CFDataRef data = CFDataCreate(NULL, buffer, result);
37
38 CFErrorRef error = mDestination->SetAttribute(mDestinationName, data);
39
40 CFReleaseNull(data);
41
42 if (error != NULL) // we have a problem, there was probably an abort on the chain
43 {
44 return; // quiesce the source
45 }
46 }
47 } while (result > 0);
48
49 if (result < 0)
50 {
51 // we got an error!
52 CFErrorRef error = CFReadStreamCopyError(mReadStream);
53 mDestination->SetAttribute(mDestinationName, error);
54 if (error)
55 {
56 // NOTE: CF doesn't always tell us about this error. Arguably it could be better to
57 // "invent" a generic error, but it is a hard argument that we want to crash in CFReleaseNull(NULL)...
58 CFReleaseNull(error);
59 }
60 }
61 else
62 {
63 // send an EOS
64 mDestination->SetAttribute(mDestinationName, NULL); // end of stream
65 }
66 }
67
68 void StreamSource::DoActivate()
69 {
70 CFRetainSafe(mDestination->GetCFObject());
71 dispatch_group_async(mReading, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
72 this->BackgroundActivate();
73 CFReleaseSafe(mDestination->GetCFObject());
74 });
75 dispatch_group_leave(mReading);
76 }
77
78 void StreamSource::Finalize()
79 {
80 dispatch_group_notify(mReading, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
81 delete this;
82 });
83 }
84
85 StreamSource::~StreamSource()
86 {
87 CFReleaseNull(mReadStream);
88 mReadStream = NULL;
89 dispatch_release(mReading);
90 mReading = NULL;
91 }
92
93
94 Boolean StreamSource::Equal(const CoreFoundationObject* object)
95 {
96 // not equal if we are not the same object
97 if (Source::Equal(object))
98 {
99 const StreamSource* ss = (StreamSource*) object;
100 return CFEqual(ss->mReadStream, mReadStream);
101 }
102
103 return false;
104 }
105
106
107
108 CFTypeRef StreamSource::Make(CFReadStreamRef input, Transform* transform, CFStringRef name)
109 {
110 return CoreFoundationHolder::MakeHolder(gInternalCFObjectName, new StreamSource(input, transform, name));
111 }
112
113
114
115 string StreamSource::DebugDescription()
116 {
117 string result = Source::DebugDescription() + ": Stream ";
118
119 char buffer[256];
120 snprintf(buffer, sizeof(buffer), "(mReadStream = %p)", mReadStream);
121
122 result += buffer;
123
124 return result;
125 }