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

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

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

////////////////////////////////////////////////////////////////////////////////
// headers
#include "csp_life.h"


////////////////////////////////////////////////////////////////////////////////
// csp_life public definitions
csp_life::csp_life(): CDialog(IDD_SP_WND) {
	_thread_h = NULL;
	_thread_id = -1;
	_running = false;
	_paused = false;
	_opened = false;
	_must_stop = false;
	_can_quit = false;
	_need_csp_flush = false;
	_waiting_csp_flush = false;
	_html_file_corrupted = false;
	_list_closing = false;

	// net part
	_sock = INVALID_SOCKET;
	_file = NULL;
	_html_file = NULL;
	_buf = NULL;

	// find css file
	char buf[MAX_PATH];
	char *fp;
	if (0 != GetFullPathName(_DEF_CSS_FILE_NAME, MAX_PATH, buf, &fp)) {
		_css_file_name = buf;
	} else _css_file_name = _DEF_CSS_FILE_NAME;
	GetCurrentDirectory(MAX_PATH, buf);
	_app_path = CString(buf) + '/';

	// gui part
	_csp_list = NULL;
	_tmp_list = NULL;
	_state_btns_open = _STATE_UNKNOWN;
	_state_btns_run = _STATE_UNKNOWN;
	_state_btns_opts = _STATE_UNKNOWN;
}


csp_life::~csp_life() {
	_buf_ctl(false);
}


BOOL csp_life::OnInitDialog() {
	// getting controls
	_btn_open = (CButton *)GetDlgItem(IDC_BTN_OPEN);
	_btn_browse = (CButton *)GetDlgItem(IDC_BTN_BROWSE);
	_stt_file = (CStatic *)GetDlgItem(IDC_STT_FILE);

	_btn_run = (CButton *)GetDlgItem(IDC_BTN_RUN);
	_btn_pause = (CButton *)GetDlgItem(IDC_BTN_PAUSE);
	_edit_file = (CEdit *)GetDlgItem(IDC_EDIT_FILE);
	_edit_host = (CEdit *)GetDlgItem(IDC_EDIT_HOST);
	_stt_host = (CStatic *)GetDlgItem(IDC_STT_HOST);

	_btn_clr_file = (CButton *)GetDlgItem(IDC_BTN_CLR_FILE);
	_btn_cr_new_html = (CButton *)GetDlgItem(IDC_BTN_CR_NHTML);
	_btn_write_html = (CButton *)GetDlgItem(IDC_BTN_WRITE_HTML);

	_btn_view_html = (CButton *)GetDlgItem(IDC_BTN_VIEW_HTML);
	_btn_rw_html = (CButton *)GetDlgItem(IDC_BTN_RW_HTML);
	_btn_filter = (CButton *)GetDlgItem(IDC_BTN_FILTER);
	_btn_show_list = (CButton *)GetDlgItem(IDC_BTN_SHOW_LIST);
	_edit_html_file = (CEdit *)GetDlgItem(IDC_EDIT_HTML_FILE);
	_stt_html = (CStatic *)GetDlgItem(IDC_STT_HTML);

	_stt_info = (CStatic *)GetDlgItem(IDC_STT_INFO);
	_edit_info = (CEdit *)GetDlgItem(IDC_EDIT_INFO);

	_btn_exit = (CButton *)GetDlgItem(IDC_BTN_EXIT);

	// precreating windows
	_csp_filter.set_icon(_icon);
	if (0 !=_csp_filter.create(this)) {
		show_error_msg("Can't load filters", 0, this);
		_btn_filter->EnableWindow(FALSE);
	} else {
		_btn_filter->EnableWindow(TRUE);
	}

	// setting defaults
	_set_state_btns_open(_STATE_BTNS_OPEN_CANOPEN);
	_set_state_btns_run(_STATE_BTNS_RUN_DISABLED);
	_set_state_btns_opts(_STATE_BTNS_OPTS_DISABLED);
	_set_state_btn_write_html(false);
	_show_file_info(false, true);

	SetIcon(_icon, TRUE);
	_btn_clr_file->SetCheck(BST_UNCHECKED);
	_btn_cr_new_html->SetCheck(BST_CHECKED);
	_edit_file->SetWindowText(_app_path + "logs/log.spf");
	cdm_addr_info ai;
	ai.set_to_local();
	_edit_host->SetWindowText(ai.host());

	// loading configs
	_csp_filter.load_from_file(_app_path + _DEF_FILTER_FILE_NAME);

	return TRUE;
}


