Use websocket for sends.

This commit is contained in:
Matthew Chen 2018-05-18 13:55:22 -04:00
parent fb3efe3647
commit 5f1682deab
11 changed files with 2100 additions and 1463 deletions

2
Pods

@ -1 +1 @@
Subproject commit 086242800e27b3ee431ad23e9f29f3358e813059
Subproject commit 9ed0ac557a1056bc8628d110199afcad87209d5d

View 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;
}

View File

@ -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,240 @@ 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];
}
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);
if (YES) {
[TSSocketManager.sharedManager makeRequest:request
success:^{
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], ^{
DDLogDebug(@"%@ Retrying: %@", self.logTag, message.debugDescription);
[self sendMessageToService:message
recipient:recipient
thread:thread
attempts:remainingAttempts
success:successHandler
failure:failureHandler];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[recipient saveWithTransaction:transaction];
[message updateWithSentRecipient:recipient.uniqueId transaction:transaction];
}];
[self handleMessageSentLocally:message];
successHandler();
});
};
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) {
DDLogError(@"%@ Message send failed.", self.logTag);
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;
}
}];
} else
[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];
}
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;
}
}];
}
- (void)handleMismatchedDevices:(NSDictionary *)dictionary

View File

@ -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

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <SocketRocket/SRWebSocket.h>
@ -14,6 +14,11 @@ typedef NS_ENUM(NSUInteger, SocketManagerState) {
SocketManagerStateOpen,
};
typedef void (^TSSocketMessageSuccess)(void);
typedef void (^TSSocketMessageFailure)(NSInteger statusCode, NSError *error);
@class TSRequest;
@interface TSSocketManager : NSObject <SRWebSocketDelegate>
@property (nonatomic, readonly) SocketManagerState state;
@ -33,4 +38,10 @@ 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

View File

