Merge in ast_strftime branch, which changes timestamps to be accurate to the microsec...
[asterisk/asterisk.git] / channels / chan_zap.c
index 81c1a8f..0e52a7b 100644 (file)
@@ -584,7 +584,7 @@ static struct zt_pvt {
        char callwait_name[AST_MAX_EXTENSION];
        char rdnis[AST_MAX_EXTENSION];
        char dnid[AST_MAX_EXTENSION];
-       unsigned int group;
+       ast_group_t group;
        int law;
        int confno;                                     /*!< Our conference */
        int confusers;                                  /*!< Who is using our conference */
@@ -1757,14 +1757,23 @@ static int restore_gains(struct zt_pvt *p)
 
 static inline int zt_set_hook(int fd, int hs)
 {
-       int x, res;
+       int x, res, count = 0;
+
        x = hs;
        res = ioctl(fd, ZT_HOOK, &x);
-       if (res < 0) 
-       {
+
+       while (res < 0 && count < 20) {
+               usleep(100000); /* 1/10 sec. */
+               x = hs;
+               res = ioctl(fd, ZT_HOOK, &x);
+               count++;
+       }
+
+       if (res < 0) {
                if (errno == EINPROGRESS) return 0;
                ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
        }
+
        return res;
 }
 
@@ -3050,7 +3059,7 @@ static int zt_answer(struct ast_channel *ast)
                /* Pick up the line */
                ast_debug(1, "Took %s off hook\n", ast->name);
                if (p->hanguponpolarityswitch) {
-                       gettimeofday(&p->polaritydelaytv, NULL);
+                       p->polaritydelaytv = ast_tvnow();
                }
                res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
                tone_zone_play_tone(p->subs[index].zfd, -1);
@@ -4454,7 +4463,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                break;
                        }
                        /* Remember last time we got a flash-hook */
-                       gettimeofday(&p->flashtime, NULL);
+                       p->flashtime = ast_tvnow();
                        switch (mysig) {
                        case SIG_FXOLS:
                        case SIG_FXOGS:
@@ -4724,7 +4733,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
                                        ast_debug(1, "Answering on polarity switch!\n");
                                        ast_setstate(p->owner, AST_STATE_UP);
                                        if (p->hanguponpolarityswitch) {
-                                               gettimeofday(&p->polaritydelaytv, NULL);
+                                               p->polaritydelaytv = ast_tvnow();
                                        }
                                } else
                                        ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
@@ -4827,7 +4836,7 @@ static struct ast_frame *__zt_exception(struct ast_channel *ast)
                        /* Do nothing */
                        break;
                case ZT_EVENT_WINKFLASH:
-                       gettimeofday(&p->flashtime, NULL);
+                       p->flashtime = ast_tvnow();
                        if (p->owner) {
                                if (option_verbose > 2) 
                                        ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
@@ -8530,7 +8539,7 @@ static void *ss7_linkset(void *data)
        while(1) {
                ast_mutex_lock(&linkset->lock);
                if ((next = ss7_schedule_next(ss7))) {
-                       gettimeofday(&tv, NULL);
+                       tv = ast_tvnow();
                        tv.tv_sec = next->tv_sec - tv.tv_sec;
                        tv.tv_usec = next->tv_usec - tv.tv_usec;
                        if (tv.tv_usec < 0) {
@@ -8651,7 +8660,7 @@ static void *ss7_linkset(void *data)
                                        {
                                                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
                                                ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
-                                               zap_queue_frame(p, &f, ss7);
+                                               zap_queue_frame(p, &f, linkset);
                                                p->progress = 1;
                                        }
                                        break;
@@ -8782,7 +8791,7 @@ static void *ss7_linkset(void *data)
                                ast_mutex_lock(&p->lock);
                                if (p->owner) {
                                        p->owner->hangupcause = e->rel.cause;
-                                       ast_queue_hangup(p->owner);
+                                       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                                } else
                                        ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
 
@@ -9293,7 +9302,7 @@ static void *pri_dchannel(void *vpri)
        int nextidle = -1;
        struct ast_channel *c;
        struct timeval tv, lowest, *next;
-       struct timeval lastidle = { 0, 0 };
+       struct timeval lastidle = ast_tvnow();
        int doidling=0;
        char *cc;
        char idlen[80];
@@ -9310,7 +9319,6 @@ static void *pri_dchannel(void *vpri)
        char plancallingani[256];
        char calledtonstr[10];
        
-       gettimeofday(&lastidle, NULL);
        if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
                /* Need to do idle dialing, check to be sure though */
                cc = strchr(pri->idleext, '@');
@@ -9380,7 +9388,7 @@ static void *pri_dchannel(void *vpri)
                                                }
                                        } else
                                                ast_log(LOG_WARNING, "Unable to request channel 'Zap/%s' for idle call\n", idlen);
-                                       gettimeofday(&lastidle, NULL);
+                                       lastidle = ast_tvnow();
                                }
                        } else if ((haveidles < pri->minunused) &&
                                   (activeidles > pri->minidle)) {
@@ -10085,25 +10093,29 @@ static void *pri_dchannel(void *vpri)
                                                        else if (pri->pvts[chanpos]->owner) {
                                                                /* Queue a BUSY instead of a hangup if our cause is appropriate */
                                                                pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-                                                               switch(e->hangup.cause) {
-                                                               case PRI_CAUSE_USER_BUSY:
-                                                                       pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
-                                                                       break;
-                                                               case PRI_CAUSE_CALL_REJECTED:
-                                                               case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
-                                                               case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-                                                               case PRI_CAUSE_SWITCH_CONGESTION:
-                                                               case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
-                                                               case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-                                                                       pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
-                                                                       break;
-                                                               default:
+                                                               if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
                                                                        pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+                                                               else {
+                                                                       switch (e->hangup.cause) {
+                                                                       case PRI_CAUSE_USER_BUSY:
+                                                                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
+                                                                               break;
+                                                                       case PRI_CAUSE_CALL_REJECTED:
+                                                                       case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+                                                                       case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+                                                                       case PRI_CAUSE_SWITCH_CONGESTION:
+                                                                       case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+                                                                       case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+                                                                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
+                                                                               break;
+                                                                       default:
+                                                                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+                                                                       }
                                                                }
                                                        }
                                                        if (option_verbose > 2) 
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n", 
-                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
+                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
                                                } else {
                                                        pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
                                                        pri->pvts[chanpos]->call = NULL;
@@ -10149,23 +10161,27 @@ static void *pri_dchannel(void *vpri)
                                                        pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
                                                else if (pri->pvts[chanpos]->owner) {
                                                        pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-                                                       switch(e->hangup.cause) {
-                                                       case PRI_CAUSE_USER_BUSY:
-                                                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
-                                                               break;
-                                                       case PRI_CAUSE_CALL_REJECTED:
-                                                       case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
-                                                       case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-                                                       case PRI_CAUSE_SWITCH_CONGESTION:
-                                                       case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
-                                                       case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-                                                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
-                                                               break;
-                                                       default:
+                                                       if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
                                                                pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+                                                       else {
+                                                               switch (e->hangup.cause) {
+                                                                       case PRI_CAUSE_USER_BUSY:
+                                                                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
+                                                                               break;
+                                                                       case PRI_CAUSE_CALL_REJECTED:
+                                                                       case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+                                                                       case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+                                                                       case PRI_CAUSE_SWITCH_CONGESTION:
+                                                                       case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+                                                                       case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+                                                                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
+                                                                               break;
+                                                                       default:
+                                                                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+                                                               }
                                                        }
                                                        if (option_verbose > 2) 
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+                                                               ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
                                                        if (e->hangup.aoc_units > -1)
                                                                if (option_verbose > 2)
                                                                        ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
@@ -11568,8 +11584,6 @@ static int linkset_addsigchan(int sigchan)
        if (cur_defaultdpc < 0) {
                ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
                return -1;
-       } else {
-               ss7_set_default_dpc(link->ss7, cur_defaultdpc);
        }
 
        if (cur_networkindicator < 0) {
@@ -12125,6 +12139,14 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                                ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
                        else
                                confp->chan.amaflags = y;
+               } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
+                       confp->chan.polarityonanswerdelay = atoi(v->value);
+               } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
+                       confp->chan.answeronpolarityswitch = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
+                       confp->chan.hanguponpolarityswitch = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "sendcalleridafter")) {
+                       confp->chan.sendcalleridafter = atoi(v->value);
                } else if (!reload){ 
                         if (!strcasecmp(v->name, "signalling")) {
                                confp->chan.outsigmod = -1;
@@ -12621,14 +12643,6 @@ static int process_zap(struct zt_chan_conf *confp, struct ast_variable *v, int r
                                        }
                                }
                                close(ctlfd);
-                       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
-                               confp->chan.polarityonanswerdelay = atoi(v->value);
-                       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
-                               confp->chan.answeronpolarityswitch = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
-                               confp->chan.hanguponpolarityswitch = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
-                               confp->chan.sendcalleridafter = atoi(v->value);
                        } else if (!strcasecmp(v->name, "defaultcic")) {
                                ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
                        } else if (!strcasecmp(v->name, "defaultozz")) {