]> git.saurik.com Git - apple/configd.git/blob - EventFactory/EventFactory.m
configd-963.260.1.tar.gz
[apple/configd.git] / EventFactory / EventFactory.m
1 //
2 // EventFactory.m
3 // SystemConfigurationNetworkEventFactory
4 //
5 // Created by Allan Nathanson on 11/15/17.
6 //
7 //
8
9 #import "EventFactory.h"
10 #import <os/log.h>
11
12 #pragma mark -
13 #pragma mark Logging
14
15 static os_log_t
16 __log_Spectacles(void)
17 {
18 static os_log_t log = NULL;
19
20 if (log == NULL) {
21 log = os_log_create("com.apple.spectacles", "SystemConfiguration");
22 }
23
24 return log;
25 }
26
27 #define specs_log_err(format, ...) os_log_error(__log_Spectacles(), format, ##__VA_ARGS__)
28 #define specs_log_notice(format, ...) os_log (__log_Spectacles(), format, ##__VA_ARGS__)
29 #define specs_log_info(format, ...) os_log_info (__log_Spectacles(), format, ##__VA_ARGS__)
30 #define specs_log_debug(format, ...) os_log_debug(__log_Spectacles(), format, ##__VA_ARGS__)
31
32 #pragma mark -
33 #pragma mark Matching
34
35 #define REMatched(re_matches, args) \
36 ((re_matches != nil) && (re_matches.count == 1) && (re_matches[0].numberOfRanges == (args + 1)))
37
38 #define REMatchRange(re_matches, arg) \
39 [re_matches[0] rangeAtIndex:arg]
40
41 #pragma mark -
42 #pragma mark SystemConfiguratioin Network Event Factory
43
44 @interface EventFactory ()
45
46 @property (readonly, nonatomic) NSRegularExpression *kevExpressionInterfaceAttach;
47 @property (readonly, nonatomic) NSRegularExpression *kevExpressionLink;
48 @property (readonly, nonatomic) NSRegularExpression *kevExpressionLinkQuality;
49
50 @end
51
52 @implementation EventFactory
53
54 - (instancetype)init
55 {
56 self = [super init];
57 if (self) {
58 NSError *expressionError;
59
60 expressionError = nil;
61 _kevExpressionInterfaceAttach = [[NSRegularExpression alloc] initWithPattern:@"Process interface (attach|detach): (\\w+)" options:0 error:&expressionError];
62 if (expressionError != nil) {
63 specs_log_info("Failed to create a regular expression: %@", expressionError);
64 }
65
66 expressionError = nil;
67 _kevExpressionLink = [[NSRegularExpression alloc] initWithPattern:@"Process interface link (down|up): (\\w+)" options:0 error:&expressionError];
68 if (expressionError != nil) {
69 specs_log_info("Failed to create a regular expression: %@", expressionError);
70 }
71
72 expressionError = nil;
73 _kevExpressionLinkQuality = [[NSRegularExpression alloc] initWithPattern:@"Process interface quality: (\\w+) \\(q=([-\\d]+)\\)" options:0 error:&expressionError];
74 if (expressionError != nil) {
75 specs_log_info("Failed to create a regular expression: %@", expressionError);
76 }
77 }
78
79 return self;
80 }
81
82 - (void)startWithLogSourceAttributes:(NSDictionary<NSString *, NSObject *> *)attributes
83 {
84 //
85 // Prepare for parsing logs
86 //
87 specs_log_info("Event factory is starting with attributes: %@", attributes);
88 }
89
90 - (void)handleLogEvent:(EFLogEvent *)logEvent completionHandler:(void (^)(NSArray<EFEvent *> * _Nullable))completionHandler
91 {
92 NSString *category;
93 NSString *message;
94 EFNetworkControlPathEvent *newNetworkEvent = nil;
95
96 message = logEvent.eventMessage;
97 if (message == nil) {
98 return;
99 }
100
101 //
102 // Parse logEvent and continue constructing SpectaclesNetworkEvent objects
103 //
104 // Note: if one or more NetworkEvent objects are complete, send them to the
105 // app in the completion handler block.
106 //
107
108
109 category = logEvent.category;
110 if ([category isEqualToString:@"InterfaceNamer"]) {
111
112 do {
113 } while (false);
114
115 specs_log_debug("Skipped [%@] message: %@", category, message);
116
117 } else if ([category isEqualToString:@"IPMonitor"]) {
118
119 do {
120 } while (false);
121
122 specs_log_debug("Skipped [%@] message: %@", category, message);
123
124 } else if ([category isEqualToString:@"KernelEventMonitor"]) {
125
126 do {
127 NSArray<NSTextCheckingResult *> *matches;
128 NSRange range = NSMakeRange(0, message.length);
129
130 //
131 // interface attach/detach
132 //
133 matches = [_kevExpressionInterfaceAttach matchesInString:message
134 options:NSMatchingReportProgress
135 range:range];
136 if (REMatched(matches, 2)) {
137 NSString *event;
138 NSString *interface;
139
140 interface = [message substringWithRange:REMatchRange(matches, 2)];
141 event = [message substringWithRange:REMatchRange(matches, 1)];
142 specs_log_debug("interface attach/detach: %@ --> %@", interface, event);
143
144 newNetworkEvent = [[EFNetworkControlPathEvent alloc] initWithLogEvent:logEvent subsystemIdentifier:[[NSData alloc] init]];
145 newNetworkEvent.interfaceBSDName = interface;
146 newNetworkEvent.interfaceStatus = [event isEqualToString:@"attach"] ? @"interface attached" : @"interface detached";
147 break;
148 }
149
150 //
151 // interface link up/down
152 //
153 matches = [_kevExpressionLink matchesInString:message
154 options:NSMatchingReportProgress
155 range:range];
156 if (REMatched(matches, 2)) {
157 NSString *event;
158 NSString *interface;
159
160 interface = [message substringWithRange:REMatchRange(matches, 2)];
161 event = [message substringWithRange:REMatchRange(matches, 1)];
162 specs_log_debug("link change: %@ --> %@", interface, event);
163
164 newNetworkEvent = [[EFNetworkControlPathEvent alloc] initWithLogEvent:logEvent subsystemIdentifier:[[NSData alloc] init]];
165 newNetworkEvent.interfaceBSDName = interface;
166 newNetworkEvent.interfaceStatus = [event isEqualToString:@"up"] ? @"link up" : @"link down";
167 break;
168 }
169
170 //
171 // interface link quality
172 //
173 matches = [_kevExpressionLinkQuality matchesInString:message
174 options:NSMatchingReportProgress
175 range:range];
176 if (REMatched(matches, 2)) {
177 NSString *interface;
178 NSString *quality;
179
180 interface = [message substringWithRange:REMatchRange(matches, 1)];
181 quality = [message substringWithRange:REMatchRange(matches, 2)];
182 specs_log_debug("link quality: %@ --> %@", interface, quality);
183
184 newNetworkEvent = [[EFNetworkControlPathEvent alloc] initWithLogEvent:logEvent subsystemIdentifier:[[NSData alloc] init]];
185 newNetworkEvent.interfaceBSDName = interface;
186 newNetworkEvent.interfaceStatus = [NSString stringWithFormat:@"link quality = %@", quality];
187 break;
188 }
189
190 specs_log_debug("Skipped [%@] message: %@", category, message);
191 } while (false);
192
193 } else if ([category isEqualToString:@"PreferencesMonitor"]) {
194
195 do {
196 } while (false);
197
198 specs_log_debug("Skipped [%@] message: %@", category, message);
199
200 } else {
201 // if we have no handler for this category
202 specs_log_debug("Skipped [%@] message: %@", category, message);
203 }
204
205 if (newNetworkEvent != nil) {
206 completionHandler(@[ newNetworkEvent ]);
207 } else {
208 completionHandler(nil);
209 }
210 }
211
212 - (void)finishWithCompletionHandler:(void (^)(NSArray<EFEvent *> * _Nullable))completionHandler
213 {
214 //
215 // Clean up
216 //
217 // Note: if one or more SpectaclesNetworkEvent objects are in the process of
218 // being built, return them in the completion handler block.
219 //
220 specs_log_notice("Event factory is finishing");
221 completionHandler(nil);
222 }
223
224 @end