appium-webdriveragent 16.5.1 → 16.7.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.
- package/CHANGELOG.md +12 -0
- package/WebDriverAgent.xcodeproj/project.pbxproj +48 -300
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentLib/Routing/{WatchOS/FBWatchHTTPServer.h → FBHTTPServer.h} +11 -7
- package/WebDriverAgentLib/Routing/{WatchOS/FBWatchHTTPServer.m → FBHTTPServer.m} +26 -13
- package/WebDriverAgentLib/Routing/FBTCPSocket.h +17 -45
- package/WebDriverAgentLib/Routing/FBTCPSocket.m +16 -95
- package/WebDriverAgentLib/Routing/FBWebServer.h +1 -1
- package/WebDriverAgentLib/Routing/FBWebServer.m +5 -55
- package/WebDriverAgentLib/Routing/{WatchOS/RouteRequest.h → RouteRequest.h} +2 -4
- package/WebDriverAgentLib/Routing/{WatchOS/RouteResponse.h → RouteResponse.h} +2 -2
- package/WebDriverAgentLib/Utilities/FBMjpegServer.h +7 -0
- package/WebDriverAgentLib/Utilities/FBMjpegServer.m +15 -16
- package/WebDriverAgentTests/IntegrationTests_watchOS/IntegrationTests_watchOS-Bridging-Header.h +2 -0
- package/WebDriverAgentTests/IntegrationTests_watchOS/WDAMjpegStreamingIntegrationTests.swift +81 -0
- package/package.json +1 -1
- package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h +0 -1220
- package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +0 -8786
- package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.h +0 -1036
- package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.m +0 -5868
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDNumber.h +0 -12
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDNumber.m +0 -88
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDRange.h +0 -56
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Categories/DDRange.m +0 -100
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPConnection.h +0 -109
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPConnection.m +0 -2281
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPLogging.h +0 -122
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPMessage.h +0 -53
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPMessage.m +0 -357
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPResponse.h +0 -149
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPServer.h +0 -126
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPServer.m +0 -372
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/LICENSE +0 -18
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPDataResponse.h +0 -13
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPDataResponse.m +0 -83
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPErrorResponse.h +0 -9
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/Responses/HTTPErrorResponse.m +0 -38
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/HTTPResponseProxy.h +0 -13
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/HTTPResponseProxy.m +0 -84
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/LICENSE +0 -19
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/Route.h +0 -18
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/Route.m +0 -11
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteRequest.h +0 -16
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteRequest.m +0 -50
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteResponse.h +0 -20
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RouteResponse.m +0 -66
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingConnection.h +0 -5
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingConnection.m +0 -142
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingHTTPServer.h +0 -55
- package/WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingHTTPServer.m +0 -303
- /package/WebDriverAgentLib/Routing/{WatchOS/RouteRequest.m → RouteRequest.m} +0 -0
- /package/WebDriverAgentLib/Routing/{WatchOS/RouteResponse.m → RouteResponse.m} +0 -0
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
<key>CFBundlePackageType</key>
|
|
16
16
|
<string>FMWK</string>
|
|
17
17
|
<key>CFBundleShortVersionString</key>
|
|
18
|
-
<string>16.
|
|
18
|
+
<string>16.7.0</string>
|
|
19
19
|
<key>CFBundleSignature</key>
|
|
20
20
|
<string>????</string>
|
|
21
21
|
<key>CFBundleVersion</key>
|
|
22
|
-
<string>16.
|
|
22
|
+
<string>16.7.0</string>
|
|
23
23
|
<key>NSPrincipalClass</key>
|
|
24
24
|
<string/>
|
|
25
25
|
</dict>
|
|
@@ -6,13 +6,11 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
//
|
|
10
|
-
// forbids - see FBTCPSocket.h/.m.
|
|
11
|
-
// FBTCPSocket, mirroring just enough of RoutingHTTPServer's API for FBWebServer.m to swap
|
|
12
|
-
// servers with a single #if TARGET_OS_WATCH.
|
|
9
|
+
// A minimal HTTP/1.1 server on top of FBTCPSocket (Network.framework-backed on every platform,
|
|
10
|
+
// since watchOS forbids BSD sockets outright - see FBTCPSocket.h/.m).
|
|
13
11
|
//
|
|
14
12
|
// No chunked encoding, range requests, or pipelining - just request line + headers +
|
|
15
|
-
// Content-Length body, and ":param" path matching
|
|
13
|
+
// Content-Length body, and ":param" path matching.
|
|
16
14
|
|
|
17
15
|
@import Foundation;
|
|
18
16
|
|
|
@@ -21,7 +19,7 @@
|
|
|
21
19
|
|
|
22
20
|
NS_ASSUME_NONNULL_BEGIN
|
|
23
21
|
|
|
24
|
-
@interface
|
|
22
|
+
@interface FBHTTPServer : NSObject
|
|
25
23
|
|
|
26
24
|
/*! The port the server is (or will be) listening on */
|
|
27
25
|
@property (nonatomic) uint16_t port;
|
|
@@ -40,9 +38,15 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
40
38
|
*/
|
|
41
39
|
- (void)setDefaultHeader:(NSString *)field value:(NSString *)value;
|
|
42
40
|
|
|
41
|
+
/**
|
|
42
|
+
Sets the local IP address to bind the listener to. Must be called before -start:. Pass nil (the
|
|
43
|
+
default) to listen on all interfaces.
|
|
44
|
+
*/
|
|
45
|
+
- (void)setInterface:(nullable NSString *)interface;
|
|
46
|
+
|
|
43
47
|
/**
|
|
44
48
|
Registers a route handler for the given HTTP method and path pattern (":param" segments are
|
|
45
|
-
captured into the request's `params
|
|
49
|
+
captured into the request's `params`).
|
|
46
50
|
*/
|
|
47
51
|
- (void)handleMethod:(NSString *)method
|
|
48
52
|
withPath:(NSString *)path
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
#import "
|
|
9
|
+
#import "FBHTTPServer.h"
|
|
10
10
|
|
|
11
11
|
#import "FBConfiguration.h"
|
|
12
12
|
#import "FBTCPSocket.h"
|
|
@@ -28,29 +28,30 @@ static NSData * _Nonnull FBUTF8Data(NSString *string)
|
|
|
28
28
|
return (NSData * _Nonnull)[string dataUsingEncoding:NSUTF8StringEncoding];
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
@interface
|
|
31
|
+
@interface FBHTTPRoute : NSObject
|
|
32
32
|
@property (nonatomic, copy) NSString *verb;
|
|
33
33
|
@property (nonatomic, strong) NSRegularExpression *regex;
|
|
34
34
|
@property (nonatomic, copy, nullable) NSArray<NSString *> *keys;
|
|
35
35
|
@property (nonatomic, copy) void (^block)(RouteRequest *request, RouteResponse *response);
|
|
36
36
|
@end
|
|
37
37
|
|
|
38
|
-
@implementation
|
|
38
|
+
@implementation FBHTTPRoute
|
|
39
39
|
@end
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
@interface
|
|
42
|
+
@interface FBHTTPServer () <FBTCPSocketDelegate>
|
|
43
43
|
|
|
44
44
|
@property (nonatomic, nullable, strong) FBTCPSocket *socket;
|
|
45
|
-
@property (nonatomic, strong) NSMutableArray<
|
|
45
|
+
@property (nonatomic, strong) NSMutableArray<FBHTTPRoute *> *routes;
|
|
46
46
|
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSString *> *defaultHeaders;
|
|
47
47
|
@property (nonatomic, nullable) dispatch_queue_t routeQueue;
|
|
48
|
+
@property (nonatomic, copy, nullable) NSString *interface;
|
|
48
49
|
// nw_connection_t isn't NSCopying, so it can't be an NSDictionary key - use NSMapTable instead.
|
|
49
50
|
@property (nonatomic, strong) NSMapTable<id, NSMutableData *> *connectionBuffers;
|
|
50
51
|
|
|
51
52
|
@end
|
|
52
53
|
|
|
53
|
-
@implementation
|
|
54
|
+
@implementation FBHTTPServer
|
|
54
55
|
|
|
55
56
|
- (instancetype)init
|
|
56
57
|
{
|
|
@@ -73,15 +74,20 @@ static NSData * _Nonnull FBUTF8Data(NSString *string)
|
|
|
73
74
|
self.defaultHeaders[field] = value;
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
- (void)setInterface:(nullable NSString *)interface
|
|
78
|
+
{
|
|
79
|
+
_interface = interface.copy;
|
|
80
|
+
}
|
|
81
|
+
|
|
76
82
|
#pragma mark - Route registration
|
|
77
83
|
|
|
78
|
-
- (
|
|
84
|
+
- (FBHTTPRoute *)compiledRouteWithPath:(NSString *)path
|
|
79
85
|
{
|
|
80
|
-
|
|
86
|
+
FBHTTPRoute *route = [FBHTTPRoute new];
|
|
81
87
|
NSMutableArray<NSString *> *keys = [NSMutableArray array];
|
|
82
88
|
|
|
83
89
|
// Escape regex-significant characters before substituting :param placeholders, like
|
|
84
|
-
// RoutingHTTPServer.m
|
|
90
|
+
// RoutingHTTPServer.m used to.
|
|
85
91
|
NSRegularExpression *escapeRegex = [NSRegularExpression regularExpressionWithPattern:@"[.+()]"
|
|
86
92
|
options:(NSRegularExpressionOptions)0
|
|
87
93
|
error:nil];
|
|
@@ -126,7 +132,7 @@ static NSData * _Nonnull FBUTF8Data(NSString *string)
|
|
|
126
132
|
withPath:(NSString *)path
|
|
127
133
|
block:(void (^)(RouteRequest *request, RouteResponse *response))block
|
|
128
134
|
{
|
|
129
|
-
|
|
135
|
+
FBHTTPRoute *route = [self compiledRouteWithPath:path];
|
|
130
136
|
route.verb = method.uppercaseString;
|
|
131
137
|
route.block = block;
|
|
132
138
|
[self.routes addObject:route];
|
|
@@ -142,6 +148,7 @@ static NSData * _Nonnull FBUTF8Data(NSString *string)
|
|
|
142
148
|
- (BOOL)start:(NSError **)error
|
|
143
149
|
{
|
|
144
150
|
FBTCPSocket *socket = [[FBTCPSocket alloc] initWithPort:self.port];
|
|
151
|
+
socket.interface = self.interface;
|
|
145
152
|
socket.delegate = self;
|
|
146
153
|
if (![socket startWithError:error]) {
|
|
147
154
|
return NO;
|
|
@@ -239,8 +246,8 @@ static NSData * _Nonnull FBUTF8Data(NSString *string)
|
|
|
239
246
|
|
|
240
247
|
NSUInteger contentLength = (NSUInteger)requestHeaders[@"content-length"].integerValue;
|
|
241
248
|
if (contentLength > FBConfiguration.sharedInstance.httpRequestBodySizeLimit) {
|
|
242
|
-
// Mirrors
|
|
243
|
-
//
|
|
249
|
+
// Mirrors CocoaHTTPServer's maxRequestBodySize enforcement. Closes the connection after
|
|
250
|
+
// responding, since the rest of the oversized body is still incoming.
|
|
244
251
|
RouteResponse *tooLarge = [RouteResponse new];
|
|
245
252
|
tooLarge.statusCode = kHTTPStatusCodeRequestEntityTooLarge;
|
|
246
253
|
[tooLarge respondWithString:@"Request Entity Too Large"];
|
|
@@ -269,7 +276,7 @@ static NSData * _Nonnull FBUTF8Data(NSString *string)
|
|
|
269
276
|
NSURLComponents *requestTarget = [NSURLComponents componentsWithString:pathAndQuery];
|
|
270
277
|
NSString *path = requestTarget.path ?: pathAndQuery;
|
|
271
278
|
|
|
272
|
-
for (
|
|
279
|
+
for (FBHTTPRoute *route in self.routes) {
|
|
273
280
|
if (![route.verb isEqualToString:method]) {
|
|
274
281
|
continue;
|
|
275
282
|
}
|
|
@@ -367,6 +374,12 @@ static NSData * _Nonnull FBUTF8Data(NSString *string)
|
|
|
367
374
|
return @"Bad Request";
|
|
368
375
|
} else if (kHTTPStatusCodeNotFound == statusCode) {
|
|
369
376
|
return @"Not Found";
|
|
377
|
+
} else if (kHTTPStatusCodeMethodNotAllowed == statusCode) {
|
|
378
|
+
return @"Method Not Allowed";
|
|
379
|
+
} else if (kHTTPStatusCodeRequestTimeout == statusCode) {
|
|
380
|
+
return @"Request Timeout";
|
|
381
|
+
} else if (kHTTPStatusCodeRequestEntityTooLarge == statusCode) {
|
|
382
|
+
return @"Request Entity Too Large";
|
|
370
383
|
} else if (kHTTPStatusCodeInternalServerError == statusCode) {
|
|
371
384
|
return @"Internal Server Error";
|
|
372
385
|
}
|
|
@@ -6,28 +6,18 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
// TARGET_OS_WATCH must be defined before the #if below runs, or (on some older Xcode/SDK
|
|
10
|
-
// toolchains) it silently evaluates as undefined/false here despite being true for the rest of
|
|
11
|
-
// the translation unit - which desyncs this file's declarations from FBTCPSocket.m's own
|
|
12
|
-
// #if TARGET_OS_WATCH branch.
|
|
13
|
-
#import <TargetConditionals.h>
|
|
14
|
-
|
|
15
|
-
#if TARGET_OS_WATCH
|
|
16
9
|
@import Foundation;
|
|
17
10
|
// A textual import, not `@import Network;` - older Xcode/watchOS SDK combinations (verified:
|
|
18
11
|
// Xcode 15.4/watchOS 10.5) fail to expose nw_listener_t/nw_connection_t and friends through the
|
|
19
12
|
// Network module map on watchOS, even though the underlying API has existed since watchOS 5.0.
|
|
13
|
+
// Kept unconditional (rather than gated to watchOS) since it also builds cleanly on iOS/tvOS.
|
|
20
14
|
#import <Network/Network.h>
|
|
21
|
-
#else
|
|
22
|
-
#import "GCDAsyncSocket.h"
|
|
23
|
-
#endif
|
|
24
15
|
|
|
25
16
|
NS_ASSUME_NONNULL_BEGIN
|
|
26
17
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
// hence a differently-shaped, push-style delegate protocol.
|
|
18
|
+
// Backed by Network.framework rather than BSD sockets on every platform, since watchOS forbids
|
|
19
|
+
// BSD sockets outright and there is no reason to keep a second, socket-based implementation
|
|
20
|
+
// around just for iOS/tvOS.
|
|
31
21
|
@protocol FBTCPSocketDelegate <NSObject>
|
|
32
22
|
|
|
33
23
|
/**
|
|
@@ -54,35 +44,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
54
44
|
|
|
55
45
|
@end
|
|
56
46
|
|
|
57
|
-
#else
|
|
58
|
-
|
|
59
|
-
@protocol FBTCPSocketDelegate
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
The callback which is fired on new TCP client connection
|
|
63
|
-
|
|
64
|
-
@param newClient The newly connected socket
|
|
65
|
-
*/
|
|
66
|
-
- (void)didClientConnect:(GCDAsyncSocket *)newClient;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
The callback which is fired when the TCP server receives a data from a connected client
|
|
70
|
-
|
|
71
|
-
@param client The client, which sent the data
|
|
72
|
-
*/
|
|
73
|
-
- (void)didClientSendData:(GCDAsyncSocket *)client;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
The callback which is fired when TCP client disconnects
|
|
77
|
-
|
|
78
|
-
@param client The actual diconnected client
|
|
79
|
-
*/
|
|
80
|
-
- (void)didClientDisconnect:(GCDAsyncSocket *)client;
|
|
81
|
-
|
|
82
|
-
@end
|
|
83
|
-
|
|
84
|
-
#endif
|
|
85
|
-
|
|
86
47
|
|
|
87
48
|
@interface FBTCPSocket : NSObject
|
|
88
49
|
|
|
@@ -92,6 +53,19 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
92
53
|
@property (nullable, nonatomic, assign) id<FBTCPSocketDelegate> delegate;
|
|
93
54
|
#endif
|
|
94
55
|
|
|
56
|
+
/**
|
|
57
|
+
The port this socket is listening on. Equal to the port passed to -initWithPort: unless that was
|
|
58
|
+
0 ("let the system assign a port"), in which case this reflects the actually assigned port once
|
|
59
|
+
-startWithError: has returned successfully.
|
|
60
|
+
*/
|
|
61
|
+
@property (nonatomic, readonly) uint16_t port;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
The local IP address to bind the listener to, or nil to listen on all interfaces. Must be set
|
|
65
|
+
before -startWithError: is called.
|
|
66
|
+
*/
|
|
67
|
+
@property (nonatomic, copy, nullable) NSString *interface;
|
|
68
|
+
|
|
95
69
|
/**
|
|
96
70
|
Creates TCP socket isntance which is going to be started on the specified port
|
|
97
71
|
|
|
@@ -113,7 +87,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
113
87
|
*/
|
|
114
88
|
- (void)stop;
|
|
115
89
|
|
|
116
|
-
#if TARGET_OS_WATCH
|
|
117
90
|
/**
|
|
118
91
|
Writes data to the given connected client
|
|
119
92
|
|
|
@@ -132,7 +105,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
132
105
|
@param completion Called once the send attempt finishes
|
|
133
106
|
*/
|
|
134
107
|
- (void)writeData:(NSData *)data toClient:(nw_connection_t)client completion:(nullable void (^)(void))completion;
|
|
135
|
-
#endif
|
|
136
108
|
|
|
137
109
|
@end
|
|
138
110
|
|
|
@@ -8,13 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
#import "FBTCPSocket.h"
|
|
10
10
|
|
|
11
|
-
#if TARGET_OS_WATCH
|
|
12
|
-
|
|
13
11
|
@interface FBTCPSocket()
|
|
14
12
|
@property (readonly, nonatomic) dispatch_queue_t socketQueue;
|
|
15
13
|
@property (nullable, nonatomic) nw_listener_t listener;
|
|
16
14
|
@property (readonly, nonatomic) NSMutableArray<nw_connection_t> *connectedClients;
|
|
17
|
-
@property (readonly, nonatomic) uint16_t port;
|
|
18
15
|
@end
|
|
19
16
|
|
|
20
17
|
|
|
@@ -38,7 +35,18 @@
|
|
|
38
35
|
NSString *portString = [NSString stringWithFormat:@"%u", (unsigned int)self.port];
|
|
39
36
|
// portString is always valid UTF8; -UTF8String is just declared nullable in general.
|
|
40
37
|
const char * _Nonnull portCString = (const char * _Nonnull)portString.UTF8String;
|
|
41
|
-
|
|
38
|
+
|
|
39
|
+
nw_listener_t listener;
|
|
40
|
+
if (nil != self.interface) {
|
|
41
|
+
const char * _Nonnull interfaceCString = (const char * _Nonnull)((NSString * _Nonnull)self.interface).UTF8String;
|
|
42
|
+
nw_endpoint_t localEndpoint = nw_endpoint_create_host(interfaceCString, portCString);
|
|
43
|
+
nw_parameters_set_local_endpoint(parameters, localEndpoint);
|
|
44
|
+
// The port is already encoded in localEndpoint above - do not also pass it to
|
|
45
|
+
// nw_listener_create_with_port, which would be ambiguous.
|
|
46
|
+
listener = nw_listener_create(parameters);
|
|
47
|
+
} else {
|
|
48
|
+
listener = nw_listener_create_with_port(portCString, parameters);
|
|
49
|
+
}
|
|
42
50
|
if (nil == listener) {
|
|
43
51
|
if (error) {
|
|
44
52
|
*error = [NSError errorWithDomain:@"FBTCPSocket"
|
|
@@ -61,6 +69,10 @@
|
|
|
61
69
|
// if/else, not switch: -Wswitch-enum, -Wswitch-default, and -Wcovered-switch-default can't
|
|
62
70
|
// all be satisfied by one switch statement at once.
|
|
63
71
|
if (nw_listener_state_ready == state) {
|
|
72
|
+
__strong typeof(weakSelf) strongSelf = weakSelf;
|
|
73
|
+
if (strongSelf) {
|
|
74
|
+
strongSelf->_port = nw_listener_get_port(listener);
|
|
75
|
+
}
|
|
64
76
|
dispatch_semaphore_signal(startupSemaphore);
|
|
65
77
|
} else if (nw_listener_state_failed == state || nw_listener_state_cancelled == state) {
|
|
66
78
|
// NSLocalizedDescriptionKey must be a string, not the underlying NSError itself, or
|
|
@@ -203,94 +215,3 @@
|
|
|
203
215
|
}
|
|
204
216
|
|
|
205
217
|
@end
|
|
206
|
-
|
|
207
|
-
#else
|
|
208
|
-
|
|
209
|
-
@interface FBTCPSocket()
|
|
210
|
-
@property (readonly, nonatomic) dispatch_queue_t socketQueue;
|
|
211
|
-
@property (readonly, nonatomic) GCDAsyncSocket *listeningSocket;
|
|
212
|
-
@property (readonly, nonatomic) NSMutableArray *connectedClients;
|
|
213
|
-
@property (readonly, nonatomic) uint16_t port;
|
|
214
|
-
@end
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
@interface FBTCPSocket(AsyncSocket) <GCDAsyncSocketDelegate>
|
|
218
|
-
|
|
219
|
-
@end
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
@implementation FBTCPSocket
|
|
223
|
-
|
|
224
|
-
- (instancetype)initWithPort:(uint16_t)port
|
|
225
|
-
{
|
|
226
|
-
if ((self = [super init])) {
|
|
227
|
-
_socketQueue = dispatch_queue_create("socketQueue", NULL);
|
|
228
|
-
_listeningSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:_socketQueue];
|
|
229
|
-
_connectedClients = [[NSMutableArray alloc] initWithCapacity:1];
|
|
230
|
-
_port = port;
|
|
231
|
-
_delegate = nil;
|
|
232
|
-
}
|
|
233
|
-
return self;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
- (BOOL)startWithError:(NSError **)error
|
|
237
|
-
{
|
|
238
|
-
if (![self.listeningSocket acceptOnPort:self.port error:error]) {
|
|
239
|
-
return NO;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
return YES;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
- (void)stop
|
|
246
|
-
{
|
|
247
|
-
@synchronized(self.connectedClients) {
|
|
248
|
-
NSArray *clients = self.connectedClients.copy;
|
|
249
|
-
[self.connectedClients removeAllObjects];
|
|
250
|
-
for (GCDAsyncSocket *client in clients) {
|
|
251
|
-
[client disconnect];
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
self.delegate = nil;
|
|
256
|
-
[self.listeningSocket disconnect];
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
@end
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
@implementation FBTCPSocket(AsyncSocket)
|
|
263
|
-
|
|
264
|
-
- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket
|
|
265
|
-
{
|
|
266
|
-
@synchronized(self.connectedClients) {
|
|
267
|
-
[self.connectedClients addObject:newSocket];
|
|
268
|
-
}
|
|
269
|
-
id<FBTCPSocketDelegate> delegate = self.delegate;
|
|
270
|
-
if (nil != delegate) {
|
|
271
|
-
[delegate didClientConnect:newSocket];
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
|
|
276
|
-
{
|
|
277
|
-
id<FBTCPSocketDelegate> delegate = self.delegate;
|
|
278
|
-
if (nil != delegate) {
|
|
279
|
-
[delegate didClientSendData:sock];
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
|
|
284
|
-
{
|
|
285
|
-
@synchronized(self.connectedClients) {
|
|
286
|
-
[self.connectedClients removeObject:sock];
|
|
287
|
-
}
|
|
288
|
-
id<FBTCPSocketDelegate> delegate = self.delegate;
|
|
289
|
-
if (nil != delegate) {
|
|
290
|
-
[delegate didClientDisconnect:sock];
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
@end
|
|
295
|
-
|
|
296
|
-
#endif
|
|
@@ -8,14 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
#import "FBWebServer.h"
|
|
10
10
|
|
|
11
|
-
#
|
|
12
|
-
#import "FBWatchHTTPServer.h"
|
|
13
|
-
#else
|
|
14
|
-
#import "RoutingConnection.h"
|
|
15
|
-
#import "RoutingHTTPServer.h"
|
|
11
|
+
#import "FBHTTPServer.h"
|
|
16
12
|
#import "FBMjpegServer.h"
|
|
17
13
|
#import "FBTCPSocket.h"
|
|
18
|
-
#endif
|
|
19
14
|
|
|
20
15
|
#import "FBCommandHandler.h"
|
|
21
16
|
#import "FBErrorBuilder.h"
|
|
@@ -32,36 +27,11 @@
|
|
|
32
27
|
static NSString *const FBServerURLBeginMarker = @"ServerURLHere->";
|
|
33
28
|
static NSString *const FBServerURLEndMarker = @"<-ServerURLHere";
|
|
34
29
|
|
|
35
|
-
#if !TARGET_OS_WATCH
|
|
36
|
-
@interface FBHTTPConnection : RoutingConnection
|
|
37
|
-
@end
|
|
38
|
-
|
|
39
|
-
@implementation FBHTTPConnection
|
|
40
|
-
|
|
41
|
-
- (void)handleResourceNotFound
|
|
42
|
-
{
|
|
43
|
-
[FBLogger logFmt:@"Received request for %@ which we do not handle", self.requestURI];
|
|
44
|
-
[super handleResourceNotFound];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
- (UInt64)maxRequestBodySize
|
|
48
|
-
{
|
|
49
|
-
return FBConfiguration.sharedInstance.httpRequestBodySizeLimit;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
@end
|
|
53
|
-
#endif
|
|
54
|
-
|
|
55
|
-
|
|
56
30
|
@interface FBWebServer ()
|
|
57
31
|
@property (nonatomic, strong) FBExceptionHandler *exceptionHandler;
|
|
58
|
-
|
|
59
|
-
@property (nonatomic, strong) FBWatchHTTPServer *server;
|
|
60
|
-
#else
|
|
61
|
-
@property (nonatomic, strong) RoutingHTTPServer *server;
|
|
32
|
+
@property (nonatomic, strong) FBHTTPServer *server;
|
|
62
33
|
@property (nonatomic, nullable) FBTCPSocket *screenshotsBroadcaster;
|
|
63
34
|
@property (nonatomic, nullable, strong) FBMjpegServer *mjpegServer;
|
|
64
|
-
#endif
|
|
65
35
|
@property (atomic, assign) BOOL keepAlive;
|
|
66
36
|
@end
|
|
67
37
|
|
|
@@ -69,9 +39,7 @@ static NSString *const FBServerURLEndMarker = @"<-ServerURLHere";
|
|
|
69
39
|
|
|
70
40
|
- (void)dealloc
|
|
71
41
|
{
|
|
72
|
-
#if !TARGET_OS_WATCH
|
|
73
42
|
[self stopScreenshotsBroadcaster];
|
|
74
|
-
#endif
|
|
75
43
|
}
|
|
76
44
|
|
|
77
45
|
+ (NSArray<Class<FBCommandHandler>> *)collectCommandHandlerClasses
|
|
@@ -96,9 +64,7 @@ static NSString *const FBServerURLEndMarker = @"<-ServerURLHere";
|
|
|
96
64
|
if (![self startHTTPServer]) {
|
|
97
65
|
return;
|
|
98
66
|
}
|
|
99
|
-
#if !TARGET_OS_WATCH
|
|
100
67
|
[self initScreenshotsBroadcaster];
|
|
101
|
-
#endif
|
|
102
68
|
|
|
103
69
|
self.keepAlive = YES;
|
|
104
70
|
NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
|
|
@@ -108,30 +74,21 @@ static NSString *const FBServerURLEndMarker = @"<-ServerURLHere";
|
|
|
108
74
|
|
|
109
75
|
- (BOOL)startHTTPServer
|
|
110
76
|
{
|
|
111
|
-
|
|
112
|
-
self.server = [[FBWatchHTTPServer alloc] init];
|
|
113
|
-
#else
|
|
114
|
-
self.server = [[RoutingHTTPServer alloc] init];
|
|
115
|
-
#endif
|
|
77
|
+
self.server = [[FBHTTPServer alloc] init];
|
|
116
78
|
[self.server setRouteQueue:dispatch_get_main_queue()];
|
|
117
79
|
[self.server setDefaultHeader:@"Server" value:@"WebDriverAgent/1.0"];
|
|
118
80
|
[self.server setDefaultHeader:@"Access-Control-Allow-Origin" value:@"*"];
|
|
119
81
|
[self.server setDefaultHeader:@"Access-Control-Allow-Headers" value:@"Content-Type, X-Requested-With"];
|
|
120
|
-
#if !TARGET_OS_WATCH
|
|
121
|
-
[self.server setConnectionClass:[FBHTTPConnection self]];
|
|
122
|
-
#endif
|
|
123
82
|
|
|
124
83
|
[self registerRouteHandlers:[self.class collectCommandHandlerClasses]];
|
|
125
84
|
[self registerServerKeyRouteHandlers];
|
|
126
85
|
|
|
127
86
|
NSRange serverPortRange = FBConfiguration.sharedInstance.bindingPortRange;
|
|
128
87
|
NSString *bindingIP = FBConfiguration.sharedInstance.bindingIPAddress;
|
|
129
|
-
#if !TARGET_OS_WATCH
|
|
130
88
|
if (bindingIP != nil) {
|
|
131
89
|
[self.server setInterface:bindingIP];
|
|
132
90
|
[FBLogger logFmt:@"Using custom binding IP address: %@", bindingIP];
|
|
133
91
|
}
|
|
134
|
-
#endif
|
|
135
92
|
|
|
136
93
|
NSError *error;
|
|
137
94
|
BOOL serverStarted = NO;
|
|
@@ -163,13 +120,13 @@ static NSString *const FBServerURLEndMarker = @"<-ServerURLHere";
|
|
|
163
120
|
return YES;
|
|
164
121
|
}
|
|
165
122
|
|
|
166
|
-
#if !TARGET_OS_WATCH
|
|
167
123
|
- (void)initScreenshotsBroadcaster
|
|
168
124
|
{
|
|
169
125
|
[self readMjpegSettingsFromEnv];
|
|
170
126
|
self.mjpegServer = [[FBMjpegServer alloc] init];
|
|
171
127
|
self.screenshotsBroadcaster = [[FBTCPSocket alloc]
|
|
172
128
|
initWithPort:(uint16_t)FBConfiguration.sharedInstance.mjpegServerPort];
|
|
129
|
+
self.mjpegServer.socket = self.screenshotsBroadcaster;
|
|
173
130
|
self.screenshotsBroadcaster.delegate = self.mjpegServer;
|
|
174
131
|
NSError *error;
|
|
175
132
|
if (![self.screenshotsBroadcaster startWithError:&error]) {
|
|
@@ -209,14 +166,11 @@ static NSString *const FBServerURLEndMarker = @"<-ServerURLHere";
|
|
|
209
166
|
FBConfiguration.sharedInstance.mjpegServerScreenshotQuality = [screenshotQuality integerValue];
|
|
210
167
|
}
|
|
211
168
|
}
|
|
212
|
-
#endif
|
|
213
169
|
|
|
214
170
|
- (void)stopServing
|
|
215
171
|
{
|
|
216
172
|
[FBSession.activeSession kill];
|
|
217
|
-
#if !TARGET_OS_WATCH
|
|
218
173
|
[self stopScreenshotsBroadcaster];
|
|
219
|
-
#endif
|
|
220
174
|
if (self.server.isRunning) {
|
|
221
175
|
[self.server stop:NO];
|
|
222
176
|
}
|
|
@@ -225,11 +179,7 @@ static NSString *const FBServerURLEndMarker = @"<-ServerURLHere";
|
|
|
225
179
|
self.keepAlive = NO;
|
|
226
180
|
}
|
|
227
181
|
|
|
228
|
-
|
|
229
|
-
- (BOOL)attemptToStartServer:(FBWatchHTTPServer *)server onPort:(NSInteger)port withError:(NSError **)error
|
|
230
|
-
#else
|
|
231
|
-
- (BOOL)attemptToStartServer:(RoutingHTTPServer *)server onPort:(NSInteger)port withError:(NSError **)error
|
|
232
|
-
#endif
|
|
182
|
+
- (BOOL)attemptToStartServer:(FBHTTPServer *)server onPort:(NSInteger)port withError:(NSError **)error
|
|
233
183
|
{
|
|
234
184
|
server.port = (UInt16)port;
|
|
235
185
|
NSError *innerError = nil;
|
|
@@ -6,10 +6,8 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// built there (see FBWatchHTTPServer.h). Exposes just the surface FBWebServer's route blocks
|
|
12
|
-
// and FBRoute.decorateRequest: read.
|
|
9
|
+
// A minimal request value type, exposing just the surface FBWebServer's route blocks and
|
|
10
|
+
// FBRoute.decorateRequest: read.
|
|
13
11
|
|
|
14
12
|
@import Foundation;
|
|
15
13
|
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
//
|
|
10
|
-
//
|
|
9
|
+
// A minimal response value type, exposing just the surface FBRoute.m/FBResponseJSONPayload.m
|
|
10
|
+
// call on it.
|
|
11
11
|
|
|
12
12
|
@import Foundation;
|
|
13
13
|
#import <WebDriverAgentLib/FBHTTPStatusCodes.h>
|
|
@@ -19,6 +19,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
19
19
|
*/
|
|
20
20
|
- (instancetype)init;
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
The socket that owns this instance as its delegate. Clients are bare nw_connection_t values
|
|
24
|
+
with no write method of their own, so frame writes are routed through
|
|
25
|
+
-[FBTCPSocket writeData:toClient:]. Must be set before streaming starts.
|
|
26
|
+
*/
|
|
27
|
+
@property (nonatomic, weak, nullable) FBTCPSocket *socket;
|
|
28
|
+
|
|
22
29
|
/**
|
|
23
30
|
Stops screenshot broadcasting and prevents future scheduling.
|
|
24
31
|
*/
|