@@ -87,11 +87,50 @@ public PushServiceSocket(SignalServiceConfiguration serviceUrls,
8787 this . contactDiscoveryClients = CreateConnectionHolders ( SignalConnectionInformation . SignalContactDiscoveryUrls ) ;
8888 }
8989
90- public async Task < bool > CreateAccount ( CancellationToken token , bool voice )
90+ public async Task RequestSmsVerificationCodeAsync ( string ? captchaToken , CancellationToken ? token = null )
9191 {
92- string path = voice ? CREATE_ACCOUNT_VOICE_PATH : CREATE_ACCOUNT_SMS_PATH ;
93- await MakeServiceRequestAsync ( token , string . Format ( path , CredentialsProvider . User ) , "GET" , null ) ;
94- return true ;
92+ if ( token == null )
93+ {
94+ token = CancellationToken . None ;
95+ }
96+
97+ string path = string . Format ( CREATE_ACCOUNT_SMS_PATH , CredentialsProvider . User ) ;
98+
99+ if ( captchaToken != null )
100+ {
101+ path += $ "?captcha={ captchaToken } ";
102+ }
103+
104+ await MakeServiceRequestAsync ( token . Value , path , "GET" , null , ( responseCode ) =>
105+ {
106+ if ( responseCode == 402 )
107+ {
108+ throw new CaptchaRequiredException ( ) ;
109+ }
110+ } ) ;
111+ }
112+
113+ public async Task RequestVoiceVerificationCodeAsync ( string ? captchaToken , CancellationToken ? token = null )
114+ {
115+ if ( token == null )
116+ {
117+ token = CancellationToken . None ;
118+ }
119+
120+ string path = string . Format ( CREATE_ACCOUNT_VOICE_PATH , CredentialsProvider . User ) ;
121+
122+ if ( captchaToken != null )
123+ {
124+ path += $ "?captcha={ captchaToken } ";
125+ }
126+
127+ await MakeServiceRequestAsync ( token . Value , path , "GET" , null , ( responseCode ) =>
128+ {
129+ if ( responseCode == 402 )
130+ {
131+ throw new CaptchaRequiredException ( ) ;
132+ }
133+ } ) ;
95134 }
96135
97136 public async Task < bool > VerifyAccountCode ( CancellationToken token , string verificationCode , string signalingKey , uint registrationId , bool fetchesMessages , string pin ,
@@ -181,7 +220,7 @@ public async Task<SendMessageResponse> SendMessage(OutgoingPushMessageList bundl
181220
182221 try
183222 {
184- string responseText = await MakeServiceRequestAsync ( string . Format ( MESSAGE_PATH , bundle . Destination ) , "PUT" , JsonUtil . ToJson ( bundle ) , unidentifiedAccess , token ) ;
223+ string responseText = await MakeServiceRequestAsync ( string . Format ( MESSAGE_PATH , bundle . Destination ) , "PUT" , JsonUtil . ToJson ( bundle ) , EmptyResponseCodeHandler , unidentifiedAccess , token ) ;
185224 return JsonUtil . FromJson < SendMessageResponse > ( responseText ) ;
186225 }
187226 catch ( NotFoundException nfe )
@@ -258,7 +297,7 @@ public async Task<List<PreKeyBundle>> GetPreKeys(SignalServiceAddress destinatio
258297 path = path + "?relay=" + destination . Relay ;
259298 }
260299
261- string responseText = await MakeServiceRequestAsync ( path , "GET" , null , unidentifiedAccess , token . Value ) ;
300+ string responseText = await MakeServiceRequestAsync ( path , "GET" , null , EmptyResponseCodeHandler , unidentifiedAccess , token . Value ) ;
262301 PreKeyResponse response = JsonUtil . FromJson < PreKeyResponse > ( responseText ) ;
263302 List < PreKeyBundle > bundles = new List < PreKeyBundle > ( ) ;
264303
@@ -427,12 +466,12 @@ public async Task<SignalServiceProfile> RetrieveProfile(SignalServiceAddress tar
427466
428467 try
429468 {
430- string response = await MakeServiceRequestAsync ( string . Format ( PROFILE_PATH , target . E164number ) , "GET" , null , unidentifiedAccess , token . Value ) ;
469+ string response = await MakeServiceRequestAsync ( string . Format ( PROFILE_PATH , target . E164number ) , "GET" , null , EmptyResponseCodeHandler , unidentifiedAccess , token . Value ) ;
431470 return JsonUtil . FromJson < SignalServiceProfile > ( response ) ;
432471 }
433472 catch ( Exception e )
434473 {
435- throw new NonSuccessfulResponseCodeException ( "Unable to parse entity: " + e . Message ) ;
474+ throw new MalformedResponseException ( "Unable to parse entity" , e ) ;
436475 }
437476 }
438477
@@ -457,7 +496,7 @@ public async Task SetProfileAvatar(CancellationToken token, ProfileAvatarData pr
457496 }
458497 catch ( IOException e )
459498 {
460- throw new NonSuccessfulResponseCodeException ( "Unable to parse entity (" + e . Message + ")" ) ;
499+ throw new MalformedResponseException ( "Unable to parse entity" , e ) ;
461500 }
462501
463502 if ( profileAvatar != null )
@@ -547,7 +586,7 @@ public async Task<DiscoveryResponse> GetContactDiscoveryRegisteredUsersAsync(str
547586 }
548587 else
549588 {
550- throw new NonSuccessfulResponseCodeException ( "Empty response!" ) ;
589+ throw new MalformedResponseException ( "Empty response!" ) ;
551590 }
552591 }
553592
@@ -688,9 +727,14 @@ private async Task<byte[]> UploadAttachment(CancellationToken token, string meth
688727 return ( digest , encryptedData ) ;
689728 }
690729
691- private async Task < string > MakeServiceRequestAsync ( CancellationToken token , string urlFragment , string method , string ? body )
730+ private async Task < string > MakeServiceRequestAsync ( CancellationToken token , string urlFragment , string method , string ? body , Action < int > ? responseCodeHandler = null )
692731 {
693- return await MakeServiceRequestAsync ( urlFragment , method , body , null , token ) ;
732+ if ( responseCodeHandler == null )
733+ {
734+ responseCodeHandler = EmptyResponseCodeHandler ;
735+ }
736+
737+ return await MakeServiceRequestAsync ( urlFragment , method , body , responseCodeHandler , null , token ) ;
694738 }
695739
696740
@@ -705,7 +749,8 @@ private async Task<string> MakeServiceRequestAsync(CancellationToken token, stri
705749 /// <returns></returns>
706750 /// <exception cref="NonSuccessfulResponseCodeException"></exception>
707751 /// <exception cref="PushNetworkException"></exception>
708- private async Task < string > MakeServiceRequestAsync ( string urlFragment , string method , string ? body , UnidentifiedAccess ? unidentifiedAccess , CancellationToken ? token = null )
752+ /// <exception cref="MalformedResponseException"></exception>
753+ private async Task < string > MakeServiceRequestAsync ( string urlFragment , string method , string ? body , Action < int > responseCodeHandler , UnidentifiedAccess ? unidentifiedAccess , CancellationToken ? token = null )
709754 {
710755 if ( token == null )
711756 {
@@ -728,13 +773,15 @@ private async Task<string> MakeServiceRequestAsync(string urlFragment, string me
728773 throw new PushNetworkException ( ioe ) ;
729774 }
730775
776+ responseCodeHandler . Invoke ( ( int ) responseCode ) ;
777+
731778 switch ( ( uint ) responseCode )
732779 {
733780 case 413 : // HttpStatusCode.RequestEntityTooLarge
734781 throw new RateLimitException ( "Rate limit exceeded: " + responseCode ) ;
735782 case 401 : // HttpStatusCode.Unauthorized
736783 case 403 : // HttpStatusCode.Forbidden
737- throw new AuthorizationFailedException ( "Authorization failed!" ) ;
784+ throw new AuthorizationFailedException ( ( int ) responseCode , "Authorization failed!" ) ;
738785 case 404 : // HttpStatusCode.NotFound
739786 throw new NotFoundException ( "Not found" ) ;
740787 case 409 : // HttpStatusCode.Conflict
@@ -789,8 +836,8 @@ private async Task<string> MakeServiceRequestAsync(string urlFragment, string me
789836
790837 if ( responseCode != HttpStatusCode . OK && responseCode != HttpStatusCode . NoContent ) // 200 & 204
791838 {
792- throw new NonSuccessfulResponseCodeException ( "Bad response: " + ( int ) responseCode + " " +
793- responseMessage ) ;
839+ throw new NonSuccessfulResponseCodeException ( ( int ) responseCode ,
840+ $ "Bad response: { ( int ) responseCode } { responseMessage } " ) ;
794841 }
795842
796843 return responseBody ;
@@ -925,7 +972,7 @@ private async Task<HttpResponseMessage> MakeRequestAsync(ConnectionHolder connec
925972 {
926973 case 401 :
927974 case 403 :
928- throw new AuthorizationFailedException ( "Authorization failed!" ) ;
975+ throw new AuthorizationFailedException ( ( int ) response . StatusCode , "Authorization failed!" ) ;
929976 case 409 :
930977 throw new RemoteAttestationResponseExpiredException ( "Remote attestation response expired" ) ;
931978 case 429 :
@@ -934,11 +981,12 @@ private async Task<HttpResponseMessage> MakeRequestAsync(ConnectionHolder connec
934981
935982 if ( response . Content != null )
936983 {
937- throw new NonSuccessfulResponseCodeException ( $ "Response: { await response . Content . ReadAsStringAsync ( ) } ") ;
984+ throw new NonSuccessfulResponseCodeException ( ( int ) response . StatusCode ,
985+ $ "Response: { await response . Content . ReadAsStringAsync ( ) } ") ;
938986 }
939987 else
940988 {
941- throw new NonSuccessfulResponseCodeException ( $ "Response: null") ;
989+ throw new NonSuccessfulResponseCodeException ( ( int ) response . StatusCode , $ "Response: null") ;
942990 }
943991 }
944992
@@ -968,6 +1016,10 @@ private T GetRandom<T>(T[] connections)
9681016 {
9691017 return connections [ Util . generateRandomNumber ( ) % connections . Length ] ;
9701018 }
1019+
1020+ private void EmptyResponseCodeHandler ( int responseCode )
1021+ {
1022+ }
9711023 }
9721024
9731025 internal class GcmRegistrationId
0 commit comments