/*
 *  OsmoGGSN - Gateway GPRS Support Node
 *  Copyright (C) 2002 Mondru AB.
 *
 *  The contents of this file may be used under the terms of the GNU
 *  General Public License Version 2, provided that the above copyright
 *  notice and this permission notice is included in all copies or
 *  substantial portions of the software.
 *
 */

/*
 * Queue.c
 * Reliable delivery of signalling messages
 */

#ifndef _QUEUE_H
#define _QUEUE_H

#include <osmocom/core/linuxlist.h>

#include "gtp.h"

#define QUEUE_DEBUG 0		/* Print debug information */

#define QUEUE_SIZE (PDP_MAX*2)	/* Size of retransmission queue */
#define QUEUE_HASH_SIZE 65536	/* Size of hash table (2^16) */

struct qmsg_t {			/* Holder for queued packets */
	int state;		/* 0=empty, 1=full */
	uint16_t seq;		/* The sequence number */
	uint8_t type;		/* The type of packet */
	void *cbp;		/* Application specific pointer */
	union gtp_packet p;	/* The packet stored */
	int l;			/* Length of the packet */
	int fd;			/* Socket packet was sent to / received from */
	struct sockaddr_in peer;	/* Address packet was sent to / received from */
	struct qmsg_t *seqnext;	/* Pointer to next in sequence hash list */
	int next;		/* Pointer to the next in queue. -1: Last */
	int prev;		/* Pointer to the previous in queue. -1: First */
	int this;		/* Pointer to myself */
	time_t timeout;		/* When do we retransmit this packet? */
	int retrans;		/* How many times did we retransmit this? */
	struct llist_head entry; /* Listed with other qmsg_t belonging to a pdp_t->qmsg_list_req */
};

struct queue_t {
	struct qmsg_t qmsga[QUEUE_SIZE];	/* Array holding signalling messages */
	void *hashseq[QUEUE_HASH_SIZE];	/* Hash array */
	int next;		/* Next location in queue to use */
	int first;		/* First packet in queue (oldest timeout) */
	int last;		/* Last packet in queue (youngest timeout) */
};

/*  Allocates and initialises new queue structure */
int queue_new(struct queue_t **queue);
/*  Deallocates queue structure */
int queue_free(struct queue_t *queue);
/* Find a new queue element. Return EOF if allready full */
int queue_newmsg(struct queue_t *queue, struct qmsg_t **qmsg,
		 struct sockaddr_in *peer, uint16_t seq);
/* Remove an element from the queue. */
int queue_freemsg(struct queue_t *queue, struct qmsg_t *qmsg);
/* Move an element to the back of the queue */
int queue_back(struct queue_t *queue, struct qmsg_t *qmsg);
/* Get the first element in the queue (oldest) */
int queue_getfirst(struct queue_t *queue, struct qmsg_t **qmsg);
/* Get the element with a particular sequence number */
int queue_seqget(struct queue_t *queue, struct qmsg_t **qmsg,
		 struct sockaddr_in *peer, uint16_t seq);
/* Free message based on sequence number */
int queue_freemsg_seq(struct queue_t *queue, struct sockaddr_in *peer,
		      uint16_t seq, uint8_t * type, void **cbp);

#endif /* !_QUEUE_H */
