## Callback Connections

### Creating callback connections

Usually remote calls are made from a client to a server. RCF also implements a callback connection concept, allowing the server to take over a connection and use it to make remote calls back to the client.

Remote calls over callback connections function just like remote calls over regular connections, except that callback connections cannot be automatically re-connected.

On the client-side, to create a callback connection to receive calls on, use `RCF::createCallbackConnection()`:

    // Client-side - start a callback server.
    RCF::RcfServer callbackServer( RCF::TcpEndpoint(0) );
    HelloWorldImpl helloWorldImpl;
    callbackServer.bind<I_HelloWorld>(helloWorldImpl);
    callbackServer.start();

    // Client-side - create callback connection.
    RcfClient<I_HelloWorld> client(( RCF::TcpEndpoint(port) ));
    RCF::createCallbackConnection(client, callbackServer);

Note that you need a callback server to receive calls through, and a `RcfClient<>` instance with which to connect to the remote server.

On the server-side, use `RcfServer::setOnCallbackConnectionCreated()` to receive notification when a callback connection is created, and take control of the callback client transport:

    // Server-side - taking control of callback connections.
    RCF::Mutex gCallbackTransportMutex;
    RCF::ClientTransportAutoPtr gCallbackTransportPtr;

    void onCallbackConnectionCreated(
        RCF::RcfSessionPtr sessionPtr,
        RCF::ClientTransportAutoPtr clientTransportPtr)
    {
        // Store the callback client transport in a global variable for later use.
        RCF::Lock lock(gCallbackTransportMutex);
        gCallbackTransportPtr = clientTransportPtr;
    }

    RCF::RcfServer server( RCF::TcpEndpoint(0) );
    server.setOnCallbackConnectionCreated(onCallbackConnectionCreated);
    server.start();

Once you have the callback client transport, you can use it to construct an appropriate `RcfClient<>` instance, and subsequently use that to make calls back to the client:

    // Server-side - wait for callback connection to be created.
    while (true)
    {
        RCF::sleepMs(1000);
        RCF::Lock lock(gCallbackTransportMutex);
        if (gCallbackTransportPtr.get())
        {
            RcfClient<I_HelloWorld> callbackClient( gCallbackTransportPtr );
            callbackClient.Print("Hello World");
            break;
        }
    }

### Identifying clients

Typically you will want a server to maintain a list of callback connections to clients, and make calls back to specific clients. To do this, the server needs a mechanism by which to identify the callback connections. The best way to do this is to have the client set some session-specific data, before it calls `RCF::createCallbackConnection()`.

Let's assume you want to identify your clients with a string - for example a name. Before the client calls `RCF::createCallbackConnection()`, it should call an application-defined remote method on the server, to set the name of the client:

    RCF_BEGIN(I_IdentifyClient, "I_IdentifyClient")
        RCF_METHOD_V1(void, SetClientName, const std::string&)
    RCF_END(I_IdentifyClient)

    // Client-side - create callback connection.
    RcfClient<I_IdentifyClient> client(( RCF::TcpEndpoint(port) ));
    client.SetClientName("ABC-123");
    RCF::createCallbackConnection(client, callbackServer);

The server implementation of `SetClientName()` creates a session object in the `RcfSession` of the connection, with the client name:

    class IdentifyClientImpl
    {
    public:
        void SetClientName(const std::string& clientName)
        {
            RCF::RcfSession & session = RCF::getCurrentRcfSession();
            std::string & sessionClientName = session.createSessionObject<std::string>();
            sessionClientName = clientName;
        }
    };

When the client subsequently calls `RCF::createCallbackConnection()`, the `RcfServer` can then retrieve the name of the client and associate the callback connection with that name:

    // Server-side - taking control of callback connections.
    RCF::Mutex                                      gCallbackClientMapMutex;

    typedef RcfClient<I_HelloWorld>                 HelloWorldClient;
    typedef boost::shared_ptr<HelloWorldClient>     HelloWorldClientPtr;
    std::map<std::string, HelloWorldClientPtr>      gCallbackClientMap;

    void onCallbackConnectionCreated(
        RCF::RcfSessionPtr sessionPtr,
        RCF::ClientTransportAutoPtr clientTransportPtr)
    {
        std::string & clientName = sessionPtr->getSessionObject<std::string>();

        // Store the callback client transport in a global variable for later use.
        RCF::Lock lock(gCallbackClientMapMutex);
        HelloWorldClientPtr hwClientPtr( new HelloWorldClient(clientTransportPtr) );
        gCallbackClientMap[clientName] = hwClientPtr;
    }

### Transport protocols

Transport protocols configured on the original client-to-server connection are not carried over to the callback connection. If you want to use a transport protocol on the callback connection, it needs to be configured explicitly:

    RcfClient<I_HelloWorld> callbackClient( gCallbackTransportPtr );
    callbackClient.getClientStub().setTransportProtocol(RCF::Tp_Ntlm);
    callbackClient.Print("Hello World");