/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* Copyright (c) 2023-2024 Brett Sheffield <bacs@librecast.net> */

/* sync.h - Librecast data & file syncing API */

#ifndef _LC_SYNC_H
#define _LC_SYNC_H 1

#include <librecast/types.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

#define NET_LOOPBACK 1
#define SYNC_SEND_THREADS 1

enum {
	/* flags for lc_sync functions */
	SYNC_NONE      = 0x00000000,
	SYNC_LOOPBACK  = 0x00000001, /* set multicast loopback on */
	SYNC_SUBDIR    = 0x00000002, /* create subdirectory within target */
	SYNC_OWNER     = 0x00000004, /* set owner */
	SYNC_GROUP     = 0x00000008, /* set group */
	SYNC_MODE      = 0x00000010, /* set mode */
	SYNC_MTIME     = 0x00000020, /* set mtime */
	SYNC_ATIME     = 0x00000040, /* set atime */
	SYNC_RECURSE   = 0x00000080, /* sync recursively */
};

typedef uint8_t hash_t[HASHSIZE];
typedef struct net_tree_s net_tree_t;
struct net_tree_s {
	uint64_t	size;	/* Total size, in bytes */
	struct timespec	mtime;  /* Time of last modification */
	struct timespec	atime;  /* Time of last access */
	mode_t		mode;	/* File type and mode */
	uid_t		uid;	/* User ID of owner */
	gid_t		gid;	/* Group ID of owner */
	uint16_t	namesz;	/* length of filename */
				/* name is prefixed to tree */
				/* (symlink target replaces tree hashes) */
	uint64_t	pad;
	unsigned char	tree[];	/* tree or directory hashes */
};

/* structure for passing stats from sync functions */
struct lc_stat_s {
	size_t byt_gross;   /* bytes: gross bytes transferred */
	size_t byt_info;    /* bytes: information bytes */
	size_t chunks_tot;  /* total chunks to transfer */
	size_t chunks_io;   /* chunks transferred */
	size_t chunks_fail; /* chunk transfer failures */
	size_t pkts_io;     /* packets in/out */
	size_t sym_origin;  /* original source symbols */
	size_t sym_repair;  /* repair symbols */
};

/* share files in mdex on interface ifx (0 = all interfaces) */
#ifdef HAVE_LIBLCRQ
lc_share_t * lc_share(lc_ctx_t *lctx, mdex_t *mdex, unsigned int ifx, lc_stat_t *stats,
		lc_sync_options_t *opt, int flags);
void lc_unshare(lc_share_t *share);

ssize_t lc_recvdir(lc_ctx_t *lctx, unsigned char *hash, net_tree_t **dir,
		lc_stat_t *stats, lc_sync_options_t *opt, int flags);
ssize_t lc_recvtree(lc_ctx_t *lctx, unsigned char *hash, mtree_t *tree,
		lc_stat_t *stats, lc_sync_options_t *opt, int flags);
ssize_t lc_recvchunk(lc_ctx_t *lctx, unsigned char *hash, void *data, const size_t len,
		lc_stat_t *stats, lc_sync_options_t *opt, int flags);
ssize_t lc_senddir(lc_ctx_t *lctx, unsigned char *hash, net_tree_t *dir,
		lc_stat_t *stats, lc_sync_options_t *opt, int flags);
ssize_t lc_sendtree(lc_ctx_t *lctx, unsigned char *hash, const mtree_t *tree,
		lc_stat_t *stats, lc_sync_options_t *opt, int flags);
ssize_t lc_sendchunk(lc_ctx_t *lctx, unsigned char *hash, const void *data, const size_t len,
		lc_stat_t *stats, lc_sync_options_t *opt, int flags);
#endif

/* local blob/file sync */
int lc_memsync(void *dst, void *src, const size_t n, q_t *q, lc_stat_t *stats,
		lc_sync_options_t *opt, int flags);
int lc_syncfilelocal(const char *dst, char *src, q_t *q, lc_stat_t *stats,
		lc_sync_options_t *opt, int flags);

/* network sync */
#ifdef HAVE_LIBLCRQ
ssize_t lc_sync(lc_ctx_t *lctx, unsigned char *hash, void *data, const size_t len,
		q_t *q, lc_stat_t *stats, lc_sync_options_t *opt, int flags);
ssize_t lc_syncfile(lc_ctx_t *lctx, unsigned char *hash, const char *pathname,
		q_t *q, lc_stat_t *stats, lc_sync_options_t *opt, int flags);
ssize_t lc_syncfile_hash(lc_ctx_t *lctx, char *src, const char *dst,
                q_t *q, lc_stat_t *stats, lc_sync_options_t *opt, int flags);
#endif

/* map local file into memory */
void *lc_mmapfile(const char *pathname, size_t *len, int prot, int flags, off_t offset,
		struct stat *sb);

#endif /* _LC_SYNC_H */
