A session ending was a single bit. A player quitting their game, an operator ending the session from the console, a stop the client itself asked for, a host crashing and a Wi-Fi drop all arrived as the same "closed" — so every client had to write one message covering all of them, and every client picked an error. That is how quitting your own game came to be reported as trouble on all three. The information was already there and thrown away: the host closes with APP_EXITED when a launched game exits, with 0 when it ends the session cleanly and 1 when it fails, and a link that simply dies never closes at all. The connection watcher now classifies that into a PunktfunkEndReason — local, game exited, host ended, host error, lost — and latches it before the shutdown flag, since the two are read by different threads and the reason must never arrive second. Exposed as punktfunk_connection_end_reason. This replaces the game-exited flag added a moment ago rather than joining it: that question is one row of this table, and it was never released. Still additive to any embedder that ignores it, and the host sends the same bytes either way, so the wire is untouched. `is_normal()` is the question nearly every caller actually has, so both the Rust and C surfaces answer it directly rather than making each client re-derive which of five values are worth alarming a user about.
238 lines
11 KiB
TOML
238 lines
11 KiB
TOML
language = "C"
|
|
pragma_once = true
|
|
include_guard = "PUNKTFUNK_CORE_H"
|
|
autogen_warning = "/* Generated by cbindgen from punktfunk-core. Do not edit by hand. */"
|
|
header = "/* punktfunk-core C ABI — see crates/punktfunk-core/src/abi.rs */"
|
|
style = "type"
|
|
cpp_compat = true
|
|
tab_width = 4
|
|
documentation = true
|
|
documentation_style = "c99"
|
|
|
|
[parse]
|
|
parse_deps = false
|
|
|
|
[export]
|
|
# Internal platform-only FFI — NOT part of the C ABI. cbindgen otherwise sweeps the foreign
|
|
# imports and their #[repr(C)] structs into the header, where socklen_t/ssize_t/iovec/msghdr are
|
|
# undefined and the C harness fails to compile: the Apple batched recv (transport/udp.rs
|
|
# `recvmsg_x` + `MsghdrX`) and the Android bionic mmsg bindings (`android_mmsg` module).
|
|
exclude = ["MsghdrX", "recvmsg_x", "mmsghdr", "sendmmsg", "recvmmsg"]
|
|
# Reached by no exported SIGNATURE, so cbindgen's sweep misses it — but a C embedder needs the
|
|
# vocabulary: `punktfunk_connection_end_reason` writes one of these as a bare byte (deliberately,
|
|
# so the JNI/Swift sides can marshal a `u8` rather than an enum), which without this would leave
|
|
# the header documenting names it never defines.
|
|
include = ["PunktfunkEndReason"]
|
|
|
|
[export.rename]
|
|
"InputEvent" = "PunktfunkInputEvent"
|
|
"InputKind" = "PunktfunkInputKind"
|
|
# Gamepad wire constants: bare BTN_* names collide with <linux/input-event-codes.h> (at
|
|
# DIFFERENT values — last definition silently wins); prefix everything we export.
|
|
"BTN_DPAD_UP" = "PUNKTFUNK_BTN_DPAD_UP"
|
|
"BTN_DPAD_DOWN" = "PUNKTFUNK_BTN_DPAD_DOWN"
|
|
"BTN_DPAD_LEFT" = "PUNKTFUNK_BTN_DPAD_LEFT"
|
|
"BTN_DPAD_RIGHT" = "PUNKTFUNK_BTN_DPAD_RIGHT"
|
|
"BTN_START" = "PUNKTFUNK_BTN_START"
|
|
"BTN_BACK" = "PUNKTFUNK_BTN_BACK"
|
|
"BTN_LS_CLICK" = "PUNKTFUNK_BTN_LS_CLICK"
|
|
"BTN_RS_CLICK" = "PUNKTFUNK_BTN_RS_CLICK"
|
|
"BTN_LB" = "PUNKTFUNK_BTN_LB"
|
|
"BTN_RB" = "PUNKTFUNK_BTN_RB"
|
|
"BTN_GUIDE" = "PUNKTFUNK_BTN_GUIDE"
|
|
"BTN_A" = "PUNKTFUNK_BTN_A"
|
|
"BTN_B" = "PUNKTFUNK_BTN_B"
|
|
"BTN_X" = "PUNKTFUNK_BTN_X"
|
|
"BTN_Y" = "PUNKTFUNK_BTN_Y"
|
|
"BTN_TOUCHPAD" = "PUNKTFUNK_BTN_TOUCHPAD"
|
|
"AXIS_LS_X" = "PUNKTFUNK_AXIS_LS_X"
|
|
"AXIS_LS_Y" = "PUNKTFUNK_AXIS_LS_Y"
|
|
"AXIS_RS_X" = "PUNKTFUNK_AXIS_RS_X"
|
|
"AXIS_RS_Y" = "PUNKTFUNK_AXIS_RS_Y"
|
|
"AXIS_LT" = "PUNKTFUNK_AXIS_LT"
|
|
"AXIS_RT" = "PUNKTFUNK_AXIS_RT"
|
|
"AUDIO_MAGIC" = "PUNKTFUNK_AUDIO_MAGIC"
|
|
"RUMBLE_MAGIC" = "PUNKTFUNK_RUMBLE_MAGIC"
|
|
"AUDIO_RED_MAGIC" = "PUNKTFUNK_AUDIO_RED_MAGIC"
|
|
"AUDIO_RED_HEADER" = "PUNKTFUNK_AUDIO_RED_HEADER"
|
|
# Same hazard as the BTN_* block above, one step worse: `FRAME_MS` and `SAMPLE_RATE_HZ` are
|
|
# generic enough that an embedder is likely to have its own, and a clashing #define silently
|
|
# takes the last definition rather than failing to compile.
|
|
"FRAME_MS" = "PUNKTFUNK_AUDIO_FRAME_MS"
|
|
"SAMPLE_RATE_HZ" = "PUNKTFUNK_AUDIO_SAMPLE_RATE_HZ"
|
|
|
|
# R21: every remaining exported constant, prefixed. cbindgen emits a bare `#define` per
|
|
# `pub const`, so without an entry here names as generic as MAX_PADS, TAG_LEN, ABI_VERSION and
|
|
# INPUT_MAGIC land in the namespace of every C embedder that includes this header — and, as the
|
|
# note above says, a clashing #define silently takes the last definition rather than failing to
|
|
# compile. The table above had been doing this by hand for the handful someone noticed; this is
|
|
# the rest of them, so the stated rule finally holds for the whole surface.
|
|
#
|
|
# NOT covered, deliberately: associated constants (`ColorInfo_CP_BT709`, `ClockResync_ROUNDS`,
|
|
# `ResyncGuard_MAX_REJECTED_STREAK`). cbindgen already qualifies those with their type name,
|
|
# which is the very property whose absence makes a bare `MAX_PADS` dangerous — they are
|
|
# namespaced, just not by us.
|
|
"ABI_VERSION" = "PUNKTFUNK_ABI_VERSION"
|
|
"APP_EXITED_CLOSE_CODE" = "PUNKTFUNK_APP_EXITED_CLOSE_CODE"
|
|
"BTN_MISC1" = "PUNKTFUNK_BTN_MISC1"
|
|
"BTN_PADDLE1" = "PUNKTFUNK_BTN_PADDLE1"
|
|
"BTN_PADDLE2" = "PUNKTFUNK_BTN_PADDLE2"
|
|
"BTN_PADDLE3" = "PUNKTFUNK_BTN_PADDLE3"
|
|
"BTN_PADDLE4" = "PUNKTFUNK_BTN_PADDLE4"
|
|
"CHROMA_IDC_420" = "PUNKTFUNK_CHROMA_IDC_420"
|
|
"CHROMA_IDC_444" = "PUNKTFUNK_CHROMA_IDC_444"
|
|
"CIPHER_AES_128_GCM" = "PUNKTFUNK_CIPHER_AES_128_GCM"
|
|
"CIPHER_CHACHA20_POLY1305" = "PUNKTFUNK_CIPHER_CHACHA20_POLY1305"
|
|
"CLIENT_CAP_AUDIO_RED" = "PUNKTFUNK_CLIENT_CAP_AUDIO_RED"
|
|
"CLIENT_CAP_CURSOR" = "PUNKTFUNK_CLIENT_CAP_CURSOR"
|
|
"CLIENT_CAP_PHASE_LOCK" = "PUNKTFUNK_CLIENT_CAP_PHASE_LOCK"
|
|
"CLIP_CANCELLED_CODE" = "PUNKTFUNK_CLIP_CANCELLED_CODE"
|
|
"CLIP_CHUNK" = "PUNKTFUNK_CLIP_CHUNK"
|
|
"CLIP_FETCH_CAP" = "PUNKTFUNK_CLIP_FETCH_CAP"
|
|
"CLIP_FETCH_DENIED" = "PUNKTFUNK_CLIP_FETCH_DENIED"
|
|
"CLIP_FETCH_OK" = "PUNKTFUNK_CLIP_FETCH_OK"
|
|
"CLIP_FETCH_STALE" = "PUNKTFUNK_CLIP_FETCH_STALE"
|
|
"CLIP_FETCH_UNAVAILABLE" = "PUNKTFUNK_CLIP_FETCH_UNAVAILABLE"
|
|
"CLIP_FILE_INDEX_NONE" = "PUNKTFUNK_CLIP_FILE_INDEX_NONE"
|
|
"CLIP_FLAG_FILES" = "PUNKTFUNK_CLIP_FLAG_FILES"
|
|
"CLIP_MAX_KINDS" = "PUNKTFUNK_CLIP_MAX_KINDS"
|
|
"CLIP_MAX_MIME" = "PUNKTFUNK_CLIP_MAX_MIME"
|
|
"CLIP_POLICY_FILES" = "PUNKTFUNK_CLIP_POLICY_FILES"
|
|
"CLIP_POLICY_TEXT" = "PUNKTFUNK_CLIP_POLICY_TEXT"
|
|
"CLIP_REASON_BACKEND_UNAVAILABLE" = "PUNKTFUNK_CLIP_REASON_BACKEND_UNAVAILABLE"
|
|
"CLIP_REASON_NO_FILES" = "PUNKTFUNK_CLIP_REASON_NO_FILES"
|
|
"CLIP_REASON_OK" = "PUNKTFUNK_CLIP_REASON_OK"
|
|
"CLIP_REASON_POLICY_DISABLED" = "PUNKTFUNK_CLIP_REASON_POLICY_DISABLED"
|
|
"CLIP_REASON_TAKEN_OVER" = "PUNKTFUNK_CLIP_REASON_TAKEN_OVER"
|
|
"CLIP_STREAM_KIND_FETCH" = "PUNKTFUNK_CLIP_STREAM_KIND_FETCH"
|
|
"ClockResync_ROUNDS" = "PUNKTFUNK_ClockResync_ROUNDS"
|
|
"CODEC_AV1" = "PUNKTFUNK_CODEC_AV1"
|
|
"CODEC_H264" = "PUNKTFUNK_CODEC_H264"
|
|
"CODEC_HEVC" = "PUNKTFUNK_CODEC_HEVC"
|
|
"CODEC_PYROWAVE" = "PUNKTFUNK_CODEC_PYROWAVE"
|
|
"ColorInfo_CP_BT2020" = "PUNKTFUNK_ColorInfo_CP_BT2020"
|
|
"ColorInfo_CP_BT709" = "PUNKTFUNK_ColorInfo_CP_BT709"
|
|
"ColorInfo_MC_BT2020_NCL" = "PUNKTFUNK_ColorInfo_MC_BT2020_NCL"
|
|
"ColorInfo_MC_BT709" = "PUNKTFUNK_ColorInfo_MC_BT709"
|
|
"ColorInfo_TRC_BT709" = "PUNKTFUNK_ColorInfo_TRC_BT709"
|
|
"ColorInfo_TRC_HLG" = "PUNKTFUNK_ColorInfo_TRC_HLG"
|
|
"ColorInfo_TRC_PQ" = "PUNKTFUNK_ColorInfo_TRC_PQ"
|
|
"CURSOR_RELATIVE_HINT" = "PUNKTFUNK_CURSOR_RELATIVE_HINT"
|
|
"CURSOR_SHAPE_MAX_SIDE" = "PUNKTFUNK_CURSOR_SHAPE_MAX_SIDE"
|
|
"CURSOR_STATE_MAGIC" = "PUNKTFUNK_CURSOR_STATE_MAGIC"
|
|
"CURSOR_VISIBLE" = "PUNKTFUNK_CURSOR_VISIBLE"
|
|
"FLAG_EOF" = "PUNKTFUNK_FLAG_EOF"
|
|
"FLAG_PIC" = "PUNKTFUNK_FLAG_PIC"
|
|
"FLAG_PROBE" = "PUNKTFUNK_FLAG_PROBE"
|
|
"FLAG_SOF" = "PUNKTFUNK_FLAG_SOF"
|
|
"HDR_META_BODY_LEN" = "PUNKTFUNK_HDR_META_BODY_LEN"
|
|
"HDR_META_MAGIC" = "PUNKTFUNK_HDR_META_MAGIC"
|
|
"HELLO_LAUNCH_MAX" = "PUNKTFUNK_HELLO_LAUNCH_MAX"
|
|
"HELLO_NAME_MAX" = "PUNKTFUNK_HELLO_NAME_MAX"
|
|
"HID_RAW_FEATURE" = "PUNKTFUNK_HID_RAW_FEATURE"
|
|
"HID_RAW_OUTPUT" = "PUNKTFUNK_HID_RAW_OUTPUT"
|
|
"HID_REPORT_MAX" = "PUNKTFUNK_HID_REPORT_MAX"
|
|
"HIDOUT_MAGIC" = "PUNKTFUNK_HIDOUT_MAGIC"
|
|
"HOST_CAP_AUDIO_RED" = "PUNKTFUNK_HOST_CAP_AUDIO_RED"
|
|
"HOST_CAP_CLIPBOARD" = "PUNKTFUNK_HOST_CAP_CLIPBOARD"
|
|
"HOST_CAP_CURSOR" = "PUNKTFUNK_HOST_CAP_CURSOR"
|
|
"HOST_CAP_GAMEPAD_STATE" = "PUNKTFUNK_HOST_CAP_GAMEPAD_STATE"
|
|
"HOST_CAP_PEN" = "PUNKTFUNK_HOST_CAP_PEN"
|
|
"HOST_CAP_TEXT_INPUT" = "PUNKTFUNK_HOST_CAP_TEXT_INPUT"
|
|
"HOST_TIMING_MAGIC" = "PUNKTFUNK_HOST_TIMING_MAGIC"
|
|
"INBOUND_REQ_FLAG" = "PUNKTFUNK_INBOUND_REQ_FLAG"
|
|
"INPUT_MAGIC" = "PUNKTFUNK_INPUT_MAGIC"
|
|
"INPUT_WIRE_LEN" = "PUNKTFUNK_INPUT_WIRE_LEN"
|
|
"LEGACY_STALE_MS" = "PUNKTFUNK_LEGACY_STALE_MS"
|
|
"MAX_DATAGRAM_BYTES" = "PUNKTFUNK_MAX_DATAGRAM_BYTES"
|
|
"MAX_PADS" = "PUNKTFUNK_MAX_PADS"
|
|
"MAX_SCALE" = "PUNKTFUNK_MAX_SCALE"
|
|
"MIC_MAGIC" = "PUNKTFUNK_MIC_MAGIC"
|
|
"MIN_SCALE" = "PUNKTFUNK_MIN_SCALE"
|
|
"MIN_SHARD_PAYLOAD" = "PUNKTFUNK_MIN_SHARD_PAYLOAD"
|
|
"MIN_STREAM_BLOCK_SHARDS" = "PUNKTFUNK_MIN_STREAM_BLOCK_SHARDS"
|
|
"MSG_BITRATE_CHANGED" = "PUNKTFUNK_MSG_BITRATE_CHANGED"
|
|
"MSG_CLIP_CONTROL" = "PUNKTFUNK_MSG_CLIP_CONTROL"
|
|
"MSG_CLIP_FETCH" = "PUNKTFUNK_MSG_CLIP_FETCH"
|
|
"MSG_CLIP_FETCH_HDR" = "PUNKTFUNK_MSG_CLIP_FETCH_HDR"
|
|
"MSG_CLIP_OFFER" = "PUNKTFUNK_MSG_CLIP_OFFER"
|
|
"MSG_CLIP_STATE" = "PUNKTFUNK_MSG_CLIP_STATE"
|
|
"MSG_CLOCK_ECHO" = "PUNKTFUNK_MSG_CLOCK_ECHO"
|
|
"MSG_CLOCK_PROBE" = "PUNKTFUNK_MSG_CLOCK_PROBE"
|
|
"MSG_CURSOR_RENDER" = "PUNKTFUNK_MSG_CURSOR_RENDER"
|
|
"MSG_CURSOR_SHAPE" = "PUNKTFUNK_MSG_CURSOR_SHAPE"
|
|
"MSG_LOSS_REPORT" = "PUNKTFUNK_MSG_LOSS_REPORT"
|
|
"MSG_PAIR_CHALLENGE" = "PUNKTFUNK_MSG_PAIR_CHALLENGE"
|
|
"MSG_PAIR_PROOF" = "PUNKTFUNK_MSG_PAIR_PROOF"
|
|
"MSG_PAIR_REQUEST" = "PUNKTFUNK_MSG_PAIR_REQUEST"
|
|
"MSG_PAIR_RESULT" = "PUNKTFUNK_MSG_PAIR_RESULT"
|
|
"MSG_PHASE_REPORT" = "PUNKTFUNK_MSG_PHASE_REPORT"
|
|
"MSG_PROBE_REQUEST" = "PUNKTFUNK_MSG_PROBE_REQUEST"
|
|
"MSG_PROBE_RESULT" = "PUNKTFUNK_MSG_PROBE_RESULT"
|
|
"MSG_RECONFIGURE" = "PUNKTFUNK_MSG_RECONFIGURE"
|
|
"MSG_RECONFIGURED" = "PUNKTFUNK_MSG_RECONFIGURED"
|
|
"MSG_REQUEST_KEYFRAME" = "PUNKTFUNK_MSG_REQUEST_KEYFRAME"
|
|
"MSG_RFI_REQUEST" = "PUNKTFUNK_MSG_RFI_REQUEST"
|
|
"MSG_SET_BITRATE" = "PUNKTFUNK_MSG_SET_BITRATE"
|
|
"MSG_SHARD_PAYLOAD_ACK" = "PUNKTFUNK_MSG_SHARD_PAYLOAD_ACK"
|
|
"MSG_SHARD_PAYLOAD_CHANGED" = "PUNKTFUNK_MSG_SHARD_PAYLOAD_CHANGED"
|
|
"NO_OUTPUT_KEYFRAME_STREAK" = "PUNKTFUNK_NO_OUTPUT_KEYFRAME_STREAK"
|
|
"PAIR_APPROVAL_TIMEOUT_CLOSE_CODE" = "PUNKTFUNK_PAIR_APPROVAL_TIMEOUT_CLOSE_CODE"
|
|
"PAIR_BOUND_OTHER_CLOSE_CODE" = "PUNKTFUNK_PAIR_BOUND_OTHER_CLOSE_CODE"
|
|
"PAIR_DENIED_CLOSE_CODE" = "PUNKTFUNK_PAIR_DENIED_CLOSE_CODE"
|
|
"PAIR_NO_IDENTITY_CLOSE_CODE" = "PUNKTFUNK_PAIR_NO_IDENTITY_CLOSE_CODE"
|
|
"PAIR_NOT_ARMED_CLOSE_CODE" = "PUNKTFUNK_PAIR_NOT_ARMED_CLOSE_CODE"
|
|
"PAIR_RATE_LIMITED_CLOSE_CODE" = "PUNKTFUNK_PAIR_RATE_LIMITED_CLOSE_CODE"
|
|
"PAIR_SUPERSEDED_CLOSE_CODE" = "PUNKTFUNK_PAIR_SUPERSEDED_CLOSE_CODE"
|
|
"PEN_ANGLE_UNKNOWN" = "PUNKTFUNK_PEN_ANGLE_UNKNOWN"
|
|
"PEN_BARREL1" = "PUNKTFUNK_PEN_BARREL1"
|
|
"PEN_BARREL2" = "PUNKTFUNK_PEN_BARREL2"
|
|
"PEN_BATCH_MAX" = "PUNKTFUNK_PEN_BATCH_MAX"
|
|
"PEN_DISTANCE_UNKNOWN" = "PUNKTFUNK_PEN_DISTANCE_UNKNOWN"
|
|
"PEN_IN_RANGE" = "PUNKTFUNK_PEN_IN_RANGE"
|
|
"PEN_PREDICTED" = "PUNKTFUNK_PEN_PREDICTED"
|
|
"PEN_SAMPLE_WIRE_LEN" = "PUNKTFUNK_PEN_SAMPLE_WIRE_LEN"
|
|
"PEN_TILT_UNKNOWN" = "PUNKTFUNK_PEN_TILT_UNKNOWN"
|
|
"PEN_TOUCH_TIMEOUT_MS" = "PUNKTFUNK_PEN_TOUCH_TIMEOUT_MS"
|
|
"PEN_TOUCHING" = "PUNKTFUNK_PEN_TOUCHING"
|
|
"PRESETS" = "PUNKTFUNK_PRESETS"
|
|
"QUIT_CLOSE_CODE" = "PUNKTFUNK_QUIT_CLOSE_CODE"
|
|
"REANCHOR_MARKS_TO_LIFT" = "PUNKTFUNK_REANCHOR_MARKS_TO_LIFT"
|
|
"REJECT_BUSY_CLOSE_CODE" = "PUNKTFUNK_REJECT_BUSY_CLOSE_CODE"
|
|
"ResyncGuard_MAX_REJECTED_STREAK" = "PUNKTFUNK_ResyncGuard_MAX_REJECTED_STREAK"
|
|
"RFI_MAX_RANGE" = "PUNKTFUNK_RFI_MAX_RANGE"
|
|
"RICH_INPUT_MAGIC" = "PUNKTFUNK_RICH_INPUT_MAGIC"
|
|
"RUMBLE_V1_LEN" = "PUNKTFUNK_RUMBLE_V1_LEN"
|
|
"RUMBLE_V2_LEN" = "PUNKTFUNK_RUMBLE_V2_LEN"
|
|
"SETUP_FAILED_CLOSE_CODE" = "PUNKTFUNK_SETUP_FAILED_CLOSE_CODE"
|
|
"TAG_LEN" = "PUNKTFUNK_TAG_LEN"
|
|
"TRIGGER_EFFECT_MAX" = "PUNKTFUNK_TRIGGER_EFFECT_MAX"
|
|
"USER_FLAG_CHUNK_ALIGNED" = "PUNKTFUNK_USER_FLAG_CHUNK_ALIGNED"
|
|
"USER_FLAG_RECOVERY_ANCHOR" = "PUNKTFUNK_USER_FLAG_RECOVERY_ANCHOR"
|
|
"USER_FLAG_RECOVERY_POINT" = "PUNKTFUNK_USER_FLAG_RECOVERY_POINT"
|
|
"USER_FLAG_SLICE_STREAM" = "PUNKTFUNK_USER_FLAG_SLICE_STREAM"
|
|
"VIDEO_CAP_10BIT" = "PUNKTFUNK_VIDEO_CAP_10BIT"
|
|
"VIDEO_CAP_444" = "PUNKTFUNK_VIDEO_CAP_444"
|
|
"VIDEO_CAP_CHACHA20" = "PUNKTFUNK_VIDEO_CAP_CHACHA20"
|
|
"VIDEO_CAP_HDR" = "PUNKTFUNK_VIDEO_CAP_HDR"
|
|
"VIDEO_CAP_HOST_TIMING" = "PUNKTFUNK_VIDEO_CAP_HOST_TIMING"
|
|
"VIDEO_CAP_MULTI_SLICE" = "PUNKTFUNK_VIDEO_CAP_MULTI_SLICE"
|
|
"VIDEO_CAP_PROBE_SEQ" = "PUNKTFUNK_VIDEO_CAP_PROBE_SEQ"
|
|
"VIDEO_CAP_STREAMED_AU" = "PUNKTFUNK_VIDEO_CAP_STREAMED_AU"
|
|
"WIRE_VERSION" = "PUNKTFUNK_WIRE_VERSION"
|
|
"WIRE_VERSION_CLOSE_CODE" = "PUNKTFUNK_WIRE_VERSION_CLOSE_CODE"
|
|
|
|
# QualifiedScreamingSnakeCase already qualifies each variant with the enum name
|
|
# (PunktfunkStatus::Ok -> PUNKTFUNK_STATUS_OK); do NOT also set prefix_with_name or it doubles.
|
|
[enum]
|
|
rename_variants = "QualifiedScreamingSnakeCase"
|
|
|
|
[fn]
|
|
sort_by = "None"
|
|
|
|
[struct]
|
|
derive_eq = false
|
|
|
|
[defines]
|
|
"feature = quic" = "PUNKTFUNK_FEATURE_QUIC"
|