unified socket application interface (for asterisk and maybe other apps)
[lcr.git] / interface.c
index 520ecbd..fa7270d 100644 (file)
@@ -18,62 +18,44 @@ struct interface *interface_first = NULL; /* first interface is current list */
 struct interface *interface_newlist = NULL; /* first interface in new list */
 
 
-/* set default selchannel */
-void default_selchannel(struct interface_port *ifport)
+/* set default out_channel */
+void default_out_channel(struct interface_port *ifport)
 {
        struct select_channel *selchannel, **selchannelp;
 
-       /* channel selection for TE-ports */
-       if (!ifport->mISDNport->ntmode)
+       selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
+       memuse++;
+       
+       if (ifport->mISDNport->ntmode)
+               selchannel->channel = CHANNEL_FREE;
+       else
+               selchannel->channel = CHANNEL_ANY;
+       
+       ifport->out_channel = selchannel;
+
+       /* additional channel selection for multipoint NT ports */
+       if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
        {
-               selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
-               if (!selchannel)
-               {
-                       PERROR("No memory!");
-                       return;
-               }
+               selchannelp = &(selchannel->next);
+               selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
                memuse++;
-               memset(*selchannelp, 0, sizeof(struct select_channel));
-               *selchannelp->channel = SEL_CHANNEL_ANY;
-               selchannelp = &ifport->selchannel;
-               while(*selchannelp)
-                       selchannelp = &((*selchannelp)->next);
+               selchannel->channel = CHANNEL_NO; // call waiting
                *selchannelp = selchannel;
-               return(0);
        }
+}
 
-       /* channel selection for NT-ports */
-       selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
-       if (!selchannel)
-       {
-               PERROR("No memory!");
-               return;
-       }
+
+/* set default in_channel */
+void default_in_channel(struct interface_port *ifport)
+{
+       struct select_channel *selchannel;
+
+       selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
        memuse++;
-       memset(*selchannelp, 0, sizeof(struct select_channel));
-       *selchannelp->channel = SEL_CHANNEL_FREE;
-       selchannelp = &ifport->selchannel;
-       while(*selchannelp)
-               selchannelp = &((*selchannelp)->next);
-       *selchannelp = selchannel;
-
-       /* additional channel selection for multipoint ports */
-       if (!ifport->mISDNport->ptp)
-       {
-               selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
-               if (!selchannel)
-               {
-                       PERROR("No memory!");
-                       return;
-               }
-               memuse++;
-               memset(*selchannelp, 0, sizeof(struct select_channel));
-               *selchannelp->channel = SEL_CHANNEL_NO; // call waiting
-               selchannelp = &ifport->selchannel;
-               while(*selchannelp)
-                       selchannelp = &((*selchannelp)->next);
-               *selchannelp = selchannel;
-       }
+       
+       selchannel->channel = CHANNEL_FREE;
+       
+       ifport->in_channel = selchannel;
 }
 
 
