
Добавил:
korayakov
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабы / 2 / lab.03.by mice / claw / client
.cpp/*******************************************************************************
* file: client.cpp *
* version: 0.0.1 *
* author: d-evil [tmd] (mailto:d-evil.tmd@mail.ru) *
* description: not available *
*******************************************************************************/
#include "client.h"
////////////////////////////////////////////////////////////////////////////////
// ccw_server public definition
ccw_client::ccw_client() {
_is_sender = true;
_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;
_total_sz = -1;
_done_sz = -1;
}
ccw_client::~ccw_client() {
ReleaseMutex(_run_mtx);
ReleaseMutex(_pause_mtx);
}
int ccw_client::change_mode(const bool is_sender) {
if (NULL != GetSafeHwnd()) return -1;
_is_sender = is_sender;
return 0;
}
int ccw_client::set_caption() {
CString cap;
if (NULL != _parent) {
_parent->GetWindowText(cap);
} else cap = "Claw /root";
CString name;
if (_is_sender) name = "senders";
else name = "receivers";
if (_sock.is_connected()) {
name.AppendFormat("/%s:%s", _sock.iaddr()->host(), _sock.iaddr()->port_str());
}
cap.AppendFormat("/%s", name);
SetWindowText(cap);
return 0;
}
int ccw_client::update_recver() {
if (NULL == GetSafeHwnd() || _is_sender) return -1;
_edit_host->SetWindowText(_sock.iaddr()->host());
_edit_ip->SetWindowText(_sock.iaddr()->ip_str());
_edit_port->SetWindowText(_sock.iaddr()->port_str());
set_caption();
return 0;
}
int ccw_client::give_life() {
Create(IDD_DLG_CLIENT, _parent);
ShowWindow(SW_SHOW);
return 0;
}
int ccw_client::take_life() {
return 0;
}
BOOL ccw_client::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_file = (CEdit *)GetDlgItem(IDC_EDIT_FILE);
_edit_size = (CEdit *)GetDlgItem(IDC_EDIT_SIZE);
_edit_status = (CEdit *)GetDlgItem(IDC_EDIT_STATUS);
_edit_time = (CEdit *)GetDlgItem(IDC_EDIT_TIME);
_progress_bar = (CProgressCtrl *)GetDlgItem(IDC_BAR);
_btn_browse = (CButton *)GetDlgItem(IDC_BTN_BROWSE);
_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_client::OnClose() {
if (!_stoped) stop();
if (WAIT_TIMEOUT == WaitForSingleObject(_run_mtx, 100)) {
PostMessage(WM_CLOSE, 0, 0);
return;
}
if (NULL != _parent) {
_parent->PostMessage(MSG_DEL_CLIENT, _claw_id, 0);
} else {
EndDialog(0);
delete this; // guess it will not work :)
}
}
int ccw_client::run() {
_thread_h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_client_proc_helper, this, 0, &_thread_id);
if (NULL == _thread_h) return -1;
return 0;
}
int ccw_client::stop() {
_stoped = true;
if (_paused) upause();
return 0;
}
int ccw_client::pause() {
_set_pbtn_state(0);
if (WAIT_TIMEOUT == WaitForSingleObject(_pause_mtx, 5000)) return -1;
_paused = true;
return 0;
}
int ccw_client::upause() {
_set_pbtn_state(0);
_paused = false;
ReleaseMutex(_pause_mtx);
return 0;
}
int ccw_client::wait(const int timeout) {
if (WAIT_TIMEOUT == WaitForSingleObject(_run_mtx, timeout))
return -1;
return 0;
}
int ccw_client::recv_header() {
if (_is_sender || !_sock.is_connected()) return -1;
clock_t t1 = clock();
clock_t t2;
do {
t2 = clock();
if (0 > _sock.CanRead()) continue;
int rev = _sock.Receive((char *)&_total_sz, sizeof(_total_sz));
if (sizeof(_total_sz) != rev) return -1;
CString str;
size_to_str(_total_sz, str);
_edit_size->SetWindowText(str);
return 0;
} while (t2 - t1 < READ_SZ_TIMEOUT*CLOCKS_PER_SEC);
return -1;
}
ccw_client *ccw_client::mk_client(const int claw_id, const bool is_sender) {
ccw_client *clnt = new ccw_client;
clnt->set_claw_id(claw_id);
clnt->_is_sender = is_sender;
return clnt;
}
int ccw_client::rm_client(ccw_client *const clnt) {
if (NULL == clnt) return -1;
delete clnt;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// ccw_server protected definition
BEGIN_MESSAGE_MAP(ccw_client, CDialog)
ON_WM_CLOSE()
ON_COMMAND(IDC_BTN_BROWSE, _on_btn_browse)
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_client::_on_btn_browse() {
if (_is_sender) _sender_browse();
else _recver_browse();
}
void ccw_client::_on_btn_run() {
switch (_run_btn_state) {
case 1: run(); break;
case 2: stop(); break;
default: break;
}
}
void ccw_client::_on_btn_pause() {
switch (_pause_btn_state) {
case 1: pause(); break;
case 2: upause(); break;
default: break;
}
}
void ccw_client::_on_btn_exit() {
PostMessage(WM_CLOSE, 0, 0);
}
void ccw_client::_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_size->SetWindowText("none");
_edit_status->SetWindowText("none");
_edit_time->SetWindowText("--:--:--");
if (_is_sender) _ulock_edits();
else _lock_edits();
_set_rbtn_state(1);
_set_pbtn_state(0);
set_caption();
}
void ccw_client::_lock_edits() {
_edit_host->PostMessage(EM_SETREADONLY, TRUE, 0);
_edit_port->PostMessage(EM_SETREADONLY, TRUE, 0);
}
void ccw_client::_ulock_edits() {
_edit_host->PostMessage(EM_SETREADONLY, FALSE, 0);
_edit_port->PostMessage(EM_SETREADONLY, FALSE, 0);
}
void ccw_client::_lock_file_edit() {
_edit_file->PostMessage(EM_SETREADONLY, TRUE, 0);
_btn_browse->EnableWindow(FALSE);
SetFocus();
}
void ccw_client::_ulock_file_edit() {
_edit_file->PostMessage(EM_SETREADONLY, FALSE, 0);
_btn_browse->EnableWindow(TRUE);
}
void ccw_client::_set_rbtn_state(const int st) {
if (st == _run_btn_state) return;
_run_btn_state = st;
switch (st) {
case 1:
if (_is_sender) _btn_run->SetWindowText("Send");
else _btn_run->SetWindowText("Accept");
_btn_run->EnableWindow(TRUE);
break;
case 2:
_btn_run->SetWindowText("Cancel");
_btn_run->EnableWindow(TRUE);
break;
default:
_btn_run->SetWindowText("N/A");
_btn_run->EnableWindow(FALSE);
SetFocus();
break;
}
}
void ccw_client::_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;
}
}
void ccw_client::_sender_browse() {
CString fname;
_edit_file->GetWindowText(fname);
CString filter = "All Files (*.*)|*.*|Text files (*.txt;*.doc;*.rtf;*.inf)|*.txt;*.doc;*.rtf;*.inf|Applications (*.exe;*.com;*.bat)|*.exe;*.com;*.bat|Images (*.bmp;*.jpeg;*.jpg;*.gif;*.psd)|*.bmp;*.jpeg;*.jpg;*.gif;*.psd||";
CFileDialog fdlg(TRUE, NULL, fname,
OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_NOTESTFILECREATE,
filter, this, 0
);
if (IDOK == fdlg.DoModal()) {
fname = fdlg.GetPathName();
_edit_file->SetWindowText(fname);
HANDLE hf = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hf) {
DWORD sz = GetFileSize(hf, NULL);
CloseHandle(hf);
size_to_str(sz, fname);
_edit_size->SetWindowText(fname);
} else _edit_size->SetWindowText("none");
}
}
void ccw_client::_recver_browse() {
CString fname;
_edit_file->GetWindowText(fname);
CString filter = "All Files (*.*)|*.*|Text files (*.txt;*.doc;*.rtf;*.inf)|*.txt;*.doc;*.rtf;*.inf|Applications (*.exe;*.com;*.bat)|*.exe;*.com;*.bat|Images (*.bmp;*.jpeg;*.jpg;*.gif;*.psd)|*.bmp;*.jpeg;*.jpg;*.gif;*.psd||";
CFileDialog fdlg(FALSE, NULL, fname,
OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_NOTESTFILECREATE,
filter, this, 0
);
if (IDOK != fdlg.DoModal()) return;
fname = fdlg.GetPathName();
_edit_file->SetWindowText(fname);
}
int ccw_client::_sender_proc() {
_stoped = false;
_progress_bar->SetPos(0);
_edit_time->SetWindowText("00:00:00");
if (WAIT_TIMEOUT == WaitForSingleObject(_run_mtx, 10000)) {
show_error_msg("Can't launch sender (скорее всего уже и не получится:)", 0, this);
_edit_status->SetWindowText("stoped via error.");
return -1;
}
// [entering level 0] (lock controls, gather info and try to open file)
_edit_status->SetWindowText("gathering information...");
_lock_edits();
_lock_file_edit();
_set_rbtn_state(0);
_set_pbtn_state(0);
CString host;
_edit_host->GetWindowText(host);
CString port_str;
_edit_port->GetWindowText(port_str);
unsigned short port = atoi(port_str);
CString fname;
_edit_file->GetWindowText(fname);
_edit_status->SetWindowText("opening file...");
HANDLE hf = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hf) {
show_error_msg("Can't open file for reading", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_0;
}
_total_sz = GetFileSize(hf, NULL);
_done_sz = 0;
// [entering level 1] (resolve host and create socket)
_edit_status->SetWindowText("resolving host...");
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_1;
}
_edit_host->SetWindowText(_sock.iaddr()->host());
_edit_port->SetWindowText(_sock.iaddr()->port_str());
_edit_ip->SetWindowText(_sock.iaddr()->ip_str());
if (0 != _sock.Create()) {
show_error_msg("Can't create socket", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_1;
}
// [entering level 2] (try to connect and allocate buffer)
_edit_status->SetWindowText("connecting...");
if (0 != _sock.Connect()) {
show_error_msg("Can't establish connection", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_2;
}
_edit_status->SetWindowText("allocating buffer...");
char *buf = (char *)malloc(SOCK_IO_BUF_SZ * sizeof(char));
if (NULL == buf) {
show_error_msg("Can't allocate buffer (no memory)", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_2;
}
// [entering level 3] (sending loop)
_set_rbtn_state(2);
_set_pbtn_state(1);
set_caption();
_edit_status->SetWindowText("sending...");
clock_t t_base = clock();
clock_t up_time = 0;
// send file size
_sock.Send((char *)&_total_sz, sizeof(_total_sz));
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("sending...");
t_base = clock() - tmp_clock;
}
int rev = _sock.CanWrite();
if (0 > rev) {
show_error_msg("Can't select() socket for writing", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_2;
}
if (0 >= rev) continue;
DWORD dwr;
if (0 == ReadFile(hf, buf, SOCK_IO_BUF_SZ, &dwr, NULL)) {
show_error_msg("Can't read from opened file", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_3;
}
if (0 == dwr) {
show_error_msg("Error reading file", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_3;
}
rev = _sock.Send(buf, dwr);
if (rev != dwr) {
show_error_msg("Can't send data", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_3;
}
_done_sz += dwr;
if (_done_sz == _total_sz) {
_progress_bar->SetPos(100);
_edit_status->SetWindowText("done.");
goto exit_level_3;
}
if (_done_sz > _total_sz) {
show_error_msg("Wrong file size - streams not supported in free version", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_3;
}
double pos = 100*(double)_done_sz / (double)_total_sz;
_progress_bar->SetPos((int)ceil(pos));
}
if (_stoped) _edit_status->SetWindowText("stoped via user.");
exit_level_3:
free(buf);
exit_level_2:
_sock.Close();
exit_level_1:
CloseHandle(hf);
exit_level_0:
_ulock_edits();
_ulock_file_edit();
_set_rbtn_state(1);
_set_pbtn_state(0);
set_caption();
ReleaseMutex(_run_mtx);
_stoped = true;
return 0;
}
int ccw_client::_recver_proc() {
_stoped = false;
_progress_bar->SetPos(0);
_edit_time->SetWindowText("00:00:00");
bool no_way_back = false;
if (WAIT_TIMEOUT == WaitForSingleObject(_run_mtx, 10000)) {
show_error_msg("Can't launch receiver (скорее всего уже и не получится:)", 0, this);
_edit_status->SetWindowText("stoped via error.");
return -1;
}
// [entering level 0] (lock controls and try to open file for writing)
// setting buttons and edits
_edit_status->SetWindowText("opening file...");
_lock_edits();
_lock_file_edit();
_set_rbtn_state(0);
_set_pbtn_state(0);
CString fname;
_edit_file->GetWindowText(fname);
HANDLE hf = CreateFile(fname, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hf) {
show_error_msg("Can't open file for writing", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_0;
}
// [entering level 1] (allocating buffer)
_edit_status->SetWindowText("allocating buffer...");
char *buf = (char *)malloc(SOCK_IO_BUF_SZ * sizeof(char));
if (NULL == buf) {
show_error_msg("Can't get memory for read buffer", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_1;
}
// [entering level 2] (startint recving)
_edit_status->SetWindowText("receiving...");
_set_rbtn_state(2);
_set_pbtn_state(1);
_done_sz = 0;
while (0 > _total_sz) Sleep(200);
clock_t t_base = clock();
clock_t up_time = 0;
no_way_back = true;
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("receiving...");
t_base = clock() - tmp_clock;
}
int rev = _sock.CanRead();
if (0 > rev) {
show_error_msg("Can't select() socket for reading", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_2;
}
if (0 >= rev) continue;
rev = _sock.Receive(buf, SOCK_IO_BUF_SZ);
if (0 >= rev) {
show_error_msg("Can't receive anymore", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_2;
}
DWORD bwr;
int wres = WriteFile(hf, buf, rev, &bwr, NULL);
if (0 == wres || bwr != rev) {
show_error_msg("Can't write to file", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_2;
}
_done_sz += rev;
if (_done_sz > _total_sz) {
show_error_msg("Wrong file size - streams not supported in free version", 0, this);
_edit_status->SetWindowText("stoped via error.");
goto exit_level_2;
}
if (_done_sz == _total_sz) {
_progress_bar->SetPos(100);
_edit_status->SetWindowText("done.");
goto exit_level_2;
}
double pos = 100*(double)_done_sz / (double)_total_sz;
_progress_bar->SetPos((int)ceil(pos));
}
if (_stoped) _edit_status->SetWindowText("stoped via user.");
exit_level_2:
free(buf);
_done_sz = -1;
_total_sz = -1;
exit_level_1:
CloseHandle(hf);
exit_level_0:
if (no_way_back) {
_set_rbtn_state(0);
_set_pbtn_state(0);
_sock.Close();
} else {
_set_rbtn_state(1);
_set_pbtn_state(0);
_ulock_file_edit();
}
ReleaseMutex(_run_mtx);
_stoped = true;
return 0;
}
Соседние файлы в папке claw