@ -10,18 +10,20 @@
#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"
static const CGFloat kSocketHeartbeatPeriodSeconds = 30.f;
static const CGFloat kSocketReconnectDelaySeconds = 5.f;
@ -36,6 +38,71 @@ static const CGFloat kBackgroundKeepSocketAliveDurationSeconds = 15.f;
NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_SocketManagerStateDidChange";
@interface TSSocketMessage : NSObject
@property (nonatomic) UInt64 requestId;
@property (nonatomic) TSSocketMessageSuccess success;
@property (nonatomic) TSSocketMessageFailure failure;
@property (nonatomic) BOOL hasCompleted;
@end
#pragma mark -
@implementation TSSocketMessage
- (void)didSucceed
{
@synchronized(self)
{
if (self.hasCompleted) {
return;
}
self.hasCompleted = YES;
}
OWSAssert(self.success);
OWSAssert(self.failure);
self.success();
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);
self.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 ()
@ -60,6 +127,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 -
@ -87,6 +156,10 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
@property (nonatomic) BOOL hasObservedNotifications;
// These two properties should only be accessed while synchronized on the socket manager.
@property (nonatomic) UInt64 requestIdCounter;
@property (nonatomic, readonly) NSMutableDictionary<NSNumber *, TSSocketMessage *> *socketMessageMap;
@end
#pragma mark -
@ -106,6 +179,9 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
_signalService = [OWSSignalService sharedInstance];
_messageReceiver = [OWSMessageReceiver sharedInstance];
_state = SocketManagerStateClosed;
// Ensure that all request ids are non-zero.
_requestIdCounter = 1;
_socketMessageMap = [NSMutableDictionary new];
OWSSingletonAssert();
@ -330,6 +406,104 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
self.state = SocketManagerStateClosed;
}
#pragma mark - Message Sending
- (void)makeRequest:(TSRequest *)request success:(TSSocketMessageSuccess)success failure:(TSSocketMessageFailure)failure
{
DispatchMainThreadSafe(^{
[self makeRequestOnMain:request success:success failure:failure];
});
}
// TODO: Currently we schedule requests on main since we want to consult the state property.
// There are alternatives.
- (void)makeRequestOnMain:(TSRequest *)request
success:(TSSocketMessageSuccess)success
failure:(TSSocketMessageFailure)failure
{
OWSAssertIsOnMainThread();
OWSAssert(request);
OWSAssert(request.HTTPMethod.length > 0);
OWSAssert(success);
OWSAssert(failure);
TSSocketMessage *socketMessage = [TSSocketMessage new];
socketMessage.success = success;
socketMessage.failure = failure;
@synchronized(self)
{
socketMessage.requestId = self.requestIdCounter++;
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
// TODO:
options:(NSJSONWritingOptions)0
// options:NSJSONWritingPrettyPrinted
error:&error];
if (!jsonData || error) {
OWSProdLogAndFail(@"%@ could not serialize request JSON: %@", self.logTag, error);
// TODO:
[socketMessage didFailBeforeSending];
return;
}
}
if (self.state != SocketManagerStateOpen) {
DDLogError(@"%@ makeRequest: socket not open.", self.logTag);
// TODO:
[socketMessage didFailBeforeSending];
return;
}
WebSocketResourcesWebSocketRequestMessageBuilder *requestBuilder =
[WebSocketResourcesWebSocketRequestMessageBuilder new];
requestBuilder.id = socketMessage.requestId;
[requestBuilder setVerb:request.HTTPMethod];
[requestBuilder setPath:requestPath];
[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);
// TODO:
[socketMessage didFailBeforeSending];
return;
}
NSError *error;
BOOL wasScheduled =
// TODO: Consider using sendDataNoCopy.
[self.websocket sendData:messageData error:&error];
if (!wasScheduled || error) {
OWSProdLogAndFail(@"%@ could not serialize request JSON: %@", self.logTag, error);
// TODO:
[socketMessage didFailBeforeSending];
return;
}
DDLogVerbose(@"%@ message scheduled: %lld, %@, %@, %zd.",
self.logTag,
socketMessage.requestId,
request.HTTPMethod,
requestPath,
jsonData.length);
// [socketMessage didSucceed];
}
#pragma mark - Delegate methods
- (void)webSocketDidOpen:(SRWebSocket *)webSocket {
@ -364,18 +538,21 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
return;
}
WebSocketMessage *wsMessage = [WebSocketMessage parseFromData:data];
WebSocketResourcesWebSocketMessage *wsMessage = [WebSocketResourcesWebSocketMessage parseFromData:data];
if (wsMessage.type == WebSocketMessageTypeRequest) {
if (wsMessage.type == WebSocketResourcesWebSocketMessageTypeRequest) {
DDLogVerbose(@"%@ webSocket:didReceiveMessage: request.", self.logTag);
[self processWebSocketRequestMessage:wsMessage.request];
} else if (wsMessage.type == WebSocketMessageTypeResponse) {
} else if (wsMessage.type == WebSocketResourcesWebSocketMessageTypeResponse) {
DDLogVerbose(@"%@ webSocket:didReceiveMessage: response.", self.logTag);
[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);
@ -395,7 +572,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
if (!decryptedPayload) {
DDLogWarn(@"%@ Failed to decrypt incoming payload or bad HMAC", self.logTag);
[self sendWebSocketMessageAcknowledgement:message];
[self sendWebSocketResourcesWebSocketMessageAcknowledgement:message];
backgroundTask = nil;
return;
}
@ -417,38 +594,91 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
}
dispatch_async(dispatch_get_main_queue(), ^{
[self sendWebSocketMessageAcknowledgement:message];
[self sendWebSocketResourcesWebSocketMessageAcknowledgement:message];
backgroundTask = nil;
});
});
} else if ([message.path isEqualToString:@"/api/v1/queue/empty"]) {
// Queue is drained.
[self sendWebSocketMessageAcknowledgement:message];
[self sendWebSocketResourcesWebSocketMessageAcknowledgement:message];
} else {
DDLogWarn(@"%@ Unsupported WebSocket Request", self.logTag);
[self sendWebSocketMessageAcknowledgement:message];
[self sendWebSocketResourcesWebSocketMessageAcknowledgement:message];
}
}
- (void)processWebSocketResponseMessage:(WebSocketResponseMessage *)message {
- (void)processWebSocketResponseMessage:(WebSocketResourcesWebSocketResponseMessage *)message
{
OWSAssertIsOnMainThread();
OWSAssert(message);
DDLogWarn(@"Client should not receive WebSocket Respond messages");
DDLogInfo(@"%@ received WebSocket response.", self.logTag);
if (![message hasId]) {
DDLogError(@"%@ received incomplete WebSocket response.", self.logTag);
return;
}
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;
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 didSucceed = 200 <= responseStatus && responseStatus <= 299;
if (didSucceed) {
[socketMessage didSucceed];
} 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);
}
- (void)sendWebSocketMessageAcknowledgement:(WebSocketRequestMessage *)request {
- (void)sendWebSocketResourcesWebSocketMessageAcknowledgement:(WebSocketResourcesWebSocketRequestMessage *)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];

View 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)

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -59,7 +59,7 @@ NSError *OWSErrorMakeMessageSendDisabledDueToPreKeyUpdateFailuresError()
NSError *OWSErrorMakeMessageSendFailedToBlockListError()
{
return OWSErrorWithCodeDescription(OWSErrorCodeMessageSendFailedToBlockList,
return OWSErrorWithCodeDescription(OWSErrorCodeMessageRequestFailedToBlockList,
NSLocalizedString(@"ERROR_DESCRIPTION_MESSAGE_SEND_FAILED_DUE_TO_BLOCK_LIST",
@"Error message indicating that message send failed due to block list"));
}