/*
 * ==================================================================================
 * Network Interface Header - Raw Socket ICMP/ICMPv6 Operations
 *
 * ISA Project
 * Author: Roman Necas (xnecasr00)
 * Date: 13. October 2025
 *
 * PURPOSE:
 * This header defines the network interface layer for the ICMP covert channel
 * file transfer application. It provides abstractions for raw socket operations,
 * supporting both IPv4 (ICMP) and IPv6 (ICMPv6) Echo-Request/Reply messages.
 *
 * RESPONSIBILITIES:
 * - Raw socket creation and management (requires root privileges)
 * - ICMP packet transmission and reception
 * - Address family abstraction (IPv4/IPv6)
 * - Timeout handling for reliable communication
 * - Network statistics tracking
 * - Checksum calculation for ICMPv4 packets
 *
 * PROTOCOL SUPPORT:
 * - IPv4: ICMP Echo-Request (type 8) / Echo-Reply (type 0)
 * - IPv6: ICMPv6 Echo-Request (type 128) / Echo-Reply (type 129)
 *
 * RAW SOCKET REQUIREMENTS:
 * - Requires CAP_NET_RAW capability or root privileges
 * - Uses IPPROTO_ICMP for IPv4, IPPROTO_ICMPV6 for IPv6
 * - IPv4: Application must calculate ICMP checksum
 * - IPv6: Kernel automatically calculates ICMPv6 checksum (RFC 3542)
 *
 * KEY FEATURES:
 * - Dual-stack support (IPv4/IPv6) with automatic detection
 * - Hostname resolution via getaddrinfo()
 * - Configurable send/receive timeouts
 * - Non-blocking receive mode for server operation
 * - MTU discovery for optimal packet sizing
 * - Comprehensive error handling with detailed diagnostics
 * ==================================================================================
 */

#ifndef NETWORK_H
#define NETWORK_H

#include "common.h"

/*
 * ==================================================================================
 * NETWORK INTERFACE STRUCTURE
 * ==================================================================================
 */

/*
 * network_interface_t - Network layer state management
 *
 * This structure encapsulates all state required for ICMP socket operations.
 * It abstracts the differences between IPv4 and IPv6, providing a unified
 * interface for packet transmission and reception.
 *
 * LIFECYCLE:
 * 1. Allocated by caller (typically on stack or in session structure)
 * 2. Initialized by network_init() - creates raw socket, resolves destination
 * 3. Configured by network_set_timeout() if custom timeouts needed
 * 4. Used for network_send_packet() and network_recv_packet() operations
 * 5. Cleaned up by network_cleanup() (closes socket)
 *
 * USAGE PATTERNS:
 *
 * Client mode:
 *   network_interface_t net;
 *   network_init(&net, "192.168.1.100");
 *   network_send_packet(&net, packet, packet_len);
 *   network_recv_packet(&net, buffer, buffer_len, &src_addr, &src_addr_len);
 *   network_cleanup(&net);
 *
 * Server mode:
 *   network_interface_t net;
 *   network_init(&net, NULL);  // No destination for server
 *   network_recv_packet_nonblocking(&net, buffer, buffer_len, &src_addr, &src_addr_len);
 *   network_send_reply(&net, payload, payload_len, &src_addr, src_addr_len);
 *   network_cleanup(&net);
 *
 * THREAD SAFETY:
 * This structure is NOT thread-safe. Each thread should have its own instance.
 *
 * SECURITY NOTES:
 * - Raw socket operations require elevated privileges
 * - Socket is bound to ICMP protocol only - cannot send arbitrary IP packets
 * - Timeouts prevent indefinite blocking on malicious/slow peers
 */