void csp_life::OnClose() {
	_btn_exit->EnableWindow(FALSE);
	if (_running) {
		stop();
		PostMessage(WM_CLOSE);
		return;
	}

	if (NULL != _csp_list) PostMessage(csp_list::SPM_LST_CLOSE_ME);
	_csp_list = NULL;
	if (NULL != _tmp_list) {
		PostMessage(WM_CLOSE);
		return;
	}

	if (_opened) {
		_close_file();
		PostMessage(WM_CLOSE);
		return;
	}

	_csp_filter.hide();
	_csp_filter.save_to_file(_app_path + _DEF_FILTER_FILE_NAME);

	// we need this just to be shure, that all previous messages are processed
	if (!_can_quit) {
		PostMessage(_WM_CAN_QUIT);
		return;
	}

	EndDialog(0);
}


int csp_life::open_file() {
	_set_state_btns_open(_STATE_BTNS_OPEN_DISABLED);
	_set_state_btns_run(_STATE_BTNS_RUN_DISABLED);
	_set_state_btns_opts(_STATE_BTNS_OPTS_DISABLED);

	if (0 != _open_file()) {
		show_error_msg("Can't open file", 0, this);
		_set_state_btns_open(_STATE_BTNS_OPEN_CANOPEN);
		_set_state_btns_run(_STATE_BTNS_RUN_DISABLED);
		_set_state_btns_opts(_STATE_BTNS_OPTS_DISABLED);
		return -1;
	}

	_set_state_btns_open(_STATE_BTNS_OPEN_CANCLOSE);
	_set_state_btns_run(_STATE_BTNS_RUN_CANRUN);
	_set_state_btns_opts(_STATE_BTNS_OPTS_ENABLED);

	return 0;
}


int csp_life::close_file() {
	_set_state_btns_open(_STATE_BTNS_OPEN_DISABLED);
	_set_state_btns_run(_STATE_BTNS_RUN_DISABLED);
	_set_state_btns_opts(_STATE_BTNS_OPTS_DISABLED);

	if (0 != _close_file()) {
		show_error_msg("Error occurred while closing file", 0, this);
	}
	_set_state_btns_open(_STATE_BTNS_OPEN_CANOPEN);
	_set_state_btns_run(_STATE_BTNS_RUN_DISABLED);
	_set_state_btns_opts(_STATE_BTNS_OPTS_DISABLED);

	return 0;
}


int csp_life::run() {
	int _old_state_btns_run = _state_btns_run;
	_set_state_btns_run(_STATE_BTNS_RUN_DISABLED);
	_set_state_btns_open(_STATE_BTNS_OPEN_DISABLED);
	if (_running) {
		show_error_msg("Stop it, before run again", 0, this);
		_set_state_btns_run(_old_state_btns_run);
		_set_state_btns_open(_STATE_BTNS_OPEN_CANCLOSE);
		return -1;
	}

	_thread_h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_run_proc_helper,
							 this, 0, &_thread_id);
	if (NULL == _thread_h) {
		show_error_msg("Can't create new thread", 0, this);
		_set_state_btns_run(_STATE_BTNS_RUN_CANRUN);
		_set_state_btns_open(_STATE_BTNS_OPEN_CANCLOSE);

		return -1;
	}

	return 0;
}


int csp_life::stop() {
	_set_state_btns_run(_STATE_BTNS_RUN_DISABLED);
	_set_state_btns_open(_STATE_BTNS_OPEN_DISABLED);
	_must_stop = true;

	return 0;
}


