isdn_lib.c
来自「一个非常美妙的proxy。功能强大。基于sip的协议。如果还要的话」· C语言 代码 · 共 2,927 行 · 第 1/5 页
C
2,927 行
if (ret < mISDN_HEADER_LEN) { noentity: fprintf(stderr, "cannot request MGR_NEWENTITY from mISDN: %s\n",strerror(errno)); exit(-1); } entity = frm->dinfo & 0xffff ; if (!entity) goto noentity; return midev; }void te_lib_destroy(int midev){ char buf[1024]; mISDN_write_frame(midev, buf, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC); cb_log(4, 0, "Entetity deleted\n"); mISDN_close(midev); cb_log(4, 0, "midev closed\n");}void misdn_lib_transfer(struct misdn_bchannel* holded_bc){ holded_bc->holded=0;}struct misdn_bchannel *manager_find_bc_by_pid(int pid){ struct misdn_stack *stack; int i; for (stack=glob_mgr->stack_list; stack; stack=stack->next) { for (i=0; i<stack->b_num; i++) if (stack->bc[i].pid == pid) return &stack->bc[i]; } return NULL;}struct misdn_bchannel *manager_find_bc_holded(struct misdn_bchannel* bc){ struct misdn_stack *stack=get_stack_by_bc(bc); return find_bc_holded(stack);}struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel){ struct misdn_stack *stack; int i; if (channel < 0 || channel > MAX_BCHANS) return NULL; for (stack=glob_mgr->stack_list; stack; stack=stack->next) { if (stack->port == port) { if (channel > 0) { if (channel <= stack->b_num) { for (i = 0; i < stack->b_num; i++) { if (stack->bc[i].in_use && stack->bc[i].channel == channel) { return NULL; } } } else return NULL; } for (i = 0; i < stack->b_num; i++) { if (!stack->bc[i].in_use) { stack->bc[i].channel = channel; stack->bc[i].channel_preselected = channel?1:0; stack->bc[i].in_use = 1; return &stack->bc[i]; } } return NULL; } } return NULL;}void misdn_lib_log_ies(struct misdn_bchannel *bc){ if (!bc) return; struct misdn_stack *stack=get_stack_by_bc(bc); if (!stack) return; cb_log(2, stack->port, " --> mode:%s cause:%d ocause:%d rad:%s\n", stack->mode==NT_MODE?"NT":"TE", bc->cause, bc->out_cause, bc->rad); cb_log(2, stack->port, " --> info_dad:%s onumplan:%c dnumplan:%c rnumplan:%c\n", bc->info_dad, bc->onumplan>=0?'0'+bc->onumplan:' ', bc->dnumplan>=0?'0'+bc->dnumplan:' ', bc->rnumplan>=0?'0'+bc->rnumplan:' ' ); cb_log(2, stack->port, " --> channel:%d caps:%s pi:%x keypad:%s\n", bc->channel, bearer2str(bc->capability),bc->progress_indicator, bc->keypad); cb_log(3, stack->port, " --> urate:%d rate:%d mode:%d user1:%d\n", bc->urate, bc->rate, bc->mode,bc->user1); cb_log(3, stack->port, " --> pid:%d addr:%x l3id:%x\n", bc->pid, bc->addr, bc->l3_id); cb_log(4, stack->port, " --> bc:%x h:%d sh:%d\n", bc, bc->holded, bc->stack_holder);}int misdn_lib_send_event(struct misdn_bchannel *bc, enum event_e event ){ msg_t *msg; int err = -1 ; if (!bc) goto ERR; struct misdn_stack *stack=get_stack_by_bc(bc); if ( stack->mode == NT_MODE && !stack->l1link) { /** Queue Event **/ bc->evq=event; cb_log(1, stack->port, "Queueing Event %s because L1 is down (btw. Activating L1)\n", isdn_get_info(msgs_g, event, 0)); { /* Pull Up L1 */ iframe_t act; act.prim = PH_ACTIVATE | REQUEST; act.addr = (stack->upper_id & IF_ADDRMASK) | IF_DOWN ; act.dinfo = 0; act.len = 0; mISDN_write(glob_mgr->midev, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC); } return 0; } cb_log(1, stack->port, "I SEND:%s oad:%s dad:%s port:%d\n", isdn_get_info(msgs_g, event, 0), bc->oad, bc->dad, stack->port); misdn_lib_log_ies(bc); switch (event) { case EVENT_SETUP: if (create_process(glob_mgr->midev, bc)<0) { cb_log(0, stack->port, " No free channel at the moment @ send_event\n"); err=-ENOCHAN; goto ERR; } break; case EVENT_CONNECT: case EVENT_PROGRESS: case EVENT_ALERTING: case EVENT_PROCEEDING: case EVENT_SETUP_ACKNOWLEDGE: case EVENT_RETRIEVE_ACKNOWLEDGE: if (stack->mode == NT_MODE) { if (bc->channel <=0 ) { /* else we have the channel already */ bc->channel = find_free_chan_in_stack(stack, 0); if (!bc->channel) { cb_log(0, stack->port, " No free channel at the moment\n"); err=-ENOCHAN; goto ERR; } } /* Its that i generate channels */ } setup_bc(bc); if ( event == EVENT_CONNECT ) { if ( *bc->crypt_key ) { cb_log(4, stack->port, " --> ENABLING BLOWFISH port:%d channel:%d oad%d:%s dad%d:%s \n", stack->port, bc->channel, bc->onumplan,bc->oad, bc->dnumplan,bc->dad); manager_ph_control_block(bc, BF_ENABLE_KEY, bc->crypt_key, strlen(bc->crypt_key) ); } if ( misdn_cap_is_speech(bc->capability)) { if (!bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0); if (bc->ec_enable) manager_ec_enable(bc); if (bc->txgain != 0) { cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain); manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain); } if ( bc->rxgain != 0 ) { cb_log(4, stack->port, "--> Changing rxgain to %d\n", bc->rxgain); manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain); } } } if (event == EVENT_RETRIEVE_ACKNOWLEDGE) { manager_bchannel_activate(bc); } break; case EVENT_HOLD_ACKNOWLEDGE: { struct misdn_bchannel *holded_bc=malloc(sizeof(struct misdn_bchannel)); memcpy(holded_bc,bc,sizeof(struct misdn_bchannel)); holded_bc->holded=1; stack_holder_add(stack,holded_bc); if (stack->mode == NT_MODE) { empty_chan_in_stack(stack,bc->channel); empty_bc(bc); clean_up_bc(bc); } /** we set it up later at RETRIEVE_ACK again.**/ holded_bc->upset=0; holded_bc->active=0; cb_event( EVENT_NEW_BC, holded_bc, glob_mgr->user_data); } break; case EVENT_RELEASE: break; case EVENT_RELEASE_COMPLETE: empty_chan_in_stack(stack,bc->channel); empty_bc(bc); clean_up_bc(bc); break; case EVENT_CONNECT_ACKNOWLEDGE: if (misdn_cap_is_speech(bc->capability)) { if ( !bc->nodsp) manager_ph_control(bc, DTMF_TONE_START, 0); if (bc->ec_enable) manager_ec_enable(bc); if ( bc->txgain != 0 ) { cb_log(4, stack->port, "--> Changing txgain to %d\n", bc->txgain); manager_ph_control(bc, VOL_CHANGE_TX, bc->txgain); } if ( bc->rxgain != 0 ) { cb_log(4, stack->port, "--> Changing rxgain to %d\n", bc->rxgain); manager_ph_control(bc, VOL_CHANGE_RX, bc->rxgain); } } break; default: break; } /* Later we should think about sending bchannel data directly to misdn. */ msg = isdn_msg_build_event(msgs_g, bc, event, stack->mode==NT_MODE?1:0); msg_queue_tail(&stack->downqueue, msg); sem_post(&glob_mgr->new_msg); return 0; ERR: return -1; }int manager_isdn_handler(iframe_t *frm ,msg_t *msg){ if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM)) { printf("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n"); } if (handle_timers(msg)) return 0 ; if (handle_mgmt(msg)) return 0 ; if (handle_l2(msg)) return 0 ; /* Its important to handle l1 AFTER l2 */ if (handle_l1(msg)) return 0 ; if (handle_bchan(msg)) return 0 ; /** Handle L2/3 Signalling after bchans **/ if (handle_frm_nt(msg)) return 0 ; if (handle_frm(msg)) return 0 ; cb_log(0, frm->addr&IF_CONTRMASK, "Unhandled Message: prim %x len %d from addr %x, dinfo %x on port: %d\n",frm->prim, frm->len, frm->addr, frm->dinfo, frm->addr&IF_CONTRMASK); free_msg(msg); return 0;}int misdn_lib_get_port_info(int port){ msg_t *msg=alloc_msg(MAX_MSG_SIZE); iframe_t *frm; struct misdn_stack *stack=find_stack_by_port(port); if (!msg) { cb_log(0, port, "misgn_lib_get_port: alloc_msg failed!\n"); return -1; } frm=(iframe_t*)msg->data; if (!stack ) { cb_log(0, port, "There is no Stack on Port:%d\n",port); return -1; } /* activate bchannel */ frm->prim = CC_STATUS_ENQUIRY | REQUEST; frm->addr = stack->upper_id; frm->dinfo = 0; frm->len = 0; msg_queue_tail(&glob_mgr->activatequeue, msg); sem_post(&glob_mgr->new_msg); return 0; }int misdn_lib_port_restart(int port){ struct misdn_stack *stack=find_stack_by_port(port); cb_log(0, port, "Restarting Port:%d\n",port); if (stack) { cb_log(0, port, "Stack:%p\n",stack); clear_l3(stack); { msg_t *msg=alloc_msg(MAX_MSG_SIZE); iframe_t *frm; if (!msg) { cb_log(0, port, "port_restart: alloc_msg fialed\n"); return -1; } frm=(iframe_t*)msg->data; /* we must activate if we are deactivated */ /* activate bchannel */ frm->prim = DL_RELEASE | REQUEST; frm->addr = stack->upper_id ; frm->dinfo = 0; frm->len = 0; msg_queue_tail(&glob_mgr->activatequeue, msg); sem_post(&glob_mgr->new_msg); } return 0; stack_te_destroy(stack); { struct misdn_stack *tmpstack; struct misdn_stack *newstack=stack_te_init(stack->midev ,port, stack->ptp); if (stack == glob_mgr->stack_list) { struct misdn_stack *n=glob_mgr->stack_list->next; glob_mgr->stack_list = newstack ; glob_mgr->stack_list->next = n; } else { for (tmpstack=glob_mgr->stack_list; tmpstack->next; tmpstack=tmpstack->next) if (tmpstack->next == stack) break; if (!tmpstack->next) { cb_log(0, port, "Stack to restart not found\n"); return 0; } else { struct misdn_stack *n=tmpstack->next->next; tmpstack->next=newstack; newstack->next=n; } } { int i; for(i=0;i<newstack->b_num; i++) { int r; if ((r=init_bc(newstack, &newstack->bc[i], newstack->midev,port,i, "", 1))<0) { cb_log(0, port, "Got Err @ init_bc :%d\n",r); return 0; } } } free(stack); } } return 0;}sem_t handler_started; void manager_event_handler(void *arg){ sem_post(&handler_started); while (1) { struct misdn_stack *stack; msg_t *msg; /** wait for events **/ sem_wait(&glob_mgr->new_msg); for (msg=msg_dequeue(&glob_mgr->activatequeue); msg; msg=msg_dequeue(&glob_mgr->activatequeue) ) { iframe_t *frm = (iframe_t*) msg->data ; switch ( frm->prim) { case MGR_SETSTACK | REQUEST : break; default: mISDN_write(glob_mgr->midev, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC); free_msg(msg); } } for (stack=glob_mgr->stack_list; stack; stack=stack->next ) { while ( (msg=msg_dequeue(&stack->downqueue)) ) { if (stack->mode == NT_MODE ){ if (stack->nst.manager_l3(&stack->nst, msg)) cb_log(0, stack->port, "Error@ Sending Message in NT-Stack.\n"); } else { if (msg) { iframe_t *frm = (iframe_t *)msg->data; struct misdn_bchannel *bc = find_bc_by_l3id(stack, frm->dinfo); if (bc) send_msg(glob_mgr->midev, bc, msg); } } } } }}int misdn_lib_maxports_get() { /** BE AWARE WE HAVE NO CB_LOG HERE! **/ int i = mISDN_open(); int max=0; if (i<0) return -1; max = mISDN_get_stack_count(i); mISDN_close(i); return max;}int misdn_lib_init(char *portlist, struct misdn_lib_iface *iface, void *user_data){ struct misdn_lib *mgr=calloc(1, sizeof(struct misdn_lib)); char *tok, *tokb; char plist[1024]; int midev; int port_count=0; cb_log = iface->cb_log; cb_event = iface->cb_event; cb_clearl3_true = iface->cb_clearl3_true; glob_mgr = mgr; msg_init(); debug_init(0 , NULL, NULL, NULL); if (!portlist || (*portlist == 0) ) return 1; init_flip_bits(); { strncpy(plist,portlist, 1024); plist[1023] = 0; } memcpy(tone_425_flip,tone_425,TONE_425_SIZE); flip_buf_bits(tone_425_flip,TONE_425_SIZE); memcpy(tone_silence_flip,tone_SILENCE,TONE_SILENCE_SIZE); flip_buf_bits(tone_silence_flip,TONE_SILENCE_SIZE); midev=te_lib_init(); mgr->midev=midev; port_count=mISDN_get_stack_count(midev); msg_queue_init(&mgr->activatequeue); if (sem_init(&mgr->new_msg, 1, 0)<0) sem_init(&mgr->new_msg, 0, 0); for (tok=strtok_r(plist," ,",&tokb ); tok; tok=strtok_r(NULL," ,",&tokb)) { int port = atoi(tok); struct misdn_stack *stack; static int first=1; int ptp=0; if (strstr(tok, "ptp")) ptp=1; if (port > port_count) { cb_log(0, port, "Couldn't Initialize Port:%d since we have only %d ports\n",port, port_count); exit(1); } stack=stack_te_init(midev, port, ptp); if (!stack) { perror("init_stack"); exit(1); } if (stack && first) { mgr->stack_list=stack; first=0; { int i; for(i=0;i<stack->b_num; i++) { int r; if ((r=init_bc(stack, &stack->bc[i], stack->midev,port,i, "", 1))<0) { cb_log(0, port, "Got Err @ init_bc :%d\n",r); exit(1); } } } continue; } if (stack) { struct misdn_stack * help; for ( help=mgr->stack_list; help; help=help->next ) if (help->next == NULL) break; help->next=stack; { int i; for(i=0;i<stack->b_num; i++) { int r; if ((r=init_bc(sta
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?