/*
 * ==================================================================================
 * IFTP Protocol Header - ICMP File Transfer Protocol specification
 *
 * ISA Project
 * Author: Roman Necas (xnecasr00)
 * Date: 13. October 2025
 *
 * PURPOSE:
 * This module defines IFTP (ICMP File Transfer Protocol), a custom application-
 * layer protocol for transferring encrypted files through ICMP Echo-Request/Reply
 * messages. IFTP provides reliable, ordered delivery with integrity checking.
 *
 * PROTOCOL OVERVIEW:
 * IFTP is layered on top of ICMP and provides:
 * - Session management (unique session IDs)
 * - Reliable delivery (sequence numbers, ACKs)
 * - Fragmentation support (for large files)
 * - Integrity checking (CRC32 checksums)
 * - Metadata transmission (filename, size, crypto parameters)
 *
 * PACKET STRUCTURE:
 * ┌─────────────────────────────────────────┐
 * │ ICMP Header (8 bytes)                   │
 * ├─────────────────────────────────────────┤
 * │ IFTP Header (26 bytes)                  │
 * │  - Magic, Session ID                    │
 * │  - Message Type, Flags                  │
 * │  - Sequence Number, Fragment Info       │
 * │  - Payload Length, CRC32                │
 * ├─────────────────────────────────────────┤
 * │ IFTP Payload (0-1400 bytes)             │
 * │  - START: iftp_metadata_t               │
 * │  - DATA: Encrypted file chunk           │
 * │  - END: Empty                           │
 * │  - ACK/NACK: Optional error info        │
 * └─────────────────────────────────────────┘
 *
 * TRANSFER FLOW:
 * 1. Client → Server: START packet (metadata: filename, size, IV, salt)
 * 2. Server → Client: ACK
 * 3. Client → Server: DATA packet(s) with encrypted file chunks
 * 4. Server → Client: ACK for each DATA packet
 * 5. Client → Server: END packet
 * 6. Server → Client: ACK
 *
 * ERROR HANDLING:
 * - NACK packets sent for errors (bad checksum, wrong sequence, etc.)
 * - Client retries on timeout or NACK with exponential backoff
 * - Maximum retry attempts enforced (MAX_RETRIES)
 *
 * MESSAGE TYPES:
 * - START (0x01): Initiate transfer with metadata
 * - DATA (0x02): Transfer encrypted file chunk
 * - END (0x03): Signal completion
 * - ACK (0x04): Acknowledge received packet
 * - NACK (0x05): Negative acknowledgment (error)
 * - HEARTBEAT (0x06): Keep-alive (reserved for future use)
 * ==================================================================================
 */

#ifndef PROTOCOL_H
#define PROTOCOL_H

#include "common.h"
#include "crypto.h"

/*
 * ==================================================================================
 * PROTOCOL CONSTANTS
 * ==================================================================================
 */

/*
 * IFTP Magic Number (0xDEADBEEF)
 *
 * This 32-bit value appears at the start of every IFTP header to identify
 * packets as belonging to our protocol. It helps:
 * - Distinguish IFTP packets from other ICMP traffic
 * - Detect corruption (if magic is wrong, packet is invalid)
 *
 * The value 0xDEADBEEF is commonly used in debugging/networking as it's
 * easily recognizable in hex dumps and unlikely to appear by accident.
 */
#define IFTP_MAGIC 0xDEADBEEF

/*
 * ==================================================================================
 * MESSAGE TYPES
 * ==================================================================================
 */

/*
 * iftp_msg_type_t - IFTP message type enumeration
 *
 * Defines all possible message types in the IFTP protocol. Each message type
 * has a specific purpose in the file transfer process.
 */
