Asterisk - The Open Source Telephony Project GIT-master-8924258
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 <since>
42 <version>1.8.0</version>
43 </since>
44 <synopsis>
45 Initiate an SRV query.
46 </synopsis>
47 <syntax>
48 <parameter name="service" required="true">
49 <para>The service for which to look up SRV records. An example would be something
50 like <literal>_sip._udp.example.com</literal></para>
51 </parameter>
52 </syntax>
53 <description>
54 <para>This will do an SRV lookup of the given service.</para>
55 </description>
56 </function>
57 <function name="SRVRESULT" language="en_US">
58 <since>
59 <version>1.8.0</version>
60 </since>
61 <synopsis>
62 Retrieve results from an SRVQUERY.
63 </synopsis>
64 <syntax>
65 <parameter name="id" required="true">
66 <para>The identifier returned by the SRVQUERY function.</para>
67 </parameter>
68 <parameter name="resultnum" required="true">
69 <para>The number of the result that you want to retrieve.</para>
70 <para>Results start at <literal>1</literal>. If this argument is specified
71 as <literal>getnum</literal>, then it will return the total number of results
72 that are available.</para>
73 </parameter>
74 <parameter name="field" required="false">
75 <para>The field of the result to retrieve.</para>
76 <para>The fields that can be retrieved are:</para>
77 <enumlist>
78 <enum name="host"/>
79 <enum name="port"/>
80 <enum name="priority"/>
81 <enum name="weight"/>
82 </enumlist>
83 </parameter>
84 </syntax>
85 <description>
86 <para>This function will retrieve results from a previous use
87 of the SRVQUERY function.</para>
88 </description>
89 </function>
90 ***/
91
94 char id[1];
95};
96
97static void srds_destroy_cb(void *data)
98{
99 struct srv_result_datastore *datastore = data;
100 ast_srv_cleanup(&datastore->context);
101 ast_free(datastore);
102}
103
105 .type = "SRVQUERY",
106 .destroy = srds_destroy_cb,
107};
108
109static struct srv_context *srv_datastore_setup(const char *service, struct ast_channel *chan)
110{
111 struct srv_result_datastore *srds;
112 struct ast_datastore *datastore;
113 const char *host;
114 unsigned short port;
115
116 if (!(srds = ast_calloc(1, sizeof(*srds) + strlen(service)))) {
117 return NULL;
118 }
119
121 if (ast_srv_lookup(&srds->context, service, &host, &port) < 0) {
123 ast_log(LOG_NOTICE, "Error performing lookup of service '%s'\n", service);
124 ast_free(srds);
125 return NULL;
126 }
128
129 strcpy(srds->id, service);
130
131 if (!(datastore = ast_datastore_alloc(&srv_result_datastore_info, srds->id))) {
132 ast_srv_cleanup(&srds->context);
133 ast_free(srds);
134 return NULL;
135 }
136
137 datastore->data = srds;
138 ast_channel_lock(chan);
139 ast_channel_datastore_add(chan, datastore);
140 ast_channel_unlock(chan);
141 return srds->context;
142}
143
144static int srv_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
145{
146 struct ast_datastore *datastore;
147
148 if (!chan) {
149 ast_log(LOG_WARNING, "%s cannot be used without a channel\n", cmd);
150 return -1;
151 }
152
153 if (ast_strlen_zero(data)) {
154 ast_log(LOG_WARNING, "%s requires a service as an argument\n", cmd);
155 return -1;
156 }
157
158 /* If they already called SRVQUERY for this service once,
159 * we need to kill the old datastore.
160 */
161 ast_channel_lock(chan);
163 ast_channel_unlock(chan);
164
165 if (datastore) {
166 ast_channel_datastore_remove(chan, datastore);
167 ast_datastore_free(datastore);
168 }
169
170 if (!srv_datastore_setup(data, chan)) {
171 return -1;
172 }
173
175
176 return 0;
177}
178
180 .name = "SRVQUERY",
181 .read = srv_query_read,
182};
183
184static int srv_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
185{
186 struct srv_result_datastore *srds;
187 struct ast_datastore *datastore;
188 struct srv_context *srv_context;
189 char *parse;
190 const char *host;
191 unsigned short port, priority, weight;
192 unsigned int num;
194 AST_APP_ARG(id);
195 AST_APP_ARG(resultnum);
196 AST_APP_ARG(field);
197 );
198
199 if (!chan) {
200 ast_log(LOG_WARNING, "%s cannot be used without a channel\n", cmd);
201 return -1;
202 }
203
204 if (ast_strlen_zero(data)) {
205 ast_log(LOG_WARNING, "%s requires two arguments (id and resultnum)\n", cmd);
206 return -1;
207 }
208
209 parse = ast_strdupa(data);
210
212
213 ast_channel_lock(chan);
215 ast_channel_unlock(chan);
216
217 if (!datastore) {
218 /* They apparently decided to call SRVRESULT without first calling SRVQUERY.
219 * No problem, we'll do the SRV lookup now.
220 */
222 if (!srv_context) {
223 return -1;
224 }
225 } else {
226 srds = datastore->data;
227 srv_context = srds->context;
228 }
229
230 if (!strcasecmp(args.resultnum, "getnum")) {
231 snprintf(buf, len, "%u", ast_srv_get_record_count(srv_context));
232 return 0;
233 }
234
235 if (ast_strlen_zero(args.field)) {
236 ast_log(LOG_ERROR, "A field must be provided when requesting SRV data\n");
237 return -1;
238 }
239
240 if (sscanf(args.resultnum, "%30u", &num) != 1) {
241 ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to %s\n", args.resultnum, cmd);
242 return -1;
243 }
244
245 if (ast_srv_get_nth_record(srv_context, num, &host, &port, &priority, &weight)) {
246 ast_log(LOG_ERROR, "Failed to get record number %u for %s\n", num, cmd);
247 return -1;
248 }
249
250 if (!strcasecmp(args.field, "host")) {
251 ast_copy_string(buf, host, len);
252 } else if (!strcasecmp(args.field, "port")) {
253 snprintf(buf, len, "%d", port);
254 } else if (!strcasecmp(args.field, "priority")) {
255 snprintf(buf, len, "%d", priority);
256 } else if (!strcasecmp(args.field, "weight")) {
257 snprintf(buf, len, "%d", weight);
258 } else {
259 ast_log(LOG_WARNING, "Unrecognized SRV field '%s'\n", args.field);
260 return -1;
261 }
262
263 return 0;
264}
265
267 .name = "SRVRESULT",
268 .read = srv_result_read,
269};
270
271static int unload_module(void)
272{
273 int res = 0;
274
277
278 return res;
279}
280
281static int load_module(void)
282{
284 if (res < 0) {
286 }
288 if (res < 0) {
290 }
291
293}
294
295AST_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:389
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:2414
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2423
#define ast_channel_lock(chan)
Definition: channel.h:2970
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:2971
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:2428
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:266
static const struct ast_datastore_info srv_result_datastore_info
Definition: func_srv.c:104
static struct srv_context * srv_datastore_setup(const char *service, struct ast_channel *chan)
Definition: func_srv.c:109
static struct ast_custom_function srv_query_function
Definition: func_srv.c:179
static int srv_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_srv.c:144
static void srds_destroy_cb(void *data)
Definition: func_srv.c:97
static int load_module(void)
Definition: func_srv.c:281
static int unload_module(void)
Definition: func_srv.c:271
static int srv_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_srv.c:184
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:581
#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:1559
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:93
const char * args