Unique Call ID logging Phases III and IV
authorJonathan Rose <jrose@digium.com>
Tue, 26 Jun 2012 21:45:22 +0000 (21:45 +0000)
committerJonathan Rose <jrose@digium.com>
Tue, 26 Jun 2012 21:45:22 +0000 (21:45 +0000)
Adds call ID logging changes to specific channel drivers that weren't handled
handled in phase II of Call ID Logging. Also covers logging for threads for
threads created by systems that may be involved with many different calls.
Extra special thanks to Richard for rigorous review of chan_dahdi and its
various signalling modules.

review: https://reviewboard.asterisk.org/r/1927/
review: https://reviewboard.asterisk.org/r/1950/

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@369414 65c4cc65-6c06-0410-ace0-fbb531ad65f3

15 files changed:
channels/chan_agent.c
channels/chan_dahdi.c
channels/chan_iax2.c
channels/chan_local.c
channels/sig_analog.c
channels/sig_pri.c
channels/sig_ss7.c
include/asterisk/logger.h
main/autoservice.c
main/bridging.c
main/channel_internal_api.c
main/cli.c
main/features.c
main/logger.c
main/pbx.c

index 29f49f8..2468b09 100644 (file)
@@ -1099,7 +1099,7 @@ static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct
 }
 
 /*! \brief Create new agent channel */
-static struct ast_channel *agent_new(struct agent_pvt *p, int state, const char *linkedid)
+static struct ast_channel *agent_new(struct agent_pvt *p, int state, const char *linkedid, struct ast_callid *callid)
 {
        struct ast_channel *tmp;
 #if 0
@@ -1117,6 +1117,10 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state, const char
                return NULL;
        }
 
+       if (callid) {
+               ast_channel_callid_set(tmp, callid);
+       }
+
        ast_channel_tech_set(tmp, &agent_tech);
        if (p->chan) {
                ast_format_cap_copy(ast_channel_nativeformats(tmp), ast_channel_nativeformats(p->chan));
@@ -1329,7 +1333,7 @@ static int check_availability(struct agent_pvt *newlyavailable, int needlock)
                if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
                        ast_debug(1, "Call '%s' looks like a winner for agent '%s'\n", ast_channel_name(p->owner), newlyavailable->agent);
                        /* We found a pending call, time to merge */
-                       chan = agent_new(newlyavailable, AST_STATE_DOWN, p->owner ? ast_channel_linkedid(p->owner) : NULL);
+                       chan = agent_new(newlyavailable, AST_STATE_DOWN, p->owner ? ast_channel_linkedid(p->owner) : NULL, NULL);
                        parent = p->owner;
                        p->abouttograb = 1;
                        ast_mutex_unlock(&p->lock);
@@ -1422,6 +1426,7 @@ static struct ast_channel *agent_request(const char *type, struct ast_format_cap
        int waitforagent=0;
        int hasagent = 0;
        struct timeval now;
+       struct ast_callid *callid = ast_read_threadstorage_callid();
 
        s = data;
        if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1)) {
@@ -1445,7 +1450,7 @@ static struct ast_channel *agent_request(const char *type, struct ast_format_cap
                                /* Agent must be registered, but not have any active call, and not be in a waiting state */
                                if (!p->owner && p->chan) {
                                        /* Fixed agent */
-                                       chan = agent_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
+                                       chan = agent_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL, callid);
                                }
                                if (chan) {
                                        ast_mutex_unlock(&p->lock);
@@ -1468,7 +1473,7 @@ static struct ast_channel *agent_request(const char *type, struct ast_format_cap
                                        /* Agent must be registered, but not have any active call, and not be in a waiting state */
                                        if (!p->owner && p->chan) {
                                                /* Could still get a fixed agent */
-                                               chan = agent_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
+                                               chan = agent_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL, callid);
                                        }
                                        if (chan) {
                                                ast_mutex_unlock(&p->lock);
@@ -1487,7 +1492,7 @@ static struct ast_channel *agent_request(const char *type, struct ast_format_cap
                        ast_debug(1, "Creating place holder for '%s'\n", s);
                        p = add_agent(data, 1);
                        p->group = groupmatch;
-                       chan = agent_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
+                       chan = agent_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL, callid);
                        if (!chan) 
                                ast_log(LOG_WARNING, "Weird...  Fix this to drop the unused pending agent\n");
                } else {
@@ -1497,6 +1502,10 @@ static struct ast_channel *agent_request(const char *type, struct ast_format_cap
        *cause = hasagent ? AST_CAUSE_BUSY : AST_CAUSE_UNREGISTERED;
        AST_LIST_UNLOCK(&agents);
 
+       if (callid) {
+               callid = ast_callid_unref(callid);
+       }
+
        if (chan) {
                ast_mutex_lock(&p->lock);
                if (p->pending) {
index 5b0fa00..2e2770f 100644 (file)
@@ -2577,14 +2577,25 @@ static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel
        return;
 }
 
-static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
+/*!
+ * \internal
+ * \brief performs duties of dahdi_new, but also removes and possibly unbinds (if callid_created is 1) before returning
+ * \note this variant of dahdi should only be used in conjunction with ast_callid_threadstorage_auto()
+ *
+ * \param callid_created value returned from ast_callid_threadstorage_auto()
+ */
+static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linked, struct ast_callid *callid, int callid_created);
+
+static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid, struct ast_callid *callid);
 
 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
 {
+       struct ast_callid *callid = NULL;
+       int callid_created = ast_callid_threadstorage_auto(&callid);
        struct dahdi_pvt *p = pvt;
        int dsub = analogsub_to_dahdisub(sub);
 
-       return dahdi_new(p, state, startpbx, dsub, 0, requestor ? ast_channel_linkedid(requestor) : "");
+       return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
 }
 
 #if defined(HAVE_PRI) || defined(HAVE_SS7)
@@ -2604,6 +2615,8 @@ static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, enum sig
        struct dahdi_pvt *p = pvt;
        int audio;
        int newlaw = -1;
+       struct ast_callid *callid = NULL;
+       int callid_created = ast_callid_threadstorage_auto(&callid);
 
        switch (p->sig) {
        case SIG_PRI_LIB_HANDLE_CASES:
@@ -2639,7 +2652,8 @@ static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, enum sig
                        newlaw = DAHDI_LAW_MULAW;
                        break;
        }
-       return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "");
+
+       return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
 }
 #endif /* defined(HAVE_PRI) */
 
@@ -3519,6 +3533,8 @@ static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig
        struct dahdi_pvt *p = pvt;
        int audio;
        int newlaw;
+       struct ast_callid *callid = NULL;
+       int callid_created = ast_callid_threadstorage_auto(&callid);
 
        /* Set to audio mode at this point */
        audio = 1;
@@ -3545,7 +3561,7 @@ static struct ast_channel *my_new_ss7_ast_channel(void *pvt, int state, enum sig
                newlaw = DAHDI_LAW_MULAW;
                break;
        }
-       return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "");
+       return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
 }
 #endif /* defined(HAVE_SS7) */
 
@@ -3986,6 +4002,8 @@ static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, con
 {
        struct dahdi_pvt *p;
        struct ast_channel *c;
+       struct ast_callid *callid = NULL;
+       int callid_created = ast_callid_threadstorage_auto(&callid);
        ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
                        openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
                        openr2_proto_get_category_string(category));
@@ -3994,7 +4012,7 @@ static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, con
        if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
                ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
                dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
-               return;
+               goto dahdi_r2_on_call_offered_cleanup;
        }
        ast_mutex_lock(&p->lock);
        p->mfcr2_recvd_category = category;
@@ -4015,16 +4033,16 @@ static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, con
                ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
                                p->channel, p->exten, p->context);
                dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
-               return;
+               goto dahdi_r2_on_call_offered_cleanup;
        }
        if (!p->mfcr2_accept_on_offer) {
                /* The user wants us to start the PBX thread right away without accepting the call first */
-               c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
+               c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
                if (c) {
                        /* Done here, don't disable reading now since we still need to generate MF tones to accept
                           the call or reject it and detect the tone off condition of the other end, all of this
                           will be done in the PBX thread now */
-                       return;
+                       goto dahdi_r2_on_call_offered_cleanup;
                }
                ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
                dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
@@ -4035,6 +4053,9 @@ static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, con
                ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
                openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
        }
