user_agent.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 <unistd.h>
00024 #include "user_agent.h"
00025 
00026 #define USER_AGENT_LOG_LEVEL 20
00027 
00028 #define FIFO_PERMS (S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
00029 
00030 using namespace freesecs;
00031 
00032 user_agent_t::user_agent_t(const char *in_ctl_fifo_name
00033                             ,const char *out_ctl_fifo_name
00034                             ,const char *in_data_fifo_name
00035                             ,const char *out_data_fifo_name
00036                             ,pcnx_t pcnx)
00037 :_pcnx(pcnx)
00038 {
00039     char ar_name[64];
00040     mode_t old_umask = umask(~FIFO_PERMS);
00041 
00042     if(-1 == mkfifo(in_ctl_fifo_name, FIFO_PERMS))
00043     {
00044         umask(old_umask);
00045         TRACE_ERROR("HSMSD: failed creating FIFO %s", in_ctl_fifo_name);
00046         throw;
00047     }
00048 
00049     if(-1 == (_fd_ctl_in = open(in_ctl_fifo_name, O_RDWR)))
00050     {
00051         TRACE_ERROR("HSMSD: failed opening FIFO %s", in_ctl_fifo_name);
00052         throw;
00053     }
00054 
00055     if(-1 == mkfifo(out_ctl_fifo_name, FIFO_PERMS))
00056     {
00057         umask(old_umask);
00058         TRACE_ERROR("HSMSD: failed creating FIFO %s", out_ctl_fifo_name);
00059         throw;
00060     }
00061 
00062     if(-1 == (_fd_ctl_out = open(out_ctl_fifo_name, O_RDWR)))
00063     {
00064         TRACE_ERROR("HSMSD: failed opening FIFO %s", out_ctl_fifo_name);
00065         throw;
00066     }
00067     if(-1 == mkfifo(in_data_fifo_name, FIFO_PERMS))
00068     {
00069         umask(old_umask);
00070         TRACE_ERROR("HSMSD: failed creating FIFO %s", in_data_fifo_name);
00071         throw;
00072     }
00073 
00074     if(-1 == (_fd_data_in = open(in_data_fifo_name, O_RDWR)))
00075     {
00076         TRACE_ERROR("HSMSD: failed opening FIFO %s", in_data_fifo_name);
00077         throw;
00078     }
00079     if(-1 == mkfifo(out_data_fifo_name, FIFO_PERMS))
00080     {
00081         umask(old_umask);
00082         TRACE_ERROR("HSMSD: failed creating FIFO %s", out_data_fifo_name);
00083         throw;
00084     }
00085 
00086     if(-1 == (_fd_data_out = open(out_data_fifo_name, O_RDWR)))
00087     {
00088         TRACE_ERROR("HSMSD: failed opening FIFO %s", out_data_fifo_name);
00089         throw;
00090     }
00091 
00092     umask(old_umask);
00093 
00094     _pcnx->rx_signal.add_handler(this, &user_agent_t::cnx_data_handler);
00095     _pcnx->state_signal.add_handler(this, &user_agent_t::cnx_state_handler);
00096 
00097     sprintf(ar_name, "%s client ctl", _pcnx->name());
00098 
00099     _ar_ctl = new async_reception_t(_fd_ctl_in, ar_name);
00100     _ar_ctl->data_recvd_signal.add_handler(this, &user_agent_t::user_ctl_handler);
00101     _ar_ctl->recv_error_signal.add_handler(this, &user_agent_t::user_error_handler);
00102 
00103     sprintf(ar_name, "%s client data", _pcnx->name());
00104     _ar_data = new async_reception_t(_fd_data_in, ar_name);
00105     _ar_data->data_recvd_signal.add_handler(this, &user_agent_t::user_data_handler);
00106     _ar_data->recv_error_signal.add_handler(this, &user_agent_t::user_error_handler);
00107 
00108     _ar_ctl->start_recv(&_client_ctl_req, sizeof(hsmsd_client_req_t));
00109     _ar_data->start_recv(&_client_data_req, sizeof(hsmsd_client_req_t));
00110 }
00111 
00112 user_agent_t::~user_agent_t()
00113 {
00114     _ar_ctl->stop_recv();
00115     _ar_data->stop_recv();
00116     close(_fd_ctl_in);
00117     close(_fd_ctl_out);
00118     close(_fd_data_in);
00119     close(_fd_data_out);
00120 }
00121 
00122 int 
00123 user_agent_t::user_ctl_handler(const size_t& num_bytes)
00124 {
00125     ua_req_handler_t::process_ctl(_client_ctl_req, num_bytes);
00126 
00127     return 0;
00128 }
00129 
00130 int 
00131 user_agent_t::user_data_handler(const size_t& num_bytes)
00132 {
00133     ua_req_handler_t::process_data(_client_data_req, num_bytes);
00134 
00135     return 0;
00136 }
00137 
00138 int 
00139 user_agent_t::user_error_handler(const int& err)
00140 {
00141     return 0;
00142 }
00143 
00144 int 
00145 user_agent_t::cnx_data_handler(const hsms_socket_t::pdata_t& pdata)
00146 {
00147     int write_res;
00148     hsmsd_server_rsp_t r;
00149     data_msg<hsms_socket_t::data_t> hsms_msg;
00150     hsms_socket_t::data_t hsms_msg_text;
00151 
00152     TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: msg recieved signal from cnx %s", _pcnx->name());
00153 
00154     if(false == hsms_msg.valid(*pdata))
00155     {
00156         TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: msg recieved from cnx %s is not valid", _pcnx->name());
00157         return -1;
00158     }
00159     TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: msg recieved from cnx %s is valid", _pcnx->name());
00160 
00161     r.type = hsmsd_server_rsp_t::MSG_RECV;
00162 
00163     r.u.msg_header.stream   = hsms_msg.stream(*pdata);
00164     r.u.msg_header.function = hsms_msg.function(*pdata);
00165     r.u.msg_header.wbit     = hsms_msg.wbit(*pdata);
00166     r.u.msg_header.sysbytes = hsms_msg.transaction_id(*pdata);
00167     r.u.msg_header.data_len = hsms_msg.text_len(*pdata);
00168 
00169     write_res = ::write(_fd_data_out, &r, sizeof(r));
00170     
00171     TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: s%df%d(0x%x), data len: %d, notified over client pipe: %d", 
00172                         r.u.msg_header.stream, 
00173                         r.u.msg_header.function, 
00174                         r.u.msg_header.sysbytes,
00175                         r.u.msg_header.data_len,
00176                         write_res);
00177 
00178     if(0 < r.u.msg_header.data_len)
00179     {
00180         if(false == hsms_msg.get_text(*pdata, hsms_msg_text))
00181         {
00182             TRACE_DEBUG(USER_AGENT_LOG_LEVEL,
00183                         "HSMSD: failed to get "
00184                         "text from msg recieved from cnx %s", 
00185                         _pcnx->name());
00186 
00187             return -2;
00188         }
00189 
00190         write_res = ::write(_fd_data_out, &hsms_msg_text[0], hsms_msg_text.size());
00191         TRACE_DEBUG(USER_AGENT_LOG_LEVEL,
00192                         "HSMSD: s%df%d(0x%x), "
00193                         "data len: %d, msg body "
00194                         "written to client pipe: %d",
00195                         r.u.msg_header.stream, 
00196                         r.u.msg_header.function, 
00197                         r.u.msg_header.sysbytes,
00198                         r.u.msg_header.data_len,
00199                         write_res);
00200     }
00201     return 0;
00202 }
00203 
00204 static hsmsd_server_rsp_t::cnx_state_t state_conv[e_hsms_not_connected_t5+1] = 
00205     {   hsmsd_server_rsp_t::CNX_NOT_CONNECTED,
00206         hsmsd_server_rsp_t::CNX_NOT_SELECTED,
00207         hsmsd_server_rsp_t::CNX_SELECTED,
00208         hsmsd_server_rsp_t::CNX_NOT_CONNECTED
00209     };
00210 
00211 int
00212 user_agent_t::cnx_state_handler(const hsms_state_et& state)
00213 {
00214     hsmsd_server_rsp_t r;
00215 
00216     r.type = hsmsd_server_rsp_t::CNX_STATE_EVT;
00217     r.u.cnx_state = state_conv[(int)state];
00218     ::write(_fd_ctl_out, &r, sizeof(r));
00219     TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: sent cnx state change to the client: %d", r.u.cnx_state);
00220 
00221     return 0;
00222 }
00223 
00224 void 
00225 user_agent_t::rcv_from_ctl(void *buf, size_t count)
00226 {
00227     _ar_ctl->start_recv(buf, count);
00228 }
00229 
00230 void 
00231 user_agent_t::rcv_from_data(void *buf, size_t count)
00232 {
00233     _ar_data->start_recv(buf, count);
00234 }
00235 
00236 void 
00237 user_agent_t::send_msg(hsms_cnx_t::pdata_t d)
00238 {
00239     hsmsd_server_rsp_t r;
00240 
00241     r.type = hsmsd_server_rsp_t::MSG_SEND;
00242     r.u.req_status = _pcnx->send(d);
00243     ::write(_fd_data_out, &r, sizeof(r));
00244 }
00245 void
00246 user_agent_t::start_cnx()
00247 {
00248     hsmsd_server_rsp_t r;
00249 
00250     r.type = hsmsd_server_rsp_t::CNX_START;
00251     r.u.req_status = _pcnx->start();
00252 
00253     ::write(_fd_ctl_out, &r, sizeof(r));
00254 }
00255 void 
00256 user_agent_t::stop_cnx()
00257 {
00258     hsmsd_server_rsp_t r;
00259 
00260     r.type = hsmsd_server_rsp_t::CNX_STOP;
00261     r.u.req_status = _pcnx->stop();
00262     ::write(_fd_ctl_out, &r, sizeof(r));
00263 }
00264 void 
00265 user_agent_t::get_cnx_state()
00266 {
00267     hsmsd_server_rsp_t r;
00268 
00269     r.type = hsmsd_server_rsp_t::CNX_STATE_RSP;
00270     TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: cnx::get_state-->");
00271     r.u.cnx_state = state_conv[(int)_pcnx->get_state()];
00272     TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: cnx::get_state<--");
00273     TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: write cnx state rsp-->");
00274     ::write(_fd_ctl_out, &r, sizeof(r));
00275     TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: write cnx state rsp<--");
00276 }
00277 
00278 ua_req_handler_t::ua_req_handler_t()
00279 :_data_state(0)
00280 {
00281     _pmsg = new hsms_cnx_t::data_t;
00282 }
00283 /*
00284  * Client request handling SM
00285  * state 0: hsmsd_client_req_t struct reception
00286  * state 1: receiving data following hsmsd_client_req_t(MSG_SEND)
00287  * state 0 -> state 1: hsmsd_client_req_t(MSG_SEND) type recvd from client
00288  * state 1 -> state 0: all data following hsmsd_client_req_t(MSG_SEND) has been received
00289  */
00290 void
00291 ua_req_handler_t::process_data(hsmsd_client_req_t& req, size_t nb_rcvd)
00292 {
00293     data_msg<hsms_cnx_t::data_t> hsms_msg;
00294 
00295     _nb_received += nb_rcvd;
00296 
00297     if(hsmsd_client_req_t::MSG_SEND != req.type)
00298     {
00299         TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: unknown data send code: %d", req.type);
00300         return;
00301     }
00302 
00303     switch(_data_state)
00304     {
00305         case 0:
00306             TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: msg send "
00307                         "req from client (sysbytes: %d)", 
00308                         req.u.msg_header.sysbytes);
00309 
00310             hsms_msg.compose(*_pmsg,
00311                                 req.u.msg_header.stream,
00312                                 req.u.msg_header.function,
00313                                 req.u.msg_header.wbit,
00314                                 req.u.msg_header.sysbytes,
00315                                 req.u.msg_header.data_len,
00316                                 NULL);
00317             _msg_len = req.u.msg_header.data_len;
00318             rcv_from_data((void*)&(*_pmsg)[HSMS_DATABYTES_OFFSET], req.u.msg_header.data_len);
00319             _nb_received = 0;
00320             _data_state = 1;
00321         break;
00322         case 1:
00323             if(_nb_received == _msg_len)
00324             {
00325                 _data_state = 0;
00326                 _nb_received = 0;
00327                 rcv_from_data((void*)&req, sizeof(req));
00328                 send_msg(_pmsg);
00329             }
00330         break;
00331         default:
00332             _data_state = 0;
00333             _nb_received = 0;
00334         break;
00335     }
00336 }
00337 
00338 
00339 void
00340 ua_req_handler_t::process_ctl(hsmsd_client_req_t& req, size_t nb_rcvd)
00341 {
00342     switch(req.type)
00343     {
00344         case hsmsd_client_req_t::CNX_START:
00345             TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: start cnx req from client");
00346             rcv_from_ctl(&req, sizeof(req));
00347             start_cnx();
00348         break;
00349         case hsmsd_client_req_t::CNX_STOP:
00350             TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: stop cnx req from client");
00351             rcv_from_ctl((void*)&req, sizeof(req));
00352             stop_cnx();
00353         break;
00354         case hsmsd_client_req_t::CNX_STATE:
00355             TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: get cnx state req from client");
00356             rcv_from_ctl((void*)&req, sizeof(req));
00357             get_cnx_state();
00358         break;
00359         default:
00360             TRACE_DEBUG(USER_AGENT_LOG_LEVEL,"HSMSD: unknown ctl req code: %d", req.type);
00361             break;
00362     }
00363 }

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