Welcome! Log In Create A New Profile

Advanced

Unexpected DSI Exception with C++

Posted by arasium 
Unexpected DSI Exception with C++
August 24, 2009 01:58PM
Hi everybody,

i've made a c++ class to encapsulate Http request mecanism. This class do its job without error when i compile it under Visual Studio and running under Windows.

But when i modify it to be compatible with wii (network initialization is different), it crash when the destructor is called (i think it's a segmentation fault, but i don't know where it can occure...).

Here is my code (download here)

NetworkRequest.h
#ifndef _NETWORKREQUEST_H_
#define _NETWORKREQUEST_H_

#include 
#include "NetworkResponse.h"
#include 

#define NETWORK_BLOCK_SIZE	1000
#define NETWORK_PORT		80

class NetworkRequest
{
private:
	s32  _sockfd;
	std::string _request;
	std::string _hostName;
	std::string _path;

	void Connect();
	void Disconnect();
	static void Init();
	u32 Read(void *buffer, u32 len);
	void Write(const void *buffer, u32 len);
	u32 GetResponseLength();
public:

	NetworkRequest(const std::string &request);
	~NetworkRequest();
	NetworkResponse GetResponse();
};

#endif

NetworkRequest.cpp
#include "header/NetworkRequest.h"

#include 
#include 
#include 
#include 
#include 

#include "header/Exception.h"

using namespace std;


void NetworkRequest::Init()
{
	static bool isInitialized = false;
	s32 ret;

	/* if is already initialized, we do nothing */
	if(isInitialized)
		return;

	/* Initialize network */
	static char _hostip[16];
	ret = if_config(_hostip, NULL, NULL, true);
	if (ret < 0)
		throw new Exception("Can't initialize network!",ret);

	isInitialized = true;

	return;
}
NetworkRequest::NetworkRequest(const string &request)
{
	/* ensure that the network is initialized */
	Init();

	/* store local variables */
	_sockfd = -1;
	_request = request;
	_hostName = _request.substr(7,_request.find_first_of('/',7) - 7);
	_path = request.substr(_hostName.size() + 7,string::npos);
}

void NetworkRequest::Connect()
{
	struct hostent *he;
	struct sockaddr_in sa;

	s32 ret;

	/* Ensure that the socket is disconnected */
	Disconnect();

	/* Create socket */
	_sockfd = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (_sockfd < 0)
		throw new Exception("Error creating a socket!",_sockfd);

	/* Get host by name */
	he = net_gethostbyname(_hostName.c_str());
	if (!he)
		throw new Exception("Can't find the host!",-1);

	/* Setup socket */
	memcpy(&sa.sin_addr, he->h_addr_list[0], he->h_length);
	sa.sin_family = AF_INET;
	sa.sin_port = htons(80);

	ret = net_connect(_sockfd, (struct sockaddr *)&sa, sizeof(sa));
	if (ret < 0)
		throw new Exception("Can't connect to the socket!",ret);
}

void NetworkRequest::Disconnect()
{
	if (_sockfd >= 0)
	{
		net_close(_sockfd);
		_sockfd = -1;
	}
}

NetworkRequest::~NetworkRequest()
{
	Disconnect();
}

u32 NetworkRequest::Read(void *buffer, u32 len)
{
	u32 read = 0, ret = 0;

	/* Data to be read */
	for (read = 0; read < len; read += ret) {
		u32 size;

		/* Size to read */
		size = len - read;
		if (size > NETWORK_BLOCK_SIZE)
			size = NETWORK_BLOCK_SIZE;

		/* Read network data */
		ret = net_recv(_sockfd, (char*)buffer + read, size, 0);
		if (ret < 0)
			throw new Exception("Can't read from the net socket!",ret);

		/* Read finished */
		if (!ret)
			break;
	}

	return read;
}

