Skip to content

Commit 1198040

Browse files
authored
DevServer connection fix - Improve sockets handshake response check (#577)
* Improve sockets handshake response check
1 parent a0e7c10 commit 1198040

File tree

6 files changed

+208
-2
lines changed

6 files changed

+208
-2
lines changed

LeanplumSDK/LeanplumSDK.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,10 @@
488488
6AD978582774F3F000A7C6C6 /* NotificationsProxy+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD978562774F3F000A7C6C6 /* NotificationsProxy+Utilities.swift */; };
489489
6ADC90C72807461F00CE42C7 /* Dictionary+ValueKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ADC90C62807461F00CE42C7 /* Dictionary+ValueKeyPath.swift */; };
490490
6ADC90C82807461F00CE42C7 /* Dictionary+ValueKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ADC90C62807461F00CE42C7 /* Dictionary+ValueKeyPath.swift */; };
491+
6B7B6E8C2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B7B6E8A2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h */; settings = {ATTRIBUTES = (Public, ); }; };
492+
6B7B6E8D2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B7B6E8A2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h */; settings = {ATTRIBUTES = (Public, ); }; };
493+
6B7B6E8E2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B7B6E8B2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m */; };
494+
6B7B6E8F2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B7B6E8B2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m */; };
491495
A0371C8C3E1D6D0AB924FF99 /* libPods-Leanplum-Static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 897B64EE76852A68ECECB184 /* libPods-Leanplum-Static.a */; };
492496
C90C489D2707299D00E33F1F /* NotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = C90C489C2707299D00E33F1F /* NotificationSettings.swift */; };
493497
C90C489E2707299D00E33F1F /* NotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = C90C489C2707299D00E33F1F /* NotificationSettings.swift */; };
@@ -829,6 +833,8 @@
829833
6AD978532774F2F700A7C6C6 /* NotificationsProxy+iOS9.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationsProxy+iOS9.swift"; sourceTree = "<group>"; };
830834
6AD978562774F3F000A7C6C6 /* NotificationsProxy+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationsProxy+Utilities.swift"; sourceTree = "<group>"; };
831835
6ADC90C62807461F00CE42C7 /* Dictionary+ValueKeyPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+ValueKeyPath.swift"; sourceTree = "<group>"; };
836+
6B7B6E8A2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Leanplum_WebSocket+Utils.h"; sourceTree = "<group>"; };
837+
6B7B6E8B2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "Leanplum_WebSocket+Utils.m"; sourceTree = "<group>"; };
832838
6C2FB1913D58B5EF901363C9 /* Pods_Leanplum.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Leanplum.framework; sourceTree = BUILT_PRODUCTS_DIR; };
833839
897B64EE76852A68ECECB184 /* libPods-Leanplum-Static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Leanplum-Static.a"; sourceTree = BUILT_PRODUCTS_DIR; };
834840
B335B24E5DF5CE017C0BE58D /* Pods-Leanplum-Static.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Leanplum-Static.release.xcconfig"; path = "Target Support Files/Pods-Leanplum-Static/Pods-Leanplum-Static.release.xcconfig"; sourceTree = "<group>"; };
@@ -1106,6 +1112,8 @@
11061112
075AADA826847EC3007CA1BD /* Leanplum_WebSocket.h */,
11071113
075AADA926847EC3007CA1BD /* AsyncSocket */,
11081114
075AADAC26847EC3007CA1BD /* Leanplum_WebSocket.m */,
1115+
6B7B6E8A2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h */,
1116+
6B7B6E8B2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m */,
11091117
);
11101118
path = WebSocket;
11111119
sourceTree = "<group>";
@@ -1454,6 +1462,7 @@
14541462
075AAE5526847EC4007CA1BD /* LPMessageTemplateUtilities.h in Headers */,
14551463
075AAE4026847EC4007CA1BD /* LPPushAskToAskMessageTemplate.h in Headers */,
14561464
075AAEA526847EC4007CA1BD /* UIDevice+IdentifierAddition.h in Headers */,
1465+
6B7B6E8C2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h in Headers */,
14571466
075AAE3126847EC4007CA1BD /* LPOpenUrlMessageTemplate.h in Headers */,
14581467
075AADF926847EC4007CA1BD /* LeanplumSocket.h in Headers */,
14591468
075AAEAC26847EC4007CA1BD /* LPVar-Internal.h in Headers */,
@@ -1542,6 +1551,7 @@
15421551
6A714B0326F8B317004A34A9 /* LPMessageTemplateUtilities.h in Headers */,
15431552
6A714B0426F8B317004A34A9 /* LPPushAskToAskMessageTemplate.h in Headers */,
15441553
6A714B0526F8B317004A34A9 /* UIDevice+IdentifierAddition.h in Headers */,
1554+
6B7B6E8D2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h in Headers */,
15451555
6A714B0626F8B317004A34A9 /* LPOpenUrlMessageTemplate.h in Headers */,
15461556
6A714B0726F8B317004A34A9 /* LeanplumSocket.h in Headers */,
15471557
6A714B0826F8B317004A34A9 /* LPVar-Internal.h in Headers */,
@@ -1896,6 +1906,7 @@
18961906
6A9DEC6E27ABD52D00052807 /* ActionManager+Processor.swift in Sources */,
18971907
075AAE9D26847EC4007CA1BD /* NSTimer+Blocks.m in Sources */,
18981908
075AAE2026847EC4007CA1BD /* LPLogManager.m in Sources */,
1909+
6B7B6E8E2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m in Sources */,
18991910
39C0819F2781D3D000C1DBD6 /* ActionManager+Queue.swift in Sources */,
19001911
6A29EAF528EF37090024880E /* IdentityManager.swift in Sources */,
19011912
075AAEB126847EC4007CA1BD /* LPSecuredVars.m in Sources */,
@@ -2026,6 +2037,7 @@
20262037
6A9DEC6F27ABD52D00052807 /* ActionManager+Processor.swift in Sources */,
20272038
6A714B8426F8B317004A34A9 /* LPAppIconManager.m in Sources */,
20282039
6A714B8526F8B317004A34A9 /* NSTimer+Blocks.m in Sources */,
2040+
6B7B6E8F2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m in Sources */,
20292041
6A714B8626F8B317004A34A9 /* LPLogManager.m in Sources */,
20302042
6A29EAF628EF37090024880E /* IdentityManager.swift in Sources */,
20312043
6A714B8726F8B317004A34A9 /* LPSecuredVars.m in Sources */,
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// Leanplum_WebSocket+Utils.h
3+
// LeanplumSDK
4+
//
5+
// Created by Nikola Zagorchev on 31.01.24.
6+
// Copyright © 2024 Leanplum. All rights reserved.
7+
8+
#import <Foundation/Foundation.h>
9+
#import "Leanplum_WebSocket.h"
10+
11+
NS_ASSUME_NONNULL_BEGIN
12+
13+
@interface Leanplum_WebSocket (Utils)
14+
15+
/**
16+
* Checks if the socket handshake response is successful.
17+
* Validates the HTTP status code, Upgrade and Connection headers.
18+
* @param response The handshake string response.
19+
*/
20+
+ (BOOL)isHandshakeSuccessful:(NSString *)response;
21+
22+
@end
23+
24+
NS_ASSUME_NONNULL_END
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//
2+
// Leanplum_WebSocket+Utils.m
3+
// LeanplumSDK
4+
//
5+
// Created by Nikola Zagorchev on 31.01.24.
6+
// Copyright © 2024 Leanplum. All rights reserved.
7+
8+
#import "Leanplum_WebSocket+Utils.h"
9+
#import "LPLogManager.h"
10+
11+
NSString* const kUpgradeHeader = @"upgrade:";
12+
NSString* const kConnectionHeader = @"connection:";
13+
NSString* const kStatusCodeString = @"101";
14+
15+
NSString* const kUpgradeHeaderExpected = @"websocket";
16+
NSString* const kConnectionHeaderExpected = @"upgrade";
17+
18+
@implementation Leanplum_WebSocket (Utils)
19+
20+
+ (BOOL)isHandshakeSuccessful:(NSString *)response {
21+
/*
22+
Check the status code and headers.
23+
Status code is the second value, after the protocol.
24+
Headers are case insensitive.
25+
Example reponse string (new lines can be \r\n or \n):
26+
@"HTTP/1.1 101 Switching Protocols\r\n\
27+
WebSocket-Origin: http://dev.leanplum.com\r\n\
28+
WebSocket-Location: ws://dev.leanplum.com/socket.io/1/websocket/y12oUiE3teSTh4S5TeSt\r\n\
29+
Date: Wed, 31 Jan 2024 15:27:15 GMT\r\n\
30+
Via: 1.1 google\r\n\
31+
Upgrade: websocket\r\n\
32+
Connection: Upgrade";
33+
*/
34+
35+
NSArray *lines = [response componentsSeparatedByString:@"\n"];
36+
NSString *firstLine = [lines firstObject];
37+
NSArray *firstLineComponents = [firstLine componentsSeparatedByString:@" "];
38+
if ([firstLineComponents count] > 2) {
39+
NSString *statusCode = firstLineComponents[1];
40+
if ([statusCode isEqualToString:kStatusCodeString]) {
41+
// Iterate through the lines to find Upgrade and Connection values
42+
NSString *upgradeValue;
43+
NSString *connectionValue;
44+
for (NSString *line in lines) {
45+
NSString *lineLowercase = [line lowercaseString];
46+
if ([lineLowercase hasPrefix:kUpgradeHeader]) {
47+
upgradeValue = [line substringFromIndex:[kUpgradeHeader length]];
48+
} else if ([lineLowercase hasPrefix:kConnectionHeader]) {
49+
connectionValue = [line substringFromIndex:[kConnectionHeader length]];
50+
}
51+
}
52+
if ([[upgradeValue lowercaseString] containsString:kUpgradeHeaderExpected] &&
53+
[[connectionValue lowercaseString] containsString:kConnectionHeaderExpected]) {
54+
return YES;
55+
}
56+
LPLog(LPDebug, @"Invalid Upgrade and/or Connection headers. Upgrade: %@, Connection: %@.", upgradeValue, connectionValue);
57+
} else {
58+
LPLog(LPDebug, @"Invalid Status Code: %@, line: %@.", statusCode, [lines firstObject]);
59+
}
60+
}
61+
62+
return NO;
63+
}
64+
65+
@end

