Riferimenti per il file server.c

#include "Include/server.h"
#include <fcntl.h>
#include <sys/stat.h>
#include "common.h"
#include "comandi.h"
#include "lista.h"
#include "../../../Fat/Src/Include/fat.h"
#include "../../../Fat/Src/Include/load_fat.h"

Vai al codice sorgente di questo file.

Funzioni

int main (int argc, char **argv)
void gestore (int sig)

Descrizione dettagliata

Autore:
Tranchida Giulio, No Matricola 241732
Si dichiara che il contenuto di questo file e', in ogni sua parte, opera originale dell'autore.

This program is free software; you can redistribuite it and/or modify it under the terms of the GNU/General Pubblic License as published the Free software Foundation; either version 2 of the License, or (at your opinion) any later version.

Definizione nel file server.c.


Documentazione delle funzioni

int main ( int  argc,
char **  argv 
)

Main / Dispather

  • Registro il mio gestore e la mia maschera dei segnali,
  • Controllo che il filesystem esista, che sia un file regolare e lo monto,
  • Creo la socket,
  • Entro in un ciclo infinito in cui riamango in attesa di una connessione da parte di un nuovo client,
  • Una volta che un nuovo client ha stabilito una connessione, creo un thread che gestira' le comunicazioni tra quel client e il server
  • La condizione di uscita dal ciclo e' quitflag != 0, impostato ad 1, esclusivamente nel gestore dei segnali.
  • Una volta uscito dal ciclo, attendo la chiusura di ogni thread attivo,
  • Chiudo la socket e la elimino fisicamente dal filesystem.
  • Libero le ultime risorse allocate ed esco.

Definizione alla linea 30 del file server.c.

