Welcome! Log In Create A New Profile

Advanced

[SOLVED] Need help with connecting to a TCP server on the internet

Posted by TheCodingBrony 
[SOLVED] Need help with connecting to a TCP server on the internet
July 29, 2015 02:13PM
I'm working on this TCP client test program that tries to connect to a host name (www.google.com) and sends a GET request when a connection to it has been successfully established. So far, I only got the IP address resolving working but I cannot seem to connect to the addresses of the host name no matter what I do with my code.

Is it because libogc is too crap to connect to a TCP server as a client? I don't think so as I've seen numerous homebrew programs capable of downloading files off of a web server.


Here's my TCP client test program (now working):
// Re-add the <> symbols on the include because Phorum will clear its contents for some reason
#include stdio.h
#include stdlib.h
#include string.h
#include malloc.h
#include unistd.h
#include network.h
#include errno.h

#include gccore.h
#include fat.h


#define HOST_NAME   "www.wiibrew.org"
#define GET_ADDR    "/"


#define MAX_MSG_LEN     4096


// Stuff for video and framebuffer
GXRModeObj	*videoMode;	// Video mode registers
void		*xfb=NULL;	// External framebuffer


// Declaration of the video init routine
void initVideo();


// Structure for holding socket data
typedef struct {
    sockaddr_in socketAddr;
    int         socket;
    char        socketBuff[MAX_MSG_LEN];
} hostSocket;


// Connect function
hostSocket *Connect(const char *ipAddr, int port) {

    hostSocket *handle = (hostSocket*)malloc(sizeof(hostSocket));
    memset(handle, 0x00, sizeof(hostSocket));


    // Set appropriate values to the socket address
    handle->socketAddr.sin_family = AF_INET;
    handle->socketAddr.sin_port = htons(port);
    handle->socketAddr.sin_addr.s_addr = inet_addr(ipAddr);


    // Create a socket handle
    handle->socket = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

    if (handle->socket < 0) {
        printf("Cannot create socket.\n");
        free(handle);
        return(NULL);
    }


    printf("Socket created... Connecting to address %s... ", ipAddr);


    // Establish connection
    if (net_connect(handle->socket, (struct sockaddr*)&handle->socketAddr, sizeof(sockaddr_in)) == -1) {

        printf("Connect failed.\n");
        net_close(handle->socket);
        free(handle);
        return(NULL);

    }


    return(handle);

}


