appium-mac2-driver 4.1.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/WebDriverAgentMac/IntegrationTests/AMFindElementTests.m +165 -2
  3. package/WebDriverAgentMac/IntegrationTests/AMIntegrationTestCase.h +11 -0
  4. package/WebDriverAgentMac/IntegrationTests/AMIntegrationTestCase.m +33 -0
  5. package/WebDriverAgentMac/IntegrationTests/AMW3CActionsTests.m +7 -9
  6. package/WebDriverAgentMac/WebDriverAgent/Base.lproj/Main.storyboard +16 -1
  7. package/WebDriverAgentMac/WebDriverAgent/WebViewController.h +21 -0
  8. package/WebDriverAgentMac/WebDriverAgent/WebViewController.m +49 -0
  9. package/WebDriverAgentMac/WebDriverAgentLib/Categories/NSPredicate+FBFormat.m +80 -0
  10. package/WebDriverAgentMac/WebDriverAgentLib/Categories/XCUIElement+AMAttributes.h +29 -1
  11. package/WebDriverAgentMac/WebDriverAgentLib/Categories/XCUIElement+AMAttributes.m +66 -15
  12. package/WebDriverAgentMac/WebDriverAgentLib/Routing/AMHTTPServer.h +84 -0
  13. package/WebDriverAgentMac/WebDriverAgentLib/Routing/AMHTTPServer.m +493 -0
  14. package/WebDriverAgentMac/WebDriverAgentLib/Routing/AMTCPSocket.h +109 -0
  15. package/WebDriverAgentMac/WebDriverAgentLib/Routing/AMTCPSocket.m +235 -0
  16. package/WebDriverAgentMac/WebDriverAgentLib/Routing/FBWebServer.h +1 -1
  17. package/WebDriverAgentMac/WebDriverAgentLib/Routing/FBWebServer.m +9 -21
  18. package/WebDriverAgentMac/WebDriverAgentLib/Routing/RouteRequest.h +36 -0
  19. package/WebDriverAgentMac/WebDriverAgentLib/Routing/RouteRequest.m +33 -0
  20. package/WebDriverAgentMac/WebDriverAgentLib/Routing/RouteResponse.h +37 -0
  21. package/WebDriverAgentMac/WebDriverAgentLib/Routing/RouteResponse.m +62 -0
  22. package/WebDriverAgentMac/WebDriverAgentLib/Utilities/AMSnapshotUtils.h +22 -0
  23. package/WebDriverAgentMac/WebDriverAgentLib/Utilities/AMSnapshotUtils.m +5 -11
  24. package/WebDriverAgentMac/WebDriverAgentLib/Utilities/FBElementUtils.m +7 -1
  25. package/WebDriverAgentMac/WebDriverAgentMac.xcodeproj/project.pbxproj +46 -180
  26. package/npm-shrinkwrap.json +75 -146
  27. package/package.json +2 -1
  28. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h +0 -1226
  29. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +0 -8513
  30. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.h +0 -1036
  31. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.m +0 -5632
  32. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDNumber.h +0 -12
  33. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDNumber.m +0 -88
  34. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDRange.h +0 -56
  35. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDRange.m +0 -106
  36. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPConnection.h +0 -107
  37. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPConnection.m +0 -2238
  38. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPLogging.h +0 -122
  39. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPMessage.h +0 -48
  40. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPMessage.m +0 -114
  41. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPResponse.h +0 -149
  42. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPServer.h +0 -200
  43. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPServer.m +0 -720
  44. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPDataResponse.h +0 -13
  45. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPDataResponse.m +0 -83
  46. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPErrorResponse.h +0 -9
  47. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPErrorResponse.m +0 -40
  48. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/HTTPResponseProxy.h +0 -13
  49. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/HTTPResponseProxy.m +0 -84
  50. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/Route.h +0 -18
  51. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/Route.m +0 -11
  52. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteRequest.h +0 -16
  53. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteRequest.m +0 -50
  54. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteResponse.h +0 -20
  55. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteResponse.m +0 -66
  56. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingConnection.h +0 -5
  57. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingConnection.m +0 -142
  58. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingHTTPServer.h +0 -55
  59. package/WebDriverAgentMac/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingHTTPServer.m +0 -288
