struct packet {
	char priority;
	char type;
	uint32_t sequence;
	uint32_t length;
	uint8_t  *payload;
	struct sockaddr_in source;
	struct sockaddr_in destination;
	/* "extra" info that is never put on a stream: */
	void * info;
	char *dot_addr;
};


struct packet_q_wrapper {
	struct packet *packet;
	struct packet_q_wrapper *next;
	struct packet_q_wrapper *prev;
	/* add extra info here: */
	double time; 
	int reset_count;
};

struct packet_q {
	/*struct packet *first;
	struct packet *last;*/
	struct packet_q_wrapper *w_first;
	struct packet_q_wrapper *w_last;
	struct packet_q_wrapper *w_iter_current;
	struct packet_q_wrapper *w_iter_next;
	struct packet *current;
	double current_time;
	int current_resets;
	int length;
};

void packet_q_new(struct packet_q* packet_q);
void packet_q_enqueue(struct packet_q* packet_q, struct packet* packet);

/* side effect of add_by_sequence: the iterator is reset */
void packet_q_add_by_sequence(struct packet_q* packet_q, struct packet *packet); 

/*void packet_q_dequeue(struct packet_q* packet_q, struct packet* packet);*/
void packet_q_reset_iter(struct packet_q* packet_q);
void packet_q_remove_current(struct packet_q* packet_q);
struct packet* packet_q_next(struct packet_q* packet_q);


int Socket(int domain, int type, int protocol);
int Bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);
int Sendto(int s, void *buf, size_t len, int flags, 
		struct sockaddr *to, socklen_t tolen);
ssize_t Recvfrom(int s, void *buf, size_t len, int flags,
				struct sockaddr *from, socklen_t *fromlen);
FILE *Fopen(char *path, char *mode);
ssize_t Write(int fd, const void *buf, size_t count);

double get_time();

void error(char *message);
uint8_t* packet_to_buffer(struct packet *packet, unsigned int *packet_size);
struct packet* buffer_to_packet(uint8_t *);

void packet_send(int sockfd, struct packet* packet);

struct packet* packet_receive(int sockfd);

void print_packet(struct packet* packet);
void print_sockaddr(struct sockaddr_in* a);


unsigned int options_parse_port();
void str_to_sockaddr_in(struct sockaddr_in *addr, const char *s);


uint8_t* packet_to_buffer(struct packet *packet, unsigned int *packet_size);
struct packet* buffer_to_packet(uint8_t *);

