1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef SOCKS
#include <socks.h> // contient la definition des differents types et variables utilisés pour le traitement des sockets
#endif
#define BUFFSIZE 1024
static int quiteof = 0;
/*
traitement du transfert des données
*/
static void trans(int sock)
{
fd_set fds;
int stdin_ok = 1;
FD_ZERO(&fds);
while(stdin_ok) {
FD_SET(sock, &fds);
if (stdin_ok) FD_SET(STDIN_FILENO, &fds);
if (0 < select(sock+1, &fds, NULL, NULL, NULL)) {// select permet de surveiller plusieurs descripteurs pour le fichier
char buff[BUFFSIZE];
long len;
if (stdin_ok && FD_ISSET(STDIN_FILENO, &fds)) { /
len = read(STDIN_FILENO, buff, sizeof(buff));
#ifdef DEBUG
fprintf(stderr, "stdin: len=%ld\n", len);
#endif
if (0 < len) {
write(sock, buff, len);//write ecrit jusqu'à "len" au descripteur depuis le buffer pointé
} else {
if (quiteof) exit(0);
stdin_ok = 0;
}
}
if (FD_ISSET(sock, &fds)) {// si "sock" est contenu dans "fds"
len = read(sock, buff, sizeof(buff)); // read lit jusqu'à la taille de buff depuis sock dans le buffer pointé par buff.
//read renvoie -1 s'il échoue , sinon renvoie le nombre d'octets lus
#ifdef DEBUG
fprintf(stderr, "sock: len=%ld\n", len);
#endif
if (0 < len) {
write(STDOUT_FILENO, buff, len);//write ecrit jusqu'à "len" au descripteur depuis le buffer pointé "buff"
} else {
exit(0);
}
}
}
}
exit(0);
}
/*
Message de retour sous format HTML
*/
static void die(char* s)
{
printf("HTTP/1.0 300 erreur\r\n\r\n");
printf("<html><body>%s</body></html>\r\n", s);
fprintf(stderr,"erreur: %s\n", s);
exit(1);
}
/*
traitement de connexions
*/
int main(int argc, char** argv)
{
struct sockaddr_in sin1; // sockaddr permet d'associer une adresse(repertoire local) pour la socket pour pouvoir echanger les données
struct in_addr host1;// valeur sur 32 bits de l'adresse
int port1, sock1;
static char buff0[1024];
static char nomhost[1024];
long len;
#ifdef SOCKS // La directive #ifdef permet de compiler toute la série de lignes qui suivent si la variable de compilation "sock" a précédemment été définie
{
char* nomprog;
if ((nomprog = strrchr(argv[0], '/')) == NULL)
nomprog = argv[0];
else
nomprog++;
SOCKSinit(nomprog); // reinitialisation de la socket par la nouvelle valeur de "nomprog"
}
#endif // La directive #endif indique la fin de la partie de code conditonnelle
// traitement des erreurs lors des tentatives de connexions
{
char *hp = nomhost, *p = buff0;
int i;
len = read(STDIN_FILENO, buff0, sizeof(buff0));
i = len;
if (i <= 0) exit(1);
while(i-- && isalpha(*p)) p++;//isalpha vérifie si l'on a un caractère alphabétique.
if (!i) die("mauvaise requete");
while(i-- && isspace(*p)) p++;//vérifie si l'on a un caractère blanc, d'espacement.
if (!i) die("mauvaise requete");
if (strncmp("http://", p, 7)) die("mauvaise requete");// speçifier le nombre 7 comme etant maximal pour comparer la chaine "http://" à 'p'
p+=7;
while(i-- && ' ' < *p && *p != '/' && *p != ':') *(hp++) = *(p++);
*hp = '\0';
port1 = 80;
if (*p == ':') port1 = atoi(p+1);
if (port1 != 80 && port1 < 1024) die("port non conforme");// erreur si le port utilisé n'est pas conforme
}
fprintf(stderr, "requette: %s, %d\n", nomhost, port1);//retour du message
/* recherche du hote */
if (!inet_aton(nomhost, &host1)) { // convertir l'adresse Internet de l'hôte "nomhost" depuis la notation standard avec nombres et points en une donnée binaire, et la stocke dans la structure pointée par "&host1".
struct hostent *hent;
hent = gethostbyname(nomhost);// "hent" reçoit la structure de l'hote "nomhost"
if (hent == NULL) {
die("host non trouvé");
exit(2);
}
memcpy(&host1, hent->h_addr_list[0], sizeof(host1));//Copie nombre d'octets du "host1" depuis la zone memoire "hent" vers la zone "host1"
}
#ifdef DEBUG
fprintf(stderr, "host=%lx, port=%d\n", *(unsigned long*)&host1, port1);
#endif
/* Se connecter */
memset(&sin1, 0, sizeof(sin1));
sin1.sin_family = AF_INET;// represente la famille du protocole utilisé , dans notre cas AF_INET represente le TCP/IP utilisant une adresse Internet sur 4 octets
sin1.sin_port = htons(port1);//La fonction htons() convertit un entier court (short)hostshort depuis l'ordre des octets de l'hôte vers celuidu réseau
memcpy(&sin1.sin_addr.s_addr, &host1, sizeof(sin1.sin_addr.s_addr));
if ((sock1 = socket(AF_INET, SOCK_STREAM, 0)) < 0) {// SOCK_STREAM est un Support de dialogue garantissant l'intégrité, fournissant un flux de données binaires, et intégrant un mécanisme pour les transmissions de données hors-bande.
//socket retourne un descripteur référençant la socket créée en cas de réussite. En cas d'échec -1 est renvoyé, et errno contient le code d'erreur
// on teste alors si le descripteur est inferieur à 0 si c'est le cas , alors la socket n'a pas été crée
die("socket erreur");
exit(4);
}
if (connect(sock1, (struct sockaddr*)&sin1, sizeof(sin1)) < 0) {//connect renvoie 0 s'il réussit, ou -1 s'il échoue
// on test si connect a renvoyer un nombre < 0 , si c'est le cas , alors la connexion a echouée
die("connexion refusée");
exit(5);
}
fprintf(stderr, "CONNECTE: %s, %d\n", nomhost, port1);
/* debut du transfert des données si la connexion a été reussie */
write(sock1, buff0, len);
trans(sock1);
return(0);
} |
Partager