On 7/23/04 12:18 PM, "Bruce Bernstein" <email@hidden> wrote:
> For some stupid reason PPC2003 allocates 3 times the amount of space
> needed for the socket address list...
The problem is that not all Windows CE platforms do this. For example, on
mine, it doesn't return 3x the size. It returns the correct size, but some
of the data isn't correct (e.g. the address count is always 0).
> size += sizeof(int); //The next address list query will return an
> error unless we do this.
This can corrupt memory and cause a crash because you're passing a buffer
size to WSAIoctl that is larger than the size of the actual buffer. I think
you're better off using the original code, which doubled the size of the
memory it allocates and reported was available. Doubling the amount of
memory allocated provides some margin of error because the subsequent loop
is going to access memory that could potentially be outside of the returned
data (due to the Windows CE bug requiring a workaround) so having the extra
memory reduces the chance that you'll access memory outside of the allocated
memory. This is also why calloc was used instead of malloc...so the memory
is zeroed to avoid garbage data being misinterpreted as being valid.
> if( n == 0 && (((size-sizeof(int))>0)))
> {
> n = (size - sizeof(int))/(3*sizeof(SOCKET_ADDRESS));
I think you may be getting mislead by the difference between a
SOCKET_ADDRESS and a sockaddr. A SOCKET_ADDRESS does not have space to
contain the actual data for the address. It simply contains a pointer to the
real data (the sockaddr) and a size. This may be why you think it is
returning 3x the size since the space required to return a full address is
24 bytes, which is a SOCKET_ADDRESS (8 bytes) + a sockaddr (16 bytes), which
happens to be 3x the size of a SOCKET_ADDRESS.
The original code opted for safety by allocating 2x the requested memory,
zeroing it, then limiting the workaround to a single interface. This allowed
the code to safely access at least 1 interface even if Windows CE returns
some incorrect data, but as you discovered, it doesn't support more than 1
interface as long as Windows CE is returning incorrect data.
What I did in my copy of the code was keep everything basically the same as
the original code except I did the following things to be more aggressive
about detecting multiple interfaces:
1) Increase the size returned from WSAIoctl to at least the size of a
SOCKET_ADDRESS_LIST. This wasn't needed in any of the tests cases I ran
across, but it provided an extra level of security in case it returned
something too small to even access the count field. I did this before
doubling the size.
2) Changed the hard-coding of 1 interface in the case when iAddressCount is
incorrectly returned as 0 to use the following calculation:
n = ( size - offsetof( SOCKET_ADDRESS_LIST, Address ) ) /
( sizeof( SOCKET_ADDRESS ) + sizeof( struct sockaddr ) );
This should be a safe way of detecting how many entire addresses can fit
inside the returned data, assuming each address represents a standard IPv4
sockaddr (the loop will ignore non-IPv4 entries).
3) Added a check as the first thing in the body of the loop that Address[ i
].iSockaddrLength == sizeof( struct sockaddr ). This just provides some
assurance that it is looking at a valid entry since it'll be 0 if it is
outside the returned data (because the memory was calloc'd) or it is likely
to be some other value otherwise.
With these changes, the code worked with 0, 1, and 2 interfaces (the only
cases I could test) on all the Windows CE platforms I had access to. It
should work with other variants as well and if Microsoft ever fixes Windows
CE to return the correct data, it should work there as well.
_______________________________________________
rendezvous mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/rendezvous
Do not post admin requests to the list. They will be ignored.