typedef struct {
    /*
     * sockfd - Primary raw ICMP socket file descriptor
     *
     * Client mode: Single socket (IPv4 or IPv6) based on destination address
     * - IPv4: socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
     * - IPv6: socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)
     *
     * Server mode: IPv4 socket (used with sockfd_v6 for dual-stack)
     * - Always: socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
     *
     * Values:
     * - >= 0: Valid socket descriptor
     * - -1: Invalid/uninitialized socket
     *
     * Closed by network_cleanup() using SAFE_CLOSE macro.
     */
    int sockfd;

    /*
     * sockfd_v6 - IPv6 socket file descriptor (server mode only)
     *
     * Client mode: Not used (always -1)
     * Server mode: IPv6 socket for dual-stack support
     * - socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)
     *
     * This enables server to receive both IPv4 (ICMP) and IPv6 (ICMPv6) packets
     * simultaneously. The server uses select() to poll both sockfd and sockfd_v6.
     *
     * Values:
     * - >= 0: Valid IPv6 socket (server mode)
     * - -1: Not used (client mode) or uninitialized
     *
     * Closed by network_cleanup() using SAFE_CLOSE macro.
     */
    int sockfd_v6;

    /*
     * dest_addr - Destination address storage (IPv4 or IPv6)
     *
     * This is a polymorphic structure capable of holding both sockaddr_in (IPv4)
     * and sockaddr_in6 (IPv6) addresses. The actual type is determined by the
     * addr_family field.
     *
     * Structure layout:
     * - sockaddr_storage is guaranteed to be large enough for any socket address
     * - Size: Typically 128 bytes (platform-dependent)
     * - Alignment: Suitable for casting to sockaddr_in or sockaddr_in6
     *
     * Population:
     * - Client mode: Populated by network_init() via getaddrinfo()
     * - Server mode: Populated by network_recv_packet() from incoming packets
     *
     * Usage:
     *   struct sockaddr_in *sin = (struct sockaddr_in *)&net->dest_addr;
     *   sin->sin_port;  // Access IPv4 fields
     *
     *   struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&net->dest_addr;
     *   sin6->sin6_port;  // Access IPv6 fields
     */
    struct sockaddr_storage dest_addr;

    /*
     * dest_addr_len - Actual length of dest_addr structure
     *
     * This field specifies the actual size of the address stored in dest_addr.
     * It is required because dest_addr is a generic storage structure that can
     * hold addresses of different sizes.
     *
     * Typical values:
     * - IPv4: sizeof(struct sockaddr_in) = 16 bytes
     * - IPv6: sizeof(struct sockaddr_in6) = 28 bytes
     *
     * Used by:
     * - sendto() to specify destination address size
     * - recvfrom() to receive actual address size (pass as pointer)
     */
    socklen_t dest_addr_len;

    /*
     * addr_family - Address family indicator
     *
     * Specifies whether this interface is operating in IPv4 or IPv6 mode.
     * This determines which socket protocol, address structures, and ICMP
     * message types are used.
     *
     * Values:
     * - AF_INET (2): IPv4 address family
     *   * Uses IPPROTO_ICMP
     *   * Uses struct sockaddr_in
     *   * ICMP Echo-Request (type 8) / Echo-Reply (type 0)
     *
     * - AF_INET6 (10): IPv6 address family
     *   * Uses IPPROTO_ICMPV6
     *   * Uses struct sockaddr_in6
     *   * ICMPv6 Echo-Request (type 128) / Echo-Reply (type 129)
     *
     * Determined automatically by network_init() based on getaddrinfo() results.
     */
    int addr_family;

    /*
     * send_timeout - Send operation timeout in seconds
     *
     * Maximum time to wait for send operations to complete before returning error.
     * This timeout is set using setsockopt() with SO_SNDTIMEO option.
     *
     * Purpose:
     * - Prevents indefinite blocking if network is congested
     * - Allows application to retry or abort transfer
     *
     * Default: INITIAL_TIMEOUT (2 seconds)
     * Range: 1-300 seconds (validated by argument parser)
     *
     * Note: Send operations on raw sockets rarely block, as the kernel typically
     * queues outgoing packets. Timeout mainly protects against kernel buffer exhaustion.
     */
    int send_timeout;

    /*
     * recv_timeout - Receive operation timeout in seconds
     *
     * Maximum time to wait for incoming packets before returning EAGAIN/EWOULDBLOCK.
     * This timeout is set using setsockopt() with SO_RCVTIMEO option.
     *
     * Purpose:
     * - Enables retry logic with exponential backoff
     * - Prevents infinite waiting for lost/dropped packets
     * - Critical for client mode when waiting for ACK responses
     *
     * Default: INITIAL_TIMEOUT (2 seconds)
     * Range: 1-300 seconds
     *
     * Client mode usage:
     * - Wait for ACK after sending DATA packet
     * - If timeout occurs, increment retry counter and resend
     * - Timeout value increases exponentially: 2s → 4s → 8s → 16s → 32s (capped at MAX_TIMEOUT)
     *
     * Server mode usage:
     * - Use non-blocking receive (network_recv_packet_nonblocking)
     * - Timeout is less critical as server waits indefinitely
     */
    int recv_timeout;
} network_interface_t;

/*
 * ==================================================================================
 * NETWORK STATISTICS STRUCTURE
 * ==================================================================================
 */

/*
 * network_stats_t - Network performance and error metrics
 *
 * This structure tracks comprehensive statistics about network operations during
 * a file transfer session. It is used for:
 * - Debugging network issues
 * - Performance analysis
 * - Identifying reliability problems (high retransmissions, checksum errors)
 * - User feedback (display transfer progress)
 *
 * LIFECYCLE:
 * 1. Initialized by network_init_stats() (zeros all fields)
 * 2. Updated by network_update_stats() after each send/receive operation
 * 3. Displayed by network_print_stats() at end of transfer
 *
 * USAGE:
 *   network_stats_t stats;
 *   network_init_stats(&stats);
 *   // ... perform transfers ...
 *   network_update_stats(&stats, 1, packet_len, 0);  // Sent packet
 *   network_update_stats(&stats, 0, 0, 1);           // Retransmission
 *   network_print_stats(&stats);
 *
 * All counters are 64-bit to prevent overflow even for very large transfers
 * (e.g., 10 GB file = ~7.5 million 1400-byte packets).
 */
typedef struct {
    /*
     * packets_sent - Total number of packets transmitted
     *
     * Incremented for every successful call to network_send_packet() or
     * network_send_reply(). Includes both original transmissions and
     * retransmissions (counted separately in retransmissions field).
     *
     * Example values:
     * - 1 MB file: ~750 packets (1400-byte payload)
     * - 10 MB file: ~7500 packets
     */
    uint64_t packets_sent;

    /*
     * packets_received - Total number of packets received
     *
     * Incremented for every successful call to network_recv_packet() or
     * network_recv_packet_nonblocking() that returns valid data. Includes
     * both valid and invalid packets (invalid counted in checksum_errors).
     *
     * Client mode: Primarily ACK responses from server
     * Server mode: DATA packets from client, END packet
     */
    uint64_t packets_received;

    /*
     * bytes_sent - Total bytes transmitted at network layer
     *
     * Cumulative sum of all packet sizes sent, including:
     * - ICMP header (8 bytes)
     * - IFTP header (24 bytes)
     * - IFTP payload (0-1400 bytes)
     *
     * Does NOT include:
     * - IP header (added by kernel)
     * - Link layer headers (Ethernet, etc.)
     *
     * Used to calculate transfer throughput and verify file size.
     */
    uint64_t bytes_sent;

    /*
     * bytes_received - Total bytes received at network layer
     *
     * Cumulative sum of all packet sizes received. Includes all received
     * packets, even those discarded due to checksum errors or protocol
     * violations.
     */
    uint64_t bytes_received;

    /*
     * retransmissions - Number of packet retransmissions
     *
     * Incremented whenever a packet is sent more than once due to:
     * - Timeout waiting for ACK
     * - NACK response from peer
     * - Checksum error detection
     *
     * High retransmission count indicates:
     * - Network congestion or packet loss
     * - Peer overload (slow processing)
     * - Aggressive timeout settings
     *
     * Normal values: 0-5% of packets_sent
     * Problematic: >10% of packets_sent
     */
    uint64_t retransmissions;

    /*
     * checksum_errors - Number of checksum validation failures
     *
     * Incremented when received packet has invalid CRC32 checksum in IFTP
     * header. Indicates:
     * - Network corruption (rare on wired networks)
     * - Software bugs in sender
     * - Malicious packet injection
     *
     * Should be 0 in normal operation. Any non-zero value requires investigation.
     */
    uint64_t checksum_errors;

    /*
     * timeouts - Number of timeout events
     *
     * Incremented when network_recv_packet() returns timeout error (EAGAIN/
     * EWOULDBLOCK) after waiting recv_timeout seconds. Indicates:
     * - Packet loss
     * - Peer failure or slowdown
     * - Network path issues
     *
     * Client mode: Timeout waiting for ACK triggers retransmission
     * Server mode: Timeout waiting for next DATA packet (logged but not critical)
     *
     * Normal values: Similar to retransmissions count
     */
    uint64_t timeouts;
} network_stats_t;