// Main function
int main(int argc, char *argv[]) {

	// Initialize video for console display
	initVideo();

	// Initialize console
	console_init(xfb, 20, 20, videoMode->fbWidth, videoMode->xfbHeight, videoMode->fbWidth*2);


    // Initialize file system for dumping received data to a file for analysis
	fatInitDefault();


	// Print Hello World message
	printf("\nInitializing network... ");
	if (net_init()) {
        printf("Failed to initialize network.\n");
        exit(EXIT_FAILURE);
	}
	printf("Ok!\n");


    // Get IP addresses of domain and print out the results
    printf("Resolving IP addresses to domain %s... ", HOST_NAME);
    hostent *host = net_gethostbyname(HOST_NAME);
    if (!host) {
        printf("Could not resolve domain address.\n");
        exit(EXIT_FAILURE);
    }
    printf("Ok!\n");

    printf("Address list:\n");
    for(int i=0; host->h_addr_list != NULL; i++) {
        printf(" %s\n", inet_ntoa(*((in_addr*)host->h_addr_list)));
    }

    char *ipAddr = strdup(inet_ntoa(*((in_addr*)host->h_addr_list[0])));


    printf("Connecting to %s... ", ipAddr);
    hostSocket *socket = Connect(ipAddr, 80);
    if (!socket) {
        exit(EXIT_FAILURE);
    }
    printf("Ok!\n");

    free(ipAddr);


    // Send GET request
    printf("Sending GET request... ");

    sprintf(socket->socketBuff, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", GET_ADDR, HOST_NAME);
    if (net_send(socket->socket, socket->socketBuff, strlen(socket->socketBuff), 0) < 0) {

        printf("Could not send request.\n");
        net_close(socket->socket);
        exit(EXIT_FAILURE);

    }

    printf("Ok.\n");


    // Print out and dump received data into a file
    FILE *fp = fopen("/dump.bin", "w");
    printf("\nReceived data:\n");

    while(1) {

        int bytes = net_recv(socket->socket, socket->socketBuff, MAX_MSG_LEN, 0);

        // net_recv() will return 0 if the connection has been closed by the server
        if (bytes <= 0)
            break;

        // Write to file
        if (fp != NULL)
            fwrite(socket->socketBuff, 1, bytes, fp);

        // Print the data
        socket->socketBuff[bytes-1] = 0x00;
        printf("%s", socket->socketBuff);

    }


    // Close socket and file
    net_close(socket->socket);
    fclose(fp);

    printf("\n\nReceive complete and socket is closed.\n");


	// Wait until reset is pressed
	while(SYS_ResetButtonDown() == false) {
		VIDEO_WaitVSync();
	}

	printf("Exiting...\n");

}

// Simple video init routine for displaying a text console
void initVideo() {

	// Initialize video subsystem
	VIDEO_Init();

	// Get preferred video mode according to the console's configuration
	videoMode = VIDEO_GetPreferredMode(NULL);

	// Create external framebuffer and clear it
	// (only one framebuffer since we're only going to display a text console)
	xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(videoMode));
	VIDEO_ClearFrameBuffer(videoMode, xfb, 0x00000000);

	// Configure video system, set framebuffer and clear display mask
	VIDEO_Configure(videoMode);
	VIDEO_SetNextFramebuffer(xfb);
	VIDEO_SetBlack(FALSE);
	VIDEO_Flush();

}

And no, don't give me the 'Look for BSD Socket examples' answer as I've already looked through several of such examples and none of them worked for me... Unless the example works with libogc right off the bat that is.

Any useful help will be greatly appreciated!



Edited 2 time(s). Last edit at 07/30/2015 01:29PM by TheCodingBrony.
Re: Need help with connecting to a TCP server on the internet
July 29, 2015 04:06PM
It would help if you said which function is failing (net_socket, net_connect etc).
Re: Need help with connecting to a TCP server on the internet
July 30, 2015 12:43AM
Oops, forgot to mention that... net_connect() is the one that kept failing. I had no issue resolving the host name and creating a socket.
Re: Need help with connecting to a TCP server on the internet
July 30, 2015 02:47AM
I did a whole lot of tests and I'm still not sure if it works perfectly but here is my connect function(if you want the whole code file you can send me a email);

static s32 initialise_network() {
    s32 result;
    while ((result = net_init()) == -EAGAIN);
    return result;
}

static int wait_for_network_initialisation() {
	if(network_on==true) return 0;	
	
    if(http_debug) printf("Waiting for network to initialise...\n");
    if (initialise_network() >= 0) {
		char myIP[16];	
		if (if_config(myIP, NULL, NULL, true) < 0) {
			if(http_debug) printf("Error reading IP address, exiting\n");			
			return -1;
		}
        if(http_debug) printf("Network initialised.\n");
		network_on=true;
		return 0;
    } else {
        if(http_debug) printf("Unable to initialise network, exiting\n");
    }
	
	network_on=false;
	return -1;
}

typedef s32 (*transferrer_type)(s32 s, void *mem, s32 len);
inline static s32 transfer_exact(s32 s, char *buf, s32 length, transferrer_type transferrer) {
    s32 bytes_transferred = 0;
    s32 remaining = length;
    while (remaining) {
        if ((bytes_transferred = transferrer(s, buf, remaining > BUFFER_SIZE ? BUFFER_SIZE : remaining)) > 0) {
            remaining -= bytes_transferred;
            buf += bytes_transferred;
        } else if (bytes_transferred < 0) {
            return bytes_transferred;
        } else {
            return -ENODATA;
        }
    }
    return 0;
}

