#ifndef DPPFRAG_H
#define DPPFRAG_H

#ifdef USE_LIBDPP

#include <time.h>
#include <easy/utils.h>
#include <easy/if_utils.h>
#include <wifidefs.h>
#include <easy/hlist.h>
#include <stdbool.h>
#include <stdint.h>
#include <timer_impl.h>

struct agent;
struct netif_ap;


#define DPP_GAS_INITIAL_RESP_HEADER_LEN 20
#define DPP_GAS_INITIAL_REQ_HEADER_LEN 19

#ifndef MAC_ADDR_HASH
#define MAC_ADDR_HASH(_a)	(_a[0] ^ _a[1] ^ _a[2] ^ _a[3] ^ _a[4] ^ _a[5])
#endif

#define NUM_FRAGMENTS	128

#define dppfrag_hash(d, s) \
		((MAC_ADDR_HASH(s) ^ (d)) & (NUM_FRAGMENTS - 1))

struct dppfrag_rx {
	uint8_t frametype;
	uint8_t *frame;
	uint16_t framelen;
	uint8_t fid;
	uint8_t id;
	bool lastfrag;
	uint8_t numfrags; /* will only be set on first received fragment */
	uint8_t totfrags;
	uint16_t totlen;
	uint8_t src[6];
	struct dppfrag_rx *next, *last;
	struct timespec tsp;
	atimer_t ageing_timer;
	void *priv;

	struct hlist_node hlist;
};

bool dppfrag_complete(struct agent *a, uint8_t id, uint8_t *src);

uint8_t *dpp_build_gas_initial_response(uint16_t buflen, uint8_t *buf,
					uint16_t status, uint8_t dialogue_token,
					bool fragment, uint16_t *outlen);

uint8_t *dpp_build_gas_comeback_response(uint16_t buflen, uint8_t *buf,
					 uint16_t status, uint8_t dialogue_token,
					 uint8_t id);
int dpp_send_gas_comeback_responses(struct agent *a, struct netif_ap *ap,
				    uint8_t *enrollee, uint8_t *payload,
				    uint16_t len, uint8_t dialog_token);

uint8_t *dppfrag_defrag_payload(struct agent *a, uint8_t hlen,
					      uint8_t dialog_token,
					      uint8_t *src,
					      uint16_t *outlen);


int dppfrag_queue_enqueue(struct agent *a, uint16_t frametype, uint8_t *frame,
			  uint16_t framelen, uint8_t fragbyte, uint8_t id,
			  uint8_t *src);

#endif
#endif