]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
(closes issue #12982)
authorSteve Murphy <murf@digium.com>
Tue, 5 Aug 2008 23:13:20 +0000 (23:13 +0000)
committerSteve Murphy <murf@digium.com>
Tue, 5 Aug 2008 23:13:20 +0000 (23:13 +0000)
Reported by: bcnit
Tested by: murf

I discovered that also, in the previous bug fixes and changes,
the cdr.conf 'unanswered' option is not being obeyed, so
I fixed this.

And, yes, there are two 'answer' times involved in this
scenario, and I would agree with you, that the first
answer time is the time that should appear in the CDR.
(the second 'answer' time is the time that the bridge
was begun).

I made the necessary adjustments, recording the first
answer time into the peer cdr, and then using that to
override the bridge cdr's value.

To get the 'unanswered' CDRs to appear, I purposely
output them, using the dial cmd to mark them as
DIALED (with a new flag), and outputting them if
they bear that flag, and you are in the right mode.

I also corrected one small mention of the Zap device
to equally consider the dahdi device.

I heavily tested 10-sec-wait macros in dial, and
without the macro call; I tested hangups while the
macro was running vs. letting the macro complete
and the bridge form. Looks OK. Removed all the
instrumentation and debug.

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

apps/app_dial.c
include/asterisk/cdr.h
main/cdr.c
main/channel.c
res/res_features.c

index fb46e58372d6bbc2a208bcd701d434092cd16bad..540a74e89de281bb91df5e2c1bcac2ecb64f9c63 100644 (file)
@@ -578,6 +578,10 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l
                                                if (option_verbose > 2)
                                                        ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
                                                peer = c;
+                                               if (peer->cdr) {
+                                                       peer->cdr->answer = ast_tvnow();
+                                                       peer->cdr->disposition = AST_CDR_ANSWERED;
+                                               }
                                                ast_copy_flags(peerflags, o,
                                                               OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
                                                               OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
@@ -1761,8 +1765,9 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                                res = -1;
                                goto done;
                        }
-                       if (opermode && (!strncmp(chan->name,"Zap",3)) &&
-                               (!strncmp(peer->name,"Zap",3)))
+                       if (opermode && 
+                               (((!strncasecmp(chan->name,"Zap",3)) && (!strncasecmp(peer->name,"Zap",3))) ||
+                                ((!strncasecmp(chan->name,"Dahdi",5)) && (!strncasecmp(peer->name,"Dahdi",5)))))
                        {
                                struct oprmode oprmode;
 
index dc53f39322b06b2b4419ee73b5f5e88d93d533e0..74f6a0ab1a4ab7e15ff8e011279bddbe4fd2ea0a 100644 (file)
@@ -36,6 +36,7 @@
 #define AST_CDR_FLAG_ENABLE                    (1 << 7)
 #define AST_CDR_FLAG_ANSLOCKED      (1 << 8)
 #define AST_CDR_FLAG_DONT_TOUCH     (1 << 9)
+#define AST_CDR_FLAG_DIALED         (1 << 10)
 
 /*! Disposition */
 #define AST_CDR_NULL                0
@@ -103,6 +104,7 @@ struct ast_cdr {
        struct ast_cdr *next;
 };
 
+int ast_cdr_isset_unanswered(void);
 void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw);
 int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int recur);
 int ast_cdr_serialize_variables(struct ast_cdr *cdr, char *buf, size_t size, char delim, char sep, int recur);
index 3afe07aad6efeafc7d5fd73c97b5b2a678306103..1df433c32752f71cdf79edb48067f0a9768028e8 100644 (file)
@@ -162,6 +162,11 @@ void ast_cdr_unregister(const char *name)
        AST_LIST_UNLOCK(&be_list);
 }
 
+int ast_cdr_isset_unanswered(void)
+{
+       return unanswered;
+}
+
 /*! Duplicate a CDR record 
        \returns Pointer to new CDR record
 */
index 1383feb0f3dd8e885fb6354fc557daf851f789ad..fb51c20fa8b07b72b176b8392c5de068a2a96a1e 100644 (file)
@@ -1514,7 +1514,10 @@ int ast_hangup(struct ast_channel *chan)
                        ast_cause2str(chan->hangupcause)
                        );
 