/*
 * ==================================================================================
 * CORE NETWORK FUNCTIONS
 * ==================================================================================
 */

/*
 * network_init - Initialize network interface and create raw ICMP socket
 *
 * This function sets up the network interface for ICMP communication. It performs
 * the following operations:
 *
 * 1. Creates raw socket (requires root privileges):
 *    - IPv4: socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)
 *    - IPv6: socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)
 *
 * 2. Resolves destination address (client mode only):
 *    - Accepts IPv4 addresses: "192.168.1.100"
 *    - Accepts IPv6 addresses: "::1", "fe80::1"
 *    - Accepts hostnames: "example.com"
 *    - Uses getaddrinfo() for resolution
 *
 * 3. Sets default timeouts (2 seconds send, 2 seconds receive)
 *
 * 4. Initializes network_interface_t structure fields
 *
 * PRIVILEGE REQUIREMENTS:
 * Raw sockets require CAP_NET_RAW capability or effective UID 0 (root).
 * The application verifies root privileges in argument parser before calling
 * this function.
 *
 * ERROR HANDLING:
 * - Returns -1 and sets error context on failure
 * - Common errors:
 *   * EPERM: Insufficient privileges for raw socket
 *   * EPROTONOSUPPORT: ICMP protocol not supported by kernel
 *   * EAI_*: getaddrinfo() resolution failures
 *
 * @param net: Network interface structure to initialize (output parameter)
 * @param dest_address: Destination IP address or hostname (NULL for server mode)
 *
 * @return:
 *    0: Success - socket created and destination resolved
 *   -1: Failure - error details in error context
 */
int network_init(network_interface_t *net, const char *dest_address);

/*
 * network_send_packet - Send ICMP packet to destination
 *
 * Transmits a complete ICMP packet to the destination address stored in the
 * network interface structure. The packet must already contain:
 * - ICMP header (8 bytes) with correct type, code, checksum
 * - IFTP header (24 bytes) with protocol fields
 * - Optional payload (0-1400 bytes)
 *
 * CHECKSUM HANDLING:
 * - IPv4: Caller MUST calculate ICMP checksum using network_calculate_icmp_checksum()
 * - IPv6: Checksum field MUST be 0, kernel calculates automatically (RFC 3542)
 *
 * SEND BEHAVIOR:
 * - Uses sendto() syscall with destination from net->dest_addr
 * - Blocks until packet is accepted by kernel (rarely blocks in practice)
 * - Respects SO_SNDTIMEO timeout if configured
 * - Returns number of bytes accepted by kernel (not necessarily transmitted)
 *
 * MTU CONSIDERATIONS:
 * This function does NOT perform fragmentation. Caller must ensure packet_len
 * does not exceed path MTU (typically 1500 bytes). Use network_get_mtu() to
 * query MTU if needed.
 *
 * ERROR HANDLING:
 * - EMSGSIZE: Packet too large for MTU (reduce payload size)
 * - ENETUNREACH: Network unreachable (routing problem)
 * - EHOSTUNREACH: Host unreachable (no route to destination)
 * - EAGAIN: Send buffer full (temporary, retry)
 *
 * @param net: Initialized network interface
 * @param packet: Complete ICMP packet with headers and payload
 * @param packet_len: Total packet length in bytes (ICMP + IFTP + payload)
 *
 * @return:
 *   >0: Number of bytes sent (should equal packet_len)
 *   -1: Error occurred (details in error context)
 */
int network_send_packet(network_interface_t *net, const void *packet, size_t packet_len);