@@ -1,720 +0,0 @@
1
- #import "HTTPServer.h"
2
- #import "HTTPConnection.h"
3
- #import "HTTPLogging.h"
4
-
5
- #import "GCDAsyncSocket.h"
6
-
7
- #if ! __has_feature(objc_arc)
8
- #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
9
- #endif
10
-
11
- #pragma clang diagnostic ignored "-Wdirect-ivar-access"
12
- #pragma clang diagnostic ignored "-Wimplicit-retain-self"
13
- #pragma clang diagnostic ignored "-Wnullable-to-nonnull-conversion"
14
- #pragma clang diagnostic ignored "-Wunused"
15
-
16
- // Log levels: off, error, warn, info, verbose
17
- // Other flags: trace
18
- static const int httpLogLevel = HTTP_LOG_LEVEL_INFO; // | HTTP_LOG_FLAG_TRACE;
19
-
20
- @interface HTTPServer (PrivateAPI)
21
-
22
- - (void)unpublishBonjour;
23
- - (void)publishBonjour;
24
-
25
- + (void)startBonjourThreadIfNeeded;
26
- + (void)performBonjourBlock:(dispatch_block_t)block;
27
-
28
- @end
29
-
30
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
31
- #pragma mark -
32
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33
-
34
- @implementation HTTPServer
35
-
36
- /**
37
- * Standard Constructor.
38
- * Instantiates an HTTP server, but does not start it.
39
- **/
40
- - (id)init
41
- {
42
- if ((self = [super init]))
43
- {
44
- HTTPLogTrace();
45
-
46
- // Setup underlying dispatch queues
47
- serverQueue = dispatch_queue_create("HTTPServer", NULL);
48
- connectionQueue = dispatch_queue_create("HTTPConnection", NULL);
49
-
50
- IsOnServerQueueKey = &IsOnServerQueueKey;
51
- IsOnConnectionQueueKey = &IsOnConnectionQueueKey;
52
-
53
- void *nonNullUnusedPointer = (__bridge void *)self; // Whatever, just not null
54
-
55
- dispatch_queue_set_specific(serverQueue, IsOnServerQueueKey, nonNullUnusedPointer, NULL);
56
- dispatch_queue_set_specific(connectionQueue, IsOnConnectionQueueKey, nonNullUnusedPointer, NULL);
57
-
58
- // Initialize underlying GCD based tcp socket
59
- asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:(id<GCDAsyncSocketDelegate>)self delegateQueue:serverQueue];
60
-
61
- // Use default connection class of HTTPConnection
62
- connectionClass = [HTTPConnection self];
63
-
64
- // By default bind on all available interfaces, en1, wifi etc
65
- interface = nil;
66
-
67
- // Use a default port of 0
68
- // This will allow the kernel to automatically pick an open port for us
69
- port = 0;
70
-
71
- // Configure default values for bonjour service
72
-
73
- // Bonjour domain. Use the local domain by default
74
- domain = @"local.";
75
-
76
- // If using an empty string ("") for the service name when registering,
77
- // the system will automatically use the "Computer Name".
78
- // Passing in an empty string will also handle name conflicts
79
- // by automatically appending a digit to the end of the name.
80
- name = @"";
81
-
82
- // Initialize arrays to hold all the HTTP connections
83
- connections = [[NSMutableArray alloc] init];
84
-
85
- connectionsLock = [[NSLock alloc] init];
86
-
87
- // Register for notifications of closed connections
88
- [[NSNotificationCenter defaultCenter] addObserver:self
89
- selector:@selector(connectionDidDie:)
90
- name:HTTPConnectionDidDieNotification
91
- object:nil];
92
-
93
- isRunning = NO;
94
- }
95
- return self;
96
- }
97
-
98
- /**
99
- * Standard Deconstructor.
100
- * Stops the server, and clients, and releases any resources connected with this instance.
101
- **/
102
- - (void)dealloc
103
- {
104
- HTTPLogTrace();
105
-
106
- // Remove notification observer
107
- [[NSNotificationCenter defaultCenter] removeObserver:self];
108
-
109
- // Stop the server if it's running
110
- [self stop];
111
-
112
- // Release all instance variables
113
-
114
- #if !OS_OBJECT_USE_OBJC
115
- dispatch_release(serverQueue);
116
- dispatch_release(connectionQueue);
117
- #endif
118
-
119
- [asyncSocket setDelegate:nil delegateQueue:NULL];
120
- }
121
-
122
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
123
- #pragma mark Server Configuration
124
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
125
-
126
- /**
127
- * The document root is filesystem root for the webserver.
128
- * Thus requests for /index.html will be referencing the index.html file within the document root directory.
129
- * All file requests are relative to this document root.
130
- **/
131
- - (NSString *)documentRoot
132
- {
133
- __block NSString *result;
134
-
135
- dispatch_sync(serverQueue, ^{
136
- result = documentRoot;
137
- });
138
-
139
- return result;
140
- }
141
-
142
- - (void)setDocumentRoot:(NSString *)value
143
- {
144
- HTTPLogTrace();
145
-
146
- // Document root used to be of type NSURL.
147
- // Add type checking for early warning to developers upgrading from older versions.
148
-
149
- if (value && ![value isKindOfClass:[NSString class]])
150
- {
151
- HTTPLogWarn(@"%@: %@ - Expecting NSString parameter, received %@ parameter",
152
- THIS_FILE, THIS_METHOD, NSStringFromClass([value class]));
153
- return;
154
- }
155
-
156
- NSString *valueCopy = [value copy];
157
-
158
- dispatch_async(serverQueue, ^{
159
- documentRoot = valueCopy;
160
- });
161
-
162
- }
163
-
164
- /**
165
- * The connection class is the class that will be used to handle connections.
166
- * That is, when a new connection is created, an instance of this class will be intialized.
167
- * The default connection class is HTTPConnection.
168
- * If you use a different connection class, it is assumed that the class extends HTTPConnection
169
- **/
170
- - (Class)connectionClass
171
- {
172
- __block Class result;
173
-
174
- dispatch_sync(serverQueue, ^{
175
- result = connectionClass;
176
- });
177
-
178
- return result;
179
- }
180
-
181
- - (void)setConnectionClass:(Class)value
182
- {
183
- HTTPLogTrace();
184
-
185
- dispatch_async(serverQueue, ^{
186
- connectionClass = value;
187
- });
188
- }
189
-
190
- /**
191
- * What interface to bind the listening socket to.
192
- **/
193
- - (NSString *)interface
194
- {
195
- __block NSString *result;
196
-
197
- dispatch_sync(serverQueue, ^{
198
- result = interface;
199
- });
200
-
201
- return result;
202
- }
203
-
204
- - (void)setInterface:(NSString *)value
205
- {
206
- NSString *valueCopy = [value copy];
207
-
208
- dispatch_async(serverQueue, ^{
209
- interface = valueCopy;
210
- });
211
-
212
- }
213
-
214
- /**
215
- * The port to listen for connections on.
216
- * By default this port is initially set to zero, which allows the kernel to pick an available port for us.
217
- * After the HTTP server has started, the port being used may be obtained by this method.
218
- **/
219
- - (UInt16)port
220
- {
221
- __block UInt16 result;
222
-
223
- dispatch_sync(serverQueue, ^{
224
- result = port;
225
- });
226
-
227
- return result;
228
- }
229
-
230
- - (UInt16)listeningPort
231
- {
232
- __block UInt16 result;
233
-
234
- dispatch_sync(serverQueue, ^{
235
- if (isRunning)
236
- result = [asyncSocket localPort];
237
- else
238
- result = 0;
239
- });
240
-
241
- return result;
242
- }
243
-
244
- - (void)setPort:(UInt16)value
245
- {
246
- HTTPLogTrace();
247
-
248
- dispatch_async(serverQueue, ^{
249
- port = value;
250
- });
251
- }
252
-
253
- /**
254
- * Domain on which to broadcast this service via Bonjour.
255
- * The default domain is @"local".
256
- **/
257
- - (NSString *)domain
258
- {
259
- __block NSString *result;
260
-
261
- dispatch_sync(serverQueue, ^{
262
- result = domain;
263
- });
264
-
265
- return result;
266
- }
267
-
268
- - (void)setDomain:(NSString *)value
269
- {
270
- HTTPLogTrace();
271
-
272
- NSString *valueCopy = [value copy];
273
-
274
- dispatch_async(serverQueue, ^{
275
- domain = valueCopy;
276
- });
277
-
278
- }
279
-
280
- /**
281
- * The name to use for this service via Bonjour.
282
- * The default name is an empty string,
283
- * which should result in the published name being the host name of the computer.
284
- **/
285
- - (NSString *)name
286
- {
287
- __block NSString *result;
288
-
289
- dispatch_sync(serverQueue, ^{
290
- result = name;
291
- });
292
-
293
- return result;
294
- }
295
-
296
- - (NSString *)publishedName
297
- {
298
- __block NSString *result;
299
-
300
- dispatch_sync(serverQueue, ^{
301
-
302
- if (netService == nil)
303
- {
304
- result = nil;
305
- }
306
- else
307
- {
308
-
309
- dispatch_block_t bonjourBlock = ^{
310
- result = [[netService name] copy];
311
- };
312
-
313
- [[self class] performBonjourBlock:bonjourBlock];
314
- }
315
- });
316
-
317
- return result;
318
- }
319
-
320
- - (void)setName:(NSString *)value
321
- {
322
- NSString *valueCopy = [value copy];
323
-
324
- dispatch_async(serverQueue, ^{
325
- name = valueCopy;
326
- });
327
-
328
- }
329
-
330
- /**
331
- * The type of service to publish via Bonjour.
332
- * No type is set by default, and one must be set in order for the service to be published.
333
- **/
334
- - (NSString *)type
335
- {
336
- __block NSString *result;
337
-
338
- dispatch_sync(serverQueue, ^{
339
- result = type;
340
- });
341
-
342
- return result;
343
- }
344
-
345
- - (void)setType:(NSString *)value
346
- {
347
- NSString *valueCopy = [value copy];
348
-
349
- dispatch_async(serverQueue, ^{
350
- type = valueCopy;
351
- });
352
-
353
- }
354
-
355
- /**
356
- * The extra data to use for this service via Bonjour.
357
- **/
358
- - (NSDictionary *)TXTRecordDictionary
359
- {
360
- __block NSDictionary *result;
361
-
362
- dispatch_sync(serverQueue, ^{
363
- result = txtRecordDictionary;
364
- });
365
-
366
- return result;
367
- }
368
-
369
- - (void)setTXTRecordDictionary:(NSDictionary *)value
370
- {
371
- HTTPLogTrace();
372
-
373
- NSDictionary *valueCopy = [value copy];
374
-
375
- dispatch_async(serverQueue, ^{
376
-
377
- txtRecordDictionary = valueCopy;
378
-
379
- // Update the txtRecord of the netService if it has already been published
380
- if (netService)
381
- {
382
- NSNetService *theNetService = netService;
383
- NSData *txtRecordData = nil;
384
- if (txtRecordDictionary)
385
- txtRecordData = [NSNetService dataFromTXTRecordDictionary:txtRecordDictionary];
386
-
387
- dispatch_block_t bonjourBlock = ^{
388
- [theNetService setTXTRecordData:txtRecordData];
389
- };
390
-
391
- [[self class] performBonjourBlock:bonjourBlock];
392
- }
393
- });
394
-
395
- }
396
-
397
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
398
- #pragma mark Server Control
399
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
400
-
401
- - (BOOL)start:(NSError **)errPtr
402
- {
403
- HTTPLogTrace();
404
-
405
- __block BOOL success = YES;
406
- __block NSError *err = nil;
407
-
408
- dispatch_sync(serverQueue, ^{ @autoreleasepool {
409
-
410
- success = [asyncSocket acceptOnInterface:interface port:port error:&err];
411
- if (success)
412
- {
413
- HTTPLogInfo(@"%@: Started HTTP server on port %hu", THIS_FILE, [asyncSocket localPort]);
414
-
415
- isRunning = YES;
416
- [self publishBonjour];
417
- }
418
- else
419
- {
420
- HTTPLogError(@"%@: Failed to start HTTP Server: %@", THIS_FILE, err);
421
- }
422
- }});
423
-
424
- if (errPtr)
425
- *errPtr = err;
426
-
427
- return success;
428
- }
429
-
430
- - (void)stop
431
- {
432
- [self stop:NO];
433
- }
434
-
435
- - (void)stop:(BOOL)keepExistingConnections
436
- {
437
- HTTPLogTrace();
438
-
439
- dispatch_sync(serverQueue, ^{ @autoreleasepool {
440
-
441
- // First stop publishing the service via bonjour
442
- [self unpublishBonjour];
443
-
444
- // Stop listening / accepting incoming connections
445
- [asyncSocket disconnect];
446
- isRunning = NO;
447
-
448
- if (!keepExistingConnections)
449
- {
450
- // Stop all HTTP connections the server owns
451
- [connectionsLock lock];
452
- for (HTTPConnection *connection in connections)
453
- {
454
- [connection stop];
455
- }
456
- [connections removeAllObjects];
457
- [connectionsLock unlock];
458
- }
459
- }});
460
- }
461
-
462
- - (BOOL)isRunning
463
- {
464
- __block BOOL result;
465
-
466
- dispatch_sync(serverQueue, ^{
467
- result = isRunning;
468
- });
469
-
470
- return result;
471
- }
472
-
473
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
474
- #pragma mark Server Status
475
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
476
-
477
- /**
478
- * Returns the number of http client connections that are currently connected to the server.
479
- **/
480
- - (NSUInteger)numberOfHTTPConnections
481
- {
482
- NSUInteger result = 0;
483
-
484
- [connectionsLock lock];
485
- result = [connections count];
486
- [connectionsLock unlock];
487
-
488
- return result;
489
- }
490
-
491
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
492
- #pragma mark Incoming Connections
493
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
494
-
495
- - (HTTPConfig *)config
496
- {
497
- // Override me if you want to provide a custom config to the new connection.
498
- //
499
- // Generally this involves overriding the HTTPConfig class to include any custom settings,
500
- // and then having this method return an instance of 'MyHTTPConfig'.
501
-
502
- // Note: Think you can make the server faster by putting each connection on its own queue?
503
- // Then benchmark it before and after and discover for yourself the shocking truth!
504
- //
505
- // Try the apache benchmark tool (already installed on your Mac):
506
- // $ ab -n 1000 -c 1 http://localhost:<port>/some_path.html
507
-
508
- return [[HTTPConfig alloc] initWithServer:self documentRoot:documentRoot queue:connectionQueue];
509
- }
510
-
511
- - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket
512
- {
513
- HTTPConnection *newConnection = (HTTPConnection *)[[connectionClass alloc] initWithAsyncSocket:newSocket
514
- configuration:[self config]];
515
- [connectionsLock lock];
516
- [connections addObject:newConnection];
517
- [connectionsLock unlock];
518
-
519
- [newConnection start];
520
- }
521
-
522
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
523
- #pragma mark Bonjour
524
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
525
-
526
- - (void)publishBonjour
527
- {
528
- HTTPLogTrace();
529
-
530
- NSAssert(dispatch_get_specific(IsOnServerQueueKey) != NULL, @"Must be on serverQueue");
531
-
532
- if (type)
533
- {
534
- netService = [[NSNetService alloc] initWithDomain:domain type:type name:name port:[asyncSocket localPort]];
535
- [netService setDelegate:self];
536
-
537
- NSNetService *theNetService = netService;
538
- NSData *txtRecordData = nil;
539
- if (txtRecordDictionary)
540
- txtRecordData = [NSNetService dataFromTXTRecordDictionary:txtRecordDictionary];
541
-
542
- dispatch_block_t bonjourBlock = ^{
543
-
544
- [theNetService removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
545
- [theNetService scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
546
- [theNetService publish];
547
-
548
- // Do not set the txtRecordDictionary prior to publishing!!!
549
- // This will cause the OS to crash!!!
550
- if (txtRecordData)
551
- {
552
- [theNetService setTXTRecordData:txtRecordData];
553
- }
554
- };
555
-
556
- [[self class] startBonjourThreadIfNeeded];
557
- [[self class] performBonjourBlock:bonjourBlock];
558
- }
559
- }
560
-
561
- - (void)unpublishBonjour
562
- {
563
- HTTPLogTrace();
564
-
565
- NSAssert(dispatch_get_specific(IsOnServerQueueKey) != NULL, @"Must be on serverQueue");
566
-
567
- if (netService)
568
- {
569
- NSNetService *theNetService = netService;
570
-
571
- dispatch_block_t bonjourBlock = ^{
572
-
573
- [theNetService stop];
574
- };
575
-
576
- [[self class] performBonjourBlock:bonjourBlock];
577
-
578
- netService = nil;
579
- }
580
- }
581
-
582
- /**
583
- * Republishes the service via bonjour if the server is running.
584
- * If the service was not previously published, this method will publish it (if the server is running).
585
- **/
586
- - (void)republishBonjour
587
- {
588
- HTTPLogTrace();
589
-
590
- dispatch_async(serverQueue, ^{
591
-
592
- [self unpublishBonjour];
593
- [self publishBonjour];
594
- });
595
- }
596
-
597
- /**
598
- * Called when our bonjour service has been successfully published.
599
- * This method does nothing but output a log message telling us about the published service.
600
- **/
601
- - (void)netServiceDidPublish:(NSNetService *)ns
602
- {
603
- // Override me to do something here...
604
- //
605
- // Note: This method is invoked on our bonjour thread.
606
-
607
- HTTPLogInfo(@"Bonjour Service Published: domain(%@) type(%@) name(%@)", [ns domain], [ns type], [ns name]);
608
- }
609
-
610
- /**
611
- * Called if our bonjour service failed to publish itself.
612
- * This method does nothing but output a log message telling us about the published service.
613
- **/
614
- - (void)netService:(NSNetService *)ns didNotPublish:(NSDictionary *)errorDict
615
- {
616
- // Override me to do something here...
617
- //
618
- // Note: This method in invoked on our bonjour thread.
619
-
620
- HTTPLogWarn(@"Failed to Publish Service: domain(%@) type(%@) name(%@) - %@",
621
- [ns domain], [ns type], [ns name], errorDict);
622
- }
623
-
624
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
625
- #pragma mark Notifications
626
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
627
-
628
- /**
629
- * This method is automatically called when a notification of type HTTPConnectionDidDieNotification is posted.
630
- * It allows us to remove the connection from our array.
631
- **/
632
- - (void)connectionDidDie:(NSNotification *)notification
633
- {
634
- // Note: This method is called on the connection queue that posted the notification
635
-
636
- [connectionsLock lock];
637
-
638
- HTTPLogTrace();
639
- [connections removeObject:[notification object]];
640
-
641
- [connectionsLock unlock];
642
- }
643
-
644
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
645
- #pragma mark Bonjour Thread
646
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
647
-
648
- /**
649
- * NSNetService is runloop based, so it requires a thread with a runloop.
650
- * This gives us two options:
651
- *
652
- * - Use the main thread
653
- * - Setup our own dedicated thread
654
- *
655
- * Since we have various blocks of code that need to synchronously access the netservice objects,
656
- * using the main thread becomes troublesome and a potential for deadlock.
657
- **/
658
-
659
- static NSThread *bonjourThread;
660
-
661
- + (void)startBonjourThreadIfNeeded
662
- {
663
- HTTPLogTrace();
664
-
665
- static dispatch_once_t predicate;
666
- dispatch_once(&predicate, ^{
667
-
668
- HTTPLogVerbose(@"%@: Starting bonjour thread...", THIS_FILE);
669
-
670
- bonjourThread = [[NSThread alloc] initWithTarget:self
671
- selector:@selector(bonjourThread)
672
- object:nil];
673
- [bonjourThread start];
674
- });
675
- }
676
-
677
- + (void)bonjourThread
678
- {
679
- @autoreleasepool {
680
-
681
- HTTPLogVerbose(@"%@: BonjourThread: Started", THIS_FILE);
682
-
683
- // We can't run the run loop unless it has an associated input source or a timer.
684
- // So we'll just create a timer that will never fire - unless the server runs for 10,000 years.
685
- #pragma clang diagnostic push
686
- #pragma clang diagnostic ignored "-Wundeclared-selector"
687
- [NSTimer scheduledTimerWithTimeInterval:[[NSDate distantFuture] timeIntervalSinceNow]
688
- target:self
689
- selector:@selector(donothingatall:)
690
- userInfo:nil
691
- repeats:YES];
692
- #pragma clang diagnostic pop
693
-
694
- [[NSRunLoop currentRunLoop] run];
695
-
696
- HTTPLogVerbose(@"%@: BonjourThread: Aborted", THIS_FILE);
697
-
698
- }
699
- }
700
-
701
- + (void)executeBonjourBlock:(dispatch_block_t)block
702
- {
703
- HTTPLogTrace();
704
-
705
- NSAssert([NSThread currentThread] == bonjourThread, @"Executed on incorrect thread");
706
-
707
- block();
708
- }
709
-
710
- + (void)performBonjourBlock:(dispatch_block_t)block
711
- {
712
- HTTPLogTrace();
713
-
714
- [self performSelector:@selector(executeBonjourBlock:)
715
- onThread:bonjourThread
716
- withObject:block
717
- waitUntilDone:YES];
718
- }
719
-
720
- @end