1# zx_channel_call
2
3## NAME
4
5<!-- Updated by update-docs-from-abigen, do not edit. -->
6
7channel_call - send a message to a channel and await a reply
8
9## SYNOPSIS
10
11<!-- Updated by update-docs-from-abigen, do not edit. -->
12
13```
14#include <zircon/syscalls.h>
15
16zx_status_t zx_channel_call(zx_handle_t handle,
17                            uint32_t options,
18                            zx_time_t deadline,
19                            const zx_channel_call_args_t* args,
20                            uint32_t* actual_bytes,
21                            uint32_t* actual_handles);
22```
23
24## DESCRIPTION
25
26`zx_channel_call()` is like a combined [`zx_channel_write()`], [`zx_object_wait_one()`],
27and [`zx_channel_read()`], with the addition of a feature where a transaction id at
28the front of the message payload *bytes* is used to match reply messages with send
29messages, enabling multiple calling threads to share a channel without any additional
30userspace bookkeeping.
31
32The write and read phases of this operation behave like [`zx_channel_write()`] and
33[`zx_channel_read()`] with the difference that their parameters are provided via the
34`zx_channel_call_args_t` structure.
35
36The first four bytes of the written and read back messages are treated as a
37transaction ID of type `zx_txid_t`.  The kernel generates a txid for the
38written message, replacing that part of the message as read from userspace.
39The kernel generated txid will be between 0x80000000 and 0xFFFFFFFF, and will
40not collide with any txid from any other `zx_channel_call()` in progress against
41this channel endpoint.  If the written message has a length of fewer than four
42bytes, an error is reported.
43
44When the outbound message is written, simultaneously an interest is registered
45for inbound messages of the matching txid.
46
47While *deadline* has not passed, if an inbound message arrives with a matching txid,
48instead of being added to the tail of the general inbound message queue, it is delivered
49directly to the thread waiting in `zx_channel_call()`.
50
51If such a reply arrives after *deadline* has passed, it will arrive in the general
52inbound message queue, cause **ZX_CHANNEL_READABLE** to be signaled, etc.
53
54Inbound messages that are too large to fit in *rd_num_bytes* and *rd_num_handles*
55are discarded and **ZX_ERR_BUFFER_TOO_SMALL** is returned in that case.
56
57As with [`zx_channel_write()`], the handles in *handles* are always consumed by
58`zx_channel_call()` and no longer exist in the calling process.
59
60## RIGHTS
61
62<!-- Updated by update-docs-from-abigen, do not edit. -->
63
64*handle* must be of type **ZX_OBJ_TYPE_CHANNEL** and have **ZX_RIGHT_READ** and have **ZX_RIGHT_WRITE**.
65
66All wr_handles of *args* must have **ZX_RIGHT_TRANSFER**.
67
68## RETURN VALUE
69
70`zx_channel_call()` returns **ZX_OK** on success and the number of bytes and
71count of handles in the reply message are returned via *actual_bytes* and
72*actual_handles*, respectively.
73
74## ERRORS
75
76**ZX_ERR_BAD_HANDLE**  *handle* is not a valid handle, any element in
77*handles* is not a valid handle, or there are duplicates among the handles
78in the *handles* array.
79
80**ZX_ERR_WRONG_TYPE**  *handle* is not a channel handle.
81
82**ZX_ERR_INVALID_ARGS**  any of the provided pointers are invalid or null,
83or *wr_num_bytes* is less than four, or *options* is nonzero.
84
85**ZX_ERR_ACCESS_DENIED**  *handle* does not have **ZX_RIGHT_WRITE** or
86any element in *handles* does not have **ZX_RIGHT_TRANSFER**.
87
88**ZX_ERR_PEER_CLOSED**  The other side of the channel was closed or became
89closed while waiting for the reply.
90
91**ZX_ERR_CANCELED**  *handle* was closed while waiting for a reply.
92
93**ZX_ERR_NO_MEMORY**  Failure due to lack of memory.
94There is no good way for userspace to handle this (unlikely) error.
95In a future build this error will no longer occur.
96
97**ZX_ERR_OUT_OF_RANGE**  *wr_num_bytes* or *wr_num_handles* are larger than the
98largest allowable size for channel messages.
99
100**ZX_ERR_BUFFER_TOO_SMALL**  *rd_num_bytes* or *rd_num_handles* are too small
101to contain the reply message.
102
103**ZX_ERR_NOT_SUPPORTED**  one of the handles in *handles* was *handle*
104(the handle to the channel being written to).
105
106## NOTES
107
108The facilities provided by `zx_channel_call()` can interoperate with message dispatchers
109using [`zx_channel_read()`] and [`zx_channel_write()`] directly, provided the following rules
110are observed:
111
1121. A server receiving synchronous messages via [`zx_channel_read()`] should ensure that the
113txid of incoming messages is reflected back in outgoing responses via [`zx_channel_write()`]
114so that clients using `zx_channel_call()` can correctly route the replies.
115
1162. A client sending messages via [`zx_channel_write()`] that will be replied to should ensure
117that it uses txids between 0 and 0x7FFFFFFF only, to avoid colliding with other threads
118communicating via `zx_channel_call()`.
119
120If a `zx_channel_call()` returns due to **ZX_ERR_TIMED_OUT**, if the server eventually replies,
121at some point in the future, the reply *could* match another outbound request (provided about
1222^31 `zx_channel_call()`s have happened since the original request.  This syscall is designed
123around the expectation that timeouts are generally fatal and clients do not expect to continue
124communications on a channel that is timing out.
125
126## SEE ALSO
127
128 - [`zx_channel_create()`]
129 - [`zx_channel_read()`]
130 - [`zx_channel_write()`]
131 - [`zx_handle_close()`]
132 - [`zx_handle_duplicate()`]
133 - [`zx_handle_replace()`]
134 - [`zx_object_wait_async()`]
135 - [`zx_object_wait_many()`]
136 - [`zx_object_wait_one()`]
137
138<!-- References updated by update-docs-from-abigen, do not edit. -->
139
140[`zx_channel_create()`]: channel_create.md
141[`zx_channel_read()`]: channel_read.md
142[`zx_channel_write()`]: channel_write.md
143[`zx_handle_close()`]: handle_close.md
144[`zx_handle_duplicate()`]: handle_duplicate.md
145[`zx_handle_replace()`]: handle_replace.md
146[`zx_object_wait_async()`]: object_wait_async.md
147[`zx_object_wait_many()`]: object_wait_many.md
148[`zx_object_wait_one()`]: object_wait_one.md
149