/*********************************************************/
/*    Autori:                                            */
/*            Pelosi Giovanni, 346787, pelosi            */
/*            Pesce  Agatino,  456868, pesce             */
/*                                                       */
/*  Progetto: Sistemi 2: biblioteca                      */
/*  Data Pr.: 9/2/96                                     */
/*      File: socket.h                                   */
/*                                                       */
/*********************************************************/

#ifndef _SOCKET_H
#define _SOCKET_H

#include "system.h"
#include "libro.h"
#include "message.h"

#define TRUE 1
#define FALSE 0

/************************************/
/*** stato interazione con socket ***/
/************************************/

typedef enum SocketType_tag
  {
    SockTypeUnknown                 = '0',     /* socket non identificata (dopo accept) */
	 SockTypeClient                          = '1',        /* socket di tipo client */
	 SockTypeServer                          = '2',        /* socket di tipo server (risposta) */
    SockTypeControl                 = '3',     /* socket di controllo per collegamento iniziale */
	 SockTypeListen                          = '4'        /* socket di listen  */

  } SocketType_t;

typedef      enum SocketControl_tag
  {
	 SockCtrlNone                    = '0',     /* socket non client */
	 SockCtrlLocalServer     = '1',          /* socket in ricerca locale */
	 SockCtrlNextServer      = '2',     /* socket scansione server */
	 SockCtrlContinue                = '3'      /* socket trattamento risposta server */

  } SocketControl_t;

typedef    enum SocketState_tag
  {
	 SockStateIdle                           = '0',        /* stato iniziale di socked accepted */
	 SockStateWaitRead                       = '1',        /* inizio lettura messaggio */
    SockStateReading                        = '2',        /* continuazione lettura messaggio */
	 SockStateWriting                        = '3'         /* scrittura in corso */

  } SocketState_t;


typedef   struct SocketInfo_tag
{
  SocketType_t            Type;           /* stato connessione (req_state) */
  SocketState_t           State;                  /* stato connessione (req_state) */
  SocketControl_t         Control;                /* stato richiesta (se client) */
  int                                     Request;          /* indice scansione server */
  long                                    Offset;           /* Offset ricerca su file  */
  int                                     Linked;           /* socket client (per richieste da server) */
  int                                     NoForward;          /* flag per inoltro ad altri server */
  Libro_t                         Libro;            /* struttura dati query/riposte */
  int                                     Len;                  /* lunghezza messaggio  */
  int                                     ToRead;               /* numero bytes letti  */
  int                                     ToWrite;              /* numero bytes scritti */
  MessageText_t           Text;                   /* buffer messaggio (padded) */

} SocketInfo_t;


/**********************/
/*** tabella server ***/
/**********************/

typedef   enum HostState_tag
  {
	 HostStateNone                           = '0',
	 HostStateConnectable            = '1',
	 HostStateConnected              = '2',
	 HostStateAccepted                       = '3'

  } HostState_t;

typedef      struct HostInfo_tag
{
  int                                             Inactive;   /* flag annullamento host */
  HostState_t                             State;     /* nome descrittivo biblioteca */
  Biblio_t                                        Biblio;         /* nome descrittivo biblioteca */
  int                                             Socket;     /* socket (connected/accepted)  */
  struct sockaddr_in      Peer;       /* host:port peer se accepted  */

} HostInfo_t;

/*
 * Stampa a video una socket
 */
void DumpSocket(int Sock);

int  CreateSocket(void);
int  CreateConnectSocket(void);        /*usata per connettersi a server*/
int  CreateAcceptedSocket(int Socket);    /*usata per client o nouvi server (inizio)*/
void DestroySocket(int Socket);
int  AddAcceptedPeer(int Socket, struct sockaddr_in * Sin);
int  AddRemoteHost(char * Host, char * Port);

int  PassiveSocket(int Port, int Qlen);

SocketInfo_t*      RetrieveSockInfo(int Socket);
HostInfo_t*        RetrieveHostInfo(int Host);
int                GetHostCount(void);


int InitSocket(void);
int ExitSocket(void);
void LoadSelectFds(void);
int GetFdSetSize(void);

#ifdef __HPUX_D__
struct fd_set* GetActiveWriteFds(void);
struct fd_set* GetActiveReadFds(void);
struct fd_set* GetSelectWriteFds(void);
struct fd_set* GetSelectReadFds(void);
#else
fd_set* GetActiveWriteFds(void);
fd_set* GetActiveReadFds(void);
fd_set* GetSelectWriteFds(void);
fd_set* GetSelectReadFds(void);
#endif

void SetWriteToken(int Socket);
void ResetWriteToken(int Socket);
void SetReadToken(int Socket);
void ResetReadToken(int Socket);

int ActiveSocket(char* Host, char * Port);
int PassiveSocket(int Port, int Qlen);

HostInfo_t * RetrieveHostBySocket(int Socket);
#endif