root/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_code_2_str
  2. get_bits
  3. sngisdn_trace_interpreted_q921
  4. sngisdn_trace_raw_q921
  5. sngisdn_decode_q921
  6. sngisdn_trace_interpreted_q931
  7. sngisdn_trace_raw_q931
  8. sngisdn_decode_q931
  9. sngisdn_decode_ie
  10. print_hex_dump
  11. sngisdn_get_frame_info
  12. sngisdn_map_call

   1 /*
   2  * Copyright (c) 2010, Sangoma Technologies
   3  * David Yat Sin <davidy@sangoma.com>
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * * Redistributions of source code must retain the above copyright
  11  * notice, this list of conditions and the following disclaimer.
  12  *
  13  * * Redistributions in binary form must reproduce the above copyright
  14  * notice, this list of conditions and the following disclaimer in the
  15  * documentation and/or other materials provided with the distribution.
  16  *
  17  * * Neither the name of the original author; nor the names of any contributors
  18  * may be used to endorse or promote products derived from this software
  19  * without specific prior written permission.
  20  *
  21  *
  22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33  */
  34 
  35 #include "ftmod_sangoma_isdn.h"
  36 #include "ftmod_sangoma_isdn_trace.h"
  37 
  38 #define OCTET(x) (ieData[x-1] & 0xFF)
  39 #define MAX_DECODE_STR_LEN 2000
  40 
  41 typedef struct sngisdn_trace_info
  42 {
  43         uint8_t call_ref_flag;
  44         uint16_t call_ref;
  45         uint8_t msgtype;
  46         uint8_t bchan_no;
  47         ftdm_trace_dir_t dir;
  48 } sngisdn_frame_info_t;
  49 
  50 void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end);
  51 uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start);
  52 static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found);
  53 static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *frame_info);
  54 
  55 uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi);
  56 char* get_code_2_str(int code, struct code2str *pCodeTable);
  57 void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len);
  58 void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len);
  59 
  60 
  61 char* get_code_2_str(int code, struct code2str *pCodeTable)
  62 {
  63         struct code2str* pCode2txt;
  64         pCode2txt = pCodeTable; 
  65         while(pCode2txt) {
  66                 if(pCode2txt->code >= 0) {
  67                         if (pCode2txt->code == code) {
  68                                 return pCode2txt->text;
  69                         }
  70                         pCode2txt++;
  71                 } else {
  72                         /* This is the default value from the table */
  73                         return pCode2txt->text;
  74                 }
  75         }
  76         return (char*)"unknown";
  77 }
  78 
  79 
  80 uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi)
  81 {
  82         if (!bitLo || !bitHi) {
  83                 return 0;
  84         }
  85         if (bitLo > bitHi) {
  86                 return 0;
  87         }
  88 
  89         bitLo--;
  90         bitHi--;
  91 
  92         switch(bitHi - bitLo) {
  93                 case 0:
  94                         return (octet >> bitLo) & 0x01;
  95                 case 1:
  96                         return (octet >> bitLo) & 0x03;
  97                 case 2:
  98                         return (octet >> bitLo) & 0x07;
  99                 case 3:
 100                         return (octet >> bitLo) & 0x0F;
 101                 case 4:
 102                         return (octet >> bitLo) & 0x1F;
 103                 case 5:
 104                         return (octet >> bitLo) & 0x3F;
 105                 case 6:
 106                         return (octet >> bitLo) & 0x7F;
 107                 case 7:
 108                         return (octet >> bitLo) & 0xFF;
 109         }
 110         return 0;
 111 }
 112 
 113 void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
 114 {
 115         char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
 116         sngisdn_decode_q921(data_str, data, data_len);
 117         ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
 118         ftdm_safe_free(data_str);
 119 }
 120 
 121 void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
 122 {
 123         uint8_t                         *raw_data;
 124         ftdm_sigmsg_t           sigev;
 125         
 126         memset(&sigev, 0, sizeof(sigev));
 127 
 128         sigev.span_id = signal_data->ftdm_span->span_id;
 129         sigev.chan_id = signal_data->dchan->chan_id;
 130         sigev.channel = signal_data->dchan;
 131         sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
 132         
 133         sigev.ev_data.trace.dir = dir;
 134         sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q921;
 135         
 136         raw_data = ftdm_malloc(data_len);
 137         ftdm_assert(raw_data, "Failed to malloc");
 138         
 139         memcpy(raw_data, data, data_len);
 140         sigev.raw.data = raw_data;
 141         sigev.raw.len = data_len;
 142         sigev.raw.autofree = 1;
 143         ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
 144 }
 145 
 146 void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len)
 147 {
 148         int str_len;
 149         uint32_t i;
 150         uint8_t sapi, cr, ea, tei, ns, nr, pf, p, cmd;
 151         uint8_t frame_format = 0;
 152 
 153         str_len = 0;
 154 
 155         if(data_len >= 2) {
 156                 switch ((int)data[2] & 0x03) {
 157                         case 0: case 2:
 158                                 frame_format = I_FRAME;
 159                                 break;
 160                         case 1: 
 161                                 frame_format = S_FRAME;
 162                                 break;
 163                         case 3:
 164                                 frame_format = U_FRAME;
 165                                 break;
 166                 }
 167         }
 168 
 169         str_len+= sprintf(&str[str_len], "  format: %s\n",
 170                                                                                 get_code_2_str(frame_format, dcodQ921FrameFormatTable));
 171                                                                                 
 172         for(i=0; i < data_len; i++) {
 173                 switch(i) {
 174                         case 0: // Octet 2
 175                                 sapi = (uint8_t)((data[i]>>2) & 0x3F);
 176                                 cr = (uint8_t)((data[i]>>1) & 0x1);
 177                                 ea = (uint8_t)(data[i] & 0x1);
 178                                 str_len+= sprintf(&str[str_len], "  sapi: %03d  c/r: %01d  ea: %01d\n", sapi, cr, ea);
 179                                 break;
 180                         case 1:
 181                                 tei = (uint8_t)((data[i]>>1) & 0x7F);
 182                                 ea = (uint8_t)(data[i] & 0x1);
 183                                 str_len+= sprintf(&str[str_len], "   tei: %03d          ea: %01d\n", tei, ea);
 184                                 break;
 185                         case 2:
 186                                 switch(frame_format) {
 187                                         case I_FRAME:
 188                                                 ns = (uint8_t)((data[i]>>1) & 0x7F);
 189                                                 nr = (uint8_t)((data[i+1]>>1) & 0x7F);
 190                                                 p = (uint8_t)(data[i+1] & 0x01);
 191                                                 str_len+= sprintf(&str[str_len], "  n(s): %03d\n  n(r): %03d  p: %01d\n", ns, nr, p);
 192                                                 break;
 193                                         case S_FRAME:
 194                                                 nr = (uint8_t)((data[i+1]>>1) & 0x7F);
 195                                                 pf = (uint8_t)(data[i+1] & 0x01);
 196                                                 str_len+= sprintf(&str[str_len], "  n(r): %03d  p/f: %01d\n", nr, pf);
 197 
 198                                                 cmd = (uint8_t)((data[i]>>2) & 0x03);
 199                                                 str_len+= sprintf(&str[str_len], "   cmd: %s\n", get_code_2_str(cmd, dcodQ921SupervisoryCmdTable));
 200                                                 
 201                                                 break;
 202                                         case U_FRAME:
 203                                                 pf = (uint8_t)((data[i]>>4) & 0x01);
 204                                                 str_len+= sprintf(&str[str_len], "   p/f: %01d\n", pf);
 205 
 206                                                 cmd = (uint8_t)((data[i]>>2) & 0x03);
 207                                                 cmd |= (uint8_t)((data[i]>>5) & 0x07);
 208                                                 
 209                                                 str_len+= sprintf(&str[str_len], "   cmd: %s\n", get_code_2_str(cmd, dcodQ921UnnumberedCmdTable));
 210                                                 break;
 211                                 }
 212                                 break;
 213                 }
 214         }
 215         return;
 216 }
 217 
 218 
 219 void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
 220 {
 221         char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
 222         sngisdn_decode_q931(data_str, data, data_len);
 223         ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
 224         ftdm_safe_free(data_str);
 225 }
 226 
 227 void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
 228 {
 229         uint8_t                         *raw_data;
 230         ftdm_sigmsg_t           sigev;
 231         ftdm_channel_t *ftdmchan = NULL;
 232         sngisdn_frame_info_t  frame_info;
 233 
 234         memset(&sigev, 0, sizeof(sigev));
 235 
 236         /* Note: Mapped raw trace assume only exclusive b-channel selection is used. i.e the b-channel selected on outgoing SETUP is always used for the call */
 237         
 238         if (sngisdn_get_frame_info(data, data_len, dir, &frame_info) == FTDM_SUCCESS) {
 239                 if (sngisdn_map_call(signal_data, frame_info, &ftdmchan) == FTDM_SUCCESS) {
 240                         sigev.call_id = ftdmchan->caller_data.call_id;
 241                         sigev.span_id = ftdmchan->physical_span_id;
 242                         sigev.chan_id = ftdmchan->physical_chan_id;
 243                         sigev.channel = ftdmchan;
 244                 }
 245                 sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
 246 
 247                 sigev.ev_data.trace.dir = dir;
 248                 sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q931;
 249 
 250                 raw_data = ftdm_malloc(data_len);
 251                 ftdm_assert(raw_data, "Failed to malloc");
 252 
 253                 memcpy(raw_data, data, data_len);
 254                 sigev.raw.data = raw_data;
 255                 sigev.raw.len = data_len;
 256                 sigev.raw.autofree = 1;
 257                 ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
 258         }
 259 }
 260 
 261 void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len)
 262 {
 263         uint32_t str_len;
 264         uint8_t  prot_disc, callRefFlag;
 265         uint16_t lenCallRef, c, i;
 266         uint8_t current_codeset = 0;
 267 
 268         str_len = 0;
 269 
 270         /* Decode Protocol Discrimator */
 271         prot_disc = (uint8_t)data[0];
 272         str_len += sprintf(&str[str_len], "  Prot Disc:%s (0x%02x)\n", get_code_2_str(prot_disc, dcodQ931ProtDiscTable), prot_disc);
 273         
 274         /* Decode Call Reference */
 275         lenCallRef = (uint8_t) (data[1] & 0x0F);
 276 
 277         str_len += sprintf(&str[str_len], "  Call Ref:");
 278         c=2;
 279         callRefFlag = get_bits(data[c], 8,8);
 280         for(i=0; i<(2*lenCallRef);i++) {
 281                 if(i==0) {
 282                         str_len += sprintf(&str[str_len], "%s%s",
 283                                                 get_code_2_str((uint8_t)(data[c] & 0x70), dcodQ931CallRefHiTable),
 284                                                 get_code_2_str((uint8_t)(data[c] & 0x0F), dcodQ931CallRefLoTable));
 285                 } else {
 286                         str_len += sprintf(&str[str_len], "%s%s",
 287                                                 get_code_2_str((uint8_t)(data[c] & 0xF0), dcodQ931CallRefHiTable),
 288                                                 get_code_2_str((uint8_t)(data[c] & 0x0F), dcodQ931CallRefLoTable));
 289                 }
 290 
 291                 i=i+1;
 292                 c=c+1;
 293         }
 294         str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Originating");
 295 
 296         /* Decode message type */
 297         str_len+= sprintf(&str[str_len], "  Type:%s (0x%x)\n", get_code_2_str((int)(data[2+lenCallRef] & 0xFF), dcodQ931MsgTypeTable), (int)(data[2+lenCallRef] & 0xFF));
 298 
 299         /* go through rest of data and look for important info */
 300         for(i=3+lenCallRef; i < data_len; i++) {
 301                 switch (data[i] & 0xF8) {
 302                         case Q931_LOCKING_SHIFT:
 303                                 current_codeset = (data[i] & 0x7);
 304                                 str_len+= sprintf(&str[str_len], "Codeset shift to %d (locking)\n", current_codeset);
 305                                 continue;
 306                         case Q931_NON_LOCKING_SHIFT:
 307                                 current_codeset = (data[i] & 0x7);
 308                                 str_len+= sprintf(&str[str_len], "Codeset shift to %d (non-locking)\n", current_codeset);
 309                                 continue;
 310                 }
 311                 i+= sngisdn_decode_ie(str, &str_len, current_codeset, data, i);
 312         }
 313         print_hex_dump(str, &str_len, (uint8_t*) data, 0, data_len);
 314         return;
 315 }
 316 
 317 uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start)
 318 {
 319         unsigned char* ieData;
 320         uint8_t ieId;
 321         uint32_t len = 0;
 322         int index_end;
 323 
 324         ieData = (unsigned char*) &data[index_start];
 325 
 326         ieId = OCTET(1);
 327         len = OCTET(2); 
 328         index_end = index_start+len+1;
 329 
 330         *str_len += sprintf(&str[*str_len], "  %s:", get_code_2_str(data[index_start], dcodQ931IEIDTable));
 331         switch(ieId) {
 332                 case PROT_Q931_IE_BEARER_CAP:
 333                         {
 334                                 uint8_t codingStandard, infTransferCap, transferMode, infTransferRate, usrL1Prot;
 335                                 
 336                                 codingStandard = get_bits(OCTET(3),6,7);
 337                                 infTransferCap = get_bits(OCTET(3),1,5);
 338                                 transferMode = get_bits(OCTET(4),6,7);
 339                                 infTransferRate = get_bits(OCTET(4),1,5);
 340                                 usrL1Prot = get_bits(OCTET(5),1,5);
 341                                 
 342                                 *str_len+= sprintf(&str[*str_len], "Coding:%s(%d) TransferCap:%s(%d) TransferRate:%s(%d) L1Prot:%s(%d)\n",
 343                                                                                                                         get_code_2_str(codingStandard, dcodQ931BcCodingStandardTable), codingStandard,
 344                                                                                                                         get_code_2_str(infTransferCap, dcodQ931BcInfTransferCapTable), infTransferCap,
 345                                                                                                                         get_code_2_str(infTransferRate, dcodQ931BcInfTransferRateTable), infTransferRate,
 346                                                                                                                         get_code_2_str(usrL1Prot, dcodQ931BcusrL1ProtTable), usrL1Prot);
 347                         }
 348                         break;
 349                 case PROT_Q931_IE_CAUSE:
 350                         {
 351                                 uint8_t codingStandard, location, cause,diagOct = 5;
 352                                 codingStandard = get_bits(OCTET(3),6,7);
 353                                 location = get_bits(OCTET(3),1,4);
 354                                 
 355                                 cause = get_bits(OCTET(4),1,7);
 356 
 357                                 *str_len+= sprintf(&str[*str_len], "coding:%s(%d) location:%s(%d) val:%s(%d)\n",
 358                                                                                         get_code_2_str(codingStandard, dcodQ931BcCodingStandardTable), codingStandard,
 359                                                                                         get_code_2_str(location,dcodQ931IelocationTable), location,
 360                                                                                         get_code_2_str(cause, dcodQ931CauseCodeTable),
 361                                                                                         cause);
 362                                 switch(cause) {
 363                                         case PROT_Q931_RELEASE_CAUSE_IE_NOT_EXIST:
 364                                                 while(diagOct++ < len) {
 365                                                         *str_len+= sprintf(&str[*str_len], "  %d:IE %s(0x%02x)\n",
 366                                                                                                                         diagOct,
 367                                                                                                                         get_code_2_str(OCTET(diagOct), dcodQ931IEIDTable),
 368                                                                                                                         OCTET(diagOct));
 369                                                 }
 370                                                 break;
 371                                         case PROT_Q931_RELEASE_CAUSE_WRONG_CALL_STATE:
 372                                                 while(diagOct++ < len) {
 373                                                         *str_len+= sprintf(&str[*str_len], "  %d:Message %s(0x%02x)\n",
 374                                                                                                                         diagOct,
 375                                                                                                                         get_code_2_str(OCTET(diagOct), dcodQ931MsgTypeTable),
 376                                                                                                                         OCTET(diagOct));
 377                                                 }
 378                                                 break;
 379                                         case PROT_Q931_RECOVERY_ON_TIMER_EXPIRE:
 380                                                 *str_len+= sprintf(&str[*str_len], "  Timer T\n");
 381                                                 while(diagOct++ < len) {
 382                                                         if(OCTET(diagOct) >= ' ' && OCTET(diagOct) < 0x7f) {
 383                                                                 *str_len+= sprintf(&str[*str_len], "%c", OCTET(diagOct));
 384                                                         } else {
 385                                                                 *str_len+= sprintf(&str[*str_len], ".");
 386                                                         }
 387                                                 }
 388                                                 break;
 389                                         default:
 390                                                 while(diagOct++ < len) {
 391                                                         *str_len+= sprintf(&str[*str_len], " %d: 0x%02x\n",
 392                                                                                                                                         diagOct,
 393                                                                                                                                         OCTET(diagOct));
 394                                                 }
 395                                                 break;
 396                                 }
 397                         }               
 398                         break;          
 399                 case PROT_Q931_IE_CHANNEL_ID:
 400                         {
 401                                 uint8_t infoChannelSelection=0;
 402                                 uint8_t prefExclusive=0;
 403                                 uint8_t ifaceIdPresent=0;
 404                                 uint8_t ifaceIdentifier = 0; /* octet_3_1 */
 405                                 uint8_t chanType=0, numberMap=0, codingStandard=0;
 406                                 uint8_t channelNo = 0;
 407                                 
 408                                 infoChannelSelection = get_bits(OCTET(3),1,2);
 409                                 prefExclusive = get_bits(OCTET(3),4,4);
 410                                 ifaceIdPresent = get_bits(OCTET(3),7,7);
 411         
 412                                 if (ifaceIdPresent) {
 413                                         ifaceIdentifier= get_bits(OCTET(4),1,7);
 414                                         chanType = get_bits(OCTET(5),1,4);
 415                                         numberMap = get_bits(OCTET(5),5,5);
 416                                         codingStandard = get_bits(OCTET(5),6,7);
 417                                         channelNo = get_bits(OCTET(6),1,7);
 418                                 } else {
 419                                         chanType = get_bits(OCTET(4),1,4);
 420                                         numberMap = get_bits(OCTET(4),5,5);
 421                                         codingStandard = get_bits(OCTET(4),6,7);
 422                                         channelNo = get_bits(OCTET(5),1,7);
 423                                 }
 424                                 
 425                                 if (numberMap) {
 426                                         *str_len+= sprintf(&str[*str_len], " MAP:%s ", get_code_2_str(infoChannelSelection, dcodQ931InfoChannelSelTable));
 427                                 } else {
 428                                         *str_len+= sprintf(&str[*str_len], "No:%d ", channelNo);
 429                                 }
 430         
 431                                 *str_len+= sprintf(&str[*str_len], "Type:%s(%d) %s ", get_code_2_str(chanType,dcodQ931ChanTypeTable), chanType, (numberMap)? "Map":"");
 432                                 *str_len+= sprintf(&str[*str_len], "%s/%s \n",
 433                                                                         (prefExclusive)? "Exclusive":"Preferred", 
 434                                                                         (ifaceIdPresent)? "Explicit":"Implicit");
 435                         }
 436                         break;
 437                 case PROT_Q931_IE_CALLING_PARTY_NUMBER:
 438                         {
 439                                 uint8_t plan, type, screening = 0, presentation = 0, callingNumOct, j;
 440                                 uint8_t screeningEnabled = 0, presentationEnabled = 0;
 441                                 char callingNumDigits[32];
 442                                 memset(callingNumDigits, 0, sizeof(callingNumDigits));
 443                                 
 444                                 plan = get_bits(OCTET(3),1,4);
 445                                 type = get_bits(OCTET(3),5,7);
 446 
 447                                 if(!get_bits(OCTET(3),8,8)) {
 448                                         screening = get_bits(OCTET(4),1,2);
 449                                         presentation = get_bits(OCTET(4),6,7);
 450                                         screeningEnabled = 1;
 451                                         presentationEnabled = 1;
 452                                         callingNumOct = 4;
 453                                 } else {
 454                                         callingNumOct = 3;
 455                                 }
 456                                 if(len >= sizeof(callingNumDigits)) {   
 457                                         len = sizeof(callingNumDigits)-1;
 458                                 }
 459                                 j = 0;
 460                                 while(callingNumOct++ <= len+1) {
 461                                         callingNumDigits[j++]=ia5[get_bits(OCTET(callingNumOct),1,4)][get_bits(OCTET(callingNumOct),5,8)];
 462                                 }
 463                                 callingNumDigits[j]='\0';
 464                                 *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)",
 465                                                                                                                          
 466                                                                                                                         callingNumDigits, j,
 467                                                                                                                         get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
 468                                                                                                                         get_code_2_str(type, dcodQ931TypeofNumberTable), type);
 469                                                                                                                         
 470                                 if (presentationEnabled||screeningEnabled) {
 471                                         *str_len+= sprintf(&str[*str_len], "scr:%s(%d) pres:%s(%d)\n",
 472                                                                                                                 get_code_2_str(screening, dcodQ931ScreeningTable),      screening,
 473                                                                                                                 get_code_2_str(presentation, dcodQ931PresentationTable), presentation);
 474                                 } else {
 475                                         *str_len+= sprintf(&str[*str_len], "\n");
 476                                 }
 477                         }
 478                         break;
 479                 
 480                 case PROT_Q931_IE_CALLED_PARTY_NUMBER:
 481                         {
 482                                 uint8_t plan, type, calledNumOct,j;
 483                                 char calledNumDigits[32];
 484                                 memset(calledNumDigits, 0, sizeof(calledNumDigits));
 485                                 plan = get_bits(OCTET(3),1,4);
 486                                 type = get_bits(OCTET(3),5,7);
 487 
 488                                 if(len >= sizeof(calledNumDigits)) {    
 489                                         len = sizeof(calledNumDigits)-1;
 490                                 }
 491                                 calledNumOct = 3;
 492                                 j = 0;
 493                                 while(calledNumOct++ <= len+1) {
 494                                         calledNumDigits[j++]=ia5[get_bits(OCTET(calledNumOct),1,4)][get_bits(OCTET(calledNumOct),5,8)];
 495                                 }
 496                                 calledNumDigits[j]='\0';
 497                                 *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)\n",
 498                                                                                                                 calledNumDigits, j,
 499                                                                                                                 get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
 500                                                                                                                 get_code_2_str(type, dcodQ931TypeofNumberTable), type);
 501                         }
 502                         break;
 503                 case PROT_Q931_IE_REDIRECTING_NUMBER: //rdnis
 504                         {
 505                                 uint8_t plan, type, screening = 0, presentation = 0, reason = 0, rdnisOct,j;
 506                                 uint8_t screeningEnabled = 0, presentationEnabled = 0, reasonEnabled = 0;
 507                                 char rdnis_string[32];
 508                                 memset(rdnis_string, 0, sizeof(rdnis_string));
 509                                 rdnisOct = 5;
 510                                 plan = get_bits(OCTET(3),1,4);
 511                                 type = get_bits(OCTET(3),5,7);
 512                         
 513                                 if(!get_bits(OCTET(3),8,8)) { //Oct 3a exists
 514                                         rdnisOct++;
 515                                         screening = get_bits(OCTET(4),1,2);
 516                                         presentation = get_bits(OCTET(4),6,7);
 517                                         screeningEnabled = 1;
 518                                         presentationEnabled = 1;
 519                                         if (!get_bits(OCTET(4),8,8)) { //Oct 3b exists
 520                                                 rdnisOct++;
 521                                                 reason = get_bits(OCTET(5),1,4);
 522                                                 reasonEnabled = 1;
 523                                         }
 524                                 } 
 525         
 526                                 if(len >= sizeof(rdnis_string)) {       
 527                                         len = sizeof(rdnis_string)-1;
 528                                 }
 529                                 
 530                                 j = 0;
 531                                 while(rdnisOct++ <= len+1) {
 532                                         rdnis_string[j++]=ia5[get_bits(OCTET(rdnisOct),1,4)][get_bits(OCTET(rdnisOct),5,8)];
 533                                 }
 534         
 535                                 rdnis_string[j]='\0';   
 536                                 *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)",
 537                                                                                                                         rdnis_string, j,
 538                                                                                                                         get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
 539                                                                                                                         get_code_2_str(type, dcodQ931TypeofNumberTable), type);
 540                                                                                                                         
 541                                 if(presentationEnabled || screeningEnabled) {
 542                                         *str_len+= sprintf(&str[*str_len], "scr:%s(%d) pres:%s(%d)",
 543                                                                                                                 get_code_2_str(screening, dcodQ931ScreeningTable),      screening,
 544                                                                                                                 get_code_2_str(presentation, dcodQ931PresentationTable), presentation);
 545                                 }
 546         
 547                                 if(reasonEnabled) {
 548                                         *str_len+= sprintf(&str[*str_len], "reason:%s(%d)",
 549                                                                                                                 get_code_2_str(reason, dcodQ931ReasonTable), reason);
 550                                 }
 551                                 *str_len+= sprintf(&str[*str_len], "\n");
 552                         }
 553                         break;
 554                 case PROT_Q931_IE_USER_USER:
 555                         {
 556                                 uint8_t protDiscr = 0x00, j, uui_stringOct;
 557                                 char uui_string[32];
 558                                 memset(uui_string, 0, sizeof(uui_string));
 559                                 protDiscr = OCTET(3);
 560                                 uui_stringOct = 3;
 561                                 if (protDiscr != 0x04) { /* Non-IA5 */
 562                                         *str_len+= sprintf(&str[*str_len], "%s (0x%02x)\n",
 563                                                                                                                         get_code_2_str(protDiscr, dcodQ931UuiProtDiscrTable), protDiscr);
 564                                 } else {
 565                                         j = 0;
 566                                         
 567                                         if(len >= sizeof(uui_string)) { 
 568                                                 len = sizeof(uui_string)-1;
 569                                         }
 570                                         while(uui_stringOct++ <= len+1) {
 571                                                 uui_string[j++]=ia5[get_bits(OCTET(uui_stringOct),1,4)][get_bits(OCTET(uui_stringOct),5,8)];
 572                                         }
 573                                         uui_string[j]='\0';     
 574                                         *str_len+= sprintf(&str[*str_len], "  %s (0x%02x) <%s>\n",
 575                                                                                                                         get_code_2_str(protDiscr, dcodQ931UuiProtDiscrTable), protDiscr,
 576                                                                                                                         uui_string);
 577                                 }
 578                         }
 579                         break;
 580                 case PROT_Q931_IE_DISPLAY:
 581                         {
 582                                 uint8_t displayStrOct=2, j;
 583                                 char displayStr[82];
 584                                 memset(displayStr, 0, sizeof(displayStr));
 585                                 
 586                                 if(get_bits(OCTET(3),8,8)) {
 587                                         displayStrOct++;
 588                                 }
 589                                 j = 0;  
 590                                 if(len >= sizeof(displayStr)) { 
 591                                         len = sizeof(displayStr)-1;
 592                                 }
 593                                 while(displayStrOct++ <= len+1) {
 594                                         displayStr[j++]=ia5[get_bits(OCTET(displayStrOct),1,4)][get_bits(OCTET(displayStrOct),5,8)];
 595                                 }
 596                                 displayStr[j]='\0';
 597                                 *str_len+= sprintf(&str[*str_len], "%s(l:%d)\n",
 598                                                                                                                 displayStr, len);
 599                         }
 600                         break;
 601                 case PROT_Q931_IE_RESTART_IND:
 602                         {
 603                                 uint8_t indClass;
 604                                 indClass = get_bits(OCTET(3),1,3);
 605                                 *str_len+= sprintf(&str[*str_len], "class:%s(%d)\n",
 606                                                                                                         get_code_2_str(indClass,dcodQ931RestartIndClassTable), indClass);
 607                         }
 608                         break;
 609                 case PROT_Q931_IE_PROGRESS_IND:
 610                         {
 611                                 uint8_t codingStandard, location, progressDescr;
 612                                 codingStandard = get_bits(OCTET(3),6,7);
 613                                 location = get_bits(OCTET(3),1,4);
 614                                 progressDescr = get_bits(OCTET(4),1,7);
 615                                 *str_len+= sprintf(&str[*str_len], "coding:%s(%d) location:%s(%d) descr:%s(%d)\n",
 616                                                                                                         get_code_2_str(codingStandard,dcodQ931BcCodingStandardTable), codingStandard,
 617                                                                                                         get_code_2_str(location,dcodQ931IelocationTable), location,
 618                                                                                                         get_code_2_str(progressDescr,dcodQ931IeprogressDescrTable), progressDescr);
 619                         }
 620                         break;
 621                 case PROT_Q931_IE_KEYPAD_FACILITY:
 622                         {
 623                                 uint8_t keypadFacilityStrOct = 3, j;
 624                                 char keypadFacilityStr[82];
 625                                 memset(keypadFacilityStr, 0, sizeof(keypadFacilityStr));
 626                                 
 627                                 j = 0;  
 628                                 if(len >= sizeof(keypadFacilityStr)) {  
 629                                         len = sizeof(keypadFacilityStr)-1;
 630                                 }
 631                                 while(keypadFacilityStrOct++ < len+1) {
 632                                         keypadFacilityStr[j++]=ia5[get_bits(OCTET(keypadFacilityStrOct),1,4)][get_bits(OCTET(keypadFacilityStrOct),5,8)];
 633                                 }
 634                                 keypadFacilityStr[j]='\0';
 635                                 *str_len+= sprintf(&str[*str_len], "  digits:%s(l:%d)\n",
 636                                                                                                                 keypadFacilityStr, len);
 637                         }
 638                         break;
 639                 case PROT_Q931_IE_FACILITY:
 640                         {
 641                                 uint8_t protProfile;
 642                                 protProfile = get_bits(OCTET(3),1,5);
 643                                 *str_len+= sprintf(&str[*str_len], "Prot profile:%s(%d)\n",
 644                                                                                                         get_code_2_str(protProfile,dcodQ931IeFacilityProtProfileTable), protProfile);
 645                         }
 646                         break;
 647                 case PROT_Q931_IE_GENERIC_DIGITS:
 648                         {
 649                                 uint8_t encoding,type;
 650                                 int value = 0;
 651 
 652                                 encoding = get_bits(OCTET(3),6,8);
 653                                 type = get_bits(OCTET(3),1,5);
 654 
 655                                 *str_len+= sprintf(&str[*str_len], "encoding:%s(%d) type:%s(%d) ",
 656                                                                                                         get_code_2_str(encoding,dcodQ931GenDigitsEncodingTable), encoding,
 657                                                                                                         get_code_2_str(encoding,dcodQ931GenDigitsTypeTable), type);
 658 
 659                                 if (len > 1) {
 660                                         uint32_t j=0;
 661                                         
 662                                         while(++j < len) {
 663                                                 switch(encoding) {
 664                                                         case 0: /* BCD even */
 665                                                         case 1: /* BCD odd */
 666                                                                 {
 667                                                                         uint8_t byte = OCTET(j+3);
 668                                                                         value = (get_bits(byte,1,4)*10) + get_bits(byte,5,8) + (value*10);
 669                                                                 }
 670                                                                 break;
 671                                                         case 2: /* IA 5 */                                                      
 672                                                                 value = value*10 + OCTET(j+3)-'0';
 673                                                                 *str_len+= sprintf(&str[*str_len], "%c", OCTET(j+3));
 674                                                                 break;
 675                                                         case 3: 
 676                                                                 /* Don't know how to decode binary encoding yet */
 677                                                                 *str_len+= sprintf(&str[*str_len], "Binary encoded");
 678                                                                 break;
 679                                                 }
 680                                         }
 681                                         *str_len+= sprintf(&str[*str_len], " ");
 682                                         switch(type) {
 683                                                 case 4: /* info digits */
 684                                                         *str_len+= sprintf(&str[*str_len], "ani2:%s(%d)", get_code_2_str(value,dcodQ931LineInfoTable), value);
 685                                                         break;
 686                                                 case 5: /* Callid */
 687                                                         *str_len+= sprintf(&str[*str_len], "Caller ID not implemented\n");
 688                                                         break;
 689                                         }
 690                                 }
 691                                 *str_len+= sprintf(&str[*str_len], "\n");
 692                                 print_hex_dump(str, str_len, (uint8_t*) data, index_start, index_end);
 693                         }
 694                         break;
 695                 case PROT_Q931_IE_SENDING_COMPLETE:
 696                         /* No need to decode sending complete IE, as no additional info is available except that sending is done */
 697                         /* This is a single octet IE */
 698                         *str_len+= sprintf(&str[*str_len], "\n");
 699                         return 0;
 700                         break;
 701                 case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS:
 702                         {
 703                                 uint8_t type;
 704                                 uint8_t currentOct, j=0;
 705                                 char calling_subaddr_string[82];
 706                                 memset(calling_subaddr_string, 0, sizeof(calling_subaddr_string));
 707                                 type = get_bits(OCTET(3),5,7);
 708                                 currentOct = 3;
 709                                 while(currentOct++ <= len+1) {
 710                                                 calling_subaddr_string[j++]=ia5[get_bits(OCTET(currentOct),1,4)][get_bits(OCTET(currentOct),5,8)];
 711                                 }
 712                                 calling_subaddr_string[j++]='\0';
 713                                 *str_len += sprintf(&str[*str_len], "%s (l:%d) type:%s(%d) \n",
 714                                                                                                                 calling_subaddr_string, (j-1), get_code_2_str(type, dcodQ931TypeOfSubaddressTable), type);
 715                         }
 716                         break;
 717                 case PROT_Q931_IE_REDIRECTION_NUMBER:
 718                 case PROT_Q931_IE_NOTIFICATION_IND:
 719                 case PROT_Q931_IE_DATE_TIME:
 720                 case PROT_Q931_IE_INFORMATION_REQUEST:
 721                 case PROT_Q931_IE_SIGNAL:
 722                 case PROT_Q931_IE_SWITCHOOK:
 723                 case PROT_Q931_IE_FEATURE_ACT:
 724                 case PROT_Q931_IE_FEATURE_IND:
 725                 case PROT_Q931_IE_INFORMATION_RATE:
 726                 case PROT_Q931_IE_END_TO_END_TRANSIT_DELAY:
 727                 case PROT_Q931_IE_TRANSIT_DELAY_SELECT_IND:
 728                 case PROT_Q931_IE_PACKET_LAYER_BINARY_PARAMS:
 729                 case PROT_Q931_IE_PACKET_LAYER_WINDOW_SIZE:
 730                 case PROT_Q931_IE_PACKET_LAYER_SIZE:
 731                 case PROT_Q931_IE_TRANSIT_NETWORK_SELECTION:
 732                 case PROT_Q931_IE_LOW_LAYER_COMPAT:
 733                 case PROT_Q931_IE_HIGH_LAYER_COMPAT:
 734                 case PROT_Q931_IE_ESCAPE_FOR_EXTENSION:
 735                 case PROT_Q931_IE_CALL_IDENTITY:
 736                 case PROT_Q931_IE_CALL_STATE:
 737                 case PROT_Q931_IE_SEGMENTED_MESSAGE:
 738                 case PROT_Q931_IE_NETWORK_SPF_FACILITY:
 739                 case PROT_Q931_IE_CALLING_PARTY_SUBADDRESS:
 740                 default:
 741                         {
 742                                 *str_len += sprintf(&str[*str_len], "Undecoded");
 743                                 print_hex_dump((char*)str, str_len, data, index_start, index_end);
 744                         }
 745                         break;
 746         }
 747 
 748         return len+1;
 749 }
 750 
 751 void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end)
 752 {
 753         uint32_t k;
 754         *str_len += sprintf(&str[*str_len], "  [ ");
 755         for(k=index_start; k <= index_end; k++) {
 756                 if (k && !(k%32)) {
 757                         *str_len += sprintf(&str[*str_len], "\n    ");
 758                 }
 759                 *str_len += sprintf(&str[*str_len], "%02x ", data[k]);
 760         }
 761         *str_len += sprintf(&str[*str_len], "]\n");
 762         return;
 763 }
 764 
 765 static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *target)
 766 {
 767         uint8_t pos = 0;
 768         uint8_t flag;
 769         uint16_t ref = 0;
 770         uint8_t ref_len = 0;
 771         uint8_t bchan_no = 0;
 772         uint8_t msgtype;
 773 
 774         /* First octet is protocol discriminator */
 775         pos++;
 776         /* Second octet contains length of call reference */
 777         ref_len = data[pos++] & 0x0F;
 778 
 779         /* third octet is call reference */
 780         flag = (data[pos] & 0x80) >> 7;
 781         if (ref_len == 2) {
 782                 ref = (data[pos++] & 0x7F) << 8;
 783                 ref |= (data[pos++] & 0xFF) ;
 784         } else {
 785                 ref = (data[pos++] & 0x7F);
 786         }
 787 
 788         /* Next octet is the message type */
 789         msgtype = data[pos++] & 0x7F;
 790         
 791         /*
 792                 ftdm_log(FTDM_LOG_DEBUG, "Raw frame:call_ref:0x%04x flag:%d msgtype:%d\n", ref, flag, msgtype);
 793         */
 794         if (!ref) {
 795                 /* This is not a call specific message (RESTART for example and we do not care about it) */
 796                 return FTDM_FAIL;
 797         }
 798 
 799         /* Look for the b-channel */
 800         if (msgtype == PROT_Q931_MSGTYPE_SETUP) {
 801                 /* Try to find the b-channel no*/
 802 
 803                 for(; pos < data_len; pos++) {
 804                         uint8_t ie_id = data[pos];
 805                         uint8_t ie_len = data[pos+1];
 806 
 807                         switch(ie_id) {
 808                                 case PROT_Q931_IE_SENDING_COMPLETE:
 809                                         /* Single octet ie's do not have a length */
 810                                         ie_len = 0;
 811                                         break;
 812                                 case PROT_Q931_IE_CHANNEL_ID:
 813                                         {
 814                                                 /* Try to obtain the b-channel */
 815                                                 uint8_t ie_pos = pos+2;                                 
 816                                                 //ifaceIdPresent = get_bits(OCTET(3),7,7);
 817                                                 if (data[ie_pos] & 0x20) {
 818                                                         /* Interface type is Primary Rate */
 819                                                         ie_pos+=2;
 820                                                         bchan_no = data[ie_pos] & 0x7F;
 821                                                 } else {
 822                                                         /* Interface type is Basic Interface */
 823                                                         /* Get the channel number from info channel selection */
 824                                                         bchan_no = data[ie_pos] & 0x03;
 825                                                 }
 826                                                 ftdm_log(FTDM_LOG_DEBUG, "Found b-channel:%d\n", bchan_no);
 827                                                 goto parse_ies_done;
 828                                         }
 829                                         break;
 830                                 default:
 831                                         pos = pos+ie_len+1;
 832                         }
 833                         //ftdm_log(FTDM_LOG_DEBUG, "Decoded IE:%s\n", get_code_2_str(ie_id, dcodQ931IEIDTable));
 834                 }
 835                 if (!bchan_no) {
 836                         char tmp[1000];
 837                         print_hex_dump(tmp, 0, data, 0, data_len);                      
 838                         ftdm_log(FTDM_LOG_WARNING, "Failed to determine b-channel on SETUP message\n%s\n", tmp);
 839                 }
 840         }
 841 
 842 parse_ies_done:
 843 
 844         target->call_ref = ref;
 845         target->call_ref_flag = flag;
 846         target->msgtype = msgtype;
 847         target->bchan_no = bchan_no;
 848         target->dir = dir;
 849 
 850         return FTDM_SUCCESS;
 851 }
 852 
 853 static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found)
 854 {
 855         sngisdn_chan_data_t *sngisdn_info;
 856         ftdm_channel_t *ftdmchan = NULL;
 857         ftdm_iterator_t *chaniter = NULL;
 858         ftdm_iterator_t *curr = NULL;
 859         ftdm_status_t status = FTDM_FAIL;
 860         uint8_t outbound_call = 0;
 861         
 862         if ((!frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_OUTGOING) ||
 863                 (frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_INCOMING)) {
 864 
 865                 /* If this is an outgoing frame and this frame was sent by the originating side
 866                         of the call (frame_info.call_ref_flag == 0), then this is an outbound call */
 867                 outbound_call = 1;
 868         } else {
 869                 outbound_call = 0;
 870         }
 871 
 872         switch (frame_info.msgtype) {
 873                 case PROT_Q931_MSGTYPE_SETUP:
 874                         /* We initiated this outgoing call try to match the call reference with our internal call-id*/
 875                         if (!frame_info.bchan_no) {
 876                                 /* We were not able to determine the bchannel on this call, so we will not be able to match it anyway */
 877                                 status = FTDM_FAIL;
 878                         }
 879                         
 880                         chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
 881                         for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
 882                                 ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr));
 883                                 ftdm_channel_lock(ftdmchan);
 884                                 
 885                                 if (outbound_call) {
 886                                         sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
 887                                         if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
 888                                                 if (ftdmchan->caller_data.call_id && ftdmchan->physical_chan_id == frame_info.bchan_no) {
 889 
 890                                                         sngisdn_info->call_ref = frame_info.call_ref;
 891                                                         *found = ftdmchan;
 892                                                         status = FTDM_SUCCESS;
 893                                                 }
 894                                         }
 895                                 } else {
 896                                         if (ftdmchan->physical_chan_id == frame_info.bchan_no) {
 897                                                 *found = ftdmchan;
 898                                                 status = FTDM_SUCCESS;
 899                                         }
 900                                 }
 901                                 ftdm_channel_unlock(ftdmchan);
 902                         }
 903                         ftdm_iterator_free(chaniter);
 904                         break;
 905                 case PROT_Q931_MSGTYPE_ALERTING:
 906                 case PROT_Q931_MSGTYPE_PROCEEDING:
 907                 case PROT_Q931_MSGTYPE_PROGRESS:
 908                 case PROT_Q931_MSGTYPE_CONNECT:
 909                 case PROT_Q931_MSGTYPE_SETUP_ACK:
 910                 case PROT_Q931_MSGTYPE_CONNECT_ACK:
 911                 case PROT_Q931_MSGTYPE_USER_INFO:
 912                 case PROT_Q931_MSGTYPE_DISCONNECT:
 913                 case PROT_Q931_MSGTYPE_RELEASE:
 914                 case PROT_Q931_MSGTYPE_RELEASE_ACK:
 915                 case PROT_Q931_MSGTYPE_RELEASE_COMPLETE:
 916                 case PROT_Q931_MSGTYPE_FACILITY:
 917                 case PROT_Q931_MSGTYPE_NOTIFY:
 918                 case PROT_Q931_MSGTYPE_STATUS_ENQUIRY:
 919                 case PROT_Q931_MSGTYPE_INFORMATION:
 920                 case PROT_Q931_MSGTYPE_STATUS:
 921                         /* Look for an outbound call on that span and and try to match the call-id */
 922                         chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
 923                         for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
 924                                 ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr));
 925                                 ftdm_channel_lock(ftdmchan);
 926                                 sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
 927                                 if (outbound_call) {
 928                                         if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
 929                                                 if (sngisdn_info->call_ref == frame_info.call_ref) {
 930 
 931                                                         *found = ftdmchan;
 932                                                         status = FTDM_SUCCESS;
 933                                                 }
 934                                         }
 935                                 } else {
 936                                         if (sngisdn_info && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
 937                                                 if (sngisdn_info->call_ref && sngisdn_info->call_ref == frame_info.call_ref) {
 938 
 939                                                         *found = ftdmchan;
 940                                                         status = FTDM_SUCCESS;
 941                                                 }
 942                                         }
 943                                 }
 944                                 ftdm_channel_unlock(ftdmchan);
 945                         }
 946                         ftdm_iterator_free(chaniter);
 947                         break;
 948                 default:
 949                         /* This frame is not call specific, ignore */
 950                         break;
 951         }
 952         if (status == FTDM_SUCCESS) {
 953                 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Mapped %s with Call Ref:%04x to call-id:%d\n", get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref, (*found)->caller_data.call_id);
 954         } else {
 955                 /* We could not map this frame to a call-id */
 956                 ftdm_log(FTDM_LOG_DEBUG, "Failed to map %s with Call Ref:%04x to local call\n",
 957                                  get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref);
 958         }
 959 
 960         return status;
 961 }
 962 
 963 
 964 

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