/*********************************************************/ /* Autori: */ /* Pelosi Giovanni, 346787, pelosi */ /* Pesce Agatino, 456868, pesce */ /* */ /* Progetto: Sistemi 2: biblioteca */ /* Data Pr.: 9/2/96 */ /* File: message.c */ /* */ /*********************************************************/ #include <string.h> #include <assert.h> #include <signal.h> #include "system.h" #include "message.h" #include "socket.h" #ifdef __cplusplus typedef void (*fptr)(int); #else typedef void (*fptr)(); #endif static int _sigpipe = 0; /* ************************************************************************ * * handler per sigpipe in caso di write su socket chiusa * ************************************************************************ */ void SigPipeHandler(int sig) { sig ++; /* causa compilatore idiota*/ signal(SIGPIPE,(fptr) SigPipeHandler); _sigpipe ++; return; } /* ************************************************************************ * * funzioni comuni per trattamento struttura libro in messaggi * ************************************************************************ */ int SizeRawLibro(void) { int size=0; Libro_t Libro; /* Orribile, casomai ripensarci */ size += sizeof(Libro.Titolo); size += sizeof(Libro.Autore); size += sizeof(Libro.Anno); return size; } int PutRawLibro(char* t, Libro_t* Libro) { char *p = t; strncpy(p, Libro->Titolo, sizeof(Libro->Titolo)); p += sizeof(Libro->Titolo); strncpy(p, Libro->Autore, sizeof(Libro->Autore)); p += sizeof(Libro->Autore); strncpy(p, Libro->Anno, sizeof(Libro->Anno)); p += sizeof(Libro->Anno); return (int)(p - t); } int GetRawLibro(Libro_t* Libro, char* t) { char *p = t; strncpy(Libro->Titolo, p, sizeof(Libro->Titolo)); p += sizeof(Libro->Titolo); strncpy(Libro->Autore, p, sizeof(Libro->Autore)); p += sizeof(Libro->Autore); strncpy(Libro->Anno, p, sizeof(Libro->Anno)); p += sizeof(Libro->Anno); return (int)(p - t); } /* ************************************************************************ * * funzioni trattamento messaggi "control" * ************************************************************************ */ int SizeMsgControl(void) { int size=0; size++; /* Type */ size+=sizeof(struct in_addr); size+=sizeof(unsigned short); return size; } int GetMsgControl(MessageControl_t* Msg ,char* t) { char *p = t; memcpy(&Msg->Sin.sin_addr, p, sizeof(struct in_addr)); p+=sizeof(struct in_addr); memcpy(&Msg->Sin.sin_port, p, sizeof(unsigned short)); p+=sizeof(unsigned short); return (int)(p - t); } int PutMsgControl(int Socket, struct sockaddr_in * Sin) { SocketInfo_t* Info=RetrieveSockInfo(Socket); char *p = Info->Text; memset(Info->Text,0,sizeof(MessageText_t)); *p = MsgTypeControl; p++; memcpy(p, &Sin->sin_addr, sizeof(struct in_addr)); p+=sizeof(struct in_addr); memcpy(p, &Sin->sin_port, sizeof(unsigned short)); p+=sizeof(unsigned short); Info->Len = Info->ToWrite = (int)(p - Info->Text); return Info->Len; } /* ************************************************************************ * * funzioni trattamento messaggi "query" * ************************************************************************ */ int SizeMsgQuery(void) { int size=0; size++; /*Type*/ size++; /*NoForward*/ size+=SizeRawLibro(); return size; } int ClPutMsgQuery(MessageText_t Text, char NoForward, Libro_t* Libro) { char *p = Text; memset(Text,0,sizeof(MessageText_t)); *p = MsgTypeQuery; p++; *p = NoForward; p++; p += PutRawLibro(p,Libro); return (int)(p - Text); } int PutMsgQuery(int Socket, char NoForward, Libro_t* Libro) { SocketInfo_t* Info=RetrieveSockInfo(Socket); Info->Len = Info->ToWrite = ClPutMsgQuery(Info->Text, NoForward, Libro); return Info->Len; } int GetMsgQuery(MessageQuery_t* Msg, char* t) { char *p = t; Msg->NoForward = *p; p++; p += GetRawLibro(&Msg->Libro,p); return (int)(p - t); } /* ************************************************************************ * * funzioni trattamento messaggi "replay" * ************************************************************************ */ int SizeMsgReply(void) { int size=0; size++; /*Type*/ size += sizeof(Biblio_t); size += SizeRawLibro(); return size; } int PutMsgReply(int Socket, Biblio_t Biblio, Libro_t* Libro) { SocketInfo_t* Info=RetrieveSockInfo(Socket); char *p = Info->Text; memset(Info->Text,0,sizeof(MessageText_t)); *p = MsgTypeReply; p++; strncpy(p,(char*) Biblio, sizeof(Biblio_t)); p += sizeof(Biblio_t); p += PutRawLibro(p,Libro); Info->Len = Info->ToWrite = (int)(p - Info->Text); return Info->Len; } int ClGetMsgReply(MessageReply_t* Msg, char* t) { char *p = t; memset(Msg, 0, sizeof(MessageReply_t)); strncpy(Msg->Biblio,p, sizeof(Biblio_t)); p += sizeof(Biblio_t); p += GetRawLibro(&Msg->Libro,p); return (int)(p - t); } int GetMsgReply(MessageReply_t* Msg, char* t) { return ClGetMsgReply(Msg, t); } /* ************************************************************************ * * funzioni per impostazione ciclo nullo di ritorno select() * ************************************************************************ */ int PutMsgNil(int Socket) { SocketInfo_t* Info=RetrieveSockInfo(Socket); Info->Len= Info->ToWrite = 0; return 0; } /* ************************************************************************ * * funzioni generale per lettura messaggi da socket in buffer * ************************************************************************ */ /* restituisce: * -1 su errore o eof * 0 su messaggio non ancora completato * 1 su messaggio completato */ int ReadMessage( int Socket, Message_t* Msg ) { int n; SocketInfo_t* Info = RetrieveSockInfo(Socket); char *p=Info->Text; p++; memset(Msg,0,sizeof(Message_t)); assert(Info->State==SockStateReading || Info->State==SockStateWaitRead); n = read(Socket, &Info->Text[Info->Len - Info->ToRead], Info->ToRead ); if ( n < 0 ) /* if (n < 0) --> (err) */ { Msg->Type = MsgTypeError; return -1; /*valutare utilizzo rc type/len*/ } if ( n == 0 ) /* if (n == 0) --> (eof) */ { if (Info->Len == Info->ToRead) Msg->Type = MsgTypeEof; else Msg->Type = MsgTypeError; return -1; /*valutare utilizzo rc type/len*/ } Info->ToRead -= n; switch(Info->Text[0]) { case MsgTypeQuery: Msg->Type = MsgTypeQuery; break; case MsgTypeReply: Msg->Type = MsgTypeReply; break; case MsgTypeControl: Msg->Type = MsgTypeControl; break; default: Msg->Type = MsgTypeError; return -1; } if(Info->State==SockStateWaitRead) { Info->State = SockStateReading; Info->Len = MessageLen(Msg->Type); Info->ToRead = Info->Len - 1; } if ( Info->ToRead > 0 ) return 0; switch (Msg->Type) { case MsgTypeQuery: GetMsgQuery(&Msg->Body.Query,p); return 1; case MsgTypeReply: GetMsgReply(&Msg->Body.Reply,p); return 1; case MsgTypeControl: GetMsgControl(&Msg->Body.Control,p); return 1; default: /* per casi strani tipo errore formato messaggio */ Msg->Type = MsgTypeError; return -1; } } /* ************************************************************************ * * funzioni generale per scrittura messaggi a socket da buffer * ************************************************************************ */ /* * restituisce: * -1 su errore o eof * 0 su messaggio non ancora completato * 1 su messaggio completato */ int WriteMessage( int Socket ) { int n; /* n.bytes letti */ SocketInfo_t * Info = RetrieveSockInfo(Socket); assert(Info->State==SockStateWriting); if( Info->ToWrite == 0 ) /* per i casi in cui la write serve solo a */ return 1; /* dare il via alla read */ signal(SIGPIPE,(fptr)SigPipeHandler); _sigpipe = 0; n = write(Socket, &Info->Text[Info->Len - Info->ToWrite], Info->ToWrite ); signal(SIGPIPE,SIG_DFL); if ( _sigpipe !=0 ) return -1; if ( n <= 0 ) /* if (n < 0) --> (err) */ return -1; /* errore perche non EWOULDBLOCK da select*/ Info->ToWrite -= n; if ( Info->ToWrite > 0 ) return 0; /* incompleta -> continue */ return 1; /**End of Write*/ } /* ************************************************************************ * * funzioni generale per determinare lunghezza messaggio * ************************************************************************ */ int MessageLen(int Type) { switch(Type) { case MsgTypeQuery: return SizeMsgQuery(); case MsgTypeReply: return SizeMsgReply(); case MsgTypeControl: return SizeMsgControl(); } return -1; }