X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=chan_lcr.c;h=0234e4ce7e1ef702662a1556a67bd5a43d60fdc5;hp=4abb766ebea25bd86c76bd18e809b9df01354391;hb=01c427aa46ffb006e60d112d5536ac76d9e968f0;hpb=1e8009963503f713ab8b3866090b340a70f5aa77 diff --git a/chan_lcr.c b/chan_lcr.c index 4abb766..0234e4c 100644 --- a/chan_lcr.c +++ b/chan_lcr.c @@ -27,6 +27,7 @@ From that point on, the ref is not valid, so no other message may be sent with that reference. */ +bchannel-handling muss noch #include #include @@ -42,12 +43,12 @@ with that reference. #include #include "extension.h" #include "message.h" -#include "admin.h" +#include "lcrsocket.h" #include "cause.h" #include "bchannel.h" #include "chan_lcr.h" -int sock; +int lcr_sock = -1; struct admin_list { struct admin_list *next; @@ -112,6 +113,28 @@ void free_call(struct chan_call *call) } } +unsigned short new_brige_id(void) +{ + struct chan_call *call; + unsigned short id = 1; + + /* search for lowest bridge id that is not in use and not 0 */ + while(id) + { + call = call_first; + while(call) + { + if (call->bridge_id == id) + break; + call = call->next; + } + if (!call) + break; + id++; + } + return(id); +} + /* * receive bchannel data @@ -195,6 +218,8 @@ int receive_message(int message_type, unsigned long ref, union parameter *param) { bchannel->ref = ref; call->bchannel_handle = param->bchannel.handle; +#warning hier muesen alle stati gesetzt werden falls sie vor dem b-kanal verfügbar waren + bchannel_join(call->bridge_id); } if (bchannel_create(bchannel)) bchannel_activate(bchannel, 1); @@ -208,6 +233,7 @@ int receive_message(int message_type, unsigned long ref, union parameter *param) case BCHANNEL_REMOVE: if (!(bchannel = find_bchannel_handle(param->bchannel.handle))) { + alle fprintf nach ast_log fprintf(stderr, "error: bchannel handle %x not assigned.\n", param->bchannel.handle); return(-1); } @@ -279,15 +305,57 @@ int receive_message(int message_type, unsigned long ref, union parameter *param) /* handle messages */ switch(message_type) { -#warning we must see if ref is a reply or a request, do we?? + case MESSAGE_SETUP: +todo + break; + + case MESSAGE_OVERLAP: +todo + break; + + case MESSAGE_PROCEEDING: +todo + break; + + case MESSAGE_ALERTING: +todo + break; + + case MESSAGE_CONNECT: +todo + break; + + case MESSAGE_DISCONNECT: +todo + break; + case MESSAGE_RELEASE: -#warning release call +todo free_call(call); return(0); - case MESSAGE_SETUP: -#warning handle incoming setup, send to asterisk + case MESSAGE_INFORMATION: +todo + break; + + case MESSAGE_FACILITY: +todo + break; + + case MESSAGE_PATTERN: +todo + break; + + case MESSAGE_NOPATTERN: +todo + break; + + case MESSAGE_AUDIOPATH: +todo break; + + default: +unhandled } return(0); } @@ -370,23 +438,24 @@ int handle_socket(void) } /* - * main function + * open and close socket */ -int main(int argc, char *argv[]) +int open_socket(void) { + int ret; + int sock; char *socket_name = SOCKET_NAME; int conn; struct sockaddr_un sock_address; int ret; unsigned long on = 1; union parameter param; - int work; /* open socket */ if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { - fprintf(stderr, "Failed to create socket.\n"); - exit(EXIT_FAILURE); + ast_log(LOG_ERROR, "Failed to create socket.\n"); + return(sock); } /* set socket address and name */ @@ -398,16 +467,16 @@ int main(int argc, char *argv[]) if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0) { close(sock); - fprintf(stderr, "Failed to connect to socket \"%s\".\nIs LCR running?\n", sock_address.sun_path); - exit(EXIT_FAILURE); + ast_log(LOG_ERROR, "Failed to connect to socket \"%s\". Is LCR running?\n", sock_address.sun_path); + return(conn); } /* set non-blocking io */ - if (ioctl(sock, FIONBIO, (unsigned char *)(&on)) < 0) + if ((ret = ioctl(sock, FIONBIO, (unsigned char *)(&on))) < 0) { close(sock); - fprintf(stderr, "Failed to set socket into non-blocking IO.\n"); - exit(EXIT_FAILURE); + ast_log(LOG_ERROR, "Failed to set socket into non-blocking IO.\n"); + return(ret); } /* enque hello message */ @@ -415,10 +484,21 @@ int main(int argc, char *argv[]) strcpy(param.hello.application, "asterisk"); send_message(MESSAGE_HELLO, 0, ¶m); - /* bchannel */ - if (!bchannel_initialize()) - goto bchannel_failed; - + return(sock); +} + +void close_socket(int sock) +{ + /* close socket */ + if (socket >= 0) + close(sock); +} + + +void lcr_thread(void) +{ + int work; + while(42) { work = 0; @@ -438,21 +518,285 @@ int main(int argc, char *argv[]) if (!work) usleep(30000); } +} - bchannel_deinitialize(); - bchannel_failed: +/* call from asterisk (new instance) */ +static int lcr_call(struct ast_channel *ast, char *dest, int timeout) +{ + int port=0; + int r; + struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast); + struct misdn_bchannel *newbc; + char *opts=NULL, *ext; + char dest_cp[256]; - /* close socket */ - close(sock); - /* now we say good bye */ - if (ret) { - printf("%s\n", ret); - exit(EXIT_FAILURE); + strncpy(dest_cp,dest,sizeof(dest_cp)-1); + dest_cp[sizeof(dest_cp)]=0; + + ext=dest_cp; + strsep(&ext,"/"); + if (ext) { + opts=ext; + strsep(&opts,"/"); + } else { + ast_log(LOG_WARNING, "Malformed dialstring\n"); + return -1; + } + } + + if (!ast) { + ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n"); + return -1; + } + + if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest ) { + ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name); + ast->hangupcause=41; + ast_setstate(ast, AST_STATE_DOWN); + return -1; + } + + if (!ch) { + ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name); + ast->hangupcause=41; + ast_setstate(ast, AST_STATE_DOWN); + return -1; + } + + newbc=ch->bc; + + if (!newbc) { + ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name); + ast->hangupcause=41; + ast_setstate(ast, AST_STATE_DOWN); + return -1; } + + port=newbc->port; + + + chan_misdn_log(1, port, "* CALL: %s\n",dest); + + chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context); + + chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten); + if (ast->exten) { + int l = sizeof(newbc->dad); + strncpy(ast->exten,ext,sizeof(ast->exten)); + + strncpy(newbc->dad,ext,l); + + newbc->dad[l-1] = 0; + } + newbc->rad[0]=0; + chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast)); + if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) { + + if (AST_CID_P(ast)) { + int l = sizeof(newbc->oad); + strncpy(newbc->oad,AST_CID_P(ast), l); + newbc->oad[l-1] = 0; + } + } + + { + struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast); + if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;} + + newbc->capability=ast->transfercapability; + pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability)); + if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) { + chan_misdn_log(2, port, " --> * Call with flag Digital\n"); + } + + + /* update screening and presentation */ + update_config(ch,ORG_AST); + + /* fill in some ies from channel vary*/ + import_ch(ast, newbc, ch); + + /* Finally The Options Override Everything */ + if (opts) + misdn_set_opt_exec(ast,opts); + else + chan_misdn_log(2,port,"NO OPTS GIVEN\n"); + + /*check for bridging*/ + int bridging; + misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int)); + if (bridging && ch->other_ch) { + chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n"); + *ch->bc->pipeline=0; + *ch->other_ch->bc->pipeline=0; + } + + r=misdn_lib_send_event( newbc, EVENT_SETUP ); + + /** we should have l3id after sending setup **/ + ch->l3id=newbc->l3_id; + } + + if ( r == -ENOCHAN ) { + chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n"); + chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1); + ast->hangupcause=34; + ast_setstate(ast, AST_STATE_DOWN); + return -1; + } + + chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1); + + ast_setstate(ast, AST_STATE_DIALING); + ast->hangupcause=16; + +wenn pattern available soll gestoppt werden, sonst nicht: + if (newbc->nt) stop_bc_tones(ch); + + ch->state=MISDN_CALLING; + + return 0; } +static struct ast_channel_tech misdn_tech = { + .type="lcr", + .description="Channel driver for connecting to Linux-Call-Router", + .capabilities= je nach option?AST_FORMAT_ALAW:AST_FORMAT_ULAW , + .requester=lcr_request, + .send_digit=lcr_digit, + .call=lcr_call, + .bridge=lcr_bridge, + .hangup=lcr_hangup, + .answer=lcr_answer, + .read=lcr_read, + .write=lcr_write, + .indicate=lcr_indication, + .fixup=lcr_fixup, + .send_text=lcr_send_text, + .properties=0 +}; + +/* + * module loading and destruction + */ +int load_module(void) +{ +// ast_mutex_init(&release_lock); + +// lcr_cfg_update_ptp(); + + if (!(lcr_sock = open_socket())) { + ast_log(LOG_ERROR, "Unable to connect %s\n", misdn_type); + lcr_sock = -1; + /* continue with closed socket */ + } + + if (!bchannel_initialize()) { + ast_log(LOG_ERROR, "Unable to open mISDN device\n"); + unload_module(); + return -1; + } + mISDN_created = 1; + + if (ast_channel_register(&lcr_tech)) { + ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type); + unload_module(); + return -1; + } + + ast_cli_register(&cli_show_lcr); + ast_cli_register(&cli_show_calls); + + ast_cli_register(&cli_reload_routing); + ast_cli_register(&cli_reload_interfaces); + ast_cli_register(&cli_port_block); + ast_cli_register(&cli_port_unblock); + + ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt", + "misdn_set_opt(::..):\n" + "Sets mISDN opts. and optargs\n" + "\n" + "The available options are:\n" + " d - Send display text on called phone, text is the optparam\n" + " n - don't detect dtmf tones on called channel\n" + " h - make digital outgoing call\n" + " c - make crypted outgoing call, param is keyindex\n" + " e - perform echo cancelation on this channel,\n" + " takes taps as arguments (32,64,128,256)\n" + " s - send Non Inband DTMF as inband\n" + " vr - rxgain control\n" + " vt - txgain control\n" + ); + + + lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE); + + chan_lcr_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n"); + + return 0; +} + +int unload_module(void) +{ + /* First, take us out of the channel loop */ + ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n"); + + misdn_tasks_destroy(); + + if (!g_config_initialized) return 0; + + ast_cli_unregister(&cli_show_lcr); + ast_cli_unregister(&cli_show_calls); + ast_cli_unregister(&cli_reload_routing); + ast_cli_unregister(&cli_reload_interfaces); + ast_cli_unregister(&cli_port_block); + ast_cli_unregister(&cli_port_unblock); + ast_unregister_application("misdn_set_opt"); + + ast_channel_unregister(&lcr_tech); + + if (mISDN_created) { + bchannel_deinitialize(); + mISDN_created = 0; + } + + if (lcr_sock >= 0) { + close(lcr_sock); + lcr_sock = -1; + } + + was ist mit dem mutex + + return 0; +} + +int reload(void) +{ + reload_config(); + + return 0; +} + +int usecount(void) +{ + int res; + ast_mutex_lock(&usecnt_lock); + res = usecnt; + ast_mutex_unlock(&usecnt_lock); + return res; +} + +char *description(void) +{ + return desc; +} + +char *key(void) +{ + return ASTERISK_GPL_KEY; +}