+
+dahdi_r2_on_call_offered_cleanup:
+       ast_callid_threadstorage_auto_clean(callid, callid_created);
 }
 
 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
@@ -4051,6 +4072,8 @@ static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t
 {
        struct dahdi_pvt *p = NULL;
        struct ast_channel *c = NULL;
+       struct ast_callid *callid = NULL;
+       int callid_created = ast_callid_threadstorage_auto(&callid);
        p = openr2_chan_get_client_data(r2chan);
        dahdi_enable_ec(p);
        p->mfcr2_call_accepted = 1;
@@ -4067,19 +4090,19 @@ static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t
                                ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
                                dahdi_r2_answer(p);
                        }
-                       return;
+                       goto dahdi_r2_on_call_accepted_cleanup;
                }
-               c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
+               c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
                if (c) {
                        /* chan_dahdi will take care of reading from now on in the PBX thread, tell the
                           library to forget about it */
                        openr2_chan_disable_read(r2chan);
-                       return;
+                       goto dahdi_r2_on_call_accepted_cleanup;
                }
                ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
                /* failed to create the channel, bail out and report it as an out of order line */
                dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
-               return;
+               goto dahdi_r2_on_call_accepted_cleanup;
        }
        /* this is an outgoing call, no need to launch the PBX thread, most likely we're in one already */
        ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
@@ -4087,6 +4110,9 @@ static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t
        p->dialing = 0;
        /* chan_dahdi will take care of reading from now on in the PBX thread, tell the library to forget about it */
        openr2_chan_disable_read(r2chan);
+
+dahdi_r2_on_call_accepted_cleanup:
+       ast_callid_threadstorage_auto_clean(callid, callid_created);
 }
 
 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
@@ -8590,6 +8616,8 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                        p->subs[SUB_REAL].needflash = 1;
                                        goto winkflashdone;
                                } else if (!check_for_conference(p)) {
+                                       struct ast_callid *callid = NULL;
+                                       int callid_created;
                                        char cid_num[256];
                                        char cid_name[256];
 
@@ -8619,7 +8647,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                                ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
                                                goto winkflashdone;
                                        }
-
+                                       callid_created = ast_callid_threadstorage_auto(&callid);
                                        /*
                                         * Make new channel
                                         *
@@ -8628,7 +8656,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                         */
                                        ast_mutex_unlock(&p->lock);
                                        ast_channel_unlock(ast);
-                                       chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
+                                       chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, callid);
                                        ast_channel_lock(ast);
                                        ast_mutex_lock(&p->lock);
                                        if (p->dahditrcallerid) {
@@ -8665,6 +8693,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                                }
                                                p->subs[SUB_THREEWAY].needhold = 1;
                                        }
+                                       ast_callid_threadstorage_auto_clean(callid, callid_created);
                                }
                        } else {
                                /* Already have a 3 way call */
@@ -9699,7 +9728,16 @@ static struct ast_str *create_channel_name(struct dahdi_pvt *i)
        return chan_name;
 }
 
-static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
+static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid, struct ast_callid *callid, int callid_created)
+{
+       struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, linkedid, callid);
+
+       ast_callid_threadstorage_auto_clean(callid, callid_created);
+
+       return new_channel;
+}
+
+static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid, struct ast_callid *callid)
 {
        struct ast_channel *tmp;
        struct ast_format deflaw;
@@ -9731,8 +9769,14 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
 
        tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, linkedid, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
        ast_free(chan_name);
-       if (!tmp)
+       if (!tmp) {
                return NULL;
+       }
+
+       if (callid) {
+               ast_channel_callid_set(tmp, callid);
+       }
+
        ast_channel_tech_set(tmp, &dahdi_tech);
 #if defined(HAVE_PRI)
        if (i->pri) {
@@ -11197,6 +11241,8 @@ static void *mwi_thread(void *data)
 
                if (i & DAHDI_IOMUX_SIGEVENT) {
                        struct ast_channel *chan;
+                       struct ast_callid *callid = NULL;
+                       int callid_created;
 
                        /* If we get an event, screen out events that we do not act on.
                         * Otherwise, cancel and go to the simple switch to let it deal with it.
@@ -11229,13 +11275,14 @@ static void *mwi_thread(void *data)
                                handle_alarms(mtd->pvt, res);
                                break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
                        default:
+                               callid_created = ast_callid_threadstorage_auto(&callid);
                                ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to analog_ss_thread\n", res, event2str(res));
                                callerid_free(cs);
 
                                restore_gains(mtd->pvt);
                                mtd->pvt->ringt = mtd->pvt->ringt_base;
 
-                               if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
+                               if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, callid))) {
                                        int result;
 
                                        if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
@@ -11253,6 +11300,8 @@ static void *mwi_thread(void *data)
                                } else {
                                        ast_log(LOG_WARNING, "Could not create channel to handle call\n");
                                }
+
+                               ast_callid_threadstorage_auto_clean(callid, callid_created);
                                goto quit_no_clean;
                        }
                } else if (i & DAHDI_IOMUX_READ) {
@@ -11532,6 +11581,8 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
        int res;
        pthread_t threadid;
        struct ast_channel *chan;
+       struct ast_callid *callid = NULL;
+       int callid_created;
 
        /* Handle an event on a given channel for the monitor thread. */
 
@@ -11549,8 +11600,11 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
                case SIG_FXOGS:
                case SIG_FXOKS:
                        res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
-                       if (res && (errno == EBUSY))
+                       if (res && (errno == EBUSY)) {
                                break;
+                       }
+
+                       callid_created = ast_callid_threadstorage_auto(&callid);
 
                        /* Cancel VMWI spill */
                        ast_free(i->cidspill);
@@ -11561,7 +11615,7 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
                                dahdi_enable_ec(i);
                                /* The channel is immediately up.  Start right away */
                                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
-                               chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
+                               chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, callid);
                                if (!chan) {
                                        ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
                                        res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
@@ -11570,7 +11624,7 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
                                }
                        } else {
                                /* Check for callerid, digits, etc */
-                               chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
+                               chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, callid);
                                if (chan) {
                                        if (has_voicemail(i))
                                                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
@@ -11588,6 +11642,8 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
                                } else
                                        ast_log(LOG_WARNING, "Unable to create channel\n");
                        }
+
+                       ast_callid_threadstorage_auto_clean(callid, callid_created);
                        break;
                case SIG_FXSLS:
                case SIG_FXSGS:
@@ -11610,10 +11666,11 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
                case SIG_SF_FEATB:
                case SIG_SF:
                        /* Check for callerid, digits, etc */
+                       callid_created = ast_callid_threadstorage_auto(&callid);
                        if (i->cid_start == CID_START_POLARITY_IN) {
-                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
+                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
                        } else {
-                               chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
+                               chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, callid);
                        }
 
                        if (!chan) {
@@ -11626,6 +11683,8 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
                                }
                                ast_hangup(chan);
                        }
+
+                       ast_callid_threadstorage_auto_clean(callid, callid_created);
                        break;
                default:
                        ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
@@ -11731,6 +11790,7 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
                           created, but it wasn't handled. We need polarity
                           to be REV for remote hangup detection to work.
                           At least in Spain */
+                       callid_created = ast_callid_threadstorage_auto(&callid);
                        if (i->hanguponpolarityswitch)
                                i->polarity = POLARITY_REV;
                        if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
@@ -11738,13 +11798,14 @@ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
                                ast_verb(2, "Starting post polarity "
                                        "CID detection on channel %d\n",
                                        i->channel);
-                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
+                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
                                if (!chan) {
                                        ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
                                } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
                                        ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
                                }
                        }
+                       ast_callid_threadstorage_auto_clean(callid, callid_created);
                        break;
                default:
                        ast_log(LOG_WARNING, "handle_init_event detected "
@@ -12003,7 +12064,9 @@ static void *do_monitor(void *data)
                                                                                doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
                                                                                i->dtmfcid_holdoff_state = 1;
                                                                        } else {
-                                                                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
+                                                                               struct ast_callid *callid = NULL;
+                                                                               int callid_created = ast_callid_threadstorage_auto(&callid);
+                                                                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
                                                                                if (!chan) {
                                                                                        ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
                                                                                } else {
@@ -12014,6 +12077,7 @@ static void *do_monitor(void *data)
                                                                                                i->dtmfcid_holdoff_state = 1;
                                                                                        }
                                                                                }