typedef enum {
    /*
     * START (0x01) - Transfer initiation packet
     *
     * Sent by client to begin a new file transfer session.
     * Payload: iftp_metadata_t containing filename, size, IV, salt
     * Response: ACK from server
     * Sequence: Must be seq_num = 0
     */
    IFTP_START = 0x01,

    /*
     * DATA (0x02) - File data chunk packet
     *
     * Sent by client to transmit encrypted file data.
     * Payload: Encrypted file chunk (max 1400 bytes)
     * Response: ACK from server
     * Sequence: Increments for each DATA packet (1, 2, 3, ...)
     * Fragmentation: May be fragmented if chunk doesn't fit in one packet
     */
    IFTP_DATA = 0x02,

    /*
     * END (0x03) - Transfer completion packet
     *
     * Sent by client to signal successful completion of file transfer.
     * Payload: Empty (payload_len = 0)
     * Response: ACK from server
     * Sequence: Final sequence number (after last DATA packet)
     */
    IFTP_END = 0x03,

    /*
     * ACK (0x04) - Acknowledgment packet
     *
     * Sent by server to acknowledge receipt of START, DATA, or END packet.
     * Payload: Empty (payload_len = 0)
     * Sequence: Echoes the seq_num from the packet being acknowledged
     * Purpose: Confirms successful receipt and processing
     */
    IFTP_ACK = 0x04,

    /*
     * NACK (0x05) - Negative acknowledgment packet
     *
     * Sent by server to indicate an error occurred.
     * Payload: iftp_error_t containing error code and message
     * Sequence: Echoes the seq_num from the failed packet
     * Causes: Checksum error, sequence mismatch, crypto error, etc.
     */
    IFTP_NACK = 0x05,

    /*
     * HEARTBEAT (0x06) - Keep-alive message
     *
     * Reserved for future use to detect dead connections.
     * Not currently used in the implementation.
     */
    IFTP_HEARTBEAT = 0x06
} iftp_msg_type_t;

/*
 * ==================================================================================
 * PROTOCOL FLAGS
 * ==================================================================================
 */

/*
 * IFTP Control Flags
 *
 * 8-bit flag field in IFTP header for optional features. Multiple flags can
 * be combined using bitwise OR. Currently defined but not all are used.
 */

/* COMPRESSED flag (0x01) - Payload is compressed
 * Reserved for future use. Current implementation does not compress data. */
#define IFTP_FLAG_COMPRESSED    0x01

/* URGENT flag (0x02) - High priority packet
 * Reserved for future use. Not currently implemented. */
#define IFTP_FLAG_URGENT        0x02

/* FRAGMENTED flag (0x04) - Packet is part of a fragmented message
 * Set when a large encrypted chunk must be split across multiple ICMP packets.
 * fragment_current and fragment_total fields indicate fragment position. */
#define IFTP_FLAG_FRAGMENTED    0x04

/* ENCRYPTED flag (0x08) - Payload contains encrypted data
 * Set for DATA packets containing AES-encrypted file chunks.
 * Not set for START, END, ACK, NACK packets. */
#define IFTP_FLAG_ENCRYPTED     0x08

/*
 * ==================================================================================
 * IFTP HEADER STRUCTURE
 * ==================================================================================
 */

/*
 * iftp_header_t - IFTP protocol header (26 bytes fixed)
 *
 * This structure defines the fixed-size header that appears at the start of
 * every IFTP packet. The header is packed to ensure consistent layout across
 * platforms and compilers.
 *
 * MEMORY LAYOUT (26 bytes total):
 * Offset | Size | Field
 * -------|------|------------------
 *   0    |  4   | magic (0xDEADBEEF)
 *   4    |  2   | session_id
 *   6    |  1   | msg_type
 *   7    |  1   | flags
 *   8    |  4   | seq_num
 *  12    |  4   | fragment_current
 *  16    |  4   | fragment_total
 *  20    |  2   | payload_len
 *  22    |  4   | crc32
 *
 * PACKING:
 * __attribute__((packed)) ensures no padding bytes are inserted between fields.
 * This is critical for network protocols where exact byte layout matters.
 *
 * BYTE ORDER:
 * All multi-byte fields use network byte order (big-endian).
 * Use htons/htonl for writing, ntohs/ntohl for reading.
 */
