Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1015 connectés 

  FORUM HardWare.fr
  Programmation
  C

  [C/Socket]Programmer un proxy

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C/Socket]Programmer un proxy

n°1342173
psyphi
Posté le 08-04-2006 à 20:02:26  profilanswer
 

Salut all, je cherche de la doc sur comment programmez un proxy minimal sans cache ou autre fioriture.
J'ai bien une idée, ouvrir deux sockets en parallèle (multithreading) de cette façon mais je ne suis pas du tout sur:
client -> socket 1 -> serveur
client <- socket 2 <- serveur
 
Donc avant de me lancer dans l'inconnu je vous demande de l'aide: des sources courtes ou des tutos.
merci :jap:

mood
Publicité
Posté le 08-04-2006 à 20:02:26  profilanswer
 

n°1342243
nargy
Posté le 08-04-2006 à 23:55:03  profilanswer
 

c'est un poil plus compliqué: il faut que tu lise la requête HTTP, et que tu envoye cette requête au serveur désignée dans la requête. Une fois la connexion effectuée tu lit les données reçues pour les transmettre au navigateur (socket en lecture/écriture, donc).
Le shemas ressemble plus à ça:
client <---> proxy <----> serveur
 
Note que certaines options dans les entêtes sont utiles (genre connexion:close), et que tu doit aussi envoyer les cookies, les formulaires et les fichiers joints.

n°1342451
psyphi
Posté le 09-04-2006 à 17:11:00  profilanswer
 

Pourquoi est ce qu'il est nécessaire de lire l'entête http?
Dans le cas d'utilisation d'un proxy l'adresse ip de destination est celle du proxy ou celle du site web?
L'entête est directement envoyé par le navigateur j'aurai pensé que le proxy l'envoyais directement sans traitement vers le site web.
Autre question: suivant ton schéma comment faire pour traiter en parallèle  les envois et les réponses, je pense que je suis obligé d'utiliser les threads non?
Merci de ton aide (PS: si t'as des sources je suis preneur)

n°1342464
Zipo
Ours bipolaire
Posté le 09-04-2006 à 18:15:20  profilanswer
 

tiens j'avais fais un proxy smtp si ça peut t'aider, ya le source en C et le rapport ici :
http://kaiserzipo.free.fr/web/.dir [...] eseau&3=TP
 
et effectivement tu utilises plusieurs threads ;)


Message édité par Zipo le 09-04-2006 à 18:15:50

---------------
- mon feed-back
n°1342474
nargy
Posté le 09-04-2006 à 18:45:00  profilanswer
 

Citation :


Pourquoi est ce qu'il est nécessaire de lire l'entête http?
Dans le cas d'utilisation d'un proxy l'adresse ip de destination est celle du proxy ou celle du site web?
L'entête est directement envoyé par le navigateur j'aurai pensé que le proxy l'envoyais directement sans traitement vers le site web.


 
Au niveau TCP, le navigateur envoye la requête au proxy, et non pas au serveur. C'est au proxy de prendre en charge la requête, et donc pour contacter le serveur il devra lire l'entête. Certaines options sur les sockets peuvent être fixées par le navigateur ou le serveur: par exemple les temps d'attente maximums. Le proxy devra en tenir compte. Je ne peut pas te donner une liste exhaustive des options d'entête qu'il te faudra traiter, mais tu trouvera plein de doc sur le web.
 

Citation :


Autre question: suivant ton schéma comment faire pour traiter en parallèle  les envois et les réponses, je pense que je suis obligé d'utiliser les threads non?


 
Tout à fait, la structure principale d'une proxy est la même que celle d'un serveur web!
 

Citation :


Merci de ton aide (PS: si t'as des sources je suis preneur)


 
Il y a plein de proxys en open source, une petite recherche sur le net et tu trouvera ton bonheur. Même si souvent ces proxys tournent sur Unix, tu peut les adapter pour Windows.
 
La meilleure source que tu puisse avoir c'est celle du serveur Apache sur apache.org!
 
Bon courage :)
 
(rem: c'est pas si dur, mais c'est long, j'avais fait un serveur web compatible HTTP/1.1, j'y avais intégré la plupart des gestion d'entêtes, mais il m'a fallu 6 mois)

n°1342489
psyphi
Posté le 09-04-2006 à 19:43:50  profilanswer
 

J'ai bien essayé de regarder des logiciels open, j'ai télécharger les sources de squid mais bon faut avoir un certain niveau, je maitrise bien le C/C++ et d'autre langage mais lire un tel projet c'est chaud.

n°1342508
nargy
Posté le 09-04-2006 à 20:24:36  profilanswer
 

Entraîne toi sur le forum, debugger les programmes des autres c'est pas toujours évident.