+                                                                               ast_callid_threadstorage_auto_clean(callid, callid_created);
                                                                        }
                                                                        ast_mutex_lock(&iflock);
                                                                }
@@ -13772,12 +13836,15 @@ static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap
        int transcapdigital = 0;
 #endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
        struct dahdi_starting_point start;
+       struct ast_callid *callid = NULL;
+       int callid_created = ast_callid_threadstorage_auto(&callid);
 
        ast_mutex_lock(&iflock);
        p = determine_starting_point(data, &start);
        if (!p) {
                /* We couldn't determine a starting point, which likely means badly-formatted channel name. Abort! */
                ast_mutex_unlock(&iflock);
+               ast_callid_threadstorage_auto_clean(callid, callid_created);
                return NULL;
        }
 
@@ -13858,7 +13925,7 @@ static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap
                                tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
 #endif /* defined(HAVE_SS7) */
                        } else {
-                               tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? ast_channel_linkedid(requestor) : "");
+                               tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? ast_channel_linkedid(requestor) : "", callid);
                        }
                        if (!tmp) {
                                p->outgoing = 0;
@@ -13917,6 +13984,7 @@ next:
                }
        }
 
+       ast_callid_threadstorage_auto_clean(callid, callid_created);
        return tmp;
 }
 
@@ -14090,12 +14158,12 @@ static void dahdi_ss7_message(struct ss7 *ss7, char *s)
        if (ss7) {
                for (i = 0; i < NUM_SPANS; i++) {
                        if (linksets[i].ss7.ss7 == ss7) {
-                               ast_verbose("[%d] %s", i + 1, s);
+                               ast_verbose_callid(NULL, "[%d] %s", i + 1, s);
                                return;
                        }
                }
        }
-       ast_verbose("%s", s);
+       ast_verbose_callid(NULL, "%s", s);
 }
 #endif /* defined(HAVE_SS7) */
 
@@ -14107,12 +14175,12 @@ static void dahdi_ss7_error(struct ss7 *ss7, char *s)
        if (ss7) {
                for (i = 0; i < NUM_SPANS; i++) {
                        if (linksets[i].ss7.ss7 == ss7) {
-                               ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
+                               ast_log_callid(LOG_ERROR, NULL, "[%d] %s", i + 1, s);
                                return;
                        }
                }
        }
-       ast_log(LOG_ERROR, "%s", s);
+       ast_log_callid(LOG_ERROR, NULL, "%s", s);
 }
 #endif /* defined(HAVE_SS7) */
 
@@ -14225,22 +14293,22 @@ static void dahdi_pri_message(struct pri *pri, char *s)
                }
                if (-1 < span) {
                        if (1 < dchancount) {
-                               ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
+                               ast_verbose_callid(NULL, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
                        } else {
-                               ast_verbose("PRI Span: %d %s", span + 1, s);
+                               ast_verbose_callid(NULL, "PRI Span: %d %s", span + 1, s);
                        }
                } else {
-                       ast_verbose("PRI Span: ? %s", s);
+                       ast_verbose_callid(NULL, "PRI Span: ? %s", s);
                }
        } else {
-               ast_verbose("PRI Span: ? %s", s);
+               ast_verbose_callid(NULL, "PRI Span: ? %s", s);
        }
 
        ast_mutex_lock(&pridebugfdlock);
 
        if (pridebugfd >= 0) {
                if (write(pridebugfd, s, strlen(s)) < 0) {
-                       ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
+                       ast_log_callid(LOG_WARNING, NULL, "write() failed: %s\n", strerror(errno));
                }
        }
 
@@ -14276,22 +14344,22 @@ static void dahdi_pri_error(struct pri *pri, char *s)
                }
                if (-1 < span) {
                        if (1 < dchancount) {
-                               ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
+                               ast_log_callid(LOG_ERROR, NULL, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
                        } else {
-                               ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
+                               ast_log_callid(LOG_ERROR, NULL, "PRI Span: %d %s", span + 1, s);
                        }
                } else {
-                       ast_log(LOG_ERROR, "PRI Span: ? %s", s);
+                       ast_log_callid(LOG_ERROR, NULL, "PRI Span: ? %s", s);
                }
        } else {
-               ast_log(LOG_ERROR, "PRI Span: ? %s", s);
+               ast_log_callid(LOG_ERROR, NULL, "PRI Span: ? %s", s);
        }
 
        ast_mutex_lock(&pridebugfdlock);
 
        if (pridebugfd >= 0) {
                if (write(pridebugfd, s, strlen(s)) < 0) {
-                       ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
+                       ast_log_callid(LOG_WARNING, NULL, "write() failed: %s\n", strerror(errno));
                }
        }
 
index a723d2c..ba662c9 100644 (file)
@@ -653,6 +653,8 @@ struct iax2_pvt_ref;
 struct chan_iax2_pvt {
        /*! Socket to send/receive on for this call */
        int sockfd;
+       /*! ast_callid bound to dialog */
+       struct ast_callid *callid;
        /*! Last received voice format */
        iax2_format voiceformat;
        /*! Last received video format */
@@ -1067,6 +1069,33 @@ static void signal_condition(ast_mutex_t *lock, ast_cond_t *cond)
  */
 static struct chan_iax2_pvt *iaxs[IAX_MAX_CALLS + 1];
 
+static struct ast_callid *iax_pvt_callid_get(int callno)
+{
+       if (iaxs[callno]->callid) {
+               return ast_callid_ref(iaxs[callno]->callid);
+       }
+       return NULL;
+}
+
+static void iax_pvt_callid_set(int callno, struct ast_callid *callid)
+{
+       if (iaxs[callno]->callid) {
+               ast_callid_unref(iaxs[callno]->callid);
+       }
+       ast_callid_ref(callid);
+       iaxs[callno]->callid = callid;
+}
+
+static void iax_pvt_callid_new(int callno)
+{
+       struct ast_callid *callid = ast_create_callid();
+       char buffer[AST_CALLID_BUFFER_LENGTH];
+       ast_callid_strnprint(buffer, sizeof(buffer), callid);
+       ast_log(LOG_NOTICE, "iax_pvt_callid_new created and set %s\n", buffer);
+       iax_pvt_callid_set(callno, callid);
+       ast_callid_unref(callid);
+}
+
 /*!
  * \brief Another container of iax2_pvt structures
  *
@@ -1986,6 +2015,11 @@ static void pvt_destructor(void *obj)
                jb_destroy(pvt->jb);
                ast_string_field_free_memory(pvt);
        }
+
+       if (pvt->callid) {
+               ast_callid_unref(pvt->callid);
+       }
+
 }
 
 static struct chan_iax2_pvt *new_iax(struct sockaddr_in *sin, const char *host)
@@ -5750,6 +5784,7 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
        struct chan_iax2_pvt *i;
        struct ast_variable *v = NULL;
        struct ast_format tmpfmt;
+       struct ast_callid *callid;
 
        if (!(i = iaxs[callno])) {
                ast_log(LOG_WARNING, "No IAX2 pvt found for callno '%d' !\n", callno);
@@ -5770,8 +5805,14 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
                return NULL;
        }
        iax2_ami_channelupdate(i);
-       if (!tmp)
+       if (!tmp) {
                return NULL;
+       }
+
+       if ((callid = iaxs[callno]->callid)) {
+               ast_channel_callid_set(tmp, callid);
+       }
+
        ast_channel_tech_set(tmp, &iax2_tech);
        /* We can support any format by default, until we get restricted */
        ast_format_cap_from_old_bitfield(ast_channel_nativeformats(tmp), capability);
@@ -9920,7 +9961,7 @@ static void set_hangup_source_and_cause(int callno, unsigned char causecode)
        }
 }
 
-static int socket_process(struct iax2_thread *thread)
+static int socket_process_helper(struct iax2_thread *thread)
 {
        struct sockaddr_in sin;
        int res;
@@ -10103,8 +10144,15 @@ static int socket_process(struct iax2_thread *thread)
                }
        }
 
