begin process at 2008 07 06 17:01:44
1 205 660 membres
227 nouveaux aujourd'hui
14 119 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

[C/WIN32] PROXY AVEC THREAD


Information sur la source

Catégorie :Réseaux & Internet Classé sous : proxy, thread, serveur, http Niveau : Initié Date de création : 18/04/2006 Date de mise à jour : 10/02/2007 15:33:18 Vu / téléchargé: 7 431 / 808

Note :
8,5 / 10 - par 2 personnes
8,50 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (29)
Ajouter un commentaire et/ou une note

Description

Voila un proxy que j'ai conçu en C avec l'API win32. Pour le moment il me satisfait, je n'ai pas eu de grosses erreurs j'attend vos retours, si vous avez des bugs ou des remarques.

Utilisation:
------------
Configurer votre navigateur internet ainsi: proxy 127.0.0.1 port 8080

Retours:
--------
En cas de site qui ne fonctionne pas et qui fonctionne sans mon proxy:
Envoyez un mail à: psyphi_at_gmail_dot_com avec:
- Nom de votre navigateur (IE6, firefox ...)
- Adresse exacte du site et de la page.

En cas de bugs:
Envoyez un mail à: psyphi_at_gmail_dot_com avec:
- Nom de votre navigateur (IE6, firefox ...)
- Adresse exacte du site et de la page.
- Copier-coller de la console (clic-droit selectionner puis [ENTRER] pour coller)
- Message d'erreur si il y en a eu un.

En cas de commentaires sur mon code ;) :
- Poster un message dans les commentaires :)

Have fun!



Conclusion

Développé avec code::blocks(compilateur MINGW (gcc) )sous windows XP, puis avec Visual Studio 2005.
Pour télécharger code::blocks c'est ici:
http://prdownloads.sourceforge.net/codeblocks/codeblocks-1.0rc2_mingw.exe?download
Ne pas oublié de linker avec ws2_32.lib ou libws2_32.a en fonction de votre compilateur.
Le projet est maintenue pour les deux compilateurs, vous trouvez deux dossiers différents dans le zip un pour code:blocks l'autre pour visual studio 2005.
Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

