Fri Jul 24 00:41:46 2009

Asterisk developer's documentation


iax2-parser.h File Reference

Implementation of the IAX2 protocol. More...

#include "asterisk/linkedlists.h"
#include "asterisk/aes.h"

Go to the source code of this file.

Data Structures

struct  iax_frame
struct  iax_ie_data
struct  iax_ies

Defines

#define DIRECTION_INGRESS   1
#define DIRECTION_OUTGRESS   2

Functions

void iax_frame_free (struct iax_frame *fr)
iax_frameiax_frame_new (int direction, int datalen, unsigned int cacheable)
void iax_frame_wrap (struct iax_frame *fr, struct ast_frame *f)
int iax_get_frames (void)
int iax_get_iframes (void)
int iax_get_oframes (void)
const char * iax_ie2str (int ie)
int iax_ie_append (struct iax_ie_data *ied, unsigned char ie)
int iax_ie_append_addr (struct iax_ie_data *ied, unsigned char ie, const struct sockaddr_in *sin)
int iax_ie_append_byte (struct iax_ie_data *ied, unsigned char ie, unsigned char dat)
int iax_ie_append_int (struct iax_ie_data *ied, unsigned char ie, unsigned int value)
int iax_ie_append_raw (struct iax_ie_data *ied, unsigned char ie, const void *data, int datalen)
int iax_ie_append_short (struct iax_ie_data *ied, unsigned char ie, unsigned short value)
int iax_ie_append_str (struct iax_ie_data *ied, unsigned char ie, const char *str)
int iax_parse_ies (struct iax_ies *ies, unsigned char *data, int datalen)
void iax_set_error (void(*output)(const char *data))
void iax_set_output (void(*output)(const char *data))
void iax_showframe (struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, struct sockaddr_in *sin, int datalen)


Detailed Description

Implementation of the IAX2 protocol.

Definition in file iax2-parser.h.


Define Documentation

#define DIRECTION_INGRESS   1

Definition at line 82 of file iax2-parser.h.

Referenced by iax_frame_free(), iax_frame_new(), and iaxfrdup2().

#define DIRECTION_OUTGRESS   2

Definition at line 83 of file iax2-parser.h.

Referenced by iax2_send(), iax_frame_free(), and send_trunk().


Function Documentation

void iax_frame_free ( struct iax_frame fr  ) 

Definition at line 1072 of file iax2-parser.c.

References iax_frame::afdatalen, ast_atomic_fetchadd_int(), ast_free, AST_LIST_FIRST, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, ast_threadstorage_get(), iax_frame::cacheable, iax_frame::direction, DIRECTION_INGRESS, DIRECTION_OUTGRESS, errorf, frame_cache, FRAME_CACHE_MAX_SIZE, and iax_frames::list.

Referenced by iax2_frame_free(), and network_thread().

01073 {
01074 #if !defined(LOW_MEMORY)
01075    struct iax_frames *iax_frames = NULL;
01076 #endif
01077 
01078    /* Note: does not remove from scheduler! */
01079    if (fr->direction == DIRECTION_INGRESS)
01080       ast_atomic_fetchadd_int(&iframes, -1);
01081    else if (fr->direction == DIRECTION_OUTGRESS)
01082       ast_atomic_fetchadd_int(&oframes, -1);
01083    else {
01084       errorf("Attempt to double free frame detected\n");
01085       return;
01086    }
01087    ast_atomic_fetchadd_int(&frames, -1);
01088 
01089 #if !defined(LOW_MEMORY)
01090    if (!fr->cacheable || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
01091       ast_free(fr);
01092       return;
01093    }
01094 
01095    if (iax_frames->size < FRAME_CACHE_MAX_SIZE) {
01096       fr->direction = 0;
01097       /* Pseudo-sort: keep smaller frames at the top of the list. This should
01098        * increase the chance that we pick the smallest applicable frame for use. */
01099       if (AST_LIST_FIRST(&iax_frames->list) && AST_LIST_FIRST(&iax_frames->list)->afdatalen < fr->afdatalen) {
01100          AST_LIST_INSERT_TAIL(&iax_frames->list, fr, list);
01101       } else {
01102          AST_LIST_INSERT_HEAD(&iax_frames->list, fr, list);
01103       }
01104       iax_frames->size++;
01105       return;
01106    }
01107 #endif
01108    ast_free(fr);
01109 }

struct iax_frame* iax_frame_new ( int  direction,
int  datalen,
unsigned int  cacheable 
)

Definition at line 1014 of file iax2-parser.c.

References iax_frame::afdatalen, ast_atomic_fetchadd_int(), ast_calloc, ast_calloc_cache, AST_LIST_FIRST, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_realloc, ast_threadstorage_get(), DIRECTION_INGRESS, frame_cache, FRAME_CACHE_MAX_SIZE, and iax_frame::list.

Referenced by iax2_send(), and iaxfrdup2().

