Merge branch 'master' of ssh://jolly@www.mISDN.org/var/git/lcr
authorSuper User <root@isdn.jolly.ten>
Mon, 28 Apr 2008 17:34:33 +0000 (19:34 +0200)
committerSuper User <root@isdn.jolly.ten>
Mon, 28 Apr 2008 17:34:33 +0000 (19:34 +0200)
Conflicts:

chan_lcr.c

1  2 
chan_lcr.c
chan_lcr.h

diff --combined chan_lcr.c
  
  /*
  
 -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 <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <asterisk/features.h>
  #include <asterisk/sched.h>
  
 +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)
                                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 */
                                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);
        }
        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;
        }
  }
  
 -
 -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)
  }
  
  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,
        .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
  
  /* 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." }, \
 +};
 +