Asterisk - The Open Source Telephony Project GIT-master-a358458
func_srv.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2010 Digium, Inc.
5 *
6 * See http://www.asterisk.org for more information about
7 * the Asterisk project. Please do not directly contact
8 * any of the maintainers of this project for assistance;
9 * the project provides a web site, mailing lists and IRC
10 * channels for your use.
11 *
12 * This program is free software, distributed under the terms of
13 * the GNU General Public License Version 2. See the LICENSE file
14 * at the top of the source tree.
15 */
16
17/*! \file
18 *
19 * \brief SRV Functions
20 *
21 * \author Mark Michelson <mmichelson@digium.com>
22 *
23 * \ingroup functions
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30#include "asterisk.h"
31
32#include "asterisk/module.h"
33#include "asterisk/srv.h"
34#include "asterisk/pbx.h"
35#include "asterisk/app.h"
36#include "asterisk/datastore.h"
37#include "asterisk/channel.h"
38
39/*** DOCUMENTATION
40 <function name="SRVQUERY" language="en_US">
41 <synopsis>
42 Initiate an SRV query.
43 </synopsis>
44 <syntax>
45 <parameter name="service" required="true">
46 <para>The service for which to look up SRV records. An example would be something
47 like <literal>_sip._udp.example.com</literal></para>
48 </parameter>
49 </syntax>
50 <description>
51 <para>This will do an SRV lookup of the given service.</para>
52 </description>
53 </function>
54 <function name="SRVRESULT" language="en_US">
55 <synopsis>
56 Retrieve results from an SRVQUERY.
57 </synopsis>
58 <syntax>
59 <parameter name="id" required="true">
60 <para>The identifier returned by the SRVQUERY function.</para>
61 </parameter>
62 <parameter name="resultnum" required="true">
63 <para>The number of the result that you want to retrieve.</para>
64 <para>Results start at <literal>1</literal>. If this argument is specified
65 as <literal>getnum</literal>, then it will return the total number of results
66 that are available.</para>
67 </parameter>
68 <parameter name="field" required="false">
69 <para>The field of the result to retrieve.</para>
70 <para>The fields that can be retrieved are:</para>
71 <enumlist>
72 <enum name="host"/>
73 <enum name="port"/>
74 <enum name="priority"/>
75 <enum name="weight"/>
76 </enumlist>
77 </parameter>
78 </syntax>
79 <description>
80 <para>This function will retrieve results from a previous use
81 of the SRVQUERY function.</para>
82 </description>
83 </function>
84 ***/
85
88 char id[1];
89};
90
91static void srds_destroy_cb(void *data)
92{
93 struct srv_result_datastore *datastore = data;
94 ast_srv_cleanup(&datastore->context);
95 ast_free(datastore);
96}
97
99 .type = "SRVQUERY",
100 .destroy = srds_destroy_cb,
101};
102
103static struct srv_context *srv_datastore_setup(const char *service, struct ast_channel *chan)
104{
105 struct srv_result_datastore *srds;
106 struct ast_datastore *datastore;
107 const char *host;
108 unsigned short port;
109
110 if (!(srds = ast_calloc(1, sizeof(*srds) + strlen(service)))) {
111 return NULL;
112 }
113
115 if (ast_srv_lookup(&srds->context, service, &host, &port) < 0) {
117 ast_log(LOG_NOTICE, "Error performing lookup of service '%s'\n", service);
118 ast_free(srds);
119 return NULL;
120 }
122
123 strcpy(srds->id, service);
124
125 if (!(datastore = ast_datastore_alloc(&srv_result_datastore_info, srds->id))) {
126 ast_srv_cleanup(&srds->context);
127 ast_free(srds);
128 return NULL;
129 }
130
131 datastore->data = srds;
132 ast_channel_lock(chan);
133 ast_channel_datastore_add(chan, datastore);
134 ast_channel_unlock(chan);
135 return srds->context;
136}
137
138static int srv_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
139{
140 struct ast_datastore *datastore;
141
142 if (!chan) {
143 ast_log(LOG_WARNING, "%s cannot be used without a channel\n", cmd);
144 return -1;
145 }
146
147 if (ast_strlen_zero(data)) {
148 ast_log(LOG_WARNING, "%s requires a service as an argument\n", cmd);
149 return -1;
150 }
151
152 /* If they already called SRVQUERY for this service once,
153 * we need to kill the old datastore.
154 */
155 ast_channel_lock(chan);
157 ast_channel_unlock(chan);
158
159 if (datastore) {
160 ast_channel_datastore_remove(chan, datastore);
161 ast_datastore_free(datastore);
162 }
163
164 if (!srv_datastore_setup(data, chan)) {
165 return -1;
166 }
167
169
170 return 0;
171}
172
174 .name = "SRVQUERY",
175 .read = srv_query_read,
176};
177
178static int srv_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
179{
180 struct srv_result_datastore *srds;
181 struct ast_datastore *datastore;
182 struct srv_context *srv_context;
183 char *parse;
184 const char *host;
185 unsigned short port, priority, weight;
186 unsigned int num;
188 AST_APP_ARG(id);
189 AST_APP_ARG(resultnum);
190 AST_APP_ARG(field);
191 );
192
193 if (!chan) {
194 ast_log(LOG_WARNING, "%s cannot be used without a channel\n", cmd);
195 return -1;
196 }
197
198 if (ast_strlen_zero(data)) {
199 ast_log(LOG_WARNING, "%s requires two arguments (id and resultnum)\n", cmd);
200 return -1;
201 }
202
203 parse = ast_strdupa(data);
204
206
207 ast_channel_lock(chan);
209 ast_channel_unlock(chan);
210
211 if (!datastore) {
212 /* They apparently decided to call SRVRESULT without first calling SRVQUERY.
213 * No problem, we'll do the SRV lookup now.
214 */
216 if (!srv_context) {
217 return -1;
218 }
219 } else {
220 srds = datastore->data;
221 srv_context = srds->context;
222 }
223
224 if (!strcasecmp(args.resultnum, "getnum")) {
225 snprintf(buf, len, "%u", ast_srv_get_record_count(srv_context));
226 return 0;
227 }
228
229 if (ast_strlen_zero(args.field)) {
230 ast_log(LOG_ERROR, "A field must be provided when requesting SRV data\n");
231 return -1;
232 }
233
234 if (sscanf(args.resultnum, "%30u", &num) != 1) {
235 ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to %s\n", args.resultnum, cmd);
236 return -1;
237 }
238
239 if (ast_srv_get_nth_record(srv_context, num, &host, &port, &priority, &weight)) {
240 ast_log(LOG_ERROR, "Failed to get record number %u for %s\n", num, cmd);
241 return -1;
242 }
243
244 if (!strcasecmp(args.field, "host")) {
245 ast_copy_string(buf, host, len);
246 } else if (!strcasecmp(args.field, "port")) {
247 snprintf(buf, len, "%d", port);
248 } else if (!strcasecmp(args.field, "priority")) {
249 snprintf(buf, len, "%d", priority);
250 } else if (!strcasecmp(args.field, "weight")) {
251 snprintf(buf, len, "%d", weight);
252 } else {
253 ast_log(LOG_WARNING, "Unrecognized SRV field '%s'\n", args.field);
254 return -1;
255 }
256
257 return 0;
258}
259
261 .name = "SRVRESULT",
262 .read = srv_result_read,
263};
264
265static int unload_module(void)
266{
267 int res = 0;
268
271
272 return res;
273}
274
275static int load_module(void)
276{
278 if (res < 0) {
280 }
282 if (res < 0) {
284 }
285
287}
288
289AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SRV related dialplan functions");
char weight
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
enum ast_cc_service_type service
Definition: ccss.c:383
static int priority
General Asterisk PBX channel definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2394
#define ast_channel_lock(chan)
Definition: channel.h:2922
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
#define ast_channel_unlock(chan)
Definition: channel.h:2923
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
Asterisk datastore objects.
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct ast_custom_function srv_result_function
Definition: func_srv.c:260
static const struct ast_datastore_info srv_result_datastore_info
Definition: func_srv.c:98
static struct srv_context * srv_datastore_setup(const char *service, struct ast_channel *chan)
Definition: func_srv.c:103
static struct ast_custom_function srv_query_function
Definition: func_srv.c:173
static int srv_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_srv.c:138
static void srds_destroy_cb(void *data)
Definition: func_srv.c:91
static int load_module(void)
Definition: func_srv.c:275
static int unload_module(void)
Definition: func_srv.c:265
static int srv_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_srv.c:178
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
Core PBX routines and definitions.
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
#define NULL
Definition: resample.c:96
Support for DNS SRV records, used in to locate SIP services.
unsigned int ast_srv_get_record_count(struct srv_context *context)
Get the number of records for a given SRV context.
Definition: srv.c:304
int ast_srv_get_nth_record(struct srv_context *context, int record_num, const char **host, unsigned short *port, unsigned short *priority, unsigned short *weight)
Retrieve details from a specific SRV record.
Definition: srv.c:309
void ast_srv_cleanup(struct srv_context **context)
Cleanup resources associated with ast_srv_lookup.
Definition: srv.c:248
int ast_srv_lookup(struct srv_context **context, const char *service, const char **host, unsigned short *port)
Retrieve set of SRV lookups, in order.
Definition: srv.c:202
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Main Channel structure associated with a channel.
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
struct srv_context * context
Definition: func_srv.c:87
const char * args