Welcome! Log In Create A New Profile

Advanced

net_gethostbyname vs. numeric IPs?

Posted by Drmn4ea 
net_gethostbyname vs. numeric IPs?
January 08, 2010 09:14AM
Hi all,
Digging in with my first homebrew effort, a simple client-server Wii demo to test a forthcoming (if I get around to it!) matchmaker server for online multiplayer homebrew. I'm finding net_gethostbyname() fails when fed a hostname which is already a numeric IP. (A forum search shows this has been mentioned before, see http://forum.wiibrew.org/read.php?11,23056,23127)

Currently I'm using bushing's http and socket code from WiiEarth (http.c/http.h), modified slightly to (I hoped!) handle both cases. The below is called using

hSocket = tcp_connect("192.168.1.4", 12345);

where 192.168.1.4 is a PC on the local network running a simple server. The Wii has taken address 192.168.1.100. Just before the above runs, the headers fetched from google.com are displayed to verify that everything is at least working via gethostbyname.

s32 tcp_connect (char *host, const u16 port) {
	struct sockaddr_in sa;
	s32 s, res;
	s64 t;

	// added for testing for numeric IPs
	struct in_addr * myaddr;

	if (inet_aton(host, myaddr))
	{
		printf("Host is numeric IP\n");
		//...
		// setup 'sa' with binarified address and a couple other things
		memset (&sa, 0, sizeof (struct sockaddr_in));
		sa.sin_family= PF_INET;
		sa.sin_len = sizeof (struct sockaddr_in); // 4 bytes
		sa.sin_port= htons (port);
		//memcpy ((char *) &sa.sin_addr, &myaddr, sizeof(struct in_addr));
		memcpy ((char *) &sa.sin_addr, host, strlen(host));
		//printf("Size of sa.in_addr: %d  Size of in_addr: %d  size of myaddr: %d\n", sizeof(sa.sin_addr), sizeof(struct in_addr), sizeof(myaddr));
	}

	else {
		//original net_gethostbyname stuff here...
		struct hostent *hp = net_gethostbyname(host);
		
		if (!hp || !(hp->h_addrtype == PF_INET)) {
			printf ("net_gethostbyname failed: %d\n", errno);
			return errno;
		}

		memset (&sa, 0, sizeof (struct sockaddr_in));
		sa.sin_family= PF_INET;
		sa.sin_len = sizeof (struct sockaddr_in);
		sa.sin_port= htons (port);
		memcpy ((char *) &sa.sin_addr, hp->h_addr_list[0], hp->h_length);
	} // else

I'm a bit unclear on what contents are expected for h_addr (a.k.a. h_addr_list[0]) within the hostent structure, which gets later copied into sa.sin_addr. Neither of the obvious choices seem to work (passing the numeric string smells wrong, but seems to make better progress- fails with a tcp_connect timeout, while passing the inet_aton result causes an EAFNOSUPPORT error code from net_connect()). In any case, no connection attempt is seen on the PC side.

Does anyone know a more correct way to do this, or at least what one expects to find in h_addr_list[]?
Re: net_gethostbyname vs. numeric IPs?
January 08, 2010 11:43AM
[www.gnu.org]
has the details on the hostent structure

as for the EAFNOSUPPORT error, you are probably not recreating the structure correctly as the error is only returned if the evaluation of the structure is deems it to be unsuitable
Re: net_gethostbyname vs. numeric IPs?
January 09, 2010 11:40AM
Found the problem... silly mistake. I was passing memcpy a pointer to (pointer to) the in_addr structure itself. The following works correctly for numeric IPs, I am receiving bytes from the PC via net_read(). hostent.h_addr is expecting the numeric address in the form of an int32 (IPv4 addresses) in network order, compatible with the output of inet_aton().

	struct in_addr myaddr;

	if (inet_aton(host, &myaddr))
	{
		printf("Host is numeric IP\n");
		//...
		// setup 'sa' with binarified address and a couple other things
		memset (&sa, 0, sizeof (struct sockaddr_in));
		sa.sin_family= PF_INET;
		sa.sin_len = sizeof (struct sockaddr_in);
		sa.sin_port= htons (port);
		memcpy ((char *) &sa.sin_addr, &myaddr.s_addr, sizeof(struct in_addr));
	}

Now to find out, is there any available mechanism to provide an IRQ/callback when a packet arrives, rather that poll continuously for them? (Or is this why there are hardly any networked multiplayer homebrew games...)
Re: net_gethostbyname vs. numeric IPs?
January 09, 2010 12:32PM
Quote
Drmn4ea
Now to find out, is there any available mechanism to provide an IRQ/callback when a packet arrives, rather that poll continuously for them? (Or is this why there are hardly any networked multiplayer homebrew games...)

theoretically, if you set a callback it is polling continuosly as without polling it wont know if had recieved anything.

i would suggest using threading since that seems the most sensible idea.

pseudo-code
Polling function

check if data is recieved
if data exists then append to buffer
if no data then do nothing


Main function

Initiate network
Connect to ip

Initialise threading
Assign polling function to thread (the above polling function)

while threading
{
check buffer
if buffer has data then pause threading and output
after output clear buffer
restart threading

do nothing if buffer empty

sleep for a short period of time (just for stability)
}

the above pseudo code is just an example of how it could be done, since its a barebones irc system i think you should be able to manipulate to your use



Edited 1 time(s). Last edit at 01/09/2010 12:32PM by SteelSLasher.
Re: net_gethostbyname vs. numeric IPs?
January 10, 2010 06:42AM
Quote

theoretically, if you set a callback it is polling continuosly as without polling it wont know if had recieved anything.

A callback won't do anything unless called... I was hoping there was a mechanism to have the network adapter generate an interrupt, then an interrupt handler could call back the appropriate handler (probably just add the packet to a buffer for the game to poll cheaply, per your example above). The Wii netcard is SDIO (similar to an SD-card interface, but with an extra line for device-to-host IRQ), but I don't know if the IRQ line is implemented.

Assuming it isn't though, I'm intrigued with your ideas and would like to subscribe to your newsletter :-) . Is there documentation or examples (including well-written homebrew with published source) of how to use threading on Wii? I have to admit most of my programming experience is with 8-bit micros; I've never explicitly written a multithreaded app before. Most of the networking code has big 'NOT THREADSAFE' warnings all over it (mentioning static buffers, etc); I'm guessing this means it is unsafe to use these functions across multiple threads, NOT unsafe to call them from a single thread in a multithreaded app, right?

What kind of overhead / resource hit does the thread handling add?
Re: net_gethostbyname vs. numeric IPs?
January 10, 2010 11:02AM
Using threads isn't essential. It would only move the polling out of the main thread to a different one.

Most unix network apps poll select() to see if there's data waiting on one or more sockets. Unfortunately it hasn't been implemented in libogc and you have to use net_poll() instead, which does something similar. Other options are:
- use non-blocking sockets and check if net_recv() returns -EAGAIN
- re-implement various functions in network_wii.c to use asynch IOS calls. This worked well when I wanted to do non-blocking host lookups. It would let you implement a callback system, but also requires a lot of work. On the positive side, you can raise the network heap size if it starts to become a problem when many sockets are in use.
Sorry, only registered users may post in this forum.

Click here to login