18 avril 2006 22:49:34 :
Correction ortographique :-S
20 avril 2006 20:26:17 :
Correction de la majorité des bugs. Programmation propre des threads: (Merci à fearyourself pour son aide => http://www.developpez.net/forums/showthread.php?p=855335#post855335)
23 avril 2006 00:36:09 :
Analyse et traitement de la requête HTTP, avec reconstruction de cette dernière.
24 avril 2006 00:29:15 :
Corrections des bugs des threads, meilleur traitement des requêtes GET
24 avril 2006 17:53:20 :
Support de HTTP/1.1. Correction de bug lié à l'allocation dynamique, j'espère qu'il n'y en as plus ce coup ci.
26 avril 2006 00:00:50 :
Implémentation de la commande POST. Corrections de diverses erreurs. Meilleurs traitements des erreurs.
17 août 2006 23:07:41 :
Découpage du projet en plusieurs fichiers. Corrections des fuites de mémoire :-/.
10 février 2007 15:33:19 :
Diverses corrections de bugs, améliorations et portage de la source pour compilations avec visual studio 2005.
  • signaler à un administrateur
    Commentaire de ymca2003 le 18/04/2006 23:22:44

    char * host = (char *)malloc(256 * sizeof(char));
    memset(host, '\0', sizeof(host));
    => ne va initialiser q'une partie du buffer alloué car sizeof(host) va renvoyer 4 sur plateforme 32 bits
    memset(host, '\0', 256*sizeof(char)); met tout le buffer à 0

    int proxy(SOCKET socket_client)
    => pas le bon prototype il faut :
    DWORD CALLBACK proxy(LPVOID)
    ou au moins
    int CALLBACK proxy(SOCKET socket_client)

  • signaler à un administrateur
    Commentaire de psyphi le 18/04/2006 23:26:20

    Merci de ton aide :D
    >Comment se fait-il que sizeof(host) renvoie 4 ?
    >Tu peux m'expliquer un peu plus cet histoire de prototype?
    >Toujours pas d'idées quant a mon histore de buffer2?

  • signaler à un administrateur
    Commentaire de BruNews le 18/04/2006 23:33:47 administrateur CS

    L'éternel piège du sizeof qu'on répète à longueur de forum.
    sizeof ne donnera la taille d'une variable que si elle est de taille fixe et connue dans la portée de la fonction ou globale mais dans la cas d'un pointeur c'est, comme dit plus haut, 4 en sytème 32 bits et 8 en système 64 bits.

  • signaler à un administrateur
    Commentaire de psyphi le 18/04/2006 23:37:11

    Oki merci bien, au fond ca semble logique en plus.
    Sinon pourquoi 4 octets pour un pointeur?

  • signaler à un administrateur
    Commentaire de BruNews le 18/04/2006 23:41:35 administrateur CS

    La taille du DWORD 'machine' (taille registre du cpu), permet d'adresser sur une plage 4 Go (32 bits full sur 32 bits) et en téra (à calculer) sur 64 bits, sinon un pointeur ne serait pas valide pour référencer une adresse mémoire.

  • signaler à un administrateur
    Commentaire de psyphi le 18/04/2006 23:55:03

    Ouki, c'est en fonction du bus d'adresse du processeur 2^32 = 4294967296 adresses possibles. Il faut donc une capacité de 4 octets (32bits) [Tout ca pour un processeur 32bits] c'est là encore logique ;-) merci BruNews de m'avoir éclairé.

  • signaler à un administrateur
    Commentaire de Stormy le 22/04/2006 08:40:32

    Pour ce qui est de la réception des données dans les tampons (buffer1 et buffer2), je vois que tu fixes une limite importante de 4 et 2 Ko. Néanmoins, n'as-tu pas peur d'éventuels débordements? Le risque est-il possible?
    En tout cas cette source est très intéressante ++

  • signaler à un administrateur
    Commentaire de psyphi le 22/04/2006 18:08:38

    Merci de t'interessé à ma source.
    Question débordement je ne pense pas, car dans quand je reçois les données avec la fonction recv(), le troisième argument sert à définir la longueur maximal du message reçu en octet, donc si je définit comme longueur maximale la taille de mon tampon, je ne pense pas qu'il y ait de problème.
    Pour la taille des buffers par contre je ne sais pas trop qu'elle est la meilleur taille à utiliser pour des transferts de données, on m'a dit sur un forum d'utiliser des buffers de 4ko ou 16ko, si qqun à des propositions avec explications je suis preneur.
    Peut être qu'il y a encore des erreurs dans la reception des requêtes, il faudrait peut être que je rajoute un filtre spéciale, car on n'est pas à l'abris que quelqu'un forge sa propre requête avec des commandes fallacieuses.

  • signaler à un administrateur
    Commentaire de psyphi le 23/04/2006 00:39:13

    J'ai un nouveau problème, encore un :-S. Depuis que j'ai rajouté mes fonctions de parse de requete HTTP, le nombre de site qui fonctionne est bien meilleur qu'auparavant mais par contre le multithreading plante !!
    J'ai des erreurs du type:
    0x0040155f emploie l'adresse mémoire 0x0014a0000. La mémoire ne peut pas être "read".
    Quelqu'un saurait me dire de quoi cela peut provenir.
    PS: si vous voulez une source fonctionnel commenté CreateThread et décommenté la ligne du dessous.

  • signaler à un administrateur
    Commentaire de psyphi le 24/04/2006 00:29:51

    J'ai corrigé l'erreur du multithreading, c bon.

  • signaler à un administrateur
    Commentaire de Stormy le 24/04/2006 19:32:36

    J'aimerais le compiler sous Win32 avec VC6. Penses-tu que c'est possible? J'ai beaucoup d'erreurs provoquées par 'redefinition; different linkage'.

  • signaler à un administrateur
    Commentaire de bipbip45 le 24/04/2006 20:43:17

    Je ne connais pas calloc. Dans la mesure où c'est équivalent à malloc, je pense qu'il conviendrait de vérifier le code de retour de cette fonction avant de considérer le pointeur comme alloué:
        if(buf==NULL) {
            desallocation des autres buffers et fermeture des fd
            return EXIT_FAILURE;
        }

        suite du code

    Par ailleurs, juste histoire de simplifier le code, tu aurais peut-être pu utiliser snprintf plutot que de multiplier l'emploi de strncat.

    Dans tous les cas, merci pour ton code.

  • signaler à un administrateur
    Commentaire de psyphi le 25/04/2006 23:38:25

    @Stormy: J'ai essayé de compiler avec Visual C++ 6, je n'ai pas réussis, je n'ai pas trop compris pourquoi. Essaye code::block et mingw
    http://prdownloads.sourceforge.net/codeblocks/codeblocks-1.0rc2_mingw.exe?download
    @BIPBIP45: j'étais justement en train de corriger les erreurs dont tu me fesais part. calloc et équivalent à malloc + memset, il alloue et initialize le contenu.
    Sinon en quoi snprintf est plus simple que strncat?
    Pour finir je viens de faire une nouvelle mise à jour.

  • signaler à un administrateur
    Commentaire de bipbip45 le 30/04/2006 18:51:18

    En fait snprintf te permet de formater une chaîne de caractères de la même manière que printf, mais au lieu que ce soit vers la sortie standard de l'exécutable, c'est dans un buffer délimité en taille (afin de se prémunir des buffer overflow comme strncat).
    Voici son prototype:
    int snprintf (char *str, size_t size, const char  *format, ...)
    Pour plus d'info sur snprintf, un page de manuel en français se trouve à l'URL : http://dpobel.free.fr/man/html/affiche_man.php/3369/man/snprintf/

    Voici un exemple de remplacement de deux strncat par un snprintf:
    strncat(httpRequest, header, strlen(header));       strncat(httpRequest, "\r\n", 2);

    snprintf(httpRequest,sizeof(httpRequest),"%s\r\n",header);

    Néanmoins cela nécessiterait que tu revoies toute la gestion de ton buffer httpRequest; car au lieu d'ajouter en fin de buffer comme le fait strncat, snprintf repart du début du buffer.
    Cela aurait pu simplifier l'écriture de la fonction "build_post_request". En effet, ce que tu réalises avec l'appel à moulte strncat (un strcat s'est perdu dans la fonction par ailleurs), aurait pu être remplacer par un unique snprintf.

    En terme de performances, il faut voir que chaque appel de fonction implique de placer dans la pile les arguments et donc une consommation de mémoire ce qui est assez critique pour un serveur.

    Voilà, ce n'était par pour pinailler mais juste pour apporter une briquette à ton édifice.

  • signaler à un administrateur
    Commentaire de psyphi le 30/04/2006 23:07:55

    Merci beaucoup de ta remarque, je vais essayer d'en tenir compte.

  • signaler à un administrateur
    Commentaire de bipbip45 le 02/05/2006 17:06:01

    J'ai commencé à lire ton code un peu plus dans le détail et voici quelques éléments qui 'mont surpris en dehors de ceux précités:
    > on trouve dans le code, par exemple en ligne 97-98  beaucoup de boucles du type:
                   while(buffer[i]!='car')
                       i++;
    Il se peut que le proxy recoive des paquets malformés voire forgés. Dans ce cas, et sans limite d'indice, il y a de grande chance qu'à force d'incrémenter i, on obtienne une erreur de segmentation due à une lecture arbitraire sur une zone mémoire interdite. (idem ligne 15-116,134-138,164-168,...)

    > la fonction get_header_if_exist renvoie un code de retour de type short qui n'est pas exploité lors des appels dans la fonction parse_http_request.

    > dans la fonction get_content_lenth : dans le cas ou tu recois un paquet malforme ou le champ "Content" comprend plus de 10 caracteres, ton buffer vas exploser ce qui entrainera au mieux une erreur de segmentation et au pire l'écrasement des données suivantes dans la pile. Peut etre vaudrait-il mieux realiser le calloc un fois que tu sais combien il faut allouer (size-i+1 je crois). De plus, une fois que size est calcule, c'est que ContentLength termine par '\0' (sinon strlen echoue) et donc on pourrait directement ecrire size=atoi(ContentLength+(i+1)).

    >lorsque tu emploies la fonction strstr, je pense qu'il faudrait se méfier; en effet en lisant la documentation de strstr(), si la fonction ne trouve pas la sous-chaine, elle renvoie NULL. Je pense que, en ligne 134 par exemple, il faudrait faire une verfication de buffer avant d'effectuer buffer[i] en sortie de strstr.

    Voila, j'espere ne pas d'embeter avec ces commentaires; n'hesite pas a me le dire si c est le cas et je me rendrai silencieux.

  • signaler à un administrateur
    Commentaire de psyphi le 02/05/2006 18:53:12

    A non pas du tout tes commentaires ne me gêne pas au contraire, sinon je posterais pas mon proxy en OpenSource ;-).
    Merci de tes conseils et remarques, qui je pense, sont sensées. Je vais m'atteler à la correction dès que j'aurai un peu plus de temps et moins de partiels :-/ .
    C'est peut-être pour l'une des raisons que tu as cité que parfois mon proxy plante sans raison, ce qui est très embêtant; lol.
    Si t'as encore d'autres remarques n'hésite pas, merci.

  • signaler à un administrateur
    Commentaire de bipbip45 le 03/05/2006 17:12:41

    J'ai enfin fini de lire le code (pas encore exécuté car suis sous Linux). Et voici quelques autres commentaires:

    > en mode thread, il me semble que lorsqu'un thread, réalise un exit, c'est l'ensemble des threads et donc ton programme qui réalise un exit. En conséquence, je pense que tu devrais éviter de faire des appels à exit(1) (en ligne 204, 282 ...) lorsqu'une erreur est rencontrée. Mieux vaut propager l'erreur vers les fonctions appelantes avec return EXIT_FAILURE, qui, si c'est la fonction principale du thread mettra fin à celui-ci.

    > la fonction proxy() est critique: en effet dans cette fonction, tu alloues l'ensemble des buffers ... Je pense qu'il faudrait réaliser la désallocation de l'ensemble des buffers avant de faire return, qu'un erreur se soit produite ou non. Donc tous les appels à calloc() qui ont eu lieu dans cette fonction ou dans les fonctions appellées (ex: port (l387) ou hostname alloué par gethost() ...)

    > fonction send (ex: l.441, l.449): il se peut que send ne parviennent pas à transmettre une requete. C'est pouquoi cette fonction a une code de retour correspondant au nombre de caractères écrits dans la socket. Il convient donc à mon avis de l'exploiter.

    > closesocket (l.502, l.516): ici tu fais un close(socket_client) en cas d'erreur. Je pense que c'est un lapsus et qu'il s'agit de socket_local. En effet, socket_local n'existe qu'après l'appel accept (l.512).

    > l.529 et l.541 return EXIT_FAILURE: tu as oublié de fermer les sockets avant de sortir.

    > enfin je ne connais pas l'API des threads windows mais la version POSIX indique qu'il faut explicitement les détacher si on se moque de leur code de retour car dans le cas contraire, on risque une fuite de ressource. Ici tu ne le fais pas (cf man pthread_join,pthread_detach).

    Bon courage pour tes partiels.

  • signaler à un administrateur
    Commentaire de bloom1 le 13/08/2006 07:13:05

    Chez moi il fonctionne nikel, il recoit tout et n'as pas encore planté (3 site que je visites à date)

    Donc merci :)

  • signaler à un administrateur
    Commentaire de xav987 le 08/02/2007 09:49:16

    Il y a un petit bug qui fait que certains compilo retournent une erreur. CodeBock, qui est moins rigoureux, ne signale rien :
    Dans ta fonction proxy() tu fais un "buffer2[size]='\0';", donc tu ecrases le dernier octet du buffer2. Sa provoque un stack arround.
    Moi j'ai mis "buffer2[KB_SIZE*4+1]" dans la declaration de buffer2 et "sizeof(buffer2)-1" dans la declaration de "size", comme ça on reste dans des echanges de 4096 octet.
    Sinon, sur certains site (genre Wikipedia), j'ai un message d'erreur avec la fonction send() et la page ne s'affiche pas, j'ai pas encore trouvé la raison.

    A part ça, magnifique programme, difficilement lisible, je trouve, mais qui me servira beaucoup ! 9* =)

  • signaler à un administrateur
    Commentaire de psyphi le 08/02/2007 10:11:26

    Salut XAV97, merci de t'intéresser à mon programme :).
    Voici effectivement quelques corrections:
    - Rajout de +1 à la taille des buffers pour le '\0' de fin de chaine ^^.

    char buffer[KB_SIZE*16+1]; // 16 ko pour la requete http
    char buffer2[KB_SIZE*4+1];      // 4 ko pour les paquet de transfert

    - Correction du nombre d'octet reçu par les fonctions recv() en ajoutant un -1 après les sizeof().
    int size = recv(socket_client, buffer, sizeof(buffer)-1, 0);
    size = recv(envoi, buffer2, sizeof(buffer2)-1,0)

    Maintenant on a bien des échanges de 16ko et 4ko au maximum. Il ne faut en effet pas oublié que les fonctions send et recv ne transmette pas les '\0' de fin de chaine, il faut donc laisser une case de libre dans les chaines de buffer pour les acceuillir. Ce que j'avais oublié de faire :-S.

    Merci de tes remarques, maintenant tout devrait mieux fonctionner.
    Je mets le zip à jour dès que j'ai le temps.

    Désolé pour la lecture du programme mais au fur et à mesure de son amélioration il est devenu de plus en plus complexe et difficile à lire :-/ .

  • signaler à un administrateur
    Commentaire de xav987 le 08/02/2007 11:13:52

    Pour l'erreur du Wiki, j'ai trouvé à quoi elle est liée :
    Quand on affiche la page du Wiki et qu'on la ferme avant qu'elle ne soit pas totalement apparut, il genere une erreur dans la fonction send(). Sa ne le fait que pour le Wiki, je ne sait pas pourquoi.

    Sous CodeBlock, sa continue de tourné, mais sous d'autre compilo, il genere une erreur a cause du free(port). En effet juste avant tu as "port = "80"" donc tu libere un espace qui n'a pas été aloué dynamiquement.
    Tu as le meme probleme avec le "free(httpRequest);" qu'on retrouve assez souvent alors qu'il n'a pas encore été declaré...
    J'ai remplacé "port = "80"" par "strcpy(port, "80");" et sa passe sans probleme.

    Pour la lisibilité, c'est surtout une question de gout personnel. Je n'aime pas mais certains doivent apprecier ta façon de presenter ton code, c'etait juste une petite remarque et pas du tout un reproche, et ce n'est valable que pour moi.

  • signaler à un administrateur
    Commentaire de xav987 le 08/02/2007 11:31:43

    Autres petits details (mais là c'est vraiment un tres petit detail) :
    le QUARTER_SIZE n'est jamais utilisé,
    Le HALF_SIZE pour l'host c'est un peu juste, j'ai eu des erreurs pour afficher certains site où ce n'etait pas suffisant (sur 01.net par exemple il ont des url tres longues).

    Mais c'est vraiment la seul source de Proxy que j'ai trouver sur le net qui fonctionne aussi bien... Encore felicitation !

  • signaler à un administrateur
    Commentaire de psyphi le 08/02/2007 11:55:51

    Tu compiles avec quel compilateur et quelle version?

  • signaler à un administrateur
    Commentaire de xav987 le 08/02/2007 17:13:21

    J'ai testé avec :
    - GCC de DevCpp (version 3.4.quelque chose !) qui à l'avantage d'etre multiplateforme (mais ma version est un peu vielle,
    - Le compilo de Borland C++ 6
    - Le compilo de Visual Studio 2005 (et je ne suis pas specialement partisant des produits micro$oft, mais ça reste le meilleur compilo celon moi.

    L'interface de Code::Block est sympa, mais son compilo par default (mais on peu en parametrer un autre) est vraiment à chier (enfin, c'est mon avis) ! Il laisse passer plein de Warning, et pire de quelques erreurs.
    Et l'outils de debogage n'est pas top (j'aurais jamais trouvé les erreurs d'allocations et d'ecrasement de données dans les buffer avec code block).

  • signaler à un administrateur
    Commentaire de psyphi le 08/02/2007 20:44:35

    Ok bon là j'ai essayé de compiler avec Visual Studio 2005, j'ai eu pas mal d'erreurs, j'en ai corrigé pas mal, dès que tout est propre je poste le .zip

  • signaler à un administrateur
    Commentaire de psyphi le 10/02/2007 15:35:17

    Voila la nouvelle version est postée j'attends vos retours :)

  • signaler à un administrateur
    Commentaire de victorcoasne le 11/07/2007 23:22:53

    Essaye ebay.fr et tu vas rire ;)

  • signaler à un administrateur
    Commentaire de victorcoasne le 13/07/2007 01:47:41

    J'ai rencontré le même problème quand j'ai fabriqué mon propre proxy.
    Cela vient de la spécification HTTP qui autorise un navigateur qui transmet à un proxy à inclure l'adresse avec http:// mais qui ne l'autorise pas à la transmettre avec les http:// au serveur qui fourni l'adresse (sur ebay Microsoft IIS).

Ajouter un commentaire

Discussions en rapport avec ce code source

Pub



Appels d'offres

Plugin Dialer outlook
Budget : 2 000€
Travail graphique- ill...
Budget : 1 000€
creation de marque et ...
Budget : 1 000€

CalendriCode

Juillet 2008
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Téléchargements

Logiciels à télécharger sur le même thème :

Boutique

Boutique de goodies CodeS-SourceS