Startpunkten
This commit is contained in:
362
ftp_app.c
Normal file
362
ftp_app.c
Normal file
@@ -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");
|
||||
Reference in New Issue
Block a user