#ifndef _RPS_DIST_H_
#define _RPS_DIST_H_


#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <regex.h>
#include <stdarg.h>
#include <fcntl.h>

#include <trace.h>
#include <irrd_ops.h>
#include <hdr_comm.h>

extern long SEQUENCE;
extern char * DB_NAME;
extern trace_t *default_trace;
extern char * ENCODING;

#define NONE 0
#define COMMIT 1
#define NORMAL 2
#define LEGACY 3

regex_t trans_sub_begin, resp_auth_type, trans_conf_type, trans_sub_end;
regex_t trans_label, sequence, timestamp, integrity;
regex_t auth_dep;
regex_t rep_sig, signature;
regex_t trans_begin, trans_method;
regex_t trans_request, seq_begin, seq_end;
regex_t trans_resp;
regex_t heartbeat;
regex_t snap_req;
regex_t snap_begin;
regex_t blank_line;

regex_t add_peer, rm_peer, sh_peer;

struct initial_transaction{
  char dbname[100];
  int  ident;
  int  response_type;
  int  confirm_type;
};

struct red_transaction{
  char label[100];
  long sequence;
  char timestamp[50];
};

struct auth_d{
  char * repos;
  long   sequence;
  int    time_stamp;
};


typedef struct peer_rep{
  int fd;
  char * host;
  int port;
  struct peer_rep * next;
  pthread_mutex_t write;
}peer_t;

typedef struct root_l{
  peer_t * first;
  peer_t * last;
}root_t;

root_t peer_list;


char * custom_strcat(int num_strings, ...);
int decapsulate_transaction(int fd);
void time_stamp(int);
int make_heartbeat(peer_t *);
void send_to_peers(char *, int, int);
int parse_transaction(int fd);
void zip_stream(int, int);
void unzip_stream(int, int);
int encapsulate_transaction(int);
int scanning_read(int fd, char * buffer, int buf_size);
int check_timestamp(char * stamp);
void init_regexes(void);
void clear_regexes(void);
int decode_transaction(char * repos, char * method, int fd);
int encode_transaction(int fd, char * method);
int handle_new_submit(int fd, struct initial_transaction * tran);
peer_t * find_peer_obj (root_t * start, char*, int);
peer_t * create_peer_obj (int fd, char * host, int port);
void add_peer_obj (root_t * start, peer_t *obj);
void delete_peer_obj(root_t * start, peer_t * obj);
int confirm_transaction(int, struct initial_transaction * tran);
#endif
