Demo entry 6628169

a

   

Submitted by anonymous on Jul 01, 2017 at 20:02
Language: C. Code size: 10.0 kB.

/*  
    Martino Godswill Essuman - N86/456
    Progetto di Laboratorio di Sistemi Operativi I - prof. C. Galdi
    FTP Mirror
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <fcntl.h> 
#include <sys/stat.h> 
#include <sys/types.h>
#include <dirent.h> 
#include <sys/param.h> //MAXPATHLEN
#include <sys/types.h>

//headers
#include "utility.h"

void send_welcome(int cli_fd);   //invia il benvenuto ad un nuovo client che si collega al server
void send_menu(int cli_fd);      //invia il menù utente ad un client
int comando_valido(char *str);  //verifica se in str sono presenti comandi accettati
void list(char *path, char *nomefile, int receiver);
void client_disconnesso(struct sockaddr_in client); //stampa un messaggio quando il client si disconnette
void disconnection_handler(int sig);

int main(int argc, char *argv[]){ // 1)numero porta  2)directory di servizio
    int sock_fd, 
        cli_fd,
        port=0, 
        pid;
    char *servicedir, 
        buf[MAX_BUF],
        comando_nomefile[MAX_BUF],
        *comando,
        *nomefile;
    struct sockaddr_in server, client; 
    socklen_t len; 
    struct stat st;

    //definizione parametri connessione
    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = htonl(INADDR_ANY);

    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if( sock_fd<0 ){
        perror("");
        close(sock_fd);
        mywrite(RED"Errore creazione socket\n"RESET);
    }

    if(argv[1])
        port = atoi(argv[1]);

    while(1){
        if( port<=0 ) {   // n. porta non valido
            mywrite(RED"ERRORE: porta già in uso/non valida\n\nPrego inserire un numero porta valido: "RESET);
            empty_buff(buf, MAX_BUF);
            read(STDIN_FILENO, buf, MAX_BUF);
            buf[strlen(buf)-1] = '\0';
            port = atoi(buf);
            mywrite("\n");
        }

        server.sin_port = htons(port);

        int option=1; 
        if( setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option))<0 ) {    //per poter riutilizzare subito il server dopo disconnessione
            perror("");
            mywrite(RED"Errore impostazioni socket\n"RESET); 
            port=0;
            continue;
        }

        if( bind(sock_fd, (struct sockaddr*)&server, sizeof(server))<0){
            port=0;
        }
        else
            break;
    }


    if(argv[2]){
        servicedir = (char*)malloc(sizeof(char)* strlen(argv[2]));
        strcpy(servicedir, argv[2]); 
    }
    
    if(stat(servicedir, &st)<0){    //controlla se esiste cartella specificata da commandline
        do{
            mywrite(RED"ERRORE: cartella inesistente!\nPrego inserire cartella valida per continuare: "RESET);
            empty_buff(buf, MAX_BUF);
            read(STDIN_FILENO, buf, MAX_BUF);
            buf[strlen(buf)-1] = '\0';
            mywrite("\n");
        }
        while(stat(buf, &st)<0);

        servicedir = (char*)malloc(sizeof(char)* MAX_BUF);
        strcpy(servicedir, buf);
    }


    mywrite(CYN"\nCartella di servizio selezionata:  \n");
    mywrite(servicedir);
    mywrite("\n\n"RESET);

    
    if( listen(sock_fd, 50)<0 ) perror("->ERRORE LISTEN: "), exit(-1);
        mywrite(GRN"In ascolto...\n"RESET);

    while(1){
        //accept client
        len = sizeof(struct sockaddr_in);
        cli_fd=accept(sock_fd, (struct sockaddr*)&client, &len);
        if( cli_fd<0 ) {
            mywrite(RED"Errore di comunicazione!\n"RESET);
            exit(-1);
        }

        empty_buff(buf, MAX_BUF);
        sprintf(buf, GRN"Client %s connesso\n"RESET, inet_ntoa(client.sin_addr));
        mywrite(buf);

        if( (pid=fork())<0 ){
            perror("->ERRORE FORK: "); 
            client_disconnesso(client);
            continue;
        }
        if(pid==0){     //client

            empty_buff(buf, MAX_BUF);
            sock_read(cli_fd, buf, MAX_BUF);    //READY
            send_welcome(cli_fd);               //invia benvenuto 

            while(1){
                empty_buff(buf, MAX_BUF);
                sock_read(cli_fd, buf, MAX_BUF);    //READY
                send_menu(cli_fd);                  //invia menu
                mywrite(MAG"Attendo comando...\n"RESET);

                empty_buff(comando_nomefile, MAX_BUF);
                sock_read(cli_fd, comando_nomefile, MAX_BUF);    //riceve comando

                comando = strtok(comando_nomefile, " \n");    //estraggo comando
                nomefile = strtok(NULL, "\n");               //estraggo nomefile
                
                if( comando_valido(comando)==1 ){
                    if(strcasecmp(comando, "exit")==0 ){
                        sock_write(cli_fd, VALID_COMMAND, strlen(VALID_COMMAND));   //invia "comando valido"
                        break;
                    }
                    else if(!nomefile){ 
                        sock_write(cli_fd, INVALID_COMMAND, strlen(INVALID_COMMAND));   //invia "comando non valido"
                        mywrite(INVALID_COMMAND);
                        mywrite("\n");
                        continue;
                    }

                    sock_write(cli_fd, VALID_COMMAND, strlen(VALID_COMMAND));   //invia "comando valido"


                    if(strcasecmp(comando, "list")==0){
                        empty_buff(buf, MAX_BUF);
                        sock_read(cli_fd, buf, MAX_BUF);    //READY
                        list(servicedir, nomefile, cli_fd);                 
                        sock_write(cli_fd, END_SEQUENCE, strlen(END_SEQUENCE)); //fine list
                    }
                    else if(strcasecmp(comando, "get")==0){
                        empty_buff(buf, MAX_BUF);
                        sock_read(cli_fd, buf, MAX_BUF);    //READY
                        mysend(servicedir, nomefile, cli_fd);
                        
                    }
                    else if(strcasecmp(comando, "put")==0){
                        chdir(servicedir);    //sarà tutto scaricato nella cartella di download
                        empty_buff(buf, MAX_BUF);
                        sock_read(cli_fd, buf, MAX_BUF);   //READY
                        sock_write(cli_fd, READY, strlen(READY));  //synch
                        prepare(cli_fd);
                        sock_write(cli_fd, READY, strlen(READY));   //synch
                        chdir("..");
                    }                    

                }
                else{
                    sock_write(cli_fd, INVALID_COMMAND, strlen(INVALID_COMMAND));   //invia "comando non valido"
                    mywrite(INVALID_COMMAND);
                    mywrite("\n");
                    continue;
                }

            }

            client_disconnesso(client);
            close(cli_fd);
            exit(1);
        }
        else{   //server
            close(cli_fd);
        }

    }
    
    close(sock_fd);
}


void send_welcome(int cli_fd){
    char buf[MAX_BUF];

    sprintf(buf, MAG"@@@ Benvenuto nel server! @@@\n"RESET);
    sock_write(cli_fd, buf, strlen(buf));
}

void send_menu(int cli_fd){
    char buf[MAX_BUF];

    sprintf(buf, MAG "### MENU' ###" RESET "\nNb: Omettere le parentesi angolari\nInserire il nome del file includendo l'estensione.\n\n"MAG"• List <nomefile>" RESET " - Se <nomefile> è un file, ne visualizza la dimensione; se è una directory visualizza l'elenco dei file in essa.\n"MAG"• Get <nomefile>"RESET " - Scarica <nomefile> dal server.\n"MAG"• Put <nomefile> "RESET " - Carica <nomefile> sul server.\n"MAG "• Exit"RESET " - Termina connessione\n\n");
    sock_write(cli_fd, buf, strlen(buf));
}

int comando_valido(char *str){
    return ( (strcasecmp(str, "list")==0) || (strcasecmp(str, "get")==0) || (strcasecmp(str, "put")==0) || (strcasecmp(str, "exit")==0) );
}


void list(char *path, char *filename, int receiver){  
    DIR *dp;
    struct dirent *d;
    struct stat st;
    char statpath[MAXPATHLEN], filepath[MAXPATHLEN], buf[MAX_BUF];

    sprintf(statpath, "%s/%s", path, filename);

    if( stat(statpath, &st)<0 ){
        sock_write(receiver, FILE_NOT_FOUND, strlen(FILE_NOT_FOUND));
        mywrite(FILE_NOT_FOUND);
        mywrite("\n");
        empty_buff(buf, MAX_BUF);
        sock_read(receiver, buf, MAX_BUF);    //READY
        return;
    }
    else{

        if(S_ISREG(st.st_mode)){    //client chiede singolo file
            sprintf(buf, "%s\t%d Byte", filename, (int)st.st_size);
            sock_write(receiver, buf, strlen(buf));
            empty_buff(buf, MAX_BUF);
            sock_read(receiver, buf, MAX_BUF);  //riceve permesso per continuare
        }
        else if(S_ISDIR(st.st_mode)){   //client chiede cartella

            dp = opendir(statpath);

            while( (d=readdir(dp)) ){
                if(is_hidden(d->d_name)!=0)  //salta i file nascosti
                    continue;

                empty_buff(statpath, MAXPATHLEN);
                sprintf(statpath, "%s/%s/%s", path, filename, d->d_name);   //ricreo percorso file
                stat(statpath, &st);
                empty_buff(buf, MAX_BUF);
                sprintf(buf, "%s\t%d Bytes", d->d_name, (int)st.st_size);
                sock_write(receiver, buf, strlen(buf));     //invio nome file + dimensione

                empty_buff(buf, MAX_BUF);
                sock_read(receiver, buf, MAX_BUF);     //riceve permesso per continuare
            }

            closedir(dp);
        }
        else{
            sock_write(receiver, FILE_UNKNOWN_TYPE, strlen(FILE_UNKNOWN_TYPE));
            mywrite(FILE_UNKNOWN_TYPE);
            mywrite("\n");
            empty_buff(buf, MAX_BUF);
            sock_read(receiver, buf, MAX_BUF);    //READY
            return; 
        }
    }

    mywrite(GRN"Risposta inviata\n"RESET);
    return;
}




void client_disconnesso(struct sockaddr_in client){
    char buf[MAX_BUF];

    sprintf(buf, GRN "Client %s disconnesso\n" RESET, inet_ntoa(client.sin_addr));
    mywrite(buf);
}

This snippet took 0.02 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).