Startpunkten

This commit is contained in:
2026-03-05 13:37:25 +01:00
commit 00233de938
22 changed files with 4613 additions and 0 deletions

362
ftp_app.c Normal file
View 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");