Merge branch 'charlesmchen/websocketRequests'
This commit is contained in:
commit
ebd24feff6
2
Pods
2
Pods
@ -1 +1 @@
|
||||
Subproject commit 086242800e27b3ee431ad23e9f29f3358e813059
|
||||
Subproject commit ba63216170bbe6d85d9c46c4ee37cdf672f6a7a7
|
||||
@ -6,7 +6,7 @@ PROTOC=protoc \
|
||||
--proto_path="${HOME}/src/signal/protobuf-objc/src/compiler/google/protobuf/" \
|
||||
--proto_path='./'
|
||||
|
||||
all: signal_service_proto provisioning_protos fingerprint_protos
|
||||
all: signal_service_proto provisioning_protos fingerprint_protos websocket_protos
|
||||
|
||||
signal_service_proto: OWSSignalServiceProtos.proto
|
||||
$(PROTOC) --objc_out=../src/Messages/ \
|
||||
@ -20,3 +20,6 @@ fingerprint_protos: OWSFingerprintProtos.proto
|
||||
$(PROTOC) --objc_out=../src/Security/ \
|
||||
OWSFingerprintProtos.proto
|
||||
|
||||
websocket_protos: WebSocketResources.proto
|
||||
$(PROTOC) --objc_out=../src/Network/WebSockets/ \
|
||||
WebSocketResources.proto
|
||||
|
||||
45
SignalServiceKit/protobuf/WebSocketResources.proto
Normal file
45
SignalServiceKit/protobuf/WebSocketResources.proto
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package signalservice;
|
||||
|
||||
option java_package = "org.whispersystems.signalservice.internal.websocket";
|
||||
option java_outer_classname = "WebSocketProtos";
|
||||
|
||||
// Signal-iOS
|
||||
import "objectivec-descriptor.proto";
|
||||
option (google.protobuf.objectivec_file_options).class_prefix = "WebSocketResources";
|
||||
|
||||
message WebSocketRequestMessage
|
||||
{
|
||||
optional string verb = 1;
|
||||
optional string path = 2;
|
||||
optional bytes body = 3;
|
||||
repeated string headers = 5;
|
||||
optional uint64 id = 4;
|
||||
}
|
||||
|
||||
message WebSocketResponseMessage
|
||||
{
|
||||
optional uint64 id = 1;
|
||||
optional uint32 status = 2;
|
||||
optional string message = 3;
|
||||
repeated string headers = 5;
|
||||
optional bytes body = 4;
|
||||
}
|
||||
|
||||
message WebSocketMessage
|
||||
{
|
||||
enum Type {
|
||||
UNKNOWN = 0;
|
||||
REQUEST = 1;
|
||||
RESPONSE = 2;
|
||||
}
|
||||
|
||||
optional Type type = 1;
|
||||
optional WebSocketRequestMessage request = 2;
|
||||
optional WebSocketResponseMessage response = 3;
|
||||
}
|
||||
@ -39,6 +39,7 @@
|
||||
#import "TSOutgoingMessage.h"
|
||||
#import "TSPreKeyManager.h"
|
||||
#import "TSQuotedMessage.h"
|
||||
#import "TSSocketManager.h"
|
||||
#import "TSThread.h"
|
||||
#import "Threading.h"
|
||||
#import <AxolotlKit/AxolotlExceptions.h>
|
||||
@ -975,117 +976,192 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
messages:deviceMessages
|
||||
relay:recipient.relay
|
||||
timeStamp:message.timestamp];
|
||||
[self.networkManager makeRequest:request
|
||||
success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
if (isLocalNumber && deviceMessages.count == 0) {
|
||||
DDLogInfo(@"%@ Sent a message with no device messages; clearing 'mayHaveLinkedDevices'.", self.logTag);
|
||||
// In order to avoid skipping necessary sync messages, the default value
|
||||
// for mayHaveLinkedDevices is YES. Once we've successfully sent a
|
||||
// sync message with no device messages (e.g. the service has confirmed
|
||||
// that we have no linked devices), we can set mayHaveLinkedDevices to NO
|
||||
// to avoid unnecessary message sends for sync messages until we learn
|
||||
// of a linked device (e.g. through the device linking UI or by receiving
|
||||
// a sync message, etc.).
|
||||
[OWSDeviceManager.sharedManager clearMayHaveLinkedDevicesIfNotSet];
|
||||
if (TSSocketManager.sharedManager.canMakeRequests) {
|
||||
[TSSocketManager.sharedManager makeRequest:request
|
||||
success:^(id _Nullable responseObject) {
|
||||
[self messageSendDidSucceed:message
|
||||
recipient:recipient
|
||||
isLocalNumber:isLocalNumber
|
||||
deviceMessages:deviceMessages
|
||||
success:successHandler];
|
||||
}
|
||||
|
||||
dispatch_async([OWSDispatch sendingQueue], ^{
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[recipient saveWithTransaction:transaction];
|
||||
[message updateWithSentRecipient:recipient.uniqueId transaction:transaction];
|
||||
}];
|
||||
|
||||
[self handleMessageSentLocally:message];
|
||||
successHandler();
|
||||
});
|
||||
}
|
||||
failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
DDLogInfo(@"%@ sending to recipient: %@, failed with error.", self.logTag, recipient.uniqueId);
|
||||
[DDLog flushLog];
|
||||
|
||||
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
|
||||
long statuscode = response.statusCode;
|
||||
NSData *responseData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
|
||||
|
||||
void (^retrySend)(void) = ^void() {
|
||||
if (remainingAttempts <= 0) {
|
||||
// Since we've already repeatedly failed to send to the messaging API,
|
||||
// it's unlikely that repeating the whole process will succeed.
|
||||
[error setIsRetryable:NO];
|
||||
return failureHandler(error);
|
||||
}
|
||||
|
||||
dispatch_async([OWSDispatch sendingQueue], ^{
|
||||
DDLogDebug(@"%@ Retrying: %@", self.logTag, message.debugDescription);
|
||||
[self sendMessageToService:message
|
||||
recipient:recipient
|
||||
thread:thread
|
||||
attempts:remainingAttempts
|
||||
success:successHandler
|
||||
failure:failureHandler];
|
||||
});
|
||||
};
|
||||
|
||||
switch (statuscode) {
|
||||
case 401: {
|
||||
DDLogWarn(@"%@ Unable to send due to invalid credentials. Did the user's client get de-authed by "
|
||||
@"registering elsewhere?",
|
||||
self.logTag);
|
||||
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeSignalServiceFailure, NSLocalizedString(@"ERROR_DESCRIPTION_SENDING_UNAUTHORIZED", @"Error message when attempting to send message"));
|
||||
// No need to retry if we've been de-authed.
|
||||
[error setIsRetryable:NO];
|
||||
return failureHandler(error);
|
||||
}
|
||||
case 404: {
|
||||
DDLogWarn(@"%@ Unregistered recipient: %@", self.logTag, recipient.uniqueId);
|
||||
|
||||
[self unregisteredRecipient:recipient message:message thread:thread];
|
||||
NSError *error = OWSErrorMakeNoSuchSignalRecipientError();
|
||||
// No need to retry if the recipient is not registered.
|
||||
[error setIsRetryable:NO];
|
||||
// If one member of a group deletes their account,
|
||||
// the group should ignore errors when trying to send
|
||||
// messages to this ex-member.
|
||||
[error setShouldBeIgnoredForGroups:YES];
|
||||
return failureHandler(error);
|
||||
}
|
||||
case 409: {
|
||||
// Mismatched devices
|
||||
DDLogWarn(@"%@ Mismatch Devices for recipient: %@", self.logTag, recipient.uniqueId);
|
||||
|
||||
NSError *error;
|
||||
NSDictionary *serializedResponse =
|
||||
[NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
|
||||
if (error) {
|
||||
OWSProdError([OWSAnalyticsEvents messageSenderErrorCouldNotParseMismatchedDevicesJson]);
|
||||
[error setIsRetryable:YES];
|
||||
return failureHandler(error);
|
||||
}
|
||||
|
||||
[self handleMismatchedDevices:serializedResponse recipient:recipient completion:retrySend];
|
||||
break;
|
||||
}
|
||||
case 410: {
|
||||
// Stale devices
|
||||
DDLogWarn(@"%@ Stale devices for recipient: %@", self.logTag, recipient.uniqueId);
|
||||
|
||||
if (!responseData) {
|
||||
DDLogWarn(@"Stale devices but server didn't specify devices in response.");
|
||||
NSError *error = OWSErrorMakeUnableToProcessServerResponseError();
|
||||
[error setIsRetryable:YES];
|
||||
return failureHandler(error);
|
||||
}
|
||||
|
||||
[self handleStaleDevicesWithResponse:responseData
|
||||
recipientId:recipient.uniqueId
|
||||
completion:retrySend];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
retrySend();
|
||||
break;
|
||||
failure:^(NSInteger statusCode, NSError *error) {
|
||||
[self messageSendDidFail:message
|
||||
recipient:recipient
|
||||
thread:thread
|
||||
isLocalNumber:isLocalNumber
|
||||
deviceMessages:deviceMessages
|
||||
remainingAttempts:remainingAttempts
|
||||
statusCode:statusCode
|
||||
error:error
|
||||
success:successHandler
|
||||
failure:failureHandler];
|
||||
}];
|
||||
} else {
|
||||
[self.networkManager makeRequest:request
|
||||
success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
[self messageSendDidSucceed:message
|
||||
recipient:recipient
|
||||
isLocalNumber:isLocalNumber
|
||||
deviceMessages:deviceMessages
|
||||
success:successHandler];
|
||||
}
|
||||
failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response;
|
||||
NSInteger statusCode = response.statusCode;
|
||||
|
||||
[self messageSendDidFail:message
|
||||
recipient:recipient
|
||||
thread:thread
|
||||
isLocalNumber:isLocalNumber
|
||||
deviceMessages:deviceMessages
|
||||
remainingAttempts:remainingAttempts
|
||||
statusCode:statusCode
|
||||
error:error
|
||||
success:successHandler
|
||||
failure:failureHandler];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)messageSendDidSucceed:(TSOutgoingMessage *)message
|
||||
recipient:(SignalRecipient *)recipient
|
||||
isLocalNumber:(BOOL)isLocalNumber
|
||||
deviceMessages:(NSArray<NSDictionary *> *)deviceMessages
|
||||
success:(void (^)(void))successHandler
|
||||
{
|
||||
OWSAssert(message);
|
||||
OWSAssert(recipient);
|
||||
OWSAssert(deviceMessages);
|
||||
OWSAssert(successHandler);
|
||||
|
||||
DDLogInfo(@"%@ Message send succeeded.", self.logTag);
|
||||
|
||||
if (isLocalNumber && deviceMessages.count == 0) {
|
||||
DDLogInfo(@"%@ Sent a message with no device messages; clearing 'mayHaveLinkedDevices'.", self.logTag);
|
||||
// In order to avoid skipping necessary sync messages, the default value
|
||||
// for mayHaveLinkedDevices is YES. Once we've successfully sent a
|
||||
// sync message with no device messages (e.g. the service has confirmed
|
||||
// that we have no linked devices), we can set mayHaveLinkedDevices to NO
|
||||
// to avoid unnecessary message sends for sync messages until we learn
|
||||
// of a linked device (e.g. through the device linking UI or by receiving
|
||||
// a sync message, etc.).
|
||||
[OWSDeviceManager.sharedManager clearMayHaveLinkedDevicesIfNotSet];
|
||||
}
|
||||
|
||||
dispatch_async([OWSDispatch sendingQueue], ^{
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[recipient saveWithTransaction:transaction];
|
||||
[message updateWithSentRecipient:recipient.uniqueId transaction:transaction];
|
||||
}];
|
||||
|
||||
[self handleMessageSentLocally:message];
|
||||
successHandler();
|
||||
});
|
||||
}
|
||||
|
||||
- (void)messageSendDidFail:(TSOutgoingMessage *)message
|
||||
recipient:(SignalRecipient *)recipient
|
||||
thread:(TSThread *)thread
|
||||
isLocalNumber:(BOOL)isLocalNumber
|
||||
deviceMessages:(NSArray<NSDictionary *> *)deviceMessages
|
||||
remainingAttempts:(int)remainingAttempts
|
||||
statusCode:(NSInteger)statusCode
|
||||
error:(NSError *)error
|
||||
success:(void (^)(void))successHandler
|
||||
failure:(RetryableFailureHandler)failureHandler
|
||||
{
|
||||
OWSAssert(message);
|
||||
OWSAssert(recipient);
|
||||
OWSAssert(thread);
|
||||
OWSAssert(deviceMessages);
|
||||
OWSAssert(error);
|
||||
OWSAssert(successHandler);
|
||||
OWSAssert(failureHandler);
|
||||
|
||||
DDLogInfo(@"%@ sending to recipient: %@, failed with error.", self.logTag, recipient.uniqueId);
|
||||
[DDLog flushLog];
|
||||
|
||||
NSData *responseData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
|
||||
|
||||
void (^retrySend)(void) = ^void() {
|
||||
if (remainingAttempts <= 0) {
|
||||
// Since we've already repeatedly failed to send to the messaging API,
|
||||
// it's unlikely that repeating the whole process will succeed.
|
||||
[error setIsRetryable:NO];
|
||||
return failureHandler(error);
|
||||
}
|
||||
|
||||
dispatch_async([OWSDispatch sendingQueue], ^{
|
||||
DDLogDebug(@"%@ Retrying: %@", self.logTag, message.debugDescription);
|
||||
[self sendMessageToService:message
|
||||
recipient:recipient
|
||||
thread:thread
|
||||
attempts:remainingAttempts
|
||||
success:successHandler
|
||||
failure:failureHandler];
|
||||
});
|
||||
};
|
||||
|
||||
switch (statusCode) {
|
||||
case 401: {
|
||||
DDLogWarn(@"%@ Unable to send due to invalid credentials. Did the user's client get de-authed by "
|
||||
@"registering elsewhere?",
|
||||
self.logTag);
|
||||
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeSignalServiceFailure,
|
||||
NSLocalizedString(
|
||||
@"ERROR_DESCRIPTION_SENDING_UNAUTHORIZED", @"Error message when attempting to send message"));
|
||||
// No need to retry if we've been de-authed.
|
||||
[error setIsRetryable:NO];
|
||||
return failureHandler(error);
|
||||
}
|
||||
case 404: {
|
||||
DDLogWarn(@"%@ Unregistered recipient: %@", self.logTag, recipient.uniqueId);
|
||||
|
||||
[self unregisteredRecipient:recipient message:message thread:thread];
|
||||
NSError *error = OWSErrorMakeNoSuchSignalRecipientError();
|
||||
// No need to retry if the recipient is not registered.
|
||||
[error setIsRetryable:NO];
|
||||
// If one member of a group deletes their account,
|
||||
// the group should ignore errors when trying to send
|
||||
// messages to this ex-member.
|
||||
[error setShouldBeIgnoredForGroups:YES];
|
||||
return failureHandler(error);
|
||||
}
|
||||
case 409: {
|
||||
// Mismatched devices
|
||||
DDLogWarn(@"%@ Mismatch Devices for recipient: %@", self.logTag, recipient.uniqueId);
|
||||
|
||||
NSError *error;
|
||||
NSDictionary *serializedResponse =
|
||||
[NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
|
||||
if (error) {
|
||||
OWSProdError([OWSAnalyticsEvents messageSenderErrorCouldNotParseMismatchedDevicesJson]);
|
||||
[error setIsRetryable:YES];
|
||||
return failureHandler(error);
|
||||
}
|
||||
|
||||
[self handleMismatchedDevices:serializedResponse recipient:recipient completion:retrySend];
|
||||
break;
|
||||
}
|
||||
case 410: {
|
||||
// Stale devices
|
||||
DDLogWarn(@"%@ Stale devices for recipient: %@", self.logTag, recipient.uniqueId);
|
||||
|
||||
if (!responseData) {
|
||||
DDLogWarn(@"Stale devices but server didn't specify devices in response.");
|
||||
NSError *error = OWSErrorMakeUnableToProcessServerResponseError();
|
||||
[error setIsRetryable:YES];
|
||||
return failureHandler(error);
|
||||
}
|
||||
|
||||
[self handleStaleDevicesWithResponse:responseData recipientId:recipient.uniqueId completion:retrySend];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
retrySend();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleMismatchedDevices:(NSDictionary *)dictionary
|
||||
|
||||
@ -1,273 +0,0 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
|
||||
#import <ProtocolBuffers/ProtocolBuffers.h>
|
||||
|
||||
// @@protoc_insertion_point(imports)
|
||||
|
||||
@class WebSocketMessage;
|
||||
@class WebSocketMessageBuilder;
|
||||
@class WebSocketRequestMessage;
|
||||
@class WebSocketRequestMessageBuilder;
|
||||
@class WebSocketResponseMessage;
|
||||
@class WebSocketResponseMessageBuilder;
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif // __has_feature
|
||||
|
||||
#ifndef NS_RETURNS_NOT_RETAINED
|
||||
#if __has_feature(attribute_ns_returns_not_retained)
|
||||
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
|
||||
#else
|
||||
#define NS_RETURNS_NOT_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
WebSocketMessageTypeUnknown = 0,
|
||||
WebSocketMessageTypeRequest = 1,
|
||||
WebSocketMessageTypeResponse = 2,
|
||||
} WebSocketMessageType;
|
||||
|
||||
BOOL WebSocketMessageTypeIsValidValue(WebSocketMessageType value);
|
||||
|
||||
|
||||
@interface SubProtocolRoot : NSObject {
|
||||
}
|
||||
+ (PBExtensionRegistry *)extensionRegistry;
|
||||
+ (void)registerAllExtensions:(PBMutableExtensionRegistry *)registry;
|
||||
@end
|
||||
|
||||
@interface WebSocketRequestMessage : PBGeneratedMessage {
|
||||
@private
|
||||
BOOL hasId_ : 1;
|
||||
BOOL hasVerb_ : 1;
|
||||
BOOL hasPath_ : 1;
|
||||
BOOL hasBody_ : 1;
|
||||
UInt64 id;
|
||||
NSString *verb;
|
||||
NSString *path;
|
||||
NSData *body;
|
||||
}
|
||||
- (BOOL)hasVerb;
|
||||
- (BOOL)hasPath;
|
||||
- (BOOL)hasBody;
|
||||
- (BOOL)hasId;
|
||||
@property (readonly, strong) NSString *verb;
|
||||
@property (readonly, strong) NSString *path;
|
||||
@property (readonly, strong) NSData *body;
|
||||
@property (readonly) UInt64 id;
|
||||
|
||||
+ (WebSocketRequestMessage *)defaultInstance;
|
||||
- (WebSocketRequestMessage *)defaultInstance;
|
||||
|
||||
- (BOOL)isInitialized;
|
||||
- (void)writeToCodedOutputStream:(PBCodedOutputStream *)output;
|
||||
- (WebSocketRequestMessageBuilder *)builder;
|
||||
+ (WebSocketRequestMessageBuilder *)builder;
|
||||
+ (WebSocketRequestMessageBuilder *)builderWithPrototype:(WebSocketRequestMessage *)prototype;
|
||||
- (WebSocketRequestMessageBuilder *)toBuilder;
|
||||
|
||||
+ (WebSocketRequestMessage *)parseFromData:(NSData *)data;
|
||||
+ (WebSocketRequestMessage *)parseFromData:(NSData *)data extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
+ (WebSocketRequestMessage *)parseFromInputStream:(NSInputStream *)input;
|
||||
+ (WebSocketRequestMessage *)parseFromInputStream:(NSInputStream *)input
|
||||
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
+ (WebSocketRequestMessage *)parseFromCodedInputStream:(PBCodedInputStream *)input;
|
||||
+ (WebSocketRequestMessage *)parseFromCodedInputStream:(PBCodedInputStream *)input
|
||||
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
@end
|
||||
|
||||
@interface WebSocketRequestMessageBuilder : PBGeneratedMessageBuilder {
|
||||
@private
|
||||
WebSocketRequestMessage *result;
|
||||
}
|
||||
|
||||
- (WebSocketRequestMessage *)defaultInstance;
|
||||
|
||||
- (WebSocketRequestMessageBuilder *)clear;
|
||||
- (WebSocketRequestMessageBuilder *)clone;
|
||||
|
||||
- (WebSocketRequestMessage *)build;
|
||||
- (WebSocketRequestMessage *)buildPartial;
|
||||
|
||||
- (WebSocketRequestMessageBuilder *)mergeFrom:(WebSocketRequestMessage *)other;
|
||||
- (WebSocketRequestMessageBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input;
|
||||
- (WebSocketRequestMessageBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input
|
||||
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
|
||||
- (BOOL)hasVerb;
|
||||
- (NSString *)verb;
|
||||
- (WebSocketRequestMessageBuilder *)setVerb:(NSString *)value;
|
||||
- (WebSocketRequestMessageBuilder *)clearVerb;
|
||||
|
||||
- (BOOL)hasPath;
|
||||
- (NSString *)path;
|
||||
- (WebSocketRequestMessageBuilder *)setPath:(NSString *)value;
|
||||
- (WebSocketRequestMessageBuilder *)clearPath;
|
||||
|
||||
- (BOOL)hasBody;
|
||||
- (NSData *)body;
|
||||
- (WebSocketRequestMessageBuilder *)setBody:(NSData *)value;
|
||||
- (WebSocketRequestMessageBuilder *)clearBody;
|
||||
|
||||
- (BOOL)hasId;
|
||||
- (UInt64)id;
|
||||
- (WebSocketRequestMessageBuilder *)setId:(UInt64)value;
|
||||
- (WebSocketRequestMessageBuilder *)clearId;
|
||||
@end
|
||||
|
||||
@interface WebSocketResponseMessage : PBGeneratedMessage {
|
||||
@private
|
||||
BOOL hasId_ : 1;
|
||||
BOOL hasMessage_ : 1;
|
||||
BOOL hasBody_ : 1;
|
||||
BOOL hasStatus_ : 1;
|
||||
UInt64 id;
|
||||
NSString *message;
|
||||
NSData *body;
|
||||
UInt32 status;
|
||||
}
|
||||
- (BOOL)hasId;
|
||||
- (BOOL)hasStatus;
|
||||
- (BOOL)hasMessage;
|
||||
- (BOOL)hasBody;
|
||||
@property (readonly) UInt64 id;
|
||||
@property (readonly) UInt32 status;
|
||||
@property (readonly, strong) NSString *message;
|
||||
@property (readonly, strong) NSData *body;
|
||||
|
||||
+ (WebSocketResponseMessage *)defaultInstance;
|
||||
- (WebSocketResponseMessage *)defaultInstance;
|
||||
|
||||
- (BOOL)isInitialized;
|
||||
- (void)writeToCodedOutputStream:(PBCodedOutputStream *)output;
|
||||
- (WebSocketResponseMessageBuilder *)builder;
|
||||
+ (WebSocketResponseMessageBuilder *)builder;
|
||||
+ (WebSocketResponseMessageBuilder *)builderWithPrototype:(WebSocketResponseMessage *)prototype;
|
||||
- (WebSocketResponseMessageBuilder *)toBuilder;
|
||||
|
||||
+ (WebSocketResponseMessage *)parseFromData:(NSData *)data;
|
||||
+ (WebSocketResponseMessage *)parseFromData:(NSData *)data extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
+ (WebSocketResponseMessage *)parseFromInputStream:(NSInputStream *)input;
|
||||
+ (WebSocketResponseMessage *)parseFromInputStream:(NSInputStream *)input
|
||||
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
+ (WebSocketResponseMessage *)parseFromCodedInputStream:(PBCodedInputStream *)input;
|
||||
+ (WebSocketResponseMessage *)parseFromCodedInputStream:(PBCodedInputStream *)input
|
||||
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
@end
|
||||
|
||||
@interface WebSocketResponseMessageBuilder : PBGeneratedMessageBuilder {
|
||||
@private
|
||||
WebSocketResponseMessage *result;
|
||||
}
|
||||
|
||||
- (WebSocketResponseMessage *)defaultInstance;
|
||||
|
||||
- (WebSocketResponseMessageBuilder *)clear;
|
||||
- (WebSocketResponseMessageBuilder *)clone;
|
||||
|
||||
- (WebSocketResponseMessage *)build;
|
||||
- (WebSocketResponseMessage *)buildPartial;
|
||||
|
||||
- (WebSocketResponseMessageBuilder *)mergeFrom:(WebSocketResponseMessage *)other;
|
||||
- (WebSocketResponseMessageBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input;
|
||||
- (WebSocketResponseMessageBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input
|
||||
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
|
||||
- (BOOL)hasId;
|
||||
- (UInt64)id;
|
||||
- (WebSocketResponseMessageBuilder *)setId:(UInt64)value;
|
||||
- (WebSocketResponseMessageBuilder *)clearId;
|
||||
|
||||
- (BOOL)hasStatus;
|
||||
- (UInt32)status;
|
||||
- (WebSocketResponseMessageBuilder *)setStatus:(UInt32)value;
|
||||
- (WebSocketResponseMessageBuilder *)clearStatus;
|
||||
|
||||
- (BOOL)hasMessage;
|
||||
- (NSString *)message;
|
||||
- (WebSocketResponseMessageBuilder *)setMessage:(NSString *)value;
|
||||
- (WebSocketResponseMessageBuilder *)clearMessage;
|
||||
|
||||
- (BOOL)hasBody;
|
||||
- (NSData *)body;
|
||||
- (WebSocketResponseMessageBuilder *)setBody:(NSData *)value;
|
||||
- (WebSocketResponseMessageBuilder *)clearBody;
|
||||
@end
|
||||
|
||||
@interface WebSocketMessage : PBGeneratedMessage {
|
||||
@private
|
||||
BOOL hasRequest_ : 1;
|
||||
BOOL hasResponse_ : 1;
|
||||
BOOL hasType_ : 1;
|
||||
WebSocketRequestMessage *request;
|
||||
WebSocketResponseMessage *response;
|
||||
WebSocketMessageType type;
|
||||
}
|
||||
- (BOOL)hasType;
|
||||
- (BOOL)hasRequest;
|
||||
- (BOOL)hasResponse;
|
||||
@property (readonly) WebSocketMessageType type;
|
||||
@property (readonly, strong) WebSocketRequestMessage *request;
|
||||
@property (readonly, strong) WebSocketResponseMessage *response;
|
||||
|
||||
+ (WebSocketMessage *)defaultInstance;
|
||||
- (WebSocketMessage *)defaultInstance;
|
||||
|
||||
- (BOOL)isInitialized;
|
||||
- (void)writeToCodedOutputStream:(PBCodedOutputStream *)output;
|
||||
- (WebSocketMessageBuilder *)builder;
|
||||
+ (WebSocketMessageBuilder *)builder;
|
||||
+ (WebSocketMessageBuilder *)builderWithPrototype:(WebSocketMessage *)prototype;
|
||||
- (WebSocketMessageBuilder *)toBuilder;
|
||||
|
||||
+ (WebSocketMessage *)parseFromData:(NSData *)data;
|
||||
+ (WebSocketMessage *)parseFromData:(NSData *)data extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
+ (WebSocketMessage *)parseFromInputStream:(NSInputStream *)input;
|
||||
+ (WebSocketMessage *)parseFromInputStream:(NSInputStream *)input
|
||||
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
+ (WebSocketMessage *)parseFromCodedInputStream:(PBCodedInputStream *)input;
|
||||
+ (WebSocketMessage *)parseFromCodedInputStream:(PBCodedInputStream *)input
|
||||
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
@end
|
||||
|
||||
@interface WebSocketMessageBuilder : PBGeneratedMessageBuilder {
|
||||
@private
|
||||
WebSocketMessage *result;
|
||||
}
|
||||
|
||||
- (WebSocketMessage *)defaultInstance;
|
||||
|
||||
- (WebSocketMessageBuilder *)clear;
|
||||
- (WebSocketMessageBuilder *)clone;
|
||||
|
||||
- (WebSocketMessage *)build;
|
||||
- (WebSocketMessage *)buildPartial;
|
||||
|
||||
- (WebSocketMessageBuilder *)mergeFrom:(WebSocketMessage *)other;
|
||||
- (WebSocketMessageBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input;
|
||||
- (WebSocketMessageBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input
|
||||
extensionRegistry:(PBExtensionRegistry *)extensionRegistry;
|
||||
|
||||
- (BOOL)hasType;
|
||||
- (WebSocketMessageType)type;
|
||||
- (WebSocketMessageBuilder *)setType:(WebSocketMessageType)value;
|
||||
- (WebSocketMessageBuilder *)clearType;
|
||||
|
||||
- (BOOL)hasRequest;
|
||||
- (WebSocketRequestMessage *)request;
|
||||
- (WebSocketMessageBuilder *)setRequest:(WebSocketRequestMessage *)value;
|
||||
- (WebSocketMessageBuilder *)setRequestBuilder:(WebSocketRequestMessageBuilder *)builderForValue;
|
||||
- (WebSocketMessageBuilder *)mergeRequest:(WebSocketRequestMessage *)value;
|
||||
- (WebSocketMessageBuilder *)clearRequest;
|
||||
|
||||
- (BOOL)hasResponse;
|
||||
- (WebSocketResponseMessage *)response;
|
||||
- (WebSocketMessageBuilder *)setResponse:(WebSocketResponseMessage *)value;
|
||||
- (WebSocketMessageBuilder *)setResponseBuilder:(WebSocketResponseMessageBuilder *)builderForValue;
|
||||
- (WebSocketMessageBuilder *)mergeResponse:(WebSocketResponseMessage *)value;
|
||||
- (WebSocketMessageBuilder *)clearResponse;
|
||||
@end
|
||||
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,11 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <SocketRocket/SRWebSocket.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
static void *SocketManagerStateObservationContext = &SocketManagerStateObservationContext;
|
||||
|
||||
extern NSString *const kNSNotification_SocketManagerStateDidChange;
|
||||
@ -14,9 +16,16 @@ typedef NS_ENUM(NSUInteger, SocketManagerState) {
|
||||
SocketManagerStateOpen,
|
||||
};
|
||||
|
||||
typedef void (^TSSocketMessageSuccess)(id _Nullable responseObject);
|
||||
// statusCode is zero by default, if request never made or failed.
|
||||
typedef void (^TSSocketMessageFailure)(NSInteger statusCode, NSError *error);
|
||||
|
||||
@class TSRequest;
|
||||
|
||||
@interface TSSocketManager : NSObject <SRWebSocketDelegate>
|
||||
|
||||
@property (nonatomic, readonly) SocketManagerState state;
|
||||
@property (atomic, readonly) BOOL canMakeRequests;
|
||||
|
||||
+ (instancetype)sharedManager;
|
||||
|
||||
@ -33,4 +42,12 @@ typedef NS_ENUM(NSUInteger, SocketManagerState) {
|
||||
// This method can be called from any thread.
|
||||
+ (void)requestSocketOpen;
|
||||
|
||||
#pragma mark - Message Sending
|
||||
|
||||
- (void)makeRequest:(TSRequest *)request
|
||||
success:(TSSocketMessageSuccess)success
|
||||
failure:(TSSocketMessageFailure)failure;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -10,18 +10,22 @@
|
||||
#import "NSTimer+OWS.h"
|
||||
#import "NotificationsProtocol.h"
|
||||
#import "OWSBackgroundTask.h"
|
||||
#import "OWSError.h"
|
||||
#import "OWSMessageManager.h"
|
||||
#import "OWSMessageReceiver.h"
|
||||
#import "OWSPrimaryStorage.h"
|
||||
#import "OWSSignalService.h"
|
||||
#import "OWSSignalServiceProtos.pb.h"
|
||||
#import "OWSWebsocketSecurityPolicy.h"
|
||||
#import "SubProtocol.pb.h"
|
||||
#import "TSAccountManager.h"
|
||||
#import "TSConstants.h"
|
||||
#import "TSErrorMessage.h"
|
||||
#import "TSRequest.h"
|
||||
#import "TextSecureKitEnv.h"
|
||||
#import "Threading.h"
|
||||
#import "WebSocketResources.pb.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
static const CGFloat kSocketHeartbeatPeriodSeconds = 30.f;
|
||||
static const CGFloat kSocketReconnectDelaySeconds = 5.f;
|
||||
@ -33,9 +37,102 @@ static const CGFloat kSocketReconnectDelaySeconds = 5.f;
|
||||
static const CGFloat kBackgroundOpenSocketDurationSeconds = 25.f;
|
||||
// b) It has received a message over the socket in the last 15 seconds.
|
||||
static const CGFloat kBackgroundKeepSocketAliveDurationSeconds = 15.f;
|
||||
// c) It is in the process of making a request.
|
||||
static const CGFloat kMakeRequestKeepSocketAliveDurationSeconds = 30.f;
|
||||
|
||||
NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_SocketManagerStateDidChange";
|
||||
|
||||
@interface TSSocketMessage : NSObject
|
||||
|
||||
@property (nonatomic, readonly) UInt64 requestId;
|
||||
@property (nonatomic, nullable) TSSocketMessageSuccess success;
|
||||
@property (nonatomic, nullable) TSSocketMessageFailure failure;
|
||||
@property (nonatomic) BOOL hasCompleted;
|
||||
@property (nonatomic, readonly) OWSBackgroundTask *backgroundTask;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation TSSocketMessage
|
||||
|
||||
- (instancetype)initWithRequestId:(UInt64)requestId
|
||||
success:(TSSocketMessageSuccess)success
|
||||
failure:(TSSocketMessageFailure)failure
|
||||
{
|
||||
if (self = [super init]) {
|
||||
OWSAssert(success);
|
||||
OWSAssert(failure);
|
||||
|
||||
_requestId = requestId;
|
||||
_success = success;
|
||||
_failure = failure;
|
||||
_backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)didSucceedWithResponseObject:(id _Nullable)responseObject
|
||||
{
|
||||
@synchronized(self)
|
||||
{
|
||||
if (self.hasCompleted) {
|
||||
return;
|
||||
}
|
||||
self.hasCompleted = YES;
|
||||
}
|
||||
|
||||
OWSAssert(self.success);
|
||||
OWSAssert(self.failure);
|
||||
|
||||
TSSocketMessageSuccess success = self.success;
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
success(responseObject);
|
||||
});
|
||||
|
||||
self.success = nil;
|
||||
self.failure = nil;
|
||||
}
|
||||
|
||||
- (void)didFailBeforeSending
|
||||
{
|
||||
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeMessageRequestFailed,
|
||||
NSLocalizedString(@"ERROR_DESCRIPTION_REQUEST_FAILED", @"Error indicating that a socket request failed."));
|
||||
|
||||
[self didFailWithStatusCode:0 error:error];
|
||||
}
|
||||
|
||||
- (void)didFailWithStatusCode:(NSInteger)statusCode error:(NSError *)error
|
||||
{
|
||||
OWSAssert(error);
|
||||
|
||||
@synchronized(self)
|
||||
{
|
||||
if (self.hasCompleted) {
|
||||
return;
|
||||
}
|
||||
self.hasCompleted = YES;
|
||||
}
|
||||
|
||||
OWSAssert(self.success);
|
||||
OWSAssert(self.failure);
|
||||
|
||||
TSSocketMessageFailure failure = self.failure;
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
failure(statusCode, error);
|
||||
});
|
||||
|
||||
self.success = nil;
|
||||
self.failure = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// TSSocketManager's properties should only be accessed from the main thread.
|
||||
@interface TSSocketManager ()
|
||||
|
||||
@ -46,9 +143,9 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
//
|
||||
// The first tier is the actual websocket and the timers used
|
||||
// to keep it alive and connected.
|
||||
@property (nonatomic) SRWebSocket *websocket;
|
||||
@property (nonatomic) NSTimer *heartbeatTimer;
|
||||
@property (nonatomic) NSTimer *reconnectTimer;
|
||||
@property (nonatomic, nullable) SRWebSocket *websocket;
|
||||
@property (nonatomic, nullable) NSTimer *heartbeatTimer;
|
||||
@property (nonatomic, nullable) NSTimer *reconnectTimer;
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@ -60,6 +157,8 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
// Due to concurrency, this property can fall out of sync with the
|
||||
// websocket's actual state, so we're defensive and distrustful of
|
||||
// this property.
|
||||
//
|
||||
// We only ever access this state on the main thread.
|
||||
@property (nonatomic) SocketManagerState state;
|
||||
|
||||
#pragma mark -
|
||||
@ -72,13 +171,13 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
// trying to keep the socket open), all three should be clear.
|
||||
//
|
||||
// This represents how long we're trying to keep the socket open.
|
||||
@property (nonatomic) NSDate *backgroundKeepAliveUntilDate;
|
||||
@property (nonatomic, nullable) NSDate *backgroundKeepAliveUntilDate;
|
||||
// This timer is used to check periodically whether we should
|
||||
// close the socket.
|
||||
@property (nonatomic) NSTimer *backgroundKeepAliveTimer;
|
||||
@property (nonatomic, nullable) NSTimer *backgroundKeepAliveTimer;
|
||||
// This is used to manage the iOS "background task" used to
|
||||
// keep the app alive in the background.
|
||||
@property (nonatomic) OWSBackgroundTask *backgroundTask;
|
||||
@property (nonatomic, nullable) OWSBackgroundTask *backgroundTask;
|
||||
|
||||
// We cache this value instead of consulting [UIApplication sharedApplication].applicationState,
|
||||
// because UIKit only provides a "will resign active" notification, not a "did resign active"
|
||||
@ -87,6 +186,11 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
|
||||
@property (nonatomic) BOOL hasObservedNotifications;
|
||||
|
||||
// This property should only be accessed while synchronized on the socket manager.
|
||||
@property (nonatomic, readonly) NSMutableDictionary<NSNumber *, TSSocketMessage *> *socketMessageMap;
|
||||
|
||||
@property (atomic) BOOL canMakeRequests;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
@ -106,6 +210,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
_signalService = [OWSSignalService sharedInstance];
|
||||
_messageReceiver = [OWSMessageReceiver sharedInstance];
|
||||
_state = SocketManagerStateClosed;
|
||||
_socketMessageMap = [NSMutableDictionary new];
|
||||
|
||||
OWSSingletonAssert();
|
||||
|
||||
@ -290,13 +395,17 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
// the socket failed immediately for some reason), so we update the state
|
||||
// _before_ calling it, not after.
|
||||
_state = state;
|
||||
_canMakeRequests = state == SocketManagerStateOpen;
|
||||
[socket open];
|
||||
[self failAllPendingSocketMessagesIfNecessary];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_state = state;
|
||||
_canMakeRequests = state == SocketManagerStateOpen;
|
||||
|
||||
[self failAllPendingSocketMessagesIfNecessary];
|
||||
[self notifyStatusChange];
|
||||
}
|
||||
|
||||
@ -330,6 +439,201 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
self.state = SocketManagerStateClosed;
|
||||
}
|
||||
|
||||
#pragma mark - Message Sending
|
||||
|
||||
- (void)makeRequest:(TSRequest *)request success:(TSSocketMessageSuccess)success failure:(TSSocketMessageFailure)failure
|
||||
{
|
||||
OWSAssert(request);
|
||||
OWSAssert(request.HTTPMethod.length > 0);
|
||||
OWSAssert(success);
|
||||
OWSAssert(failure);
|
||||
|
||||
TSSocketMessage *socketMessage =
|
||||
[[TSSocketMessage alloc] initWithRequestId:[Cryptography randomUInt64] success:success failure:failure];
|
||||
|
||||
@synchronized(self)
|
||||
{
|
||||
self.socketMessageMap[@(socketMessage.requestId)] = socketMessage;
|
||||
}
|
||||
|
||||
NSURL *requestUrl = request.URL;
|
||||
NSString *requestPath = [@"/" stringByAppendingString:requestUrl.path];
|
||||
|
||||
NSData *_Nullable jsonData = nil;
|
||||
if (request.parameters) {
|
||||
NSError *error;
|
||||
jsonData = [NSJSONSerialization
|
||||
dataWithJSONObject:request.parameters
|
||||
options:(NSJSONWritingOptions)0
|
||||
error:&error];
|
||||
if (!jsonData || error) {
|
||||
OWSProdLogAndFail(@"%@ could not serialize request JSON: %@", self.logTag, error);
|
||||
[socketMessage didFailBeforeSending];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WebSocketResourcesWebSocketRequestMessageBuilder *requestBuilder =
|
||||
[WebSocketResourcesWebSocketRequestMessageBuilder new];
|
||||
requestBuilder.id = socketMessage.requestId;
|
||||
[requestBuilder setVerb:request.HTTPMethod];
|
||||
[requestBuilder setPath:requestPath];
|
||||
if (jsonData) {
|
||||
// TODO: Do we need body & headers for requests with no parameters?
|
||||
[requestBuilder setBody:jsonData];
|
||||
[requestBuilder setHeadersArray:@[
|
||||
@"content-type:application/json",
|
||||
]];
|
||||
}
|
||||
|
||||
WebSocketResourcesWebSocketMessageBuilder *messageBuilder = [WebSocketResourcesWebSocketMessageBuilder new];
|
||||
[messageBuilder setType:WebSocketResourcesWebSocketMessageTypeRequest];
|
||||
[messageBuilder setRequestBuilder:requestBuilder];
|
||||
|
||||
NSData *messageData = [messageBuilder build].data;
|
||||
if (!messageData) {
|
||||
OWSProdLogAndFail(@"%@ could not serialize message.", self.logTag);
|
||||
[socketMessage didFailBeforeSending];
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self.canMakeRequests) {
|
||||
DDLogError(@"%@ makeRequest: socket not open.", self.logTag);
|
||||
[socketMessage didFailBeforeSending];
|
||||
return;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
BOOL wasScheduled = [self.websocket sendDataNoCopy:messageData error:&error];
|
||||
if (!wasScheduled || error) {
|
||||
OWSProdLogAndFail(@"%@ could not serialize request JSON: %@", self.logTag, error);
|
||||
[socketMessage didFailBeforeSending];
|
||||
return;
|
||||
}
|
||||
DDLogVerbose(@"%@ message scheduled: %lld, %@, %@, %zd.",
|
||||
self.logTag,
|
||||
socketMessage.requestId,
|
||||
request.HTTPMethod,
|
||||
requestPath,
|
||||
jsonData.length);
|
||||
|
||||
const int64_t kSocketTimeoutSeconds = 10;
|
||||
__weak TSSocketMessage *weakSocketMessage = socketMessage;
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kSocketTimeoutSeconds * NSEC_PER_SEC),
|
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||
^{
|
||||
[weakSocketMessage didFailBeforeSending];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)processWebSocketResponseMessage:(WebSocketResourcesWebSocketResponseMessage *)message
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
OWSAssert(message);
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[self processWebSocketResponseMessageAsync:message];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)processWebSocketResponseMessageAsync:(WebSocketResourcesWebSocketResponseMessage *)message
|
||||
{
|
||||
OWSAssert(message);
|
||||
|
||||
DDLogInfo(@"%@ received WebSocket response.", self.logTag);
|
||||
|
||||
if (![message hasId]) {
|
||||
DDLogError(@"%@ received incomplete WebSocket response.", self.logTag);
|
||||
return;
|
||||
}
|
||||
|
||||
DispatchMainThreadSafe(^{
|
||||
[self requestSocketAliveForAtLeastSeconds:kMakeRequestKeepSocketAliveDurationSeconds];
|
||||
});
|
||||
|
||||
UInt64 requestId = message.id;
|
||||
UInt32 responseStatus = 0;
|
||||
if (message.hasStatus) {
|
||||
responseStatus = message.status;
|
||||
}
|
||||
NSString *_Nullable responseMessage;
|
||||
if (message.hasMessage) {
|
||||
responseMessage = message.message;
|
||||
}
|
||||
NSData *_Nullable responseBody;
|
||||
if (message.hasBody) {
|
||||
responseBody = message.body;
|
||||
}
|
||||
NSArray<NSString *> *_Nullable responseHeaders = message.headers;
|
||||
|
||||
BOOL hasValidResponse = YES;
|
||||
id responseObject = responseBody;
|
||||
if (responseBody) {
|
||||
NSError *error;
|
||||
id _Nullable responseJson =
|
||||
[NSJSONSerialization JSONObjectWithData:responseBody options:(NSJSONReadingOptions)0 error:&error];
|
||||
if (!responseJson || error) {
|
||||
OWSProdLogAndFail(@"%@ could not parse WebSocket response JSON: %@.", self.logTag, error);
|
||||
hasValidResponse = NO;
|
||||
} else {
|
||||
responseObject = responseJson;
|
||||
}
|
||||
}
|
||||
|
||||
TSSocketMessage *_Nullable socketMessage;
|
||||
@synchronized(self)
|
||||
{
|
||||
socketMessage = self.socketMessageMap[@(requestId)];
|
||||
[self.socketMessageMap removeObjectForKey:@(requestId)];
|
||||
}
|
||||
|
||||
if (!socketMessage) {
|
||||
DDLogError(@"%@ received response to unknown request.", self.logTag);
|
||||
} else {
|
||||
BOOL hasSuccessStatus = 200 <= responseStatus && responseStatus <= 299;
|
||||
BOOL didSucceed = hasSuccessStatus && hasValidResponse;
|
||||
if (didSucceed) {
|
||||
[socketMessage didSucceedWithResponseObject:responseObject];
|
||||
} else {
|
||||
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeMessageResponseFailed,
|
||||
NSLocalizedString(
|
||||
@"ERROR_DESCRIPTION_RESPONSE_FAILED", @"Error indicating that a socket response failed."));
|
||||
[socketMessage didFailWithStatusCode:(NSInteger)responseStatus error:error];
|
||||
}
|
||||
}
|
||||
|
||||
DDLogVerbose(@"%@ received WebSocket response: %llu, %zd, %@, %zd, %@, %d, %@.",
|
||||
self.logTag,
|
||||
(unsigned long long)requestId,
|
||||
(NSInteger)responseStatus,
|
||||
responseMessage,
|
||||
responseBody.length,
|
||||
responseHeaders,
|
||||
socketMessage != nil,
|
||||
responseObject);
|
||||
}
|
||||
|
||||
- (void)failAllPendingSocketMessagesIfNecessary
|
||||
{
|
||||
if (!self.canMakeRequests) {
|
||||
[self failAllPendingSocketMessages];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)failAllPendingSocketMessages
|
||||
{
|
||||
NSArray<TSSocketMessage *> *socketMessages;
|
||||
@synchronized(self)
|
||||
{
|
||||
socketMessages = self.socketMessageMap.allValues;
|
||||
[self.socketMessageMap removeAllObjects];
|
||||
}
|
||||
|
||||
for (TSSocketMessage *socketMessage in socketMessages) {
|
||||
[socketMessage didFailBeforeSending];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Delegate methods
|
||||
|
||||
- (void)webSocketDidOpen:(SRWebSocket *)webSocket {
|
||||
@ -359,23 +663,32 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(NSData *)data {
|
||||
OWSAssertIsOnMainThread();
|
||||
OWSAssert(webSocket);
|
||||
|
||||
if (webSocket != self.websocket) {
|
||||
// Ignore events from obsolete web sockets.
|
||||
return;
|
||||
}
|
||||
|
||||
WebSocketMessage *wsMessage = [WebSocketMessage parseFromData:data];
|
||||
WebSocketResourcesWebSocketMessage *wsMessage;
|
||||
@try {
|
||||
wsMessage = [WebSocketResourcesWebSocketMessage parseFromData:data];
|
||||
} @catch (NSException *exception) {
|
||||
OWSProdLogAndFail(@"%@ Received an invalid message: %@", self.logTag, exception.debugDescription);
|
||||
// TODO: Add analytics.
|
||||
return;
|
||||
}
|
||||
|
||||
if (wsMessage.type == WebSocketMessageTypeRequest) {
|
||||
if (wsMessage.type == WebSocketResourcesWebSocketMessageTypeRequest) {
|
||||
[self processWebSocketRequestMessage:wsMessage.request];
|
||||
} else if (wsMessage.type == WebSocketMessageTypeResponse) {
|
||||
} else if (wsMessage.type == WebSocketResourcesWebSocketMessageTypeResponse) {
|
||||
[self processWebSocketResponseMessage:wsMessage.response];
|
||||
} else {
|
||||
DDLogWarn(@"Got a WebSocketMessage of unknown type");
|
||||
DDLogWarn(@"%@ webSocket:didReceiveMessage: unknown.", self.logTag);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)processWebSocketRequestMessage:(WebSocketRequestMessage *)message {
|
||||
- (void)processWebSocketRequestMessage:(WebSocketResourcesWebSocketRequestMessage *)message
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
|
||||
DDLogInfo(@"%@ Got message with verb: %@ and path: %@", self.logTag, message.verb, message.path);
|
||||
@ -432,23 +745,18 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
}
|
||||
}
|
||||
|
||||
- (void)processWebSocketResponseMessage:(WebSocketResponseMessage *)message {
|
||||
- (void)sendWebSocketMessageAcknowledgement:(WebSocketResourcesWebSocketRequestMessage *)request
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
|
||||
DDLogWarn(@"Client should not receive WebSocket Respond messages");
|
||||
}
|
||||
|
||||
- (void)sendWebSocketMessageAcknowledgement:(WebSocketRequestMessage *)request {
|
||||
OWSAssertIsOnMainThread();
|
||||
|
||||
WebSocketResponseMessageBuilder *response = [WebSocketResponseMessage builder];
|
||||
WebSocketResourcesWebSocketResponseMessageBuilder *response = [WebSocketResourcesWebSocketResponseMessage builder];
|
||||
[response setStatus:200];
|
||||
[response setMessage:@"OK"];
|
||||
[response setId:request.id];
|
||||
|
||||
WebSocketMessageBuilder *message = [WebSocketMessage builder];
|
||||
WebSocketResourcesWebSocketMessageBuilder *message = [WebSocketResourcesWebSocketMessage builder];
|
||||
[message setResponse:response.build];
|
||||
[message setType:WebSocketMessageTypeResponse];
|
||||
[message setType:WebSocketResourcesWebSocketMessageTypeResponse];
|
||||
|
||||
NSError *error;
|
||||
[self.websocket sendDataNoCopy:message.build.data error:&error];
|
||||
@ -475,9 +783,10 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket
|
||||
didCloseWithCode:(NSInteger)code
|
||||
reason:(NSString *)reason
|
||||
wasClean:(BOOL)wasClean {
|
||||
didCloseWithCode:(NSInteger)code
|
||||
reason:(nullable NSString *)reason
|
||||
wasClean:(BOOL)wasClean
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
OWSAssert(webSocket);
|
||||
if (webSocket != self.websocket) {
|
||||
@ -730,3 +1039,5 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
330
SignalServiceKit/src/Network/WebSockets/WebSocketResources.pb.h
Normal file
330
SignalServiceKit/src/Network/WebSockets/WebSocketResources.pb.h
Normal file
@ -0,0 +1,330 @@
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
|
||||
#import <ProtocolBuffers/ProtocolBuffers.h>
|
||||
|
||||
// @@protoc_insertion_point(imports)
|
||||
|
||||
@class ObjectiveCFileOptions;
|
||||
@class ObjectiveCFileOptionsBuilder;
|
||||
@class PBDescriptorProto;
|
||||
@class PBDescriptorProtoBuilder;
|
||||
@class PBDescriptorProtoExtensionRange;
|
||||
@class PBDescriptorProtoExtensionRangeBuilder;
|
||||
@class PBEnumDescriptorProto;
|
||||
@class PBEnumDescriptorProtoBuilder;
|
||||
@class PBEnumOptions;
|
||||
@class PBEnumOptionsBuilder;
|
||||
@class PBEnumValueDescriptorProto;
|
||||
@class PBEnumValueDescriptorProtoBuilder;
|
||||
@class PBEnumValueOptions;
|
||||
@class PBEnumValueOptionsBuilder;
|
||||
@class PBFieldDescriptorProto;
|
||||
@class PBFieldDescriptorProtoBuilder;
|
||||
@class PBFieldOptions;
|
||||
@class PBFieldOptionsBuilder;
|
||||
@class PBFileDescriptorProto;
|
||||
@class PBFileDescriptorProtoBuilder;
|
||||
@class PBFileDescriptorSet;
|
||||
@class PBFileDescriptorSetBuilder;
|
||||
@class PBFileOptions;
|
||||
@class PBFileOptionsBuilder;
|
||||
@class PBMessageOptions;
|
||||
@class PBMessageOptionsBuilder;
|
||||
@class PBMethodDescriptorProto;
|
||||
@class PBMethodDescriptorProtoBuilder;
|
||||
@class PBMethodOptions;
|
||||
@class PBMethodOptionsBuilder;
|
||||
@class PBOneofDescriptorProto;
|
||||
@class PBOneofDescriptorProtoBuilder;
|
||||
@class PBServiceDescriptorProto;
|
||||
@class PBServiceDescriptorProtoBuilder;
|
||||
@class PBServiceOptions;
|
||||
@class PBServiceOptionsBuilder;
|
||||
@class PBSourceCodeInfo;
|
||||
@class PBSourceCodeInfoBuilder;
|
||||
@class PBSourceCodeInfoLocation;
|
||||
@class PBSourceCodeInfoLocationBuilder;
|
||||
@class PBUninterpretedOption;
|
||||
@class PBUninterpretedOptionBuilder;
|
||||
@class PBUninterpretedOptionNamePart;
|
||||
@class PBUninterpretedOptionNamePartBuilder;
|
||||
@class WebSocketResourcesWebSocketMessage;
|
||||
@class WebSocketResourcesWebSocketMessageBuilder;
|
||||
@class WebSocketResourcesWebSocketRequestMessage;
|
||||
@class WebSocketResourcesWebSocketRequestMessageBuilder;
|
||||
@class WebSocketResourcesWebSocketResponseMessage;
|
||||
@class WebSocketResourcesWebSocketResponseMessageBuilder;
|
||||
|
||||
|
||||
typedef NS_ENUM(SInt32, WebSocketResourcesWebSocketMessageType) {
|
||||
WebSocketResourcesWebSocketMessageTypeUnknown = 0,
|
||||
WebSocketResourcesWebSocketMessageTypeRequest = 1,
|
||||
WebSocketResourcesWebSocketMessageTypeResponse = 2,
|
||||
};
|
||||
|
||||
BOOL WebSocketResourcesWebSocketMessageTypeIsValidValue(WebSocketResourcesWebSocketMessageType value);
|
||||
NSString *NSStringFromWebSocketResourcesWebSocketMessageType(WebSocketResourcesWebSocketMessageType value);
|
||||
|
||||
|
||||
@interface WebSocketResourcesWebSocketResourcesRoot : NSObject {
|
||||
}
|
||||
+ (PBExtensionRegistry*) extensionRegistry;
|
||||
+ (void) registerAllExtensions:(PBMutableExtensionRegistry*) registry;
|
||||
@end
|
||||
|
||||
#define WebSocketRequestMessage_verb @"verb"
|
||||
#define WebSocketRequestMessage_path @"path"
|
||||
#define WebSocketRequestMessage_body @"body"
|
||||
#define WebSocketRequestMessage_headers @"headers"
|
||||
#define WebSocketRequestMessage_id @"id"
|
||||
@interface WebSocketResourcesWebSocketRequestMessage : PBGeneratedMessage<GeneratedMessageProtocol> {
|
||||
@private
|
||||
BOOL hasId_:1;
|
||||
BOOL hasVerb_:1;
|
||||
BOOL hasPath_:1;
|
||||
BOOL hasBody_:1;
|
||||
UInt64 id;
|
||||
NSString* verb;
|
||||
NSString* path;
|
||||
NSData* body;
|
||||
NSMutableArray * headersArray;
|
||||
}
|
||||
- (BOOL) hasVerb;
|
||||
- (BOOL) hasPath;
|
||||
- (BOOL) hasBody;
|
||||
- (BOOL) hasId;
|
||||
@property (readonly, strong) NSString* verb;
|
||||
@property (readonly, strong) NSString* path;
|
||||
@property (readonly, strong) NSData* body;
|
||||
@property (readonly, strong) NSArray * headers;
|
||||
@property (readonly) UInt64 id;
|
||||
- (NSString*)headersAtIndex:(NSUInteger)index;
|
||||
|
||||
+ (instancetype) defaultInstance;
|
||||
- (instancetype) defaultInstance;
|
||||
|
||||
- (BOOL) isInitialized;
|
||||
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) builder;
|
||||
+ (WebSocketResourcesWebSocketRequestMessageBuilder*) builder;
|
||||
+ (WebSocketResourcesWebSocketRequestMessageBuilder*) builderWithPrototype:(WebSocketResourcesWebSocketRequestMessage*) prototype;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) toBuilder;
|
||||
|
||||
+ (WebSocketResourcesWebSocketRequestMessage*) parseFromData:(NSData*) data;
|
||||
+ (WebSocketResourcesWebSocketRequestMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (WebSocketResourcesWebSocketRequestMessage*) parseFromInputStream:(NSInputStream*) input;
|
||||
+ (WebSocketResourcesWebSocketRequestMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (WebSocketResourcesWebSocketRequestMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
+ (WebSocketResourcesWebSocketRequestMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
@end
|
||||
|
||||
@interface WebSocketResourcesWebSocketRequestMessageBuilder : PBGeneratedMessageBuilder {
|
||||
@private
|
||||
WebSocketResourcesWebSocketRequestMessage* resultWebSocketRequestMessage;
|
||||
}
|
||||
|
||||
- (WebSocketResourcesWebSocketRequestMessage*) defaultInstance;
|
||||
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) clear;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) clone;
|
||||
|
||||
- (WebSocketResourcesWebSocketRequestMessage*) build;
|
||||
- (WebSocketResourcesWebSocketRequestMessage*) buildPartial;
|
||||
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) mergeFrom:(WebSocketResourcesWebSocketRequestMessage*) other;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
|
||||
- (BOOL) hasVerb;
|
||||
- (NSString*) verb;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) setVerb:(NSString*) value;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) clearVerb;
|
||||
|
||||
- (BOOL) hasPath;
|
||||
- (NSString*) path;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) setPath:(NSString*) value;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) clearPath;
|
||||
|
||||
- (BOOL) hasBody;
|
||||
- (NSData*) body;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) setBody:(NSData*) value;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) clearBody;
|
||||
|
||||
- (NSMutableArray *)headers;
|
||||
- (NSString*)headersAtIndex:(NSUInteger)index;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder *)addHeaders:(NSString*)value;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder *)setHeadersArray:(NSArray *)array;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder *)clearHeaders;
|
||||
|
||||
- (BOOL) hasId;
|
||||
- (UInt64) id;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) setId:(UInt64) value;
|
||||
- (WebSocketResourcesWebSocketRequestMessageBuilder*) clearId;
|
||||
@end
|
||||
|
||||
#define WebSocketResponseMessage_id @"id"
|
||||
#define WebSocketResponseMessage_status @"status"
|
||||
#define WebSocketResponseMessage_message @"message"
|
||||
#define WebSocketResponseMessage_headers @"headers"
|
||||
#define WebSocketResponseMessage_body @"body"
|
||||
@interface WebSocketResourcesWebSocketResponseMessage : PBGeneratedMessage<GeneratedMessageProtocol> {
|
||||
@private
|
||||
BOOL hasId_:1;
|
||||
BOOL hasMessage_:1;
|
||||
BOOL hasBody_:1;
|
||||
BOOL hasStatus_:1;
|
||||
UInt64 id;
|
||||
NSString* message;
|
||||
NSData* body;
|
||||
UInt32 status;
|
||||
NSMutableArray * headersArray;
|
||||
}
|
||||
- (BOOL) hasId;
|
||||
- (BOOL) hasStatus;
|
||||
- (BOOL) hasMessage;
|
||||
- (BOOL) hasBody;
|
||||
@property (readonly) UInt64 id;
|
||||
@property (readonly) UInt32 status;
|
||||
@property (readonly, strong) NSString* message;
|
||||
@property (readonly, strong) NSArray * headers;
|
||||
@property (readonly, strong) NSData* body;
|
||||
- (NSString*)headersAtIndex:(NSUInteger)index;
|
||||
|
||||
+ (instancetype) defaultInstance;
|
||||
- (instancetype) defaultInstance;
|
||||
|
||||
- (BOOL) isInitialized;
|
||||
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) builder;
|
||||
+ (WebSocketResourcesWebSocketResponseMessageBuilder*) builder;
|
||||
+ (WebSocketResourcesWebSocketResponseMessageBuilder*) builderWithPrototype:(WebSocketResourcesWebSocketResponseMessage*) prototype;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) toBuilder;
|
||||
|
||||
+ (WebSocketResourcesWebSocketResponseMessage*) parseFromData:(NSData*) data;
|
||||
+ (WebSocketResourcesWebSocketResponseMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (WebSocketResourcesWebSocketResponseMessage*) parseFromInputStream:(NSInputStream*) input;
|
||||
+ (WebSocketResourcesWebSocketResponseMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (WebSocketResourcesWebSocketResponseMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
+ (WebSocketResourcesWebSocketResponseMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
@end
|
||||
|
||||
@interface WebSocketResourcesWebSocketResponseMessageBuilder : PBGeneratedMessageBuilder {
|
||||
@private
|
||||
WebSocketResourcesWebSocketResponseMessage* resultWebSocketResponseMessage;
|
||||
}
|
||||
|
||||
- (WebSocketResourcesWebSocketResponseMessage*) defaultInstance;
|
||||
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) clear;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) clone;
|
||||
|
||||
- (WebSocketResourcesWebSocketResponseMessage*) build;
|
||||
- (WebSocketResourcesWebSocketResponseMessage*) buildPartial;
|
||||
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) mergeFrom:(WebSocketResourcesWebSocketResponseMessage*) other;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
|
||||
- (BOOL) hasId;
|
||||
- (UInt64) id;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) setId:(UInt64) value;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) clearId;
|
||||
|
||||
- (BOOL) hasStatus;
|
||||
- (UInt32) status;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) setStatus:(UInt32) value;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) clearStatus;
|
||||
|
||||
- (BOOL) hasMessage;
|
||||
- (NSString*) message;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) setMessage:(NSString*) value;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) clearMessage;
|
||||
|
||||
- (NSMutableArray *)headers;
|
||||
- (NSString*)headersAtIndex:(NSUInteger)index;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder *)addHeaders:(NSString*)value;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder *)setHeadersArray:(NSArray *)array;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder *)clearHeaders;
|
||||
|
||||
- (BOOL) hasBody;
|
||||
- (NSData*) body;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) setBody:(NSData*) value;
|
||||
- (WebSocketResourcesWebSocketResponseMessageBuilder*) clearBody;
|
||||
@end
|
||||
|
||||
#define WebSocketMessage_type @"type"
|
||||
#define WebSocketMessage_request @"request"
|
||||
#define WebSocketMessage_response @"response"
|
||||
@interface WebSocketResourcesWebSocketMessage : PBGeneratedMessage<GeneratedMessageProtocol> {
|
||||
@private
|
||||
BOOL hasRequest_:1;
|
||||
BOOL hasResponse_:1;
|
||||
BOOL hasType_:1;
|
||||
WebSocketResourcesWebSocketRequestMessage* request;
|
||||
WebSocketResourcesWebSocketResponseMessage* response;
|
||||
WebSocketResourcesWebSocketMessageType type;
|
||||
}
|
||||
- (BOOL) hasType;
|
||||
- (BOOL) hasRequest;
|
||||
- (BOOL) hasResponse;
|
||||
@property (readonly) WebSocketResourcesWebSocketMessageType type;
|
||||
@property (readonly, strong) WebSocketResourcesWebSocketRequestMessage* request;
|
||||
@property (readonly, strong) WebSocketResourcesWebSocketResponseMessage* response;
|
||||
|
||||
+ (instancetype) defaultInstance;
|
||||
- (instancetype) defaultInstance;
|
||||
|
||||
- (BOOL) isInitialized;
|
||||
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) builder;
|
||||
+ (WebSocketResourcesWebSocketMessageBuilder*) builder;
|
||||
+ (WebSocketResourcesWebSocketMessageBuilder*) builderWithPrototype:(WebSocketResourcesWebSocketMessage*) prototype;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) toBuilder;
|
||||
|
||||
+ (WebSocketResourcesWebSocketMessage*) parseFromData:(NSData*) data;
|
||||
+ (WebSocketResourcesWebSocketMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (WebSocketResourcesWebSocketMessage*) parseFromInputStream:(NSInputStream*) input;
|
||||
+ (WebSocketResourcesWebSocketMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (WebSocketResourcesWebSocketMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
+ (WebSocketResourcesWebSocketMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
@end
|
||||
|
||||
@interface WebSocketResourcesWebSocketMessageBuilder : PBGeneratedMessageBuilder {
|
||||
@private
|
||||
WebSocketResourcesWebSocketMessage* resultWebSocketMessage;
|
||||
}
|
||||
|
||||
- (WebSocketResourcesWebSocketMessage*) defaultInstance;
|
||||
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) clear;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) clone;
|
||||
|
||||
- (WebSocketResourcesWebSocketMessage*) build;
|
||||
- (WebSocketResourcesWebSocketMessage*) buildPartial;
|
||||
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) mergeFrom:(WebSocketResourcesWebSocketMessage*) other;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
|
||||
- (BOOL) hasType;
|
||||
- (WebSocketResourcesWebSocketMessageType) type;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) setType:(WebSocketResourcesWebSocketMessageType) value;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) clearType;
|
||||
|
||||
- (BOOL) hasRequest;
|
||||
- (WebSocketResourcesWebSocketRequestMessage*) request;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) setRequest:(WebSocketResourcesWebSocketRequestMessage*) value;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) setRequestBuilder:(WebSocketResourcesWebSocketRequestMessageBuilder*) builderForValue;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) mergeRequest:(WebSocketResourcesWebSocketRequestMessage*) value;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) clearRequest;
|
||||
|
||||
- (BOOL) hasResponse;
|
||||
- (WebSocketResourcesWebSocketResponseMessage*) response;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) setResponse:(WebSocketResourcesWebSocketResponseMessage*) value;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) setResponseBuilder:(WebSocketResourcesWebSocketResponseMessageBuilder*) builderForValue;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) mergeResponse:(WebSocketResourcesWebSocketResponseMessage*) value;
|
||||
- (WebSocketResourcesWebSocketMessageBuilder*) clearResponse;
|
||||
@end
|
||||
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
1233
SignalServiceKit/src/Network/WebSockets/WebSocketResources.pb.m
Normal file
1233
SignalServiceKit/src/Network/WebSockets/WebSocketResources.pb.m
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@ -36,6 +36,9 @@ typedef NS_ENUM(NSInteger, TSMACType) {
|
||||
|
||||
+ (NSData *)generateRandomBytes:(NSUInteger)numberBytes;
|
||||
|
||||
+ (uint32_t)randomUInt32;
|
||||
+ (uint64_t)randomUInt64;
|
||||
|
||||
#pragma mark SHA and HMAC methods
|
||||
|
||||
// Full length SHA256 digest for `data`
|
||||
|
||||
@ -102,7 +102,25 @@ const NSUInteger kAES256_KeyByteLength = 32;
|
||||
|
||||
+ (NSData *)generateRandomBytes:(NSUInteger)numberBytes
|
||||
{
|
||||
return [Randomness generateRandomBytes:numberBytes];
|
||||
return [Randomness generateRandomBytes:(int)numberBytes];
|
||||
}
|
||||
|
||||
+ (uint32_t)randomUInt32
|
||||
{
|
||||
size_t size = sizeof(uint32_t);
|
||||
NSData *data = [self generateRandomBytes:size];
|
||||
uint32_t result = 0;
|
||||
[data getBytes:&result range:NSMakeRange(0, size)];
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (uint64_t)randomUInt64
|
||||
{
|
||||
size_t size = sizeof(uint64_t);
|
||||
NSData *data = [self generateRandomBytes:size];
|
||||
uint64_t result = 0;
|
||||
[data getBytes:&result range:NSMakeRange(0, size)];
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma mark SHA1
|
||||
|
||||
@ -43,6 +43,8 @@ typedef NS_ENUM(NSInteger, OWSErrorCode) {
|
||||
// A non-recoverable while importing or exporting a backup.
|
||||
OWSErrorCodeBackupFailure = 777419,
|
||||
OWSErrorCodeLocalAuthenticationError = 777420,
|
||||
OWSErrorCodeMessageRequestFailed = 777421,
|
||||
OWSErrorCodeMessageResponseFailed = 777422,
|
||||
};
|
||||
|
||||
extern NSString *const OWSErrorRecipientIdentifierKey;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user