/* 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