[C/Socket]Programmer un proxy

Programmer un proxy [C/Socket] - C - Programmation

Marsh Posté le 08-04-2006 à 20:02:26    

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:

Reply

Marsh Posté le 08-04-2006 à 20:02:26   

Reply

Marsh Posté le 08-04-2006 à 23:55:03    

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.

Reply

Marsh Posté le 09-04-2006 à 17:11:00    

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)

Reply

Marsh Posté le 09-04-2006 à 18:15:20    

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
Reply

Marsh Posté le 09-04-2006 à 18:45:00    

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)

Reply

Marsh Posté le 09-04-2006 à 19:43:50    

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.

Reply

Marsh Posté le 09-04-2006 à 20:24:36    

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

Reply

Marsh Posté le 10-04-2006 à 09:51:25    

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

Reply

Marsh Posté le 10-04-2006 à 09:57:36    

C'est un bon début.

Reply

Marsh Posté le 12-04-2006 à 22:35:18    

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
Reply

Marsh Posté le 12-04-2006 à 22:35:18   

Reply

Marsh Posté le 12-04-2006 à 22:40:22    

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
Reply

Marsh Posté le 12-04-2006 à 22:42:24    

: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

Reply

Marsh Posté le 13-04-2006 à 01:41:16    

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/
Reply

Marsh Posté le 14-04-2006 à 15:27:48    

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

Reply

Marsh Posté le 18-04-2006 à 15:15:43    

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  :)

Reply

Marsh Posté le 18-04-2006 à 15:21:58    

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
Reply

Marsh Posté le 18-04-2006 à 15:23:40    

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
Reply

Marsh Posté le 18-04-2006 à 15:40:01    

: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 ?

Reply

Marsh Posté le 18-04-2006 à 16:05:49    

> 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)

Reply

Marsh Posté le 18-04-2006 à 16:09:06    

ha tiens: 206 Partial Content

Reply

Marsh Posté le 18-04-2006 à 16:10:21    

Reply

Marsh Posté le 18-04-2006 à 17:21:03    

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?

Reply

Marsh Posté le 18-04-2006 à 17:30:29    

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
Reply

Marsh Posté le 20-04-2006 à 22:00:03    

Reply

Marsh Posté le 21-04-2006 à 10:32:35    

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

Reply

Marsh Posté le 21-04-2006 à 10:40:52    

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.

Reply

Marsh Posté le 21-04-2006 à 10:41:55    

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

Reply

Marsh Posté le 23-04-2006 à 00:44:52    

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.

Reply

Marsh Posté le 23-04-2006 à 00:56:56    

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 ! [:thalis]
Reply

Marsh Posté le 23-04-2006 à 00:59:48    

> 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.

Reply

Marsh Posté le 23-04-2006 à 01:02:15    

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

Reply

Marsh Posté le 23-04-2006 à 01:03:14    

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 ! [:thalis]
Reply

Marsh Posté le 23-04-2006 à 01:43:33    

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?

Reply

Marsh Posté le 23-04-2006 à 01:49:53    

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 ! [:thalis]
Reply

Marsh Posté le 26-04-2006 à 00:12:54    

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 :)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed