Skip to content

Declared in <galanthus/c_api/gln_capi.h>.

GLN_API gln_status_t GLN_CALL gln_resume_continuation(
    gln_backend_t*                  in_backend,
    gln_continuation_t*             in_continuation,
    gln_secret_t*                   in_interactive_secret_or_null,
    const gln_continuation_input_t* in_input,
    gln_backend_result_t**          out_result);
  • Family: Backend operations
  • Return type: gln_status_t

Purpose

gln_resume_continuation resumes an operation represented by a gln_continuation_t and returns a new gln_backend_result_t envelope.

The continuation is usually obtained from an action-required envelope with gln_take_backend_result_continuation or loaded from a continuation store. The continuation identifies the original operation, so the resumed success kind and typed accessor are operation-dependent.

Backend support is operation-specific. Use gln_check_backend_operation_support to check whether a backend supports this operation before calling it. Unsupported operations return an envelope whose status is GLN_ERR_NOT_SUPPORTED.

When To Use

Use this operation after an earlier backend result reports GLN_BACKEND_OUTCOME_ACTION_REQUIRED and the caller has collected the requested TAN, decoupled-poll step, HHDuc response, or VoP confirmation.

Use gln_save_continuation and gln_load_continuation when the operation may be resumed after process restart. Use gln_inspect_continuation or gln_describe_continuation when the caller needs to inspect a saved continuation before resuming it.

For the full flow, see Continuations and TAN and Resume.

Call Contract

GLN_OK from the function means an envelope was produced in *out_result; it does not mean the backend operation succeeded. Inspect the envelope with gln_get_backend_result_outcome, gln_get_backend_result_status, and gln_get_backend_result_kind.

out_result == NULL is the no-envelope invalid-argument case. In that case the function returns GLN_ERR_INVALID_ARG directly.

Pass a non-null in_input initialized by calling gln_default_continuation_input. For a normal TAN entry, pass the TAN as in_interactive_secret_or_null and leave in_input->kind as GLN_CONTINUATION_INPUT_KIND_NONE; hhduc_response_or_null may also be set when a chipTAN/HHDuc response must accompany the TAN. For a decoupled poll, set kind to GLN_CONTINUATION_INPUT_KIND_DECOUPLED_POLL. For a standalone HHDuc response without an interactive secret, set kind to GLN_CONTINUATION_INPUT_KIND_HHDUC_RESPONSE.

gln_default_continuation_input without an interactive secret is not a complete resume input; the returned envelope reports GLN_ERR_INVALID_ARG.

For VoP confirmation, set kind to GLN_CONTINUATION_INPUT_KIND_VOP_CONFIRM and pass NULL for in_interactive_secret_or_null. Supported VoP confirmation resume paths treat that kind as confirmation of the VoP id stored in the continuation. Unsupported VoP confirmation resume paths return an error envelope with status GLN_ERR_NOT_SUPPORTED and issue type unsupported_vop_confirmation_backend.

The parameter table is binding for required handles and output slots.

Return

Returns GLN_OK when the call produced a gln_backend_result_t envelope in out_result. Operation success, caller action, provider rejection, and operation errors are reported inside that envelope.

TypeNullabilityOwnership
gln_status_tvaluevalue

Parameters

NameDirectionTypeNullabilityOwnership
in_backendinputgln_backend_t*nonnullborrowed
in_continuationinputgln_continuation_t*nonnullborrowed
in_interactive_secret_or_nullinputgln_secret_t*nullableborrowed
in_inputinputconst gln_continuation_input_t*nonnullborrowed
out_resultoutputgln_backend_result_t**nonnulltransferred_out

Success Result

Successful resumed envelopes have outcome GLN_BACKEND_OUTCOME_SUCCESS and status GLN_OK; the result kind is the original operation's success kind.

For example, resuming a TAN media listing can produce GLN_BACKEND_RESULT_KIND_TAN_MEDIA and should be read with gln_get_backend_result_tan_media, while resuming a transaction listing can produce GLN_BACKEND_RESULT_KIND_TRANSACTIONS and should be read with gln_get_backend_result_transactions. Opaque JSON results should be read only when the result kind is GLN_BACKEND_RESULT_KIND_OPAQUE_JSON.