n°1342735
psyphi
Posté le 10-04-2006 à 09:51:25  profilanswer
 

J'ai une petite idée d'algo, qu'en pensez vous? :

Code :
  1. Creer un nouveau thread à chaque nouvelle connexion
  2. recevoir paquet
  3. Analyser l'header http
  4. sortir le host
  5. envoyer le paquet vers host
  6. attendre réponse
  7. renvoyer la réponse au client

n°1342742
nargy
Posté le 10-04-2006 à 09:57:36  profilanswer
 

C'est un bon début.

n°1345606
psyphi
Posté le 12-04-2006 à 22:35:18  profilanswer
 

J'ai créer un bou de code qui fonctionne a peu près, mais il y a beaucoup de bugs que je ne comprend, les connexions foires au bout d'un moment et j'ai beaucoup de bug d'affichage à croire que tout le code des pages web n'est pas transmit.
Si des âmes charitables veulent bien le tester  :jap: :
Pour configurer, dans firefox: paramètre de connexion -> proxy 127.0.0.1 port 3080
adresse pour télécharger directement: http://membres.lycos.fr/bobov/code/main.c
ou ici:

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <windows.h>
  5. #include <winsock2.h>
  6. #pragma comment(lib, "ws2_32.lib" )
  7. /**************
  8. * prototypes *
  9. **************/
  10. char * get_host(char * httpRequest);
  11. int proxy(SOCKET socket_client);
  12. /*************
  13. * functions *
  14. *************/
  15. /*
  16. * get_host()
  17. * fonction qui isole le header http (Host:)
  18. */
  19. char * get_host(char * httpRequest){
  20. unsigned short i = 0, j = 0;
  21. char * buffer = strstr(httpRequest, "Host: " );
  22. char * host = (char *)malloc(256 * sizeof(char));
  23. while( buffer[i] != '\n' )
  24.  i++;
  25. for(j = 6; j < i-1; j++)
  26.  host[j - 6] = buffer[j];
  27. host[j-6+1] = '\0';
  28. return host;
  29. }
  30. /*
  31. * proxy()
  32. */
  33. int proxy(SOCKET socket_client){
  34. SOCKET envoi;
  35.   SOCKADDR_IN server2;
  36.   struct hostent * structHost;
  37. char buffer[1024];
  38. char buffer2[1024*1024]; // 1 ko
  39. memset(buffer,'\0',sizeof(buffer));
  40. // On recoit la requete du navigateur
  41. int size = recv(socket_client, buffer, sizeof(buffer), 0);
  42.   printf("size : %d \r\n", size);
  43.   fprintf(stdout, "----\r\n%s----\r\n", buffer);
  44. // On récupère le header (Host:) de la requete  
  45. // pour pouvoir se connecter au serveur web
  46. char * host = get_host(buffer);
  47. printf("Host : [%s]\r\n", get_host(buffer));
  48. // On envoie la requete au serveur web
  49. // grace a un nouveau socket
  50.   if((structHost = gethostbyname(host)) == NULL){
  51.   fprintf(stderr,"Host error\n" );
  52. }
  53.   if((envoi = socket(AF_INET, SOCK_STREAM, 0)) == -1){
  54.  printf("socket error\r\n" );
  55. }
  56.     server2.sin_family = AF_INET;
  57.     server2.sin_port   = htons(80);
  58.  server2.sin_addr   = *((struct in_addr *)structHost->h_addr);
  59.  memset(&(server2.sin_zero),'\0',8);
  60.     if( connect(envoi,(struct sockaddr * )&server2,sizeof(struct sockaddr)) == -1){
  61.         printf("error connect\r\n" );
  62.         return -1;
  63.     }
  64.     send(envoi, buffer, strlen(buffer), 0);
  65.     memset(buffer2,'\0',sizeof(buffer2));
  66. // Reception des donnees a partir du serveur
  67. // et les renvoies au navigateur
  68.    while( (size = recv(envoi,buffer2,sizeof(buffer2),0)) != 0){
  69.     buffer2[size] = '\0';
  70.     fprintf(stdout, "%s", buffer2);
  71.     // Renvoie de la réponse au navigateur
  72.     send(socket_client, buffer2,strlen(buffer2),0);
  73.     memset(buffer2,'\0',sizeof(buffer2));
  74.    }
  75. //Nettoyage
  76.     closesocket(socket_client);
  77.     WSACleanup();
  78.     ExitThread(0);
  79.     return 0;
  80. }
  81. /**********
  82. * main() *
  83. **********/
  84. int main(int argc, char * argv[]){
  85. // Initialisation  
  86.     WSADATA WSAData;
  87.     WSAStartup(MAKEWORD(2,0), &WSAData);
  88. // Variables
  89.     SOCKET socket_local;
  90.     SOCKET socket_client;
  91.     SOCKADDR_IN server;
  92.     SOCKADDR_IN client;
  93.     DWORD  dwThreadID;
  94.     int sin_size = sizeof(SOCKADDR_IN);
  95.     socket_local = socket(AF_INET,SOCK_STREAM,0);
  96. // Configuration du proxy (port 3080)
  97.         server.sin_family      = AF_INET;
  98. server.sin_port        = htons(3080);
  99. server.sin_addr.s_addr = INADDR_ANY;
  100. memset(&(server.sin_zero),'\0',8);
  101.     bind(socket_local,(struct sockaddr * )&server,sizeof(struct sockaddr));
  102.     listen(socket_local,5);
  103. // Attente de connexion
  104. while(1)
  105. {
  106.  if( (socket_client = accept(socket_local,(struct sockaddr * )&client,&sin_size)) == -1)
  107.  {
  108.    fprintf(stderr, "Accept error.Error: %d\n", WSAGetLastError());
  109.    closesocket(socket_client);
  110.    WSACleanup();
  111.    return 1;
  112.  }
  113.  else
  114.  {
  115.   fprintf(stdout,"Connection de : %s \n",inet_ntoa(client.sin_addr));
  116. // On cree un thread par nouvelle connexion en
  117. // appelant la fonction proxy avec comme paramètre le socket client
  118.   CreateThread( NULL,
  119.      0,
  120.      (LPTHREAD_START_ROUTINE) proxy,
  121.      socket_client,
  122.      0,
  123.      &dwThreadID);
  124.  }
  125. }
  126.     return 0;
  127. }
  128. }


Edit: commentaires sur le code ajouté.


Message édité par psyphi le 14-04-2006 à 15:31:49
mood
Publicité
Posté le 12-04-2006 à 22:35:18  profilanswer
 

n°1345614
Zipo
Ours bipolaire
Posté le 12-04-2006 à 22:40:22  profilanswer
 

on sent que tu aimes commenter ton code toi :d

Message cité 1 fois
Message édité par Zipo le 12-04-2006 à 22:40:45

---------------
- mon feed-back
n°1345616
psyphi
Posté le 12-04-2006 à 22:42:24  profilanswer
 

:sweat: C'est vrai que je ne l'ai pas super commenté, généralement je commente mon code quand je sais que j'aurai des problèmes en le relisant mais la le principe est connu donc j'ai pas beaucoup commenté. Mais je vais corriger ca par la suite.  :D

n°1345682
Emmanuel D​elahaye
C is a sharp tool
Posté le 13-04-2006 à 01:41:16  profilanswer
 

Zipo a écrit :

on sent que tu aimes commenter ton code toi :d


Il y a le minimum vital... Si on connait le sujet, il n'y pas trop de mystères...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1346953
psyphi
Posté le 14-04-2006 à 15:27:48  profilanswer
 

Voila j'ai édité mon message précédent et commenté mon code ;)

n°1348846
psyphi
Posté le 18-04-2006 à 15:15:43  profilanswer
 

