Merged revisions 198311 via svnmerge from
[asterisk/asterisk.git] / res / res_smdi.c
index aa86b18..d1d40f0 100644 (file)
@@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/lock.h"
 #include "asterisk/utils.h"
+#define AST_API_MODULE
 #include "asterisk/smdi.h"
 #include "asterisk/config.h"
 #include "asterisk/astobj.h"
@@ -305,8 +306,10 @@ static inline void unref_msg(void *msg, enum smdi_message_type type)
        switch (type) {
        case SMDI_MWI:
                ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
+               break;
        case SMDI_MD:
                ASTOBJ_UNREF(md_msg, ast_smdi_md_message_destroy);
+               break;
        }
 }
 
@@ -378,7 +381,18 @@ static void *smdi_msg_find(struct ast_smdi_interface *iface,
 
        switch (type) {
        case SMDI_MD:
-               if (ast_test_flag(&options, OPT_SEARCH_TERMINAL)) {
+               if (ast_strlen_zero(search_key)) {
+                       struct ast_smdi_md_message *md_msg = NULL;
+
+                       /* No search key provided (the code from chan_dahdi does this).
+                        * Just pop the top message off of the queue. */
+
+                       ASTOBJ_CONTAINER_TRAVERSE(&iface->md_q, !md_msg, do {
+                               md_msg = ASTOBJ_REF(iterator);
+                       } while (0); );
+
+                       msg = md_msg;
+               } else if (ast_test_flag(&options, OPT_SEARCH_TERMINAL)) {
                        struct ast_smdi_md_message *md_msg = NULL;
 
                        /* Searching by the message desk terminal */
@@ -406,7 +420,20 @@ static void *smdi_msg_find(struct ast_smdi_interface *iface,
                }
                break;
        case SMDI_MWI:
-               msg = ASTOBJ_CONTAINER_FIND(&iface->mwi_q, search_key);
+               if (ast_strlen_zero(search_key)) {
+                       struct ast_smdi_mwi_message *mwi_msg = NULL;
+
+                       /* No search key provided (the code from chan_dahdi does this).
+                        * Just pop the top message off of the queue. */
+
+                       ASTOBJ_CONTAINER_TRAVERSE(&iface->mwi_q, !mwi_msg, do {
+                               mwi_msg = ASTOBJ_REF(iterator);
+                       } while (0); );
+
+                       msg = mwi_msg;
+               } else {
+                       msg = ASTOBJ_CONTAINER_FIND(&iface->mwi_q, search_key);
+               }
                break;
        }
 
@@ -419,10 +446,25 @@ static void *smdi_message_wait(struct ast_smdi_interface *iface, int timeout,
        struct timeval start;
        long diff = 0;
        void *msg;
+       ast_cond_t *cond = NULL;
+       ast_mutex_t *lock = NULL;
+
+       switch (type) {
+       case SMDI_MWI:
+               cond = &iface->mwi_q_cond;
+               lock = &iface->mwi_q_lock;
+               break;
+       case SMDI_MD:
+               cond = &iface->md_q_cond;
+               lock = &iface->md_q_lock;
+               break;
+       }
+
+       start = ast_tvnow();
 
        while (diff < timeout) {
                struct timespec ts = { 0, };
-               struct timeval tv;
+               struct timeval wait;
 
                lock_msg_q(iface, type);
 
@@ -431,14 +473,14 @@ static void *smdi_message_wait(struct ast_smdi_interface *iface, int timeout,
                        return msg;
                }
 
-               tv = ast_tvadd(start, ast_tv(0, timeout));
-               ts.tv_sec = tv.tv_sec;
-               ts.tv_nsec = tv.tv_usec * 1000;
+               wait = ast_tvadd(start, ast_tv(0, timeout));
+               ts.tv_sec = wait.tv_sec;
+               ts.tv_nsec = wait.tv_usec * 1000;
 
                /* If there were no messages in the queue, then go to sleep until one
                 * arrives. */
 
-               ast_cond_timedwait(&iface->md_q_cond, &iface->md_q_lock, &ts);
+               ast_cond_timedwait(cond, lock, &ts);
 
                if ((msg = smdi_msg_find(iface, type, search_key, options))) {
                        unlock_msg_q(iface, type);
@@ -763,7 +805,7 @@ static void *mwi_monitor_handler(void *data)
 {
        while (!mwi_monitor.stop) {
                struct timespec ts = { 0, };
-               struct timeval tv;
+               struct timeval polltime;
                struct mailbox_mapping *mm;
 
                ast_mutex_lock(&mwi_monitor.lock);
@@ -775,9 +817,9 @@ static void *mwi_monitor_handler(void *data)
 
                /* Sleep up to the configured polling interval.  Allow unload_module()
                 * to signal us to wake up and exit. */
-               tv = ast_tvadd(mwi_monitor.last_poll, ast_tv(mwi_monitor.polling_interval, 0));
-               ts.tv_sec = tv.tv_sec;
-               ts.tv_nsec = tv.tv_usec * 1000;
+               polltime = ast_tvadd(mwi_monitor.last_poll, ast_tv(mwi_monitor.polling_interval, 0));
+               ts.tv_sec = polltime.tv_sec;
+               ts.tv_nsec = polltime.tv_usec * 1000;
                ast_cond_timedwait(&mwi_monitor.cond, &mwi_monitor.lock, &ts);
 
                ast_mutex_unlock(&mwi_monitor.lock);
@@ -833,7 +875,7 @@ static int smdi_load(int reload)
        int msdstrip = 0;              /* strip zero digits */
        long msg_expiry = SMDI_MSG_EXPIRY_TIME;
 
-       if (!(conf = ast_config_load(config_file, config_flags))) {
+       if (!(conf = ast_config_load(config_file, config_flags)) || conf == CONFIG_STATUS_FILEINVALID) {
                if (reload)
                        ast_log(LOG_NOTICE, "Unable to reload config %s: SMDI untouched\n", config_file);
                else
@@ -1147,7 +1189,7 @@ static int smdi_msg_retrieve_read(struct ast_channel *chan, const char *cmd, cha
        smd->id = ast_atomic_fetchadd_int((int *) &smdi_msg_id, 1);
        snprintf(buf, len, "%u", smd->id);
 
-       if (!(datastore = ast_channel_datastore_alloc(&smdi_msg_datastore_info, buf)))
+       if (!(datastore = ast_datastore_alloc(&smdi_msg_datastore_info, buf)))
                goto return_error;
 
        datastore->data = smd;
@@ -1245,7 +1287,7 @@ static int smdi_msg_read(struct ast_channel *chan, const char *cmd, char *data,
 return_error:
        ast_module_user_remove(u);
 
-       return 0;
+       return res;
 }
 
 static struct ast_custom_function smdi_msg_retrieve_function = {
@@ -1293,6 +1335,8 @@ static struct ast_custom_function smdi_msg_function = {
        .read = smdi_msg_read,
 };
 
+static int unload_module(void);
+
 static int load_module(void)
 {
        int res;
@@ -1310,8 +1354,10 @@ static int load_module(void)
        /* load the config and start the listener threads*/
        res = smdi_load(0);
        if (res < 0) {
+               unload_module();
                return res;
        } else if (res == 1) {
+               unload_module();
                ast_log(LOG_NOTICE, "No SMDI interfaces are available to listen on, not starting SMDI listener.\n");
                return AST_MODULE_LOAD_DECLINE;
        }