typedef struct {
    /*
     * Magic number (4 bytes) - Protocol identifier
     *
     * Must always be 0xDEADBEEF. Used to:
     * - Identify IFTP packets among other ICMP traffic
     * - Detect header corruption
     * - Quick rejection of non-IFTP packets
     */
    uint32_t magic;

    /*
     * Session ID (2 bytes) - Unique transfer session identifier
     *
     * Randomly generated by client at start of transfer.
     * Used to:
     * - Distinguish between concurrent transfers
     * - Detect stale packets from previous sessions
     * - Match ACKs to requests
     *
     * Generated by: generate_secure_session_id() using RAND_bytes()
     * Range: 1-65535 (0 is invalid)
     */
    uint16_t session_id;

    /*
     * Message type (1 byte) - Type of IFTP message
     *
     * One of: START, DATA, END, ACK, NACK, HEARTBEAT
     * Determines how payload is interpreted.
     */
    uint8_t msg_type;

    /*
     * Flags (1 byte) - Control flags
     *
     * Bitwise OR of IFTP_FLAG_* constants.
     * Currently used: FRAGMENTED, ENCRYPTED
     * Reserved: COMPRESSED, URGENT
     */
    uint8_t flags;

    /*
     * Sequence number (4 bytes) - Packet ordering
     *
     * Used for:
     * - Ordering packets (especially DATA packets)
     * - Detecting duplicates
     * - Matching ACKs to requests
     *
     * Sequence:
     * - START: seq_num = 0
     * - First DATA: seq_num = 1
     * - Subsequent DATA: seq_num = 2, 3, 4, ...
     * - END: seq_num = (last DATA seq_num + 1)
     * - ACK: echoes seq_num of packet being acknowledged
     */
    uint32_t seq_num;

    /*
     * Current fragment number (4 bytes)
     *
     * For FRAGMENTED packets: 0-based index of this fragment
     * For non-fragmented packets: 0
     *
     * Example: If a 3000-byte encrypted chunk is split into 3 fragments:
     *   Fragment 0: bytes 0-1399
     *   Fragment 1: bytes 1400-2799
     *   Fragment 2: bytes 2800-2999
     */
    uint32_t fragment_current;

    /*
     * Total fragment count (4 bytes)
     *
     * For FRAGMENTED packets: Total number of fragments in this message
     * For non-fragmented packets: 1
     *
     * Server uses this to know when all fragments have been received.
     */
    uint32_t fragment_total;

    /*
     * Payload length (2 bytes) - Actual bytes in payload
     *
     * Number of bytes following this header.
     * Range: 0-1400 bytes (MAX_PAYLOAD_SIZE)
     *
     * Examples:
     * - START: sizeof(iftp_metadata_t) (~350 bytes)
     * - DATA: Encrypted chunk size (variable, max 1400)
     * - END: 0 (no payload)
     * - ACK: 0 (no payload)
     * - NACK: sizeof(iftp_error_t) (~70 bytes)
     */
    uint16_t payload_len;

    /*
     * CRC32 checksum (4 bytes) - Integrity verification
     *
     * CRC32 checksum of header + payload for corruption detection.
     * Calculated over:
     * 1. All header fields EXCEPT crc32 field itself (set to 0 during calc)
     * 2. Entire payload
     *
     * Algorithm: CRC-32 (polynomial 0xEDB88320)
     * Verification: Recalculate on receipt and compare
     * Mismatch: Send NACK with IFTP_ERROR_CHECKSUM_ERROR
     */
    uint32_t crc32;
} __attribute__((packed)) iftp_header_t;

/*
 * ==================================================================================
 * IFTP METADATA STRUCTURE
 * ==================================================================================
 */

/*
 * iftp_metadata_t - File transfer metadata (START packet payload)
 *
 * This structure is transmitted in the payload of START packets to provide
 * the server with all information needed to receive and decrypt the file.
 *
 * SIZE: ~350 bytes (varies with filename length)
 * TRANSMISSION: Once per transfer, in START packet
 * USAGE: Server extracts this to initialize crypto engine and file writer
 */