static inline s32 write_exact(s32 s, char *buf, s32 length) {
    return transfer_exact(s, buf, length, (transferrer_type)net_write);
}

//---------------------------------------------------------------------------------------------


// Write our message to the server
static s32 send_message(s32 server, char *msg) {
	u32 msglen = strlen(msg);
	char msgbuf[msglen + 1];
	if (msgbuf == NULL) return -ENOMEM;
	sprintf(msgbuf, "%s", msg);
	//if(http_debug) printf("Sent message: %s", msgbuf);
	return write_exact(server, msgbuf, msglen);
}  


// Connect to the remote server
struct hostent *hp;
char *last_ipa_address=" ";
	struct sockaddr_in connect_addr;

static s32 server_connect(char *ipa_address) {

	//struct sockaddr_in server;
	
	s32 socket = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if (socket < 0) { 
		net_close(socket);
		if(http_debug) printf("Error creating socket, exiting\n"); 
		return -1; 
	}
	
	if( strcmp(last_ipa_address, ipa_address) != 0 ){
		
		memset(&connect_addr, 0, sizeof(connect_addr));
		connect_addr.sin_family = AF_INET;
		connect_addr.sin_port = SOCKET_PORT;  //80 SOCKET_PORT
		connect_addr.sin_addr.s_addr= inet_addr(ipa_address);
		
		if(connect_addr.sin_addr.s_addr==-1){	
			if(http_debug) printf("Connect via inet_addr() failed : %i\n", connect_addr.sin_addr.s_addr);
			if(http_debug) printf("Attempting net_gethostbyname()...\n");			
			
				hp = net_gethostbyname(ipa_address);  //NOT threadsafe
				if (hp  == NULL ) {            
					if(http_debug) printf("NET_GETHOSTBYNAME failed: errno=[%d] for %s \n",errno, ipa_address); 	
					
					net_close(socket);
					return -1;
				} else {
				   if(http_debug) printf("NET_GETHOSTBYNAME successfull resolved\n"); 
				   strcpy(last_ipa_address, ipa_address);
				}	
			
			
			memcpy ((char *) &connect_addr.sin_addr, hp->h_addr_list[0], hp->h_length);
		} else {
			if(http_debug) printf("IPA successfull resolved\n"); 
		}
	
	} else {
			if(http_debug) printf("IPA SAME AS LAST - REUSING CONNECTION\n" ); 			
			//sleep(4);
	}
		
	http_status_code=9;
	
	if (net_connect(socket, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) == -1) {
		net_close(socket);
		strcpy(last_ipa_address, "");
		if(http_debug) printf("Failed to connect to the remote server.\n");
		return -1;
	}	
	
	return socket;
}

yeah if that doesn't help shout me a email
Re: Need help with connecting to a TCP server on the internet
July 30, 2015 05:46AM
I think it's more likely that the call to net_socket() is failing (you need to pass IPPROTO_IP for the protocol, not IPPROTO_TCP) and you're not detecting it because you only check for a result of INVALID_SOCKET. Failure is indicated by a return value that is less than zero, which will map to a constant defined in errno.h. The same goes for net_connect(), you should performing more stringent error handling than just checking for a result of -1.
Re: Need help with connecting to a TCP server on the internet
July 30, 2015 01:25PM
Well, I was finally able to get this test program to connect and download some data by following tueidj's advice and changing the port number to 80 instead of 8080 specified in my Connect() function. I'll update the code provided in the first post with the working version so that others can learn off of it when they're having similar issues.

Thanks a lot guys!

By the way tueidj, does the network library also support UDP protocol or is it TCP only? I have a feeling that its the latter since the BSD socket implementation in libogc is not exactly complete by the looks of it.



Edited 1 time(s). Last edit at 07/30/2015 01:31PM by TheCodingBrony.
Re: Need help with connecting to a TCP server on the internet
July 30, 2015 04:17PM
It's not incomplete, it just has mistakes. The wii does support UDP but libogc doesn't.
Sorry, only registered users may post in this forum.

Click here to login