/* SPDX-License-Identifier: GPL-3.0-only */
#ifndef HTP_N3N_H
#define HTP_N3N_H

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct htp_n3n_edge htp_n3n_edge;

typedef enum {
    HTP_N3N_IDLE = 0,
    HTP_N3N_CONNECTING = 1,
    HTP_N3N_CONNECTED = 2,
    HTP_N3N_STOPPING = 3,
    HTP_N3N_STOPPED = 4,
    HTP_N3N_FAILED = 5,
} htp_n3n_state;

typedef enum {
    HTP_N3N_TRANSPORT_UDP_P2P = 0,
    HTP_N3N_TRANSPORT_UDP_RELAY = 1,
    HTP_N3N_TRANSPORT_TCP_RELAY = 2,
} htp_n3n_transport;

typedef enum {
    HTP_N3N_PEER_PATH_UNKNOWN = 0,
    HTP_N3N_PEER_PATH_P2P = 1,
    HTP_N3N_PEER_PATH_RELAY = 2,
} htp_n3n_peer_path;

typedef struct {
    const char *supernode;
    const char *community;
    const char *key;
    const char *local_ipv4;
    const char *peer_ipv4;
    uint8_t prefix_length;
    uint16_t mtu;
    htp_n3n_transport transport;
} htp_n3n_config;

typedef void (*htp_n3n_state_callback)(void *context, htp_n3n_state state, const char *detail);
typedef int (*htp_n3n_protect_socket_callback)(void *context, int socket_fd);

typedef struct {
    void *context;
    htp_n3n_state_callback state_changed;
    htp_n3n_protect_socket_callback protect_socket;
} htp_n3n_callbacks;

htp_n3n_edge *htp_n3n_create(const htp_n3n_config *config, const htp_n3n_callbacks *callbacks);
int htp_n3n_start(htp_n3n_edge *edge);
int htp_n3n_send_ip_packet(htp_n3n_edge *edge, const uint8_t *packet, size_t packet_length);
int htp_n3n_receive_ip_packet(
    htp_n3n_edge *edge,
    uint8_t *packet,
    size_t packet_capacity,
    size_t *packet_length,
    int timeout_ms);
int htp_n3n_resolve_peer(htp_n3n_edge *edge, const char *peer_ipv4, int timeout_ms);
htp_n3n_state htp_n3n_get_state(const htp_n3n_edge *edge);
htp_n3n_peer_path htp_n3n_get_peer_path(const htp_n3n_edge *edge);
void htp_n3n_stop(htp_n3n_edge *edge);
void htp_n3n_destroy(htp_n3n_edge *edge);
const char *htp_n3n_version(void);

#ifdef __cplusplus
}
#endif

#endif