typedef struct {
    /*
     * Filename (256 bytes) - Name of file being transferred
     *
     * Null-terminated string, max 255 chars + null.
     * Contains only the basename (no directory path).
     *
     * Security: Server validates this to prevent:
     * - Path traversal attacks (..)
     * - Absolute paths (/)
     * - Invalid characters
     *
     * Server may rename if file exists (appends _1, _2, etc.)
     */
    char filename[MAX_FILENAME_LEN + 1];

    /*
     * File size (8 bytes) - Total size of plaintext file
     *
     * Size in bytes of the original file before encryption.
     * Used by:
     * - Server to allocate buffer/track progress
     * - Client to calculate total packets needed
     * - Progress reporting
     *
     * Note: Encrypted size will be larger due to AES padding (up to 16 bytes)
     */
    uint64_t file_size;

    /*
     * Initialization Vector (16 bytes) - AES-CBC IV
     *
     * Randomly generated IV for AES-256-CBC encryption.
     * Must be unique for each file transfer.
     * Generated by: RAND_bytes() on client
     * Used by: Server to initialize decryption (crypto_init)
     *
     * Security: IV does not need to be secret, only unpredictable.
     */
    uint8_t iv[AES_IV_SIZE];

    /*
     * PBKDF2 Salt (32 bytes) - Key derivation salt
     *
     * Randomly generated salt for PBKDF2 key derivation.
     * Ensures each transfer has a unique encryption key.
     * Generated by: RAND_bytes() on client
     * Used by: Server to derive decryption key from login
     *
     * Security: Salt does not need to be secret, only unique.
     */
    uint8_t salt[PBKDF2_SALT_SIZE];

    /*
     * Chunk size (4 bytes) - Size of encryption chunks
     *
     * Currently not used in implementation but reserved for:
     * - Configurable chunk sizes
     * - Adaptive sizing based on network conditions
     * - Future optimizations
     */
    uint32_t chunk_size;

    /*
     * Compression type (1 byte)
     *
     * Reserved for future use. Currently always 0 (no compression).
     * Could indicate compression algorithm if IFTP_FLAG_COMPRESSED is used.
     */
    uint8_t compression_type;

    /*
     * Reserved (7 bytes) - Padding for future extensions
     *
     * Set to zero. Available for future protocol extensions without
     * breaking compatibility. Could be used for:
     * - Additional crypto parameters
     * - Checksums
     * - Feature flags
     * - Timestamps
     */
    uint8_t reserved[7];
} __attribute__((packed)) iftp_metadata_t;

/*
 * ==================================================================================
 * ERROR HANDLING
 * ==================================================================================
 */

/*
 * iftp_error_code_t - Error codes for NACK packets
 *
 * Specific error codes sent in NACK packets to indicate why a packet failed.
 * Helps client understand what went wrong and whether retry might succeed.
 */
typedef enum {
    IFTP_ERROR_NONE = 0,              /* No error (should not appear in NACK) */
    IFTP_ERROR_INVALID_PACKET = 1,    /* Malformed packet (bad header, etc.) */
    IFTP_ERROR_SEQUENCE_ERROR = 2,    /* Wrong sequence number (out of order) */
    IFTP_ERROR_CHECKSUM_ERROR = 3,    /* CRC32 validation failed (corruption) */
    IFTP_ERROR_CRYPTO_ERROR = 4,      /* Decryption failed (wrong key, padding) */
    IFTP_ERROR_FILE_ERROR = 5,        /* File I/O error (disk full, permissions) */
    IFTP_ERROR_TIMEOUT = 6,           /* Operation timed out */
    IFTP_ERROR_SESSION_ERROR = 7      /* Invalid or expired session */
} iftp_error_code_t;

/*
 * iftp_error_t - Error information structure (NACK packet payload)
 *
 * Detailed error information sent in NACK packet payload.
 * Helps client diagnose problems and decide on retry strategy.
 */
typedef struct {
    /*
     * Error code (1 byte) - Type of error that occurred
     * One of the iftp_error_code_t values
     */
    uint8_t error_code;

    /*
     * Failed sequence number (4 bytes) - Which packet failed
     * Sequence number of the packet that caused this error
     */
    uint32_t failed_seq_num;

    /*
     * Error message (64 bytes) - Human-readable description
     * Null-terminated string with additional details about the error
     * Example: "CRC mismatch: expected 0x12345678, got 0x87654321"
     */
    char error_message[64];
} __attribute__((packed)) iftp_error_t;

/*
 * ==================================================================================
 * PACKET CREATION AND PARSING
 * ==================================================================================
 */

/*
 * create_iftp_packet - Construct IFTP packet from header and payload
 *
 * Low-level function that combines header and payload into a complete packet.
 * Calculates and fills in the CRC32 checksum.
 *
 * @param header: Pointer to filled-in IFTP header
 * @param payload: Pointer to payload data (or NULL if no payload)
 * @param packet_buffer: Output buffer for complete packet
 * @param packet_len: Output parameter for total packet length
 * @return: 0 on success, -1 on error
 */
int create_iftp_packet(const iftp_header_t *header, const void *payload,
                      uint8_t *packet_buffer, size_t *packet_len);

/*
 * parse_iftp_packet - Extract header and payload from received packet
 *
 * Parses a received packet, validates magic/CRC, and extracts
 * header and payload into separate structures.
 *
 * VALIDATION:
 * - Checks magic number (0xDEADBEEF)
 * - Validates CRC32 checksum
 * - Validates payload length
 *
 * @param packet_buffer: Raw packet data from network
 * @param packet_len: Total packet length
 * @param header: Output parameter for parsed header
 * @param payload: Output buffer for payload data
 * @param payload_len: Output parameter for payload length
 * @return: 0 on success, -1 on error
 */
