📄 hsmsd_cnx_proxy.cpp
字号:
/* * (c) Copyright 2008 Philipp Skadorov (philipp_s@users.sourceforge.net) * * This file is part of FREESECS. * * FREESECS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FREESECS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with FREESECS, see COPYING. * If not, see <http://www.gnu.org/licenses/>. */#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include "tsqueue.h"#include "log.h"#include "hsmsd_interface.h"#include "hsmsd_cnx_proxy.h"#define CNX_PROXY_LOG_LEVEL 1000using namespace freesecs;template<typename handler_t>int set_handler(handler_t &old_h, handler_t &new_h){ int r = 0; if(old_h != NULL && new_h != NULL) { r = EPERM; } else if(old_h == new_h) { r = EALREADY; } else { old_h = new_h; } return r;}hsmsd_proxy_t::pump_events_to_client_t hsmsd_proxy_t::client_event_pump;hsmsd_proxy_t::hsmsd_proxy_t(const char *cnx_name):_cnx_name(cnx_name),_fd_ctl_in(0),_fd_ctl_out(0),_fd_data_in(0),_fd_data_out(0),_rstate(0),_msg_h(NULL),_cnx_state_h(NULL),_cnx_error_h(NULL){ int reg_fd, rsp_fd; ssize_t req_sz, rsp_sz; hsmsd_register_req_t register_req; hsmsd_register_rsp_t register_rsp; if(-1 == (reg_fd = ::open(HSMSD_REGISTER_FIFO_IN, O_RDWR))) { throw; } if(-1 == (rsp_fd = ::open(HSMSD_REGISTER_FIFO_OUT, O_RDWR))) { throw; } strncpy(register_req.cnx_name, cnx_name, HSMS_NAME_MAX_LEN); register_req.cli_pid = getpid(); req_sz = sizeof(register_req); if(req_sz != write(reg_fd, ®ister_req, req_sz)) { throw; } rsp_sz = sizeof(register_rsp); if(rsp_sz != read(rsp_fd, ®ister_rsp, rsp_sz)) { throw; } if(hsmsd_register_rsp_t::REG_OK != register_rsp.rsp_code) { TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, "HSMSCLI: register rsp: %d\n", register_rsp.rsp_code); throw; } close(reg_fd); close(rsp_fd); TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, "HSMSCLI: cnx %s : user pipes: %s, %s, %s, %s\n", cnx_name, register_rsp.pipe_name_ctl_req, register_rsp.pipe_name_ctl_rsp, register_rsp.pipe_name_data_req, register_rsp.pipe_name_data_rsp); if(-1 == (_fd_ctl_out = open(register_rsp.pipe_name_ctl_req, O_RDWR))) { throw; } if(-1 == (_fd_ctl_in = open(register_rsp.pipe_name_ctl_rsp, O_RDWR))) { throw; } if(-1 == (_fd_data_out = open(register_rsp.pipe_name_data_req, O_RDWR))) { throw; } if(-1 == (_fd_data_in = open(register_rsp.pipe_name_data_rsp, O_RDWR))) { throw; } for(int i=0; i < hsmsd_server_rsp_t::MAX_RSP_TYPE; ++i) { if(0 != sem_init(&_rsp_sem_pool[i], 0, 0)) { throw; } } std::string pipe_name = _cnx_name; pipe_name += " ctrl"; _ctl_ar = new async_reception_t(_fd_ctl_in, pipe_name.c_str()); pipe_name = _cnx_name; pipe_name += " data"; _data_ar = new async_reception_t(_fd_data_in, pipe_name.c_str()); _ctl_ar->data_recvd_signal.add_handler(this, &hsmsd_proxy_t::ctrl_rcvd_handler); _ctl_ar->recv_error_signal.add_handler(this, &hsmsd_proxy_t::rcv_error_handler); _data_ar->data_recvd_signal.add_handler(this, &hsmsd_proxy_t::data_rcvd_handler); _data_ar->recv_error_signal.add_handler(this, &hsmsd_proxy_t::rcv_error_handler); _ctl_ar->start_recv(&_srv_ctl_msg, sizeof(_srv_ctl_msg)); _data_ar->start_recv(&_srv_data_msg, sizeof(_srv_data_msg));}hsmsd_proxy_t::~hsmsd_proxy_t(){ _ctl_ar->stop_recv(); _data_ar->stop_recv(); close(_fd_ctl_in); close(_fd_ctl_out); close(_fd_data_in); close(_fd_data_out); for(size_t i=0; i < sizeof(_rsp_sem_pool); ++i) { sem_destroy(&_rsp_sem_pool[i]); }}int hsmsd_proxy_t::set_msg_handler(hsmsd_msg_handler_t new_h){ return set_handler(_msg_h, new_h);}int hsmsd_proxy_t::set_cnx_state_handler(hsmsd_cnx_state_handler_t new_h){ return set_handler(_cnx_state_h, new_h);}int hsmsd_proxy_t::set_cnx_error_handler(hsmsd_cnx_error_handler_t new_h){ return set_handler(_cnx_error_h, new_h);}int hsmsd_proxy_t::start(){ int r = 0; size_t len; hsmsd_client_req_t req; req.type = hsmsd_client_req_t::CNX_START; len = write(_fd_ctl_out, &req, sizeof(req)); if(sizeof(req) == len) { TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, "HSMSCLI: cnx %s : sent cnx start, " "waiting for reply...\n", _cnx_name.c_str()); sem_wait(&_rsp_sem_pool[hsmsd_server_rsp_t::CNX_START]); r = _srv_msg_pool[hsmsd_server_rsp_t::CNX_START].u.req_status; TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, "HSMSCLI: cnx %s : sent " "cnx start reply: %d\n", _cnx_name.c_str(), r); } else { r = errno; } return r;}int hsmsd_proxy_t::stop(){ int r = 0; size_t len; hsmsd_client_req_t req; req.type = hsmsd_client_req_t::CNX_STOP; len = write(_fd_ctl_out, &req, sizeof(req)); if(sizeof(req) == len) { sem_wait(&_rsp_sem_pool[hsmsd_server_rsp_t::CNX_STOP]); r = _srv_msg_pool[hsmsd_server_rsp_t::CNX_STOP].u.req_status; } else { r = errno; } return r;}int hsmsd_proxy_t::get_state(hsmsd_cnx_state_t* state){ int r = 0; size_t len; hsmsd_client_req_t req; req.type = hsmsd_client_req_t::CNX_STATE; len = write(_fd_ctl_out, &req, sizeof(req)); if(sizeof(req) == len) { sem_wait(&_rsp_sem_pool[hsmsd_server_rsp_t::CNX_STATE_RSP]); *state = (hsmsd_cnx_state_t)_srv_msg_pool[hsmsd_server_rsp_t::CNX_STATE_RSP].u.cnx_state; } else { r = errno; } return r;}int hsmsd_proxy_t::send_msg(hsmsd_msg_t* msg){ int r = 0; ssize_t len; hsmsd_client_req_t *req; len = sizeof(hsmsd_client_req_t) + msg->data_len; char *pmem = (char*)malloc(len); memset(pmem, 0, sizeof(len)); if(msg->data_len) { memcpy(pmem + sizeof(hsmsd_client_req_t), msg->data, msg->data_len); } req = (hsmsd_client_req_t*)pmem; req->type = hsmsd_client_req_t::MSG_SEND; req->u.msg_header.stream = msg->stream; req->u.msg_header.function = msg->function; req->u.msg_header.wbit = msg->wbit; req->u.msg_header.sysbytes = msg->sysbytes; req->u.msg_header.data_len = msg->data_len; if(len != (r = write(_fd_data_out, pmem, len))) { r = errno; } else { sem_wait(&_rsp_sem_pool[hsmsd_server_rsp_t::MSG_SEND]); r = _srv_msg_pool[hsmsd_server_rsp_t::MSG_SEND].u.req_status; } free(pmem); return r;}int hsmsd_proxy_t::ctrl_rcvd_handler(const size_t &size){ size_t len = sizeof(_srv_ctl_msg); if(size != len && _cnx_error_h) { //_cnx_error_h(-3); client_event_pump << new error_event_t(_cnx_error_h, -3); } _srv_msg_pool[_srv_ctl_msg.type] = _srv_ctl_msg; sem_post(&_rsp_sem_pool[_srv_ctl_msg.type]); /*fire rsp type-specific handlers!*/ if(hsmsd_server_rsp_t::CNX_STATE_EVT == _srv_ctl_msg.type && _cnx_state_h) { //_cnx_state_h((hsmsd_cnx_state_t)_srv_ctl_msg.u.cnx_state); client_event_pump << new state_event_t(_cnx_state_h, (hsmsd_cnx_state_t)_srv_ctl_msg.u.cnx_state); } else if(hsmsd_server_rsp_t::CNX_ERROR_EVT == _srv_ctl_msg.type && _cnx_error_h) { //_cnx_error_h(_srv_ctl_msg.u.cnx_error); client_event_pump << new error_event_t(_cnx_error_h, _srv_ctl_msg.u.cnx_error); } _ctl_ar->start_recv(&_srv_ctl_msg, len); return 0;}int hsmsd_proxy_t::data_rcvd_handler(const size_t &size){ hsmsd_msg_t *pmsg; void *pbuf = &_srv_data_msg; size_t len = sizeof(_srv_data_msg); TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, "HSMSCLI: server data response: " "type=%d, req status=%d, " "error=%d, cnx state=%d", _srv_data_msg.type, _srv_data_msg.u.req_status, _srv_data_msg.u.cnx_error, _srv_data_msg.u.cnx_state); switch(_rstate) { case 0: TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, "HSMSCLI: receiving data: status=%d, "\ "msg size=%d, expected size=%d", _rstate, size, len); if(size == len && hsmsd_server_rsp_t::MSG_RECV == _srv_data_msg.type) { //_msg_data.clear(); _msg_data.resize(_srv_data_msg.u.msg_header.data_len, 0); _rstate = 1; pbuf = &_msg_data[0]; len = _srv_data_msg.u.msg_header.data_len; } else if(size == len && hsmsd_server_rsp_t::MSG_SEND == _srv_data_msg.type) { _srv_msg_pool[_srv_data_msg.type] = _srv_data_msg; sem_post(&_rsp_sem_pool[_srv_data_msg.type]); _rstate = 0; } else if(_cnx_error_h) { //_cnx_error_h(-3); client_event_pump << new error_event_t(_cnx_error_h, -3); } break; case 1: TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, "HSMSCLI: receiving status=%d, " "msg size=%d, expected size=%d/%d", _rstate, size, _msg_data.size(), _srv_data_msg.u.msg_header.data_len); if(size == _msg_data.size() && size == _srv_data_msg.u.msg_header.data_len) { if(_msg_h) { pmsg = (hsmsd_msg_t*)malloc(sizeof(hsmsd_msg_t) + size - 1); pmsg->stream = _srv_data_msg.u.msg_header.stream; pmsg->function = _srv_data_msg.u.msg_header.function; pmsg->wbit = _srv_data_msg.u.msg_header.wbit; pmsg->sysbytes = _srv_data_msg.u.msg_header.sysbytes; pmsg->data_len = size; memcpy(&pmsg->data[0], &_msg_data[0], size); TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, "HSMSCLI: s%df%d(0x%x) received from server" , pmsg->stream, pmsg->function , pmsg->sysbytes); client_event_pump << new msg_event_t(_msg_h, pmsg); //_msg_h(pmsg); } _srv_msg_pool[_srv_data_msg.type] = _srv_data_msg; sem_post(&_rsp_sem_pool[_srv_data_msg.type]); } else { if(_cnx_error_h) { client_event_pump << new error_event_t(_cnx_error_h, EBADMSG); } } _rstate = 0; break; } _data_ar->start_recv(pbuf, len); return 0;}int hsmsd_proxy_t::rcv_error_handler(const int &err){ if(_cnx_error_h) { //_cnx_error_h(-5); client_event_pump << new error_event_t(_cnx_error_h, EIO); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -