iodine 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/ext/iodine/fio-stl.h +861 -250
- data/ext/iodine/fio-stl.md +150 -195
- data/ext/iodine/iodine_utils.h +1 -1
- data/lib/iodine/version.rb +1 -1
- metadata +2 -2
data/ext/iodine/fio-stl.md
CHANGED
|
@@ -17878,39 +17878,17 @@ int main(void) {
|
|
|
17878
17878
|
#include FIO_INCLUDE_FILE
|
|
17879
17879
|
```
|
|
17880
17880
|
|
|
17881
|
-
IPC is the messaging backbone of the facil.io worker/master model. Workers
|
|
17882
|
-
fork from a master process. The master keeps listeners, manages state, and
|
|
17883
|
-
handles anything that needs a single authoritative view of the world. Workers
|
|
17884
|
-
handle client connections. IPC bridges the two: a worker sends a message to
|
|
17885
|
-
the master (or to every process in the cluster), the master executes it and
|
|
17886
|
-
optionally streams replies back.
|
|
17881
|
+
IPC is the messaging backbone of the facil.io worker/master model. Workers fork from a master process. The master keeps listeners, manages state, and handles anything that needs a single authoritative view of the world. Workers handle client connections. IPC bridges the two: a worker sends a message to the master (or to every process in the cluster), the master executes it and optionally streams replies back.
|
|
17887
17882
|
|
|
17888
|
-
|
|
17889
|
-
the process secret. Local IPC runs over a Unix socket (or auto-generated TCP
|
|
17890
|
-
socket). Multi-machine RPC extends the same protocol over TCP with optional
|
|
17891
|
-
UDP peer discovery.
|
|
17883
|
+
IPC supports local messages and, when configured with a shared secret, messages between cluster peers. Register op-codes for messages sent between machines; do not send function pointers across machines.
|
|
17892
17884
|
|
|
17893
|
-
See [./400 io-overview.md](./400 io-overview.md) for where IPC sits in the
|
|
17894
|
-
full IO stack.
|
|
17885
|
+
See [./400 io-overview.md](./400 io-overview.md) for where IPC sits in the full IO stack.
|
|
17895
17886
|
|
|
17896
17887
|
---
|
|
17897
17888
|
|
|
17898
17889
|
## Worker/Master Model
|
|
17899
17890
|
|
|
17900
|
-
|
|
17901
|
-
master process
|
|
17902
|
-
├── owns IPC listener socket
|
|
17903
|
-
├── executes messages sent by workers
|
|
17904
|
-
├── forwards cluster/broadcast messages to other machines
|
|
17905
|
-
└── worker process × N
|
|
17906
|
-
├── each has its own IO reactor loop
|
|
17907
|
-
├── connects back to master via IPC socket on startup
|
|
17908
|
-
└── sends fio_ipc_* messages to reach master or peers
|
|
17909
|
-
```
|
|
17910
|
-
|
|
17911
|
-
The master is always the hub. Workers can only talk *through* the master —
|
|
17912
|
-
there is no direct worker-to-worker channel. On shutdown the master sends a
|
|
17913
|
-
local broadcast instructing all workers to stop.
|
|
17891
|
+
Workers send local messages through the master. Use `fio_ipc_call` to reach the master, or `fio_ipc_local` to reach the master and local workers. For cluster peers, use `fio_ipc_cluster` or `fio_ipc_broadcast`.
|
|
17914
17892
|
|
|
17915
17893
|
---
|
|
17916
17894
|
|
|
@@ -17931,28 +17909,24 @@ Define before including the header to override defaults.
|
|
|
17931
17909
|
|
|
17932
17910
|
```c
|
|
17933
17911
|
typedef struct fio_ipc_s {
|
|
17934
|
-
fio_io_s *from;
|
|
17935
|
-
/*
|
|
17936
|
-
|
|
17937
|
-
uint16_t
|
|
17938
|
-
|
|
17939
|
-
uint64_t
|
|
17940
|
-
uint64_t id; /* random 64-bit value — part of nonce (unencrypted) */
|
|
17912
|
+
fio_io_s *from; /* originating IO on receipt */
|
|
17913
|
+
uint32_t len; /* payload length */
|
|
17914
|
+
uint16_t flags; /* application flags */
|
|
17915
|
+
uint16_t routing_flags; /* routing state; do not edit directly */
|
|
17916
|
+
uint64_t timestamp; /* message timestamp */
|
|
17917
|
+
uint64_t id; /* message ID */
|
|
17941
17918
|
union {
|
|
17942
|
-
void (*call)(struct fio_ipc_s *); /*
|
|
17943
|
-
uint32_t opcode; /* registered
|
|
17919
|
+
void (*call)(struct fio_ipc_s *); /* local handler */
|
|
17920
|
+
uint32_t opcode; /* registered handler ID */
|
|
17944
17921
|
};
|
|
17945
|
-
void (*on_reply)(struct fio_ipc_s *); /*
|
|
17946
|
-
void (*on_done)(struct fio_ipc_s *); /*
|
|
17947
|
-
void *udata;
|
|
17948
|
-
char data[];
|
|
17922
|
+
void (*on_reply)(struct fio_ipc_s *); /* reply handler */
|
|
17923
|
+
void (*on_done)(struct fio_ipc_s *); /* final reply handler */
|
|
17924
|
+
void *udata; /* caller context */
|
|
17925
|
+
char data[]; /* payload; read only len bytes */
|
|
17949
17926
|
} fio_ipc_s;
|
|
17950
17927
|
```
|
|
17951
17928
|
|
|
17952
|
-
Messages are reference-counted.
|
|
17953
|
-
payload) is encrypted on the wire. `from`, `timestamp`, and `id` are unencrypted
|
|
17954
|
-
and unauthenticated (they form the nonce). `len`, `flags`, and `routing_flags`
|
|
17955
|
-
are unencrypted but authenticated via AEAD.
|
|
17929
|
+
Messages are reference-counted. In callbacks, `data` contains `len` payload bytes; do not assume it is null-terminated. Treat routing state as read-only.
|
|
17956
17930
|
|
|
17957
17931
|
### `fio_ipc_args_s` — construction arguments
|
|
17958
17932
|
|
|
@@ -18008,8 +17982,7 @@ typedef struct {
|
|
|
18008
17982
|
(fio_buf_info_s[]){ __VA_ARGS__, { .len = ((size_t)-1) } }
|
|
18009
17983
|
```
|
|
18010
17984
|
|
|
18011
|
-
Composes multiple buffers into a single message without intermediate
|
|
18012
|
-
allocation. Iteration stops at the first entry with `len == (size_t)-1`.
|
|
17985
|
+
Composes multiple buffers into a single message without intermediate allocation. Iteration stops at the first entry with `len == (size_t)-1`.
|
|
18013
17986
|
|
|
18014
17987
|
```c
|
|
18015
17988
|
uint32_t seq = 42;
|
|
@@ -18026,8 +17999,7 @@ fio_ipc_call(.call = my_handler,
|
|
|
18026
17999
|
|
|
18027
18000
|
## Delivery Macros
|
|
18028
18001
|
|
|
18029
|
-
All four macros call `fio_ipc_new(...)` then `fio_ipc_send(...)`. They accept
|
|
18030
|
-
named fields from `fio_ipc_args_s`.
|
|
18002
|
+
All four macros call `fio_ipc_new(...)` then `fio_ipc_send(...)`. They accept named fields from `fio_ipc_args_s`.
|
|
18031
18003
|
|
|
18032
18004
|
| Macro | Delivered to |
|
|
18033
18005
|
|-------|-------------|
|
|
@@ -18047,11 +18019,9 @@ named fields from `fio_ipc_args_s`.
|
|
|
18047
18019
|
#define fio_ipc_broadcast(...) fio_ipc_send(fio_ipc_new(.workers = 1, .cluster = 1, __VA_ARGS__))
|
|
18048
18020
|
```
|
|
18049
18021
|
|
|
18050
|
-
`fio_ipc_cluster` and `fio_ipc_broadcast` require an `opcode` (not a function
|
|
18051
|
-
pointer) because function pointers are meaningless across machine boundaries.
|
|
18022
|
+
`fio_ipc_cluster` and `fio_ipc_broadcast` require an `opcode` (not a function pointer) because function pointers are meaningless across machine boundaries.
|
|
18052
18023
|
|
|
18053
|
-
Use `.exclude = FIO_IPC_EXCLUDE_SELF` to skip the calling process when
|
|
18054
|
-
broadcasting locally.
|
|
18024
|
+
Use `.exclude = FIO_IPC_EXCLUDE_SELF` to skip the calling process when broadcasting locally.
|
|
18055
18025
|
|
|
18056
18026
|
**`FIO_IPC_EXCLUDE_SELF`**
|
|
18057
18027
|
|
|
@@ -18059,8 +18029,7 @@ broadcasting locally.
|
|
|
18059
18029
|
#define FIO_IPC_EXCLUDE_SELF ((fio_io_s *)((char *)-1LL))
|
|
18060
18030
|
```
|
|
18061
18031
|
|
|
18062
|
-
Pass as `.exclude` in `fio_ipc_args_s`, or set `ipc->from = FIO_IPC_EXCLUDE_SELF`
|
|
18063
|
-
before calling `fio_ipc_send`.
|
|
18032
|
+
Pass as `.exclude` in `fio_ipc_args_s`, or set `ipc->from = FIO_IPC_EXCLUDE_SELF` before calling `fio_ipc_send`.
|
|
18064
18033
|
|
|
18065
18034
|
---
|
|
18066
18035
|
|
|
@@ -18130,9 +18099,7 @@ SFUNC void fio_ipc_reply(fio_ipc_reply_args_s args);
|
|
|
18130
18099
|
fio_ipc_reply((fio_ipc_reply_args_s){ .ipc = (r), __VA_ARGS__ })
|
|
18131
18100
|
```
|
|
18132
18101
|
|
|
18133
|
-
Send one or more replies from the master back to the caller. Set `.done = 1`
|
|
18134
|
-
on the final reply to trigger the caller's `on_done` callback. Replies inherit
|
|
18135
|
-
`call`, `on_reply`, `on_done`, and `udata` from the original request.
|
|
18102
|
+
Send one or more replies from the master back to the caller. Set `.done = 1` on the final reply to trigger the caller's `on_done` callback. Replies inherit `call`, `on_reply`, `on_done`, and `udata` from the original request.
|
|
18136
18103
|
|
|
18137
18104
|
Streaming replies:
|
|
18138
18105
|
|
|
@@ -18152,8 +18119,7 @@ void stream_handler(fio_ipc_s *msg) {
|
|
|
18152
18119
|
|
|
18153
18120
|
## Op-Code Registration
|
|
18154
18121
|
|
|
18155
|
-
Op-codes
|
|
18156
|
-
pointers (which differ per binary). Register before `fio_io_start`.
|
|
18122
|
+
Op-codes select handlers for cluster messages. Register them before `fio_io_start` on every participating process.
|
|
18157
18123
|
|
|
18158
18124
|
```c
|
|
18159
18125
|
SFUNC int fio_ipc_opcode_register(fio_ipc_opcode_s opcode);
|
|
@@ -18166,7 +18132,7 @@ SFUNC const fio_ipc_opcode_s *fio_ipc_opcode(uint32_t opcode);
|
|
|
18166
18132
|
```
|
|
18167
18133
|
|
|
18168
18134
|
- Op-codes must be non-zero `uint32_t` values.
|
|
18169
|
-
- Values `>= 0xFF000000` are reserved
|
|
18135
|
+
- Values `>= 0xFF000000` are reserved; choose a lower value.
|
|
18170
18136
|
- Pass `call = NULL` to unregister.
|
|
18171
18137
|
- Must be called before `fio_io_start()` (not thread-safe after that).
|
|
18172
18138
|
- Returns 0 on success, -1 on error.
|
|
@@ -18185,8 +18151,7 @@ fio_ipc_opcode_register(.opcode = OP_SYNC, .call = NULL);
|
|
|
18185
18151
|
|
|
18186
18152
|
## IPC URL
|
|
18187
18153
|
|
|
18188
|
-
The IPC
|
|
18189
|
-
in `$TMPDIR`). Override before `fio_io_start` on the master:
|
|
18154
|
+
The IPC URL is generated at startup. The master can override it before `fio_io_start`:
|
|
18190
18155
|
|
|
18191
18156
|
```c
|
|
18192
18157
|
/** Returns current IPC socket URL. */
|
|
@@ -18225,14 +18190,59 @@ SFUNC void fio_ipc_cluster_connect(const char *url);
|
|
|
18225
18190
|
SFUNC uint16_t fio_ipc_cluster_port(void);
|
|
18226
18191
|
```
|
|
18227
18192
|
|
|
18228
|
-
|
|
18229
|
-
|
|
18230
|
-
|
|
18231
|
-
|
|
18232
|
-
|
|
18193
|
+
### Cluster Peer Connection Callbacks
|
|
18194
|
+
|
|
18195
|
+
#### `FIO_IPC_CLUSTER_PEER_MAX_SUBSCRIBERS`
|
|
18196
|
+
|
|
18197
|
+
```c
|
|
18198
|
+
#define FIO_IPC_CLUSTER_PEER_MAX_SUBSCRIBERS 32
|
|
18199
|
+
```
|
|
18200
|
+
|
|
18201
|
+
At most 32 peer lifecycle callbacks can be registered per process. Further registrations return `-1`.
|
|
18202
|
+
|
|
18203
|
+
#### `fio_ipc_cluster_on_peer_s` and `fio_ipc_cluster_on_peer`
|
|
18204
|
+
|
|
18205
|
+
```c
|
|
18206
|
+
typedef struct fio_ipc_cluster_on_peer_s {
|
|
18207
|
+
void (*on_attached)(fio_ipc_s *event); /* optional */
|
|
18208
|
+
void (*on_detached)(fio_ipc_s *event); /* optional */
|
|
18209
|
+
void *udata; /* callback context; borrowed */
|
|
18210
|
+
} fio_ipc_cluster_on_peer_s;
|
|
18211
|
+
|
|
18212
|
+
SFUNC int fio_ipc_cluster_on_peer(fio_ipc_cluster_on_peer_s args);
|
|
18213
|
+
#define fio_ipc_cluster_on_peer(...) \
|
|
18214
|
+
fio_ipc_cluster_on_peer((fio_ipc_cluster_on_peer_s){__VA_ARGS__})
|
|
18215
|
+
```
|
|
18216
|
+
|
|
18217
|
+
Call on the master before `fio_io_start`. Each call adds a subscriber; at least one callback is required. `udata` may be NULL and remains caller-owned. Keep it valid while callbacks can run. Returns `0` on success, or `-1` for invalid callbacks, a worker, running IO, or full capacity. Registration is not thread-safe. There is no unsubscribe API.
|
|
18218
|
+
|
|
18219
|
+
Callbacks borrow a `fio_ipc_s` event whose `data` contains the peer UUID (`event->len == 16`). During `on_attached`, `event->from` identifies the connected peer. During `on_detached`, it is `NULL`. To retain an event beyond the callback, use `fio_ipc_dup` and later `fio_ipc_free`.
|
|
18220
|
+
|
|
18221
|
+
**Note:** To send to an attached peer, create a new opcode message and pass it with `event->from` to `fio_ipc_send_to` during the callback. The send takes ownership of the new message. Do not send or reply to the event itself. Keeping an attached event beyond the callback may delay its detach notification.
|
|
18222
|
+
|
|
18223
|
+
```c
|
|
18224
|
+
#define PEER_HELLO_OP 42
|
|
18225
|
+
static void peer_hello(fio_ipc_s *message) { (void)message; }
|
|
18226
|
+
static void peer_attached(fio_ipc_s *event) {
|
|
18227
|
+
fio_ipc_s *message = fio_ipc_new(
|
|
18228
|
+
.cluster = 1, .opcode = PEER_HELLO_OP,
|
|
18229
|
+
.data = FIO_IPC_DATA(FIO_BUF_INFO1((char *)"hello")));
|
|
18230
|
+
if (message)
|
|
18231
|
+
fio_ipc_send_to(event->from, message);
|
|
18232
|
+
}
|
|
18233
|
+
static void peer_detached(fio_ipc_s *event) { (void)event; }
|
|
18234
|
+
/* On each peer before fio_io_start (illustrative setup statements): */
|
|
18235
|
+
if (fio_ipc_opcode_register(.opcode = PEER_HELLO_OP, .call = peer_hello) ||
|
|
18236
|
+
fio_ipc_cluster_on_peer(.on_attached = peer_attached,
|
|
18237
|
+
.on_detached = peer_detached)) {
|
|
18238
|
+
/* handle registration failure before starting IO */
|
|
18239
|
+
}
|
|
18240
|
+
```
|
|
18241
|
+
|
|
18242
|
+
- Call `fio_ipc_cluster_listen` from the master before or after `fio_io_start` to accept and discover peers.
|
|
18243
|
+
- Set the same `SECRET` environment variable on all instances. Cluster encryption does not provide forward secrecy; rotate the secret by restarting instances.
|
|
18233
18244
|
- All instances receive all `cluster` / `broadcast` messages.
|
|
18234
|
-
- `fio_ipc_cluster_connect` lets you manually reach peers on other subnets
|
|
18235
|
-
where UDP broadcast doesn't reach.
|
|
18245
|
+
- `fio_ipc_cluster_connect` lets you manually reach peers on other subnets where UDP broadcast doesn't reach.
|
|
18236
18246
|
|
|
18237
18247
|
```c
|
|
18238
18248
|
/* Typical setup */
|
|
@@ -18245,19 +18255,17 @@ fio_io_start(4);
|
|
|
18245
18255
|
|
|
18246
18256
|
## Core Lifetime API
|
|
18247
18257
|
|
|
18248
|
-
|
|
18249
|
-
advanced use (e.g., constructing messages for local execution, or async
|
|
18250
|
-
message handling).
|
|
18258
|
+
Use these functions to construct, send, and retain messages when the delivery macros do not fit your use case.
|
|
18251
18259
|
|
|
18252
18260
|
```c
|
|
18253
18261
|
/** Create a message without sending it. */
|
|
18254
18262
|
SFUNC fio_ipc_s *fio_ipc_new(fio_ipc_args_s args);
|
|
18255
18263
|
#define fio_ipc_new(...) fio_ipc_new((fio_ipc_args_s){ __VA_ARGS__ })
|
|
18256
18264
|
|
|
18257
|
-
/**
|
|
18265
|
+
/** Send the message according to its delivery options. Takes ownership. */
|
|
18258
18266
|
SFUNC void fio_ipc_send(fio_ipc_s *ipc);
|
|
18259
18267
|
|
|
18260
|
-
/**
|
|
18268
|
+
/** Send directly to a specific IO. Takes ownership. */
|
|
18261
18269
|
SFUNC void fio_ipc_send_to(fio_io_s *to, fio_ipc_s *ipc);
|
|
18262
18270
|
|
|
18263
18271
|
/** Increment reference count. */
|
|
@@ -18293,29 +18301,20 @@ void async_done(fio_ipc_s *msg) {
|
|
|
18293
18301
|
|
|
18294
18302
|
---
|
|
18295
18303
|
|
|
18296
|
-
##
|
|
18304
|
+
## Message encryption (advanced)
|
|
18297
18305
|
|
|
18298
18306
|
```c
|
|
18299
|
-
/** Encrypt a message in-place (idempotent). Called automatically by fio_ipc_send. */
|
|
18300
18307
|
SFUNC void fio_ipc_encrypt(fio_ipc_s *m);
|
|
18301
|
-
|
|
18302
|
-
/** Decrypt a message in-place. Returns 0 on success, non-zero on MAC failure. */
|
|
18303
18308
|
FIO_IFUNC int fio_ipc_decrypt(fio_ipc_s *m);
|
|
18304
18309
|
```
|
|
18305
18310
|
|
|
18306
|
-
|
|
18307
|
-
message's `id` and `timestamp` fields (which form the nonce). `len`, `flags`,
|
|
18308
|
-
and `routing_flags` are authenticated but unencrypted. Everything else
|
|
18309
|
-
(`call`/`opcode`, `on_reply`, `on_done`, `udata`, `data`) is encrypted.
|
|
18310
|
-
|
|
18311
|
-
Decryption failure logs a security warning and the connection is closed.
|
|
18312
|
-
Only processes sharing the same secret can communicate.
|
|
18311
|
+
Sending encrypts messages automatically. `fio_ipc_encrypt` encrypts a message in place; `fio_ipc_decrypt` returns `0` on success or nonzero if authentication fails. Most applications should use the delivery functions instead.
|
|
18313
18312
|
|
|
18314
18313
|
---
|
|
18315
18314
|
|
|
18316
18315
|
## Routing Flags
|
|
18317
18316
|
|
|
18318
|
-
|
|
18317
|
+
The routing flags are defined in the header for advanced use. Prefer the delivery macros and `.flags` for application data. Do not modify `routing_flags` on a received message:
|
|
18319
18318
|
|
|
18320
18319
|
```c
|
|
18321
18320
|
#define FIO_IPC_FLAG_ENCRYPTED ((uint16_t)1 << 0) /* message is encrypted */
|
|
@@ -18332,21 +18331,6 @@ Only processes sharing the same secret can communicate.
|
|
|
18332
18331
|
|
|
18333
18332
|
---
|
|
18334
18333
|
|
|
18335
|
-
## Keepalive
|
|
18336
|
-
|
|
18337
|
-
IPC and cluster connections use an automatic ping/pong protocol. On the first
|
|
18338
|
-
timeout the system sends a ping; if no pong arrives before the next timeout
|
|
18339
|
-
the connection is closed. Ping frames are never delivered to user callbacks.
|
|
18340
|
-
|
|
18341
|
-
Default timeouts (set in the protocol initializer):
|
|
18342
|
-
|
|
18343
|
-
| Connection type | Timeout |
|
|
18344
|
-
|-----------------|---------|
|
|
18345
|
-
| Local IPC (master ↔ worker) | ~6 minutes |
|
|
18346
|
-
| Cluster RPC (machine ↔ machine) | ~55 seconds |
|
|
18347
|
-
|
|
18348
|
-
---
|
|
18349
|
-
|
|
18350
18334
|
## Memory Management
|
|
18351
18335
|
|
|
18352
18336
|
- Messages are reference-counted (`fio_ipc_dup` / `fio_ipc_free`).
|
|
@@ -18366,6 +18350,8 @@ Default timeouts (set in the protocol initializer):
|
|
|
18366
18350
|
- `fio_ipc_dup` / `fio_ipc_free` are thread-safe.
|
|
18367
18351
|
- `fio_ipc_opcode_register` is **not** thread-safe after `fio_io_start`.
|
|
18368
18352
|
- `fio_ipc_url_set` must be called on the master before `fio_io_start`.
|
|
18353
|
+
|
|
18354
|
+
---
|
|
18369
18355
|
# OpenSSL TLS Backend
|
|
18370
18356
|
|
|
18371
18357
|
```c
|
|
@@ -20292,32 +20278,11 @@ support in [DEFLATE / Gzip](./162 deflate.md).
|
|
|
20292
20278
|
- upgrade helpers for WebSocket and SSE connections.
|
|
20293
20279
|
- pub/sub helpers for upgraded connections.
|
|
20294
20280
|
- handle access helpers: `fio_http_io` and `fio_http_settings`.
|
|
20295
|
-
- the HTTP handle API
|
|
20296
|
-
`432 http types.h`), including request / response fields, headers,
|
|
20281
|
+
- the HTTP handle API, including request / response fields, headers,
|
|
20297
20282
|
cookies, body storage, writing, static-file responses, logging, MIME
|
|
20298
20283
|
lookup, and controller hooks.
|
|
20299
20284
|
|
|
20300
|
-
|
|
20301
|
-
|
|
20302
|
-
---
|
|
20303
|
-
|
|
20304
|
-
## Module Files
|
|
20305
|
-
|
|
20306
|
-
All HTTP module files share the `FIO_HTTP` flag.
|
|
20307
|
-
|
|
20308
|
-
- `430 http api.h` — public declarations: settings, listener / route /
|
|
20309
|
-
client APIs, and the full handle API.
|
|
20310
|
-
- `432 http types.h` — internal types plus the handle and core
|
|
20311
|
-
implementation (header cache, body storage, static-file responses).
|
|
20312
|
-
- `434 http accept.h` — accept path, request dispatchers, upgrade
|
|
20313
|
-
authorization.
|
|
20314
|
-
- `434 http1.h` — HTTP/1.1 request / response glue, protocol and
|
|
20315
|
-
controller.
|
|
20316
|
-
- `434 sse.h` — EventSource (SSE) upgrade, helpers, protocol, controller.
|
|
20317
|
-
- `434 websocket.h` — WebSocket upgrade, events, protocol, write,
|
|
20318
|
-
controller.
|
|
20319
|
-
- `438 http.h` — listen / connect glue, protocol wiring, shared helpers.
|
|
20320
|
-
- `439 http.h` — cleanup tail (the module's only `#undef FIO_HTTP` site).
|
|
20285
|
+
Names prefixed with `fio___` are private and not part of the API.
|
|
20321
20286
|
|
|
20322
20287
|
The parsers are separate modules: [`004 http1 parser.h`](./004 http1 parser.md)
|
|
20323
20288
|
and [`004 websocket parser.h`](./004 websocket parser.md).
|
|
@@ -20417,7 +20382,7 @@ Other settings:
|
|
|
20417
20382
|
| `sse_timeout` | SSE timeout; timeout pings are sent. |
|
|
20418
20383
|
| `connect_timeout` | Client connection timeout. |
|
|
20419
20384
|
| `log` | Enables HTTP request logging. |
|
|
20420
|
-
| `compress_static` | Opt-in static-file compression (on-demand `.br`/`.gz` creation). Per-route; routes inherit the listener's root value at route-creation.
|
|
20385
|
+
| `compress_static` | Opt-in static-file compression (on-demand `.br`/`.gz` creation). Per-route; routes inherit the listener's root value at route-creation. May drop to 0 when creation is disabled after failures (see *Static File Service*). See the compression security note below. |
|
|
20421
20386
|
| `compress_dynamic` | Opt-in dynamic response compression. Connection-global; per-route values are ignored. See the compression security note below. |
|
|
20422
20387
|
| `compress_ws` | Opt-in WebSocket `permessage-deflate`. Connection-global; per-route values are ignored. See the compression security note below. |
|
|
20423
20388
|
|
|
@@ -20425,21 +20390,18 @@ Other settings:
|
|
|
20425
20390
|
secrets together with attacker-reflected data enables length-oracle attacks
|
|
20426
20391
|
(BREACH/CRIME). Do not enable compression for responses that mix secrets
|
|
20427
20392
|
(CSRF tokens, session data) with attacker-controlled reflections, or emit
|
|
20428
|
-
such messages uncompressed
|
|
20429
|
-
|
|
20430
|
-
|
|
20431
|
-
uncompressed).
|
|
20393
|
+
such messages uncompressed: leave `compress_dynamic` / `compress_ws` off
|
|
20394
|
+
for listeners serving them, or pre-set a response `content-encoding` header
|
|
20395
|
+
(it is always respected) to pass a body through uncompressed.
|
|
20432
20396
|
|
|
20433
20397
|
**WebSocket `permessage-deflate` negotiation:** the server ALWAYS responds
|
|
20434
20398
|
with `permessage-deflate; server_no_context_takeover;
|
|
20435
20399
|
client_no_context_takeover` (RFC 7692 allows either endpoint to request the
|
|
20436
20400
|
flags unilaterally), honoring `server_max_window_bits` when offered (the
|
|
20437
20401
|
compressor clamps its distances accordingly) and never emitting window-bits
|
|
20438
|
-
parameters. Cross-message history is never used,
|
|
20439
|
-
|
|
20440
|
-
|
|
20441
|
-
static process-wide slot pool checked out per call — under extreme
|
|
20442
|
-
contention a message simply goes out uncompressed.
|
|
20402
|
+
parameters. Cross-message history is never used, keeping per-connection
|
|
20403
|
+
compression memory minimal. Under heavy load, a message may be sent
|
|
20404
|
+
uncompressed.
|
|
20443
20405
|
|
|
20444
20406
|
**Accept-Encoding handling:** `q=0` (in any zero-padded form) forbids an
|
|
20445
20407
|
encoding (RFC 9110). `Vary: accept-encoding` is set whenever compressed
|
|
@@ -20613,33 +20575,29 @@ least as fresh as the original (modification time) is served, with
|
|
|
20613
20575
|
selected (RFC 9110 §12.5.3).
|
|
20614
20576
|
|
|
20615
20577
|
With `compress_static` enabled, missing or stale `.br` / `.gz` variants are
|
|
20616
|
-
created on demand and written into the root folder.
|
|
20617
|
-
|
|
20618
|
-
|
|
20619
|
-
|
|
20578
|
+
created on demand and written into the root folder. The value is read from the
|
|
20579
|
+
matching route's settings (routes inherit the listener's root value at
|
|
20580
|
+
route-creation); handles without settings (created with `fio_http_new`) never
|
|
20581
|
+
create variants.
|
|
20620
20582
|
|
|
20621
20583
|
- creation is limited to compressible (text-like) MIME types and originals
|
|
20622
20584
|
between 1024 bytes and `FIO_HTTP_STATIC_FILE_COMPRESS_LIMIT` (2 MiB);
|
|
20623
20585
|
- creation is skipped when compression would not shrink the file;
|
|
20624
|
-
- `.br` variants are compressed at brotli quality 4
|
|
20625
|
-
|
|
20626
|
-
variants at gzip level 6;
|
|
20586
|
+
- `.br` variants are compressed at brotli quality 4 and `.gz` variants at
|
|
20587
|
+
gzip level 6;
|
|
20627
20588
|
- `zstd` / `deflate` variants are only ever served pre-generated — they are
|
|
20628
20589
|
never created on demand;
|
|
20629
20590
|
- on-demand creation writes into the served folder and is triggered by
|
|
20630
20591
|
client requests; the folder must be writable for creation to succeed
|
|
20631
|
-
(
|
|
20592
|
+
(repeated failures disable creation, see below). Variants
|
|
20632
20593
|
may also be pre-generated at deploy time with any external tool — the
|
|
20633
20594
|
server only stats the files.
|
|
20634
20595
|
|
|
20635
|
-
`compress_static`
|
|
20636
|
-
|
|
20637
|
-
|
|
20638
|
-
|
|
20639
|
-
|
|
20640
|
-
does a single filesystem-full / permission error (`ENOSPC`, `EACCES`,
|
|
20641
|
-
`EROFS`, `EDQUOT` — `value = 0`). Once 0, creation stays disabled until the
|
|
20642
|
-
settings are re-applied. Detached handles carry no memoization state.
|
|
20596
|
+
Any non-zero `compress_static` value enables on-demand creation. The server
|
|
20597
|
+
disables creation (setting the value to 0) after repeated consecutive
|
|
20598
|
+
failures, or after a single filesystem-full / permission error (`ENOSPC`,
|
|
20599
|
+
`EACCES`, `EROFS`, `EDQUOT`). Once disabled, creation stays off until the
|
|
20600
|
+
settings are re-applied.
|
|
20643
20601
|
|
|
20644
20602
|
`Vary: accept-encoding` is set whenever a variant is served, and on
|
|
20645
20603
|
identity responses whenever variants may be created, so caches key on the
|
|
@@ -20856,12 +20814,35 @@ fio_http_controller_s *fio_http_controller_set(fio_http_s *h,
|
|
|
20856
20814
|
`udata` and `udata2` are for application state. `cdata` and the controller are
|
|
20857
20815
|
used by the HTTP layer and custom controllers.
|
|
20858
20816
|
|
|
20817
|
+
`fio_http_controller` gets the handle's controller; `fio_http_controller_set`
|
|
20818
|
+
sets it and returns the controller in use. Passing `NULL` installs a no-op
|
|
20819
|
+
controller. Missing callbacks in a custom controller are filled in with no-op
|
|
20820
|
+
defaults, so the controller object must be writable and outlive the handle.
|
|
20821
|
+
|
|
20859
20822
|
### Request / response properties
|
|
20860
20823
|
|
|
20861
20824
|
```c
|
|
20862
20825
|
size_t fio_http_status(fio_http_s *h);
|
|
20863
20826
|
size_t fio_http_status_set(fio_http_s *h, size_t status);
|
|
20864
20827
|
fio_str_info_s fio_http_method(fio_http_s *h);
|
|
20828
|
+
int fio_http_method_is_get(fio_http_s *h);
|
|
20829
|
+
int fio_http_method_is_head(fio_http_s *h);
|
|
20830
|
+
int fio_http_method_is_post(fio_http_s *h);
|
|
20831
|
+
int fio_http_method_is_put(fio_http_s *h);
|
|
20832
|
+
int fio_http_method_is_delete(fio_http_s *h);
|
|
20833
|
+
int fio_http_method_is_connect(fio_http_s *h);
|
|
20834
|
+
int fio_http_method_is_options(fio_http_s *h);
|
|
20835
|
+
int fio_http_method_is_trace(fio_http_s *h);
|
|
20836
|
+
int fio_http_method_is_patch(fio_http_s *h);
|
|
20837
|
+
int fio_http_method_is_query(fio_http_s *h);
|
|
20838
|
+
int fio_http_method_is_propfind(fio_http_s *h);
|
|
20839
|
+
int fio_http_method_is_proppatch(fio_http_s *h);
|
|
20840
|
+
int fio_http_method_is_mkcol(fio_http_s *h);
|
|
20841
|
+
int fio_http_method_is_copy(fio_http_s *h);
|
|
20842
|
+
int fio_http_method_is_move(fio_http_s *h);
|
|
20843
|
+
int fio_http_method_is_lock(fio_http_s *h);
|
|
20844
|
+
int fio_http_method_is_unlock(fio_http_s *h);
|
|
20845
|
+
int fio_http_method_is_search(fio_http_s *h);
|
|
20865
20846
|
fio_str_info_s fio_http_method_set(fio_http_s *h, fio_str_info_s value);
|
|
20866
20847
|
fio_str_info_s fio_http_opath(fio_http_s *h);
|
|
20867
20848
|
fio_str_info_s fio_http_opath_set(fio_http_s *h, fio_str_info_s value);
|
|
@@ -20878,10 +20859,18 @@ int64_t fio_http_received_at_set(fio_http_s *h, int64_t value);
|
|
|
20878
20859
|
`opath` is the original path before route prefix trimming. `path` is the routed
|
|
20879
20860
|
path visible to the current callback.
|
|
20880
20861
|
|
|
20881
|
-
|
|
20882
|
-
|
|
20862
|
+
The `fio_http_method_is_*` helpers test whether the request method matches the
|
|
20863
|
+
named method, ignoring ASCII case. They return `1` for a match and `0` otherwise;
|
|
20864
|
+
pass a non-`NULL` HTTP handle (`h`). Unlike `fio_http_resource_action`, these
|
|
20865
|
+
helpers do not classify paths or combine PUT, POST, and PATCH into a single
|
|
20866
|
+
action. The helpers cover the core HTTP methods, PATCH, QUERY, and commonly
|
|
20867
|
+
used WebDAV methods (PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, and
|
|
20868
|
+
SEARCH).
|
|
20883
20869
|
|
|
20884
|
-
|
|
20870
|
+
`fio_http_status_set(h, 0)` normalizes to `200`; values above `1023` normalize
|
|
20871
|
+
to `500`.
|
|
20872
|
+
|
|
20873
|
+
### State checks
|
|
20885
20874
|
|
|
20886
20875
|
```c
|
|
20887
20876
|
int fio_http_is_clean(fio_http_s *h);
|
|
@@ -20893,25 +20882,6 @@ int fio_http_is_sse(fio_http_s *h);
|
|
|
20893
20882
|
int fio_http_is_freeing(fio_http_s *h);
|
|
20894
20883
|
```
|
|
20895
20884
|
|
|
20896
|
-
The handle also exposes inline flag helpers generated for `cflags` and
|
|
20897
|
-
`uflags`:
|
|
20898
|
-
|
|
20899
|
-
```c
|
|
20900
|
-
uint16_t fio_http_cflags(fio_http_s *h);
|
|
20901
|
-
uint16_t fio_http_cflags_set(fio_http_s *h, uint16_t flags);
|
|
20902
|
-
uint16_t fio_http_cflags_unset(fio_http_s *h, uint16_t flags);
|
|
20903
|
-
uint16_t fio_http_cflags_flip(fio_http_s *h, uint16_t flags);
|
|
20904
|
-
uint16_t fio_http_cflags_is_set(fio_http_s *h, uint16_t flags);
|
|
20905
|
-
|
|
20906
|
-
uint16_t fio_http_uflags(fio_http_s *h);
|
|
20907
|
-
uint16_t fio_http_uflags_set(fio_http_s *h, uint16_t flags);
|
|
20908
|
-
uint16_t fio_http_uflags_unset(fio_http_s *h, uint16_t flags);
|
|
20909
|
-
uint16_t fio_http_uflags_flip(fio_http_s *h, uint16_t flags);
|
|
20910
|
-
uint16_t fio_http_uflags_is_set(fio_http_s *h, uint16_t flags);
|
|
20911
|
-
```
|
|
20912
|
-
|
|
20913
|
-
Prefer the state helpers unless implementing protocol or controller glue.
|
|
20914
|
-
|
|
20915
20885
|
### Headers
|
|
20916
20886
|
|
|
20917
20887
|
```c
|
|
@@ -21132,13 +21102,10 @@ void fio_http_write_log(fio_http_s *h);
|
|
|
21132
21102
|
int fio_http_from(fio_str_info_s *dest, const fio_http_s *h);
|
|
21133
21103
|
fio_str_info_s fio_http_date(uint64_t now_in_seconds);
|
|
21134
21104
|
fio_str_info_s fio_http_log_time(uint64_t now_in_seconds);
|
|
21135
|
-
int64_t fio_http_get_timestump(void);
|
|
21136
21105
|
```
|
|
21137
21106
|
|
|
21138
|
-
|
|
21139
|
-
`
|
|
21140
|
-
`fio_http_received_at` or formats them with `fio_http_date` /
|
|
21141
|
-
`fio_http_log_time`.
|
|
21107
|
+
Read request timestamps with `fio_http_received_at`; format dates with
|
|
21108
|
+
`fio_http_date` / `fio_http_log_time`.
|
|
21142
21109
|
|
|
21143
21110
|
`fio_http_from` writes a best-effort peer address starting with the `Forwarded`
|
|
21144
21111
|
header, then socket peer address, then `"[unknown]"`.
|
|
@@ -21179,7 +21146,8 @@ struct fio_http_controller_s {
|
|
|
21179
21146
|
```
|
|
21180
21147
|
|
|
21181
21148
|
Controllers allow the handle to write through different protocols. Initialize
|
|
21182
|
-
custom controllers to zero before use
|
|
21149
|
+
custom controllers to zero before use; `private_flags` is reserved and must
|
|
21150
|
+
remain zero. If controller callbacks are not
|
|
21183
21151
|
thread-safe, call `fio_http_write` only from the controller's expected thread.
|
|
21184
21152
|
|
|
21185
21153
|
---
|
|
@@ -21217,24 +21185,11 @@ FIO_HTTP_LOG_X_REQUEST_START /* 1 */
|
|
|
21217
21185
|
FIO_HTTP_ENFORCE_LOWERCASE_HEADERS /* 0 */
|
|
21218
21186
|
```
|
|
21219
21187
|
|
|
21220
|
-
|
|
21221
|
-
|
|
21222
|
-
|
|
21223
|
-
|
|
21224
|
-
|
|
21225
|
-
FIO_HTTP_STATE_UPGRADED
|
|
21226
|
-
FIO_HTTP_STATE_WEBSOCKET
|
|
21227
|
-
FIO_HTTP_STATE_SSE
|
|
21228
|
-
FIO_HTTP_STATE_COOKIES_PARSED
|
|
21229
|
-
FIO_HTTP_STATE_FREEING
|
|
21230
|
-
|
|
21231
|
-
FIO_HTTP_CFLAG_COMPRESS_DYNAMIC
|
|
21232
|
-
FIO_HTTP_CFLAG_COMPRESS_WS
|
|
21233
|
-
FIO_HTTP_CFLAG_COMPRESS_STATIC
|
|
21234
|
-
```
|
|
21235
|
-
|
|
21236
|
-
Prefer public helper functions over reading state bits directly in application
|
|
21237
|
-
code.
|
|
21188
|
+
With `FIO_HTTP_LOG_X_REQUEST_START`, request logs (`.log = 1`) include the
|
|
21189
|
+
request's wait time when the client or proxy sends an `X-Request-Start`
|
|
21190
|
+
header holding a millisecond timestamp (optionally prefixed with `t=`). The
|
|
21191
|
+
wait time is omitted when the header is missing or the wait is 512 seconds or
|
|
21192
|
+
more.
|
|
21238
21193
|
|
|
21239
21194
|
---
|
|
21240
21195
|
|
data/ext/iodine/iodine_utils.h
CHANGED
|
@@ -247,7 +247,7 @@ FIO_SFUNC VALUE iodine_utils_is_eq(VALUE mod, VALUE a, VALUE b) { // clang-forma
|
|
|
247
247
|
Randomness and Friends
|
|
248
248
|
***************************************************************************** */
|
|
249
249
|
|
|
250
|
-
FIO_DEFINE_RANDOM128_FN(static, iodine_random,
|
|
250
|
+
FIO_DEFINE_RANDOM128_FN(static, iodine_random, 11, 0)
|
|
251
251
|
|
|
252
252
|
FIO_SFUNC VALUE iodine_utils_hmac512(VALUE self, VALUE secret, VALUE massage) {
|
|
253
253
|
rb_check_type(secret, RUBY_T_STRING);
|
data/lib/iodine/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: iodine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Boaz Segev
|
|
@@ -133,7 +133,7 @@ metadata:
|
|
|
133
133
|
homepage_uri: https://github.com/boazsegev/iodine
|
|
134
134
|
source_code_uri: https://github.com/boazsegev/iodine
|
|
135
135
|
changelog_uri: https://github.com/boazsegev/iodine/blob/master/CHANGELOG.md
|
|
136
|
-
post_install_message: Thank you for installing Iodine 0.8.
|
|
136
|
+
post_install_message: Thank you for installing Iodine 0.8.2.
|
|
137
137
|
rdoc_options: []
|
|
138
138
|
require_paths:
|
|
139
139
|
- lib
|