summaryrefslogtreecommitdiff
path: root/app/v3_c/src/tcpserver.c
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2011-01-23 14:36:05 +0000
committerLudovic Pouzenc <ludovic@pouzenc.fr>2011-01-23 14:36:05 +0000
commitdcda721939bc81c58f66850aa21f6b6f0c64cab3 (patch)
tree4788908cfc11c7526c1e8d1491146438b10c1c3f /app/v3_c/src/tcpserver.c
parent31f0e4b4067901e35ba3c3c66a77e84f35e74992 (diff)
download2011-usi-dcda721939bc81c58f66850aa21f6b6f0c64cab3.tar.gz
2011-usi-dcda721939bc81c58f66850aa21f6b6f0c64cab3.tar.bz2
2011-usi-dcda721939bc81c58f66850aa21f6b6f0c64cab3.zip
Refactoring : myhttpd -> tcpserver et process -> dispatcher. Faisaons de belles briques bien claires d'entrée de jeu !
git-svn-id: file:///var/svn/2011-usi/trunk@15 db941bf7-0cb3-4dda-9634-87faf64f93a7
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;
+}
+