/*
    Tucnak - VHF contest log
    Copyright (C) 2011-2023 Ladislav Vaiz <ok1zia@nagano.cz>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

*/

#ifndef __NET_H
#define __NET_H

#define LO_CW   0x01
#define LO_NAME 0x02
#define LO_QRV  0x04
#define LO_DEF  0x08

#define C0(item) (item?item:"")
#define PEER_FUNC void(*)(void)

struct qso;
union zsockaddr;

extern struct net *gnet;

enum net_state {
    NS_INIT=0,
    NS_CONNECTING,
    NS_CONNECTED,
    NS_WAIT_ACK,
    NS_DISCONNECTED,
    NS_DEAD,  /* conn removed immediately */
	NS_LONG
};

extern char *ns_desc[];

enum authstate{
    AS_NOTNEEDED = 0,
    AS_WAIT,
    AS_OK
};

struct conn{
    struct sockaddr_in sin;   /* {sin_port, sin_addr.s_addr } */
    int sock;
    enum net_state state;
    GString *wrbuf, *rdbuf;
    int relseq;
    int timer;
    gchar *remote_id;
    gchar *remote_ac;
    gchar *operator_;
    gchar *rwbands;
    int is_same_ctest;
    int replicating;     /* replicating from other station in progress, huge amout of QSOs */
	enum authstate authstate;
    char *salt;
	time_t start;
	long rx, tx;
	char *fid;
};

struct net{
    struct sockaddr_in my; /* IP of first interface (except lo) in alphab. order. host byteorder */
    gchar *myid; /* 0.0.0.0:0 or 192.168.1.97:55555 */
    struct sockaddr_in global; /* global master */
    time_t global_expire;
	int global_priority;
	int master_priority;
    int udpsock;   /* listen for announcement, -1 unused */
    int tcpsock;   /* listen for slaves, -1 unused */
    int udptimer_id;
    int udptimer_period;
    struct sockaddr bcast_addr[MAX_INTERFACES];
    int max_addrs;

    struct conn *master;
    GPtrArray *peers; /* struct conn[] */
    gchar *allpeers;  /* separated by semicolon */
    gchar *rwbpeers; /* separated by semicolon. ID;OP;RWB */
    gchar *bpeers;    /* separated by semicolon. ID;OP;B */
    void (*peerfunc)(void); /* todo */
	GString *peers3;
	int timer3_id;

	struct conn *remote;
	struct zasyncdns *radns;
    int v3compatibility;  /* set if heard broadcast without priority. 
                             to guess master, compare only IP and port */
};

struct net *init_net(void);
void free_net(struct net *net);

int init_net_udp (struct net *net);
int init_net_tcp (struct net *net);
int init_net_ifaces(struct net *net, int free_global);
void free_net_udp(struct net *net);
void free_net_tcp(struct net *net);
void free_net_ifaces(struct net *net);
void free_conn(struct conn *conn);

void udp_read_handler(void *);
void udp_exception_handler(void *);
void udp_timer(void *);
void udp_sendto(struct sockaddr_in *asin, int direct);

#ifdef LEAK_DEBUG_LIST
void debug_tcp_disconnect(char *file, int line, struct conn *conn);
#define tcp_disconnect(a) debug_tcp_disconnect(__FILE__, __LINE__, (a))
#else
void tcp_disconnect(struct conn *conn);
#endif

void tcp_read_handler(void *);
void tcp_write_handler(void *);
void tcp_exception_handler(void *);
void tcp_accept_handler(void *);

void rel_write(struct conn *conn, gchar *s);
void rel_write_all(gchar *s);
void rel_read(struct conn *conn, gchar *s);

void tcp_set_state(struct conn *conn, enum net_state state);

void tcp_connect(struct conn *conn);
void tcp_kill(struct conn *conn);
int cmp_sin(struct sockaddr_in *a, struct sockaddr_in *b);
int cmp_master(int pria, int prib, struct sockaddr_in *a, struct sockaddr_in *b);
void net_send_id(void);
void net_send_ac(void);
void net_send_operator(void);
void net_send_read_write_bands(void);
void net_send_talk(void);
void net_test_same_contest(struct conn *conn, gchar *ac_text);
void compare_remote_with_me(gpointer key, gpointer value, gpointer data);
void qso_from_net(struct conn *conn, gchar *c);
void replicate_qso(struct conn *conn, struct qso *q);
gchar *get_timer_str(struct conn *conn);
void send_config_request(int no);
void send_cwdb_request(int no);
int conn_prod_state(struct conn *conn);
int some_replicating(struct net *net);
struct conn *find_conn_by_remote_id(gchar *remote_id);
void remove_conn_timer(void *arg);
char *tcp_state_s(struct conn *conn);

void iface_info(GString *gs);
void net_connect_remote(struct net *);
void net_remote_addrinfo(struct zasyncdns *adns, int n, int *family, int *socktype, int *protocol, int *addrlen, union zsockaddr *addr, char *errorstr);

void conn_set_fid(struct conn *conn);



#endif
