Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабы / 2 / lab.05.by mice / spice / src / cdm_addr_info

.cpp
Скачиваний:
10
Добавлен:
17.04.2013
Размер:
4.79 Кб
Скачать
/*******************************************************************************
* file:         cdm_addr_info.h                                                *
* version:      0.9.0                                                          *
* author:       d-evil [tmd] (mailto:d-evil.tmd@mail.ru)                       *
* description:  not available                                                  *
*******************************************************************************/

#include "cdm_addr_info.h"


////////////////////////////////////////////////////////////////////////////////
// cdm_addr_info public definition
cdm_addr_info::cdm_addr_info() {
	_init();

	_saddr_in.sin_addr.s_addr = 0;
	_saddr_in.sin_port = 0;
	_saddr_in.sin_family = AF_INET;
}


cdm_addr_info::cdm_addr_info(const char *const host, const unsigned short port) {
	_init();
	set(host, port);
}


cdm_addr_info::~cdm_addr_info() {
	if (NULL != _addr_info) freeaddrinfo(_addr_info);
	free(_ip_str);
	free(_port_str);
	free(_host);
}


addrinfo *cdm_addr_info::info(const int index) {
	int i = index;
	addrinfo *ai = _addr_info;
	while (NULL != ai && 0 < i) {
		--i;
		ai = ai->ai_next;
	}

	return ai;
}


int cdm_addr_info::set(const sockaddr_in *const saddrin) {
	int rev = set_port(ntohs(saddrin->sin_port));
	if (0 != rev) return rev;

	rev = _set_ip(saddrin->sin_addr);
	if (0 != rev) {
		if (NULL != _host) _host[0] = '\0';
		return rev;
	}
	_updt_addr_info(_ip_str);

	return _updt_host();
}


int cdm_addr_info::set(const char *const host, const unsigned short port) {
	int rev = set_port(port);
	if (0 != rev) return rev;

	return set_host(host);
}


int cdm_addr_info::set_port(const unsigned short port) {
	_saddr_in.sin_port = htons(port);
	if (NULL == _port_str) {
		// try to alloc some memory
		_port_str = (char *)malloc(MX_PORTLEN * sizeof(char));
		if (NULL == _port_str) return ERC_NOMEM;
	}
	_port_str = itoa(port, _port_str, 10);

	return 0;
}


int cdm_addr_info::set_host(const char *const host) {
	int rev = resolve_host(host, &_saddr_in.sin_addr);
	if (0 != rev) return rev;

	rev = _set_ip(_saddr_in.sin_addr);
	if (0 != rev) {
		if (NULL != _host) _host[0] = '\0';
		return rev;
	}
	_updt_addr_info(_ip_str);

	return _updt_host();
}


int cdm_addr_info::set_ip(const unsigned int ip) {
	sockaddr_in saddr;
	saddr.sin_addr.s_addr = ip;

	return set(&saddr);
}


int cdm_addr_info::set_to_local(const unsigned short port) {
	char str[MX_LOCAL_HOST_LEN];

	if (0 != gethostname(str, MX_LOCAL_HOST_LEN)) return -1;

	return set(str, port);
}


int cdm_addr_info::resolve_host(const char *const host, in_addr *const addr) {
	addr->s_addr = inet_addr(host);
	// If the supplied server address wasn’t in the form "aaa.bbb.ccc.ddd"
	// it’s a host name, so try to resolve it
	if (INADDR_NONE == addr->s_addr) {
		hostent *ht;
		ht = gethostbyname(host);
		if (NULL == ht) return ERC_CANTRESOLVE;
		memcpy(addr, ht->h_addr_list[0], ht->h_length);
	}

	return 0;
}


////////////////////////////////////////////////////////////////////////////////
// cdm_addr_info protected definition
void cdm_addr_info::_init() {
	_ip_str = NULL;
	_port_str = NULL;
	_host = NULL;
	_addr_info = NULL;
}


int cdm_addr_info::_set_ip(const in_addr ip) {
	_saddr_in.sin_addr = ip;
	
	char *ip_str = inet_ntoa(_saddr_in.sin_addr);
	if (NULL == ip_str) {
		if (NULL != _ip_str) _ip_str[0] = '\0';
		return ERC_WSA;
	}
	size_t len = strlen(ip_str) + 1;

	char *tmp = (char *)realloc(_ip_str, len * sizeof(char));
	if (NULL == tmp) {
		_ip_str = '\0';
		return ERC_NOMEM;
	}
	_ip_str = tmp;

	memcpy(_ip_str, ip_str, len * sizeof(char));

	return 0;
}


int cdm_addr_info::_updt_host() {
	hostent *ht = gethostbyaddr((char *)&_saddr_in.sin_addr,
				sizeof(_saddr_in.sin_addr), _saddr_in.sin_family);
	if (NULL == ht || NULL == ht->h_name) {
		if (NULL != _host) _host[0] = '\0';
		return 0;	// ERC_CANTRESOLVE;	// can't resolve
	}

	size_t len = strlen(ht->h_name) + 1;
	char *tmp = (char *)realloc(_host, len * sizeof(char));
	if (NULL == tmp) {
		if (NULL != _host) _host[0] = '\0';
		return ERC_NOMEM;
	}
	_host = tmp;

	memcpy(_host, ht->h_name, len * sizeof(char));

	return 0;
}


int cdm_addr_info::_updt_addr_info(char *const host) {
	if (NULL != _addr_info) freeaddrinfo(_addr_info);
	_addr_info = NULL;

	char *h;
	if (NULL != host) h = host;
	else if (NULL != _host) h = _host;
	else if (NULL != _ip_str) h = _ip_str;
	else return -1;

	addrinfo hints;
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	if (0 != getaddrinfo(h, NULL, &hints, &_addr_info)) return -1;

	return 0;
}
Соседние файлы в папке src