Set up a proxy connection to be associated with the supplied connection. The proxy connection is then placed in the epoll event queue. - The supplied connection must be valid - If the other connection does not exist it will be created Please note that connections have three possible types as follows:- Direct: The hzIpConnex is that of a direct client of this service, with no proxy. In this case the hzIpConnex m_Input member receives the client requests (populated by epoll read events). The m_Outgoing member is populated by processing the request (i.e. it is the response). The contents of m_Outgoing are written to the client socket by the _xmit function. Has Proxy: The hzIpConnex is that of a client of this service, but has a proxy hzIpConnex to another service. Once the proxy hzIpConnex is established, the epoll reads are redirected. Instead of populating the m_Input member of the client hzIpConnex instance, client requests arriving via epoll reads populate the m_Outgoing member of the proxy hzIpConnex instance. The _xmit function as applied to the proxy hzIpConnex instance, then transmits the request to the other service. Is Proxy: The hzIpConnex is the proxy, which is the mirror image of the has-proxy case. The input (the response from the other service), is redirected to populate the m_Outgoing member of the client hzIpConnex. The _xmit function as applied to the client hzIpConnex instance, then transmits the response to the client. This function creates the proxy hzIpConnex instance, forms the association with the client hzIpConnex, and copies across any data received so far.

Return TypeFunction nameArguments
hzEcodehzIpServer::ProxyTo(hzIpConnex*,uint32_t,)

Declared in file: hzIpServer.h
Defined in file : hzIpServer.cpp

Function Logic:

0:START 1:unknown 2:Return hzerr(E_ARGUMENT,No connection) 3:unknown 4:pExt 5:hostname 6:unknown 7:items 8:Return E_HOSTFAIL 9:items svrAddr items svrAddr 10:unknown 11:Return hzerr(E_NOSOCKET,Could not create socket (returns %d, errno %d),nSock,errno) 12:unknown 13:Return hzerr(E_HOSTFAIL,Could not connect to %s on port %d (errno=%d),*hostname,nPort,errno) 14:rc 15:unknown 16:Return rc 17:tv tv 18:unknown 19:Return E_HOSTFAIL 20:epEventNew EPOLLIN epEventNew 21:unknown 22:items 23:unknown 24:items 25:m_bShutdown 26:Return E_HOSTFAIL 27:pConn 28:pExt pExt currCC items items items items 29:items items 30:Return E_OK

Function body:

hzEcode hzIpServer::ProxyTo (hzIpConnex* pConn)uint32_t nPort, 
{
   //  Set up a proxy connection to be associated with the supplied connection. The proxy connection is then placed in the epoll event queue.
   //  
   //   - The supplied connection must be valid
   //   - If the other connection does not exist it will be created
   //  
   //  Please note that connections have three possible types as follows:-
   //  
   //   Direct:  The hzIpConnex is that of a direct client of this service, with no proxy. In this case the hzIpConnex m_Input member receives the client requests (populated
   //      by epoll read events). The m_Outgoing member is populated by processing the request (i.e. it is the response). The contents of m_Outgoing are written to the
   //      client socket by the _xmit function.
   //  
   //   Has Proxy: The hzIpConnex is that of a client of this service, but has a proxy hzIpConnex to another service. Once the proxy hzIpConnex is established, the epoll reads
   //      are redirected. Instead of populating the m_Input member of the client hzIpConnex instance, client requests arriving via epoll reads populate the m_Outgoing
   //      member of the proxy hzIpConnex instance. The _xmit function as applied to the proxy hzIpConnex instance, then transmits the request to the other service.
   //  
   //   Is Proxy: The hzIpConnex is the proxy, which is the mirror image of the has-proxy case. The input (the response from the other service), is redirected to populate the
   //      m_Outgoing member of the client hzIpConnex. The _xmit function as applied to the client hzIpConnex instance, then transmits the response to the client.
   //  
   //  This function creates the proxy hzIpConnex instance, forms the association with the client hzIpConnex, and copies across any data received so far.
   _hzfunc("hzIpServer::ProxyTo") ;
   SOCKADDRIN          svrAddr ;       //  Server address
   HOSTENT*            pHost ;         //  External service host
   struct epoll_event  epEventNew ;    //  Epoll event for new connections
   struct timeval      tv ;            //  Timeout structure
   hzIpConnex*         pExt ;          //  External connection
   hzXDate             now ;           //  Time now (used to log connections)
   hzString            hostname ;      //  External service hostname
   int32_t             nSock ;         //  External connection socket
   hzEcode             rc ;            //  Return code
   if (!pConn)
       return hzerr(E_ARGUMENT, "No connection") ;
   if (pConn->m_pProxy)
       pExt = pConn->m_pProxy ;
   else
   {
       //  Get the hostname
       hostname = "127.0.0.1" ;
       if (!(pHost = gethostbyname(*hostname)))
       {
           threadLog("Unknown Host [%s]\n", *hostname) ;
           return E_HOSTFAIL ;
       }
       //  Create the socket
       memset(&svrAddr, 0,sizeof(svrAddr)) ;
       svrAddr.sin_family = AF_INET ;
       memcpy(&svrAddr.sin_addr, pHost->h_addr, pHost->h_length) ;
       svrAddr.sin_port = htons(nPort) ;
       //  Connect
       if ((nSock = socket(AF_INET, SOCK_STREAM, 0))< 0)
           return hzerr(E_NOSOCKET, "Could not create socket (returns %d, errno %d)", nSock, errno) ;
       //  Connect stage
       if (connect(nSock, (struct sockaddr *) &svrAddr, sizeof(svrAddr)) < 0)
           return hzerr(E_HOSTFAIL, "Could not connect to %s on port %d (errno=%d)", *hostname, nPort, errno) ;
       //  Set timeouts and non-blocking
       rc = _nonblock(nSock) ;
       if (rc != E_OK)
           return rc ;
       tv.tv_sec = 10;
       tv.tv_usec = 0;
       if (setsockopt(nSock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
           return E_HOSTFAIL ;
       //  Add the external connection to the epoll loop
       epEventNew.data.fd = nSock ;
       epEventNew.events = EPOLLIN | EPOLLOUT ;    //  | EPOLLET ;
       if (epoll_ctl(s_epollSocket, EPOLL_CTL_ADD, nSock, &epEventNew) < 0)
       {
           m_pLog->Log("Loop %u: EPOLL ERROR: Could not add client connection handler on sock %d/%d. Error=%s\n", m_nLoop, nSock, pConn->CliPort(), strerror(errno)) ;
           if (close(nSock) < 0)
               m_pLog->Log("NOTE: Could not close socket %d after memory allocation failure. errno=%d\n", nSock, errno) ;
           m_bShutdown = true ;
           return E_HOSTFAIL ;
       }
       //  Initialize and oxygenate the connection
       pExt = pConn->m_pProxy = new hzIpConnex(m_pLog) ;
       pExt->m_pProxy = pConn ;
       currCC[nSock] = pExt ;
       pExt->SetSocket(nSock) ;
       pExt->Oxygen() ;
       now.SysDateTime() ;
       m_pLog->Log("%s: Loop %u: NEW Proxy on socket %d/%d from %d:%d\n", now.Txt(FMT_TIME_USEC), m_nLoop, nSock, pExt->CliPort(), pConn->CliSocket(), pConn->CliPort()) ;
   }
   //  Now copy the data that has come into the original connection, to the output of the client connection
   pExt->SendData(pConn->InputZone()) ;
   pConn->InputZone().Clear() ;
   return E_OK ;
}