# Calling

> UCall for C

`ucall_client_call()` returns a synchronous acceptance outcome; success guarantees one completion and refusal produces none.
Keep the borrowed URL, headers, body, and security-key inputs alive until completion retrieval.
`ucall_client_take_completed()` drives progress and retrieves a batch of records containing the caller cookie, final outcome, and response.
Retrieval returns each call's admission credit.
The connection budget must be positive; a zero call budget uses the connection budget times `max_pipelined_calls`.
Retrieved responses belong to the caller until `ucall_client_response_free()`; client teardown discards unretrieved results.
Response accessors take only the response, which stays readable after its client is freed.
HTTP calls support connection reuse, pipelining, chunked receive framing, redirects, and request deadlines.
A client's `max_pipelined_calls` bounds the calls one connection carries at once, and no call is pipelined behind one that is not idempotent or that sends `Connection: close`.
A pipelined connection lost mid-flight retries its unanswered idempotent calls and finishes the rest with `ucall_status_connection_closed_k`.
Calls a server left unread when it announced a close are sent again on a new connection.
Host names go through a built-in stub resolver driven by the client's own engine: `/etc/resolv.conf` with `search` and `ndots` and `/etc/hosts` on POSIX, the adapters' settings on Windows, AAAA and A over UDP with TCP on truncation, CNAME chains, and answers cached for their TTL.
Connections race the answered addresses as RFC 8305's Happy Eyeballs does.
`max_response_bytes` caps what a call buffers, failing with `ucall_status_overflow_k` past it, and the client's `log` reports failed dials, refused handshakes and refused redirects.

`#include <ucall/types.h>`

`#include <ucall/client.h>`

## ucall_client_t

Opaque client handle.

```c
typedef struct ucall_client_handle_t * ucall_client_t;
```

At a high level, a __client__ is responsible for:

- Establishing connections to one or more servers, reusing encryption keys between requests.
- Following redirects chains automatically, unless disabled.
- Driving accepted calls when the application polls for completions.

See also: Deals with `[ucall_received_http_response_t](#ucall_received_http_response_t)`.

See also: Use with `ucall_client_init()` and `ucall_client_free()` for lifetime.

See also: Use `ucall_client_call()` for logic.

## ucall_received_http_response_t

Opaque handle for a single Remote Procedure Call reply on the __client__ side.

```c
typedef struct ucall_received_http_response_handle_t * ucall_received_http_response_t;
```

## ucall_client_options_t

Configuration parameters for the UCall client.

```c
struct ucall_client_options_t
```

