00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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, ®ister_req, req_sz))
00083 {
00084 throw;
00085 }
00086 rsp_sz = sizeof(register_rsp);
00087 if(rsp_sz != read(rsp_fd, ®ister_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
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
00329 if(hsmsd_server_rsp_t::CNX_STATE_EVT == _srv_ctl_msg.type && _cnx_state_h)
00330 {
00331
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
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
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
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
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
00444 client_event_pump << new error_event_t(_cnx_error_h, EIO);
00445 }
00446 return 0;
00447 }