////////////////////////////////////////////////////////////////////////////////
// csp_life protected definitions
const char *csp_life::_DEF_CSS_FILE_NAME = "files/style.css";
const char *csp_life::_DEF_FILTER_FILE_NAME = "files/filter.txt";
const char *csp_life::_html_intro = "<html><head>"
		"<link rel=\"StyleSheet\" href=\"style.css\" type=\"text/css\">"
		"<title>Spice generated html file</title>"
		"</head><body>";
const char *csp_life::_html_outtro = "</body></html>";


BEGIN_MESSAGE_MAP(csp_life, CDialog)
	ON_WM_CLOSE()
	ON_MESSAGE(_WM_CAN_QUIT, _on_can_quit)
	ON_MESSAGE(_WM_DO_CLOSE, _on_do_close)
	ON_MESSAGE(_WM_DO_OPEN, _on_do_open)
	ON_MESSAGE(_WM_DO_CSP_FLUSH, _on_do_csp_flush)
	ON_MESSAGE(csp_list::SPM_LST_CLOSE_ME, _on_close_list)
	ON_MESSAGE(csp_filter::SPM_FLT_CLOSE_ME, _on_close_filter)
	ON_COMMAND(IDC_BTN_RUN, _on_btn_run)
	ON_COMMAND(IDC_BTN_PAUSE, _on_btn_pause)
	ON_COMMAND(IDC_BTN_BROWSE, _on_btn_browse)
	ON_COMMAND(IDC_BTN_OPEN, _on_btn_open)
	ON_COMMAND(IDC_BTN_VIEW_HTML, _on_btn_show_html)
	ON_COMMAND(IDC_BTN_WRITE_HTML, _on_btn_write_html)
	ON_COMMAND(IDC_BTN_RW_HTML, _on_btn_rw_html)
	ON_COMMAND(IDC_BTN_FILTER, _on_btn_filter)
	ON_COMMAND(IDC_BTN_SHOW_LIST, _on_btn_show_list)
	ON_COMMAND(IDC_BTN_HELP, _on_btn_help)
	ON_COMMAND(IDC_BTN_ABOUT, _on_btn_about)
	ON_COMMAND(IDC_BTN_EXIT, _on_btn_exit)
END_MESSAGE_MAP()


void csp_life::_on_btn_browse() {
	CString fname;
	_edit_file->GetWindowText(fname);
	CString filter = "Spice file (*.spf)|*.spf|All Files (*.*)|*.*||";
	CFileDialog fdlg(FALSE, ".spf", NULL,
		OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_NOTESTFILECREATE,
		filter, this, 0
	);

	if (IDOK != fdlg.DoModal()) return;

	fname = fdlg.GetPathName();
	_edit_file->SetWindowText(fname);
}


void csp_life::_on_btn_open() {
	switch (_state_btns_open) {
		case _STATE_BTNS_OPEN_CANOPEN:
			PostMessage(_WM_DO_OPEN);
			break;

		case _STATE_BTNS_OPEN_CANCLOSE:
			PostMessage(_WM_DO_CLOSE);
			break;

		default:
			show_error_msg("You are not allowed to push this button now :^)", 0, this);
	}
}


void csp_life::_on_btn_run() {
	switch(_state_btns_run) {
		case _STATE_BTNS_RUN_CANRUN:
			run();
			break;

		case _STATE_BTNS_RUN_CANSTOPR:
		case _STATE_BTNS_RUN_CANSTOPP:
			stop();
			break;

		default:
			show_error_msg("Мальчик, ты чей?", 0, this);
			break;
	}
}


void csp_life::_on_btn_pause() {
	_set_state_btns_run(_STATE_BTNS_RUN_DISABLED);

	if (_paused) {
		_set_state_btns_run(_STATE_BTNS_RUN_CANSTOPR);
		_paused = false;
	} else {
		_set_state_btns_run(_STATE_BTNS_RUN_CANSTOPP);
		_paused = true;
	}
}


void csp_life::_on_btn_show_html() {
	CString fn;
	_edit_html_file->GetWindowText(fn);
	if (0 >= fn.GetLength()) return;
	int rev = (sfx_data)ShellExecute(GetSafeHwnd(), NULL, fn, NULL, NULL, SW_SHOWNORMAL);
	if (32 > rev) {
		show_error_msg("Can't open this file (if it is a file at all)", rev, this);
	}
}


void csp_life::_on_btn_write_html() {
	if (BST_CHECKED == _btn_write_html->GetCheck())
		_set_state_btn_write_html(false);
	else
		_set_state_btn_write_html(true);

}


void csp_life::_on_btn_rw_html() {
	// flush csp file
	if (!_waiting_csp_flush) {
		_btn_rw_html->EnableWindow(FALSE);
		_waiting_csp_flush = true;
		_need_csp_flush = true;
		PostMessage(_WM_DO_CSP_FLUSH);
	}

	if (_need_csp_flush) {
		PostMessage(WM_COMMAND, IDC_BTN_RW_HTML);
		return;
	}
	_waiting_csp_flush = false;

	// try top open csp file for reading
	CString fn;
	_edit_file->GetWindowText(fn);
	HANDLE hf = CreateFile(fn, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
					   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (INVALID_HANDLE_VALUE == hf) {
		show_error_msg("Can't open file", 0, this);
		_btn_rw_html->EnableWindow(TRUE);
		return;
	}

	csp_file csp_file;
	if (0 != csp_file.use_handle(hf, true)) {
		show_error_msg("Can't use this file", 0, this);
		CloseHandle(hf);
		_btn_rw_html->EnableWindow(TRUE);
		return;
	}

	// copy css file
	_copy_css(fn);

	// disable run-time writing 
	_set_state_btn_write_html(false);
	_btn_write_html->EnableWindow(FALSE);
	_html_file_corrupted = true;

	// cut existing file
	SetFilePointer(_html_file, 0, NULL, FILE_BEGIN);
	SetEndOfFile(_html_file);
	DWORD wr;

	// write intro
	WriteFile(_html_file, _html_intro, (int)strlen(_html_intro), &wr, NULL);

	char dtgm[_DTGM_MAX_LENGTH];
	csp_file::ssp_arch *arch = csp_file.load_first_arch();
	while (NULL != arch) {
		int num = csp_file.arch_used(arch);
		for (int i = 0; i < num; ++i) {
			csp_file.load_dtgm(arch, i, dtgm);
			_parser.parse(dtgm, arch->items[i].length);
			WriteFile(_html_file, _parser.html(), _parser.html_len(), &wr, NULL);
		}
		arch = csp_file.load_next_arch(arch, true);
	}

	WriteFile(_html_file, _html_outtro, (int)strlen(_html_outtro), &wr, NULL);
	csp_file.finish_using();
	CloseHandle(hf);

	_btn_rw_html->EnableWindow(TRUE);
	_btn_write_html->EnableWindow(TRUE);
}


void csp_life::_on_btn_filter() {
	if (_csp_filter.is_visible()) _csp_filter.hide();
	else _csp_filter.show();
}


void csp_life::_on_btn_show_list() {
	// flush csp file
	if (!_waiting_csp_flush) {
		_btn_show_list->EnableWindow(FALSE);
		_btn_show_list->SetWindowText("N/A");
		_waiting_csp_flush = true;
		_need_csp_flush = true;
		PostMessage(_WM_DO_CSP_FLUSH);
	}

	if (_need_csp_flush) {
		PostMessage(WM_COMMAND, IDC_BTN_SHOW_LIST);
		return;
	}
	_waiting_csp_flush = false;

	// close list
	if (NULL != _csp_list) {
		PostMessage(csp_list::SPM_LST_CLOSE_ME);
		return;
	}

	// show list
	_list_closing = false;
	_tmp_list = new csp_list();
	_tmp_list->set_icon(_icon);
	_tmp_list->set_app_path(_app_path);
	_tmp_list->create(this);
	_tmp_list->ShowWindow(SW_SHOW);
	_tmp_list->use_csp_file(_file);
	_tmp_list->update();

	_csp_list = _tmp_list;
	_btn_show_list->SetWindowText("Hide list");
	_btn_show_list->EnableWindow(TRUE);
}


void csp_life::_on_btn_help() {
	CString fn = _app_path + "docs/help.html";
	int rev = (sfx_data)ShellExecute(GetSafeHwnd(), NULL, fn, NULL, NULL, SW_SHOWNORMAL);
	if (32 > rev) {
		show_error_msg("Can't open this file (if it is a file at all)", rev, this);
	}
}


void csp_life::_on_btn_about() {
	CString fn = _app_path + "docs/about.html";
	int rev = (sfx_data)ShellExecute(GetSafeHwnd(), NULL, fn, NULL, NULL, SW_SHOWNORMAL);
	if (32 > rev) {
		show_error_msg("Can't open this file (if it is a file at all)", rev, this);
	}
}


void csp_life::_on_btn_exit() {
	PostMessage(WM_CLOSE, 0, 0);
}


LRESULT csp_life::_on_can_quit(WPARAM pch, LPARAM hz) {
	_can_quit = true;
	PostMessage(WM_CLOSE);

	return 0;
}


LRESULT csp_life::_on_do_open(WPARAM pch, LPARAM hz) {
	if (_running) {
		stop();
		PostMessage(_WM_DO_OPEN);
		return 0;
	}

	if (_opened) {
		close_file();
		PostMessage(_WM_DO_OPEN);
		return 0;
	}

	return open_file();
}


LRESULT csp_life::_on_do_close(WPARAM pch, LPARAM hz) {
	if (_running) {
		stop();
		PostMessage(_WM_DO_CLOSE);
		return 0;
	}

	if (NULL != _csp_list) PostMessage(csp_list::SPM_LST_CLOSE_ME);
	_csp_list = NULL;
	if (NULL != _tmp_list) {
		PostMessage(_WM_DO_CLOSE);
		return 0;
	}

	return close_file();
}


LRESULT csp_life::_on_close_list(WPARAM pch, LPARAM hz) {
	if (!_list_closing) {
		_list_closing = true;
		if (!_running) _csp_list = NULL;
	}

	if (NULL != _csp_list) {
		PostMessage(csp_list::SPM_LST_CLOSE_ME);
		return 0;
	}

	_tmp_list->DestroyWindow();
	delete _tmp_list;
	_tmp_list = NULL;

	_btn_show_list->SetWindowText("Show list");
	if (_STATE_BTNS_OPTS_ENABLED == _state_btns_opts)
		_btn_show_list->EnableWindow(TRUE);

	return 0;
}


LRESULT csp_life::_on_close_filter(WPARAM pch, LPARAM hz) {
	_csp_filter.hide();

	return 0;
}


LRESULT csp_life::_on_do_csp_flush(WPARAM pch, LPARAM hz) {
	if (!_need_csp_flush) return 0;
	if (!_running) {
		_need_csp_flush = false;
		return 0;
	}
	
	PostMessage(_WM_DO_CSP_FLUSH);
	return 0;
}


void csp_life::_set_state_btns_open(const int state) {
	if (state == _state_btns_open) return;
	_state_btns_open = state;
	switch (state) {
		case _STATE_BTNS_OPEN_DISABLED:
			_btn_open->EnableWindow(FALSE);
			_btn_open->SetWindowText("N/A");
			_btn_browse->EnableWindow(FALSE);
			edit_set_readonly(_edit_file->GetSafeHwnd(), true);
			_btn_clr_file->EnableWindow(FALSE);
			_btn_cr_new_html->EnableWindow(FALSE);
			_stt_file->EnableWindow(FALSE);
			_edit_file->EnableWindow(FALSE);
			_edit_info->EnableWindow(FALSE);
			_stt_info->EnableWindow(FALSE);
			break;

		case _STATE_BTNS_OPEN_CANOPEN:
			_btn_open->EnableWindow(TRUE);
			_btn_open->SetWindowText("Open");
			_btn_browse->EnableWindow(TRUE);
			edit_set_readonly(_edit_file->GetSafeHwnd(), false);
			_btn_clr_file->EnableWindow(TRUE);
			_btn_cr_new_html->EnableWindow(TRUE);
			_stt_file->EnableWindow(TRUE);
			_edit_file->EnableWindow(TRUE);
			_edit_info->EnableWindow(FALSE);
			_stt_info->EnableWindow(FALSE);
			break;

		case _STATE_BTNS_OPEN_CANCLOSE:
			_btn_open->EnableWindow(TRUE);
			_btn_open->SetWindowText("Close");
			_btn_browse->EnableWindow(FALSE);
			edit_set_readonly(_edit_file->GetSafeHwnd(), true);
			_btn_clr_file->EnableWindow(FALSE);
			_btn_cr_new_html->EnableWindow(FALSE);
			_stt_file->EnableWindow(TRUE);
			_edit_file->EnableWindow(TRUE);
			_edit_info->EnableWindow(TRUE);
			_stt_info->EnableWindow(TRUE);
			break;

		default:
			show_error_msg("Unknown open buttons state.", 0, this);
	}
}


void csp_life::_set_state_btns_run(const int state) {
	if (state == _state_btns_run) return;
	_state_btns_run = state;
	switch (state) {
		case _STATE_BTNS_RUN_DISABLED:
			_btn_run->EnableWindow(FALSE);
			_btn_run->SetWindowText("N/A");
			_btn_pause->EnableWindow(FALSE);
			_btn_pause->SetWindowText("N/A");
			edit_set_readonly(_edit_host->GetSafeHwnd(), true);
			_edit_host->EnableWindow(FALSE);
			_stt_host->EnableWindow(FALSE);
			break;

		case _STATE_BTNS_RUN_CANRUN:
			_btn_run->EnableWindow(TRUE);
			_btn_run->SetWindowText("Run");
			_btn_pause->EnableWindow(FALSE);
			_btn_pause->SetWindowText("N/A");
			edit_set_readonly(_edit_host->GetSafeHwnd(), false);
			_edit_host->EnableWindow(TRUE);
			_stt_host->EnableWindow(TRUE);
			break;

		case _STATE_BTNS_RUN_CANSTOPR:	// running
			_btn_run->EnableWindow(TRUE);
			_btn_run->SetWindowText("Stop");
			_btn_pause->EnableWindow(TRUE);
			_btn_pause->SetWindowText("Pause");
			edit_set_readonly(_edit_host->GetSafeHwnd(), true);
			_edit_host->EnableWindow(TRUE);
			_stt_host->EnableWindow(TRUE);
			break;

		case _STATE_BTNS_RUN_CANSTOPP:	// paused
			_btn_run->EnableWindow(TRUE);
			_btn_run->SetWindowText("Stop");
			_btn_pause->EnableWindow(TRUE);
			_btn_pause->SetWindowText("Resume");
			edit_set_readonly(_edit_host->GetSafeHwnd(), true);
			_edit_host->EnableWindow(TRUE);
			_stt_host->EnableWindow(TRUE);
			break;

		default:
			show_error_msg("Unknown run buttons state.", 0, this);
	}
}


void csp_life::_set_state_btns_opts(const int state) {
	if (state == _state_btns_opts) return;
	_state_btns_opts = state;
	switch (state) {
		case _STATE_BTNS_OPTS_ENABLED:
			_btn_view_html->EnableWindow(TRUE);
			_btn_rw_html->EnableWindow(TRUE);
			_btn_show_list->EnableWindow(TRUE);
			_btn_write_html->EnableWindow(TRUE);
			_stt_html->EnableWindow(TRUE);
			break;

		case _STATE_BTNS_OPTS_DISABLED:
			_btn_view_html->EnableWindow(FALSE);
			_btn_rw_html->EnableWindow(FALSE);
			_btn_show_list->EnableWindow(FALSE);
			_btn_write_html->EnableWindow(FALSE);
			_stt_html->EnableWindow(FALSE);
			break;

		default:
			show_error_msg("Unknown options buttons state.", 0, this);
	}
}


void csp_life::_set_state_btn_write_html(const bool is_active) {
	_write_html = is_active;
	if (is_active) _btn_write_html->SetCheck(BST_CHECKED);
	else _btn_write_html->SetCheck(BST_UNCHECKED);
}


void csp_life::_show_file_info(const bool running, const bool clear) {
	if (clear) {
		_edit_info->SetWindowText("no file");
		return;
	}

	CString str;
	if (running) {
		str.Format("%u (now: %u) dtgms in %u arches",
			_csp_file.total_datagrams(),
			_total_dtgms,
			_csp_file.total_arches()
		);
	} else {
		str.Format("%u dtgms in %u arches",
			_csp_file.total_datagrams(),
			_csp_file.total_arches()
		);

	}

	_edit_info->SetWindowText(str);
}


int csp_life::_run_proc_helper(csp_life *const life) {
	life->_must_stop = false;
	life->_running = true;

	int rev = life->_run_proc();

	life->_set_state_btns_open(_STATE_BTNS_OPEN_CANCLOSE);
	life->_set_state_btns_run(_STATE_BTNS_RUN_CANRUN);
	life->_paused = false;
	life->_running = false;

	return rev;
}


int csp_life::_run_proc() {
	if (0 != _make_socket()) {
		show_error_msg("Can't create socket", 0, this);
		goto exit_level_0;
	}

	_set_state_btns_open(_STATE_BTNS_OPEN_CANCLOSE);
	_set_state_btns_run(_STATE_BTNS_RUN_CANSTOPR);

	_total_dtgms = 0;
	_show_file_info();
	while (!_must_stop) {
		if (_need_csp_flush) {	// i really don't remember for what this stuff %)
			_csp_file.flush();	// heh:) now it's only for html-rewrite function
			_need_csp_flush = false;
		}

		if (_list_closing) _csp_list = NULL;

		if (_paused) {
			Sleep(500);
			continue;
		}

		int rev = _can_read(_sock);
		if (0 == rev) continue;
		if (1 != rev) {
			show_error_msg("Can't select() from socket", 0, this);
			goto exit_level_1;
		}

		const int _total_dtgms_old = _total_dtgms;
		// read data from socket
		if (0 != _swallow(_sock)) {
			show_error_msg("Can't perform \"swallow\" action (while working with datagram)", 0, this);
			goto exit_level_1;
		}

		if (_total_dtgms_old != _total_dtgms) {
			_show_file_info();
			if (NULL != _csp_list) {
				_csp_file.flush(csp_file::FLUSH_ARCHES);
				_csp_list->update();
			}
		}
	}

exit_level_1:
	_kill_socket();

exit_level_0:
	_csp_file.flush();

	return 0;
}


int csp_life::_open_file() {
	_close_file();

	// open bin file
	CString fn;
	_edit_file->GetWindowText(fn);
	DWORD dwCreationDisposition;
	if (BST_CHECKED == _btn_clr_file->GetCheck()) dwCreationDisposition = CREATE_ALWAYS;
	else dwCreationDisposition = OPEN_ALWAYS;

	_file = CreateFile(fn, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, NULL,
					   dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
	if (INVALID_HANDLE_VALUE == _file) {
		_file = NULL;
		return -1;
	}
	if (0 != _csp_file.use_handle(_file)) {
		_close_file();
		return -1;
	}

	// open html file (funny, but it was swap in previous version :^) )
	CString sn;
	if (BST_CHECKED == _btn_cr_new_html->GetCheck()) {
		sn.Format("%s.html", fn);
		_html_file = CreateFile(sn, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, NULL,
								CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	} else {
		int n = 0;
		do {
			sn.Format("%s.%03i.html", fn, n);
			_html_file = CreateFile(sn, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, NULL,
									CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
			if (INVALID_HANDLE_VALUE == _html_file) {
				_html_file = NULL;
				++n;
			}
		} while (NULL == _html_file && n < 999);
	}
	if (NULL == _html_file) {
		_close_file();
		return -1;
	}

	_edit_html_file->SetWindowText(sn);
	DWORD wr;
	WriteFile(_html_file, _html_intro, (int)strlen(_html_intro), &wr, NULL);
	if (strlen(_html_intro) != wr) {
		show_error_msg("Can't write to html file", 0, this);
	}

	// copy css file
	if (0 != _copy_css(sn)) {
		show_error_msg("Can't copy CSS file", 0, this);
	}

	_show_file_info(false);
	_opened = true;

	return 0;
}


int csp_life::_close_file() {
	if (NULL != _file) {
		_csp_file.finish_using();
		CloseHandle(_file);
		_file = NULL;
	}
	if (NULL != _html_file) {
		DWORD wr;
		if (!_html_file_corrupted) {
			WriteFile(_html_file, _html_outtro, (int)strlen(_html_outtro), &wr, NULL);
		} else _html_file_corrupted = false;
		CloseHandle(_html_file);
		_html_file = NULL;
	}
	_edit_html_file->SetWindowText("");

	_show_file_info(false, true);
	_opened = false;

	return 0;
}


int csp_life::_copy_css(CString &html_fn) {
	char buf[MAX_PATH];
	char *fp;
	GetFullPathName(html_fn, MAX_PATH, buf, &fp);
	*fp = '\0';
	CString css_fn;
	css_fn.Format("%sstyle.css", buf);
	if (FALSE != PathFileExists(css_fn)) return 0;
	if (FALSE == CopyFile(_css_file_name, css_fn, TRUE)) return -1;

	return 0;
}


int csp_life::_make_socket() {
	_kill_socket();

	_sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
	if (INVALID_SOCKET == _sock) return -1;

	CString host;
	_edit_host->GetWindowText(host);
	cdm_addr_info ai;
	ai.set_host(host);
	if (0 != bind(_sock, ai.saddr(), ai.saddr_sz())) return -1;
	
	unsigned long arg = 1;
	if (0 != ioctlsocket(_sock, SIO_RCVALL, &arg)) return -1;

	return 0;
}


int csp_life::_kill_socket() {
	if (INVALID_SOCKET == _sock) return 0;

	if (0 != closesocket(_sock)) return -1;
	_sock = INVALID_SOCKET;

	return 0;
}


int csp_life::_can_read(const SOCKET sock, 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 csp_life::_can_read_sz(const SOCKET sock) {
	unsigned long arg;
	ioctlsocket(sock, FIONREAD, &arg);

	return arg;
}


int csp_life::_buf_ctl(const bool alloc) {
	if (alloc) {
		if (NULL != _buf) return 0;
		_buf = (char *)malloc(_NET_BUF_SZ * sizeof(char));
		if (NULL == _buf) return -1;

		return 0;
	}

	free(_buf);
	_buf = NULL;

	return 0;
}


int csp_life::_read_datagram(const SOCKET sock) {
	if (0 != _buf_ctl()) return -1;

	_saddr_sz_gived = sizeof(_saddr_gived);
	int rev = recvfrom(sock, _buf, _NET_BUF_SZ, 0, &_saddr_gived, &_saddr_sz_gived);
	if (SOCKET_ERROR == rev) return -1;
	_dtgm = _buf;
	_dtgm_sz = rev;

	return 0;
}


int csp_life::_swallow(const SOCKET sock) {
	while (0 < _can_read_sz(sock) && !_must_stop) {
		_read_datagram(sock);
		if (!_csp_filter.test((header_ip *)_dtgm)) continue;

		if (0 != _csp_file.add_dtgm(_dtgm, _dtgm_sz)) return -1;
		++_total_dtgms;

		if (_write_html) {
			if (_html_file_corrupted) {
				SetFilePointer(_html_file, 0, NULL, FILE_BEGIN);
				SetEndOfFile(_html_file);
				DWORD wr;
				WriteFile(_html_file, _html_intro, (int)strlen(_html_intro), &wr, NULL);
				_html_file_corrupted = false;
			}

			_parser.parse(_dtgm, _dtgm_sz);
			DWORD wr;
			WriteFile(_html_file, _parser.html(), _parser.html_len(), &wr, NULL);
		}
	}

	return 0;
}


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