The endpoint defined by Glacier2.Client.Endpoints is used by the Ice run time in a client to interact directly with the router. It is also the endpoint where requests from routed proxies are sent. This endpoint is defined on the public network interface because it must be accessible to clients.
1 Furthermore, the endpoint uses a fixed port because clients may be statically configured with a proxy for this endpoint.
A client’s session is destroyed when explicitly requested, or when the session is inactive for a configurable number of seconds. For this example, we have specified a timeout of 60 seconds. It is not mandatory to define a timeout, but it is recommended, otherwise session state might accumulate in the router. See
Section 43.6 for more information on sessions.
Note that this configuration enables the router to forward requests from clients to servers, but not from servers to clients (that is, it cannot forward callbacks). We discuss callbacks in
Section 43.4.
The router’s simplest authentication mechanism uses an access control list in a file consisting of user name–password pairs. The password is a 13‑character string encoded using the
crypt algorithm, similar to a
passwd file on a typical Unix system. The property
Glacier2.CryptPasswords specifies the name of the password file:
The format of the password file is very simple. Each user name–password pair must reside on a separate line, with whitespace separating the user name from the password. For example, the following password file contains an entry for the user name
test:
You can use the openssl utility (included in the OpenSSL toolkit) to generate
crypt passwords:
$ openssl
OpenSSL>
passwd
Password:
Verifying ‑ Password:
xxMqsnnDcK8tw
At the prompt, issue the passwd command. You are asked for a password, and then asked to confirm the password, at which point the utility displays the
crypt-encoded version of your password that you can paste into the router’s password file.
$ glacier2router ‑h
Usage: glacier2router [options]
Options:
‑h, ‑‑help Show this message.
‑v, ‑‑version Display the Ice version.
‑‑nowarn Suppress warnings.
The --nowarn option prevents the router from displaying warning messages at startup when it is unable to contact a permissions verifier object or a session manager object specified by its configuration.
Assuming the configuration properties shown in Section 43.3.1 and
Section 43.3.2 are stored in a file named
config, you can start the router with the following command:
$ glacier2router ‑‑Ice.Config=config
The value of the Ice.Default.Router property is a proxy whose endpoints must match those in
Glacier2.Client.Endpoints.
The property Ice.ACM.Client governs the behavior of
active connection management (ACM, see
Section 37.4), which conserves resources by periodically closing idle outgoing connections. This feature must be disabled in a client that uses a Glacier2 router, otherwise ACM might transparently close a client’s connection to a router and thereby terminate the router session prematurely. ACM is enabled by default, and therefore must be disabled by setting this property to zero.
Finally, setting Ice.RetryIntervals to
‑1 disables automatic retries, which are not useful for proxies configured to use a Glacier2 router. For more information about automatic retries, see
Section 32.23.
A Glacier2 router hosts two well-known objects. The default identities of these objects are
Glacier2/router and
Glacier2/admin, corresponding to the
Glacier2::Router and
Glacier2::Admin interfaces, respectively. If an application requires the use of multiple different (that is, not replicated) routers, it is a good idea to assign unique identities to these objects by configuring the routers with different values of the
Glacier2.InstanceName property, as shown in the following example:
This property changes the category of the object identities, which become PublicRouter/router and
PublicRouter/admin. The client’s configuration must also be changed to reflect the new identity:
One exception to this rule is if you deploy multiple Glacier2 routers as replicas, for example, to gain redundancy or to distribute the message forwarding load over a number of machines. In that case, all the routers must use the same instance name; the clients in that case use proxies with multiple endpoints, such as:
module Glacier2 {
exception PermissionDeniedException {
string reason;
};
interface Router extends Ice::Router {
Session* createSession(string userId, string password)
throws PermissionDeniedException,
CannotCreateSessionException;
Session* createSessionFromSecureConnection()
throws PermissionDeniedException,
CannotCreateSessionException;
idempotent string getCategoryForClient();
idempotent long getSessionTimeout();
void destroySession()
throws SessionNotExistException;
};
};
The interface defines two operations for creating sessions: createSession and
createSessionFromSecureConnection. The router requires each client to create a session using one of these operations; only after the session is created will the router forward requests on behalf of the client.
The createSession operation expects a user name and password, and returns a
Session proxy or nil, depending on the router’s configuration (see
Section 43.6). When using the default authentication scheme, the given user name and password must match an entry in the router’s password file in order to successfully create a session.
The createSessionFromSecureConnection operation does not require a user name and password because it uses the credentials supplied by an SSL connection to authenticate the client (see
Section 43.5).
To create a session, the client typically obtains the router proxy from the communicator, downcasts the proxy to the
Glacier2::Router interface, and invokes one of the operations. The sample code below demonstrates how to do it in C++; the code will look very similar in the other language mappings.
Ice::RouterPrx defaultRouter =
communicator‑>getDefaultRouter();
Glacier2::RouterPrx router =
Glacier2::RouterPrx::checkedCast(defaultRouter);
string username = ...;
string password = ...;
Glacier2::SessionPrx session;
try
{
session = router‑>createSession(username, password);
}
catch(const Glacier2::PermissionDeniedException& ex)
{
cout << "permission denied:\n" << ex.reason << endl;
}
catch(const Glacier2::CannotCreateSessionException& ex)
{
cout << "cannot create session:\n" << ex.reason << endl;
}
If the router is configured with a session manager, the createSession and
createSessionFromSecureConnection operations may return a proxy for an object implementing the
Glacier2::Session interface (or an application-specific derived interface). The client receives a null proxy if no session manager is configured.
In order to successfully use a session proxy, it must be configured with the router that created it; that is, the session object is only accessible via the router. If the router is configured as the client’s default router at the time
createSession or
createSessionFromSecureConnection is invoked, as is the case in the example above, then the session proxy is already properly configured and nothing else is required. Otherwise, the client must explicitly configure the session proxy with a router using the
ice_router proxy method (see
Section 32.11.2).
If the client wishes to destroy the session explicitly, it must invoke destroySession on the router proxy. If a client does not destroy its session, the router destroys it automatically when it expires due to inactivity. A client can obtain the inactivity timeout value by calling
getSessionTimeout (see
Section 43.6.2).
Note that a router client must be prepared for the destroySession operation to raise
ConnectionLostException, as shown in the following C++ example:
try {
router‑>destroySession();
} catch (const Ice::ConnectionLostException&) {
// Expected
}
A Glacier2 router may be configured to destroy sessions after a period of inactivity. This feature allows the router, as well as a custom session manager, to reclaim resources acquired during the session (see
Section 43.6), but it requires some coordination between the router and its clients.
Ideally you would select a session timeout that is long enough to accommodate the usage patterns of your clients. For example, if a client invokes an operation on a back-end server once every five seconds, then a session timeout of thirty seconds is a reasonable choice. However, that timeout could disrupt a different client that has long periods of inactivity, such as when its invocations are prompted by human interaction.
If you cannot predict with certainty the usage patterns of your clients, we recommend modifying the clients so that they actively prevent their sessions from expiring. A client simply needs to make an invocation at regular intervals, where the period is less than the router’s timeout by a comfortable margin. Typically a client creates a dedicated thread that periodically "pings" an object using the
ice_ping operation. It does not matter which object the client pings, as long as it is accessed via the router session. For example, the client could ping the session object itself or, if no session proxy was provided, the client could ping an object in a back-end server.
You can find a C++ example of this technique in the demo/Glacier2/chat subdirectory of your Ice distribution.
Note that if a session times out, the next client invocation raises ConnectionLostException. To re-establish the session, the client must explicitly re-create it. If the client uses callbacks (see
Section 43.4), it must re-create the callback adapter re-add the callback servants to the ASM.