#include #include #include #include #include #include #include #include #include #include "const.h" #include "tools.h" #include "parsage.h" #ifdef ENABLE_MODULE #include "modules/modules.h" #endif //#define DEBUG struct hostent * ResolveName (char *name) { struct hostent *hp; if ((hp = gethostbyname (name)) == NULL) { printf ("Hote %s inconnu\n", name); perror ("gethostbyname"); return NULL; } else return hp; } int Connexion (int *csock, int port, struct struct_client *s_client) { struct sockaddr_in csin; struct hostent *hp; hp = ResolveName (s_client->host); if (hp == NULL) return 0; csin.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr))->s_addr; csin.sin_family = AF_INET; csin.sin_port = htons (port); *csock = socket (AF_INET, SOCK_STREAM, 0); if (csock == 0) return 0; if (connect (*csock, (struct sockaddr *) &csin, sizeof (csin)) < 0) { printf ("Serveur introuvable [%s]\n", s_client->host); return 0; } printf ("Connexion reussi [%s]\n", s_client->host); return 1; } int EnvoiRequeteServeur (struct struct_client *s_client) { memset (s_client->envoi, 0, MAX_BUFFER_LARGE); sprintf (s_client->envoi, "GET %s HTTP/1.%d\r\n", s_client->get, s_client->protocole); sprintf (s_client->envoi, "%sHost: %s\r\n", s_client->envoi, s_client->host); sprintf (s_client->envoi, "%sUser-Agent: %s\r\n", s_client->envoi, s_client->user_agent); if (strncmp (s_client->keep_alive, "keep-alive", strlen ("keep-alive"))) sprintf (s_client->envoi, "%sKeep-alive: 300\r\n", s_client->envoi); sprintf (s_client->envoi, "%sConnection: %s\r\n\r\n", s_client->envoi, s_client->keep_alive); // sprintf(s_client->envoi,"%s\r\n",s_client->envoi); if (send (s_client->csock, s_client->envoi, strlen (s_client->envoi), 0) < 0) return 0; else return 1; } int EnvoiClientErreur (struct struct_client *s_client) { printf ("Envoi erreur 502 : Bad Gateway...\n"); memset (s_client->envoi, 0, MAX_BUFFER_LARGE); sprintf (s_client->envoi, "HTTP/1.1 502 Bad Gateway\r\n\ Connection : close\r\n\ Content-type : plain/text\r\n\r\n\ Erreur lors de la connexion au serveur : %s\r\n", s_client->host); if (send (s_client->sock, s_client->envoi, strlen (s_client->envoi), 0) < 0) return 0; else return 1; } int RecvSendRequeteServeur (struct struct_client *s_client) { unsigned int size = 0; short occurence; short debut; char byte; int i; unsigned int total; unsigned short sortie = 0; char buff_number[MAX_BUFFER]; printf ("Corps de la requete...\n"); total = 0; while (1) { while (sortie == 0) { size = 0; memset (s_client->envoi, 0, MAX_BUFFER_LARGE); if (s_client->content_lenght <= MAX_BUFFER_LARGE || (s_client->content_lenght - total) <= MAX_BUFFER_LARGE) { while (total != s_client->content_lenght) { memset (s_client->envoi, 0, MAX_BUFFER_LARGE); if ((size = (unsigned int) recv_s (s_client->csock, s_client->envoi, (s_client->content_lenght - total), 0, s_client)) == 0) break; if (send_s (s_client->sock, s_client->envoi, size, 0, s_client) < 0) { perror ("send"); return 0; } total += size; // printf ("(2) %d >> %d\n", size, total); } sortie = 1; break; } else { while ((s_client->content_lenght - total) > MAX_BUFFER_LARGE) { memset (s_client->envoi, 0, MAX_BUFFER_LARGE); if ((size = (unsigned int) recv_s (s_client->csock, s_client->envoi, MAX_BUFFER_LARGE, 0, s_client)) == 0) break; if (send_s (s_client->sock, s_client->envoi, size, 0, s_client) < 0) { perror ("send"); return 0; } total += size; // printf ("(1) %d >> %d\n", size, total); } //sortie = 1; } } // printf ("Total == %d octets\n", total); total = 0; if (strncmp (s_client->transfer_encoding, "chunked", strlen ("chunked")) == 0) { byte = 0; occurence = 0; i = 0; debut = 0; memset (buff_number, 0, MAX_BUFFER); // printf ("Calcul...\n"); while (i <= MAX_BUFFER) { if (recv (s_client->csock, &byte, 1, 0) < 0) { perror ("recv"); return 0; } if (byte == '\r' || byte == '\n') { if (occurence == 0) debut = 1; occurence++; } else { buff_number[i] = byte; i++; } if (occurence >= 4 && debut == 1) break; else if (occurence >= 2 && debut == 0) break; } //printf ("Chiffre : !%s!\n", buff_number); s_client->content_lenght = (unsigned int) strtoul (buff_number, '\0', 16); memset (buff_number, 0, strlen (buff_number)); if (occurence >= 4 && debut == 1) sprintf (buff_number, "\r\n%d\r\n", s_client->content_lenght); else if (occurence >= 2 && debut == 0) sprintf (buff_number, "%d\r\n", s_client->content_lenght); if (send_s (s_client->sock, buff_number, strlen (buff_number), 0, s_client) < 0) perror ("send"); if (s_client->content_lenght == 0) { printf ("Fin de l'envoi chunked...\n"); #ifdef ENABLE_MODULE SendBindAllModule (NULL, s_client, END); #endif return 0; } else { printf ("Autre partie ...%d octets...\n", s_client->content_lenght); sortie = 0; } } else break; } #ifdef ENABLE_MODULE SendBindAllModule (NULL, s_client, END); #endif printf ("Corps de la requete envoye et recu\n"); return 1; } int RecvSendRequeteServeurHeader (struct struct_client *s_client) { char byte; int i; int end = 0; s_client->transfer_encoding[0] = '\0'; s_client->content_type[0] = '\0'; s_client->content_lenght = 0; while (1) { memset (s_client->envoi_h, 0, MAX_BUFFER_LINE); i = 0; byte = 0; while (byte != '\n' && i < MAX_BUFFER_LINE) { if (recv_s (s_client->csock, &byte, 1, 0, s_client) < 0) { perror ("recv"); return 0; } s_client->envoi_h[i] = byte; i++; } if (s_client->transfer_encoding[0] == '\0') ParseTransferEncoding (s_client->envoi_h, s_client->transfer_encoding); if (s_client->content_type[0] == '\0') ParseContentType (s_client->envoi_h, s_client->content_type); if (ParseContentLenght (s_client->envoi_h, &s_client->content_lenght) == 1) { if (send (s_client->sock, s_client->envoi_h, strlen(s_client->envoi_h), 0) < 0) { perror ("send"); break; } } else { if (strcmp (s_client->envoi_h, "\r\n") != 0) { if (send (s_client->sock, s_client->envoi_h, strlen(s_client->envoi_h), 0) < 0) { perror ("send"); break; } } else { #ifdef ENABLE_MODULE if (CheckIfModuleBind (s_client) > 0) { if (send (s_client->sock, "Transfer-Encoding: chunked\r\n\r\n", strlen ("Transfer-Encoding: chunked\r\n\r\n"), 0) < 0) { perror ("send"); break; } } else { if (s_client->content_lenght != 0) { memset (s_client->envoi_h, 0, MAX_BUFFER_LINE); sprintf (s_client->envoi_h, "Content-Lenght: %d\r\n\r\n", s_client->content_lenght); if (send (s_client->sock, s_client->envoi_h, strlen(s_client->envoi_h), 0) < 0) { perror ("send"); break; } } else { #endif if (send (s_client->sock, "\r\n", strlen ("\r\n"), 0) < 0) { perror ("send"); break; } #ifdef ENABLE_MODULE } } #endif end = 1; } } if (end == 1 && (strncmp (s_client->transfer_encoding, "chunked", strlen ("chunked"))) == 0 && s_client->content_lenght != -1) { printf ("Transfer chunked\n"); memset (s_client->envoi_h, 0, MAX_BUFFER_LINE); i = 0; byte = 0; while (byte != '\n' && i < (MAX_BUFFER_LINE - 2)) //-2 pour pouvoir stocker le fin de ligne { if (recv_s (s_client->csock, &byte, 1, 0, s_client) < 0) { perror ("recv"); return 0; } s_client->envoi_h[i] = byte; i++; } #ifdef ENABLE_MODULE if (send (s_client->sock, s_client->envoi_h, strlen (s_client->envoi_h), 0) < 0 && CheckIfModuleBind (s_client) > 0) //envoi de la ligne au client { perror ("send"); break; } #else if (send (s_client->sock, s_client->envoi_h, strlen (s_client->envoi_h), 0) < 0) { perror ("send"); break; } #endif /* la on enleve les sauts de ligne pour la conversion en int */ if (s_client->envoi_h[i] == '\n') s_client->envoi_h[i] = '\0'; if (s_client->envoi_h[(i - 1)] == '\r') s_client->envoi_h[(i - 1)] = '\0'; s_client->envoi_h[i] = '\0'; s_client->content_lenght = strtoul (s_client->envoi_h, '\0', 16); printf ("%d octets...\n", s_client->content_lenght); break; } else if (end == 1) { if (send (s_client->sock, "\r\n", strlen ("\r\n"), 0) < 0) { perror ("send"); break; } break; } } printf ("Header recu et envoye...\n"); return 1; } void SignalQuit (int signal) { int i; #ifdef ENABLE_MODULE int a; #endif printf ("(signal %d) Demande de fermeture, liberation des ressources...\n", signal); for (i = 0; i < MAX_CLIENT; i++) { if (s_client[i] != NULL) { close (s_client[i]->csock); close (s_client[i]->sock); free (s_client[i]); } } printf ("Threads %d [OK]\n", i); #ifdef ENABLE_MODULE if (s_all_module.NB_MODULES_LOAD != 0) { for (i = 0; i < s_all_module.NB_MODULES_LOAD; i++) { // if (s_all_module.s_module[i] != NULL) // { for (a = 0; a < s_all_module.s_module[i].NB_BIND; a++) { free (s_all_module.s_module[i].s_bind_module[a]); } // free (s_all_module.s_module[i]); // } } printf ("BindModules %d Modules %d [OK]\n", a, i); } #endif close (serveur_sock); exit (0); } void BrokenPipe (int signal) { int i; pthread_t thread; thread = pthread_self(); for (i = 0; i < MAX_CLIENT; i++) { if (s_client[i] != NULL) { if (s_client[i]->t_client == thread && s_client[i]->error != 1) { printf ("Terminaison du thread %d\n", i); if(s_client[i] != NULL) { s_client[i]->error = 1; #ifdef ENABLE_MODULE SendBindAllModule(NULL, s_client[i], ERROR); #endif } } } } } int recv_s (int s, void *buf, int len, unsigned int flags, struct struct_client *s_client) { int ret = 0; int delay = 0; //ms while (ret != len && delay < DEFAULT_TIMEOUT_REQUEST) { ret = recv (s, buf, len, flags); usleep ((WAITING_BEFORE_REQUEST * 1000)); delay += WAITING_BEFORE_REQUEST; } if (delay >= DEFAULT_TIMEOUT) { s_client->error = 1; #ifdef ENABLE_MODULE SendBindAllModule(NULL, s_client, ERROR); #endif return 0; } #ifdef ENABLE_MODULE SendBindAllModule (buf, s_client, RECV); #endif //printf("End Recv\n"); return ret; } int send_s (int s, void *buf, int len, unsigned int flags, struct struct_client *s_client) { int ret; #ifdef ENABLE_MODULE if (CheckIfModuleBind (s_client) > 0) SendBindAllModule (buf, s_client, SEND); else ret = send (s, buf, len, flags); #else ret = send (s, buf, len, flags); #endif return ret; } /* fonction itoa reprise depuis * http://www.jb.man.ac.uk/~slowe/cpp/itoa.html */ char * itoa (int val, int base) { static char buf[32] = { 0 }; int i = 30; for (; val && i; --i, val /= base) buf[i] = "0123456789abcdef"[val % base]; return &buf[i + 1]; }