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 Type | Function name | Arguments |
|---|---|---|
| hzEcode | hzIpServer::ProxyTo | (hzIpConnex*,uint32_t,) |
Declared in file: hzIpServer.h
Defined in file : hzIpServer.cpp
Function Logic:
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 ;
}