J'ai fait une mise à jour du code proper et commenté cette fois ci, mais mon proxy ne fonctionne pas avec les images, qqun peut il m'aider?
Lien direct vers le .c : http://membres.lycos.fr/bobov/code/main.c  
(Configuration du navigateur: 127.0.0.1:8080)

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <windows.h>
  5. #include <winsock2.h>
  6. #pragma comment(lib, "ws2_32.lib" )
  7. /**************
  8. * prototypes *
  9. **************/
  10. void display_error(char * errorType);
  11. char * get_host(char * httpRequest);
  12. int proxy(SOCKET socket_client);
  13. /*************
  14. * functions *
  15. *************/
  16. /*
  17. * display_error()
  18. */
  19. void display_error(char * errorType){
  20. LPVOID lpMsgBuf;
  21. FormatMessage(  FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  22.     NULL,
  23.     GetLastError(),
  24.     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  25.     (LPTSTR) &lpMsgBuf,
  26.     0,
  27.     NULL);
  28. // Affichage du message dans une boite de dialogue
  29. MessageBox( NULL, lpMsgBuf, errorType, MB_OK | MB_ICONERROR );
  30. // Libération du buffer
  31. LocalFree( lpMsgBuf );
  32. }
  33. /*
  34. * get_host()
  35. * fonction qui isole le header http (Host:)
  36. */
  37. char * get_host(char * httpRequest){
  38. unsigned short i = 0, j = 0;
  39. char * buffer = strstr(httpRequest, "Host: " );
  40. char * host = (char *)malloc(256 * sizeof(char));
  41. memset(host, '\0', sizeof(host));
  42. while( buffer[i] != '\n' )
  43.  i++;
  44. for(j = 6; j < i-1; j++)
  45.  host[j - 6] = buffer[j];
  46. host[j-6+1] = '\0';
  47. return host;
  48. }
  49. /*
  50. * proxy()
  51. */
  52. int proxy(SOCKET socket_client){
  53. SOCKET envoi;
  54. SOCKADDR_IN server2;
  55. struct hostent * structHost;
  56. char buffer[1024*10]; // 10 ko
  57. char buffer2[1024*50]; // 50 ko
  58. memset(buffer,'\0', sizeof(buffer));
  59. memset(buffer2,'\0', sizeof(buffer));
  60. // On recoit la requete du navigateur
  61. int size = recv(socket_client, buffer, sizeof(buffer), 0);
  62. fprintf(stdout, "----Commande recue ----\r\n%s----\r\n", buffer);
  63. // On récupère le header (Host:) de la requete
  64. // pour pouvoir se connecter au serveur web
  65. char * host = get_host(buffer);
  66. //fprintf(stdout,"Host : [%s]\r\n", get_host(buffer));
  67. // On envoie la requete au serveur web
  68. // grace a un nouveau socket
  69. if((structHost = gethostbyname(host)) == NULL){
  70.   fprintf(stderr,"Host error\r\n" );
  71.   display_error("Host error !" );
  72.   return -1;
  73. }
  74. if((envoi = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
  75.  fprintf(stderr, "Socket error. Error: %d\r\n", WSAGetLastError());
  76.         display_error("Socket error !" );
  77.         return -1;
  78. }
  79.     server2.sin_family = AF_INET;
  80. server2.sin_port   = htons(80);
  81. server2.sin_addr   = *((struct in_addr *)structHost->h_addr);
  82. memset(&(server2.sin_zero),'\0',8);
  83.     if( connect(envoi,(struct sockaddr * )&server2,sizeof(struct sockaddr)) == -1){
  84.         fprintf(stderr,"Error connect\r\n" );
  85.         display_error("Connect Error !" );
  86.         return -1;
  87.     }
  88.     send(envoi, buffer, strlen(buffer), 0);
  89. // Reception des donnees a partir du serveur
  90. // et les renvoies au navigateur
  91.    while( (size = recv(envoi,buffer2,sizeof(buffer2),0)) != 0){
  92.     buffer2[size] = '\0';
  93.     //fprintf(stdout, "%s", buffer2);
  94. // Renvoie de la réponse au navigateur
  95.     send(socket_client, buffer2,strlen(buffer2),0);
  96.     memset(buffer2,'\0',sizeof(buffer2));
  97.    }
  98. //Nettoyage
  99.     closesocket(socket_client);
  100.     fprintf(stdout, "Exiting Thread.\r\n" );
  101.     ExitThread(0);
  102.     return 0;
  103. }
  104. /**********
  105. * main() *
  106. **********/
  107. int main(int argc, char * argv[]){
  108. // Initialisation
  109.     WSADATA WSAData;
  110. if( WSAStartup(MAKEWORD(2,0),&WSAData) != 0 )
  111.     {
  112.         fprintf(stderr, "WSAStartup error. Error: %d\r\n", WSAGetLastError());
  113.         display_error("WSAStartup error !" );
  114.         return 1;
  115.     }
  116. // Variables
  117.     SOCKET socket_local;
  118.     SOCKET socket_client;
  119.     SOCKADDR_IN server;
  120.     SOCKADDR_IN client;
  121. DWORD  dwThreadID;
  122.     int sin_size = sizeof(SOCKADDR_IN);
  123.     if( (socket_local = socket(AF_INET,SOCK_STREAM,0) ) == INVALID_SOCKET )
  124.     {
  125.         fprintf(stderr, "Socket error. Error: %d\r\n", WSAGetLastError());
  126.         display_error("Socket error !" );
  127.  WSACleanup();
  128.         return 1;
  129.     }
  130. // Configuration du proxy (port 8080)
  131. server.sin_family      = AF_INET;
  132. server.sin_port        = htons(8080);
  133. server.sin_addr.s_addr = INADDR_ANY;
  134. memset(&(server.sin_zero),'\0',8);
  135.     if( bind(socket_local,(struct sockaddr * )&server,sizeof(struct sockaddr)) == SOCKET_ERROR)
  136.     {
  137.  fprintf(stderr, "Bind error. Error: %d\r\n", WSAGetLastError());
  138.         display_error("Bind error !" );
  139.  closesocket(socket_client);
  140.  WSACleanup();
  141.         return 1;
  142.     }
  143.     listen(socket_local, SOMAXCONN);
  144. // Attente de connexion, si erreur on quitte le programme
  145. while(1)
  146. {
  147.  if( (socket_client = accept(socket_local,(struct sockaddr * )&client,&sin_size)) == INVALID_SOCKET )
  148.  {
  149.    fprintf(stderr, "Accept error.Error: %d\r\n", WSAGetLastError());
  150.    display_error("Accept error !" );
  151.    closesocket(socket_client);
  152.    WSACleanup();
  153.    return 1;
  154.  }
  155.  else
  156.  {
  157.   fprintf(stdout,"Connection de : %s \n",inet_ntoa(client.sin_addr));
  158. // On cree un thread par nouvelle connexion en
  159. // appelant la fonction proxy avec comme paramètre le socket client
  160. // Si erreur a la creation d un thread on quitte
  161.   if( CreateThread( NULL,
  162.        0,
  163.        (LPTHREAD_START_ROUTINE) proxy,
  164.        socket_client,
  165.        0,
  166.        &dwThreadID) == NULL )
  167.   {
  168.    fprintf(stderr, "CreateThread error.\r\n" );
  169.    display_error("CreateThread error !" );
  170.    return 1;
  171.   }
  172.  }
  173. }
  174.     return 0;
  175. }


Merci d'avance  :)

n°1348861
nargy
Posté le 18-04-2006 à 15:21:58  profilanswer
 

oui! parceque les navigateurs moderne ne demandent pas l'image en entier. Ils en font la demande au serveur bout par bout, selon l'affichage necessaire. Par exemple, si l'internaute va directement au bas de la page, le téléchargement des images du haut de la page est interrompu après le bout courant et sera repris en dernier.
 
La  demande partiel est, il me semble le code HTTP 304. Tu doit le traiter spécialement.
 
Comme quoi, je t'avais dit, c'est pas aussi évident... :D Mais tu es sur la bonne voie.


Message édité par nargy le 18-04-2006 à 15:24:17
n°1348865
nargy
Posté le 18-04-2006 à 15:23:40  profilanswer
 

heu non, c'est pas le code 304. là je me souviens plus. tu devrais le trouver sur le web.


Message édité par nargy le 18-04-2006 à 15:24:42
n°1348896
psyphi
Posté le 18-04-2006 à 15:40:01  profilanswer
 

:sweat:  :cry: ouin je pensais pas que c'était si dur que ça.
En tout cas heureusement que tu me dis ça car j'en pouvais de chercher sans comprendre, je pensais que ca venait de mon code.
Ou est ce que je vais trouver ce code spécifique dans les RFC ?

n°1348948
nargy
Posté le 18-04-2006 à 16:05:49  profilanswer
 

> Ou est ce que je vais trouver ce code spécifique dans les RFC ?
- heu je l'avais trouvé, j'ai un poil la flemme de rechercher là. pourtant je l'ai presque sous les yeux, dans mes logs c'est affiché quelquepart. si, si, je t'assure :lol:
- indice: fait un debug de l'entête totale envoyée par le navigateur au proxy (jusqu'au double \n\n)