-       if (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_BRIDGED) && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED) && chan->cdr->disposition != AST_CDR_NULL) {
+       if (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_BRIDGED) && 
+               !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED) && 
+           (chan->cdr->disposition != AST_CDR_NULL || ast_test_flag(chan->cdr, AST_CDR_FLAG_DIALED))) {
+                       
                ast_cdr_end(chan->cdr);
                ast_cdr_detach(chan->cdr);
        }
@@ -3052,6 +3055,8 @@ int ast_call(struct ast_channel *chan, char *addr, int timeout)
        /* Stop if we're a zombie or need a soft hangup */
        ast_channel_lock(chan);
        if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) {
+               if (chan->cdr)
+                       ast_set_flag(chan->cdr, AST_CDR_FLAG_DIALED);
                if (chan->tech->call)
                        res = chan->tech->call(chan, addr, timeout);
                ast_set_flag(chan, AST_FLAG_OUTGOING);
index e326a8960614959ca291e68531cfc775b25fb3cd..75e1ccbd91daa085ae494b71d7fa817767fed53f 100644 (file)
@@ -1475,8 +1475,19 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                                ast_cdr_start(bridge_cdr);
                        }
                }
-               ast_cdr_answer(bridge_cdr);
-               ast_cdr_answer(chan->cdr); /* for the sake of cli status checks */
+               /* peer->cdr->answer will be set when a macro runs on the peer;
+                  in that case, the bridge answer will be delayed while the
+                  macro plays on the peer channel. The peer answered the call
+                  before the macro started playing. To the phone system,
+                  this is billable time for the call, even tho the caller
+                  hears nothing but ringing while the macro does its thing. */
+               if (peer->cdr && !ast_tvzero(peer->cdr->answer)) {
+                       bridge_cdr->answer = peer->cdr->answer;
+                       chan->cdr->answer = peer->cdr->answer;
+               } else {
+                       ast_cdr_answer(bridge_cdr);
+                       ast_cdr_answer(chan->cdr); /* for the sake of cli status checks */
+               }
                ast_set_flag(chan->cdr, AST_CDR_FLAG_BRIDGED);
                if (peer->cdr) {
                        ast_set_flag(peer->cdr, AST_CDR_FLAG_BRIDGED);
@@ -1550,7 +1561,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                if (res < 0) {
                        if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
                                ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
-                       return -1;
+                       goto before_you_go;
                }
                
                if (!f || (f->frametype == AST_FRAME_CONTROL &&
@@ -1647,6 +1658,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                        ast_frfree(f);
 
        }
+   before_you_go:
        /* obey the NoCDR() wishes. */
        if (!chan->cdr || (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED))) {
                
@@ -1659,12 +1671,22 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
                        ast_cdr_specialized_reset(chan->cdr,0);
                }
                if (peer->cdr) {
-                       if (orig_peer_cdr && peer->cdr != orig_peer_cdr) {
-                               /* this can only happen if there was a transfer, methinks */
-                               ast_cdr_specialized_reset(orig_peer_cdr,0);
-                       } else {
-                               ast_cdr_specialized_reset(peer->cdr,0);
+                       /* before resetting the peer cdr, throw a copy of it to the
+                          backend, just in case the cdr.conf file is calling for
+                          unanswered CDR's. */
+                       
+                       /* When peer->cdr isn't the same addr as orig_peer_cdr,
+                          this can only happen if there was a transfer, methinks;
+                          at any rate, only pay attention to the original*/
+                       if (ast_cdr_isset_unanswered()) {
+                               struct ast_cdr *dupd = ast_cdr_dup(orig_peer_cdr);
+                               if (dupd) {
+                                       if (ast_tvzero(dupd->end) && ast_cdr_isset_unanswered())
+                                               ast_cdr_end(dupd);
+                                       ast_cdr_detach(dupd);
+                               }
                        }
+                       ast_cdr_specialized_reset(orig_peer_cdr,0);
                }
        }
        return res;