Добавил:
korayakov
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабы / 2 / lab.03.by mice / claw / server
.cpp/*******************************************************************************
* 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;
}