@ -79,7 +79,7 @@ typedef NS_ENUM(NSInteger, OWSSendMessageOperationState) {
 
		
	
		
			
				
 
		
	
		
			
				-  ( void ) attemptToSendMessage : ( TSOutgoingMessage  * ) message  
		
	
		
			
				                     success : ( void  ( ^) ( ) ) successHandler 
 
		
	
		
			
				                     failure : ( void ( ^) ( NSError  * error )  ) failureHandler ; 
 
		
	
		
			
				                     failure : ( RetryableFailureHandler ) failureHandler ; 
 
		
	
		
			
				
 
		
	
		
			
				@ end  
		
	
		
			
				
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -209,10 +209,17 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
 
		
	
		
			
				
 
		
	
		
			
				-  ( void ) tryWithRemainingRetries : ( NSUInteger ) remainingRetries  
		
	
		
			
				{  
		
	
		
			
				    DDLogDebug ( @ "%@ remainingRetries: %lu", self.tag,  remainingRetries);
 
		
	
		
			
				    DDLogDebug ( @ "%@ remainingRetries: %lu", self.tag,  (unsigned long) remainingRetries);
 
		
	
		
			
				
 
		
	
		
			
				    void ( ^retryableFailureHandler ) ( NSError  * _Nonnull )  =  ^( NSError  * _Nonnull  error  )  { 
 
		
	
		
			
				    RetryableFailureHandler retryableFailureHandler  =  ^( NSError  * _Nonnull  error ,  BOOL  isRetryable  )  { 
 
		
	
		
			
				        DDLogInfo ( @ "%@ Sending failed.", self.tag); 
 
		
	
		
			
				
 
		
	
		
			
				        if  ( !isRetryable )  { 
 
		
	
		
			
				            DDLogInfo ( @ "%@ Skipping retry due to terminal error: %@", self.tag, error); 
 
		
	
		
			
				            self . failureHandler ( error ) ; 
 
		
	
		
			
				            return ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				
 
		
	
		
			
				        if  ( remainingRetries  >  0 )  { 
 
		
	
		
			
				            [ self  tryWithRemainingRetries : remainingRetries  -  1 ] ; 
 
		
	
		
			
				        }  else  { 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -349,12 +356,13 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				
 
		
	
		
			
				-  ( void ) attemptToSendMessage : ( TSOutgoingMessage  * ) message  
		
	
		
			
				                     success : ( void  ( ^) ( ) ) successHandler 
 
		
	
		
			
				                     failure : ( void ( ^) ( NSError  * error )  ) failureHandler 
 
		
	
		
			
				                     failure : ( RetryableFailureHandler ) failureHandler 
 
		
	
		
			
				{  
		
	
		
			
				    DDLogDebug ( @ "%@ sending message: %@", self.tag, message.debugDescription); 
 
		
	
		
			
				    void  ( ^markAndFailureHandler ) ( NSError  * error )  =  ^( NSError  * error )  { 
 
		
	
		
			
				    RetryableFailureHandler  markAndFailureHandler  =  ^( NSError  * error ,  BOOL  isRetryable )  { 
 
		
	
		
			
				        / /  TODO  do  we  really  want  to  mark  this  as  failed  if  we ' re  still  retrying ?
 
		
	
		
			
				        [ self  saveMessage : message  withError : error ] ; 
 
		
	
		
			
				        failureHandler ( error ; 
 
		
	
		
			
				        failureHandler ( error , isRetryable  ); 
 
		
	
		
			
				    } ; 
 
		
	
		
			
				
 
		
	
		
			
				    [ self  ensureAnyAttachmentsUploaded : message 
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -366,7 +374,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				
 
		
	
		
			
				-  ( void ) ensureAnyAttachmentsUploaded : ( TSOutgoingMessage  * ) message  
		
	
		
			
				                             success : ( void  ( ^) ( ) ) successHandler 
 
		
	
		
			
				                             failure : ( void ( ^) ( NSError  * error )  ) failureHandler 
 
		
	
		
			
				                             failure : ( RetryableFailureHandler ) failureHandler 
 
		
	
		
			
				{  
		
	
		
			
				    if  ( !message . hasAttachments )  { 
 
		
	
		
			
				        DDLogDebug ( @ "%@ No attachments for message: %@", self.tag, message); 
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -379,7 +387,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				    if  ( !attachmentStream )  { 
 
		
	
		
			
				        DDLogError ( @ "%@ Unable to find local saved attachment to upload.", self.tag); 
 
		
	
		
			
				        NSError  * error  =  OWSErrorMakeFailedToSendOutgoingMessageError ( ) ; 
 
		
	
		
			
				        return  failureHandler ( error ) ; 
 
		
	
		
			
				        / /  Not  finding  local  attachment  is  a  terminal  failure . 
 
		
	
		
			
				        return  failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    [ self . uploadingService  uploadAttachmentStream : attachmentStream 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -471,8 +480,15 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				
 
		
	
		
			
				        / /  Normally  marking  as  unsent  is  handled  in  sendMessage  happy  path ,  but  beacuse  we ' re  skipping  the  common  entry 
 
		
	
		
			
				        / /  point  to  message  sending  in  order  to  send  to  a  single  recipient ,  we  have  to  handle  it  ourselves . 
 
		
	
		
			
				        void ( ^markAndFailureHandler ) ( NSError  * error )  =  ^( NSError  * error  )  { 
 
		
	
		
			
				        RetryableFailureHandler markAndFailureHandler  =  ^( NSError  * error ,  BOOL  isRetryable  )  { 
 
		
	
		
			
				            [ self  saveMessage : message  withError : error ] ; 
 
		
	
		
			
				            if  ( isRetryable )  { 
 
		
	
		
			
				                / /  FIXME :  Fixing  this  will  require  a  larger  refactor .  In  the  meanwhile ,  we  don ' t 
 
		
	
		
			
				                / /  retry  message  sending  from  accepting  key - changes  in  a  group .  ( Except  for  the  inner  retry  logic  w /  the 
 
		
	
		
			
				                / /  messages  API ) 
 
		
	
		
			
				                DDLogWarn ( @ "%@ Skipping retry for group-message failure during %s.", self.tag, __PRETTY_FUNCTION__); 
 
		
	
		
			
				            } 
 
		
	
		
			
				
 
		
	
		
			
				            failureHandler ( error ) ; 
 
		
	
		
			
				        } ; 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -512,7 +528,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				
 
		
	
		
			
				-  ( void ) deliverMessage : ( TSOutgoingMessage  * ) message  
		
	
		
			
				               success : ( void  ( ^) ( ) ) successHandler 
 
		
	
		
			
				               failure : ( void ( ^) ( NSError  * error )  ) failureHandler 
 
		
	
		
			
				               failure : ( RetryableFailureHandler ) failureHandler 
 
		
	
		
			
				{  
		
	
		
			
				    TSThread  * thread  =  message . thread ; 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -526,11 +542,13 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				
 
		
	
		
			
				            if  ( recipients . count  ==  0 )  { 
 
		
	
		
			
				                if  ( error )  { 
 
		
	
		
			
				                    failureHandler ( error ) ; 
 
		
	
		
			
				                    / /  If  not  recipients  were  found ,  there ' s  no  reason  to  retry .  It  will  just  fail  again . 
 
		
	
		
			
				                    failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				                    return ; 
 
		
	
		
			
				                }  else  { 
 
		
	
		
			
				                    DDLogError ( @ "%@ Unknown error finding contacts", self.tag); 
 
		
	
		
			
				                    failureHandler ( OWSErrorMakeFailedToSendOutgoingMessageError ( ) ) ; 
 
		
	
		
			
				                    / /  If  not  recipients  were  found ,  there ' s  no  reason  to  retry .  It  will  just  fail  again . 
 
		
	
		
			
				                    failureHandler ( OWSErrorMakeFailedToSendOutgoingMessageError ( ) ,  NO ) ; 
 
		
	
		
			
				                    return ; 
 
		
	
		
			
				                } 
 
		
	
		
			
				            } 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -558,7 +576,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				            if  ( [ blockedPhoneNumbers  containsObject : recipientContactId ] )  { 
 
		
	
		
			
				                DDLogInfo ( @ "%@ skipping 1:1 send to blocked contact: %@", self.tag, recipientContactId); 
 
		
	
		
			
				                NSError  * error  =  OWSErrorMakeMessageSendFailedToBlocklistError ( ) ; 
 
		
	
		
			
				                failureHandler ( error ) ; 
 
		
	
		
			
				                / /  No  need  to  retry  -  the  user  will  continue  to  be  blocked . 
 
		
	
		
			
				                failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				                return ; 
 
		
	
		
			
				            } 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -575,7 +594,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				                    } 
 
		
	
		
			
				
 
		
	
		
			
				                    DDLogError ( @ "%@ contact lookup failed with error: %@", self.tag, error); 
 
		
	
		
			
				                    failureHandler ( error ) ; 
 
		
	
		
			
				                    / /  No  need  to  repeat  trying  to  find  a  failure .  Apart  from  repeatedly  failing ,  it  would  also  cause  us 
 
		
	
		
			
				                    / /  to  print  redundant  error  messages . 
 
		
	
		
			
				                    failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				                    return ; 
 
		
	
		
			
				                } 
 
		
	
		
			
				            } 
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -583,7 +604,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				            if  ( !recipient )  { 
 
		
	
		
			
				                NSError  * error  =  OWSErrorMakeFailedToSendOutgoingMessageError ( ) ; 
 
		
	
		
			
				                DDLogWarn ( @ "recipient  contact  still  not  found  after  attempting  lookup . ") ; 
 
		
	
		
			
				                failureHandler ( error ) ; 
 
		
	
		
			
				                / /  No  need  to  repeat  trying  to  find  a  failure .  Apart  from  repeatedly  failing ,  it  would  also  cause  us  to 
 
		
	
		
			
				                / /  print  redundant  error  messages . 
 
		
	
		
			
				                failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				                return ; 
 
		
	
		
			
				            } 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -595,8 +618,12 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				                      failure : failureHandler ] ; 
 
		
	
		
			
				        }  else  { 
 
		
	
		
			
				            DDLogError ( @ "%@ Unexpected unhandlable message: %@", self.tag, message); 
 
		
	
		
			
				
 
		
	
		
			
				            / /  Neither  a  group  nor  contact  thread ? This  should  never  happen . 
 
		
	
		
			
				            OWSAssert ( NO ) ; 
 
		
	
		
			
				
 
		
	
		
			
				            NSError  * error  =  OWSErrorMakeFailedToSendOutgoingMessageError ( ) ; 
 
		
	
		
			
				            failureHandler ( error ) ; 
 
		
	
		
			
				            failureHandler ( error , NO  ); 
 
		
	
		
			
				        } 
 
		
	
		
			
				    } ) ; 
 
		
	
		
			
				}  
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -616,7 +643,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				        success : ^{ 
 
		
	
		
			
				            [ futureSource  trySetResult : @ 1 ] ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				        failure : ^( NSError  * error )  { 
 
		
	
		
			
				        failure : ^( NSError  * error ,  BOOL  isRetryable )  { 
 
		
	
		
			
				            / /  FIXME  what  to  do  WRT  retryable  here ?
 
		
	
		
			
				            [ futureSource  trySetFailure : error ] ; 
 
		
	
		
			
				        } ] ; 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -627,7 +655,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				          message : ( TSOutgoingMessage  * ) message 
 
		
	
		
			
				           thread : ( TSThread  * ) thread 
 
		
	
		
			
				          success : ( void  ( ^) ( ) ) successHandler 
 
		
	
		
			
				          failure : ( void ( ^) ( NSError  * error )  ) failureHandler 
 
		
	
		
			
				          failure : ( RetryableFailureHandler ) failureHandler 
 
		
	
		
			
				{  
		
	
		
			
				    [ self  saveGroupMessage : message  inThread : thread ] ; 
 
		
	
		
			
				    NSMutableArray < TOCFuture  * >  * futures  =  [ NSMutableArray  array ] ; 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -669,14 +697,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				                if  ( failedFuture . hasFailed )  { 
 
		
	
		
			
				                    id  failureResult  =  failedFuture . forceGetFailure ; 
 
		
	
		
			
				                    if  ( [ failureResult  isKindOfClass : [ NSError  class ] ] )  { 
 
		
	
		
			
				                        return  failureHandler ( ( NSError  * ) failureResult ) ; 
 
		
	
		
			
				                        / /  Generally  we  assume  that  failures  are  retryable 
 
		
	
		
			
				                        return  failureHandler ( ( NSError  * ) failureResult ,  YES ) ; 
 
		
	
		
			
				                    } 
 
		
	
		
			
				                } 
 
		
	
		
			
				            } 
 
		
	
		
			
				        } 
 
		
	
		
			
				
 
		
	
		
			
				        DDLogWarn ( @ "%@ Unexpected generic failure: %@", self.tag, failure); 
 
		
	
		
			
				        return  failureHandler ( OWSErrorMakeFailedToSendOutgoingMessageError ( ) ) ; 
 
		
	
		
			
				        OWSAssert ( NO ) ; 
 
		
	
		
			
				        return  failureHandler ( OWSErrorMakeFailedToSendOutgoingMessageError ( ) ,  YES ) ; 
 
		
	
		
			
				    } ] ; 
 
		
	
		
			
				}  
		
	
		
			
				
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -696,7 +726,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				             thread : ( TSThread  * ) thread 
 
		
	
		
			
				           attempts : ( int ) remainingAttempts 
 
		
	
		
			
				            success : ( void  ( ^) ( ) ) successHandler 
 
		
	
		
			
				            failure : ( void ( ^) ( NSError  * error )  ) failureHandler 
 
		
	
		
			
				            failure : ( RetryableFailureHandler ) failureHandler 
 
		
	
		
			
				{  
		
	
		
			
				    DDLogDebug ( @ "%@ sending message to service: %@", self.tag, message.debugDescription); 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -717,13 +747,15 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				            } ] ; 
 
		
	
		
			
				
 
		
	
		
			
				        DDLogError ( @ "%@ Message send failed due to repeated inability to update prekeys.", self.tag); 
 
		
	
		
			
				        return  failureHandler ( OWSErrorMakeMessageSendDisabledDueToPreKeyUpdateFailuresError ( ) ; 
 
		
	
		
			
				        return  failureHandler ( OWSErrorMakeMessageSendDisabledDueToPreKeyUpdateFailuresError ( ) , YES  ); 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
		
			
				    if  ( remainingAttempts  < =  0 )  { 
 
		
	
		
			
				        / /  We  should  always  fail  with  a  specific  error . 
 
		
	
		
			
				        DDLogError ( @ "%@ Unexpected generic failure.", self.tag); 
 
		
	
		
			
				        return  failureHandler ( OWSErrorMakeFailedToSendOutgoingMessageError ( ) ) ; 
 
		
	
		
			
				        OWSAssert ( NO ) ; 
 
		
	
		
			
				
 
		
	
		
			
				        return  failureHandler ( OWSErrorMakeFailedToSendOutgoingMessageError ( ) ,  YES ) ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				    remainingAttempts  - =  1 ; 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -741,14 +773,18 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				            NSError  * error  =  OWSErrorWithCodeDescription ( OWSErrorCodeUntrustedIdentityKey , 
 
		
	
		
			
				                NSLocalizedString ( @ "FAILED_SENDING_BECAUSE_UNTRUSTED_IDENTITY_KEY ", 
 
		
	
		
			
				                    @ "action  sheet  header  when  re - sending  message  which  failed  because  of  untrusted  identity  keys ") ) ; 
 
		
	
		
			
				            return  failureHandler ( error ) ; 
 
		
	
		
			
				            / /  Key  will  continue  to  be  unaccepted ,  so  no  need  to  retry .  It ' ll  only  cause  us  to  hit  the  Pre - Key  request 
 
		
	
		
			
				            / /  rate  limit 
 
		
	
		
			
				            return  failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				
 
		
	
		
			
				        if  ( [ exception . name  isEqualToString : OWSMessageSenderRateLimitedException ] )  { 
 
		
	
		
			
				            NSError  * error  =  OWSErrorWithCodeDescription ( OWSErrorCodeSignalServiceRateLimited , 
 
		
	
		
			
				                NSLocalizedString ( @ "FAILED_SENDING_BECAUSE_RATE_LIMIT ", 
 
		
	
		
			
				                    @ "action  sheet  header  when  re - sending  message  which  failed  because  of  too  many  attempts ") ) ; 
 
		
	
		
			
				            return  failureHandler ( error ) ; 
 
		
	
		
			
				
 
		
	
		
			
				            / /  We ' re  already  rate - limited .  No  need  to  exacerbate  the  problem . 
 
		
	
		
			
				            return  failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				
 
		
	
		
			
				        if  ( remainingAttempts  ==  0 )  { 
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -756,7 +792,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				                @ "%@ Terminal failure to build any device messages. Giving up with exception:%@", self.tag, exception); 
 
		
	
		
			
				            [ self  processException : exception  outgoingMessage : message  inThread : thread ] ; 
 
		
	
		
			
				            NSError  * error  =  OWSErrorMakeFailedToSendOutgoingMessageError ( ) ; 
 
		
	
		
			
				            return  failureHandler ( error ) ; 
 
		
	
		
			
				            / /  Since  we ' ve  already  repeatedly  failed  to  build  messages ,  it ' s  unlikely  that  repeating  the  whole  process 
 
		
	
		
			
				            / /  will  succeed . 
 
		
	
		
			
				            return  failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				    } 
 
		
	
		
			
				
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -783,7 +821,9 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				
 
		
	
		
			
				            void  ( ^retrySend ) ( )  =  ^void ( )  { 
 
		
	
		
			
				                if  ( remainingAttempts  < =  0 )  { 
 
		
	
		
			
				                    return  failureHandler ( error ) ; 
 
		
	
		
			
				                    / /  Since  we ' ve  already  repeatedly  failed  to  send  to  the  messaging  API , 
 
		
	
		
			
				                    / /  it ' s  unlikely  that  repeating  the  whole  process  will  succeed . 
 
		
	
		
			
				                    return  failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				                } 
 
		
	
		
			
				
 
		
	
		
			
				                dispatch_async ( [ OWSDispatch  sendingQueue ] ,  ^{ 
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -801,12 +841,14 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				                case  401 :  { 
 
		
	
		
			
				                    DDLogWarn ( @ "%@ Unable to send due to invalid credentials. Did the user's client get de-authed by registering elsewhere?", self.tag); 
 
		
	
		
			
				                    NSError  * error  =  OWSErrorWithCodeDescription ( OWSErrorCodeSignalServiceFailure ,  NSLocalizedString ( @ "ERROR_DESCRIPTION_SENDING_UNAUTHORIZED ",  @ "Error  message  when  attempting  to  send  message ") ) ; 
 
		
	
		
			
				                    return  failureHandler ( error ) ; 
 
		
	
		
			
				                    / /  No  need  to  retry  if  we ' ve  been  de - authed . 
 
		
	
		
			
				                    return  failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				                } 
 
		
	
		
			
				                case  404 :  { 
 
		
	
		
			
				                    [ self  unregisteredRecipient : recipient  message : message  thread : thread ] ; 
 
		
	
		
			
				                    NSError  * error  =  OWSErrorMakeNoSuchSignalRecipientError ( ) ; 
 
		
	
		
			
				                    return  failureHandler ( error ) ; 
 
		
	
		
			
				                    / /  No  need  to  retry  if  the  recipient  is  not  registered . 
 
		
	
		
			
				                    return  failureHandler ( error ,  NO ) ; 
 
		
	
		
			
				                } 
 
		
	
		
			
				                case  409 :  { 
 
		
	
		
			
				                    / /  Mismatched  devices 
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -817,7 +859,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				                        [ NSJSONSerialization  JSONObjectWithData : responseData  options : 0  error : & error ] ; 
 
		
	
		
			
				                    if  ( error )  { 
 
		
	
		
			
				                        DDLogError ( @ "%@ Failed to serialize response of mismatched devices: %@", self.tag, error); 
 
		
	
		
			
				                        return  failureHandler ( error ; 
 
		
	
		
			
				                        return  failureHandler ( error , YES  ); 
 
		
	
		
			
				                    } 
 
		
	
		
			
				
 
		
	
		
			
				                    [ self  handleMismatchedDevices : serializedResponse  recipient : recipient ] ; 
 
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
			
			@ -831,7 +873,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				                    if  ( !responseData )  { 
 
		
	
		
			
				                        DDLogWarn ( @ "Stale  devices  but  server  didn ' t  specify  devices  in  response . ") ; 
 
		
	
		
			
				                        NSError  * error  =  OWSErrorMakeUnableToProcessServerResponseError ( ) ; 
 
		
	
		
			
				                        return  failureHandler ( error ; 
 
		
	
		
			
				                        return  failureHandler ( error , YES  ); 
 
		
	
		
			
				                    } 
 
		
	
		
			
				
 
		
	
		
			
				                    [ self  handleStaleDevicesWithResponse : responseData  recipientId : recipient . uniqueId ] ; 
 
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
			
			@ -933,7 +975,12 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
		
	
		
			
				        success : ^{ 
 
		
	
		
			
				            DDLogInfo ( @ "Succesfully  sent  sync  transcript . ") ; 
 
		
	
		
			
				        } 
 
		
	
		
			
				        failure : ^( NSError  * error )  { 
 
		
	
		
			
				        failure : ^( NSError  * error ,  BOOL  isRetryable )  { 
 
		
	
		
			
				            / /  FIXME :  We  don ' t  yet  honor  the  isRetryable  flag  here ,  since  sendSyncTranscriptForMessage 
 
		
	
		
			
				            / /  isn ' t  yet  wrapped  in  our  retryable  SendMessageOperation .  Addressing  this  would  require 
 
		
	
		
			
				            / /  a  refactor  to  the  MessageSender .  Note  that  we  * do *  however  continue  to  respect  the 
 
		
	
		
			
				            / /  OWSMessageSenderRetryAttempts ,  which  is  an  "inner " retry  loop ,  encompassing  only  the 
 
		
	
		
			
				            / /  messaging  API . 
 
		
	
		
			
				            DDLogInfo ( @ "Failed  to  send  sync  transcript : %@", error); 
 
		
	
		
			
				        } ] ; 
 
		
	
		
			
				}