FreeCalypso > hg > themwi-system-sw
view sip-in/readconf.c @ 118:a4450ae8fd09
sip-manual-out UAC: use the new CSeq parsing function
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 29 Sep 2022 13:03:27 -0800 |
parents | 9b87894704eb |
children | 7e04d28fae8b |
line wrap: on
line source
/* * In this module we implement the reading of /var/gsm/themwi-sip-in.cfg: * the main settings are bind-ip and bind-port, but we also have some * optional config settings. */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> struct in_addr sip_bind_ip; unsigned sip_bind_port; int cfg_use_100rel = 1; int cfg_force_pcma; unsigned cfg_retrans_timeout = 500; unsigned cfg_retrans_count = 10; unsigned max_forwards = 70; unsigned sip_linger_acked = 5; unsigned sip_linger_gotbye = 30; unsigned sip_linger_error = 180; static char config_file_pathname[] = "/var/gsm/themwi-sip-in.cfg"; struct parse_state { int lineno; int set_mask; }; static void require_one_arg(st, kw, arg) struct parse_state *st; char *kw, *arg; { char *cp; if (*arg == '\0' || *arg == '#') { inv_syntax: fprintf(stderr, "%s line %d: %s setting requires one argument\n", config_file_pathname, st->lineno, kw); exit(1); } for (cp = arg; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') goto inv_syntax; } static void handle_ip(st, kw, arg, var) struct parse_state *st; char *kw, *arg; struct in_addr *var; { require_one_arg(st, kw, arg); var->s_addr = inet_addr(arg); if (var->s_addr == INADDR_NONE) { fprintf(stderr, "%s line %d: invalid IP address argument \"%s\"\n", config_file_pathname, st->lineno, arg); exit(1); } } static void handle_num(st, kw, arg, var) struct parse_state *st; char *kw, *arg; unsigned *var; { char *endp; require_one_arg(st, kw, arg); *var = strtoul(arg, &endp, 10); if (*endp) { fprintf(stderr, "%s line %d: invalid numeric argument \"%s\"\n", config_file_pathname, st->lineno, arg); exit(1); } } static void handle_bool(st, kw, arg, var) struct parse_state *st; char *kw, *arg; int *var; { require_one_arg(st, kw, arg); if (!strcmp(arg, "true") || !strcmp(arg, "on") || !strcmp(arg, "yes") || !strcmp(arg, "1")) { *var = 1; return; } if (!strcmp(arg, "false") || !strcmp(arg, "off") || !strcmp(arg, "no") || !strcmp(arg, "0")) { *var = 0; return; } fprintf(stderr, "%s line %d: invalid boolean argument \"%s\"\n", config_file_pathname, st->lineno, arg); exit(1); } static void handle_retrans_conf(st, kw, arg) struct parse_state *st; char *kw, *arg; { char *cp = arg; if (!isdigit(*cp)) { inv: fprintf(stderr, "%s line %d: %s setting requires two numeric arguments\n", config_file_pathname, st->lineno, kw); exit(1); } cfg_retrans_timeout = strtoul(cp, &cp, 10); while (isspace(*cp)) cp++; if (!isdigit(*cp)) goto inv; cfg_retrans_count = strtoul(cp, &cp, 10); while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') goto inv; } static void process_line(st, line) struct parse_state *st; char *line; { char *cp, *kw; void (*handler)(), *var; int set_id; if (!index(line, '\n')) { fprintf(stderr, "%s line %d: too long or missing newline\n", config_file_pathname, st->lineno); exit(1); } for (cp = line; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') return; for (kw = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(kw, "bind-ip")) { handler = handle_ip; var = &sip_bind_ip; set_id = 1; } else if (!strcmp(kw, "bind-port")) { handler = handle_num; var = &sip_bind_port; set_id = 2; } else if (!strcmp(kw, "use-100rel")) { handler = handle_bool; var = &cfg_use_100rel; set_id = 0; } else if (!strcmp(kw, "force-pcma-codec")) { handler = handle_bool; var = &cfg_force_pcma; set_id = 0; } else if (!strcmp(kw, "sip-udp-retrans")) { handler = handle_retrans_conf; var = (void *) 0; set_id = 0; } else if (!strcmp(kw, "sip-linger-acked")) { handler = handle_num; var = &sip_linger_acked; set_id = 0; } else if (!strcmp(kw, "sip-linger-got-bye")) { handler = handle_num; var = &sip_linger_gotbye; set_id = 0; } else if (!strcmp(kw, "sip-linger-error")) { handler = handle_num; var = &sip_linger_error; set_id = 0; } else if (!strcmp(kw, "max-forwards")) { handler = &handle_num; var = &max_forwards; set_id = 0; } else { fprintf(stderr, "%s line %d: non-understood keyword \"%s\"\n", config_file_pathname, st->lineno, kw); exit(1); } if (st->set_mask & set_id) { fprintf(stderr, "%s line %d: duplicate %s setting\n", config_file_pathname, st->lineno, kw); exit(1); } while (isspace(*cp)) cp++; handler(st, kw, cp, var); st->set_mask |= set_id; } read_config_file() { FILE *inf; struct parse_state pst; char linebuf[256]; inf = fopen(config_file_pathname, "r"); if (!inf) { perror(config_file_pathname); exit(1); } pst.set_mask = 0; for (pst.lineno = 1; fgets(linebuf, sizeof linebuf, inf); pst.lineno++) process_line(&pst, linebuf); fclose(inf); if (pst.set_mask != 3) { fprintf(stderr, "error: %s did not set all required settings\n", config_file_pathname); exit(1); } }