D
Dave Thompson
On 9 Jul 2004 17:45:54 -0700, (e-mail address removed) (j0mbolar) wrote:
[Stevens v1 2e p720]void udp_write(char *buf, <everything else omitted)
struct udpiphdr *ui;
struct ip *ip;
ip = (struct ip *) buf;
ui = (struct udpiphdr *) buf;
It will work on any platform which doesn't enforce alighment
requirements, and on any platform at all provided the pointer passed
is suitably aligned, as I imagine the book's code will do.
If you really want to ensure it's always aligned, add a wrapper
something like this:
void a_udp_write(char *buf,size_t size,...)
The parameter could better be const char *, but back in the '80s that
wasn't reliably portable, and before that didn't exist at all.
{
char *abuf,*tbuf=buf;
int a=0;
if ((buf&15)!=0)
That requires an explicit conversion (cast) -- and then formally as
far as C is concerned the result is implementation-defined, although
it should be correct on any Unix and probably any platform where
BSD-ish sockets make sense at all.
{
a++;
abuf=(char*)malloc(size+16);
Cast not needed in C if malloc is correctly declared, as it must be,
tbuf=abuf & ~15;
Not needed; the value returned by {m,c,re}alloc, if successful, must
be sufficiently aligned for any object type (including struct of
anything) on the implementation. And if it was needed it would be
backwards; you would need to round *up*, into the space allocated.
In general there is no way to automatically determine what the
strictest alignment is, although you can get an upper bound for any
predetermined (finite) set of types by something like
offsetof ( struct { char a; union { long l; double d; } u } , u ).
For IPv4+UDP in particular, we know that no header field requires more
than 4-byte alignment.
memcpy(tbuf,buf,size);
}
udp_write(tbuf,size,...);
if (a!=0)
free(abuf);
Instead of a separate flag variable a, why not just initialize abuf to
NULL, and then unconditionally free() it -- if (still) null it does
nothing, and if non-null it frees the malloc'ed space.
Or, since UDP is lossy anyway, could just do
if( (ulong)buf & 15 ) return;
or to be "nice" about it
... { errno = EPULLTHEOTHERONE; return; }
}
Then you can be certain udp_write() is always working with an aligned
buffer (on a 16 byte boundary here), even if the caller didn't.
James.
- David.Thompson1 at worldnet.att.net