Why does Ice limit the size of a request?

You may have noticed that Ice limits the size of requests and replies. By default, any received message that is larger than 1MB raises a MemoryLimitException. The 1MB limit applies not to the size of the application data (that is, the payload of the request or reply), but to the entire message as sent over the network. This means that the maximum size of the payload is somewhat smaller than 1MB: the Ice protocol requires a few bytes for its protocol header and, in its marshaled form, depending on the data in the message, the payload can be somewhat larger than the sum of the sizes of its data elements. The exact amount of protocol overhead depends on the operation name, the length of the object identity of the target object, and the type of data you are sending; in general, unless you have very small payloads of only a few bytes, the overhead is insignificant.

So, why does Ice apply this arbitrary message size limit? The answer is simple: without a limit, the Ice run time at the receiving end would be at the mercy of the sending side. To understand why, consider what happens inside the Ice run time when data becomes available for reading on a connection: the run time reads a 14-byte protocol header that contains the size of the message, allocates a buffer that can hold the entire message, and then does a single read system call to read the remaining size-14 bytes into the buffer. During unmarshaling, the run time reads the message data from this buffer and, once it has unmarshaled the message payload into parameters, deallocates the buffer again.

Consider now what would happen if someone accidentally or maliciously were to send a protocol header that contains a very large message size, such as 1GB. Without a limit on the size of a message, the run time would attempt to allocate a 1GB buffer in preparation for reading the remainder of the message. Assuming that the allocation succeeds, the receiving process will have just increased its virtual address space by a gigabyte. If that process is a server, and a number of clients send such bogus requests, the server will repeatedly run out of memory. At best, all this allocated memory consumes swap space, which negatively affects other processes on the same machine; at worst, the server may simply crash. The message size limitation therefore acts as a safety stop to weed out messages that are "unreasonably large."

If your application needs to pass more than around 1MB of data with a single RPC, you can change the default limit by setting the value of the Ice.MessageSizeMax property. This property contains the maximum message size in kilobytes. Note that, if your application only exchanges small amounts of data, it does no harm to set Ice.MessageSizeMax to an appropriate smaller value. Doing so ensures that any bogus messages are rejected as soon as the protocol header is read.

For UDP messages, Ice uses two additional properties, Ice.UDP.SndSize and Ice.UDP.RcvSize. (Note that the value of these properties is in bytes, not kilobytes.) These properties determine the maximum size for the sending and receipt of UDP messages. The default value depends on your operating system. (Typical defaults are 64kB on Windows, and 8kB on Linux.) The maximum sensible value for these properties is 65535 (64kB). You can set them to larger values, but doing so merely increases the size of the kernel buffers and does not affect the hard limit of 65507 bytes for the payload of a UDP packet. (It follows that, for UDP, the maximum Ice message size, including protocol overhead, is 65507 bytes because that is the limit imposed by UDP.) If you set Ice.MessageSizeMax in addition to the UDP receive size, the smaller of the property settings applies.

Finally, Ice not only limits the overall size of requests but, during unmarshaling, also provides a number of sanity checks on the received data. For example, the run time keeps track of how much data has been unmarshaled so far and, whenever it unmarshals a sequence, it ensures that the sequence can fit into remaining buffer space for the yet to-be-unmarshaled portion of the message. This makes it impossible for a malicious sender to craft messages with bogus sequence sizes that would result in memory allocations whose sum of sizes would exceed the limit set by Ice.MessageSizeMax.

See Also