-       if (fr->callno > 0)
+       if (fr->callno > 0) {
+               struct ast_callid *mount_callid;
                ast_mutex_lock(&iaxsl[fr->callno]);
+               if ((mount_callid = iax_pvt_callid_get(fr->callno))) {
+                       /* Bind to thread */
+                       ast_callid_threadassoc_add(mount_callid);
+                       ast_callid_unref(mount_callid);
+               }
+       }
 
        if (!fr->callno || !iaxs[fr->callno]) {
                /* A call arrived for a nonexistent destination.  Unless it's an "inval"
@@ -10791,6 +10839,9 @@ static int socket_process(struct iax2_thread *thread)
                                                                                                using_prefs);
 
                                                                iaxs[fr->callno]->chosenformat = format;
+
+                                                               /* Since this is a new call, we should go ahead and set the callid for it. */
+                                                               iax_pvt_callid_new(fr->callno);
                                                                ast_set_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART);
                                                        } else {
                                                                ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_TBD);
@@ -11732,6 +11783,17 @@ immediatedial:
        return 1;
 }
 
+static int socket_process(struct iax2_thread *thread)
+{
+       struct ast_callid *callid;
+       int res = socket_process_helper(thread);
+       if ((callid = ast_read_threadstorage_callid())) {
+               ast_callid_threadassoc_remove();
+               callid = ast_callid_unref(callid);
+       }
+       return res;
+}
+
 /* Function to clean up process thread if it is cancelled */
 static void iax2_process_thread_cleanup(void *data)
 {
@@ -12204,11 +12266,14 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
        struct parsed_dial_string pds;
        struct create_addr_info cai;
        char *tmpstr;
+       struct ast_callid *callid;
 
        memset(&pds, 0, sizeof(pds));
        tmpstr = ast_strdupa(data);
        parse_dial_string(tmpstr, &pds);
 
+       callid = ast_read_threadstorage_callid();
+
        if (ast_strlen_zero(pds.peer)) {
                ast_log(LOG_WARNING, "No peer provided in the IAX2 dial string '%s'\n", data);
                return NULL;
@@ -12242,15 +12307,22 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
                        callno = new_callno;
        }
        iaxs[callno]->maxtime = cai.maxtime;
-       if (cai.found)
+       if (callid) {
+               iax_pvt_callid_set(callno, callid);
+       }
+
+       if (cai.found) {
                ast_string_field_set(iaxs[callno], host, pds.peer);
+       }
 
        c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability, requestor ? ast_channel_linkedid(requestor) : NULL);
-
        ast_mutex_unlock(&iaxsl[callno]);
 
        if (c) {
                struct ast_format_cap *joint;
+               if (callid) {
+                       ast_channel_callid_set(c, callid);
+               }
 
                /* Choose a format we can live with */
                if ((joint = ast_format_cap_joint(ast_channel_nativeformats(c), cap))) {
@@ -12274,6 +12346,9 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
                ast_format_copy(ast_channel_writeformat(c), ast_channel_readformat(c));
        }
 
+       if (callid) {
+               ast_callid_unref(callid);
+       }
        return c;
 }
 
index 3c5fca5..695949f 100644 (file)
@@ -1161,7 +1161,7 @@ static struct local_pvt *local_alloc(const char *data, struct ast_format_cap *ca
 }
 
 /*! \brief Start new local channel */
-static struct ast_channel *local_new(struct local_pvt *p, int state, const char *linkedid)
+static struct ast_channel *local_new(struct local_pvt *p, int state, const char *linkedid, struct ast_callid *callid)
 {
        struct ast_channel *tmp = NULL, *tmp2 = NULL;
        int randnum = ast_random() & 0xffff;
@@ -1192,6 +1192,11 @@ static struct ast_channel *local_new(struct local_pvt *p, int state, const char
                return NULL;
        }
 
+       if (callid) {
+               ast_channel_callid_set(tmp, callid);
+               ast_channel_callid_set(tmp2, callid);
+       }
+
        ast_channel_tech_set(tmp, &local_tech);
        ast_channel_tech_set(tmp2, &local_tech);
 
@@ -1233,13 +1238,15 @@ static struct ast_channel *local_request(const char *type, struct ast_format_cap
 {
        struct local_pvt *p;
        struct ast_channel *chan;
+       struct ast_callid *callid = ast_read_threadstorage_callid();
 
        /* Allocate a new private structure and then Asterisk channel */
        p = local_alloc(data, cap);
        if (!p) {
-               return NULL;
+               chan = NULL;
+               goto local_request_end;
        }
-       chan = local_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
+       chan = local_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL, callid);
        if (!chan) {
                ao2_unlink(locals, p);
        } else if (ast_channel_cc_params_init(chan, requestor ? ast_channel_get_cc_config_params((struct ast_channel *)requestor) : NULL)) {
@@ -1252,6 +1259,12 @@ static struct ast_channel *local_request(const char *type, struct ast_format_cap
        }
        ao2_ref(p, -1); /* kill the ref from the alloc */
 
+local_request_end:
+
+       if (callid) {
+               ast_callid_unref(callid);
+       }
+
        return chan;
 }
 
index 03c799e..7c238d0 100644 (file)
@@ -1770,6 +1770,7 @@ static void *__analog_ss_thread(void *data)
        int len = 0;
        int res;
        int idx;
+       struct ast_callid *callid;
 
        analog_increase_ss_count(p);
 
@@ -1779,6 +1780,12 @@ static void *__analog_ss_thread(void *data)
                /* What happened to the channel? */
                goto quit;
        }
+
+       if ((callid = ast_channel_callid(chan))) {
+               ast_callid_threadassoc_add(callid);
+               ast_callid_unref(callid);
+       }
+
        /* in the bizarre case where the channel has become a zombie before we
           even get started here, abort safely
        */
@@ -3220,6 +3227,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                        ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_FLASH);
                                        goto winkflashdone;
                                } else if (!analog_check_for_conference(p)) {
+                                       struct ast_callid *callid = NULL;
+                                       int callid_created;
                                        char cid_num[256];
                                        char cid_name[256];
 
@@ -3250,6 +3259,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                goto winkflashdone;
                                        }
 
+                                       callid_created = ast_callid_threadstorage_auto(&callid);
+
                                        /*
                                         * Make new channel
                                         *
@@ -3266,6 +3277,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                        "Cannot allocate new call structure on channel %d\n",
                                                        p->channel);
                                                analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
+                                               ast_callid_threadstorage_auto_clean(callid, callid_created);
                                                goto winkflashdone;
                                        }
                                        if (p->dahditrcallerid) {
@@ -3303,6 +3315,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                                                !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
                                                }
                                        }
+                                       ast_callid_threadstorage_auto_clean(callid, callid_created);
                                }
                        } else {
                                /* Already have a 3 way call */
@@ -3687,6 +3700,8 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
        int res;
        pthread_t threadid;
        struct ast_channel *chan;
+       struct ast_callid *callid = NULL;
+       int callid_created;
 
        ast_debug(1, "channel (%d) - signaling (%d) - event (%s)\n",
                                i->channel, i->sig, analog_event2str(event));
@@ -3708,6 +3723,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                        if (res && (errno == EBUSY)) {
                                break;
                        }
+                       callid_created = ast_callid_threadstorage_auto(&callid);
 
                        /* Cancel VMWI spill */
                        analog_cancel_cidspill(i);
@@ -3748,6 +3764,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                                } else
                                        ast_log(LOG_WARNING, "Unable to create channel\n");
                        }
+                       ast_callid_threadstorage_auto_clean(callid, callid_created);
                        break;
                case ANALOG_SIG_FXSLS:
                case ANALOG_SIG_FXSGS:
@@ -3769,6 +3786,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                case ANALOG_SIG_SF_FEATDMF:
                case ANALOG_SIG_SF_FEATB:
                case ANALOG_SIG_SF:
+                       callid_created = ast_callid_threadstorage_auto(&callid);
                        /* Check for callerid, digits, etc */
                        if (i->cid_start == ANALOG_CID_START_POLARITY_IN || i->cid_start == ANALOG_CID_START_DTMF_NOALERT) {
                                chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL);
@@ -3786,6 +3804,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                                }
                                ast_hangup(chan);
                        }
+                       ast_callid_threadstorage_auto_clean(callid, callid_created);
                        break;
                default:
                        ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", analog_sigtype_to_str(i->sig), i->channel);
@@ -3859,6 +3878,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                case ANALOG_SIG_FXSLS:
                case ANALOG_SIG_FXSKS:
                case ANALOG_SIG_FXSGS:
