b1c3ec3af4
- Protocol definition with 6-byte header (chunk_idx: 2B, payload: N B, crc32: 4B) - Node.js server with chunk-based HTTP delivery - C client library with resumable download support - CRC32 implementation (IEEE 802.3) - Test suites for both server and CRC32 - 1024B default chunk size (0.59% overhead)
302 lines
8.0 KiB
C
302 lines
8.0 KiB
C
/**
|
|
* @file protocol.h
|
|
* @brief OTA Chunk Transfer Protocol Definitions
|
|
*/
|
|
|
|
#ifndef OTA_CHUNK_PROTOCOL_H
|
|
#define OTA_CHUNK_PROTOCOL_H
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* =========================================================================
|
|
* Protocol Constants
|
|
* ========================================================================= */
|
|
|
|
#define CHUNK_PROTOCOL_VERSION 1
|
|
#define CHUNK_DEFAULT_SIZE 1024
|
|
#define CHUNK_MIN_SIZE 256
|
|
#define CHUNK_MAX_SIZE 65535
|
|
#define CHUNK_INDEX_MAX 65535 /* 2-byte unsigned */
|
|
|
|
/* Maximum file size: CHUNK_INDEX_MAX * CHUNK_MAX_SIZE ≈ 4.29 GB */
|
|
#define CHUNK_MAX_FILE_SIZE ((uint32_t)CHUNK_INDEX_MAX * CHUNK_MAX_SIZE)
|
|
|
|
/* =========================================================================
|
|
* Protocol Structures
|
|
* ========================================================================= */
|
|
|
|
/**
|
|
* Chunk packet structure (network format)
|
|
*
|
|
* Layout:
|
|
* +------------+----------------+----------+
|
|
* | chunk_idx | payload (N B) | crc32 |
|
|
* | 2 B | N B | 4 B |
|
|
* +------------+----------------+----------+
|
|
*
|
|
* Note: This structure includes padding. Use packing for network transmission.
|
|
*/
|
|
|
|
#pragma pack(push, 1)
|
|
typedef struct {
|
|
uint16_t chunk_idx; /* Chunk index (little-endian) */
|
|
/* payload follows immediately */
|
|
/* crc32 follows payload */
|
|
} chunk_header_t;
|
|
|
|
#pragma pack(pop)
|
|
|
|
/**
|
|
* Chunk data descriptor (in-memory representation)
|
|
*/
|
|
typedef struct {
|
|
uint16_t chunk_idx; /* Chunk index */
|
|
uint16_t payload_len; /* Payload length */
|
|
uint8_t *payload; /* Payload pointer */
|
|
uint32_t crc32; /* CRC32 of payload */
|
|
} chunk_data_t;
|
|
|
|
/**
|
|
* Transfer state
|
|
*/
|
|
typedef enum {
|
|
CHUNK_STATE_IDLE,
|
|
CHUNK_STATE_FETCHING_SIZE,
|
|
CHUNK_STATE_TRANSFERRING,
|
|
CHUNK_STATE_RESUMING,
|
|
CHUNK_STATE_COMPLETE,
|
|
CHUNK_STATE_ERROR
|
|
} chunk_state_t;
|
|
|
|
/**
|
|
* Error codes
|
|
*/
|
|
typedef enum {
|
|
CHUNK_ERR_OK = 0,
|
|
CHUNK_ERR_INVALID_PARAM = -1,
|
|
CHUNK_ERR_MEMORY = -2,
|
|
CHUNK_ERR_NETWORK = -3,
|
|
CHUNK_ERR_CRC = -4,
|
|
CHUNK_ERR_FILE_NOT_FOUND = -5,
|
|
CHUNK_ERR_RANGE_INVALID = -6,
|
|
CHUNK_ERR_TIMEOUT = -7,
|
|
CHUNK_ERR_SERVER_ERROR = -8,
|
|
} chunk_err_t;
|
|
|
|
/* =========================================================================
|
|
* Callback Types
|
|
* ========================================================================= */
|
|
|
|
/**
|
|
* Chunk received callback
|
|
*
|
|
* @param chunk_idx Chunk index
|
|
* @param data Payload data
|
|
* @param len Payload length
|
|
* @param user_ctx User context
|
|
*/
|
|
typedef void (*chunk_received_cb)(uint16_t chunk_idx, const uint8_t *data,
|
|
uint16_t len, void *user_ctx);
|
|
|
|
/**
|
|
* Transfer complete callback
|
|
*
|
|
* @param total_bytes Total bytes transferred
|
|
* @param user_ctx User context
|
|
*/
|
|
typedef void (*transfer_complete_cb)(uint32_t total_bytes, void *user_ctx);
|
|
|
|
/**
|
|
* Transfer error callback
|
|
*
|
|
* @param err_code Error code
|
|
* @param user_ctx User context
|
|
*/
|
|
typedef void (*transfer_error_cb)(chunk_err_t err_code, void *user_ctx);
|
|
|
|
/**
|
|
* Progress update callback
|
|
*
|
|
* @param current_chunk Current chunk index
|
|
* @param total_chunks Total chunks
|
|
* @param user_ctx User context
|
|
*/
|
|
typedef void (*progress_cb)(uint16_t current_chunk, uint16_t total_chunks,
|
|
void *user_ctx);
|
|
|
|
/* =========================================================================
|
|
* Configuration Structures
|
|
* ========================================================================= */
|
|
|
|
/**
|
|
* Chunk client configuration
|
|
*/
|
|
typedef struct {
|
|
const char *server_url; /* Server base URL */
|
|
uint16_t chunk_size; /* Chunk size in bytes */
|
|
uint32_t timeout_ms; /* Timeout in milliseconds */
|
|
|
|
/* Callbacks */
|
|
chunk_received_cb on_chunk_received;
|
|
transfer_complete_cb on_complete;
|
|
transfer_error_cb on_error;
|
|
progress_cb on_progress;
|
|
|
|
void *user_ctx; /* User context passed to callbacks */
|
|
} chunk_client_config_t;
|
|
|
|
/**
|
|
* Chunk server configuration
|
|
*/
|
|
typedef struct {
|
|
uint16_t port; /* Server port */
|
|
const char *root_path; /* Root directory for files */
|
|
uint16_t chunk_size; /* Chunk size in bytes */
|
|
} chunk_server_config_t;
|
|
|
|
/* =========================================================================
|
|
* CRC32 Functions
|
|
* ========================================================================= */
|
|
|
|
/**
|
|
* Calculate CRC32 (IEEE 802.3 polynomial)
|
|
*
|
|
* @param data Input data
|
|
* @param len Input length
|
|
* @return CRC32 value
|
|
*/
|
|
uint32_t chunk_crc32(const uint8_t *data, size_t len);
|
|
|
|
/**
|
|
* Update CRC32 with additional data
|
|
*
|
|
* @param crc Previous CRC value
|
|
* @param data New data
|
|
* @param len Data length
|
|
* @return Updated CRC value
|
|
*/
|
|
uint32_t chunk_crc32_update(uint32_t crc, const uint8_t *data, size_t len);
|
|
|
|
/* =========================================================================
|
|
* Client Functions
|
|
* ========================================================================= */
|
|
|
|
/**
|
|
* Initialize chunk client
|
|
*
|
|
* @param config Configuration structure
|
|
* @return CHUNK_ERR_OK on success, error code otherwise
|
|
*/
|
|
chunk_err_t chunk_client_init(const chunk_client_config_t *config);
|
|
|
|
/**
|
|
* Start file download
|
|
*
|
|
* @param filename Filename to download
|
|
* @return CHUNK_ERR_OK on success, error code otherwise
|
|
*/
|
|
chunk_err_t chunk_client_download(const char *filename);
|
|
|
|
/**
|
|
* Resume download from specific chunk
|
|
*
|
|
* @param filename Filename to download
|
|
* @param start_chunk Chunk index to resume from
|
|
* @return CHUNK_ERR_OK on success, error code otherwise
|
|
*/
|
|
chunk_err_t chunk_client_resume(const char *filename, uint16_t start_chunk);
|
|
|
|
/**
|
|
* Cancel current transfer
|
|
*/
|
|
void chunk_client_cancel(void);
|
|
|
|
/**
|
|
* Get current transfer state
|
|
*
|
|
* @return Current state
|
|
*/
|
|
chunk_state_t chunk_client_get_state(void);
|
|
|
|
/**
|
|
* Get current progress
|
|
*
|
|
* @param current_chunk Current chunk index (output)
|
|
* @param total_chunks Total chunks (output)
|
|
* @return CHUNK_ERR_OK on success
|
|
*/
|
|
chunk_err_t chunk_client_get_progress(uint16_t *current_chunk,
|
|
uint16_t *total_chunks);
|
|
|
|
/**
|
|
* Cleanup client resources
|
|
*/
|
|
void chunk_client_cleanup(void);
|
|
|
|
/* =========================================================================
|
|
* Server Functions (for reference / embedded use)
|
|
* ========================================================================= */
|
|
|
|
/**
|
|
* Initialize chunk server
|
|
*
|
|
* @param config Configuration structure
|
|
* @return CHUNK_ERR_OK on success, error code otherwise
|
|
*/
|
|
chunk_err_t chunk_server_init(const chunk_server_config_t *config);
|
|
|
|
/**
|
|
* Start server (blocking)
|
|
*
|
|
* @return CHUNK_ERR_OK on success, error code otherwise
|
|
*/
|
|
chunk_err_t chunk_server_start(void);
|
|
|
|
/**
|
|
* Stop server
|
|
*/
|
|
void chunk_server_stop(void);
|
|
|
|
/* =========================================================================
|
|
* Utility Functions
|
|
* ========================================================================= */
|
|
|
|
/**
|
|
* Calculate total chunks for a file
|
|
*
|
|
* @param file_size File size in bytes
|
|
* @param chunk_size Chunk size in bytes
|
|
* @return Total number of chunks
|
|
*/
|
|
static inline uint16_t chunk_calc_total_chunks(uint32_t file_size,
|
|
uint16_t chunk_size) {
|
|
return (uint16_t)((file_size + chunk_size - 1) / chunk_size);
|
|
}
|
|
|
|
/**
|
|
* Calculate payload size for a chunk
|
|
*
|
|
* @param file_size File size in bytes
|
|
* @param chunk_idx Chunk index
|
|
* @param chunk_size Chunk size in bytes
|
|
* @return Payload size for this chunk
|
|
*/
|
|
static inline uint16_t chunk_calc_payload_size(uint32_t file_size,
|
|
uint16_t chunk_idx,
|
|
uint16_t chunk_size) {
|
|
uint32_t remaining = file_size - (uint32_t)chunk_idx * chunk_size;
|
|
return (uint16_t)(remaining < chunk_size ? remaining : chunk_size);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* OTA_CHUNK_PROTOCOL_H */
|