示例#1
0
/**
 * Performs the same function as getipbyname(),
 * except that it will prevent extremely expensive net_gethostbyname() calls by caching the result
 */
u32 getipbynamecached(char *domain)
{
	//Search if this domainname is already cached
	struct dnsentry *node = firstdnsentry;
	struct dnsentry *previousnode = NULL;
	
	while(node != NULL)
	{
		if(strcmp(node->domain, domain) == 0)
		{
			//DNS node found in the cache, move it to the front of the list
			if(previousnode != NULL)
				previousnode->nextnode = node->nextnode;
				
			if(node != firstdnsentry)
				node->nextnode = firstdnsentry;
			firstdnsentry = node;
			
			return node->ip;
		}
		//Go to the next element in the list
		previousnode = node;
		node = node->nextnode;
	}
	u32 ip = getipbyname(domain);
	
	//No cache of this domain could be found, create a cache node and add it to the front of the cache
	struct dnsentry *newnode = malloc(sizeof(struct dnsentry));
	if(newnode == NULL) return ip;
		
	newnode->ip = ip;
	newnode->domain = malloc(strlen(domain)+1);
	if(newnode->domain == NULL)
	{
		free(newnode);
		return ip;
	}
	strcpy(newnode->domain, domain);
	
	newnode->nextnode = firstdnsentry;
	firstdnsentry = newnode;
	dnsentrycount++;

	//If the cache grows too big delete the last (and probably least important) node of the list
	if(dnsentrycount > MAX_DNS_CACHE_ENTRIES)
	{
		struct dnsentry *node = firstdnsentry;
		struct dnsentry *previousnode = NULL;
		
		//Fetch the last two elements of the list
		while(node->nextnode != NULL)
		{
			previousnode = node;
			node = node->nextnode;
		}
		
		if(node == NULL)
		{
			printf("Configuration error, MAX_DNS_ENTRIES reached while the list is empty\n");
			exit(1);
		} else if(previousnode == NULL)
		{
			firstdnsentry = NULL;
		} else {
			previousnode->nextnode = NULL;
		}
		
		free(node->domain);
		free(node);
		dnsentrycount--;
	}

	return newnode->ip;
}
示例#2
0
/**
 * Downloads the contents of a URL to memory
 * This method is not threadsafe (because networking is not threadsafe on the Wii)
 */
struct block downloadfile(const char *url)
{
        //Check if the url starts with "http://", if not it is not considered a valid url
	if(strncmp(url, "http://", strlen("http://")) != 0)
	{
		sprintf(emptyblock.error,TX.URLnoBegin, url); //doen't start with http://
		return emptyblock;
	}
	
	//Locate the path part of the url by searching for '/' past "http://"
	char *path = strchr(url + strlen("http://"), '/');
	
	//At the very least the url has to end with '/', ending with just a domain is invalid
	if(path == NULL)
	{
		sprintf(emptyblock.error,TX.URLnoPath, url); //no path part in URL
		return emptyblock;
	}
	
	//Extract the domain part out of the url
	int domainlength = path - url - strlen("http://");
	
	if(domainlength == 0)
	{
		sprintf(emptyblock.error,TX.URLnoDomain, url); //couldn't find a domain in url
		return emptyblock;
	}
	
	char domain[domainlength + 1];
	strncpy(domain, url + strlen("http://"), domainlength);
	domain[domainlength] = '\0';
	
	//Parsing of the URL is done, start making an actual connection
	u32 ipaddress = getipbyname(domain); //slower but doesn't leak memory
	
	if(ipaddress == 0)
	{
		sprintf(emptyblock.error,TX.errorDomain, domain); //couldn't resolve domain
		return emptyblock;
	}


	s32 connection = server_connect(ipaddress, 80);
	
	if(connection < 0) {
		sprintf(emptyblock.error,TX.errEstablishConn); //couldn't establish connection
		return emptyblock;
	}
	
	//Form a nice request header to send to the webserver
	char* headerformat = "GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: WiiEarthh 1.0\r\n\r\n";;
	char header[strlen(headerformat) + strlen(domain) + strlen(path)];
	sprintf(header, headerformat, path, domain);

	//Do the request and get the response
	send_message(connection, header);
	struct block response = read_message(connection);
	net_close(connection);

	//Search for the 4-character sequence \r\n\r\n in the response which signals the start of the http payload (file)
	unsigned char *filestart = NULL;
	u32 filesize = 0;
	int i;
	for(i = 3; i < response.size; i++)
	{
		if(response.data[i] == '\n' &&
			response.data[i-1] == '\r' &&
			response.data[i-2] == '\n' &&
			response.data[i-3] == '\r')
		{
			filestart = response.data + i + 1;
			filesize = response.size - i - 1;
			break;
		}
	}
	
	if(filestart == NULL)
	{
		sprintf(emptyblock.error,TX.HTTPnoFile);
		return emptyblock;
	}
	
	//Copy the file part of the response into a new memoryblock to return
	struct block file;
	file.data = CFMalloc(filesize);
	file.size = filesize;
	
	if(file.data == NULL)
	{
		sprintf(emptyblock.error,TX.noMemCopy ); //couldn't copy the file to the block
		CFFree(response.data);
		return emptyblock;
	}
	
	memcpy(file.data, filestart, filesize);

	//Dispose of the original response
	CFFree(response.data);
	
	return file;
}