/*
 * network_recv_packet - Receive ICMP packet (blocking with timeout)
 *
 * Receives an ICMP packet from the network interface. This function blocks
 * until a packet arrives or the receive timeout expires (configured via
 * network_set_timeout() or defaults to INITIAL_TIMEOUT).
 *
 * RECEIVE BEHAVIOR:
 * - Uses recvfrom() syscall
 * - Blocks until packet arrives or timeout (SO_RCVTIMEO)
 * - Returns source address of sender (useful for server replies)
 * - May receive packets destined for other ICMP applications (filtering required)
 *
 * PACKET FILTERING:
 * This function returns ALL ICMP Echo-Request/Reply packets received by the
 * kernel, not just those for this application. Caller MUST:
 * 1. Verify ICMP type (Echo-Request/Reply)
 * 2. Verify IFTP magic number (0xDEADBEEF)
 * 3. Verify session ID matches expected session
 * 4. Verify CRC32 checksum
 *
 * IPv4 BEHAVIOR:
 * - Receives packets WITH IP header prepended (use IPPROTO_ICMP)
 * - Caller must skip IP header (typically 20 bytes) to access ICMP header
 * - IP header length varies (check IHL field)
 *
 * IPv6 BEHAVIOR:
 * - Receives packets WITHOUT IPv6 header (kernel strips it)
 * - First byte in buffer is ICMPv6 header
 *
 * TIMEOUT HANDLING:
 * - Returns -1 with errno = EAGAIN or EWOULDBLOCK on timeout
 * - Caller should check errno and retry if appropriate
 * - Client mode: Timeout waiting for ACK triggers retransmission
 *
 * @param net: Initialized network interface
 * @param buffer: Buffer to receive packet data (min MAX_BUFFER_SIZE = 2048 bytes)
 * @param buffer_len: Size of receive buffer
 * @param src_addr: Output parameter for source address of received packet (can be NULL)
 * @param src_addr_len: Input/output parameter for src_addr length (can be NULL)
 *
 * @return:
 *   >0: Number of bytes received (total packet size including headers)
 *    0: Connection closed (rare for raw sockets)
 *   -1: Error occurred (check errno for timeout vs. real error)
 */
int network_recv_packet(network_interface_t *net, void *buffer, size_t buffer_len,
                       struct sockaddr_storage *src_addr, socklen_t *src_addr_len);

/*
 * network_recv_packet_nonblocking - Receive ICMP packet (non-blocking)
 *
 * Same as network_recv_packet() but sets socket to non-blocking mode before
 * receiving. This function returns immediately if no packet is available.
 *
 * PURPOSE:
 * Used primarily in server mode where we want to:
 * - Poll for incoming packets without blocking forever
 * - Process multiple concurrent sessions
 * - Implement session timeouts
 *
 * BEHAVIOR:
 * 1. Sets socket to non-blocking mode (fcntl F_SETFL O_NONBLOCK)
 * 2. Calls recvfrom() which returns immediately
 * 3. Restores socket to blocking mode
 *
 * RETURN VALUES:
 * - >0: Packet received (length in bytes)
 * - -1 with errno = EAGAIN/EWOULDBLOCK: No packet available (NOT an error)
 * - -1 with other errno: Real error occurred
 *
 * @param net: Initialized network interface
 * @param buffer: Buffer to receive packet data
 * @param buffer_len: Size of receive buffer
 * @param src_addr: Output parameter for source address (can be NULL)
 * @param src_addr_len: Input/output parameter for src_addr length (can be NULL)
 *
 * @return:
 *   >0: Number of bytes received
 *   -1: No packet available (errno = EAGAIN) or error
 */
int network_recv_packet_nonblocking(network_interface_t *net, void *buffer, size_t buffer_len,
                                    struct sockaddr_storage *src_addr, socklen_t *src_addr_len);

/*
 * network_send_reply - Send ICMP Echo Reply to specific address
 *
 * Convenience function for server mode to send ICMP Echo Reply packets back
 * to a client. This is used to send ACK/NACK responses after receiving DATA
 * packets.
 *
 * BEHAVIOR:
 * - Creates ICMP Echo Reply packet (type 0 for IPv4, type 129 for IPv6)
 * - Sets ICMP ID and sequence from original request (stored in payload)
 * - Calculates checksum (IPv4 only)
 * - Sends to specified destination address
 *
 * DIFFERENCE FROM network_send_packet():
 * - network_send_packet(): Sends to net->dest_addr (client mode)
 * - network_send_reply(): Sends to specified address (server mode)
 *
 * @param net: Initialized network interface
 * @param payload: IFTP packet payload (contains ACK/NACK response)
 * @param payload_len: Length of payload
 * @param dest_addr: Destination address (client that sent the request)
 * @param dest_addr_len: Length of destination address
 *
 * @return:
 *   >0: Number of bytes sent
 *   -1: Error occurred
 */