+                       callid_created = ast_callid_threadstorage_auto(&callid);
                        /* We have already got a PR before the channel was
                           created, but it wasn't handled. We need polarity
                           to be REV for remote hangup detection to work.
@@ -3879,6 +3899,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                                        ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
                                }
                        }
+                       ast_callid_threadstorage_auto_clean(callid, callid_created);
                        break;
                default:
                        ast_log(LOG_WARNING, "handle_init_event detected "
@@ -3892,6 +3913,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                case ANALOG_SIG_FXSLS:
                case ANALOG_SIG_FXSKS:
                case ANALOG_SIG_FXSGS:
+                       callid_created = ast_callid_threadstorage_auto(&callid);
                        if (i->cid_start == ANALOG_CID_START_DTMF_NOALERT) {
                                ast_verb(2, "Starting DTMF CID detection on channel %d\n",
                                        i->channel);
@@ -3903,6 +3925,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
                                        ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
                                }
                        }
+                       ast_callid_threadstorage_auto_clean(callid, callid_created);
                        break;
                default:
                        ast_log(LOG_WARNING, "handle_init_event detected "
index ead02f5..0e9c90e 100644 (file)
@@ -1867,6 +1867,12 @@ static void *do_idle_thread(void *v_pvt)
        char ex[80];
        /* Wait up to 30 seconds for an answer */
        int newms, ms = 30000;
+       struct ast_callid *callid;
+
+       if ((callid = ast_channel_callid(chan))) {
+               ast_callid_threadassoc_add(callid);
+               callid = ast_callid_unref(callid);
+       }
 
        ast_verb(3, "Initiating idle call on channel %s\n", ast_channel_name(chan));
        snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
@@ -1916,12 +1922,18 @@ static void *pri_ss_thread(void *data)
        int res;
        int len;
        int timeout;
+       struct ast_callid *callid;
 
        if (!chan) {
                /* We lost the owner before we could get started. */
                return NULL;
        }
 
+       if ((callid = ast_channel_callid(chan))) {
+               ast_callid_threadassoc_add(callid);
+               ast_callid_unref(callid);
+       }
+
        /*
         * In the bizarre case where the channel has become a zombie before we
         * even get started here, abort safely.
@@ -5151,6 +5163,60 @@ static void sig_pri_ami_hold_event(struct ast_channel *chan, int is_held)
 }
 #endif /* defined(HAVE_PRI_CALL_HOLD) */
 
+/*!
+ * \internal
+ * \brief Set callid threadstorage for the pri_dchannel thread when a new call is created
+ *
+ * \return A new callid which has been bound to threadstorage. The return must be
+ *         unreffed and the threadstorage should be unbound when the pri_dchannel
+ *         primary loop wraps.
+ */
+static struct ast_callid *func_pri_dchannel_new_callid(void)
+{
+       struct ast_callid *callid = ast_create_callid();
+
+       if (callid) {
+               ast_callid_threadassoc_add(callid);
+       }
+
+       return callid;
+}
+
+/*!
+ * \internal
+ * \brief Set callid threadstorage for the pri_dchannel thread to that of an existing channel
+ *
+ * \param pri PRI span control structure.
+ * \param chanpos channel position in the span
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return a reference to the callid bound to the channel which has also
+ *         been bound to threadstorage if it exists. If this returns non-NULL,
+ *         the callid must be unreffed and the threadstorage should be unbound
+ *         when the pri_dchannel primary loop wraps.
+ */
+static struct ast_callid *func_pri_dchannel_chanpos_callid(struct sig_pri_span *pri, int chanpos)
+{
+       if (chanpos < 0) {
+               return NULL;
+       }
+
+       sig_pri_lock_owner(pri, chanpos);
+       if (pri->pvts[chanpos]->owner) {
+               struct ast_callid *callid;
+               callid = ast_channel_callid(pri->pvts[chanpos]->owner);
+               ast_channel_unlock(pri->pvts[chanpos]->owner);
+               if (callid) {
+                       ast_callid_threadassoc_add(callid);
+                       return callid;
+               }
+       }
+
+       return NULL;
+}
+
 #if defined(HAVE_PRI_CALL_HOLD)
 /*!
  * \internal
@@ -5171,6 +5237,7 @@ static int sig_pri_handle_hold(struct sig_pri_span *pri, pri_event *ev)
        int chanpos_old;
        int chanpos_new;
        struct ast_channel *owner;
+       struct ast_callid *callid = NULL;
 
        chanpos_old = pri_find_principle_by_call(pri, ev->hold.call);
        if (chanpos_old < 0) {
@@ -5190,6 +5257,13 @@ static int sig_pri_handle_hold(struct sig_pri_span *pri, pri_event *ev)
        if (!owner) {
                goto done_with_private;
        }
+
+       callid = ast_channel_callid(owner);
+
+       if (callid) {
+               ast_callid_threadassoc_add(callid);
+       }
+
        if (pri->pvts[chanpos_old]->call_level != SIG_PRI_CALL_LEVEL_CONNECT) {
                /*
                 * Make things simple.  Don't allow placing a call on hold that
@@ -5224,6 +5298,11 @@ done_with_private:;
                retval = 0;
        }
 
+       if (callid) {
+               ast_callid_unref(callid);
+               ast_callid_threadassoc_remove();
+       }
+
        return retval;
 }
 #endif /* defined(HAVE_PRI_CALL_HOLD) */
@@ -5244,6 +5323,7 @@ done_with_private:;
 static void sig_pri_handle_hold_ack(struct sig_pri_span *pri, pri_event *ev)
 {
        int chanpos;
+       struct ast_callid *callid;
 
        /*
         * We were successfully put on hold by the remote party
@@ -5266,11 +5346,18 @@ static void sig_pri_handle_hold_ack(struct sig_pri_span *pri, pri_event *ev)
        }
 
        sig_pri_lock_private(pri->pvts[chanpos]);
+       callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
        sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->hold_ack.subcmds, ev->hold_ack.call);
        sig_pri_moh_fsm_event(pri->pvts[chanpos]->owner, pri->pvts[chanpos],
                SIG_PRI_MOH_EVENT_HOLD_ACK);
        sig_pri_unlock_private(pri->pvts[chanpos]);
        sig_pri_span_devstate_changed(pri);
+
+       if (callid) {
+               ast_callid_unref(callid);
+               ast_callid_threadassoc_remove();
+       }
 }
 #endif /* defined(HAVE_PRI_CALL_HOLD) */
 
@@ -5290,6 +5377,7 @@ static void sig_pri_handle_hold_ack(struct sig_pri_span *pri, pri_event *ev)
 static void sig_pri_handle_hold_rej(struct sig_pri_span *pri, pri_event *ev)
 {
        int chanpos;
+       struct ast_callid *callid;
 
        chanpos = pri_find_principle(pri, ev->hold_rej.channel, ev->hold_rej.call);
        if (chanpos < 0) {
@@ -5309,10 +5397,17 @@ static void sig_pri_handle_hold_rej(struct sig_pri_span *pri, pri_event *ev)
                ev->hold_rej.cause, pri_cause2str(ev->hold_rej.cause));
 
        sig_pri_lock_private(pri->pvts[chanpos]);
+       callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
        sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->hold_rej.subcmds, ev->hold_rej.call);
        sig_pri_moh_fsm_event(pri->pvts[chanpos]->owner, pri->pvts[chanpos],
                SIG_PRI_MOH_EVENT_HOLD_REJ);
        sig_pri_unlock_private(pri->pvts[chanpos]);
+
+       if (callid) {
+               ast_callid_unref(callid);
+               ast_callid_threadassoc_remove();
+       }
 }
 #endif /* defined(HAVE_PRI_CALL_HOLD) */
 
@@ -5332,6 +5427,7 @@ static void sig_pri_handle_hold_rej(struct sig_pri_span *pri, pri_event *ev)
 static void sig_pri_handle_retrieve(struct sig_pri_span *pri, pri_event *ev)
 {
        int chanpos;
+       struct ast_callid *callid;
 
        if (!(ev->retrieve.channel & PRI_HELD_CALL)) {
                /* The call is not currently held. */
@@ -5373,6 +5469,7 @@ static void sig_pri_handle_retrieve(struct sig_pri_span *pri, pri_event *ev)
                return;
        }
        sig_pri_lock_private(pri->pvts[chanpos]);
+       callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
        sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve.subcmds, ev->retrieve.call);
        sig_pri_lock_owner(pri, chanpos);
        pri_queue_control(pri, chanpos, AST_CONTROL_UNHOLD);