@@ -256,7 +238,6 @@ static int inter_port(struct interface *interface, char *filename, int line, cha
 {
        struct interface_port *ifport, **ifportp;
        struct interface *searchif;
-       struct interface_port *searchport;
        int val;
 
        val = get_number(value);
@@ -269,7 +250,7 @@ static int inter_port(struct interface *interface, char *filename, int line, cha
        searchif = interface_newlist;
        while(searchif)
        {
-               searchport = searchif->ifport;
+               ifport = searchif->ifport;
                while(ifport)
                {
                        if (ifport->portnum == val)
@@ -282,14 +263,8 @@ static int inter_port(struct interface *interface, char *filename, int line, cha
                searchif = searchif->next;
        }
        /* alloc port substructure */
-       ifport = (struct interface_port *)malloc(sizeof(struct interface_port));
-       if (!ifport)
-       {
-               SPRINT(interface_error, "No memory!");
-               return(-1);
-       }
+       ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
        memuse++;
-       memset(ifport, 0, sizeof(struct interface_port));
        ifport->interface = interface;
        /* set value */
        ifport->portnum = val;
@@ -325,7 +300,7 @@ static int inter_channel_out(struct interface *interface, char *filename, int li
                if (!strcasecmp(el, "force"))
                {
                        ifport->channel_force = 1;
-                       if (ifport->selchannel)
+                       if (ifport->out_channel)
                        {
                                SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
                                return(-1);
@@ -333,17 +308,17 @@ static int inter_channel_out(struct interface *interface, char *filename, int li
                } else
                if (!strcasecmp(el, "any"))
                {
-                       val = SEL_CHANNEL_ANY;
+                       val = CHANNEL_ANY;
                        goto selchannel;
                } else
                if (!strcasecmp(el, "free"))
                {
-                       val = SEL_CHANNEL_FREE;
+                       val = CHANNEL_FREE;
                        goto selchannel;
                } else
                if (!strcasecmp(el, "no"))
                {
-                       val = SEL_CHANNEL_NO;
+                       val = CHANNEL_NO;
                        goto selchannel;
                } else
                {
@@ -361,18 +336,12 @@ static int inter_channel_out(struct interface *interface, char *filename, int li
                        }
                        selchannel:
                        /* add to select-channel list */
-                       selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
-                       if (!selchannel)
-                       {
-                               SPRINT(interface_error, "No memory!");
-                               return(-1);
-                       }
+                       selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
                        memuse++;
-                       memset(selchannel, 0, sizeof(struct select_channel));
                        /* set value */
                        selchannel->channel = val;
                        /* tail port */
-                       selchannelp = &ifport->selchannel;
+                       selchannelp = &ifport->out_channel;
                        while(*selchannelp)
                                selchannelp = &((*selchannelp)->next);
                        *selchannelp = selchannel;
@@ -402,14 +371,14 @@ static int inter_channel_in(struct interface *interface, char *filename, int lin
        {
                el = p;
                p = get_seperated(p);
-               if (ifport->in_select) if (ifport->in_select->channel == SEL_CHANNEL_FREE)
+               if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
                {
                        SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
                                return(-1);
                }
                if (!strcasecmp(el, "free"))
                {
-                       val = SEL_CHANNEL_FREE;
+                       val = CHANNEL_FREE;
                        goto selchannel;
                } else
                {
@@ -427,18 +396,12 @@ static int inter_channel_in(struct interface *interface, char *filename, int lin
                        }
                        selchannel:
                        /* add to select-channel list */
-                       selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
-                       if (!selchannel)
-                       {
-                               SPRINT(interface_error, "No memory!");
-                               return(-1);
-                       }
+                       selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
                        memuse++;
-                       memset(selchannel, 0, sizeof(struct select_channel));
                        /* set value */
                        selchannel->channel = val;
                        /* tail port */
-                       selchannelp = &ifport->in_select;
+                       selchannelp = &ifport->in_channel;
                        while(*selchannelp)
                                selchannelp = &((*selchannelp)->next);
                        *selchannelp = selchannel;
@@ -469,14 +432,8 @@ static int inter_msn(struct interface *interface, char *filename, int line, char
                el = p;
                p = get_seperated(p);
                /* add MSN to list */
-               ifmsn = (struct interface_msn *)malloc(sizeof(struct interface_msn));
-               if (!ifmsn)
-               {
-                       SPRINT(interface_error, "No memory!");
-                       return(-1);
-               }
+               ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
                memuse++;
-               memset(ifmsn, 0, sizeof(struct interface_msn));
                /* set value */
                SCPY(ifmsn->msn, el);
                /* tail port */
@@ -501,15 +458,10 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
        el = p;
        p = get_seperated(p);
        /* add screen entry to list*/
-       ifscreen = (struct interface_screen *)malloc(sizeof(struct interface_screen));
-       if (!ifscreen)
-       {
-               SPRINT(interface_error, "No memory!");
-               return(-1);
-       }
+       ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
        memuse++;
-       memset(ifscreen, 0, sizeof(struct interface_screen));
-#warning handle unchanged as unchanged!!
+       ifscreen->match_type = -1; /* unchecked */
+       ifscreen->match_present = -1; /* unchecked */
        ifscreen->result_type = -1; /* unchanged */
        ifscreen->result_present = -1; /* unchanged */
        /* tail port */
@@ -554,7 +506,7 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
                        if (ifscreen->match_present != -1)
                        {
                                presenterror:
-                               SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line, parameter);
+                               SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
                                return(-1);
                        }
                        ifscreen->match_present = INFO_PRESENT_ALLOWED;
@@ -566,6 +518,15 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
                        ifscreen->match_present = INFO_PRESENT_RESTRICTED;
                } else {
                        SCPY(ifscreen->match, el);
+                       /* check for % at the end */
+                       if (strchr(el, '%'))
+                       {
+                               if (strchr(el, '%') != el+strlen(el)-1)
+                               {
+                                       SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
+                                       return(-1);
+                               }
+                       }
                        break;
                }
        }
@@ -616,6 +577,15 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
                        ifscreen->result_present = INFO_PRESENT_RESTRICTED;
                } else {
                        SCPY(ifscreen->result, el);
+                       /* check for % at the end */
+                       if (strchr(el, '%'))
+                       {
+                               if (strchr(el, '%') != el+strlen(el)-1)
+                               {
+                                       SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
+                                       return(-1);
+                               }
+                       }
                        break;
                }
        }
@@ -640,11 +610,30 @@ static int inter_screen_out(struct interface *interface, char *filename, int lin
 {
        return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
 }
-static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
+static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
 {
+       struct interface_port *ifport;
+
+       /* port in chain ? */
+       if (!interface->ifport)
+       {
+               SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
+               return(-1);
+       }
+       /* goto end of chain */
+       ifport = interface->ifport;
+       while(ifport->next)
+               ifport = ifport->next;
+       ifport->nodtmf = 1;
+       return(0);
+}
 #warning filter to be done
+#if 0
+static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
        return(0);
 }
+#endif
 
 
 /*
@@ -679,7 +668,7 @@ struct interface_param interface_param[] = {
        "This is required on PRI NT-mode ports that are point-to-point by default.\n"
        "This parameter must follow a 'port' parameter."},
 
-       {"channel_out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
+       {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
        "Channel selection list for all outgoing calls to the interface.\n"
        "A free channels is searched in order of appearance.\n"
        "This parameter must follow a 'port' parameter.\n"
@@ -689,13 +678,13 @@ struct interface_param interface_param[] = {
        " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
        " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
 
-       {"channel_in", &inter_channel_in, "[force,][<number>][,...][,free][,any][,no]",
+       {"channel-in", &inter_channel_in, "[force,][<number>][,...][,free][,any][,no]",
        "Channel selection list for all incomming calls from the interface.\n"
        "A free channels is accepted if in the list.\n"
-       "If no channel was requested, the first free channel found is selected.\n"
+       "If any channel was requested, the first free channel found is selected.\n"
        "This parameter must follow a 'port' parameter.\n"
        " <number>[,...] - List of channels to accept.\n"
-       " free - Accept any free channel\n"
+       " free - Accept any free channel"},
 
        {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
        "Incomming caller ID is checked against given MSN numbers.\n"
@@ -716,10 +705,17 @@ struct interface_param interface_param[] = {
        "Adds an entry for outgoing calls to the caller ID screen list.\n"
        "See 'screen-in' for help."},
 
+       {"nodtmf", &inter_nodtmf, "",
+       "Disables DTMF detection for this interface.\n"
+       "This parameter must follow a 'port' parameter."},
+
+#if 0
+#warning todo: filter, also in the PmISDN object
        {"filter", &inter_filter, "<filter> [parameters]",
        "Adds/appends a filter. Filters are ordered in transmit direction.\n"
        "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
        "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
+#endif
 
        {NULL, NULL, NULL, NULL}
 };
@@ -744,10 +740,7 @@ struct interface *read_interfaces(void)
        struct interface_param  *ifparam;
 
        if (interface_newlist != NULL)
-       {
-               PERROR("software error, list is not empty.\n");
-               exit(-1);
-       }
+               FATAL("list is not empty.\n");
        interface_error[0] = '\0';
        SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
 
@@ -838,7 +831,7 @@ struct interface *read_interfaces(void)
                        parameter[strlen(parameter)-1] = '\0';
 
                        /* check if interface name already exists */
-                       interface = interface_first;
+                       interface = interface_newlist;
                        while(interface)
                        {
                                if (!strcasecmp(interface->name, parameter+1))
@@ -850,14 +843,8 @@ struct interface *read_interfaces(void)
                        }
 
                        /* append interface to new list */
-                       interface = (struct interface *)malloc(sizeof(struct interface));
-                       if (!interface)
-                       {
-                               SPRINT(interface_error, "No memory!");
-                               goto error;
-                       }
+                       interface = (struct interface *)MALLOC(sizeof(struct interface));
                        memuse++;
-                       memset(interface, 0, sizeof(struct interface));
 
                        /* name interface */
                        SCPY(interface->name, parameter+1);
@@ -876,10 +863,12 @@ struct interface *read_interfaces(void)
                        {
                                if (ifparam->func(interface, filename, line, parameter, value))
                                        goto error;
-                               continue;
+                               break;
                        }
                        ifparam++;
                }
+               if (ifparam->name)
+                       continue;
 
                SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
                goto error;
@@ -918,8 +907,7 @@ void free_interfaces(struct interface *interface)
                        {
                                temp = selchannel;
                                selchannel = selchannel->next;
-                               memset(temp, 0, sizeof(struct select_channel));
-                               free(temp);
+                               FREE(temp, sizeof(struct select_channel));
                                memuse--;
                        }
                        selchannel = ifport->out_channel;
@@ -927,14 +915,12 @@ void free_interfaces(struct interface *interface)
                        {
                                temp = selchannel;
                                selchannel = selchannel->next;
-                               memset(temp, 0, sizeof(struct select_channel));
-                               free(temp);
+                               FREE(temp, sizeof(struct select_channel));
                                memuse--;
                        }
                        temp = ifport;
                        ifport = ifport->next;
-                       memset(temp, 0, sizeof(struct interface_port));
-                       free(temp);
+                       FREE(temp, sizeof(struct interface_port));
                        memuse--;
                }
                ifmsn = interface->ifmsn;
@@ -942,8 +928,7 @@ void free_interfaces(struct interface *interface)
                {
                        temp = ifmsn;
                        ifmsn = ifmsn->next;
-                       memset(temp, 0, sizeof(struct interface_msn));
-                       free(temp);
+                       FREE(temp, sizeof(struct interface_msn));
                        memuse--;
                }
                ifscreen = interface->ifscreen_in;
@@ -951,8 +936,7 @@ void free_interfaces(struct interface *interface)
                {
                        temp = ifscreen;
                        ifscreen = ifscreen->next;
-                       memset(temp, 0, sizeof(struct interface_screen));
-                       free(temp);
+                       FREE(temp, sizeof(struct interface_screen));
                        memuse--;
                }
                ifscreen = interface->ifscreen_out;
@@ -960,8 +944,7 @@ void free_interfaces(struct interface *interface)
                {
                        temp = ifscreen;
                        ifscreen = ifscreen->next;
-                       memset(temp, 0, sizeof(struct interface_screen));
-                       free(temp);
+                       FREE(temp, sizeof(struct interface_screen));
                        memuse--;
                }
                iffilter = interface->iffilter;
@@ -969,18 +952,43 @@ void free_interfaces(struct interface *interface)
                {
                        temp = iffilter;
                        iffilter = iffilter->next;
-                       memset(temp, 0, sizeof(struct interface_filter));
-                       free(temp);
+                       FREE(temp, sizeof(struct interface_filter));
                        memuse--;
                }
                temp = interface;
                interface = interface->next;
-               memset(temp, 0, sizeof(struct interface));
-               free(temp);
+               FREE(temp, sizeof(struct interface));
                memuse--;
        }
 }
 
+/*
+ * defaults of ports if not specified by config
+ */
+static void set_defaults(struct interface_port *ifport)
+{
+       /* default channel selection list */
+       if (!ifport->out_channel)
+               default_out_channel(ifport);
+       if (!ifport->in_channel)
+               default_in_channel(ifport);
+       /* default is_tones */
+       if (ifport->interface->is_tones)
+               ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
+       else
+               ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
+       /* default is_earlyb */
+       if (ifport->interface->is_earlyb)
+               ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
+       else
+               ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
+       /* set locally flag */
+       if (ifport->interface->extension)
+               ifport->mISDNport->locally = 1;
+       else
+               ifport->mISDNport->locally = 0;
+}
+
 
 /*
  * all links between mISDNport and interface are made
@@ -1015,6 +1023,7 @@ void relink_interfaces(void)
                                {
                                        ifport->mISDNport = mISDNport;
                                        mISDNport->ifport = ifport;
+                                       set_defaults(ifport);
                                }
                                mISDNport = mISDNport->next;
                        }
@@ -1047,36 +1056,37 @@ void relink_interfaces(void)
                {
                        if (!ifport->mISDNport)
                        {
-                               /* open new port */
-                               mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp);
-                               if (mISDNport)
-                               {
-                                       ifport->mISDNport = mISDNport;
-                                       mISDNport->ifport = ifport;
-                               }
-                       }
-                       if (ifport->mISDNport)
-                       {
-                               /* default channel selection list */
-                               if (!ifport->selchannel)
-                                       default_selchannel(ifport);
-                               /* default is_tones */
-                               if (ifport->interface->is_tones)
-                                       ifport->mISDNport->is_tones = (ifport->interface->is_tones==IS_YES);
-                               else
-                                       ifport->mISDNport->is_tones = (ifport->mISDNport->ntmode)?1:0;
-                               /* default is_earlyb */
-                               if (ifport->interface->is_earlyb)
-                                       ifport->mISDNport->is_earlyb = (ifport->interface->is_earlyb==IS_YES);
-                               else
-                                       ifport->mISDNport->is_earlyb = (ifport->mISDNport->ntmode)?0:1;
+                               load_port(ifport);
                        }
+                       ifport = ifport->next;
                }
                interface = interface->next;
        }
 
 }
 
+
+/*
+ * load port
+ */
+void load_port(struct interface_port *ifport)
+{
+       struct mISDNport *mISDNport;
+
+       /* open new port */
+       mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp, ifport->interface);
+       if (mISDNport)
+       {
+               /* link port */
+               ifport->mISDNport = mISDNport;
+               mISDNport->ifport = ifport;
+               set_defaults(ifport);
+       } else
+       {
+               ifport->block = 2; /* not available */
+       }
+}
+
 /*
  * give summary of interface syntax
  */
@@ -1104,4 +1114,3 @@ void doc_interface(void)
        }
 }
 
-