0

I'm developing an after effects plugin and I'm trying to integrate raknet which is a c++ network library. When the raknet library is trying to get the ipv4 address by calling

gethostbyname

it then throws an error access violation reading location 0xFFFFFFFFFFFFFFFF

int idx=0;
char ac[ 80 ];
int err = gethostname( ac, sizeof( ac ) );
(void) err;
RakAssert(err != -1);

struct hostent *phe = gethostbyname( ac );

if ( phe == 0 )
{
RakAssert(phe!=0);
return ;
}
for ( idx = 0; idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ++idx )
{
if (phe->h_addr_list[ idx ] == 0)
    break;

memcpy(&addresses[idx].address.addr4.sin_addr,phe->h_addr_list[ idx ], sizeof(struct in_addr));
}

while (idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS)
{
addresses[idx]=UNASSIGNED_SYSTEM_ADDRESS;
idx++;
}

Here are some pictures of what I see.

http://jacobsgriffith.com/stackoverflow/noaccesserror.png

I've read this and it doesn't look like the library implemented it wrong. Microsoft Documentation On gethostbyname

When I hover over h_addr_list and h_aliases I get .

http://jacobsgriffith.com/stackoverflow/noaccess.jpg

Anybody have any ideas? Why is this failing I'm pretty sure this is a common function.

Another thing, is there any difference between the implementations of the gethostbyname function from winsock and winsock2?

jacobsgriffith
  • 1,448
  • 13
  • 18
  • Please don't post pictures of code. Post your code as you typed it. In any case, it's not likely crashing on gethostbyname, otherwise you wouldn't have been able to debug it to the point where you got "phe" assigned to something valid. That for-loop below the gethostbyname call looks suspicious, but I can't see what your for-loop conditional expression is is because it's obscured by the debug window and the relevant portions below the break statement are cut off. Please post the entire body to your GetMyIP function call. – selbie Mar 07 '13 at 07:07
  • Sorry about that I forgot to include the code.. Updated question – jacobsgriffith Mar 07 '13 at 07:36

2 Answers2

1

I'm surprised the Windows implementation isn't thread safe and using thread local storage for each hostent. But in any case...

Just use getaddrinfo to resolve host names. It's thread safe and is meant as a replacement for gethostname.

But your ultimate goal is to enumerate the local IP addresses on the box. In that case, just use getifaddrs on UNIX and the combination of GetAdaptersInfo and GetAdatperAddresses on Windows to enumerate local IP addresses. You can also use the SIO_ADDRESS_LIST_QUERY ioctl with a dummy socket on Windows.

Community
  • 1
  • 1
selbie
  • 100,020
  • 15
  • 103
  • 173
  • WinSock's implementation of `gethostbyname()` is thread-safe, and does use TLS. [The documentation](http://msdn.microsoft.com/en-us/library/windows/desktop/ms738524.aspx) even says so: "The memory for the hostent structure returned by the gethostbyname function is allocated internally by the Winsock DLL from thread local storage." – Remy Lebeau Mar 07 '13 at 19:27
  • But yes, you are right that `gethostbyname/getaddrinfo()` should not be used to get the calling PC's local IP addresses, `getifaddrs()` and `GetAdaptersAddresses/GetAdaptersInfo()` should be used instead. – Remy Lebeau Mar 07 '13 at 19:33
0

This is the solution I came up with. Aparently gethostname is not thread safe. After effects is multithreaded.

I replaced this

int idx=0;
char ac[ 80 ];
int err = gethostname( ac, sizeof( ac ) );
(void) err;
RakAssert(err != -1);

struct hostent *phe = gethostbyname( ac );

if ( phe == 0 )
{
    RakAssert(phe!=0);
    return ;
}
for ( idx = 0; idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS; ++idx )
{
    if (phe->h_addr_list[ idx ] == 0)
        break;

    memcpy(&addresses[idx].address.addr4.sin_addr,phe->h_addr_list[ idx ],sizeof(struct in_addr));
}

while (idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS)
{
    addresses[idx]=UNASSIGNED_SYSTEM_ADDRESS;
    idx++;
}

with this

int idx=0;
struct addrinfo* feed_server = NULL;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
getaddrinfo("localhost", NULL, &hints, &feed_server);
struct addrinfo *res;
for(res = feed_server; res != NULL; res = res->ai_next) {
    struct sockaddr_in* saddr = (struct sockaddr_in*)res->ai_addr;
    //char* ipv4Str = inet_ntoa(saddr->sin_addr);
    memcpy(&addresses[idx].address.addr4.sin_addr, &saddr->sin_addr, sizeof(struct in_addr));
    idx++;
} 
while (idx < MAXIMUM_NUMBER_OF_INTERNAL_IDS) {
    addresses[idx]=UNASSIGNED_SYSTEM_ADDRESS;
    idx++;
}

And this is why I went that route. Anybody object?

gethostname not thread safe

jacobsgriffith
  • 1,448
  • 13
  • 18