From 00233de9384c81e313fb8f9bd8480f08d3e3f9e2 Mon Sep 17 00:00:00 2001 From: Christian Ohlsson Date: Thu, 5 Mar 2026 13:37:25 +0100 Subject: [PATCH] Startpunkten --- body.c | 45 ++ ftp_app | Bin 0 -> 35931 bytes ftp_app.c | 362 ++++++++++ ftp_layer.c | 364 ++++++++++ header_ftp.h | 29 + link.cpp | 689 ++++++++++++++++++ link.h | 52 ++ link_signal.h | 48 ++ physerr.log | 3 + physlayer.c | 1886 +++++++++++++++++++++++++++++++++++++++++++++++++ physlayer.h | 96 +++ signal_prim.h | 48 ++ socketio.h | 94 +++ sockets.h | 132 ++++ state.h | 12 + student.h | 145 ++++ studlib.a | Bin 0 -> 15642 bytes systems.h | 91 +++ udefs.h | 236 +++++++ unixsockets.h | 90 +++ uselect.h | 103 +++ utimer.h | 88 +++ 22 files changed, 4613 insertions(+) create mode 100644 body.c create mode 100644 ftp_app create mode 100644 ftp_app.c create mode 100644 ftp_layer.c create mode 100644 header_ftp.h create mode 100644 link.cpp create mode 100644 link.h create mode 100644 link_signal.h create mode 100644 physerr.log create mode 100644 physlayer.c create mode 100644 physlayer.h create mode 100644 signal_prim.h create mode 100644 socketio.h create mode 100644 sockets.h create mode 100644 state.h create mode 100644 student.h create mode 100644 studlib.a create mode 100644 systems.h create mode 100644 udefs.h create mode 100644 unixsockets.h create mode 100644 uselect.h create mode 100644 utimer.h diff --git a/body.c b/body.c new file mode 100644 index 0000000..5ab839f --- /dev/null +++ b/body.c @@ -0,0 +1,45 @@ +#include "student.h" + +#define PATH ".phys_socket" +#define LPATH ".link_socket" + +int PSOCK_FD, LSOCK_FD; + +void do_something(void) +{ + PollSOcket(LSOCK_FD, PSOCK_FD, NULL); +} + +void main(int argc, char *argv[]) +{ + int tmp_fd1; + + if((LSOCK_FD = CreateUnixClientSocket(LPATH)) < 0) + { + fprintf(stderr, "Can't create unix client socket\n"); + exit(1); + } + + if((tmp_fd1 = CreateUnixServerSocket(PATH) < 0) + { + fprintf(stderr, "Can't create unix server socket\n"); + exit(1); + } + + switch(fork()) + { + case -1: fprintf(stderr, "Fork failed\n"); + case 0: close(PSOCK_FD); + close(LSOCK_FD); + execv("./physical_layer", argv); + exit(1); + default: if((PSOCK_FD = AcceptConnection(tmp_fd1)) < 0 + { + fprintf(stderr, "Can't accept unix client signal socket\n"); + exit(1); + } + + do_something(); + exit(1); + } +} diff --git a/ftp_app b/ftp_app new file mode 100644 index 0000000000000000000000000000000000000000..b43d9246307713393c337885de6c731aa90416b7 GIT binary patch literal 35931 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 literal 0 HcmV?d00001 diff --git a/ftp_app.c b/ftp_app.c new file mode 100644 index 0000000..5e7f546 --- /dev/null +++ b/ftp_app.c @@ -0,0 +1,362 @@ +/*================================================================ + LAB I DATAKOMMUNIKATION + FTP_APPLICATION + Stefan Sonesson + Christian Ohlsson + Karlstad 981215 +-----------------------------------------------------------------*/ +#include "header_ftp.h" +#include "signal_prim.h" +#include "state.h" +#include "student.h" +/*================================================================ + meny() + Skriver ut menyn på skärmen + pre : none + post : Menyn är utskriven + calls: none +-----------------------------------------------------------------*/ +void meny() +{ + printf ("Meny\n"); + printf ("====\n"); + printf("1. Send a file\n"); + printf("2. Quit\n"); +} +/*================================================================ + sendIt() + Skickar en data request, filstorleken (som long), filnamn + samt själva datan till ftp-layer så länge som + det finns tecken i bufferten. + pre : Filen finns + post : Filen är skickad + calls: WriteDatatoSocket, WriteSignaltoSocket +-----------------------------------------------------------------*/ +void sendIt(long fileSize, char *fileName, int fd) +{ + char buffer[BUFSIZE]; + int len; + + printf("FileSize: %d\n", fileSize); + len = strlen(fileName)+1; + WriteSignaltoSocket(FSOCK_FD, AF_Data_Req, SIGLEN); + WriteDatatoSocket(FSOCK_FD, (char *)&len, sizeof(long)); + WriteDatatoSocket(FSOCK_FD, fileName, len); + while(fileSize > 0){ + if((len = read(fd, buffer, BUFSIZE)) == -1){ + fprintf(stderr, "Can't read from file\n"); + return; + } + WriteSignaltoSocket(FSOCK_FD, AF_Data_Req, SIGLEN); + WriteDatatoSocket(FSOCK_FD, (char *)&len, sizeof(long)); + WriteDatatoSocket(FSOCK_FD, buffer, len); + fileSize -= len; + } + close(fd); +} +/*================================================================ + sendFile() + Ber användaren mata in ett filnamn som skall skickas + och ser om filen är öppningsbar. Om filen är + öppningsbar anropas sendIt. + pre : none + post : Filen är öppnad och filstorleken känd + calls: sendIt +-----------------------------------------------------------------*/ +void sendFile() +{ + int toSend; + long fileSize; + char fileName[FNSIZE]; + struct stat st; + + printf("Skriv in filnamn: \n"); + gets(fileName); /*Mata in filnamn*/ + if((toSend = open(fileName, 0)) == -1){ /*Går filen att öppna?*/ + printf("Unable to open file %s\n", fileName); + return; + } + fstat(toSend, &st); /*Hämta filstorleken*/ + fileSize = st.st_size; + sendIt(fileSize, fileName, toSend); +} +/*================================================================ + menu() + Ber användaren mata in vilken operation som skall utföras + och returnerar valet (om val = 0 avslutas programmet). + pre : none + post : Menyvalet är gjort + calls: Beror på menyvalet +-----------------------------------------------------------------*/ + int menu() +{ + char val; + + do{ + meny(); + val=getchar(); /*Mata in menyval*/ + switch(val){ + case '1' : sendFile();break; + case '2' : printf ("Programmet avslutat...\n");break; + default : printf ("Felaktigt val...\n");break; + } + fflush(STDIN); /*Ta bort alla tecken utom det första*/ + }while(val != '1' && val != '2'); + return (val - 2); +} +/*================================================================ + readData() + Öppnar en socket och hämtar filstorlek, och sedan + själva datan, som den skriver till den nya filen. + pre : none + post : Filen är överförd + calls: Polla, ReadDatafromSocket +-----------------------------------------------------------------*/ +int readData(int fd) +{ + int poll, len; + char buffer[BUFSIZE]; + + Polla(FSOCK_FD, FSOCK_FD); /*Hämta filstorlek*/ + ReadDatafromSocket(FSOCK_FD, (char *)&len,sizeof(long)); + Polla(FSOCK_FD, FSOCK_FD); /*Hämta data*/ + ReadDatafromSocket(FSOCK_FD,buffer,len); + return write(fd,buffer,len) == -1; +} +/*================================================================ + Polla() + Genomför en PollSocket och om det gick bra + returneras socket'ens nummer (+1) + pre : + post : En socket är öppnad + calls: Pollsocket +-----------------------------------------------------------------*/ +int Polla(int fd1,int fd2) +{ + int poll; + + poll = PollSocket(fd1, fd2, NULL); /*Öppna en socket*/ + if(poll == -1){ /*Gick det bra?*/ + fprintf(stderr, "PollSocket failed\n"); + exit(4); + } + return poll; /*Returnera socket'ens nummer*/ +} +/*================================================================ + State_IDLE() + Om vi i detta tillstånd får en Connect Indication + läser vi filstorlek samt själva datan från socket'en + pre : none + post : TRUE om vi fick en Connect Indication + calls: Polla, ReadDatafromSocket, WriteSignaltoSocket +-----------------------------------------------------------------*/ +int State_IDLE(int sig, long len, char buffer[BUFSIZE], int fd) +{ + if(sig == AF_Con_Ind) { + Polla(FSOCK_FD, FSOCK_FD); + ReadDatafromSocket(FSOCK_FD, (char *)&len, sizeof(long)); + Polla(FSOCK_FD, FSOCK_FD); + ReadDatafromSocket(FSOCK_FD, buffer, len); + if((fd = open(buffer, O_WRONLY)) == -1) { + printf("Unable to open file.\n"); + WriteSignaltoSocket(FSOCK_FD, AF_Rej_Req, SIGLEN); + return TRUE; + } + else + WriteSignaltoSocket(FSOCK_FD, AF_Con_Resp, SIGLEN); + } + return FALSE; +} +/*================================================================ + State_UUUK() + Känner av om vi får en Connect Confirm, då ropar vi + på sendFile, annars felhantering + pre : none + post : state returnerat + calls: sendFile, WriteSignaltoSocket +-----------------------------------------------------------------*/ +int State_UUUK(int sig) +{ + int state; + + if(sig == AF_Con_Conf){ + state = DATA; + sendFile(); + } + else if(sig == AF_Rej_Ind){ + printf("The other side don't wanna play with you..."); + WriteSignaltoSocket(FSOCK_FD, AF_Rej_Resp, SIGLEN); + state = IDLE; + } + else{ + WriteSignaltoSocket(FSOCK_FD, AF_Abort_Req, SIGLEN); + state = IDLE; + } + return state; +} +/*================================================================ + State_DATA() + Känner av om vi får en data indication och då läser vi + data från socket'en, annars felhantering + pre : none + post : state returnerat + calls: readData, WriteSignaltoSocket +-----------------------------------------------------------------*/ +int State_DATA(int sig, int fd) +{ + int state; + + if(sig == AF_Data_Ind){ + if(readData(fd)) { + WriteSignaltoSocket(FSOCK_FD,AF_Abort_Req,SIGLEN); + printf("Can't write to file\n"); + close(fd); + state = IDLE; + } + } + else if(sig == AF_Disc_Ind){ + close(fd); + WriteSignaltoSocket(FSOCK_FD, AF_Disc_Resp, SIGLEN); + state = IDLE; + } + else{ + WriteSignaltoSocket(FSOCK_FD, AF_Abort_Req, SIGLEN); + close(fd); + state = IDLE; + } + return state; +} +/*================================================================ + State_UUNK() + Känner av om vi får en disconnect confirm och ställer + oss i IDLE, annars felhantering + pre : none + post : state returnerat + calls: WriteSignaltoSocket +-----------------------------------------------------------------*/ +int State_UUNK(int sig) +{ + int state; + + if(sig == AF_Disc_Conf) + state = IDLE; + else{ + WriteSignaltoSocket(FSOCK_FD, AF_Abort_Req, SIGLEN); + state = IDLE; + } + return state; +} +/*================================================================ + State_TERR() + Känner av om vi får en reject confirm och ställer oss + då i IDLE, annars felhantering + pre : none + post : state returnerat + calls: WriteSignaltoSocket +-----------------------------------------------------------------*/ +int State_TERR(int sig) +{ + int state; + + if(sig == AF_Rej_Conf) + state = IDLE; + else{ + WriteSignaltoSocket(FSOCK_FD, AF_Abort_Req, SIGLEN); + state = IDLE; + } + return state; +} +/*================================================================ + do_something() + Ligger hela tiden och känner av vilka signaler + som kommer in från socketen och genomför lämpliga + operationer beroende på insignalen. + pre : + post : none + calls: Polla, WriteSignaltoSocket, ReadSignalfromSocket, + sendFile, ReadDatafromSocket +-----------------------------------------------------------------*/ + void do_something() +{ + int sig, poll, fd, state = IDLE; + long len; + char buffer[BUFSIZE]; + + while(1){ /*Loopa alltid*/ + poll = Polla(STDIN, FSOCK_FD); + if(poll - 1 == STDIN){ + switch(state) + { + case IDLE : /*Tillstånd när inget händer*/ + if(menu()){ + WriteSignaltoSocket(FSOCK_FD, AF_Con_Req, 3); + state = UUUK; + } + else + exit(0); + break; + case DATA : /*Datafas*/ + sendFile(); + default : + fflush(STDIN); + menu(); + } + } + else if(poll - 1 == FSOCK_FD){ + sig = ReadSignalfromSocket(FSOCK_FD, 3); + if(sig == AF_Abort_Ind) + state = IDLE; + else + switch(state) { + case IDLE : /*Tillstånd när inget händer*/ + if(State_IDLE(sig, len, buffer, fd)) + state = DATA; + break; + case UUUK : /*Under utgående uppkoppling*/ + state = State_UUUK(sig); + break; + case DATA : /*Datafas*/ + state = State_DATA(sig, fd); + break; + case UUNK : /*Under utgående nedkoppling*/ + state = State_UUNK(sig); + break; + case TERR : /*Transfer error*/ + state = State_TERR(sig); + break; + default: + printf("Cancel transfer"); + break; + } + } + } +} +/*================================================================ + main() + Skapar en socket och kontrollerar så att socket'en + är redo för dataöverföring + pre : + post : Socket'en är skapad, och data kan överföras + calls: CreateUnixServerSocket, AcceptConnection, do_something +-----------------------------------------------------------------*/ +int main(int argc, char *argv[]) +{ + int tmp_fd1, x; + printf("FTP_APP startad...\n"); + if((tmp_fd1 = CreateUnixServerSocket(S_PATH)) < 0){ + fprintf(stderr, "Can't create Unix Server Signal Socket\n"); + exit(1); + } + printf("FTP_APP har skapat FTP_LAYER Socket...\n"); + switch(fork()) { + case -1: fprintf(stderr, "Fork failed in application\n"); + case 0: close(FSOCK_FD); execv(L_PATH, argv); exit(0); + default: if((FSOCK_FD = AcceptConnection(tmp_fd1)) < 0){ + fprintf(stderr, "Can't accept unix client signal socket\n"); + exit(1); + } + do_something(); + exit(1); + } +} + diff --git a/ftp_layer.c b/ftp_layer.c new file mode 100644 index 0000000..3e74934 --- /dev/null +++ b/ftp_layer.c @@ -0,0 +1,364 @@ +/* FTP-layer av Daniel W och Anders W för datakommunikation-lab! */ + +#include "student.h" +#include "signal_prim.h" + +#define FPATH "./ftp_socket" +#define LPATH "./link_socket" +#define AF 1 /* send AF_Abort_Ind to app with cancel() */ +#define L 0 /* send L_Abort_Req to linker with cancel()*/ +#define IsFTP 0x80 /* set the ID-bit to indicate FTP & !chat */ +#define OPMASK 0x7f /* to mask out the 'operation'-field */ +#define SIGPACKLEN 3 /* lenght of a sigpacket; primitive or PDU */ +#define MAXDATALEN 200 /* max datalen to tfr between ftp and linker */ +#define IDLE 0 +#define UUUK 1 +#define UIUK 2 +#define DATA 3 +#define UUNK 4 +#define UINK 5 +#define TERROR 6 /* the states */ +#define CR 1 +#define CA 2 +#define DR 3 +#define DA 4 +#define RR 5 +#define RA 6 +#define DT 7 /* the PDU's */ +/* #define NULL 0 */ + +void do_something(void); +int Polla(int,int); /* handles error from PollSocket() */ +void cancel(int); /* sets 'state' to IDLE */ +void WriteSigToApp(int); /* write a sig and handle error */ +void WriteSigToLink(int); /* write a sig and handle error */ +int WriteDataToLink(char*, int); /* cancel(AF/L) if no L_Stat from link */ +void WriteDataToApp(char*,int); +int doSigPacket(int); /* uses WriteDataToLink() */ +int ConnToLinker(void); /* executes cancel(AF/L) on error */ +void DiscFromLinker(void); /* executes cancel(L) on error */ + +int lSock_fd, fSock_fd, state=IDLE, stderr=2; + +main(int argc,char *argv[]) { + + int temp_fd; + printf("FTP_LAYER startat\n"); + if((fSock_fd=CreateUnixClientSocket(FPATH))<0) { + fprintf(stderr,"Can't create client signal socket to application!\n"); + exit(1); + } + printf("FTP_Layer har startat APP-socket...\n"); + if((temp_fd=CreateUnixServerSocket(LPATH))<0) { + fprintf(stderr,"Can't create server signal socket to linker!\n"); + exit(2); + } + printf("FTP_Layer har startat LINK-socket...\n"); + switch(fork()) { + case -1: + fprintf(stderr,"Fork failed in FTP-layer!\n"); + exit(4); + case 0: + close(fSock_fd); + close(temp_fd); + execv("./link_layer",argv); + exit(0); + default: + if((lSock_fd=AcceptConnection(temp_fd))<0) { + fprintf(stderr,"Can't accept client signal socket from application!\n"); + exit(3); + } + do_something(); + exit(0); + } +} + +int Polla(int fd1, int fd2) { + int poll; + poll=PollSocket(fd1,fd2,NULL); + if(poll==-1) { + fprintf(stderr,"PollSocket-error in FTP-layer, quitting!\n\n"); + exit(8); + } + return poll-1; +} + +void do_something() { + int sig, poll; + char buf[MAXDATALEN+SIGPACKLEN], x; + long len; + while(1) { + poll=Polla(fSock_fd,lSock_fd); + if(poll==fSock_fd) { /* signal från applikationen */ + sig=ReadSignalfromSocket(fSock_fd,SIGPACKLEN); + if(sig==AF_Abort_Req) + cancel(L); + else if(sig==-1) { + fprintf(stderr,"ReadSignal-error in FTP-layer, quitting!\n\n"); + exit(15); + } + else { + switch(state) { + case IDLE: + if(sig==AF_Con_Req) { + if(ConnToLinker()) + if(doSigPacket(CR)) state=UUUK; + } + else + cancel(AF); + break; + case UIUK: + if(sig==AF_Con_Resp) + if(doSigPacket(CA)) state=DATA; + else { + cancel(AF); + cancel(L); + } + break; + case DATA: + if(sig==AF_Data_Req) { + PollSocket(fSock_fd,fSock_fd,NULL); + ReadDatafromSocket(fSock_fd, (char*)&len,sizeof(long)); + if(len) { + PollSocket(fSock_fd,fSock_fd,NULL); + while(len>0) { + x=ReadDatafromSocket(fSock_fd,buf+3,len>MAXDATALEN?MAXDATALEN:len); + if(x>0) { + buf[0]=x+2; + buf[1]=x; + buf[2]=IsFTP | DT; + if(!WriteDataToLink(buf,x+SIGPACKLEN)) break; + len-=x; + } + else if(x==-1) { + fprintf(stderr,"Readerror in FTP-layer, quitting!\n\n"); + exit(14); + } + } + } + } + else if(sig==AF_Disc_Req) + if(doSigPacket(DR)) state=UUNK; + else { + cancel(AF); + cancel(L); + } + break; + case UINK: + if(sig==AF_Disc_Resp) { + if(doSigPacket(DA)) { + state=IDLE; + DiscFromLinker(); + } + } + else { + cancel(AF); + cancel(L); + } + break; + case TERROR: + if(sig==AF_Rej_Resp) + if(doSigPacket(RA)) state=IDLE; + else + cancel(AF); + cancel(L); + break; + default: /* I UUUK & UUNK ska man inte få signaler från app */ + cancel(AF); + cancel(L); + } + } + } + else if(poll==lSock_fd) { /* signal från linkern */ + sig=ReadSignalfromSocket(lSock_fd,SIGPACKLEN); + if(sig==L_Abort_Ind) + cancel(AF); + else if(sig==L_Data_Ind) + Polla(lSock_fd,lSock_fd); + else if(sig==-1) { + fprintf(stderr,"ReadSignal-error in FTP-layer, quitting!\n\n"); + exit(15); + } + else { + switch(state) { + case IDLE: + if(sig==L_Con_Ind) { + WriteSigToLink(L_Con_Resp); + Polla(lSock_fd,lSock_fd); + if(ReadSignalfromSocket(lSock_fd,SIGPACKLEN)==L_Data_Req) { + Polla(lSock_fd,lSock_fd); + ReadDatafromSocket(lSock_fd,buf,1); + Polla(lSock_fd,lSock_fd); + ReadDatafromSocket(lSock_fd,buf,buf[0]); + if(buf[1] & IsFTP) { + if((buf[1] & OPMASK)==CR) { + WriteSigToApp(AF_Con_Ind); + state=UIUK; + } + else + cancel(L); + } + } + else + cancel(L); + } + else { + cancel(AF); + cancel(L); + } + break; + case UUUK: + if(sig==L_Data_Ind) { + ReadDatafromSocket(lSock_fd,buf,1); + Polla(lSock_fd,lSock_fd); + ReadDatafromSocket(lSock_fd,buf,buf[0]); + if(buf[1] & IsFTP) { + if((buf[1] & OPMASK)==CA) { + WriteSigToApp(AF_Con_Conf); + state=DATA; + } + else if((buf[1] & OPMASK)==RR) { + WriteSigToApp(AF_Rej_Ind); + state=TERROR; + } + } + } + else + cancel(AF); + break; + case DATA: + if(sig==L_Data_Ind) { + ReadDatafromSocket(lSock_fd,buf,1); + Polla(lSock_fd,lSock_fd); + ReadDatafromSocket(lSock_fd,buf,buf[0]); + if(buf[1] & IsFTP) { + if((buf[1] & OPMASK)==DT) { + len=buf[0]; + WriteDataToApp((char*)&len,sizeof(long)); + WriteDataToApp(buf+2,len); + } + else if((buf[1] & OPMASK)==DR) { + WriteSigToApp(AF_Disc_Ind); + state=UINK; + } + else { + cancel(AF); + cancel(L); + } + } + } + else { + cancel(AF); + cancel(L); + } + break; + case UUNK: + if(sig==L_Data_Ind) { + ReadDatafromSocket(lSock_fd,buf,1); + Polla(lSock_fd,lSock_fd); + ReadDatafromSocket(lSock_fd,buf,buf[0]); + if(buf[1] & IsFTP) { + if((buf[1] & OPMASK)==DA) { + WriteSigToApp(AF_Disc_Conf); + state=IDLE; + DiscFromLinker(); + } + else { + cancel(AF); + cancel(L); + } + } + } + else { + cancel(AF); + cancel(L); + } + break; + default: /* i UIUK, UINK & TERROR ska man inte få sig. från linker */ + cancel(AF); + cancel(L); + } + } + } + } +} + +void cancel(int af_abort) { + if(af_abort) + WriteSigToApp(AF_Abort_Ind); + else + WriteSigToLink(L_Abort_Req); + state=IDLE; +} + +void WriteSigToLink(int flag) { + if(WriteSignaltoSocket(lSock_fd,flag,SIGPACKLEN)==-1) { + fprintf(stderr,"Write-error to linker, quitting!\n\n"); + exit(10); +} } + +void WriteSigToApp(int flag) { + if(WriteSignaltoSocket(fSock_fd,flag,SIGPACKLEN)==-1) { + fprintf(stderr,"Write-error to application, quitting!\n\n"); + exit(11); +} } + +int WriteDataToLink(char* buf,int len) { + int x; + WriteSigToLink(L_Data_Req); + PollSocket(lSock_fd,lSock_fd,NULL); + if(ReadSignalfromSocket(lSock_fd,SIGPACKLEN)!=L_Status) { + cancel(AF); + cancel(L); + return 0; + } + if((x=WriteDatatoSocket(lSock_fd,buf,len))==-1) { + fprintf(stderr,"Write-error to linker, quitting!\n\n"); + exit(13); + } + else + while(x +#include +#include +#include +#define FALSE 0 +#define TRUE 1 +#define ENTER 13 +#define BACKSPACE 8 +#define PERMS 0644 +#define BUFSIZE 4000 +#define FNSIZE 300 +#define SIGLEN 3 +#define S_PATH "./ftp_socket" +#define L_PATH "./ftp_layer" +#define STDIN 0 +int FSOCK_FD; + +#endif diff --git a/link.cpp b/link.cpp new file mode 100644 index 0000000..8cec7ee --- /dev/null +++ b/link.cpp @@ -0,0 +1,689 @@ +#include "physlayer.h" +#include +#include +#include +#include "link_signal.h" +#include "link.h" +#include "student.h" + + +const CONTROL_FRAME_SIZE = 14; +int PSOCK_FD; +int USOCK_FD; + +typedef enum state{IDLE, UICON, UOCON, DATA, UIDCON, UODCON}state; +state LINK_STATE = IDLE; + +static action ALIST[] = { +{ L_DATA_REQUEST , DataRequest }, +{ L_DATA_INDICATION , DataIndication }, +{ L_CONNECT_REQUEST , ConnectRequest }, +{ L_CONNECT_INDICATION , ConnectIndication }, +{ L_CONNECT_RESPONSE , ConnectResponse }, +{ L_CONNECT_CONFIRM , ConnectConfirm }, +{ L_DISCONNECT_REQUEST , DisconnectRequest }, +{ L_DISCONNECT_INDICATION , DisconnectIndication }, +{ L_DISCONNECT_RESPONSE , DisconnectResponse }, +{ L_DISCONNECT_CONFIRM , DisconnectConfirm }, +{ L_ABORT_REQUEST , AbortRequest }, +{ L_ABORT_INDICATION , AbortIndication }, +{ SYSTEM_FAILURE , SystemError }, +{ DEFAULT , Default }, +}; + +int incoming_frame_status = 0, incoming_frame_index = 0; // global! +int incoming_frame_length = 0; +struct Frame +{ + char start_header[6]; + short control; + short length; + short cc; + char *data; + char end_header[6]; +}; + +Frame incoming_frame; // global! (tillfälligt). + +int ConnectRequest(void) +{ + int return_value; + + if(LINK_STATE == IDLE) + { + return_value = WriteSignaltoSocket(PSOCK_FD, F_CONNECT_REQUEST, SIG_LEN); + if(return_value < 0) + return SYSTEM_FAILURE; + + LINK_STATE = UOCON; + } + else + { + return_value = Abort(BO); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + +int ConnectIndication(void) +{ + int return_value; + + if(LINK_STATE == IDLE) + { + return_value = WriteSignaltoSocket(PSOCK_FD, F_CONNECT_RESPONSE, SIG_LEN); + if(return_value < 0) + return SYSTEM_FAILURE; + + LINK_STATE = UICON; + } + else + { + return_value = Abort(BO); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + + +int ConnectConfirm(void) +{ + Frame frame; + int return_value, frame_length; + + if(LINK_STATE == IDLE) + { + return_value = Abort(SP); + if(return_value < 0) + return SYSTEM_FAILURE; + } + else if(LINK_STATE == UOCON) + { + frame_length = PutDataInFrame("", 0, &frame, SABM); + if(frame_length == -10) + return SYSTEM_FAILURE; + + return_value = SendFrame(&frame, PSOCK_FD); + if(return_value < 0) + return SYSTEM_FAILURE; + } + else + { + return_value = Abort(BO); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + +int ConnectResponse(void) +{ + Frame frame; + int return_value, frame_length; + + if(LINK_STATE == IDLE) + { + return_value = Abort(SU); + if(return_value < 0) + return SYSTEM_FAILURE; + } + else if(LINK_STATE == UICON) + { + frame_length = PutDataInFrame("", 0, &frame, UA); + if(frame_length == -10) + return SYSTEM_FAILURE; + + return_value = SendFrame(&frame, PSOCK_FD); + if(return_value < 0) + return SYSTEM_FAILURE; + + LINK_STATE = DATA; + } + else + { + return_value = Abort(BO); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + +int DisconnectRequest(void) +{ + Frame frame; + int return_value, frame_length; + + if(LINK_STATE == IDLE) + { + return_value = Abort(SU); + if(return_value < 0) + return SYSTEM_FAILURE; + + LINK_STATE = IDLE; + } + else if(LINK_STATE == DATA) + { + frame_length = PutDataInFrame("", 0, &frame, DISC); + if(frame_length == -10) + return SYSTEM_FAILURE; + + return_value = SendFrame(&frame, PSOCK_FD); + if(return_value < 0) + return SYSTEM_FAILURE; + + LINK_STATE = UODCON; + } + else + { + return_value = Abort(BO); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + +int DisconnectIndication(void) +{ + int return_value; + + if(LINK_STATE == IDLE) + { + return_value = Abort(SP); + if(return_value < 0) + return SYSTEM_FAILURE; + } + else if(LINK_STATE == UIDCON) + { + return_value = WriteSignaltoSocket(PSOCK_FD, F_DISCONNECT_RESPONSE, SIG_LEN); + if(return_value < 0) + return SYSTEM_FAILURE; + + LINK_STATE = IDLE; + } + else + { + return_value = Abort(BO); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + +int DisconnectResponse(void) +{ + Frame frame; + int return_value, frame_length; + + if(LINK_STATE == IDLE) + { + return_value = Abort(SU); + if(return_value < 0) + return SYSTEM_FAILURE; + + LINK_STATE = IDLE; + } + else if(LINK_STATE == UIDCON) + { + frame_length = PutDataInFrame("", 0, &frame, UA); + if(frame_length == -10) + return SYSTEM_FAILURE; + + return_value = SendFrame(&frame, PSOCK_FD); + if(return_value < 0) + return SYSTEM_FAILURE; + } + else + { + return_value = Abort(BO); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + +int DisconnectConfirm(void) +{ + int return_value; + + if(LINK_STATE == IDLE) + { + return_value = Abort(SP); + if(return_value < 0) + return SYSTEM_FAILURE; + } + else if(LINK_STATE == UODCON) + LINK_STATE = IDLE; + else + { + return_value = Abort(BO); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + +int AbortRequest(void) +{ + int return_value; + + if(LINK_STATE == IDLE) + // Do nothing. + ; + else + { + return_value = Abort(SP); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + +int AbortIndication(void) +{ + int return_value; + + if(LINK_STATE == IDLE) + ;// Do nothing. + + else + { + return_value = Abort(SU); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + +int Status(void) +{ + int return_value; + char frame_status; + + frame_status = CheckFrame(&incoming_frame); + + return_value = WriteSignaltoSocket(USOCK_FD, L_STATUS, SIG_LEN); + if(return_value < 0) + return SYSTEM_FAILURE; + + return_value = WriteDatatoSocket(USOCK_FD, &frame_status, sizeof(char)); + if(return_value < 0) + return SYSTEM_FAILURE; + + return SUCCESS; +} + +int Abort(short who) +{ + int return_value; + + if((who == SU) || (who == BO)) + { + return_value = WriteSignaltoSocket(USOCK_FD, L_ABORT_INDICATION, SIG_LEN); + if(return_value < 0) + return SYSTEM_FAILURE; + } + if((who == SP) || (who == BO)) + { + return_value = WriteSignaltoSocket(PSOCK_FD, F_ABORT_REQUEST, SIG_LEN); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + LINK_STATE = IDLE; + + return SUCCESS; +} + +int Checksum(int data_length) +{ + int sum; + + // Vet ej varför, men det står i laborationshäftet. + sum = data_length % 128; + + return sum; +} + +int PutDataInFrame(char *data, short data_length, Frame *frame, short control) +{ + int frame_length, cc = 0; + + strcat(frame->start_header, "DLEST"); + frame->start_header[5] = 'X'; + + frame->control = control; + frame->length = data_length; + + if(control == I) + cc = Checksum(data_length); + else + { + frame->cc = cc; + data_length = sizeof(frame->data); + } + + frame->data = data; + + strcat(frame->start_header, "DLEET"); + frame->end_header[5] = 'X'; + + frame_length = 6 + 6 + 2 + 2 + 2 + data_length; + + return frame_length; +} + +int ClearFrame(Frame *frame) +{ + frame->start_header[0] = 0; + frame->end_header[0] = 0; + frame->control = 0; + frame->length = 0; + frame->cc = 0; + if(frame->data != NULL) + { + delete[] frame->data; + frame->data = NULL; + } + + incoming_frame_status = 0; // Global variabel. + incoming_frame_index = 0; // Global variabel. +} + +int FillInFrame(Frame *frame, char data, char *charframe) +{ + int status; + + if(CheckFrame(frame) == -1) + return FRAME_ERROR; + + if(incoming_frame_status) + return FRAME_IS_FULL; + + if(incoming_frame_index == 12) + { + if(frame->control == I) + { + frame->data = new char[frame->length]; + if(frame->data == NULL) + return SYSTEM_FAILURE; + + charframe[incoming_frame_index] = data; + incoming_frame_index++; + } + } + else + { + charframe[incoming_frame_index] = data; + incoming_frame_index++; + } + + return CheckFrame(frame); +} + +int CheckFrame(Frame *frame) +{ + int start, end, cc; + + if(incoming_frame_index == 10) // HEADER_LENGTH = 22 + incoming_frame_length = HEADER_LENGTH + frame->length; + + if(incoming_frame_index >= 10) + { + if(incoming_frame_index == incoming_frame_length) + { + start = CheckStartHeader((char*)frame); + end = CheckEndHeader((char*)frame); + cc = CheckCC(frame); + FixFrameData(frame); // tar bort de onödiga DLE om det behövs. + + if(start == 0 && end == 0 && cc == 0) + { + incoming_frame_status = 1; + return FRAME_IS_FULL; // frame_is_full = 1 + } + else + return FRAME_ERROR; // frame_error = -1 + } + } + + return FRAME_NOT_READY; // frame_not_ready = 0 +} + +int CheckStartHeader(char *frame) +{ + int index; + char start[7]; + start[7] = '\0'; + + for(index = 0; index < 6; index++) + start[index] = (char)frame[index]; + + return strcmp(start, "DLESTX"); +} + +int CheckEndHeader(char *frame) +{ + if(incoming_frame_status != 1) + return FRAME_ERROR; + + int index; + char start[7]; + start[7] = '\0'; + + for(index = 0; index < 6; index++) + start[index] = (char)frame[incoming_frame_index - 5 + index]; + + return strcmp(start, "DLEETX"); +} + +int CheckCC(Frame *frame) +{ + int cc; + cc = Checksum(frame->length); + + if(cc == frame->cc) + return 0; + + return FRAME_ERROR; +} + +int FixFrameData(Frame *frame) +{ + char *tmp; + int length, index, tmpindex, before = 0; + length = frame->length; + + for(index = 0; index < frame->length; index++) + { + if(frame->data[index] == 'D' && frame->data[index+1] == 'L' && frame->data[index+2] +== 'E') { + if(before == 1) + { length--; before = 0; } + else + before = 1; + } + } + + if(length == frame->length) + return SUCCESS; + + tmp = new char[length]; + if(tmp == NULL) + return SYSTEM_FAILURE; + + for(index = 0, tmpindex = 0; index < frame->length; index++, tmpindex++) + { + if(frame->data[index] == 'D' && frame->data[index+1] == 'L' && frame->data[index+2] == 'E') + { + if(before == 1) + { before = 0; index += 3; } + else + before = 1; + } + + if(index < frame->length) + tmp[tmpindex]; + } + + delete[] frame->data; + frame->data = tmp; + frame->length = length; + return SUCCESS; +} + +int SendFrame(Frame *frame, int socket_id) +{ + int frame_length, index = 0, return_value; + frame_length = GetFrameLength(frame); + + if(socket_id == USOCK_FD) + { + return_value = WriteSignaltoSocket(USOCK_FD, L_DATA_INDICATION, SIG_LEN); + if(return_value < 0) + return SYSTEM_FAILURE; + + return_value = WriteDatatoSocket(USOCK_FD, frame->data, +frame->length); if(return_value < 0) + return SYSTEM_FAILURE; + } + else if(socket_id == PSOCK_FD) + { + for(index = 0; index < frame_length; index++) + { + return_value = WriteSignaltoSocket(PSOCK_FD, F_DATA_REQUEST, SIG_LEN); + if(return_value < 0) + return SYSTEM_FAILURE; + + return_value = WriteDatatoSocket(PSOCK_FD, (char +*)&frame[index], sizeof(char)); if(return_value < 0) + return SYSTEM_FAILURE; } + } + else + return SYSTEM_FAILURE; + + return SUCCESS; +} + +int DataIndication(void) +{ + /*Frame *frame; + char temp = 'a'; + int return_value, frame_length; + + if(LINK_STATE == IDLE) + Abort(SP); + else if(LINK_STATE == UICON) + { + return_value = ReadDatafromSocket(PSOCK_FD, &temp, TWO_BYTES); + if(return_value < 0) + return SYSTEM_FAILURE; + + return_value = ReadDatafromSocket(PSOCK_FD, temp, BYTE_LEN); + if(return_value < 0) + return SYSTEM_FAILURE; + } + else + { + return_value = Abort(BO); + if(return_value < 0) + return SYSTEM_FAILURE; + } + + if(frame != NULL) + delete[] frame; */ + + return SUCCESS; + +} + +void main(int argc, char *argv[]) +{ + int tmp_fd1, PSOCK; + printf("LINK_LAYER har startat...\n"); + + if((PSOCK = CreateUnixClientSocket(UPATH)) < 0) + { + fprintf(stderr, "Can't create unix client signal socket 111\n"); + exit(1); + } + printf("LINK_LAYER har skapat FTP_LAYER Socket...\n"); + if((tmp_fd1 = CreateUnixServerSocket(PPATH)) < 0) + { + fprintf(stderr, "Can't create unix server signal socket.\n"); + exit(1); + } + printf("LINK_LAYER har skapat PHYS_LAYER Socket...\n"); + switch(fork()) + { + case -1: + fprintf(stderr, "Fork failed.\n"); + + case 0: + printf("Fuck you\n\n"); + close(PSOCK_FD); + close(USOCK_FD); + execv("./phys_layer", argv); + exit(1); + + default: + if((PSOCK = AcceptConnection(tmp_fd1)) < 0) + { + fprintf(stderr, "Can't accept unix client signal socket.\n"); + exit(1); + } + + MainLoop(); + exit(1); + } +} + +void MainLoop(void) +{ + int return_value; + do + { + return_value = PollSocket(PSOCK_FD, USOCK_FD, NULL); + if(return_value < 0) + return; + + return_value = ReadSignalfromSocket(return_value - 1, SIG_LEN); + return_value = (* FindAction(return_value, ALIST))(); + if(return_value < 0) + return ; + + } while(return_value >= 0); + +} + +int DataRequest(void) +{ + return 10; +} + +int Default(void) +{ + return 10; +} + + +int GetFrameLength(Frame *frame) +{ + return frame->length; +} + +int SystemError(void) +{ + return 108; +} diff --git a/link.h b/link.h new file mode 100644 index 0000000..eddda43 --- /dev/null +++ b/link.h @@ -0,0 +1,52 @@ +#ifndef _link_h_ +#define _link_h_ + +#define SABM 401 +#define UA 403 +#define I 405 +#define RR 406 +#define DISC 407 +#define SIG_LEN 2 +#define BO 2 +#define SU 1 +#define SP 3 +#define DEFAULT 10 +#define FRAME_ERROR 13 +#define FRAME_IS_FULL 34 +#define FRAME_NOT_READY 123 +#define HEADER_LENGTH 22 +#define TWO_BYTES 56 +#define UPATH "./link_socket" +#define PPATH "./.phys_socket" + +struct Frame; +int SystemError(void); +int GetFrameLength(Frame *frame); +int Default(void); +int DataRequest(void); +int ConnectRequest(void); +int ConnectIndication(void); +int ConnectConfirm(void); +int ConnectResponse(void); +int DisconnectRequest(void); +int DisconnectIndication(void); +int DisconnectResponse(void); +int DisconnectConfirm(void); +int AbortRequest(void); +int AbortIndication(void); +int Status(void); +int Abort(short who); +int Checksum(int data_length); +int PutDataInFrame(char *data, short data_length, Frame *frame, short control); +int ClearFrame(Frame *frame); +int FillInFrame(char *frame, char data, char *charframe); +int CheckFrame(Frame *frame); +int CheckStartHeader(char *frame); +int CheckEndHeader(char *frame); +int CheckCC(Frame *frame); +int FixFrameData(Frame *frame); +int SendFrame(Frame *frame, int socket_id); +int DataIndication(void); +void MainLoop(void); + +#endif diff --git a/link_signal.h b/link_signal.h new file mode 100644 index 0000000..cc0473d --- /dev/null +++ b/link_signal.h @@ -0,0 +1,48 @@ +#ifndef ___SIGNAL_PRIM___ +#define ___SIGNAL_PRIM___ + +#define L_CONNECT_REQUEST 101 +#define L_CONNECT_INDICATION 102 +#define L_CONNECT_RESPONSE 103 +#define L_CONNECT_CONFIRM 104 +#define L_DATA_REQUEST 105 +#define L_DATA_INDICATION 106 +#define L_DISCONNECT_REQUEST 107 +#define L_DISCONNECT_RESPONSE 108 +#define L_DISCONNECT_INDICATION 109 +#define L_DISCONNECT_CONFIRM 110 +#define L_ABORT_REQUEST 111 +#define L_ABORT_INDICATION 112 +#define L_STATUS 113 + +#define AF_Con_Req 201 +#define AF_Con_Ind 202 +#define AF_Con_Resp 203 +#define AF_Con_Conf 204 +#define AF_Data_Req 205 +#define AF_Data_Ind 206 +#define AF_Disc_Req 207 +#define AF_Disc_Ind 208 +#define AF_Disc_Resp 209 +#define AF_Disc_Conf 210 +#define AF_Rej_Req 211 +#define AF_Rej_Ind 212 +#define AF_Rej_Resp 213 +#define AF_Rej_Conf 214 +#define AF_Abort_Req 215 +#define AF_Abort_Ind 216 + +#define AI_Con_Req 301 +#define AI_Con_Ind 302 +#define AI_Con_Resp 303 +#define AI_Con_Conf 304 +#define AI_Data_Req 305 +#define AI_Data_Ind 306 +#define AI_Disc_Req 307 +#define AI_Disc_Ind 308 +#define AI_Disc_Resp 309 +#define AI_Disc_Conf 310 +#define AI_Abort_Req 311 +#define AI_Abort_Ind 312 + +#endif diff --git a/physerr.log b/physerr.log new file mode 100644 index 0000000..015d23e --- /dev/null +++ b/physerr.log @@ -0,0 +1,3 @@ +Wed Dec 16 14:55:03 1998 +System failure +No such file or directory \ No newline at end of file diff --git a/physlayer.c b/physlayer.c new file mode 100644 index 0000000..c8ca4b2 --- /dev/null +++ b/physlayer.c @@ -0,0 +1,1886 @@ +/****************************************************************************** +* +* (c) Copyright 1998, University of Karlstad. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 1, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* Please report any bugs you find in this code or any improvements to: +* +* Hans Hedbom, Dept. of Computer Science, +* University of Karlstad, Sweden. +* +* Phone: +46 54 838157 +* E-mail: Hans.Hedbom@hks.se +* +* ============================================================================ +* +* FILE: +* +* physlayer.c [ the Data Communication I course programming project ] +* +* AUTHORS: +* +* Jonny Wiederholm +* E-mail: fr7wied@cse.hks.se or +* jonnwied@hks.se +* +* Per-Ola Gustafsson +* E-mail: fr7gust@cse.hks.se +* +* CREATION DATE: +* +* Jan, 08, 1998 +* +* DESCRIPTION: +* +* Implementation of the Physical Layer, which is part of the example +* implementation of the Data Communication I course programming project. +* +* NOTE: +* +* All debug functions ( prefixed FDbg or FDebug ) are ignored ( at least from +* an abstract point of view ) if the constant DEBUG is undefined. The window +* debugger is only available under Linux and since it is implemented using +* Tcl-Tk and Tcl-Tk uses a different technique when polling sockets we have +* to provide two so called file event handlers, one for each socket, namely +* FDbgPESocketEventHandler() and FDbgSUSocketEventHandler(). These functions +* are not really part of the Physical Layer module ( they should have been +* included in the physdebuglib.c library ) but they were placed here since +* we wanted to avoid having global variables that could be accessed outside +* this module ( lets keep things private ). +* +* MODIFICATIONS: Date Changes +* ---------------------------------------------------------------------------- +* +*/ + +/****************************************************************************** +* INCLUDE FILES +*/ + +#include "systems.h" +#include "udefs.h" +#include "error.h" +#include "ustring.h" +#include "ustdlib.h" +#include "memory.h" +#include "utime.h" +#include "file.h" +#include "sockets.h" +#include "socketio.h" +#include "unixsockets.h" +#include "inetsockets.h" +#include "uselect.h" +#include "usignal.h" +#include "student.h" +#include "transmissionerror.h" +#include "physservices.h" +#include "physdebug.h" +#include "physlayer.h" + +/****************************************************************************** +* DEFINE CONSTANTS +*/ + +/* + Value returned when recieving non state transition signals when in state + idle. + */ +#define IGNORE_SIGNAL SUCCESS + +/* The number of arguments required when starting as server. */ +#define SERVER 5 + +/* The number of arguments required when starting as server. */ +#define CLIENT 6 + +/* Position in command line of arguments. */ +#define PORTPOS 1 /* Port number. */ +#define HOSTNAMEPOS 2 /* Host name or ip address. */ + +/* Relative position of arguments in the command line counting from the end. */ +#define RELLOSEBYTEPOS 1 /* Probability of loosing a byte. */ +#define RELDELAYPOS 2 /* Probability of a transmission delay. */ +#define RELFAULTPOS 3 /* Probability that a byte will get corrupted. */ + +/* Time of the delay in seconds. */ +#define DELAYTIME 1 + +/* The maximum allowed port number. */ +#define MAX_PORT 50000 + +/* The minimum allowed port number. */ +#define MIN_PORT 1023 + +/* Path to the debug file. */ +#define DBGLOG_NAME "./physdebug.log" + +/* Path to the error log file. */ +#define ERRLOG_NAME "./physerr.log" + +/* Integer format. */ +#define INT_FORMAT "%d" + +/* + Passed as parameter to kill() to kill all processes in the same process + group. +*/ +#define PROCESS_GROUP 0 + +/* Protocol signals.*/ +#define WANT_CONNECTION 120 +#define WANT_DISCONNECTION 122 +#define CONNECTION_REQUEST_REPLY 124 +#define DISCONNECTION_REQUEST_REPLY 126 +#define INCOMING_DATA 128 +#define ABORT 666 +#define DEFAULT 0 + +/****************************************************************************** +* DEFINE TYPES +*/ + +/* + Internal state codes. Each code represents one of the following internal + states: Idle, Under incoming connection, Under outgoing connection, Under + data transfer, Under incoming disconnection or Under outgoing disconnection. + */ +enum state {IDLE, UICON, UOCON, DATA, UIDCON, UODCON}; +typedef enum state state; + +/* + Abort destination code. Is used to determine where to send an abort. Each + code represents one of the following destinations of the abort : the Peer + entity, the Service user or Both. + */ +enum abortdst {PE, SU, BO}; +typedef enum abortdst abortdst; + +/****************************************************************************** +* DECLARE FUNCTIONS +*/ + +/* See function definitions for documentation. */ + +static int FConnectRequest __P((void)); +static int FConnectIndication __P((void)); +static int FConnectResponse __P((void)); +static int FConnectConfirm __P((void)); +static int FDisconnectRequest __P((void)); +static int FDisconnectIndication __P((void)); +static int FDisconnectResponse __P((void)); +static int FDisconnectConfirm __P((void)); +static int FDataRequest __P((void)); +static int FDataIndication __P((void)); +static int FAbortRequest __P((void)); +static int FAbortIndication __P((void)); +static int FAbort __P((abortdst)); +static int FSystemError __P((void)); +static int FDefault __P((void)); +static void FDbgPESocketEventHandler __P((void_ptr_, int)); +static void FDbgSUSocketEventHandler __P((void_ptr_, int)); +static void CleanUp __P((void)); +static void ErrorHandler __P((string_ptr_)); +static int InitSignalHandler __P((void (*) __P((int)))); +static void SignalHandler __P((int)); +static void MainLoop __P((void)); +static void Server __P((int)); +static void Client __P((int, string_ptr_)); + +/****************************************************************************** +* DEFINE GLOBALS +*/ + +/* Internal state. */ +static state PHYS_STATE = IDLE; + +/* + Socket file descriptors. They can't be of type static since they are used + in other libraries. + */ +static int PE_FD, SU_FD, TMP_FD; + +/* + Probabilities that a byte will get corrupted, that a byte will get delayed + and that a byte will get lost. + */ +static double FAULT_PROBABILITY, DELAY_PROBABILITY, LOSEBYTE_PROBABILITY; + +/* Indicates when a fatal error is in progress. */ +static volatile int FATAL_ERROR_IN_PROGRESS = 0; + +/* Array containing the function associated with a certain signal. */ +static const__ action ALIST[] = { +{ F_DATA_REQUEST , FDataRequest }, +{ INCOMING_DATA , FDataIndication }, +{ F_CONNECT_REQUEST , FConnectRequest }, +{ WANT_CONNECTION , FConnectIndication }, +{ F_CONNECT_RESPONSE , FConnectResponse }, +{ CONNECTION_REQUEST_REPLY , FConnectConfirm }, +{ F_DISCONNECT_REQUEST , FDisconnectRequest }, +{ WANT_DISCONNECTION , FDisconnectIndication }, +{ F_DISCONNECT_RESPONSE , FDisconnectResponse }, +{ DISCONNECTION_REQUEST_REPLY, FDisconnectConfirm }, +{ F_ABORT_REQUEST , FAbortRequest }, +{ ABORT , FAbortIndication }, +{ SYSTEM_FAILURE , FSystemError }, +{ DEFAULT , FDefault }, +}; + +/* + Array containing the error text message associated with a certain status + code. */ +static const__ errmess ERRLIST[] = { +{ 1, "Failed to create Unix client socket\n" }, +{ 2, "Port number out of range \n" }, +{ 3, "System failure \n" }, +{ 4, "Argument out of range \n" }, +{ 5, "Failed to create Inet server socket\n" }, +{ 6, "Failed to accept Inet client socket\n" }, +{ 7, "Failed to create Inet client socket\n" }, +{ 8, "Failed to initialize signal handler\n" }, +{ 9, "Wrong number of arguments \n" }, +{ 10, "Failed to poll sockets \n" }, +{ 0, "Unknown error \n" }, +}; + +/* + Array containing the debug text message associated with a certain debug + code. */ +static const__ dbgmess DBGLIST[] = { +{ 1, "\nGot signal F_CONNECT_REQUEST from service user" }, +{ 2, "\nSending signal WANT_CONNECTION to peer entity\n" }, +{ 3, "\nIn wrong state. Sending signal ABORT to peer entity and signal \ +F_ABORT_INDICATION to service user\n" }, +{ 4, "\nGot signal WANT_CONNECTION from peer entity" }, +{ 5, "\nSending signal F_CONNECT_INDICATION to service user\n" }, +{ 6, "\nGot signal F_CONNECT_RESPONSE from service user" }, +{ 7, "\nSending signal CONNECTION_REQUEST_REPLY to peer entity\n" }, +{ 8, "\nIn state idle. Ignoring signal\n" }, +{ 9, "\nGot signal CONNECTION_REQUEST_REPLY from peer entity" }, +{ 10, "\nSending signal F_CONNECT_CONFIRM to service user\n" }, +{ 11, "\nGot signal F_DISCONNECT_REQUEST from service user" }, +{ 12, "\nSending signal WANT_DISCONNECTION to peer entity\n" }, +{ 13, "\nGot signal WANT_DISCONNECTION from peer entity" }, +{ 14, "\nSending signal F_DISCONNECT_INDICATION to service user\n" }, +{ 15, "\nGot signal F_DISCONNECT_RESPONSE from service user" }, +{ 16, "\nSending signal DISCONNECTION_REQUEST_REPLY to peer entity\n" }, +{ 17, "\nGot signal DISCONNECTION_REQUEST_REPLY from peer entity" }, +{ 18, "\nSending signal F_DISCONNECT_CONFIRM to service user\n" }, +{ 19, "\nGot signal F_DATA_REQUEST from service user and a byte with the \ +ascii value " }, +{ 20, "\nSending signal INCOMING_DATA to peer entity along with the byte\n" }, +{ 21, "\nGot signal INCOMING_DATA from peer entity and a byte with the ascii \ +value " }, +{ 22, "\nSending signal F_DATA_INDICATION to service user along with the \ +byte\n" }, +{ 23, "\nGot signal F_ABORT_REQUEST from service user" }, +{ 24, "\nSending signal ABORT to peer entity\n" }, +{ 25, "\nGot signal ABORT from peer entity" }, +{ 26, "\nSending signal F_ABORT_INDICATION to service user\n" }, +{ 27, "\nGot unknown signal from service user" }, +{ 28, "\nSorry, but the byte of data got lost in cyberspace\n" }, +{ 0, "\nUnknown debug prompt\n" }, +}; + +/****************************************************************************** +* DEFINE FUNCTIONS +*/ + +/****************************************************************************** +* +* FUNCTION: +* +* int FConnectRequest(void) +* +* DESCRIPTION: +* +* Handles a connect request from the service user by sending the signal +* WANT_CONNECTION to the peer entity and setting the internal state to under +* outgoing connection. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* PE_FD references the socket connected to the peer entity. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If FConnectRequest() is called and the internal state is not set to idle, it +* will send an abort request to the peer entity and the service user and set +* the internal state to idle. +* +*/ + +#ifdef __STDC__ +int FConnectRequest(void) +#else + int FConnectRequest() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 1, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 2, DBGLIST, NULL, NULL, 0); + retval = WriteSignaltoSocket(PE_FD, WANT_CONNECTION, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + PHYS_STATE = UOCON; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FConnectIndication(void) +* +* DESCRIPTION: +* +* Handles a connect request from the peer entity by sending the signal +* F_CONNECT_INDICATION to the service user and setting the internal state to +* under incoming connection. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* SU_FD references the socket connected to the service user. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If FConnectIndication() is called when the internal state is not set to +* idle, it will send an abort request to the peer entity and the service user +* and set the internal state to idle. +* +*/ + +#ifdef __STDC__ +int FConnectIndication(void) +#else + int FConnectIndication() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 4, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 5, DBGLIST, NULL, NULL, 0); + retval = WriteSignaltoSocket(SU_FD, F_CONNECT_INDICATION, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + PHYS_STATE = UICON; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FConnectResponse(void) +* +* DESCRIPTION: +* +* Handles a connect response from the service user by sending the signal +* CONNECTION_REQUEST_REPLY to the peer entity and setting the internal state +* to data transfer. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* PE_FD references the socket connected to the peer entity. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If FConnectResponse() is called when the internal state is set to idle, it +* will ignore the request. Otherwise, if called when the internal state is not +* set to under incoming connection, it will send an abort request to the peer +* entity and the service user and set the internal state to idle. +* +*/ + +#ifdef __STDC__ +int FConnectResponse(void) +#else + int FConnectResponse() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 6, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == UICON){ + FDebug(DBGLOG_NAME, 7, DBGLIST, NULL, NULL, 0); + retval = WriteSignaltoSocket(PE_FD, CONNECTION_REQUEST_REPLY, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + PHYS_STATE = DATA; + } + else if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FConnectConfirm(void) +* +* DESCRIPTION: +* +* Handles a connect response from the peer entity by sending the signal +* F_CONNECT_CONFIRM to the service user and setting the internal state to data +* transfer. +* +* PARAMETERS: +* +* void -- None +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* SU_FD references the socket connected to the service user. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If FConnectConfirm() is called when the internal state is set to idle, it +* will ignore the request. Otherwise, if called when the internal state is not +* set to under outgoing connection, it will send an abort request to the peer +* entity and the service user and set the internal state to idle. +* +*/ + +#ifdef __STDC__ +int FConnectConfirm(void) +#else + int FConnectConfirm() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 9, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == UOCON){ + FDebug(DBGLOG_NAME, 10, DBGLIST, NULL, NULL, 0); + retval = WriteSignaltoSocket(SU_FD, F_CONNECT_CONFIRM, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + PHYS_STATE = DATA; + } + else if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FDisconnectRequest(void) +* +* DESCRIPTION: +* +* Handles a disconnect request from the service user by sending the signal +* WANT_DISCONNECTION to the peer entity and setting the internal state to +* under outgoing connection. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* PE_FD is referencing the socket connected to the peer entity. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If FDisconnectRequest() is called when the internal state is set to idle it +* will ignore the request. Otherwise if called when the internal state is not +* set to data transfer it will send an abort request to the peer entity and +* the service user and set the internal state to idle. +* +*/ + +#ifdef __STDC__ +int FDisconnectRequest(void) +#else + int FDisconnectRequest() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 11, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == DATA){ + FDebug(DBGLOG_NAME, 12, DBGLIST, NULL, NULL, 0); + retval = WriteSignaltoSocket(PE_FD, WANT_DISCONNECTION, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + PHYS_STATE = UODCON; + } + else if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FDisconnectIndication(void) +* +* DESCRIPTION: +* +* Handles a disconnect request from the peer entity by sending the signal +* F_DISCONNECT_INDICATION to the service user and setting the internal state +* to under incoming disconnection. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* SU_FD is referencing the socket connected to the service user. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If FDisconnectIndication() is called when the internal state is set to idle, +* it will ignore the request. Otherwise, if called when the internal state is +* not set to data transfer, it will send an abort request to the peer entity +* and the service user and set the internal state to idle. +* +*/ + +#ifdef __STDC__ +int FDisconnectIndication(void) +#else + int FDisconnectIndication() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 13, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == DATA){ + FDebug(DBGLOG_NAME, 14, DBGLIST, NULL, NULL, 0); + retval = WriteSignaltoSocket(SU_FD, F_DISCONNECT_INDICATION, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + PHYS_STATE = UIDCON; + } + else if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FDisconnectResponse(void) +* +* DESCRIPTION: +* +* Handles a disconnect request response from the service user by sending the +* signal DISCONNECTION_REQUEST_REPLY to the peer entity and setting the +* internal state to idle. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* PE_FD references the socket connected to the peer entity. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If FDisconnectResponse() is called when the internal state is set to idle, +* it will ignore the request. Otherwise, if called when the internal state is +* not set to under incoming disconnection, it will send an abort request to +* the peer entity and the service user and set the internal state to idle. +* +*/ + +#ifdef __STDC__ +int FDisconnectResponse(void) +#else + int FDisconnectResponse() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 15, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == UIDCON){ + FDebug(DBGLOG_NAME, 16, DBGLIST, NULL, NULL, 0); + retval = WriteSignaltoSocket(PE_FD, DISCONNECTION_REQUEST_REPLY, \ + SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + PHYS_STATE = IDLE; + } + else if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FDisconnectConfirm(void) +* +* DESCRIPTION: +* +* Handles a disconnect response from the peer entity by sending the signal +* F_DISCONNECT_CONFIRM to the service user and setting the internal state to +* idle. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* SU_FD references the socket connected to the service user. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If FDisconnectConfirm() is called and the internal state is set to idle, it +* will ignore the request. Otherwise, if called when the internal state is not +* set to under outgoing disconnection, it will send an abort request to the +* peer entity and the service user and set the internal state to idle. +* +*/ + +#ifdef __STDC__ +int FDisconnectConfirm(void) +#else + int FDisconnectConfirm() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 17, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == UODCON){ + FDebug(DBGLOG_NAME, 18, DBGLIST, NULL, NULL, 0); + retval = WriteSignaltoSocket(SU_FD, F_DISCONNECT_CONFIRM, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + PHYS_STATE = IDLE; + } + else if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FDataRequest(void) +* +* DESCRIPTION: +* +* Handles a data request from the service user by accepting a byte of data and +* transmitting that byte to the peer entity, using the signal INCOMING_DATA. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* PE_FD is referencing the socket connected to the peer entity. +* SU_FD is referencing the socket connected to the service user. +* FAULT_PROBABILITY specifies the probability that a byte will get corrupted. +* DELAY_PROBABILITY specifies the probability of a transmission delay. +* LOSEBYTE_PROBABILITY specifies the probability of loosing a byte. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If FDataRequest() is called when the internal state is set to idle it will +* ignore the request. Otherwise if called when the internal state is not set +* to transfer data it will send an abort request to the peer entity and the +* service user and set the internal state to idle. +* +*/ + +#ifdef __STDC__ +int FDataRequest(void) +#else + int FDataRequest() +#endif +{ + int retval; + char databuf; + + /* + We always read data from the socket to make sure that no pending data + exists in the socket buffer if we start a new session. + */ + retval = ReadDatafromSocket(SU_FD, &databuf, BYTE_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + FDebug(DBGLOG_NAME, 19, DBGLIST, &databuf, INT_FORMAT, BYTE_LEN); + if(PHYS_STATE == DATA){ + /* The byte of data might get lost. */ + retval = LoseByte(LOSEBYTE_PROBABILITY); + if(retval == BYTETRANSMITTED){ + + /* + If the byte is not lost we introduce delays and noice on the line. + */ + CreateNoice(FAULT_PROBABILITY, &databuf); + CreateDelays(DELAY_PROBABILITY, DELAYTIME); + FDebug(DBGLOG_NAME, 20, DBGLIST, NULL, NULL, 0); + retval = WriteSignaltoSocket(PE_FD, INCOMING_DATA, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + retval = WriteDatatoSocket(PE_FD, &databuf, BYTE_LEN); + fprintf(stderr, "databuf = %d", databuf); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + else{ + FDebug(DBGLOG_NAME, 28, DBGLIST, NULL, NULL, 0); + } + } + else if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FDataIndication(void) +* +* DESCRIPTION: +* +* Handles a data request from the peer entity by accepting a byte of data and +* transmitting that byte to the service user, using the signal +* F_DATA_INDICATION. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* PE_FD references the socket connected to the peer entity. +* SU_FD references the socket connected to the service user. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If FDataIndication() is called when the internal state is set to idle it +* will ignore the request. Otherwise if called when the internal state is not +* in state data transfer it will send an abort request to the peer entity and +* the service user and set the internal state to idle. +* +*/ + +#ifdef __STDC__ +int FDataIndication(void) +#else + int FDataIndication() +#endif +{ + int retval; + char databuf; + + /* + We always read data from the socket to make sure that no pending data + exists in the socket buffer if we start a new session. + */ + retval = ReadDatafromSocket(PE_FD, &databuf, BYTE_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + fprintf(stderr, "databuf2 = %d", databuf); + FDebug(DBGLOG_NAME, 21, DBGLIST, &databuf, INT_FORMAT, BYTE_LEN); + if(PHYS_STATE == DATA){ + FDebug(DBGLOG_NAME, 22, DBGLIST, NULL, NULL, 0); + retval = WriteSignaltoSocket(SU_FD, F_DATA_INDICATION, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + retval = WriteDatatoSocket(SU_FD, &databuf, BYTE_LEN); + fprintf(stderr, "sending data = %d", databuf); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + else if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FAbortRequest(void) +* +* DESCRIPTION: +* +* Handles an abort request from the service user by sending the signal ABORT +* to the peer entity and setting the internal state to idle. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* PE_FD references the socket connected to the peer entity. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If the internal state is set to idle, FAbortRequest() will ignore the +* request. +* +*/ + +#ifdef __STDC__ +int FAbortRequest(void) +#else + int FAbortRequest() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 23, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 24, DBGLIST, NULL, NULL, 0); + retval = FAbort(PE); + if(retval < 0){ + return SYSTEM_FAILURE; + } + + return SUCCESS; + } +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FAbortIndication(void) +* +* DESCRIPTION: +* +* Handles an abort request from the peer entity by sending the signal +* F_ABORT_INDICATION to the service user and setting the internal state to +* idle. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* SU_FD is referencing the socket connected to the service user. +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +* If the internal state is set to idle FAbortIndication() will ignore the +* request. +* +*/ + +#ifdef __STDC__ +int FAbortIndication(void) +#else + int FAbortIndication() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 25, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 26, DBGLIST, NULL, NULL, 0); + retval = FAbort(SU); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FAbort(abortdst dst) +* +* DESCRIPTION: +* +* Sends an abort request to either the peer entity, the service user or both +* depending on the value specified by the parameter `dst', and sets the +* internal state to idle. +* +* PARAMETERS: +* +* abortdst dst -- The destination of the abort. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* PHYS_STATE specifies the internal state. +* PE_FD references the socket connected to the peer entity. +* SU_FD references the socket connected to the service user. +* +* NOTE: +* +*/ + +#ifdef __STDC__ +int FAbort(abortdst dst) +#else + int FAbort(abortdst) + abortdst dst; +#endif +{ + int retval; + + if((dst == SU) || (dst == BO)){ + retval = WriteSignaltoSocket(SU_FD, F_ABORT_INDICATION, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + if((dst == PE) || (dst == BO)){ + retval = WriteSignaltoSocket(PE_FD, ABORT, SIG_LEN); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + PHYS_STATE = IDLE; + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FSystemError(void) +* +* DESCRIPTION: +* +* To be able to catch a system error when finding the correct function +* corresponding to a signal in FindAction(), FSystemError() just returns -1 +* since every signal corresponds to a function and FindAction() has to return +* a pointer to a function a signal can't be returned to the calling +* environment unless its corresponding function does the job. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- Always -1. +* +* NOTE: +* +*/ + +#ifdef __STDC__ +int FSystemError(void) +#else + int FSystemError() +#endif +{ + return SYSTEM_FAILURE; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int FDefault(void) +* +* DESCRIPTION: +* +* The default function used in FindAction() as a break condition to make sure +* FindAction() won't go into an infinite loop. FDefault() is invoked when +* FindAction() encounters an undefined signal and FDefault() sends an abort +* request to the peer entity and the service user. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* GLOBALS: +* +* DBGLIST contains all debug codes and their respective text messages. +* +* NOTE: +* +*/ + +#ifdef __STDC__ +int FDefault(void) +#else + int FDefault() +#endif +{ + int retval; + + FDebug(DBGLOG_NAME, 27, DBGLIST, NULL, NULL, 0); + if(PHYS_STATE == IDLE){ + FDebug(DBGLOG_NAME, 8, DBGLIST, NULL, NULL, 0); + return IGNORE_SIGNAL; + } + else{ + FDebug(DBGLOG_NAME, 3, DBGLIST, NULL, NULL, 0); + retval = FAbort(BO); + if(retval < 0){ + return SYSTEM_FAILURE; + } + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* void FDbgPESocketEventHandler(void_ptr_ clientData, int mask) +* +* DESCRIPTION: +* +* This function is passed to SetFDbgSocketEventHandler() together with the +* socket file descriptor PE_FD. When the socket becomes available for reading +* this function will be invoked. +* +* PARAMETERS: +* +* void_ptr_ clientData -- ?. +* int mask -- ?. +* +* RETURNS: +* +* void -- Nothing. +* +* GLOBALS: +* +* PE_FD references the socket connected to the service user. +* ALIST contains all signals and their respective function. +* ERRLIST contains all error codes and their respective text messages. +* +* NOTE: +* +* The function passed to SetFDbgSocketEventHandler() needs two in-parameters. +* The first must be of type void pointer and the second of type int. +* +*/ + +#ifdef __STDC__ +void FDbgPESocketEventHandler(void_ptr_ clientData, int mask) +#else + void FDbgPESocketEventHandler(clientData, mask) + void_ptr_ clientData; + int mask; +#endif +{ + int retval; + + retval = (* FindAction(ReadSignalfromSocket(PollSocket(PE_FD, SU_FD, NULL) \ + - 1 , SIG_LEN), ALIST))(); + if(retval < 0){ + ErrorHandler(FindErrMsgStr(3, ERRLIST)); + return ; + } + + return ; +} + +/****************************************************************************** +* +* FUNCTION: +* +* void FDbgSUSocketEventHandler(void_ptr_ clientData, int mask) +* +* DESCRIPTION: +* +* This function is passed to SetFDbgSocketEventHandler() together with the +* socket file descriptor SU_FD. When the socket becomes available for reading +* this function will be invoked. +* +* PARAMETERS: +* +* void_ptr_ clientData -- ?. +* int mask -- ?. +* +* RETURNS: +* +* void -- Nothing. +* +* GLOBALS: +* +* PE_FD references the socket connected to the service user. +* ALIST contains all signals and their respective function. +* ERRLIST contains all error codes and their respective text messages. +* +* NOTE: +* +* The function passed to SetFDbgSocketEventHandler() needs two in-parameters. +* The first must be of type void pointer and the second of type int. +* +*/ + +#ifdef __STDC__ +void FDbgSUSocketEventHandler(void_ptr_ clientData, int mask) +#else + void FDbgSUSocketEventHandler(clientData, mask) + void_ptr_ clientData; + int mask; +#endif +{ + int retval; + + retval = (* FindAction(ReadSignalfromSocket(SU_FD, SIG_LEN), ALIST))(); + if(retval < 0){ + ErrorHandler(FindErrMsgStr(3, ERRLIST)); + return ; + } + + return ; +} + +/****************************************************************************** +* +* FUNCTION: +* +* void CleanUp(void) +* +* DESCRIPTION: +* +* Closes all global socket file descriptors and removes all related files. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* void -- Nothing. +* +* GLOBALS: +* +* PATH is the file to which the socket connected to the service user, is +* bound. +* TMP_FD references the temporary socket needed when creating a server socket. +* PE_FD references the socket connected to the peer entity. +* SU_FD references the socket connected to the service user. +* +* NOTE: +* +*/ + +#ifdef __STDC__ +void CleanUp(void) +#else + void CleanUp() +#endif +{ + /* + We don't test any return values since this function is called just before + we exit the program so if we fail in closing any file descriptors we hope + that exit() will do it for us. + */ + unlink(F_PATH); + CloseFile(TMP_FD); + CloseFile(PE_FD); + CloseFile(SU_FD); + + return ; +} + +/****************************************************************************** +* +* FUNCTION: +* +* void ErrorHandler(str_ptr_ errormsg) +* +* DESCRIPTION: +* +* Handles system errors. If possible it logs the error specified by the +* character string parameter `errormsg', closes all global socket file +* descriptors, removes all related files and kills all processes in the same +* process group before it exits. +* +* PARAMETERS: +* +* str_ptr_ errormsg -- Pointer to a character string containing the error +* -- message that will be written to the log. +* +* RETURNS: +* +* void -- Nothing. +* +* GLOBALS: +* +* FATAL_ERROR_IN_PROGRESS indicates if a fatal error is in progress or not. +* ERRLIST contains all error codes and their respective text messages. +* +* NOTE: +* +*/ + +#ifdef __STDC__ +void ErrorHandler(string_ptr_ errmsg) +#else + void ErrorHandler(errmsg) + string_ptr_ errmsg; +#endif +{ + /* + FATAL_ERROR_IN_PROGRES works as a semaphore to prevent that a signal + is catched while we are terminating the program. + */ + FATAL_ERROR_IN_PROGRESS = 1; + + /* + We don't test any return values since this function is called just before + we exit the program so there is no need to take care of system failures + at this point. + */ + LogError(ERRLOG_NAME, errmsg); + CleanUp(); + kill(PROCESS_GROUP, SIGINT); + exit(NON_NORMAL_EXIT); + + return ; +} + +/****************************************************************************** +* +* FUNCTION: +* +* int InitSignalHandler(void (* handler)(int)) +* +* DESCRIPTION: +* +* Sets the signals SIGINT, SIGHUP, SIGQUIT and SIGTERM desposition, which is a +* pointer to a function taking an int and returning nothing. +* +* PARAMETERS: +* +* void (* handler)(int) -- Pointer to a function that takes an int and +* -- returns nothing, which is the signal handler +* -- that will be invoked when one of the signals +* -- are raised. +* +* RETURNS: +* +* int -- On success 0. +* -- Otherwise, -1. +* +* NOTE: +* +*/ + +#ifdef __STDC__ +int InitSignalHandler(void (* handler) __P((int))) +#else + int InitSignalHandler(handler) + void (* handler) __P((int)); +#endif +{ + if(SetSignalHandler(SIGINT, handler) < 0){ + return SYSTEM_FAILURE; + } + if(SetSignalHandler(SIGHUP, handler) < 0){ + return SYSTEM_FAILURE; + } + if(SetSignalHandler(SIGTERM, handler) < 0){ + return SYSTEM_FAILURE; + } + if(SetSignalHandler(SIGQUIT, handler) < 0){ + return SYSTEM_FAILURE; + } + + return SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* void SignalHandler(int signum) +* +* DESCRIPTION: +* +* Handles system signals. If a signal set by InitSignalHandler() is raised +* SignalHandler() catches that signal and if possible closes all global socket +* file descriptors, removes all related files and kills all processes in the +* same process group before it raises the signal again and lets the system +* handle the exit in it's default manner. +* +* PARAMETERS: +* +* int signum -- The signal that was catched. +* +* RETURNS: +* +* void -- Nothing. +* +* GLOBALS: +* +* FATAL_ERROR_IN_PROGRESS indicates if a fatal error is in progress or not. +* +* NOTE: +* +* `signum' is set to the value of the signal that was catched, automatically +* by the system. +* +*/ + +#ifdef __STDC__ +void SignalHandler(int signum) +#else + void SignalHandler(signum) + int signum; +#endif +{ + /* + FATAL_ERROR_IN_PROGRESS works as a semaphore preventing that several + signals will be catched at the same time. If it is set we just raise + the signal again and continue the termination of the program. + */ + if(FATAL_ERROR_IN_PROGRESS){ + raise(signum); + } + FATAL_ERROR_IN_PROGRESS = 1; + + /* + We don't test any return values since this function is called just before + we exit the program so there is no need to take care of system failures + at this point. + */ + CleanUp(); + + /* Set the signal's desposition to the default signal handler. */ + if(SetSignalHandler(signum, SIG_DFL) < 0){ + exit(NON_NORMAL_EXIT); + } + kill(PROCESS_GROUP, SIGINT); + if(raise(signum) < 0){ + exit(NON_NORMAL_EXIT); + } + + return ; +} + +/****************************************************************************** +* +* FUNCTION: +* +* void MainLoop(void) +* +* DESCRIPTION: +* +* Creates a client socket in the UNIX domain which will connect to the server +* socket bound to the file specified by the character-string parameter `path'. +* Then it will poll the socket connected to the peer entity and the socket +* connected to the service user for signals and take actions depending on the +* value of the signal inside an infinite loop. +* +* PARAMETERS: +* +* void -- None. +* +* RETURNS: +* +* void -- Nothing. +* +* GLOBALS: +* +* PE_FD references the socket connected to the peer entity. +* SU_FD references the socket connected to the service user. +* ALIST contains all signals and their respective function. +* ERRLIST contains all error codes and their respective text messages. +* +* NOTE: +* +*/ + +#ifdef __STDC__ +void MainLoop(void) +#else + void MainLoop() +#endif +{ + int retval; + + SU_FD = CreateUnixClientSocket(F_PATH); + if(SU_FD < 0){ + ErrorHandler(FindErrMsgStr(1, ERRLIST)); + return ; + } + SetFDbgSocketEventHandler(PE_FD, FDbgPESocketEventHandler); + SetFDbgSocketEventHandler(SU_FD, FDbgPESocketEventHandler); + FDbgMainLoop(); + /* + All actions are taken place in an infinite loop (gag) and execution has + to be terminated implicitly by the user by pressing CTRL D. We do this + since we simulate a peer to peer connection and we don't want to break + the socket connections everytime we start a new ( abstract ) connection + with the peer entity and the service user. + */ + do{ + retval = PollSocket(PE_FD, SU_FD, NULL); + if(retval < 0){ + ErrorHandler(FindErrMsgStr(9, ERRLIST)); + return ; + } + /* + We don't test the return value since a system failure will be + caught by FindAction. + */ + retval = ReadSignalfromSocket(retval - 1, SIG_LEN); + retval = (* FindAction(retval, ALIST))(); + if(retval < 0){ + ErrorHandler(FindErrMsgStr(3, ERRLIST)); + return ; + } + }while(retval >= 0); + + return ; +} + +/****************************************************************************** +* +* FUNCTION: +* +* void Server(int port) +* +* DESCRIPTION: +* +* Creates a server socket in the INET domain. The socket will listen for +* incoming connections on the port specified by the parameter `port'. Incoming +* connections are accepted and controll is passed to the main loop. +* +* PARAMETERS: +* +* int port -- Port on which the socket will listen for incoming +* -- connections. +* +* RETURNS: +* +* void -- Nothing. +* +* GLOBALS: +* +* TMP_FD references the temporary socket needed when creating a server socket. +* PE_FD references the socket that will connect to the peer entity. +* ERRLIST contains all error codes and their respective text messages. +* +* NOTE: +* +*/ + +#ifdef __STDC__ +void Server(int port) +#else + void Server(port) + int port; +#endif +{ + TMP_FD = CreateInetServerSocket(port); + if(TMP_FD < 0){ + ErrorHandler(FindErrMsgStr(5, ERRLIST)); + return ; + } + PE_FD = AcceptConnection(TMP_FD); + if(PE_FD < 0){ + ErrorHandler(FindErrMsgStr(6, ERRLIST)); + return ; + } + MainLoop(); + + return ; +} + +/****************************************************************************** +* +* FUNCTION: +* +* void Client(int port, string_ptr_ serv_id) +* +* DESCRIPTION: +* +* Creates a client socket in the INET domain which tries to connect to the +* port specified by the parameter `port' on the host specified by the +* character string parameter `serv_id' and then controll is passed to the main +* loop. +* +* PARAMETERS: +* +* int port -- Port which the socket will connect to. +* string_ptr_ serv_id -- Pointer to a character-string containing the +* -- hosts name or the hosts IP address. +* +* RETURNS: +* +* void -- Nothing. +* +* GLOBALS: +* +* PE_FD references the socket that will connect to the peer entity. +* ERRLIST contains all error codes and their respective text messages. +* +* NOTE: +* +*/ + +#ifdef __STDC__ +void Client(int port, string_ptr_ serv_id) +#else + void Client(port, serv_id) + int port; + string_ptr_ serv_id; +#endif +{ + PE_FD = CreateInetClientSocket(port, serv_id); + if(PE_FD < 0){ + ErrorHandler(FindErrMsgStr(7, ERRLIST)); + return ; + } + MainLoop(); + + return ; +} + +/****************************************************************************** +* +* FUNCTION: +* +* void main(int argc, char *argv[]) +* +* DESCRIPTION: +* +* The main program. Starts as server or client depending on the number +* of arguments given in the command line. +* +* PARAMETERS: +* +* int argc -- The number of arguments. +* char *argv[] -- Array of pointers to character strings. Every string is +* -- associated with one command line argument. +* +* RETURNS: +* +* void -- Nothing. +* +* GLOBALS: +* +* FAULT_PROBABILITY specifies the probability that a byte will get corrupted. +* DELAY_PROBABILITY specifies the probability of a transmission delay. +* LOSEBYTE_PROBABILITY specifies the probability of loosing a byte. +* ERRLIST contains all error codes and their respective text messages. +* +* NOTE: +* +*/ + +#ifdef __STDC__ +void main(int argc, char *argv[]) +#else + void main(argc, argv) + int argc; + char *argv[]; +#endif +{ + int retval, port; + + unlink(ERRLOG_NAME); + unlink(DBGLOG_NAME); + InitFDbg(&argc, argv); + CreateFDbgWindow(); + CreateFDbgHelpDbase(); + CreateFDbgHelpDbaseBrowser(); + if((argc != SERVER) && (argc != CLIENT)){ + ErrorHandler(FindErrMsgStr(9, ERRLIST)); + return ; + } + retval = InitSignalHandler(SignalHandler); + if(retval < 0){ + ErrorHandler(FindErrMsgStr(8, ERRLIST)); + return ; + } + FAULT_PROBABILITY = atof(argv[argc - RELFAULTPOS]); + retval = ValidateProbability(FAULT_PROBABILITY); + if(retval == INVALID){ + ErrorHandler(FindErrMsgStr(4, ERRLIST)); + return ; + } + DELAY_PROBABILITY = atof(argv[argc - RELDELAYPOS]); + retval = ValidateProbability(DELAY_PROBABILITY); + if(retval == INVALID){ + ErrorHandler(FindErrMsgStr(4, ERRLIST)); + return ; + } + LOSEBYTE_PROBABILITY = atof(argv[argc - RELLOSEBYTEPOS]); + retval = ValidateProbability(LOSEBYTE_PROBABILITY); + if(retval == INVALID){ + ErrorHandler(FindErrMsgStr(4, ERRLIST)); + return ; + } + port = atoi(argv[PORTPOS]); + if((port > MAX_PORT) || (port < MIN_PORT)){ + ErrorHandler(FindErrMsgStr(2, ERRLIST)); + return ; + } + if(argc == SERVER){ + Server(port); + } + else if(argc == CLIENT){ + Client(port, argv[HOSTNAMEPOS]); + } + + return; +} + +/****************************************************************************** +* END +*/ + + + + diff --git a/physlayer.h b/physlayer.h new file mode 100644 index 0000000..8c47195 --- /dev/null +++ b/physlayer.h @@ -0,0 +1,96 @@ +/****************************************************************************** +* +* (c) Copyright 1998, University of Karlstad. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 1, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* Please report any bugs you find in this code or any improvements to: +* +* Hans Hedbom, Dept. of Computer Science, +* University of Karlstad, Sweden. +* +* Phone: +46 54 838157 +* E-mail: Hans.Hedbom@hks.se +* +* ============================================================================ +* +* FILE: +* +* physlayer.h [ the Data Communication I course programming project ] +* +* AUTHORS: +* +* Jonny Wiederholm +* E-mail: fr7wied@cse.hks.se or +* jonnwied@hks.se +* +* Per-Ola Gustafsson +* E-mail: fr7gust@cse.hks.se +* +* CREATION DATE: +* +* Jan, 08, 1998 +* +* DESCRIPTION: +* +* Includes constants used in the implementation of the Physical Layer, which +* is part of the example implementation of the Data Communication I course +* programming project. +* +* MODIFICATIONS: Date Changes +* ---------------------------------------------------------------------------- +* +*/ + +#ifndef _PHYSLAYER_H /* Avoid multiple copies of this file. */ +#define _PHYSLAYER_H + +#ifdef __cplusplus /* Make this file possible to use in C++ code. */ +extern "C" { +#endif + +/****************************************************************************** +* INCLUDE FILES +*/ + +#include "systems.h" + +/****************************************************************************** +* DEFINE CONSTANTS +*/ + +/* Byte length. */ +#define BYTE_LEN 1 + +/* + Primitives (signals) not visible to the service user. The service user will + only be able to access these primitives via function calls. + */ +#define F_CONNECT_REQUEST 100 +#define F_CONNECT_RESPONSE 104 +#define F_DISCONNECT_REQUEST 108 +#define F_DISCONNECT_RESPONSE 112 +#define F_DATA_REQUEST 116 +#define F_ABORT_REQUEST 188 + +/****************************************************************************** +* END +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _PHYSLAYER_H */ diff --git a/signal_prim.h b/signal_prim.h new file mode 100644 index 0000000..b28561d --- /dev/null +++ b/signal_prim.h @@ -0,0 +1,48 @@ +#ifndef ___SIGNAL_PRIM___ +#define ___SIGNAL_PRIM___ + +#define L_Con_Req 401 +#define L_Con_Ind 402 +#define L_Con_Resp 403 +#define L_Con_Conf 404 +#define L_Data_Req 405 +#define L_Data_Ind 406 +#define L_Disc_Req 407 +#define L_Disc_Resp 408 +#define L_Disc_Ind 409 +#define L_Disc_Conf 410 +#define L_Abort_Req 411 +#define L_Abort_Ind 412 +#define L_Status 413 + +#define AF_Con_Req 201 +#define AF_Con_Ind 202 +#define AF_Con_Resp 203 +#define AF_Con_Conf 204 +#define AF_Data_Req 205 +#define AF_Data_Ind 206 +#define AF_Disc_Req 207 +#define AF_Disc_Ind 208 +#define AF_Disc_Resp 209 +#define AF_Disc_Conf 210 +#define AF_Rej_Req 211 +#define AF_Rej_Ind 212 +#define AF_Rej_Resp 213 +#define AF_Rej_Conf 214 +#define AF_Abort_Req 215 +#define AF_Abort_Ind 216 + +#define AI_Con_Req 301 +#define AI_Con_Ind 302 +#define AI_Con_Resp 303 +#define AI_Con_Conf 304 +#define AI_Data_Req 305 +#define AI_Data_Ind 306 +#define AI_Disc_Req 307 +#define AI_Disc_Ind 308 +#define AI_Disc_Resp 309 +#define AI_Disc_Conf 310 +#define AI_Abort_Req 311 +#define AI_Abort_Ind 312 + +#endif diff --git a/socketio.h b/socketio.h new file mode 100644 index 0000000..e7f9226 --- /dev/null +++ b/socketio.h @@ -0,0 +1,94 @@ +/****************************************************************************** +* +* (c) Copyright 1998, University of Karlstad. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 1, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* Please report any bugs you find in this code or any improvements to: +* +* Hans Hedbom, Dept. of Computer Science, +* University of Karlstad, Sweden. +* +* Phone: +46 54 838157 +* E-mail: Hans.Hedbom@hks.se +* +* ============================================================================ +* +* FILE: +* +* socketio.h [ the Data Communication I course programming project ] +* +* AUTHORS: +* +* Jonny Wiederholm +* E-mail: fr7wied@cse.hks.se or +* jonnwied@hks.se +* +* Per-Ola Gustafsson +* E-mail: fr7gust@cse.hks.se +* +* CREATION DATE: +* +* Jan, 05, 1998 +* +* DESCRIPTION: +* +* Includes declarations of functions needed to handle input and output to +* sockets in the example implementation of the Data Communication I course +* programming project. +* +* MODIFICATIONS: Date Changes +* +* ---------------------------------------------------------------------------- +* +*/ + +#ifndef _SOCKETIO_H /* Avoid multiple copies of this file. */ +#define _SOCKETIO_H + +#ifdef __cplusplus /* Make this file possible to use in C++ code. */ +extern "C" { +#endif + +/****************************************************************************** +* INCLUDE FILES +*/ + +#include "systems.h" +#include "udefs.h" + +/****************************************************************************** +* DECLARE FUNCTIONS +*/ + +/* See function definitions for documentation. */ + +extern int WriteSignaltoSocket __P((int sockfd, u_int_ signal, \ + size_t_ siglen)); +extern int ReadSignalfromSocket __P((int sockfd, size_t_ siglen)); +extern int WriteDatatoSocket __P((int sockfd, c_buf_ptr_ databuf, \ + size_t_ datalen)); +extern int ReadDatafromSocket __P((int sockfd, buf_ptr_ databuf, \ + size_t_ datalen)); + +/****************************************************************************** +* END +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _SOCKETIO_H */ diff --git a/sockets.h b/sockets.h new file mode 100644 index 0000000..f6e0d68 --- /dev/null +++ b/sockets.h @@ -0,0 +1,132 @@ +/****************************************************************************** +* +* (c) Copyright 1998, University of Karlstad. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 1, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* Please report any bugs you find in this code or any improvements to: +* +* Hans Hedbom, Dept. of Computer Science, +* University of Karlstad, Sweden. +* +* Phone: +46 54 838157 +* E-mail: Hans.Hedbom@hks.se +* +* ============================================================================ +* +* FILE: +* +* sockets.h [ the Data Communication I course programming project ] +* +* AUTHORS: +* +* Jonny Wiederholm +* E-mail: fr7wied@cse.hks.se or +* jonnwied@hks.se +* +* Per-Ola Gustafsson +* E-mail: fr7gust@cse.hks.se +* +* CREATION DATE: +* +* Jan, 06, 1998 +* +* DESCRIPTION: +* +* Includes constants, types and declarations of functions needed to create +* and connect sockets in the example implementation of the Data Communication +* I course programming project. +* +* MODIFICATIONS: Date Changes +* ---------------------------------------------------------------------------- +* +*/ + +#ifndef _SOCKETS_H /* Avoid multiple copies of this file. */ +#define _SOCKETS_H + +#ifdef __cplusplus /* Make this file possible to use in C++ code. */ +extern "C" { +#endif + +/****************************************************************************** +* INCLUDE FILES +*/ + +#include "systems.h" +#include "udefs.h" + +/****************************************************************************** +* DEFINE CONSTANTS +*/ + +#if defined (_AIX) || defined (__linux__) + +/* Communication semantics. */ +#define SOCK_STREAM 1 /* Stream socket. */ + +#elif defined (sun) + +#define SOCK_STREAM 2 + +#endif + +/* Communication domains. */ +#define AF_UNIX 1 /* Local to host (pipes, portals). */ +#define AF_INET 2 /* Internetwork: UDP, TCP, etc. */ + +/****************************************************************************** +* DEFINE TYPES +*/ + +#if defined (__linux__) || defined (sun) + +/* Structure used by kernel to store most addresses. */ +struct sockaddr { + unsigned short int sa_family; /* Address family AF_xxx. */ + char sa_data[14]; /* 14 bytes of protocol address. */ +}; + +#elif defined (_AIX) + +struct sockaddr { + unsigned char sa_len; /* Total length. */ + unsigned char sa_family; /* Address family AF_xxx. */ + char sa_data[14]; /* 14 bytes of protocol address. */ +}; + +#endif /* defined (__linux__) || defined (sun) */ + +/***************************************************************************** +* DECLARE FUNCTIONS +*/ + +/* See function definitions for documentation. */ + +extern int CreateSocket __P((int domain, int type, int protocol)); +extern int BindSocket __P((int sockfd, struct sockaddr *name, int namelen)); +extern int ConnectSocket __P((int sockfd, struct sockaddr *name, int namelen)); +extern int ListenforConnection __P((int sockfd, int limit)); +extern int AcceptConnection __P((int sockfd)); + +/****************************************************************************** +* END +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _SOCKETS_H */ diff --git a/state.h b/state.h new file mode 100644 index 0000000..b1f5cd5 --- /dev/null +++ b/state.h @@ -0,0 +1,12 @@ +#ifndef _state_h_ +#define _state_h_ + +#define IDLE 0 +#define UUUK 1 +#define DATA 2 +#define UUNK 3 +#define UINK 4 +#define UIUK 5 +#define TERR 6 + +#endif diff --git a/student.h b/student.h new file mode 100644 index 0000000..8d62f15 --- /dev/null +++ b/student.h @@ -0,0 +1,145 @@ +/****************************************************************************** +* +* (c) Copyright 1998, University of Karlstad. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 1, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* Please report any bugs you find in this code or any improvements to: +* +* Hans Hedbom, Dept. of Computer Science, +* University of Karlstad, Sweden. +* +* Phone: +46 54 838157 +* E-mail: Hans.Hedbom@hks.se +* +* ============================================================================ +* +* FILE: +* +* student.h [ the Data Communication I course programming project ] +* +* AUTHORS: +* +* Jonny Wiederholm +* E-mail: fr7wied@cse.hks.se or +* jonnwied@hks.se +* +* Per-Ola Gustafsson +* E-mail: fr7gust@cse.hks.se +* +* CREATION DATE: +* +* Jan, 08, 1998 +* +* DESCRIPTION: +* +* Includes header files, declaring the functions that are available +* and can be used in the Data Communication I course programming project. +* +* NOTE: +* +* If any system header files needs to be included in the same module as this +* file is included, make sure they are included before this file or otherwise +* it might not be possible to compile due to type redeclaration errors. +* +* MODIFICATIONS: Date Changes +* ---------------------------------------------------------------------------- +* +* 1998-03-16 Added the function FindAction. +* +*/ + +#ifndef _STUDENT_H /* Avoid multiple copies of this file. */ +#define _STUDENT_H + +#ifdef __cplusplus /* Make this file possible to include in C++ code. */ +extern "C" { +#endif + +/****************************************************************************** +* INCLUDE FILES +*/ + +#include "systems.h" +#include "udefs.h" +#include "sockets.h" +#include "socketio.h" +#include "unixsockets.h" +#include "uselect.h" +#include "utimer.h" + +/****************************************************************************** +* +* sockets.h: +* +* int AcceptConnection(int sockfd) +* +* socketio.h: +* +* int WriteSignaltoSocket(int sockfd, unsigned int signal, \ +* unsigned int siglen) +* int ReadSignalfromSocket(int sockfd, unsigned int siglen) +* int WriteDatatoSocket(int sockfd, char* databuf, unsigned int datalen) +* int ReadDatafromSocket(int sockfd, char* databuf, unsigned int datalen) +* +* unixsockets.h: +* +* int CreateUnixClientSocket(char *path) +* int CreateUnixServerSocket(char *path) +* +* uselect.h: +* +* struct timeval *SetPollTimeout(int seconds, int microseconds) +* int PollSocket(int sockfd1, int sockfd2, struct timeval *tv) +* +* utimer.h: +* +* void SetTimer(unsigned int seconds) +* void ResetTimer(void) +* int SetTimeoutHandler(void (*handler)(int)) +* +*/ + +/****************************************************************************** +* DEFINE TYPES +*/ + +/* Pointer to a function that takes nothing and returns an int. */ +typedef int (*psf) __P((void)); + +/* Struct defining the relationship between a signal and a function. */ +typedef struct action{ + int signal; + psf function; +} action; + +/****************************************************************************** +* DECLARE FUNCTIONS +*/ + +/* See function definitions for documentation. */ + +extern psf FindAction __P((int signal, const__ action *list)); + +/****************************************************************************** +* END +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _STUDENT_H */ + diff --git a/studlib.a b/studlib.a new file mode 100644 index 0000000000000000000000000000000000000000..2f40c688199e60d188f369ea5c3e952eb8cc07e6 GIT binary patch literal 15642 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 v@n>YiZGCmjuxrBm%@KIjEwa5a-#iUvLd