void NetworkRequest::Write(const void *buffer, u32 len)
{
	u32 ret = 0, written = 0;

	/* Data to be written */
	for (written = 0; written < len; written += ret) {
		u32 size;

		/* Size to read */
		size = len - written;
		if (size > NETWORK_BLOCK_SIZE)
			size = NETWORK_BLOCK_SIZE;

		/* Write network data */
		ret = net_send(_sockfd, (char*)buffer + written, size, 0);
		if (ret < 0)
			throw new Exception("Can't write into the net socket!",ret);

		/* Write finished */
		if (!ret)
			break;
	}
}

u32 NetworkRequest::GetResponseLength()
{
	char buf[1024], *ptr = NULL;
	u32  len;
	s32  ret;

	string totalRequest = "GET " + _path + " HTTP/1.1\r\nHost: " + _hostName + "\r\nConnection: close\r\n\r\n";

	/* send request */
	ret = net_send(_sockfd, totalRequest.c_str(), totalRequest.length(), 0);
	if(ret < 0)
		throw new Exception("Impossible to send the request to the host!",ret);

	/* Clear buffer */
	memset(buf, 0, sizeof(buf));

	/* Read HTTP header */
	for (u32 cnt = 0; !strstr(buf, "\r\n\r\n"); cnt++)
		if (net_recv(_sockfd, buf + cnt, 1, 0) <= 0)
			throw new Exception("Invalid header response!",-1);

	/* HTTP request OK? */
	if (!strstr(buf, "HTTP/1.1 200 OK"))
		throw new Exception("The response status is not OK!",-1);

	/* Retrieve content size */
	ptr = strstr(buf, "Content-Length:");
	if (!ptr)
		throw new Exception("Can't find the response length!",-1);

	sscanf(ptr, "Content-Length: %u", &len);

	return len;
}

NetworkResponse NetworkRequest::GetResponse()
{
	u32 len;

	void* buffer = NULL;

	Connect();
	len = GetResponseLength();

	/* Allocate response memory */
	buffer = malloc(len);
	if (!buffer)
		throw Exception("Not enough memory!",-1);

	/* Download file */
	try
	{
		Read(buffer, len);
	}
	catch(Exception * ex)
	{
		free(buffer);
		throw;
	}

	NetworkResponse response(buffer, len);
	Disconnect();
	free(buffer);
	return response;
}

NetworkResponse.h
#ifndef _NETWORKRESPONSE_H_
#define _NETWORKRESPONSE_H_

#include 
#include 

class NetworkResponse
{
private:
	void *_buffer;
	u64 _size;
public:
	NetworkResponse(void *buffer = NULL, const u64 &size = 0);
	NetworkResponse(const NetworkResponse &src);
	NetworkResponse& operator=(const NetworkResponse &src);
	~NetworkResponse();

	u64 Size() const;
	void* Content() const;
};

#endif

NetworkResponse.cpp
#include "header/NetworkResponse.h"
#include 
using namespace std;

NetworkResponse::NetworkResponse(void *buffer, const u64 &size)
{
	_size = size;
	if(buffer != NULL && _size > 0)
	{
		_buffer = (void*)new char;
		memcpy(_buffer,buffer, size);
	}
	else
		_buffer = NULL;
}

NetworkResponse::NetworkResponse(const NetworkResponse &src)
{
	_size = src.Size();
	_buffer = (void*)new char[_size];
	memcpy(_buffer,src.Content(), _size);
}

NetworkResponse& NetworkResponse::operator=(const NetworkResponse &src)
{
	if(_buffer != NULL)
	{
		delete[] (char*)_buffer;
		_buffer = NULL;
	}

	_buffer = (void*)new char[src.Size()];
	memcpy(_buffer,src.Content(), src.Size());
	_size = src.Size();

	return *this;
}

NetworkResponse::~NetworkResponse()
{
	if(_buffer != NULL)
	{
		delete[] (char*)_buffer;
		_buffer = NULL;
	}
}

u64 NetworkResponse::Size() const
{
	return _size;
}

void* NetworkResponse::Content() const
{
	return _buffer;
}



Edited 1 time(s). Last edit at 08/24/2009 02:08PM by arasium.
Sorry, only registered users may post in this forum.

Click here to login