Main Page   Class Hierarchy   Compound List   File List   Compound Members  

C_SocketSCTP.cpp

00001 /*
00002  *  This program is free software; you can redistribute it and/or modify
00003  *  it under the terms of the GNU General Public License as published by
00004  *  the Free Software Foundation; either version 2 of the License, or
00005  *  (at your option) any later version.
00006  *
00007  *  This program is distributed in the hope that it will be useful,
00008  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00009  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010  *  GNU General Public License for more details.
00011  *
00012  *  You should have received a copy of the GNU General Public License
00013  *  along with this program; if not, write to the Free Software
00014  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00015  *
00016  * (c)Copyright 2006 Hewlett-Packard Development Company, LP.
00017  *
00018  */
00019 #include "C_SocketSCTP.hpp"
00020 #include "Utils.hpp"
00021 
00022 #include "iostream_t.hpp"
00023 
00024 #include <cerrno>     // for errno
00025 #include <cstring>    // for strerror
00026 #include <unistd.h>   // for close()
00027 #include <fcntl.h>
00028 
00029 #define BUFLEN       1024
00030 #define DECODEBUFLEN 2048
00031 #define MSGFLAG      0
00032 #define MAX_OUTGOING 128
00033 #define MAX_INCOMING 128
00034 
00035 #define SOCKET_ERROR(l,m) iostream_error << m << iostream_endl << iostream_flush
00036 
00037 #ifdef DEBUG_MODE
00038 #define SOCKET_DEBUG(l,m) iostream_error << m << iostream_endl << iostream_flush
00039 #else
00040 #define SOCKET_DEBUG(l,m)
00041 #endif
00042 
00043 C_SocketSCTP::C_SocketSCTP(int P_channel_id) {
00044    SOCKET_DEBUG(1, "C_SocketSCTP::C_SocketSCTP (" 
00045                 << P_channel_id 
00046                 << ") id="
00047                 << m_socket_id);
00048    m_socket_id = -1 ;
00049    m_channel_id = P_channel_id ;
00050    m_state = E_SOCKET_STATE_NOT_READY ;
00051    m_decode = NULL ;
00052    m_recv_msg_list = NULL ;
00053    m_recv_buflen = BUFLEN ;
00054    ALLOC_TABLE(m_recv_buf, char*, sizeof(char), BUFLEN);
00055 }
00056 
00057 C_SocketSCTP::C_SocketSCTP(T_SocketType P_type, 
00058                    int          P_port, 
00059                    int          P_channel_id) {
00060   
00061   SOCKET_DEBUG(1, "C_SocketSCTP::C_SocketSCTP (" 
00062                << P_port << "," << P_channel_id << ") id=" << m_socket_id);
00063 
00064   m_socket_id = -1 ;
00065   m_type = P_type ;
00066   m_src_port = P_port ;
00067   m_channel_id = P_channel_id ;
00068   m_state = E_SOCKET_STATE_NOT_READY ;
00069   m_recv_buflen = BUFLEN ;
00070   ALLOC_TABLE(m_recv_buf, char*, sizeof(char), BUFLEN);
00071   m_decode = NULL ;
00072   m_recv_msg_list = NULL ;
00073 }
00074 
00075 C_SocketSCTP::C_SocketSCTP(T_SocketType P_type, 
00076                    int          P_channel_id) {
00077   
00078   SOCKET_DEBUG(1, "C_SocketSCTP::C_SocketSCTP (" 
00079                << P_channel_id << ") id=" << m_socket_id);
00080   m_socket_id = -1 ;
00081   m_type = P_type ;
00082   m_channel_id = P_channel_id ;
00083   m_state = E_SOCKET_STATE_NOT_READY ;
00084   m_recv_buflen = BUFLEN ;
00085   ALLOC_TABLE(m_recv_buf, char*, sizeof(char), BUFLEN);
00086   m_decode = NULL ;
00087   m_recv_msg_list = NULL ;
00088 }
00089 
00090 C_pSCTPDataDecode C_SocketSCTP::get_decode() {
00091   return (m_decode);
00092 }
00093 C_ProtocolBinaryFrame* C_SocketSCTP::get_protocol() {
00094   return (m_protocol);
00095 }
00096 T_pRcvMsgCtxtList C_SocketSCTP::get_list() {
00097   return (m_recv_msg_list);
00098 }
00099 
00100 void C_SocketSCTP::set_channel_id(int P_channel_id) {
00101   SOCKET_DEBUG(1, "C_SocketSCTP::set_channel_id(" << P_channel_id << ") id=" 
00102                << m_socket_id);
00103   m_channel_id = P_channel_id ;
00104 }
00105 
00106 int C_SocketSCTP::_open(int                    P_socket_domain, 
00107                         size_t                 P_buffer_size,
00108                         C_ProtocolBinaryFrame *P_protocol) {
00109   
00110   int L_socketSCTP_type   ; /* socket type */
00111   int L_socket_domain ; /* socket domain */
00112 
00113   SOCKET_DEBUG(1, "C_SocketSCTP::_open ()");
00114 
00115   m_buffer_size = P_buffer_size ;
00116   L_socket_domain = P_socket_domain ; 
00117 
00118   /* first, determine type of socket to be used */
00119   switch (m_type) {
00120   case E_SOCKET_TCP_MODE:
00121     L_socketSCTP_type = SOCK_STREAM ;
00122     break ;
00123   case E_SOCKET_UDP_MODE:
00124     L_socketSCTP_type = SOCK_DGRAM ;
00125     break ;
00126   default:
00127     SOCKET_ERROR(0, "Unsupported transport type");
00128     exit (1);
00129   }
00130   
00131   /* allocate a free socket                 */
00132   /* Internet address family, Stream socket */
00133   m_socket_id = call_socket(L_socket_domain, L_socketSCTP_type, IPPROTO_SCTP);
00134   
00135   SOCKET_DEBUG(1, "m_socket_id [" << m_socket_id << "]");
00136 
00137   if (m_socket_id < 0) {
00138     perror("allocation failed");
00139   } else { 
00140     set_properties() ;
00141   } 
00142   
00143   m_protocol = P_protocol ;
00144 
00145   return (0) ;
00146 }
00147 
00148 C_SocketSCTP::~C_SocketSCTP() {
00149   FREE_TABLE(m_recv_buf);
00150   SOCKET_DEBUG(1, "C_SocketSCTP::~C_SocketSCTP ()");
00151 }
00152 
00153 int C_SocketSCTP::get_id () {
00154   SOCKET_DEBUG(1, "C_SocketSCTP::get_id ()");
00155   return (m_socket_id);
00156 }
00157 
00158 int C_SocketSCTP::get_channel_id () {
00159   SOCKET_DEBUG(1, "C_SocketSCTP::get_channel_id ()");
00160   return (m_channel_id);
00161 }
00162 
00163 void C_SocketSCTP::_close () {
00164   SOCKET_DEBUG(1, "C_SocketSCTP::_close ()");
00165   call_shutdown(m_socket_id, SHUT_RDWR);
00166   if (call_close(m_socket_id) != 0) {
00167     SOCKET_ERROR(0, 
00168                  "close socket ["
00169                  << m_socket_id
00170                  << "] failed ["
00171                  << errno
00172                  << "] ["
00173                  << strerror(errno)
00174                  << "]");
00175   }
00176 }
00177 
00178 
00179 void C_SocketSCTP::set_fd_set(fd_set *P_rSet, fd_set *P_wSet) {
00180   SOCKET_DEBUG(1, "C_SocketSCTP::set_fd_set () id=" << m_socket_id);
00181   switch (m_state) {
00182   case E_SOCKET_STATE_READY:
00183     FD_SET(m_socket_id, P_rSet);
00184     break ;
00185   case E_SOCKET_STATE_INPROGESS:
00186     FD_SET(m_socket_id, P_rSet);
00187     // FD_SET(m_socket_id, P_wSet); CONFIRM ?
00188     break ;
00189   case E_SOCKET_STATE_NOT_READY:
00190     break ;
00191   }
00192 }
00193 
00194 void C_SocketSCTP::set_properties() {
00195 
00196   //  int           L_sock_opt ;
00197   unsigned int  L_max_buf_size ;
00198   struct linger L_linger ;
00199   int           L_flags ;
00200 
00201   SOCKET_DEBUG(1, "C_SocketSCTP::set_properties()");
00202   if (m_type == E_SOCKET_TCP_MODE) {
00203     // max wait time after a close
00204     L_linger.l_onoff = 1;
00205     L_linger.l_linger = 0;
00206     if (call_setsockopt (m_socket_id, SOL_SOCKET, SO_LINGER,
00207                     &L_linger, sizeof (L_linger)) < 0) {
00208       SOCKET_ERROR(1, "Unable to set SO_LINGER option");
00209     }
00210   }
00211 
00212   // SCTP BEGIN
00213   {
00214     struct sctp_initmsg         init;
00215     sctp_event_subscribe        events;
00216 
00217 
00218     init.sinit_num_ostreams   = MAX_OUTGOING;
00219     init.sinit_max_instreams  = MAX_INCOMING;
00220     init.sinit_max_attempts   = 3;
00221     init.sinit_max_init_timeo = 30;
00222     if(call_setsockopt(m_socket_id, IPPROTO_SCTP, 
00223                        SCTP_INITMSG, (void*)&init, sizeof(init)) < 0) {
00224       SOCKET_ERROR(1, "Unable to set SCTP_INITMSG option");
00225     }
00226 
00227     events.sctp_data_io_event = 1;
00228     events.sctp_association_event = 1;
00229     events.sctp_address_event = 1;
00230     events.sctp_send_failure_event = 1;
00231     events.sctp_peer_error_event = 1;
00232     events.sctp_shutdown_event = 1;
00233     events.sctp_partial_delivery_event = 1;
00234     events.sctp_adaption_layer_event = 1;
00235 
00236     if(call_setsockopt(m_socket_id, IPPROTO_SCTP,
00237                        SCTP_EVENTS,&events,sizeof(events)) < 0) {
00238       SOCKET_ERROR(1, "Unable to set SCTP_EVENTS option");
00239     }
00240 
00241   // SCTP END
00242   
00243   }
00244 
00245   // size of recv buf
00246   L_max_buf_size = m_buffer_size ;
00247   if(call_setsockopt(m_socket_id, SOL_SOCKET, SO_SNDBUF,
00248                      &L_max_buf_size, sizeof(L_max_buf_size))) {
00249     SOCKET_ERROR(1,"Unable to set socket sndbuf");
00250   }
00251   
00252   // size of send buff
00253   L_max_buf_size = m_buffer_size ;
00254   if(call_setsockopt(m_socket_id, SOL_SOCKET, SO_RCVBUF,
00255                      &L_max_buf_size, sizeof(L_max_buf_size))) {
00256     SOCKET_ERROR(1, "Unable to set socket rcvbuf");
00257   }
00258   
00259   // non blocking mode (for connect only ?)
00260   L_flags = call_fcntl(m_socket_id, F_GETFL , NULL);
00261   L_flags |= O_NONBLOCK;
00262   call_fcntl(m_socket_id, F_SETFL , L_flags);
00263 
00264 }
00265 
00266 C_SocketSCTPListen::C_SocketSCTPListen(T_SocketType P_type, 
00267                                        T_pIpAddr    P_addr, 
00268                                        int          P_channel_id)   
00269   : C_SocketSCTP(P_type, P_channel_id) {
00270   SOCKET_DEBUG(0, "C_SocketSCTPListen::C_SocketSCTPListen() id=" << m_socket_id);
00271   m_source_addr_info = P_addr ;
00272 }
00273 
00274 
00275 C_SocketSCTPListen::~C_SocketSCTPListen() {
00276   SOCKET_DEBUG(0, "C_SocketSCTPListen::~C_SocketSCTPListen() id=" << m_socket_id);
00277 }
00278 
00279 size_t C_SocketSCTPListen::received_buffer (unsigned char  *P_data, 
00280                                             size_t          P_size_buf,
00281                                             struct timeval *P_time) {
00282   SOCKET_DEBUG(0, "C_SocketSCTPListen::received_buffer() id=" << m_socket_id);
00283   return (0); 
00284 }
00285 
00286 int C_SocketSCTPListen::_open (size_t                 P_buffer_size, 
00287                                C_ProtocolBinaryFrame *P_protocol) {
00288 
00289    int               L_rc          ; /* system calls return value storage */
00290 
00291    SOCKET_DEBUG(0, "C_SocketSCTPListen::_open()");
00292 
00293    L_rc = C_SocketSCTP::_open(get_domain(m_source_addr_info), 
00294                           P_buffer_size,
00295                           P_protocol) ;
00296 
00297    if (L_rc == 0) {
00298   
00299      //     set_properties() ;
00300 
00301      /* bind the socket to the newly formed address */
00302      L_rc = call_bind(m_socket_id, 
00303                       (sockaddr *)(void *)&(m_source_addr_info->m_addr),
00304                       SOCKADDR_IN_SIZE(&(m_source_addr_info->m_addr)));
00305    /* check there was no error */
00306      if (L_rc) {
00307        SOCKET_ERROR(1, "bind [" << strerror(errno) << "]");
00308      } else {
00309        
00310        if (m_type == E_SOCKET_TCP_MODE) {
00311          /* ask the system to listen for incoming connections   */
00312          /* to the address we just bound. specify that up to            */
00313          /* 5 pending connection requests will be queued by the */
00314          /* system, if we are not directly awaiting them using  */
00315          /* the accept() system call, when they arrive.         */
00316          L_rc = call_listen(m_socket_id, 5);
00317          
00318          /* check there was no error */
00319          if (L_rc) {
00320            SOCKET_ERROR(1, "listen [" << strerror(errno) << "]");
00321          }
00322        }
00323 
00324        m_state = E_SOCKET_STATE_READY ;
00325      }
00326    }
00327 
00328    return (L_rc);
00329   
00330 }
00331 
00332 C_SocketSCTP* C_SocketSCTPListen::process_fd_set (fd_set           *P_rSet, 
00333                                                   fd_set           *P_wSet,
00334                                                   C_TransportEvent *P_event) {
00335 
00336   C_SocketSCTPServer  *L_socket = NULL ;
00337   int                  L_ret ;
00338   
00339   SOCKET_DEBUG(0, "C_SocketSCTPListen::process_fd_set() id=" << m_socket_id);
00340 
00341 
00342   if (FD_ISSET(m_socket_id, P_rSet)) {
00343     NEW_VAR(L_socket, C_SocketSCTPServer(this, m_channel_id));
00344     L_ret = L_socket->_open(m_buffer_size, m_protocol) ;
00345     if (L_ret == 0) {
00346       SOCKET_DEBUG(0, "C_SocketSCTPWithData::process_fd_set() CNX");
00347       P_event->m_type = C_TransportEvent::E_TRANS_CONNECTION ;
00348       P_event->m_channel_id = m_channel_id ;
00349       P_event->m_id = L_socket->get_id() ;
00350     } else {
00351       SOCKET_DEBUG(0, "C_SocketSCTPWithData::process_fd_set() NOEVENT open failed");
00352       DELETE_VAR(L_socket);
00353       P_event->m_type = C_TransportEvent::E_TRANS_NO_EVENT ;
00354     }
00355   } else {
00356     SOCKET_DEBUG(0, "C_SocketSCTPWithData::process_fd_set() NOEVENT");
00357     P_event->m_type = C_TransportEvent::E_TRANS_NO_EVENT ;
00358   }
00359   
00360   return (L_socket);
00361 }
00362 
00363 T_SockAddrStorage* C_SocketSCTPListen::get_source_address() {
00364   return(&(m_source_addr_info->m_addr));
00365 }
00366 
00367 C_SocketSCTPServer::C_SocketSCTPServer(C_SocketSCTPListen *P_listen, 
00368                                        int                 P_channel_id)
00369   : C_SocketSCTPWithData(P_channel_id) {
00370   SOCKET_DEBUG(0, "C_SocketSCTPServer::C_SocketSCTPServer() id=" << m_socket_id);
00371   m_listen_sock = P_listen ;
00372 }
00373 
00374 C_SocketSCTPServer::~C_SocketSCTPServer() {
00375   SOCKET_DEBUG(0, "C_SocketSCTPServer::~C_SocketSCTPServer() id=" << m_socket_id);
00376 }
00377 
00378 int C_SocketSCTPServer::_open(size_t                 P_buffer_size,
00379                               C_ProtocolBinaryFrame *P_protocol) {
00380 
00381   tool_socklen_t L_size   ;
00382   int            L_rc = 0 ;
00383 
00384   SOCKET_DEBUG(0, "C_SocketSCTPServer::_open()");
00385 
00386   L_size = SOCKADDR_IN_SIZE(m_listen_sock->get_source_address());
00387   memset(&m_accepted_addr, 0, L_size);
00388 
00389   m_socket_id = call_accept (m_listen_sock->get_id(), 
00390                         (sockaddr *)(void *)&m_accepted_addr,
00391                         &L_size);
00392 
00393   m_protocol = P_protocol ;
00394 
00395   m_buffer_size = P_buffer_size ;
00396 
00397   set_properties () ;
00398 
00399   if (m_socket_id < 0) {
00400     SOCKET_ERROR(0, "accept failed for listen [" << m_listen_sock->get_id()
00401                  << "] [" << strerror(errno) << "]");
00402     L_rc = -1 ;
00403   } else {
00404     m_state = E_SOCKET_STATE_READY ;
00405   }
00406 
00407   return (L_rc);
00408 }
00409 
00410 C_SocketSCTPClient::C_SocketSCTPClient(T_SocketType P_type, 
00411                                T_pIpAddr    P_addr, 
00412                                int          P_channel_id)
00413   : C_SocketSCTPWithData(P_type, P_addr, P_channel_id) {
00414   SOCKET_DEBUG(0, "C_SocketSCTPClient::C_SocketSCTPClient() id=" << m_socket_id);
00415 }
00416 
00417 C_SocketSCTPClient::~C_SocketSCTPClient() {
00418   SOCKET_DEBUG(0, "C_SocketSCTPClient::~C_SocketSCTPClient() id=" << m_socket_id);
00419 }
00420 
00421 int C_SocketSCTPClient::_open(T_pOpenStatus          P_status,
00422                               size_t                 P_buffer_size,
00423                               C_ProtocolBinaryFrame *P_protocol) {
00424 
00425   int             L_rc = 0 ;
00426   
00427   SOCKET_DEBUG(0, "C_SocketSCTPClient::_open()");
00428   L_rc = C_SocketSCTP::_open(get_domain(m_remote_addr_info), 
00429                              P_buffer_size,
00430                              P_protocol) ;
00431 
00432   if (L_rc == 0) {
00433     //    set_properties() ;
00434     L_rc = call_connect (m_socket_id, 
00435                     (struct sockaddr*)(void*)&(m_remote_addr_info->m_addr),
00436                     SOCKADDR_IN_SIZE(&(m_remote_addr_info->m_addr))) ;
00437     if (L_rc) {
00438       if (errno != EINPROGRESS) {
00439         SOCKET_ERROR(1, "connect failed [" 
00440                      << L_rc << "][" 
00441                      << strerror(errno) << "]");
00442         *P_status = E_OPEN_FAILED ;
00443       } else {
00444         m_state = E_SOCKET_STATE_INPROGESS ;
00445         *P_status = E_OPEN_DELAYED ;
00446         L_rc = 0 ;
00447       }
00448       
00449     } else {
00450       m_state = E_SOCKET_STATE_READY ;
00451       *P_status = E_OPEN_OK ;
00452     }
00453   }
00454   return (L_rc);
00455 }
00456 
00457 C_SocketSCTPWithData::C_SocketSCTPWithData(int P_channel_id)
00458   : C_SocketSCTP (P_channel_id) {
00459   SOCKET_DEBUG(0, "C_SocketSCTPWithData::C_SocketSCTPWithData() id=" << m_socket_id);
00460   m_data_queue.clear();
00461   m_data_recv = false ;
00462   NEW_VAR(m_decode, C_SCTPDataDecode(DECODEBUFLEN));
00463   NEW_VAR(m_recv_msg_list, T_RcvMsgCtxtList());
00464   m_recv_msg_list->clear();
00465 }
00466 
00467 C_SocketSCTPWithData::C_SocketSCTPWithData(T_SocketType P_type,
00468                                            T_pIpAddr    P_addr,
00469                                            int          P_channel_id)
00470   : C_SocketSCTP (P_type, P_channel_id) {
00471   SOCKET_DEBUG(0, "C_SocketSCTPWithData::C_SocketSCTPWithData() id=" << m_socket_id);
00472   m_data_queue.clear();
00473   m_remote_addr_info = P_addr;
00474   NEW_VAR(m_decode, C_SCTPDataDecode(DECODEBUFLEN));
00475   NEW_VAR(m_recv_msg_list, T_RcvMsgCtxtList());
00476   m_recv_msg_list->clear();
00477 }
00478 
00479 
00480 C_SocketSCTPWithData::~C_SocketSCTPWithData() {
00481   SOCKET_DEBUG(0, "C_SocketSCTPWithData::~C_SocketSCTPWithData()");
00482   if (!m_data_queue.empty()) {
00483     m_data_queue.erase(m_data_queue.begin(), m_data_queue.end());
00484   }
00485   DELETE_VAR(m_decode);
00486   if (!m_recv_msg_list->empty()) {
00487     // to do delete message
00488     m_recv_msg_list->erase(m_recv_msg_list->begin(),
00489                            m_recv_msg_list->end());
00490   }
00491   DELETE_VAR(m_recv_msg_list);
00492 }
00493 
00494 void C_SocketSCTPWithData::sctp_event_handler (C_TransportEvent *P_event) {
00495 
00496   struct sctp_assoc_change *sac;
00497   struct sctp_send_failed  *ssf;
00498   struct sctp_paddr_change *spc;
00499   struct sctp_remote_error *sre;
00500   union  sctp_notification *snp;
00501   //  char   addrbuf[INET6_ADDRSTRLEN];
00502   //  const  char *ap;
00503   struct sockaddr_in *sin;
00504   struct sockaddr_in6 *sin6;
00505 
00506   snp = (union sctp_notification *)m_recv_buf;
00507 
00508   switch (snp->sn_header.sn_type) {
00509 
00510     case SCTP_ASSOC_CHANGE:
00511       sac = &snp->sn_assoc_change;
00512       SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler()" <<
00513                    "EVENT assoc_change: state="
00514                    << sac->sac_state
00515                    <<", error="
00516                    << sac->sac_error
00517                    <<", instr="
00518                    << sac->sac_inbound_streams
00519                    <<", outstr="
00520                    << sac->sac_outbound_streams);
00521 
00522       switch(sac->sac_state) {
00523       case SCTP_COMM_UP:
00524         SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00525                      "ASSOC EVENT: COMMUNICATION UP");
00526 
00527         switch (m_state) {
00528         case E_SOCKET_STATE_INPROGESS:
00529           m_state = E_SOCKET_STATE_READY ;
00530           P_event->m_type = C_TransportEvent::E_TRANS_OPEN ;
00531           P_event->m_channel_id = m_channel_id ;
00532           P_event->m_id = m_socket_id ;
00533           break ;
00534         default:
00535           break ;
00536         }
00537         break;
00538 
00539       case SCTP_COMM_LOST:
00540         SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00541                      "ASSOC EVENT: COMMUNICATION LOST");
00542         switch (m_state) {
00543 
00544         case E_SOCKET_STATE_READY:
00545           P_event->m_type = C_TransportEvent::E_TRANS_CLOSED ;
00546           P_event->m_channel_id = m_channel_id ;
00547           P_event->m_id = m_socket_id ;
00548           break ;
00549 
00550         case E_SOCKET_STATE_INPROGESS:
00551           P_event->m_type = C_TransportEvent::E_TRANS_OPEN_FAILED ;
00552           P_event->m_channel_id = m_channel_id ;
00553           P_event->m_id = m_socket_id ;
00554           break;
00555 
00556         default:
00557           break ;
00558         }
00559         break ;
00560       case SCTP_RESTART:
00561         SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00562                      "ASSOC EVENT: RESTART");
00563         break;
00564       case SCTP_SHUTDOWN_COMP:
00565         SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00566                      "ASSOC EVENT: SHUTDOWN COMPLETE");
00567         break;
00568       case SCTP_CANT_STR_ASSOC:
00569         SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00570                      "ASSOC EVENT: CANT START ASSOC "
00571                      << (uint32_t)sac->sac_assoc_id);
00572         exit(0);
00573         break;
00574       default:
00575         SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00576                      "ASSOC EVENT: UNKNOWN");
00577         break ;
00578       } 
00579 
00580       break;
00581 
00582   case SCTP_SEND_FAILED:
00583     ssf = &snp->sn_send_failed;
00584     SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " << 
00585                  "EVENT sendfailed: len="
00586                  << ssf->ssf_length
00587                  << " err=" << ssf->ssf_error);
00588     break;
00589 
00590   case SCTP_PEER_ADDR_CHANGE:
00591     spc = &snp->sn_paddr_change;
00592 
00593     switch(spc->spc_state) {
00594     case SCTP_ADDR_REACHABLE:
00595       SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " << 
00596                    "ASSOC PEER: ADDRESS REACHABLE");
00597       break;
00598     case SCTP_ADDR_UNREACHABLE:
00599       SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00600                    "ASSOC PEER: ADDRESS UNAVAILABLE");
00601       break;
00602     case SCTP_ADDR_REMOVED:
00603       SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00604                    "ASSOC PEER: ADDRESS REMOVED");
00605       break;
00606     case SCTP_ADDR_ADDED:
00607       SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00608                    "ASSOC PEER: ADDRESS ADDED");
00609       break;
00610     case SCTP_ADDR_MADE_PRIM:
00611       SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00612                    "ASSOC PEER: ADDRESS MADE PRIMARY");
00613       break;
00614     case SCTP_ADDR_CONFIRMED:
00615       SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00616                    "ASSOC PEER: ADDRESS CONFIRMED");
00617       break;
00618     default:
00619       SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00620                    "ASSOC PEER: UNKNOWN");
00621       break ;
00622     } /* end switch */
00623     
00624     if (spc->spc_aaddr.ss_family == AF_INET) {
00625       sin = (struct sockaddr_in *)&spc->spc_aaddr;
00626       //    ap = inet_ntop(AF_INET, &sin->sin_addr, addrbuf, INET6_ADDRSTRLEN);
00627     } else {
00628       sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
00629       //      ap = inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, INET6_ADDRSTRLEN);
00630     }
00631     //    printf("EVENT intf_change: %s state=%d, error=%d\n", ap, spc->spc_state, spc->spc_error);
00632     //    printf("EVENT intf_change: state=%d, error=%d\n", spc->spc_state, spc->spc_error);
00633     break;
00634 
00635   case SCTP_REMOTE_ERROR:
00636     sre = &snp->sn_remote_error;
00637     //    printf("EVENT: remote_error: err=%hu len=%hu\n", ntohs(sre->sre_error), ntohs(sre->sre_length));
00638     break;
00639 
00640   case SCTP_ADAPTION_INDICATION:
00641     SOCKET_DEBUG(0, "C_SocketSCTPWithData::sctp_event_handler() " <<
00642                  "EVENT: ADAPTATION INDICATION");
00643     break;
00644     
00645 //   case SCTP_PARTIAL_DELIVERY_EVENT: {
00646 //     printf("EVENT: PARTIAL DELIVERY\n");
00647 //     struct sctp_pdapi_event *pdapi;
00648 //     pdapi = &snp->sn_pdapi_event;
00649 //     printf("SCTP_PD-API event:%u\n",
00650 //         pdapi->pdapi_indication);
00651 //     if(pdapi->pdapi_indication == SCTP_PARTIAL_DELIVERY_ABORTED){
00652 //       printf("PDI- Aborted\n");
00653 //     }
00654 //   }
00655 //     break;
00656 
00657   case SCTP_SHUTDOWN_EVENT:
00658     SOCKET_DEBUG(0, 
00659                  "C_SocketSCTPWithData::sctp_event_handler() EVENT shutdown");
00660     break;
00661     
00662   default:
00663     SOCKET_DEBUG(0,
00664                  "C_SocketSCTPWithData::sctp_event_handler() EVENT unknown "
00665                  << snp->sn_header.sn_type);
00666     break;
00667   }
00668 
00669 }
00670 
00671 bool C_SocketSCTPWithData::sctp_recv_msg (struct msghdr *msg, 
00672                                           ssize_t *nrp, size_t cmsglen) {
00673 
00674   ssize_t nr = 0, nnr = 0;
00675   struct iovec iov[1];
00676 
00677   iov->iov_base = m_recv_buf;
00678   iov->iov_len = m_recv_buflen ;
00679   msg->msg_iov = iov;
00680   msg->msg_iovlen = 1;
00681 
00682   while(true) {
00683 
00684     msg->msg_flags = MSGFLAG ; 
00685     msg->msg_controllen = cmsglen;
00686     
00687     nnr = call_recvmsg(m_socket_id, msg, 0);
00688 
00689     if (nnr <= 0) {
00690       /* EOF or error */
00691       *nrp = nr;
00692       return (false);
00693     }
00694     
00695     nr += nnr;
00696 
00697     if ((msg->msg_flags & MSG_EOR) != 0) {
00698       *nrp = nr;
00699       return (true);
00700     }
00701 
00702     /* Realloc the buffer? */
00703     if (m_recv_buflen == (size_t)nr) {
00704       m_recv_buflen *= 2;
00705       REALLOC_VAR(m_recv_buf, char*, m_recv_buflen);
00706     }
00707 
00708     /* Set the next read offset */
00709     iov->iov_base = m_recv_buf + nr;
00710     iov->iov_len = m_recv_buflen - nr;
00711   }
00712 }
00713 
00714 void C_SocketSCTPWithData::sctp_dispatch_msg (C_TransportEvent *P_event) {
00715 
00716   T_pDataRcv L_data ;
00717 
00718   ssize_t nr;
00719   struct sctp_sndrcvinfo *sri;
00720   struct msghdr msg[1];
00721   struct cmsghdr *cmsg;
00722   char cbuf[sizeof (*cmsg) + sizeof (*sri)];
00723   struct iovec iov[1];
00724   size_t cmsglen = sizeof (*cmsg) + sizeof (*sri);
00725 
00726   m_data_recv = false ;
00727 
00728   nr = 0 ;
00729 
00730   /* Set up the msghdr structure for receiving */
00731   memset(msg, 0, sizeof (*msg));
00732   msg->msg_control = cbuf;
00733   msg->msg_controllen = cmsglen;
00734   msg->msg_flags = 0;
00735   cmsg = (struct cmsghdr *)cbuf;
00736   sri = (struct sctp_sndrcvinfo *)(cmsg + 1);
00737 
00738   /* check if something is received */
00739   while (sctp_recv_msg(msg, &nr, cmsglen)) {
00740 
00741     /* Intercept notifications here */
00742     if (msg->msg_flags & MSG_NOTIFICATION) {
00743       sctp_event_handler (P_event);
00744       continue;
00745     }
00746   
00747     iov->iov_base = m_recv_buf;
00748     iov->iov_len = nr;
00749     msg->msg_iov = iov;
00750     msg->msg_iovlen = 1;
00751   
00752     if (nr) {
00753       // data recv
00754       // write data on buffer
00755       if (m_data_recv == false) {
00756         SOCKET_DEBUG(0, "C_SocketSCTPWithData::process_fd_set() RCV " << nr);
00757         P_event->m_type = C_TransportEvent::E_TRANS_RECEIVED ;
00758         P_event->m_channel_id = m_channel_id ;
00759         P_event->m_id = m_socket_id ;
00760         m_data_recv = true ;
00761       }
00762 
00763       ALLOC_VAR(L_data, T_pDataRcv, sizeof(T_DataRcv));
00764       L_data->m_size = nr ;
00765       ALLOC_TABLE(L_data->m_data, 
00766                   unsigned char*, 
00767                   sizeof(unsigned char*), 
00768                   nr);
00769       memcpy(L_data->m_data, m_recv_buf, nr);
00770       m_data_queue.push_back(L_data);
00771 
00772     } else { break ; }
00773   
00774   }
00775 
00776   if (nr < 0) {
00777     SOCKET_DEBUG(0, "C_SocketSCTPWithData::process_fd_set() CLOSED");
00778     P_event->m_type = C_TransportEvent::E_TRANS_CLOSED ;
00779     P_event->m_channel_id = m_channel_id ;
00780     P_event->m_id = m_socket_id ;
00781   }
00782 }
00783 
00784 
00785 C_SocketSCTP* C_SocketSCTPWithData::process_fd_set (fd_set           *P_rSet,
00786                                                     fd_set           *P_wSet,
00787                                                     C_TransportEvent *P_event) {
00788 
00789   SOCKET_DEBUG(0, "C_SocketSCTPWithData::process_fd_set() id=" << m_socket_id);
00790 
00791   switch (m_state) {
00792 
00793   case E_SOCKET_STATE_READY:
00794   case E_SOCKET_STATE_INPROGESS:
00795 
00796     if (FD_ISSET(m_socket_id, P_rSet)) {
00797       sctp_dispatch_msg (P_event) ;
00798     }
00799     break ;
00800 
00801   case E_SOCKET_STATE_NOT_READY:
00802     break ;
00803     
00804   }
00805 
00806   return (NULL);
00807 }
00808 
00809 size_t C_SocketSCTPWithData::received_buffer(unsigned char *P_data, 
00810                                              size_t         P_size_buf,
00811                                              struct timeval *P_time) {
00812 
00813   size_t                  L_size = 0 ;
00814   T_DataRcvList::iterator L_it ;
00815   T_pDataRcv              L_data ;
00816   
00817   SOCKET_DEBUG(0, "C_SocketSCTPWithData::received_buffer() id=" << m_socket_id);
00818 
00819   if (!m_data_queue.empty()) {
00820     L_it = m_data_queue.begin();
00821     L_data = *L_it ;
00822     m_data_queue.erase(L_it);
00823     L_size = L_data->m_size ;
00824     SOCKET_DEBUG(0, "C_SocketSCTPWithData::received_buffer() size=" << L_size);
00825     memcpy(P_data, L_data->m_data, L_size);
00826     SOCKET_DEBUG(0, "C_SocketSCTPWithData::received_buffer() L_buf=" 
00827                  << L_data->m_data);
00828     *P_time = L_data->m_time ;
00829     FREE_TABLE(L_data->m_data);
00830     FREE_VAR(L_data) ;
00831   }
00832 
00833   SOCKET_DEBUG(0, "C_SocketSCTPWithData::received_buffer() return=" 
00834                << L_size);
00835   return (L_size);
00836 }
00837 

Generated on Wed Mar 7 14:44:58 2007 for Seagull by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002