int parse_iftp_packet(const uint8_t *packet_buffer, size_t packet_len,
                     iftp_header_t *header, uint8_t *payload, size_t *payload_len);

/*
 * ==================================================================================
 * HIGH-LEVEL PACKET CREATION FUNCTIONS
 * ==================================================================================
 */

/* Create START packet with metadata */
int create_start_packet(uint16_t session_id, const iftp_metadata_t *metadata,
                       uint8_t *packet_buffer, size_t *packet_len);

/* Create DATA packet with file chunk */
int create_data_packet(uint16_t session_id, uint32_t seq_num, uint32_t frag_current,
                      uint32_t frag_total, const void *data, size_t data_len,
                      uint8_t *packet_buffer, size_t *packet_len);

/* Create END packet (no payload) */
int create_end_packet(uint16_t session_id, uint32_t seq_num,
                     uint8_t *packet_buffer, size_t *packet_len);

/* Create ACK packet (no payload) */
int create_ack_packet(uint16_t session_id, uint32_t seq_num,
                     uint8_t *packet_buffer, size_t *packet_len);

/* Create NACK packet with error information */
int create_nack_packet(uint16_t session_id, uint32_t seq_num, iftp_error_code_t error_code,
                      const char *error_message, uint8_t *packet_buffer, size_t *packet_len);

/* Create HEARTBEAT packet (reserved for future use) */
int create_heartbeat_packet(uint16_t session_id, uint32_t seq_num,
                           uint8_t *packet_buffer, size_t *packet_len);

/*
 * ==================================================================================
 * UTILITY FUNCTIONS
 * ==================================================================================
 */

/*
 * calculate_crc32 - Compute CRC32 checksum
 *
 * Calculates CRC32 checksum using standard polynomial (0xEDB88320).
 * Used for integrity checking of IFTP packets.
 *
 * ALGORITHM: CRC-32 (used in Ethernet, ZIP, PNG, etc.)
 *
 * @param data: Data to checksum
 * @param len: Length of data in bytes
 * @return: 32-bit CRC value
 */
uint32_t calculate_crc32(const void *data, size_t len);

/*
 * validate_iftp_header - Validate IFTP header fields
 *
 * Checks header for validity:
 * - Magic number matches IFTP_MAGIC
 * - Message type is valid
 * - Payload length is within bounds
 *
 * @param header: Header to validate
 * @return: 0 if valid, -1 if invalid
 */
int validate_iftp_header(const iftp_header_t *header);

/*
 * iftp_msg_type_to_string - Convert message type to string
 *
 * Returns human-readable name for message type.
 * Useful for logging and debugging.
 *
 * @param msg_type: Message type enum value
 * @return: String representation (e.g., "START", "DATA", "ACK")
 */
const char *iftp_msg_type_to_string(iftp_msg_type_t msg_type);

/*
 * iftp_error_to_string - Convert error code to string
 *
 * Returns human-readable description of error code.
 *
 * @param error_code: Error code enum value
 * @return: String description (e.g., "Checksum error", "Sequence error")
 */
const char *iftp_error_to_string(iftp_error_code_t error_code);

/*
 * ==================================================================================
 * SESSION MANAGEMENT
 * ==================================================================================
 */

/*
 * protocol_session_t - Session state tracking
 *
 * Maintains protocol state for a transfer session.
 * Tracks sequence numbers and detects protocol violations.
 */
typedef struct {
    uint16_t session_id;         /* Session identifier */
    uint32_t next_seq_send;      /* Next sequence number to send */
    uint32_t next_seq_recv;      /* Next sequence number expected */
    uint32_t last_ack_sent;      /* Last ACK sent */
    uint32_t last_ack_recv;      /* Last ACK received */
    time_t last_activity;        /* Last activity timestamp (for timeouts) */
} protocol_session_t;

/* Initialize protocol session */
int protocol_session_init(protocol_session_t *session, uint16_t session_id);

/* Update session after sending a packet */
int protocol_session_update_send(protocol_session_t *session, uint32_t seq_num);

/* Update session after receiving a packet */
int protocol_session_update_recv(protocol_session_t *session, uint32_t seq_num);

/* Check if session has timed out */
int protocol_session_check_timeout(const protocol_session_t *session, int timeout_seconds);

#endif /* PROTOCOL_H */