00030                                 {
00031         extern FILE * fs;
00032         extern struct fat_ctrl f_ctrl;
00033         extern int num_threads;
00034         extern pthread_mutex_t lock;
00035         extern serverChannel_t sk_ascolto;
00036         extern struct lista my_socket;
00037         struct sigaction action;
00038         pthread_attr_t pta;     
00039         pthread_t tid=0;        
00040         sigset_t set;           
00041         channel_t sk_cl;        
00042         char * path;            
00043         struct stat buf;
00044         int err;
00045 
00046         path = NULL; fs = NULL; f_ctrl.fat_ptr = NULL;
00047         sk_ascolto = 0; num_threads = 0; quitflag = 0;
00048 
00049         /* ========= Gestione dei segnali ========= */
00050         /* Blocco i segnali */
00051         if (sigfillset(&set) == -1){
00052         errore(__FILE__,__LINE__,"Server: error sigfillset",errno);
00053         return EXIT_FAILURE;
00054         }
00055         if (pthread_sigmask(SIG_SETMASK, &set, NULL) != 0) {
00056                 errore(__FILE__,__LINE__,"Server: pthread_sigmask error 'sigsetmask'",errno);
00057                 return EXIT_FAILURE;
00058         }
00059         /* Installo il nuovo gestore */
00060         memset(&action, sizeof(action), 0);
00061         if (sigemptyset(&action.sa_mask) == -1){
00062         errore(__FILE__,__LINE__,"Server: error sigemptyset",errno);
00063         return EXIT_FAILURE;
00064         }
00065         /* Ignoro il SIGPIPE */
00066         action.sa_handler = SIG_IGN;
00067         if (sigaction(SIGPIPE, &action, NULL) == -1) {
00068                 errore(__FILE__,__LINE__, "Server: sigaction error 'SIGPIPE'", errno);
00069                 exit(EXIT_FAILURE);
00070         }
00071         action.sa_handler = gestore;
00072         action.sa_flags = 0;
00073         /* Definisco i segnali che voglio gestire */
00074         if (sigaction(SIGINT, &action, NULL) < 0){
00075                 errore(__FILE__,__LINE__,"Server: sigaction error 'SIGINT'",errno);
00076                 return EXIT_FAILURE;
00077         }
00078         if (sigaction(SIGTERM, &action, NULL) < 0){
00079         errore(__FILE__,__LINE__,"Server: sigaction error 'SIGTERM'",errno);
00080         return EXIT_FAILURE;;
00081         }
00082         /* Installo la nuova maschera dei segnali */
00083         if (pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL) != 0) {
00084                 errore(__FILE__,__LINE__,"Server: pthread_sigmask error 'sigsetmask'",errno);
00085                 return EXIT_FAILURE;
00086         }
00087 
00088         /* ========= Filesystem ========= */
00089         /* Argomento da riga di comando */
00090         if (argc<2) {
00091                 fprintf(stderr,"Server: errore non e' stato passato alcun filesystem\n");
00092                 return EXIT_FAILURE;
00093         }
00094         /* Esiste il file? */
00095         if (lstat(argv[1], &buf) < 0) {
00096                 errore(__FILE__,__LINE__, "Server: error filesystem",errno);
00097                 return EXIT_FAILURE;
00098         }
00099         /* E' un file regolare? */
00100         if (!(S_ISREG(buf.st_mode))) {
00101                 fprintf(stderr,"Server: error %s is not a regular file\n",argv[1]);
00102                 return EXIT_FAILURE;
00103         }
00104         /* Apro in lettura e scrittura il filesystem */
00105         if (!(fs = fopen(argv[1], "r+"))) {
00106                 errore(__FILE__,__LINE__, "Server: error on open filesystem",errno);
00107                 return EXIT_FAILURE;
00108         }
00109         /* Monto il filesystem */
00110         if ((err = mount_fat(fs, &f_ctrl)) != 0){ fclose(fs); return err; }
00111 
00112         /* ========= Attributi dei thread ========= */
00113         if (pthread_attr_init(&pta)!=0) {
00114                 errore(__FILE__,__LINE__,"Server: error pthread_attr_init",errno);
00115                 fclose(fs);
00116                 return EXIT_FAILURE;
00117         }
00118         /* I nuovi thread che andro' a creare saranno' gia' nello stato 'DETACHED' */
00119         if (pthread_attr_setdetachstate(&pta, PTHREAD_CREATE_DETACHED)!=0) {
00120                 errore(__FILE__,__LINE__,"Server: error pthread_attr_setdetachstate",errno);
00121                 fclose(fs); pthread_attr_destroy(&pta);
00122                 return EXIT_FAILURE;
00123         }
00124 
00125         /* Inizializzo la lista dei thread */
00126         inizializza (&my_socket);
00127 
00128         /* ========= Socket ========= */
00129         if (!(path = calloc((strlen(TMP) + strlen(SKTNAME) + 1), sizeof(char)))) {
00130                 errore(__FILE__,__LINE__, "Server: error on allocate memory for 'path'",errno);
00131                 free(f_ctrl.fat_ptr); fclose(fs); pthread_attr_destroy(&pta);
00132                 return EXIT_FAILURE;
00133         }
00134         strncpy(path,TMP,strlen(TMP));
00135         strncat(path,SKTNAME,strlen(SKTNAME));
00136         if ((lstat(path, &buf) == 0) && (unlink(path) < 0))
00137                 errore(__FILE__,__LINE__,"Server: socket unlink",errno);
00138         /* Creo la socket di ascolto del server */
00139         if ((sk_ascolto = createServerChannel(path)) == -1) exit(-1);
00140         else if (sk_ascolto == SFATENAMETOOLONG) {
00141                 fprintf(stderr,"Error Path Too Long (exceeding UNIX_PATH_MAX)\n");
00142                 free(f_ctrl.fat_ptr); free(path); fclose(fs); pthread_attr_destroy(&pta);
00143                 return EXIT_FAILURE;
00144         }
00145 
00146         /* ========= Ciclo di ascolto delle richieste ========= */
00147         while (!quitflag) {
00148                 /* Pongo il server in attesa di nuove connessioni da parte dei client */
00149                 if ((sk_cl = acceptConnection(sk_ascolto)) < 0) break;
00150                 else {
00151                         /* Solo se non ho gia' raggiunto il numero massimo di thread fissato */
00152                         pthread_mutex_lock(&lock);
00153                         while (num_threads == THREAD_MAX)
00154                                 pthread_cond_wait(&wait_me, &lock);
00155                         /* Creo un nuovo elemento della lista dei socket.
00156                          * Il nuovo elemento verra' inserito alla testa della lista */
00157                         num_threads++;
00158                         if (ins_new_elem(sk_cl, &my_socket)) break;
00159                         pthread_mutex_unlock(&lock);
00160                         /* Creo un nuovo thread */
00161                         if (pthread_create(&tid, &pta, thread_servernte,
00162                                         &(my_socket.top_elem->sk_cl))) {
00163                                 errore(__FILE__,__LINE__, "Server: error pthread_create",errno);
00164                                 break;
00165                         }
00166                 }
00167         }
00168 
00169         /* Aspetto la chiusura di ogni thread aperto */
00170         pthread_mutex_lock(&lock);
00171         while (num_threads != 0)
00172                 pthread_cond_wait(&wait_me, &lock);
00173         pthread_mutex_unlock(&lock);
00174 
00175         /* Chiudo la socket del server */
00176         closeSocket(sk_ascolto);
00177 
00178         /* Elimino la socket dal filesystem (se esiste) */
00179         if ((lstat(path, &buf) == 0) && (unlink(path) < 0))
00180                 errore(__FILE__,__LINE__,"Server: socket unlink",errno);
00181 
00182         /* Libero le risorse allocate */
00183         free(path); free(f_ctrl.fat_ptr); fclose(fs); pthread_attr_destroy(&pta);
00184 
00185         exit(EXIT_FAILURE);
00186 }

void gestore ( int  sig  ) 

Il mio gestore dei segnali
Stampa a monitor il codice del segnale ricevuto se questo e' SIGTERM o SIGINT e mette quitflag a 1, altrimenti se e' un SIGPIPE non fa nulla.

Parametri:
sig codice del segnale ricevuto

Definizione alla linea 196 del file server.c.

00196                       {
00197         switch (sig) {
00198                 case SIGTERM:
00199                         write(2, "server: signal 15 detected\n", 27);
00200                         quitflag = 1;
00201                 break;
00202                 case SIGINT:
00203                         write(2, "server: signal 2 detected\n", 26);
00204                         quitflag = 1;
00205                 break;
00206         }
00207 }

Generato il Fri Jan 28 22:16:29 2011 per SFAT: Simplified File Allocation Table Project da  doxygen 1.6.3