X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=chan_lcr.c;h=52c2a3121a13762fb30ee200ff7d2463258e5bed;hp=dc7ebed353d15d52f7df97bef75a5374c8f47d08;hb=b1ab2b9ac1cfc15d2a8f5850145dd69043cc3ef7;hpb=a114e74299f4708d96b490be055ab8939b9e7610 diff --git a/chan_lcr.c b/chan_lcr.c index dc7ebed..52c2a31 100644 --- a/chan_lcr.c +++ b/chan_lcr.c @@ -295,6 +295,7 @@ struct chan_call *alloc_call(void) free_call(*callp); return(NULL); } + fcntl((*callp)->pipe[0], F_SETFL, O_NONBLOCK); CDEBUG(*callp, NULL, "Call instance allocated.\n"); return(*callp); } @@ -456,12 +457,12 @@ void apply_opt(struct chan_call *call, char *data) break; case 't': if (opt[1] != '\0') { - CERROR(call, call->ast, "Option 't' (transparent) expects no parameter.\n", opt); + CERROR(call, call->ast, "Option 't' (no_dsp) expects no parameter.\n", opt); break; } - CDEBUG(call, call->ast, "Option 't' (transparent).\n"); - if (!call->transparent) { - call->transparent = 1; + CDEBUG(call, call->ast, "Option 't' (no dsp).\n"); + if (!call->nodsp) { + call->nodsp = 1; newmode = 1; } break; @@ -476,7 +477,7 @@ void apply_opt(struct chan_call *call, char *data) bchannel_pipeline(call->bchannel, call->pipeline); break; case 'r': - if (opt[1] == '\0') { + if (opt[1] != '\0') { CERROR(call, call->ast, "Option 'r' (re-buffer 160 bytes) expects no parameter.\n", opt); break; } @@ -523,7 +524,7 @@ todo /* re-open, if bchannel is created */ if (call->bchannel && call->bchannel->b_sock > -1) { bchannel_destroy(call->bchannel); - if (bchannel_create(call->bchannel, ((call->transparent)?1:0) + ((call->hdlc)?2:0))) + if (bchannel_create(call->bchannel, ((call->nodsp)?1:0) + ((call->hdlc)?2:0))) bchannel_activate(call->bchannel, 1); } } @@ -591,8 +592,13 @@ static void send_setup_to_lcr(struct chan_call *call) newparam.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN; } newparam.setup.capainfo.bearer_capa = ast->transfercapability; - newparam.setup.capainfo.bearer_info1 = (options.law=='a')?3:2; newparam.setup.capainfo.bearer_mode = INFO_BMODE_CIRCUIT; + if (call->hdlc) + newparam.setup.capainfo.source_mode = B_MODE_HDLC; + else { + newparam.setup.capainfo.source_mode = B_MODE_TRANSPARENT; + newparam.setup.capainfo.bearer_info1 = (options.law=='a')?3:2; + } newparam.setup.capainfo.hlc = INFO_HLC_NONE; newparam.setup.capainfo.exthlc = INFO_HLC_NONE; send_message(MESSAGE_SETUP, call->ref, &newparam); @@ -740,7 +746,11 @@ static void lcr_start_pbx(struct chan_call *call, struct ast_channel *ast, int c goto release; } call->pbx_started = 1; - return; +// if (call->state == CHAN_LCR_STATE_IN_DIALING) + ast_setstate(ast, AST_STATE_RINGING); +// else +// ast_setstate(ast, AST_STATE_RINGING); +// return; } /* @@ -809,9 +819,7 @@ static void lcr_in_setup(struct chan_call *call, int message_type, union paramet } ast->transfercapability = param->setup.capainfo.bearer_capa; /* enable hdlc if transcap is data */ - if (ast->transfercapability == INFO_BC_DATAUNRESTRICTED - || ast->transfercapability == INFO_BC_DATARESTRICTED - || ast->transfercapability == INFO_BC_VIDEO) + if (param->setup.capainfo.source_mode == B_MODE_HDLC) call->hdlc = 1; strncpy(call->oad, numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international), sizeof(call->oad)-1); @@ -994,6 +1002,13 @@ static void lcr_in_information(struct chan_call *call, int message_type, union p return; } + /* change dailing state after setup */ + if (call->state == CHAN_LCR_STATE_IN_SETUP) { + CDEBUG(call, call->ast, "Changing from SETUP to DIALING state.\n"); + call->state = CHAN_LCR_STATE_IN_DIALING; +// ast_setstate(ast, AST_STATE_DIALING); + } + /* queue digits */ if (call->state == CHAN_LCR_STATE_IN_DIALING && param->information.id[0]) strncat(call->queue_string, param->information.id, sizeof(call->queue_string)-1); @@ -1127,7 +1142,7 @@ int receive_message(int message_type, unsigned int ref, union parameter *param) bchannel_join(bchannel, call->bridge_id); } /* create only, if call exists, othewhise it bchannel is freed below... */ - if (bchannel_create(bchannel, ((call->transparent)?1:0) + ((call->hdlc)?2:0))) + if (bchannel_create(bchannel, ((call->nodsp)?1:0) + ((call->hdlc)?2:0))) bchannel_activate(bchannel, 1); } /* acknowledge */ @@ -1413,7 +1428,6 @@ int handle_socket(void) int open_socket(void) { int ret; - char *socket_name = SOCKET_NAME; int conn; struct sockaddr_un sock_address; unsigned int on = 1; @@ -1429,7 +1443,7 @@ int open_socket(void) /* set socket address and name */ memset(&sock_address, 0, sizeof(sock_address)); sock_address.sun_family = PF_UNIX; - strcpy(sock_address.sun_path, socket_name); + sprintf(sock_address.sun_path, SOCKET_NAME, options.lock); /* connect socket */ if ((conn = connect(lcr_sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0) @@ -1518,10 +1532,11 @@ static int queue_send(void) CDEBUG(call, ast, "Sending queued digit '%c' to Asterisk.\n", *p); /* send digit to asterisk */ memset(&fr, 0, sizeof(fr)); - fr.frametype = AST_FRAME_DTMF; + fr.frametype = AST_FRAME_DTMF_BEGIN; fr.subclass = *p; fr.delivery = ast_tv(0, 0); - fr.len = 100; + ast_queue_frame(ast, &fr); + fr.frametype = AST_FRAME_DTMF_END; ast_queue_frame(ast, &fr); break; default: @@ -1821,17 +1836,19 @@ static int lcr_answer(struct ast_channel *ast) return -1; } - CDEBUG(call, ast, "Received answer from Asterisk.\n"); + CDEBUG(call, ast, "Received answer from Asterisk (maybe during lcr_bridge).\n"); /* copy connectinfo, if bridged */ if (call->bridge_call) memcpy(&call->connectinfo, &call->bridge_call->connectinfo, sizeof(struct connect_info)); /* send connect message to lcr */ - memset(&newparam, 0, sizeof(union parameter)); - memcpy(&newparam.connectinfo, &call->connectinfo, sizeof(struct connect_info)); - send_message(MESSAGE_CONNECT, call->ref, &newparam); + if (call->state != CHAN_LCR_STATE_CONNECT) { + memset(&newparam, 0, sizeof(union parameter)); + memcpy(&newparam.connectinfo, &call->connectinfo, sizeof(struct connect_info)); + send_message(MESSAGE_CONNECT, call->ref, &newparam); + call->state = CHAN_LCR_STATE_CONNECT; + } /* change state */ - call->state = CHAN_LCR_STATE_CONNECT; /* request bchannel */ if (!call->bchannel) { CDEBUG(call, ast, "Requesting B-channel.\n"); @@ -1882,7 +1899,7 @@ static int lcr_hangup(struct ast_channel *ast) if (ast->hangupcause > 0) send_release_and_import(call, ast->hangupcause, LOCATION_PRIVATE_LOCAL); else - send_release_and_import(call, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL); + send_release_and_import(call, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL); /* remove call */ free_call(call); if (!pthread_equal(tid, chan_tid)) @@ -1933,8 +1950,7 @@ static int lcr_write(struct ast_channel *ast, struct ast_frame *f) static struct ast_frame *lcr_read(struct ast_channel *ast) { struct chan_call *call; - int i, len; - unsigned char *p; + int len; ast_mutex_lock(&chan_lock); call = ast->tech_pvt; @@ -1943,20 +1959,23 @@ static struct ast_frame *lcr_read(struct ast_channel *ast) return NULL; } if (call->pipe[0] > -1) { - len = read(call->pipe[0], call->read_buff, sizeof(call->read_buff)); + if (call->rebuffer && !call->hdlc) { + len = read(call->pipe[0], call->read_buff, 160); + } else { + len = read(call->pipe[0], call->read_buff, sizeof(call->read_buff)); + } + if (len < 0 && errno == EAGAIN) { + ast_mutex_unlock(&chan_lock); + return &ast_null_frame; + } if (len <= 0) { close(call->pipe[0]); call->pipe[0] = -1; + ast_mutex_unlock(&chan_lock); return NULL; } } - p = call->read_buff; - for (i = 0; i < len; i++) { - *p = flip_bits[*p]; - p++; - } - call->read_fr.frametype = AST_FRAME_VOICE; call->read_fr.subclass = ast->nativeformats; call->read_fr.datalen = len; @@ -2076,21 +2095,25 @@ static int lcr_indicate(struct ast_channel *ast, int cond, const void *data, siz /* * fixup asterisk */ -static int lcr_fixup(struct ast_channel *oldast, struct ast_channel *newast) +static int lcr_fixup(struct ast_channel *oldast, struct ast_channel *ast) { struct chan_call *call; + if (!ast) { + return -1; + } + ast_mutex_lock(&chan_lock); - call = oldast->tech_pvt; + call = ast->tech_pvt; if (!call) { - CERROR(NULL, oldast, "Received fixup from Asterisk, but no call instance exists.\n"); + CERROR(NULL, ast, "Received fixup from Asterisk, but no call instance exists.\n"); ast_mutex_unlock(&chan_lock); return -1; } - CDEBUG(call, oldast, "Received fixup from Asterisk.\n"); - call->ast = newast; - ast_mutex_lock(&chan_lock); + CDEBUG(call, ast, "Received fixup from Asterisk.\n"); + call->ast = ast; + ast_mutex_unlock(&chan_lock); return 0; } @@ -2137,26 +2160,54 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1, carr[0] = ast1; carr[1] = ast2; - + /* join via dsp (if the channels are currently open) */ ast_mutex_lock(&chan_lock); - bridge_id = new_bridge_id(); call1 = ast1->tech_pvt; call2 = ast2->tech_pvt; - if (call1 && call2) - { + if (!call1 || !call2) { + CDEBUG(NULL, NULL, "Bridge, but we don't have two call instances, exitting.\n"); + ast_mutex_unlock(&chan_lock); + return AST_BRIDGE_COMPLETE; + } + + /* join, if both call instances uses dsp */ + if (!call1->nodsp && !call2->nodsp) { + CDEBUG(NULL, NULL, "Both calls use DSP, briding via DSP.\n"); + + /* get bridge id and join */ + bridge_id = new_bridge_id(); + call1->bridge_id = bridge_id; if (call1->bchannel) bchannel_join(call1->bchannel, bridge_id); - call1->bridge_call = call2; - } - if (call2) - { + call2->bridge_id = bridge_id; if (call2->bchannel) bchannel_join(call2->bchannel, bridge_id); - call2->bridge_call = call1; + } else + if (call1->nodsp && call2->nodsp) + CDEBUG(NULL, NULL, "Both calls use no DSP, briding in channel driver.\n"); + else + CDEBUG(NULL, NULL, "One call uses no DSP, briding in channel driver.\n"); + call1->bridge_call = call2; + call2->bridge_call = call1; + + if (call1->state == CHAN_LCR_STATE_IN_SETUP + || call1->state == CHAN_LCR_STATE_IN_DIALING + || call1->state == CHAN_LCR_STATE_IN_PROCEEDING + || call1->state == CHAN_LCR_STATE_IN_ALERTING) { + CDEBUG(call1, ast1, "Bridge established before lcr_answer, so we call it ourself: Calling lcr_answer...\n"); + lcr_answer(ast1); + } + if (call2->state == CHAN_LCR_STATE_IN_SETUP + || call2->state == CHAN_LCR_STATE_IN_DIALING + || call2->state == CHAN_LCR_STATE_IN_PROCEEDING + || call2->state == CHAN_LCR_STATE_IN_ALERTING) { + CDEBUG(call2, ast2, "Bridge established before lcr_answer, so we call it ourself: Calling lcr_answer...\n"); + lcr_answer(ast2); } + ast_mutex_unlock(&chan_lock); while(1) { @@ -2203,24 +2254,24 @@ enum ast_bridge_result lcr_bridge(struct ast_channel *ast1, ast_mutex_lock(&chan_lock); call1 = ast1->tech_pvt; call2 = ast2->tech_pvt; - if (call1) + if (call1 && call1->bridge_id) { call1->bridge_id = 0; if (call1->bchannel) bchannel_join(call1->bchannel, 0); if (call1->bridge_call) call1->bridge_call->bridge_call = NULL; - call1->bridge_call = NULL; } - if (call2) + if (call2 && call1->bridge_id) { call2->bridge_id = 0; if (call2->bchannel) bchannel_join(call2->bchannel, 0); if (call2->bridge_call) call2->bridge_call->bridge_call = NULL; - call2->bridge_call = NULL; } + call1->bridge_call = NULL; + call2->bridge_call = NULL; ast_mutex_unlock(&chan_lock); return AST_BRIDGE_COMPLETE; @@ -2404,7 +2455,7 @@ int load_module(void) " d - Send display text on called phone, text is the optarg.\n" " n - Don't detect dtmf tones on called channel.\n" " h - Force data call (HDLC).\n" - " t - Disable all audio features (required for fax application).\n" + " t - Disable mISDN_dsp features (required for fax application).\n" " c - Make crypted outgoing call, optarg is keyindex.\n" " e - Perform echo cancelation on this channel.\n" " Takes mISDN pipeline option as optarg.\n"