01015 {
01016    struct iax_frame *fr = NULL;
01017 
01018 #if !defined(LOW_MEMORY)
01019    struct iax_frames *iax_frames = NULL;
01020    struct iax_frame *smallest = NULL;
01021 
01022    /* Attempt to get a frame from this thread's cache */
01023    if ((iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {
01024       smallest = AST_LIST_FIRST(&iax_frames->list);
01025       AST_LIST_TRAVERSE_SAFE_BEGIN(&iax_frames->list, fr, list) {
01026          if (fr->afdatalen >= datalen) {
01027             size_t afdatalen = fr->afdatalen;
01028             AST_LIST_REMOVE_CURRENT(list);
01029             iax_frames->size--;
01030             memset(fr, 0, sizeof(*fr));
01031             fr->afdatalen = afdatalen;
01032             break;
01033          } else if (smallest->afdatalen > fr->afdatalen) {
01034             smallest = fr;
01035          }
01036       }
01037       AST_LIST_TRAVERSE_SAFE_END;
01038    }
01039    if (!fr) {
01040       if (iax_frames->size >= FRAME_CACHE_MAX_SIZE && smallest) {
01041          /* Make useless cache into something more useful */
01042          AST_LIST_REMOVE(&iax_frames->list, smallest, list);
01043          if (!(fr = ast_realloc(smallest, sizeof(*fr) + datalen))) {
01044             AST_LIST_INSERT_TAIL(&iax_frames->list, smallest, list);
01045             return NULL;
01046          }
01047       } else if (!(fr = ast_calloc_cache(1, sizeof(*fr) + datalen)))
01048          return NULL;
01049       fr->afdatalen = datalen;
01050    }
01051 #else
01052    if (!(fr = ast_calloc(1, sizeof(*fr) + datalen)))
01053       return NULL;
01054    fr->afdatalen = datalen;
01055 #endif
01056 
01057 
01058    fr->direction = direction;
01059    fr->retrans = -1;
01060    fr->cacheable = cacheable;
01061    
01062    if (fr->direction == DIRECTION_INGRESS)
01063       ast_atomic_fetchadd_int(&iframes, 1);
01064    else
01065       ast_atomic_fetchadd_int(&oframes, 1);
01066    
01067    ast_atomic_fetchadd_int(&frames, 1);
01068 
01069    return fr;
01070 }

void iax_frame_wrap ( struct iax_frame fr,
struct ast_frame f 
)

Definition at line 983 of file iax2-parser.c.

References iax_frame::af, iax_frame::afdata, iax_frame::afdatalen, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_swapcopy_samples(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, f, ast_frame::frametype, ast_frame::len, LOG_ERROR, ast_frame::mallocd, ast_frame::offset, ast_frame::ptr, ast_frame::samples, ast_frame::src, and ast_frame::subclass.

Referenced by iax2_send(), iaxfrdup2(), socket_process(), and socket_process_meta().

00984 {
00985    fr->af.frametype = f->frametype;
00986    fr->af.subclass = f->subclass;
00987    fr->af.mallocd = 0;           /* Our frame is static relative to the container */
00988    fr->af.datalen = f->datalen;
00989    fr->af.samples = f->samples;
00990    fr->af.offset = AST_FRIENDLY_OFFSET;
00991    fr->af.src = f->src;
00992    fr->af.delivery.tv_sec = 0;
00993    fr->af.delivery.tv_usec = 0;
00994    fr->af.data.ptr = fr->afdata;
00995    fr->af.len = f->len;
00996    if (fr->af.datalen) {
00997       size_t copy_len = fr->af.datalen;
00998       if (copy_len > fr->afdatalen) {
00999          ast_log(LOG_ERROR, "Losing frame data because destination buffer size '%d' bytes not big enough for '%d' bytes in the frame\n",
01000             (int) fr->afdatalen, (int) fr->af.datalen);
01001          copy_len = fr->afdatalen;
01002       }
01003 #if __BYTE_ORDER == __LITTLE_ENDIAN
01004       /* We need to byte-swap slinear samples from network byte order */
01005       if ((fr->af.frametype == AST_FRAME_VOICE) && (fr->af.subclass == AST_FORMAT_SLINEAR)) {
01006          /* 2 bytes / sample for SLINEAR */
01007          ast_swapcopy_samples(fr->af.data.ptr, f->data.ptr, copy_len / 2);
01008       } else
01009 #endif
01010          memcpy(fr->af.data.ptr, f->data.ptr, copy_len);
01011    }
01012 }

int iax_get_frames ( void   ) 

Definition at line 1124 of file iax2-parser.c.

Referenced by handle_cli_iax2_show_stats().

01124 { return frames; }

int iax_get_iframes ( void   ) 

Definition at line 1125 of file iax2-parser.c.

Referenced by handle_cli_iax2_show_stats().

01125 { return iframes; }

int iax_get_oframes ( void   ) 

Definition at line 1126 of file iax2-parser.c.

Referenced by handle_cli_iax2_show_stats().

01126 { return oframes; }

const char* iax_ie2str ( int  ie  ) 

Definition at line 302 of file iax2-parser.c.

References ARRAY_LEN, infoelts, and iax2_ie::name.

Referenced by iax_ie_append_raw(), and iax_parse_ies().

00303 {
00304    int x;
00305    for (x = 0; x < ARRAY_LEN(infoelts); x++) {
00306       if (infoelts[x].ie == ie)
00307          return infoelts[x].name;
00308    }
00309    return "Unknown IE";
00310 }

int iax_ie_append ( struct iax_ie_data ied,
unsigned char  ie 
)

Definition at line 612 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by iax2_call(), and iax_firmware_append().

00613 {
00614    return iax_ie_append_raw(ied, ie, NULL, 0);
00615 }

int iax_ie_append_addr ( struct iax_ie_data ied,
unsigned char  ie,
const struct sockaddr_in *  sin 
)

Definition at line 583 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by iax2_start_transfer(), and update_registry().

00584 {
00585    return iax_ie_append_raw(ied, ie, sin, (int)sizeof(struct sockaddr_in));
00586 }

int iax_ie_append_byte ( struct iax_ie_data ied,
unsigned char  ie,
unsigned char  dat 
)

Definition at line 607 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by __auth_reject(), __auto_hangup(), authenticate_request(), iax2_call(), iax2_hangup(), iax_provision_build(), and socket_process().

00608 {
00609    return iax_ie_append_raw(ied, ie, &dat, 1);
00610 }

int iax_ie_append_int ( struct iax_ie_data ied,
unsigned char  ie,
unsigned int  value 
)

Definition at line 588 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by cache_get_callno_locked(), construct_rr(), iax2_call(), iax2_start_transfer(), iax_firmware_append(), iax_provision_build(), socket_process(), try_transfer(), and update_registry().

00589 {
00590    unsigned int newval;
00591    newval = htonl(value);
00592    return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
00593 }

int iax_ie_append_raw ( struct iax_ie_data ied,
unsigned char  ie,
const void *  data,
int  datalen 
)

Definition at line 568 of file iax2-parser.c.

References iax_ie_data::buf, errorf, iax_ie2str(), and iax_ie_data::pos.

Referenced by iax2_call(), iax2_key_rotate(), iax2_provision(), iax_firmware_append(), iax_ie_append(), iax_ie_append_addr(), iax_ie_append_byte(), iax_ie_append_int(), iax_ie_append_short(), and iax_ie_append_str().

00569 {
00570    char tmp[256];
00571    if (datalen > ((int)sizeof(ied->buf) - ied->pos)) {
00572       snprintf(tmp, (int)sizeof(tmp), "Out of space for ie '%s' (%d), need %d have %d\n", iax_ie2str(ie), ie, datalen, (int)sizeof(ied->buf) - ied->pos);
00573       errorf(tmp);
00574       return -1;
00575    }
00576    ied->buf[ied->pos++] = ie;
00577    ied->buf[ied->pos++] = datalen;
00578    memcpy(ied->buf + ied->pos, data, datalen);
00579    ied->pos += datalen;
00580    return 0;
00581 }

int iax_ie_append_short ( struct iax_ie_data ied,
unsigned char  ie,
unsigned short  value 
)

Definition at line 595 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by authenticate_request(), cache_get_callno_locked(), construct_rr(), dp_lookup(), iax2_call(), iax2_do_register(), iax2_start_transfer(), iax_provision_build(), registry_authrequest(), registry_rerequest(), socket_process(), and update_registry().

00596 {
00597    unsigned short newval;
00598    newval = htons(value);
00599    return iax_ie_append_raw(ied, ie, &newval, (int)sizeof(newval));
00600 }

int iax_ie_append_str ( struct iax_ie_data ied,
unsigned char  ie,
const char *  str 
)

Definition at line 602 of file iax2-parser.c.

References iax_ie_append_raw().

Referenced by __auth_reject(), __auto_hangup(), authenticate(), authenticate_request(), cache_get_callno_locked(), dp_lookup(), iax2_call(), iax2_do_register(), iax2_dprequest(), iax2_transfer(), iax_provision_build(), registry_authrequest(), registry_rerequest(), socket_process(), and update_registry().

00603 {
00604    return iax_ie_append_raw(ied, ie, str, strlen(str));
00605 }

int iax_parse_ies ( struct iax_ies ies,
unsigned char *  data,
int  datalen 
)

Definition at line 627 of file iax2-parser.c.

References iax_ies::adsicpe, iax_ies::apparent_addr, ast_copy_string(), ast_free, ast_str_create(), ast_str_set(), ast_variable_new(), iax_ies::authmethods, iax_ies::autoanswer, iax_ies::called_context, iax_ies::called_number, iax_ies::calling_ani, iax_ies::calling_name, iax_ies::calling_number, iax_ies::calling_pres, iax_ies::calling_tns, iax_ies::calling_ton, iax_ies::callno, iax_ies::capability, iax_ies::cause, iax_ies::causecode, iax_ies::challenge, iax_ies::codec_prefs, iax_ies::datetime, iax_ies::devicetype, iax_ies::dnid, iax_ies::dpstatus, iax_ies::enckey, iax_ies::enckeylen, iax_ies::encmethods, errorf, ast_variable::file, iax_ies::firmwarever, iax_ies::format, iax_ies::fwdata, iax_ies::fwdatalen, iax_ies::fwdesc, get_unaligned_uint16(), get_unaligned_uint32(), iax_ie2str(), IAX_IE_ADSICPE, IAX_IE_APPARENT_ADDR, IAX_IE_AUTHMETHODS, IAX_IE_AUTOANSWER, IAX_IE_CALLED_CONTEXT, IAX_IE_CALLED_NUMBER, IAX_IE_CALLING_ANI, IAX_IE_CALLING_NAME, IAX_IE_CALLING_NUMBER, IAX_IE_CALLINGPRES, IAX_IE_CALLINGTNS, IAX_IE_CALLINGTON, IAX_IE_CALLNO, IAX_IE_CAPABILITY, IAX_IE_CAUSE, IAX_IE_CAUSECODE, IAX_IE_CHALLENGE, IAX_IE_CODEC_PREFS, IAX_IE_DATETIME, IAX_IE_DEVICETYPE, IAX_IE_DNID, IAX_IE_DPSTATUS, IAX_IE_ENCKEY, IAX_IE_ENCRYPTION, IAX_IE_FIRMWAREVER, IAX_IE_FORMAT, IAX_IE_FWBLOCKDATA, IAX_IE_FWBLOCKDESC, IAX_IE_IAX_UNKNOWN, IAX_IE_LANGUAGE, IAX_IE_MD5_RESULT, IAX_IE_MSGCOUNT, IAX_IE_MUSICONHOLD, IAX_IE_OSPTOKEN, IAX_IE_PASSWORD, IAX_IE_PROVVER, IAX_IE_RDNIS, IAX_IE_REFRESH, IAX_IE_RR_DELAY, IAX_IE_RR_DROPPED, IAX_IE_RR_JITTER, IAX_IE_RR_LOSS, IAX_IE_RR_OOO, IAX_IE_RR_PKTS, IAX_IE_RSA_RESULT, IAX_IE_SAMPLINGRATE, IAX_IE_SERVICEIDENT, IAX_IE_TRANSFERID, IAX_IE_USERNAME, IAX_IE_VARIABLE, IAX_IE_VERSION, IAX_MAX_OSPBLOCK_NUM, IAX_RATE_8KHZ, iax_ies::iax_unknown, iax_ies::language, len(), iax_ies::md5_result, iax_ies::msgcount, iax_ies::musiconhold, ast_variable::name, ast_variable::next, iax_ies::ospblocklength, iax_ies::osptokenblock, outputf, iax_ies::password, iax_ies::provver, iax_ies::provverpres, iax_ies::rdnis, iax_ies::refresh, iax_ies::rr_delay, iax_ies::rr_dropped, iax_ies::rr_jitter, iax_ies::rr_loss, iax_ies::rr_ooo, iax_ies::rr_pkts, iax_ies::rsa_result, iax_ies::samprate, iax_ies::serviceident, str, iax_ies::transferid, iax_ies::username, ast_variable::value, var, iax_ies::vars, and iax_ies::version.

Referenced by socket_process().

00628 {
00629    /* Parse data into information elements */
00630    int len;
00631    int ie;
00632    char tmp[256], *tmp2;
00633    struct ast_variable *var, *var2, *prev;
00634    unsigned int count;
00635    memset(ies, 0, (int)sizeof(struct iax_ies));
00636    ies->msgcount = -1;
00637    ies->firmwarever = -1;
00638    ies->calling_ton = -1;
00639    ies->calling_tns = -1;
00640    ies->calling_pres = -1;
00641    ies->samprate = IAX_RATE_8KHZ;
00642    while(datalen >= 2) {
00643       ie = data[0];
00644       len = data[1];
00645       if (len > datalen - 2) {
00646          errorf("Information element length exceeds message size\n");
00647          return -1;
00648       }
00649       switch(ie) {
00650       case IAX_IE_CALLED_NUMBER:
00651          ies->called_number = (char *)data + 2;
00652          break;
00653       case IAX_IE_CALLING_NUMBER:
00654          ies->calling_number = (char *)data + 2;
00655          break;
00656       case IAX_IE_CALLING_ANI:
00657          ies->calling_ani = (char *)data + 2;
00658          break;
00659       case IAX_IE_CALLING_NAME:
00660          ies->calling_name = (char *)data + 2;
00661          break;
00662       case IAX_IE_CALLED_CONTEXT:
00663          ies->called_context = (char *)data + 2;
00664          break;
00665       case IAX_IE_USERNAME:
00666          ies->username = (char *)data + 2;
00667          break;
00668       case IAX_IE_PASSWORD:
00669          ies->password = (char *)data + 2;
00670          break;
00671       case IAX_IE_CODEC_PREFS:
00672          ies->codec_prefs = (char *)data + 2;
00673          break;
00674       case IAX_IE_CAPABILITY:
00675          if (len != (int)sizeof(unsigned int)) {
00676             snprintf(tmp, (int)sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00677             errorf(tmp);
00678          } else
00679             ies->capability = ntohl(get_unaligned_uint32(data + 2));
00680          break;
00681       case IAX_IE_FORMAT:
00682          if (len != (int)sizeof(unsigned int)) {
00683             snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00684             errorf(tmp);
00685          } else
00686             ies->format = ntohl(get_unaligned_uint32(data + 2));
00687          break;
00688       case IAX_IE_LANGUAGE:
00689          ies->language = (char *)data + 2;
00690          break;
00691       case IAX_IE_VERSION:
00692          if (len != (int)sizeof(unsigned short)) {
00693             snprintf(tmp, (int)sizeof(tmp),  "Expecting version to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00694             errorf(tmp);
00695          } else
00696             ies->version = ntohs(get_unaligned_uint16(data + 2));
00697          break;
00698       case IAX_IE_ADSICPE:
00699          if (len != (int)sizeof(unsigned short)) {
00700             snprintf(tmp, (int)sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00701             errorf(tmp);
00702          } else
00703             ies->adsicpe = ntohs(get_unaligned_uint16(data + 2));
00704          break;
00705       case IAX_IE_SAMPLINGRATE:
00706          if (len != (int)sizeof(unsigned short)) {
00707             snprintf(tmp, (int)sizeof(tmp), "Expecting samplingrate to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00708             errorf(tmp);
00709          } else
00710             ies->samprate = ntohs(get_unaligned_uint16(data + 2));
00711          break;
00712       case IAX_IE_DNID:
00713          ies->dnid = (char *)data + 2;
00714          break;
00715       case IAX_IE_RDNIS:
00716          ies->rdnis = (char *)data + 2;
00717          break;
00718       case IAX_IE_AUTHMETHODS:
00719          if (len != (int)sizeof(unsigned short))  {
00720             snprintf(tmp, (int)sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00721             errorf(tmp);
00722          } else
00723             ies->authmethods = ntohs(get_unaligned_uint16(data + 2));
00724          break;
00725       case IAX_IE_ENCRYPTION:
00726          if (len != (int)sizeof(unsigned short))  {
00727             snprintf(tmp, (int)sizeof(tmp), "Expecting encryption to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00728             errorf(tmp);
00729          } else
00730             ies->encmethods = ntohs(get_unaligned_uint16(data + 2));
00731          break;
00732       case IAX_IE_CHALLENGE:
00733          ies->challenge = (char *)data + 2;
00734          break;
00735       case IAX_IE_MD5_RESULT:
00736          ies->md5_result = (char *)data + 2;
00737          break;
00738       case IAX_IE_RSA_RESULT:
00739          ies->rsa_result = (char *)data + 2;
00740          break;
00741       case IAX_IE_APPARENT_ADDR:
00742          ies->apparent_addr = ((struct sockaddr_in *)(data + 2));
00743          break;
00744       case IAX_IE_REFRESH:
00745          if (len != (int)sizeof(unsigned short)) {
00746             snprintf(tmp, (int)sizeof(tmp),  "Expecting refresh to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00747             errorf(tmp);
00748          } else
00749             ies->refresh = ntohs(get_unaligned_uint16(data + 2));
00750          break;
00751       case IAX_IE_DPSTATUS:
00752          if (len != (int)sizeof(unsigned short)) {
00753             snprintf(tmp, (int)sizeof(tmp),  "Expecting dpstatus to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00754             errorf(tmp);
00755          } else
00756             ies->dpstatus = ntohs(get_unaligned_uint16(data + 2));
00757          break;
00758       case IAX_IE_CALLNO:
00759          if (len != (int)sizeof(unsigned short)) {
00760             snprintf(tmp, (int)sizeof(tmp),  "Expecting callno to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00761             errorf(tmp);
00762          } else
00763             ies->callno = ntohs(get_unaligned_uint16(data + 2));
00764          break;
00765       case IAX_IE_CAUSE:
00766          ies->cause = (char *)data + 2;
00767          break;
00768       case IAX_IE_CAUSECODE:
00769          if (len != 1) {
00770             snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len);
00771             errorf(tmp);
00772          } else {
00773             ies->causecode = data[2];
00774          }
00775          break;
00776       case IAX_IE_IAX_UNKNOWN:
00777          if (len == 1)
00778             ies->iax_unknown = data[2];
00779          else {
00780             snprintf(tmp, (int)sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len);
00781             errorf(tmp);
00782          }
00783          break;
00784       case IAX_IE_MSGCOUNT:
00785          if (len != (int)sizeof(unsigned short)) {
00786             snprintf(tmp, (int)sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00787             errorf(tmp);
00788          } else
00789             ies->msgcount = ntohs(get_unaligned_uint16(data + 2));   
00790          break;
00791       case IAX_IE_AUTOANSWER:
00792          ies->autoanswer = 1;
00793          break;
00794       case IAX_IE_MUSICONHOLD:
00795          ies->musiconhold = 1;
00796          break;
00797       case IAX_IE_TRANSFERID:
00798          if (len != (int)sizeof(unsigned int)) {
00799             snprintf(tmp, (int)sizeof(tmp), "Expecting transferid to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00800             errorf(tmp);
00801          } else
00802             ies->transferid = ntohl(get_unaligned_uint32(data + 2));
00803          break;
00804       case IAX_IE_DATETIME:
00805          if (len != (int)sizeof(unsigned int)) {
00806             snprintf(tmp, (int)sizeof(tmp), "Expecting date/time to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00807             errorf(tmp);
00808          } else
00809             ies->datetime = ntohl(get_unaligned_uint32(data + 2));
00810          break;
00811       case IAX_IE_FIRMWAREVER:
00812          if (len != (int)sizeof(unsigned short)) {
00813             snprintf(tmp, (int)sizeof(tmp), "Expecting firmwarever to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00814             errorf(tmp);
00815          } else
00816             ies->firmwarever = ntohs(get_unaligned_uint16(data + 2));   
00817          break;
00818       case IAX_IE_DEVICETYPE:
00819          ies->devicetype = (char *)data + 2;
00820          break;
00821       case IAX_IE_SERVICEIDENT:
00822          ies->serviceident = (char *)data + 2;
00823          break;
00824       case IAX_IE_FWBLOCKDESC:
00825          if (len != (int)sizeof(unsigned int)) {
00826             snprintf(tmp, (int)sizeof(tmp), "Expected block desc to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00827             errorf(tmp);
00828          } else
00829             ies->fwdesc = ntohl(get_unaligned_uint32(data + 2));
00830          break;
00831       case IAX_IE_FWBLOCKDATA:
00832          ies->fwdata = data + 2;
00833          ies->fwdatalen = len;
00834          break;
00835       case IAX_IE_ENCKEY:
00836          ies->enckey = data + 2;
00837          ies->enckeylen = len;
00838          break;
00839       case IAX_IE_PROVVER:
00840          if (len != (int)sizeof(unsigned int)) {
00841             snprintf(tmp, (int)sizeof(tmp), "Expected provisioning version to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00842             errorf(tmp);
00843          } else {
00844             ies->provverpres = 1;
00845             ies->provver = ntohl(get_unaligned_uint32(data + 2));
00846          }
00847          break;
00848       case IAX_IE_CALLINGPRES:
00849          if (len == 1)
00850             ies->calling_pres = data[2];
00851          else {
00852             snprintf(tmp, (int)sizeof(tmp), "Expected single byte callingpres, but was %d long\n", len);
00853             errorf(tmp);
00854          }
00855          break;
00856       case IAX_IE_CALLINGTON:
00857          if (len == 1)
00858             ies->calling_ton = data[2];
00859          else {
00860             snprintf(tmp, (int)sizeof(tmp), "Expected single byte callington, but was %d long\n", len);
00861             errorf(tmp);
00862          }
00863          break;
00864       case IAX_IE_CALLINGTNS:
00865          if (len != (int)sizeof(unsigned short)) {
00866             snprintf(tmp, (int)sizeof(tmp), "Expecting callingtns to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00867             errorf(tmp);
00868          } else
00869             ies->calling_tns = ntohs(get_unaligned_uint16(data + 2));   
00870          break;
00871                case IAX_IE_RR_JITTER:
00872                        if (len != (int)sizeof(unsigned int)) {
00873                                snprintf(tmp, (int)sizeof(tmp), "Expected jitter rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00874                                errorf(tmp);
00875                        } else {
00876                                ies->rr_jitter = ntohl(get_unaligned_uint32(data + 2));
00877                        }
00878                        break;
00879                case IAX_IE_RR_LOSS:
00880                        if (len != (int)sizeof(unsigned int)) {
00881                                snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00882                                errorf(tmp);
00883                        } else {
00884                                ies->rr_loss = ntohl(get_unaligned_uint32(data + 2));
00885                        }
00886                        break;
00887                case IAX_IE_RR_PKTS:
00888                        if (len != (int)sizeof(unsigned int)) {
00889                                snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00890                                errorf(tmp);
00891                        } else {
00892                                ies->rr_pkts = ntohl(get_unaligned_uint32(data + 2));
00893                        }
00894                        break;
00895                case IAX_IE_RR_DELAY:
00896                        if (len != (int)sizeof(unsigned short)) {
00897                                snprintf(tmp, (int)sizeof(tmp), "Expected loss rr to be %d bytes long but was %d\n", (int)sizeof(unsigned short), len);
00898                         errorf(tmp);
00899                        } else {
00900                                ies->rr_delay = ntohs(get_unaligned_uint16(data + 2));
00901                        }
00902                        break;
00903       case IAX_IE_RR_DROPPED:
00904          if (len != (int)sizeof(unsigned int)) {
00905             snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00906             errorf(tmp);
00907          } else {
00908             ies->rr_dropped = ntohl(get_unaligned_uint32(data + 2));
00909          }
00910          break;
00911       case IAX_IE_RR_OOO:
00912          if (len != (int)sizeof(unsigned int)) {
00913             snprintf(tmp, (int)sizeof(tmp), "Expected packets rr to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len);
00914             errorf(tmp);
00915          } else {
00916             ies->rr_ooo = ntohl(get_unaligned_uint32(data + 2));
00917          }
00918          break;
00919       case IAX_IE_VARIABLE:
00920          ast_copy_string(tmp, (char *)data + 2, len + 1);
00921          tmp2 = strchr(tmp, '=');
00922          if (tmp2)
00923             *tmp2++ = '\0';
00924          else
00925             tmp2 = "";
00926          {
00927             struct ast_str *str = ast_str_create(16);
00928             /* Existing variable or new variable? */
00929             for (var2 = ies->vars, prev = NULL; var2; prev = var2, var2 = var2->next) {
00930                if (strcmp(tmp, var2->name) == 0) {
00931                   ast_str_set(&str, 0, "%s%s", var2->value, tmp2);
00932                   var = ast_variable_new(tmp, str->str, var2->file);
00933                   var->next = var2->next;
00934                   if (prev) {
00935                      prev->next = var;
00936                   } else {
00937                      ies->vars = var;
00938                   }
00939                   snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
00940                   errorf(tmp);
00941                   ast_free(var2);
00942                   break;
00943                }
00944             }
00945             ast_free(str);
00946          }
00947 
00948          if (!var2) {
00949             var = ast_variable_new(tmp, tmp2, "");
00950             snprintf(tmp, sizeof(tmp), "Assigned (%p)%s to (%p)%s\n", var->name, var->name, var->value, var->value);
00951             errorf(tmp);
00952             var->next = ies->vars;
00953             ies->vars = var;
00954          }
00955          break;
00956       case IAX_IE_OSPTOKEN:
00957          if ((count = data[2]) < IAX_MAX_OSPBLOCK_NUM) {
00958             ies->osptokenblock[count] = (char *)data + 2 + 1;
00959             ies->ospblocklength[count] = len - 1;
00960          } else {
00961             snprintf(tmp, (int)sizeof(tmp), "Expected OSP token block index to be 0~%d but was %d\n", IAX_MAX_OSPBLOCK_NUM - 1, count);
00962             errorf(tmp);
00963          }
00964          break;
00965       default:
00966          snprintf(tmp, (int)sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len);
00967          outputf(tmp);
00968       }
00969       /* Overwrite information element with 0, to null terminate previous portion */
00970       data[0] = 0;
00971       datalen -= (len + 2);
00972       data += (len + 2);
00973    }
00974    /* Null-terminate last field */
00975    *data = '\0';
00976    if (datalen) {
00977       errorf("Invalid information element contents, strange boundary\n");
00978       return -1;
00979    }
00980    return 0;
00981 }

void iax_set_error ( void(*)(const char *data)  output  ) 

void iax_set_output ( void(*)(const char *data)  output  ) 

void iax_showframe ( struct iax_frame f,
struct ast_iax2_full_hdr fhi,
int  rx,
struct sockaddr_in *  sin,
int  datalen 
)

Definition at line 411 of file iax2-parser.c.

References ARRAY_LEN, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_IAX, ast_inet_ntoa(), ast_iax2_full_hdr::csub, ast_iax2_full_hdr::dcallno, dir, dump_ies(), f, IAX_FLAG_FULL, IAX_FLAG_RETRANS, iaxs, ast_iax2_full_hdr::iedata, ast_iax2_full_hdr::iseqno, ast_iax2_full_hdr::oseqno, outputf, ast_iax2_full_hdr::scallno, ast_iax2_full_hdr::ts, and ast_iax2_full_hdr::type.

Referenced by iax_outputframe(), and send_packet().

00412 {
00413    const char *framelist[] = {
00414       "(0?)",
00415       "DTMF_E ",
00416       "VOICE  ",
00417       "VIDEO  ",
00418       "CONTROL",
00419       "NULL   ",
00420       "IAX    ",
00421       "TEXT   ",
00422       "IMAGE  ",
00423       "HTML   ",
00424       "CNG    ",
00425       "MODEM  ",
00426       "DTMF_B ",
00427    };
00428    const char *iaxs[] = {
00429       "(0?)",
00430       "NEW    ",
00431       "PING   ",
00432       "PONG   ",
00433       "ACK    ",
00434       "HANGUP ",
00435       "REJECT ",
00436       "ACCEPT ",
00437       "AUTHREQ",
00438       "AUTHREP",
00439       "INVAL  ",
00440       "LAGRQ  ",
00441       "LAGRP  ",
00442       "REGREQ ",
00443       "REGAUTH",
00444       "REGACK ",
00445       "REGREJ ",
00446       "REGREL ",
00447       "VNAK   ",
00448       "DPREQ  ",
00449       "DPREP  ",
00450       "DIAL   ",
00451       "TXREQ  ",
00452       "TXCNT  ",
00453       "TXACC  ",
00454       "TXREADY",
00455       "TXREL  ",
00456       "TXREJ  ",
00457       "QUELCH ",
00458       "UNQULCH",
00459       "POKE   ",
00460       "PAGE   ",
00461       "MWI    ",
00462       "UNSPRTD",
00463       "TRANSFR",
00464       "PROVISN",
00465       "FWDWNLD",
00466       "FWDATA ",
00467       "TXMEDIA"
00468    };
00469    const char *cmds[] = {
00470       "(0?)",
00471       "HANGUP ",
00472       "RING   ",
00473       "RINGING",
00474       "ANSWER ",
00475       "BUSY   ",
00476       "TKOFFHK",
00477       "OFFHOOK",
00478       "CONGSTN",
00479       "FLASH  ",
00480       "WINK   ",
00481       "OPTION ",
00482       "RDKEY  ",
00483       "RDUNKEY",
00484       "PROGRES",
00485       "PROCDNG",
00486       "HOLD   ",
00487       "UNHOLD ",
00488       "VIDUPDT", };
00489    struct ast_iax2_full_hdr *fh;
00490    char retries[20];
00491    char class2[20];
00492    char subclass2[20];
00493    const char *class;
00494    const char *subclass;
00495    char *dir;
00496    char tmp[512];
00497 
00498    switch(rx) {
00499    case 0:
00500       dir = "Tx";
00501       break;
00502    case 2:
00503       dir = "TE";
00504       break;
00505    case 3:
00506       dir = "RD";
00507       break;
00508    default:
00509       dir = "Rx";
00510       break;
00511    }
00512    if (f) {
00513       fh = f->data;
00514       snprintf(retries, sizeof(retries), "%03d", f->retries);
00515    } else {
00516       fh = fhi;
00517       if (ntohs(fh->dcallno) & IAX_FLAG_RETRANS)
00518          strcpy(retries, "Yes");
00519       else
00520          strcpy(retries, " No");
00521    }
00522    if (!(ntohs(fh->scallno) & IAX_FLAG_FULL)) {
00523       /* Don't mess with mini-frames */
00524       return;
00525    }
00526    if (fh->type >= ARRAY_LEN(framelist)) {
00527       snprintf(class2, sizeof(class2), "(%d?)", fh->type);
00528       class = class2;
00529    } else {
00530       class = framelist[(int)fh->type];
00531    }
00532    if (fh->type == AST_FRAME_DTMF_BEGIN || fh->type == AST_FRAME_DTMF_END) {
00533       sprintf(subclass2, "%c", fh->csub);
00534       subclass = subclass2;
00535    } else if (fh->type == AST_FRAME_IAX) {
00536       if (fh->csub >= (int)sizeof(iaxs)/(int)sizeof(iaxs[0])) {
00537          snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
00538          subclass = subclass2;
00539       } else {
00540          subclass = iaxs[(int)fh->csub];
00541       }
00542    } else if (fh->type == AST_FRAME_CONTROL) {
00543       if (fh->csub >= (int)sizeof(cmds)/(int)sizeof(cmds[0])) {
00544          snprintf(subclass2, sizeof(subclass2), "(%d?)", fh->csub);
00545          subclass = subclass2;
00546       } else {
00547          subclass = cmds[(int)fh->csub];
00548       }
00549    } else {
00550       snprintf(subclass2, sizeof(subclass2), "%d", fh->csub);
00551       subclass = subclass2;
00552    }
00553    snprintf(tmp, sizeof(tmp), 
00554        "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
00555        dir,
00556        retries, fh->oseqno, fh->iseqno, class, subclass);
00557    outputf(tmp);
00558    snprintf(tmp, sizeof(tmp), 
00559        "   Timestamp: %05lums  SCall: %5.5d  DCall: %5.5d [%s:%d]\n",
00560        (unsigned long)ntohl(fh->ts),
00561        ntohs(fh->scallno) & ~IAX_FLAG_FULL, ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS,
00562        ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
00563    outputf(tmp);
00564    if (fh->type == AST_FRAME_IAX)
00565       dump_ies(fh->iedata, datalen);
00566 }


Generated on Fri Jul 24 00:41:46 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7