summaryrefslogtreecommitdiff
path: root/app/v3_c/src/tcpserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/v3_c/src/tcpserver.c')
-rw-r--r--app/v3_c/src/tcpserver.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/app/v3_c/src/tcpserver.c b/app/v3_c/src/tcpserver.c
new file mode 100644
index 0000000..53b86a9
--- /dev/null
+++ b/app/v3_c/src/tcpserver.c
@@ -0,0 +1,118 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "utils.h"
+#include "tcpserver.h"
+#include "dispatcher.h"
+
+int end=0;
+
+void _signals(int signum) {
+ static int force=0;
+
+ if (0) printf("signal %i\n", signum);
+
+ if(!force) {
+ end=1;
+ force=1;
+ logs("Tentative d'arrêt soft du serveur...");
+ } else {
+ logs("Arrêt d'urgence du serveur");
+ exit(1);
+ }
+}
+
+
+int tcpserver() {
+ int res;
+ int sockServ, sockCli;
+ struct sockaddr_in servAddr, cliAddr;
+ socklen_t cliAddrLen;
+
+ // Création socket
+ sockServ = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockServ < 0) { perror("socket"); return(2); }
+
+ // Accrochage du socket (adresse et port locaux)
+ bzero((char *) &servAddr, sizeof(servAddr));
+ servAddr.sin_family = AF_INET;
+ servAddr.sin_addr.s_addr = INADDR_ANY;
+ servAddr.sin_port = htons(LISTEN_PORT);
+ res=bind(sockServ, (struct sockaddr *) &servAddr, sizeof(servAddr));
+ if (res < 0) { perror("bind"); return(3); }
+
+ // On lance l'écoute
+ listen(sockServ,LISTEN_BACKLOG);
+ if (res < 0) { perror("listen"); return(4); }
+
+ // On active la gestion des signaux
+ signal(2,_signals);
+
+ res=initDispatcher();
+ if (res != 0 ) {
+#ifdef DEBUG
+ logs("initDispatcher() error");
+#endif
+ return(5);
+ }
+
+ // Boucle d'acceptation des clients
+ cliAddrLen = sizeof(cliAddr);
+ while ( ! end ) {
+ // Appel bloquant d'acceptation d'un nouveau client
+ sockCli=accept(sockServ, (struct sockaddr *) &cliAddr, &cliAddrLen);
+
+ // Il y plein de raisons pour qu'un accept echoue
+ if (sockCli < 0) {
+ switch(errno) {
+ case EAGAIN:
+ case EINTR:
+ // Cas qui ne sont pas des erreurs, mais nécessitent de rappeler accept
+#ifdef DEBUG
+ perror("accept (info)");
+#endif
+ break;
+ case EMFILE:
+ case ENFILE:
+ case ENOBUFS:
+ case ENOMEM:
+ // Cas d'erreur transitoire (attente d'une seconde histoire d'attendre un peu si ressources fichiers, ram épuisés
+#ifdef DEBUG
+ perror("accept (warn)");
+ sleep(1);
+#endif
+ break;
+ default:
+ // Cas d'erreur fatales
+ perror("accept (err)");
+ end=2;
+ }
+ } else {
+ // Cas nominal : un nouveau socket est disponible avec un client au bout
+#ifdef HEAVYDEBUG
+ logs("Client accepté");
+#endif
+ end=requestDispatcher(sockCli, &cliAddr, &cliAddrLen);
+ }
+ }
+
+ freeDispatcher();
+
+ if ( end != 1 ) {
+#ifdef DEBUG
+ logs("Fin anormale du serveur");
+#endif
+ return(6);
+ }
+
+ return 0;
+}
+