int network_send_reply(network_interface_t *net, const void *payload, size_t payload_len,
                      const struct sockaddr_storage *dest_addr, socklen_t dest_addr_len);

/*
 * network_cleanup - Clean up network interface and close socket
 *
 * Releases all resources associated with the network interface. This function:
 * 1. Closes raw socket using SAFE_CLOSE macro
 * 2. Zeros network_interface_t structure
 *
 * SAFE TO CALL MULTIPLE TIMES:
 * Uses SAFE_CLOSE which sets sockfd = -1 after closing, making subsequent
 * calls safe no-ops.
 *
 * MUST BE CALLED:
 * Failure to call this function leaks a file descriptor. Always call in
 * cleanup paths, even on error.
 *
 * @param net: Network interface to clean up
 */
void network_cleanup(network_interface_t *net);

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

/*
 * network_set_timeout - Configure send and receive timeouts
 *
 * Updates the socket timeout values using setsockopt() with SO_SNDTIMEO and
 * SO_RCVTIMEO options. Timeouts are specified in seconds and converted to
 * struct timeval internally.
 *
 * TIMEOUT EFFECTS:
 * - Send timeout: Maximum time to wait for send buffer space
 * - Receive timeout: Maximum time to wait for incoming packet
 *
 * DEFAULT VALUES:
 * Both timeouts default to INITIAL_TIMEOUT (2 seconds) set by network_init().
 *
 * EXPONENTIAL BACKOFF:
 * Client mode typically increases recv_timeout on each retry:
 *   Attempt 1: 2 seconds
 *   Attempt 2: 4 seconds
 *   Attempt 3: 8 seconds
 *   Attempt 4: 16 seconds
 *   Attempt 5: 30 seconds (capped at MAX_TIMEOUT)
 *
 * @param net: Network interface to configure
 * @param send_timeout: Send timeout in seconds (1-300)
 * @param recv_timeout: Receive timeout in seconds (1-300)
 *
 * @return:
 *    0: Success
 *   -1: Error setting socket options
 */
int network_set_timeout(network_interface_t *net, int send_timeout, int recv_timeout);

/*
 * network_get_mtu - Query path MTU to destination
 *
 * Attempts to determine the Maximum Transmission Unit (MTU) for the path to
 * the destination address. This is useful for optimizing packet size to avoid
 * IP-level fragmentation.
 *
 * METHODS:
 * 1. Query IP_MTU socket option (Linux-specific)
 * 2. Parse /proc/sys/net/ipv4/route (fallback)
 * 3. Return default 1500 if unable to determine
 *
 * TYPICAL MTU VALUES:
 * - Ethernet: 1500 bytes
 * - PPPoE: 1492 bytes
 * - VPN: 1400 bytes
 * - Internet (safe minimum): 576 bytes
 *
 * USAGE:
 * This application uses fixed MAX_PAYLOAD_SIZE = 1400 bytes which is
 * conservative and should work on all networks. This function is provided
 * for future optimization but not currently used.
 *
 * @param net: Initialized network interface
 * @param dest_address: Destination IP address or hostname
 *
 * @return:
 *   >0: Path MTU in bytes
 *   -1: Unable to determine MTU
 */
int network_get_mtu(network_interface_t *net, const char *dest_address);

/*
 * network_addr_to_string - Convert socket address to string representation
 *
 * Converts sockaddr_storage (IPv4 or IPv6) to human-readable string format
 * using inet_ntop().
 *
 * OUTPUT FORMATS:
 * - IPv4: "192.168.1.100"
 * - IPv6: "fe80::1", "2001:db8::1"
 *
 * BUFFER SIZE:
 * Caller must provide buffer of at least INET6_ADDRSTRLEN (46) bytes to
 * accommodate longest possible IPv6 address string.
 *
 * @param addr: Socket address to convert
 * @param buffer: Output buffer for string representation
 * @param buffer_size: Size of output buffer (min INET6_ADDRSTRLEN)
 *
 * @return:
 *   Pointer to buffer on success
 *   NULL on error
 */
