aboutsummaryrefslogtreecommitdiff
path: root/crates/arti-rpc-client-core/cbindgen.toml
blob: 48f2546af4c02c93334b8f0e807a0789d8cba64d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# We emit a C header by default.
language = "C"

# We use this macro to prevent double-includes of our header.
include_guard = "ARTI_RPC_CLIENT_CORE_H_"

# This appears at the top of the file.
header = """\
/**
 * # Arti RPC core library header.
 *
 * ## Implementation status
 *
 * Note: As of Jan 2025, this library, and the Arti RPC system,
 * are still under active development.
 * We believe that they are ready to try out, but it is likely
 * that they still have bugs and design flaws that we'll need to fix.
 * Please be ready to report issues at
 * <https://gitlab.torproject.org/tpo/core/arti>.
 *
 * We will make an effort to keep API compatibility over time,
 * but it's possible that we'll need to break things in small ways.
 * If we do, we will note them in our changelog and our announcements.
 *
 * For now, the Arti RPC interface itself provides only limited
 * functionality.  We will add support for more features over time.
 *
 * ## Who should use this library
 *
 * You should use this library if you want to write a program that controls Arti
 * via its RPC interface, and you don't want to write an implementation of the RPC
 * protocol from scratch.
 *
 * ## What this library does
 *
 * The Arti RPC system works by establishing connections to an Arti instance,
 * and then exchanging requests and replies in a format inspired by
 * JSON-RPC.  This library takes care of the work of connecting to an Arti
 * instance, authenticating, validating outgoing JSON requests, and matching
 * their corresponding JSON responses as they arrive.
 *
 * This library _does not_ do the work of creating well-formed requests,
 * or interpreting the responses.
 *
 * Despite this library being exposed via a set of C functions,
 * we don't actually expect you to use it from C.  It's probably a better
 * idea to wrap it in a higher-level language and then use it from there.
 *
 * The `arti_rpc` python package (available from the Arti git repository)
 * is one example of such a wrapper.
 *
 * ## Using this library
 *
 * ### Making a connection to Arti
 *
 * First, you will need to have Arti running, and configured to use
 * rpc.  This will eventually be the default behavior, but for now,
 * make sure that arti was built using the `rpc` cargo feature, and that
 * the configuration option `rpc.enable` is set to true.
 *
 * (For more detailed instructions on how to do this,
 * and for examples code,
 * see the Arti RPC book.)
 * (TODO Add link once there is one.)
 *
 * Your connection to Arti is represented by an `ArtiRpcConn *`.
 * To get one:
 * - Call `arti_rpc_conn_builder_new()` to make an `ArtiRpcConnBuilder`.
 * - Configure the `ArtiRpcConnBuilder` as needed,
 *   to tell it where to find Arti.
 *   (If you configured Arti as described above,
 *   and you're running as the same user,
 *   then no additional configuration should be necessary.)
 * - Call `arti_rpc_conn_builder_connect()` to try to connect to Arti.
 *
 * <!-- TODO: We'll want to have documentation about connect points,
 *  but it won't go here. -->
 *
 * Once you have a connection, you can sent Arti various requests in
 * JSON format.  These requests have documentation of their own;
 * We'll add a link to it once we've figured out where to host it.
 *
 * Use `arti_rpc_execute()` to send a simple request; the function will
 * return when the request succeeds, or fails.
 *
 * Except when noted otherwise, all functions in this library are thread-safe.
 *
 * ## Error handling
 *
 * On success, fallible functions return `ARTI_RPC_STATUS_SUCCESS`.  On failure,
 * they return some other error code, and set an `* error_out` parameter
 * to a newly allocated `ArtiRpcError` object.
 * (If `error_out==NULL`, then no error is allocated.)
 *
 * You can access information about the an `ArtiRpcError`
 * by calling `arti_rpc_err_{status,message,response}()` on it.
 * When you are done with an error, you should free it with
 * `arti_rpc_err_free()`.
 *
 * The `error_out` parameter always appears last.
 *
 * ## Interface conventions
 *
 * - All functions check for NULL pointers in their arguments.
 *   - As in C tor, `foo_free()` functions treat `foo_free(NULL)` as a no-op.
 *
 * - All input strings should be valid UTF-8.  (The library will check.)
 *   All output strings will be valid UTF-8.
 *
 * - Fallible functions return an ArtiStatus.
 *
 * - All identifiers are prefixed with `ARTI_RPC`, `ArtiRpc`, or `arti_rpc` as appropriate.
 *
 * - Newly allocated objects are returned via out-parameters,
 *   with `out` in their names.
 *   (For example, `ArtiRpcObject **out`).  In such cases, `* out` will be set to a resulting object,
 *   or to NULL if no such object is returned.   Any earlier value of `*out` will be replaced
 *   without freeing it.
 *   (If `out` is NULL, then any object the library would have returned will instead be discarded.)
 *   discarded.
 *   While the function is running,
 *   `*out` and `**out` may not be read or written by any other part of the program,
 *   and they may not alias any other arguments.)
 *   - Note that `*out` will be set to NULL if an error occurs
 *     or the function's inputs are invalid.
 *     (The `*error_out` parameter, of course,
 *     is set to NULL when there is _no_ error, and to an error otherwise.)
 *
 * - When any object is exposed as a non-const pointer,
 *   the application becomes the owner of that object.
 *   The application is expected to eventually free that object via the corresponding `arti_rpc_*_free()` function.
 *
 * - When any object is exposed via a const pointer,
 *   that object is *not* owned by the application.
 *   That object's lifetime will be as documented.
 *   The application must not modify or free such an object.
 *
 * - If a function should be considered a method on a given type of object,
 *   it will take a pointer to that object as its first argument.
 *
 * - If a function consumes (takes ownership of) one of its inputs,
 *   it does so regardless of whether the function succeeds or fails.
 *
 * - Whenever one or more functions take an argument via a `const Type *`,
 *   it is safe to pass the same object to multiple functions at once.
 *   (This does not apply to functions that take an argument via a
 *   non-const pointer.)
 *
 * - Whenever a function returns an error, it returns no other newly allocated objects
 *   besides the error object itself.
 *
 * ## Correctness requirements
 *
 * If any correctness requirements stated here or elsewhere are violated,
 * it is Undefined Behaviour.
 * Violations will not be detected by the library.
 *
 * - Basic C rules apply:
 *     - If you pass a non-NULL pointer to a function, the pointer must be properly aligned.
 *       It must point to valid, initialized data of the correct type.
 *       - As an exception, functions that take a `Type **out` parameter allow the value of `*out`
 *         (but not `out` itself!) to be uninitialized.
 *     - If you receive data via a `const *`, you must not modify that data.
 *     - If you receive a pointer of type `struct Type *`,
 *       and we do not give you the definition of `struct Type`,
 *       you must not attempt to dereference the pointer.
 *     - You may not call any `_free()` function on an object that is currently in use.
 *     - After you have `_freed()` an object, you may not use it again.
 * - Every object allocated by this library has a corresponding `*_free()` function:
 *   You must not use libc's free() to free such objects.
 * - All objects passed as input to a library function must not be mutated
 *   while that function is running.
 * - All objects passed as input to a library function via a non-const pointer
 *   must not be mutated, inspected, or passed to another library function
 *   while the function is running.
 *   - Furthermore, if a function takes any non-const pointer arguments,
 *     those arguments must not alias one another,
 *     and must not alias any const arguments passed to the function.
 * - All `const char*` passed as inputs to library functions
 *   are nul-terminated strings.
 *   Additionally, they must be no larger than `SSIZE_MAX`,
     including the nul.
 * - If a function takes any mutable pointers
 **/"""