Outcomes

  • GLN_BACKEND_OUTCOME_SUCCESS: read the payload matching gln_get_backend_result_kind; typed result kinds use typed accessors and GLN_BACKEND_RESULT_KIND_OPAQUE_JSON uses gln_get_backend_result_opaque_json.
  • GLN_BACKEND_OUTCOME_ACTION_REQUIRED: the resumed operation still needs another caller action. Inspect gln_get_backend_result_interrupt_info, take the new continuation with gln_take_backend_result_continuation, and resume again after satisfying that prompt. The envelope status identifies the pending action: GLN_ERR_TAN_REQUIRED, GLN_ERR_DECOUPLED_PENDING, or GLN_ERR_VOP_CONFIRMATION_REQUIRED.
  • GLN_BACKEND_OUTCOME_REJECTED: inspect gln_get_backend_result_status and gln_get_backend_result_error for the bank rejection details.
  • GLN_BACKEND_OUTCOME_ERROR: inspect gln_get_backend_result_status and gln_get_backend_result_error. Other backends use this outcome with status GLN_ERR_NOT_SUPPORTED; invalid continuation payloads use status GLN_ERR_RESUME_ARTIFACT_INVALID.

Ownership And Lifetime

The resumed envelope returned through out_result is caller-owned and must be released with gln_destroy_backend_result.

in_continuation, in_interactive_secret_or_null, and in_input are borrowed for the duration of the call; the library copies what it needs. Current implementation does not transfer or destroy in_continuation, so the caller remains responsible for releasing it with gln_destroy_continuation after resume or after saving it elsewhere.

Typed views, row pointers, row strings, JSON strings, errors, and interrupt details borrowed from the resumed envelope become invalid when that envelope is destroyed. A continuation taken from the resumed envelope is caller-owned and must be destroyed separately.

Example

gln_continuation_t* continuation =
    gln_take_backend_result_continuation(action_required_result);
gln_destroy_backend_result(action_required_result);

if (continuation == NULL) {
    return GLN_ERR_INTERNAL;
}

gln_continuation_input_t input = {0};

gln_default_continuation_input(&input);
gln_backend_result_t* resumed = NULL;
gln_status_t rc = gln_resume_continuation(
    backend,
    continuation,
    tan_secret_or_null,
    &input,
    &resumed);
if (rc != GLN_OK) {
    gln_destroy_continuation(continuation);
    return rc;
}

if (gln_get_backend_result_outcome(resumed) == GLN_BACKEND_OUTCOME_SUCCESS) {
    switch (gln_get_backend_result_kind(resumed)) {
        case GLN_BACKEND_RESULT_KIND_TAN_MEDIA:
            read_tan_media(gln_get_backend_result_tan_media(resumed));
            break;
        case GLN_BACKEND_RESULT_KIND_TRANSACTIONS:
            read_transactions(gln_get_backend_result_transactions(resumed));
            break;
        case GLN_BACKEND_RESULT_KIND_OPAQUE_JSON:
            read_opaque_json(gln_get_backend_result_opaque_json(resumed));
            break;
        default:
            handle_unexpected_success_kind(gln_get_backend_result_kind(resumed));
            break;
    }
}
else if (gln_get_backend_result_outcome(resumed) == GLN_BACKEND_OUTCOME_ACTION_REQUIRED) {
    const gln_interrupt_info_t* interrupt = gln_get_backend_result_interrupt_info(resumed);
    handle_next_interrupt(interrupt);

    gln_continuation_t* next = gln_take_backend_result_continuation(resumed);
    if (next != NULL) {
        save_next_continuation(next);
        gln_destroy_continuation(next);
    }
}
else {
    handle_resume_failure(
        gln_get_backend_result_status(resumed),
        gln_get_backend_result_error(resumed));
}

gln_destroy_backend_result(resumed);
gln_destroy_continuation(continuation);

See Also