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

Лабы / 2 / lab.03.by mice / claw / server

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

#include "server.h"


////////////////////////////////////////////////////////////////////////////////
// ccw_server public definition
ccw_server::ccw_server() {
	_parent = NULL;
	_hicon = NULL;
	_run_mtx = CreateMutex(NULL, 0, NULL);
	_pause_mtx = CreateMutex(NULL, 0, NULL);
	_thread_h = NULL;
	_thread_id = 0;
	_stoped = false;
	_paused = false;
	_run_btn_state = -1;
	_pause_btn_state = -1;
	_claw_id = 0;
}


ccw_server::~ccw_server() {
	ReleaseMutex(_run_mtx);
	ReleaseMutex(_pause_mtx);
}


int ccw_server::set_caption() {
	CString str;
	if (NULL != _parent) _parent->GetWindowText(str);
	else str = "Claw /root";
	str.Append("/servers");

	if (_sock.is_binded()) {
		str.AppendFormat("/%s:%s", _sock.iaddr()->host(), _sock.iaddr()->port_str());
	}

	SetWindowText(str);

	return 0;
}


int ccw_server::give_life() {
	Create(IDD_DLG_SERVER, _parent);
	ShowWindow(SW_SHOW);

	return 0;
}


int ccw_server::take_life() {
	stop();

	return 0;
}


BOOL ccw_server::OnInitDialog() {
	if (NULL !=_hicon) SetIcon(_hicon, FALSE);

	_edit_host = (CEdit *)GetDlgItem(IDC_EDIT_HOST);
	_edit_ip = (CEdit *)GetDlgItem(IDC_EDIT_IP);
	_edit_port = (CEdit *)GetDlgItem(IDC_EDIT_PORT);
	_edit_status = (CEdit *)GetDlgItem(IDC_EDIT_STATUS);
	_edit_time = (CEdit *)GetDlgItem(IDC_EDIT_TIME);

	_btn_run = (CButton *)GetDlgItem(IDC_BTN_RUN);
	_btn_pause = (CButton *)GetDlgItem(IDC_BTN_PAUSE);
	_btn_exit = (CButton *)GetDlgItem(IDC_BTN_EXIT);
	
	_init_controls();

	return TRUE;
}


void ccw_server::OnClose() {
	if (!_stoped) stop();

	if (WAIT_TIMEOUT == WaitForSingleObject(_run_mtx, 100)) {
		PostMessage(WM_CLOSE, 0, 0);
		return;
	}

	if (NULL != _parent) {
		_parent->PostMessage(MSG_DEL_SERVER, _claw_id, 0);
	} else {
		EndDialog(0);
		delete this;	// guess it will not work :)
	}
}


int ccw_server::run() {
	_thread_h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_serv_proc_helper, this, 0, &_thread_id);
	if (NULL == _thread_h) return -1;

	return 0;
}


int ccw_server::stop() {
	if (_paused) upause();
	_stoped = true;

	return 0;
}


int ccw_server::pause() {
	_set_pbtn_state(0);
	if (WAIT_TIMEOUT == WaitForSingleObject(_pause_mtx, 5000)) return -1;
	_paused = true;

	return 0;
}


int ccw_server::upause() {
	_set_pbtn_state(0);
	_paused = false;
	ReleaseMutex(_pause_mtx);

	return 0;
}


int ccw_server::wait(const int timeout) {
	if (WAIT_TIMEOUT == WaitForSingleObject(_run_mtx, timeout))
		return -1;

	return 0;
}



////////////////////////////////////////////////////////////////////////////////
// ccw_server protected definition
BEGIN_MESSAGE_MAP(ccw_server, CDialog)
	ON_WM_CLOSE()
	ON_COMMAND(IDC_BTN_RUN, _on_btn_run)
	ON_COMMAND(IDC_BTN_PAUSE, _on_btn_pause)
	ON_COMMAND(IDC_BTN_EXIT, _on_btn_exit)
END_MESSAGE_MAP()


void ccw_server::_on_btn_run() {
	switch (_run_btn_state) {
		case 1: run(); break;
		case 2: stop(); break;
		default: break;
	}
}


void ccw_server::_on_btn_pause() {
	switch (_pause_btn_state) {
		case 1: pause(); break;
		case 2: upause(); break;
		default: break;
	}
}


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


void ccw_server::_init_controls() {
	if (0 != _sock.iaddr()->set_to_local()) {
		show_error_msg("Can't set local address", 0, this);
	}

	_edit_host->SetWindowText(_sock.iaddr()->host());
	_edit_ip->SetWindowText(_sock.iaddr()->ip_str());
	_edit_port->SetWindowText(_sock.iaddr()->port_str());

	_edit_status->SetWindowText("none");
	_edit_time->SetWindowText("--:--:--");

	_set_rbtn_state(1);
	_set_pbtn_state(0);

	set_caption();
}


void ccw_server::_lock_edits() {
	_edit_host->PostMessage(EM_SETREADONLY, TRUE, 0);
	_edit_port->PostMessage(EM_SETREADONLY, TRUE, 0);
}


void ccw_server::_ulock_edits() {
	_edit_host->PostMessage(EM_SETREADONLY, FALSE, 0);
	_edit_port->PostMessage(EM_SETREADONLY, FALSE, 0);
}