const char *network_addr_to_string(const struct sockaddr_storage *addr, char *buffer, size_t buffer_size);

/*
 * network_compare_addresses - Compare two socket addresses for equality
 *
 * Compares two socket addresses to determine if they refer to the same host.
 * Handles both IPv4 and IPv6 addresses correctly.
 *
 * COMPARISON:
 * - Checks address family matches (AF_INET vs AF_INET6)
 * - Compares address bytes using memcmp()
 * - Ignores port numbers
 * - IPv6 scope ID is NOT compared
 *
 * USAGE:
 * Server mode uses this to verify that ACK responses come from the same
 * client that sent the original request (prevents hijacking).
 *
 * @param addr1: First address to compare
 * @param addr2: Second address to compare
 *
 * @return:
 *    0: Addresses are equal
 *   -1: Addresses differ or comparison error
 */
int network_compare_addresses(const struct sockaddr_storage *addr1, const struct sockaddr_storage *addr2);

/*
 * ==================================================================================
 * STATISTICS FUNCTIONS
 * ==================================================================================
 */

/*
 * network_init_stats - Initialize statistics structure to zero
 *
 * Zeros all fields in network_stats_t structure. Should be called once at
 * the beginning of a transfer session.
 *
 * @param stats: Statistics structure to initialize
 */
void network_init_stats(network_stats_t *stats);

/*
 * network_update_stats - Update statistics after network operation
 *
 * Updates statistics counters based on the result of a network operation.
 * This function is called after each successful send or receive.
 *
 * @param stats: Statistics structure to update
 * @param sent: 1 if operation was a send, 0 if receive
 * @param bytes: Number of bytes sent or received
 * @param retransmit: 1 if this was a retransmission, 0 otherwise
 */
void network_update_stats(network_stats_t *stats, int sent, size_t bytes, int retransmit);

/*
 * network_print_stats - Display statistics summary to stdout
 *
 * Prints a formatted summary of network statistics including:
 * - Total packets and bytes sent/received
 * - Retransmission count and percentage
 * - Checksum error count
 * - Timeout count
 *
 * OUTPUT EXAMPLE:
 *   Network Statistics:
 *   - Packets sent: 750
 *   - Packets received: 750
 *   - Bytes sent: 1050000 (1.00 MB)
 *   - Bytes received: 18000 (0.02 MB)
 *   - Retransmissions: 5 (0.67%)
 *   - Checksum errors: 0
 *   - Timeouts: 5
 *
 * @param stats: Statistics structure to display
 */
void network_print_stats(const network_stats_t *stats);

/*
 * ==================================================================================
 * CHECKSUM FUNCTIONS
 * ==================================================================================
 */

/*
 * network_calculate_icmp_checksum - Calculate ICMPv4 checksum
 *
 * Computes the Internet Checksum (RFC 1071) for an ICMPv4 packet. This is
 * the standard 16-bit one's complement checksum used by IP, ICMP, UDP, TCP.
 *
 * ALGORITHM (RFC 1071):
 * 1. Set checksum field to 0
 * 2. Sum all 16-bit words in the packet
 * 3. Add carry bits to the sum
 * 4. Take one's complement (~sum)
 *
 * USAGE:
 * IPv4 ICMP packets MUST have checksum calculated by application:
 *   icmp_hdr->checksum = 0;
 *   icmp_hdr->checksum = network_calculate_icmp_checksum(packet, packet_len);
 *
 * IPv6 ICMPv6 packets MUST NOT use this function - kernel calculates automatically.
 *
 * PADDING:
 * If packet length is odd, a zero byte is appended for checksum calculation
 * only (not transmitted).
 *
 * @param data: ICMP packet data (starting at ICMP header)
 * @param len: Length of packet in bytes
 *
 * @return: 16-bit checksum value (in network byte order, ready to use)
 */
uint16_t network_calculate_icmp_checksum(const void *data, size_t len);

#endif /* NETWORK_H */
