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

Лабы / 2 / lab.04.by mice / hail / cdm_hailer

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

#include "cdm_hailer.h"


////////////////////////////////////////////////////////////////////////////////
// cdm_hailer public definition
cdm_hailer::cdm_hailer() {
	_init();
}


cdm_hailer::~cdm_hailer() {
	_free();
}


int cdm_hailer::target(const char *const host, const int pckt_sz) {
	if (0 != _iaddr.set_host(host)) return -1;
	if (NULL == _iaddr.info()) return -1;
	_iaddr.set_port(0);

	if (0 >= pckt_sz) return -1;
	_pckt_sz = pckt_sz;

	return 0;
}


int cdm_hailer::link() {
	if (INVALID_SOCKET == _sock) closesocket(_sock);
	_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
	if (INVALID_SOCKET == _sock) return -1;

	if (0 != connect(_sock, _iaddr.info()->ai_addr, (int)_iaddr.info()->ai_addrlen)) return -1;

	return 0;
}


int cdm_hailer::can_read(const int timeout_ms) {
	fd_set set;
	set.fd_count = 1;
	set.fd_array[0] = _sock;

	timeval to;
	to.tv_sec = 0;
	to.tv_usec = timeout_ms * 1000;

	int rev = select(0, &set, NULL, NULL, &to);
	switch (rev) {
		case SOCKET_ERROR: return -1;
		case 0: return 0;
		default: return 1;
	}

	return -1;	// dummy return
}


int cdm_hailer::hail_it(const int num) {
	memset(_snd_buf, 0, MX_BUF_SZ);

	icmp_h *h = (icmp_h *)_snd_buf;
	h->type = ICMP_ECHO;
	h->code = 0;
	h->num = num;
	h->id = _id;
	int len = _pckt_sz + sizeof(icmp_h);
	char *data = _snd_buf + sizeof(icmp_h);
	*(clock_t *)data = clock();
	h->check_sum = in_cksum((unsigned short *)_snd_buf, len);

	int ds = send(_sock, _snd_buf, len, 0);
	if (ds != len) return -1;

	return 0;
}


int cdm_hailer::listen_it(const int timeout) {
	if (0 >= can_read(timeout)) return -1;

	int dr = recv(_sock, _rcv_buf, MX_BUF_SZ, 0);
	if (0 > dr) return -1;

	ip_h *hip = (ip_h *)_rcv_buf;
	icmp_h *h = (icmp_h *)(_rcv_buf + sizeof(ip_h));
	if (h->id != _id) return -1;

	if (NULL == _hail_res) _hail_res = new sdm_hail_res;

	_hail_res->ttl = ((ip_h *)_rcv_buf)->ttl;
	clock_t st = *(clock_t *)(_rcv_buf + sizeof(ip_h) + sizeof(icmp_h));
	_hail_res->rtime = clock() - st;
	_hail_res->num = h->num;
	
	return 0;
}


////////////////////////////////////////////////////////////////////////////////
// cdm_hailer protected definition
int cdm_hailer::_init() {
	_sock = INVALID_SOCKET;
	_hail_res = NULL;
	_pckt_sz = DEF_PCKT_SZ;
	_id = (unsigned short)GetProcessId(GetCurrentProcess());

	_snd_buf = (char *)malloc(MX_BUF_SZ);
	_rcv_buf = (char *)malloc(MX_BUF_SZ);
	if (NULL == _snd_buf || NULL == _rcv_buf) return -1;

	return 0;
}


int cdm_hailer::_free() {
	if (INVALID_SOCKET != _sock) closesocket(_sock);
	if (NULL != _hail_res) delete _hail_res;
	free(_snd_buf);
	free(_rcv_buf);

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