@@ -5386,6 +5483,11 @@ static void sig_pri_handle_retrieve(struct sig_pri_span *pri, pri_event *ev)
                SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK);
        sig_pri_unlock_private(pri->pvts[chanpos]);
        sig_pri_span_devstate_changed(pri);
+
+       if (callid) {
+               ast_callid_unref(callid);
+               ast_callid_threadassoc_remove();
+       }
 }
 #endif /* defined(HAVE_PRI_CALL_HOLD) */
 
@@ -5405,6 +5507,7 @@ static void sig_pri_handle_retrieve(struct sig_pri_span *pri, pri_event *ev)
 static void sig_pri_handle_retrieve_ack(struct sig_pri_span *pri, pri_event *ev)
 {
        int chanpos;
+       struct ast_callid *callid;
 
        chanpos = pri_find_fixup_principle(pri, ev->retrieve_ack.channel,
                ev->retrieve_ack.call);
@@ -5413,12 +5516,19 @@ static void sig_pri_handle_retrieve_ack(struct sig_pri_span *pri, pri_event *ev)
        }
 
        sig_pri_lock_private(pri->pvts[chanpos]);
+       callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
        sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve_ack.subcmds,
                ev->retrieve_ack.call);
        sig_pri_moh_fsm_event(pri->pvts[chanpos]->owner, pri->pvts[chanpos],
                SIG_PRI_MOH_EVENT_RETRIEVE_ACK);
        sig_pri_unlock_private(pri->pvts[chanpos]);
        sig_pri_span_devstate_changed(pri);
+
+       if (callid) {
+               ast_callid_unref(callid);
+               ast_callid_threadassoc_remove();
+       }
 }
 #endif /* defined(HAVE_PRI_CALL_HOLD) */
 
@@ -5438,6 +5548,7 @@ static void sig_pri_handle_retrieve_ack(struct sig_pri_span *pri, pri_event *ev)
 static void sig_pri_handle_retrieve_rej(struct sig_pri_span *pri, pri_event *ev)
 {
        int chanpos;
+       struct ast_callid *callid;
 
        chanpos = pri_find_principle(pri, ev->retrieve_rej.channel, ev->retrieve_rej.call);
        if (chanpos < 0) {
@@ -5457,11 +5568,18 @@ static void sig_pri_handle_retrieve_rej(struct sig_pri_span *pri, pri_event *ev)
                ev->retrieve_rej.cause, pri_cause2str(ev->retrieve_rej.cause));
 
        sig_pri_lock_private(pri->pvts[chanpos]);
+       callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
        sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve_rej.subcmds,
                ev->retrieve_rej.call);
        sig_pri_moh_fsm_event(pri->pvts[chanpos]->owner, pri->pvts[chanpos],
                SIG_PRI_MOH_EVENT_RETRIEVE_REJ);
        sig_pri_unlock_private(pri->pvts[chanpos]);
+
+       if (callid) {
+               ast_callid_unref(callid);
+               ast_callid_threadassoc_remove();
+       }
 }
 #endif /* defined(HAVE_PRI_CALL_HOLD) */
 
@@ -5515,6 +5633,8 @@ static void *pri_dchannel(void *vpri)
                        ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
        }
        for (;;) {
+               struct ast_callid *callid = NULL;
+
                for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
                        if (!pri->dchans[i])
                                break;
@@ -5824,6 +5944,9 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->digit.subcmds,
                                        e->digit.call);
                                /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
@@ -5855,6 +5978,9 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.subcmds, e->ring.call);
                                /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
                                if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
@@ -5954,6 +6080,9 @@ static void *pri_dchannel(void *vpri)
                                if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
                                        /* Any channel requested. */
                                        chanpos = pri_find_empty_chan(pri, 1);
+                                       if (-1 < chanpos) {
+                                               callid = func_pri_dchannel_new_callid();
+                                       }
                                } else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
                                        /* No channel specified. */
 #if defined(HAVE_PRI_CALL_WAITING)
@@ -5971,11 +6100,15 @@ static void *pri_dchannel(void *vpri)
                                                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
                                                break;
                                        }
+
+                                       callid = func_pri_dchannel_new_callid();
+
                                        /* Setup the call interface to use. */
                                        sig_pri_init_config(pri->pvts[chanpos], pri);
 #endif /* defined(HAVE_PRI_CALL_WAITING) */
                                } else {
                                        /* A channel is specified. */
+                                       callid = func_pri_dchannel_new_callid();
                                        chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call);
                                        if (chanpos < 0) {
                                                ast_log(LOG_WARNING,
@@ -6419,6 +6552,8 @@ static void *pri_dchannel(void *vpri)
                                }
                                sig_pri_lock_private(pri->pvts[chanpos]);
 
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->ringing.subcmds,
                                        e->ringing.call);
                                sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCNR);
@@ -6477,6 +6612,9 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.subcmds,
                                        e->proceeding.call);
 
@@ -6534,6 +6672,9 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.subcmds,
                                        e->proceeding.call);
                                if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
@@ -6580,6 +6721,9 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
 #if defined(HAVE_PRI_CALL_REROUTING)
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.subcmds,
                                        e->facility.subcall);
@@ -6663,6 +6807,8 @@ static void *pri_dchannel(void *vpri)
 #endif /* defined(HAVE_PRI_CALL_WAITING) */
                                sig_pri_lock_private(pri->pvts[chanpos]);
 
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
 #if defined(HAVE_PRI_CALL_WAITING)
                                if (pri->pvts[chanpos]->is_call_waiting) {
                                        pri->pvts[chanpos]->is_call_waiting = 0;
@@ -6724,6 +6870,9 @@ static void *pri_dchannel(void *vpri)
                                }
 
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->connect_ack.subcmds,
                                        e->connect_ack.call);
                                sig_pri_open_media(pri->pvts[chanpos]);
@@ -6748,6 +6897,9 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.subcmds,
                                        e->hangup.call);
                                switch (e->hangup.cause) {
@@ -6893,6 +7045,9 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.subcmds,
                                        e->hangup.call);
 #if defined(HAVE_PRI_CALL_HOLD)
@@ -7035,6 +7190,9 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
                                pri->pvts[chanpos]->call = NULL;
                                if (pri->pvts[chanpos]->owner) {
                                        ast_verb(3, "Span %d: Channel %d/%d got hangup ACK\n", pri->span,
@@ -7138,6 +7296,9 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->setup_ack.subcmds,
                                        e->setup_ack.call);
                                if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_OVERLAP) {
@@ -7198,6 +7359,9 @@ static void *pri_dchannel(void *vpri)
                                }
 #endif /* !defined(HAVE_PRI_CALL_HOLD) */
                                sig_pri_lock_private(pri->pvts[chanpos]);
+
+                               callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
+
 #if defined(HAVE_PRI_CALL_HOLD)
                                sig_pri_handle_subcmds(pri, chanpos, e->e, e->notify.subcmds,
                                        e->notify.call);
@@ -7285,6 +7449,11 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                        }
+                       /* If a callid was set, we need to deref it and remove it from thread storage. */
+                       if (callid) {
+                               callid = ast_callid_unref(callid);
+                               ast_callid_threadassoc_remove();
+                       }
                }
                ast_mutex_unlock(&pri->lock);
        }
index 73288a4..24de805 100644 (file)
@@ -555,6 +555,8 @@ static void ss7_start_call(struct sig_ss7_chan *p, struct sig_ss7_linkset *links
        int law;
        struct ast_channel *c;
        char tmp[256];
+       struct ast_callid *callid = NULL;
+       int callid_created = ast_callid_threadstorage_auto(&callid);
 
        if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
                p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING;
@@ -584,6 +586,7 @@ static void ss7_start_call(struct sig_ss7_chan *p, struct sig_ss7_linkset *links
                isup_rel(linkset->ss7, p->ss7call, -1);
                p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
                p->alreadyhungup = 1;
+               ast_callid_threadstorage_auto_clean(callid, callid_created);
                return;
        }
 
@@ -685,6 +688,7 @@ static void ss7_start_call(struct sig_ss7_chan *p, struct sig_ss7_linkset *links
        /* Must return with linkset and private lock. */
        ast_mutex_lock(&linkset->lock);
        sig_ss7_lock_private(p);
+       ast_callid_threadstorage_auto_clean(callid, callid_created);
 }
 
 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct sig_ss7_linkset *ss7, const char *number, const unsigned nai)
