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
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
|
package vendor_curl
import c "core:c/libc"
CURLM :: struct {}
Mcode :: enum c.int {
CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
curl_multi_socket*() soon */
OK,
BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
BAD_EASY_HANDLE, /* an easy handle was not good/valid */
OUT_OF_MEMORY, /* if you ever get this, you are in deep sh*t */
INTERNAL_ERROR, /* this is a libcurl bug */
BAD_SOCKET, /* the passed in socket argument did not match */
UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
ADDED_ALREADY, /* an easy handle already added to a multi handle was
attempted to get added - again */
RECURSIVE_API_CALL, /* an api function was called from inside a
callback */
WAKEUP_FAILURE, /* wakeup is unavailable or failed */
BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */
ABORTED_BY_CALLBACK,
UNRECOVERABLE_POLL,
CALL_MULTI_SOCKET = CALL_MULTI_PERFORM,
}
/* bitmask bits for CURLMOPT_PIPELINING */
PIPE_NOTHING :: 0
PIPE_HTTP1 :: 1
PIPE_MULTIPLEX :: 2
MSG :: enum c.int {
NONE, /* first, not used */
DONE, /* This easy handle has completed. 'result' contains
the CURLcode of the transfer */
}
Msg :: struct {
msg: MSG, /* what this message means */
easy_handle: ^CURL, /* the handle it concerns */
data: struct #raw_union {
whatever: rawptr, /* message-specific data */
result: code, /* return code for transfer */
},
}
/* Based on poll(2) structure and values.
* We do not use pollfd and POLL* constants explicitly
* to cover platforms without poll(). */
WAIT_POLLIN :: 0x0001
WAIT_POLLPRI :: 0x0002
WAIT_POLLOUT :: 0x0004
waitfd :: struct {
fd: socket_t,
events: c.short,
revents: c.short,
}
@(default_calling_convention="c", link_prefix="curl_")
foreign lib {
/*
* Name: curl_multi_init()
*
* Desc: initialize multi-style curl usage
*
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
*/
multi_init :: proc() -> ^CURLM ---
/*
* Name: curl_multi_add_handle()
*
* Desc: add a standard curl handle to the multi stack
*
* Returns: CURLMcode type, general multi error code.
*/
multi_add_handle :: proc(multi_handle: ^CURLM, curl_handle: ^CURL) -> Mcode ---
/*
* Name: curl_multi_remove_handle()
*
* Desc: removes a curl handle from the multi stack again
*
* Returns: CURLMcode type, general multi error code.
*/
multi_remove_handle :: proc(multi_handle: ^CURLM, curl_handle: ^CURL) -> Mcode ---
/*
* Name: curl_multi_fdset()
*
* Desc: Ask curl for its fd_set sets. The app can use these to select() or
* poll() on. We want curl_multi_perform() called as soon as one of
* them are ready.
*
* Returns: CURLMcode type, general multi error code.
*/
multi_fdset :: proc(multi_handle: ^CURLM,
read_fd_set: ^platform_fd_set,
write_fd_set: ^platform_fd_set,
exc_fd_set: ^platform_fd_set,
max_fd: ^c.int) -> Mcode ---
/*
* Name: curl_multi_wait()
*
* Desc: Poll on all fds within a CURLM set as well as any
* additional fds passed to the function.
*
* Returns: CURLMcode type, general multi error code.
*/
multi_wait :: proc(multi_handle: ^CURLM,
extra_fds: [^]waitfd,
extra_nfds: c.uint,
timeout_ms: c.int,
ret: ^c.int) -> Mcode ---
/*
* Name: curl_multi_poll()
*
* Desc: Poll on all fds within a CURLM set as well as any
* additional fds passed to the function.
*
* Returns: CURLMcode type, general multi error code.
*/
multi_poll :: proc(multi_handle: ^CURLM,
extra_fds: [^]waitfd,
extra_nfds: c.uint,
timeout_ms: c.int,
ret: ^c.int) -> Mcode ---
/*
* Name: curl_multi_wakeup()
*
* Desc: wakes up a sleeping curl_multi_poll call.
*
* Returns: CURLMcode type, general multi error code.
*/
multi_wakeup :: proc(multi_handle: ^CURLM) -> Mcode ---
/*
* Name: curl_multi_perform()
*
* Desc: When the app thinks there is data available for curl it calls this
* function to read/write whatever there is right now. This returns
* as soon as the reads and writes are done. This function does not
* require that there actually is data available for reading or that
* data can be written, it can be called just in case. It returns
* the number of handles that still transfer data in the second
* argument's integer-pointer.
*
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
* returns errors etc regarding the whole multi stack. There might
* still have occurred problems on individual transfers even when
* this returns OK.
*/
multi_perform :: proc(multi_handle: ^CURLM, running_handles: ^c.int) -> Mcode ---
/*
* Name: curl_multi_cleanup()
*
* Desc: Cleans up and removes a whole multi stack. It does not free or
* touch any individual easy handles in any way. We need to define
* in what state those handles will be if this function is called
* in the middle of a transfer.
*
* Returns: CURLMcode type, general multi error code.
*/
multi_cleanup :: proc(multi_handle: ^CURLM) -> Mcode ---
/*
* Name: curl_multi_info_read()
*
* Desc: Ask the multi handle if there is any messages/informationals from
* the individual transfers. Messages include informationals such as
* error code from the transfer or just the fact that a transfer is
* completed. More details on these should be written down as well.
*
* Repeated calls to this function will return a new struct each
* time, until a special "end of msgs" struct is returned as a signal
* that there is no more to get at this point.
*
* The data the returned pointer points to will not survive calling
* curl_multi_cleanup().
*
* The 'CURLMsg' struct is meant to be simple and only contain basic
* information. If more involved information is wanted, we will
* provide the particular "transfer handle" in that struct and that
* should/could/would be used in subsequent curl_easy_getinfo() calls
* (or similar). The point being that we must never expose complex
* structs to applications, as then we will undoubtably get backwards
* compatibility problems in the future.
*
* Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
* of structs. It also writes the number of messages left in the
* queue (after this read) in the integer the second argument points
* to.
*/
multi_info_read :: proc(multi_handle: ^CURLM, msgs_in_queue: ^c.int) -> ^Msg ---
/*
* Name: curl_multi_strerror()
*
* Desc: The curl_multi_strerror function may be used to turn a CURLMcode
* value into the equivalent human readable error string. This is
* useful for printing meaningful error messages.
*
* Returns: A pointer to a null-terminated error message.
*/
multi_strerror :: proc(Mcode) -> cstring ---
}
/*
* Name: curl_multi_socket() and
* curl_multi_socket_all()
*
* Desc: An alternative version of curl_multi_perform() that allows the
* application to pass in one of the file descriptors that have been
* detected to have "action" on them and let libcurl perform.
* See manpage for details.
*/
POLL_NONE :: 0
POLL_IN :: 1
POLL_OUT :: 2
POLL_INOUT :: 3
POLL_REMOVE :: 4
SOCKET_TIMEOUT :: SOCKET_BAD
CSELECT_IN :: 0x01
CSELECT_OUT :: 0x02
CSELECT_ERR :: 0x04
socket_callback :: #type proc "c" (
easy: ^CURL, /* easy handle */
s: socket_t, /* socket */
what: c.int, /* see above */
userp: rawptr, /* private callback pointer */
socketp: rawptr,
) -> c.int /* private socket pointer */
/*
* Name: curl_multi_timer_callback
*
* Desc: Called by libcurl whenever the library detects a change in the
* maximum number of milliseconds the app is allowed to wait before
* curl_multi_socket() or curl_multi_perform() must be called
* (to allow libcurl's timed events to take place).
*
* Returns: The callback should return zero.
*/
multi_timer_callback :: #type proc "c" (multi: ^CURLM, /* multi handle */
timeout_ms: c.long, /* see above */
userp: rawptr) -> c.int /* private callback pointer */
@(default_calling_convention="c", link_prefix="curl_")
foreign lib {
multi_socket_action :: proc(multi_handle: ^CURLM,
s: socket_t,
ev_bitmask: c.int,
running_handles: ^c.int) -> Mcode ---
/*
* Name: curl_multi_timeout()
*
* Desc: Returns the maximum number of milliseconds the app is allowed to
* wait before curl_multi_socket() or curl_multi_perform() must be
* called (to allow libcurl's timed events to take place).
*
* Returns: CURLM error code.
*/
multi_timeout :: proc(multi_handle: ^CURLM, milliseconds: ^c.long) -> Mcode ---
}
Moption :: enum c.int {
/* This is the socket callback function pointer */
SOCKETFUNCTION = OPTTYPE_FUNCTIONPOINT + 1,
/* This is the argument passed to the socket callback */
SOCKETDATA = OPTTYPE_OBJECTPOINT + 2,
/* set to 1 to enable pipelining for this multi handle */
PIPELINING = OPTTYPE_LONG + 3,
/* This is the timer callback function pointer */
TIMERFUNCTION = OPTTYPE_FUNCTIONPOINT + 4,
/* This is the argument passed to the timer callback */
TIMERDATA = OPTTYPE_OBJECTPOINT + 5,
/* maximum number of entries in the connection cache */
MAXCONNECTS = OPTTYPE_LONG + 6,
/* maximum number of (pipelining) connections to one host */
MAX_HOST_CONNECTIONS = OPTTYPE_LONG + 7,
/* maximum number of requests in a pipeline */
MAX_PIPELINE_LENGTH = OPTTYPE_LONG + 8,
/* a connection with a content-length longer than this
will not be considered for pipelining */
CONTENT_LENGTH_PENALTY_SIZE = OPTTYPE_OFF_T + 9,
/* a connection with a chunk length longer than this
will not be considered for pipelining */
CHUNK_LENGTH_PENALTY_SIZE = OPTTYPE_OFF_T + 10,
/* a list of site names(+port) that are blocked from pipelining */
PIPELINING_SITE_BL = OPTTYPE_OBJECTPOINT + 11,
/* a list of server types that are blocked from pipelining */
PIPELINING_SERVER_BL = OPTTYPE_OBJECTPOINT + 12,
/* maximum number of open connections in total */
MAX_TOTAL_CONNECTIONS = OPTTYPE_LONG + 13,
/* This is the server push callback function pointer */
PUSHFUNCTION = OPTTYPE_FUNCTIONPOINT + 14,
/* This is the argument passed to the server push callback */
PUSHDATA = OPTTYPE_OBJECTPOINT + 15,
/* maximum number of concurrent streams to support on a connection */
MAX_CONCURRENT_STREAMS = OPTTYPE_LONG + 16,
/* network has changed, adjust caches/connection reuse */
NETWORK_CHANGED = OPTTYPE_LONG + 17,
/* This is the notify callback function pointer */
NOTIFYFUNCTION = OPTTYPE_FUNCTIONPOINT + 18,
/* This is the argument passed to the notify callback */
NOTIFYDATA = OPTTYPE_OBJECTPOINT + 19,
}
/* Definition of bits for the CURLMOPT_NETWORK_CHANGED argument: */
/* - CURLMNWC_CLEAR_CONNS tells libcurl to prevent further reuse of existing
connections. Connections that are idle will be closed. Ongoing transfers
will continue with the connection they have. */
MNWC_CLEAR_CONNS :: 1 << 0
/* - CURLMNWC_CLEAR_DNS tells libcurl to prevent further reuse of existing
connections. Connections that are idle will be closed. Ongoing transfers
will continue with the connection they have. */
MNWC_CLEAR_DNS :: 1 << 0
Minfo :: enum c.int {
/* first, never use this */
NONE = 0,
/* The number of easy handles currently managed by the multi handle,
* e.g. have been added but not yet removed. */
XFERS_CURRENT = 1,
/* The number of easy handles running, e.g. not done and not queueing. */
XFERS_RUNNING = 2,
/* The number of easy handles waiting to start, e.g. for a connection
* to become available due to limits on parallelism, max connections
* or other factors. */
INFO_XFERS_PENDING = 3,
/* The number of easy handles finished, waiting for their results to
* be read via `curl_multi_info_read()`. */
XFERS_DONE = 4,
/* The total number of easy handles added to the multi handle, ever. */
XFERS_ADDED = 5,
/* the last unused */
LASTENTRY,
}
@(default_calling_convention="c", link_prefix="curl_")
foreign lib {
/*
* Name: curl_multi_setopt()
*
* Desc: Sets options for the multi handle.
*
* Returns: CURLM error code.
*/
multi_setopt :: proc(multi_handle: ^CURLM, option: Moption, #c_vararg args: ..any) -> Mcode ---
/*
* Name: curl_multi_assign()
*
* Desc: This function sets an association in the multi handle between the
* given socket and a private pointer of the application. This is
* (only) useful for curl_multi_socket uses.
*
* Returns: CURLM error code.
*/
multi_assign :: proc(multi_handle: ^CURLM, sockfd: socket_t, sockp: rawptr) -> Mcode ---
/*
* Name: curl_multi_get_handles()
*
* Desc: Returns an allocated array holding all handles currently added to
* the multi handle. Marks the final entry with a NULL pointer. If
* there is no easy handle added to the multi handle, this function
* returns an array with the first entry as a NULL pointer.
*
* Returns: NULL on failure, otherwise a CURL **array pointer
*/
multi_get_handles :: proc(multi_handle: ^CURLM) -> [^]^CURL ---
/*
* Name: curl_multi_get_offt()
*
* Desc: Retrieves a numeric value for the `CURLMINFO_*` enums.
*
* Returns: CULRM_OK or error when value could not be obtained.
*/
multi_get_offt :: proc(multi_handle: ^CURLM, info: Minfo, value: ^off_t) -> Mcode ---
}
/*
* Notifications dispatched by a multi handle, when enabled.
*/
MULTI_NOTIFY :: enum c.uint {
INFO_READ = 0,
EASY_DONE = 1,
}
/*
* Callback to install via CURLMOPT_NOTIFYFUNCTION.
*/
curl_notify_function :: #type proc "c" (multi_handle: ^CURLM, notification: MULTI_NOTIFY, easy: ^CURL, user_data: rawptr)
@(default_calling_convention="c", link_prefix="curl_")
foreign lib {
multi_notify_disable :: proc(multi: ^CURLM, notification: MULTI_NOTIFY) -> Mcode ---
multi_notify_enable :: proc(multi: ^CURLM, notification: MULTI_NOTIFY) -> Mcode ---
}
/*
* Name: curl_push_callback
*
* Desc: This callback gets called when a new stream is being pushed by the
* server. It approves or denies the new stream. It can also decide
* to completely fail the connection.
*
* Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT
*/
PUSH_OK :: 0
PUSH_DENY :: 1
PUSH_ERROROUT :: 2 /* added in 7.72.0 */
pushheaders :: struct {}
push_callback :: #type proc "c"(parent: ^CURL,
easy: ^CURL,
num_headers: c.size_t,
headers: [^]pushheaders,
userp: rawptr) -> c.int
@(default_calling_convention="c", link_prefix="curl_")
foreign lib {
pushheader_bynum :: proc(h: ^pushheaders, num: c.size_t) -> cstring ---
pushheader_byname :: proc(h: ^pushheaders, name: cstring) -> cstring ---
/*
* Name: curl_multi_waitfds()
*
* Desc: Ask curl for fds for polling. The app can use these to poll on.
* We want curl_multi_perform() called as soon as one of them are
* ready. Passing zero size allows to get just a number of fds.
*
* Returns: CURLMcode type, general multi error code.
*/
multi_waitfds :: proc(multi: ^CURLM,
ufds: [^]waitfd,
size: c.uint,
fd_count: ^c.uint) -> Mcode ---
}
|