aboutsummaryrefslogtreecommitdiff
path: root/src/reducer/anastasis_api_recovery_redux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reducer/anastasis_api_recovery_redux.c')
-rw-r--r--src/reducer/anastasis_api_recovery_redux.c165
1 files changed, 164 insertions, 1 deletions
diff --git a/src/reducer/anastasis_api_recovery_redux.c b/src/reducer/anastasis_api_recovery_redux.c
index fab3c24..95632cc 100644
--- a/src/reducer/anastasis_api_recovery_redux.c
+++ b/src/reducer/anastasis_api_recovery_redux.c
@@ -151,6 +151,13 @@ struct SelectChallengeContext
151 * Payment secret, if we are in the "pay" state. 151 * Payment secret, if we are in the "pay" state.
152 */ 152 */
153 struct ANASTASIS_PaymentSecretP ps; 153 struct ANASTASIS_PaymentSecretP ps;
154
155 /**
156 * Application asked us to only poll for existing
157 * asynchronous challenges, and not to being a
158 * new one.
159 */
160 bool poll_only;
154}; 161};
155 162
156 163
@@ -741,7 +748,6 @@ solve_challenge_cb (void *cls,
741 &ps), 748 &ps),
742 GNUNET_JSON_spec_end () 749 GNUNET_JSON_spec_end ()
743 }; 750 };
744
745 json_t *challenge; 751 json_t *challenge;
746 752
747 if (NULL == ri) 753 if (NULL == ri)
@@ -769,6 +775,80 @@ solve_challenge_cb (void *cls,
769 return; 775 return;
770 } 776 }
771 777
778 /* resume all async, unsolved challenges */
779 {
780 bool poll_started = false;
781
782 for (unsigned int i = 0; i<ri->cs_len; i++)
783 {
784 struct ANASTASIS_Challenge *ci = ri->cs[i];
785 const struct ANASTASIS_ChallengeDetails *cd;
786 json_t *challenge;
787 json_t *pin;
788
789 cd = ANASTASIS_challenge_get_details (ci);
790 if (cd->solved ||
791 (! cd->async) )
792 continue;
793
794 challenge = find_challenge_in_ri (sctx->state,
795 &cd->uuid);
796 if (NULL == challenge)
797 {
798 GNUNET_break_op (0);
799 ANASTASIS_redux_fail_ (sctx->cb,
800 sctx->cb_cls,
801 TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
802 "challenge not found");
803 sctx_free (sctx);
804 return;
805 }
806 pin = json_object_get (challenge,
807 "answer-pin");
808 if (! json_is_integer (pin))
809 {
810 GNUNET_break_op (0);
811 ANASTASIS_redux_fail_ (sctx->cb,
812 sctx->cb_cls,
813 TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
814 "async challenge 'answer-pin' not found");
815 sctx_free (sctx);
816 return;
817 }
818 if (GNUNET_OK !=
819 ANASTASIS_challenge_answer2 (ci,
820 psp,
821 timeout,
822 json_integer_value (pin),
823 &answer_feedback_cb,
824 sctx))
825 {
826 ANASTASIS_redux_fail_ (sctx->cb,
827 sctx->cb_cls,
828 TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
829 "Failed to begin answering asynchronous challenge");
830 sctx_free (sctx);
831 return;
832 }
833 poll_started = true;
834 }
835
836 if (sctx->poll_only)
837 {
838 if (! poll_started)
839 {
840 GNUNET_break_op (0);
841 ANASTASIS_redux_fail_ (sctx->cb,
842 sctx->cb_cls,
843 TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
844 "no challenge available for polling");
845 return;
846 }
847 /* only polling, do not start new challenges */
848 return;
849 }
850 } /* end resuming async challenges */
851
772 /* Check if we got a payment_secret */ 852 /* Check if we got a payment_secret */
773 challenge = find_challenge_in_ri (sctx->state, 853 challenge = find_challenge_in_ri (sctx->state,
774 &sctx->uuid); 854 &sctx->uuid);
@@ -823,6 +903,7 @@ solve_challenge_cb (void *cls,
823 psp = &ps; 903 psp = &ps;
824 } 904 }
825 905
906 /* start or solve selected challenge */
826 for (unsigned int i = 0; i<ri->cs_len; i++) 907 for (unsigned int i = 0; i<ri->cs_len; i++)
827 { 908 {
828 struct ANASTASIS_Challenge *ci = ri->cs[i]; 909 struct ANASTASIS_Challenge *ci = ri->cs[i];
@@ -830,6 +911,8 @@ solve_challenge_cb (void *cls,
830 int ret; 911 int ret;
831 912
832 cd = ANASTASIS_challenge_get_details (ci); 913 cd = ANASTASIS_challenge_get_details (ci);
914 if (cd->async)
915 continue; /* handled above */
833 if (0 != 916 if (0 !=
834 GNUNET_memcmp (&sctx->uuid, 917 GNUNET_memcmp (&sctx->uuid,
835 &cd->uuid)) 918 &cd->uuid))
@@ -883,6 +966,12 @@ solve_challenge_cb (void *cls,
883 { 966 {
884 uint64_t ianswer = json_integer_value (pin); 967 uint64_t ianswer = json_integer_value (pin);
885 968
969 /* persist answer, in case async processing
970 happens via poll */
971 GNUNET_assert (0 ==
972 json_object_set (challenge,
973 "answer-pin",
974 pin));
886 ret = ANASTASIS_challenge_answer2 (ci, 975 ret = ANASTASIS_challenge_answer2 (ci,
887 psp, 976 psp,
888 timeout, 977 timeout,
@@ -1153,6 +1242,75 @@ solve_challenge (json_t *state,
1153 1242
1154 1243
1155/** 1244/**
1245 * The user asked for us to poll on pending
1246 * asynchronous challenges to see if they have
1247 * now completed / been satisfied.
1248 *
1249 * @param[in] state we are in
1250 * @param arguments our arguments with the solution
1251 * @param cb functiont o call with the new state
1252 * @param cb_cls closure for @a cb
1253 * @return handle to cancel challenge selection step
1254 */
1255static struct ANASTASIS_ReduxAction *
1256poll_challenges (json_t *state,
1257 const json_t *arguments,
1258 ANASTASIS_ActionCallback cb,
1259 void *cb_cls)
1260{
1261 struct SelectChallengeContext *sctx
1262 = GNUNET_new (struct SelectChallengeContext);
1263 json_t *rd;
1264
1265 if (NULL == arguments)
1266 {
1267 ANASTASIS_redux_fail_ (cb,
1268 cb_cls,
1269 TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
1270 "arguments missing");
1271 return NULL;
1272 }
1273 rd = json_object_get (state,
1274 "recovery_document");
1275 if (NULL == rd)
1276 {
1277 GNUNET_break_op (0);
1278 ANASTASIS_redux_fail_ (cb,
1279 cb_cls,
1280 TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
1281 "poll_challenges");
1282 return NULL;
1283 }
1284 sctx->poll_only = true;
1285 sctx->cb = cb;
1286 sctx->cb_cls = cb_cls;
1287 sctx->state = json_incref (state);
1288 sctx->args = json_incref ((json_t*) arguments);
1289 sctx->r = ANASTASIS_recovery_deserialize (ANASTASIS_REDUX_ctx_,
1290 rd,
1291 &solve_challenge_cb,
1292 sctx,
1293 &core_secret_cb,
1294 sctx);
1295 if (NULL == sctx->r)
1296 {
1297 json_decref (sctx->state);
1298 json_decref (sctx->args);
1299 GNUNET_free (sctx);
1300 GNUNET_break_op (0);
1301 ANASTASIS_redux_fail_ (cb,
1302 cb_cls,
1303 TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
1304 "'recovery_document' invalid");
1305 return NULL;
1306 }
1307 sctx->ra.cleanup = &sctx_free;
1308 sctx->ra.cleanup_cls = sctx;
1309 return &sctx->ra;
1310}
1311
1312
1313/**
1156 * The user selected a challenge to be solved. Handle the payment 1314 * The user selected a challenge to be solved. Handle the payment
1157 * process. 1315 * process.
1158 * 1316 *
@@ -1712,6 +1870,11 @@ ANASTASIS_recovery_action_ (json_t *state,
1712 }, 1870 },
1713 { 1871 {
1714 ANASTASIS_RECOVERY_STATE_CHALLENGE_SELECTING, 1872 ANASTASIS_RECOVERY_STATE_CHALLENGE_SELECTING,
1873 "poll",
1874 &poll_challenges
1875 },
1876 {
1877 ANASTASIS_RECOVERY_STATE_CHALLENGE_SELECTING,
1715 "back", 1878 "back",
1716 &ANASTASIS_back_generic_decrement_ 1879 &ANASTASIS_back_generic_decrement_
1717 }, 1880 },