简体   繁体   中英

Asterisk create_stasis_message Invalid magic number

I stuck to send a stasis_message for a self made module to the ARI.

I try to use the code example from the documentation :

https://wiki.asterisk.org/wiki/display/AST/Stasis+Message+Bus

I use asterisk 13 instead example (who use the 12), and some signature are changed.

Here is the initialisation :

struct stasis_topic *foo_topic;

static int load_module(void)
{
    //  Register to stasis.
    stasis_app_register(app, callback_stasis, 0);
    // Create a bridge on witch ARI can conenct.
    stasis_app_bridge_create("mixing", app, "11000");

    // Create the topic
    foo_topic = stasis_topic_create(app);
    return ast_register_application_xml(app, exec);
}

And the code method who is calling when phone arrive :

static int exec()
{
    publish_foo();
}

static void publish_foo()
{
   printf("Trace 1\n");

   char* test =  "dataToSend";
   RAII_VAR(struct stasis_message_type*, foo_type, NULL, ao2_cleanup);
   stasis_message_type_create(app, NULL, &foo_type);

   RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
   printf("Trace 3\n");
   msg = stasis_message_create(type, test);

   if (!msg)
      return;

    stasis_publish(foo_topic, msg);

    printf("PASSING MESSAGE 4\n");
}

I always get message like :

bad magic number 0x332065 for object 0x7f2ea5ab8ec5

And this error appends in the method stasis_create_message().

[Edit]

I do not understand the error and the cause any help is appreciated.

As suggest by arheops, there is the function who are created problem. Apparently my object cannot be convert to an Asterisk object. Probably the structure I need to send to the create_message_function must be on a astobj2 type.

static struct astobj2 *INTERNAL_OBJ(void *user_data)
{
        struct astobj2 *p;

        if (!user_data) {
                ast_log(LOG_ERROR, "user_data is NULL\n");
                return NULL;
        }

        p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
        if (AO2_MAGIC != p->priv_data.magic) {
                if (p->priv_data.magic) {
                        ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
                                p->priv_data.magic, user_data);
                } else {
                        ast_log(LOG_ERROR,
                                "bad magic number for object %p. Object is likely destroyed.\n",
                                user_data);
                }
                ast_assert(0);
                return NULL;
        }

        return p;
}

And the struct of astobj2 definition :

struct astobj2 
{    
   struct __priv_data priv_data;
   void *user_data[0];
};

I tried to create a a2object like describe here , and I get an error :

*** Error in `asterisk': free(): invalid pointer:

Thanks

To send a stasis message, you need to create an a2object, normally you can perform this part with the macro :

RAII_VAR

But I cannot get a working example with this, so I create my-self the object with the following methods :

typedef struct ast_foo
{
    int n;

} ast_foo;

// Destructor is automatically called when the message is not referenced anymore.
static void foo_dtor(void *obj)
{
    struct foo *obj_foo = obj;
    // Free all resources you have reserve here.
}

/**
 * @return a ast_foo struct, with destructor setted.
 */
static struct ast_foo* make_me_a_foo(void)
{
    struct ast_foo *obj_foo;
    obj_foo = ao2_alloc(sizeof(ast_foo), foo_dtor);

    // if char* do malloc for them.
    if (!obj_foo) {
        ast_log(LOG_NOTICE, "make foo failed... 2\n");
        return NULL;
    }

    return obj_foo;
}

There is a full example for send and subscribe a stasis message :

static const char app[] = "StasisTest";
struct stasis_topic *foo_topic;

typedef struct ast_foo
{
    int n;

} ast_foo;

// Destructor automatically call when message is not referenced anymore.
static void foo_dtor(void *obj)
{
    struct foo *obj_foo = obj;
    // Free all resources you have reserve here.
}

/**
 * @return a ast_foo struct, with destructor setted.
 */
static struct ast_foo* make_me_a_foo(void)
{
    struct ast_foo *obj_foo;
    obj_foo = ao2_alloc(sizeof(ast_foo), foo_dtor);

    // if char* do malloc for them.
    if (!obj_foo) {
        ast_log(LOG_NOTICE, "make foo failed... 2\n");
        return NULL;
    }

    return obj_foo;
}

/**
 * Send a stasis message, with the long way...
 */
static void publish_foo()
{
    ast_log(LOG_NOTICE, "Enter publish message\n");
    RAII_VAR(struct stasis_message_type*, foo_type, NULL, ao2_cleanup);

    ast_log(LOG_NOTICE, "Create data to send\n");
    ast_foo* foo_data = make_me_a_foo();
    foo_data->n = 12;

    ast_log(LOG_NOTICE, "Create the message to send.\n");
    stasis_message_type_create(app, NULL, &foo_type);

    if (!foo_type)
    {
        ast_log(LOG_NOTICE, "Oh no my type is NULL \n");
    }
    else
    {
        ast_log(LOG_NOTICE, "Ok foo type \n");
    }

    RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
    msg = stasis_message_create(foo_type, foo_data);

    if (!msg)
    {
        ast_log(LOG_NOTICE, "Fail to send message\n");
        sleep(1);
        return;
    }

    stasis_publish(foo_topic, msg);
}

static int exec()
{
    // First method.
    publish_foo();

    return 0;
}

static int unload_module(void) {
    stasis_app_unregister(app);

    ao2_cleanup(foo_topic);
    foo_topic = NULL;
    return ast_unregister_application(app);
}


void bar_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
{
    ast_log(LOG_NOTICE, "Test stasis received a message from topic\n");
}

static int load_module(void) {
    stasis_init();

    // Register.
    ast_foo* foo_data2 = make_me_a_foo();
    foo_topic = stasis_topic_create("StasisTest");
    stasis_subscribe(foo_topic, bar_callback, foo_data2);

    return ast_register_application_xml(app, exec);
}

But there is a really more simpler way with the send of json object tought

#include "asterisk.h"

ASTERISK_FILE_VERSION(__FILE__, "$Revision$")

#include "asterisk/astobj2.h"
#include "asterisk/module.h"
#include "asterisk/stasis.h"
#include "asterisk/json.h"
#include "asterisk/stasis_app.h"

#include "StasisTest.h"

#define AST_MODULE "stasis_test"

static const char app[] = "StasisTest";

static int exec()
{
    // Second simpler method.
    struct ast_json* inte = ast_json_integer_create(51);
    int result = stasis_app_send("StasisTest", inte);
    ast_log(LOG_NOTICE, "Stasis send %d\n", result);

    return 0;
}

static int unload_module(void) 
{
    stasis_app_unregister(app);
    return ast_unregister_application(app);
}

//Test stasis
void callback_stasis(void* data, const char* app_name, struct ast_json* message)
{
    ast_log(LOG_NOTICE, "Receive a stasis message from json\n");

    int json_res = ast_json_integer_get(message);
    ast_log(LOG_NOTICE, "Integer get : %d\n", json_res);
}

static int load_module(void) {
    stasis_init();
    // Register for the short way.
    stasis_app_register(app, callback_stasis, 0);

    return ast_register_application_xml(app, exec);
}

AST_MODULE_INFO(ASTERISK_GPL_KEY, 0, "The wonders of foo", .load = load_module, .unload = unload_module);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM