From: brian g. <bg...@us...> - 2002-12-06 23:44:30
|
Hi everybody, We're thinking about changing the data format of Player's external socket interface. We've had no end of problems to do with sizing, swapping, and packing of data and command packets, so we're thinking of a slightly different solution. Specifically, we're looking at eXternal Data Representation (XDR), which is part of the standard Sun RPC library. The relevant RFC is here (thanks Boyoon): http://www.faqs.org/rfcs/rfc1014.html This looks promising. The XDR specification includes formats for all common primitive data types (both integral and floating point), and the XDR C libraries provide primitives for encoding and decoding them. Such libraries appear to be available on most UNIX-like systems, including Linux, Solaris, and OS X. Furthermore, other languages, including Python, also have XDR support. The XDR format is not that different from what we're using now. In particular, for integral types, the XDR format is just normal big-endian, which we're already using. One significant change is that XDR data (even single bytes) are always aligned on 4-byte boundaries, which will grow some (but not all) of our packets. An advantage of this alignment is that we would no longer have to specify '__attribute__ ((packed))', which is more portable and efficient (currently, we're running some machines, including Sparcs, in a super inefficient byte-by-byte mode that's used to access misaligned data in memory). A cool thing is that the XDR library functions operate on a 'stream', into which the data is packed and unpacked automatically, relieving us from having to do the pointer bookkeeping. I've appended a sample program showing how to use the functions. They actually use the same function to encode and decode each data type; the direction is determined by whether you specify XDR_ENCODE or XDR_DECODE when you create the XDR object. Similarly, by parsing <player.h>, we can autogenerate functions that will either encode or decode entire structs, simply by calling the underlying primitive translation functions. If we go this way, we can just declare that Player's external interface adheres to XDR, which is well-known. Comments, opinions? brian. ------------------------------------------------------------------------------- #include <stdio.h> #include <rpc/xdr.h> int main(void) { XDR xdrenc; XDR xdrdec; double foo = 3.14159; double bar; int bat = 4; int baz; float bang = 45.6; float boom; char buf[64]; xdrmem_create(&xdrenc, buf, sizeof(buf), XDR_ENCODE); xdr_double(&xdrenc, &foo); xdr_int(&xdrenc, &bat); xdr_float(&xdrenc, &bang); xdrmem_create(&xdrdec, buf, sizeof(buf), XDR_DECODE); xdr_double(&xdrdec, &bar); xdr_int(&xdrdec, &baz); xdr_float(&xdrdec, &boom); printf("%lf\n", bar); printf("%d\n", baz); printf("%f\n", boom); xdr_destroy(&xdrenc); xdr_destroy(&xdrdec); return(0); } |