📄 chan_misdn.c
字号:
switch (bc->AOCDtype) { case Fac_AOCDCurrency: pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency"); if (bc->AOCD.currency.chargeNotAvailable) pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no"); else { pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes"); if (bc->AOCD.currency.freeOfCharge) pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes"); else { pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no"); if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) { pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf); if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf)) pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf); } } } break; case Fac_AOCDChargingUnit: pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit"); if (bc->AOCD.chargingUnit.chargeNotAvailable) pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no"); else { pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes"); if (bc->AOCD.chargingUnit.freeOfCharge) pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes"); else { pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no"); if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) { pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf); if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf)) pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf); } } } break; default: break; }}/*************** Helpers END *************/static void sighandler(int sig){}static void* misdn_tasks_thread_func (void *data){ int wait; struct sigaction sa; sa.sa_handler = sighandler; sa.sa_flags = SA_NODEFER; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGUSR1); sigaction(SIGUSR1, &sa, NULL); sem_post((sem_t *)data); while (1) { wait = ast_sched_wait(misdn_tasks); if (wait < 0) wait = 8000; if (poll(NULL, 0, wait) < 0) chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n"); ast_sched_runq(misdn_tasks); } return NULL;}static void misdn_tasks_init (void){ sem_t blocker; int i = 5; if (sem_init(&blocker, 0, 0)) { perror("chan_misdn: Failed to initialize semaphore!"); exit(1); } chan_misdn_log(4, 0, "Starting misdn_tasks thread\n"); misdn_tasks = sched_context_create(); pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker); while (sem_wait(&blocker) && --i); sem_destroy(&blocker);}static void misdn_tasks_destroy (void){ if (misdn_tasks) { chan_misdn_log(4, 0, "Killing misdn_tasks thread\n"); if ( pthread_cancel(misdn_tasks_thread) == 0 ) { cb_log(4, 0, "Joining misdn_tasks thread\n"); pthread_join(misdn_tasks_thread, NULL); } sched_context_destroy(misdn_tasks); }}static inline void misdn_tasks_wakeup (void){ pthread_kill(misdn_tasks_thread, SIGUSR1);}static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data, int variable){ int task_id; if (!misdn_tasks) { misdn_tasks_init(); } task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable); misdn_tasks_wakeup(); return task_id;}static int misdn_tasks_add (int timeout, ast_sched_cb callback, const void *data){ return _misdn_tasks_add_variable(timeout, callback, data, 0);}static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data){ return _misdn_tasks_add_variable(timeout, callback, data, 1);}static void misdn_tasks_remove (int task_id){ AST_SCHED_DEL(misdn_tasks, task_id);}static int misdn_l1_task (const void *data){ misdn_lib_isdn_l1watcher(*(int *)data); chan_misdn_log(5, *(int *)data, "L1watcher timeout\n"); return 1;}static int misdn_overlap_dial_task (const void *data){ struct timeval tv_end, tv_now; int diff; struct chan_list *ch = (struct chan_list *)data; chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state); if (ch->state != MISDN_WAITING4DIGS) { ch->overlap_dial_task = -1; return 0; } ast_mutex_lock(&ch->overlap_tv_lock); tv_end = ch->overlap_tv; ast_mutex_unlock(&ch->overlap_tv_lock); tv_end.tv_sec += ch->overlap_dial; tv_now = ast_tvnow(); diff = ast_tvdiff_ms(tv_end, tv_now); if (diff <= 100) { char *dad=ch->bc->dad, sexten[]="s"; /* if we are 100ms near the timeout, we are satisfied.. */ stop_indicate(ch); if (ast_strlen_zero(ch->bc->dad)) { dad=sexten; strcpy(ch->ast->exten, sexten); } if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) { ch->state=MISDN_DIALING; if (pbx_start_chan(ch) < 0) { chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n"); goto misdn_overlap_dial_task_disconnect; } } else {misdn_overlap_dial_task_disconnect: hanguptone_indicate(ch); ch->bc->out_cause=1; ch->state=MISDN_CLEANING; misdn_lib_send_event(ch->bc, EVENT_DISCONNECT); } ch->overlap_dial_task = -1; return 0; } else return diff;}static void send_digit_to_chan(struct chan_list *cl, char digit ){ static const char* dtmf_tones[] = { "!941+1336/100,!0/100", /* 0 */ "!697+1209/100,!0/100", /* 1 */ "!697+1336/100,!0/100", /* 2 */ "!697+1477/100,!0/100", /* 3 */ "!770+1209/100,!0/100", /* 4 */ "!770+1336/100,!0/100", /* 5 */ "!770+1477/100,!0/100", /* 6 */ "!852+1209/100,!0/100", /* 7 */ "!852+1336/100,!0/100", /* 8 */ "!852+1477/100,!0/100", /* 9 */ "!697+1633/100,!0/100", /* A */ "!770+1633/100,!0/100", /* B */ "!852+1633/100,!0/100", /* C */ "!941+1633/100,!0/100", /* D */ "!941+1209/100,!0/100", /* * */ "!941+1477/100,!0/100" }; /* # */ struct ast_channel *chan=cl->ast; if (digit >= '0' && digit <='9') ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0); else if (digit >= 'A' && digit <= 'D') ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0); else if (digit == '*') ast_playtones_start(chan,0,dtmf_tones[14], 0); else if (digit == '#') ast_playtones_start(chan,0,dtmf_tones[15], 0); else { /* not handled */ ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name); }}/*** CLI HANDLING ***/static int misdn_set_debug(int fd, int argc, char *argv[]){ int level; if (argc != 4 && argc != 5 && argc != 6 && argc != 7) return RESULT_SHOWUSAGE; level = atoi(argv[3]); switch (argc) { case 4: case 5: { int i; int only = 0; if (argc == 5) { if (strncasecmp(argv[4], "only", strlen(argv[4]))) return RESULT_SHOWUSAGE; else only = 1; } for (i=0; i<=max_ports; i++) { misdn_debug[i] = level; misdn_debug_only[i] = only; } ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":""); } break; case 6: case 7: { int port; if (strncasecmp(argv[4], "port", strlen(argv[4]))) return RESULT_SHOWUSAGE; port = atoi(argv[5]); if (port <= 0 || port > max_ports) { switch (max_ports) { case 0: ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n"); break; case 1: ast_cli(fd, "port number not valid! only port 1 is available.\n"); break; default: ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports); } return 0; } if (argc == 7) { if (strncasecmp(argv[6], "only", strlen(argv[6]))) return RESULT_SHOWUSAGE; else misdn_debug_only[port] = 1; } else misdn_debug_only[port] = 0; misdn_debug[port] = level; ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port); } } return 0;}static int misdn_set_crypt_debug(int fd, int argc, char *argv[]){ if (argc != 5) return RESULT_SHOWUSAGE; return 0;}static int misdn_port_block(int fd, int argc, char *argv[]){ int port; if (argc != 4) return RESULT_SHOWUSAGE; port = atoi(argv[3]); misdn_lib_port_block(port); return 0;}static int misdn_port_unblock(int fd, int argc, char *argv[]){ int port; if (argc != 4) return RESULT_SHOWUSAGE; port = atoi(argv[3]); misdn_lib_port_unblock(port); return 0;}static int misdn_restart_port (int fd, int argc, char *argv[]){ int port; if (argc != 4) return RESULT_SHOWUSAGE; port = atoi(argv[3]); misdn_lib_port_restart(port); return 0;}static int misdn_restart_pid (int fd, int argc, char *argv[]){ int pid; if (argc != 4) return RESULT_SHOWUSAGE; pid = atoi(argv[3]); misdn_lib_pid_restart(pid); return 0;}static int misdn_port_up (int fd, int argc, char *argv[]){ int port; if (argc != 4) return RESULT_SHOWUSAGE; port = atoi(argv[3]); misdn_lib_get_port_up(port); return 0;}static int misdn_port_down (int fd, int argc, char *argv[]){ int port; if (argc != 4) return RESULT_SHOWUSAGE; port = atoi(argv[3]); misdn_lib_get_port_down(port); return 0;}static inline void show_config_description (int fd, enum misdn_cfg_elements elem){ char section[BUFFERSIZE]; char name[BUFFERSIZE]; char desc[BUFFERSIZE]; char def[BUFFERSIZE]; char tmp[BUFFERSIZE]; misdn_cfg_get_name(elem, tmp, sizeof(tmp)); term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp)); misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def)); if (elem < MISDN_CFG_LAST) term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section)); else term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section)); if (*def) ast_cli(fd, "[%s] %s (Default: %s)\n\t%s\n", section, name, def, desc); else ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);}static int misdn_show_config (int fd, int argc, char *argv[]){ char buffer[BUFFERSIZE]; enum misdn_cfg_elements elem; int linebreak; int onlyport = -1; int ok = 0; if (argc >= 4) { if (!strcmp(argv[3], "description")) { if (argc == 5) { enum misdn_cfg_elements elem = misdn_cfg_get_elem (argv[4]); if (elem == MISDN_CFG_FIRST) ast_cli(fd, "Unknown element: %s\n", argv[4]); else show_config_description(fd, elem); return 0; } return RESULT_SHOWUSAGE; } if (!strcmp(argv[3], "descriptions")) { if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "general"))) { for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) { show_config_description(fd, elem); ast_cli(fd, "\n"); } ok = 1; } if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "ports"))) { for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) { show_config_description(fd, elem); ast_cli(fd, "\n"); } ok = 1; } return ok ? 0 : RESULT_SHOWUSAGE; } if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) { ast_cli(fd, "Unknown option: %s\n", argv[3]); return RESULT_SHOWUSAGE; } } if (argc == 3 || onlyport == 0) { ast_cli(fd,"Misdn General-Config: \n"); for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) { misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE); ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : ""); } ast_cli(fd, "\n"); } if (onlyport < 0) { int port = misdn_cfg_get_next_port(0); for (; port > 0; port = misdn_cfg_get_next_port(port)) { ast_cli(fd, "\n[PORT %d]\n", port); for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) { misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE); ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : ""); } ast_cli(fd, "\n"); } } if (onlyport > 0) { if (misdn_cfg_is_port_valid(onlyport)) { ast_cli(fd, "[PORT %d]\n", onlyport); for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) { misdn_cfg_get_config_string(onlyport, elem, buffer, BUFFERSIZE); ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : ""); } ast_cli(fd, "\n"); } else { ast_cli(fd, "Port %d is not active!\n", onlyport); } } return 0;}struct state_struct { enum misdn_chan_state state; char txt[255] ;} ;static struct state_struct state_array[] = { {MISDN_NOTHING,"NOTHING"}, /* at beginning */ {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /* when waiting for infos */ {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /* when asterisk couldn't match our ext */ {MISDN_INCOMING_SETUP,"INCOMING SETUP"}, /* when pbx_start */ {MISDN_DIALING,"DIALING"}, /* when pbx_start */ {MISDN_PROGRESS,"PROGRESS"}, /* when pbx_start */ {MISDN_PROCEEDING,"PROCEEDING"}, /* when pbx_start */ {MISDN_CALLING,"CALLING"}, /* when misdn_call is called */ {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */ {MISDN_ALERTING,"ALERTING"}, /* when Alerting */ {MISDN_BUSY,"BUSY"}, /* when BUSY */ {MISDN_CONNECTED,"CONNECTED"}, /* when connected */ {MISDN_PRECONNECTED,"PRECONNECTED"}, /* when connected */ {MISDN_DISCONNECTED,"DISCONNECTED"}, /* when connected */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -