root/src/m3ua_client.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. create_conn_socket
  2. m3uac_connection_close
  3. m3uac_connection_open
  4. m3uac_exec_command
  5. m3uac_connection_read
  6. m3uac_connection_readp
  7. m3uac_connection_write
  8. m3uac_call_init
  9. m3uac_event_init
  10. m3uac_event_id_name

   1 /*
   2  *  m3ua_client.c
   3  *  freetdm
   4  *
   5  *  Created by Shane Burrell on 4/3/08.
   6  *  Copyright 2008 Shane Burrell. All rights reserved.
   7  *
   8  * 
   9   * Copyright (c) 2007, Anthony Minessale II, Nenad Corbic
  10  * Redistribution and use in source and binary forms, with or without
  11  * modification, are permitted provided that the following conditions
  12  * are met:
  13  * 
  14  * * Redistributions of source code must retain the above copyright
  15  * notice, this list of conditions and the following disclaimer.
  16  * 
  17  * * Redistributions in binary form must reproduce the above copyright
  18  * notice, this list of conditions and the following disclaimer in the
  19  * documentation and/or other materials provided with the distribution.
  20  * 
  21  * * Neither the name of the original author; nor the names of any contributors
  22  * may be used to endorse or promote products derived from this software
  23  * without specific prior written permission.
  24  * 
  25  * 
  26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  27  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  28  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  29  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  30  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  31  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  32  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  33  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  34  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  35  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  36  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  37  */
  38 
  39 #if HAVE_NETDB_H
  40 #include <netdb.h>
  41 #endif
  42 
  43 #include "freetdm.h"
  44 #include <m3ua_client.h>
  45 
  46 
  47 #ifndef HAVE_GETHOSTBYNAME_R
  48 extern int gethostbyname_r (const char *__name,
  49                                                         struct hostent *__result_buf,
  50                                                         char *__buf, size_t __buflen,
  51                                                         struct hostent **__result,
  52                                                         int *__h_errnop);
  53 #endif
  54 
  55 struct m3uac_map {
  56         uint32_t event_id;
  57         const char *name;
  58 };
  59 
  60 static struct m3uac_map m3uac_table[] = {
  61         {M3UA_EVENT_CALL_START, "CALL_START"},
  62         {M3UA_EVENT_CALL_START_ACK, "CALL_START_ACK"},
  63         {M3UA_EVENT_CALL_START_NACK, "CALL_START_NACK"},
  64         {M3UA_EVENT_CALL_START_NACK_ACK, "CALL_START_NACK_ACK"},
  65         {M3UA_EVENT_CALL_ANSWERED, "CALL_ANSWERED"},
  66         {M3UA_EVENT_CALL_STOPPED, "CALL_STOPPED"},
  67         {M3UA_EVENT_CALL_STOPPED_ACK, "CALL_STOPPED_ACK"},
  68         {M3UA_EVENT_SYSTEM_RESTART, "SYSTEM_RESTART"},
  69         {M3UA_EVENT_SYSTEM_RESTART_ACK, "SYSTEM_RESTART_ACK"},
  70         {M3UA_EVENT_HEARTBEAT, "HEARTBEAT"},
  71         {M3UA_EVENT_INSERT_CHECK_LOOP, "LOOP START"},
  72         {M3UA_EVENT_REMOVE_CHECK_LOOP, "LOOP STOP"} 
  73 }; 
  74 
  75 
  76 
  77 static int create_conn_socket(m3uac_connection_t *mcon, char *local_ip, int local_port, char *ip, int port)
  78 {
  79         int rc;
  80         struct hostent *result, *local_result;
  81         char buf[512], local_buf[512];
  82         int err = 0;
  83 
  84         memset(&mcon->remote_hp, 0, sizeof(mcon->remote_hp));
  85         memset(&mcon->local_hp, 0, sizeof(mcon->local_hp));
  86         mcon->socket = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
  87  
  88         ftdm_log(FTDM_LOG_DEBUG, "Creating L=%s:%d R=%s:%d\n",
  89                         local_ip,local_port,ip,port);
  90 
  91         if (mcon->socket >= 0) {
  92                 int flag;
  93 
  94                 flag = 1;
  95                 gethostbyname_r(ip, &mcon->remote_hp, buf, sizeof(buf), &result, &err);
  96                 gethostbyname_r(local_ip, &mcon->local_hp, local_buf, sizeof(local_buf), &local_result, &err);
  97                 if (result && local_result) {
  98                         mcon->remote_addr.sin_family = mcon->remote_hp.h_addrtype;
  99                         memcpy((char *) &mcon->remote_addr.sin_addr.s_addr, mcon->remote_hp.h_addr_list[0], mcon->remote_hp.h_length);
 100                         mcon->remote_addr.sin_port = htons(port);
 101 
 102                         mcon->local_addr.sin_family = mcon->local_hp.h_addrtype;
 103                         memcpy((char *) &mcon->local_addr.sin_addr.s_addr, mcon->local_hp.h_addr_list[0], mcon->local_hp.h_length);
 104                         mcon->local_addr.sin_port = htons(local_port);
 105 
 106 
 107                         setsockopt(mcon->socket, IPPROTO_SCTP, SCTP_NODELAY, (char *)&flag, sizeof(int));
 108 
 109                         rc=listen(mcon->socket,100);
 110                         if (rc) {
 111                         close(mcon->socket);
 112                         mcon->socket = -1;
 113                         
 114                         }
 115                 }
 116         }
 117 
 118         ftdm_mutex_create(&mcon->mutex);
 119 
 120         return mcon->socket;
 121 }
 122 
 123 int m3uac_connection_close(m3uac_connection_t *mcon)
 124 {
 125         if (mcon->socket > -1) {
 126                 close(mcon->socket);
 127         }
 128 
 129         ftdm_mutex_lock(mcon->mutex);
 130         ftdm_mutex_unlock(mcon->mutex);
 131         ftdm_mutex_destroy(&mcon->mutex);
 132         memset(mcon, 0, sizeof(*mcon));
 133         mcon->socket = -1;
 134 
 135         return 0;
 136 }
 137 
 138 int m3uac_connection_open(m3uac_connection_t *mcon, char *local_ip, int local_port, char *ip, int port)
 139 {
 140         create_conn_socket(mcon, local_ip, local_port, ip, port);
 141         return mcon->socket;
 142 }
 143 
 144 
 145 int m3uac_exec_command(m3uac_connection_t *mcon, int span, int chan, int id, int cmd, int cause)
 146 {
 147     m3uac_event_t oevent;
 148     int retry = 5;
 149 
 150     m3uac_event_init(&oevent, cmd, chan, span);
 151     oevent.release_cause = cause;
 152 
 153         if (cmd == SIGBOOST_EVENT_SYSTEM_RESTART) {
 154                 mcon->rxseq_reset = 1;
 155                 mcon->txseq = 0;
 156                 mcon->rxseq = 0;
 157                 mcon->txwindow = 0;
 158         }
 159 
 160     if (id >= 0) {
 161         oevent.call_setup_id = id;
 162     }
 163 
 164     while (m3uac_connection_write(mcon, &oevent) <= 0) {
 165         if (--retry <= 0) {
 166             ftdm_log(FTDM_LOG_CRIT, "Failed to tx on M3UA socket: %s\n", strerror(errno));
 167             return -1;
 168         } else {
 169             ftdm_log(FTDM_LOG_WARNING, "Failed to tx on M3UA socket: %s :retry %i\n", strerror(errno), retry);
 170                         ftdm_sleep(1);
 171         }
 172     }
 173 
 174     return 0;
 175 }
 176 
 177 
 178 
 179 m3uac_event_t *m3uac_connection_read(m3uac_connection_t *mcon, int iteration)
 180 {
 181         unsigned int fromlen = sizeof(struct sockaddr_in);
 182         int bytes = 0;
 183 
 184         bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, 
 185                                          (struct sockaddr *) &mcon->local_addr, &fromlen);
 186 
 187         if (bytes == sizeof(mcon->event) || bytes == (sizeof(mcon->event)-sizeof(uint32_t))) {
 188 
 189                 if (mcon->rxseq_reset) {
 190                         if (mcon->event.event_id == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) {
 191                                 ftdm_log(FTDM_LOG_DEBUG, "Rx sync ok\n");
 192                                 mcon->rxseq = mcon->event.fseqno;
 193                                 return &mcon->event;
 194                         }
 195                         errno=EAGAIN;
 196                         ftdm_log(FTDM_LOG_DEBUG, "Waiting for rx sync...\n");
 197                         return NULL;
 198                 }
 199                 
 200                 mcon->txwindow = mcon->txseq - mcon->event.bseqno;
 201                 mcon->rxseq++;
 202 
 203                 if (mcon->rxseq != mcon->event.fseqno) {
 204                         ftdm_log(FTDM_LOG_CRIT, "Invalid Sequence Number Expect=%i Rx=%i\n", mcon->rxseq, mcon->event.fseqno);
 205                         return NULL;
 206                 }
 207 
 208                 return &mcon->event;
 209         } else {
 210                 if (iteration == 0) {
 211                         ftdm_log(FTDM_LOG_CRIT, "Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
 212                         return NULL;
 213                 }
 214         }
 215 
 216         return NULL;
 217 }
 218 
 219 m3uac_event_t *m3uac_connection_readp(m3uac_connection_t *mcon, int iteration)
 220 {
 221         unsigned int fromlen = sizeof(struct sockaddr_in);
 222         int bytes = 0;
 223 
 224         bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, (struct sockaddr *) &mcon->local_addr, &fromlen);
 225 
 226         if (bytes == sizeof(mcon->event) || bytes == (sizeof(mcon->event)-sizeof(uint32_t))) {
 227                 return &mcon->event;
 228         } else {
 229                 if (iteration == 0) {
 230                         ftdm_log(FTDM_LOG_CRIT, "Critical Error: PQ Invalid Event lenght from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
 231                         return NULL;
 232                 }
 233         }
 234 
 235         return NULL;
 236 }
 237 
 238 
 239 int m3uac_connection_write(m3uac_connection_t *mcon, ss7bc_event_t *event)
 240 {
 241         int err;
 242 
 243         if (!event || mcon->socket < 0 || !mcon->mutex) {
 244                 ftdm_log(FTDM_LOG_DEBUG,  "Critical Error: No Event Device\n");
 245                 return -EINVAL;
 246         }
 247 
 248         if (event->span > 16 || event->chan > 31) {
 249                 ftdm_log(FTDM_LOG_CRIT, "Critical Error: TX Cmd=%s Invalid Span=%i Chan=%i\n", m3uac_event_id_name(event->event_id), event->span,event->chan);
 250                 return -1;
 251         }
 252 
 253         gettimeofday(&event->tv,NULL);
 254         
 255         ftdm_mutex_lock(mcon->mutex);
 256         event->fseqno = mcon->txseq++;
 257         event->bseqno = mcon->rxseq;
 258         err = sendto(mcon->socket, event, sizeof(m3uac_event_t), 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr));
 259         ftdm_mutex_unlock(mcon->mutex);
 260 
 261         if (err != sizeof(m3uac_event_t)) {
 262                 err = -1;
 263         }
 264         
 265         ftdm_log(FTDM_LOG_DEBUG, "TX EVENT: %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i Cd=[%s] Ci=[%s]\n",
 266                         m3uac_event_id_name(event->event_id),
 267                         event->event_id,
 268                         event->span+1,
 269                         event->chan+1,
 270                         event->release_cause,
 271                         event->call_setup_id,
 272                         event->fseqno,
 273                         (event->called_number_digits_count ? (char *) event->called_number_digits : "N/A"),
 274                         (event->calling_number_digits_count ? (char *) event->calling_number_digits : "N/A")
 275                         );
 276 
 277         return err;
 278 }
 279 
 280 void m3uac_call_init(m3uac_event_t *event, const char *calling, const char *called, int setup_id)
 281 {
 282         memset(event, 0, sizeof(m3uac_event_t));
 283         event->event_id = M3UA_EVENT_CALL_START;
 284 
 285         if (calling) {
 286                 strncpy((char*)event->calling_number_digits, calling, sizeof(event->calling_number_digits)-1);
 287                 event->calling_number_digits_count = strlen(calling);
 288         }
 289 
 290         if (called) {
 291                 strncpy((char*)event->called_number_digits, called, sizeof(event->called_number_digits)-1);
 292                 event->called_number_digits_count = strlen(called);
 293         }
 294                 
 295         event->call_setup_id = setup_id;
 296         
 297 }
 298 
 299 void m3uac_event_init(m3uac_event_t *event, m3uac_event_id_t event_id, int chan, int span) 
 300 {
 301         memset(event, 0, sizeof(ss7bc_event_t));
 302         event->event_id = event_id;
 303         event->chan = chan;
 304         event->span = span;
 305 }
 306 
 307 const char *m3uac_event_id_name(uint32_t event_id)
 308 {
 309         unsigned int x;
 310         const char *ret = NULL;
 311 
 312         for (x = 0 ; x < sizeof(m3uac_table)/sizeof(struct m3uac_map); x++) {
 313                 if (m3uac_table[x].event_id == event_id) {
 314                         ret = m3uac_table[x].name;
 315                         break;
 316                 }
 317         }
 318 
 319         return ret;
 320 }
 321 
 322 /* For Emacs:
 323  * Local Variables:
 324  * mode:c
 325  * indent-tabs-mode:t
 326  * tab-width:4
 327  * c-basic-offset:4
 328  * End:
 329  * For VIM:
 330  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
 331  */
 332 
 333 

/* [<][>][^][v][top][bottom][index][help] */