## Remote Calls - Server-side

On the server-side, your application is responsible for dispatching remote calls from clients. Typically you will create a `RcfServer`:

    RCF::RcfServer server( RCF::TcpEndpoint(50001) );

, bind a servant object to it:

    HelloWorldImpl helloWorldImpl;
    server.bind<I_HelloWorld>(helloWorldImpl);

, and start the server:

    server.start();

When a client makes a remote call to the `I_HelloWorld` interface, the relevant member function of the servant object is executed. From within the servant object, you can access the current server side remote call session through `RCF::getCurrentSession()`:

    class HelloWorldImpl
    {
    public:
        void Print(const std::string & s)
        {
            std::cout << "I_HelloWorld service: " << s << std::endl;

            RCF::RcfSession & session = RCF::getCurrentRcfSession();
            // ...
        }
    };

`RCF::getCurrentSession()` returns a `RcfSession` reference, through which server-side per-session configuration is done. A `RcfSession` is created for every connection to a RcfServer, and it's lifetime matches that of the underlying transport connection.

### Configuring a server

#### Adding transports

A `RcfServer` listens on one or more transports, for remote calls from clients. Server transports can be configured by passing in an endpoint parameter to the `RcfServer` constructor:

    RCF::RcfServer server( RCF::TcpEndpoint(50001) );

Alternatively, to configure multiple transports, use `RcfServer::addEndpoint()`:

    RCF::RcfServer server;
    server.addEndpoint( RCF::TcpEndpoint(50001) );
    server.addEndpoint( RCF::UdpEndpoint(50002) );

#### Starting and stopping a server

A `RcfServer` instance will not start dispatching remote calls until `RcfServer::start()` is called. The server can be stopped manually by calling `RcfServer::stop()`:

    RCF::RcfServer server( RCF::TcpEndpoint(50001) );
    server.start();
    // ...
    server.stop();

You can also simply let the `RcfServer` object go out of scope, in which case the server is stopped automatically.

#### Binding servant objects

`RcfServer::bind<>()` is used to bind servant objects to RCF interfaces. Every bound servant object has a binding name which identifies it. The default servant binding name is the runtime name of the interface it is exposed through. So the following code:

    server.bind<I_HelloWorld>(helloWorldImpl);

, creates a servant binding with the servant binding name `"I_HelloWorld"`, as that is the runtime identifier of the `I_HelloWorld` interface:

    RCF_BEGIN(I_HelloWorld, "I_HelloWorld")
        RCF_METHOD_V1(void, Print, const std::string &)
    RCF_END(I_HelloWorld)

The servant binding name can also be set explicitly:

    server.bind<I_HelloWorld>(helloWorldImpl, "CustomBindingName");

Each remote call from a client specifies a servant binding name, which is used by the server to dispatch the remote call. The servant binding name supplied by a `RcfClient<>` defaults to the runtime name of the RCF interface it is using. So the following client code:

    RcfClient<I_HelloWorld> client( RCF::TcpEndpoint(50001) );
    client.Print("Hello World");

, will make a remote call to the servant object with the servant binding name `"I_HelloWorld"`.

The client can also set the servant binding name explicitly:

    RcfClient<I_HelloWorld> client( RCF::TcpEndpoint(50001), "CustomBindingName" );
    client.Print("Hello World");

, to get the call dispatched to the nominated servant binding.

#### Server threading

By default, a `RcfServer` will use a single thread to dispatch calls across all its transports. This behavior can be modified by explicitly assigning a thread pool to the `RcfServer`:

    RCF::RcfServer server( RCF::TcpEndpoint(50001) );

    RCF::ThreadPoolPtr threadPoolPtr( new RCF::ThreadPool(1, 5) );
    server.setThreadPool(threadPoolPtr);

`RCF::ThreadPool` can be configured to use a fixed number of threads, or a varying number of threads depending on server load:

    // Thread pool with a fixed number of threads (5).
    RCF::ThreadPoolPtr threadPoolPtr( new RCF::ThreadPool(5) );
    server.setThreadPool(threadPoolPtr);

    // Thread pool with a dynamically varying number of threads (1-25).
    RCF::ThreadPoolPtr threadPoolPtr( new RCF::ThreadPool(1, 25) );
    server.setThreadPool(threadPoolPtr);

A thread pool assigned to the `RcfServer` will be shared by all the transports of that `RcfServer`. It is also possible to assign thread pools to specific transports:

    RCF::RcfServer server;

    RCF::ThreadPoolPtr threadPool1( new RCF::ThreadPool(1) );
    server.addEndpoint( RCF::TcpEndpoint(50001) ).setThreadPool(threadPool1);

    RCF::ThreadPoolPtr threadPool2( new RCF::ThreadPool(1) );
    server.addEndpoint( RCF::TcpEndpoint(50002) ).setThreadPool(threadPool2);

### Server-side sessions

You can use `RcfSession` to find out a number of things about the current client connection, including:

- The transport being used:

    RCF::RcfSession & session = RCF::getCurrentRcfSession();
    RCF::TransportType transportType = session.getTransportType();

- The network address of the client:

    const RCF::RemoteAddress & clientAddress = session.getClientAddress();
    std::string strClientAddress = clientAddress.string();

- The current request header:

    RCF::RemoteCallRequest request = session.getRemoteCallRequest();

- Any custom request data passed in by the client:

    std::string customRequestData = session.getRequestUserData();

- You can create, retrieve and delete session objects:

    session.createSessionObject<MySessionObj>();
    MySessionObj & obj = session.getSessionObject<MySessionObj>();
    MySessionObj * pObj = session.querySessionObject<MySessionObj>();
    session.deleteSessionObject<MySessionObj>();

- How long the client has been connected:

    // When the connection was established, as reported by CRT time() function.
    time_t connectedAt = session.getConnectedAtTime();

    // Connection duration in seconds.
    boost::uint32_t connectionDurationS = session.getConnectionDuration();

- How many calls have been made on this connection:

    boost::uint32_t callsMade = session.getRemoteCallCount();

- How many bytes have been sent and received on this connection:

    boost::uint64_t totalBytesReceived = session.getTotalBytesReceived();
    boost::uint64_t totalBytesSent = session.getTotalBytesSent();