📄 chan_vpb.cc
字号:
} } else if (e->data == VPB_FAX) { if (!p->faxhandled) { if (strcmp(p->owner->exten, "fax")) { const char *target_context = S_OR(p->owner->macrocontext, p->owner->context); if (ast_exists_extension(p->owner, target_context, "fax", 1, p->owner->cid.cid_num)) { ast_verb(3, "Redirecting %s to fax extension\n", p->owner->name); /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", p->owner->exten); if (ast_async_goto(p->owner, target_context, "fax", 1)) { ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", p->owner->name, target_context); } } else { ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); } } else { ast_debug(1, "Already in a fax extension, not redirecting\n"); } } else { ast_debug(1, "Fax already handled\n"); } } else if (e->data == VPB_GRUNT) { if (ast_tvdiff_ms(ast_tvnow(), p->lastgrunt) > gruntdetect_timeout) { /* Nothing heard on line for a very long time * Timeout connection */ ast_verb(3, "grunt timeout\n"); ast_log(LOG_NOTICE, "%s: Line hangup due of lack of conversation\n", p->dev); f.subclass = AST_CONTROL_HANGUP; } else { p->lastgrunt = ast_tvnow(); f.frametype = AST_FRAME_NULL; } } else { f.frametype = AST_FRAME_NULL; } break; case VPB_CALLEND: #ifdef DIAL_WITH_CALL_PROGRESS if (e->data == VPB_CALL_CONNECTED) { f.subclass = AST_CONTROL_ANSWER; } else if (e->data == VPB_CALL_NO_DIAL_TONE || e->data == VPB_CALL_NO_RING_BACK) { f.subclass = AST_CONTROL_CONGESTION; } else if (e->data == VPB_CALL_NO_ANSWER || e->data == VPB_CALL_BUSY) { f.subclass = AST_CONTROL_BUSY; } else if (e->data == VPB_CALL_DISCONNECTED) { f.subclass = AST_CONTROL_HANGUP; } #else ast_log(LOG_NOTICE, "%s: Got call progress callback but blind dialing \n", p->dev); f.frametype = AST_FRAME_NULL; #endif break; case VPB_STATION_OFFHOOK: f.subclass = AST_CONTROL_ANSWER; break; case VPB_DROP: if ((p->mode == MODE_FXO) && (UseLoopDrop)) { /* ignore loop drop on stations */ if (p->owner->_state == AST_STATE_UP) { f.subclass = AST_CONTROL_HANGUP; } else { f.frametype = AST_FRAME_NULL; } } break; case VPB_LOOP_ONHOOK: if (p->owner->_state == AST_STATE_UP) { f.subclass = AST_CONTROL_HANGUP; } else { f.frametype = AST_FRAME_NULL; } break; case VPB_STATION_ONHOOK: f.subclass = AST_CONTROL_HANGUP; break; case VPB_STATION_FLASH: f.subclass = AST_CONTROL_FLASH; break; /* Called when dialing has finished and ringing starts * No indication that call has really been answered when using blind dialing */ case VPB_DIALEND: if (p->state < 5) { f.subclass = AST_CONTROL_ANSWER; ast_verb(2, "%s: Dialend\n", p->dev); } else { f.frametype = AST_FRAME_NULL; } break;/* case VPB_PLAY_UNDERFLOW: f.frametype = AST_FRAME_NULL; vpb_reset_play_fifo_alarm(p->handle); break; case VPB_RECORD_OVERFLOW: f.frametype = AST_FRAME_NULL; vpb_reset_record_fifo_alarm(p->handle); break;*/ default: f.frametype = AST_FRAME_NULL; break; }/* ast_verb(4, "%s: LOCKING in handle_owned [%d]\n", p->dev,res); res = ast_mutex_lock(&p->lock); ast_verb(4, "%s: LOCKING count[%d] owner[%d] \n", p->dev, p->lock.__m_count,p->lock.__m_owner);*/ if (p->bridge) { /* Check what happened, see if we need to report it. */ switch (f.frametype) { case AST_FRAME_DTMF: if ( !(p->bridge->c0 == p->owner && (p->bridge->flags & AST_BRIDGE_DTMF_CHANNEL_0) ) && !(p->bridge->c1 == p->owner && (p->bridge->flags & AST_BRIDGE_DTMF_CHANNEL_1) )) { /* Kill bridge, this is interesting. */ endbridge = 1; } break; case AST_FRAME_CONTROL: if (!(p->bridge->flags & AST_BRIDGE_IGNORE_SIGS)) { #if 0 if (f.subclass == AST_CONTROL_BUSY || f.subclass == AST_CONTROL_CONGESTION || f.subclass == AST_CONTROL_HANGUP || f.subclass == AST_CONTROL_FLASH) #endif endbridge = 1; } break; default: break; } if (endbridge) { if (p->bridge->fo) { *p->bridge->fo = ast_frisolate(&f); } if (p->bridge->rc) { *p->bridge->rc = p->owner; } ast_mutex_lock(&p->bridge->lock); p->bridge->endbridge = 1; ast_cond_signal(&p->bridge->cond); ast_mutex_unlock(&p->bridge->lock); } } if (endbridge) { res = ast_mutex_unlock(&p->lock);/* ast_verb(4, "%s: unLOCKING in handle_owned [%d]\n", p->dev,res);*/ return 0; } ast_verb(4, "%s: handle_owned: Prepared frame type[%d]subclass[%d], bridge=%p owner=[%s]\n", p->dev, f.frametype, f.subclass, (void *)p->bridge, p->owner->name); /* Trylock used here to avoid deadlock that can occur if we * happen to be in here handling an event when hangup is called * Problem is that hangup holds p->owner->lock */ if ((f.frametype >= 0) && (f.frametype != AST_FRAME_NULL) && (p->owner)) { if (ast_channel_trylock(p->owner) == 0) { ast_queue_frame(p->owner, &f); ast_channel_unlock(p->owner); ast_verb(4, "%s: handled_owned: Queued Frame to [%s]\n", p->dev, p->owner->name); } else { ast_verbose("%s: handled_owned: Missed event %d/%d \n", p->dev, f.frametype, f.subclass); } } res = ast_mutex_unlock(&p->lock);/* ast_verb(4, "%s: unLOCKING in handle_owned [%d]\n", p->dev,res);*/ return 0;}static inline int monitor_handle_notowned(struct vpb_pvt *p, VPB_EVENT *e){ char s[2] = {0}; struct ast_channel *owner = p->owner; char cid_num[256]; char cid_name[256];/* struct ast_channel *c;*/ char str[VPB_MAX_STR]; vpb_translate_event(e, str); ast_verb(4, "%s: handle_notowned: mode=%d, event[%d][%s]=[%d]\n", p->dev, p->mode, e->type,str, e->data); switch (e->type) { case VPB_LOOP_ONHOOK: case VPB_LOOP_POLARITY: if (UsePolarityCID == 1) { ast_verb(4, "Polarity reversal\n"); if (p->callerid_type == 1) { ast_verb(4, "Using VPB Caller ID\n"); get_callerid(p); /* UK CID before 1st ring*/ }/* get_callerid_ast(p); */ /* Caller ID using the ast functions */ } break; case VPB_RING: if (p->mode == MODE_FXO) /* FXO port ring, start * */ { vpb_new(p, AST_STATE_RING, p->context); if (UsePolarityCID != 1) { if (p->callerid_type == 1) { ast_verb(4, "Using VPB Caller ID\n"); get_callerid(p); /* Australian CID only between 1st and 2nd ring */ } get_callerid_ast(p); /* Caller ID using the ast functions */ } else { ast_log(LOG_ERROR, "Setting caller ID: %s %s\n", p->cid_num, p->cid_name); ast_set_callerid(p->owner, p->cid_num, p->cid_name, p->cid_num); p->cid_num[0] = 0; p->cid_name[0] = 0; } vpb_timer_stop(p->ring_timer); vpb_timer_start(p->ring_timer); } break; case VPB_RING_OFF: break; case VPB_STATION_OFFHOOK: if (p->mode == MODE_IMMEDIATE) { vpb_new(p,AST_STATE_RING, p->context); } else { ast_verb(4, "%s: handle_notowned: playing dialtone\n", p->dev); playtone(p->handle, &Dialtone); p->state = VPB_STATE_PLAYDIAL; p->wantdtmf = 1; p->ext[0] = 0; /* Just to be sure & paranoid.*/ } break; case VPB_DIALEND: if (p->mode == MODE_DIALTONE) { if (p->state == VPB_STATE_PLAYDIAL) { playtone(p->handle, &Dialtone); p->wantdtmf = 1; p->ext[0] = 0; /* Just to be sure & paranoid. */ }#if 0 /* These are not needed as they have timers to restart them */ else if (p->state == VPB_STATE_PLAYBUSY) { playtone(p->handle, &Busytone); p->wantdtmf = 1; p->ext[0] = 0; } else if (p->state == VPB_STATE_PLAYRING) { playtone(p->handle, &Ringbacktone); p->wantdtmf = 1; p->ext[0] = 0; }#endif } else { ast_verb(4, "%s: handle_notowned: Got a DIALEND when not really expected\n",p->dev); } break; case VPB_STATION_ONHOOK: /* clear ext */ stoptone(p->handle); p->wantdtmf = 1 ; p->ext[0] = 0; p->state = VPB_STATE_ONHOOK; break; case VPB_TIMEREXP: if (e->data == p->dtmfidd_timer_id) { if (ast_exists_extension(NULL, p->context, p->ext, 1, p->callerid)){ ast_verb(4, "%s: handle_notowned: DTMF IDD timer out, matching on [%s] in [%s]\n", p->dev, p->ext, p->context); vpb_new(p, AST_STATE_RING, p->context); } } else if (e->data == p->ring_timer_id) { /* We didnt get another ring in time! */ if (p->owner) { if (p->owner->_state != AST_STATE_UP) { /* Assume caller has hung up */ vpb_timer_stop(p->ring_timer); } } else { /* No owner any more, Assume caller has hung up */ vpb_timer_stop(p->ring_timer); } } break; case VPB_DTMF: if (p->state == VPB_STATE_ONHOOK){ /* DTMF's being passed while on-hook maybe Caller ID */ if (p->mode == MODE_FXO) { if (e->data == DTMF_CID_START) { /* CallerID Start signal */ p->dtmf_caller_pos = 0; /* Leaves the first digit out */ memset(p->callerid, 0, sizeof(p->callerid)); } else if (e->data == DTMF_CID_STOP) { /* CallerID End signal */ p->callerid[p->dtmf_caller_pos] = '\0'; ast_verb(3, " %s: DTMF CallerID %s\n", p->dev, p->callerid); if (owner) { /* if (owner->cid.cid_num) ast_free(owner->cid.cid_num); owner->cid.cid_num=NULL; if (owner->cid.cid_name) ast_free(owner->cid.cid_name); owner->cid.cid_name=NULL; owner->cid.cid_num = strdup(p->callerid); */ cid_name[0] = '\0'; cid_num[0] = '\0'; ast_callerid_split(p->callerid, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); ast_set_callerid(owner, cid_num, cid_name, cid_num); } else { ast_verb(3, " %s: DTMF CallerID: no owner to assign CID \n", p->dev); } } else if (p->dtmf_caller_pos < AST_MAX_EXTENSION) { if (p->dtmf_caller_pos >= 0) { p->callerid[p->dtmf_caller_pos] = e->data; } p->dtmf_caller_pos++; } } break; } if (p->wantdtmf == 1) { stoptone(p->handle); p->wantdtmf = 0; } p->state = VPB_STATE_GETDTMF; s[0] = e->data; strncat(p->ext, s, sizeof(p->ext) - strlen(p->ext) - 1); #if 0 if (!strcmp(p->ext, ast_pickup_ext())) { /* Call pickup has been dialled! */ if (ast_pickup_call(c)) { /* Call pickup wasnt possible */ } } else #endif if (ast_exists_extension(NULL, p->context, p->ext, 1, p->callerid)) { if (ast_canmatch_extension(NULL, p->context, p->ext, 1, p->callerid)) { ast_verb(4, "%s: handle_notowned: Multiple matches on [%s] in [%s]\n", p->dev, p->ext, p->context); /* Start DTMF IDD timer */ vpb_timer_stop(p->dtmfidd_timer); vpb_timer_start(p->dtmfidd_timer); } else { ast_verb(4, "%s: handle_notowned: Matched on [%s] in [%s]\n", p->dev, p->ext , p->context); vpb_new(p, AST_STATE_UP, p->context); } } else if (!ast_canmatch_extension(NULL, p->context, p->ext, 1, p->callerid)) { if (ast_exists_extension(NULL, "default", p->ext, 1, p->callerid)) { vpb_new(p, AST_STATE_UP, "default"); } else if (!ast_canmatch_extension(NULL, "default", p->ext, 1, p->callerid)) { ast_verb(4, "%s: handle_notowned: can't match anything in %s or default\n", p->dev, p->context); playtone(p->handle, &Busytone); vpb_timer_stop(p->busy_timer); vpb_timer_start(p->busy_timer); p->state = VPB_STATE_PLAYBUSY; } } break; default: /* Ignore.*/ break; } ast_verb(4, "%s: handle_notowned: mode=%d, [%d=>%d]\n", p->dev, p->mode, e->type, e->data); return 0;}static void *do_monitor(void *unused){ /* Monitor thread, doesn't die until explicitly killed. */ ast_verb(2, "Starting vpb monitor thread[%ld]\n", pthread_self()); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); for (;;) { VPB_EVENT e; VPB_EVENT je; char str[VPB_MAX_STR]; struct vpb_pvt *p; /* ast_verb(4, "Monitor waiting for event\n"); */ int res = vpb_get_event_sync(&e, VPB_WAIT_TIMEOUT); if ((res == VPB_NO_EVENTS) || (res == VPB_TIME_OUT)) { /* if (res == VPB_NO_EVENTS) { ast_verb(4, "No events....\n"); } else { ast_verb(4, "No events, timed out....\n"); } */ continue; } if (res != VPB_OK) { ast_log(LOG_ERROR,"Monitor get event error %d\n", res ); ast_verbose("Monitor get event error %d\n", res ); continue; } str[0] = 0; p = NULL; ast_mutex_lock(&monlock); if (e.type == VPB_NULL_EVENT) { ast_verb(4, "Monitor got null event\n"); } else { vpb_translate_event(&e, str); if (*str && *(str + 1)) { str[strlen(str) - 1] = '\0'; } ast_mutex_lock(&iflock); for (p = iflist; p && p->handle != e.handle; p = p->next); ast_mutex_unlock(&iflock); if (p) { ast_verb(4, "%s: Event [%d=>%s]\n", p ? p->dev : "null", e.type, str); } } ast_mutex_unlock(&monlock); if (!p) { if (e.type != VPB_NULL_EVENT) { ast_log(LOG_WARNING, "Got event [%s][%d], no matching iface!\n", str, e.type); ast_verb(4, "vpb/ERR: No interface for Event [%d=>%s] \n", e.type, str);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -