This page describes notable additions and improvements in Ice 3.6. For a detailed list of the changes in this release, please refer to the changelog in the source tree. Our upgrade guide documents the changes that may affect the operation of your applications or have an impact on your source code.
On this page:
Ice 3.6 includes a number of significant new features, many of them in response to requests from our commercial users.
wss -h www.myhost.com -p 443 directs the client to use a secure WebSocket connection via the standard HTTPS port. The WebSocket protocol is supported by all Ice language mappings.
- an Ice server listening directly on port 80 (HTTP) or port 443 (HTTPS),
- an HTTP server (e.g., Nginx) that supports reverse proxying of WebSocket connections,
- an HTTP load balancer (e.g., HAProxy) that supports forwarding WebSocket connections.
Here's how it works when using an HTTP server reverse proxy:
The client connects to the HTTP server and sends an HTTP request to upgrade the existing connection to support WebSocket. The message includes a resource path, such as
/MyService in the example above, that the HTTP server translates into a target back-end service. The HTTP server establishes its own connection to the service and then relays messages between the client and the service. The service is an Ice server listening on a WS or WSS endpoint.
The WebSocket protocol provides an alternative to opening a port on your corporate firewall. You can instead leverage your existing web infrastructure to allow Ice clients on the other side of your firewall to access your Ice services.
The Objective-C mapping from Ice Touch is now included in the Ice distribution.
It currently lacks support for the following features:
- Asynchronous method dispatch (AMD)
Please refer to the manual for complete details on the Objective-C mapping.
In an effort to simplify bootstrapping and minimize configuration, we're introducing two new components that facilitate the discovery of Ice servers via UDP multicast.
IceDiscovery provides a lightweight location service that enables clients to discover objects at run time. Implemented as an Ice plug-in, the service requires only minimal configuration and very few changes to your application code. IceDiscovery is an ideal solution for applications that don't need the additional features that IceGrid offers, such as server activation and centralized administration, but could still take advantage of the benefits provided by indirect proxies and replication.
Consider the following code example:
Notice here that the code translates the stringified proxy
"hello" containing no endpoint information. Ice resolves such proxies using a locator supplied by the IceDiscovery plug-in, all we need to do is configure the client to load the plug-in:
At the proxy's first remote invocation (the call to
checkedCast in the example above), IceDiscovery issues a multicast query to determine if any servers are available that provide the
hello object. If more than one server responds, it means the object is replicated and the client selects one of the servers based on additional configuration settings. This discovery process is handled internally by the plug-in and is transparent to clients and servers.
UDP multicast is only used by IceDiscovery to locate available servers. Clients and servers communicate using the transport of your choosing.
In practical terms, using the plug-in means a client no longer needs to hard-code the addressing information of its servers in its source code or configuration files. Assuming the underlying network supports multicast, IceDiscovery enables servers to start, stop, and migrate to different hosts without affecting the ability of clients to find them, and without requiring any administrative changes.
In previous versions of Ice, using IceGrid was the primary way for applications to leverage the benefits of indirect proxies; the only other alternative was to write a custom "locator" service. Indirect proxies help to minimize coupling between clients and servers by eliminating most of the addressing information from application code and configuration files. The one exception has always been the
Ice.Default.Locator property, which needed to contain at least one endpoint for an IceGrid registry:
In a replicated IceGrid deployment consisting of a master replica and one or more slave replicas, the
Ice.Default.Locator property would normally include endpoints for some or all of the replicas.
The IceLocatorDiscovery plug-in alleviates the need to statically configure locator endpoints by using UDP multicast to dynamically discover the active locators in a network. Integrating the plug-in simply requires updating client configuration files to install the plug-in and remove the
Ice.Default.Locator property. No changes are necessary in your application code.
IceGrid Custom Load Balancing
We've enhanced the IceGrid registry to support pluggable load balancing strategies, making it possible for you to implement application-specific load balancing algorithms or filter the registry's results based on user input.
Two kinds of filters are supported:
- Replica group filter
The registry invokes a replica group filter each time a client requests the endpoints of a replica group or object adapter, as well as for calls to
findAllReplicas. The registry passes information about the query that the filter can use in its implementation, including the list of object adapters participating in the replica group whose nodes are active at the time of the request. The object adapter list is initially ordered using the load balancing type configured for the replica group; the filter can modify this list however it chooses.
- Type filter
The registry invokes a type filter for each query that a client issues to find a well-known object by type using the operations
findObjectByTypeOnLeastLoadedNode. Included in the information passed to the filter is a list of proxies for the matching well-known objects; the filter implementation decides which of these proxies are returned to the client.
Filters are implemented in C++ as regular Ice plug-ins that you install in the IceGrid registry via configuration properties.
Timeout semantics have changed for the better with the addition of invocation timeouts. Ice still supports the existing timeout facility, referred to as a connection timeout or endpoint timeout, but now it only affects network activities. The new invocation timeout facility enables you to set an arbitrary timeout per invocation, independent of the connection timeout. Furthermore, when an invocation timeout occurs, it only affects that invocation and the connection remains open. The code below demonstrates the new semantics:
Review the upgrade guide to learn how your existing application might be impacted by and benefit from these changes.
It's now possible to cancel an asynchronous invocation using the
cancel method of the
Ice::AsyncResult object. This method prevents a queued invocation from being sent or, if the invocation has already been sent, ignores a reply if the server sends one. It has no effect on the server. A canceled invocation is considered to be completed and the result of the invocation is an
Active Connection Management
We've enhanced the Active Connection Management facility to give applications more control over ACM behavior. Included in these enhancements is a new "heartbeat" feature that you can use in your applications when you need to ensure that a connection remains open. For example, you can use heartbeats to keep a Glacier2 session alive or prevent a bidirectional connection from being closed prematurely. This feature eliminates the need for an application to implement its own background thread to keep a connection or session alive. We've also added the ability to register a callback with the connection that is notified when the connection closes or receives a heartbeat. The code below shows how to enable heartbeats and install a callback on a connection:
Refer to our upgrade guide for more information on how the ACM changes can impact existing Ice applications.
We've essentially re-written the IceSSL plug-in to make use of a platform's native SSL APIs where possible. On OS X, the plug-in now uses Apple's Secure Transport facility, and on Windows it now uses SChannel. Linux is the only platform on which IceSSL still uses OpenSSL.
By using native SSL APIs instead of OpenSSL for secure communications on OS X and Windows, your applications can more easily take advantage of any hotfixes provided by the operating system vendors when security issues arise.
If you use IceSSL, we recommend reviewing the upgrade guide because there have been some changes to the IceSSL APIs and configuration properties.
Other New Features
This section describes several more additions and improvements in Ice 3.6 that we'd like to bring to your attention.
The Ice administrative facility adds a new logger facet that allows remote access to a program's log activity. The IceGrid administrative tools now use this feature to let you view the recent log output of Ice servers, IceBox services, and IceGrid nodes and registries.
Garbage Collection Improvements
Ice for C++ has included a garbage collection facility for many years, but it suffered from one significant flaw: it was impossible to guarantee that object graphs could be collected in a thread-safe manner. In this release, we've improved the implementation and modified the API to ensure it's efficient and thread-safe. The application is now responsible for telling the Ice run time when an object graph is eligible for collection by calling the
Object::ice_collectable(bool) method. Ice assumes that a graph eligible for collection is immutable, therefore you must not update the structure of the graph after marking it as collectable. The code below demonstrates the new API:
Users of previous Ice versions should refer to the upgrade guide for details on what has changed.
Aside from adding the WebSocket transports and overhauling our SSL plug-in, we've made a few more enhancements to the Ice transports.
Outgoing TCP and SSL connections can now be mediated by an HTTP network proxy service that supports HTTP CONNECT tunneling. The new properties
Ice.HTTPProxyPort configure the addressing information for the proxy.
Proxy endpoints can now include the
--sourceAddress option to specify a network interface on which to bind outgoing connections. The
Ice.Default.SourceAddress property supplies a default value when the endpoint option is not used.
Collocated invocations have been reimplemented to provide location transparency semantics that are much more consistent with those of regular remote invocations. For example, you can now make asynchronous invocations on a collocated servant, and the Python language mapping now supports collocated invocations.
If your application relies on collocated invocations, you should review our upgrade guide for more information.
Router and locator implementations are now required to implement a finder interface that allows a client to obtain a proxy for the service while knowing only its address and port. A finder object has a well-known identity that a client can combine with addressing information to compose its initial proxy. Using the finder proxy, the client can request a proxy for the target service. For example, the IceGrid administrative utility only needs to prompt the user for addressing details but does not need to ask for the identity of the service's well-known object, which may have been customized in the service's configuration.
Ice for Java now allows an application to safely interrupt a thread that's blocked in a call to the Ice run time. Attempting to use interrupts in previous Ice releases led to undefined and generally undesirable behavior, but in Ice 3.6 the semantics are clearly defined. Consider this example:
Here we've shown how an application can deal with an interrupt that occurs during a remote invocation. Calls to other blocking Ice APIs, such as
Communicator.waitForShutdown(), can also be interrupted. Consult the manual for a complete description of the semantics and a list of the valid interruption points.
Java Lambda Functions
Ice 3.6 adds support for Java 8, which means you can now use lambda functions for asynchronous callbacks. As an example of how lambda functions can simplify your code, consider these two equivalent invocations:
The new metadata tag
"java:buffer" can be applied to sequences of certain primitive types, causing the translator to use subclasses of
java.nio.Buffer instead of the default mapping to a native Java array. The buffer mapping is especially convenient when an application already has data in a buffer object because it eliminates the need to create and fill a temporary array just to call a Slice operation. The buffer mapping also avoids copying when receiving these sequences by directly referencing Ice's unmarshaling buffer.
Here's a simple example:
translate operation maps to the following Java method:
On the client side, a call to the
translate proxy method returns an
IntBuffer view of the data in the results buffer. On the server side, the implementation receives a
ByteBuffer wrapper of the relevant portion of the incoming parameter buffer.
C++ View Types
cpp:type:view-type metadata directive allows you to safely use "view" C++ types for operation parameters. Such C++ types point to memory held by other objects and don't copy memory. A typical example is the experimental C++14
cpp:type:view-type can be applied to string, sequence and dictionary parameters, to speed-up your application by reducing the number of copies made during remote invocations. See the cpp:type and cpp:view-type Metadata Directives for details.
Linking with C++ Libraries on Windows
You no longer need to list Ice import libraries (such as
IceD.lib) when linking with Ice C++ libraries on Windows.
pragma directives in Ice header files provide these import library names to the linker, for example:
The Ice Builder for Visual Studio automatically configures the
$(IceLib) directory that contains these import libraries.
$(IceLib) depends on the versions of Ice and Visual Studio you're using, and on the target architecture. For example,
$(IceLib) for a Ice 3.6, Visual Studio 2012 and a x64 target is
C++ Plug-in for Crypt Password Files
Both the Glacier2 router and IceGrid registry provide a simple file-based authentication mechanism using a "crypt password" file that contains a list of user name and password-hash pairs.
In Ice 3.5 and earlier releases, the Glacier2 router and IceGrid registry use the archaic DES-based Unix Crypt algorithm to hash the provided password and verify if this hash matches the hash in the password-file. This DES Unix Crypt implementation was provided by OpenSSL on all platforms.
Ice 3.6 supports more recent and secure hash formats and algorithms:
- Windows and OS X: PBKDF2 with SHA-1, SHA-256, or SHA-512 as digest algorithm
- Linux: SHA-256 and SHA-512 Crypt, plus the old DES-based Unix Crypt for compatibility with earlier releases
Windows and OS X no longer rely on OpenSSL for this password hashing, nor for anything else.
In Ice 3.6, we have also moved the implementation of this authentication mechanism to a separate C++ plug-in, the
Glacier2CryptPermissionsVerifier plug-in. This plug-in is loaded automatically by Glacier2 or IceGrid if you configure a crypt passwords file using one of the existing
IceGrid.Registry.CryptPasswords. If you don't use the simple authentication mechanism provided by the
CryptPasswords properties, you don't need to include this plug-in with your application.
Support for -fvisibility=hidden with GCC and clang
Ice for C++ is now built by default with
-fvisibility=hidden on Linux (with GCC) and OS X (with clang). You can also build code generated by
-fvisibility=hidden, and use the
--dll-export option to export symbols from such generated code.