Skip to content

Commit

Permalink
Merge pull request #1947 from ably/fix/1945-max-message-size
Browse files Browse the repository at this point in the history
[ECO-4873] Max message size fix
  • Loading branch information
maratal authored Jul 18, 2024
2 parents be39b20 + 61758e2 commit 296361c
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 23 deletions.
10 changes: 9 additions & 1 deletion Source/ARTConnection.m
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#import "ARTConnection+Private.h"

#import "ARTDefault.h"
#import "ARTRealtime+Private.h"
#import "ARTEventEmitter+Private.h"
#import "ARTQueuedDealloc.h"
#import "ARTRealtimeChannels+Private.h"
#import "ARTRealtimeChannel+Private.h"
#import "ARTDefault+Private.h"
#import "ARTClientOptions+Private.h"

#define IsInactiveConnectionState(state) (state == ARTRealtimeClosing || state == ARTRealtimeClosed || state == ARTRealtimeFailed || state == ARTRealtimeSuspended)

Expand Down Expand Up @@ -193,6 +195,12 @@ - (NSString *)key_nosync {
return _key;
}

- (NSInteger)maxMessageSize {
if (_maxMessageSize)
return _maxMessageSize;
return _realtime.options.isProductionEnvironment ? [ARTDefault maxProductionMessageSize] : [ARTDefault maxSandboxMessageSize];
}

- (ARTRealtimeConnectionState)state_nosync {
return _state;
}
Expand Down
32 changes: 30 additions & 2 deletions Source/ARTDefault.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
static NSString *const ARTDefault_realtimeHost = @"realtime.ably.io";

static NSTimeInterval _connectionStateTtl = 60.0;
static NSInteger _maxMessageSize = 65536;
static NSInteger _maxMessageSize = 0;
static NSInteger _maxProductionMessageSize = 65536;
static NSInteger _maxSandboxMessageSize = 16384;

@implementation ARTDefault

Expand Down Expand Up @@ -70,7 +72,21 @@ + (NSTimeInterval)realtimeRequestTimeout {
}

+ (NSInteger)maxMessageSize {
return _maxMessageSize;
if (_maxMessageSize)
return _maxMessageSize;
#if DEBUG
return _maxSandboxMessageSize;
#else
return _maxProductionMessageSize;
#endif
}

+ (NSInteger)maxSandboxMessageSize {
return _maxSandboxMessageSize;
}

+ (NSInteger)maxProductionMessageSize {
return _maxProductionMessageSize;
}

+ (void)setConnectionStateTtl:(NSTimeInterval)value {
Expand All @@ -85,6 +101,18 @@ + (void)setMaxMessageSize:(NSInteger)value {
}
}

+ (void)setMaxProductionMessageSize:(NSInteger)value {
@synchronized (self) {
_maxProductionMessageSize = value;
}
}

+ (void)setMaxSandboxMessageSize:(NSInteger)value {
@synchronized (self) {
_maxSandboxMessageSize = value;
}
}

+ (NSString *)libraryAgent {
return [ARTClientInformation libraryAgentIdentifier];
}
Expand Down
10 changes: 3 additions & 7 deletions Source/ARTProtocolMessage.m
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ - (id)copyWithZone:(NSZone *)zone {
return pm;
}

