]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_transform/lib/Transform.h
Security-57337.20.44.tar.gz
[apple/security.git] / OSX / libsecurity_transform / lib / Transform.h
1 #ifndef __TRANSFORM__
2 #define __TRANSFORM__
3
4 #include <CoreFoundation/CFError.h>
5 #include "CoreFoundationBasics.h"
6 #include "SecTransform.h"
7 #include "SecCustomTransform.h"
8 #include <dispatch/dispatch.h>
9 #include "misc.h"
10
11 // Since we are doing everything in CF, we just define an
12 // attribute as a CFDictionary containing a value and
13 // a CFArray of objects which need notification when that
14 // value changes
15
16 // defines for transform externalization
17 #define EXTERN_TRANSFORM_TRANSFORM_ARRAY CFSTR("TRANSFORMS")
18 #define EXTERN_TRANSFORM_CONNECTION_ARRAY CFSTR("ARRAY")
19 #define EXTERN_TRANSFORM_CUSTOM_EXPORTS_DICTIONARY CFSTR("CUSTOM_EXPORTS")
20
21 #define EXTERN_TRANSFORM_NAME CFSTR("NAME")
22 #define EXTERN_TRANSFORM_TYPE CFSTR("TYPE")
23 #define EXTERN_TRANSFORM_STATE CFSTR("STATE")
24 #define EXTERN_TRANSFORM_FROM_NAME CFSTR("FROM_NAME")
25 #define EXTERN_TRANSFORM_FROM_ATTRIBUTE CFSTR("FROM_ATTRIBUTE")
26 #define EXTERN_TRANSFORM_TO_NAME CFSTR("TO_NAME")
27 #define EXTERN_TRANSFORM_TO_ATTRIBUTE CFSTR("TO_ATTRIBUTE")
28
29 #ifndef __clang__
30 #define GCC_BUG_WORKAROUND ::
31 #else
32 #define GCC_BUG_WORKAROUND
33 #endif
34
35
36 class Monitor;
37 typedef CFTypeRef SecMonitorRef;
38
39 struct transform_attribute {
40 CFStringRef name;
41 CFTypeRef value;
42 CFMutableArrayRef connections;
43 // NOTE: this does NOT have a reference.
44 class Transform *transform;
45 static CFTypeID cftype;
46
47 // NOTE: NULL is a valid value to pushback, so we can't just use pushback_value==NULL for "nothing pushed back"
48 // pb_empty => no value currently pushed back
49 // pb_value => we have a value, we havn't presented it yet (if pushback_value==NULL we won't present again until another attribute changes)
50 // pb_repush => pushed back value currently being re-processed
51 // pb_presented_once => we have a value, and tried to process it and got it back again (don't present until another attribute changes)
52 //
53 enum pushback_states { pb_empty, pb_value, pb_repush, pb_presented_once, pb_discard } pushback_state;
54 CFTypeRef pushback_value;
55
56 // (for pushback support; also need pushback state & value)
57 dispatch_queue_t q;
58 dispatch_semaphore_t semaphore;
59
60 // This attribute needs a value set, or to have something connected to it before running the transform
61 unsigned int required:1;
62 // This attribute needs to have an outgoing connection before running the transform
63 unsigned int requires_outbound_connection:1;
64 // This attribute should not be presented to the transform until after execution starts
65 unsigned int deferred:1;
66 // This attribute comes in N chunks followed by a NULL
67 unsigned int stream:1;
68 // This attribute should be saved when externalizing
69 unsigned int ignore_while_externalizing:1;
70 // Set by Transform::Connect
71 unsigned int has_incoming_connection:1;
72 // CustomTransform should't special case CFErrors for this attribute
73 unsigned int direct_error_handling:1;
74 // External sets are problematic, I think they should be disallowed full stop, but 7947393 says we need them sometimes
75 unsigned int allow_external_sets:1;
76 // Value has been created as a source (therefore deferred), give it special treatment
77 unsigned int has_been_deferred:1;
78
79 void *attribute_changed_block;
80 void *attribute_validate_block;
81 };
82
83 typedef void (^ActivityMonitor)(CFStringRef name, CFTypeRef value);
84
85 class GroupTransform; // Forward reference so we do not have to include
86 // the header and break a circular dependency
87 class BlockMonitor;
88
89 class Transform : public CoreFoundationObject
90 {
91 friend CFTypeRef SecTransformExecute(SecTransformRef tranformRef, CFErrorRef* errorRef);
92 friend CFTypeRef SecTransformGetAttribute(SecTransformRef transformRef, CFStringRef key);
93 friend class BlockMonitor;
94 protected:
95 dispatch_queue_t mDispatchQueue, mActivationQueue;
96 dispatch_group_t mActivationPending;
97 CFMutableSetRef mAttributes;
98 CFMutableArrayRef mPushedback;
99 Boolean mIsActive;
100 Boolean mIsFinalizing;
101 Boolean mAlwaysSelfNotify, mProcessingPushbacks;
102 GroupTransform *mGroup;
103 CFErrorRef mAbortError;
104 CFStringRef mTypeName;
105
106 SecTransformAttributeRef AbortAH, DebugAH;
107
108 Transform(CFStringRef transformType, CFStringRef CFobjectType = CFSTR("SecTransform"));
109
110 transform_attribute *getTA(SecTransformStringOrAttributeRef attr, bool create_ok);
111 void TAGetAll(transform_attribute **attributes);
112 CFIndex GetAttributeCount();
113
114 CFDictionaryRef GetAHDictForSaveState(SecTransformStringOrAttributeRef key);
115
116 CFTypeRef ValueForNewAttribute(CFStringRef key, CFTypeRef value);
117 CFMutableDictionaryRef AddNewAttribute(CFStringRef key, CFTypeRef value);
118 CFErrorRef SetAttributeNoCallback(SecTransformStringOrAttributeRef key, CFTypeRef value);
119
120 CFErrorRef ProcessExecute(CFStringRef &outputAttached, SecMonitorRef monitor);
121 typedef void (^AccumulateDictonary)(CFDictionaryRef d);
122 CFErrorRef ProcessExternalize(CFMutableArrayRef transforms, CFMutableArrayRef connections);
123
124 void FinalizeForClang();
125
126 virtual void Finalize();
127 // subclasses with non-trivial finalization can implement this (default: delete this)
128 virtual void FinalizePhase2();
129 // subclasses that want to reject some connections can use this
130 virtual bool validConnectionPoint(CFStringRef attributeName);
131
132 void try_pushbacks();
133
134 void Initialize();
135
136 void ActivateInputs();
137
138 virtual std::string DebugDescription();
139
140 typedef CFErrorRef (^TransformOperation)(Transform*);
141 typedef void (^TransformAsyncOperation)(Transform*);
142 CFErrorRef ForAllNodes(bool parallel, bool includeOwningGroup, TransformOperation op);
143
144 CFErrorRef TraverseTransform(CFMutableSetRef visited, TransformOperation t);
145
146
147 CFErrorRef SendAttribute(SecTransformStringOrAttributeRef key, CFTypeRef value);
148 CFErrorRef SendMetaAttribute(SecTransformStringOrAttributeRef key, SecTransformMetaAttributeType type, CFTypeRef value);
149
150 // Abort all transforms in this transform's RootGroup, including this transform
151 virtual void AbortAllTransforms(CFTypeRef error);
152 // Abort just this transform (and maybe schedule a later call to AbortAllTransforms), should only be
153 // called via AbortAllTransforms
154 virtual void AbortJustThisTransform(CFErrorRef abortMsg);
155
156 void phase3Activation();
157 void DoPhase3Activation();
158
159 bool HasNoInboundConnections();
160 bool HasNoOutboundConnections();
161
162 private:
163 CFErrorRef ExecuteOperation(CFStringRef &outputAttached, SecMonitorRef output, dispatch_queue_t phase2, dispatch_queue_t phase3);
164 SecTransformAttributeRef makeAH(transform_attribute *ta);
165
166 public:
167
168 static CFTypeID GetCFTypeID();
169
170 // these functions are overloaded to implement the functionality of your transform
171 virtual ~Transform();
172
173 // this is called when one of your attributes (e.g. input) changes
174 virtual void AttributeChanged(SecTransformAttributeRef ah, CFTypeRef value);
175 // this is for backwards compatibility only (XXX: convert all existing Transform subclasses to not use it then remove)
176 virtual void AttributeChanged(CFStringRef name, CFTypeRef value);
177
178 // overload to return true if your transform can be externalized (generally true unless you are a monitor)
179 virtual bool IsExternalizable();
180
181 // Base implementation saves all attributes that have kSecTransformMetaAttributeExternalize TRUE (which is the default).
182 // If that isn't useful for your transform overload to return a CFDictionary that contains the state of
183 // your transform. Values returned should be serializable. Remember that this state will be restored
184 // before SecTransformExecute is called. Do not include the transform name in your state (this will be
185 // done for you by SecTransformCopyExternalRep).
186 virtual CFDictionaryRef CopyState();
187
188 // overload to restore the state of your transform
189 virtual void RestoreState(CFDictionaryRef state);
190 virtual void SetCustomExternalData(CFDictionaryRef customData);
191
192 virtual Boolean TransformCanExecute();
193 virtual CFErrorRef TransformStartingExecution();
194
195 SecTransformAttributeRef getAH(SecTransformStringOrAttributeRef attr, bool create_ok =true, bool create_undesrscore_ok =false);
196 CFArrayRef GetAllAH();
197
198 CFStringRef GetName();
199
200 // Output debugging information if the DEBUG attribute is set for this transform
201 void Debug(const char *fmt, ...);
202
203 CFErrorRef RefactorErrorToIncludeAbortingTransform(CFErrorRef sourceError);
204
205 public:
206 CFErrorRef Connect(GroupTransform *group, Transform* destinationTransform, CFStringRef myKey, CFStringRef hisKey);
207 CFErrorRef Disconnect(Transform* destinationTransform, CFStringRef myKey, CFStringRef hisKey);
208
209 CFErrorRef ExternalSetAttribute(SecTransformStringOrAttributeRef key, CFTypeRef value);
210 CFErrorRef SetAttribute(SecTransformStringOrAttributeRef key, CFTypeRef value);
211 CFTypeRef GetAttribute(SecTransformStringOrAttributeRef key);
212 CFTypeRef GetMetaAttribute(SecTransformStringOrAttributeRef key, SecTransformMetaAttributeType type);
213
214 CFErrorRef Pushback(SecTransformAttributeRef ah, CFTypeRef value);
215
216 void Do(SecTransformAttributeRef name, CFTypeRef value);
217
218 CFTypeRef Execute(dispatch_queue_t deliveryQueue, SecMessageBlock deliveryBlock, CFErrorRef* errorRef);
219
220 // set to get notified every time this transform does something -- used for debugging
221 void SetActivityMonitor(ActivityMonitor am);
222
223 virtual CFDictionaryRef Externalize(CFErrorRef *error);
224
225 // Returns NULL if not in a group; can return this
226 GroupTransform* GetRootGroup();
227
228 friend class GroupTransform;
229 friend Transform::TransformOperation makeIdleOp(dispatch_group_t idle_group);
230
231 void SetGroup(GroupTransform* group) {mGroup = group;}
232 CFDictionaryRef GetCustomExternalData();
233 };
234
235
236 inline struct transform_attribute *ah2ta(SecTransformAttributeRef ah) {
237 // CF stores our data just after the CFRuntimeBase, we just have a single pointer there.
238 return *(struct transform_attribute **)(1 + (CFRuntimeBase*)ah);
239 }
240
241 #endif