Remote Call Framework 3.1
Proxy Endpoints

Proxy endpoints allow RCF clients to connect to RCF servers that they are otherwise unable to connect directly to.

There are a number of situations in which a client may be unable to establish a direct network connection to a server it intends to call.

  • The network address of the server may not be known to the client.
  • The network address of the server may be dynamic.
  • There may be firewalls or other network infrastructure present, preventing direct client-to-server network connections.

Proxy endpoints provide a workaround for these situations, allowing one RCF server (the proxy server) to serve as a proxy for another RCF server (the destination server). The proxy server maintains a pool of connections from the destination server, and uses these connections to allow clients to connect through to the destination server.

Configuring a Proxy Server

The proxy server accepts connections from a destination server, and keeps these connections in a connection pool. The connections are then subsequently used for clients wanting to connect to that particular destination server.

Each destination server must present a name to the proxy server. The destination server name is arbitrary and chosen by your application. The clients will use the destination server name to specify which server they want to connect to.

To set up a proxy server, you configure a RCF::RcfServer as usual, and then call RCF::RcfServer::setEnableProxyEndpoints(). Once started, the RcfServer will begin registering destination servers and proxying connections from clients to those destination servers.

// Proxy server.
int proxyPort = 50001;
RCF::RcfServer proxyServer( RCF::TcpEndpoint("0.0.0.0", proxyPort) );
proxyServer.setEnableProxyEndpoints(true);
proxyServer.setThreadPool(RCF::ThreadPoolPtr(new RCF::ThreadPool(1,10)));
proxyServer.start();

At any time, you can query the proxy server, for the names of the proxy endpoints that are currently available:

std::vector<std::string> proxyEndpointNames;
proxyServer.enumerateProxyEndpoints(proxyEndpointNames);

Configuring a Destination Server

The destination RcfServer is configured with a RCF::ProxyEndpoint parameter, specifying the network address of the proxy server, and the name the destination server will be exposed as.

// Destination server.
RCF::RcfServer destinationServer( RCF::ProxyEndpoint(RCF::TcpEndpoint(proxyIp, proxyPort), "RoamingPrintSvr") );
PrintService printService;
destinationServer.bind<I_PrintService>(printService);
destinationServer.start();

Once started, the destination RcfServer will begin initiating network connections to the proxy server. These connections will subsequently be used by clients to make remote calls back to the destination server.

Connecting Through a Proxy Server

Once the destination server and proxy server are up and running, a client can connect to the destination server by using a RCF::ProxyEndpoint and specifying the proxy server along with the name of the destination server.

// Client calling through to destination server, using in-process access to the proxy server.
RcfClient<I_PrintService> client( RCF::ProxyEndpoint(proxyServer, "RoamingPrintSvr") );
client.Print("Calling I_PrintService through a proxy endpoint.");
// Client calling through to destination server, using network access to the proxy server.
RcfClient<I_PrintService> client(RCF::ProxyEndpoint(RCF::TcpEndpoint(proxyIp, proxyPort), "RoamingPrintSvr"));
client.Print("Calling I_PrintService through a proxy endpoint.");

Using a proxied connection, the client can make remote calls as usual, and is able to disconnect and re-connect, just as with an un-proxied connection. Distinct RCF clients will have distinct network connections to the destination server, and the lifetime of any session objects created on the destination server, will be mapped to the lifetime of the clients proxied network connection.

Two-way communication using proxy endpoints

It's quite common to have a situation where clients connect to a server, but subsequently the server needs to be able to make remote calls in the opposite direction, back to the clients. We refer to this as two-way communication.

Beginning with RCF 3.0, two-way communication is supported using proxy endpoints. For example, assume we have a server process and a client process, and we want to implement two-way communication between them. In the server process, you would enable proxy endpoint support on the RcfServer:

// Server process listening on port 50001, with proxy endpoint support enabled.
RCF::RcfServer proxyServer(RCF::TcpEndpoint("0.0.0.0", 50001));
proxyServer.setEnableProxyEndpoints(true);

Any server-side code that needs to make a call to the client process, would do so by using a proxy endpoint:

// Server-side code, making calls to the client process.
RcfClient<I_PrintService> client(RCF::ProxyEndpoint(proxyServer, "SomeUniqueClientId"));
client.Print("Making call from server to client.");

In the client process, you need to start a RcfServer, configured with the relevant proxy endpoint, in order to receive calls from the server process:

// Client-side configuration code, to allow calls to be received from the server process.
PrintService printService;
std::string serverAddress;
RCF::TcpEndpoint serverEp(serverAddress, 50001);
RCF::RcfServer server(RCF::ProxyEndpoint(serverEp, "SomeUniqueClientId") );
server.bind<I_PrintService>(printService);
server.start();