@@ -719,6 +723,36 @@ static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
        return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
 }
 
+/*!
+ * \internal
+ * \brief Set callid threadstorage for the ss7_linkset thread to that of an existing channel
+ *
+ * \param linkset ss7 span control structure.
+ * \param chanpos channel position in the span
+ *
+ * \note Assumes the ss7->lock is already obtained.
+ * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
+ *
+ * \return a reference to the callid bound to the channel which has also
+ *         been bound to threadstorage if it exists. If this returns non-NULL,
+ *         the callid must be unreffed and the threadstorage should be unbound
+ *         before the while loop wraps in ss7_linkset.
+ */
+static struct ast_callid *func_ss7_linkset_callid(struct sig_ss7_linkset *linkset, int chanpos)
+{
+       struct ast_callid *callid = NULL;
+       sig_ss7_lock_owner(linkset, chanpos);
+       if (linkset->pvts[chanpos]->owner) {
+               callid = ast_channel_callid(linkset->pvts[chanpos]->owner);
+               ast_channel_unlock(linkset->pvts[chanpos]->owner);
+               if (callid) {
+                       ast_callid_threadassoc_add(callid);
+               }
+       }
+
+       return callid;
+}
+
 /* This is a thread per linkset that handles all received events from libss7. */
 void *ss7_linkset(void *data)
 {
@@ -795,6 +829,7 @@ void *ss7_linkset(void *data)
                }
 
                while ((e = ss7_check_event(ss7))) {
+                       struct ast_callid *callid = NULL;
                        int chanpos = -1;
                        char cause_str[30];
 
@@ -834,6 +869,8 @@ void *ss7_linkset(void *data)
                                }
                                p = linkset->pvts[chanpos];
                                sig_ss7_lock_private(p);
+                               callid = func_ss7_linkset_callid(linkset, chanpos);
+
                                switch (e->cpg.event) {
                                case CPG_EVENT_ALERTING:
                                        if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING) {
@@ -871,6 +908,7 @@ void *ss7_linkset(void *data)
                                }
                                p = linkset->pvts[chanpos];
                                sig_ss7_lock_private(p);
+                               callid = func_ss7_linkset_callid(linkset, chanpos);
                                sig_ss7_set_inservice(p, 1);
                                sig_ss7_set_remotelyblocked(p, 0);
                                isup_set_call_dpc(e->rsc.call, p->dpc);
@@ -1077,6 +1115,7 @@ void *ss7_linkset(void *data)
                                }
                                p = linkset->pvts[chanpos];
                                sig_ss7_lock_private(p);
+                               callid = func_ss7_linkset_callid(linkset, chanpos);
                                sig_ss7_lock_owner(linkset, chanpos);
                                if (p->owner) {
                                        snprintf(cause_str, sizeof(cause_str), "SS7 ISUP_EVENT_REL (%d)", e->rel.cause);
@@ -1111,6 +1150,7 @@ void *ss7_linkset(void *data)
                                        }
 
                                        sig_ss7_lock_private(p);
+                                       callid = func_ss7_linkset_callid(linkset, chanpos);
                                        sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROCEEDING);
                                        if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING) {
                                                p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING;
@@ -1226,6 +1266,7 @@ void *ss7_linkset(void *data)
                                {
                                        p = linkset->pvts[chanpos];
                                        sig_ss7_lock_private(p);
+                                       callid = func_ss7_linkset_callid(linkset, chanpos);
                                        if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
                                                p->call_level = SIG_SS7_CALL_LEVEL_CONNECT;
                                        }
@@ -1245,6 +1286,7 @@ void *ss7_linkset(void *data)
                                {
                                        p = linkset->pvts[chanpos];
                                        sig_ss7_lock_private(p);
+                                       callid = func_ss7_linkset_callid(linkset, chanpos);
                                        if (p->alreadyhungup) {
                                                if (!p->owner) {
                                                        p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
@@ -1269,6 +1311,7 @@ void *ss7_linkset(void *data)
                                        p = linkset->pvts[chanpos];
                                        ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
                                        sig_ss7_lock_private(p);
+                                       callid = func_ss7_linkset_callid(linkset, chanpos);
                                        if (p->alreadyhungup){
                                                if (!p->owner) {
                                                        p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
@@ -1306,6 +1349,12 @@ void *ss7_linkset(void *data)
                                        sig_ss7_unlock_private(p);
                                }
                        }
+
+                       /* Call ID stuff needs to be cleaned up here */
+                       if (callid) {
+                               callid = ast_callid_unref(callid);
+                               ast_callid_threadassoc_remove();
+                       }
                }
                ast_mutex_unlock(&linkset->lock);
        }
index 518a4f0..4437ee7 100644 (file)
@@ -43,6 +43,8 @@ extern "C" {
 #define VERBOSE_PREFIX_3 "    -- "
 #define VERBOSE_PREFIX_4 "       > "
 
+#define AST_CALLID_BUFFER_LENGTH 13
+
 /*! \brief Used for sending a log message
        This is the standard logger function.  Probably the only way you will invoke it would be something like this:
        ast_log(AST_LOG_WHATEVER, "Problem with the %s Captain.  We should get some more.  Will %d be enough?\n", "flux capacitor", 10);
@@ -95,11 +97,18 @@ void __attribute__((format(printf, 5, 6))) ast_queue_log(const char *queuename,
  */
 void __attribute__((format(printf, 5, 6))) __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt, ...);
 
-#define ast_verbose(...) __ast_verbose(__FILE__, __LINE__, __PRETTY_FUNCTION__, -1, __VA_ARGS__)
+/*! Send a verbose message (based on verbose level) with deliberately specified callid
+ *  \brief just like __ast_verbose, only __ast_verbose_callid allows you to specify which callid is being used
+ *  for the log without needing to bind it to a thread. NULL is a valid argument for this function and will
+ *  allow you to specify that a log will never display a call id even when there is a call id bound to the
+ *  thread.
+ */
+void __attribute__((format(printf, 6, 7))) __ast_verbose_callid(const char *file, int line, const char *func, int level, struct ast_callid *callid, const char *fmt, ...);
 
-void __attribute__((format(printf, 5, 0))) __ast_verbose_ap(const char *file, int line, const char *func, int level, const char *fmt, va_list ap);
+#define ast_verbose(...) __ast_verbose(__FILE__, __LINE__, __PRETTY_FUNCTION__, -1, __VA_ARGS__)
+#define ast_verbose_callid(callid, ...) __ast_verbose_callid(__FILE__, __LINE__, __PRETTY_FUNCTION__, -1, callid, __VA_ARGS__)
 
-#define ast_verbose_ap(fmt, ap)        __ast_verbose_ap(__FILE__, __LINE__, __PRETTY_FUNCTION__, -1, fmt, ap)
+void __attribute__((format(printf, 6, 0))) __ast_verbose_ap(const char *file, int line, const char *func, int level, struct ast_callid *callid, const char *fmt, va_list ap);
 
 void __attribute__((format(printf, 2, 3))) ast_child_verbose(int level, const char *fmt, ...);
 
@@ -342,6 +351,7 @@ void ast_callid_strnprint(char *buffer, size_t buffer_size, struct ast_callid *c
 } while (0)
 
 #define ast_verb(level, ...) __ast_verbose(__FILE__, __LINE__, __PRETTY_FUNCTION__, level, __VA_ARGS__)
+#define ast_verb_callid(level, callid, ...) __ast_verbose_callid(__FILE__, __LINE__, __PRETTY_FUNCTION__, level, callid, __VA_ARGS__)
 
 #ifndef _LOGGER_BACKTRACE_H
 #define _LOGGER_BACKTRACE_H
index 4d53f15..37bbee6 100644 (file)
@@ -90,6 +90,7 @@ static void *autoservice_run(void *ign)
                int i, x = 0, ms = 50;
                struct ast_frame *f = NULL;
                struct ast_frame *defer_frame = NULL;
+               struct ast_callid *callid = NULL;
 
                AST_LIST_LOCK(&aslist);
 
@@ -128,6 +129,10 @@ static void *autoservice_run(void *ign)
                        continue;
                }
 
+               if ((callid = ast_channel_callid(chan))) {
+                       ast_callid_threadassoc_add(callid);
+               }
+
                f = ast_read(chan);
 
                if (!f) {
@@ -168,6 +173,11 @@ static void *autoservice_run(void *ign)
                } else if (f) {
                        ast_frfree(f);
                }
+
+               if (callid) {
+                       ast_callid_threadassoc_remove();
+                       callid = ast_callid_unref(callid);
+               }
        }
 
        asthread = AST_PTHREADT_NULL;