void ccw_server::_set_rbtn_state(const int st) {
	if (st == _run_btn_state) return;
	_run_btn_state = st;

	switch (st) {
		case 1:
			_btn_run->SetWindowText("Run");
			_btn_run->EnableWindow(TRUE);
			break;

		case 2:
			_btn_run->SetWindowText("Stop");
			_btn_run->EnableWindow(TRUE);
			break;

		default:
			_btn_run->SetWindowText("N/A");
			_btn_run->EnableWindow(FALSE);
			SetFocus();
			break;
	}
}


void ccw_server::_set_pbtn_state(const int st) {
	if (st == _pause_btn_state) return;
	_pause_btn_state = st;

	switch (st) {
		case 1:
			_btn_pause->SetWindowText("Pause");
			_btn_pause->EnableWindow(TRUE);
			break;

		case 2:
			_btn_pause->SetWindowText("Resume");
			_btn_pause->EnableWindow(TRUE);
			break;

		default:
			_btn_pause->SetWindowText("N/A");
			_btn_pause->EnableWindow(FALSE);
			SetFocus();
			break;
	}
}


int ccw_server::_serv_proc() {
	_stoped = false;
	_edit_time->SetWindowText("00:00:00");
	if (WAIT_TIMEOUT == WaitForSingleObject(_run_mtx, 10000)) {
		show_error_msg("Can't launch server (скорее всего уже и не получится:)", 0, this);
		return -1;
	}

	// [entering level 0] (lock controls and try to init CSocket object)
	_edit_status->SetWindowText("gethering information...");
	// setting buttons and edits
	_lock_edits();
	_set_rbtn_state(0);
	_set_pbtn_state(0);

	// getting address info
	CString host;
	_edit_host->GetWindowText(host);
	CString port_str;
	_edit_port->GetWindowText(port_str);
	unsigned short port = atoi(port_str);

	if (0 != _sock.iaddr()->set(host, port)) {
		show_error_msg("Can't resolve host", 0, this);
		_edit_status->SetWindowText("stoped via error.");
		goto exit_level_0;
	}

	_edit_host->SetWindowText(_sock.iaddr()->host());
	_edit_port->SetWindowText(_sock.iaddr()->port_str());
	_edit_ip->SetWindowText(_sock.iaddr()->ip_str());

	// [entering level 1] (create, bind socket and put it in listen state)
	_edit_status->SetWindowText("creating socket...");
	// creating and binding socket
	if (0 != _sock.Create()) {
		show_error_msg("Can't create socket", 0, this);
		_edit_status->SetWindowText("stoped via error.");
		goto exit_level_1;
	}
	if (0 != _sock.Bind()) {
		show_error_msg("Can't bind socket", 0, this);
		_edit_status->SetWindowText("stoped via error.");
		goto exit_level_1;
	}
	set_caption();

	if (0 != _sock.Listen()) {
		show_error_msg("Can't put socket in listen state", 0, this);
		_edit_status->SetWindowText("stoped via error.");
		goto exit_level_1;
	}

	// [entering level 2] (listen loop)
	_edit_status->SetWindowText("listening...");
	// listen loop
	_set_rbtn_state(2);
	_set_pbtn_state(1);

	clock_t t_base = clock();
	clock_t up_time = 0;

	while (!_stoped) {
		clock_t tmp_clock = clock() - t_base;
		if (CLOCKS_PER_SEC/3 < tmp_clock - up_time) {
			CString str;
			clock_to_str(tmp_clock, str);
			_edit_time->SetWindowText(str);
			up_time = tmp_clock;
		}

		if (_paused) {
			_edit_status->SetWindowText("paused.");
			_set_pbtn_state(2);
			WaitForSingleObject(_pause_mtx, INFINITE);
			ReleaseMutex(_pause_mtx);
			_set_pbtn_state(1);
			_edit_status->SetWindowText("listening...");
			t_base = clock() - tmp_clock;
		}

		int rev = _sock.CanRead();
		if (0 == rev) continue;
		if (0 > rev) {
			show_error_msg("Can't select() socket", 0, this);
			_edit_status->SetWindowText("stoped via error.");
			goto exit_level_2;
		}

		// begin acception
		ccw_client *clnt;
		if (0 != _parent->SendMessage(MSG_ADD_RECVER, (WPARAM)&clnt, 0)) {
			show_error_msg("Can't create recver (памяти имхо мало)", 0, this);
			continue;
		}

		if (0 != _sock.Accept( *(clnt->sock()) )) {
			show_error_msg("Can't accept connection", 0, this);
			_parent->PostMessage(ccw_client::MSG_DEL_CLIENT, clnt->get_claw_id(), 0);
			continue;
		}

		if (0 != clnt->recv_header()) {
			show_error_msg("Can't get header info", 0, this);
			_parent->PostMessage(ccw_client::MSG_DEL_CLIENT, clnt->get_claw_id(), 0);
			continue;
		}

		if (0 != clnt->update_recver()) {
			show_error_msg("Can't update receiver info", 0, this);
			continue;
		}
	}
	_edit_status->SetWindowText("stoped via user.");

exit_level_2:
	// dummy now

exit_level_1:
	if (0 != _sock.Close()) {
		show_error_msg("Can't close socket", 0, this);
	}
	set_caption();

exit_level_0:
	_ulock_edits();
	_set_rbtn_state(1);
	_set_pbtn_state(0);
	ReleaseMutex(_run_mtx);
	_stoped = true;

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