- `max_concurrent_connections` `size_t`: Required positive budget for simultaneously open connections.
- `max_pipelined_calls` `size_t`: Calls one connection may carry before the next call opens or waits for another; zero means one.
- `connect_timeout_microseconds` `size_t`: Time budget for establishing a connection.
- `call_timeout_microseconds` `size_t`: Time budget for a full request-response exchange.
- `noise_private_key` `ucall_noise_key_t const *`: Client identity for handshakes.
- `peer_authorizer` `ucall_peer_authorizer_t`: Vets server static keys.
- `peer_authorizer_context` `void *`: Passed verbatim to `peer_authorizer`.
- `log` `ucall_log_t`: Where log lines go.
- `max_concurrent_calls` `size_t`: Accepted calls, including unretrieved completions; zero uses the connection budget times `max_pipelined_calls`.
- `backend` `ucall_io_backend_t`: Requested I/O backend; automatic chooses an available native backend.
- `cpu_class` `ucall_cpu_class_t`: Ceiling on the CPU class: the newest compiled class under it runs, and unknown takes the initialization thread's capabilities.
- `max_response_bytes` `size_t`: Largest response a call buffers, head and body, past which it fails with [`ucall_status_overflow_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_overflow_k), as `max_request_bytes` bounds a server's requests.
- `server` `ucall_server_t`: A server whose event loop drives this client, or NULL for a client with its own engine.
- `event_loop` `size_t`: Which of `server's` event loops; ignored without `server`.

See also: Initialize with `ucall_client_init()`.

## ucall_client_call_options_t

Options of one client call: time budget, retries, redirects and security.

```c
struct ucall_client_call_options_t
```

- `timeout_microseconds` `size_t`: Time budget including queueing and redirects.
- `max_retries` `size_t`: Additional connection attempts before sending the request.
- `max_redirects` `size_t`: Redirect hops followed before failing.
- `security` `ucall_security_t`: Transport security for this call.
- `noise_private_key` `ucall_noise_key_t const *`: The client's identity; needed for KK.
- `noise_peer_key` `ucall_noise_key_t const *`: The server's expected key; needed for IK and KK.

## ucall_completed_call_t

A final result for one accepted client call.

```c
struct ucall_completed_call_t
```

- `context` `void *`: Cookie supplied when the call was submitted.
- `outcome` `ucall_outcome_t`: Final network or protocol outcome, independent of the acceptance result.
- `response` `ucall_received_http_response_t`: Received response, or NULL on failure.

## ucall_client_init

Initializes the client state.

```c
void ucall_client_init(ucall_client_init_t *arguments);
```

- `client`: Output for the new client.
- `outcome`: Synchronous initialization result.
- `options`: Requested configuration.
- `resolved`: Optional output for `options` with every default filled in.

Notes: One owner at a time may submit, poll, or free the client, on any thread.

Statuses: - [`ucall_status_invalid_argument_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_invalid_argument_k) An output or the configuration is missing, the connection budget is zero, or the default call budget overflows.
- [`ucall_status_unsupported_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_unsupported_k) This machine does not run the requested CPU class, or no I/O backend serves the configuration on it.
- [`ucall_status_overflow_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_overflow_k) The connection, pipelining and call budgets overflow a counter.

## ucall_client_free

Frees the client state.

```c
void ucall_client_free(ucall_client_t client);
```

Does nothing for `NULL`.

- `client` (in): Client from `ucall_client_init()`, or `NULL`.

Notes: Cancels accepted calls and discards unretrieved completions. Retrieved responses remain caller-owned and readable. Do not submit or poll concurrently with teardown.

## ucall_client_call

Submits one HTTP exchange without driving network progress.

```c
void ucall_client_call(ucall_client_call_t *arguments);
```

- `client`: The client this call operates on.
- `outcome`: Synchronous acceptance result.
- `url`: Full URL, with an explicit byte length.
- `verb`: HTTP method, like [`ucall_verb_get_k`](https://www.unum.cloud/docs/ucall/c/serving.md#ucall_verb_get_k) or [`ucall_verb_post_k`](https://www.unum.cloud/docs/ucall/c/serving.md#ucall_verb_post_k), etc.
- `headers`: Every HTTP header line, each as a counted byte view.
- `headers_count`: Number of strings in the `headers` array.
- `body`: Request body; an empty view sends no payload.
- `options`: Per-request timeouts, retries, redirects, and security.
- `context`: Caller cookie returned with the final completion.

Notes: Success guarantees exactly one record from `ucall_client_take_completed()`. Keep URL, headers, body, and security-key inputs alive until that completion is retrieved. The argument struct and acceptance outcome may be reused after submission returns. One owner submits and polls this client; calls are not internally synchronized.

Notes: Host, Content-Length, and User-Agent are generated by the client. Do not supply them in the header array. Redirects obey `[ucall_client_call_options_t::max_redirects](#ucall_client_call_options_t)`.

Statuses: - [`ucall_status_uninitialized_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_uninitialized_k) The `client` is `NULL`.
- [`ucall_status_unsupported_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_unsupported_k) The `url` names a scheme other than `http` and `http+noise`.
- [`ucall_status_invalid_argument_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_invalid_argument_k) A view, the `verb` or the security mode is invalid, the mode lacks the key or authorizer it needs, or the `url` has no scheme or a malformed authority.
- [`ucall_status_contended_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_contended_k) Every call the client admits is taken.
- [`ucall_status_overflow_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_overflow_k) The `url's` length overflows its counter.

## ucall_client_take_completed

Drives client I/O and retrieves a batch of final call results on the calling thread.

```c
void ucall_client_take_completed(
    ucall_client_take_completed_t *arguments);
```

- `client`: Client whose accepted calls to advance.
- `outcome`: Outcome of polling, independently of the completed calls' outcomes.
- `calls`: Caller-owned completion storage.
- `capacity`: Entries available in `calls`; zero advances I/O without retrieving completions.
- `count`: Output for the number of retrieved entries.
- `timeout_microseconds`: Maximum wait for completions; zero performs one bounded nonblocking progress round.

Notes: Retrieving a completion returns its admission credit. Free its response after use. Only one owner may submit or poll this client at a time.

Statuses: - [`ucall_status_uninitialized_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_uninitialized_k) The `client` is `NULL`.
- [`ucall_status_invalid_argument_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_invalid_argument_k) The `count` output is `NULL`, or `calls` is `NULL` with a nonzero `capacity`.

## ucall_client_response_status

Returns the HTTP status of a received response.

```c
ucall_http_status_t ucall_client_response_status(
    ucall_received_http_response_t response);
```

- `response` (in): Response from ucall_client_take_completed().

## ucall_client_response_header

Extracts the named string header from the received response.

```c
void ucall_client_response_header(
    ucall_client_response_header_t *arguments);
```

Header name matching is case-insensitive per RFC 7230.

- `response`: The received response from `ucall_client_take_completed()`, readable after its client is freed.
- `outcome`: The verb's status, listed on the verb.
- `name`: The name of the HTTP header to extract (case-insensitive).
- `value`: Output for a borrowed view of the header value.

Notes: __Thread-safe__ across responses, though two threads must not use one `response` at once.

Statuses: - [`ucall_status_invalid_argument_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_invalid_argument_k) The `response` or the `value` output is `NULL`, or the header name is not an HTTP token.
- [`ucall_status_not_found_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_not_found_k) The response has no such header.

## ucall_client_response_fields_count

Counts the header field lines of the received response, repeated names included.

```c
void ucall_client_response_fields_count(
    ucall_client_response_fields_count_t *arguments);
```

- `response`: The received response from `ucall_client_take_completed()`, readable after its client is freed.
- `outcome`: The verb's status, listed on the verb.
- `count`: Output for the number of header field lines, in arrival order.

Notes: __Thread-safe__ across responses, though two threads must not use one `response` at once.

Statuses: - [`ucall_status_invalid_argument_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_invalid_argument_k) The `response` or the `count` output is `NULL`.

## ucall_client_response_field

Extracts one header field line of the received response by its arrival order.

```c
void ucall_client_response_field(
    ucall_client_response_field_t *arguments);
```

- `response`: The received response from `ucall_client_take_completed()`, readable after its client is freed.
- `outcome`: The verb's status, listed on the verb.
- `index`: Which field line, below `ucall_client_response_fields_count()`.
- `name`: Output for a borrowed view of its name, lowercased as the parser keeps every field name.
- `value`: Output for a borrowed view of its value, without surrounding whitespace.

Notes: __Thread-safe__ across responses, though two threads must not use one `response` at once.

Statuses: - [`ucall_status_invalid_argument_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_invalid_argument_k) The `response`, the `name` or the `value` output is `NULL`.
- [`ucall_status_not_found_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_not_found_k) The `index` is past the last field line.

## ucall_client_response_body

Extracts the body content from the received response.

```c
void ucall_client_response_body(
    ucall_client_response_body_t *arguments);
```

- `response`: The received response from `ucall_client_take_completed()`, readable after its client is freed.
- `outcome`: The verb's status, listed on the verb.
- `body`: Output for a borrowed view of the body.

Notes: __Thread-safe__ across responses, though two threads must not use one `response` at once.

Statuses: - [`ucall_status_invalid_argument_k`](https://www.unum.cloud/docs/ucall/c/errors.md#ucall_status_invalid_argument_k) The `response` or the `body` output is `NULL`.

## ucall_client_response_free

Frees the received response handle.

```c
void ucall_client_response_free(
    ucall_received_http_response_t response);
```

Does nothing for `NULL`.

- `response` (in): The received response from `ucall_client_take_completed()`, or `NULL`.

Notes: __Thread-safe__ across responses. Two threads must not operate on the __same__ `response` concurrently.