index 54ce9ae..8bb13f9 100644 (file)
@@ -376,6 +376,10 @@ static void *bridge_thread(void *data)
 
        ao2_lock(bridge);
 
+       if (bridge->callid) {
+               ast_callid_threadassoc_add(bridge->callid);
+       }
+
        ast_debug(1, "Started bridge thread for %p\n", bridge);
 
        /* Loop around until we are told to stop */
@@ -536,6 +540,10 @@ int ast_bridge_destroy(struct ast_bridge *bridge)
 
        ao2_lock(bridge);
 
+       if (bridge->callid) {
+               bridge->callid = ast_callid_unref(bridge->callid);
+       }
+
        bridge->stop = 1;
 
        bridge_poke(bridge);
@@ -931,6 +939,10 @@ static enum ast_bridge_channel_state bridge_channel_join(struct ast_bridge_chann
 
        ao2_lock(bridge_channel->bridge);
 
+       if (!bridge_channel->bridge->callid) {
+               bridge_channel->bridge->callid = ast_read_threadstorage_callid();
+       }
+
        state = bridge_channel->state;
 
        /* Add channel into the bridge */
@@ -1059,6 +1071,10 @@ static void bridge_channel_destroy(void *obj)
 {
        struct ast_bridge_channel *bridge_channel = obj;
 
+       if (bridge_channel->callid) {
+               bridge_channel->callid = ast_callid_unref(bridge_channel->callid);
+       }
+
        if (bridge_channel->bridge) {
                ao2_ref(bridge_channel->bridge, -1);
                bridge_channel->bridge = NULL;
@@ -1122,6 +1138,10 @@ static void *bridge_channel_thread(void *data)
        struct ast_bridge_channel *bridge_channel = data;
        enum ast_bridge_channel_state state;
 
+       if (bridge_channel->callid) {
+               ast_callid_threadassoc_add(bridge_channel->callid);
+       }
+
        state = bridge_channel_join(bridge_channel);
 
        /* If no other thread is going to take the channel then hang it up, or else we would have to service it until something else came along */
@@ -1144,6 +1164,7 @@ static void *bridge_channel_thread(void *data)
 int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, int allow_hangup)
 {
        struct ast_bridge_channel *bridge_channel = bridge_channel_alloc(bridge);
+
        /* Try to allocate a structure for the bridge channel */
        if (!(bridge_channel)) {
                return -1;
@@ -1154,7 +1175,7 @@ int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struc
        bridge_channel->swap = swap;
        bridge_channel->features = features;
        bridge_channel->allow_impart_hangup = allow_hangup;
-
+       bridge_channel->callid = ast_read_threadstorage_callid();
 
        /* Actually create the thread that will handle the channel */
        if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) {
index 9333864..768afc6 100644 (file)
@@ -851,8 +851,8 @@ void ast_channel_callid_set(struct ast_channel *chan, struct ast_callid *callid)
        if (chan->callid) {
 
                if ((option_debug >= 3) || (ast_opt_dbg_module && ast_debug_get_by_module(AST_MODULE) >= 3)) {
-                       char call_identifier_from[13];
-                       char call_identifier_to[13];
+                       char call_identifier_from[AST_CALLID_BUFFER_LENGTH];
+                       char call_identifier_to[AST_CALLID_BUFFER_LENGTH];
                        ast_callid_strnprint(call_identifier_from, sizeof(call_identifier_from), chan->callid);
                        ast_callid_strnprint(call_identifier_to, sizeof(call_identifier_to), callid);
                        ast_log(LOG_DEBUG, "Channel Call ID changing from %s to %s\n", call_identifier_from, call_identifier_to);
index e6d629b..bb20bc1 100644 (file)
@@ -1398,7 +1398,7 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
        long elapsed_seconds=0;
        int hour=0, min=0, sec=0;
        struct ast_callid *callid;
-       char call_identifier_str[13] = "";
+       char call_identifier_str[AST_CALLID_BUFFER_LENGTH] = "";
 #ifdef CHANNEL_TRACE
        int trace_enabled;
 #endif
index fbeaa75..79d1036 100644 (file)
@@ -5417,8 +5417,17 @@ static int parked_call_exec(struct ast_channel *chan, const char *data)
        }
        AST_LIST_TRAVERSE_SAFE_END;
        if (pu) {
+               struct ast_callid *callid = ast_read_threadstorage_callid();
+
                /* Found a parked call to pickup. */
                peer = pu->chan;
+
+               /* We need to map the call id we have from this thread to the channel we found. */
+               if (callid) {
+                       ast_channel_callid_set(peer, callid);
+                       callid = ast_callid_unref(callid);
+               }
+
                con = ast_context_find(parkinglot->cfg.parking_con);
                if (con) {
                        if (ast_context_remove_extension2(con, pu->parkingexten, 1, NULL, 0)) {
index 6bfafe9..ca26481 100644 (file)
@@ -1691,7 +1691,7 @@ void ast_backtrace(void)
 #endif /* defined(HAVE_BKTR) */
 }
 
-void __ast_verbose_ap(const char *file, int line, const char *func, int level, const char *fmt, va_list ap)
+void __ast_verbose_ap(const char *file, int line, const char *func, int level, struct ast_callid *callid, const char *fmt, va_list ap)
 {
        struct ast_str *buf = NULL;
        int res = 0;
@@ -1743,15 +1743,30 @@ void __ast_verbose_ap(const char *file, int line, const char *func, int level, c
                return;
        }
 
-       ast_log(__LOG_VERBOSE, file, line, func, "%s", ast_str_buffer(buf));
+       ast_log_callid(__LOG_VERBOSE, file, line, func, callid, "%s", ast_str_buffer(buf));
 }
 
 void __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt, ...)
 {
+       struct ast_callid *callid;
        va_list ap;
 
+       callid = ast_read_threadstorage_callid();
+
+       va_start(ap, fmt);
+       __ast_verbose_ap(file, line, func, level, callid, fmt, ap);
+       va_end(ap);
+
+       if (callid) {
+               ast_callid_unref(callid);
+       }
+}
+
+void __ast_verbose_callid(const char *file, int line, const char *func, int level, struct ast_callid *callid, const char *fmt, ...)
+{
+       va_list ap;
        va_start(ap, fmt);
-       __ast_verbose_ap(file, line, func, level, fmt, ap);
+       __ast_verbose_ap(file, line, func, level, callid, fmt, ap);
        va_end(ap);
 }
 
@@ -1760,11 +1775,18 @@ void __ast_verbose(const char *file, int line, const char *func, int level, cons
 void __attribute__((format(printf, 1,2))) ast_verbose(const char *fmt, ...);
 void ast_verbose(const char *fmt, ...)
 {
+       struct ast_callid *callid;
        va_list ap;
 
+       callid = ast_read_threadstorage_callid();
+
        va_start(ap, fmt);
-       __ast_verbose_ap("", 0, "", 0, fmt, ap);
+       __ast_verbose_ap("", 0, "", 0, callid, fmt, ap);
        va_end(ap);
+
+       if (callid) {
+               ast_callid_unref(callid);
+       }
 }
 
 int ast_register_verbose(void (*v)(const char *string))
index 0d6df93..006549c 100644 (file)
@@ -9202,6 +9202,14 @@ static void *async_wait(void *data)
        struct ast_frame *f;
        struct ast_app *app;
 
+       if (chan) {
+               struct ast_callid *callid = ast_channel_callid(chan);
+               if (callid) {
+                       ast_callid_threadassoc_add(callid);
+                       ast_callid_unref(callid);
+               }
+       }
+
        while (timeout && (ast_channel_state(chan) != AST_STATE_UP)) {
                res = ast_waitfor(chan, timeout);
                if (res < 1)