Skip to content
This repository was archived by the owner on Nov 4, 2023. It is now read-only.

chat : server : server.c\.h

sᴀʟᴠᴀᴛᴏʀᴇ ʙ edited this page Jul 23, 2017 · 1 revision

server.h

// file descriptor del server
extern int server_pipe;
extern char* server_pipe_path;

void start();
void stop();
void getClientPipePath(pid_t pid, char* bufferPath);
int readCommand(char **str);
void getFirstField(char keyword[20], char* cmd);
void getPidFromCmd(char* cmd, pid_t* pid);
int getPipeByPid(pid_t pid, Client* head);
Client* getLastClient(Client *head);

server.c

void start() {
	createPipe(server_pipe_path);
	openServerPipe();

	// l'apertura non deve essere bloccante, ma le successive read sì, perciò modifico i flag
	int saved_flags = fcntl(server_pipe, F_GETFL);
	// maschero O_NONBLOCK
	fcntl(server_pipe, F_SETFL, saved_flags & (~O_NONBLOCK));
}

La funzione start() richiama la creazione ed apertura della server_pipe, infine modifica i flag del descrittore del file in modo che le successive read siano bloccanti.

void openServerPipe() {
	/* apertura della server_pipe in lettura e ovviamente
	 * non bloccante, dato che non è necessario che esistano client gia' in attesa*/
	server_pipe = open(server_pipe_path, O_RDONLY | O_NONBLOCK);
	if (server_pipe == -1) {
		printf("\n[ERROR] (%s) Pipe creata ma inutilizzabile",
				server_pipe_path);
	} else if (verboseMode == 1) {
		printf("\n[LOG] %s: pipe pronta all'utilizzo", server_pipe_path);
		fflush(stdout);
	}
}
 void stop() {
	closeConnection(server_pipe, server_pipe_path);
}
/* Ritorna il nome completo della pipe di un client
 * pid + "_client_pipe" */
void getClientPipePath(pid_t pid, char* bufferPath) {
	sprintf(bufferPath, "./%d%s", pid, "_client_pipe");
}
/* Ritorna un puntatore all'ultimo client della lista */
Client* getLastClient(Client *head) {
	if (head == NULL) {
		return NULL;
	}
	Client *last = head;
	while (last->next != NULL) {
		last = last->next;
	}
	return last;
}
/*
 * Legge il comando ricevuto in server_pipe, inserendolo in "str"
 * Restituisce 1 se è presente un comando nella stringa, altrimenti 0
 */
int readCommand(char **str) {
	int dim = 512;
/* non essendo possibile prevedere la lunghezza massima del messaggio ricevuto
	 * si alloca dinamicamente lo spazio del buffer
	 */
	*str = realloc(*str, sizeof(char) * dim);
	char* temp = *str;
	int n, count = 0;
	do { // Legge fino a '\0' o EOF
		/*
	* Nota: la read è bloccante fino a che c'è almeno un client connesso,
		 * altrimenti legge EOF ed esce, rientrando ed uscendo all'infinito.
		 */
		n = read(server_pipe, temp, 1);
		if (n != 0) {
			count++;
			if (count == dim) {
				//rialloco il doppio della dimensione precedente
				temp = realloc(temp, sizeof(char) * (dim * 2));
				dim *= 2;
				temp += (count - 1); //riposiziono il puntatore
			}
		} else {
			**str = '\0';
		}
	} while (n > 0 && *temp++ != '\0');
	return n;
}

La funzione readCommand() salva in un buffer temporaneo ogni singolo carattere letto dalla server_pipe, non essendo nota la dimensione si allocano inizialmente 512 byte, che vengono raddoppiati se il messaggio risulta più lungo (che sarà comunque minore o uguale a 4096 byte)

/*
 * Acquisisce il primo campo della stringa ricevuta,
 * ovvero la keyword che identifica il tipo di comando e
 * la inserisce nella variabile keyword
 */
void getFirstField(char keyword[20], char* cmd) {
	int i = 0;
	while (*cmd != ' ' && *cmd != '\0') {
		keyword[i] = *cmd;
		cmd++;
		i++;
	}
	keyword[i] = '\0';
}
/*
 * Ottiene il pid dai comandi con la seguente sintassi
 * "<COMMAND> <pid>"
 */
void getPidFromCmd(char* cmd, pid_t* pid) {
	int i = 0;
	char temp[20];
// raggiungo il primo spazio
	while (*cmd != ' ') {
		cmd++;
	}
	cmd++;
// copio il pid
	while (*cmd != '\0') {
		temp[i] = *cmd;
		cmd++;
		i++;
	}
	temp[i] = '\0';
	*pid = strtol(temp, NULL, 10);
}

La funzione getPidFromCmd è utilizzabile per i comandi come LIST, CONNECT e DISCONNECT, i quali sono seguiti dal pid del client interessato.

/* Ottiene il file descriptor della pipe del client individuato da pid.
 * Restituisce 0 se il client non esiste, altrimenti restituisce il fd.*/
int getPipeByPid(pid_t pid, Client* head) {
	if (head == NULL) {
		return 0;
	} else {
		int found = 0;
		do {
			if (head->pid == pid)
				// il valore della pipe sarà sicuramente diverso da 0
				found = head->pipe;
			head = head->next;
		} while (found == 0 && head != NULL);
		return found;
	}
}

Clone this wiki locally