hsms_socket.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 <string>
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <sys/param.h>
00024 #include "log.h"
00025 #include "hsms_msg.h"
00026 #include "hsms_socket.h"
00027 #include "tsqueue.h"
00028 #include "hsms_signums.h"
00029 #include "log.h"
00030 
00031 #define HSMS_SOCK_LOG_LEVEL 9
00032 
00033     
00034 #define MAXRECV 1024
00035 
00036 using namespace freesecs;
00037 
00038 hsms_socket_t::hsms_socket_t(const char *name, const int port)
00039 :_remote_host(""), _port(port), _sock(-1)
00040 {
00041     _name = name;
00042     _name += " sock";
00043     _cnx_sm_name = _name;
00044     _cnx_sm_name += " cnx sm";
00045 
00046     memset (&_addr, 0, sizeof (_addr));
00047 
00048     if(0 != create_socket())
00049     {
00050         throw;
00051     }
00052 }
00053 
00054 hsms_socket_t::hsms_socket_t(const char *name, const char *host, const int port)
00055 :_remote_host(host), _port(port), _sock(-1)
00056 {
00057     _name = name;
00058     _name += " sock";
00059     _cnx_sm_name = _name;
00060     _cnx_sm_name += " cnx sm";
00061 
00062     memset (&_addr, 0, sizeof (_addr));
00063 
00064     if(0 != create_socket())
00065     {
00066         throw;
00067     }
00068 }
00069 
00070 int
00071 hsms_socket_t::create_socket()
00072 {
00073 
00074     _sock = socket (AF_INET, SOCK_STREAM, 0);
00075     if (_sock <= 0)
00076     {
00077         TRACE_ERROR("%s: failed creating streaming socket", __func__);
00078         return errno;
00079     }
00080     
00081     int on = 1;
00082 
00083     if (setsockopt (_sock, 
00084                 SOL_SOCKET, 
00085                 SO_REUSEADDR, 
00086                 (const char *) &on, 
00087                 sizeof (on)) == -1)
00088     {
00089         TRACE_ERROR("%s: failed setting socket options", __func__);
00090         return errno;
00091     }
00092 
00093     return 0;
00094 }
00095 
00096 hsms_socket_t::~hsms_socket_t () 
00097 {
00098     disconnect();
00099 }
00100 
00101 int
00102 hsms_socket_t::bind () 
00103 {
00104     if (_sock <= 0)
00105     {
00106         return EBADF;
00107     }
00108     _addr.sin_family = AF_INET;
00109     _addr.sin_addr.s_addr = htonl (INADDR_ANY);
00110     _addr.sin_port = htons (_port);
00111     
00112     if(-1 == ::bind(_sock, (struct sockaddr*)&_addr, sizeof(_addr)))
00113     {
00114         return errno;
00115     }
00116 
00117     return 0;
00118 }
00119 
00120 int
00121 hsms_socket_t::listen () 
00122 {
00123     if (_sock <= 0)
00124     {
00125         return EBADF;
00126     }
00127 
00128     if(-1 == ::listen (_sock, MAXCONNECTIONS))
00129     {
00130         return errno;
00131     }
00132 
00133     return 0;
00134 }
00135 
00136 int
00137 hsms_socket_t::accept () 
00138 {
00139     sock_cnx_ev_t ev;
00140     int new_sock = 0;
00141     int addr_length = sizeof (_addr);
00142 
00143     new_sock =::accept (_sock, (sockaddr *) & _addr, (socklen_t *) & addr_length);
00144     
00145     if (new_sock <= 0)
00146     {
00147         return errno;
00148     }
00149     TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL, "hsms_socket_t::accept: cnx established");
00150 
00151     ::shutdown(_sock, SHUT_RDWR);
00152     ::close (_sock);
00153     _sock = new_sock;
00154 
00155     return 0;
00156 }
00157 
00158 int freesecs::hsms_socket_t::connect_to() 
00159 {
00160     if (_sock <= 0)
00161     {
00162         TRACE_ERROR("hsms_socket_t::remote_connect - socket is not valid");
00163         return EBADF;
00164     }
00165     _addr.sin_family = AF_INET;
00166     _addr.sin_port = htons (_port);
00167     int
00168     status = inet_pton (AF_INET, _remote_host.c_str (), &_addr.sin_addr);
00169 
00170     if (status && errno == EAFNOSUPPORT)
00171     {
00172         TRACE_ERROR("hsms_socket_t::remote_connect - invalid address: %s", _remote_host.c_str());
00173         return errno;
00174     }
00175     
00176     if(-1 == ::connect (_sock, (sockaddr *) & _addr, sizeof (_addr)))
00177     {
00178         TRACE_ERROR("hsms_socket_t::remote_connect - failed connecting to address: %s/%d", 
00179                                                                     _remote_host.c_str(), _port);
00180         return errno;
00181     }
00182     TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL, "hsms_socket_t::remote_connect to %s/%d OK!", 
00183                                                                 _remote_host.c_str(),  _port);
00184 
00185     return 0;
00186 }
00187 
00188 int
00189 hsms_socket_t::connect_tcp()
00190 {
00191     int r = 0;
00192 
00193     if(0 == _sock)
00194     {
00195         if(0 != (r=create_socket()))
00196         {
00197             TRACE_ERROR("hsms_socket_t::connect: create socket failed: %s", strerror(r));
00198             return r;
00199         }
00200     }
00201 
00202     if(_remote_host.length() == 0)
00203     {
00204         TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL, "hsms_socket_t::connect: bind");
00205         if(0 != (r = bind()))
00206         {
00207             TRACE_ERROR("hsms_socket_t::connect: bind failed: %s", strerror(errno));
00208             return r;
00209         }
00210         if(0 != (r = listen()))
00211         {
00212             TRACE_ERROR("hsms_socket_t::connect: listen failed: %s", strerror(errno));
00213             return r;
00214         }
00215 
00216         TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL,"hsms_socket_t::connect: accept");
00217 
00218         r = accept();
00219         if(0 != r)
00220         {
00221             TRACE_ERROR("hsms_socket_t::connect: accept failed: %s", strerror(errno));
00222             return r;
00223         }
00224     }
00225     else
00226     {
00227         r = connect_to();
00228     }
00229     return r;
00230 }
00231 
00232 int
00233 hsms_socket_t::disconnect_tcp()
00234 {
00235     int r = 0;
00236 
00237     if(::shutdown(_sock, SHUT_RDWR))
00238     {
00239         r = errno;
00240         TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL, "hsms_socket_t::disconnect: shutdown returned %s", strerror(r));
00241     }
00242 
00243     if(::close(_sock))
00244     {
00245         r = errno;
00246         TRACE_ERROR("hsms_socket_t::disconnect: close returned %s", strerror(r));
00247     }
00248 
00249     _sock = 0;
00250 
00251     //return r;
00252     return 0;
00253 }
00254 
00255 hsms_socket_t::cnx_state_et 
00256 hsms_socket_t::get_cnx_state() const
00257 {
00258     return _cnx_state;
00259 }
00260 
00261 int
00262 hsms_socket_t::connect()
00263 {
00264     sock_cnx_ev_t ev = {e_connect,};
00265     return process(ev);
00266 }
00267 
00268 int
00269 hsms_socket_t::disconnect()
00270 {
00271     sock_cnx_ev_t ev = {e_disconnect,};
00272     return process(ev);
00273 }
00274 
00275 int 
00276 hsms_socket_t::send (pdata_t pdata)
00277 {
00278     sock_cnx_ev_t ev = {e_send, pdata};
00279     return process(ev);
00280 }
00281 
00282 int 
00283 hsms_socket_t::receive(pdata_t pdata)
00284 {
00285     sock_cnx_ev_t ev = {e_recv, pdata};
00286     return process(ev);
00287 }
00288 
00289 int
00290 hsms_socket_t::send_tcp(pdata_t pd)
00291 {
00292     int r = 0;
00293     ssize_t sent, size = (*pd).size();
00294     
00295     sent = ::send (_sock, (void*)pd->data(), size, MSG_NOSIGNAL);
00296 
00297     if(sent != size)
00298     {
00299         r = errno;
00300     }
00301 
00302     return r;
00303 }
00304 
00305 int
00306 hsms_socket_t::process(sock_cnx_ev_t ev)
00307 {
00308     int r = 0;
00309     cnx_state_et state_old = _cnx_state;
00310 
00311     TRACE_FSM_BEGIN(HSMS_SOCK_LOG_LEVEL, _cnx_sm_name.c_str(), _cnx_state, ev.type);
00312 
00313     switch(_cnx_state)
00314     {
00315         case NOT_CONNECTED:
00316         if(e_connect == ev.type)
00317         {
00318             _cnx_state = CONNECTING;
00319         }
00320         else
00321         {
00322             goto sm_wrong_ev;
00323         }
00324         break;
00325         case CONNECTING:
00326         if(e_connected == ev.type)
00327         {
00328             _cnx_state = CONNECTED;
00329         }
00330         else if(e_connect_failed == ev.type)
00331         {
00332             r = z3(ev);
00333             _cnx_state = NOT_CONNECTED;
00334         }
00335         else if(e_disconnect == ev.type)
00336         {
00337             _cnx_state = NOT_CONNECTED;
00338         }
00339         else
00340         {
00341             goto sm_wrong_ev;
00342         }
00343         break;
00344         case CONNECTED:
00345         if(e_disconnect == ev.type)
00346         {
00347             _cnx_state = NOT_CONNECTED;
00348         }
00349         else if(e_send == ev.type)
00350         {
00351             r = z1(ev);
00352         }
00353         else if(e_recv == ev.type)
00354         {
00355             r = z2(ev);
00356         }
00357         else
00358         {
00359             goto sm_wrong_ev;
00360         }
00361         break;
00362         default:
00363             r = ENOTSUP;
00364         break;
00365     }
00366 
00367     if(state_old == _cnx_state)
00368     {
00369         goto sm_end;
00370     }
00371 
00372     TRACE_FSM_TRANS(HSMS_SOCK_LOG_LEVEL, _cnx_sm_name.c_str(), state_old, _cnx_state);
00373     
00374     switch(_cnx_state)
00375     {
00376         case NOT_CONNECTED:
00377             r = z1_0(ev);
00378         break;
00379         case CONNECTING:
00380             r = z2_0(ev);
00381         break;
00382         case CONNECTED:
00383             r = z3_0(ev);
00384         break;
00385         default:
00386             r = ENOTSUP;
00387         break;
00388     }
00389 sm_end:
00390     TRACE_FSM_END(HSMS_SOCK_LOG_LEVEL, _cnx_sm_name.c_str(), _cnx_state, ev.type);
00391     return r;
00392 sm_wrong_ev:
00393 
00394     TRACE_FSM_ERROR(HSMS_SOCK_LOG_LEVEL, _cnx_sm_name.c_str(),
00395                     ", %s: event %d not handled in current state: %d", 
00396                     _name.c_str(), ev.type, _cnx_state);
00397     TRACE_FSM_END(HSMS_SOCK_LOG_LEVEL, _name.c_str(), _cnx_state, ev.type);
00398     return ENOTSUP;
00399 }
00400 
00401 int 
00402 hsms_socket_t::z1(sock_cnx_ev_t ev)
00403 {
00404     return send_tcp(ev.pdata);
00405 }
00406 
00407 int 
00408 hsms_socket_t::z2(sock_cnx_ev_t ev)
00409 {
00410     return recv_tcp(ev.pdata);
00411 }
00412 
00413 int
00414 hsms_socket_t::z3(sock_cnx_ev_t)
00415 {
00416     cnx_failed_signal();
00417     return 0;
00418 }
00419 
00420 int 
00421 hsms_socket_t::z1_0(sock_cnx_ev_t ev)
00422 {
00423     int r = disconnect_tcp();
00424     cnx_state_signal(_cnx_state);
00425     return r;
00426 }
00427 
00428 int 
00429 hsms_socket_t::z2_0(sock_cnx_ev_t ev)
00430 {
00431     int r = 0;
00432     pthread_t tid;
00433     pthread_attr_t attr;
00434 
00435 
00436     cnx_state_signal(_cnx_state);
00437 
00438     pthread_attr_init(&attr);
00439     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00440 
00441     if(pthread_create(&tid, &attr, tcp_cnx_thread, (void*)this))
00442     {
00443         r = errno;
00444     }
00445 
00446     pthread_attr_destroy(&attr);
00447 
00448     return r;
00449 }
00450 
00451 int 
00452 hsms_socket_t::z3_0(sock_cnx_ev_t ev)
00453 {
00454     cnx_state_signal(_cnx_state);
00455     return 0;
00456 }
00457 
00458 void *
00459 hsms_socket_t::tcp_cnx_thread(void *arg)
00460 {
00461     int r;
00462     sock_cnx_ev_t ev;
00463     hsms_socket_t *psock = (hsms_socket_t*)arg;
00464 
00465     r = psock->connect_tcp();
00466     if(0 == r)
00467     {
00468         ev.type = e_connected;
00469     }
00470     else
00471     {
00472         ev.type = e_connect_failed;
00473     }
00474 
00475     psock->process(ev);
00476 
00477     pthread_exit(NULL);
00478 }
00479 
00480 /*<<<async socket>>>*/
00481 hsms_socket_async_t::hsms_socket_async_t(const char *name, const int port)
00482 :hsms_socket_t(name, port)
00483 {
00484 }
00485 
00486 hsms_socket_async_t::hsms_socket_async_t(const char *name, const char *host, int port)
00487 :hsms_socket_t(name, host, port),_ar(NULL)
00488 {
00489 
00490 }
00491 
00492 hsms_socket_async_t::~hsms_socket_async_t()
00493 {
00494     disconnect();
00495 }
00496 
00497 int
00498 hsms_socket_async_t::disconnect_tcp()
00499 {
00500     process(e_i_deinit);
00501     return freesecs::hsms_socket_t::disconnect_tcp();
00502 }
00503 
00504 int 
00505 hsms_socket_async_t::recv_tcp(pdata_t pmessage)
00506 {
00507     _pmessage = pmessage;
00508     process(e_i_init);
00509     return EWOULDBLOCK;
00510 }
00511 
00512 #if 0
00513 bool 
00514 hsms_socket_async_t::x1()
00515 {
00516     bool valid = HSMS_LEN_BYTES_LEN + HSMS_HDR_LEN == _bytes_read;
00517     TRACE_FSM_ACTION(HSMS_SOCK_LOG_LEVEL, _name.c_str(), __func__, ": %d", valid);
00518     return valid;
00519 
00520 }
00521 
00522 bool 
00523 hsms_socket_async_t::x2()
00524 {
00525     int msg_len = ntohl(HSMS_MSG_LEN(&(*_pmessage)[0]));
00526     bool valid = msg_len >= HSMS_HDR_LEN;
00527     TRACE_FSM_ACTION(HSMS_SOCK_LOG_LEVEL, _name.c_str(), __func__, ": len %d, valid %d", 
00528                             msg_len, 
00529                             valid);
00530     return valid;
00531 }
00532 
00533 bool 
00534 hsms_socket_async_t::x3()
00535 {
00536 /*    hsms_msg_base<data_t> msg_base;
00537     bool valid = msg_base.valid(*_pmessage);
00538 */
00539     bool valid = HSMS_HDR_LEN <= ntohl(HSMS_MSG_LEN(&(*_pmessage)[0]))
00540         && _pmessage->size() >= HSMS_LEN_BYTES_LEN + HSMS_HDR_LEN
00541             && hsms_msg_base<data_t>::e_separate_req 
00542                                    >= HSMS_MSG_STYPE(&(*_pmessage)[0]);
00543 
00544     TRACE_FSM_ACTION(HSMS_SOCK_LOG_LEVEL, _name.c_str(), __func__, ": %d", valid);
00545     return valid;
00546 }
00547 
00548 bool 
00549 hsms_socket_async_t::x4()
00550 {
00551     hsms_msg_base<data_t> msg_base;
00552     bool valid = hsms_msg_base<data_t>::e_data == msg_base.type(*_pmessage);
00553     TRACE_FSM_ACTION(HSMS_SOCK_LOG_LEVEL, _name.c_str(), __func__, ": %d", valid);
00554     return valid;
00555 }
00556 
00557 bool 
00558 hsms_socket_async_t::x5()
00559 {
00560     bool valid = _rx_error > 0;
00561     TRACE_FSM_ACTION(HSMS_SOCK_LOG_LEVEL, _name.c_str(), __func__, ": %d", valid);
00562     return valid;
00563 }
00564 
00565 bool 
00566 hsms_socket_async_t::x6()
00567 {
00568     data_msg<data_t> msg;
00569     bool valid = msg.text_len(*_pmessage) <= _bytes_read
00570                     - HSMS_LEN_BYTES_LEN - HSMS_HDR_LEN;
00571     TRACE_FSM_ACTION(HSMS_SOCK_LOG_LEVEL, _name.c_str(), __func__, ": %d", valid);
00572     return valid; 
00573 }
00574 
00575 int 
00576 hsms_socket_async_t::z0()
00577 {
00578     int len = HSMS_LEN_BYTES_LEN + HSMS_HDR_LEN;
00579 
00580     if(!_pmessage.get())
00581     {
00582         _pmessage = new data_t;
00583     }
00584     //_pmessage->clear();
00585     _pmessage->resize(len, 0);
00586 
00587     if(NULL == _ar.get())
00588     {
00589         _ar = new async_reception_t(_sock, _name.c_str());
00590         _ar->data_partially_recvd_signal.add_handler(this, &freesecs::hsms_socket_async_t::data_rcvd_handler);
00591         _ar->data_recvd_signal.add_handler(this, &freesecs::hsms_socket_async_t::data_rcvd_handler);
00592         _ar->recv_error_signal.add_handler(this, &freesecs::hsms_socket_async_t::rcv_error_handler);
00593     }
00594     _ar->start_recv((void*)&(*_pmessage)[0], len);
00595 
00596     return 0;
00597 }
00598 
00599 int 
00600 hsms_socket_async_t::z1()
00601 {
00602     data_msg<data_t> msg;
00603     
00604     unsigned text_len = msg.text_len(*_pmessage);
00605     unsigned total_len = HSMS_LEN_BYTES_LEN + HSMS_HDR_LEN + text_len;
00606     
00607     TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL,
00608                 "%s::z1: text length %d,"
00609                 " total length %d", 
00610                 _name.c_str(),
00611                 text_len, total_len);
00612 
00613     if(_bytes_read < total_len)
00614     {
00615         _pmessage->resize(total_len, 0);
00616     }
00617 
00618     _ar->start_recv((void*)&(*_pmessage)[HSMS_DATABYTES_OFFSET], text_len);
00619 
00620     return 0;
00621 }
00622 
00623 int 
00624 hsms_socket_async_t::z3()
00625 {
00626     state_signal(e_again);
00627     return 0;
00628 }
00629 
00630 int 
00631 hsms_socket_async_t::z4()
00632 {
00633     state_signal(e_again);
00634     return 0;
00635 }
00636 
00637 int 
00638 hsms_socket_async_t::z5()
00639 {
00640     TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL, "%s::z5: disconnect...", _name.c_str());
00641 
00642     _ar->stop_recv();
00643     _ar = NULL;
00644     return 0;
00645 }
00646 
00647 int 
00648 hsms_socket_async_t::z1_0()
00649 {
00650     _rx_error = 0;
00651     _bytes_read = 0;
00652     *_pmessage = data_t(HSMS_LEN_BYTES_LEN + HSMS_HDR_LEN, 0);
00653 
00654     state_signal(_state);
00655     return 0;
00656 }
00657 
00658 int 
00659 hsms_socket_async_t::z2_0()
00660 {
00661     state_signal(_state);
00662     return 0;
00663 }
00664 
00665 int 
00666 hsms_socket_async_t::z3_0()
00667 {
00668     state_signal(_state);
00669     msg_signal(_pmessage);
00670     return 0;
00671 }
00672 
00673 int 
00674 hsms_socket_async_t::z4_0()
00675 {
00676     state_signal(_state);
00677     return 0;
00678 }
00679 #endif
00680 
00695 void 
00696 hsms_socket_async_t::process(internal_event_t e)
00697 {
00698     state_t state_old = _state;
00699 
00700     TRACE_FSM_BEGIN(HSMS_SOCK_LOG_LEVEL, _name.c_str(), _state, e);
00701 
00702     switch(_state)
00703     {
00704         case inactive:
00705             if(e_i_init == e)
00706             {
00707                 _state = wtg_for_header;
00708             }
00709         break;
00710         case wtg_for_header:
00711             if(e_i_deinit == e)
00712             {
00713                 _state = inactive;
00714             }
00715             else if(e_i_data_received == e)
00716             {
00717                 //if the whole header received,
00718                 //go to wtg_for_data state
00719                 if(x0())
00720                 {
00721                     if(x2())
00722                     {
00723                         z1();
00724                         z1_0();
00725                     }
00726                     else
00727                     {
00728                         _state = wtg_for_data;
00729                     }
00730                 }
00731                 else
00732                 {
00733                     z2();
00734                 }
00735             }
00736             else if(e_i_recv_error == e)
00737             {
00738                //just reset the data buf
00739                //do not change the state
00740                z0();
00741                z3();
00742             }
00743         break;
00744         case wtg_for_data:
00745             if(e_i_deinit == e)
00746             {
00747                 _state = inactive;
00748             }
00749             else if(e_i_data_received == e)
00750             {
00751                 //if the whole msg received,
00752                 //transit to wtg_for_header state
00753                 if(x1())
00754                 {
00755                     //signal msg recieved
00756                     z1();
00757                     _state = wtg_for_header;
00758                 }
00759                 else
00760                 {
00761                     z2();
00762                 }
00763             }
00764             else if(e_i_recv_error == e)
00765             {
00766                 //reset the databuf and transit
00767                 //to wtg_for_header state
00768                 z3();
00769                 _state = wtg_for_header;
00770             }
00771         default:
00772         break;
00773     }
00774 
00775     if(state_old == _state)
00776     {
00777         goto sm_end;
00778     }
00779 
00780     TRACE_FSM_TRANS(HSMS_SOCK_LOG_LEVEL, _name.c_str(), state_old, _state);
00781 
00782     switch(_state)
00783     {
00784         case inactive:
00785             z0_0();
00786         break;
00787         case wtg_for_header:
00788             z1_0();
00789         break;
00790         case wtg_for_data:
00791             z2_0();
00792         default:
00793         break;
00794     }
00795 
00796 sm_end:
00797     TRACE_FSM_END(HSMS_SOCK_LOG_LEVEL, _name.c_str(), _state, e);
00798     return;
00799 }
00800 
00801 bool 
00802 hsms_socket_async_t::x0()
00803 {
00804     bool valid = HSMS_LEN_BYTES_LEN + HSMS_HDR_LEN == _bytes_read;
00805     valid &= HSMS_HDR_LEN <= ntohl(HSMS_MSG_LEN(&(*_pmessage)[0]))
00806         && _pmessage->size() >= HSMS_LEN_BYTES_LEN + HSMS_HDR_LEN
00807             && hsms_msg_base<data_t>::e_separate_req 
00808                                    >= HSMS_MSG_STYPE(&(*_pmessage)[0]);
00809     TRACE_FSM_ACTION(HSMS_SOCK_LOG_LEVEL, _name.c_str(), __func__, ": %d", valid);
00810     return valid;
00811 }
00812 bool 
00813 hsms_socket_async_t::x1()
00814 {
00815     hsms_msg_base<data_t> msg_base;
00816 
00817     bool valid = msg_base.valid(*_pmessage);
00818     TRACE_FSM_ACTION(HSMS_SOCK_LOG_LEVEL, _name.c_str(), __func__, ": %d", valid);
00819     return valid;
00820 }
00821 bool 
00822 hsms_socket_async_t::x2()
00823 {
00824     return HSMS_HDR_LEN == ntohl(HSMS_MSG_LEN(&(*_pmessage)[0]));
00825 }
00826 void 
00827 hsms_socket_async_t::z0()
00828 {
00829     _rx_error = 0;
00830     _bytes_read = 0;
00831     *_pmessage = data_t(HSMS_LEN_BYTES_LEN + HSMS_HDR_LEN, 0);
00832 }
00833 void 
00834 hsms_socket_async_t::z1()
00835 {
00836     msg_signal(_pmessage);
00837 }
00838 void 
00839 hsms_socket_async_t::z2()
00840 {
00841     data_partially_recvd();
00842 }
00843 void 
00844 hsms_socket_async_t::z3()
00845 {
00846     recv_error();
00847 }
00848 void 
00849 hsms_socket_async_t::z0_0()
00850 {
00851     _ar->stop_recv();
00852     _ar = NULL;
00853 }
00854 void 
00855 hsms_socket_async_t::z1_0()
00856 {
00857     _rx_error = 0;
00858     _bytes_read = 0;
00859     *_pmessage = data_t(HSMS_LEN_BYTES_LEN + HSMS_HDR_LEN, 0);
00860 
00861     if(NULL == _ar.get())
00862     {
00863         _ar = new async_reception_t(_sock, _name.c_str());
00864         _ar->data_partially_recvd_signal.add_handler(this, &freesecs::hsms_socket_async_t::data_rcvd_handler);
00865         _ar->data_recvd_signal.add_handler(this, &freesecs::hsms_socket_async_t::data_rcvd_handler);
00866         _ar->recv_error_signal.add_handler(this, &freesecs::hsms_socket_async_t::rcv_error_handler);
00867     }
00868 
00869     _ar->start_recv(&(*_pmessage)[0], _pmessage->size());
00870 }
00871 void 
00872 hsms_socket_async_t::z2_0()
00873 {
00874     data_msg<data_t> msg;
00875     
00876     unsigned text_len = msg.text_len(*_pmessage);
00877     unsigned total_len = HSMS_LEN_BYTES_LEN + HSMS_HDR_LEN + text_len;
00878     
00879     TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL,
00880                 "%s::z1: text length %d,"
00881                 " total length %d", 
00882                 _name.c_str(),
00883                 text_len, total_len);
00884 
00885     if(_bytes_read < total_len)
00886     {
00887         _pmessage->resize(total_len, 0);
00888     }
00889 
00890     _ar->start_recv((void*)&(*_pmessage)[HSMS_DATABYTES_OFFSET], text_len);
00891 }
00892 
00893 #if 0
00894 void 
00895 hsms_socket_async_t::process(internal_event_t e)
00896 {
00897     state_t state_old = _state;
00898 
00899     TRACE_FSM_BEGIN(HSMS_SOCK_LOG_LEVEL, _name.c_str(), _state, e);
00900 
00901     switch(_state)
00902     {
00903         case idle:
00904             if(e_i_init == e)
00905             {
00906                 z0();
00907                 _state = wtg_for_header;
00908             }
00909         break;
00910         case msg_received:
00911         case error:
00912             if(e_i_init == e)
00913             {
00914                 z0();
00915                 _state = wtg_for_header;
00916             }
00917             else if(e_i_cancelled == e)
00918             {
00919                 z5();
00920                 _state = idle;
00921             }
00922         break;
00923         case wtg_for_header:
00924             if(e_i_data_received == e)
00925             {
00926                 if(x5())
00927                 {
00928                     _state = error;
00929                 }
00930                 else if(!x1())
00931                 {
00932                     z3();
00933                 }
00934                 else if(!(x2() && x3()))
00935                 {
00936                     _state = error;
00937                 }
00938                 else if(x4())
00939                 {
00940                     z1();
00941                     _state = wtg_for_data;
00942                 }
00943                 else
00944                 {
00945                     _state = msg_received;
00946                 }
00947             }
00948             else if(e_i_cancelled == e)
00949             {
00950                 z5();
00951                 _state = idle;
00952             }
00953 #ifdef GRACEFUL_RECEIVE
00954             if(error == _state)
00955             {
00956                 z0();
00957                 state_old = idle;
00958                 _state= wtg_for_header;
00959             }
00960 #endif
00961         break;
00962         case wtg_for_data:
00963             if(e_i_data_received == e)
00964             {
00965                 if(!x6())
00966                 {
00967                     z4();
00968                 }
00969                 else if(!x5())
00970                 {
00971                     _state = msg_received;
00972                 }
00973                 else
00974                 {
00975                     _state = error;
00976                 }
00977 
00978             }
00979             else if(e_i_cancelled == e)
00980             {
00981                 z5();
00982                 _state = idle;
00983             }
00984         default:
00985         break;
00986     }
00987 
00988     if(state_old == _state)
00989     {
00990         goto sm_end;
00991     }
00992 
00993     TRACE_FSM_TRANS(HSMS_SOCK_LOG_LEVEL, _name.c_str(), state_old, _state);
00994 
00995     switch(_state)
00996     {
00997         case idle:
00998         break;
00999         case wtg_for_header:
01000             z1_0();
01001         break;
01002         case wtg_for_data:
01003             z2_0();
01004         break;
01005         case msg_received:
01006             z3_0();
01007         break;
01008         case error:
01009             z4_0();
01010         break;
01011         default:
01012         break;
01013     }
01014 
01015 sm_end:
01016     TRACE_FSM_END(HSMS_SOCK_LOG_LEVEL, _name.c_str(), _state, e);
01017     return;
01018 }
01019 #endif
01020 
01021 int 
01022 hsms_socket_async_t::data_rcvd_handler(const size_t &num_bytes)
01023 {
01024     _bytes_read += num_bytes;
01025     process(e_i_data_received);
01026     return 0;
01027 }
01028 
01029 int 
01030 hsms_socket_async_t::rcv_error_handler(const int &err)
01031 {
01032     _rx_error = err;
01033     if(ECANCELED == err)
01034     {
01035         process(e_i_deinit);
01036     }
01037     else
01038     {
01039         _bytes_read = 0;
01040         process(e_i_data_received);
01041     }
01042     return 0;
01043 }
01044 
01045 
01046 /*<<<<timed socket>>>>*/
01047 
01048 #ifdef USE_TIMED_SOCK
01049 static char
01050     buf[MAXRECV];
01051 int
01052 hsms_socket_timed_t::_recv (data_t & data, size_t size, 
01053                             bool wait_all, bool flash_unwanted, 
01054                             int timeout) const
01055 {
01056     int retcode = 0;
01057 
01058     if (MAXRECV < size)
01059     return -1;
01060     int flags = wait_all && size ? MSG_WAITALL : 0;
01061 
01062     size_t actual_size = flash_unwanted ? MAXRECV : size;
01063     memset (buf, 0, MAXRECV);
01064     int status =::recv (_sock, buf, actual_size, flags);
01065 
01066     if (status < 0)
01067     
01068     {
01069         TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL, "hsms_socket_timed_t::_recv: status: -1   errno: %d", errno);
01070         if (EWOULDBLOCK == errno)
01071         
01072         {
01073             TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL, "recv timeout in hsms_socket_timed_t::recv!!");
01074             retcode = -1;
01075         }
01076         retcode = status;
01077     }
01078     
01079     else if (status == 0)
01080     
01081     {
01082         TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL, "cnx closed from other side!");
01083         retcode = -2;
01084     }
01085     
01086     else if (size > 0)
01087     
01088     {
01089         char *begin = buf;
01090         char *end = buf + status;
01091 
01092         data.reserve (status);
01093         data.assign (begin, end);
01094     }
01095     return retcode;
01096 }
01097 int
01098 hsms_socket_timed_t::recv (data_t & d, int timeout_ms) const
01099 {
01100     if(timeout_ms)
01101     {
01102         _set_timer (_sock, timeout_ms);
01103     }
01104     return _recv (d, MAXRECV, false, false, 0);
01105 }
01106 int
01107 hsms_socket_timed_t::recvn (data_t & d, size_t size, int timeout_ms) const 
01108 {
01109     if(timeout_ms)
01110     {
01111         _set_timer (_sock, timeout_ms);
01112     }
01113     return _recv (d, size, true, false, 0);
01114 }
01115 
01116 void
01117 hsms_socket_timed_t::set_non_blocking (const bool b) 
01118 {
01119     int opts;
01120 
01121     opts = fcntl (_sock, F_GETFL);
01122     if (opts < 0)
01123     
01124     {
01125         return;
01126     }
01127     if (b)
01128     opts = (opts | O_NONBLOCK);
01129     
01130     else
01131     opts = (opts & ~O_NONBLOCK);
01132     fcntl (_sock, F_SETFL, opts);
01133 }
01134 void
01135 hsms_socket_timed_t::_set_timer (int sock_fd, int timeout_ms) 
01136 {
01137     timeval tv;
01138 
01139     if (sock_fd <= 0)
01140     {
01141         return;
01142     }
01143 
01144     if (0 >= timeout_ms)
01145     {
01146         tv.tv_sec = 0;
01147         tv.tv_usec = 0;
01148     }
01149     
01150     else
01151     
01152     {
01153         tv.tv_sec = timeout_ms / 1000;
01154         tv.tv_usec = MAX (0, MAX (0, timeout_ms - 1000 * tv.tv_sec) * 1000);
01155     }
01156     ::setsockopt (sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv));
01157     TRACE_DEBUG(HSMS_SOCK_LOG_LEVEL, "sock timer: sec=%d usec=%d", tv.tv_sec, tv.tv_usec);
01158 }
01159 #endif/*USE_TIMED_SOCK*/

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