From 6eb7c1698c544f8345d49552e9a05d7b9a2e5593 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Wed, 30 Sep 2026 16:18:07 +1000 Subject: [PATCH] [common] network: use LGProtocol codecs --- client/transports/Network/connection.h | 2 +- client/transports/Network/network.c | 2 +- common/CMakeLists.txt | 5 +- common/include/common/network/protocol.h | 488 ---- common/include/common/network/services.h | 994 ------- common/include/common/network/wire.h | 97 - common/src/network/protocol.c | 730 ------ common/src/network/services.c | 2285 ----------------- common/src/network/wire.c | 355 --- idd/LGCommon/LGCommon.vcxproj | 9 +- idd/LGCommon/LGCommon.vcxproj.filters | 5 +- .../transport/network/CNetworkServer.cpp | 2 +- idd/LGIdd/transport/network/NetworkSettings.h | 2 +- repos/LGProtocol | 2 +- 14 files changed, 10 insertions(+), 4968 deletions(-) delete mode 100644 common/include/common/network/protocol.h delete mode 100644 common/include/common/network/services.h delete mode 100644 common/include/common/network/wire.h delete mode 100644 common/src/network/protocol.c delete mode 100644 common/src/network/services.c delete mode 100644 common/src/network/wire.c diff --git a/client/transports/Network/connection.h b/client/transports/Network/connection.h index b1107247..a73772ff 100644 --- a/client/transports/Network/connection.h +++ b/client/transports/Network/connection.h @@ -24,7 +24,7 @@ #include "interface/transport.h" -#include "common/network/protocol.h" +#include #include #include diff --git a/client/transports/Network/network.c b/client/transports/Network/network.c index 13cfc867..d02f68ba 100644 --- a/client/transports/Network/network.c +++ b/client/transports/Network/network.c @@ -28,7 +28,7 @@ #include "common/debug.h" #include "common/event.h" #include "common/locking.h" -#include "common/network/protocol.h" +#include #include "common/option.h" #include diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 51a5ceaa..94386ea3 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -45,16 +45,13 @@ set(COMMON_SOURCES src/cpuinfo.c src/debug.c src/ll.c - src/network/protocol.c - src/network/services.c - src/network/wire.c ) add_library(lg_common STATIC ${COMMON_SOURCES}) target_link_libraries(lg_common PUBLIC lg_common_platform - LGProtocol::LGProtocol + LGProtocol::Network ) if(ENABLE_BACKTRACE) diff --git a/common/include/common/network/protocol.h b/common/include/common/network/protocol.h deleted file mode 100644 index c7fec9df..00000000 --- a/common/include/common/network/protocol.h +++ /dev/null @@ -1,488 +0,0 @@ -/** - * Looking Glass - * Copyright © 2017-2026 The Looking Glass Authors - * https://looking-glass.io - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _H_LG_COMMON_NETWORK_PROTOCOL_ -#define _H_LG_COMMON_NETWORK_PROTOCOL_ - -#include "common/network/wire.h" - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Encoded as the byte sequence "LGNW" by the little-endian wire writer. */ -#define LG_NET_WIRE_MAGIC UINT32_C(0x574E474C) -#define LG_NET_WIRE_VERSION_MAJOR 1U -#define LG_NET_WIRE_VERSION_MINOR 0U -#define LG_NET_ENVELOPE_WIRE_SIZE 64U -#define LG_NET_MAX_PAYLOAD_LENGTH (64U * 1024U * 1024U) -#define LG_NET_MESSAGE_VERSION_CURRENT 1U -#define LG_NET_MESSAGE_VERSION_INITIAL 1U -#define LG_NET_PROTOCOL_VERSION_CURRENT 1U -#define LG_NET_PROTOCOL_VERSION_MIN 1U -#define LG_NET_PROTOCOL_VERSION_MAX LG_NET_PROTOCOL_VERSION_CURRENT -#define LG_NET_MAX_CAPABILITY_RECORDS 64U -#define LG_NET_HELLO_NONCE_LENGTH 32U -#define LG_NET_PASSWORD_SALT_MAX_LENGTH 64U -#define LG_NET_PASSWORD_CHALLENGE_MAX_LENGTH 64U -#define LG_NET_PASSWORD_NONCE_MAX_LENGTH 64U -#define LG_NET_PASSWORD_PROOF_MAX_LENGTH 64U -/* 19527 is 0x4c47 (ASCII "LG") and is currently IANA-unassigned. */ -#define LG_NET_DEFAULT_PORT 19527U -#define LG_NET_ALPN "looking-glass/1" -#define LG_NET_ALPN_LENGTH (sizeof(LG_NET_ALPN) - 1U) - -#define LG_NET_CORE_VERSION_CURRENT 1U -#define LG_NET_CORE_VERSION_MIN 1U -#define LG_NET_CORE_VERSION_MAX LG_NET_CORE_VERSION_CURRENT -#define LG_NET_RECOVERY_VERSION_CURRENT 1U -#define LG_NET_RECOVERY_VERSION_MIN 1U -#define LG_NET_RECOVERY_VERSION_MAX LG_NET_RECOVERY_VERSION_CURRENT -#define LG_NET_VIDEO_VERSION_CURRENT 1U -#define LG_NET_VIDEO_VERSION_MIN 1U -#define LG_NET_VIDEO_VERSION_MAX LG_NET_VIDEO_VERSION_CURRENT -#define LG_NET_CURSOR_VERSION_CURRENT 1U -#define LG_NET_CURSOR_VERSION_MIN 1U -#define LG_NET_CURSOR_VERSION_MAX LG_NET_CURSOR_VERSION_CURRENT -#define LG_NET_INPUT_VERSION_CURRENT 1U -#define LG_NET_INPUT_VERSION_MIN 1U -#define LG_NET_INPUT_VERSION_MAX LG_NET_INPUT_VERSION_CURRENT -#define LG_NET_AUDIO_VERSION_CURRENT 1U -#define LG_NET_AUDIO_VERSION_MIN 1U -#define LG_NET_AUDIO_VERSION_MAX LG_NET_AUDIO_VERSION_CURRENT -#define LG_NET_CLIPBOARD_VERSION_CURRENT 1U -#define LG_NET_CLIPBOARD_VERSION_MIN 1U -#define LG_NET_CLIPBOARD_VERSION_MAX LG_NET_CLIPBOARD_VERSION_CURRENT -#define LG_NET_FILE_VERSION_CURRENT 1U -#define LG_NET_FILE_VERSION_MIN 1U -#define LG_NET_FILE_VERSION_MAX LG_NET_FILE_VERSION_CURRENT -/* Reserved now so a future USB implementation cannot collide with a service. */ -#define LG_NET_USB_VERSION_RESERVED 1U - -typedef uint16_t LGNetService; - -enum -{ - LG_NET_SERVICE_CORE = 1, - LG_NET_SERVICE_RECOVERY = 2, - LG_NET_SERVICE_VIDEO = 3, - LG_NET_SERVICE_CURSOR = 4, - LG_NET_SERVICE_INPUT = 5, - LG_NET_SERVICE_AUDIO = 6, - LG_NET_SERVICE_CLIPBOARD = 7, - LG_NET_SERVICE_FILE = 8, - LG_NET_SERVICE_USB = 9, -}; - -typedef uint16_t LGNetCoreMessage; - -enum -{ - LG_NET_CORE_MESSAGE_HELLO = 1, - LG_NET_CORE_MESSAGE_HELLO_ACK = 2, - LG_NET_CORE_MESSAGE_AUTH_CHALLENGE = 3, - LG_NET_CORE_MESSAGE_AUTH_RESPONSE = 4, - LG_NET_CORE_MESSAGE_AUTH_RESULT = 5, - LG_NET_CORE_MESSAGE_CAPABILITY = 6, - LG_NET_CORE_MESSAGE_CAPABILITIES_DONE = 7, - LG_NET_CORE_MESSAGE_SESSION_INFO = 8, - LG_NET_CORE_MESSAGE_STATUS = 9, - LG_NET_CORE_MESSAGE_PING = 10, - LG_NET_CORE_MESSAGE_PONG = 11, - LG_NET_CORE_MESSAGE_GOODBYE = 12, - LG_NET_CORE_MESSAGE_ERROR = 13, -}; - -typedef uint16_t LGNetRecoveryMessage; - -enum -{ - LG_NET_RECOVERY_MESSAGE_GET_INFO = 1, - LG_NET_RECOVERY_MESSAGE_INFO = 2, - LG_NET_RECOVERY_MESSAGE_REQUEST = 3, - LG_NET_RECOVERY_MESSAGE_STATUS = 4, -}; - -typedef uint16_t LGNetVideoMessage; - -enum -{ - LG_NET_VIDEO_MESSAGE_SUBSCRIBE = 1, - LG_NET_VIDEO_MESSAGE_UNSUBSCRIBE = 2, - LG_NET_VIDEO_MESSAGE_STREAM_CONFIG = 3, - LG_NET_VIDEO_MESSAGE_FRAME = 4, - LG_NET_VIDEO_MESSAGE_FRAME_FRAGMENT = 5, - LG_NET_VIDEO_MESSAGE_KEYFRAME_REQUEST = 6, - LG_NET_VIDEO_MESSAGE_SCHEDULE = 7, - LG_NET_VIDEO_MESSAGE_FEEDBACK = 8, - LG_NET_VIDEO_MESSAGE_STATUS = 9, -}; - -typedef uint16_t LGNetCursorMessage; - -enum -{ - LG_NET_CURSOR_MESSAGE_STATE = 1, - LG_NET_CURSOR_MESSAGE_POSITION = 2, - LG_NET_CURSOR_MESSAGE_SHAPE = 3, - LG_NET_CURSOR_MESSAGE_TRANSFORM = 4, - LG_NET_CURSOR_MESSAGE_STATUS = 5, -}; - -typedef uint16_t LGNetInputMessage; - -enum -{ - LG_NET_INPUT_MESSAGE_CLAIM = 1, - LG_NET_INPUT_MESSAGE_CLAIM_RESULT = 2, - LG_NET_INPUT_MESSAGE_KEEPALIVE = 3, - LG_NET_INPUT_MESSAGE_RELEASE = 4, - LG_NET_INPUT_MESSAGE_RESET = 5, - LG_NET_INPUT_MESSAGE_MOUSE_RELATIVE = 6, - LG_NET_INPUT_MESSAGE_MOUSE_ABSOLUTE = 7, - LG_NET_INPUT_MESSAGE_KEYBOARD = 8, - LG_NET_INPUT_MESSAGE_STATUS = 9, - LG_NET_INPUT_MESSAGE_KEYBOARD_LEDS = 10, -}; - -typedef uint16_t LGNetAudioMessage; - -enum -{ - LG_NET_AUDIO_MESSAGE_SUBSCRIBE = 1, - LG_NET_AUDIO_MESSAGE_STATUS = 2, - LG_NET_AUDIO_MESSAGE_PLAYBACK_START = 3, - LG_NET_AUDIO_MESSAGE_PLAYBACK_STOP = 4, - LG_NET_AUDIO_MESSAGE_PLAYBACK_DATA = 5, - LG_NET_AUDIO_MESSAGE_PLAYBACK_VOLUME = 6, - LG_NET_AUDIO_MESSAGE_PLAYBACK_MUTE = 7, - LG_NET_AUDIO_MESSAGE_CAPTURE_START = 8, - LG_NET_AUDIO_MESSAGE_CAPTURE_STOP = 9, - LG_NET_AUDIO_MESSAGE_CAPTURE_DATA = 10, - LG_NET_AUDIO_MESSAGE_CAPTURE_VOLUME = 11, - LG_NET_AUDIO_MESSAGE_CAPTURE_MUTE = 12, - LG_NET_AUDIO_MESSAGE_CLOCK_FEEDBACK = 13, - LG_NET_AUDIO_MESSAGE_KEEPALIVE = 14, - LG_NET_AUDIO_MESSAGE_RELEASE = 15, - LG_NET_AUDIO_MESSAGE_STATE_BARRIER = 16, - LG_NET_AUDIO_MESSAGE_STATE_ACK = 17, -}; - -typedef uint16_t LGNetClipboardMessage; - -enum -{ - LG_NET_CLIPBOARD_MESSAGE_CLAIM = 1, - LG_NET_CLIPBOARD_MESSAGE_CLAIM_RESULT = 2, - LG_NET_CLIPBOARD_MESSAGE_KEEPALIVE = 3, - LG_NET_CLIPBOARD_MESSAGE_RELEASE = 4, - LG_NET_CLIPBOARD_MESSAGE_OFFER = 5, - LG_NET_CLIPBOARD_MESSAGE_CLEAR = 6, - LG_NET_CLIPBOARD_MESSAGE_REQUEST = 7, - LG_NET_CLIPBOARD_MESSAGE_DATA_BEGIN = 8, - LG_NET_CLIPBOARD_MESSAGE_DATA_CHUNK = 9, - LG_NET_CLIPBOARD_MESSAGE_DATA_END = 10, - LG_NET_CLIPBOARD_MESSAGE_DATA_READY = 11, - LG_NET_CLIPBOARD_MESSAGE_CANCEL = 12, - LG_NET_CLIPBOARD_MESSAGE_STATUS = 13, -}; - -typedef uint16_t LGNetFileMessage; - -enum -{ - LG_NET_FILE_MESSAGE_OFFER = 1, - LG_NET_FILE_MESSAGE_ACQUIRE = 2, - LG_NET_FILE_MESSAGE_ACQUIRED = 3, - LG_NET_FILE_MESSAGE_RELEASE = 4, - LG_NET_FILE_MESSAGE_REQUEST = 5, - LG_NET_FILE_MESSAGE_ENTRY = 6, - LG_NET_FILE_MESSAGE_DATA_BEGIN = 7, - LG_NET_FILE_MESSAGE_DATA_CHUNK = 8, - LG_NET_FILE_MESSAGE_DATA_END = 9, - LG_NET_FILE_MESSAGE_DATA_READY = 10, - LG_NET_FILE_MESSAGE_CANCEL = 11, - LG_NET_FILE_MESSAGE_STATUS = 12, -}; - -/* Message IDs are reserved for the future USB service; their payloads are not - * defined by this protocol version. */ -typedef uint16_t LGNetUSBMessage; - -enum -{ - LG_NET_USB_MESSAGE_CAPABILITIES = 1, - LG_NET_USB_MESSAGE_DEVICE = 2, - LG_NET_USB_MESSAGE_CLAIM = 3, - LG_NET_USB_MESSAGE_CONTROL = 4, - LG_NET_USB_MESSAGE_ENDPOINT = 5, - LG_NET_USB_MESSAGE_CANCEL = 6, - LG_NET_USB_MESSAGE_RESET = 7, - LG_NET_USB_MESSAGE_STATUS = 8, -}; - -typedef uint32_t LGNetEnvelopeFlags; - -enum -{ - LG_NET_ENVELOPE_RESPONSE = 1U << 0, - LG_NET_ENVELOPE_FINAL = 1U << 1, - LG_NET_ENVELOPE_RELIABLE = 1U << 2, - LG_NET_ENVELOPE_DATAGRAM = 1U << 3, - LG_NET_ENVELOPE_ACK_REQUIRED = 1U << 4, - LG_NET_ENVELOPE_ERROR = 1U << 5, - LG_NET_ENVELOPE_EARLY_DATA = 1U << 6, -}; - -typedef struct LGNetEnvelope -{ - uint16_t wireMajor; - uint16_t wireMinor; - uint16_t headerSize; - LGNetService service; - uint16_t messageType; - uint16_t serviceVersion; - uint16_t messageVersion; - LGNetEnvelopeFlags flags; - uint32_t payloadLength; - uint64_t sessionEpoch; - uint64_t componentEpoch; - uint64_t sequence; - uint64_t requestID; -} -LGNetEnvelope; - -typedef struct LGNetPacketView -{ - LGNetEnvelope envelope; - const uint8_t * payload; - size_t payloadLength; - size_t wireSize; -} -LGNetPacketView; - -typedef uint16_t LGNetRole; - -enum -{ - LG_NET_ROLE_CLIENT = 1, - LG_NET_ROLE_SERVER = 2, -}; - -typedef uint16_t LGNetAuthMode; - -enum -{ - LG_NET_AUTH_NONE = 0, - LG_NET_AUTH_PASSWORD = 1, -}; - -#define LG_NET_AUTH_MODE_FLAG(mode) (UINT32_C(1) << (mode)) -#define LG_NET_AUTH_MODE_DEFAULT LG_NET_AUTH_NONE -#define LG_NET_AUTH_MODES_DEFAULT LG_NET_AUTH_MODE_FLAG(LG_NET_AUTH_NONE) -#define LG_NET_AUTH_MODES_KNOWN \ - (LG_NET_AUTH_MODE_FLAG(LG_NET_AUTH_NONE) | \ - LG_NET_AUTH_MODE_FLAG(LG_NET_AUTH_PASSWORD)) - -typedef struct LGNetHello -{ - LGNetRole role; - uint16_t protocolMin; - uint16_t protocolMax; - uint32_t authModes; - uint32_t maxPayloadLength; - uint32_t maxDatagramPayload; - uint32_t capabilityCount; - uint8_t nonce[LG_NET_HELLO_NONCE_LENGTH]; -} -LGNetHello; - -typedef uint32_t LGNetHelloAckFlags; - -enum -{ - LG_NET_HELLO_ACK_RESUMED = 1U << 0, -}; - -typedef struct LGNetHelloAck -{ - uint16_t protocolVersion; - LGNetAuthMode authMode; - LGNetHelloAckFlags flags; - uint32_t maxPayloadLength; - uint32_t maxDatagramPayload; - uint32_t capabilityCount; - uint64_t sessionEpoch; - uint8_t nonce[LG_NET_HELLO_NONCE_LENGTH]; -} -LGNetHelloAck; - -#define LG_NET_HELLO_WIRE_SIZE 56U -#define LG_NET_HELLO_ACK_WIRE_SIZE 64U - -typedef uint16_t LGNetCapabilityFlags; - -enum -{ - LG_NET_CAPABILITY_REQUIRED = 1U << 0, - LG_NET_CAPABILITY_SELECTED = 1U << 1, - LG_NET_CAPABILITY_RELIABLE = 1U << 2, - LG_NET_CAPABILITY_DATAGRAM = 1U << 3, - LG_NET_CAPABILITY_BULK = 1U << 4, - LG_NET_CAPABILITY_MULTI_CLIENT = 1U << 5, -}; - -typedef struct LGNetCapability -{ - LGNetService service; - uint16_t versionMin; - uint16_t versionMax; - LGNetCapabilityFlags flags; - uint64_t features; - uint32_t maxPayloadLength; - uint32_t maxDatagramPayload; - uint16_t maxBidirectionalStreams; - uint16_t maxUnidirectionalStreams; -} -LGNetCapability; - -#define LG_NET_CAPABILITY_WIRE_SIZE 32U - -/* Password proofs are carried by this library but derived by the application. - * A password must never be sent on the wire. The negotiated algorithm defines - * the proof and transcript binding; cryptography is outside this wire codec. */ -typedef uint16_t LGNetPasswordAlgorithm; - -enum -{ - LG_NET_PASSWORD_PBKDF2_HMAC_SHA256 = 1, -}; - -typedef struct LGNetPasswordChallenge -{ - LGNetPasswordAlgorithm algorithm; - uint32_t rounds; - uint16_t saltLength; - uint16_t challengeLength; - uint8_t salt [LG_NET_PASSWORD_SALT_MAX_LENGTH]; - uint8_t challenge[LG_NET_PASSWORD_CHALLENGE_MAX_LENGTH]; -} -LGNetPasswordChallenge; - -typedef struct LGNetPasswordResponse -{ - LGNetPasswordAlgorithm algorithm; - uint16_t nonceLength; - uint16_t proofLength; - uint8_t nonce[LG_NET_PASSWORD_NONCE_MAX_LENGTH]; - uint8_t proof[LG_NET_PASSWORD_PROOF_MAX_LENGTH]; -} -LGNetPasswordResponse; - -typedef uint16_t LGNetAuthResultCode; - -enum -{ - LG_NET_AUTH_RESULT_ACCEPTED = 1, - LG_NET_AUTH_RESULT_REJECTED = 2, - LG_NET_AUTH_RESULT_UNSUPPORTED = 3, - LG_NET_AUTH_RESULT_ERROR = 4, -}; - -typedef struct LGNetAuthResult -{ - LGNetAuthResultCode result; - uint16_t proofLength; - uint32_t retryAfterMs; - uint8_t proof[LG_NET_PASSWORD_PROOF_MAX_LENGTH]; -} -LGNetAuthResult; - -#define LG_NET_PASSWORD_CHALLENGE_HEADER_SIZE 16U -#define LG_NET_PASSWORD_RESPONSE_HEADER_SIZE 12U -#define LG_NET_AUTH_RESULT_HEADER_SIZE 12U - -void lgNetEnvelopeInit(LGNetEnvelope * envelope, LGNetService service, - uint16_t messageType, uint16_t serviceVersion, - uint16_t messageVersion); -bool lgNetEnvelopeEncode(void * data, size_t size, - const LGNetEnvelope * envelope); -LGNetParseResult lgNetEnvelopeDecode(LGNetEnvelope * envelope, - const void * data, size_t size); -bool lgNetPacketSize(const LGNetEnvelope * envelope, size_t * size); -bool lgNetPacketEncode(void * data, size_t size, - const LGNetEnvelope * envelope, const void * payload); -LGNetParseResult lgNetPacketDecode(LGNetPacketView * packet, - const void * data, size_t size); - -bool lgNetServiceKnown(LGNetService service); -bool lgNetMessageKnown(LGNetService service, uint16_t messageType); - -void lgNetHelloInit(LGNetHello * hello, LGNetRole role); -bool lgNetHelloValid(const LGNetHello * hello); -bool lgNetHelloEncode(void * data, size_t size, const LGNetHello * hello); -LGNetParseResult lgNetHelloDecode(LGNetHello * hello, - const void * data, size_t size); - -void lgNetHelloAckInit(LGNetHelloAck * hello, uint64_t sessionEpoch); -bool lgNetHelloAckValid(const LGNetHelloAck * hello); -bool lgNetHelloAckEncode( - void * data, size_t size, const LGNetHelloAck * hello); -LGNetParseResult lgNetHelloAckDecode(LGNetHelloAck * hello, - const void * data, size_t size); - -bool lgNetCapabilityValid(const LGNetCapability * capability); -bool lgNetCapabilityEncode(void * data, size_t size, - const LGNetCapability * capability); -LGNetParseResult lgNetCapabilityDecode(LGNetCapability * capability, - const void * data, size_t size); - -size_t lgNetPasswordChallengeSize( - const LGNetPasswordChallenge * challenge); -bool lgNetPasswordChallengeValid( - const LGNetPasswordChallenge * challenge); -bool lgNetPasswordChallengeEncode(void * data, size_t size, - const LGNetPasswordChallenge * challenge); -LGNetParseResult lgNetPasswordChallengeDecode( - LGNetPasswordChallenge * challenge, const void * data, size_t size); - -size_t lgNetPasswordResponseSize(const LGNetPasswordResponse * response); -bool lgNetPasswordResponseValid(const LGNetPasswordResponse * response); -bool lgNetPasswordResponseEncode(void * data, size_t size, - const LGNetPasswordResponse * response); -LGNetParseResult lgNetPasswordResponseDecode( - LGNetPasswordResponse * response, const void * data, size_t size); - -size_t lgNetAuthResultSize(const LGNetAuthResult * result); -bool lgNetAuthResultValid(const LGNetAuthResult * result); -bool lgNetAuthResultEncode( - void * data, size_t size, const LGNetAuthResult * result); -LGNetParseResult lgNetAuthResultDecode(LGNetAuthResult * result, - const void * data, size_t size); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/include/common/network/services.h b/common/include/common/network/services.h deleted file mode 100644 index aa290cdc..00000000 --- a/common/include/common/network/services.h +++ /dev/null @@ -1,994 +0,0 @@ -/** - * Looking Glass - * Copyright © 2017-2026 The Looking Glass Authors - * https://looking-glass.io - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _H_LG_COMMON_NETWORK_SERVICES_ -#define _H_LG_COMMON_NETWORK_SERVICES_ - -#include "common/network/protocol.h" - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Variable-length decoders return borrowed views into their input buffer. The - * caller must keep that buffer alive while using the decoded payload. */ - -/* Fixed boundaries must not move when a service's current version changes. */ -#define LG_NET_VIDEO_PYROWAVE_INTRODUCED_SERVICE_VERSION 1U -#define LG_NET_CURSOR_SHAPE_INTRODUCED_SERVICE_VERSION 1U -#define LG_NET_INPUT_LEDS_INTRODUCED_SERVICE_VERSION 1U -#define LG_NET_AUDIO_PCM_INTRODUCED_SERVICE_VERSION 1U -#define LG_NET_CLIPBOARD_CHUNK_INTRODUCED_SERVICE_VERSION 1U -#define LG_NET_FILE_CHUNK_INTRODUCED_SERVICE_VERSION 1U -#define LG_NET_USB_RESERVED_INTRODUCED_SERVICE_VERSION 1U - -#define LG_NET_VIDEO_MAX_WIDTH 32768U -#define LG_NET_VIDEO_MAX_HEIGHT 32768U -#define LG_NET_VIDEO_MAX_PLANES 4U -#define LG_NET_VIDEO_STREAM_CONFIG_WIRE_SIZE 60U -#define LG_NET_VIDEO_FRAME_HEADER_WIRE_SIZE 56U -#define LG_NET_VIDEO_FRAGMENT_HEADER_WIRE_SIZE 40U -#define LG_NET_VIDEO_FEEDBACK_WIRE_SIZE 56U -#define LG_NET_VIDEO_MAX_FRAME_LENGTH \ - (LG_NET_MAX_PAYLOAD_LENGTH - LG_NET_VIDEO_FRAME_HEADER_WIRE_SIZE) -#define LG_NET_VIDEO_MAX_FRAGMENT_LENGTH 65535U -#define LG_NET_VIDEO_MAX_FRAGMENTS 65535U -#define LG_NET_VIDEO_MAX_BLOCKS 65535U - -#define LG_NET_CURSOR_MAX_WIDTH 4096U -#define LG_NET_CURSOR_MAX_HEIGHT 4096U -#define LG_NET_CURSOR_MAX_SHAPE_LENGTH (16U * 1024U * 1024U) -#define LG_NET_CURSOR_POSITION_WIRE_SIZE 40U -#define LG_NET_CURSOR_SHAPE_HEADER_WIRE_SIZE 40U - -#define LG_NET_INPUT_CLAIM_WIRE_SIZE 24U -#define LG_NET_INPUT_STATUS_WIRE_SIZE 32U -#define LG_NET_INPUT_RELATIVE_WIRE_SIZE 40U -#define LG_NET_INPUT_ABSOLUTE_WIRE_SIZE 48U -#define LG_NET_INPUT_KEYBOARD_WIRE_SIZE 32U -#define LG_NET_INPUT_LEDS_WIRE_SIZE 16U -#define LG_NET_INPUT_ABSOLUTE_MAX_WIDTH 32768U -#define LG_NET_INPUT_ABSOLUTE_MAX_HEIGHT 32768U -#define LG_NET_INPUT_KEYBOARD_MODIFIER_MASK UINT32_C(0x000000FF) - -#define LG_NET_AUDIO_MAX_CHANNELS 32U -#define LG_NET_AUDIO_MAX_SAMPLE_RATE 768000U -#define LG_NET_AUDIO_MAX_PACKET_FRAMES 16384U -#define LG_NET_AUDIO_MAX_DATA_LENGTH (4U * 1024U * 1024U) -#define LG_NET_AUDIO_FORMAT_WIRE_SIZE 40U -#define LG_NET_AUDIO_DATA_HEADER_WIRE_SIZE 48U -#define LG_NET_AUDIO_STATE_WIRE_SIZE 32U -#define LG_NET_AUDIO_CLOCK_FEEDBACK_WIRE_SIZE 48U - -#define LG_NET_CLIPBOARD_MAX_MIME_LENGTH 255U -#define LG_NET_CLIPBOARD_MAX_FORMATS 256U -#define LG_NET_CLIPBOARD_MAX_CHUNK_LENGTH (4U * 1024U * 1024U) -#define LG_NET_CLIPBOARD_CLAIM_WIRE_SIZE 24U -#define LG_NET_CLIPBOARD_OFFER_HEADER_WIRE_SIZE 40U -#define LG_NET_CLIPBOARD_REQUEST_WIRE_SIZE 32U -#define LG_NET_CLIPBOARD_CHUNK_HEADER_WIRE_SIZE 40U -#define LG_NET_CLIPBOARD_STATUS_WIRE_SIZE 32U - -#define LG_NET_FILE_MAX_LABEL_LENGTH 1024U -#define LG_NET_FILE_MAX_PATH_LENGTH 4096U -#define LG_NET_FILE_MAX_LINK_TARGET_LENGTH 4096U -#define LG_NET_FILE_MAX_ENTRIES 1048576U -#define LG_NET_FILE_MAX_CHUNK_LENGTH (4U * 1024U * 1024U) -#define LG_NET_FILE_OFFER_HEADER_WIRE_SIZE 32U -#define LG_NET_FILE_ENTRY_HEADER_WIRE_SIZE 56U -#define LG_NET_FILE_REQUEST_WIRE_SIZE 40U -#define LG_NET_FILE_CHUNK_HEADER_WIRE_SIZE 48U -#define LG_NET_FILE_STATUS_WIRE_SIZE 40U - -#define LG_NET_USB_RESERVED_HEADER_WIRE_SIZE 32U -#define LG_NET_USB_MAX_RESERVED_PAYLOAD_LENGTH \ - (LG_NET_MAX_PAYLOAD_LENGTH - LG_NET_USB_RESERVED_HEADER_WIRE_SIZE) - -typedef uint16_t LGNetVideoCodec; - -enum -{ - LG_NET_VIDEO_CODEC_PYROWAVE = 1, -}; - -typedef uint16_t LGNetVideoPixelFormat; - -enum -{ - LG_NET_VIDEO_PIXEL_FORMAT_NV12 = 1, - LG_NET_VIDEO_PIXEL_FORMAT_P010 = 2, - LG_NET_VIDEO_PIXEL_FORMAT_YUV420P8 = 3, - LG_NET_VIDEO_PIXEL_FORMAT_YUV420P10 = 4, - LG_NET_VIDEO_PIXEL_FORMAT_YUV422P8 = 5, - LG_NET_VIDEO_PIXEL_FORMAT_YUV422P10 = 6, - LG_NET_VIDEO_PIXEL_FORMAT_YUV444P8 = 7, - LG_NET_VIDEO_PIXEL_FORMAT_YUV444P10 = 8, - LG_NET_VIDEO_PIXEL_FORMAT_YUV444P16F = 9, -}; - -typedef uint8_t LGNetVideoChromaSubsampling; - -enum -{ - LG_NET_VIDEO_CHROMA_420 = 1, - LG_NET_VIDEO_CHROMA_422 = 2, - LG_NET_VIDEO_CHROMA_444 = 3, -}; - -typedef uint8_t LGNetColorPrimaries; - -enum -{ - LG_NET_COLOR_PRIMARIES_BT601 = 1, - LG_NET_COLOR_PRIMARIES_BT709 = 2, - LG_NET_COLOR_PRIMARIES_BT2020 = 3, -}; - -typedef uint8_t LGNetColorTransfer; - -enum -{ - LG_NET_COLOR_TRANSFER_LINEAR = 1, - LG_NET_COLOR_TRANSFER_SRGB = 2, - LG_NET_COLOR_TRANSFER_BT709 = 3, - LG_NET_COLOR_TRANSFER_PQ = 4, - LG_NET_COLOR_TRANSFER_HLG = 5, -}; - -typedef uint8_t LGNetColorMatrix; - -enum -{ - LG_NET_COLOR_MATRIX_BT601 = 1, - LG_NET_COLOR_MATRIX_BT709 = 2, - LG_NET_COLOR_MATRIX_BT2020 = 3, - LG_NET_COLOR_MATRIX_RGB = 4, -}; - -typedef uint8_t LGNetColorRange; - -enum -{ - LG_NET_COLOR_RANGE_LIMITED = 1, - LG_NET_COLOR_RANGE_FULL = 2, -}; - -typedef uint16_t LGNetVideoStreamFlags; - -enum -{ - LG_NET_VIDEO_STREAM_HDR = 1U << 0, - LG_NET_VIDEO_STREAM_ALPHA = 1U << 1, - LG_NET_VIDEO_STREAM_GPU_PLANES_ONLY = 1U << 2, - LG_NET_VIDEO_STREAM_DATAGRAMS = 1U << 3, -}; - -typedef struct LGNetVideoStreamConfig -{ - uint32_t streamID; - LGNetVideoCodec codec; - uint16_t codecVersion; - uint64_t configEpoch; - uint32_t width; - uint32_t height; - uint32_t refreshNumerator; - uint32_t refreshDenominator; - LGNetVideoPixelFormat pixelFormat; - LGNetVideoChromaSubsampling chromaSubsampling; - LGNetColorPrimaries colorPrimaries; - LGNetColorTransfer colorTransfer; - LGNetColorMatrix colorMatrix; - LGNetColorRange colorRange; - uint8_t planeCount; - uint8_t bitDepth; - LGNetVideoStreamFlags flags; - uint32_t maxFrameLength; - uint32_t maxFragmentLength; - uint32_t maxFrameLatencyMs; -} -LGNetVideoStreamConfig; - -typedef uint16_t LGNetVideoFrameFlags; - -enum -{ - LG_NET_VIDEO_FRAME_KEYFRAME = 1U << 0, - LG_NET_VIDEO_FRAME_DISCONTINUITY = 1U << 1, - LG_NET_VIDEO_FRAME_END_OF_STREAM = 1U << 2, - LG_NET_VIDEO_FRAME_HAS_CHECKSUM = 1U << 3, -}; - -/* checksum is CRC-32C (Castagnoli), reflected polynomial 0x82f63b78, with - * initial and final XOR 0xffffffff, over exactly encodedLength bytes of data. - * It is zero when LG_NET_VIDEO_FRAME_HAS_CHECKSUM is clear. */ -typedef struct LGNetVideoFrame -{ - uint32_t streamID; - LGNetVideoCodec codec; - LGNetVideoFrameFlags flags; - uint64_t configEpoch; - uint64_t frameID; - uint64_t captureTimestampNs; - uint64_t presentationTimestampNs; - uint32_t encodedLength; - uint16_t blockCount; - uint16_t fragmentCount; - uint32_t deadlineMs; - uint32_t checksum; - const uint8_t * data; -} -LGNetVideoFrame; - -typedef uint16_t LGNetVideoFragmentFlags; - -enum -{ - LG_NET_VIDEO_FRAGMENT_BLOCK_START = 1U << 0, - LG_NET_VIDEO_FRAGMENT_BLOCK_END = 1U << 1, - LG_NET_VIDEO_FRAGMENT_FRAME_END = 1U << 2, - LG_NET_VIDEO_FRAGMENT_RECOVERY = 1U << 3, -}; - -typedef struct LGNetVideoFragment -{ - uint32_t streamID; - uint64_t configEpoch; - uint64_t frameID; - uint32_t frameLength; - uint32_t offset; - uint16_t fragmentIndex; - uint16_t fragmentCount; - uint16_t blockIndex; - uint16_t blockCount; - uint16_t payloadLength; - LGNetVideoFragmentFlags flags; - const uint8_t * payload; -} -LGNetVideoFragment; - -typedef uint32_t LGNetVideoFeedbackFlags; - -enum -{ - LG_NET_VIDEO_FEEDBACK_REQUEST_KEYFRAME = 1U << 0, - LG_NET_VIDEO_FEEDBACK_CONGESTED = 1U << 1, - LG_NET_VIDEO_FEEDBACK_DECODER_STALLED = 1U << 2, -}; - -typedef struct LGNetVideoFeedback -{ - uint32_t streamID; - LGNetVideoFeedbackFlags flags; - uint64_t lastCompleteFrameID; - uint64_t highestSeenFrameID; - uint64_t lastDecodedFrameID; - uint32_t lostFrames; - uint32_t lostFragments; - uint32_t receiveQueueUs; - uint32_t decodeQueueUs; - uint32_t roundTripUs; -} -LGNetVideoFeedback; - -typedef uint32_t LGNetCursorPositionFlags; - -enum -{ - LG_NET_CURSOR_POSITION_VISIBLE = 1U << 0, - LG_NET_CURSOR_POSITION_RELATIVE = 1U << 1, -}; - -typedef struct LGNetCursorPosition -{ - uint64_t updateID; - uint64_t timestampNs; - int32_t x; - int32_t y; - uint32_t desktopWidth; - uint32_t desktopHeight; - LGNetCursorPositionFlags flags; - uint32_t displayID; -} -LGNetCursorPosition; - -typedef uint16_t LGNetCursorFormat; - -enum -{ - LG_NET_CURSOR_FORMAT_BGRA8_PREMULTIPLIED = 1, - LG_NET_CURSOR_FORMAT_RGBA8_PREMULTIPLIED = 2, - LG_NET_CURSOR_FORMAT_MASKED_COLOR = 3, - LG_NET_CURSOR_FORMAT_MONOCHROME = 4, -}; - -typedef uint16_t LGNetCursorShapeFlags; - -enum -{ - LG_NET_CURSOR_SHAPE_HIDDEN = 1U << 0, - LG_NET_CURSOR_SHAPE_ANIMATED = 1U << 1, -}; - -typedef struct LGNetCursorShape -{ - uint64_t shapeID; - uint32_t width; - uint32_t height; - uint32_t pitch; - uint32_t dataLength; - LGNetCursorFormat format; - LGNetCursorShapeFlags flags; - uint32_t hotspotX; - uint32_t hotspotY; - uint32_t frameDurationMs; - const uint8_t * data; -} -LGNetCursorShape; - -typedef uint32_t LGNetInputClaimFlags; - -enum -{ - LG_NET_INPUT_CLAIM_KEYBOARD = 1U << 0, - LG_NET_INPUT_CLAIM_POINTER = 1U << 1, - LG_NET_INPUT_CLAIM_EXCLUSIVE = 1U << 2, -}; - -typedef struct LGNetInputClaim -{ - uint64_t claimantID; - uint64_t claimEpoch; - uint32_t leaseMs; - LGNetInputClaimFlags flags; -} -LGNetInputClaim; - -typedef uint32_t LGNetInputStatusCode; - -enum -{ - LG_NET_INPUT_STATUS_ACCEPTED = 1, - LG_NET_INPUT_STATUS_REJECTED = 2, - LG_NET_INPUT_STATUS_RELEASED = 3, - LG_NET_INPUT_STATUS_EXPIRED = 4, - LG_NET_INPUT_STATUS_UNSUPPORTED = 5, - LG_NET_INPUT_STATUS_ERROR = 6, -}; - -typedef struct LGNetInputStatus -{ - uint64_t claimEpoch; - uint64_t lastSequence; - LGNetInputStatusCode status; - LGNetInputClaimFlags flags; - uint32_t leaseRemainingMs; - uint32_t detail; -} -LGNetInputStatus; - -typedef uint32_t LGNetPointerButtons; - -enum -{ - LG_NET_POINTER_BUTTON_LEFT = 1U << 0, - LG_NET_POINTER_BUTTON_RIGHT = 1U << 1, - LG_NET_POINTER_BUTTON_MIDDLE = 1U << 2, - LG_NET_POINTER_BUTTON_BACK = 1U << 3, - LG_NET_POINTER_BUTTON_FORWARD = 1U << 4, -}; - -typedef struct LGNetInputRelative -{ - uint64_t sequence; - uint64_t timestampNs; - int32_t deltaX; - int32_t deltaY; - int32_t wheelX; - int32_t wheelY; - LGNetPointerButtons buttons; - LGNetPointerButtons changedButtons; -} -LGNetInputRelative; - -typedef struct LGNetInputAbsolute -{ - uint64_t sequence; - uint64_t timestampNs; - int32_t x; - int32_t y; - uint32_t width; - uint32_t height; - int32_t wheelX; - int32_t wheelY; - LGNetPointerButtons buttons; - LGNetPointerButtons changedButtons; -} -LGNetInputAbsolute; - -typedef uint16_t LGNetKeyboardFlags; - -enum -{ - LG_NET_KEYBOARD_DOWN = 1U << 0, - LG_NET_KEYBOARD_REPEAT = 1U << 1, - LG_NET_KEYBOARD_EXTENDED = 1U << 2, - LG_NET_KEYBOARD_E1 = 1U << 3, -}; - -/* modifiers uses the USB HID keyboard modifier byte in its low eight bits; - * all other bits are reserved and must be zero. */ -typedef struct LGNetInputKeyboard -{ - uint64_t sequence; - uint64_t timestampNs; - uint16_t usagePage; - uint16_t usage; - uint16_t scanCode; - LGNetKeyboardFlags flags; - uint32_t modifiers; -} -LGNetInputKeyboard; - -typedef uint32_t LGNetKeyboardLEDs; - -enum -{ - LG_NET_KEYBOARD_LED_NUM_LOCK = 1U << 0, - LG_NET_KEYBOARD_LED_CAPS_LOCK = 1U << 1, - LG_NET_KEYBOARD_LED_SCROLL_LOCK = 1U << 2, - LG_NET_KEYBOARD_LED_COMPOSE = 1U << 3, - LG_NET_KEYBOARD_LED_KANA = 1U << 4, -}; - -typedef struct LGNetInputLEDs -{ - uint64_t sequence; - LGNetKeyboardLEDs state; - LGNetKeyboardLEDs validMask; -} -LGNetInputLEDs; - -typedef uint16_t LGNetAudioDirection; - -enum -{ - LG_NET_AUDIO_DIRECTION_PLAYBACK = 1, - LG_NET_AUDIO_DIRECTION_CAPTURE = 2, -}; - -typedef uint16_t LGNetAudioSampleFormat; - -enum -{ - LG_NET_AUDIO_SAMPLE_S16_LE = 1, - LG_NET_AUDIO_SAMPLE_S24_LE = 2, - LG_NET_AUDIO_SAMPLE_S32_LE = 3, - LG_NET_AUDIO_SAMPLE_F32_LE = 4, -}; - -typedef uint32_t LGNetAudioFormatFlags; - -enum -{ - LG_NET_AUDIO_FORMAT_INTERLEAVED = 1U << 0, -}; - -typedef struct LGNetAudioFormat -{ - uint32_t streamID; - LGNetAudioDirection direction; - LGNetAudioSampleFormat sampleFormat; - uint64_t formatEpoch; - uint32_t sampleRate; - uint16_t channels; - uint16_t framesPerPacket; - uint32_t channelMask; - LGNetAudioFormatFlags flags; - uint32_t maxPacketFrames; -} -LGNetAudioFormat; - -typedef uint16_t LGNetAudioDataFlags; - -enum -{ - LG_NET_AUDIO_DATA_DISCONTINUITY = 1U << 0, - LG_NET_AUDIO_DATA_SILENT = 1U << 1, - LG_NET_AUDIO_DATA_END_OF_STREAM = 1U << 2, -}; - -typedef struct LGNetAudioData -{ - uint32_t streamID; - LGNetAudioDirection direction; - LGNetAudioDataFlags flags; - uint64_t formatEpoch; - uint64_t packetID; - uint64_t timestampNs; - uint64_t startFrame; - uint32_t frameCount; - uint32_t dataLength; - const uint8_t * data; -} -LGNetAudioData; - -typedef uint16_t LGNetAudioStateCode; - -enum -{ - LG_NET_AUDIO_STATE_STOPPED = 1, - LG_NET_AUDIO_STATE_RUNNING = 2, - LG_NET_AUDIO_STATE_PAUSED = 3, - LG_NET_AUDIO_STATE_ERROR = 4, -}; - -typedef uint32_t LGNetAudioStateFlags; - -enum -{ - LG_NET_AUDIO_STATE_MUTED = 1U << 0, - LG_NET_AUDIO_STATE_FORMAT_ACTIVE = 1U << 1, -}; - -typedef struct LGNetAudioState -{ - uint32_t streamID; - LGNetAudioDirection direction; - LGNetAudioStateCode state; - uint64_t stateSequence; - uint64_t formatEpoch; - int32_t volumeMillibels; - LGNetAudioStateFlags flags; -} -LGNetAudioState; - -typedef struct LGNetAudioClockFeedback -{ - uint32_t streamID; - LGNetAudioDirection direction; - uint64_t formatEpoch; - uint64_t packetID; - uint64_t framePosition; - uint64_t timestampNs; - int32_t queuedFrames; - int32_t driftPpm; -} -LGNetAudioClockFeedback; - -typedef uint32_t LGNetClipboardClaimFlags; - -enum -{ - LG_NET_CLIPBOARD_CLAIM_READ = 1U << 0, - LG_NET_CLIPBOARD_CLAIM_WRITE = 1U << 1, -}; - -typedef struct LGNetClipboardClaim -{ - uint64_t ownerID; - uint64_t claimEpoch; - uint32_t leaseMs; - LGNetClipboardClaimFlags flags; -} -LGNetClipboardClaim; - -typedef uint16_t LGNetClipboardOfferFlags; - -enum -{ - LG_NET_CLIPBOARD_OFFER_LAZY = 1U << 0, - LG_NET_CLIPBOARD_OFFER_SENSITIVE = 1U << 1, -}; - -typedef struct LGNetClipboardOffer -{ - uint64_t offerID; - uint64_t serial; - uint64_t estimatedSize; - uint32_t formatIndex; - uint32_t formatCount; - uint16_t mimeLength; - LGNetClipboardOfferFlags flags; - const uint8_t * mime; -} -LGNetClipboardOffer; - -typedef struct LGNetClipboardRequest -{ - uint64_t offerID; - uint64_t requestID; - uint32_t formatIndex; - uint32_t maxChunkLength; - uint64_t offset; -} -LGNetClipboardRequest; - -typedef uint16_t LGNetClipboardChunkFlags; - -enum -{ - LG_NET_CLIPBOARD_CHUNK_FIRST = 1U << 0, - LG_NET_CLIPBOARD_CHUNK_FINAL = 1U << 1, -}; - -typedef struct LGNetClipboardChunk -{ - uint64_t requestID; - uint64_t offerID; - uint64_t offset; - uint64_t totalLength; - uint32_t dataLength; - LGNetClipboardChunkFlags flags; - const uint8_t * data; -} -LGNetClipboardChunk; - -typedef uint32_t LGNetClipboardStatusCode; - -enum -{ - LG_NET_CLIPBOARD_STATUS_OK = 1, - LG_NET_CLIPBOARD_STATUS_NOT_FOUND = 2, - LG_NET_CLIPBOARD_STATUS_UNSUPPORTED = 3, - LG_NET_CLIPBOARD_STATUS_CANCELLED = 4, - LG_NET_CLIPBOARD_STATUS_BUSY = 5, - LG_NET_CLIPBOARD_STATUS_ERROR = 6, -}; - -typedef struct LGNetClipboardStatus -{ - uint64_t requestID; - uint64_t offerID; - LGNetClipboardStatusCode status; - uint32_t detail; - uint64_t processedLength; -} -LGNetClipboardStatus; - -typedef uint32_t LGNetFileOfferFlags; - -enum -{ - LG_NET_FILE_OFFER_COPY = 1U << 0, - LG_NET_FILE_OFFER_MOVE = 1U << 1, - LG_NET_FILE_OFFER_RECURSIVE = 1U << 2, -}; - -typedef struct LGNetFileOffer -{ - uint64_t offerID; - uint64_t totalBytes; - uint32_t entryCount; - LGNetFileOfferFlags flags; - uint16_t labelLength; - const uint8_t * label; -} -LGNetFileOffer; - -typedef uint16_t LGNetFileEntryType; - -enum -{ - LG_NET_FILE_ENTRY_REGULAR = 1, - LG_NET_FILE_ENTRY_DIRECTORY = 2, - LG_NET_FILE_ENTRY_SYMLINK = 3, -}; - -typedef uint16_t LGNetFileEntryFlags; - -enum -{ - LG_NET_FILE_ENTRY_EXECUTABLE = 1U << 0, - LG_NET_FILE_ENTRY_HIDDEN = 1U << 1, -}; - -/* File path fields are strict UTF-8 without a trailing NUL. They are relative - * to a receiver-selected transfer root and use '/' as their only separator. - * Receivers must reject absolute paths, empty, '.' or '..' components, and - * platform-native alternate separators before accessing the filesystem. The - * same traversal rules apply to symbolic-link targets. */ -typedef struct LGNetFileEntry -{ - uint64_t offerID; - uint64_t entryID; - uint64_t parentID; - uint64_t size; - uint64_t modifiedNs; - uint32_t mode; - LGNetFileEntryType type; - LGNetFileEntryFlags flags; - uint16_t pathLength; - uint16_t linkTargetLength; - const uint8_t * path; - const uint8_t * linkTarget; -} -LGNetFileEntry; - -typedef uint32_t LGNetFileRequestFlags; - -enum -{ - LG_NET_FILE_REQUEST_METADATA = 1U << 0, - LG_NET_FILE_REQUEST_DATA = 1U << 1, -}; - -typedef struct LGNetFileRequest -{ - uint64_t requestID; - uint64_t offerID; - uint64_t entryID; - uint64_t offset; - uint32_t length; - LGNetFileRequestFlags flags; -} -LGNetFileRequest; - -typedef uint16_t LGNetFileChunkFlags; - -enum -{ - LG_NET_FILE_CHUNK_FIRST = 1U << 0, - LG_NET_FILE_CHUNK_FINAL = 1U << 1, -}; - -typedef struct LGNetFileChunk -{ - uint64_t requestID; - uint64_t offerID; - uint64_t entryID; - uint64_t offset; - uint64_t totalLength; - uint32_t dataLength; - LGNetFileChunkFlags flags; - const uint8_t * data; -} -LGNetFileChunk; - -typedef uint32_t LGNetFileStatusCode; - -enum -{ - LG_NET_FILE_STATUS_OK = 1, - LG_NET_FILE_STATUS_NOT_FOUND = 2, - LG_NET_FILE_STATUS_DENIED = 3, - LG_NET_FILE_STATUS_CANCELLED = 4, - LG_NET_FILE_STATUS_INVALID = 5, - LG_NET_FILE_STATUS_UNSUPPORTED = 6, - LG_NET_FILE_STATUS_ERROR = 7, -}; - -typedef struct LGNetFileStatus -{ - uint64_t requestID; - uint64_t offerID; - uint64_t entryID; - LGNetFileStatusCode status; - uint32_t detail; - uint64_t transferredLength; -} -LGNetFileStatus; - -/* This header reserves framing only. It deliberately defines no USB - * redirection operations or device semantics. */ -typedef uint16_t LGNetUSBReservedFlags; - -enum -{ - LG_NET_USB_RESERVED_RESPONSE = 1U << 0, - LG_NET_USB_RESERVED_FINAL = 1U << 1, -}; - -typedef struct LGNetUSBReserved -{ - uint16_t version; - uint16_t headerSize; - uint16_t messageType; - LGNetUSBReservedFlags flags; - uint64_t requestID; - uint64_t sequence; - uint32_t payloadLength; - const uint8_t * payload; -} -LGNetUSBReserved; - -bool lgNetVideoStreamConfigValid(const LGNetVideoStreamConfig * config); -bool lgNetVideoStreamConfigEncode(void * data, size_t size, - const LGNetVideoStreamConfig * config); -LGNetParseResult lgNetVideoStreamConfigDecode( - LGNetVideoStreamConfig * config, const void * data, size_t size); - -size_t lgNetVideoFrameSize(const LGNetVideoFrame * frame); -bool lgNetVideoFrameValid(const LGNetVideoFrame * frame); -bool lgNetVideoFrameEncode( - void * data, size_t size, const LGNetVideoFrame * frame); -LGNetParseResult lgNetVideoFrameDecode( - LGNetVideoFrame * frame, const void * data, size_t size); - -size_t lgNetVideoFragmentSize(const LGNetVideoFragment * fragment); -bool lgNetVideoFragmentValid(const LGNetVideoFragment * fragment); -bool lgNetVideoFragmentEncode( - void * data, size_t size, const LGNetVideoFragment * fragment); -LGNetParseResult lgNetVideoFragmentDecode( - LGNetVideoFragment * fragment, const void * data, size_t size); - -bool lgNetVideoFeedbackValid(const LGNetVideoFeedback * feedback); -bool lgNetVideoFeedbackEncode( - void * data, size_t size, const LGNetVideoFeedback * feedback); -LGNetParseResult lgNetVideoFeedbackDecode( - LGNetVideoFeedback * feedback, const void * data, size_t size); - -bool lgNetCursorPositionValid(const LGNetCursorPosition * position); -bool lgNetCursorPositionEncode( - void * data, size_t size, const LGNetCursorPosition * position); -LGNetParseResult lgNetCursorPositionDecode( - LGNetCursorPosition * position, const void * data, size_t size); - -size_t lgNetCursorShapeSize(const LGNetCursorShape * shape); -bool lgNetCursorShapeValid(const LGNetCursorShape * shape); -bool lgNetCursorShapeEncode( - void * data, size_t size, const LGNetCursorShape * shape); -LGNetParseResult lgNetCursorShapeDecode( - LGNetCursorShape * shape, const void * data, size_t size); - -bool lgNetInputClaimValid(const LGNetInputClaim * claim); -bool lgNetInputClaimEncode( - void * data, size_t size, const LGNetInputClaim * claim); -LGNetParseResult lgNetInputClaimDecode( - LGNetInputClaim * claim, const void * data, size_t size); - -bool lgNetInputStatusValid(const LGNetInputStatus * status); -bool lgNetInputStatusEncode( - void * data, size_t size, const LGNetInputStatus * status); -LGNetParseResult lgNetInputStatusDecode( - LGNetInputStatus * status, const void * data, size_t size); - -bool lgNetInputRelativeValid(const LGNetInputRelative * relative); -bool lgNetInputRelativeEncode( - void * data, size_t size, const LGNetInputRelative * relative); -LGNetParseResult lgNetInputRelativeDecode( - LGNetInputRelative * relative, const void * data, size_t size); - -bool lgNetInputAbsoluteValid(const LGNetInputAbsolute * absolute); -bool lgNetInputAbsoluteEncode( - void * data, size_t size, const LGNetInputAbsolute * absolute); -LGNetParseResult lgNetInputAbsoluteDecode( - LGNetInputAbsolute * absolute, const void * data, size_t size); - -bool lgNetInputKeyboardValid(const LGNetInputKeyboard * keyboard); -bool lgNetInputKeyboardEncode( - void * data, size_t size, const LGNetInputKeyboard * keyboard); -LGNetParseResult lgNetInputKeyboardDecode( - LGNetInputKeyboard * keyboard, const void * data, size_t size); - -bool lgNetInputLEDsValid(const LGNetInputLEDs * leds); -bool lgNetInputLEDsEncode( - void * data, size_t size, const LGNetInputLEDs * leds); -LGNetParseResult lgNetInputLEDsDecode( - LGNetInputLEDs * leds, const void * data, size_t size); - -bool lgNetAudioFormatValid(const LGNetAudioFormat * format); -bool lgNetAudioFormatEncode( - void * data, size_t size, const LGNetAudioFormat * format); -LGNetParseResult lgNetAudioFormatDecode( - LGNetAudioFormat * format, const void * data, size_t size); - -size_t lgNetAudioDataSize(const LGNetAudioData * audio); -bool lgNetAudioDataValid(const LGNetAudioData * audio); -bool lgNetAudioDataMatchesFormat( - const LGNetAudioData * audio, const LGNetAudioFormat * format); -bool lgNetAudioDataEncode( - void * data, size_t size, const LGNetAudioData * audio); -LGNetParseResult lgNetAudioDataDecode( - LGNetAudioData * audio, const void * data, size_t size); - -bool lgNetAudioStateValid(const LGNetAudioState * state); -bool lgNetAudioStateEncode( - void * data, size_t size, const LGNetAudioState * state); -LGNetParseResult lgNetAudioStateDecode( - LGNetAudioState * state, const void * data, size_t size); - -bool lgNetAudioClockFeedbackValid( - const LGNetAudioClockFeedback * feedback); -bool lgNetAudioClockFeedbackEncode(void * data, size_t size, - const LGNetAudioClockFeedback * feedback); -LGNetParseResult lgNetAudioClockFeedbackDecode( - LGNetAudioClockFeedback * feedback, const void * data, size_t size); - -bool lgNetClipboardClaimValid(const LGNetClipboardClaim * claim); -bool lgNetClipboardClaimEncode( - void * data, size_t size, const LGNetClipboardClaim * claim); -LGNetParseResult lgNetClipboardClaimDecode( - LGNetClipboardClaim * claim, const void * data, size_t size); - -size_t lgNetClipboardOfferSize(const LGNetClipboardOffer * offer); -bool lgNetClipboardOfferValid(const LGNetClipboardOffer * offer); -bool lgNetClipboardOfferEncode( - void * data, size_t size, const LGNetClipboardOffer * offer); -LGNetParseResult lgNetClipboardOfferDecode( - LGNetClipboardOffer * offer, const void * data, size_t size); - -bool lgNetClipboardRequestValid(const LGNetClipboardRequest * request); -bool lgNetClipboardRequestEncode( - void * data, size_t size, const LGNetClipboardRequest * request); -LGNetParseResult lgNetClipboardRequestDecode( - LGNetClipboardRequest * request, const void * data, size_t size); - -size_t lgNetClipboardChunkSize(const LGNetClipboardChunk * chunk); -bool lgNetClipboardChunkValid(const LGNetClipboardChunk * chunk); -bool lgNetClipboardChunkEncode( - void * data, size_t size, const LGNetClipboardChunk * chunk); -LGNetParseResult lgNetClipboardChunkDecode( - LGNetClipboardChunk * chunk, const void * data, size_t size); - -bool lgNetClipboardStatusValid(const LGNetClipboardStatus * status); -bool lgNetClipboardStatusEncode( - void * data, size_t size, const LGNetClipboardStatus * status); -LGNetParseResult lgNetClipboardStatusDecode( - LGNetClipboardStatus * status, const void * data, size_t size); - -size_t lgNetFileOfferSize(const LGNetFileOffer * offer); -bool lgNetFileOfferValid(const LGNetFileOffer * offer); -bool lgNetFileOfferEncode( - void * data, size_t size, const LGNetFileOffer * offer); -LGNetParseResult lgNetFileOfferDecode( - LGNetFileOffer * offer, const void * data, size_t size); - -size_t lgNetFileEntrySize(const LGNetFileEntry * entry); -bool lgNetFileEntryValid(const LGNetFileEntry * entry); -bool lgNetFileEntryEncode( - void * data, size_t size, const LGNetFileEntry * entry); -LGNetParseResult lgNetFileEntryDecode( - LGNetFileEntry * entry, const void * data, size_t size); - -bool lgNetFileRequestValid(const LGNetFileRequest * request); -bool lgNetFileRequestEncode( - void * data, size_t size, const LGNetFileRequest * request); -LGNetParseResult lgNetFileRequestDecode( - LGNetFileRequest * request, const void * data, size_t size); - -size_t lgNetFileChunkSize(const LGNetFileChunk * chunk); -bool lgNetFileChunkValid(const LGNetFileChunk * chunk); -bool lgNetFileChunkEncode( - void * data, size_t size, const LGNetFileChunk * chunk); -LGNetParseResult lgNetFileChunkDecode( - LGNetFileChunk * chunk, const void * data, size_t size); - -bool lgNetFileStatusValid(const LGNetFileStatus * status); -bool lgNetFileStatusEncode( - void * data, size_t size, const LGNetFileStatus * status); -LGNetParseResult lgNetFileStatusDecode( - LGNetFileStatus * status, const void * data, size_t size); - -size_t lgNetUSBReservedSize(const LGNetUSBReserved * reserved); -bool lgNetUSBReservedValid(const LGNetUSBReserved * reserved); -bool lgNetUSBReservedEncode( - void * data, size_t size, const LGNetUSBReserved * reserved); -LGNetParseResult lgNetUSBReservedDecode( - LGNetUSBReserved * reserved, const void * data, size_t size); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/include/common/network/wire.h b/common/include/common/network/wire.h deleted file mode 100644 index dc965aa9..00000000 --- a/common/include/common/network/wire.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Looking Glass - * Copyright © 2017-2026 The Looking Glass Authors - * https://looking-glass.io - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _H_LG_COMMON_NETWORK_WIRE_ -#define _H_LG_COMMON_NETWORK_WIRE_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum LGNetParseResult -{ - LG_NET_PARSE_OK, - LG_NET_PARSE_TRUNCATED, - LG_NET_PARSE_INVALID_MAGIC, - LG_NET_PARSE_INVALID_VERSION, - LG_NET_PARSE_INVALID_HEADER, - LG_NET_PARSE_INVALID_LENGTH, - LG_NET_PARSE_INVALID_VALUE, -} -LGNetParseResult; - -typedef struct LGNetWriter -{ - uint8_t * data; - size_t capacity; - size_t offset; - bool failed; -} -LGNetWriter; - -typedef struct LGNetReader -{ - const uint8_t * data; - size_t size; - size_t offset; - bool failed; -} -LGNetReader; - -void lgNetWriterInit(LGNetWriter * writer, void * data, size_t capacity); -size_t lgNetWriterSize(const LGNetWriter * writer); -size_t lgNetWriterRemaining(const LGNetWriter * writer); -bool lgNetWriterValid(const LGNetWriter * writer); -bool lgNetWriterU8(LGNetWriter * writer, uint8_t value); -bool lgNetWriterU16(LGNetWriter * writer, uint16_t value); -bool lgNetWriterU32(LGNetWriter * writer, uint32_t value); -bool lgNetWriterU64(LGNetWriter * writer, uint64_t value); -bool lgNetWriterI32(LGNetWriter * writer, int32_t value); -bool lgNetWriterI64(LGNetWriter * writer, int64_t value); -bool lgNetWriterBytes( - LGNetWriter * writer, const void * data, size_t size); -bool lgNetWriterZero(LGNetWriter * writer, size_t size); - -void lgNetReaderInit( - LGNetReader * reader, const void * data, size_t size); -size_t lgNetReaderConsumed(const LGNetReader * reader); -size_t lgNetReaderRemaining(const LGNetReader * reader); -bool lgNetReaderValid(const LGNetReader * reader); -bool lgNetReaderU8(LGNetReader * reader, uint8_t * value); -bool lgNetReaderU16(LGNetReader * reader, uint16_t * value); -bool lgNetReaderU32(LGNetReader * reader, uint32_t * value); -bool lgNetReaderU64(LGNetReader * reader, uint64_t * value); -bool lgNetReaderI32(LGNetReader * reader, int32_t * value); -bool lgNetReaderI64(LGNetReader * reader, int64_t * value); -bool lgNetReaderBytes(LGNetReader * reader, void * data, size_t size); -bool lgNetReaderView( - LGNetReader * reader, const uint8_t ** data, size_t size); -bool lgNetReaderSkip(LGNetReader * reader, size_t size); -bool lgNetReaderZero(LGNetReader * reader, size_t size); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/src/network/protocol.c b/common/src/network/protocol.c deleted file mode 100644 index ba3cee62..00000000 --- a/common/src/network/protocol.c +++ /dev/null @@ -1,730 +0,0 @@ -/** - * Looking Glass - * Copyright © 2017-2026 The Looking Glass Authors - * https://looking-glass.io - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "common/network/protocol.h" - -#include -#include - -static const LGNetEnvelopeFlags ENVELOPE_FLAGS = - LG_NET_ENVELOPE_RESPONSE | - LG_NET_ENVELOPE_FINAL | - LG_NET_ENVELOPE_RELIABLE | - LG_NET_ENVELOPE_DATAGRAM | - LG_NET_ENVELOPE_ACK_REQUIRED | - LG_NET_ENVELOPE_ERROR | - LG_NET_ENVELOPE_EARLY_DATA; - -static const LGNetCapabilityFlags CAPABILITY_FLAGS = - LG_NET_CAPABILITY_REQUIRED | - LG_NET_CAPABILITY_SELECTED | - LG_NET_CAPABILITY_RELIABLE | - LG_NET_CAPABILITY_DATAGRAM | - LG_NET_CAPABILITY_BULK | - LG_NET_CAPABILITY_MULTI_CLIENT; - -static bool envelopeValid(const LGNetEnvelope * envelope, bool encode) -{ - if (!envelope || envelope->wireMajor != LG_NET_WIRE_VERSION_MAJOR || - envelope->headerSize < LG_NET_ENVELOPE_WIRE_SIZE || - (encode && envelope->wireMinor != LG_NET_WIRE_VERSION_MINOR) || - (encode && envelope->headerSize != LG_NET_ENVELOPE_WIRE_SIZE) || - !envelope->service || !envelope->messageType || - !envelope->serviceVersion || !envelope->messageVersion || - envelope->payloadLength > LG_NET_MAX_PAYLOAD_LENGTH) - return false; - - return true; -} - -static bool authModeKnown(LGNetAuthMode mode) -{ - return mode == LG_NET_AUTH_NONE || mode == LG_NET_AUTH_PASSWORD; -} - -static bool passwordAlgorithmKnown(LGNetPasswordAlgorithm algorithm) -{ - return algorithm == LG_NET_PASSWORD_PBKDF2_HMAC_SHA256; -} - -static LGNetParseResult fixedDecodeResult( - const LGNetReader * reader, size_t expected, size_t actual) -{ - if (!reader || !lgNetReaderValid(reader)) - return LG_NET_PARSE_INVALID_VALUE; - if (actual != expected || lgNetReaderConsumed(reader) != expected) - return LG_NET_PARSE_INVALID_LENGTH; - return LG_NET_PARSE_OK; -} - -void lgNetEnvelopeInit(LGNetEnvelope * envelope, LGNetService service, - uint16_t messageType, uint16_t serviceVersion, - uint16_t messageVersion) -{ - if (!envelope) - return; - - memset(envelope, 0, sizeof(*envelope)); - envelope->wireMajor = LG_NET_WIRE_VERSION_MAJOR; - envelope->wireMinor = LG_NET_WIRE_VERSION_MINOR; - envelope->headerSize = LG_NET_ENVELOPE_WIRE_SIZE; - envelope->service = service; - envelope->messageType = messageType; - envelope->serviceVersion = serviceVersion; - envelope->messageVersion = messageVersion; -} - -bool lgNetEnvelopeEncode(void * data, size_t size, - const LGNetEnvelope * envelope) -{ - if (!data || size < LG_NET_ENVELOPE_WIRE_SIZE || - !envelopeValid(envelope, true) || - envelope->flags & ~ENVELOPE_FLAGS) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU32(&writer, LG_NET_WIRE_MAGIC) && - lgNetWriterU16(&writer, envelope->wireMajor) && - lgNetWriterU16(&writer, envelope->wireMinor) && - lgNetWriterU16(&writer, envelope->headerSize) && - lgNetWriterU16(&writer, envelope->service) && - lgNetWriterU16(&writer, envelope->messageType) && - lgNetWriterU16(&writer, envelope->serviceVersion) && - lgNetWriterU16(&writer, envelope->messageVersion) && - lgNetWriterU16(&writer, 0) && - lgNetWriterU32(&writer, envelope->flags) && - lgNetWriterU32(&writer, envelope->payloadLength) && - lgNetWriterU32(&writer, 0) && - lgNetWriterU64(&writer, envelope->sessionEpoch) && - lgNetWriterU64(&writer, envelope->componentEpoch) && - lgNetWriterU64(&writer, envelope->sequence) && - lgNetWriterU64(&writer, envelope->requestID) && - lgNetWriterSize(&writer) == LG_NET_ENVELOPE_WIRE_SIZE; -} - -LGNetParseResult lgNetEnvelopeDecode(LGNetEnvelope * envelope, - const void * data, size_t size) -{ - if (!envelope || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_ENVELOPE_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetEnvelope decoded; - uint32_t magic; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, LG_NET_ENVELOPE_WIRE_SIZE); - if (!lgNetReaderU32(&reader, &magic) || - !lgNetReaderU16(&reader, &decoded.wireMajor) || - !lgNetReaderU16(&reader, &decoded.wireMinor) || - !lgNetReaderU16(&reader, &decoded.headerSize) || - !lgNetReaderU16(&reader, &decoded.service) || - !lgNetReaderU16(&reader, &decoded.messageType) || - !lgNetReaderU16(&reader, &decoded.serviceVersion) || - !lgNetReaderU16(&reader, &decoded.messageVersion) || - !lgNetReaderZero(&reader, 2) || - !lgNetReaderU32(&reader, &decoded.flags) || - !lgNetReaderU32(&reader, &decoded.payloadLength) || - !lgNetReaderZero(&reader, 4) || - !lgNetReaderU64(&reader, &decoded.sessionEpoch) || - !lgNetReaderU64(&reader, &decoded.componentEpoch) || - !lgNetReaderU64(&reader, &decoded.sequence) || - !lgNetReaderU64(&reader, &decoded.requestID)) - return LG_NET_PARSE_INVALID_HEADER; - - if (magic != LG_NET_WIRE_MAGIC) - return LG_NET_PARSE_INVALID_MAGIC; - if (decoded.wireMajor != LG_NET_WIRE_VERSION_MAJOR) - return LG_NET_PARSE_INVALID_VERSION; - if (decoded.headerSize < LG_NET_ENVELOPE_WIRE_SIZE) - return LG_NET_PARSE_INVALID_HEADER; - if (decoded.headerSize > size) - return LG_NET_PARSE_TRUNCATED; - if (!envelopeValid(&decoded, false) || decoded.flags & ~ENVELOPE_FLAGS) - return LG_NET_PARSE_INVALID_VALUE; - - *envelope = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetPacketSize(const LGNetEnvelope * envelope, size_t * size) -{ - if (!size || !envelopeValid(envelope, false) || - envelope->headerSize > SIZE_MAX - envelope->payloadLength) - return false; - - *size = (size_t)envelope->headerSize + envelope->payloadLength; - return true; -} - -bool lgNetPacketEncode(void * data, size_t size, - const LGNetEnvelope * envelope, const void * payload) -{ - uint8_t header[LG_NET_ENVELOPE_WIRE_SIZE]; - size_t wireSize; - if (!data || !envelope || (envelope->payloadLength && !payload) || - !lgNetPacketSize(envelope, &wireSize) || wireSize > size || - !lgNetEnvelopeEncode(header, sizeof(header), envelope)) - return false; - - if (envelope->payloadLength) - memmove((uint8_t *)data + envelope->headerSize, payload, - envelope->payloadLength); - memcpy(data, header, sizeof(header)); - return true; -} - -LGNetParseResult lgNetPacketDecode(LGNetPacketView * packet, - const void * data, size_t size) -{ - if (!packet) - return LG_NET_PARSE_INVALID_VALUE; - - LGNetPacketView decoded; - memset(&decoded, 0, sizeof(decoded)); - const LGNetParseResult result = lgNetEnvelopeDecode( - &decoded.envelope, data, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetPacketSize(&decoded.envelope, &decoded.wireSize)) - return LG_NET_PARSE_INVALID_LENGTH; - if (decoded.wireSize > size) - return LG_NET_PARSE_TRUNCATED; - - decoded.payload = (const uint8_t *)data + decoded.envelope.headerSize; - decoded.payloadLength = decoded.envelope.payloadLength; - *packet = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetServiceKnown(LGNetService service) -{ - return service >= LG_NET_SERVICE_CORE && service <= LG_NET_SERVICE_USB; -} - -bool lgNetMessageKnown(LGNetService service, uint16_t messageType) -{ - if (!messageType) - return false; - - switch (service) - { - case LG_NET_SERVICE_CORE: - return messageType <= LG_NET_CORE_MESSAGE_ERROR; - - case LG_NET_SERVICE_RECOVERY: - return messageType <= LG_NET_RECOVERY_MESSAGE_STATUS; - - case LG_NET_SERVICE_VIDEO: - return messageType <= LG_NET_VIDEO_MESSAGE_STATUS; - - case LG_NET_SERVICE_CURSOR: - return messageType <= LG_NET_CURSOR_MESSAGE_STATUS; - - case LG_NET_SERVICE_INPUT: - return messageType <= LG_NET_INPUT_MESSAGE_KEYBOARD_LEDS; - - case LG_NET_SERVICE_AUDIO: - return messageType <= LG_NET_AUDIO_MESSAGE_STATE_ACK; - - case LG_NET_SERVICE_CLIPBOARD: - return messageType <= LG_NET_CLIPBOARD_MESSAGE_STATUS; - - case LG_NET_SERVICE_FILE: - return messageType <= LG_NET_FILE_MESSAGE_STATUS; - - case LG_NET_SERVICE_USB: - return messageType <= LG_NET_USB_MESSAGE_STATUS; - } - - return false; -} - -void lgNetHelloInit(LGNetHello * hello, LGNetRole role) -{ - if (!hello) - return; - - memset(hello, 0, sizeof(*hello)); - hello->role = role; - hello->protocolMin = LG_NET_PROTOCOL_VERSION_MIN; - hello->protocolMax = LG_NET_PROTOCOL_VERSION_CURRENT; - hello->authModes = LG_NET_AUTH_MODES_DEFAULT; - hello->maxPayloadLength = LG_NET_MAX_PAYLOAD_LENGTH; -} - -bool lgNetHelloValid(const LGNetHello * hello) -{ - return hello && - (hello->role == LG_NET_ROLE_CLIENT || hello->role == LG_NET_ROLE_SERVER) && - hello->protocolMin && hello->protocolMin <= hello->protocolMax && - hello->authModes && - hello->maxPayloadLength && - hello->maxPayloadLength <= LG_NET_MAX_PAYLOAD_LENGTH && - hello->maxDatagramPayload <= hello->maxPayloadLength && - hello->capabilityCount <= LG_NET_MAX_CAPABILITY_RECORDS; -} - -bool lgNetHelloEncode(void * data, size_t size, const LGNetHello * hello) -{ - if (!data || size < LG_NET_HELLO_WIRE_SIZE || !lgNetHelloValid(hello)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU16(&writer, hello->role) && - lgNetWriterU16(&writer, hello->protocolMin) && - lgNetWriterU16(&writer, hello->protocolMax) && - lgNetWriterU16(&writer, 0) && - lgNetWriterU32(&writer, hello->authModes) && - lgNetWriterU32(&writer, hello->maxPayloadLength) && - lgNetWriterU32(&writer, hello->maxDatagramPayload) && - lgNetWriterU32(&writer, hello->capabilityCount) && - lgNetWriterBytes(&writer, hello->nonce, sizeof(hello->nonce)) && - lgNetWriterSize(&writer) == LG_NET_HELLO_WIRE_SIZE; -} - -LGNetParseResult lgNetHelloDecode(LGNetHello * hello, - const void * data, size_t size) -{ - if (!hello || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_HELLO_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetHello decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU16(&reader, &decoded.role) || - !lgNetReaderU16(&reader, &decoded.protocolMin) || - !lgNetReaderU16(&reader, &decoded.protocolMax) || - !lgNetReaderZero(&reader, 2) || - !lgNetReaderU32(&reader, &decoded.authModes) || - !lgNetReaderU32(&reader, &decoded.maxPayloadLength) || - !lgNetReaderU32(&reader, &decoded.maxDatagramPayload) || - !lgNetReaderU32(&reader, &decoded.capabilityCount) || - !lgNetReaderBytes(&reader, decoded.nonce, - sizeof(decoded.nonce))) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_HELLO_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetHelloValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *hello = decoded; - return LG_NET_PARSE_OK; -} - -void lgNetHelloAckInit(LGNetHelloAck * hello, uint64_t sessionEpoch) -{ - if (!hello) - return; - - memset(hello, 0, sizeof(*hello)); - hello->protocolVersion = LG_NET_PROTOCOL_VERSION_CURRENT; - hello->authMode = LG_NET_AUTH_MODE_DEFAULT; - hello->maxPayloadLength = LG_NET_MAX_PAYLOAD_LENGTH; - hello->sessionEpoch = sessionEpoch; -} - -bool lgNetHelloAckValid(const LGNetHelloAck * hello) -{ - return hello && - hello->protocolVersion >= LG_NET_PROTOCOL_VERSION_MIN && - hello->protocolVersion <= LG_NET_PROTOCOL_VERSION_MAX && - authModeKnown(hello->authMode) && - !(hello->flags & ~LG_NET_HELLO_ACK_RESUMED) && - hello->maxPayloadLength && - hello->maxPayloadLength <= LG_NET_MAX_PAYLOAD_LENGTH && - hello->maxDatagramPayload <= hello->maxPayloadLength && - hello->capabilityCount <= LG_NET_MAX_CAPABILITY_RECORDS && - hello->sessionEpoch; -} - -bool lgNetHelloAckEncode( - void * data, size_t size, const LGNetHelloAck * hello) -{ - if (!data || size < LG_NET_HELLO_ACK_WIRE_SIZE || - !lgNetHelloAckValid(hello)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU16(&writer, hello->protocolVersion) && - lgNetWriterU16(&writer, hello->authMode) && - lgNetWriterU32(&writer, hello->flags) && - lgNetWriterU32(&writer, hello->maxPayloadLength) && - lgNetWriterU32(&writer, hello->maxDatagramPayload) && - lgNetWriterU32(&writer, hello->capabilityCount) && - lgNetWriterU32(&writer, 0) && - lgNetWriterU64(&writer, hello->sessionEpoch) && - lgNetWriterBytes(&writer, hello->nonce, sizeof(hello->nonce)) && - lgNetWriterSize(&writer) == LG_NET_HELLO_ACK_WIRE_SIZE; -} - -LGNetParseResult lgNetHelloAckDecode(LGNetHelloAck * hello, - const void * data, size_t size) -{ - if (!hello || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_HELLO_ACK_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetHelloAck decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU16(&reader, &decoded.protocolVersion) || - !lgNetReaderU16(&reader, &decoded.authMode) || - !lgNetReaderU32(&reader, &decoded.flags) || - !lgNetReaderU32(&reader, &decoded.maxPayloadLength) || - !lgNetReaderU32(&reader, &decoded.maxDatagramPayload) || - !lgNetReaderU32(&reader, &decoded.capabilityCount) || - !lgNetReaderZero(&reader, 4) || - !lgNetReaderU64(&reader, &decoded.sessionEpoch) || - !lgNetReaderBytes(&reader, decoded.nonce, - sizeof(decoded.nonce))) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_HELLO_ACK_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetHelloAckValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *hello = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetCapabilityValid(const LGNetCapability * capability) -{ - if (!capability || !capability->service || - !capability->versionMin || - capability->versionMin > capability->versionMax || - capability->flags & ~CAPABILITY_FLAGS || - !capability->maxPayloadLength || - capability->maxPayloadLength > LG_NET_MAX_PAYLOAD_LENGTH || - capability->maxDatagramPayload > capability->maxPayloadLength) - return false; - - if ((capability->flags & LG_NET_CAPABILITY_SELECTED) && - capability->versionMin != capability->versionMax) - return false; - if (!!(capability->flags & LG_NET_CAPABILITY_DATAGRAM) != - !!capability->maxDatagramPayload) - return false; - return true; -} - -bool lgNetCapabilityEncode(void * data, size_t size, - const LGNetCapability * capability) -{ - if (!data || size < LG_NET_CAPABILITY_WIRE_SIZE || - !lgNetCapabilityValid(capability)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU16(&writer, capability->service) && - lgNetWriterU16(&writer, capability->versionMin) && - lgNetWriterU16(&writer, capability->versionMax) && - lgNetWriterU16(&writer, capability->flags) && - lgNetWriterU64(&writer, capability->features) && - lgNetWriterU32(&writer, capability->maxPayloadLength) && - lgNetWriterU32(&writer, capability->maxDatagramPayload) && - lgNetWriterU16(&writer, capability->maxBidirectionalStreams) && - lgNetWriterU16(&writer, capability->maxUnidirectionalStreams) && - lgNetWriterU32(&writer, 0) && - lgNetWriterSize(&writer) == LG_NET_CAPABILITY_WIRE_SIZE; -} - -LGNetParseResult lgNetCapabilityDecode(LGNetCapability * capability, - const void * data, size_t size) -{ - if (!capability || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_CAPABILITY_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetCapability decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU16(&reader, &decoded.service) || - !lgNetReaderU16(&reader, &decoded.versionMin) || - !lgNetReaderU16(&reader, &decoded.versionMax) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderU64(&reader, &decoded.features) || - !lgNetReaderU32(&reader, &decoded.maxPayloadLength) || - !lgNetReaderU32(&reader, &decoded.maxDatagramPayload) || - !lgNetReaderU16(&reader, &decoded.maxBidirectionalStreams) || - !lgNetReaderU16(&reader, &decoded.maxUnidirectionalStreams) || - !lgNetReaderZero(&reader, 4)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_CAPABILITY_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetCapabilityValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *capability = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetPasswordChallengeSize( - const LGNetPasswordChallenge * challenge) -{ - if (!lgNetPasswordChallengeValid(challenge)) - return 0; - return LG_NET_PASSWORD_CHALLENGE_HEADER_SIZE + - challenge->saltLength + challenge->challengeLength; -} - -bool lgNetPasswordChallengeValid( - const LGNetPasswordChallenge * challenge) -{ - return challenge && passwordAlgorithmKnown(challenge->algorithm) && - challenge->rounds && challenge->saltLength && - challenge->saltLength <= LG_NET_PASSWORD_SALT_MAX_LENGTH && - challenge->challengeLength && - challenge->challengeLength <= LG_NET_PASSWORD_CHALLENGE_MAX_LENGTH; -} - -bool lgNetPasswordChallengeEncode(void * data, size_t size, - const LGNetPasswordChallenge * challenge) -{ - const size_t required = lgNetPasswordChallengeSize(challenge); - if (!data || !required || size < required) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU16(&writer, challenge->algorithm) && - lgNetWriterU16(&writer, 0) && - lgNetWriterU32(&writer, challenge->rounds) && - lgNetWriterU16(&writer, challenge->saltLength) && - lgNetWriterU16(&writer, challenge->challengeLength) && - lgNetWriterU32(&writer, 0) && - lgNetWriterBytes(&writer, challenge->salt, - challenge->saltLength) && - lgNetWriterBytes(&writer, challenge->challenge, - challenge->challengeLength) && - lgNetWriterSize(&writer) == required; -} - -LGNetParseResult lgNetPasswordChallengeDecode( - LGNetPasswordChallenge * challenge, const void * data, size_t size) -{ - if (!challenge || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_PASSWORD_CHALLENGE_HEADER_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetPasswordChallenge decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU16(&reader, &decoded.algorithm) || - !lgNetReaderZero(&reader, 2) || - !lgNetReaderU32(&reader, &decoded.rounds) || - !lgNetReaderU16(&reader, &decoded.saltLength) || - !lgNetReaderU16(&reader, &decoded.challengeLength) || - !lgNetReaderZero(&reader, 4)) - return LG_NET_PARSE_INVALID_VALUE; - - if (decoded.saltLength > LG_NET_PASSWORD_SALT_MAX_LENGTH || - decoded.challengeLength > LG_NET_PASSWORD_CHALLENGE_MAX_LENGTH) - return LG_NET_PARSE_INVALID_LENGTH; - - const size_t expected = LG_NET_PASSWORD_CHALLENGE_HEADER_SIZE + - decoded.saltLength + decoded.challengeLength; - if (size < expected) - return LG_NET_PARSE_TRUNCATED; - if (size != expected || - !lgNetReaderBytes(&reader, decoded.salt, decoded.saltLength) || - !lgNetReaderBytes(&reader, decoded.challenge, - decoded.challengeLength)) - return LG_NET_PARSE_INVALID_LENGTH; - if (!lgNetPasswordChallengeValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *challenge = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetPasswordResponseSize(const LGNetPasswordResponse * response) -{ - if (!lgNetPasswordResponseValid(response)) - return 0; - return LG_NET_PASSWORD_RESPONSE_HEADER_SIZE + - response->nonceLength + response->proofLength; -} - -bool lgNetPasswordResponseValid(const LGNetPasswordResponse * response) -{ - return response && passwordAlgorithmKnown(response->algorithm) && - response->nonceLength && - response->nonceLength <= LG_NET_PASSWORD_NONCE_MAX_LENGTH && - response->proofLength && - response->proofLength <= LG_NET_PASSWORD_PROOF_MAX_LENGTH; -} - -bool lgNetPasswordResponseEncode(void * data, size_t size, - const LGNetPasswordResponse * response) -{ - const size_t required = lgNetPasswordResponseSize(response); - if (!data || !required || size < required) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU16(&writer, response->algorithm) && - lgNetWriterU16(&writer, response->nonceLength) && - lgNetWriterU16(&writer, response->proofLength) && - lgNetWriterU16(&writer, 0) && - lgNetWriterU32(&writer, 0) && - lgNetWriterBytes(&writer, response->nonce, - response->nonceLength) && - lgNetWriterBytes(&writer, response->proof, - response->proofLength) && - lgNetWriterSize(&writer) == required; -} - -LGNetParseResult lgNetPasswordResponseDecode( - LGNetPasswordResponse * response, const void * data, size_t size) -{ - if (!response || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_PASSWORD_RESPONSE_HEADER_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetPasswordResponse decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU16(&reader, &decoded.algorithm) || - !lgNetReaderU16(&reader, &decoded.nonceLength) || - !lgNetReaderU16(&reader, &decoded.proofLength) || - !lgNetReaderZero(&reader, 2) || - !lgNetReaderZero(&reader, 4)) - return LG_NET_PARSE_INVALID_VALUE; - - if (decoded.nonceLength > LG_NET_PASSWORD_NONCE_MAX_LENGTH || - decoded.proofLength > LG_NET_PASSWORD_PROOF_MAX_LENGTH) - return LG_NET_PARSE_INVALID_LENGTH; - - const size_t expected = LG_NET_PASSWORD_RESPONSE_HEADER_SIZE + - decoded.nonceLength + decoded.proofLength; - if (size < expected) - return LG_NET_PARSE_TRUNCATED; - if (size != expected || - !lgNetReaderBytes(&reader, decoded.nonce, decoded.nonceLength) || - !lgNetReaderBytes(&reader, decoded.proof, decoded.proofLength)) - return LG_NET_PARSE_INVALID_LENGTH; - if (!lgNetPasswordResponseValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *response = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetAuthResultSize(const LGNetAuthResult * result) -{ - if (!lgNetAuthResultValid(result)) - return 0; - return LG_NET_AUTH_RESULT_HEADER_SIZE + result->proofLength; -} - -bool lgNetAuthResultValid(const LGNetAuthResult * result) -{ - return result && - result->result >= LG_NET_AUTH_RESULT_ACCEPTED && - result->result <= LG_NET_AUTH_RESULT_ERROR && - result->proofLength <= LG_NET_PASSWORD_PROOF_MAX_LENGTH; -} - -bool lgNetAuthResultEncode( - void * data, size_t size, const LGNetAuthResult * result) -{ - const size_t required = lgNetAuthResultSize(result); - if (!data || !required || size < required) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU16(&writer, result->result) && - lgNetWriterU16(&writer, result->proofLength) && - lgNetWriterU32(&writer, result->retryAfterMs) && - lgNetWriterU32(&writer, 0) && - lgNetWriterBytes(&writer, result->proof, - result->proofLength) && - lgNetWriterSize(&writer) == required; -} - -LGNetParseResult lgNetAuthResultDecode(LGNetAuthResult * result, - const void * data, size_t size) -{ - if (!result || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_AUTH_RESULT_HEADER_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetAuthResult decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU16(&reader, &decoded.result) || - !lgNetReaderU16(&reader, &decoded.proofLength) || - !lgNetReaderU32(&reader, &decoded.retryAfterMs) || - !lgNetReaderZero(&reader, 4)) - return LG_NET_PARSE_INVALID_VALUE; - - if (decoded.proofLength > LG_NET_PASSWORD_PROOF_MAX_LENGTH) - return LG_NET_PARSE_INVALID_LENGTH; - - const size_t expected = LG_NET_AUTH_RESULT_HEADER_SIZE + - decoded.proofLength; - if (size < expected) - return LG_NET_PARSE_TRUNCATED; - if (size != expected || - !lgNetReaderBytes(&reader, decoded.proof, decoded.proofLength)) - return LG_NET_PARSE_INVALID_LENGTH; - if (!lgNetAuthResultValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *result = decoded; - return LG_NET_PARSE_OK; -} diff --git a/common/src/network/services.c b/common/src/network/services.c deleted file mode 100644 index 5e41f59e..00000000 --- a/common/src/network/services.c +++ /dev/null @@ -1,2285 +0,0 @@ -/** - * Looking Glass - * Copyright © 2017-2026 The Looking Glass Authors - * https://looking-glass.io - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "common/network/services.h" - -#include -#include - -static const LGNetVideoStreamFlags VIDEO_STREAM_FLAGS = - LG_NET_VIDEO_STREAM_HDR | - LG_NET_VIDEO_STREAM_ALPHA | - LG_NET_VIDEO_STREAM_GPU_PLANES_ONLY | - LG_NET_VIDEO_STREAM_DATAGRAMS; - -static const LGNetVideoFrameFlags VIDEO_FRAME_FLAGS = - LG_NET_VIDEO_FRAME_KEYFRAME | - LG_NET_VIDEO_FRAME_DISCONTINUITY | - LG_NET_VIDEO_FRAME_END_OF_STREAM | - LG_NET_VIDEO_FRAME_HAS_CHECKSUM; - -static const LGNetVideoFragmentFlags VIDEO_FRAGMENT_FLAGS = - LG_NET_VIDEO_FRAGMENT_BLOCK_START | - LG_NET_VIDEO_FRAGMENT_BLOCK_END | - LG_NET_VIDEO_FRAGMENT_FRAME_END | - LG_NET_VIDEO_FRAGMENT_RECOVERY; - -static const LGNetVideoFeedbackFlags VIDEO_FEEDBACK_FLAGS = - LG_NET_VIDEO_FEEDBACK_REQUEST_KEYFRAME | - LG_NET_VIDEO_FEEDBACK_CONGESTED | - LG_NET_VIDEO_FEEDBACK_DECODER_STALLED; - -static const LGNetCursorPositionFlags CURSOR_POSITION_FLAGS = - LG_NET_CURSOR_POSITION_VISIBLE | - LG_NET_CURSOR_POSITION_RELATIVE; - -static const LGNetCursorShapeFlags CURSOR_SHAPE_FLAGS = - LG_NET_CURSOR_SHAPE_HIDDEN | - LG_NET_CURSOR_SHAPE_ANIMATED; - -static const LGNetInputClaimFlags INPUT_CLAIM_FLAGS = - LG_NET_INPUT_CLAIM_KEYBOARD | - LG_NET_INPUT_CLAIM_POINTER | - LG_NET_INPUT_CLAIM_EXCLUSIVE; - -static const LGNetKeyboardFlags KEYBOARD_FLAGS = - LG_NET_KEYBOARD_DOWN | - LG_NET_KEYBOARD_REPEAT | - LG_NET_KEYBOARD_EXTENDED | - LG_NET_KEYBOARD_E1; - -static const LGNetKeyboardLEDs KEYBOARD_LEDS = - LG_NET_KEYBOARD_LED_NUM_LOCK | - LG_NET_KEYBOARD_LED_CAPS_LOCK | - LG_NET_KEYBOARD_LED_SCROLL_LOCK | - LG_NET_KEYBOARD_LED_COMPOSE | - LG_NET_KEYBOARD_LED_KANA; - -static const LGNetAudioFormatFlags AUDIO_FORMAT_FLAGS = - LG_NET_AUDIO_FORMAT_INTERLEAVED; - -static const LGNetAudioDataFlags AUDIO_DATA_FLAGS = - LG_NET_AUDIO_DATA_DISCONTINUITY | - LG_NET_AUDIO_DATA_SILENT | - LG_NET_AUDIO_DATA_END_OF_STREAM; - -static const LGNetAudioStateFlags AUDIO_STATE_FLAGS = - LG_NET_AUDIO_STATE_MUTED | - LG_NET_AUDIO_STATE_FORMAT_ACTIVE; - -static const LGNetClipboardClaimFlags CLIPBOARD_CLAIM_FLAGS = - LG_NET_CLIPBOARD_CLAIM_READ | - LG_NET_CLIPBOARD_CLAIM_WRITE; - -static const LGNetClipboardOfferFlags CLIPBOARD_OFFER_FLAGS = - LG_NET_CLIPBOARD_OFFER_LAZY | - LG_NET_CLIPBOARD_OFFER_SENSITIVE; - -static const LGNetClipboardChunkFlags CLIPBOARD_CHUNK_FLAGS = - LG_NET_CLIPBOARD_CHUNK_FIRST | - LG_NET_CLIPBOARD_CHUNK_FINAL; - -static const LGNetFileOfferFlags FILE_OFFER_FLAGS = - LG_NET_FILE_OFFER_COPY | - LG_NET_FILE_OFFER_MOVE | - LG_NET_FILE_OFFER_RECURSIVE; - -static const LGNetFileEntryFlags FILE_ENTRY_FLAGS = - LG_NET_FILE_ENTRY_EXECUTABLE | - LG_NET_FILE_ENTRY_HIDDEN; - -static const LGNetFileRequestFlags FILE_REQUEST_FLAGS = - LG_NET_FILE_REQUEST_METADATA | - LG_NET_FILE_REQUEST_DATA; - -static const LGNetFileChunkFlags FILE_CHUNK_FLAGS = - LG_NET_FILE_CHUNK_FIRST | - LG_NET_FILE_CHUNK_FINAL; - -static const LGNetUSBReservedFlags USB_RESERVED_FLAGS = - LG_NET_USB_RESERVED_RESPONSE | - LG_NET_USB_RESERVED_FINAL; - -static bool variableSize(size_t headerSize, size_t payloadLength, - size_t payloadLimit, size_t * wireSize) -{ - if (!wireSize || payloadLength > payloadLimit || - headerSize > SIZE_MAX - payloadLength || - headerSize + payloadLength > LG_NET_MAX_PAYLOAD_LENGTH) - return false; - - *wireSize = headerSize + payloadLength; - return true; -} - -static LGNetParseResult fixedDecodeResult( - const LGNetReader * reader, size_t expected, size_t actual) -{ - if (!reader || !lgNetReaderValid(reader)) - return LG_NET_PARSE_INVALID_VALUE; - if (actual != expected || lgNetReaderConsumed(reader) != expected) - return LG_NET_PARSE_INVALID_LENGTH; - return LG_NET_PARSE_OK; -} - -static LGNetParseResult variableDecodeSize(size_t headerSize, - size_t payloadLength, size_t payloadLimit, size_t actual, - size_t * expected) -{ - if (!variableSize(headerSize, payloadLength, payloadLimit, expected)) - return LG_NET_PARSE_INVALID_LENGTH; - if (actual < *expected) - return LG_NET_PARSE_TRUNCATED; - if (actual != *expected) - return LG_NET_PARSE_INVALID_LENGTH; - return LG_NET_PARSE_OK; -} - -static bool videoCodecKnown(LGNetVideoCodec codec) -{ - return codec == LG_NET_VIDEO_CODEC_PYROWAVE; -} - -static bool videoPixelFormatKnown(LGNetVideoPixelFormat format) -{ - return format >= LG_NET_VIDEO_PIXEL_FORMAT_NV12 && - format <= LG_NET_VIDEO_PIXEL_FORMAT_YUV444P16F; -} - -static bool videoPixelFormatValid(const LGNetVideoStreamConfig * config) -{ - switch (config->pixelFormat) - { - case LG_NET_VIDEO_PIXEL_FORMAT_NV12: - return config->chromaSubsampling == LG_NET_VIDEO_CHROMA_420 && - config->planeCount == 2 && config->bitDepth == 8; - - case LG_NET_VIDEO_PIXEL_FORMAT_P010: - return config->chromaSubsampling == LG_NET_VIDEO_CHROMA_420 && - config->planeCount == 2 && config->bitDepth == 10; - - case LG_NET_VIDEO_PIXEL_FORMAT_YUV420P8: - return config->chromaSubsampling == LG_NET_VIDEO_CHROMA_420 && - config->planeCount == 3 && config->bitDepth == 8; - - case LG_NET_VIDEO_PIXEL_FORMAT_YUV420P10: - return config->chromaSubsampling == LG_NET_VIDEO_CHROMA_420 && - config->planeCount == 3 && config->bitDepth == 10; - - case LG_NET_VIDEO_PIXEL_FORMAT_YUV422P8: - return config->chromaSubsampling == LG_NET_VIDEO_CHROMA_422 && - config->planeCount == 3 && config->bitDepth == 8; - - case LG_NET_VIDEO_PIXEL_FORMAT_YUV422P10: - return config->chromaSubsampling == LG_NET_VIDEO_CHROMA_422 && - config->planeCount == 3 && config->bitDepth == 10; - - case LG_NET_VIDEO_PIXEL_FORMAT_YUV444P8: - return config->chromaSubsampling == LG_NET_VIDEO_CHROMA_444 && - config->planeCount == 3 && config->bitDepth == 8; - - case LG_NET_VIDEO_PIXEL_FORMAT_YUV444P10: - return config->chromaSubsampling == LG_NET_VIDEO_CHROMA_444 && - config->planeCount == 3 && config->bitDepth == 10; - - case LG_NET_VIDEO_PIXEL_FORMAT_YUV444P16F: - return config->chromaSubsampling == LG_NET_VIDEO_CHROMA_444 && - config->planeCount == 3 && config->bitDepth == 16; - } - - return false; -} - -static bool videoChromaKnown(LGNetVideoChromaSubsampling chroma) -{ - return chroma >= LG_NET_VIDEO_CHROMA_420 && - chroma <= LG_NET_VIDEO_CHROMA_444; -} - -static bool colorPrimariesKnown(LGNetColorPrimaries primaries) -{ - return primaries >= LG_NET_COLOR_PRIMARIES_BT601 && - primaries <= LG_NET_COLOR_PRIMARIES_BT2020; -} - -static bool colorTransferKnown(LGNetColorTransfer transfer) -{ - return transfer >= LG_NET_COLOR_TRANSFER_LINEAR && - transfer <= LG_NET_COLOR_TRANSFER_HLG; -} - -static bool colorMatrixKnown(LGNetColorMatrix matrix) -{ - return matrix >= LG_NET_COLOR_MATRIX_BT601 && - matrix <= LG_NET_COLOR_MATRIX_RGB; -} - -static bool colorRangeKnown(LGNetColorRange range) -{ - return range == LG_NET_COLOR_RANGE_LIMITED || - range == LG_NET_COLOR_RANGE_FULL; -} - -bool lgNetVideoStreamConfigValid(const LGNetVideoStreamConfig * config) -{ - return config && config->streamID && videoCodecKnown(config->codec) && - config->codecVersion && config->configEpoch && config->width && - config->width <= LG_NET_VIDEO_MAX_WIDTH && config->height && - config->height <= LG_NET_VIDEO_MAX_HEIGHT && - config->refreshNumerator && config->refreshDenominator && - videoPixelFormatKnown(config->pixelFormat) && - videoChromaKnown(config->chromaSubsampling) && - colorPrimariesKnown(config->colorPrimaries) && - colorTransferKnown(config->colorTransfer) && - colorMatrixKnown(config->colorMatrix) && - colorRangeKnown(config->colorRange) && config->planeCount && - config->planeCount <= LG_NET_VIDEO_MAX_PLANES && config->bitDepth >= 8 && - config->bitDepth <= 16 && !(config->flags & ~VIDEO_STREAM_FLAGS) && - (config->flags & LG_NET_VIDEO_STREAM_GPU_PLANES_ONLY) && - videoPixelFormatValid(config) && - config->maxFrameLength && - config->maxFrameLength <= LG_NET_VIDEO_MAX_FRAME_LENGTH && - config->maxFragmentLength && - config->maxFragmentLength <= LG_NET_VIDEO_MAX_FRAGMENT_LENGTH && - config->maxFragmentLength <= config->maxFrameLength && - config->maxFrameLatencyMs; -} - -bool lgNetVideoStreamConfigEncode(void * data, size_t size, - const LGNetVideoStreamConfig * config) -{ - if (!data || size < LG_NET_VIDEO_STREAM_CONFIG_WIRE_SIZE || - !lgNetVideoStreamConfigValid(config)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU32(&writer, config->streamID) && - lgNetWriterU16(&writer, config->codec) && - lgNetWriterU16(&writer, config->codecVersion) && - lgNetWriterU64(&writer, config->configEpoch) && - lgNetWriterU32(&writer, config->width) && - lgNetWriterU32(&writer, config->height) && - lgNetWriterU32(&writer, config->refreshNumerator) && - lgNetWriterU32(&writer, config->refreshDenominator) && - lgNetWriterU16(&writer, config->pixelFormat) && - lgNetWriterU8 (&writer, config->chromaSubsampling) && - lgNetWriterU8 (&writer, config->colorPrimaries) && - lgNetWriterU8 (&writer, config->colorTransfer) && - lgNetWriterU8 (&writer, config->colorMatrix) && - lgNetWriterU8 (&writer, config->colorRange) && - lgNetWriterU8 (&writer, config->planeCount) && - lgNetWriterU8 (&writer, config->bitDepth) && - lgNetWriterU8 (&writer, 0) && - lgNetWriterU16(&writer, config->flags) && - lgNetWriterU16(&writer, 0) && - lgNetWriterU32(&writer, config->maxFrameLength) && - lgNetWriterU32(&writer, config->maxFragmentLength) && - lgNetWriterU32(&writer, config->maxFrameLatencyMs) && - lgNetWriterZero(&writer, 2) && - lgNetWriterSize(&writer) == LG_NET_VIDEO_STREAM_CONFIG_WIRE_SIZE; -} - -LGNetParseResult lgNetVideoStreamConfigDecode( - LGNetVideoStreamConfig * config, const void * data, size_t size) -{ - if (!config || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_VIDEO_STREAM_CONFIG_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetVideoStreamConfig decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU32(&reader, &decoded.streamID) || - !lgNetReaderU16(&reader, &decoded.codec) || - !lgNetReaderU16(&reader, &decoded.codecVersion) || - !lgNetReaderU64(&reader, &decoded.configEpoch) || - !lgNetReaderU32(&reader, &decoded.width) || - !lgNetReaderU32(&reader, &decoded.height) || - !lgNetReaderU32(&reader, &decoded.refreshNumerator) || - !lgNetReaderU32(&reader, &decoded.refreshDenominator) || - !lgNetReaderU16(&reader, &decoded.pixelFormat) || - !lgNetReaderU8 (&reader, &decoded.chromaSubsampling) || - !lgNetReaderU8 (&reader, &decoded.colorPrimaries) || - !lgNetReaderU8 (&reader, &decoded.colorTransfer) || - !lgNetReaderU8 (&reader, &decoded.colorMatrix) || - !lgNetReaderU8 (&reader, &decoded.colorRange) || - !lgNetReaderU8 (&reader, &decoded.planeCount) || - !lgNetReaderU8 (&reader, &decoded.bitDepth) || - !lgNetReaderZero(&reader, 1) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderZero(&reader, 2) || - !lgNetReaderU32(&reader, &decoded.maxFrameLength) || - !lgNetReaderU32(&reader, &decoded.maxFragmentLength) || - !lgNetReaderU32(&reader, &decoded.maxFrameLatencyMs) || - !lgNetReaderZero(&reader, 2)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_VIDEO_STREAM_CONFIG_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetVideoStreamConfigValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *config = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetVideoFrameSize(const LGNetVideoFrame * frame) -{ - size_t size; - return frame && variableSize(LG_NET_VIDEO_FRAME_HEADER_WIRE_SIZE, - frame->encodedLength, LG_NET_VIDEO_MAX_FRAME_LENGTH, &size) ? size : 0; -} - -bool lgNetVideoFrameValid(const LGNetVideoFrame * frame) -{ - return frame && frame->streamID && videoCodecKnown(frame->codec) && - !(frame->flags & ~VIDEO_FRAME_FLAGS) && frame->configEpoch && - frame->frameID && frame->captureTimestampNs && - frame->presentationTimestampNs && frame->encodedLength && frame->data && - frame->blockCount && frame->fragmentCount && frame->deadlineMs && - ((frame->flags & LG_NET_VIDEO_FRAME_HAS_CHECKSUM) || !frame->checksum) && - lgNetVideoFrameSize(frame) != 0; -} - -bool lgNetVideoFrameEncode( - void * data, size_t size, const LGNetVideoFrame * frame) -{ - const size_t wireSize = lgNetVideoFrameSize(frame); - if (!data || !wireSize || size < wireSize || !lgNetVideoFrameValid(frame)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU32(&writer, frame->streamID) && - lgNetWriterU16(&writer, frame->codec) && - lgNetWriterU16(&writer, frame->flags) && - lgNetWriterU64(&writer, frame->configEpoch) && - lgNetWriterU64(&writer, frame->frameID) && - lgNetWriterU64(&writer, frame->captureTimestampNs) && - lgNetWriterU64(&writer, frame->presentationTimestampNs) && - lgNetWriterU32(&writer, frame->encodedLength) && - lgNetWriterU16(&writer, frame->blockCount) && - lgNetWriterU16(&writer, frame->fragmentCount) && - lgNetWriterU32(&writer, frame->deadlineMs) && - lgNetWriterU32(&writer, frame->checksum) && - lgNetWriterBytes(&writer, frame->data, frame->encodedLength) && - lgNetWriterSize(&writer) == wireSize; -} - -LGNetParseResult lgNetVideoFrameDecode( - LGNetVideoFrame * frame, const void * data, size_t size) -{ - if (!frame || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_VIDEO_FRAME_HEADER_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetVideoFrame decoded; - LGNetReader reader; - size_t expected; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU32(&reader, &decoded.streamID) || - !lgNetReaderU16(&reader, &decoded.codec) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderU64(&reader, &decoded.configEpoch) || - !lgNetReaderU64(&reader, &decoded.frameID) || - !lgNetReaderU64(&reader, &decoded.captureTimestampNs) || - !lgNetReaderU64(&reader, &decoded.presentationTimestampNs) || - !lgNetReaderU32(&reader, &decoded.encodedLength) || - !lgNetReaderU16(&reader, &decoded.blockCount) || - !lgNetReaderU16(&reader, &decoded.fragmentCount) || - !lgNetReaderU32(&reader, &decoded.deadlineMs) || - !lgNetReaderU32(&reader, &decoded.checksum)) - return LG_NET_PARSE_INVALID_VALUE; - - LGNetParseResult result = variableDecodeSize( - LG_NET_VIDEO_FRAME_HEADER_WIRE_SIZE, decoded.encodedLength, - LG_NET_VIDEO_MAX_FRAME_LENGTH, size, &expected); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetReaderView(&reader, &decoded.data, decoded.encodedLength)) - return LG_NET_PARSE_INVALID_VALUE; - result = fixedDecodeResult(&reader, expected, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetVideoFrameValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *frame = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetVideoFragmentSize(const LGNetVideoFragment * fragment) -{ - size_t size; - return fragment && variableSize(LG_NET_VIDEO_FRAGMENT_HEADER_WIRE_SIZE, - fragment->payloadLength, LG_NET_VIDEO_MAX_FRAGMENT_LENGTH, &size) ? - size : 0; -} - -bool lgNetVideoFragmentValid(const LGNetVideoFragment * fragment) -{ - return fragment && fragment->streamID && fragment->configEpoch && - fragment->frameID && fragment->frameLength && - fragment->frameLength <= LG_NET_VIDEO_MAX_FRAME_LENGTH && - fragment->fragmentCount && - fragment->fragmentIndex < fragment->fragmentCount && - fragment->blockCount && - fragment->blockIndex < fragment->blockCount && fragment->payloadLength && - fragment->payload && !(fragment->flags & ~VIDEO_FRAGMENT_FLAGS) && - fragment->offset <= fragment->frameLength && - fragment->payloadLength <= fragment->frameLength - fragment->offset && - (!(fragment->flags & LG_NET_VIDEO_FRAGMENT_FRAME_END) || - fragment->offset + fragment->payloadLength == fragment->frameLength) && - lgNetVideoFragmentSize(fragment) != 0; -} - -bool lgNetVideoFragmentEncode( - void * data, size_t size, const LGNetVideoFragment * fragment) -{ - const size_t wireSize = lgNetVideoFragmentSize(fragment); - if (!data || !wireSize || size < wireSize || - !lgNetVideoFragmentValid(fragment)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU32(&writer, fragment->streamID) && - lgNetWriterU64(&writer, fragment->configEpoch) && - lgNetWriterU64(&writer, fragment->frameID) && - lgNetWriterU32(&writer, fragment->frameLength) && - lgNetWriterU32(&writer, fragment->offset) && - lgNetWriterU16(&writer, fragment->fragmentIndex) && - lgNetWriterU16(&writer, fragment->fragmentCount) && - lgNetWriterU16(&writer, fragment->blockIndex) && - lgNetWriterU16(&writer, fragment->blockCount) && - lgNetWriterU16(&writer, fragment->payloadLength) && - lgNetWriterU16(&writer, fragment->flags) && - lgNetWriterBytes(&writer, fragment->payload, - fragment->payloadLength) && - lgNetWriterSize(&writer) == wireSize; -} - -LGNetParseResult lgNetVideoFragmentDecode( - LGNetVideoFragment * fragment, const void * data, size_t size) -{ - if (!fragment || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_VIDEO_FRAGMENT_HEADER_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetVideoFragment decoded; - LGNetReader reader; - size_t expected; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU32(&reader, &decoded.streamID) || - !lgNetReaderU64(&reader, &decoded.configEpoch) || - !lgNetReaderU64(&reader, &decoded.frameID) || - !lgNetReaderU32(&reader, &decoded.frameLength) || - !lgNetReaderU32(&reader, &decoded.offset) || - !lgNetReaderU16(&reader, &decoded.fragmentIndex) || - !lgNetReaderU16(&reader, &decoded.fragmentCount) || - !lgNetReaderU16(&reader, &decoded.blockIndex) || - !lgNetReaderU16(&reader, &decoded.blockCount) || - !lgNetReaderU16(&reader, &decoded.payloadLength) || - !lgNetReaderU16(&reader, &decoded.flags)) - return LG_NET_PARSE_INVALID_VALUE; - - LGNetParseResult result = variableDecodeSize( - LG_NET_VIDEO_FRAGMENT_HEADER_WIRE_SIZE, decoded.payloadLength, - LG_NET_VIDEO_MAX_FRAGMENT_LENGTH, size, &expected); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetReaderView(&reader, &decoded.payload, decoded.payloadLength)) - return LG_NET_PARSE_INVALID_VALUE; - result = fixedDecodeResult(&reader, expected, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetVideoFragmentValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *fragment = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetVideoFeedbackValid(const LGNetVideoFeedback * feedback) -{ - return feedback && feedback->streamID && - !(feedback->flags & ~VIDEO_FEEDBACK_FLAGS) && - feedback->lastCompleteFrameID <= feedback->highestSeenFrameID && - feedback->lastDecodedFrameID <= feedback->lastCompleteFrameID; -} - -bool lgNetVideoFeedbackEncode( - void * data, size_t size, const LGNetVideoFeedback * feedback) -{ - if (!data || size < LG_NET_VIDEO_FEEDBACK_WIRE_SIZE || - !lgNetVideoFeedbackValid(feedback)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU32(&writer, feedback->streamID) && - lgNetWriterU32(&writer, feedback->flags) && - lgNetWriterU64(&writer, feedback->lastCompleteFrameID) && - lgNetWriterU64(&writer, feedback->highestSeenFrameID) && - lgNetWriterU64(&writer, feedback->lastDecodedFrameID) && - lgNetWriterU32(&writer, feedback->lostFrames) && - lgNetWriterU32(&writer, feedback->lostFragments) && - lgNetWriterU32(&writer, feedback->receiveQueueUs) && - lgNetWriterU32(&writer, feedback->decodeQueueUs) && - lgNetWriterU32(&writer, feedback->roundTripUs) && - lgNetWriterU32(&writer, 0) && - lgNetWriterSize(&writer) == LG_NET_VIDEO_FEEDBACK_WIRE_SIZE; -} - -LGNetParseResult lgNetVideoFeedbackDecode( - LGNetVideoFeedback * feedback, const void * data, size_t size) -{ - if (!feedback || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_VIDEO_FEEDBACK_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetVideoFeedback decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU32(&reader, &decoded.streamID) || - !lgNetReaderU32(&reader, &decoded.flags) || - !lgNetReaderU64(&reader, &decoded.lastCompleteFrameID) || - !lgNetReaderU64(&reader, &decoded.highestSeenFrameID) || - !lgNetReaderU64(&reader, &decoded.lastDecodedFrameID) || - !lgNetReaderU32(&reader, &decoded.lostFrames) || - !lgNetReaderU32(&reader, &decoded.lostFragments) || - !lgNetReaderU32(&reader, &decoded.receiveQueueUs) || - !lgNetReaderU32(&reader, &decoded.decodeQueueUs) || - !lgNetReaderU32(&reader, &decoded.roundTripUs) || - !lgNetReaderZero(&reader, 4)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_VIDEO_FEEDBACK_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetVideoFeedbackValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *feedback = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetCursorPositionValid(const LGNetCursorPosition * position) -{ - return position && position->updateID && position->timestampNs && - position->desktopWidth && position->desktopHeight && - position->desktopWidth <= LG_NET_VIDEO_MAX_WIDTH && - position->desktopHeight <= LG_NET_VIDEO_MAX_HEIGHT && - !(position->flags & ~CURSOR_POSITION_FLAGS); -} - -bool lgNetCursorPositionEncode( - void * data, size_t size, const LGNetCursorPosition * position) -{ - if (!data || size < LG_NET_CURSOR_POSITION_WIRE_SIZE || - !lgNetCursorPositionValid(position)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, position->updateID) && - lgNetWriterU64(&writer, position->timestampNs) && - lgNetWriterI32(&writer, position->x) && - lgNetWriterI32(&writer, position->y) && - lgNetWriterU32(&writer, position->desktopWidth) && - lgNetWriterU32(&writer, position->desktopHeight) && - lgNetWriterU32(&writer, position->flags) && - lgNetWriterU32(&writer, position->displayID) && - lgNetWriterSize(&writer) == LG_NET_CURSOR_POSITION_WIRE_SIZE; -} - -LGNetParseResult lgNetCursorPositionDecode( - LGNetCursorPosition * position, const void * data, size_t size) -{ - if (!position || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_CURSOR_POSITION_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetCursorPosition decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.updateID) || - !lgNetReaderU64(&reader, &decoded.timestampNs) || - !lgNetReaderI32(&reader, &decoded.x) || - !lgNetReaderI32(&reader, &decoded.y) || - !lgNetReaderU32(&reader, &decoded.desktopWidth) || - !lgNetReaderU32(&reader, &decoded.desktopHeight) || - !lgNetReaderU32(&reader, &decoded.flags) || - !lgNetReaderU32(&reader, &decoded.displayID)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_CURSOR_POSITION_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetCursorPositionValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *position = decoded; - return LG_NET_PARSE_OK; -} - -static bool cursorFormatKnown(LGNetCursorFormat format) -{ - return format >= LG_NET_CURSOR_FORMAT_BGRA8_PREMULTIPLIED && - format <= LG_NET_CURSOR_FORMAT_MONOCHROME; -} - -static bool cursorShapeLayoutValid(const LGNetCursorShape * shape) -{ - uint32_t minimumPitch; - switch (shape->format) - { - case LG_NET_CURSOR_FORMAT_BGRA8_PREMULTIPLIED: - case LG_NET_CURSOR_FORMAT_RGBA8_PREMULTIPLIED: - case LG_NET_CURSOR_FORMAT_MASKED_COLOR: - minimumPitch = shape->width * 4U; - break; - - case LG_NET_CURSOR_FORMAT_MONOCHROME: - minimumPitch = (shape->width + 7U) / 8U; - break; - - default: - return false; - } - - return shape->pitch >= minimumPitch && - shape->height <= shape->dataLength / shape->pitch; -} - -size_t lgNetCursorShapeSize(const LGNetCursorShape * shape) -{ - size_t size; - return shape && variableSize(LG_NET_CURSOR_SHAPE_HEADER_WIRE_SIZE, - shape->dataLength, LG_NET_CURSOR_MAX_SHAPE_LENGTH, &size) ? size : 0; -} - -bool lgNetCursorShapeValid(const LGNetCursorShape * shape) -{ - return shape && shape->shapeID && shape->width && - shape->width <= LG_NET_CURSOR_MAX_WIDTH && shape->height && - shape->height <= LG_NET_CURSOR_MAX_HEIGHT && shape->pitch && - shape->dataLength && shape->data && cursorFormatKnown(shape->format) && - !(shape->flags & ~CURSOR_SHAPE_FLAGS) && shape->hotspotX < shape->width && - shape->hotspotY < shape->height && - cursorShapeLayoutValid(shape) && - ((shape->flags & LG_NET_CURSOR_SHAPE_ANIMATED) ? - shape->frameDurationMs != 0 : shape->frameDurationMs == 0) && - lgNetCursorShapeSize(shape) != 0; -} - -bool lgNetCursorShapeEncode( - void * data, size_t size, const LGNetCursorShape * shape) -{ - const size_t wireSize = lgNetCursorShapeSize(shape); - if (!data || !wireSize || size < wireSize || !lgNetCursorShapeValid(shape)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, shape->shapeID) && - lgNetWriterU32(&writer, shape->width) && - lgNetWriterU32(&writer, shape->height) && - lgNetWriterU32(&writer, shape->pitch) && - lgNetWriterU32(&writer, shape->dataLength) && - lgNetWriterU16(&writer, shape->format) && - lgNetWriterU16(&writer, shape->flags) && - lgNetWriterU32(&writer, shape->hotspotX) && - lgNetWriterU32(&writer, shape->hotspotY) && - lgNetWriterU32(&writer, shape->frameDurationMs) && - lgNetWriterBytes(&writer, shape->data, shape->dataLength) && - lgNetWriterSize(&writer) == wireSize; -} - -LGNetParseResult lgNetCursorShapeDecode( - LGNetCursorShape * shape, const void * data, size_t size) -{ - if (!shape || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_CURSOR_SHAPE_HEADER_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetCursorShape decoded; - LGNetReader reader; - size_t expected; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.shapeID) || - !lgNetReaderU32(&reader, &decoded.width) || - !lgNetReaderU32(&reader, &decoded.height) || - !lgNetReaderU32(&reader, &decoded.pitch) || - !lgNetReaderU32(&reader, &decoded.dataLength) || - !lgNetReaderU16(&reader, &decoded.format) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderU32(&reader, &decoded.hotspotX) || - !lgNetReaderU32(&reader, &decoded.hotspotY) || - !lgNetReaderU32(&reader, &decoded.frameDurationMs)) - return LG_NET_PARSE_INVALID_VALUE; - - LGNetParseResult result = variableDecodeSize( - LG_NET_CURSOR_SHAPE_HEADER_WIRE_SIZE, decoded.dataLength, - LG_NET_CURSOR_MAX_SHAPE_LENGTH, size, &expected); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetReaderView(&reader, &decoded.data, decoded.dataLength)) - return LG_NET_PARSE_INVALID_VALUE; - result = fixedDecodeResult(&reader, expected, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetCursorShapeValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *shape = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetInputClaimValid(const LGNetInputClaim * claim) -{ - return claim && claim->claimantID && claim->claimEpoch && claim->leaseMs && - claim->flags && !(claim->flags & ~INPUT_CLAIM_FLAGS) && - (!(claim->flags & LG_NET_INPUT_CLAIM_EXCLUSIVE) || - (claim->flags & (LG_NET_INPUT_CLAIM_KEYBOARD | - LG_NET_INPUT_CLAIM_POINTER))); -} - -bool lgNetInputClaimEncode( - void * data, size_t size, const LGNetInputClaim * claim) -{ - if (!data || size < LG_NET_INPUT_CLAIM_WIRE_SIZE || - !lgNetInputClaimValid(claim)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, claim->claimantID) && - lgNetWriterU64(&writer, claim->claimEpoch) && - lgNetWriterU32(&writer, claim->leaseMs) && - lgNetWriterU32(&writer, claim->flags) && - lgNetWriterSize(&writer) == LG_NET_INPUT_CLAIM_WIRE_SIZE; -} - -LGNetParseResult lgNetInputClaimDecode( - LGNetInputClaim * claim, const void * data, size_t size) -{ - if (!claim || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_INPUT_CLAIM_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetInputClaim decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.claimantID) || - !lgNetReaderU64(&reader, &decoded.claimEpoch) || - !lgNetReaderU32(&reader, &decoded.leaseMs) || - !lgNetReaderU32(&reader, &decoded.flags)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_INPUT_CLAIM_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetInputClaimValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *claim = decoded; - return LG_NET_PARSE_OK; -} - -static bool inputStatusKnown(LGNetInputStatusCode status) -{ - return status >= LG_NET_INPUT_STATUS_ACCEPTED && - status <= LG_NET_INPUT_STATUS_ERROR; -} - -bool lgNetInputStatusValid(const LGNetInputStatus * status) -{ - return status && status->claimEpoch && inputStatusKnown(status->status) && - !(status->flags & ~INPUT_CLAIM_FLAGS); -} - -bool lgNetInputStatusEncode( - void * data, size_t size, const LGNetInputStatus * status) -{ - if (!data || size < LG_NET_INPUT_STATUS_WIRE_SIZE || - !lgNetInputStatusValid(status)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, status->claimEpoch) && - lgNetWriterU64(&writer, status->lastSequence) && - lgNetWriterU32(&writer, status->status) && - lgNetWriterU32(&writer, status->flags) && - lgNetWriterU32(&writer, status->leaseRemainingMs) && - lgNetWriterU32(&writer, status->detail) && - lgNetWriterSize(&writer) == LG_NET_INPUT_STATUS_WIRE_SIZE; -} - -LGNetParseResult lgNetInputStatusDecode( - LGNetInputStatus * status, const void * data, size_t size) -{ - if (!status || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_INPUT_STATUS_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetInputStatus decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.claimEpoch) || - !lgNetReaderU64(&reader, &decoded.lastSequence) || - !lgNetReaderU32(&reader, &decoded.status) || - !lgNetReaderU32(&reader, &decoded.flags) || - !lgNetReaderU32(&reader, &decoded.leaseRemainingMs) || - !lgNetReaderU32(&reader, &decoded.detail)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_INPUT_STATUS_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetInputStatusValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *status = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetInputRelativeValid(const LGNetInputRelative * relative) -{ - return relative && relative->sequence && relative->timestampNs; -} - -bool lgNetInputRelativeEncode( - void * data, size_t size, const LGNetInputRelative * relative) -{ - if (!data || size < LG_NET_INPUT_RELATIVE_WIRE_SIZE || - !lgNetInputRelativeValid(relative)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, relative->sequence) && - lgNetWriterU64(&writer, relative->timestampNs) && - lgNetWriterI32(&writer, relative->deltaX) && - lgNetWriterI32(&writer, relative->deltaY) && - lgNetWriterI32(&writer, relative->wheelX) && - lgNetWriterI32(&writer, relative->wheelY) && - lgNetWriterU32(&writer, relative->buttons) && - lgNetWriterU32(&writer, relative->changedButtons) && - lgNetWriterSize(&writer) == LG_NET_INPUT_RELATIVE_WIRE_SIZE; -} - -LGNetParseResult lgNetInputRelativeDecode( - LGNetInputRelative * relative, const void * data, size_t size) -{ - if (!relative || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_INPUT_RELATIVE_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetInputRelative decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.sequence) || - !lgNetReaderU64(&reader, &decoded.timestampNs) || - !lgNetReaderI32(&reader, &decoded.deltaX) || - !lgNetReaderI32(&reader, &decoded.deltaY) || - !lgNetReaderI32(&reader, &decoded.wheelX) || - !lgNetReaderI32(&reader, &decoded.wheelY) || - !lgNetReaderU32(&reader, &decoded.buttons) || - !lgNetReaderU32(&reader, &decoded.changedButtons)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_INPUT_RELATIVE_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetInputRelativeValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *relative = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetInputAbsoluteValid(const LGNetInputAbsolute * absolute) -{ - return absolute && absolute->sequence && absolute->timestampNs && - absolute->width && - absolute->width <= LG_NET_INPUT_ABSOLUTE_MAX_WIDTH && - absolute->height && - absolute->height <= LG_NET_INPUT_ABSOLUTE_MAX_HEIGHT && - absolute->x >= 0 && absolute->y >= 0 && - (uint32_t)absolute->x < absolute->width && - (uint32_t)absolute->y < absolute->height; -} - -bool lgNetInputAbsoluteEncode( - void * data, size_t size, const LGNetInputAbsolute * absolute) -{ - if (!data || size < LG_NET_INPUT_ABSOLUTE_WIRE_SIZE || - !lgNetInputAbsoluteValid(absolute)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, absolute->sequence) && - lgNetWriterU64(&writer, absolute->timestampNs) && - lgNetWriterI32(&writer, absolute->x) && - lgNetWriterI32(&writer, absolute->y) && - lgNetWriterU32(&writer, absolute->width) && - lgNetWriterU32(&writer, absolute->height) && - lgNetWriterI32(&writer, absolute->wheelX) && - lgNetWriterI32(&writer, absolute->wheelY) && - lgNetWriterU32(&writer, absolute->buttons) && - lgNetWriterU32(&writer, absolute->changedButtons) && - lgNetWriterSize(&writer) == LG_NET_INPUT_ABSOLUTE_WIRE_SIZE; -} - -LGNetParseResult lgNetInputAbsoluteDecode( - LGNetInputAbsolute * absolute, const void * data, size_t size) -{ - if (!absolute || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_INPUT_ABSOLUTE_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetInputAbsolute decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.sequence) || - !lgNetReaderU64(&reader, &decoded.timestampNs) || - !lgNetReaderI32(&reader, &decoded.x) || - !lgNetReaderI32(&reader, &decoded.y) || - !lgNetReaderU32(&reader, &decoded.width) || - !lgNetReaderU32(&reader, &decoded.height) || - !lgNetReaderI32(&reader, &decoded.wheelX) || - !lgNetReaderI32(&reader, &decoded.wheelY) || - !lgNetReaderU32(&reader, &decoded.buttons) || - !lgNetReaderU32(&reader, &decoded.changedButtons)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_INPUT_ABSOLUTE_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetInputAbsoluteValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *absolute = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetInputKeyboardValid(const LGNetInputKeyboard * keyboard) -{ - return keyboard && keyboard->sequence && keyboard->timestampNs && - (keyboard->usage || keyboard->scanCode) && - !(keyboard->flags & ~KEYBOARD_FLAGS) && - !(keyboard->modifiers & ~LG_NET_INPUT_KEYBOARD_MODIFIER_MASK); -} - -bool lgNetInputKeyboardEncode( - void * data, size_t size, const LGNetInputKeyboard * keyboard) -{ - if (!data || size < LG_NET_INPUT_KEYBOARD_WIRE_SIZE || - !lgNetInputKeyboardValid(keyboard)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, keyboard->sequence) && - lgNetWriterU64(&writer, keyboard->timestampNs) && - lgNetWriterU16(&writer, keyboard->usagePage) && - lgNetWriterU16(&writer, keyboard->usage) && - lgNetWriterU16(&writer, keyboard->scanCode) && - lgNetWriterU16(&writer, keyboard->flags) && - lgNetWriterU32(&writer, keyboard->modifiers) && - lgNetWriterU32(&writer, 0) && - lgNetWriterSize(&writer) == LG_NET_INPUT_KEYBOARD_WIRE_SIZE; -} - -LGNetParseResult lgNetInputKeyboardDecode( - LGNetInputKeyboard * keyboard, const void * data, size_t size) -{ - if (!keyboard || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_INPUT_KEYBOARD_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetInputKeyboard decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.sequence) || - !lgNetReaderU64(&reader, &decoded.timestampNs) || - !lgNetReaderU16(&reader, &decoded.usagePage) || - !lgNetReaderU16(&reader, &decoded.usage) || - !lgNetReaderU16(&reader, &decoded.scanCode) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderU32(&reader, &decoded.modifiers) || - !lgNetReaderZero(&reader, 4)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_INPUT_KEYBOARD_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetInputKeyboardValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *keyboard = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetInputLEDsValid(const LGNetInputLEDs * leds) -{ - return leds && leds->sequence && leds->validMask && - !(leds->state & ~KEYBOARD_LEDS) && !(leds->validMask & ~KEYBOARD_LEDS) && - !(leds->state & ~leds->validMask); -} - -bool lgNetInputLEDsEncode( - void * data, size_t size, const LGNetInputLEDs * leds) -{ - if (!data || size < LG_NET_INPUT_LEDS_WIRE_SIZE || - !lgNetInputLEDsValid(leds)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, leds->sequence) && - lgNetWriterU32(&writer, leds->state) && - lgNetWriterU32(&writer, leds->validMask) && - lgNetWriterSize(&writer) == LG_NET_INPUT_LEDS_WIRE_SIZE; -} - -LGNetParseResult lgNetInputLEDsDecode( - LGNetInputLEDs * leds, const void * data, size_t size) -{ - if (!leds || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_INPUT_LEDS_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetInputLEDs decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.sequence) || - !lgNetReaderU32(&reader, &decoded.state) || - !lgNetReaderU32(&reader, &decoded.validMask)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_INPUT_LEDS_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetInputLEDsValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *leds = decoded; - return LG_NET_PARSE_OK; -} - -static bool audioDirectionKnown(LGNetAudioDirection direction) -{ - return direction == LG_NET_AUDIO_DIRECTION_PLAYBACK || - direction == LG_NET_AUDIO_DIRECTION_CAPTURE; -} - -static bool audioSampleFormatKnown(LGNetAudioSampleFormat format) -{ - return format >= LG_NET_AUDIO_SAMPLE_S16_LE && - format <= LG_NET_AUDIO_SAMPLE_F32_LE; -} - -static size_t audioSampleSize(LGNetAudioSampleFormat format) -{ - switch (format) - { - case LG_NET_AUDIO_SAMPLE_S16_LE: - return 2; - - case LG_NET_AUDIO_SAMPLE_S24_LE: - return 3; - - case LG_NET_AUDIO_SAMPLE_S32_LE: - case LG_NET_AUDIO_SAMPLE_F32_LE: - return 4; - } - - return 0; -} - -bool lgNetAudioFormatValid(const LGNetAudioFormat * format) -{ - return format && format->streamID && - audioDirectionKnown(format->direction) && - audioSampleFormatKnown(format->sampleFormat) && format->formatEpoch && - format->sampleRate && format->sampleRate <= LG_NET_AUDIO_MAX_SAMPLE_RATE && - format->channels && format->channels <= LG_NET_AUDIO_MAX_CHANNELS && - format->framesPerPacket && - format->framesPerPacket <= LG_NET_AUDIO_MAX_PACKET_FRAMES && - format->maxPacketFrames >= format->framesPerPacket && - format->maxPacketFrames <= LG_NET_AUDIO_MAX_PACKET_FRAMES && - !(format->flags & ~AUDIO_FORMAT_FLAGS); -} - -bool lgNetAudioFormatEncode( - void * data, size_t size, const LGNetAudioFormat * format) -{ - if (!data || size < LG_NET_AUDIO_FORMAT_WIRE_SIZE || - !lgNetAudioFormatValid(format)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU32(&writer, format->streamID) && - lgNetWriterU16(&writer, format->direction) && - lgNetWriterU16(&writer, format->sampleFormat) && - lgNetWriterU64(&writer, format->formatEpoch) && - lgNetWriterU32(&writer, format->sampleRate) && - lgNetWriterU16(&writer, format->channels) && - lgNetWriterU16(&writer, format->framesPerPacket) && - lgNetWriterU32(&writer, format->channelMask) && - lgNetWriterU32(&writer, format->flags) && - lgNetWriterU32(&writer, format->maxPacketFrames) && - lgNetWriterU32(&writer, 0) && - lgNetWriterSize(&writer) == LG_NET_AUDIO_FORMAT_WIRE_SIZE; -} - -LGNetParseResult lgNetAudioFormatDecode( - LGNetAudioFormat * format, const void * data, size_t size) -{ - if (!format || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_AUDIO_FORMAT_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetAudioFormat decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU32(&reader, &decoded.streamID) || - !lgNetReaderU16(&reader, &decoded.direction) || - !lgNetReaderU16(&reader, &decoded.sampleFormat) || - !lgNetReaderU64(&reader, &decoded.formatEpoch) || - !lgNetReaderU32(&reader, &decoded.sampleRate) || - !lgNetReaderU16(&reader, &decoded.channels) || - !lgNetReaderU16(&reader, &decoded.framesPerPacket) || - !lgNetReaderU32(&reader, &decoded.channelMask) || - !lgNetReaderU32(&reader, &decoded.flags) || - !lgNetReaderU32(&reader, &decoded.maxPacketFrames) || - !lgNetReaderZero(&reader, 4)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_AUDIO_FORMAT_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetAudioFormatValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *format = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetAudioDataSize(const LGNetAudioData * audio) -{ - size_t size; - return audio && variableSize(LG_NET_AUDIO_DATA_HEADER_WIRE_SIZE, - audio->dataLength, LG_NET_AUDIO_MAX_DATA_LENGTH, &size) ? size : 0; -} - -bool lgNetAudioDataValid(const LGNetAudioData * audio) -{ - return audio && audio->streamID && - audioDirectionKnown(audio->direction) && - !(audio->flags & ~AUDIO_DATA_FLAGS) && audio->formatEpoch && - audio->packetID && audio->timestampNs && audio->frameCount && - audio->frameCount <= LG_NET_AUDIO_MAX_PACKET_FRAMES && - ((audio->flags & LG_NET_AUDIO_DATA_SILENT) ? - !audio->dataLength && !audio->data : audio->dataLength && audio->data) && - lgNetAudioDataSize(audio) != 0; -} - -bool lgNetAudioDataMatchesFormat( - const LGNetAudioData * audio, const LGNetAudioFormat * format) -{ - if (!lgNetAudioDataValid(audio) || !lgNetAudioFormatValid(format) || - audio->streamID != format->streamID || - audio->direction != format->direction || - audio->formatEpoch != format->formatEpoch || - audio->frameCount > format->maxPacketFrames) - return false; - - if (audio->flags & LG_NET_AUDIO_DATA_SILENT) - return true; - - const size_t sampleSize = audioSampleSize(format->sampleFormat); - if (!sampleSize || format->channels > SIZE_MAX / sampleSize) - return false; - - const size_t frameSize = sampleSize * format->channels; - return audio->frameCount <= SIZE_MAX / frameSize && - audio->dataLength == (size_t)audio->frameCount * frameSize; -} - -bool lgNetAudioDataEncode( - void * data, size_t size, const LGNetAudioData * audio) -{ - const size_t wireSize = lgNetAudioDataSize(audio); - if (!data || !wireSize || size < wireSize || !lgNetAudioDataValid(audio)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU32(&writer, audio->streamID) && - lgNetWriterU16(&writer, audio->direction) && - lgNetWriterU16(&writer, audio->flags) && - lgNetWriterU64(&writer, audio->formatEpoch) && - lgNetWriterU64(&writer, audio->packetID) && - lgNetWriterU64(&writer, audio->timestampNs) && - lgNetWriterU64(&writer, audio->startFrame) && - lgNetWriterU32(&writer, audio->frameCount) && - lgNetWriterU32(&writer, audio->dataLength) && - lgNetWriterBytes(&writer, audio->data, audio->dataLength) && - lgNetWriterSize(&writer) == wireSize; -} - -LGNetParseResult lgNetAudioDataDecode( - LGNetAudioData * audio, const void * data, size_t size) -{ - if (!audio || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_AUDIO_DATA_HEADER_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetAudioData decoded; - LGNetReader reader; - size_t expected; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU32(&reader, &decoded.streamID) || - !lgNetReaderU16(&reader, &decoded.direction) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderU64(&reader, &decoded.formatEpoch) || - !lgNetReaderU64(&reader, &decoded.packetID) || - !lgNetReaderU64(&reader, &decoded.timestampNs) || - !lgNetReaderU64(&reader, &decoded.startFrame) || - !lgNetReaderU32(&reader, &decoded.frameCount) || - !lgNetReaderU32(&reader, &decoded.dataLength)) - return LG_NET_PARSE_INVALID_VALUE; - - LGNetParseResult result = variableDecodeSize( - LG_NET_AUDIO_DATA_HEADER_WIRE_SIZE, decoded.dataLength, - LG_NET_AUDIO_MAX_DATA_LENGTH, size, &expected); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetReaderView(&reader, &decoded.data, decoded.dataLength)) - return LG_NET_PARSE_INVALID_VALUE; - result = fixedDecodeResult(&reader, expected, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetAudioDataValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *audio = decoded; - return LG_NET_PARSE_OK; -} - -static bool audioStateKnown(LGNetAudioStateCode state) -{ - return state >= LG_NET_AUDIO_STATE_STOPPED && - state <= LG_NET_AUDIO_STATE_ERROR; -} - -bool lgNetAudioStateValid(const LGNetAudioState * state) -{ - return state && state->streamID && - audioDirectionKnown(state->direction) && audioStateKnown(state->state) && - state->stateSequence && !(state->flags & ~AUDIO_STATE_FLAGS) && - (!(state->flags & LG_NET_AUDIO_STATE_FORMAT_ACTIVE) || state->formatEpoch); -} - -bool lgNetAudioStateEncode( - void * data, size_t size, const LGNetAudioState * state) -{ - if (!data || size < LG_NET_AUDIO_STATE_WIRE_SIZE || - !lgNetAudioStateValid(state)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU32(&writer, state->streamID) && - lgNetWriterU16(&writer, state->direction) && - lgNetWriterU16(&writer, state->state) && - lgNetWriterU64(&writer, state->stateSequence) && - lgNetWriterU64(&writer, state->formatEpoch) && - lgNetWriterI32(&writer, state->volumeMillibels) && - lgNetWriterU32(&writer, state->flags) && - lgNetWriterSize(&writer) == LG_NET_AUDIO_STATE_WIRE_SIZE; -} - -LGNetParseResult lgNetAudioStateDecode( - LGNetAudioState * state, const void * data, size_t size) -{ - if (!state || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_AUDIO_STATE_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetAudioState decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU32(&reader, &decoded.streamID) || - !lgNetReaderU16(&reader, &decoded.direction) || - !lgNetReaderU16(&reader, &decoded.state) || - !lgNetReaderU64(&reader, &decoded.stateSequence) || - !lgNetReaderU64(&reader, &decoded.formatEpoch) || - !lgNetReaderI32(&reader, &decoded.volumeMillibels) || - !lgNetReaderU32(&reader, &decoded.flags)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_AUDIO_STATE_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetAudioStateValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *state = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetAudioClockFeedbackValid( - const LGNetAudioClockFeedback * feedback) -{ - return feedback && feedback->streamID && - audioDirectionKnown(feedback->direction) && feedback->formatEpoch && - feedback->packetID && feedback->timestampNs; -} - -bool lgNetAudioClockFeedbackEncode(void * data, size_t size, - const LGNetAudioClockFeedback * feedback) -{ - if (!data || size < LG_NET_AUDIO_CLOCK_FEEDBACK_WIRE_SIZE || - !lgNetAudioClockFeedbackValid(feedback)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU32(&writer, feedback->streamID) && - lgNetWriterU16(&writer, feedback->direction) && - lgNetWriterZero(&writer, 2) && - lgNetWriterU64(&writer, feedback->formatEpoch) && - lgNetWriterU64(&writer, feedback->packetID) && - lgNetWriterU64(&writer, feedback->framePosition) && - lgNetWriterU64(&writer, feedback->timestampNs) && - lgNetWriterI32(&writer, feedback->queuedFrames) && - lgNetWriterI32(&writer, feedback->driftPpm) && - lgNetWriterSize(&writer) == LG_NET_AUDIO_CLOCK_FEEDBACK_WIRE_SIZE; -} - -LGNetParseResult lgNetAudioClockFeedbackDecode( - LGNetAudioClockFeedback * feedback, const void * data, size_t size) -{ - if (!feedback || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_AUDIO_CLOCK_FEEDBACK_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetAudioClockFeedback decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU32(&reader, &decoded.streamID) || - !lgNetReaderU16(&reader, &decoded.direction) || - !lgNetReaderZero(&reader, 2) || - !lgNetReaderU64(&reader, &decoded.formatEpoch) || - !lgNetReaderU64(&reader, &decoded.packetID) || - !lgNetReaderU64(&reader, &decoded.framePosition) || - !lgNetReaderU64(&reader, &decoded.timestampNs) || - !lgNetReaderI32(&reader, &decoded.queuedFrames) || - !lgNetReaderI32(&reader, &decoded.driftPpm)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_AUDIO_CLOCK_FEEDBACK_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetAudioClockFeedbackValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *feedback = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetClipboardClaimValid(const LGNetClipboardClaim * claim) -{ - return claim && claim->ownerID && claim->claimEpoch && claim->leaseMs && - claim->flags && !(claim->flags & ~CLIPBOARD_CLAIM_FLAGS); -} - -bool lgNetClipboardClaimEncode( - void * data, size_t size, const LGNetClipboardClaim * claim) -{ - if (!data || size < LG_NET_CLIPBOARD_CLAIM_WIRE_SIZE || - !lgNetClipboardClaimValid(claim)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, claim->ownerID) && - lgNetWriterU64(&writer, claim->claimEpoch) && - lgNetWriterU32(&writer, claim->leaseMs) && - lgNetWriterU32(&writer, claim->flags) && - lgNetWriterSize(&writer) == LG_NET_CLIPBOARD_CLAIM_WIRE_SIZE; -} - -LGNetParseResult lgNetClipboardClaimDecode( - LGNetClipboardClaim * claim, const void * data, size_t size) -{ - if (!claim || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_CLIPBOARD_CLAIM_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetClipboardClaim decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.ownerID) || - !lgNetReaderU64(&reader, &decoded.claimEpoch) || - !lgNetReaderU32(&reader, &decoded.leaseMs) || - !lgNetReaderU32(&reader, &decoded.flags)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_CLIPBOARD_CLAIM_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetClipboardClaimValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *claim = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetClipboardOfferSize(const LGNetClipboardOffer * offer) -{ - size_t size; - return offer && variableSize(LG_NET_CLIPBOARD_OFFER_HEADER_WIRE_SIZE, - offer->mimeLength, LG_NET_CLIPBOARD_MAX_MIME_LENGTH, &size) ? size : 0; -} - -bool lgNetClipboardOfferValid(const LGNetClipboardOffer * offer) -{ - return offer && offer->offerID && offer->serial && offer->formatCount && - offer->formatCount <= LG_NET_CLIPBOARD_MAX_FORMATS && - offer->formatIndex < offer->formatCount && offer->mimeLength && - offer->mime && !(offer->flags & ~CLIPBOARD_OFFER_FLAGS) && - lgNetClipboardOfferSize(offer) != 0; -} - -bool lgNetClipboardOfferEncode( - void * data, size_t size, const LGNetClipboardOffer * offer) -{ - const size_t wireSize = lgNetClipboardOfferSize(offer); - if (!data || !wireSize || size < wireSize || - !lgNetClipboardOfferValid(offer)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, offer->offerID) && - lgNetWriterU64(&writer, offer->serial) && - lgNetWriterU64(&writer, offer->estimatedSize) && - lgNetWriterU32(&writer, offer->formatIndex) && - lgNetWriterU32(&writer, offer->formatCount) && - lgNetWriterU16(&writer, offer->mimeLength) && - lgNetWriterU16(&writer, offer->flags) && - lgNetWriterU32(&writer, 0) && - lgNetWriterBytes(&writer, offer->mime, offer->mimeLength) && - lgNetWriterSize(&writer) == wireSize; -} - -LGNetParseResult lgNetClipboardOfferDecode( - LGNetClipboardOffer * offer, const void * data, size_t size) -{ - if (!offer || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_CLIPBOARD_OFFER_HEADER_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetClipboardOffer decoded; - LGNetReader reader; - size_t expected; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.offerID) || - !lgNetReaderU64(&reader, &decoded.serial) || - !lgNetReaderU64(&reader, &decoded.estimatedSize) || - !lgNetReaderU32(&reader, &decoded.formatIndex) || - !lgNetReaderU32(&reader, &decoded.formatCount) || - !lgNetReaderU16(&reader, &decoded.mimeLength) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderZero(&reader, 4)) - return LG_NET_PARSE_INVALID_VALUE; - - LGNetParseResult result = variableDecodeSize( - LG_NET_CLIPBOARD_OFFER_HEADER_WIRE_SIZE, decoded.mimeLength, - LG_NET_CLIPBOARD_MAX_MIME_LENGTH, size, &expected); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetReaderView(&reader, &decoded.mime, decoded.mimeLength)) - return LG_NET_PARSE_INVALID_VALUE; - result = fixedDecodeResult(&reader, expected, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetClipboardOfferValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *offer = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetClipboardRequestValid(const LGNetClipboardRequest * request) -{ - return request && request->offerID && request->requestID && - request->formatIndex < LG_NET_CLIPBOARD_MAX_FORMATS && - request->maxChunkLength && - request->maxChunkLength <= LG_NET_CLIPBOARD_MAX_CHUNK_LENGTH; -} - -bool lgNetClipboardRequestEncode( - void * data, size_t size, const LGNetClipboardRequest * request) -{ - if (!data || size < LG_NET_CLIPBOARD_REQUEST_WIRE_SIZE || - !lgNetClipboardRequestValid(request)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, request->offerID) && - lgNetWriterU64(&writer, request->requestID) && - lgNetWriterU32(&writer, request->formatIndex) && - lgNetWriterU32(&writer, request->maxChunkLength) && - lgNetWriterU64(&writer, request->offset) && - lgNetWriterSize(&writer) == LG_NET_CLIPBOARD_REQUEST_WIRE_SIZE; -} - -LGNetParseResult lgNetClipboardRequestDecode( - LGNetClipboardRequest * request, const void * data, size_t size) -{ - if (!request || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_CLIPBOARD_REQUEST_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetClipboardRequest decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.offerID) || - !lgNetReaderU64(&reader, &decoded.requestID) || - !lgNetReaderU32(&reader, &decoded.formatIndex) || - !lgNetReaderU32(&reader, &decoded.maxChunkLength) || - !lgNetReaderU64(&reader, &decoded.offset)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_CLIPBOARD_REQUEST_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetClipboardRequestValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *request = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetClipboardChunkSize(const LGNetClipboardChunk * chunk) -{ - size_t size; - return chunk && variableSize(LG_NET_CLIPBOARD_CHUNK_HEADER_WIRE_SIZE, - chunk->dataLength, LG_NET_CLIPBOARD_MAX_CHUNK_LENGTH, &size) ? size : 0; -} - -bool lgNetClipboardChunkValid(const LGNetClipboardChunk * chunk) -{ - if (!chunk || !chunk->requestID || !chunk->offerID || - (chunk->flags & ~CLIPBOARD_CHUNK_FLAGS) || - lgNetClipboardChunkSize(chunk) == 0) - return false; - - if (chunk->offset > chunk->totalLength || - chunk->dataLength > chunk->totalLength - chunk->offset) - return false; - - const bool first = chunk->offset == 0; - const bool final = chunk->dataLength == chunk->totalLength - chunk->offset; - return (!!(chunk->flags & LG_NET_CLIPBOARD_CHUNK_FIRST) == first) && - (!!(chunk->flags & LG_NET_CLIPBOARD_CHUNK_FINAL) == final) && - (chunk->totalLength ? chunk->dataLength && chunk->data : - !chunk->dataLength && !chunk->data); -} - -bool lgNetClipboardChunkEncode( - void * data, size_t size, const LGNetClipboardChunk * chunk) -{ - const size_t wireSize = lgNetClipboardChunkSize(chunk); - if (!data || !wireSize || size < wireSize || - !lgNetClipboardChunkValid(chunk)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, chunk->requestID) && - lgNetWriterU64(&writer, chunk->offerID) && - lgNetWriterU64(&writer, chunk->offset) && - lgNetWriterU64(&writer, chunk->totalLength) && - lgNetWriterU32(&writer, chunk->dataLength) && - lgNetWriterU16(&writer, chunk->flags) && - lgNetWriterZero(&writer, 2) && - lgNetWriterBytes(&writer, chunk->data, chunk->dataLength) && - lgNetWriterSize(&writer) == wireSize; -} - -LGNetParseResult lgNetClipboardChunkDecode( - LGNetClipboardChunk * chunk, const void * data, size_t size) -{ - if (!chunk || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_CLIPBOARD_CHUNK_HEADER_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetClipboardChunk decoded; - LGNetReader reader; - size_t expected; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.requestID) || - !lgNetReaderU64(&reader, &decoded.offerID) || - !lgNetReaderU64(&reader, &decoded.offset) || - !lgNetReaderU64(&reader, &decoded.totalLength) || - !lgNetReaderU32(&reader, &decoded.dataLength) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderZero(&reader, 2)) - return LG_NET_PARSE_INVALID_VALUE; - - LGNetParseResult result = variableDecodeSize( - LG_NET_CLIPBOARD_CHUNK_HEADER_WIRE_SIZE, decoded.dataLength, - LG_NET_CLIPBOARD_MAX_CHUNK_LENGTH, size, &expected); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetReaderView(&reader, &decoded.data, decoded.dataLength)) - return LG_NET_PARSE_INVALID_VALUE; - result = fixedDecodeResult(&reader, expected, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetClipboardChunkValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *chunk = decoded; - return LG_NET_PARSE_OK; -} - -static bool clipboardStatusKnown(LGNetClipboardStatusCode status) -{ - return status >= LG_NET_CLIPBOARD_STATUS_OK && - status <= LG_NET_CLIPBOARD_STATUS_ERROR; -} - -bool lgNetClipboardStatusValid(const LGNetClipboardStatus * status) -{ - return status && status->requestID && status->offerID && - clipboardStatusKnown(status->status); -} - -bool lgNetClipboardStatusEncode( - void * data, size_t size, const LGNetClipboardStatus * status) -{ - if (!data || size < LG_NET_CLIPBOARD_STATUS_WIRE_SIZE || - !lgNetClipboardStatusValid(status)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, status->requestID) && - lgNetWriterU64(&writer, status->offerID) && - lgNetWriterU32(&writer, status->status) && - lgNetWriterU32(&writer, status->detail) && - lgNetWriterU64(&writer, status->processedLength) && - lgNetWriterSize(&writer) == LG_NET_CLIPBOARD_STATUS_WIRE_SIZE; -} - -LGNetParseResult lgNetClipboardStatusDecode( - LGNetClipboardStatus * status, const void * data, size_t size) -{ - if (!status || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_CLIPBOARD_STATUS_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetClipboardStatus decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.requestID) || - !lgNetReaderU64(&reader, &decoded.offerID) || - !lgNetReaderU32(&reader, &decoded.status) || - !lgNetReaderU32(&reader, &decoded.detail) || - !lgNetReaderU64(&reader, &decoded.processedLength)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_CLIPBOARD_STATUS_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetClipboardStatusValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *status = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetFileOfferSize(const LGNetFileOffer * offer) -{ - size_t size; - return offer && variableSize(LG_NET_FILE_OFFER_HEADER_WIRE_SIZE, - offer->labelLength, LG_NET_FILE_MAX_LABEL_LENGTH, &size) ? size : 0; -} - -bool lgNetFileOfferValid(const LGNetFileOffer * offer) -{ - const LGNetFileOfferFlags operation = offer ? offer->flags & - (LG_NET_FILE_OFFER_COPY | LG_NET_FILE_OFFER_MOVE) : 0; - return offer && offer->offerID && offer->entryCount && - offer->entryCount <= LG_NET_FILE_MAX_ENTRIES && - !(offer->flags & ~FILE_OFFER_FLAGS) && - (operation == LG_NET_FILE_OFFER_COPY || - operation == LG_NET_FILE_OFFER_MOVE) && - (!offer->labelLength || offer->label) && lgNetFileOfferSize(offer) != 0; -} - -bool lgNetFileOfferEncode( - void * data, size_t size, const LGNetFileOffer * offer) -{ - const size_t wireSize = lgNetFileOfferSize(offer); - if (!data || !wireSize || size < wireSize || !lgNetFileOfferValid(offer)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, offer->offerID) && - lgNetWriterU64(&writer, offer->totalBytes) && - lgNetWriterU32(&writer, offer->entryCount) && - lgNetWriterU32(&writer, offer->flags) && - lgNetWriterU16(&writer, offer->labelLength) && - lgNetWriterZero(&writer, 6) && - lgNetWriterBytes(&writer, offer->label, offer->labelLength) && - lgNetWriterSize(&writer) == wireSize; -} - -LGNetParseResult lgNetFileOfferDecode( - LGNetFileOffer * offer, const void * data, size_t size) -{ - if (!offer || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_FILE_OFFER_HEADER_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetFileOffer decoded; - LGNetReader reader; - size_t expected; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.offerID) || - !lgNetReaderU64(&reader, &decoded.totalBytes) || - !lgNetReaderU32(&reader, &decoded.entryCount) || - !lgNetReaderU32(&reader, &decoded.flags) || - !lgNetReaderU16(&reader, &decoded.labelLength) || - !lgNetReaderZero(&reader, 6)) - return LG_NET_PARSE_INVALID_VALUE; - - LGNetParseResult result = variableDecodeSize( - LG_NET_FILE_OFFER_HEADER_WIRE_SIZE, decoded.labelLength, - LG_NET_FILE_MAX_LABEL_LENGTH, size, &expected); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetReaderView(&reader, &decoded.label, decoded.labelLength)) - return LG_NET_PARSE_INVALID_VALUE; - result = fixedDecodeResult(&reader, expected, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetFileOfferValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *offer = decoded; - return LG_NET_PARSE_OK; -} - -static bool fileEntryTypeKnown(LGNetFileEntryType type) -{ - return type >= LG_NET_FILE_ENTRY_REGULAR && - type <= LG_NET_FILE_ENTRY_SYMLINK; -} - -size_t lgNetFileEntrySize(const LGNetFileEntry * entry) -{ - size_t variableLength; - size_t size; - if (!entry || entry->pathLength > LG_NET_FILE_MAX_PATH_LENGTH || - entry->linkTargetLength > LG_NET_FILE_MAX_LINK_TARGET_LENGTH) - return 0; - - variableLength = (size_t)entry->pathLength + entry->linkTargetLength; - return variableSize(LG_NET_FILE_ENTRY_HEADER_WIRE_SIZE, variableLength, - LG_NET_FILE_MAX_PATH_LENGTH + LG_NET_FILE_MAX_LINK_TARGET_LENGTH, - &size) ? size : 0; -} - -bool lgNetFileEntryValid(const LGNetFileEntry * entry) -{ - return entry && entry->offerID && entry->entryID && - fileEntryTypeKnown(entry->type) && !(entry->flags & ~FILE_ENTRY_FLAGS) && - entry->pathLength && entry->pathLength <= LG_NET_FILE_MAX_PATH_LENGTH && - entry->path && - entry->linkTargetLength <= LG_NET_FILE_MAX_LINK_TARGET_LENGTH && - ((entry->type == LG_NET_FILE_ENTRY_SYMLINK) ? - entry->linkTargetLength && entry->linkTarget : - !entry->linkTargetLength && !entry->linkTarget) && - lgNetFileEntrySize(entry) != 0; -} - -bool lgNetFileEntryEncode( - void * data, size_t size, const LGNetFileEntry * entry) -{ - const size_t wireSize = lgNetFileEntrySize(entry); - if (!data || !wireSize || size < wireSize || !lgNetFileEntryValid(entry)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, entry->offerID) && - lgNetWriterU64(&writer, entry->entryID) && - lgNetWriterU64(&writer, entry->parentID) && - lgNetWriterU64(&writer, entry->size) && - lgNetWriterU64(&writer, entry->modifiedNs) && - lgNetWriterU32(&writer, entry->mode) && - lgNetWriterU16(&writer, entry->type) && - lgNetWriterU16(&writer, entry->flags) && - lgNetWriterU16(&writer, entry->pathLength) && - lgNetWriterU16(&writer, entry->linkTargetLength) && - lgNetWriterZero(&writer, 4) && - lgNetWriterBytes(&writer, entry->path, entry->pathLength) && - lgNetWriterBytes(&writer, entry->linkTarget, - entry->linkTargetLength) && - lgNetWriterSize(&writer) == wireSize; -} - -LGNetParseResult lgNetFileEntryDecode( - LGNetFileEntry * entry, const void * data, size_t size) -{ - if (!entry || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_FILE_ENTRY_HEADER_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetFileEntry decoded; - LGNetReader reader; - size_t expected; - size_t variableLength; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.offerID) || - !lgNetReaderU64(&reader, &decoded.entryID) || - !lgNetReaderU64(&reader, &decoded.parentID) || - !lgNetReaderU64(&reader, &decoded.size) || - !lgNetReaderU64(&reader, &decoded.modifiedNs) || - !lgNetReaderU32(&reader, &decoded.mode) || - !lgNetReaderU16(&reader, &decoded.type) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderU16(&reader, &decoded.pathLength) || - !lgNetReaderU16(&reader, &decoded.linkTargetLength) || - !lgNetReaderZero(&reader, 4)) - return LG_NET_PARSE_INVALID_VALUE; - - if (decoded.pathLength > LG_NET_FILE_MAX_PATH_LENGTH || - decoded.linkTargetLength > LG_NET_FILE_MAX_LINK_TARGET_LENGTH) - return LG_NET_PARSE_INVALID_LENGTH; - variableLength = (size_t)decoded.pathLength + decoded.linkTargetLength; - LGNetParseResult result = variableDecodeSize( - LG_NET_FILE_ENTRY_HEADER_WIRE_SIZE, variableLength, - LG_NET_FILE_MAX_PATH_LENGTH + LG_NET_FILE_MAX_LINK_TARGET_LENGTH, - size, &expected); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetReaderView(&reader, &decoded.path, decoded.pathLength) || - !lgNetReaderView(&reader, &decoded.linkTarget, - decoded.linkTargetLength)) - return LG_NET_PARSE_INVALID_VALUE; - result = fixedDecodeResult(&reader, expected, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetFileEntryValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *entry = decoded; - return LG_NET_PARSE_OK; -} - -bool lgNetFileRequestValid(const LGNetFileRequest * request) -{ - return request && request->requestID && request->offerID && - request->entryID && request->length && - request->length <= LG_NET_FILE_MAX_CHUNK_LENGTH && request->flags && - !(request->flags & ~FILE_REQUEST_FLAGS) && - request->offset <= UINT64_MAX - request->length; -} - -bool lgNetFileRequestEncode( - void * data, size_t size, const LGNetFileRequest * request) -{ - if (!data || size < LG_NET_FILE_REQUEST_WIRE_SIZE || - !lgNetFileRequestValid(request)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, request->requestID) && - lgNetWriterU64(&writer, request->offerID) && - lgNetWriterU64(&writer, request->entryID) && - lgNetWriterU64(&writer, request->offset) && - lgNetWriterU32(&writer, request->length) && - lgNetWriterU32(&writer, request->flags) && - lgNetWriterSize(&writer) == LG_NET_FILE_REQUEST_WIRE_SIZE; -} - -LGNetParseResult lgNetFileRequestDecode( - LGNetFileRequest * request, const void * data, size_t size) -{ - if (!request || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_FILE_REQUEST_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetFileRequest decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.requestID) || - !lgNetReaderU64(&reader, &decoded.offerID) || - !lgNetReaderU64(&reader, &decoded.entryID) || - !lgNetReaderU64(&reader, &decoded.offset) || - !lgNetReaderU32(&reader, &decoded.length) || - !lgNetReaderU32(&reader, &decoded.flags)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_FILE_REQUEST_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetFileRequestValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *request = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetFileChunkSize(const LGNetFileChunk * chunk) -{ - size_t size; - return chunk && variableSize(LG_NET_FILE_CHUNK_HEADER_WIRE_SIZE, - chunk->dataLength, LG_NET_FILE_MAX_CHUNK_LENGTH, &size) ? size : 0; -} - -bool lgNetFileChunkValid(const LGNetFileChunk * chunk) -{ - if (!chunk || !chunk->requestID || !chunk->offerID || !chunk->entryID || - (chunk->flags & ~FILE_CHUNK_FLAGS) || lgNetFileChunkSize(chunk) == 0 || - chunk->offset > chunk->totalLength || - chunk->dataLength > chunk->totalLength - chunk->offset) - return false; - - const bool first = chunk->offset == 0; - const bool final = chunk->dataLength == chunk->totalLength - chunk->offset; - return (!!(chunk->flags & LG_NET_FILE_CHUNK_FIRST) == first) && - (!!(chunk->flags & LG_NET_FILE_CHUNK_FINAL) == final) && - (chunk->totalLength ? chunk->dataLength && chunk->data : - !chunk->dataLength && !chunk->data); -} - -bool lgNetFileChunkEncode( - void * data, size_t size, const LGNetFileChunk * chunk) -{ - const size_t wireSize = lgNetFileChunkSize(chunk); - if (!data || !wireSize || size < wireSize || !lgNetFileChunkValid(chunk)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, chunk->requestID) && - lgNetWriterU64(&writer, chunk->offerID) && - lgNetWriterU64(&writer, chunk->entryID) && - lgNetWriterU64(&writer, chunk->offset) && - lgNetWriterU64(&writer, chunk->totalLength) && - lgNetWriterU32(&writer, chunk->dataLength) && - lgNetWriterU16(&writer, chunk->flags) && - lgNetWriterZero(&writer, 2) && - lgNetWriterBytes(&writer, chunk->data, chunk->dataLength) && - lgNetWriterSize(&writer) == wireSize; -} - -LGNetParseResult lgNetFileChunkDecode( - LGNetFileChunk * chunk, const void * data, size_t size) -{ - if (!chunk || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_FILE_CHUNK_HEADER_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetFileChunk decoded; - LGNetReader reader; - size_t expected; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.requestID) || - !lgNetReaderU64(&reader, &decoded.offerID) || - !lgNetReaderU64(&reader, &decoded.entryID) || - !lgNetReaderU64(&reader, &decoded.offset) || - !lgNetReaderU64(&reader, &decoded.totalLength) || - !lgNetReaderU32(&reader, &decoded.dataLength) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderZero(&reader, 2)) - return LG_NET_PARSE_INVALID_VALUE; - - LGNetParseResult result = variableDecodeSize( - LG_NET_FILE_CHUNK_HEADER_WIRE_SIZE, decoded.dataLength, - LG_NET_FILE_MAX_CHUNK_LENGTH, size, &expected); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetReaderView(&reader, &decoded.data, decoded.dataLength)) - return LG_NET_PARSE_INVALID_VALUE; - result = fixedDecodeResult(&reader, expected, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetFileChunkValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *chunk = decoded; - return LG_NET_PARSE_OK; -} - -static bool fileStatusKnown(LGNetFileStatusCode status) -{ - return status >= LG_NET_FILE_STATUS_OK && - status <= LG_NET_FILE_STATUS_ERROR; -} - -bool lgNetFileStatusValid(const LGNetFileStatus * status) -{ - return status && status->requestID && status->offerID && status->entryID && - fileStatusKnown(status->status); -} - -bool lgNetFileStatusEncode( - void * data, size_t size, const LGNetFileStatus * status) -{ - if (!data || size < LG_NET_FILE_STATUS_WIRE_SIZE || - !lgNetFileStatusValid(status)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU64(&writer, status->requestID) && - lgNetWriterU64(&writer, status->offerID) && - lgNetWriterU64(&writer, status->entryID) && - lgNetWriterU32(&writer, status->status) && - lgNetWriterU32(&writer, status->detail) && - lgNetWriterU64(&writer, status->transferredLength) && - lgNetWriterSize(&writer) == LG_NET_FILE_STATUS_WIRE_SIZE; -} - -LGNetParseResult lgNetFileStatusDecode( - LGNetFileStatus * status, const void * data, size_t size) -{ - if (!status || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_FILE_STATUS_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetFileStatus decoded; - LGNetReader reader; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU64(&reader, &decoded.requestID) || - !lgNetReaderU64(&reader, &decoded.offerID) || - !lgNetReaderU64(&reader, &decoded.entryID) || - !lgNetReaderU32(&reader, &decoded.status) || - !lgNetReaderU32(&reader, &decoded.detail) || - !lgNetReaderU64(&reader, &decoded.transferredLength)) - return LG_NET_PARSE_INVALID_VALUE; - - const LGNetParseResult result = fixedDecodeResult( - &reader, LG_NET_FILE_STATUS_WIRE_SIZE, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetFileStatusValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *status = decoded; - return LG_NET_PARSE_OK; -} - -size_t lgNetUSBReservedSize(const LGNetUSBReserved * reserved) -{ - size_t size; - return reserved && variableSize(LG_NET_USB_RESERVED_HEADER_WIRE_SIZE, - reserved->payloadLength, LG_NET_USB_MAX_RESERVED_PAYLOAD_LENGTH, - &size) ? size : 0; -} - -bool lgNetUSBReservedValid(const LGNetUSBReserved * reserved) -{ - return reserved && - reserved->version == LG_NET_USB_RESERVED_INTRODUCED_SERVICE_VERSION && - reserved->headerSize == LG_NET_USB_RESERVED_HEADER_WIRE_SIZE && - reserved->messageType && !(reserved->flags & ~USB_RESERVED_FLAGS) && - (!reserved->payloadLength || reserved->payload) && - lgNetUSBReservedSize(reserved) != 0; -} - -bool lgNetUSBReservedEncode( - void * data, size_t size, const LGNetUSBReserved * reserved) -{ - const size_t wireSize = lgNetUSBReservedSize(reserved); - if (!data || !wireSize || size < wireSize || - !lgNetUSBReservedValid(reserved)) - return false; - - LGNetWriter writer; - lgNetWriterInit(&writer, data, size); - return - lgNetWriterU16(&writer, reserved->version) && - lgNetWriterU16(&writer, reserved->headerSize) && - lgNetWriterU16(&writer, reserved->messageType) && - lgNetWriterU16(&writer, reserved->flags) && - lgNetWriterU64(&writer, reserved->requestID) && - lgNetWriterU64(&writer, reserved->sequence) && - lgNetWriterU32(&writer, reserved->payloadLength) && - lgNetWriterZero(&writer, 4) && - lgNetWriterBytes(&writer, reserved->payload, - reserved->payloadLength) && - lgNetWriterSize(&writer) == wireSize; -} - -LGNetParseResult lgNetUSBReservedDecode( - LGNetUSBReserved * reserved, const void * data, size_t size) -{ - if (!reserved || !data) - return LG_NET_PARSE_INVALID_VALUE; - if (size < LG_NET_USB_RESERVED_HEADER_WIRE_SIZE) - return LG_NET_PARSE_TRUNCATED; - - LGNetUSBReserved decoded; - LGNetReader reader; - size_t expected; - memset(&decoded, 0, sizeof(decoded)); - lgNetReaderInit(&reader, data, size); - if (!lgNetReaderU16(&reader, &decoded.version) || - !lgNetReaderU16(&reader, &decoded.headerSize) || - !lgNetReaderU16(&reader, &decoded.messageType) || - !lgNetReaderU16(&reader, &decoded.flags) || - !lgNetReaderU64(&reader, &decoded.requestID) || - !lgNetReaderU64(&reader, &decoded.sequence) || - !lgNetReaderU32(&reader, &decoded.payloadLength) || - !lgNetReaderZero(&reader, 4)) - return LG_NET_PARSE_INVALID_VALUE; - - LGNetParseResult result = variableDecodeSize( - LG_NET_USB_RESERVED_HEADER_WIRE_SIZE, decoded.payloadLength, - LG_NET_USB_MAX_RESERVED_PAYLOAD_LENGTH, size, &expected); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetReaderView(&reader, &decoded.payload, decoded.payloadLength)) - return LG_NET_PARSE_INVALID_VALUE; - result = fixedDecodeResult(&reader, expected, size); - if (result != LG_NET_PARSE_OK) - return result; - if (!lgNetUSBReservedValid(&decoded)) - return LG_NET_PARSE_INVALID_VALUE; - - *reserved = decoded; - return LG_NET_PARSE_OK; -} diff --git a/common/src/network/wire.c b/common/src/network/wire.c deleted file mode 100644 index 26423c1a..00000000 --- a/common/src/network/wire.c +++ /dev/null @@ -1,355 +0,0 @@ -/** - * Looking Glass - * Copyright © 2017-2026 The Looking Glass Authors - * https://looking-glass.io - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "common/network/wire.h" - -#include - -static bool writerReserve(LGNetWriter * writer, size_t size) -{ - if (!writer || writer->failed || writer->offset > writer->capacity || - size > writer->capacity - writer->offset) - { - if (writer) - writer->failed = true; - return false; - } - - return true; -} - -static bool readerReserve(LGNetReader * reader, size_t size) -{ - if (!reader || reader->failed || reader->offset > reader->size || - size > reader->size - reader->offset) - { - if (reader) - reader->failed = true; - return false; - } - - return true; -} - -void lgNetWriterInit(LGNetWriter * writer, void * data, size_t capacity) -{ - if (!writer) - return; - - writer->data = data; - writer->capacity = capacity; - writer->offset = 0; - writer->failed = capacity && !data; -} - -size_t lgNetWriterSize(const LGNetWriter * writer) -{ - return writer ? writer->offset : 0; -} - -size_t lgNetWriterRemaining(const LGNetWriter * writer) -{ - return writer && !writer->failed && writer->offset <= writer->capacity ? - writer->capacity - writer->offset : 0; -} - -bool lgNetWriterValid(const LGNetWriter * writer) -{ - return writer && !writer->failed && writer->offset <= writer->capacity && - (!writer->capacity || writer->data); -} - -bool lgNetWriterU8(LGNetWriter * writer, uint8_t value) -{ - if (!writerReserve(writer, 1)) - return false; - - writer->data[writer->offset++] = value; - return true; -} - -bool lgNetWriterU16(LGNetWriter * writer, uint16_t value) -{ - if (!writerReserve(writer, 2)) - return false; - - uint8_t * data = writer->data + writer->offset; - data[0] = (uint8_t)(value ); - data[1] = (uint8_t)(value >> 8); - writer->offset += 2; - return true; -} - -bool lgNetWriterU32(LGNetWriter * writer, uint32_t value) -{ - if (!writerReserve(writer, 4)) - return false; - - uint8_t * data = writer->data + writer->offset; - data[0] = (uint8_t)(value ); - data[1] = (uint8_t)(value >> 8); - data[2] = (uint8_t)(value >> 16); - data[3] = (uint8_t)(value >> 24); - writer->offset += 4; - return true; -} - -bool lgNetWriterU64(LGNetWriter * writer, uint64_t value) -{ - if (!writerReserve(writer, 8)) - return false; - - uint8_t * data = writer->data + writer->offset; - data[0] = (uint8_t)(value ); - data[1] = (uint8_t)(value >> 8); - data[2] = (uint8_t)(value >> 16); - data[3] = (uint8_t)(value >> 24); - data[4] = (uint8_t)(value >> 32); - data[5] = (uint8_t)(value >> 40); - data[6] = (uint8_t)(value >> 48); - data[7] = (uint8_t)(value >> 56); - writer->offset += 8; - return true; -} - -bool lgNetWriterI32(LGNetWriter * writer, int32_t value) -{ - uint32_t bits; - memcpy(&bits, &value, sizeof(bits)); - return lgNetWriterU32(writer, bits); -} - -bool lgNetWriterI64(LGNetWriter * writer, int64_t value) -{ - uint64_t bits; - memcpy(&bits, &value, sizeof(bits)); - return lgNetWriterU64(writer, bits); -} - -bool lgNetWriterBytes( - LGNetWriter * writer, const void * data, size_t size) -{ - if (!writerReserve(writer, size) || (size && !data)) - { - if (writer) - writer->failed = true; - return false; - } - - if (size) - memmove(writer->data + writer->offset, data, size); - writer->offset += size; - return true; -} - -bool lgNetWriterZero(LGNetWriter * writer, size_t size) -{ - if (!writerReserve(writer, size)) - return false; - - if (size) - memset(writer->data + writer->offset, 0, size); - writer->offset += size; - return true; -} - -void lgNetReaderInit( - LGNetReader * reader, const void * data, size_t size) -{ - if (!reader) - return; - - reader->data = data; - reader->size = size; - reader->offset = 0; - reader->failed = size && !data; -} - -size_t lgNetReaderConsumed(const LGNetReader * reader) -{ - return reader ? reader->offset : 0; -} - -size_t lgNetReaderRemaining(const LGNetReader * reader) -{ - return reader && !reader->failed && reader->offset <= reader->size ? - reader->size - reader->offset : 0; -} - -bool lgNetReaderValid(const LGNetReader * reader) -{ - return reader && !reader->failed && reader->offset <= reader->size && - (!reader->size || reader->data); -} - -bool lgNetReaderU8(LGNetReader * reader, uint8_t * value) -{ - if (!readerReserve(reader, 1) || !value) - { - if (reader) - reader->failed = true; - return false; - } - - *value = reader->data[reader->offset++]; - return true; -} - -bool lgNetReaderU16(LGNetReader * reader, uint16_t * value) -{ - if (!readerReserve(reader, 2) || !value) - { - if (reader) - reader->failed = true; - return false; - } - - const uint8_t * data = reader->data + reader->offset; - *value = - (uint16_t)data[0] | - (uint16_t)data[1] << 8; - reader->offset += 2; - return true; -} - -bool lgNetReaderU32(LGNetReader * reader, uint32_t * value) -{ - if (!readerReserve(reader, 4) || !value) - { - if (reader) - reader->failed = true; - return false; - } - - const uint8_t * data = reader->data + reader->offset; - *value = - (uint32_t)data[0] | - (uint32_t)data[1] << 8 | - (uint32_t)data[2] << 16 | - (uint32_t)data[3] << 24; - reader->offset += 4; - return true; -} - -bool lgNetReaderU64(LGNetReader * reader, uint64_t * value) -{ - if (!readerReserve(reader, 8) || !value) - { - if (reader) - reader->failed = true; - return false; - } - - const uint8_t * data = reader->data + reader->offset; - *value = - (uint64_t)data[0] | - (uint64_t)data[1] << 8 | - (uint64_t)data[2] << 16 | - (uint64_t)data[3] << 24 | - (uint64_t)data[4] << 32 | - (uint64_t)data[5] << 40 | - (uint64_t)data[6] << 48 | - (uint64_t)data[7] << 56; - reader->offset += 8; - return true; -} - -bool lgNetReaderI32(LGNetReader * reader, int32_t * value) -{ - uint32_t bits; - if (!value || !lgNetReaderU32(reader, &bits)) - { - if (reader) - reader->failed = true; - return false; - } - - memcpy(value, &bits, sizeof(*value)); - return true; -} - -bool lgNetReaderI64(LGNetReader * reader, int64_t * value) -{ - uint64_t bits; - if (!value || !lgNetReaderU64(reader, &bits)) - { - if (reader) - reader->failed = true; - return false; - } - - memcpy(value, &bits, sizeof(*value)); - return true; -} - -bool lgNetReaderBytes(LGNetReader * reader, void * data, size_t size) -{ - if (!readerReserve(reader, size) || (size && !data)) - { - if (reader) - reader->failed = true; - return false; - } - - if (size) - memcpy(data, reader->data + reader->offset, size); - reader->offset += size; - return true; -} - -bool lgNetReaderView( - LGNetReader * reader, const uint8_t ** data, size_t size) -{ - if (!readerReserve(reader, size) || !data) - { - if (reader) - reader->failed = true; - return false; - } - - *data = size ? reader->data + reader->offset : NULL; - reader->offset += size; - return true; -} - -bool lgNetReaderSkip(LGNetReader * reader, size_t size) -{ - if (!readerReserve(reader, size)) - return false; - - reader->offset += size; - return true; -} - -bool lgNetReaderZero(LGNetReader * reader, size_t size) -{ - if (!readerReserve(reader, size)) - return false; - - for (size_t i = 0; i < size; ++i) - if (reader->data[reader->offset + i]) - { - reader->failed = true; - return false; - } - - reader->offset += size; - return true; -} diff --git a/idd/LGCommon/LGCommon.vcxproj b/idd/LGCommon/LGCommon.vcxproj index 66fffea2..767c1cab 100644 --- a/idd/LGCommon/LGCommon.vcxproj +++ b/idd/LGCommon/LGCommon.vcxproj @@ -69,9 +69,9 @@ - - - + + + @@ -89,9 +89,6 @@ - - - diff --git a/idd/LGCommon/LGCommon.vcxproj.filters b/idd/LGCommon/LGCommon.vcxproj.filters index ffc60901..4f8ec19c 100644 --- a/idd/LGCommon/LGCommon.vcxproj.filters +++ b/idd/LGCommon/LGCommon.vcxproj.filters @@ -24,7 +24,7 @@ Source Files - + Source Files @@ -62,9 +62,6 @@ Header Files - - Header Files - Header Files diff --git a/idd/LGIdd/transport/network/CNetworkServer.cpp b/idd/LGIdd/transport/network/CNetworkServer.cpp index 0c0d62f2..666f61d8 100644 --- a/idd/LGIdd/transport/network/CNetworkServer.cpp +++ b/idd/LGIdd/transport/network/CNetworkServer.cpp @@ -27,7 +27,7 @@ #include "CDebug.h" #include "CSRWLock.h" #include "NetworkIdentity.h" -#include "common/network/protocol.h" +#include #include #include diff --git a/idd/LGIdd/transport/network/NetworkSettings.h b/idd/LGIdd/transport/network/NetworkSettings.h index 7aa37ed7..06dab3b4 100644 --- a/idd/LGIdd/transport/network/NetworkSettings.h +++ b/idd/LGIdd/transport/network/NetworkSettings.h @@ -20,7 +20,7 @@ #pragma once -#include "common/network/protocol.h" +#include #include #include diff --git a/repos/LGProtocol b/repos/LGProtocol index c9659b31..8693254b 160000 --- a/repos/LGProtocol +++ b/repos/LGProtocol @@ -1 +1 @@ -Subproject commit c9659b314a0fa95ebaccb14b7343af483cd70d1d +Subproject commit 8693254b9b394e0191ad71695a70e52cb2e371fc