hsmsd_cnx_proxy.cpp

00001 /*   
00002  *   (c) Copyright 2008 Philipp Skadorov (philipp_s@users.sourceforge.net)
00003  *
00004  *   This file is part of FREESECS.
00005  *
00006  *   FREESECS is free software: you can redistribute it and/or modify
00007  *   it under the terms of the GNU General Public License as published by
00008  *   the Free Software Foundation, either version 3 of the License, or
00009  *   (at your option) any later version.
00010  *
00011  *   FREESECS is distributed in the hope that it will be useful,
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *   GNU General Public License for more details.
00015  *
00016  *   You should have received a copy of the GNU General Public License
00017  *   along with FREESECS, see COPYING.
00018  *   If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 #include <fcntl.h>
00023 #include "tsqueue.h"
00024 #include "log.h"
00025 #include "hsmsd_interface.h"
00026 #include "hsmsd_cnx_proxy.h"
00027 
00028 #define CNX_PROXY_LOG_LEVEL 1000
00029 
00030 using namespace freesecs;
00031 
00032 template<typename handler_t>
00033 int set_handler(handler_t &old_h, handler_t &new_h)
00034 {
00035     int r = 0;
00036     if(old_h != NULL && new_h != NULL)
00037     {
00038         r = EPERM;
00039     }
00040     else if(old_h == new_h)
00041     {
00042         r = EALREADY;
00043     }
00044     else
00045     {
00046         old_h = new_h;
00047     }
00048     return r;
00049 }
00050 
00051 hsmsd_proxy_t::pump_events_to_client_t hsmsd_proxy_t::client_event_pump;
00052 
00053 hsmsd_proxy_t::hsmsd_proxy_t(const char *cnx_name)
00054 :_cnx_name(cnx_name)
00055 ,_fd_ctl_in(0)
00056 ,_fd_ctl_out(0)
00057 ,_fd_data_in(0)
00058 ,_fd_data_out(0)
00059 ,_rstate(0)
00060 ,_msg_h(NULL)
00061 ,_cnx_state_h(NULL)
00062 ,_cnx_error_h(NULL)
00063 {
00064     int reg_fd, rsp_fd;
00065     ssize_t req_sz, rsp_sz;
00066     hsmsd_register_req_t register_req;
00067     hsmsd_register_rsp_t register_rsp;
00068 
00069     if(-1 == (reg_fd = ::open(HSMSD_REGISTER_FIFO_IN, O_RDWR)))
00070     {
00071         throw;
00072     }
00073     if(-1 == (rsp_fd = ::open(HSMSD_REGISTER_FIFO_OUT, O_RDWR)))
00074     {
00075         throw;
00076     }
00077     
00078     strncpy(register_req.cnx_name, cnx_name, HSMS_NAME_MAX_LEN);
00079     register_req.cli_pid = getpid();
00080 
00081     req_sz = sizeof(register_req);
00082     if(req_sz != write(reg_fd, &register_req, req_sz))
00083     {
00084         throw;
00085     }
00086     rsp_sz = sizeof(register_rsp);
00087     if(rsp_sz != read(rsp_fd, &register_rsp, rsp_sz))
00088     {
00089         throw;
00090     }
00091     if(hsmsd_register_rsp_t::REG_OK != register_rsp.rsp_code)
00092     {
00093         TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, 
00094                     "HSMSCLI: register rsp: %d\n", 
00095                     register_rsp.rsp_code);
00096         throw;
00097     }
00098     
00099     close(reg_fd);
00100     close(rsp_fd);
00101 
00102     TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, "HSMSCLI: cnx %s : user pipes: %s, %s, %s, %s\n", 
00103                                   cnx_name, 
00104                                   register_rsp.pipe_name_ctl_req, 
00105                                   register_rsp.pipe_name_ctl_rsp,
00106                                   register_rsp.pipe_name_data_req,
00107                                   register_rsp.pipe_name_data_rsp);
00108 
00109     
00110     if(-1 == (_fd_ctl_out = open(register_rsp.pipe_name_ctl_req, O_RDWR)))
00111     {
00112         throw;
00113     }
00114 
00115 
00116     if(-1 == (_fd_ctl_in = open(register_rsp.pipe_name_ctl_rsp, O_RDWR)))
00117     {
00118         throw;
00119     }
00120 
00121     if(-1 == (_fd_data_out = open(register_rsp.pipe_name_data_req, O_RDWR)))
00122     {
00123         throw;
00124     }
00125 
00126     if(-1 == (_fd_data_in = open(register_rsp.pipe_name_data_rsp, O_RDWR)))
00127     {
00128         throw;
00129     }
00130 
00131 
00132     for(int i=0; i < hsmsd_server_rsp_t::MAX_RSP_TYPE; ++i)
00133     {
00134         if(0 != sem_init(&_rsp_sem_pool[i], 0, 0))
00135         {
00136             throw;
00137         }
00138     }
00139     std::string pipe_name = _cnx_name;
00140     pipe_name += " ctrl";
00141     _ctl_ar = new async_reception_t(_fd_ctl_in, pipe_name.c_str());
00142 
00143     pipe_name = _cnx_name;
00144     pipe_name += " data";
00145     _data_ar = new async_reception_t(_fd_data_in, pipe_name.c_str());
00146 
00147     _ctl_ar->data_recvd_signal.add_handler(this, &hsmsd_proxy_t::ctrl_rcvd_handler);
00148     _ctl_ar->recv_error_signal.add_handler(this, &hsmsd_proxy_t::rcv_error_handler);
00149 
00150     _data_ar->data_recvd_signal.add_handler(this, &hsmsd_proxy_t::data_rcvd_handler);
00151     _data_ar->recv_error_signal.add_handler(this, &hsmsd_proxy_t::rcv_error_handler);
00152 
00153     _ctl_ar->start_recv(&_srv_ctl_msg, sizeof(_srv_ctl_msg));
00154     _data_ar->start_recv(&_srv_data_msg, sizeof(_srv_data_msg));
00155 }
00156 
00157 hsmsd_proxy_t::~hsmsd_proxy_t()
00158 {
00159     _ctl_ar->stop_recv();
00160     _data_ar->stop_recv();
00161 
00162     close(_fd_ctl_in);
00163     close(_fd_ctl_out);
00164     close(_fd_data_in);
00165     close(_fd_data_out);
00166     
00167     for(size_t i=0; i < sizeof(_rsp_sem_pool); ++i)
00168     {
00169         sem_destroy(&_rsp_sem_pool[i]);
00170     }
00171 }
00172 
00173 int 
00174 hsmsd_proxy_t::set_msg_handler(hsmsd_msg_handler_t new_h)
00175 {
00176     return set_handler(_msg_h, new_h);
00177 }
00178 
00179 int 
00180 hsmsd_proxy_t::set_cnx_state_handler(hsmsd_cnx_state_handler_t new_h)
00181 {
00182     return set_handler(_cnx_state_h, new_h);
00183 }
00184 
00185 int 
00186 hsmsd_proxy_t::set_cnx_error_handler(hsmsd_cnx_error_handler_t new_h)
00187 {
00188     return set_handler(_cnx_error_h, new_h);
00189 }
00190 
00191 int 
00192 hsmsd_proxy_t::start()
00193 {
00194     int r = 0;
00195     size_t len;
00196     hsmsd_client_req_t req;
00197 
00198     
00199     req.type = hsmsd_client_req_t::CNX_START;
00200     
00201     len = write(_fd_ctl_out, &req, sizeof(req));
00202     
00203     if(sizeof(req) == len)
00204     {
00205     TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, 
00206                 "HSMSCLI: cnx %s : sent cnx start, "
00207                 "waiting for reply...\n", 
00208                 _cnx_name.c_str());
00209 
00210         sem_wait(&_rsp_sem_pool[hsmsd_server_rsp_t::CNX_START]);
00211         r = _srv_msg_pool[hsmsd_server_rsp_t::CNX_START].u.req_status;
00212 
00213         TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, 
00214                     "HSMSCLI: cnx %s : sent "
00215                     "cnx start reply: %d\n", 
00216                     _cnx_name.c_str(), r);
00217     }
00218     else
00219     {
00220         r = errno;
00221     }
00222     return r;
00223 }
00224 
00225 int 
00226 hsmsd_proxy_t::stop()
00227 {
00228     int r = 0;
00229     size_t len;
00230     hsmsd_client_req_t req;
00231     
00232     req.type = hsmsd_client_req_t::CNX_STOP;
00233    
00234     len = write(_fd_ctl_out, &req, sizeof(req));
00235     
00236     if(sizeof(req) == len)
00237     {
00238         sem_wait(&_rsp_sem_pool[hsmsd_server_rsp_t::CNX_STOP]);
00239         r = _srv_msg_pool[hsmsd_server_rsp_t::CNX_STOP].u.req_status;
00240     }
00241     else
00242     {
00243         r = errno;
00244     }
00245     return r;
00246 }
00247 
00248 int 
00249 hsmsd_proxy_t::get_state(hsmsd_cnx_state_t* state)
00250 {
00251     int r = 0;
00252     size_t len;
00253     hsmsd_client_req_t req;
00254     
00255     req.type = hsmsd_client_req_t::CNX_STATE;
00256     
00257     len = write(_fd_ctl_out, &req, sizeof(req));
00258     
00259     if(sizeof(req) == len)
00260     {
00261         sem_wait(&_rsp_sem_pool[hsmsd_server_rsp_t::CNX_STATE_RSP]);
00262         *state = (hsmsd_cnx_state_t)_srv_msg_pool[hsmsd_server_rsp_t::CNX_STATE_RSP].u.cnx_state;
00263     }
00264     else
00265     {
00266         r = errno;
00267     }
00268 
00269     return r;
00270 }
00271 
00272 int 
00273 hsmsd_proxy_t::send_msg(hsmsd_msg_t* msg)
00274 {
00275     int r = 0;
00276     ssize_t len;
00277     hsmsd_client_req_t *req;
00278 
00279     len = sizeof(hsmsd_client_req_t) + msg->data_len;
00280 
00281     char *pmem = (char*)malloc(len);
00282     memset(pmem, 0, sizeof(len));
00283 
00284     if(msg->data_len)
00285     {
00286         memcpy(pmem + sizeof(hsmsd_client_req_t), msg->data, msg->data_len);
00287     }
00288     req = (hsmsd_client_req_t*)pmem;
00289 
00290     req->type = hsmsd_client_req_t::MSG_SEND;
00291     req->u.msg_header.stream     = msg->stream;
00292     req->u.msg_header.function   = msg->function;
00293     req->u.msg_header.wbit       = msg->wbit;
00294     req->u.msg_header.sysbytes   = msg->sysbytes;
00295     req->u.msg_header.data_len   = msg->data_len;
00296 
00297 
00298     if(len != (r = write(_fd_data_out, pmem, len)))
00299     {
00300         r = errno;
00301     }
00302     else
00303     {
00304         sem_wait(&_rsp_sem_pool[hsmsd_server_rsp_t::MSG_SEND]);
00305         r = _srv_msg_pool[hsmsd_server_rsp_t::MSG_SEND].u.req_status;
00306     }
00307 
00308     free(pmem);
00309     
00310     return r;
00311 }
00312 
00313 int 
00314 hsmsd_proxy_t::ctrl_rcvd_handler(const size_t &size)
00315 {
00316     size_t len = sizeof(_srv_ctl_msg);
00317 
00318     if(size != len && _cnx_error_h)
00319     {
00320         //_cnx_error_h(-3);
00321         client_event_pump << new error_event_t(_cnx_error_h, -3);
00322     }
00323 
00324     _srv_msg_pool[_srv_ctl_msg.type] = _srv_ctl_msg;
00325 
00326     sem_post(&_rsp_sem_pool[_srv_ctl_msg.type]);
00327 
00328     /*fire rsp type-specific handlers!*/
00329     if(hsmsd_server_rsp_t::CNX_STATE_EVT == _srv_ctl_msg.type && _cnx_state_h)
00330     {
00331         //_cnx_state_h((hsmsd_cnx_state_t)_srv_ctl_msg.u.cnx_state);
00332         client_event_pump << new state_event_t(_cnx_state_h, (hsmsd_cnx_state_t)_srv_ctl_msg.u.cnx_state);
00333     }
00334     else if(hsmsd_server_rsp_t::CNX_ERROR_EVT == _srv_ctl_msg.type && _cnx_error_h)
00335     {
00336         //_cnx_error_h(_srv_ctl_msg.u.cnx_error);
00337         client_event_pump << new error_event_t(_cnx_error_h, _srv_ctl_msg.u.cnx_error);
00338     }
00339 
00340    _ctl_ar->start_recv(&_srv_ctl_msg, len);
00341 
00342     return 0;
00343 }
00344 
00345 int 
00346 hsmsd_proxy_t::data_rcvd_handler(const size_t &size)
00347 {
00348     hsmsd_msg_t *pmsg;
00349     void *pbuf = &_srv_data_msg;
00350     size_t len = sizeof(_srv_data_msg);
00351 
00352     TRACE_DEBUG(CNX_PROXY_LOG_LEVEL, 
00353                 "HSMSCLI: server data response: "
00354                 "type=%d, req status=%d, "
00355                 "error=%d, cnx state=%d", 
00356                 _srv_data_msg.type, 
00357                 _srv_data_msg.u.req_status, 
00358                 _srv_data_msg.u.cnx_error, 
00359                 _srv_data_msg.u.cnx_state);
00360 
00361     switch(_rstate)
00362     {
00363         case 0:
00364             TRACE_DEBUG(CNX_PROXY_LOG_LEVEL,
00365                         "HSMSCLI: receiving data: status=%d, "\
00366                         "msg size=%d, expected size=%d", 
00367                         _rstate, 
00368                         size, 
00369                         len);
00370             if(size == len && hsmsd_server_rsp_t::MSG_RECV == _srv_data_msg.type)
00371             {
00372                     //_msg_data.clear();
00373                     _msg_data.resize(_srv_data_msg.u.msg_header.data_len, 0);
00374                     _rstate = 1;
00375                     pbuf = &_msg_data[0];
00376                     len = _srv_data_msg.u.msg_header.data_len;
00377             }
00378             else if(size == len && hsmsd_server_rsp_t::MSG_SEND == _srv_data_msg.type)
00379             {
00380                 _srv_msg_pool[_srv_data_msg.type] = _srv_data_msg;
00381                 sem_post(&_rsp_sem_pool[_srv_data_msg.type]);
00382                 _rstate = 0;
00383             }
00384             else if(_cnx_error_h)
00385             {
00386                 //_cnx_error_h(-3);
00387                 client_event_pump << new error_event_t(_cnx_error_h, -3);
00388             }
00389         break;
00390         case 1:
00391             TRACE_DEBUG(CNX_PROXY_LOG_LEVEL,
00392                         "HSMSCLI: receiving status=%d, "
00393                         "msg size=%d, expected size=%d/%d", 
00394                         _rstate, size, _msg_data.size(),
00395                         _srv_data_msg.u.msg_header.data_len);
00396 
00397             if(size == _msg_data.size()
00398                 && size == _srv_data_msg.u.msg_header.data_len)
00399             {
00400                 if(_msg_h)
00401                 {
00402 
00403                     pmsg = (hsmsd_msg_t*)malloc(sizeof(hsmsd_msg_t) + size - 1);
00404                     pmsg->stream    = _srv_data_msg.u.msg_header.stream;
00405                     pmsg->function  = _srv_data_msg.u.msg_header.function;
00406                     pmsg->wbit      = _srv_data_msg.u.msg_header.wbit;
00407                     pmsg->sysbytes  = _srv_data_msg.u.msg_header.sysbytes;
00408                     pmsg->data_len  = size;
00409                     memcpy(&pmsg->data[0], &_msg_data[0], size);
00410             
00411                     TRACE_DEBUG(CNX_PROXY_LOG_LEVEL,
00412                                 "HSMSCLI: s%df%d(0x%x) received from server"
00413                                 , pmsg->stream, pmsg->function
00414                                 , pmsg->sysbytes);
00415 
00416                     client_event_pump << new msg_event_t(_msg_h, pmsg);
00417                     //_msg_h(pmsg);
00418                 }
00419 
00420                 _srv_msg_pool[_srv_data_msg.type] = _srv_data_msg;
00421                 sem_post(&_rsp_sem_pool[_srv_data_msg.type]);
00422             }
00423             else
00424             {
00425                 if(_cnx_error_h)
00426                 {
00427                     client_event_pump << new error_event_t(_cnx_error_h, EBADMSG);
00428                 }
00429             }
00430             _rstate = 0;
00431         break;
00432     }
00433 
00434     _data_ar->start_recv(pbuf, len);
00435     return 0;
00436 }
00437 
00438 int 
00439 hsmsd_proxy_t::rcv_error_handler(const int &err)
00440 {
00441     if(_cnx_error_h)
00442     {
00443         //_cnx_error_h(-5);
00444         client_event_pump << new error_event_t(_cnx_error_h, EIO);
00445     }
00446     return 0;
00447 }

Generated on Fri Oct 3 15:30:01 2008 for FREESECS hsms by  doxygen 1.5.1