diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 35ac69d06607f9853ffe3f5976193a9d61483d23..a47d1aa7d001e19f0a229e78eb31e47ea35d7940 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -338,6 +338,9 @@ struct hold_info { int channel; }; +#define chan_list_ref(obj, debug) (ao2_t_ref((obj), +1, (debug)), (obj)) +#define chan_list_unref(obj, debug) (ao2_t_ref((obj), -1, (debug)), NULL) + /*! * \brief Channel call record structure */ @@ -542,19 +545,6 @@ struct chan_list { */ int nttimeout; - /*! - * \brief Other channel call record PID - * \note Value imported from Asterisk environment variable MISDN_PID - */ - int other_pid; - - /*! - * \brief Bridged other channel call record - * \note Pointer set when other_pid imported from Asterisk environment - * variable MISDN_PID by either side. - */ - struct chan_list *other_ch; - /*! * \brief Tone zone sound used for dialtone generation. * \note Used as a boolean. Non-NULL to prod generation if enabled. @@ -744,6 +734,7 @@ static int misdn_chan_is_valid(struct chan_list *ch) return 0; } +/*! Returns a reference to the found chan_list. */ static struct chan_list *get_chan_by_ast(struct ast_channel *ast) { struct chan_list *tmp; @@ -751,6 +742,7 @@ static struct chan_list *get_chan_by_ast(struct ast_channel *ast) ast_mutex_lock(&cl_te_lock); for (tmp = cl_te; tmp; tmp = tmp->next) { if (tmp->ast == ast) { + chan_list_ref(tmp, "Found chan_list by ast"); ast_mutex_unlock(&cl_te_lock); return tmp; } @@ -760,6 +752,7 @@ static struct chan_list *get_chan_by_ast(struct ast_channel *ast) return NULL; } +/*! Returns a reference to the found chan_list. */ static struct chan_list *get_chan_by_ast_name(const char *name) { struct chan_list *tmp; @@ -767,6 +760,7 @@ static struct chan_list *get_chan_by_ast_name(const char *name) ast_mutex_lock(&cl_te_lock); for (tmp = cl_te; tmp; tmp = tmp->next) { if (tmp->ast && strcmp(tmp->ast->name, name) == 0) { + chan_list_ref(tmp, "Found chan_list by ast name"); ast_mutex_unlock(&cl_te_lock); return tmp; } @@ -5199,12 +5193,15 @@ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, st ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame); return 0; } + ao2_lock(tmp); #if defined(AST_MISDN_ENHANCEMENTS) max_len = sizeof(tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1; if (max_len < strlen(nr)) { ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n", nr, channame, max_len); + ao2_unlock(tmp); + chan_list_unref(tmp, "Number too long"); return 0; } tmp->bc->fac_out.Function = Fac_CallDeflection; @@ -5223,6 +5220,8 @@ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, st if (max_len < strlen(nr)) { ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n", nr, channame, max_len); + ao2_unlock(tmp); + chan_list_unref(tmp, "Number too long"); return 0; } tmp->bc->fac_out.Function = Fac_CD; @@ -5233,7 +5232,9 @@ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, st /* Send message */ print_facility(&tmp->bc->fac_out, tmp->bc); + ao2_unlock(tmp); misdn_lib_send_event(tmp->bc, EVENT_FACILITY); + chan_list_unref(tmp, "Send facility complete"); #if defined(AST_MISDN_ENHANCEMENTS) } else if (strstr(a->argv[3], "callrerouteing") || strstr(a->argv[3], "callrerouting")) { if (a->argc < 6) { @@ -5249,11 +5250,14 @@ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, st ast_verbose("Sending Call Rerouting with nr %s to %s failed: Channel does not exist.\n", nr, channame); return 0; } + ao2_lock(tmp); max_len = sizeof(tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1; if (max_len < strlen(nr)) { ast_verbose("Sending Call Rerouting with nr %s to %s failed: Number too long (up to %u digits are allowed).\n", nr, channame, max_len); + ao2_unlock(tmp); + chan_list_unref(tmp, "Number too long"); return 0; } tmp->bc->fac_out.Function = Fac_CallRerouteing; @@ -5284,11 +5288,13 @@ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, st /* Send message */ print_facility(&tmp->bc->fac_out, tmp->bc); + ao2_unlock(tmp); misdn_lib_send_event(tmp->bc, EVENT_FACILITY); + chan_list_unref(tmp, "Send facility complete"); #endif /* defined(AST_MISDN_ENHANCEMENTS) */ - } else if (strstr(a->argv[3], "CFActivate")) { - if (a->argc < 7) { - ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n"); + } else if (strstr(a->argv[3], "CFActivate")) { + if (a->argc < 7) { + ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n"); return 0; } port = atoi(a->argv[4]); @@ -5373,20 +5379,23 @@ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, st } port = atoi(a->argv[4]); - channame = argv[4]; + channame = a->argv[4]; tmp = get_chan_by_ast_name(channame); if (tmp) { /* We are going to send this FACILITY message out on an existing connection */ - msg_number = atoi(argv[5]); + msg_number = atoi(a->argv[5]); if (msg_number < ARRAY_LEN(Fac_Msgs)) { + ao2_lock(tmp); tmp->bc->fac_out = Fac_Msgs[msg_number]; /* Send message */ print_facility(&tmp->bc->fac_out, tmp->bc); + ao2_unlock(tmp); misdn_lib_send_event(tmp->bc, EVENT_FACILITY); } else { ast_verbose("test <channel-name> <msg#>\n\n"); } + chan_list_unref(tmp, "Facility test done"); } else if (a->argc < 6) { for (msg_number = 0; msg_number < ARRAY_LEN(Fac_Msgs); ++msg_number) { misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0); @@ -5410,16 +5419,16 @@ static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, st ast_verbose("test <port> [<msg#>]\n\n"); } } - } else if (strstr(argv[3], "register")) { - if (argc < 5) { - ast_cli(fd, "register <port>\n\n"); + } else if (strstr(a->argv[3], "register")) { + if (a->argc < 5) { + ast_verbose("register <port>\n\n"); return 0; } - port = atoi(argv[4]); + port = atoi(a->argv[4]); bc = misdn_lib_get_register_bc(port); if (!bc) { - ast_cli(fd, "Could not allocate REGISTER bc struct\n\n"); + ast_verbose("Could not allocate REGISTER bc struct\n\n"); return 0; } bc->fac_out = Fac_Msgs[45]; @@ -5501,6 +5510,9 @@ static char *handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struc } #if 1 for (i = 0; i < msglen; i++) { + if (!tmp->ast) { + break; + } ast_cli(a->fd, "Sending: %c\n", msg[i]); send_digit_to_chan(tmp, msg[i]); /* res = ast_safe_sleep(tmp->ast, 250); */ @@ -5508,8 +5520,11 @@ static char *handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struc /* res = ast_waitfor(tmp->ast,100); */ } #else - ast_dtmf_stream(tmp->ast, NULL, msg, 250); + if (tmp->ast) { + ast_dtmf_stream(tmp->ast, NULL, msg, 250); + } #endif + chan_list_unref(tmp, "Digit(s) sent"); return CLI_SUCCESS; } @@ -5556,6 +5571,7 @@ static char *handle_cli_misdn_toggle_echocancel(struct ast_cli_entry *e, int cmd } else { manager_ec_disable(tmp->bc); } + chan_list_unref(tmp, "Done toggling echo cancel"); return CLI_SUCCESS; } @@ -5586,12 +5602,16 @@ static char *handle_cli_misdn_send_display(struct ast_cli_entry *e, int cmd, str msg = a->argv[4]; ast_cli(a->fd, "Sending %s to %s\n", msg, channame); - tmp = get_chan_by_ast_name(channame); + tmp = get_chan_by_ast_name(channame); if (tmp && tmp->bc) { ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display)); misdn_lib_send_event(tmp->bc, EVENT_INFORMATION); + chan_list_unref(tmp, "Done sending display"); } else { + if (tmp) { + chan_list_unref(tmp, "Display failed"); + } ast_cli(a->fd, "No such channel %s\n", channame); return CLI_SUCCESS; } @@ -6457,7 +6477,6 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout) int port = 0; int r; int exceed; - int bridging; int number_type; struct chan_list *ch; struct misdn_bchannel *newbc; @@ -6675,20 +6694,6 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout) newbc->div_leg_3_rx_wanted = 1; } #endif /* defined(AST_MISDN_ENHANCEMENTS) */ - - /*check for bridging*/ - misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging)); - if (bridging && ch->other_ch) { -#ifdef MISDN_1_2 - chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n"); - *ch->bc->pipeline = 0; - *ch->other_ch->bc->pipeline = 0; -#else - chan_misdn_log(1, port, "Disabling EC on both Sides\n"); - ch->bc->ec_enable = 0; - ch->other_ch->bc->ec_enable = 0; -#endif - } } exceed = add_out_calls(port); @@ -6937,18 +6942,6 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data, chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc->pid); misdn_lib_send_event(p->bc, EVENT_ALERTING); - if (p->other_ch && p->other_ch->bc) { - if (misdn_inband_avail(p->other_ch->bc)) { - chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n"); - break; - } - - if (!p->other_ch->bc->nt) { - chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n"); - break; - } - } - chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc->pid); ast_setstate(ast, AST_STATE_RING); @@ -7034,15 +7027,22 @@ static int misdn_hangup(struct ast_channel *ast) return -1; } + ast_debug(1, "misdn_hangup(%s)\n", ast->name); + + /* Take the ast_channel's tech_pvt reference. */ ast_mutex_lock(&release_lock); p = MISDN_ASTERISK_TECH_PVT(ast); - if (!p || !misdn_chan_is_valid(p)) { + if (!p) { ast_mutex_unlock(&release_lock); return -1; } MISDN_ASTERISK_TECH_PVT(ast) = NULL; - ast_debug(1, "misdn_hangup(%s)\n", ast->name); + if (!misdn_chan_is_valid(p)) { + ast_mutex_unlock(&release_lock); + chan_list_unref(p, "Release ast_channel reference. Was not active?"); + return 0; + } if (p->hold.state == MISDN_HOLD_IDLE) { bc = p->bc; @@ -7054,6 +7054,7 @@ static int misdn_hangup(struct ast_channel *ast) "misdn_hangup: Could not find held bc for (%s)\n", ast->name); release_chan_early(p); ast_mutex_unlock(&release_lock); + chan_list_unref(p, "Release ast_channel reference"); return 0; } } @@ -7066,6 +7067,7 @@ static int misdn_hangup(struct ast_channel *ast) misdn_lib_release(bc); } ast_mutex_unlock(&release_lock); + chan_list_unref(p, "Release ast_channel reference"); return 0; } if (!bc) { @@ -7073,6 +7075,7 @@ static int misdn_hangup(struct ast_channel *ast) misdn_get_ch_state(p), p->l3id); release_chan_early(p); ast_mutex_unlock(&release_lock); + chan_list_unref(p, "Release ast_channel reference"); return 0; } @@ -7132,6 +7135,7 @@ static int misdn_hangup(struct ast_channel *ast) release_chan(p, bc); misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE); ast_mutex_unlock(&release_lock); + chan_list_unref(p, "Release ast_channel reference"); return 0; case MISDN_DIALING: if (p->hold.state == MISDN_HOLD_IDLE) { @@ -7185,6 +7189,7 @@ static int misdn_hangup(struct ast_channel *ast) case MISDN_CLEANING: ast_mutex_unlock(&release_lock); + chan_list_unref(p, "Release ast_channel reference"); return 0; case MISDN_BUSY: @@ -7208,6 +7213,7 @@ static int misdn_hangup(struct ast_channel *ast) misdn_get_ch_state(p)); ast_mutex_unlock(&release_lock); + chan_list_unref(p, "Release ast_channel reference"); return 0; } @@ -7494,20 +7500,25 @@ static enum ast_bridge_result misdn_bridge(struct ast_channel *c0, int bridging; ch1 = get_chan_by_ast(c0); + if (!ch1) { + return -1; + } ch2 = get_chan_by_ast(c1); + if (!ch2) { + chan_list_unref(ch1, "Failed to find ch2"); + return -1; + } carr[0] = c0; carr[1] = c1; - if (!(ch1 && ch2)) { - return -1; - } - misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b)); misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b)); if (! p1_b || ! p2_b) { ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n"); + chan_list_unref(ch1, "Bridge fallback ch1"); + chan_list_unref(ch2, "Bridge fallback ch2"); return AST_BRIDGE_FAILED; } @@ -7581,6 +7592,8 @@ static enum ast_bridge_result misdn_bridge(struct ast_channel *c0, misdn_lib_split_bridge(ch1->bc, ch2->bc); + chan_list_unref(ch1, "Bridge complete ch1"); + chan_list_unref(ch2, "Bridge complete ch2"); return AST_BRIDGE_COMPLETE; } @@ -7663,12 +7676,58 @@ static int stop_bc_tones(struct chan_list *cl) return 0; } +/*! + * \internal + * \brief Destroy the chan_list object. + * + * \param obj chan_list object to destroy. + * + * \return Nothing + */ +static void chan_list_destructor(void *obj) +{ + struct chan_list *ch = obj; + +#if defined(AST_MISDN_ENHANCEMENTS) + if (ch->peer) { + ao2_ref(ch->peer, -1); + ch->peer = NULL; + } +#endif /* AST_MISDN_ENHANCEMENTS */ + + if (ch->dsp) { + ast_dsp_free(ch->dsp); + ch->dsp = NULL; + } + + /* releasing jitterbuffer */ + if (ch->jb) { + misdn_jb_destroy(ch->jb); + ch->jb = NULL; + } + + if (ch->overlap_dial) { + if (ch->overlap_dial_task != -1) { + misdn_tasks_remove(ch->overlap_dial_task); + ch->overlap_dial_task = -1; + } + ast_mutex_destroy(&ch->overlap_tv_lock); + } -static struct chan_list *init_chan_list(int orig) + if (-1 < ch->pipe[0]) { + close(ch->pipe[0]); + } + if (-1 < ch->pipe[1]) { + close(ch->pipe[1]); + } +} + +/*! Returns a reference to the new chan_list. */ +static struct chan_list *chan_list_init(int orig) { struct chan_list *cl; - cl = ast_calloc(1, sizeof(*cl)); + cl = ao2_alloc(sizeof(*cl), chan_list_destructor); if (!cl) { chan_misdn_log(-1, 0, "misdn_request: malloc failed!"); return NULL; @@ -7682,6 +7741,8 @@ static struct chan_list *init_chan_list(int orig) #if defined(AST_MISDN_ENHANCEMENTS) cl->record_id = -1; #endif /* defined(AST_MISDN_ENHANCEMENTS) */ + cl->pipe[0] = -1; + cl->pipe[1] = -1; return cl; } @@ -7905,7 +7966,7 @@ static struct ast_channel *misdn_request(const char *type, format_t format, cons } /* create ast_channel and link all the objects together */ - cl = init_chan_list(ORG_AST); + cl = chan_list_init(ORG_AST); if (!cl) { ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str); return NULL; @@ -7914,11 +7975,10 @@ static struct ast_channel *misdn_request(const char *type, format_t format, cons ast = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, format, requestor ? requestor->linkedid : NULL, port, channel); if (!ast) { - ast_free(cl); + chan_list_unref(cl, "Failed to create a new channel"); ast_log(LOG_ERROR, "Could not create Asterisk channel for Dial(%s)\n", dial_str); return NULL; } - cl->ast = ast; #if defined(AST_MISDN_ENHANCEMENTS) cl->record_id = record_id; @@ -7933,13 +7993,14 @@ static struct ast_channel *misdn_request(const char *type, format_t format, cons /* important */ cl->need_hangup = 0; + chan_list_unref(cl, "Successful misdn_request()"); return ast; } static int misdn_send_text(struct ast_channel *chan, const char *text) { - struct chan_list *tmp = chan->tech_pvt; + struct chan_list *tmp = MISDN_ASTERISK_TECH_PVT(chan); if (tmp && tmp->bc) { ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display)); @@ -8050,7 +8111,10 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char tmp->writeformat = format; tmp->rawwriteformat = format; - tmp->tech_pvt = chlist; + /* Link the channel and private together */ + chan_list_ref(chlist, "Give a reference to ast_channel"); + MISDN_ASTERISK_TECH_PVT(tmp) = chlist; + chlist->ast = tmp; misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging)); tmp->tech = bridging ? &misdn_tech : &misdn_tech_wo_bridge; @@ -8087,6 +8151,7 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char return tmp; } +/*! Returns a reference to the found chan_list. */ static struct chan_list *find_chan_by_bc(struct misdn_bchannel *bc) { struct chan_list *help; @@ -8094,6 +8159,7 @@ static struct chan_list *find_chan_by_bc(struct misdn_bchannel *bc) ast_mutex_lock(&cl_te_lock); for (help = cl_te; help; help = help->next) { if (help->bc == bc) { + chan_list_ref(help, "Found chan_list by bc"); ast_mutex_unlock(&cl_te_lock); return help; } @@ -8109,24 +8175,7 @@ static struct chan_list *find_chan_by_bc(struct misdn_bchannel *bc) return NULL; } -static struct chan_list *find_chan_by_pid(int pid) -{ - struct chan_list *help; - - ast_mutex_lock(&cl_te_lock); - for (help = cl_te; help; help = help->next) { - if (help->bc && (help->bc->pid == pid)) { - ast_mutex_unlock(&cl_te_lock); - return help; - } - } - ast_mutex_unlock(&cl_te_lock); - - chan_misdn_log(6, 0, "$$$ find_chan_by_pid: No channel found for pid:%d\n", pid); - - return NULL; -} - +/*! Returns a reference to the found chan_list. */ static struct chan_list *find_hold_call(struct misdn_bchannel *bc) { struct chan_list *help; @@ -8144,6 +8193,7 @@ static struct chan_list *find_hold_call(struct misdn_bchannel *bc) for (help = cl_te; help; help = help->next) { chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel); if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port) { + chan_list_ref(help, "Found chan_list hold call"); ast_mutex_unlock(&cl_te_lock); return help; } @@ -8159,6 +8209,7 @@ static struct chan_list *find_hold_call(struct misdn_bchannel *bc) } +/*! Returns a reference to the found chan_list. */ static struct chan_list *find_hold_call_l3(unsigned long l3_id) { struct chan_list *help; @@ -8166,6 +8217,7 @@ static struct chan_list *find_hold_call_l3(unsigned long l3_id) ast_mutex_lock(&cl_te_lock); for (help = cl_te; help; help = help->next) { if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id) { + chan_list_ref(help, "Found chan_list hold call l3"); ast_mutex_unlock(&cl_te_lock); return help; } @@ -8185,6 +8237,8 @@ static struct chan_list *find_hold_call_l3(unsigned long l3_id) * * \return Found call record or NULL. * + * \note Returns a reference to the found chan_list. + * * \note There could be a possibility where we find the wrong active call to transfer. * This concern is mitigated by the fact that there could be at most one other call * on a PTMP BRI link to another device. Maybe the l3_id could help in locating an @@ -8203,6 +8257,7 @@ static struct chan_list *find_hold_active_call(struct misdn_bchannel *bc) case MISDN_PROGRESS: case MISDN_ALERTING: case MISDN_CONNECTED: + chan_list_ref(list, "Found chan_list hold active call"); ast_mutex_unlock(&cl_te_lock); return list; default: @@ -8219,6 +8274,7 @@ static void cl_queue_chan(struct chan_list *chan) { chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan); + chan_list_ref(chan, "Adding chan_list to list"); ast_mutex_lock(&cl_te_lock); chan->next = NULL; if (!cl_te) { @@ -8251,6 +8307,7 @@ static int cl_dequeue_chan(struct chan_list *chan) /* What we want is the head of the list. */ cl_te = cl_te->next; ast_mutex_unlock(&cl_te_lock); + chan_list_unref(chan, "Removed chan_list from list head"); return 1; } @@ -8265,6 +8322,9 @@ static int cl_dequeue_chan(struct chan_list *chan) } ast_mutex_unlock(&cl_te_lock); + if (found_it) { + chan_list_unref(chan, "Removed chan_list from list"); + } return found_it; } @@ -8326,7 +8386,7 @@ static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc) * * \return Nothing * - * \note ch must not be referenced after calling. + * \note The only valid thing to do with ch after calling is to chan_list_unref(ch, ""). */ static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc) { @@ -8353,6 +8413,9 @@ static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc) ch->state = MISDN_CLEANING; ch->ast = NULL; if (ast) { + struct chan_list *ast_ch; + + ast_ch = MISDN_ASTERISK_TECH_PVT(ast); MISDN_ASTERISK_TECH_PVT(ast) = NULL; chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s>\n", @@ -8367,49 +8430,17 @@ static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc) ast_setstate(ast, AST_STATE_DOWN); } ast_channel_unlock(ast); - } - -#if defined(AST_MISDN_ENHANCEMENTS) - if (ch->peer) { - ao2_ref(ch->peer, -1); - ch->peer = NULL; - } -#endif /* AST_MISDN_ENHANCEMENTS */ - - if (ch->dsp) { - ast_dsp_free(ch->dsp); - ch->dsp = NULL; - } - - /* releasing jitterbuffer */ - if (ch->jb) { - misdn_jb_destroy(ch->jb); - ch->jb = NULL; - } else { - if (!bc->nojitter) { - chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n"); + if (ast_ch) { + chan_list_unref(ast_ch, "Release ast_channel reference."); } } - if (ch->overlap_dial) { - if (ch->overlap_dial_task != -1) { - misdn_tasks_remove(ch->overlap_dial_task); - ch->overlap_dial_task = -1; - } - ast_mutex_destroy(&ch->overlap_tv_lock); - } - if (ch->originator == ORG_AST) { --misdn_out_calls[bc->port]; } else { --misdn_in_calls[bc->port]; } - close(ch->pipe[0]); - close(ch->pipe[1]); - - ast_free(ch); - ast_mutex_unlock(&release_lock); } @@ -8421,7 +8452,7 @@ static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc) * * \return Nothing * - * \note ch must not be referenced after calling. + * \note The only valid thing to do with ch after calling is to chan_list_unref(ch, ""). */ static void release_chan_early(struct chan_list *ch) { @@ -8446,37 +8477,18 @@ static void release_chan_early(struct chan_list *ch) ch->state = MISDN_CLEANING; ch->ast = NULL; if (ast) { + struct chan_list *ast_ch; + + ast_ch = MISDN_ASTERISK_TECH_PVT(ast); MISDN_ASTERISK_TECH_PVT(ast) = NULL; + if (ast->_state != AST_STATE_RESERVED) { ast_setstate(ast, AST_STATE_DOWN); } ast_channel_unlock(ast); - } - -#if defined(AST_MISDN_ENHANCEMENTS) - if (ch->peer) { - ao2_ref(ch->peer, -1); - ch->peer = NULL; - } -#endif /* AST_MISDN_ENHANCEMENTS */ - - if (ch->dsp) { - ast_dsp_free(ch->dsp); - ch->dsp = NULL; - } - - /* releasing jitterbuffer */ - if (ch->jb) { - misdn_jb_destroy(ch->jb); - ch->jb = NULL; - } - - if (ch->overlap_dial) { - if (ch->overlap_dial_task != -1) { - misdn_tasks_remove(ch->overlap_dial_task); - ch->overlap_dial_task = -1; + if (ast_ch) { + chan_list_unref(ast_ch, "Release ast_channel reference."); } - ast_mutex_destroy(&ch->overlap_tv_lock); } if (ch->hold.state != MISDN_HOLD_IDLE) { @@ -8487,11 +8499,6 @@ static void release_chan_early(struct chan_list *ch) } } - close(ch->pipe[0]); - close(ch->pipe[1]); - - ast_free(ch); - ast_mutex_unlock(&release_lock); } @@ -8796,18 +8803,6 @@ void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_ const char *tmp; ast_channel_lock(chan); - tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID"); - if (tmp) { - ch->other_pid = atoi(tmp); - chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp); - if (ch->other_pid > 0) { - ch->other_ch = find_chan_by_pid(ch->other_pid); - if (ch->other_ch) { - ch->other_ch->other_ch = ch; - } - } - } - tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE"); if (tmp && (atoi(tmp) == 1)) { bc->sending_complete = 1; @@ -8832,6 +8827,12 @@ void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_ { char tmp[32]; + /* + * The only use for MISDN_PID is if there is a problem and you + * have to use the "misdn restart pid" CLI command. Otherwise, + * the pid is not used by anyone. The internal use of MISDN_PID + * has been deleted. + */ chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid); snprintf(tmp, sizeof(tmp), "%d", bc->pid); pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp); @@ -9962,9 +9963,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) chan_misdn_log(1, bc->port, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n", bc->l3_id, bc, manager_isdn_get_info(event), bc->port, bc->channel); return -1; } - } - - if (ch) { + } else { switch (event) { case EVENT_TONE_GENERATE: break; @@ -9982,6 +9981,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) if (event != EVENT_BCHAN_DATA) { ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event)); } + chan_list_unref(ch, "No Ast or Ast private pointer"); return -1; } break; @@ -10157,7 +10157,6 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) break; case EVENT_SETUP: { - struct chan_list *ch = find_chan_by_bc(bc); struct ast_channel *chan; int exceed; int ai; @@ -10167,9 +10166,11 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) if (ch) { switch (ch->state) { case MISDN_NOTHING: + chan_list_unref(ch, "Ignore found ch. Is it for an outgoing call?"); ch = NULL; break; default: + chan_list_unref(ch, "Already have a call."); chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n"); return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /* Ignore MSNs which are not in our List */ } @@ -10190,7 +10191,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) print_bearer(bc); - ch = init_chan_list(ORG_MISDN); + ch = chan_list_init(ORG_MISDN); if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0; @@ -10202,14 +10203,12 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, AST_FORMAT_ALAW, NULL, bc->port, bc->channel); if (!chan) { - ast_free(ch); + chan_list_unref(ch, "Failed to create a new channel"); misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n"); return 0; } - ch->ast = chan; - if ((exceed = add_in_calls(bc->port))) { char tmp[16]; snprintf(tmp, sizeof(tmp), "%d", exceed); @@ -10292,6 +10291,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) ch->state = MISDN_EXTCANTMATCH; misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE); + chan_list_unref(ch, "BC not allowed, releasing call"); return RESPONSE_OK; } } @@ -10679,6 +10679,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } } } + if (held_ch) { + chan_list_unref(held_ch, "Done with held call"); + } bc->out_cause = -1; if (bc->need_release) { misdn_lib_send_event(bc, EVENT_RELEASE); @@ -11045,6 +11048,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) break; } + if (ch) { + chan_list_unref(ch, "cb_event complete OK"); + } return RESPONSE_OK; } @@ -12483,13 +12489,22 @@ static int misdn_set_opt_exec(struct ast_channel *chan, const char *data) int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len) { - struct chan_list *ch = find_chan_by_bc(bc); + struct chan_list *ch; + int res; - if (ch && ch->jb) { - return misdn_jb_empty(ch->jb, buf, len); + ch = find_chan_by_bc(bc); + if (!ch) { + return 0; } - return -1; + if (ch->jb) { + res = misdn_jb_empty(ch->jb, buf, len); + } else { + res = 0; + } + chan_list_unref(ch, "Done emptying jb"); + + return res; }