diff options
author | Richard Mudgett <rmudgett@digium.com> | 2009-04-21 17:44:01 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2009-04-21 17:44:01 +0000 |
commit | 6bb2b6c096cc8c56d0a01fb17d9723b8c5b92d0e (patch) | |
tree | 274e051566d5d31050dc6c64f1ae79bc83bf38a5 /channels/misdn | |
parent | cf95f3a1180b6e3078ca3ceaf1a28570ba340ace (diff) |
Added CCBS/CCNR Party A support and enhanced COLP support.
This change adds the following features to chan_misdn:
* CCBS/CCNR Party A support for PTMP and PTP modes.
* Enhances COLP support for call diversion and explicit call transfer.
These enhanced features require a modified version of mISDN.
The latest modified mISDN v1.1.x based version is available at:
http://svn.digium.com/svn/thirdparty/mISDN/trunk
http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
Taged versions of the modified mISDN code are available under:
http://svn.digium.com/svn/thirdparty/mISDN/tags
http://svn.digium.com/svn/thirdparty/mISDNuser/tags
Review: http://reviewboard.digium.com/r/218/
Merged from team/rmudgett/misdn_facility branch.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@189735 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/misdn')
-rw-r--r-- | channels/misdn/chan_misdn_config.h | 1 | ||||
-rw-r--r-- | channels/misdn/ie.c | 100 | ||||
-rw-r--r-- | channels/misdn/isdn_lib.c | 1256 | ||||
-rw-r--r-- | channels/misdn/isdn_lib.h | 86 | ||||
-rw-r--r-- | channels/misdn/isdn_lib_intern.h | 30 | ||||
-rw-r--r-- | channels/misdn/isdn_msg_parser.c | 394 |
6 files changed, 1191 insertions, 676 deletions
diff --git a/channels/misdn/chan_misdn_config.h b/channels/misdn/chan_misdn_config.h index d64b8c860..140e1ee26 100644 --- a/channels/misdn/chan_misdn_config.h +++ b/channels/misdn/chan_misdn_config.h @@ -65,6 +65,7 @@ enum misdn_cfg_elements { MISDN_CFG_EARLY_BCONNECT, /* int (bool) */ MISDN_CFG_INCOMING_EARLY_AUDIO, /* int (bool) */ MISDN_CFG_ECHOCANCEL, /* int */ + MISDN_CFG_CC_REQUEST_RETENTION,/* bool */ #ifdef MISDN_1_2 MISDN_CFG_PIPELINE, /* char[] */ #endif diff --git a/channels/misdn/ie.c b/channels/misdn/ie.c index 85b3d12ad..33596098d 100644 --- a/channels/misdn/ie.c +++ b/channels/misdn/ie.c @@ -1,4 +1,3 @@ - /* * Chan_Misdn -- Channel Driver for Asterisk * @@ -39,11 +38,11 @@ #define MISDN_IE_DEBG 0 /* support stuff */ -static void strnncpy(char *dest, char *src, int len, int dst_len) +static void strnncpy(char *dest, const char *src, size_t len, size_t dst_len) { if (len > dst_len-1) len = dst_len-1; - strncpy((char *)dest, (char *)src, len); + strncpy(dest, src, len); dest[len] = '\0'; } @@ -380,7 +379,7 @@ static void enc_ie_called_pn(unsigned char **ntmode, msg_t *msg, int type, int p strncpy((char *)p+3, (char *)number, strlen((char *)number)); } -static void dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, char *number, int number_len, int nt, struct misdn_bchannel *bc) +static void dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, char *number, size_t number_len, int nt, struct misdn_bchannel *bc) { *type = -1; *plan = -1; @@ -464,7 +463,7 @@ static void enc_ie_calling_pn(unsigned char **ntmode, msg_t *msg, int type, int } } -static void dec_ie_calling_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, int number_len, int nt, struct misdn_bchannel *bc) +static void dec_ie_calling_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, size_t number_len, int nt, struct misdn_bchannel *bc) { *type = -1; *plan = -1; @@ -566,7 +565,7 @@ static void enc_ie_connected_pn(unsigned char **ntmode, msg_t *msg, int type, in } } -static void dec_ie_connected_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, int number_len, int nt, struct misdn_bchannel *bc) +static void dec_ie_connected_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, char *number, size_t number_len, int nt, struct misdn_bchannel *bc) { *type = -1; *plan = -1; @@ -884,7 +883,7 @@ static void enc_ie_date(unsigned char **ntmode, msg_t *msg, time_t ti, int nt, s static void enc_ie_display(unsigned char **ntmode, msg_t *msg, char *display, int nt, struct misdn_bchannel *bc) { unsigned char *p; - Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN); + Q931_info_t *qi = (Q931_info_t *) (msg->data + mISDN_HEADER_LEN); int l; if (!display[0]) @@ -893,27 +892,28 @@ static void enc_ie_display(unsigned char **ntmode, msg_t *msg, char *display, in return; } - if (strlen((char *)display) > 80) + l = strlen(display); + if (80 < l) { - printf("%s: WARNING: display text too long (max 80 chars), cutting.\n", __FUNCTION__); - display[80] = '\0'; + l = 80; + printf("%s: WARNING: display text too long (max %d chars), cutting.\n", __FUNCTION__, l); + display[l] = '\0'; } - /* if (MISDN_IE_DEBG) printf(" display='%s' (len=%d)\n", display, strlen((char *)display)); */ + /* if (MISDN_IE_DEBG) printf(" display='%s' (len=%d)\n", display, l); */ - l = strlen((char *)display); - p = msg_put(msg, l+2); + p = msg_put(msg, l + 2); if (nt) - *ntmode = p+1; + *ntmode = p + 1; else - qi->QI_ELEMENT(display) = p - (unsigned char *)qi - sizeof(Q931_info_t); + qi->QI_ELEMENT(display) = p - (unsigned char *) qi - sizeof(Q931_info_t); p[0] = IE_DISPLAY; p[1] = l; - strncpy((char *)p+2, (char *)display, strlen((char *)display)); + strncpy((char *) p + 2, display, l); } #if 0 -static void dec_ie_display(unsigned char *p, Q931_info_t *qi, char *display, int display_len, int nt, struct misdn_bchannel *bc) +static void dec_ie_display(unsigned char *p, Q931_info_t *qi, char *display, size_t display_len, int nt, struct misdn_bchannel *bc) { *display = '\0'; @@ -965,7 +965,7 @@ static void enc_ie_keypad(unsigned char **ntmode, msg_t *msg, char *keypad, int } #endif -static void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, char *keypad, int keypad_len, int nt, struct misdn_bchannel *bc) +static void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, char *keypad, size_t keypad_len, int nt, struct misdn_bchannel *bc) { *keypad = '\0'; @@ -990,7 +990,6 @@ static void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, char *keypad, int k /* IE_NOTIFY */ -#if 0 static void enc_ie_notify(unsigned char **ntmode, msg_t *msg, int notify, int nt, struct misdn_bchannel *bc) { unsigned char *p; @@ -1015,9 +1014,7 @@ static void enc_ie_notify(unsigned char **ntmode, msg_t *msg, int notify, int nt p[1] = l; p[2] = 0x80 + notify; } -#endif -#if 0 static void dec_ie_notify(unsigned char *p, Q931_info_t *qi, int *notify, int nt, struct misdn_bchannel *bc) { *notify = -1; @@ -1040,7 +1037,6 @@ static void dec_ie_notify(unsigned char *p, Q931_info_t *qi, int *notify, int nt if (MISDN_IE_DEBG) printf(" notify=%d\n", *notify); } -#endif /* IE_PROGRESS */ @@ -1184,7 +1180,7 @@ static void enc_ie_redir_nr(unsigned char **ntmode, msg_t *msg, int type, int pl } } -static void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, int *reason, char *number, int number_len, int nt, struct misdn_bchannel *bc) +static void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, int *reason, char *number, size_t number_len, int nt, struct misdn_bchannel *bc) { *type = -1; *plan = -1; @@ -1231,11 +1227,10 @@ static void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *p /* IE_REDIR_DN (redirection = during MT_NOTIFY) */ -#if 0 static void enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, char *number, int nt, struct misdn_bchannel *bc) { unsigned char *p; -/* Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN); */ + Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN); int l; if (type<0 || type>7) @@ -1264,9 +1259,9 @@ static void enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int pl p = msg_put(msg, l+2); if (nt) *ntmode = p+1; - else -/* #warning REINSERT redir_dn, when included in te-mode */ - /*qi->QI_ELEMENT(redir_dn) = p - (unsigned char *)qi - sizeof(Q931_info_t)*/; + else { + qi->QI_ELEMENT(redirect_dn) = p - (unsigned char *)qi - sizeof(Q931_info_t); + } p[0] = IE_REDIR_DN; p[1] = l; if (present >= 0) @@ -1282,10 +1277,8 @@ static void enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int pl strncpy((char *)p+3, (char *)number, strlen((char *)number)); } } -#endif -#if 0 -static void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, char *number, int number_len, int nt, struct misdn_bchannel *bc) +static void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, char *number, size_t number_len, int nt, struct misdn_bchannel *bc) { *type = -1; *plan = -1; @@ -1295,9 +1288,8 @@ static void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *p if (!nt) { p = NULL; -/* #warning REINSERT redir_dn, when included in te-mode */ -/* if (qi->QI_ELEMENT(redir_dn)) */ -/* p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redir_dn) + 1; */ + if (qi->QI_ELEMENT(redirect_dn)) + p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(redirect_dn) + 1; } if (!p) return; @@ -1320,7 +1312,6 @@ static void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *p if (MISDN_IE_DEBG) printf(" type=%d plan=%d present=%d number='%s'\n", *type, *plan, *present, number); } -#endif /* IE_USERUSER */ @@ -1331,9 +1322,6 @@ static void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, ch Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN); int l; - char debug[768]; - int i; - if (protocol<0 || protocol>127) { printf("%s: ERROR: protocol(%d) is out of range.\n", __FUNCTION__, protocol); @@ -1344,14 +1332,16 @@ static void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, ch return; } - i = 0; - while(i < user_len) - { - if (MISDN_IE_DEBG) sprintf(debug+(i*3), " %02x", user[i]); - i++; - } + if (MISDN_IE_DEBG) { + size_t i; + char debug[768]; - if (MISDN_IE_DEBG) printf(" protocol=%d user-user%s\n", protocol, debug); + for (i = 0; i < user_len; ++i) { + sprintf(debug + (i * 3), " %02x", user[i]); + } + debug[i * 3] = 0; + printf(" protocol=%d user-user%s\n", protocol, debug); + } l = user_len+1; p = msg_put(msg, l+3); @@ -1369,9 +1359,6 @@ static void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, ch #if 1 static void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, char *user, int *user_len, int nt, struct misdn_bchannel *bc) { - char debug[768]; - int i; - *user_len = 0; *protocol = -1; @@ -1390,15 +1377,16 @@ static void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, ch *protocol = p[1]; memcpy(user, p+2, (*user_len<=128)?*(user_len):128); /* clip to 128 maximum */ - i = 0; - while(i < *user_len) - { - if (MISDN_IE_DEBG) sprintf(debug+(i*3), " %02x", user[i]); - i++; - } - debug[i*3] = '\0'; + if (MISDN_IE_DEBG) { + int i; + char debug[768]; - if (MISDN_IE_DEBG) printf(" protocol=%d user-user%s\n", *protocol, debug); + for (i = 0; i < *user_len; ++i) { + sprintf(debug + (i * 3), " %02x", user[i]); + } + debug[i * 3] = 0; + printf(" protocol=%d user-user%s\n", *protocol, debug); + } } #endif diff --git a/channels/misdn/isdn_lib.c b/channels/misdn/isdn_lib.c index 4a4ea9cc2..4a0da06d3 100644 --- a/channels/misdn/isdn_lib.c +++ b/channels/misdn/isdn_lib.c @@ -50,10 +50,6 @@ int misdn_lib_get_l2_up(struct misdn_stack *stack); struct misdn_stack *get_misdn_stack(void); -static int set_chan_in_stack(struct misdn_stack *stack, int channel); - -int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh); - int misdn_lib_port_is_pri(int port) { struct misdn_stack *stack=get_misdn_stack(); @@ -285,7 +281,6 @@ struct misdn_bchannel *stack_holder_find(struct misdn_stack *stack, unsigned lon /* from isdn_lib.h */ /* user iface */ -int te_lib_init( void ) ; /* returns midev */ void te_lib_destroy(int midev) ; struct misdn_bchannel *manager_find_bc_by_pid(int pid); struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc); @@ -483,6 +478,14 @@ static void dump_chan_list(struct misdn_stack *stack) cb_log(6, stack->port, "Idx:%d stack->cchan:%d in_use:%d Chan:%d\n", i, stack->channels[i], stack->bc[i].in_use, i + 1); } +#if defined(AST_MISDN_ENHANCEMENTS) + for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) { + if (stack->bc[i].in_use) { + cb_log(6, stack->port, "Idx:%d stack->cchan:%d REGISTER Chan:%d in_use\n", + i, stack->channels[i], i + 1); + } + } +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ } @@ -499,7 +502,7 @@ static int set_chan_in_stack(struct misdn_stack *stack, int channel) { cb_log(4,stack->port,"set_chan_in_stack: %d\n",channel); dump_chan_list(stack); - if (channel >=1 && channel <= MAX_BCHANS) { + if (1 <= channel && channel <= ARRAY_LEN(stack->channels)) { if (!stack->channels[channel-1]) stack->channels[channel-1] = 1; else { @@ -520,7 +523,7 @@ static int find_free_chan_in_stack(struct misdn_stack *stack, struct misdn_bchan { int i; int chan = 0; - int bnums = stack->pri ? stack->b_num : stack->b_num - 1; + int bnums; if (bc->channel_found) { return 0; @@ -528,32 +531,46 @@ static int find_free_chan_in_stack(struct misdn_stack *stack, struct misdn_bchan bc->channel_found = 1; - cb_log(5,stack->port,"find_free_chan: req_chan:%d\n",channel); +#if defined(AST_MISDN_ENHANCEMENTS) + if (bc->is_register_pool) { + for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->channels); ++i) { + if (!stack->channels[i]) { + chan = i + 1; + cb_log(3, stack->port, " --> found REGISTER chan: %d\n", chan); + break; + } + } + } else +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ + { + cb_log(5, stack->port, "find_free_chan: req_chan:%d\n", channel); - if (channel < 0 || channel > MAX_BCHANS) { - cb_log(0, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel); - return 0; - } + if (channel < 0 || channel > MAX_BCHANS) { + cb_log(0, stack->port, " !! out of bound call to find_free_chan_in_stack! (ch:%d)\n", channel); + return 0; + } - channel--; + --channel; - if (dec) { - for (i = bnums; i >=0; i--) { - if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */ - if (!stack->channels[i]) { - cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1); - chan=i+1; - break; + bnums = stack->pri ? stack->b_num : stack->b_num - 1; + if (dec) { + for (i = bnums; i >= 0; --i) { + if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */ + if (!stack->channels[i]) { + chan = i + 1; + cb_log(3, stack->port, " --> found chan%s: %d\n", channel >= 0 ? " (preselected)" : "", chan); + break; + } } } - } - } else { - for (i = 0; i <= bnums; i++) { - if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */ - if (!stack->channels[i]) { - cb_log (3, stack->port, " --> found chan%s: %d\n", channel>=0?" (preselected)":"", i+1); - chan=i+1; - break; + } else { + for (i = 0; i <= bnums; ++i) { + if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */ + if (!stack->channels[i]) { + chan = i + 1; + cb_log(3, stack->port, " --> found chan%s: %d\n", channel >= 0 ? " (preselected)" : "", chan); + break; + } } } } @@ -576,17 +593,16 @@ static int find_free_chan_in_stack(struct misdn_stack *stack, struct misdn_bchan return 0; } -static int empty_chan_in_stack(struct misdn_stack *stack, int channel) +static void empty_chan_in_stack(struct misdn_stack *stack, int channel) { - if (channel<=0 || channel>MAX_BCHANS) { - cb_log(0,stack?stack->port:0, "empty_chan_in_stack: cannot empty channel %d\n",channel); - return -1; + if (channel < 1 || ARRAY_LEN(stack->channels) < channel) { + cb_log(0, stack->port, "empty_chan_in_stack: cannot empty channel %d\n", channel); + return; } - cb_log (4, stack?stack->port:0, "empty_chan_in_stack: %d\n",channel); + cb_log(4, stack->port, "empty_chan_in_stack: %d\n", channel); stack->channels[channel - 1] = 0; dump_chan_list(stack); - return 0; } char *bc_state2str(enum bchannel_state state) { @@ -671,7 +687,16 @@ static void empty_bc(struct misdn_bchannel *bc) bc->redirecting.from.number[0] = 0; bc->redirecting.from.subaddress[0] = 0; + bc->redirecting.to.presentation = 0; /* allowed */ + bc->redirecting.to.number_plan = NUMPLAN_ISDN; + bc->redirecting.to.number_type = NUMTYPE_UNKNOWN; + bc->redirecting.to.name[0] = 0; + bc->redirecting.to.number[0] = 0; + bc->redirecting.to.subaddress[0] = 0; + bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN; + bc->redirecting.count = 0; + bc->redirecting.to_changed = 0; bc->dummy=0; @@ -731,6 +756,8 @@ static void empty_bc(struct misdn_bchannel *bc) bc->presentation = 0; /* allowed */ bc->set_presentation = 0; + bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID; + bc->evq=EVENT_NOTHING; bc->progress_coding=0; @@ -810,22 +837,26 @@ static void clear_l3(struct misdn_stack *stack) { int i; - for (i=0; i<=stack->b_num; i++) { - if (global_state == MISDN_INITIALIZED) { + if (global_state == MISDN_INITIALIZED) { + for (i = 0; i <= stack->b_num; ++i) { cb_event(EVENT_CLEANUP, &stack->bc[i], NULL); empty_chan_in_stack(stack, i + 1); empty_bc(&stack->bc[i]); clean_up_bc(&stack->bc[i]); stack->bc[i].in_use = 0; } - +#if defined(AST_MISDN_ENHANCEMENTS) + for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) { + empty_chan_in_stack(stack, i + 1); + empty_bc(&stack->bc[i]); + stack->bc[i].in_use = 0; + } +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ } } static int new_te_id = 0; -#define MAXPROCS 0x100 - static int misdn_lib_get_l1_down(struct misdn_stack *stack) { /* Pull Up L1 */ @@ -1179,33 +1210,20 @@ int setup_bc(struct misdn_bchannel *bc) /** IFACE **/ -static int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, int port, int bidx, char *msn, int firsttime) +static int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int midev, int port, int bidx) { - unsigned char buff[1025] = ""; - iframe_t *frm = (iframe_t *)buff; - int ret; - if (!bc) { return -1; } cb_log(8, port, "Init.BC %d.\n",bidx); - memset(bc, 0,sizeof(struct misdn_bchannel)); - bc->send_lock=malloc(sizeof(struct send_lock)); if (!bc->send_lock) { return -1; } pthread_mutex_init(&bc->send_lock->lock, NULL); - if (msn) { - int l = sizeof(bc->msn); - strncpy(bc->msn,msn, l); - bc->msn[l-1] = 0; - } - - empty_bc(bc); bc_state_change(bc, BCHAN_CLEANED); @@ -1232,8 +1250,13 @@ static int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int mid } - { +#if 0 /* This code does not seem to do anything useful */ + if (bidx <= stack->b_num) { + unsigned char buff[1025]; + iframe_t *frm = (iframe_t *) buff; stack_info_t *stinf; + int ret; + ret = mISDN_get_stack_info(midev, stack->port, buff, sizeof(buff)); if (ret < 0) { cb_log(0, port, "%s: Cannot get stack info for this port. (ret=%d)\n", __FUNCTION__, ret); @@ -1244,6 +1267,7 @@ static int init_bc(struct misdn_stack *stack, struct misdn_bchannel *bc, int mid cb_log(8, port, " --> Child %x\n",stinf->child[bidx]); } +#endif return 0; } @@ -1256,19 +1280,17 @@ static struct misdn_stack *stack_init(int midev, int port, int ptp) unsigned char buff[1025]; iframe_t *frm = (iframe_t *)buff; stack_info_t *stinf; + struct misdn_stack *stack; int i; layer_info_t li; - struct misdn_stack *stack = malloc(sizeof(struct misdn_stack)); - if (!stack ) return NULL; - + stack = calloc(1, sizeof(struct misdn_stack)); + if (!stack) { + return NULL; + } cb_log(8, port, "Init. Stack.\n"); - memset(stack,0,sizeof(struct misdn_stack)); - - for (i=0; i<MAX_BCHANS + 1; i++ ) stack->channels[i]=0; - stack->port=port; stack->midev=midev; stack->ptp=ptp; @@ -1406,11 +1428,6 @@ static struct misdn_stack *stack_init(int midev, int port, int ptp) } - if (!stack->nt) { - /*assume L1 is up, we'll get DEACTIVATES soon, for non - * up L1s*/ - stack->l1link=0; - } stack->l1link=0; stack->l2link=0; #if 0 @@ -1505,6 +1522,14 @@ static struct misdn_bchannel *find_bc_by_masked_l3id(struct misdn_stack *stack, return &stack->bc[i]; } } +#if defined(AST_MISDN_ENHANCEMENTS) + /* Search the B channel records for a REGISTER signaling link. */ + for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) { + if ((stack->bc[i].l3_id & mask) == (l3id & mask)) { + return &stack->bc[i]; + } + } +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ return stack_holder_find(stack, l3id); } @@ -1518,6 +1543,14 @@ struct misdn_bchannel *find_bc_by_l3id(struct misdn_stack *stack, unsigned long return &stack->bc[i]; } } +#if defined(AST_MISDN_ENHANCEMENTS) + /* Search the B channel records for a REGISTER signaling link. */ + for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) { + if (stack->bc[i].l3_id == l3id) { + return &stack->bc[i]; + } + } +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ return stack_holder_find(stack, l3id); } @@ -1656,7 +1689,9 @@ static int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_ if (!bc->channel) { cb_log(0, stack->port, "Any Channel Requested, but we have no more!!\n"); } else { - cb_log(0, stack->port, "Requested Channel Already in Use releasing this call with cause 34!!!!\n"); + cb_log(0, stack->port, + "Requested Channel Already in Use releasing this call with cause %d!!!!\n", + bc->out_cause); } /* when the channel is already in use, we can't @@ -1687,7 +1722,9 @@ static int handle_event ( struct misdn_bchannel *bc, enum event_e event, iframe_ static int handle_cr ( struct misdn_stack *stack, iframe_t *frm) { + struct misdn_bchannel dummybc; struct misdn_bchannel *bc; + int channel; if (!stack) return -1; @@ -1714,50 +1751,40 @@ static int handle_cr ( struct misdn_stack *stack, iframe_t *frm) break; case CC_RELEASE_CR|INDICATION: cb_log(4, stack->port, " --> lib: RELEASE_CR Ind with l3id:%x\n", frm->dinfo); - { - struct misdn_bchannel *bc=find_bc_by_l3id(stack, frm->dinfo); - struct misdn_bchannel dummybc; - - if (!bc) { - cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo); - misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0); - - bc=&dummybc; - } - - if (bc) { - int channel = bc->channel; - cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n",frm->dinfo); + bc = find_bc_by_l3id(stack, frm->dinfo); + if (!bc) { + cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo); + misdn_make_dummy(&dummybc, stack->port, frm->dinfo, stack->nt, 0); + bc = &dummybc; + } - /*bc->pid = 0;*/ - bc->need_disconnect=0; - bc->need_release=0; - bc->need_release_complete=0; + channel = bc->channel; + cb_log(4, stack->port, " --> lib: CLEANING UP l3id: %x\n", frm->dinfo); - cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data); + /* bc->pid = 0; */ + bc->need_disconnect = 0; + bc->need_release = 0; + bc->need_release_complete = 0; - empty_bc(bc); - clean_up_bc(bc); + cb_event(EVENT_CLEANUP, bc, glob_mgr->user_data); - if (channel>0) - empty_chan_in_stack(stack,channel); - bc->in_use=0; + empty_bc(bc); + clean_up_bc(bc); - dump_chan_list(stack); + if (channel > 0) + empty_chan_in_stack(stack, channel); + bc->in_use = 0; - if (bc->stack_holder) { - cb_log(4,stack->port, "REMOVING Holder\n"); - stack_holder_remove( stack, bc); - free(bc); - } - } - else { - if (stack->nt) - cb_log(4, stack->port, "BC with dinfo: %x not found.. (prim was %x and addr %x)\n",frm->dinfo, frm->prim, frm->addr); - } + dump_chan_list(stack); - return 1; + if (bc->stack_holder) { + cb_log(4, stack->port, "REMOVING Holder\n"); + stack_holder_remove(stack, bc); + free(bc); } + + return 1; + default: break; } @@ -1864,7 +1891,7 @@ int misdn_lib_port_up(int port, int check) } -int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh) +static int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh) { struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); struct misdn_bchannel dummybc; @@ -1882,13 +1909,10 @@ int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh) bc=&dummybc; } - if (bc) { - if ( (bc->l3_id & 0xff00) == 0xff00) { - cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", bc->l3_id&0xff); - stack->procids[bc->l3_id&0xff] = 0 ; - } + if ((bc->l3_id & 0xff00) == 0xff00) { + cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", bc->l3_id & 0xff); + stack->procids[bc->l3_id & 0xff] = 0; } - else cb_log(0, stack->port, "Couldn't find BC so I couldn't remove the Process!!!! this is a bad port.\n"); if (handle_cr(stack, &frm)<0) { } @@ -1898,315 +1922,317 @@ int release_cr(struct misdn_stack *stack, mISDNuser_head_t *hh) static int handle_event_nt(void *dat, void *arg) { + struct misdn_bchannel dummybc; + struct misdn_bchannel *bc; manager_t *mgr = (manager_t *)dat; msg_t *msg = (msg_t *)arg; + msg_t *dmsg; mISDNuser_head_t *hh; + struct misdn_stack *stack; + enum event_e event; int reject=0; - - struct misdn_stack *stack=find_stack_by_mgr(mgr); int port; + int l3id; + int channel; + int tmpcause; if (!msg || !mgr) return(-EINVAL); + stack = find_stack_by_mgr(mgr); hh=(mISDNuser_head_t*)msg->data; port=stack->port; cb_log(5, stack->port, " --> lib: prim %x dinfo %x\n",hh->prim, hh->dinfo); + switch(hh->prim) { + case CC_RETRIEVE|INDICATION: { - switch(hh->prim){ - case CC_RETRIEVE|INDICATION: - { - struct misdn_bchannel *bc; - struct misdn_bchannel *hold_bc; + struct misdn_bchannel *hold_bc; + iframe_t frm; /* fake te frm to add callref to global callreflist */ - iframe_t frm; /* fake te frm to add callref to global callreflist */ - frm.dinfo = hh->dinfo; + frm.dinfo = hh->dinfo; + frm.addr=stack->upper_id | FLG_MSG_DOWN; + frm.prim = CC_NEW_CR|INDICATION; + if (handle_cr( stack, &frm)< 0) { + goto ERR_NO_CHANNEL; + } - frm.addr=stack->upper_id | FLG_MSG_DOWN; + bc = find_bc_by_l3id(stack, hh->dinfo); + hold_bc = stack_holder_find(stack, bc->l3_id); + cb_log(4, stack->port, "bc_l3id:%x holded_bc_l3id:%x\n",bc->l3_id, hold_bc->l3_id); - frm.prim = CC_NEW_CR|INDICATION; + if (hold_bc) { + cb_log(4, stack->port, "REMOVING Holder\n"); - if (handle_cr( stack, &frm)< 0) { - msg_t *dmsg; - cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo); - dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1); - stack->nst.manager_l3(&stack->nst, dmsg); - free_msg(msg); - return 0; - } + /* swap the backup to our new channel back */ + stack_holder_remove(stack, hold_bc); + memcpy(bc, hold_bc, sizeof(*bc)); + free(hold_bc); - bc = find_bc_by_l3id(stack, hh->dinfo); - hold_bc = stack_holder_find(stack, bc->l3_id); - cb_log(4, stack->port, "bc_l3id:%x holded_bc_l3id:%x\n",bc->l3_id, hold_bc->l3_id); + bc->holded=0; + bc->b_stid=0; + } + break; + } - if (hold_bc) { - cb_log(4, stack->port, "REMOVING Holder\n"); + case CC_SETUP | CONFIRM: + l3id = *((int *) (msg->data + mISDNUSER_HEAD_SIZE)); - /*swap the backup to our new channel back*/ - stack_holder_remove(stack, hold_bc); - memcpy(bc, hold_bc, sizeof(*bc)); - free(hold_bc); + cb_log(4, stack->port, " --> lib: Event_ind:SETUP CONFIRM [NT] : new L3ID is %x\n", l3id); - bc->holded=0; - bc->b_stid=0; - } + bc = find_bc_by_l3id(stack, hh->dinfo); + if (bc) { + cb_log (2, bc->port, "I IND :CC_SETUP|CONFIRM: old l3id:%x new l3id:%x\n", bc->l3_id, l3id); + bc->l3_id = l3id; + cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data); + } else { + cb_log(4, stack->port, "Bc Not found (after SETUP CONFIRM)\n"); + } + free_msg(msg); + return 0; + case CC_SETUP | INDICATION: + bc = misdn_lib_get_free_bc(stack->port, 0, 1, 0); + if (!bc) { + goto ERR_NO_CHANNEL; } - break; + cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",hh->dinfo); + bc->l3_id=hh->dinfo; + break; - case CC_SETUP|CONFIRM: - { - struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); - int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE)); - cb_log(4, stack->port, " --> lib: Event_ind:SETUP CONFIRM [NT] : new L3ID is %x\n",l3id ); +#if defined(AST_MISDN_ENHANCEMENTS) + case CC_REGISTER | CONFIRM: + l3id = *((int *) (msg->data + mISDNUSER_HEAD_SIZE)); - if (!bc) { cb_log(4, stack->port, "Bc Not found (after SETUP CONFIRM)\n"); return 0; } - cb_log (2,bc->port,"I IND :CC_SETUP|CONFIRM: old l3id:%x new l3id:%x\n", bc->l3_id, l3id); - bc->l3_id=l3id; - cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data); + cb_log(4, stack->port, " --> lib: Event_ind:REGISTER CONFIRM [NT] : new L3ID is %x\n", l3id); + + bc = find_bc_by_l3id(stack, hh->dinfo); + if (bc) { + cb_log (2, bc->port, "I IND :CC_REGISTER|CONFIRM: old l3id:%x new l3id:%x\n", bc->l3_id, l3id); + bc->l3_id = l3id; + } else { + cb_log(4, stack->port, "Bc Not found (after REGISTER CONFIRM)\n"); } free_msg(msg); return 0; +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ - case CC_SETUP|INDICATION: - { - struct misdn_bchannel* bc=misdn_lib_get_free_bc(stack->port, 0, 1, 0); - if (!bc) - ERR_NO_CHANNEL: - { - msg_t *dmsg; - cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo); - dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST,MT_RELEASE_COMPLETE, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1); - stack->nst.manager_l3(&stack->nst, dmsg); - free_msg(msg); - return 0; - } - - cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",hh->dinfo); - bc->l3_id=hh->dinfo; +#if defined(AST_MISDN_ENHANCEMENTS) + case CC_REGISTER | INDICATION: + bc = misdn_lib_get_register_bc(stack->port); + if (!bc) { + goto ERR_NO_CHANNEL; } + + cb_log(4, stack->port, " --> new_process: New L3Id: %x\n",hh->dinfo); + bc->l3_id=hh->dinfo; break; +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ - case CC_CONNECT_ACKNOWLEDGE|INDICATION: + case CC_CONNECT_ACKNOWLEDGE|INDICATION: break; - case CC_ALERTING|INDICATION: - case CC_PROCEEDING|INDICATION: - case CC_SETUP_ACKNOWLEDGE|INDICATION: - if(!stack->ptp) break; - case CC_CONNECT|INDICATION: + case CC_ALERTING|INDICATION: + case CC_PROCEEDING|INDICATION: + case CC_SETUP_ACKNOWLEDGE|INDICATION: + case CC_CONNECT|INDICATION: break; - case CC_DISCONNECT|INDICATION: - { - struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); - if (!bc) { - bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000); - if (bc) { - int myprocid=bc->l3_id&0x0000ffff; - hh->dinfo=(hh->dinfo&0xffff0000)|myprocid; - cb_log(3,stack->port,"Reject dinfo: %x cause:%d\n",hh->dinfo,bc->cause); - reject=1; - } + case CC_DISCONNECT|INDICATION: + bc = find_bc_by_l3id(stack, hh->dinfo); + if (!bc) { + bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000); + if (bc) { + int myprocid=bc->l3_id&0x0000ffff; + + hh->dinfo=(hh->dinfo&0xffff0000)|myprocid; + cb_log(3,stack->port,"Reject dinfo: %x cause:%d\n",hh->dinfo,bc->cause); + reject=1; } } break; - case CC_FACILITY|INDICATION: - { - struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); - if (!bc) { - bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000); - if (bc) { - int myprocid=bc->l3_id&0x0000ffff; - hh->dinfo=(hh->dinfo&0xffff0000)|myprocid; - cb_log(4,bc->port,"Repaired reject Bug, new dinfo: %x\n",hh->dinfo); - } + case CC_FACILITY|INDICATION: + bc = find_bc_by_l3id(stack, hh->dinfo); + if (!bc) { + bc=find_bc_by_masked_l3id(stack, hh->dinfo, 0xffff0000); + if (bc) { + int myprocid=bc->l3_id&0x0000ffff; + + hh->dinfo=(hh->dinfo&0xffff0000)|myprocid; + cb_log(4,bc->port,"Repaired reject Bug, new dinfo: %x\n",hh->dinfo); } } break; - case CC_RELEASE_COMPLETE|INDICATION: - break; - - case CC_SUSPEND|INDICATION: - { - msg_t *dmsg; - cb_log(4, stack->port, " --> Got Suspend, sending Reject for now\n"); - dmsg = create_l3msg(CC_SUSPEND_REJECT | REQUEST,MT_SUSPEND_REJECT, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1); - stack->nst.manager_l3(&stack->nst, dmsg); - free_msg(msg); - return 0; - } + case CC_RELEASE_COMPLETE|INDICATION: break; - case CC_RESUME|INDICATION: - break; - case CC_RELEASE|CONFIRM: - { - struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); + case CC_SUSPEND|INDICATION: + cb_log(4, stack->port, " --> Got Suspend, sending Reject for now\n"); + dmsg = create_l3msg(CC_SUSPEND_REJECT | REQUEST,MT_SUSPEND_REJECT, hh->dinfo,sizeof(RELEASE_COMPLETE_t), 1); + stack->nst.manager_l3(&stack->nst, dmsg); + free_msg(msg); + return 0; - if (bc) { - cb_log(1, stack->port, "CC_RELEASE|CONFIRM (l3id:%x), sending RELEASE_COMPLETE\n", hh->dinfo); - misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE); - } - } - break; + case CC_RESUME|INDICATION: + break; - case CC_RELEASE|INDICATION: - break; + case CC_RELEASE|CONFIRM: + bc = find_bc_by_l3id(stack, hh->dinfo); + if (bc) { + cb_log(1, stack->port, "CC_RELEASE|CONFIRM (l3id:%x), sending RELEASE_COMPLETE\n", hh->dinfo); + misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE); + } + break; - case CC_RELEASE_CR|INDICATION: - release_cr(stack, hh); - free_msg(msg); - return 0 ; + case CC_RELEASE|INDICATION: break; - case CC_NEW_CR|INDICATION: - /* Got New CR for bchan, for now I handle this one in */ - /* connect_ack, Need to be changed */ - { - struct misdn_bchannel *bc=find_bc_by_l3id(stack, hh->dinfo); - int l3id = *((int *)(((u_char *)msg->data)+ mISDNUSER_HEAD_SIZE)); - if (!bc) { cb_log(0, stack->port, " --> In NEW_CR: didn't found bc ??\n"); return -1;}; - if (((l3id&0xff00)!=0xff00) && ((bc->l3_id&0xff00)==0xff00)) { - cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", 0xff&bc->l3_id); - stack->procids[bc->l3_id&0xff] = 0 ; - } - cb_log(4, stack->port, "lib: Event_ind:CC_NEW_CR : very new L3ID is %x\n",l3id ); + case CC_RELEASE_CR|INDICATION: + release_cr(stack, hh); + free_msg(msg); + return 0; - bc->l3_id =l3id; - cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data); + case CC_NEW_CR|INDICATION: + /* Got New CR for bchan, for now I handle this one in */ + /* connect_ack, Need to be changed */ + l3id = *((int *) (msg->data + mISDNUSER_HEAD_SIZE)); - free_msg(msg); - return 0; + bc = find_bc_by_l3id(stack, hh->dinfo); + if (!bc) { + cb_log(0, stack->port, " --> In NEW_CR: didn't found bc ??\n"); + return -1; + } + if (((l3id&0xff00)!=0xff00) && ((bc->l3_id&0xff00)==0xff00)) { + cb_log(4, stack->port, " --> Removing Process Id:%x on this port.\n", 0xff&bc->l3_id); + stack->procids[bc->l3_id&0xff] = 0 ; } + cb_log(4, stack->port, "lib: Event_ind:CC_NEW_CR : very new L3ID is %x\n",l3id ); - case DL_ESTABLISH | INDICATION: - case DL_ESTABLISH | CONFIRM: - { - cb_log(3, stack->port, "%% GOT L2 Activate Info.\n"); + bc->l3_id =l3id; + if (!bc->is_register_pool) { + cb_event(EVENT_NEW_L3ID, bc, glob_mgr->user_data); + } - if (stack->ptp && stack->l2link) { - cb_log(0, stack->port, "%% GOT L2 Activate Info. but we're activated already.. this l2 is faulty, blocking port\n"); - cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data); - } + free_msg(msg); + return 0; - if (stack->ptp && !stack->restart_sent) { - /* make sure we restart the interface of the - * other side */ - stack->restart_sent=1; - misdn_lib_send_restart(stack->port, -1); + case DL_ESTABLISH | INDICATION: + case DL_ESTABLISH | CONFIRM: + cb_log(3, stack->port, "%% GOT L2 Activate Info.\n"); - } + if (stack->ptp && stack->l2link) { + cb_log(0, stack->port, "%% GOT L2 Activate Info. but we're activated already.. this l2 is faulty, blocking port\n"); + cb_event(EVENT_PORT_ALARM, &stack->bc[0], glob_mgr->user_data); + } - /* when we get the L2 UP, the L1 is UP definitely too*/ - stack->l2link = 1; - stack->l2upcnt=0; + if (stack->ptp && !stack->restart_sent) { + /* make sure we restart the interface of the + * other side */ + stack->restart_sent=1; + misdn_lib_send_restart(stack->port, -1); - free_msg(msg); - return 0; } - break; + /* when we get the L2 UP, the L1 is UP definitely too*/ + stack->l2link = 1; + stack->l2upcnt=0; - case DL_RELEASE | INDICATION: - case DL_RELEASE | CONFIRM: - { - if (stack->ptp) { - cb_log(3 , stack->port, "%% GOT L2 DeActivate Info.\n"); + free_msg(msg); + return 0; - if (stack->l2upcnt>3) { - cb_log(0 , stack->port, "!!! Could not Get the L2 up after 3 Attempts!!!\n"); - } else { + case DL_RELEASE | INDICATION: + case DL_RELEASE | CONFIRM: + if (stack->ptp) { + cb_log(3 , stack->port, "%% GOT L2 DeActivate Info.\n"); + + if (stack->l2upcnt>3) { + cb_log(0 , stack->port, "!!! Could not Get the L2 up after 3 Attempts!!!\n"); + } else { #if 0 - if (stack->nt) misdn_lib_reinit_nt_stack(stack->port); + if (stack->nt) + misdn_lib_reinit_nt_stack(stack->port); #endif - if (stack->l1link) { - misdn_lib_get_l2_up(stack); - stack->l2upcnt++; - } + if (stack->l1link) { + misdn_lib_get_l2_up(stack); + stack->l2upcnt++; } + } - } else - cb_log(3, stack->port, "%% GOT L2 DeActivate Info.\n"); + } else + cb_log(3, stack->port, "%% GOT L2 DeActivate Info.\n"); - stack->l2link = 0; - free_msg(msg); - return 0; - } + stack->l2link = 0; + free_msg(msg); + return 0; + + default: break; - } } - { - /* Parse Events and fire_up to App. */ - struct misdn_bchannel *bc; - struct misdn_bchannel dummybc; + /* Parse Events and fire_up to App. */ + event = isdn_msg_get_event(msgs_g, msg, 1); - enum event_e event = isdn_msg_get_event(msgs_g, msg, 1); + bc = find_bc_by_l3id(stack, hh->dinfo); + if (!bc) { + cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x).\n", hh->dinfo); + misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0); + bc = &dummybc; + } - bc=find_bc_by_l3id(stack, hh->dinfo); + isdn_msg_parse_event(msgs_g, msg, bc, 1); - if (!bc) { - cb_log(4, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x).\n", hh->dinfo); - misdn_make_dummy(&dummybc, stack->port, hh->dinfo, stack->nt, 0); - bc=&dummybc; + switch (event) { + case EVENT_SETUP: + if (bc->channel <= 0 || bc->channel == 0xff) { + bc->channel = 0; + } + + if (find_free_chan_in_stack(stack, bc, bc->channel, 0) < 0) { + goto ERR_NO_CHANNEL; } - if (bc ) { - isdn_msg_parse_event(msgs_g,msg,bc, 1); + break; + case EVENT_RELEASE: + case EVENT_RELEASE_COMPLETE: + channel = bc->channel; + tmpcause = bc->cause; - switch (event) { - case EVENT_SETUP: - if (bc->channel<=0 || bc->channel==0xff) - bc->channel=0; + empty_bc(bc); + bc->cause = tmpcause; + clean_up_bc(bc); - if (find_free_chan_in_stack(stack,bc, bc->channel,0)<0) - goto ERR_NO_CHANNEL; - break; - case EVENT_RELEASE: - case EVENT_RELEASE_COMPLETE: - { - int channel=bc->channel; - int tmpcause=bc->cause; - empty_bc(bc); - bc->cause=tmpcause; - clean_up_bc(bc); - - if (channel>0) - empty_chan_in_stack(stack,channel); - bc->in_use=0; - } - break; + if (channel > 0) + empty_chan_in_stack(stack, channel); + bc->in_use = 0; + break; + default: + break; + } - default: + if(!isdn_get_info(msgs_g, event, 1)) { + cb_log(4, stack->port, "Unknown Event Ind: prim %x dinfo %x\n", hh->prim, hh->dinfo); + } else { + if (reject) { + switch(bc->cause) { + case AST_CAUSE_USER_BUSY: + cb_log(1, stack->port, "Siemens Busy reject..\n"); + break; + default: break; } - - if(!isdn_get_info(msgs_g,event,1)) { - cb_log(4, stack->port, "Unknown Event Ind: prim %x dinfo %x\n",hh->prim, hh->dinfo); - } else { - if (reject) { - switch(bc->cause){ - case AST_CAUSE_USER_BUSY: - cb_log(1, stack->port, "Siemens Busy reject..\n"); - - break; - default: - break; - } - } - cb_event(event, bc, glob_mgr->user_data); - } - } else { - cb_log(4, stack->port, "No BC found with l3id: prim %x dinfo %x\n",hh->prim, hh->dinfo); } - - free_msg(msg); + cb_event(event, bc, glob_mgr->user_data); } + free_msg(msg); + return 0; +ERR_NO_CHANNEL: + cb_log(4, stack->port, "Patch from MEIDANIS:Sending RELEASE_COMPLETE %x (No free Chan for you..)\n", hh->dinfo); + dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, hh->dinfo, sizeof(RELEASE_COMPLETE_t), 1); + stack->nst.manager_l3(&stack->nst, dmsg); + free_msg(msg); return 0; } @@ -2690,158 +2716,144 @@ static int handle_frm_nt(msg_t *msg) static int handle_frm(msg_t *msg) { - iframe_t *frm = (iframe_t*) msg->data; - - struct misdn_stack *stack=find_stack_by_addr(frm->addr); + struct misdn_bchannel dummybc; + struct misdn_bchannel *bc; + iframe_t *frm; + struct misdn_stack *stack; + enum event_e event; + enum event_response_e response; + int ret; + int channel; + int tmpcause; + int tmp_out_cause; + frm = (iframe_t*) msg->data; + stack = find_stack_by_addr(frm->addr); if (!stack || stack->nt) { return 0; } cb_log(4, stack ? stack->port : 0, "handle_frm: frm->addr:%x frm->prim:%x\n", frm->addr, frm->prim); - { - struct misdn_bchannel dummybc; - struct misdn_bchannel *bc; - int ret=handle_cr(stack, frm); - - if (ret<0) { - cb_log(3,stack?stack->port:0,"handle_frm: handle_cr <0 prim:%x addr:%x\n", frm->prim, frm->addr); - - - } - - if(ret) { - free_msg(msg); - return 1; - } - - bc=find_bc_by_l3id(stack, frm->dinfo); - - if (!bc && (frm->prim==(CC_RESTART|CONFIRM)) ) { - misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0); - bc=&dummybc; - } + ret = handle_cr(stack, frm); + if (ret < 0) { + cb_log(3, stack ? stack->port : 0, "handle_frm: handle_cr <0 prim:%x addr:%x\n", frm->prim, frm->addr); + } + if (ret) { + free_msg(msg); + return 1; + } - if (!bc && (frm->prim==(CC_SETUP|INDICATION)) ) { - misdn_make_dummy(&dummybc, stack->port, MISDN_ID_GLOBAL, stack->nt, 0); - dummybc.port=stack->port; - dummybc.l3_id=frm->dinfo; - bc=&dummybc; + bc = find_bc_by_l3id(stack, frm->dinfo); + if (!bc) { + misdn_make_dummy(&dummybc, stack->port, 0, stack->nt, 0); + switch (frm->prim) { + case CC_RESTART | CONFIRM: + dummybc.l3_id = MISDN_ID_GLOBAL; + bc = &dummybc; + break; + case CC_SETUP | INDICATION: + dummybc.l3_id = frm->dinfo; + bc = &dummybc; - misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); + misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE); free_msg(msg); return 1; - } - - -handle_frm_bc: - if (bc ) { - enum event_e event = isdn_msg_get_event(msgs_g, msg, 0); - enum event_response_e response=RESPONSE_OK; - int ret; - - isdn_msg_parse_event(msgs_g,msg,bc, 0); - - /** Preprocess some Events **/ - ret = handle_event(bc, event, frm); - if (ret<0) { - cb_log(0,stack->port,"couldn't handle event\n"); - free_msg(msg); - return 1; + default: + if (frm->prim == (CC_FACILITY | INDICATION)) { + cb_log(5, stack->port, " --> Using Dummy BC for FACILITY\n"); + } else { + cb_log(0, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo); + dummybc.l3_id = frm->dinfo; } - /* shoot up event to App: */ - cb_log(5, stack->port, "lib Got Prim: Addr %x prim %x dinfo %x\n",frm->addr, frm->prim, frm->dinfo); - - if(!isdn_get_info(msgs_g,event,0)) - cb_log(0, stack->port, "Unknown Event Ind: Addr:%x prim %x dinfo %x\n",frm->addr, frm->prim, frm->dinfo); - else - response=cb_event(event, bc, glob_mgr->user_data); -#if 1 - if (event == EVENT_SETUP) { - switch (response) { - case RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE: + bc = &dummybc; + break; + } + } - cb_log(0, stack->port, "TOTALLY IGNORING SETUP\n"); + event = isdn_msg_get_event(msgs_g, msg, 0); + isdn_msg_parse_event(msgs_g, msg, bc, 0); - break; - case RESPONSE_IGNORE_SETUP: - /* I think we should send CC_RELEASE_CR, but am not sure*/ - bc->out_cause = AST_CAUSE_NORMAL_CLEARING; - - case RESPONSE_RELEASE_SETUP: - misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); - if (bc->channel>0) - empty_chan_in_stack(stack, bc->channel); - empty_bc(bc); - bc_state_change(bc,BCHAN_CLEANED); - bc->in_use=0; - - cb_log(0, stack->port, "GOT IGNORE SETUP\n"); - break; - case RESPONSE_OK: - cb_log(4, stack->port, "GOT SETUP OK\n"); + /* Preprocess some Events */ + ret = handle_event(bc, event, frm); + if (ret < 0) { + cb_log(0, stack->port, "couldn't handle event\n"); + free_msg(msg); + return 1; + } + /* shoot up event to App: */ + cb_log(5, stack->port, "lib Got Prim: Addr %x prim %x dinfo %x\n", frm->addr, frm->prim, frm->dinfo); - break; - default: - break; - } - } - - if (event == EVENT_RELEASE_COMPLETE) { - /* release bchannel only after we've announced the RELEASE_COMPLETE */ - int channel=bc->channel; - int tmpcause=bc->cause; - int tmp_out_cause=bc->out_cause; - empty_bc(bc); - bc->cause=tmpcause; - bc->out_cause=tmp_out_cause; - clean_up_bc(bc); - - if (tmpcause == AST_CAUSE_REQUESTED_CHAN_UNAVAIL) { - cb_log(0,stack->port,"**** Received CAUSE:%d, so not cleaning up channel %d\n", AST_CAUSE_REQUESTED_CHAN_UNAVAIL, channel); - cb_log(0,stack->port,"**** This channel is now no longer available,\nplease try to restart it with 'misdn send restart <port> <channel>'\n"); - set_chan_in_stack(stack, channel); - bc->channel=channel; - misdn_lib_send_restart(stack->port, channel); - } else { - if (channel>0) - empty_chan_in_stack(stack, channel); - } - bc->in_use=0; - } + if (!isdn_get_info(msgs_g, event, 0)) { + cb_log(0, stack->port, "Unknown Event Ind: Addr:%x prim %x dinfo %x\n", frm->addr, frm->prim, frm->dinfo); + response = RESPONSE_OK; + } else { + response = cb_event(event, bc, glob_mgr->user_data); + } - if (event == EVENT_RESTART) { - cb_log(0, stack->port, "**** Received RESTART_ACK channel:%d\n", bc->restart_channel); - empty_chan_in_stack(stack, bc->restart_channel); + switch (event) { + case EVENT_SETUP: + switch (response) { + case RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE: + cb_log(0, stack->port, "TOTALLY IGNORING SETUP\n"); + break; + case RESPONSE_IGNORE_SETUP: + /* I think we should send CC_RELEASE_CR, but am not sure*/ + bc->out_cause = AST_CAUSE_NORMAL_CLEARING; + /* fall through */ + case RESPONSE_RELEASE_SETUP: + misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE); + if (bc->channel > 0) { + empty_chan_in_stack(stack, bc->channel); } + empty_bc(bc); + bc_state_change(bc, BCHAN_CLEANED); + bc->in_use = 0; - cb_log(5, stack->port, "Freeing Msg on prim:%x \n",frm->prim); - - - free_msg(msg); - return 1; -#endif - - } else { - struct misdn_bchannel dummybc; - if (frm->prim!=(CC_FACILITY|INDICATION)) - cb_log(0, stack->port, " --> Didn't find BC so temporarily creating dummy BC (l3id:%x) on this port.\n", frm->dinfo); - else - cb_log(5, stack->port, " --> Using Dummy BC for FACILITY\n"); - - memset (&dummybc,0,sizeof(dummybc)); - dummybc.port=stack->port; - dummybc.l3_id=frm->dinfo; - bc=&dummybc; - goto handle_frm_bc; + cb_log(0, stack->port, "GOT IGNORE SETUP\n"); + break; + case RESPONSE_OK: + cb_log(4, stack->port, "GOT SETUP OK\n"); + break; + default: + break; } + break; + case EVENT_RELEASE_COMPLETE: + /* release bchannel only after we've announced the RELEASE_COMPLETE */ + channel = bc->channel; + tmpcause = bc->cause; + tmp_out_cause = bc->out_cause; + + empty_bc(bc); + bc->cause = tmpcause; + bc->out_cause = tmp_out_cause; + clean_up_bc(bc); + + if (tmpcause == AST_CAUSE_REQUESTED_CHAN_UNAVAIL) { + cb_log(0, stack->port, "**** Received CAUSE:%d, so not cleaning up channel %d\n", AST_CAUSE_REQUESTED_CHAN_UNAVAIL, channel); + cb_log(0, stack->port, "**** This channel is now no longer available,\nplease try to restart it with 'misdn send restart <port> <channel>'\n"); + set_chan_in_stack(stack, channel); + bc->channel = channel; + misdn_lib_send_restart(stack->port, channel); + } else if (channel > 0) { + empty_chan_in_stack(stack, channel); + } + bc->in_use = 0; + break; + case EVENT_RESTART: + cb_log(0, stack->port, "**** Received RESTART_ACK channel:%d\n", bc->restart_channel); + empty_chan_in_stack(stack, bc->restart_channel); + break; + default: + break; } - cb_log(4, stack->port, "TE_FRM_HANDLER: Returning 0 on prim:%x \n",frm->prim); - return 0; + cb_log(5, stack->port, "Freeing Msg on prim:%x \n", frm->prim); + free_msg(msg); + return 1; } @@ -3148,7 +3160,8 @@ static void misdn_lib_isdn_event_catcher(void *arg) /** App Interface **/ -int te_lib_init(void) { +static int te_lib_init(void) +{ char buff[1025] = ""; iframe_t *frm = (iframe_t *) buff; int midev; @@ -3163,18 +3176,12 @@ int te_lib_init(void) { mISDN_write_frame(midev, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); ret = mISDN_read_frame(midev, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC); - - if (ret < mISDN_HEADER_LEN) { - noentity: + entity = frm->dinfo & 0xffff; + if (ret < mISDN_HEADER_LEN || !entity) { fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN: %s\n", strerror(errno)); exit(-1); } - entity = frm->dinfo & 0xffff ; - - if (!entity) - goto noentity; - return midev; } @@ -3221,9 +3228,11 @@ struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc) static int test_inuse(struct misdn_bchannel *bc) { struct timeval now; - gettimeofday(&now, NULL); + if (!bc->in_use) { - if (misdn_lib_port_is_pri(bc->port) && bc->last_used.tv_sec == now.tv_sec ) { + gettimeofday(&now, NULL); + if (bc->last_used.tv_sec == now.tv_sec + && misdn_lib_port_is_pri(bc->port)) { cb_log(2, bc->port, "channel with stid:%x for one second still in use! (n:%d lu:%d)\n", bc->b_stid, (int) now.tv_sec, (int) bc->last_used.tv_sec); return 1; @@ -3262,6 +3271,7 @@ struct misdn_bchannel *misdn_lib_get_free_bc(int port, int channel, int inout, i { struct misdn_stack *stack; int i; + int maxnum; if (channel < 0 || channel > MAX_BCHANS) { cb_log(0, port, "Requested channel out of bounds (%d)\n", channel); @@ -3270,71 +3280,111 @@ struct misdn_bchannel *misdn_lib_get_free_bc(int port, int channel, int inout, i usleep(1000); - for (stack=glob_mgr->stack_list; stack; stack=stack->next) { - - if (stack->port == port) { - int maxnum; + /* Find the port stack structure */ + stack = find_stack_by_port(port); + if (!stack) { + cb_log(0, port, "Port is not configured (%d)\n", port); + return NULL; + } - if (stack->blocked) { - cb_log(0,port,"Port is blocked\n"); - return NULL; - } + if (stack->blocked) { + cb_log(0, port, "Port is blocked\n"); + return NULL; + } - if (channel > 0) { - if (channel <= stack->b_num) { - for (i = 0; i < stack->b_num; i++) { - if ( stack->bc[i].channel == channel) { - if (test_inuse(&stack->bc[i])) { - cb_log(0,port,"Requested channel:%d on port:%d is already in use\n",channel, port); - return NULL; - - } else { - prepare_bc(&stack->bc[i], channel); - return &stack->bc[i]; - } - } + if (channel > 0) { + if (channel <= stack->b_num) { + for (i = 0; i < stack->b_num; i++) { + if (stack->bc[i].channel == channel) { + if (test_inuse(&stack->bc[i])) { + cb_log(0, port, "Requested channel:%d on port:%d is already in use\n", channel, port); + return NULL; + } else { + prepare_bc(&stack->bc[i], channel); + return &stack->bc[i]; } - } else { - cb_log(0,port,"Requested channel:%d is out of bounds on port:%d\n",channel, port); - return NULL; } } + } else { + cb_log(0, port, "Requested channel:%d is out of bounds on port:%d\n", channel, port); + return NULL; + } + } - maxnum = inout && !stack->pri && !stack->ptp ? stack->b_num + 1 : stack->b_num; - - if (dec) { - for (i = maxnum-1; i>=0; i--) { - if (!test_inuse(&stack->bc[i])) { - /* 3. channel on bri means CW*/ - if (!stack->pri && i==stack->b_num) - stack->bc[i].cw=1; - - prepare_bc(&stack->bc[i], channel); - stack->bc[i].dec=1; - return &stack->bc[i]; - } + /* Note: channel == 0 here */ + maxnum = (inout && !stack->pri && !stack->ptp) ? stack->b_num + 1 : stack->b_num; + if (dec) { + for (i = maxnum - 1; i >= 0; --i) { + if (!test_inuse(&stack->bc[i])) { + /* 3. channel on bri means CW*/ + if (!stack->pri && i == stack->b_num) { + stack->bc[i].cw = 1; } - } else { - for (i = 0; i <maxnum; i++) { - if (!test_inuse(&stack->bc[i])) { - /* 3. channel on bri means CW*/ - if (!stack->pri && i==stack->b_num) - stack->bc[i].cw=1; - prepare_bc(&stack->bc[i], channel); - return &stack->bc[i]; - } + prepare_bc(&stack->bc[i], channel); + stack->bc[i].dec = 1; + return &stack->bc[i]; + } + } + } else { + for (i = 0; i < maxnum; ++i) { + if (!test_inuse(&stack->bc[i])) { + /* 3. channel on bri means CW */ + if (!stack->pri && i == stack->b_num) { + stack->bc[i].cw = 1; } + + prepare_bc(&stack->bc[i], channel); + return &stack->bc[i]; } + } + } - cb_log(1,port,"There is no free channel on port (%d)\n",port); - return NULL; + cb_log(1, port, "There is no free channel on port (%d)\n", port); + return NULL; +} + +#if defined(AST_MISDN_ENHANCEMENTS) +/*! + * \brief Allocate a B channel struct from the REGISTER pool + * + * \param port Logical port number + * + * \retval B channel struct on success. + * \retval NULL on error. + */ +struct misdn_bchannel *misdn_lib_get_register_bc(int port) +{ + struct misdn_stack *stack; + struct misdn_bchannel *bc; + unsigned index; + + /* Find the port stack structure */ + stack = find_stack_by_port(port); + if (!stack) { + cb_log(0, port, "Port is not configured (%d)\n", port); + return NULL; + } + + if (stack->blocked) { + cb_log(0, port, "Port is blocked\n"); + return NULL; + } + + for (index = MAX_BCHANS + 1; index < ARRAY_LEN(stack->bc); ++index) { + bc = &stack->bc[index]; + if (!test_inuse(bc)) { + prepare_bc(bc, 0); + bc->need_disconnect = 0; + bc->need_release = 0; + return bc; } } - cb_log(0,port,"Port is not configured (%d)\n",port); + cb_log(1, port, "There is no free REGISTER link on port (%d)\n", port); return NULL; } +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ /*! * \internal @@ -3350,12 +3400,77 @@ static const char *fac2str(enum FacFunction facility) } arr[] = { /* *INDENT-OFF* */ { Fac_None, "Fac_None" }, +#if defined(AST_MISDN_ENHANCEMENTS) + { Fac_ERROR, "Fac_ERROR" }, + { Fac_RESULT, "Fac_RESULT" }, + { Fac_REJECT, "Fac_REJECT" }, + + { Fac_ActivationDiversion, "Fac_ActivationDiversion" }, + { Fac_DeactivationDiversion, "Fac_DeactivationDiversion" }, + { Fac_ActivationStatusNotificationDiv, "Fac_ActivationStatusNotificationDiv" }, + { Fac_DeactivationStatusNotificationDiv, "Fac_DeactivationStatusNotificationDiv" }, + { Fac_InterrogationDiversion, "Fac_InterrogationDiversion" }, + { Fac_DiversionInformation, "Fac_DiversionInformation" }, + { Fac_CallDeflection, "Fac_CallDeflection" }, + { Fac_CallRerouteing, "Fac_CallRerouteing" }, + { Fac_DivertingLegInformation2, "Fac_DivertingLegInformation2" }, + { Fac_InterrogateServedUserNumbers, "Fac_InterrogateServedUserNumbers" }, + { Fac_DivertingLegInformation1, "Fac_DivertingLegInformation1" }, + { Fac_DivertingLegInformation3, "Fac_DivertingLegInformation3" }, + + { Fac_EctExecute, "Fac_EctExecute" }, + { Fac_ExplicitEctExecute, "Fac_ExplicitEctExecute" }, + { Fac_RequestSubaddress, "Fac_RequestSubaddress" }, + { Fac_SubaddressTransfer, "Fac_SubaddressTransfer" }, + { Fac_EctLinkIdRequest, "Fac_EctLinkIdRequest" }, + { Fac_EctInform, "Fac_EctInform" }, + { Fac_EctLoopTest, "Fac_EctLoopTest" }, + + { Fac_ChargingRequest, "Fac_ChargingRequest" }, + { Fac_AOCSCurrency, "Fac_AOCSCurrency" }, + { Fac_AOCSSpecialArr, "Fac_AOCSSpecialArr" }, + { Fac_AOCDCurrency, "Fac_AOCDCurrency" }, + { Fac_AOCDChargingUnit, "Fac_AOCDChargingUnit" }, + { Fac_AOCECurrency, "Fac_AOCECurrency" }, + { Fac_AOCEChargingUnit, "Fac_AOCEChargingUnit" }, + + { Fac_StatusRequest, "Fac_StatusRequest" }, + + { Fac_CallInfoRetain, "Fac_CallInfoRetain" }, + { Fac_EraseCallLinkageID, "Fac_EraseCallLinkageID" }, + { Fac_CCBSDeactivate, "Fac_CCBSDeactivate" }, + { Fac_CCBSErase, "Fac_CCBSErase" }, + { Fac_CCBSRemoteUserFree, "Fac_CCBSRemoteUserFree" }, + { Fac_CCBSCall, "Fac_CCBSCall" }, + { Fac_CCBSStatusRequest, "Fac_CCBSStatusRequest" }, + { Fac_CCBSBFree, "Fac_CCBSBFree" }, + { Fac_CCBSStopAlerting, "Fac_CCBSStopAlerting" }, + + { Fac_CCBSRequest, "Fac_CCBSRequest" }, + { Fac_CCBSInterrogate, "Fac_CCBSInterrogate" }, + + { Fac_CCNRRequest, "Fac_CCNRRequest" }, + { Fac_CCNRInterrogate, "Fac_CCNRInterrogate" }, + + { Fac_CCBS_T_Call, "Fac_CCBS_T_Call" }, + { Fac_CCBS_T_Suspend, "Fac_CCBS_T_Suspend" }, + { Fac_CCBS_T_Resume, "Fac_CCBS_T_Resume" }, + { Fac_CCBS_T_RemoteUserFree, "Fac_CCBS_T_RemoteUserFree" }, + { Fac_CCBS_T_Available, "Fac_CCBS_T_Available" }, + + { Fac_CCBS_T_Request, "Fac_CCBS_T_Request" }, + + { Fac_CCNR_T_Request, "Fac_CCNR_T_Request" }, + +#else + { Fac_CFActivate, "Fac_CFActivate" }, { Fac_CFDeactivate, "Fac_CFDeactivate" }, { Fac_CD, "Fac_CD" }, { Fac_AOCDCurrency, "Fac_AOCDCurrency" }, { Fac_AOCDChargingUnit, "Fac_AOCDChargingUnit" }, +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ /* *INDENT-ON* */ }; @@ -3403,14 +3518,25 @@ void misdn_lib_log_ies(struct misdn_bchannel *bc) bc->caller.screening); cb_log(2, stack->port, - " --> redirecting:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d reason:%d\n", + " --> redirecting-from:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n", bc->redirecting.from.name, bc->redirecting.from.number, bc->redirecting.from.number_type, bc->redirecting.from.number_plan, bc->redirecting.from.presentation, - bc->redirecting.from.screening, - bc->redirecting.reason); + bc->redirecting.from.screening); + cb_log(2, stack->port, + " --> redirecting-to:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n", + bc->redirecting.to.name, + bc->redirecting.to.number, + bc->redirecting.to.number_type, + bc->redirecting.to.number_plan, + bc->redirecting.to.presentation, + bc->redirecting.to.screening); + cb_log(2, stack->port, + " --> redirecting reason:%d count:%d\n", + bc->redirecting.reason, + bc->redirecting.count); cb_log(2, stack->port, " --> connected:\"%s\" <%s> type:%d plan:%d pres:%d screen:%d\n", @@ -3427,7 +3553,7 @@ void misdn_lib_log_ies(struct misdn_bchannel *bc) cb_log(4, stack->port, " --> addr:%x l3id:%x b_stid:%x layer_id:%x\n", bc->addr, bc->l3_id, bc->b_stid, bc->layer_id); - cb_log(4, stack->port, " --> facility:%s out_facility:%s\n",fac2str(bc->fac_in.Function),fac2str(bc->fac_out.Function)); + cb_log(4, stack->port, " --> facility in:%s out:%s\n", fac2str(bc->fac_in.Function), fac2str(bc->fac_out.Function)); cb_log(5, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1); @@ -3454,8 +3580,13 @@ static void misdn_send_unlock(struct misdn_bchannel *bc) int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) { msg_t *msg; - int retval=0; + struct misdn_bchannel *bc2; + struct misdn_bchannel *holded_bc; struct misdn_stack *stack; + int retval = 0; + int channel; + int tmpcause; + int tmp_out_cause; if (!bc) RETURN(-1,OUT_POST_UNLOCK); @@ -3495,6 +3626,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) misdn_lib_log_ies(bc); switch (event) { + case EVENT_REGISTER: case EVENT_SETUP: if (create_process(glob_mgr->midev, bc) < 0) { cb_log(0, stack->port, " No free channel at the moment @ send_event\n"); @@ -3560,8 +3692,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) break; case EVENT_HOLD_ACKNOWLEDGE: - { - struct misdn_bchannel *holded_bc=malloc(sizeof(struct misdn_bchannel)); + holded_bc = malloc(sizeof(struct misdn_bchannel)); if (!holded_bc) { cb_log(0,bc->port, "Could not allocate holded_bc!!!\n"); RETURN(-1,OUT); @@ -3576,10 +3707,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) /*kill the bridge and clean the bchannel*/ if (stack->nt) { - int channel; if (bc->bc_state == BCHAN_BRIDGED) { - struct misdn_bchannel *bc2; - misdn_split_conf(bc,bc->conf_id); bc2 = find_bc_by_confid(bc->conf_id); if (!bc2) { @@ -3599,14 +3727,12 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) bc->in_use=0; } - - } - break; + break; /* finishing the channel eh ? */ case EVENT_DISCONNECT: if (!bc->need_disconnect) { - cb_log(0,bc->port," --> we have already send Disconnect\n"); + cb_log(0, bc->port, " --> we have already sent DISCONNECT\n"); RETURN(-1,OUT); } @@ -3614,7 +3740,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) break; case EVENT_RELEASE: if (!bc->need_release) { - cb_log(0,bc->port," --> we have already send Release\n"); + cb_log(0, bc->port, " --> we have already sent RELEASE\n"); RETURN(-1,OUT); } bc->need_disconnect=0; @@ -3622,7 +3748,7 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) break; case EVENT_RELEASE_COMPLETE: if (!bc->need_release_complete) { - cb_log(0,bc->port," --> we have already send Release_complete\n"); + cb_log(0, bc->port, " --> we have already sent RELEASE_COMPLETE\n"); RETURN(-1,OUT); } bc->need_disconnect=0; @@ -3631,10 +3757,10 @@ int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ) if (!stack->nt) { /* create cleanup in TE */ - int channel=bc->channel; + channel = bc->channel; + tmpcause = bc->cause; + tmp_out_cause = bc->out_cause; - int tmpcause=bc->cause; - int tmp_out_cause=bc->out_cause; empty_bc(bc); bc->cause=tmpcause; bc->out_cause=tmp_out_cause; @@ -4206,8 +4332,10 @@ int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_dat tok=strtok_r(NULL," ,",&tokb)) { int port = atoi(tok); struct misdn_stack *stack; - static int first=1; + struct misdn_stack *help; int ptp=0; + int i; + int r; if (strstr(tok, "ptp")) ptp=1; @@ -4223,27 +4351,34 @@ int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_dat exit(1); } - { - int i; - for(i=0;i<=stack->b_num; i++) { - int r; - if ((r=init_bc(stack, &stack->bc[i], stack->midev,port,i, "", 1))<0) { - cb_log(0, port, "Got Err @ init_bc :%d\n",r); - exit(1); - } + /* Initialize the B channel records for real B channels. */ + for (i = 0; i <= stack->b_num; i++) { + r = init_bc(stack, &stack->bc[i], stack->midev, port, i); + if (r < 0) { + cb_log(0, port, "Got Err @ init_bc :%d\n", r); + exit(1); } } - - if (stack && first) { - mgr->stack_list=stack; - first=0; - continue; +#if defined(AST_MISDN_ENHANCEMENTS) + /* Initialize the B channel records for REGISTER signaling links. */ + for (i = MAX_BCHANS + 1; i < ARRAY_LEN(stack->bc); ++i) { + r = init_bc(stack, &stack->bc[i], stack->midev, port, i); + if (r < 0) { + cb_log(0, port, "Got Err @ init_bc :%d\n", r); + exit(1); + } + stack->bc[i].is_register_pool = 1; } +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ - if (stack) { - struct misdn_stack * help; - for ( help=mgr->stack_list; help; help=help->next ) - if (help->next == NULL) break; + /* Add the new stack to the end of the list */ + help = mgr->stack_list; + if (!help) { + mgr->stack_list = stack; + } else { + while (help->next) { + help = help->next; + } help->next = stack; } } @@ -4473,8 +4608,9 @@ void manager_clean_bc(struct misdn_bchannel *bc ) { struct misdn_stack *stack=get_stack_by_bc(bc); - if (bc->channel>0) + if (stack && bc->channel > 0) { empty_chan_in_stack(stack, bc->channel); + } empty_bc(bc); bc->in_use=0; diff --git a/channels/misdn/isdn_lib.h b/channels/misdn/isdn_lib.h index 616721332..7bd516565 100644 --- a/channels/misdn/isdn_lib.h +++ b/channels/misdn/isdn_lib.h @@ -133,6 +133,7 @@ enum event_e { EVENT_PROCEEDING, EVENT_PROGRESS, EVENT_SETUP, + EVENT_REGISTER, EVENT_ALERTING, EVENT_CONNECT, EVENT_SETUP_ACKNOWLEDGE, @@ -216,6 +217,25 @@ enum mISDN_REDIRECTING_REASON { mISDN_REDIRECTING_REASON_CALL_FWD = 0xF }; +/*! + * \brief Notification description code enumeration + */ +enum mISDN_NOTIFY_CODE { + mISDN_NOTIFY_CODE_INVALID = -1, + /*! Call is placed on hold (Q.931) */ + mISDN_NOTIFY_CODE_USER_SUSPEND = 0x00, + /*! Call is taken off of hold (Q.931) */ + mISDN_NOTIFY_CODE_USER_RESUME = 0x01, + /*! Call is diverting (EN 300 207-1 Section 7.2.1) */ + mISDN_NOTIFY_CODE_CALL_IS_DIVERTING = 0x7B, + /*! Call diversion is enabled (cfu, cfb, cfnr) (EN 300 207-1 Section 7.2.1) */ + mISDN_NOTIFY_CODE_DIVERSION_ACTIVATED = 0x68, + /*! Call transfer, alerting (EN 300 369-1 Section 7.2) */ + mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING = 0x69, + /*! Call transfer, active(answered) (EN 300 369-1 Section 7.2) */ + mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE = 0x6A, +}; + enum { /*CODECS*/ INFO_CODEC_ULAW=2, INFO_CODEC_ALAW=3 @@ -241,6 +261,21 @@ enum layer_e { /*! Maximum keypad facility content length plus null terminator */ #define MISDN_MAX_KEYPAD_LEN (31 + 1) +/*! \brief Dialed/Called information struct */ +struct misdn_party_dialing { + /*! \brief Type-of-number in ISDN terms for the dialed/called number */ + enum mISDN_NUMBER_TYPE number_type; + + /*! \brief Type-of-number numbering plan. */ + enum mISDN_NUMBER_PLAN number_plan; + + /*! \brief Dialed/Called Phone Number (Address) */ + char number[MISDN_MAX_NUMBER_LEN]; + + /*! \brief Dialed/Called Subaddress number */ + char subaddress[MISDN_MAX_SUBADDRESS_LEN]; +}; + /*! \brief Connected-Line/Calling/Redirecting ID info struct */ struct misdn_party_id { /*! \brief Number presentation restriction code @@ -278,8 +313,17 @@ struct misdn_party_redirecting { /*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) */ struct misdn_party_id from; + /*! \brief Where the call is being redirected toward (Sent to the calling party) */ + struct misdn_party_id to; + /*! \brief Reason a call is being redirected (Q.931 field value) */ enum mISDN_REDIRECTING_REASON reason; + + /*! \brief Number of times the call has been redirected */ + int count; + + /*! \brief TRUE if the redirecting.to information has changed */ + int to_changed; }; @@ -288,6 +332,17 @@ struct misdn_bchannel { /*! \brief B channel send locking structure */ struct send_lock *send_lock; +#if defined(AST_MISDN_ENHANCEMENTS) + /*! \brief The BC, HLC (optional) and LLC (optional) contents from the SETUP message. */ + struct Q931_Bc_Hlc_Llc setup_bc_hlc_llc; +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ + + /*! + * \brief Dialed/Called information struct + * \note The number_type element is set to "dialplan" in /etc/asterisk/misdn.conf for outgoing calls + */ + struct misdn_party_dialing dialed; + /*! \brief Originating/Caller ID information struct * \note The number_type element can be set to "localdialplan" in /etc/asterisk/misdn.conf for outgoing calls * \note The number element can be set to "callerid" in /etc/asterisk/misdn.conf for outgoing calls @@ -360,6 +415,9 @@ struct misdn_bchannel { /*! \brief TRUE if the B channel number is preselected */ int channel_preselected; + /*! \brief TRUE if the B channel is allocated from the REGISTER pool */ + int is_register_pool; + /*! \brief TRUE if B channel record is in use */ int in_use; @@ -382,8 +440,6 @@ struct misdn_bchannel { /*! \brief Not used. Contents are setup but not used. */ void *astbuf; - void *misdnbuf; /* Not used */ - /*! \brief TRUE if the TE side should choose the B channel to use * \note This value is user configurable in /etc/asterisk/misdn.conf */ @@ -530,6 +586,9 @@ struct misdn_bchannel { /*! \brief TRUE if the user set the presentation restriction code */ int set_presentation; + /*! \brief Notification indicator ie description code */ + enum mISDN_NOTIFY_CODE notify_description_code; + /*! \brief SETUP message bearer capability field code value */ int capability; @@ -560,32 +619,12 @@ struct misdn_bchannel { int hdlc; /* V110 */ - /*! \brief Dialed/Called information struct */ - struct { - /*! \brief Type-of-number in ISDN terms for the dialed/called number - * \note This value is set to "dialplan" in /etc/asterisk/misdn.conf for outgoing calls - */ - enum mISDN_NUMBER_TYPE number_type; - - /*! \brief Type-of-number numbering plan. */ - enum mISDN_NUMBER_PLAN number_plan; - - /*! \brief Dialed/Called Phone Number (Address) */ - char number[MISDN_MAX_NUMBER_LEN]; - - /*! \brief Dialed/Called Subaddress number */ - char subaddress[MISDN_MAX_SUBADDRESS_LEN]; - } dialed; - /*! \brief Display message that can be displayed by the user phone. * \note Maximum displayable length is 34 or 82 octets. * It is also settable by the misdn_set_opt() application. */ char display[84]; - /*! \brief Not used. Contents are setup but not used. */ - char msn[MISDN_MAX_NUMBER_LEN]; - /*! \brief Q.931 Keypad Facility IE contents * \note Contents exported and imported to Asterisk variable MISDN_KEYPAD */ @@ -696,6 +735,9 @@ char *manager_isdn_get_info(enum event_e event); void misdn_lib_transfer(struct misdn_bchannel* holded_bc); struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel, int inout, int dec); +#if defined(AST_MISDN_ENHANCEMENTS) +struct misdn_bchannel *misdn_lib_get_register_bc(int port); +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ void manager_bchannel_activate(struct misdn_bchannel *bc); void manager_bchannel_deactivate(struct misdn_bchannel * bc); diff --git a/channels/misdn/isdn_lib_intern.h b/channels/misdn/isdn_lib_intern.h index 3347fe335..7e7ea8a61 100644 --- a/channels/misdn/isdn_lib_intern.h +++ b/channels/misdn/isdn_lib_intern.h @@ -51,7 +51,15 @@ struct isdn_msg { /* for isdn_msg_parser.c */ msg_t *create_l3msg(int prim, int mt, int dinfo , int size, int nt); +#if defined(AST_MISDN_ENHANCEMENTS) +/* Max call-completion REGISTER signaling links per stack/port */ +#define MISDN_MAX_REGISTER_LINKS MAX_BCHANS +#else +/* Max call-completion REGISTER signaling links per stack/port */ +#define MISDN_MAX_REGISTER_LINKS 0 +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ +#define MAXPROCS 0x100 struct misdn_stack { /** is first element because &nst equals &mISDNlist **/ @@ -87,8 +95,6 @@ struct misdn_stack { /*! \brief TRUE if Layer 2 is UP */ int l2link; - time_t l2establish; /* Not used */ - /*! \brief TRUE if Layer 1 is UP */ int l1link; @@ -105,7 +111,7 @@ struct misdn_stack { int pri; /*! \brief CR Process ID allocation table. TRUE if ID allocated */ - int procids[0x100+1]; + int procids[MAXPROCS]; /*! \brief Queue of Event messages to send to mISDN */ msg_queue_t downqueue; @@ -115,13 +121,17 @@ struct misdn_stack { /*! \brief Logical Layer 1 port associated with this stack */ int port; - /*! \brief B Channel record pool array */ - struct misdn_bchannel bc[MAX_BCHANS + 1]; - - struct misdn_bchannel* bc_list; /* Not used */ - - /*! \brief Array of B channels in use (a[0] = B1). TRUE if B channel in use */ - int channels[MAX_BCHANS + 1]; + /*! + * \brief B Channel record pool array + * (Must be dimensioned the same as struct misdn_stack.channels[]) + */ + struct misdn_bchannel bc[MAX_BCHANS + 1 + MISDN_MAX_REGISTER_LINKS]; + + /*! + * \brief Array of B channels in use (a[0] = B1). TRUE if B channel in use. + * (Must be dimensioned the same as struct misdn_stack.bc[]) + */ + char channels[MAX_BCHANS + 1 + MISDN_MAX_REGISTER_LINKS]; /*! \brief List of holded channels */ struct misdn_bchannel *holding; diff --git a/channels/misdn/isdn_msg_parser.c b/channels/misdn/isdn_msg_parser.c index 01c084ff7..4201cab2e 100644 --- a/channels/misdn/isdn_msg_parser.c +++ b/channels/misdn/isdn_msg_parser.c @@ -61,6 +61,80 @@ static void build_display_str(char *display, size_t display_length, int display_ } } +/*! + * \internal + * \brief Encode the Facility IE and put it into the message structure. + * + * \param ntmode Where the encoded facility was put when in NT mode. + * \param msg General message structure + * \param fac Data to encode into the facility ie. + * \param nt TRUE if in NT mode. + * + * \return Nothing + */ +static void enc_ie_facility(unsigned char **ntmode, msg_t *msg, struct FacParm *fac, int nt) +{ + int len; + Q931_info_t *qi; + unsigned char *p; + unsigned char buf[256]; + + len = encodeFac(buf, fac); + if (len <= 0) { + /* + * mISDN does not know how to build the requested facility structure + * Clear facility information + */ + fac->Function = Fac_None; + return; + } + + p = msg_put(msg, len); + if (nt) { + *ntmode = p + 1; + } else { + qi = (Q931_info_t *) (msg->data + mISDN_HEADER_LEN); + qi->QI_ELEMENT(facility) = p - (unsigned char *) qi - sizeof(Q931_info_t); + } + + memcpy(p, buf, len); + + /* Clear facility information */ + fac->Function = Fac_None; +} + +/*! + * \internal + * \brief Decode the Facility IE. + * + * \param p Encoded facility ie data to decode. (NT mode) + * \param qi Encoded facility ie data to decode. (TE mode) + * \param fac Where to put the decoded facility ie data if it is available. + * \param nt TRUE if in NT mode. + * \param bc Associated B channel + * + * \return Nothing + */ +static void dec_ie_facility(unsigned char *p, Q931_info_t *qi, struct FacParm *fac, int nt, struct misdn_bchannel *bc) +{ + fac->Function = Fac_None; + + if (!nt) { + p = NULL; + if (qi->QI_ELEMENT(facility)) { + p = (unsigned char *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1; + } + } + if (!p) { + return; + } + + if (decodeFac(p, fac)) { + cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n"); + } +} + + static void set_channel(struct misdn_bchannel *bc, int channel) { @@ -93,7 +167,7 @@ static void set_channel(struct misdn_bchannel *bc, int channel) static void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - CALL_PROCEEDING_t *proceeding=(CALL_PROCEEDING_t*)((unsigned long)msg->data+ HEADER_LEN); + CALL_PROCEEDING_t *proceeding = (CALL_PROCEEDING_t *) (msg->data + HEADER_LEN); //struct misdn_stack *stack=get_stack_by_bc(bc); { @@ -106,6 +180,9 @@ static void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_b dec_ie_progress(proceeding->PROGRESS, (Q931_info_t *)proceeding, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); + dec_ie_facility(proceeding->FACILITY, (Q931_info_t *) proceeding, &bc->fac_in, nt, bc); + + /* dec_ie_redir_dn */ #ifdef DEBUG printf("Parsing PROCEEDING Msg\n"); @@ -124,6 +201,11 @@ static msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *b if (nt) enc_ie_progress(&proceeding->PROGRESS, msg, 0, nt?1:5, 8, nt,bc); + if (bc->fac_out.Function != Fac_None) { + enc_ie_facility(&proceeding->FACILITY, msg, &bc->fac_out, nt); + } + + /* enc_ie_redir_dn */ #ifdef DEBUG printf("Building PROCEEDING Msg\n"); @@ -134,9 +216,13 @@ static msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *b static void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - ALERTING_t *alerting=(ALERTING_t*)((unsigned long)(msg->data+HEADER_LEN)); + ALERTING_t *alerting = (ALERTING_t *) (msg->data + HEADER_LEN); //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN); + dec_ie_facility(alerting->FACILITY, (Q931_info_t *) alerting, &bc->fac_in, nt, bc); + + /* dec_ie_redir_dn */ + dec_ie_progress(alerting->PROGRESS, (Q931_info_t *)alerting, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); #ifdef DEBUG @@ -158,6 +244,13 @@ static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, if (nt) enc_ie_progress(&alerting->PROGRESS, msg, 0, nt?1:5, 8, nt,bc); + + if (bc->fac_out.Function != Fac_None) { + enc_ie_facility(&alerting->FACILITY, msg, &bc->fac_out, nt); + } + + /* enc_ie_redir_dn */ + #ifdef DEBUG printf("Building ALERTING Msg\n"); #endif @@ -168,11 +261,13 @@ static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, static void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - PROGRESS_t *progress=(PROGRESS_t*)((unsigned long)(msg->data+HEADER_LEN)); + PROGRESS_t *progress = (PROGRESS_t *) (msg->data + HEADER_LEN); //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN); dec_ie_progress(progress->PROGRESS, (Q931_info_t *)progress, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); + dec_ie_facility(progress->FACILITY, (Q931_info_t *) progress, &bc->fac_in, nt, bc); + #ifdef DEBUG printf("Parsing PROGRESS Msg\n"); #endif @@ -186,17 +281,92 @@ static msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, progress=(PROGRESS_t*)((msg->data+HEADER_LEN)); + if (bc->fac_out.Function != Fac_None) { + enc_ie_facility(&progress->FACILITY, msg, &bc->fac_out, nt); + } + #ifdef DEBUG printf("Building PROGRESS Msg\n"); #endif return msg; } +#if defined(AST_MISDN_ENHANCEMENTS) +/*! + * \internal + * \brief Extract the SETUP message's BC, HLC, and LLC encoded ie contents. + * + * \param setup Indexed setup message contents + * \param nt TRUE if in NT mode. + * \param bc Associated B channel + * + * \return Nothing + */ +static void extract_setup_Bc_Hlc_Llc(SETUP_t *setup, int nt, struct misdn_bchannel *bc) +{ + __u8 *p; + Q931_info_t *qi; + + qi = (Q931_info_t *) setup; + + /* Extract Bearer Capability */ + if (nt) { + p = (__u8 *) setup->BEARER; + } else { + if (qi->QI_ELEMENT(bearer_capability)) { + p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1; + } else { + p = NULL; + } + } + if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Bc.Contents) < *p) { + bc->setup_bc_hlc_llc.Bc.Length = 0; + } else { + bc->setup_bc_hlc_llc.Bc.Length = *p; + memcpy(bc->setup_bc_hlc_llc.Bc.Contents, p + 1, *p); + } + + /* Extract Low Layer Compatibility */ + if (nt) { + p = (__u8 *) setup->LLC; + } else { + if (qi->QI_ELEMENT(llc)) { + p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1; + } else { + p = NULL; + } + } + if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Llc.Contents) < *p) { + bc->setup_bc_hlc_llc.Llc.Length = 0; + } else { + bc->setup_bc_hlc_llc.Llc.Length = *p; + memcpy(bc->setup_bc_hlc_llc.Llc.Contents, p + 1, *p); + } + + /* Extract High Layer Compatibility */ + if (nt) { + p = (__u8 *) setup->HLC; + } else { + if (qi->QI_ELEMENT(hlc)) { + p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(hlc) + 1; + } else { + p = NULL; + } + } + if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Hlc.Contents) < *p) { + bc->setup_bc_hlc_llc.Hlc.Length = 0; + } else { + bc->setup_bc_hlc_llc.Hlc.Length = *p; + memcpy(bc->setup_bc_hlc_llc.Hlc.Contents, p + 1, *p); + } +} +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ + static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - SETUP_t *setup= (SETUP_t*)((unsigned long)msg->data+HEADER_LEN); - Q931_info_t *qi=(Q931_info_t*)((unsigned long)msg->data+HEADER_LEN); + SETUP_t *setup = (SETUP_t *) (msg->data + HEADER_LEN); + Q931_info_t *qi = (Q931_info_t *) (msg->data + HEADER_LEN); int type; int plan; int present; @@ -207,7 +377,7 @@ static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchann printf("Parsing SETUP Msg\n"); #endif - dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, bc->caller.number, sizeof(bc->caller.number) - 1, nt, bc); + dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, bc->caller.number, sizeof(bc->caller.number), nt, bc); bc->caller.number_type = type; bc->caller.number_plan = plan; switch (present) { @@ -228,15 +398,17 @@ static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchann bc->caller.screening = 0; /* Unscreened */ } - dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *) setup, &type, &plan, bc->dialed.number, sizeof(bc->dialed.number) - 1, nt, bc); + dec_ie_facility(setup->FACILITY, (Q931_info_t *) setup, &bc->fac_in, nt, bc); + + dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *) setup, &type, &plan, bc->dialed.number, sizeof(bc->dialed.number), nt, bc); bc->dialed.number_type = type; bc->dialed.number_plan = plan; - dec_ie_keypad(setup->KEYPAD, (Q931_info_t *) setup, bc->keypad, sizeof(bc->keypad) - 1, nt, bc); + dec_ie_keypad(setup->KEYPAD, (Q931_info_t *) setup, bc->keypad, sizeof(bc->keypad), nt, bc); dec_ie_complete(setup->COMPLETE, (Q931_info_t *) setup, &bc->sending_complete, nt, bc); - dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *) setup, &type, &plan, &present, &screen, &reason, bc->redirecting.from.number, sizeof(bc->redirecting.from.number) - 1, nt, bc); + dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *) setup, &type, &plan, &present, &screen, &reason, bc->redirecting.from.number, sizeof(bc->redirecting.from.number), nt, bc); bc->redirecting.from.number_type = type; bc->redirecting.from.number_plan = plan; switch (present) { @@ -317,6 +489,9 @@ static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchann dec_ie_progress(setup->PROGRESS, (Q931_info_t *)setup, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); +#if defined(AST_MISDN_ENHANCEMENTS) + extract_setup_Bc_Hlc_Llc(setup, nt, bc); +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ } #define ANY_CHANNEL 0xff /* IE attribute for 'any channel' */ @@ -333,6 +508,9 @@ static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, in else enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc); + if (bc->fac_out.Function != Fac_None) { + enc_ie_facility(&setup->FACILITY, msg, &bc->fac_out, nt); + } enc_ie_calling_pn(&setup->CALLING_PN, msg, bc->caller.number_type, bc->caller.number_plan, bc->caller.presentation, bc->caller.screening, bc->caller.number, nt, bc); @@ -342,9 +520,17 @@ static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, in } if (bc->redirecting.from.number[0]) { +#if 1 + /* ETSI and Q.952 do not define the screening field */ + enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type, bc->redirecting.from.number_plan, + bc->redirecting.from.presentation, 0, bc->redirecting.reason, + bc->redirecting.from.number, nt, bc); +#else + /* Q.931 defines the screening field */ enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type, bc->redirecting.from.number_plan, bc->redirecting.from.presentation, bc->redirecting.from.screening, bc->redirecting.reason, bc->redirecting.from.number, nt, bc); +#endif } if (bc->keypad[0]) { @@ -409,6 +595,10 @@ static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, in cb_log(1,bc->port,"ENCODING USERUESRINFO:%s\n",bc->uu); } +#if defined(AST_MISDN_ENHANCEMENTS) + extract_setup_Bc_Hlc_Llc(setup, nt, bc); +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ + #ifdef DEBUG printf("Building SETUP Msg\n"); #endif @@ -418,7 +608,7 @@ static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, in static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - CONNECT_t *connect=(CONNECT_t*)((unsigned long)(msg->data+HEADER_LEN)); + CONNECT_t *connect = (CONNECT_t *) (msg->data + HEADER_LEN); int type; int plan; int pres; @@ -429,7 +619,7 @@ static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bcha dec_ie_progress(connect->PROGRESS, (Q931_info_t *)connect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); dec_ie_connected_pn(connect->CONNECT_PN, (Q931_info_t *) connect, &type, &plan, - &pres, &screen, bc->connected.number, sizeof(bc->connected.number) - 1, nt, bc); + &pres, &screen, bc->connected.number, sizeof(bc->connected.number), nt, bc); bc->connected.number_type = type; bc->connected.number_plan = plan; switch (pres) { @@ -450,6 +640,8 @@ static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bcha bc->connected.screening = 0; /* Unscreened */ } + dec_ie_facility(connect->FACILITY, (Q931_info_t *) connect, &bc->fac_in, nt, bc); + /* cb_log(1,bc->port,"CONNETED PN: %s cpn_dialplan:%d\n", connected_pn, type); */ @@ -488,6 +680,10 @@ static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, } } + if (bc->fac_out.Function != Fac_None) { + enc_ie_facility(&connect->FACILITY, msg, &bc->fac_out, nt); + } + #ifdef DEBUG printf("Building CONNECT Msg\n"); #endif @@ -497,7 +693,7 @@ static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, static void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - SETUP_ACKNOWLEDGE_t *setup_acknowledge=(SETUP_ACKNOWLEDGE_t*)((unsigned long)(msg->data+HEADER_LEN)); + SETUP_ACKNOWLEDGE_t *setup_acknowledge = (SETUP_ACKNOWLEDGE_t *) (msg->data + HEADER_LEN); { int exclusive, channel; @@ -508,6 +704,9 @@ static void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct } dec_ie_progress(setup_acknowledge->PROGRESS, (Q931_info_t *)setup_acknowledge, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); + + dec_ie_facility(setup_acknowledge->FACILITY, (Q931_info_t *) setup_acknowledge, &bc->fac_in, nt, bc); + #ifdef DEBUG printf("Parsing SETUP_ACKNOWLEDGE Msg\n"); #endif @@ -528,6 +727,10 @@ static msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bcha if (nt) enc_ie_progress(&setup_acknowledge->PROGRESS, msg, 0, nt?1:5, 8, nt,bc); + if (bc->fac_out.Function != Fac_None) { + enc_ie_facility(&setup_acknowledge->FACILITY, msg, &bc->fac_out, nt); + } + #ifdef DEBUG printf("Building SETUP_ACKNOWLEDGE Msg\n"); #endif @@ -862,12 +1065,14 @@ static msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchann static void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - DISCONNECT_t *disconnect=(DISCONNECT_t*)((unsigned long)(msg->data+HEADER_LEN)); + DISCONNECT_t *disconnect = (DISCONNECT_t *) (msg->data + HEADER_LEN); int location; int cause; dec_ie_cause(disconnect->CAUSE, (Q931_info_t *)(disconnect), &location, &cause, nt,bc); if (cause>0) bc->cause=cause; + dec_ie_facility(disconnect->FACILITY, (Q931_info_t *) disconnect, &bc->fac_in, nt, bc); + dec_ie_progress(disconnect->PROGRESS, (Q931_info_t *)disconnect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc); #ifdef DEBUG printf("Parsing DISCONNECT Msg\n"); @@ -885,7 +1090,13 @@ static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *b disconnect=(DISCONNECT_t*)((msg->data+HEADER_LEN)); enc_ie_cause(&disconnect->CAUSE, msg, (nt)?1:0, bc->out_cause,nt,bc); - if (nt) enc_ie_progress(&disconnect->PROGRESS, msg, 0, nt?1:5, 8 ,nt,bc); + if (nt) { + enc_ie_progress(&disconnect->PROGRESS, msg, 0, nt ? 1 : 5, 8, nt, bc); + } + + if (bc->fac_out.Function != Fac_None) { + enc_ie_facility(&disconnect->FACILITY, msg, &bc->fac_out, nt); + } if (bc->uulen) { int protocol=4; @@ -902,7 +1113,7 @@ static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *b static void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - RESTART_t *restart=(RESTART_t*)((unsigned long)(msg->data+HEADER_LEN)); + RESTART_t *restart = (RESTART_t *) (msg->data + HEADER_LEN); struct misdn_stack *stack=get_stack_by_bc(bc); @@ -944,12 +1155,15 @@ static msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, static void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - RELEASE_t *release=(RELEASE_t*)((unsigned long)(msg->data+HEADER_LEN)); + RELEASE_t *release = (RELEASE_t *) (msg->data + HEADER_LEN); int location; int cause; dec_ie_cause(release->CAUSE, (Q931_info_t *)(release), &location, &cause, nt,bc); if (cause>0) bc->cause=cause; + + dec_ie_facility(release->FACILITY, (Q931_info_t *) release, &bc->fac_in, nt, bc); + #ifdef DEBUG printf("Parsing RELEASE Msg\n"); #endif @@ -968,6 +1182,10 @@ static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, if (bc->out_cause>= 0) enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc); + if (bc->fac_out.Function != Fac_None) { + enc_ie_facility(&release->FACILITY, msg, &bc->fac_out, nt); + } + if (bc->uulen) { int protocol=4; enc_ie_useruser(&release->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc); @@ -983,7 +1201,7 @@ static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, static void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - RELEASE_COMPLETE_t *release_complete=(RELEASE_COMPLETE_t*)((unsigned long)(msg->data+HEADER_LEN)); + RELEASE_COMPLETE_t *release_complete = (RELEASE_COMPLETE_t *) (msg->data + HEADER_LEN); int location; int cause; iframe_t *frm = (iframe_t*) msg->data; @@ -1009,6 +1227,8 @@ static void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct m dec_ie_cause(release_complete->CAUSE, (Q931_info_t *)(release_complete), &location, &cause, nt,bc); if (cause>0) bc->cause=cause; + dec_ie_facility(release_complete->FACILITY, (Q931_info_t *) release_complete, &bc->fac_in, nt, bc); + #ifdef DEBUG printf("Parsing RELEASE_COMPLETE Msg\n"); #endif @@ -1024,6 +1244,10 @@ static msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchan enc_ie_cause(&release_complete->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc); + if (bc->fac_out.Function != Fac_None) { + enc_ie_facility(&release_complete->FACILITY, msg, &bc->fac_out, nt); + } + if (bc->uulen) { int protocol=4; enc_ie_useruser(&release_complete->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc); @@ -1042,12 +1266,13 @@ static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bch FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN); Q931_info_t *qi = (Q931_info_t*)(msg->data+HEADER_LEN); unsigned char *p = NULL; - int err; #ifdef DEBUG printf("Parsing FACILITY Msg\n"); #endif + bc->fac_in.Function = Fac_None; + if (!bc->nt) { if (qi->QI_ELEMENT(facility)) p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1; @@ -1057,9 +1282,8 @@ static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bch if (!p) return; - err = decodeFac(p, &(bc->fac_in)); - if (err) { - cb_log(5, bc->port, "Decoding FACILITY failed! (%d)\n", err); + if (decodeFac(p, &bc->fac_in)) { + cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n"); } } @@ -1079,7 +1303,11 @@ static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, len = encodeFac(fac_tmp, &(bc->fac_out)); if (len <= 0) { - /* mISDN does not know how to build the requested facility structure */ + /* + * mISDN does not know how to build the requested facility structure + * Clear facility information + */ + bc->fac_out.Function = Fac_None; return NULL; } @@ -1097,6 +1325,9 @@ static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, memcpy(ie_fac, fac_tmp, len); + /* Clear facility information */ + bc->fac_out.Function = Fac_None; + if (*bc->display) { #ifdef DEBUG printf("Sending %s as Display\n", bc->display); @@ -1107,11 +1338,106 @@ static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, return msg; } +#if defined(AST_MISDN_ENHANCEMENTS) +/*! + * \internal + * \brief Parse a received REGISTER message + * + * \param msgs Search table entry that called us. + * \param msg Received message contents + * \param bc Associated B channel + * \param nt TRUE if in NT mode. + * + * \return Nothing + */ +static void parse_register(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) +{ + int HEADER_LEN; + REGISTER_t *reg; + + HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN; + reg = (REGISTER_t *) (msg->data + HEADER_LEN); + + /* + * A facility ie is optional. + * The peer may just be establishing a connection to send + * messages later. + */ + dec_ie_facility(reg->FACILITY, (Q931_info_t *) reg, &bc->fac_in, nt, bc); +} +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ + +#if defined(AST_MISDN_ENHANCEMENTS) +/*! + * \internal + * \brief Construct a REGISTER message + * + * \param msgs Search table entry that called us. + * \param bc Associated B channel + * \param nt TRUE if in NT mode. + * + * \return Allocated built message + */ +static msg_t *build_register(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) +{ + int HEADER_LEN; + REGISTER_t *reg; + msg_t *msg; + + msg = (msg_t *) create_l3msg(CC_REGISTER | REQUEST, MT_REGISTER, bc ? bc->l3_id : -1, sizeof(REGISTER_t), nt); + HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN; + reg = (REGISTER_t *) (msg->data + HEADER_LEN); + + if (bc->fac_out.Function != Fac_None) { + enc_ie_facility(®->FACILITY, msg, &bc->fac_out, nt); + } + + return msg; +} +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ + static void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { + int HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN; + NOTIFY_t *notify = (NOTIFY_t *) (msg->data + HEADER_LEN); + int description_code; + int type; + int plan; + int present; + char number[sizeof(bc->redirecting.to.number)]; + #ifdef DEBUG printf("Parsing NOTIFY Msg\n"); #endif + + dec_ie_notify(notify->NOTIFY, (Q931_info_t *) notify, &description_code, nt, bc); + if (description_code < 0) { + bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID; + } else { + bc->notify_description_code = description_code; + } + + dec_ie_redir_dn(notify->REDIR_DN, (Q931_info_t *) notify, &type, &plan, &present, number, sizeof(number), nt, bc); + if (0 <= type) { + bc->redirecting.to_changed = 1; + + bc->redirecting.to.number_type = type; + bc->redirecting.to.number_plan = plan; + switch (present) { + default: + case 0: + bc->redirecting.to.presentation = 0; /* presentation allowed */ + break; + case 1: + bc->redirecting.to.presentation = 1; /* presentation restricted */ + break; + case 2: + bc->redirecting.to.presentation = 2; /* Number not available */ + break; + } + bc->redirecting.to.screening = 0; /* Unscreened */ + strcpy(bc->redirecting.to.number, number); + } } static msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt) @@ -1120,11 +1446,20 @@ static msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, i NOTIFY_t *notify; msg_t *msg =(msg_t*)create_l3msg(CC_NOTIFY | REQUEST, MT_NOTIFY, bc?bc->l3_id:-1, sizeof(NOTIFY_t) ,nt); - notify=(NOTIFY_t*)((msg->data+HEADER_LEN)); - #ifdef DEBUG printf("Building NOTIFY Msg\n"); #endif + + notify = (NOTIFY_t *) (msg->data + HEADER_LEN); + + enc_ie_notify(¬ify->NOTIFY, msg, bc->notify_description_code, nt, bc); + + if (bc->redirecting.to_changed) { + bc->redirecting.to_changed = 0; + enc_ie_redir_dn(¬ify->REDIR_DN, msg, bc->redirecting.to.number_type, + bc->redirecting.to.number_plan, bc->redirecting.to.presentation, + bc->redirecting.to.number, nt, bc); + } return msg; } @@ -1152,11 +1487,11 @@ static msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchanne static void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - INFORMATION_t *information=(INFORMATION_t*)((unsigned long)(msg->data+HEADER_LEN)); + INFORMATION_t *information = (INFORMATION_t *) (msg->data + HEADER_LEN); int type, plan; - dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *) information, &type, &plan, bc->info_dad, sizeof(bc->info_dad) - 1, nt, bc); - dec_ie_keypad(information->KEYPAD, (Q931_info_t *) information, bc->keypad, sizeof(bc->keypad) - 1, nt, bc); + dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *) information, &type, &plan, bc->info_dad, sizeof(bc->info_dad), nt, bc); + dec_ie_keypad(information->KEYPAD, (Q931_info_t *) information, bc->keypad, sizeof(bc->keypad), nt, bc); #ifdef DEBUG printf("Parsing INFORMATION Msg\n"); @@ -1191,7 +1526,7 @@ static msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel * static void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt) { int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN; - STATUS_t *status=(STATUS_t*)((unsigned long)(msg->data+HEADER_LEN)); + STATUS_t *status = (STATUS_t *) (msg->data + HEADER_LEN); int location; int cause; @@ -1253,6 +1588,9 @@ struct isdn_msg msgs_g[] = { { CC_ALERTING, EVENT_ALERTING, parse_alerting, build_alerting, "ALERTING" }, { CC_PROGRESS, EVENT_PROGRESS, parse_progress, build_progress, "PROGRESS" }, { CC_SETUP, EVENT_SETUP, parse_setup, build_setup, "SETUP" }, +#if defined(AST_MISDN_ENHANCEMENTS) + { CC_REGISTER, EVENT_REGISTER, parse_register, build_register, "REGISTER" }, +#endif /* defined(AST_MISDN_ENHANCEMENTS) */ { CC_CONNECT, EVENT_CONNECT, parse_connect, build_connect, "CONNECT" }, { CC_SETUP_ACKNOWLEDGE, EVENT_SETUP_ACKNOWLEDGE, parse_setup_acknowledge, build_setup_acknowledge, "SETUP_ACKNOWLEDGE" }, { CC_CONNECT_ACKNOWLEDGE, EVENT_CONNECT_ACKNOWLEDGE, parse_connect_acknowledge, build_connect_acknowledge, "CONNECT_ACKNOWLEDGE " }, |