/* Copyright (c) 2020-2021 The Creators of Simphone

   See the file COPYING.LESSER.txt for copying permission.
*/

#ifndef _MAINLINE_H_
#define _MAINLINE_H_

#include "simtypes.h"

#define MAIN_DHT_STOPPED (-3)    /* not initialized */
#define MAIN_DHT_DISCONNECT (-2) /* not working (yet) */
#define MAIN_DHT_CONNECTING (-1) /* trying to connect */
#define MAIN_DHT_CONNECTED 0     /* firewalled */
#define MAIN_DHT_LISTENING 1     /* incoming connectivity */

/* return the number of good, dubious, incoming and blocked/blacklisted DHT nodes. return value is MAIN_DHT_xxx */
int main_get_nodes (int *good, int *dubious, int *incoming, int *blocked, int *blacklisted);
#define main_get_status() main_get_nodes (NULL, NULL, NULL, NULL, NULL)

/* return UDP statistic. i is CONTACT_STATS_xxx, j is CONTACT_STAT_xxx */
simnumber main_get_stat (unsigned i, unsigned j);

/* set or unset proxy verification deadline */
void main_set_tick (simbool set);

/* change DHT socket and port */
int main_set_port (int fd, int port);

/* set a counter into an ip address table. consumes key */
void sim_set_table_number (simtype *table, simtype key, simnumber number);

/* return used cpu cycles in milliseconds, and start counting them again */
simnumber main_cputime_get (void);

/* add used cpu cycles. return blacklist milliseconds or zero if no blacklisting took place */
int main_cputime_test (simunsigned cpu, unsigned ip, simunsigned tick, unsigned factor);

#define MAIN_MODE_PASSIVE 4 /* mode (alpha and beta value) for main_search_start */
#define MAIN_MODE_ACTIVE 0  /* use main.dht.alpha and main.dht.beta */

int main_search_create (const char *address, unsigned sequence, int mode, int restart);

#define MAIN_SEARCH_SKIP (-2) /* cannot announce any more */
#define MAIN_SEARCH_OLD (-1)  /* search was already running */
#define MAIN_SEARCH_FAILED 0  /* DHT search table is full */
#define MAIN_SEARCH_NEW 1     /* search has started now */
#define MAIN_SEARCH_NONE 2    /* only used by sim_contact_search_ */

/* start searching the DHT for a DHT id; each search is identified by its sequence number. return MAIN_SEARCH_xxx */
#define main_search_start(address, sequence, mode) main_search_create (address, sequence, mode, 0)

#define MAIN_CANCEL_DENOUNCE (-1) /* stop searching AND announcing */
#define MAIN_CANCEL_CHECK 0       /* check if search is running */
#define MAIN_CANCEL_STOP 1        /* stop searching unless announcing */

/* stop searching the DHT for a contact */
simbool main_search_cancel (const char *address, unsigned sequence, int cancel);
#define main_search_stop(address) main_search_cancel (address, 0, MAIN_CANCEL_STOP)
#define main_search_denounce(address) main_search_cancel (address, 0, MAIN_CANCEL_DENOUNCE)
/* check if the specified search is still in progress */
#define main_search_test(address, sequence) main_search_cancel (address, sequence, MAIN_CANCEL_CHECK)

/* process a valid DHT packet. arguments are the same as for dht_periodic from dht.h but in different order */
void main_recv_udp (void *tosleep, const simbyte *input, int length, const void *sin, int sinlen);

/* load the mainline file (saved list of DHT nodes) */
int main_dht_load (simtype *mainline);

/* announce myself to DHT immediately */
void main_dht_logon (void);

/* connect to mainline DHT */
void main_reinit (void); /* change node id */
int main_init (simbool init);

/* disconnect from mainline DHT */
int main_exit (void);
int main_uninit_ (void);

/* check if a UDP packet is a valid DHT packet */
#define MAIN_CHECK_PACKET(input) ((input)[0] == 'd' && (input)[2] == ':' && (input)[1] >= '1' && (input)[1] <= '9')

/* table keys in mainline file */
#define MAIN_KEY_NODES "nodes"         /* good DHT nodes */
#define MAIN_KEY_TORRENTS "torrents"   /* torrent DHT nodes that were already added to MAIN_KEY_NODES */
#define MAIN_KEY_BLACKLIST "blacklist" /* blacklisted ip addresses and their search identifiers */

/* debug logging */
void main_log_searches (const char *module, int level);
void main_log_dht (const char *module, int level);

#endif
