365 lines
9.7 KiB
C
365 lines
9.7 KiB
C
/* 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<len) x+=WriteDatatoSocket(lSock_fd,buf+x,len-x);
|
|
return 1;
|
|
}
|
|
|
|
void WriteDataToApp(char* buf,int len) {
|
|
int x;
|
|
WriteSigToApp(AF_Data_Ind);
|
|
if((x=WriteDatatoSocket(fSock_fd,buf,len))==-1) {
|
|
fprintf(stderr,"Write-error to application, quitting!\n\n");
|
|
exit(13);
|
|
}
|
|
else
|
|
while(x<len) x+=WriteDatatoSocket(lSock_fd,buf+x,len-x);
|
|
}
|
|
|
|
int doSigPacket(int flag) {
|
|
char head[3];
|
|
head[0]=2;
|
|
head[1]=0;
|
|
head[2]=IsFTP | flag;
|
|
return WriteDataToLink(head,SIGPACKLEN);
|
|
}
|
|
|
|
int ConnToLinker() {
|
|
WriteSigToLink(L_Con_Req);
|
|
Polla(lSock_fd,lSock_fd);
|
|
switch(ReadSignalfromSocket(lSock_fd,SIGPACKLEN)) {
|
|
case L_Con_Conf:
|
|
return 1;
|
|
case L_Abort_Ind:
|
|
cancel(AF);
|
|
return 0;
|
|
default:
|
|
cancel(AF);
|
|
cancel(L);
|
|
return 0;
|
|
} }
|
|
|
|
void DiscFromLinker() {
|
|
WriteSigToLink(L_Disc_Req);
|
|
Polla(lSock_fd,lSock_fd);
|
|
if(ReadSignalfromSocket(lSock_fd,SIGPACKLEN)!=L_Disc_Conf) {
|
|
cancel(AF);
|
|
cancel(L);
|
|
} }
|