/* * File: server_tcp.c * Author: Arthur Brandao * * Created on 14 novembre 2018 */ #include #include #include #include #include #include "error.h" #include "server.h" /* --- Extern --- */ extern int serrno; extern int errno; /* --- Fonctions privées --- */ boolean server_bind_tcp(Server this, int port) { /* Declaration variable */ int tmp; /* Bind */ this->serv.sin_family = AF_INET; this->serv.sin_port = htons(port); this->serv.sin_addr.s_addr = htonl(INADDR_ANY); tmp = bind(this->socket, (struct sockaddr*) &this->serv, sizeof (struct sockaddr_in)); if (tmp == ERR) { free(this); serrno = SEBIND; addperror("Impossible de bind la socket"); return false; } /* Listen */ tmp = listen(this->socket, SOMAXCONN); if (tmp == ERR) { free(this); serrno = SEBIND; addperror("Impossible d'ecouter"); return false; } return true; } boolean server_accept_tcp(Server this) { /* Accept */ this->socket_client = accept(this->socket, NULL, NULL); if (this->socket_client == ERR) { serrno = SEACCEPT; addperror("Impossible d'accepter"); return false; } return true; } ssize_t server_receive_tcp(Server this, char* buf, size_t size) { int tmp; /* Lecture message */ memset(buf, 0, size); tmp = read(this->socket_client, buf, size); if (tmp == ERR) { serrno = SERECEIVE; addperror("Impossible de récupèrer les données"); return ERR; } //Si on continue sans avoir modifier buffer (et donc un read non bloquant) signe d'une deconnexion if(buf[0] == '\0'){ serrno = SEABORT; adderror("Aucune données émise par le client"); return ERR; } return tmp; } boolean server_send_tcp(Server this, char* msg) { int tmp; /* Envoi message */ tmp = write(this->socket_client, msg, strlen(msg) * sizeof (char)); if (tmp == ERR) { //Si connexion coupé (et SIGPIPE) if(errno == EPIPE){ serrno = SEABORT; } else { serrno = SESEND; } addperror("Impossible d'envoyer les données"); return false; } return true; } /* --- Fonctions publiques --- */ Server server_create_tcp() { /* Declaration variable */ Server this; int tmp, option; /* Creation socket */ this = malloc(sizeof (struct server)); this->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (this->socket == ERR) { free(this); serrno = SESOCKET; addperror("Impossible de créer la socket"); return NULL; } this->addr = sizeof (struct sockaddr_in); memset(&this->serv, 0, sizeof (struct sockaddr_in)); /* Indique la possibilité de réutiliser la socket même si elle est en TIME_WAIT */ option = 1; tmp = setsockopt(this->socket, SOL_SOCKET, SO_REUSEADDR, &option, sizeof (option)); if (tmp == -1) { free(this); serrno = SESOCKET; addperror("Impossible de modifier les options de la socket"); return NULL; } /* Lien fonctions */ this->server_bind = server_bind_tcp; this->server_receive = server_receive_tcp; this->server_send = server_send_tcp; this->server_accept = server_accept_tcp; /* Type de serveur */ this->type = SERV_TCP; /* Retour */ return this; } boolean server_close_client(Server this) { /* Que pour TCP */ if (this->type != SERV_TCP) { serrno = SETYPE; adderror("Type de la socket incorrect"); return false; } /* Ferme */ if (close(this->socket_client) == ERR) { serrno = SECLOSE; addperror("Impossible de fermer la socket"); return false; } return true; }