n°1348953
nargy
Posté le 18-04-2006 à 16:09:06  profilanswer
 

ha tiens: 206 Partial Content

n°1348957
nargy
Posté le 18-04-2006 à 16:10:21  profilanswer
 
n°1349042
psyphi
Posté le 18-04-2006 à 17:21:03  profilanswer
 

C'est quand même bizarre cette histoire je viens de trouver une autre source de proxy (enfin ! lol) et il ne gère nul part le 206 Partial Content et pourtant quand j'utilise son proxy avec la dernière version de firefox les images s'affichent.
source: http://www.cppfrance.com/code.aspx?ID=10846
Est ce que cela peut venir de mes threads?

n°1349049
psyphi
Posté le 18-04-2006 à 17:30:29  profilanswer
 

Effectivement je reviens de faire un test, en utilisant un buffer de 1 octets (char) au lieu de 1ko (char buffer2[1024]) pour la reception des données du serveur et cette fois les images s'affiches :-|.
C'est quand même bizarre ca. Faut que je trouve une solution car des buffers de 1octets pour le transfert c'est pas cool.


Message édité par psyphi le 18-04-2006 à 17:31:18
n°1350834
nargy
Posté le 20-04-2006 à 22:00:03  profilanswer
 
n°1351000
psyphi
Posté le 21-04-2006 à 10:32:35  profilanswer
 