- (BOOL)mergeFrom:(ARTProtocolMessage *)src {
- (BOOL)mergeFrom:(ARTProtocolMessage *)src maxSize:(NSInteger)maxSize {
if (![src.channel isEqualToString:self.channel] || src.action != self.action) {
// RTL6d3
return NO;
}
if ([self mergeWouldExceedMaxSize:src.messages]) {
if ([self mergeWithMessages:src.messages wouldExceedMaxSize:maxSize]) {
// RTL6d1
return NO;
}
Expand Down Expand Up @@ -142,7 +142,7 @@ - (BOOL)clientIdsAreDifferent:(NSArray<ARTMessage*>*)messages {
}
}

- (BOOL)mergeWouldExceedMaxSize:(NSArray<ARTMessage*>*)messages {
- (BOOL)mergeWithMessages:(NSArray<ARTMessage*>*)messages wouldExceedMaxSize:(NSInteger)maxSize {
NSInteger queuedMessagesSize = 0;
for (ARTMessage *message in self.messages) {
queuedMessagesSize += [message messageSize];
Expand All @@ -152,10 +152,6 @@ - (BOOL)mergeWouldExceedMaxSize:(NSArray<ARTMessage*>*)messages {
messagesSize += [message messageSize];
}
NSInteger totalSize = queuedMessagesSize + messagesSize;
NSInteger maxSize = [ARTDefault maxMessageSize];
if (_connectionDetails.maxMessageSize) {
maxSize = _connectionDetails.maxMessageSize;
}
return totalSize > maxSize;
}

Expand Down
4 changes: 2 additions & 2 deletions Source/ARTQueuedMessage.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ - (NSString *)description {
return [self.msg description];
}

- (BOOL)mergeFrom:(ARTProtocolMessage *)msg sentCallback:(ARTCallback)sentCallback ackCallback:(ARTStatusCallback)ackCallback {
if ([self.msg mergeFrom:msg]) {
- (BOOL)mergeFrom:(ARTProtocolMessage *)msg maxSize:(NSInteger)maxSize sentCallback:(ARTCallback)sentCallback ackCallback:(ARTStatusCallback)ackCallback {
if ([self.msg mergeFrom:msg maxSize:maxSize]) {
if (sentCallback) {
[self.sentCallbacks addObject:sentCallback];
}
Expand Down
3 changes: 2 additions & 1 deletion Source/ARTRealtime.m
Original file line number Diff line number Diff line change
Expand Up @@ -1273,7 +1273,8 @@ - (void)send:(ARTProtocolMessage *)msg reuseMsgSerial:(BOOL)reuseMsgSerial sentC
else if (msg.ackRequired) {
if (self.isActive && self.options.queueMessages) {
ARTQueuedMessage *lastQueuedMessage = self.queuedMessages.lastObject; //RTL6d5
BOOL merged = [lastQueuedMessage mergeFrom:msg sentCallback:nil ackCallback:ackCallback];
NSInteger maxSize = _connection.maxMessageSize;
BOOL merged = [lastQueuedMessage mergeFrom:msg maxSize:maxSize sentCallback:nil ackCallback:ackCallback];
if (!merged) {
ARTQueuedMessage *qm = [[ARTQueuedMessage alloc] initWithProtocolMessage:msg sentCallback:sentCallback ackCallback:ackCallback];
[self.queuedMessages addObject:qm];
Expand Down
5 changes: 1 addition & 4 deletions Source/ARTRealtimeChannel.m
Original file line number Diff line number Diff line change
Expand Up @@ -1066,10 +1066,7 @@ - (BOOL)exceedMaxSize:(NSArray<ARTBaseMessage *> *)messages {
for (ARTMessage *message in messages) {
size += [message messageSize];
}
NSInteger maxSize = [ARTDefault maxMessageSize];
if (self.realtime.connection.maxMessageSize) {
maxSize = self.realtime.connection.maxMessageSize;
}
NSInteger maxSize = _realtime.connection.maxMessageSize;
return size > maxSize;
}

Expand Down
3 changes: 3 additions & 0 deletions Source/PrivateHeaders/Ably/ARTDefault+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ extern NSString *const ARTDefaultProduction;
+ (void)setConnectionStateTtl:(NSTimeInterval)value;
+ (void)setMaxMessageSize:(NSInteger)value;

+ (NSInteger)maxSandboxMessageSize;
+ (NSInteger)maxProductionMessageSize;

@end
2 changes: 1 addition & 1 deletion Source/PrivateHeaders/Ably/ARTProtocolMessage+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (readonly, nonatomic) BOOL hasBacklog;
@property (readonly, nonatomic) BOOL resumed;

- (BOOL)mergeFrom:(ARTProtocolMessage *)msg;
- (BOOL)mergeFrom:(ARTProtocolMessage *)msg maxSize:(NSInteger)maxSize;

@end

Expand Down
2 changes: 1 addition & 1 deletion Source/include/Ably/ARTQueuedMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN

- (instancetype)initWithProtocolMessage:(ARTProtocolMessage *)msg sentCallback:(nullable ARTCallback)sentCallback ackCallback:(nullable ARTStatusCallback)ackCallback;

- (BOOL)mergeFrom:(ARTProtocolMessage *)msg sentCallback:(nullable ARTCallback)sentCallback ackCallback:(nullable ARTStatusCallback)ackCallback;
- (BOOL)mergeFrom:(ARTProtocolMessage *)msg maxSize:(NSInteger)maxSize sentCallback:(nullable ARTCallback)sentCallback ackCallback:(nullable ARTStatusCallback)ackCallback;

- (ARTCallback)sentCallback;
- (ARTStatusCallback)ackCallback;
Expand Down
2 changes: 1 addition & 1 deletion Test/Tests/AuthTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1914,7 +1914,7 @@ class AuthTests: XCTestCase {
guard let error = error else {
fail("Error is nil"); done(); return
}
expect(error.message).to(contain("mismatched clientId"))
expect(error.message).to(contain("invalid clientId"))
done()
}
}
Expand Down
9 changes: 6 additions & 3 deletions Test/Tests/RealtimeClientConnectionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,19 +168,22 @@ class RealtimeClientConnectionTests: XCTestCase {
options.testOptions.transportFactory = TestProxyTransportFactory()
let client = ARTRealtime(options: options)
let defaultMaxMessageSize = ARTDefault.maxMessageSize()
XCTAssertEqual(defaultMaxMessageSize, 65536)
// Sandbox apps have a 16384 limit
XCTAssertEqual(defaultMaxMessageSize, 16384)
defer {
ARTDefault.setMaxMessageSize(defaultMaxMessageSize)
client.dispose()
client.close()
}
// Setting different value to check override below
ARTDefault.setMaxMessageSize(1)

waitUntil(timeout: testTimeout) { done in
client.connection.once(.connected) { _ in
let transport = client.internal.transport as! TestProxyTransport
let firstConnectionDetails = transport.protocolMessagesReceived.filter { $0.action == .connected }[0].connectionDetails
XCTAssertEqual(firstConnectionDetails!.maxMessageSize, 16384) // Sandbox apps have a 16384 limit
let maxMessageSize = transport.protocolMessagesReceived.filter { $0.action == .connected }[0].connectionDetails?.maxMessageSize
XCTAssertEqual(maxMessageSize, defaultMaxMessageSize)
XCTAssertEqual(client.connection.maxMessageSize, maxMessageSize)
done()
}
client.connect()
Expand Down

0 comments on commit 296361c

Please sign in to comment.