LeanplumSDK/LeanplumSDK/Classes/Utilities/Vendor/WebSocket/Leanplum_WebSocket.m

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727

2828
#import "Leanplum_WebSocket.h"
2929
#import "Leanplum_AsyncSocket.h"
30-
30+
#import "Leanplum_WebSocket+Utils.h"
31+
#import "LPLogManager.h"
3132

3233
NSString* const Leanplum_WebSocketErrorDomain = @"WebSocketErrorDomain";
3334
NSString* const Leanplum_WebSocketException = @"WebSocketException";
@@ -160,7 +161,8 @@ -(void)onSocket:(Leanplum_AsyncSocket *)sock didWriteDataWithTag:(long)tag {
160161
-(void)onSocket:(Leanplum_AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
161162
if (tag == WebSocketTagHandshake) {
162163
NSString* response = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
163-
if ([response hasPrefix:@"HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\n"]) {
164+
LPLog(LPDebug, @"Handshake response: %@", response);
165+
if ([Leanplum_WebSocket isHandshakeSuccessful:response]) {
164166
connected = YES;
165167
[self _dispatchOpened];
166168

@@ -174,6 +176,7 @@ -(void)onSocket:(Leanplum_AsyncSocket *)sock didReadData:(NSData *)data withTag:
174176
if (firstByte != 0x00) return; // Discard message
175177
NSString* message = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(1, [data length]-2)] encoding:NSUTF8StringEncoding];
176178

179+
LPLog(LPDebug, @"Socket message: %@", message);
177180
[self _dispatchMessageReceived:message];
178181
[self _readNextMessage];
179182
}

LeanplumSDKApp/LeanplumSDKApp.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@
149149
6AF543A228E883AD0025F2A9 /* LeanplumLocationAndBeacons.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6AF5439728E882CA0025F2A9 /* LeanplumLocationAndBeacons.framework */; };
150150
6AF6426D298198160021A997 /* Leanplum.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6AA13C7B2900546400EDCA69 /* Leanplum.framework */; };
151151
6AF6426E298198160021A997 /* Leanplum.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6AA13C7B2900546400EDCA69 /* Leanplum.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
152+
6B7B6E912B6A962000820306 /* Leanplum_WebSocketTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B7B6E902B6A962000820306 /* Leanplum_WebSocketTest.m */; };
152153
779F1FAA8AA2F3872AC876B2 /* Pods_LeanplumSDKTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E3C9DA445D159EC6FF97D42D /* Pods_LeanplumSDKTests.framework */; };
153154
82DC3FE9A5761B14AF26B301 /* Pods_LeanplumSDKApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 916957E1B3EE91A34170B5C7 /* Pods_LeanplumSDKApp.framework */; };
154155
C9D064B1275DFB4B00A7A5F9 /* LeanplumNotificationsManagerUtilsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9D064B0275DFB4B00A7A5F9 /* LeanplumNotificationsManagerUtilsTest.swift */; };
@@ -369,6 +370,7 @@
369370
6AEAEE592795B68700680F84 /* Leanplum.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Leanplum.framework; sourceTree = BUILT_PRODUCTS_DIR; };
370371
6AEAEE612795B72A00680F84 /* LeanplumLocationAndBeacons.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LeanplumLocationAndBeacons.framework; sourceTree = BUILT_PRODUCTS_DIR; };
371372
6AF5438D28E882CA0025F2A9 /* LeanplumSDKLocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = LeanplumSDKLocation.xcodeproj; path = ../LeanplumSDKLocation/LeanplumSDKLocation.xcodeproj; sourceTree = "<group>"; };
373+
6B7B6E902B6A962000820306 /* Leanplum_WebSocketTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Leanplum_WebSocketTest.m; sourceTree = "<group>"; };
372374
916957E1B3EE91A34170B5C7 /* Pods_LeanplumSDKApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeanplumSDKApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
373375
B6B7D6D71F9664181C09E727 /* Pods-LeanplumSDKTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeanplumSDKTests.release.xcconfig"; path = "Target Support Files/Pods-LeanplumSDKTests/Pods-LeanplumSDKTests.release.xcconfig"; sourceTree = "<group>"; };
374376
C9D064B0275DFB4B00A7A5F9 /* LeanplumNotificationsManagerUtilsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeanplumNotificationsManagerUtilsTest.swift; sourceTree = "<group>"; };
@@ -518,6 +520,7 @@
518520
6A39C48D27283EE7000D5320 /* LeanplumSDKTests-Bridging-Header.h */,
519521
6A07FDAF283544E300995BE3 /* DictionaryValueKeyPathTest.swift */,
520522
6A8411BA2903080A009F0431 /* UtilitiesTest.swift */,
523+
6B7B6E902B6A962000820306 /* Leanplum_WebSocketTest.m */,
521524
);
522525
path = Classes;
523526
sourceTree = "<group>";
@@ -1060,6 +1063,7 @@
10601063
075AB1102684AAD9007CA1BD /* LPInboxTest.m in Sources */,
10611064
075AB1112684AAD9007CA1BD /* LPSecuredVarsTest.m in Sources */,
10621065
075AB1192684AAD9007CA1BD /* LPFeatureFlagManagerTest.m in Sources */,
1066+
6B7B6E912B6A962000820306 /* Leanplum_WebSocketTest.m in Sources */,
10631067
075AB1222684AAD9007CA1BD /* LPActionContextTest.m in Sources */,
10641068
07828DB7268B4AA00029A339 /* LPLocalCapsTest.m in Sources */,
10651069
075AB1232684AAD9007CA1BD /* LPFileManagerTest.m in Sources */,
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#import <Foundation/Foundation.h>
2+
#import <XCTest/XCTest.h>
3+
#import <Leanplum/Leanplum_WebSocket+Utils.h>
4+
#import <Leanplum/Leanplum.h>
5+
6+
@interface Leanplum_WebSocketTest : XCTestCase
7+
8+
@end
9+
10+
@implementation Leanplum_WebSocketTest
11+
12+
- (void)testIsHandshakeSuccessfulLegacyResponse
13+
{
14+
NSString *response = @"HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\n";
15+
XCTAssertTrue([Leanplum_WebSocket isHandshakeSuccessful:response]);
16+
}
17+
18+
- (void)testIsHandshakeSuccessfulResponse
19+
{
20+
NSString *response = @"HTTP/1.1 101 Switching Protocols\r\n\
21+
WebSocket-Origin: http://dev.leanplum.com\r\n\
22+
WebSocket-Location: ws://dev.leanplum.com/socket.io/1/websocket/y12oUiE3teSTh4S5TeSt\r\n\
23+
Date: Wed, 31 Jan 2024 15:27:15 GMT\r\n\
24+
Via: 1.1 google\r\n\
25+
Upgrade: websocket\r\n\
26+
Connection: Upgrade";
27+
XCTAssertTrue([Leanplum_WebSocket isHandshakeSuccessful:response]);
28+
}
29+
30+
- (void)testIsHandshakeSuccessfulResponseCaseInsensitive
31+
{
32+
NSString *response = @"HTTP/1.1 101 Switching Protocols\r\n\
33+
Upgrade: WebSocket\r\n\
34+
Connection: upgrade";
35+
XCTAssertTrue([Leanplum_WebSocket isHandshakeSuccessful:response]);
36+
37+
response = @"HTTP/1.1 101 Switching Protocols\r\n\
38+
upgrade: websocket\r\n\
39+
connection: Upgrade";
40+
XCTAssertTrue([Leanplum_WebSocket isHandshakeSuccessful:response]);
41+
}
42+
43+
- (void)testIsHandshakeSuccessfulInvalidStatusCode
44+
{
45+
NSString *response = @"HTTP/1.1 100 Switching Protocols\r\n\
46+
Upgrade: websocket\r\n\
47+
Connection: Upgrade";
48+
XCTAssertFalse([Leanplum_WebSocket isHandshakeSuccessful:response]);
49+
}
50+
51+
- (void)testIsHandshakeSuccessfulInvalidHeaders
52+
{
53+
NSString *response = @"HTTP/1.1 100 Switching Protocols\r\n\
54+
Upgrade: protocol/1\r\n\
55+
Connection: keep-alive";
56+
XCTAssertFalse([Leanplum_WebSocket isHandshakeSuccessful:response]);
57+
58+
NSString *responseInvalidConnection = @"HTTP/1.1 101 Switching Protocols\r\n\
59+
Upgrade: websocket\r\n\
60+
Connection: keep-alive";
61+
XCTAssertFalse([Leanplum_WebSocket isHandshakeSuccessful:responseInvalidConnection]);
62+
63+
NSString *responseInvalidUpgrade = @"HTTP/1.1 101 Switching Protocols\r\n\
64+
Upgrade: protocol/1\r\n\
65+
Connection: Upgrade";
66+
XCTAssertFalse([Leanplum_WebSocket isHandshakeSuccessful:responseInvalidUpgrade]);
67+
}
68+
69+
- (void)testIsHandshakeSuccessfulMissingHeaders
70+
{
71+
NSString *response = @"HTTP/1.1 100 Switching Protocols\r\n\
72+
WebSocket-Origin: http://dev.leanplum.com\r\n\
73+
WebSocket-Location: ws://dev.leanplum.com/socket.io/1/websocket/y12oUiE3teSTh4S5TeSt\r\n\
74+
Date: Wed, 31 Jan 2024 15:27:15 GMT\r\n\
75+
Via: 1.1 google";
76+
XCTAssertFalse([Leanplum_WebSocket isHandshakeSuccessful:response]);
77+
}
78+
79+
- (void)testIsHandshakeSuccessfulInvalidResponse
80+
{
81+
NSString *response = @"HTTP/1.1";
82+
XCTAssertFalse([Leanplum_WebSocket isHandshakeSuccessful:response]);
83+
84+
response = @"HTTP/1.1 101 Switching Protocols";
85+
XCTAssertFalse([Leanplum_WebSocket isHandshakeSuccessful:response]);
86+
87+
response = @"HTTP/1.1 Switching Protocols\r\n\
88+
WebSocket-Origin: http://dev.leanplum.com\r\n";
89+
XCTAssertFalse([Leanplum_WebSocket isHandshakeSuccessful:response]);
90+
}
91+
92+
- (void)testIsHandshakeSuccessfulEmptyResponse
93+
{
94+
NSString *response = @"";
95+
XCTAssertFalse([Leanplum_WebSocket isHandshakeSuccessful:response]);
96+
}
97+
98+
@end

0 commit comments

Comments
 (0)