J'ai fait une grosse mise à jour du code, finis les gros plantage! :)  
Problème restant, navigation lente sur certain site, impossible de naviger sur certain site, le logiciel freeze par moment, il reste coincé dans la boucle de download.  :sweat:  
Tout est ici: http://www.cppfrance.com/codes/WIN [...] 37134.aspx
la source:

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <windows.h>
  5. #include <winsock2.h>
  6. #pragma comment(lib, "ws2_32.lib" )
  7. /**************
  8. * prototypes *
  9. **************/
  10. void display_error(char * errorType);
  11. char * get_host(char * httpRequest);
  12. void cut_host_and_port(char * host, char * port);
  13. char * get_port(char * port);
  14. DWORD WINAPI proxy (LPVOID psocket);
  15. /*************
  16. * functions *
  17. *************/
  18. /*
  19. * display_error()
  20. * donne la raison de l'erreur sert au debugage
  21. */
  22. void display_error(char * errorType){
  23. LPVOID lpMsgBuf;
  24. FormatMessage(  FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  25.     NULL,
  26.     GetLastError(),
  27.     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  28.     (LPTSTR) &lpMsgBuf,
  29.     0,
  30.     NULL);
  31. // Affichage du message dans une boite de dialogue
  32. MessageBox( NULL, lpMsgBuf, errorType, MB_OK | MB_ICONERROR );
  33. // Libération du buffer
  34. LocalFree( lpMsgBuf );
  35. }
  36. /*
  37. * get_host()
  38. * fonction qui isole le header http host qui suit le "Host:"
  39. */
  40. char * get_host(char * httpRequest){
  41. unsigned short i = 0, j = 0;
  42. char * buffer = (char *)malloc(2*1024 * sizeof(char));
  43. if( !(buffer = strstr(httpRequest, "Host: " )) ){
  44.  fprintf(stderr, "Can\'t find host in this request !\r\n" );
  45.  return "error";
  46. }
  47. else{
  48.  char * host = (char *)malloc(256 * sizeof(char));
  49.  while( buffer[i] != '\n' )
  50.   i++;
  51.  for(j = 6; j < i-1; j++)
  52.   host[j - 6] = buffer[j];
  53.  host[j-6+1] = '\0';
  54.  return host;
  55. }
  56. }
  57. /*
  58. * cut_host_and_port
  59. * separe le host de son port
  60. */
  61. void cut_host_and_port(char * host, char * port){
  62.  unsigned short i = 0;
  63.  unsigned short y = 0;
  64.  unsigned short size = strlen(host);
  65.  while(host[i] != ':')
  66.   i++;
  67.  host[i] = '\0';
  68.  i++;
  69.  for(y = 0; y < 5, i < size; i++, y++)
  70.   port[y] = host[i];
  71. }
  72. /*
  73. * proxy()
  74. */
  75. DWORD WINAPI proxy (LPVOID psocket){
  76. //Recuperation de la valeur du socket
  77. SOCKET * ps = psocket;
  78. SOCKET socket_client = *ps;
  79. //On a la valeur de la socket, on peut désallouer
  80. free(psocket);
  81. SOCKET envoi;
  82. SOCKADDR_IN server2;
  83. struct hostent * structHost;
  84. char buffer[1024*2];  // 2 ko
  85. char buffer2[1024*4];   // 4 ko
  86. memset(buffer,'\0', sizeof(buffer));
  87. memset(buffer2,'\0', sizeof(buffer2));
  88. // On recoit la requete du navigateur
  89. int size = recv(socket_client, buffer, sizeof(buffer), 0);
  90. fprintf(stdout, "----Commande recue ----\r\n%s----\r\n", buffer);
  91. // On récupère le header (Host:) de la requete
  92. // pour pouvoir se connecter au serveur web
  93. char * host = get_host(buffer);
  94. // Parfois host a la forme (Host: adresse:port
  95. // donc on creer une variable port pour récupérer ce dernier
  96. char * port = (char *)malloc(5 * sizeof(char));
  97. if( !strncmp(host, "error", 5) ){
  98.  fprintf(stderr, "get_host return error.\r\n" );
  99.  closesocket(socket_client);
  100.  //ExitThread(0);
  101.  return 1;
  102. }
  103. else if( strchr(host,':')){
  104.    cut_host_and_port(host, port);
  105.   }
  106.   else{
  107.    port = "80";
  108.   }
  109. fprintf(stdout,"Host : [%s], port : [%s]\r\n", host, port);
  110. // On envoie la requete au serveur web
  111. // grace a un nouveau socket
  112. if((structHost = gethostbyname(host)) == NULL){
  113.   fprintf(stderr,"Host error. Can't find %s\r\n", host);
  114.   closesocket(socket_client);
  115.   //ExitThread(0);
  116.   return 1;
  117. }
  118. if((envoi = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
  119.  fprintf(stderr, "Socket error. Error: %d\r\n", WSAGetLastError());
  120.  closesocket(socket_client);
  121.         display_error("Socket error !" );
  122.         //ExitThread(0);
  123.         return 1;
  124. }
  125.     server2.sin_family = AF_INET;
  126. server2.sin_port   = htons(atoi(port));
  127. server2.sin_addr   = *((struct in_addr *)structHost->h_addr);
  128. memset(&(server2.sin_zero),'\0',8);
  129.     if( connect(envoi,(struct sockaddr * )&server2, sizeof(struct sockaddr)) == -1){
  130.         fprintf(stderr,"Error connect\r\n" );
  131.  closesocket(socket_client);
  132.  closesocket(envoi);
  133.         //display_error("Connect Error !" );
  134.         //ExitThread(0);
  135.         return 1;
  136.     }
  137.     send(envoi, buffer, strlen(buffer), 0);
  138. // Reception des donnees a partir du serveur
  139. // et les renvoies au navigateur
  140. while( (size = recv(envoi, buffer2, sizeof(buffer2),0)) > 0){
  141.  //fprintf(stdout, "---buffer----\r\n%s\r\n----", buffer2);
  142. // Renvoie de la réponse au navigateur
  143.  buffer2[size]='\0';
  144.  send(socket_client, buffer2, size, 0);
  145.    }
  146. //Nettoyage
  147.     closesocket(socket_client);
  148.     closesocket(envoi);
  149.     fprintf(stdout, "Exiting Thread.\r\n" );
  150. //ExitThread(0);
  151.     return 0;
  152. }
  153. /**********
  154. * main() *
  155. **********/
  156. int main(int argc, char * argv[]){
  157. // Initialisation
  158.     WSADATA WSAData;
  159. if( WSAStartup(MAKEWORD(2,0),&WSAData) != 0 )
  160.     {
  161.         fprintf(stderr, "WSAStartup error. Error: %d\r\n", WSAGetLastError());
  162.         display_error("WSAStartup error !" );
  163.         return 1;
  164.     }
  165. // Variables
  166.     SOCKET socket_local;
  167.     SOCKET socket_client;
  168.     SOCKADDR_IN server;
  169.     SOCKADDR_IN client;
  170. DWORD  dwThreadID;
  171. int * paramThread = malloc(sizeof dwThreadID);
  172. if(paramThread == NULL){
  173.  display_error("Thread error !" );
  174.  return EXIT_FAILURE;
  175. }
  176.     int sin_size = sizeof(SOCKADDR_IN);
  177.     if( (socket_local = socket(AF_INET,SOCK_STREAM,0) ) == INVALID_SOCKET )
  178.     {
  179.         fprintf(stderr, "Socket error. Error: %d\r\n", WSAGetLastError());
  180.         display_error("Socket error !" );
  181.  WSACleanup();
  182.         return 1;
  183.     }
  184. // Configuration du proxy (port 8080)
  185. server.sin_family      = AF_INET;
  186. server.sin_port        = htons(8080);
  187. server.sin_addr.s_addr = INADDR_ANY;
  188. memset(&(server.sin_zero), '\0', 8);
  189.     if( bind(socket_local,(struct sockaddr * )&server,sizeof(struct sockaddr)) == SOCKET_ERROR)
  190.     {
  191.  fprintf(stderr, "Bind error. Error: %d\r\n", WSAGetLastError());
  192.         display_error("Bind error !" );
  193.  closesocket(socket_client);
  194.  WSACleanup();
  195.         return 1;
  196.     }
  197.     listen(socket_local, SOMAXCONN);
  198. // Attente de connexion, si erreur on quitte le programme
  199. while(1)
  200. {
  201.  if( (socket_client = accept(socket_local,(struct sockaddr * )&client,&sin_size)) == INVALID_SOCKET )
  202.  {
  203.    fprintf(stderr, "Accept error.Error: %d\r\n", WSAGetLastError());
  204.    display_error("Accept error !" );
  205.    closesocket(socket_client);
  206.    WSACleanup();
  207.    return 1;
  208.  }
  209.  else
  210.  {
  211.   fprintf(stdout,"Connection de : %s \n",inet_ntoa(client.sin_addr));
  212. // On cree un thread par nouvelle connexion en
  213. // appelant la fonction proxy avec comme paramètre le socket client
  214. // Si erreur a la creation d un thread on quitte
  215.   *paramThread = socket_client;
  216.   if( CreateThread( NULL,
  217.        0,
  218.        (LPTHREAD_START_ROUTINE) proxy,
  219.        paramThread,
  220.        0,
  221.        &dwThreadID) == NULL )
  222.   {
  223.    fprintf(stderr, "CreateThread error.\r\n" );
  224.    display_error("CreateThread error !" );
  225.    return 1;
  226.   }
  227.   //proxy(paramThread );
  228.  }
  229. }
  230.     return 0;
  231. }


Merci de ton aide nargy

n°1351013
nargy
Posté le 21-04-2006 à 10:40:52  profilanswer
 

ouais le code est un peu gros, et en plus c'est du windoz. je peut pas tester là, et c'est balaise avec autant de code de compiler de tête.
je te conseillerai bien de rajouter du débug à fond, histoire de cibler le problème.

n°1351014
nargy
Posté le 21-04-2006 à 10:41:55  profilanswer
 

pour le freeze, tu doit avoir un problème de communication thread.

n°1352062
psyphi
Posté le 23-04-2006 à 00:44:52  profilanswer
 

J'ai un nouveau problème, encore un  :fou: . Depuis que j'ai rajouté mes fonctions de parse de requete HTTP, le nombre de site qui fonctionne est bien meilleur qu'auparavant et je n'ai plus de freeze mais par contre le multithreading plante !!
J'ai des erreurs du type:
Citation:
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.
 
PS2: la source devenant trop longue je ne vais pas poluer le forum, elle est ici:
http://membres.lycos.fr/bobov/code/main.c
 
PS3: Merci nargy pour ton aide jusque ici.

n°1352063
tholdan
Posté le 23-04-2006 à 00:56:56  profilanswer
 

Il plante à sur l'index du forum chez moi. :o

----Accept: []
Cookie: []
Host: []
----
Can't find host in this request !
get_host return error.
Exiting Thread Normaly.
 
C:\dev\C>


Pour les dernières lignes


---------------
Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn
n°1352065
nargy
Posté le 23-04-2006 à 00:59:48  profilanswer
 

> 0x0040155f emploie l'adresse mémoire 0x0014a0000. La mémoire ne peut pas être "read".  
 
- indique que tu as un pointeur qui se balade dans le vide. il te faut un débuggeur, qui te dira à quelle ligne de ton programme tu accède à un pointeur qui n'a pas été initialisé, ou utilisé après avoir été libéré. Sans débuggeur, tu peut trouver mais moins facilement en ajoutant des printf de débug à chaque fonctions puis chaque ligne.

n°1352068
nargy
Posté le 23-04-2006 à 01:02:15  profilanswer
 

:D oui, les entêtes n'ont pas d'ordre

n°1352069
tholdan
Posté le 23-04-2006 à 01:03:14  profilanswer
 

nargy a écrit :

> 0x0040155f emploie l'adresse mémoire 0x0014a0000. La mémoire ne peut pas être "read".  
 
- indique que tu as un pointeur qui se balade dans le vide. il te faut un débuggeur, qui te dira à quelle ligne de ton programme tu accède à un pointeur qui n'a pas été initialisé, ou utilisé après avoir été libéré. Sans débuggeur, tu peut trouver mais moins facilement en ajoutant des printf de débug à chaque fonctions puis chaque ligne.


Code :
  1. C:\\dev\\C\\proxy2.c:317: warning: 'socket_client' might be used uninitialized in this function


Si ça peut aider. :o


Message édité par tholdan le 23-04-2006 à 01:03:45

---------------
Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn
n°1352081
psyphi
Posté le 23-04-2006 à 01:43:33  profilanswer
 

Le problème des erreurs de read provennait de l'espace mémoire des threads qui était mal initialisé à chaque nouveau thread.
Normalment c'est corrigé.
Tholdan t'a compilé avec quoi, j'ai pas ce warning la moi :?.
Sinon j'ai pas de plantage à l'index du forum, j'en ai pour les requetes POST par contre. C'est quoi ton navigateur?

n°1352084
tholdan
Posté le 23-04-2006 à 01:49:53  profilanswer
 

psyphi a écrit :

Le problème des erreurs de read provennait de l'espace mémoire des threads qui était mal initialisé à chaque nouveau thread.
Normalment c'est corrigé.
Tholdan t'a compilé avec quoi, j'ai pas ce warning la moi :?.
Sinon j'ai pas de plantage à l'index du forum, j'en ai pour les requetes POST par contre. C'est quoi ton navigateur?


GCC -Wall
Et firefox 1.5 comme navigateur.


Message édité par tholdan le 23-04-2006 à 01:50:17

---------------
Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn
n°1353984
psyphi
Posté le 26-04-2006 à 00:12:54  profilanswer
 

Pour ceux que ça interesse j'ai fait une mise à jour du code avec l'implémentation de la requete POST.
http://www.cppfrance.com/code.aspx?ID=37134
En fait maintenant j'aimerais bien avoir le retour d'utilisateur :)

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  [C/Socket]Programmer un proxy

 

Sujets relatifs
QQ1 peut il m'aider à propos de socket non bloquant je n'y connais rieComment programmer une interruption matérielle???
programmer logiciel en BASICnovice en programmation doit programmer sous unix.
rmi zip socketForcer authentification au proxy
[C] select avec les socketEmulation socket
quel soft utiliser pour creer un site web sans savoir programmer??Java Socket & Crontab
Plus de sujets relatifs à : [C/Socket]Programmer un proxy


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR