Advertisement
Guest User

kannel graceful reload patch v3

a guest
Jul 23rd, 2013
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 23.53 KB | None | 0 0
  1. Index: doc/userguide/userguide.xml
  2. ===================================================================
  3. --- doc/userguide/userguide.xml (revision 5009)
  4. +++ doc/userguide/userguide.xml (working copy)
  5. @@ -2007,11 +2007,26 @@
  6.      </entry></row>
  7.  
  8.     <row><entry><literal>restart</literal></entry>
  9. -   <entry valign="bottom">
  10. +    <entry valign="bottom">
  11.          Re-start whole bearerbox, hence all SMSC links. Password required.
  12. -         Beware that you loose the smsbox connections in such a case.
  13. -   </entry></row>
  14. +        This is the hard restarting version, where we fully stop the
  15. +        bearerbox and then initiate from ground up.
  16. +       Beware that you loose the smsbox connections in such a case.
  17. +    </entry></row>
  18.  
  19. +    <row><entry><literal>graceful-restart</literal></entry>
  20. +    <entry valign="bottom">
  21. +        Re-start bearerbox gracefully, hence only the changes in the
  22. +        configuration for the SMSC connections are performed. I.e.
  23. +        an added SMSC group will be start, and a removed SMSC group
  24. +        will be shutdown and destroyed. Any unchanged SMSC connection
  25. +        keeps on running without interruption. Password required.
  26. +        This is the soft restarting version, where we keep all internal
  27. +        parts of the bearebox running, including the smsbox connections.
  28. +        The same graceful restart can be initiated by sending a SIGHUP
  29. +        signal to the bearerbox daemon process.
  30. +    </entry></row>
  31. +
  32.     <row><entry><literal>loglevel</literal></entry>
  33.     <entry valign="bottom">
  34.          Set Kannel log-level of log-files while running. This allows
  35. @@ -10429,9 +10444,12 @@
  36.          to /etc/logrotate.d) is shown below. In this example the Kannel log files found
  37.          in /var/log/kannel are rotated and compressed daily over 365 days.  See the
  38.          documentation for logrotate for more details.  Of particular note however is the
  39. -        postrotate command, this killall -HUP issues a HUP command to each Kannel
  40. -        box running. The HUP signal has the effect of reopening the log file, without this
  41. -        command Kannel will continue to write to the rotated log file.
  42. +        postrotate command, this killall -HUP issues a SIGHUP signal to each Kannel
  43. +        box process running. The SIGHUP signal has the effect of reopening the log file,
  44. +        and performing graceful restart of SMSC connections. Without this command Kannel
  45. +        will continue to write to the rotated log file. Kannel bearerbox has can use the
  46. +        SIGUSR2 to reopen the logs only, without performing the graceful restart. This
  47. +        may be more applicable for logrotate usage.
  48.          </para>
  49.  
  50.          <screen><userinput>
  51. @@ -10445,7 +10463,7 @@
  52.                create 640 kannel adm
  53.                sharedscripts
  54.                postrotate
  55. -                    killall -HUP bearerbox smsbox wapbox || true > /dev/null 2> /dev/null
  56. +                    killall -USR2 bearerbox && killall -HUP smsbox wapbox || true > /dev/null 2> /dev/null
  57.                endscript
  58.          }
  59.          </userinput></screen>
  60. Index: gw/bb_http.c
  61. ===================================================================
  62. --- gw/bb_http.c    (revision 4986)
  63. +++ gw/bb_http.c    (working copy)
  64. @@ -236,6 +236,21 @@
  65.      return octstr_create("Restarting.....");
  66.  }
  67.  
  68. +static Octstr *httpd_graceful_restart(List *cgivars, int status_type)
  69. +{
  70. +    Octstr *reply;
  71. +    if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
  72. +    if ((reply = httpd_check_status())!= NULL) return reply;
  73. +
  74. +    if (bb_status == BB_SHUTDOWN) {
  75. +        bb_status = BB_DEAD;
  76. +        bb_restart();
  77. +        return octstr_create("Already in shutdown phase, restarting hard...");
  78. +    }
  79. +    bb_graceful_restart();
  80. +    return octstr_create("Restarting gracefully.....");
  81. +}
  82. +
  83.  static Octstr *httpd_flush_dlr(List *cgivars, int status_type)
  84.  {
  85.      Octstr *reply;
  86. @@ -345,6 +360,7 @@
  87.      { "isolate", httpd_isolate },
  88.      { "resume", httpd_resume },
  89.      { "restart", httpd_restart },
  90. +    { "graceful-restart", httpd_graceful_restart },
  91.      { "flush-dlr", httpd_flush_dlr },
  92.      { "stop-smsc", httpd_stop_smsc },
  93.      { "start-smsc", httpd_restart_smsc },
  94. Index: gw/bb_smscconn.c
  95. ===================================================================
  96. --- gw/bb_smscconn.c    (revision 5002)
  97. +++ gw/bb_smscconn.c    (working copy)
  98. @@ -127,6 +127,7 @@
  99.  static volatile sig_atomic_t smsc_running;
  100.  static List *smsc_list;
  101.  static RWLock smsc_list_lock;
  102. +static Cfg *cfg_reloaded;
  103.  static List *smsc_groups;
  104.  static Octstr *unified_prefix;
  105.  
  106. @@ -554,17 +555,16 @@
  107.  
  108.  int bb_reload_smsc_groups()
  109.  {
  110. -    Cfg *cfg;
  111. -
  112. -    debug("bb.sms", 0, "Reloading groups list from disk");
  113. -    cfg =  cfg_create(cfg_filename);
  114. -    if (cfg_read(cfg) == -1) {
  115. +    debug("bb.sms", 0, "Reloading smsc groups list from config resource");
  116. +    cfg_destroy(cfg_reloaded);
  117. +    cfg_reloaded = cfg_create(cfg_filename);
  118. +    if (cfg_read(cfg_reloaded) == -1) {
  119.          warning(0, "Error opening configuration file %s", octstr_get_cstr(cfg_filename));
  120.          return -1;
  121.      }
  122. -    if (smsc_groups != NULL)
  123. -        gwlist_destroy(smsc_groups, NULL);
  124. -    smsc_groups = cfg_get_multi_group(cfg, octstr_imm("smsc"));
  125. +    gwlist_destroy(smsc_groups, NULL);
  126. +    smsc_groups = cfg_get_multi_group(cfg_reloaded, octstr_imm("smsc"));
  127. +
  128.      return 0;
  129.  }
  130.  
  131. @@ -573,8 +573,6 @@
  132.   * Other functions
  133.   */
  134.  
  135. -
  136. -
  137.  /* function to route outgoing SMS'es from delay-list
  138.   * use some nice magics to route them to proper SMSC
  139.   */
  140. @@ -653,8 +651,68 @@
  141.  }
  142.  
  143.  
  144. +static int cmp_conn_grp_checksum(void *a, void *b)
  145. +{
  146. +   int ret;
  147. +   SMSCConn *conn = a;
  148. +   Octstr *os = cfg_get_group_checksum((CfgGroup*)b, NULL);
  149.  
  150. +   ret = (octstr_compare(conn->chksum, os) == 0);
  151. +   octstr_destroy(os);
  152.  
  153. +   return ret;
  154. +}
  155. +
  156. +
  157. +static int cmp_rout_grp_checksum(void *a, void *b)
  158. +{
  159. +   int ret;
  160. +   SMSCConn *conn = a;
  161. +   Octstr *os;
  162. +
  163. +#define OCTSTR(os) octstr_imm(#os)
  164. +
  165. +   os = cfg_get_group_checksum((CfgGroup*)b,
  166. +           OCTSTR(denied-smsc-id),
  167. +           OCTSTR(allowed-smsc-id),
  168. +           OCTSTR(preferred-smsc-id),
  169. +           OCTSTR(allowed-prefix),
  170. +           OCTSTR(denied-prefix),
  171. +           OCTSTR(preferred-prefix),
  172. +           OCTSTR(unified-prefix),
  173. +           OCTSTR(reroute),
  174. +           OCTSTR(reroute-smsc-id),
  175. +           OCTSTR(reroute-receiver),
  176. +           OCTSTR(reroute-dlr),
  177. +           OCTSTR(allowed-smsc-id-regex),
  178. +           OCTSTR(denied-smsc-id-regex),
  179. +           OCTSTR(preferred-smsc-id-regex),
  180. +           OCTSTR(allowed-prefix-regex),
  181. +           OCTSTR(denied-prefix-regex),
  182. +           OCTSTR(preferred-prefix-regex),
  183. +           NULL
  184. +   );
  185. +
  186. +   ret = (octstr_compare(conn->chksum_conn, os) == 0);
  187. +   octstr_destroy(os);
  188. +
  189. +   return ret;
  190. +}
  191. +
  192. +
  193. +static int cmp_conn_grp_id(void *a, void *b)
  194. +{
  195. +   int ret;
  196. +   SMSCConn *conn = a;
  197. +   Octstr *os = cfg_get((CfgGroup*)b, octstr_imm("smsc-id"));
  198. +
  199. +   ret = (os && octstr_compare(conn->id, os) == 0);
  200. +   octstr_destroy(os);
  201. +
  202. +    return ret;
  203. +}
  204. +
  205. +
  206.  /*-------------------------------------------------------------
  207.   * public functions
  208.   *
  209. @@ -669,6 +727,9 @@
  210.  
  211.      if (smsc_running) return -1;
  212.  
  213. +    /* at start-up time there is no reloaded config */
  214. +    cfg_reloaded = NULL;
  215. +
  216.      /* create split sms counter */
  217.      split_msg_counter = counter_create();
  218.      
  219. @@ -1236,6 +1297,7 @@
  220.                  break;
  221.              default:
  222.                  sprintf(tmp3, "unknown");
  223. +                break;
  224.          }
  225.  
  226.          if (status_type == BBSTATUS_XML)
  227. @@ -1278,9 +1340,6 @@
  228.                  lb);
  229.      }
  230.  
  231. -
  232. -
  233. -
  234.      gw_rwlock_unlock(&smsc_list_lock);
  235.  
  236.      if (para)
  237. @@ -1293,6 +1352,156 @@
  238.  }
  239.  
  240.  
  241. +int smsc2_graceful_restart(void)
  242. +{
  243. +    CfgGroup *grp;
  244. +    SMSCConn *conn;
  245. +    List *keep, *add, *remove;
  246. +    List *l;
  247. +    int i;
  248. +
  249. +    if (!smsc_running)
  250. +        return -1;
  251. +
  252. +    gw_rwlock_wrlock(&smsc_list_lock);
  253. +
  254. +    /* load the smsc groups from the config resource */
  255. +    if (bb_reload_smsc_groups() != 0) {
  256. +        gw_rwlock_unlock(&smsc_list_lock);
  257. +        return -1;
  258. +    }
  259. +
  260. +    /* List of SMSCConn that we keep running */
  261. +    keep = gwlist_create();
  262. +
  263. +    /* List of CfgGroup that we will add */
  264. +    add = gwlist_create();
  265. +
  266. +    /* List of SMSCConnn that we will shutdown */
  267. +    remove = gwlist_create();
  268. +
  269. +    /*
  270. +     * Loop through the loaded smsc groups
  271. +     */
  272. +    for (i = 0; i < gwlist_len(smsc_groups) &&
  273. +        (grp = gwlist_get(smsc_groups, i)) != NULL; i++) {
  274. +        /*
  275. +         * 1st check: Search for the same md5 hash of the whole group.
  276. +         * If we find it, then this group is already running, and no
  277. +         * routing information has changed, bail out.
  278. +         */
  279. +        if ((conn = gwlist_search(smsc_list, grp, cmp_conn_grp_checksum)) != NULL) {
  280. +           gwlist_append(keep, conn);
  281. +           continue;
  282. +        }
  283. +        /*
  284. +         * 2nd check: Search for the same md5 hash minus the routing
  285. +         * information. If we find it, then this group is already running
  286. +         * and the routing information changed, we'll apply only the new
  287. +         * routing information.
  288. +         */
  289. +        if ((conn = gwlist_search(smsc_list, grp, cmp_rout_grp_checksum)) != NULL) {
  290. +           gwlist_append(keep, conn);
  291. +           smscconn_reconfig(conn, grp);
  292. +           info(0, "Re-configured routing for smsc-id `%s'.", octstr_get_cstr(conn->id));
  293. +           continue;
  294. +        }
  295. +        /*
  296. +         * 3nd check: if the smsc-id is NOT in the running list, then
  297. +         * this is a new group, add it. If the smsc-id IS found, then
  298. +         * mark it/them to be removed, and add the new group.
  299. +         */
  300. +        if ((l = gwlist_search_all(smsc_list, grp, cmp_conn_grp_id)) == NULL) {
  301. +           gwlist_append(add, grp);
  302. +           continue;
  303. +        } else {
  304. +           while ((conn = gwlist_extract_first(l)) != NULL) {
  305. +               /* add them to the remove list only
  306. +                * if they are not yet present inside. */
  307. +               if (gwlist_search_equal(remove, conn) != -1)
  308. +                   gwlist_append(remove, conn);
  309. +           }
  310. +           gwlist_destroy(l, NULL);
  311. +           gwlist_append(add, grp);
  312. +           continue;
  313. +        }
  314. +    }
  315. +
  316. +    /*
  317. +     * We may have running smsc-ids now, that haven't been
  318. +     * re-loaded from the new config, hence add them to be removed.
  319. +     */
  320. +    for (i = 0; i < gwlist_len(smsc_list) &&
  321. +        (conn = gwlist_get(smsc_list, i)) != NULL; i++) {
  322. +       /* if this is already in the remove list, bail out. */
  323. +       if (gwlist_search_equal(remove, conn) != -1)
  324. +           continue;
  325. +       /* if this is in the keep list, bail out. */
  326. +       if (gwlist_search_equal(keep, conn) != -1)
  327. +           continue;
  328. +       /* mark it to be removed */
  329. +       gwlist_append(remove, conn);
  330. +    }
  331. +    gwlist_destroy(keep, NULL);
  332. +
  333. +    /*
  334. +     * Stop any connections from the remove list.
  335. +     *
  336. +     * The smscconn_shutdown() only initiates the shutdown,
  337. +     * it is not guaranteed that the SMSC connection is stopped
  338. +     * and the status is SMSCCONN_DEAD when we return from the
  339. +     * function call. Therefore we pass the connection to a
  340. +     * retry list, in order to cleanly destroy all connection
  341. +     * structures that have been stopped and reached SMSSCONN_DEAD.
  342. +     */
  343. +    l = gwlist_create();
  344. +    gwlist_add_producer(smsc_list);
  345. +    while ((conn = gwlist_extract_first(remove)) != NULL) {
  346. +       if ((i = gwlist_search_equal(smsc_list, conn)) != -1) {
  347. +            gwlist_delete(smsc_list, i, 1);
  348. +            smscconn_shutdown(conn, 0);
  349. +            /* if smsc is still in shutdown, then add to retry list */
  350. +            if (smscconn_destroy(conn) == -1)
  351. +               gwlist_append(l, conn);
  352. +       }
  353. +    }
  354. +    gwlist_remove_producer(smsc_list);
  355. +    gwlist_destroy(remove, NULL);
  356. +
  357. +    /*
  358. +     * Start any connections from the add list.
  359. +     */
  360. +    gwlist_add_producer(smsc_list);
  361. +    while ((grp = gwlist_extract_first(add)) != NULL) {
  362. +        conn = smscconn_create(grp, 1);
  363. +        if (conn != NULL)
  364. +            gwlist_append(smsc_list, conn);
  365. +    }
  366. +    gwlist_remove_producer(smsc_list);
  367. +    gwlist_destroy(add, NULL);
  368. +
  369. +    gw_rwlock_unlock(&smsc_list_lock);
  370. +
  371. +    /* wake-up the router */
  372. +    if (router_thread >= 0)
  373. +        gwthread_wakeup(router_thread);
  374. +
  375. +    /*
  376. +     * We may still have pending connections in the retry list
  377. +     * that haven't been destroyed yet.
  378. +     */
  379. +    while ((conn = gwlist_extract_first(l)) != NULL) {
  380. +       if (smscconn_destroy(conn) == -1) {
  381. +           gwlist_append(l, conn);
  382. +           gwthread_sleep(2);
  383. +       }
  384. +    }
  385. +    gwlist_destroy(l, NULL);
  386. +
  387. +    return 0;
  388. +}
  389. +
  390. +
  391.  /* function to route outgoing SMS'es
  392.   *
  393.   * If finds a good one, puts into it and returns SMSCCONN_SUCCESS
  394. Index: gw/bearerbox.c
  395. ===================================================================
  396. --- gw/bearerbox.c  (revision 5002)
  397. +++ gw/bearerbox.c  (working copy)
  398. @@ -135,8 +135,9 @@
  399.   * Flags for main thread to check what is to do.
  400.   */
  401.  enum {
  402. -    BB_LOGREOPEN = 1,
  403. -    BB_CHECKLEAKS = 2
  404. +    BB_GRACEFUL_RESTART = 1,
  405. +    BB_CHECKLEAKS = 2,
  406. +    BB_LOGREOPEN = 3
  407.  };
  408.  /* Here we will set above flags */
  409.  static volatile sig_atomic_t bb_todo = 0;
  410. @@ -191,6 +192,10 @@
  411.              break;
  412.  
  413.          case SIGHUP:
  414. +            bb_todo |= BB_GRACEFUL_RESTART;
  415. +            break;
  416. +
  417. +        case SIGUSR2:
  418.              bb_todo |= BB_LOGREOPEN;
  419.              break;
  420.  
  421. @@ -216,6 +221,7 @@
  422.      sigaction(SIGQUIT, &act, NULL);
  423.      sigaction(SIGHUP, &act, NULL);
  424.      sigaction(SIGPIPE, &act, NULL);
  425. +    sigaction(SIGUSR2, &act, NULL);
  426.  }
  427.  
  428.  
  429. @@ -749,8 +755,16 @@
  430.              continue;
  431.          }
  432.  
  433. +        if (bb_todo & BB_GRACEFUL_RESTART) {
  434. +            warning(0, "SIGHUP received, re-opening logs and gracefully restarting.");
  435. +            log_reopen();
  436. +            alog_reopen();
  437. +            bb_graceful_restart();
  438. +            bb_todo = bb_todo & ~BB_GRACEFUL_RESTART;
  439. +        }
  440. +
  441.          if (bb_todo & BB_LOGREOPEN) {
  442. -            warning(0, "SIGHUP received, catching and re-opening logs");
  443. +            warning(0, "SIGUSR2 received, re-opening logs.");
  444.              log_reopen();
  445.              alog_reopen();
  446.              bb_todo = bb_todo & ~BB_LOGREOPEN;
  447. @@ -928,6 +942,11 @@
  448.      return bb_shutdown();
  449.  }
  450.  
  451. +int bb_graceful_restart(void)
  452. +{
  453. +    return smsc2_graceful_restart();
  454. +}
  455. +
  456.  int bb_reload_lists(void)
  457.  {
  458.      return smsc2_reload_lists();
  459. Index: gw/bearerbox.h
  460. ===================================================================
  461. --- gw/bearerbox.h  (revision 5002)
  462. +++ gw/bearerbox.h  (working copy)
  463. @@ -150,6 +150,7 @@
  464.  
  465.  int smsc2_start(Cfg *config);
  466.  int smsc2_restart(Cfg *config);
  467. +int smsc2_graceful_restart(void);
  468.  
  469.  void smsc2_suspend(void);    /* suspend (can still send but not receive) */
  470.  void smsc2_resume(int is_init);     /* resume */
  471. @@ -212,6 +213,7 @@
  472.  int bb_suspend(void);
  473.  int bb_resume(void);
  474.  int bb_restart(void);
  475. +int bb_graceful_restart(void);
  476.  int bb_flush_dlr(void);
  477.  int bb_stop_smsc(Octstr *id);
  478.  int bb_add_smsc(Octstr *id);
  479. Index: gw/smscconn.c
  480. ===================================================================
  481. --- gw/smscconn.c   (revision 5003)
  482. +++ gw/smscconn.c   (working copy)
  483. @@ -109,7 +109,7 @@
  484.      if ((rule = cfg_get(grp, octstr_imm("reroute-receiver"))) != NULL) {
  485.          List *routes;
  486.  
  487. -        /* create hash disctionary for this smsc-id */
  488. +        /* create hash dictionary for this smsc-id */
  489.          conn->reroute_by_receiver = dict_create(100, (void(*)(void *)) octstr_destroy);
  490.  
  491.          routes = octstr_split(rule, octstr_imm(";"));
  492. @@ -169,6 +169,33 @@
  493.      conn->connect_time = -1;
  494.      conn->is_stopped = start_as_stopped;
  495.  
  496. +#define OCTSTR(os) octstr_imm(#os)
  497. +
  498. +    /* checksum of the whole config */
  499. +    conn->chksum = cfg_get_group_checksum(grp, NULL);
  500. +
  501. +    /* checksum of the connection related part, without routing */
  502. +    conn->chksum_conn = cfg_get_group_checksum(grp,
  503. +           OCTSTR(denied-smsc-id),
  504. +           OCTSTR(allowed-smsc-id),
  505. +           OCTSTR(preferred-smsc-id),
  506. +           OCTSTR(allowed-prefix),
  507. +           OCTSTR(denied-prefix),
  508. +           OCTSTR(preferred-prefix),
  509. +           OCTSTR(unified-prefix),
  510. +           OCTSTR(reroute),
  511. +           OCTSTR(reroute-smsc-id),
  512. +           OCTSTR(reroute-receiver),
  513. +           OCTSTR(reroute-dlr),
  514. +           OCTSTR(allowed-smsc-id-regex),
  515. +           OCTSTR(denied-smsc-id-regex),
  516. +           OCTSTR(preferred-smsc-id-regex),
  517. +           OCTSTR(allowed-prefix-regex),
  518. +           OCTSTR(denied-prefix-regex),
  519. +           OCTSTR(preferred-prefix-regex),
  520. +           NULL
  521. +    );
  522. +
  523.      conn->received = counter_create();
  524.      conn->received_dlr = counter_create();
  525.      conn->sent = counter_create();
  526. @@ -335,10 +362,11 @@
  527.  void smscconn_shutdown(SMSCConn *conn, int finish_sending)
  528.  {
  529.      gw_assert(conn != NULL);
  530. +
  531.      mutex_lock(conn->flow_mutex);
  532.      if (conn->status == SMSCCONN_DEAD) {
  533. -   mutex_unlock(conn->flow_mutex);
  534. -   return;
  535. +       mutex_unlock(conn->flow_mutex);
  536. +       return;
  537.      }
  538.  
  539.      /* Call SMSC specific destroyer */
  540. @@ -348,10 +376,10 @@
  541.           * and will try to lock this mutex.Otherwise we have deadlock!
  542.           */
  543.          mutex_unlock(conn->flow_mutex);
  544. -   conn->shutdown(conn, finish_sending);
  545. +        conn->shutdown(conn, finish_sending);
  546.      }
  547.      else {
  548. -   conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
  549. +       conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
  550.          mutex_unlock(conn->flow_mutex);
  551.      }
  552.  
  553. @@ -390,6 +418,8 @@
  554.      octstr_destroy(conn->unified_prefix);
  555.      octstr_destroy(conn->our_host);
  556.      octstr_destroy(conn->log_file);
  557. +    octstr_destroy(conn->chksum);
  558. +    octstr_destroy(conn->chksum_conn);
  559.  
  560.      if (conn->denied_smsc_id_regex != NULL) gw_regex_destroy(conn->denied_smsc_id_regex);
  561.      if (conn->allowed_smsc_id_regex != NULL) gw_regex_destroy(conn->allowed_smsc_id_regex);
  562. @@ -658,3 +688,57 @@
  563.  }
  564.  
  565.  
  566. +void smscconn_reconfig(SMSCConn *conn, CfgGroup *grp)
  567. +{
  568. +    Octstr *tmp;
  569. +
  570. +    gw_assert(conn != NULL);
  571. +
  572. +    if (grp == NULL)
  573. +       return;
  574. +
  575. +#define GET_OPTIONAL_VAL(x, n) \
  576. +       octstr_destroy(x); \
  577. +       x = cfg_get(grp, octstr_imm(n))
  578. +#define SPLIT_OPTIONAL_VAL(x, n) \
  579. +       gwlist_destroy(x, octstr_destroy_item); \
  580. +       if ((tmp = cfg_get(grp, octstr_imm(n))) != NULL) \
  581. +           x = octstr_split(tmp, octstr_imm(";")); \
  582. +       else \
  583. +           x = NULL; \
  584. +       octstr_destroy(tmp);
  585. +#define GET_OPTIONAL_REGEX(x, n) \
  586. +       gw_regex_destroy(x); \
  587. +       if ((tmp = cfg_get(grp, octstr_imm(n))) != NULL) { \
  588. +           if ((x = gw_regex_comp(tmp, REG_EXTENDED)) == NULL) \
  589. +               error(0, "Could not compile pattern '%s'", octstr_get_cstr(tmp)); \
  590. +           octstr_destroy(tmp); \
  591. +       }
  592. +
  593. +    SPLIT_OPTIONAL_VAL(conn->allowed_smsc_id, "allowed-smsc-id");
  594. +    SPLIT_OPTIONAL_VAL(conn->denied_smsc_id, "denied-smsc-id");
  595. +    SPLIT_OPTIONAL_VAL(conn->preferred_smsc_id, "preferred-smsc-id");
  596. +    GET_OPTIONAL_VAL(conn->allowed_prefix, "allowed-prefix");
  597. +    GET_OPTIONAL_VAL(conn->denied_prefix, "denied-prefix");
  598. +    GET_OPTIONAL_VAL(conn->preferred_prefix, "preferred-prefix");
  599. +    GET_OPTIONAL_VAL(conn->unified_prefix, "unified-prefix");
  600. +    GET_OPTIONAL_REGEX(conn->allowed_smsc_id_regex, "allowed-smsc-id-regex");
  601. +    GET_OPTIONAL_REGEX(conn->denied_smsc_id_regex, "denied-smsc-id-regex");
  602. +    GET_OPTIONAL_REGEX(conn->preferred_smsc_id_regex, "preferred-smsc-id-regex");
  603. +    GET_OPTIONAL_REGEX(conn->allowed_prefix_regex, "allowed-prefix-regex");
  604. +    GET_OPTIONAL_REGEX(conn->denied_prefix_regex, "denied-prefix-regex");
  605. +    GET_OPTIONAL_REGEX(conn->preferred_prefix_regex, "preferred-prefix-regex");
  606. +
  607. +    octstr_destroy(conn->reroute_to_smsc);
  608. +    dict_destroy(conn->reroute_by_receiver);
  609. +    init_reroute(conn, grp);
  610. +
  611. +    /*
  612. +     * Since we applied changes, we need to re-compute
  613. +     * at least the overall checksum. The other one
  614. +     * is not changed as the routing values are excluded.
  615. +     * also the checksum hash values.
  616. +     */
  617. +    octstr_destroy(conn->chksum);
  618. +    conn->chksum = cfg_get_group_checksum(grp, NULL);
  619. +}
  620. Index: gw/smscconn.h
  621. ===================================================================
  622. --- gw/smscconn.h   (revision 4986)
  623. +++ gw/smscconn.h   (working copy)
  624. @@ -199,5 +199,9 @@
  625.   */
  626.  int smscconn_info(SMSCConn *smscconn, StatusInfo *infotable);
  627.  
  628. +/* Reconfigure the running SMSC for any routing relevant
  629. + * information from the configuration group.
  630. + */
  631. +void smscconn_reconfig(SMSCConn *conn, CfgGroup *grp);
  632.  
  633.  #endif
  634. Index: gw/smscconn_p.h
  635. ===================================================================
  636. --- gw/smscconn_p.h (revision 5003)
  637. +++ gw/smscconn_p.h (working copy)
  638. @@ -168,6 +168,8 @@
  639.      /* SMSCConn variables set in smscconn.c */
  640.      volatile sig_atomic_t  is_stopped;
  641.  
  642. +    Octstr *chksum;            /* MD5 hash of the whole configuration */
  643. +    Octstr *chksum_conn;   /* MD5 hash minus the routing configuration */
  644.      Octstr *name;      /* Descriptive name filled from connection info */
  645.      Octstr *id;            /* Abstract name specified in configuration and
  646.                    used for logging and routing */
  647. Index: gwlib/cfg.c
  648. ===================================================================
  649. --- gwlib/cfg.c (revision 4986)
  650. +++ gwlib/cfg.c (working copy)
  651. @@ -146,6 +146,21 @@
  652.  }
  653.  
  654.  
  655. +static int octstr_sort_cb(const void *a, const void *b)
  656. +{
  657. +    const Octstr *fa = a;
  658. +    const Octstr *fb = b;
  659. +
  660. +    return octstr_compare(fa, fb);
  661. +}
  662. +
  663. +
  664. +static int octstr_cmp_cb(void *a, void *b)
  665. +{
  666. +    return (octstr_compare((Octstr*)a, (Octstr*)b) == 0);
  667. +}
  668. +
  669. +
  670.  struct Cfg {
  671.      Octstr *filename;
  672.      Dict *single_groups;
  673. @@ -647,6 +662,56 @@
  674.      return octstr_duplicate(grp->name);
  675.  }
  676.  
  677. +Octstr *cfg_get_group_checksum(CfgGroup *grp, ...)
  678. +{
  679. +    va_list args;
  680. +   Octstr *ret, *os, *key, *val;
  681. +   List *exclude, *keys;
  682. +
  683. +   exclude = gwlist_create();
  684. +
  685. +   /*
  686. +    * Variadic Octstr* arguments may contain the
  687. +    * config key names that DO NOT go into the
  688. +    * checksum computation. This allows differential
  689. +    * compares and detection of single changes.
  690. +    */
  691. +    va_start(args, grp);
  692. +    while ((os = va_arg(args, Octstr*)) != NULL) {
  693. +       gwlist_append(exclude, os);
  694. +    }
  695. +    va_end(args);
  696. +
  697. +    /* all configured config names of this group */
  698. +    keys = dict_keys(grp->vars);
  699. +
  700. +    /* remove all excluded configs names */
  701. +    while ((os = gwlist_extract_first(exclude)) != NULL) {
  702. +       if ((key = gwlist_search(keys, os, octstr_cmp_cb)) != NULL) {
  703. +           if (gwlist_delete_equal(keys, key) != 1)
  704. +               panic(0, "%s: multiple config variables with same name `%s'?!", __func__,
  705. +                     octstr_get_cstr(key));
  706. +           octstr_destroy(key);
  707. +       }
  708. +    }
  709. +    gwlist_destroy(exclude, NULL);
  710. +
  711. +    os = octstr_duplicate(grp->name);
  712. +    gwlist_sort(keys, octstr_sort_cb);
  713. +    while ((key = gwlist_extract_first(keys)) != NULL) {
  714. +       octstr_append(os, key);
  715. +       if ((val = dict_get(grp->vars, key)) != NULL)
  716. +           octstr_append(os, val);
  717. +       octstr_destroy(key);
  718. +    }
  719. +    gwlist_destroy(keys, NULL);
  720. +
  721. +    ret = md5(os);
  722. +    octstr_destroy(os);
  723. +
  724. +    return ret;
  725. +}
  726. +
  727.  Octstr *cfg_get_configfile(CfgGroup *grp)
  728.  {
  729.      return octstr_duplicate(grp->configfile);
  730. Index: gwlib/cfg.h
  731. ===================================================================
  732. --- gwlib/cfg.h (revision 4986)
  733. +++ gwlib/cfg.h (working copy)
  734. @@ -78,6 +78,7 @@
  735.  CfgGroup *cfg_get_single_group(Cfg *cfg, Octstr *name);
  736.  List *cfg_get_multi_group(Cfg *cfg, Octstr *name);
  737.  Octstr *cfg_get_group_name(CfgGroup *grp);
  738. +Octstr *cfg_get_group_checksum(CfgGroup *grp, ...);
  739.  Octstr *cfg_get_configfile(CfgGroup *grp);
  740.  
  741.  Octstr *cfg_get_real(CfgGroup *grp, Octstr *varname, const char *file,
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement