From: Super User Date: Mon, 28 Apr 2008 17:34:33 +0000 (+0200) Subject: Merge branch 'master' of ssh://jolly@www.mISDN.org/var/git/lcr X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=commitdiff_plain;h=f94f30b0c56ae49c436ee588cd0696cc1b9db9aa;hp=-c Merge branch 'master' of ssh://jolly@mISDN.org/var/git/lcr Conflicts: chan_lcr.c --- f94f30b0c56ae49c436ee588cd0696cc1b9db9aa diff --combined chan_lcr.c index 382025b,efb092a..3e62d1a --- a/chan_lcr.c +++ b/chan_lcr.c @@@ -11,80 -11,23 +11,80 @@@ /* -How does it work: +Registering to LCR: -To connect, open a socket and send a MESSAGE_HELLO to admin socket with +To connect, open an LCR socket and send a MESSAGE_HELLO to socket with the application name. This name is unique an can be used for routing calls. +Now the channel driver is linked to LCR and can receive and make calls. -To make a call, send a MESSAGE_NEWREF and a new reference is received. -When receiving a call, a new reference is received. -The reference is received with MESSAGE_NEWREF. -Make a MESSAGE_SETUP or receive a MESSAGE_SETUP with the reference. +Call is initiated by LCR: -To release call and reference, send or receive MESSAGE_RELEASE. -From that point on, the ref is not valid, so no other message may be sent -with that reference. +If a call is received from LCR, a MESSAGE_NEWREF is received first. +A new chan_call instance is created. The call reference (ref) is given by +MESSAGE_NEWREF. The state is CHAN_LCR_STATE_IN_PREPARE. +After receiving MESSAGE_SETUP from LCR, the ast_channel instance is created +using ast_channel_alloc(1). The setup information is given to asterisk. +The new Asterisk instance pointer (ast) is stored to chan_call structure. +The state changes to CHAN_LCR_STATE_IN_SETUP. + + +Call is initiated by Asterisk: + +If a call is reveiced from Asterisk, a new chan_call instance is created. +The new Asterisk instance pointer (ast) is stored to chan_call structure. +A MESSASGE_NEWREF is sent to LCR requesting a new call reference (ref). +The current call ref is set to 0, the state is CHAN_LCR_STATE_OUT_PREPARE. +Further dialing information is queued. +After the new callref is received by special MESSAGE_NEWREF reply, new ref +is stored in the chan_call structure. +The setup information is sent to LCR using MESSAGE_SETUP. +The state changes to CHAN_LCR_STATE_OUT_SETUP. + + +Call is in process: + +During call process, messages are received and sent. +The state changes accordingly. +Any message is allowed to be sent to LCR at any time except MESSAGE_RELEASE. +If a MESSAGE_OVERLAP is received, further dialing is required. +Queued dialing information, if any, is sent to LCR using MESSAGE_DIALING. +In this case, the state changes to CHAN_LCR_STATE_OUT_DIALING. + + +Call is released by LCR: + +A MESSAGE_RELEASE is received with the call reference (ref) to be released. +The current ref is set to 0, to indicate released reference. +The state changes to CHAN_LCR_STATE_RELEASE. +ast_queue_hangup() is called, if asterisk instance (ast) exists, if not, +the chan_call instance is destroyed. +After lcr_hangup() is called-back by Asterisk, the chan_call instance +is destroyed, because the current ref is set to 0 and the state equals +CHAN_LCR_STATE_RELEASE. +If the ref is 0 and the state is not CHAN_LCR_STATE_RELEASE, see the proceedure +"Call is released by Asterisk". + + +Call is released by Asterisk: + +lcr_hangup() is called-back by Asterisk. If the call reference (ref) is set, +a MESSAGE_RELEASE is sent to LCR and the chan_call instance is destroyed. +If the ref is 0 and the state is not CHAN_LCR_STATE_RELEASE, the new state is +set to CHAN_LCR_STATE_RELEASE. +Later, if the MESSAGE_NEWREF reply is received, a MESSAGE_RELEASE is sent to +LCR and the chan_call instance is destroyed. +If the ref is 0 and the state is CHAN_LCR_STATE_RELEASE, see the proceedure +"Call is released by LCR". */ +locking asterisk process and handler +reconnect after socket closed, release all calls. +debug of call handling +denke an alle info-elements in jeder message (from asterisk & from lcr) + + #include #include #include @@@ -130,11 -73,11 +130,13 @@@ #include #include +CHAN_LCR_STATE // state description structure + int lcr_debug=1; int mISDN_created=1; + char lcr_type[]="LCR"; + int lcr_sock = -1; @@@ -182,8 -125,6 +184,8 @@@ struct chan_call *alloc_call(void callp = &((*callp)->next); *callp = (struct chan_call *)malloc(sizeof(struct chan_call)); + if (*callp) + memset(*callp, 0, sizeof(struct chan_call)); return(*callp); } @@@ -258,145 -199,6 +260,145 @@@ int send_message(int message_type, unsi } /* + * incoming setup from LCR + */ +static void lcr_in_setup(struct chan_call *call, int message_type, union parameter *param) +{ + struct ast_channel *ast; + union parameter newparam; + + /* create asterisk channel instrance */ + ast = ast_channel_alloc(1); + if (!ast) + { + /* release */ + memset(&newparam, 0, sizeof(union parameter)); + newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL; + newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + send_message(MESSAGE_RELEASE, call->ref, &newparam); + /* remove call */ + free_call(call); + return; + } + /* set ast pointer */ + call->ast = ast; + + /* fill setup information */ +#warning todo: setup-info reinschreiben + + /* send setup to asterisk */ +#warning todo: setup bei der asterisk triggern + + /* change state */ + call->state = CHAN_LCR_STATE_IN_SETUP; +} + +/* + * incoming setup acknowledge from LCR + */ +static void lcr_in_overlap(struct chan_call *call, int message_type, union parameter *param) +{ + /* send pending digits in dialque */ + if (call->dialque) + send_dialing_to_lcr(call); + /* change to overlap state */ + call->state = CHAN_LCR_STATE_OUT_DIALING; +} + +/* + * incoming proceeding from LCR + */ +static void lcr_in_proceeding(struct chan_call *call, int message_type, union parameter *param) +{ + /* change state */ + call->state = CHAN_LCR_STATE_OUT_PROCEEDING; + /* send event to asterisk */ + ast_queue_... todo +} + +/* + * incoming alerting from LCR + */ +static void lcr_in_alerting(struct chan_call *call, int message_type, union parameter *param) +{ + /* change state */ + call->state = CHAN_LCR_STATE_OUT_ALERTING; + /* send event to asterisk */ + ast_queue_... todo +} + +/* + * incoming connect from LCR + */ +static void lcr_in_connect(struct chan_call *call, int message_type, union parameter *param) +{ + /* change state */ + call->state = CHAN_LCR_STATE_CONNECT; + /* copy connectinfo */ + todo + /* send event to asterisk */ + ast_queue_... todo +} + +/* + * incoming disconnect from LCR + */ +static void lcr_in_disconnect(struct chan_call *call, int message_type, union parameter *param) +{ + /* change state */ + call->state = CHAN_LCR_STATE_IN_DISCONNECT; + /* copy disconnect info */ + todo + /* send event to asterisk */ + ast_queue_... todo +} + +/* + * incoming setup acknowledge from LCR + */ +static void lcr_in_release(struct chan_call *call, int message_type, union parameter *param) +{ + /* release ref */ + call->ref = NULL; + /* change to release state */ + call->state = CHAN_LCR_STATE_RELEASE; + /* copy release info */ + todo + /* if we have an asterisk instance, send hangup, else we are done */ + if (call->ast) + { + ast_queue_hangup(call->ast); + } else + { + free_call(call); + } + +} + +/* + * incoming information from LCR + */ +static void lcr_in_information(struct chan_call *call, int message_type, union parameter *param) +{ + /* copy digits */ + todo and write them, maybe queue them for asterisk + /* send event to asterisk */ + ast_queue_... todo +} + +/* + * incoming information from LCR + */ +static void lcr_in_facility(struct chan_call *call, int message_type, union parameter *param) +{ + /* copy progress info */ + todo and write them, maybe queue them for asterisk + /* send event to asterisk */ + ast_queue_... todo + or maybe use bride info to forward facility. +} + +/* * message received from LCR */ int receive_message(int message_type, unsigned long ref, union parameter *param) @@@ -498,13 -300,8 +500,13 @@@ fprintf(stderr, "illegal new ref %d received\n", ref); return(-1); } + /* allocate new call instance */ call = alloc_call(); + /* new state */ + call->state = CHAN_LCR_STATE_IN_PREPARE; + /* set ref */ call->ref = ref; + /* wait for setup (or release from asterisk) */ } else { /* new ref, as requested from this remote application */ @@@ -517,22 -314,8 +519,22 @@@ send_message(MESSAGE_RELEASE, ref, &newparam); return(0); } + /* store new ref */ call->ref = ref; -#warning process call (send setup, if pending) + /* send pending setup info */ + if (call->state == CHAN_LCR_STATE_OUT_PREPARE) + send_setup_to_lcr(call); + /* release if asterisk has signed off */ + else if (call->state == CHAN_LCR_STATE_RELEASE) + { + /* send release */ + newparam.disconnectinfo.cause = todo + newparam.disconnectinfo.location = todo + send_message(MESSAGE_RELEASE, ref, &newparam); + /* free call */ + free_call(call); + return(0); + } } return(0); } @@@ -554,39 -337,40 +556,39 @@@ switch(message_type) { case MESSAGE_SETUP: -#warning todo + lcr_in_setup(call, message_type, param); break; case MESSAGE_OVERLAP: -#warning todo + lcr_in_overlap(call, message_type, param); break; case MESSAGE_PROCEEDING: -#warning todo + lcr_in_proceeding(call, message_type, param); break; case MESSAGE_ALERTING: -#warning todo + lcr_in_alerting(call, message_type, param); break; case MESSAGE_CONNECT: -#warning todo + lcr_in_connect(call, message_type, param); break; case MESSAGE_DISCONNECT: -#warning todo + lcr_in_disconnect(call, message_type, param); break; case MESSAGE_RELEASE: -#warning todo - free_call(call); - return(0); + lcr_in_release(call, message_type, param); + break; case MESSAGE_INFORMATION: -#warning todo + lcr_in_disconnect(call, message_type, param); break; case MESSAGE_FACILITY: -#warning todo + lcr_in_disconnect(call, message_type, param); break; case MESSAGE_PATTERN: @@@ -744,8 -528,6 +746,8 @@@ void close_socket(int sock } +hander thread muss noch +socket muss per timer fuer das öffnen checken void lcr_thread(void) { int work; @@@ -771,171 -553,90 +773,219 @@@ } } - -static struct ast_channel *lcr_ast_new(struct chan_call *call, char *exten, char *callerid, int ref); - -static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause) +/* + * send setup info to LCR + * this function is called, when asterisk call is received and ref is received + */ +static void send_setup_to_lcr(struct chan_call *call) { - struct ast_channel *ast=NULL; + if (!ast || !call->ref) + return; - char buf[128]; - char *port_str, *ext, *p; - int port; - - ast_copy_string(buf, data, sizeof(buf)-1); - p=buf; - port_str=strsep(&p, "/"); - ext=strsep(&p, "/"); - ast_verbose("portstr:%s ext:%s\n",port_str, ext); + /* send setup message to LCR */ + memset(&newparam, 0, sizeof(union parameter)); + newparam.setup.xxxxxx = + send_message(MESSAGE_SETUP, call->ref, &newparam); + /* change to outgoing setup state */ + call->state = CHAN_LCR_STATE_OUT_SETUP; +} - sprintf(buf,"%s/%s",lcr_type,(char*)data); ++#if 0 ++CHRISTIAN: das war ein konflikt beim pullen ++siehe anderes lcr_request(); ++bedenke: das ast_log muss noch üeberall eingepflegt werden + ++static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause) ++{ + struct chan_call *call=alloc_call(); + + if (call) { + #warning hier muss jetzt wohl eine Ref angefordert werden! + ast=lcr_ast_new(call, ext, NULL, 0 ); + + if (ast) { + call->ast=ast; + } else { + ast_log(LOG_WARNING, "Could not create new Asterisk Channel\n"); + free_call(call); + } + } else { + ast_log(LOG_WARNING, "Could not create new Lcr Call Handle\n"); + } + + return ast; + } + ++ struct ast_channel *ast=NULL; ++ ++ char buf[128]; ++ char *port_str, *ext, *p; ++ int port; ++ ++ ast_copy_string(buf, data, sizeof(buf)-1); ++ p=buf; ++ port_str=strsep(&p, "/"); ++ ext=strsep(&p, "/"); ++ ast_verbose("portstr:%s ext:%s\n",port_str, ext); ++ ++ sprintf(buf,"%s/%s",lcr_type,(char*)data); ++#endif ++ +/* + * send dialing info to LCR + * this function is called, when setup acknowledge is received and dialing + * info is available. + */ +static void send_dialing_to_lcr(struct chan_call *call) +{ + if (!ast || !call->ref || !call->dialque) + return; + + /* send setup message to LCR */ + memset(&newparam, 0, sizeof(union parameter)); + strncpy(newparam.dialinginfo.id, call->dialque, sizeof(newparam.dialinginfo.id)-1); + call->dialque[0] = '\0'; + send_message(MESSAGE_INFORMATION, call->ref, &newparam); +} + +/* + * new asterisk instance + */ +static struct ast_channel *lcr_request(const char *type, int format, void *data, int *cause) +{ + /* create call instance */ + call = alloc_call(); + if (!call) + { + /* failed to create instance */ + return NULL; + } + /* create asterisk channel instrance */ + ast = ast_channel_alloc(1); + if (!ast) + { + free_call(call); + /* failed to create instance */ + return NULL; + } + /* link together */ + ast->tech_pvt = call; + call->ast = ast; + /* send MESSAGE_NEWREF */ + memset(&newparam, 0, sizeof(union parameter)); + newparam.direction = 0; /* request from app */ + send_message(MESSAGE_NEWREF, 0, &newparam); + /* set state */ + call->state = CHAN_LCR_STATE_OUT_PREPARE; +} -/* call from asterisk (new instance) */ +/* + * call from asterisk + */ static int lcr_call(struct ast_channel *ast, char *dest, int timeout) { - struct lcr_pvt *lcr=ast->tech_pvt; + struct chan_call *call=ast->tech_pvt; - if (!lcr) return -1; + if (!call) return -1; char buf[128]; char *port_str, *dad, *p; + hier muss noch ast_copy_string(buf, dest, sizeof(buf)-1); p=buf; port_str=strsep(&p, "/"); dad=strsep(&p, "/"); + /* send setup message, if we already have a callref */ + if (call->ref) + send_setup_to_lcr(call); + if (lcr_debug) ast_verbose("Call: ext:%s dest:(%s) -> dad(%s) \n", ast->exten,dest, dad); - + #warning hier müssen wi eine der geholten REFs nehmen und ein SETUP schicken, die INFOS zum SETUP stehen im Ast pointer drin, bzw. werden hier übergeben. + return 0; } +static int lcr_digit(struct ast_channel *ast, char digit) +{ + char buf[]="x"; + + /* only pass IA5 number space */ + if (digit > 126 || digit < 32) + return 0; + + /* send information or queue them */ + if (call->ref && call->state == CHAN_LCR_STATE_OUT_DIALING) + { + send_dialing_to_lcr(call); + } else + if (!call->ref + && (call->state == CHAN_LCR_STATE_OUT_PREPARE || call->state == CHAN_LCR_STATE_OUT_SETUP)); + { + *buf = digit; + strncat(call->dialque, buf, strlen(char->dialque)-1); + } else + { +digits kommen, koennen aber nicht verwendet werden. + sollen wir sie als info senden (im connect zb.) + } +} + static int lcr_answer(struct ast_channel *c) { - struct lcr_pvt *lcr=c->tech_pvt; + struct chan_call *call=c->tech_pvt; return 0; } -static int lcr_hangup(struct ast_channel *c) +static int lcr_hangup(struct ast_channel *ast) { ++<<<<<<< HEAD:chan_lcr.c + struct chan_call *call = ast->tech_pvt; ++======= + struct chan_call *call=c->tech_pvt; + c->tech_pvt=NULL; + } ++>>>>>>> 350450b9cadc6107449fe2630843d4f898f680b7:chan_lcr.c + /* disconnect asterisk, maybe not required */ + ast->tech_pvt = NULL; + if (ref) + { + /* release */ + memset(&newparam, 0, sizeof(union parameter)); + newparam.disconnectinfo.cause = CAUSE_RESSOURCEUNAVAIL; + newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + send_message(MESSAGE_RELEASE, call->ref, &newparam); + /* remove call */ + free_call(call); + return; + } else + { + /* ref is not set, due to prepare setup or release */ + if (call->state == CHAN_LCR_STATE_RELEASE) + { + /* we get the response to our release */ + free_call(call); + } else + { + /* during prepare, we change to release state */ + call->state = CHAN_LCR_STATE_RELEASE; + } + } +} static int lcr_write(struct ast_channel *c, struct ast_frame *f) { - struct lcr_pvt *lcrm= c->tech_pvt; + struct chan_call *callm= c->tech_pvt; } static struct ast_frame *lcr_read(struct ast_channel *c) { - struct lcr_pvt *lcr = c->tech_pvt; + struct chan_call *call = c->tech_pvt; } static int lcr_indicate(struct ast_channel *c, int cond, const void *data, size_t datalen) @@@ -971,11 -672,11 +1021,11 @@@ } static struct ast_channel_tech lcr_tech = { - .type="lcr", + .type=lcr_type, .description="Channel driver for connecting to Linux-Call-Router", .capabilities=AST_FORMAT_ALAW, .requester=lcr_request, -// .send_digit=lcr_digit, + .send_digit=lcr_digit, .call=lcr_call, // .bridge=lcr_bridge, .hangup=lcr_hangup, @@@ -988,6 -689,34 +1038,34 @@@ .properties=0 }; + #warning das muss mal aus der config datei gelesen werden: + char lcr_context[]="from-lcr"; + + static struct ast_channel *lcr_ast_new(struct chan_call *call, char *exten, char *callerid, int ref) + { + struct ast_channel *tmp; + char *cid_name = 0, *cid_num = 0; + + + if (callerid) + ast_callerid_parse(callerid, &cid_name, &cid_num); + + tmp = ast_channel_alloc(1, AST_STATE_RESERVED, cid_num, cid_name, "", exten, "", 0, "%s/%d", lcr_type, ref); + + if (tmp) { + tmp->tech = &lcr_tech; + tmp->writeformat = AST_FORMAT_ALAW; + tmp->readformat = AST_FORMAT_ALAW; + + ast_copy_string(tmp->context, lcr_context, AST_MAX_CONTEXT); + + } + + return tmp; + } + + + /* * cli */ @@@ -1188,7 -917,7 +1266,7 @@@ char *key(void #define AST_MODULE "chan_lcr" AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, - "Channel driver for lcr", + "Channel driver for LCR", .load = load_module, .unload = unload_module, .reload = reload_module, diff --combined chan_lcr.h index 45a5a94,e431634..f1842c6 --- a/chan_lcr.h +++ b/chan_lcr.h @@@ -11,64 -11,13 +11,66 @@@ /* structure for all calls */ struct chan_call { - struct chan_call *next; - unsigned long ref; /* callref, is 0, if not yet set */ - unsigned long bchannel_handle; /* reference to bchannel, if set */ - + struct chan_call *next; /* link to next call instance */ + int state; /* current call state CHAN_LCR_STATE */ + unsigned long ref; /* callref for this channel */ + struct ast_channel *ast; /* current asterisk channel */ + unsigned long bchannel_handle; + /* reference to bchannel, if set */ unsigned short bridge_id; /* 0 = off, equal ids are bridged */ + + struct ast_channel *ast; }; +enum { + CHAN_LCR_STATE_IN_PREPARE = 0, + CHAN_LCR_STATE_IN_SETUP, + CHAN_LCR_STATE_IN_DIALING, + CHAN_LCR_STATE_IN_PROCEEDING, + CHAN_LCR_STATE_IN_ALERTING, + CHAN_LCR_STATE_OUT_PREPARE, + CHAN_LCR_STATE_OUT_SETUP, + CHAN_LCR_STATE_OUT_DIALING, + CHAN_LCR_STATE_OUT_PROCEEDING, + CHAN_LCR_STATE_OUT_ALERTING, + CHAN_LCR_STATE_CONNECT, + CHAN_LCR_STATE_IN_DISCONNECT, + CHAN_LCR_STATE_OUT_DISCONNECT, + CHAN_LCR_STATE_RELEASE, +}; + +#define CHAN_LCR_STATE static const struct chan_lcr_state { \ + char name, \ + char meaning, \ +} chan_lcr_state[] = { \ + { "IN_PREPARE", \ + "New call from ISDN is waiting for setup." }, \ + { "IN_SETUP", \ + "Call from ISDN is currently set up." }, \ + { "IN_DIALING", \ + "Call from ISDN is currently waiting for digits to be dialed." }, \ + { "IN_PROCEEDING", \ + "Call from ISDN is complete and proceeds to ring." }, \ + { "IN_ALERTING", \ + "Call from ISDN is ringing." }, \ + { "OUT_PREPARE", \ + "New call to ISDN is wating for setup." }, \ + { "OUT_SETUP", \ + "Call to ISDN is currently set up." }, \ + { "OUT_DIALING", \ + "Call to ISDN is currently waiting for digits to be dialed." }, \ + { "OUT_PROCEEDING", \ + "Call to ISDN is complete and proceeds to ring." }, \ + { "OUT_ALERTING", \ + "Call to ISDN is ringing." }, \ + { "CONNECT", \ + "Call has been answered." }, \ + { "IN_DISCONNECT", \ + "Call has been hung up on ISDN side." }, \ + { "OUT_DISCONNECT", \ + "Call has been hung up on Asterisk side." }, \ + { "RELEASE", \ + "Call is waiting for complete release." }, \ +}; +