# This appears "between major sections"
autogen_warning = "/* Automatically generated by cbindgen. Don't modify manually. */"

# make sure our header can be included in C++.
cpp_compat = true

# Consistency with Arti.
tab_width = 8

after_includes = """\
/**
 * Type of a socket returned by RPC functions.
 *
 * This a `SOCKET` on Windows, and an fd elsewhere.
 **/
#ifdef _WIN32
typedef SOCKET ArtiRpcRawSocket;
#else
typedef int ArtiRpcRawSocket;
#endif
"""

[defines]
# This is where we would add mappings from `cfg()` to `#ifdef`.
# But the only relevant cfg we have is `cfg(feature="ffi")`,
# which we want to assume is always present if you're using the header.


[export]
# These structs are not ones we want to expose under their actual names,
# or ones that we don't want to expose at all.
exclude = ["FfiError", "RequestHandle", "RpcConnBuilder", "RpcConn", "RpcErrorCode", "Utf8CString", "ArtiRpcRawSocket"]

[export.rename]
# Having not declared these structs, we can give them new names in the
# typedefs that assign them their real names.
"RpcConn" = "struct ArtiRpcConn"
"FfiError" = "struct ArtiRpcError"
"Utf8CString" = "struct ArtiRpcStr"
"RequestHandle" = "struct ArtiRpcHandle"

[fn]
# Lay out one argument per line.
args = "vertical"

[parse]

[parse.expand]
# We need to run our crate through macro expansion in order to get all
# of the right functions and constants.
#
# (Unfortunately, this requires us to use nightly rust, so that cbindgen
# can invoke rustc with `-Zunpretty=expanded`.)
crates = ["arti-rpc-client-core"]

# Run macro-expansion with --all-features so that we see `ffi`.
all_features = true