home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / PROXY.ZIP / Proxy.cpp next >
Encoding:
C/C++ Source or Header  |  1999-04-19  |  10.0 KB  |  371 lines

  1.  
  2. // Proxy.cpp is very simple program to implement the HTTP proxy function.
  3. // To make it short and clear , some error tolerant codes are omitted.
  4. // Written by HU Zhongshan   
  5. // e-mail huzhongshan@hotmail.com OR yangjy@mail.njust.edu.cn
  6. // 1999-4-18
  7. #include "stdafx.h"
  8. #include "Proxy.h"
  9. #include <winsock2.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13.  
  14. #ifdef _DEBUG
  15. #define new DEBUG_NEW
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19.  
  20. /////////////////////////////////////////////////////////////////////////////
  21. // The one and only application object
  22.  
  23. #define HTTP  "http://"
  24. #define FTP   "ftp://"
  25. #define PROXYPORT    5060    //Proxy Listen Port
  26. #define BUFSIZE   10240      //Buffer size
  27.  
  28.  
  29. CWinApp theApp;
  30.  
  31. using namespace std;
  32.  
  33. UINT ProxyToServer(LPVOID pParam);
  34. UINT UserToProxyThread(void *pParam);
  35.  
  36. struct SocketPair{
  37.     SOCKET  user_proxy;      //socket : local machine to proxy server
  38.     SOCKET  proxy_server;    //socket : proxy sever to remote server
  39.     BOOL    IsUser_ProxyClosed; // status of local machine to proxy server
  40.     BOOL    IsProxy_ServerClosed; // status of proxy server to remote server
  41. };
  42.  
  43.  
  44. struct ProxyParam{
  45.     char Address[256];    // address of remote server
  46.     HANDLE User_SvrOK;    // status of setup connection between proxy server and remote server
  47.     SocketPair *pPair;    // pointer to socket pair
  48.     int     Port;         // port which will be used to connect to remote server
  49.     };                   //This struct is used to exchange information between threads.
  50.  
  51. SOCKET    gListen_Socket;   
  52.  
  53. int StartServer()
  54. {
  55.      WSADATA wsaData;
  56.      sockaddr_in local;
  57.      SOCKET listen_socket;
  58.  
  59.     if(::WSAStartup(0x202,&wsaData)!=0)
  60.         {printf("\nError in Startup session.\n");WSACleanup();return -1;};
  61.  
  62.     local.sin_family=AF_INET;
  63.     local.sin_addr.s_addr=INADDR_ANY;
  64.     local.sin_port=htons(PROXYPORT);
  65.  
  66.     listen_socket=socket(AF_INET,SOCK_STREAM,0);
  67.     if(listen_socket==INVALID_SOCKET)
  68.         {printf("\nError in New a Socket.");WSACleanup();return -2;}
  69.  
  70.     if(::bind(listen_socket,(sockaddr *)&local,sizeof(local))!=0)
  71.         {printf("\n Error in Binding socket.");    WSACleanup();return -3;    };
  72.  
  73.     if(::listen(listen_socket,5)!=0)
  74.         {printf("\n Error in Listen."); WSACleanup(); return -4;}
  75.     gListen_Socket=listen_socket; 
  76.     AfxBeginThread(UserToProxyThread,NULL);   //Start accept function
  77.     return 1;
  78. }
  79.  
  80. int CloseServer()
  81. {
  82.     closesocket(gListen_Socket);
  83.     WSACleanup();
  84.     return 1;
  85. }
  86.  
  87. //Analisys the string, to find the remote address
  88. int GetAddressAndPort( char * str, char *address, int * port)
  89. {
  90.     char buf[BUFSIZE], command[512], proto[128], *p;
  91.     int j;
  92.     sscanf(str,"%s%s%s",command,buf,proto);
  93.     p=strstr(buf,HTTP);
  94.     //HTTP
  95.     if(p)
  96.     {
  97.         p+=strlen(HTTP);
  98.         for(int i=0;i<strlen(p);i++)
  99.             if( *(p+i)=='/') break;
  100.         *(p+i)=0;
  101.         strcpy(address,p);
  102.         p=strstr(str,HTTP);
  103.         for(int j=0;j<i+strlen(HTTP);j++)
  104.             *(p+j)=' ';  //to remove the host name: GET http://www.njust.edu.cn/ HTTP1.1  ==> GET / HTTP1.1
  105.         *port=80;      //default http port 
  106.     }
  107.     else
  108.     {//FTP, Not supported, and following code can be omitted.
  109.      p=strstr(buf,FTP);
  110.      if(!p) return 0;
  111.          p+=strlen(FTP);
  112.         for(int i=0;i<strlen(p);i++)
  113.             if( *(p+i)=='/') break;      //Get The Remote Host
  114.         *(p+i)=0;
  115.         for(j=0;j<strlen(p);j++)
  116.             if(*(p+j)==':') 
  117.                 {*port=atoi(p+j+1);    //Get The Port
  118.                  *(p+j)=0;
  119.                 }
  120.              else *port=21;                                   
  121.  
  122.         strcpy(address,p);
  123.         p=strstr(str,FTP);
  124.         for(j=0;j<i+strlen(FTP);j++)
  125.             *(p+j)=' ';        
  126.     }
  127.     return 1; 
  128. }
  129.  
  130. // Setup chanel and read data from local , send data to remote
  131. UINT UserToProxyThread(void *pParam)
  132. {
  133.      char Buffer[BUFSIZE];
  134.      int  Len;
  135.      sockaddr_in from;
  136.      SOCKET msg_socket;
  137.      int fromlen,retval;
  138.      SocketPair SPair;
  139.      ProxyParam ProxyP;
  140.      CWinThread *pChildThread;
  141.      fromlen=sizeof(from);
  142.      msg_socket=accept(gListen_Socket,(struct sockaddr*)&from,&fromlen);
  143.       AfxBeginThread(UserToProxyThread,pParam); //Start another thread to listen.
  144.      if( msg_socket==INVALID_SOCKET)
  145.         { printf( "\nError  in accept "); return -5;}
  146.      
  147.     //recieve the first line of client
  148.  
  149.      SPair.IsUser_ProxyClosed=FALSE;
  150.      SPair.IsProxy_ServerClosed=TRUE;
  151.      SPair.user_proxy=msg_socket;
  152.  
  153.      retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);
  154.      
  155.      if(retval==SOCKET_ERROR)
  156.             { printf("\nError Recv"); 
  157.               if(SPair.IsUser_ProxyClosed==FALSE)
  158.                 {closesocket(SPair.user_proxy);
  159.                  SPair.IsUser_ProxyClosed=TRUE;
  160.                 }
  161.             }
  162.      if(retval==0)
  163.             {printf("Client Close connection\n");
  164.              if(SPair.IsUser_ProxyClosed==FALSE)
  165.                 {closesocket(SPair.user_proxy);
  166.                  SPair.IsUser_ProxyClosed=TRUE;
  167.                 }
  168.             }
  169.      Len=retval;
  170. #ifdef _DEBUG
  171.  
  172.      Buffer[Len]=0;
  173.      printf("\n Received %d bytes,data[%s]from client\n",retval,Buffer);
  174. #endif
  175.      //
  176.      SPair.IsUser_ProxyClosed=FALSE;
  177.      SPair.IsProxy_ServerClosed=TRUE;
  178.      SPair.user_proxy=msg_socket;
  179.  
  180.      ProxyP.pPair=&SPair;
  181.      ProxyP.User_SvrOK=CreateEvent(NULL,TRUE,FALSE,NULL);
  182.      
  183.      GetAddressAndPort( Buffer,ProxyP.Address,&ProxyP.Port);
  184.  
  185.      pChildThread=AfxBeginThread(ProxyToServer,(LPVOID)&ProxyP);
  186.      ::WaitForSingleObject(ProxyP.User_SvrOK,60000);  //Wait for connection between proxy and remote server
  187.      ::CloseHandle(ProxyP.User_SvrOK);
  188.  
  189.   while(SPair.IsProxy_ServerClosed ==FALSE && SPair.IsUser_ProxyClosed==FALSE)
  190.      {    
  191.        retval=send(SPair.proxy_server,Buffer,Len,0);
  192.        if(retval==SOCKET_ERROR)
  193.         { printf("\n send() failed:error%d\n",WSAGetLastError());
  194.          if(SPair.IsProxy_ServerClosed==FALSE)
  195.             {
  196.                 closesocket(SPair.proxy_server);
  197.                 SPair.IsProxy_ServerClosed=TRUE;
  198.             }
  199.           continue;
  200.         }
  201.         retval=recv(SPair.user_proxy,Buffer,sizeof(Buffer),0);
  202.      
  203.         if(retval==SOCKET_ERROR)
  204.             { printf("\nError Recv"); 
  205.               if(SPair.IsUser_ProxyClosed==FALSE)
  206.                 {closesocket(SPair.user_proxy);
  207.                  SPair.IsUser_ProxyClosed=TRUE;
  208.                 }
  209.               continue;
  210.             }
  211.         if(retval==0)
  212.             {printf("Client Close connection\n");
  213.              if(SPair.IsUser_ProxyClosed==FALSE)
  214.                 {closesocket(SPair.user_proxy);
  215.                  SPair.IsUser_ProxyClosed=TRUE;
  216.                 }
  217.              break;
  218.             }
  219.         Len=retval;
  220. #ifdef _DEBUG
  221.         Buffer[Len]=0;
  222.      printf("\n Received %d bytes,data[%s]from client\n",retval,Buffer);
  223. #endif
  224.     
  225.   } //End While
  226.  
  227.      if(SPair.IsProxy_ServerClosed==FALSE)
  228.             {
  229.                 closesocket(SPair.proxy_server);
  230.                 SPair.IsProxy_ServerClosed=TRUE;
  231.             }
  232.      if(SPair.IsUser_ProxyClosed==FALSE)
  233.                 {closesocket(SPair.user_proxy);
  234.                  SPair.IsUser_ProxyClosed=TRUE;
  235.                 }
  236.     ::WaitForSingleObject(pChildThread->m_hThread,20000);  //Should check the reture value
  237.     return 0;
  238. }
  239.  
  240. // Read data from remote and send data to local
  241. UINT ProxyToServer(LPVOID pParam)
  242. {
  243.     ProxyParam * pPar=(ProxyParam*)pParam;
  244.     char Buffer[BUFSIZE];
  245.     char *server_name= "localhost";
  246.     unsigned short port ;
  247.     int retval,Len;
  248.     unsigned int addr;
  249.     int socket_type ;
  250.     struct sockaddr_in server;
  251.     struct hostent *hp;
  252.     SOCKET  conn_socket;
  253.  
  254.     socket_type = SOCK_STREAM;
  255.     server_name = pPar->Address;
  256.     port = pPar->Port;
  257.  
  258.     if (isalpha(server_name[0])) {   /* server address is a name */
  259.         hp = gethostbyname(server_name);
  260.     }
  261.     else  { /* Convert nnn.nnn address to a usable one */
  262.         addr = inet_addr(server_name);
  263.         hp = gethostbyaddr((char *)&addr,4,AF_INET);
  264.     }
  265.     if (hp == NULL ) {
  266.         fprintf(stderr,"Client: Cannot resolve address [%s]: Error %d\n",
  267.             server_name,WSAGetLastError());
  268.         ::SetEvent(pPar->User_SvrOK);    
  269.         return 0;
  270.     }
  271.  
  272.     //
  273.     // Copy the resolved information into the sockaddr_in structure
  274.     //
  275.     memset(&server,0,sizeof(server));
  276.     memcpy(&(server.sin_addr),hp->h_addr,hp->h_length);
  277.     server.sin_family = hp->h_addrtype;
  278.     server.sin_port = htons(port);
  279.  
  280.     conn_socket = socket(AF_INET,socket_type,0); /* Open a socket */
  281.     if (conn_socket <0 ) {
  282.         fprintf(stderr,"Client: Error Opening socket: Error %d\n",
  283.             WSAGetLastError());
  284.         pPar->pPair->IsProxy_ServerClosed=TRUE;
  285.         ::SetEvent(pPar->User_SvrOK);    
  286.         return -1;
  287.     }
  288.  
  289.  
  290. #ifdef _DEBUG
  291.     printf("Client connecting to: %s\n",hp->h_name);
  292. #endif
  293.     if (connect(conn_socket,(struct sockaddr*)&server,sizeof(server))
  294.         == SOCKET_ERROR) {
  295.         fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
  296.         pPar->pPair->IsProxy_ServerClosed=TRUE;    
  297.         ::SetEvent(pPar->User_SvrOK);    
  298.         return -1;
  299.     }
  300.     pPar->pPair->proxy_server=conn_socket;
  301.     pPar->pPair->IsProxy_ServerClosed=FALSE;
  302.     ::SetEvent(pPar->User_SvrOK);
  303.     // cook up a string to send
  304.     while(!pPar->pPair->IsProxy_ServerClosed &&!pPar->pPair->IsUser_ProxyClosed)
  305.     {
  306.         retval = recv(conn_socket,Buffer,sizeof (Buffer),0 );
  307.         if (retval == SOCKET_ERROR ) {
  308.             fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());
  309.             closesocket(conn_socket);
  310.             pPar->pPair->IsProxy_ServerClosed=TRUE;
  311.             break;
  312.         }
  313.         Len=retval;
  314.         if (retval == 0) {
  315.             printf("Server closed connection\n");
  316.             closesocket(conn_socket);
  317.             pPar->pPair->IsProxy_ServerClosed=TRUE;
  318.             break;
  319.             }
  320.  
  321.         retval = send(pPar->pPair->user_proxy,Buffer,Len,0);
  322.         if (retval == SOCKET_ERROR) {
  323.             fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
  324.             closesocket(pPar->pPair->user_proxy);
  325.             pPar->pPair->IsUser_ProxyClosed=TRUE;
  326.             break;                        
  327.         }
  328. #ifdef _DEBUG    
  329.         Buffer[Len]=0;        
  330.         printf("Received %d bytes, data [%s] from server\n",retval,Buffer);
  331. #endif
  332.     }
  333.     if(pPar->pPair->IsProxy_ServerClosed==FALSE)
  334.             {
  335.                 closesocket(pPar->pPair->proxy_server);
  336.                 pPar->pPair->IsProxy_ServerClosed=TRUE;
  337.             }
  338.      if(pPar->pPair->IsUser_ProxyClosed==FALSE)
  339.                 {closesocket(pPar->pPair->user_proxy);
  340.                  pPar->pPair->IsUser_ProxyClosed=TRUE;
  341.                 }
  342.      return 1;
  343. }
  344.  
  345.  
  346.  
  347. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  348. {
  349.     int nRetCode = 0;
  350.  
  351.     // initialize MFC and print and error on failure
  352.     if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
  353.     {
  354.         // TODO: change error code to suit your needs
  355.         cerr << _T("Fatal Error: MFC initialization failed") << endl;
  356.         nRetCode = 1;
  357.     }
  358.     else
  359.     {
  360.         // TODO: code your application's behavior here.
  361.         StartServer();    
  362.         while(1)    
  363.             if(getchar()=='q') break;
  364.         CloseServer();
  365.     }
  366.  
  367.     return nRetCode;
  368. }
  369.  
  370.  
  371.