Asterisk - The Open Source Telephony Project GIT-master-3dae2cf
stasis_message.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * David M. Lee, II <dlee@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Stasis Message API.
22 *
23 * \author David M. Lee, II <dlee@digium.com>
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30#include "asterisk.h"
31
32#include "asterisk/astobj2.h"
33#include "asterisk/stasis.h"
34#include "asterisk/utils.h"
35#include "asterisk/hashtab.h"
36
37/*! \internal */
40 char *name;
41 unsigned int hash;
42 int id;
44};
45
47static int message_type_id;
48
49static void message_type_dtor(void *obj)
50{
51 struct stasis_message_type *type = obj;
52 ast_free(type->name);
53 type->name = NULL;
54}
55
59{
61
62 /* Check for declination */
65 }
66
69 if (!type) {
71 }
72 if (!vtable) {
73 /* Null object pattern, FTW! */
75 }
76
77 type->name = ast_strdup(name);
78 if (!type->name) {
81 }
83 type->vtable = vtable;
84 if (vtable->to_json) {
85 type->available_formatters |= STASIS_SUBSCRIPTION_FORMATTER_JSON;
86 }
87 if (vtable->to_ami) {
88 type->available_formatters |= STASIS_SUBSCRIPTION_FORMATTER_AMI;
89 }
90 if (vtable->to_event) {
91 type->available_formatters |= STASIS_SUBSCRIPTION_FORMATTER_EVENT;
92 }
94 *result = type;
95
97}
98
100{
101 return type->name;
102}
103
105{
106 return type->hash;
107}
108
110{
111 return type->id;
112}
113
115 const struct stasis_message_type *type)
116{
117 return type->available_formatters;
118}
119
120/*! \internal */
122 /*! Time the message was created */
123 struct timeval timestamp;
124 /*! Type of the message */
126 /*! Where this message originated. NULL if aggregate message. */
127 const struct ast_eid *eid_ptr;
128 /*! Message content */
129 void *data;
130 /*! Where this message originated. */
131 struct ast_eid eid;
132};
133
134static void stasis_message_dtor(void *obj)
135{
136 struct stasis_message *message = obj;
137 ao2_cleanup(message->data);
138}
139
141{
142 struct stasis_message *message;
143
144 if (type == NULL || data == NULL) {
145 return NULL;
146 }
147
150 if (message == NULL) {
151 return NULL;
152 }
153
154 message->timestamp = ast_tvnow();
155 /*
156 * XXX Normal ao2 ref counting rules says we should increment the message
157 * type ref here and decrement it in stasis_message_dtor(). However, the
158 * stasis message could be cached and legitimately cause the type ref count
159 * to hit the excessive ref count assertion. Since the message type
160 * practically has to be a global object anyway, we can get away with not
161 * holding a ref in the stasis message.
162 */
163 message->type = type;
164 ao2_ref(data, +1);
165 message->data = data;
166 if (eid) {
167 message->eid_ptr = &message->eid;
168 message->eid = *eid;
169 }
170
171 return message;
172}
173
175{
177}
178
179const struct ast_eid *stasis_message_eid(const struct stasis_message *msg)
180{
181 if (msg == NULL) {
182 return NULL;
183 }
184 return msg->eid_ptr;
185}
186
188{
189 if (msg == NULL) {
190 return NULL;
191 }
192 return msg->type;
193}
194
195void *stasis_message_data(const struct stasis_message *msg)
196{
197 if (msg == NULL) {
198 return NULL;
199 }
200 return msg->data;
201}
202
203const struct timeval *stasis_message_timestamp(const struct stasis_message *msg)
204{
205 if (msg == NULL) {
206 return NULL;
207 }
208 return &msg->timestamp;
209}
210
211#define INVOKE_VIRTUAL(fn, ...) \
212 ({ \
213 if (!msg) { \
214 return NULL; \
215 } \
216 ast_assert(msg->type != NULL); \
217 ast_assert(msg->type->vtable != NULL); \
218 if (!msg->type->vtable->fn) { \
219 return NULL; \
220 } \
221 msg->type->vtable->fn(__VA_ARGS__); \
222 })
223
225{
226 return INVOKE_VIRTUAL(to_ami, msg);
227}
228
230 struct stasis_message *msg,
231 struct stasis_message_sanitizer *sanitize)
232{
233 return INVOKE_VIRTUAL(to_json, msg, sanitize);
234}
235
237{
238 return INVOKE_VIRTUAL(to_event, msg);
239}
240
241#define HAS_VIRTUAL(fn, msg) \
242 ({ \
243 if (!msg) { \
244 return 0; \
245 } \
246 ast_assert(msg->type != NULL); \
247 ast_assert(msg->type->vtable != NULL); \
248 !!msg->type->vtable->fn; \
249 })
250
252{
253 return HAS_VIRTUAL(to_ami, msg);
254}
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:402
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
static PGresult * result
Definition: cel_pgsql.c:84
static const char type[]
Definition: chan_ooh323.c:109
static const char name[]
Definition: format_mp3.c:68
Generic (perhaps overly so) hashtable implementation Hash Table support in Asterisk.
unsigned int ast_hashtab_hash_string(const void *obj)
Hashes a string to a number.
Definition: hashtab.c:153
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
static void to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
#define NULL
Definition: resample.c:96
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
stasis_subscription_message_formatters
Stasis subscription formatter filters.
Definition: stasis.h:308
@ STASIS_SUBSCRIPTION_FORMATTER_EVENT
Definition: stasis.h:312
@ STASIS_SUBSCRIPTION_FORMATTER_AMI
Definition: stasis.h:311
@ STASIS_SUBSCRIPTION_FORMATTER_JSON
Definition: stasis.h:310
int stasis_message_type_declined(const char *name)
Check whether a message type is declined.
Definition: stasis.c:2284
stasis_message_type_result
Return code for Stasis message type creation attempts.
Definition: stasis.h:285
@ STASIS_MESSAGE_TYPE_DECLINED
Definition: stasis.h:288
@ STASIS_MESSAGE_TYPE_ERROR
Definition: stasis.h:286
@ STASIS_MESSAGE_TYPE_SUCCESS
Definition: stasis.h:287
struct ast_manager_event_blob * stasis_message_to_ami(struct stasis_message *msg)
Build the AMI representation of the message.
#define HAS_VIRTUAL(fn, msg)
unsigned int stasis_message_type_hash(const struct stasis_message_type *type)
Gets the hash of a given message type.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
enum stasis_subscription_message_formatters stasis_message_type_available_formatters(const struct stasis_message_type *type)
Get a bitmap of available formatters for a message type.
struct ast_json * stasis_message_to_json(struct stasis_message *msg, struct stasis_message_sanitizer *sanitize)
Build the JSON representation of the message.
static void message_type_dtor(void *obj)
static void stasis_message_dtor(void *obj)
const struct ast_eid * stasis_message_eid(const struct stasis_message *msg)
Get the entity id for a stasis_message.
struct ast_event * stasis_message_to_event(struct stasis_message *msg)
Build the Generic event system representation of the message.
static int message_type_id
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
enum stasis_message_type_result stasis_message_type_create(const char *name, struct stasis_message_vtable *vtable, struct stasis_message_type **result)
Create a new message type.
const char * stasis_message_type_name(const struct stasis_message_type *type)
Gets the name of a given message type.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
int stasis_message_type_id(const struct stasis_message_type *type)
Gets the id of a given message type.
struct stasis_message * stasis_message_create_full(struct stasis_message_type *type, void *data, const struct ast_eid *eid)
Create a new message for an entity.
#define INVOKE_VIRTUAL(fn,...)
static struct stasis_message_vtable null_vtable
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
int stasis_message_can_be_ami(struct stasis_message *msg)
Determine if the given message can be converted to AMI.
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:813
An event.
Definition: event.c:81
Abstract JSON element (object, array, string, int, ...).
Struct containing info for an AMI event to send out.
Definition: manager.h:502
Structure containing callbacks for Stasis message sanitization.
Definition: stasis.h:200
struct stasis_message_vtable * vtable
enum stasis_subscription_message_formatters available_formatters
Virtual table providing methods for messages.
Definition: stasis.h:239
struct ast_manager_event_blob *(* to_ami)(struct stasis_message *message)
Build the AMI representation of the message.
Definition: stasis.h:264
struct ast_json *(* to_json)(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
Build the JSON representation of the message.
Definition: stasis.h:252
struct ast_event *(* to_event)(struct stasis_message *message)
Build the ast_event representation of the message.
Definition: stasis.h:278
struct timeval timestamp
struct stasis_message_type * type
struct ast_eid eid
const struct ast_eid * eid_ptr
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
Utility functions.
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93