SIP channel name uniqueness
[asterisk/asterisk.git] / funcs / func_connectedline.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007, Gareth Palmer
5  *
6  * Gareth Palmer <gareth@acsdata.co.nz>
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 Connected Line dialplan function
22  *
23  * \ingroup functions
24  */
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <sys/types.h>
34
35 #include "asterisk/module.h"
36 #include "asterisk/channel.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/logger.h"
39 #include "asterisk/utils.h"
40 #include "asterisk/app.h"
41 #include "asterisk/options.h"
42 #include "asterisk/callerid.h"
43
44 /*
45  * Do not document the CONNECTEDLINE(source) datatype.
46  * It has turned out to not be needed.  The source value is really
47  * only useful as a possible tracing aid.
48  */
49 /*** DOCUMENTATION
50         <function name="CONNECTEDLINE" language="en_US">
51                 <synopsis>
52                         Gets or sets Connected Line data on the channel.
53                 </synopsis>
54                 <syntax>
55                         <parameter name="datatype" required="true">
56                                 <para>The allowable datatypes are:</para>
57                                 <enumlist>
58                                         <enum name = "all" />
59                                         <enum name = "num" />
60                                         <enum name = "name" />
61                                         <enum name = "ton" />
62                                         <enum name = "pres" />
63                                         <enum name = "subaddr[-valid]|[-type]|[-odd]">
64                                                 <para>ISDN Connected line subaddress</para>
65                                         </enum>
66                                 </enumlist>
67                         </parameter>
68                         <parameter name="i">
69                                 <para>If set, this will prevent the channel from sending out protocol
70                                 messages because of the value being set</para>
71                         </parameter>
72                 </syntax>
73                 <description>
74                         <para>Gets or sets Connected Line data on the channel.</para>
75                 </description>
76         </function>
77  ***/
78
79 static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data,
80                               char *buf, size_t len)
81 {
82         /* Ensure that the buffer is empty */
83         *buf = 0;
84
85         if (!chan)
86                 return -1;
87
88         ast_channel_lock(chan);
89
90         if (!strncasecmp("all", data, 3)) {
91                 snprintf(buf, len, "\"%s\" <%s>",
92                          S_OR(chan->connected.id.name, ""),
93                          S_OR(chan->connected.id.number, ""));
94         } else if (!strncasecmp("name", data, 4)) {
95                 if (chan->connected.id.name) {
96                         ast_copy_string(buf, chan->connected.id.name, len);
97                 }
98         } else if (!strncasecmp("num", data, 3)) {
99                 if (chan->connected.id.number) {
100                         ast_copy_string(buf, chan->connected.id.number, len);
101                 }
102         } else if (!strncasecmp("ton", data, 3)) {
103                 snprintf(buf, len, "%d", chan->connected.id.number_type);
104         } else if (!strncasecmp("pres", data, 4)) {
105                 ast_copy_string(buf, ast_named_caller_presentation(chan->connected.id.number_presentation), len);
106         } else if (!strncasecmp("source", data, 6)) {
107                 ast_copy_string(buf, ast_connected_line_source_name(chan->connected.source), len);
108         } else if (!strncasecmp("subaddr", data, 7)) {
109                 /* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
110                 if (!strncasecmp(data + 7 ,"-valid", 6)) {              /* subaddr-valid */
111                         snprintf(buf, len, "%d", chan->connected.id.subaddress.valid);
112                 } else if (!strncasecmp(data + 7 ,"-type", 5)) {        /* subaddr-type */
113                         snprintf(buf, len, "%d", chan->connected.id.subaddress.type);
114                 } else if (!strncasecmp(data + 7 ,"-odd", 4)) {         /* subaddr-odd */
115                         snprintf(buf, len, "%d", chan->connected.id.subaddress.odd_even_indicator);
116                 } else {                                                /* subaddr */
117                         if (chan->connected.id.subaddress.str) {
118                                 ast_copy_string(buf, chan->connected.id.subaddress.str, len);
119                         }
120                 }
121         } else {
122                 ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
123         }
124
125         ast_channel_unlock(chan);
126
127         return 0;
128 }
129
130 static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data,
131                                const char *value)
132 {
133         struct ast_party_connected_line connected;
134         char *val;
135         char *option;
136         void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected);
137
138         if (!value || !chan) {
139                 return -1;
140         }
141
142         /* Determine if the update indication inhibit option is present */
143         option = strchr(data, ',');
144         if (option) {
145                 option = ast_skip_blanks(option + 1);
146                 switch (*option) {
147                 case 'i':
148                         set_it = ast_channel_set_connected_line;
149                         break;
150
151                 default:
152                         ast_log(LOG_ERROR, "Unknown connectedline option '%s'.\n", option);
153                         return 0;
154                 }
155         }
156         else {
157                 set_it = ast_channel_update_connected_line;
158         }
159
160         ast_channel_lock(chan);
161         ast_party_connected_line_set_init(&connected, &chan->connected);
162         ast_channel_unlock(chan);
163
164         value = ast_skip_blanks(value);
165
166         if (!strncasecmp("all", data, 3)) {
167                 char name[256];
168                 char num[256];
169
170                 ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
171                 connected.id.name = name;
172                 connected.id.number = num;
173                 set_it(chan, &connected);
174         } else if (!strncasecmp("name", data, 4)) {
175                 connected.id.name = ast_strdupa(value);
176                 ast_trim_blanks(connected.id.name);
177                 set_it(chan, &connected);
178         } else if (!strncasecmp("num", data, 3)) {
179                 connected.id.number = ast_strdupa(value);
180                 ast_trim_blanks(connected.id.number);
181                 set_it(chan, &connected);
182         } else if (!strncasecmp("ton", data, 3)) {
183                 val = ast_strdupa(value);
184                 ast_trim_blanks(val);
185
186                 if (('0' <= val[0]) && (val[0] <= '9')) {
187                         connected.id.number_type = atoi(val);
188                         set_it(chan, &connected);
189                 } else {
190                         ast_log(LOG_ERROR, "Unknown connectedline type of number '%s', value unchanged\n", val);
191                 }
192         } else if (!strncasecmp("pres", data, 4)) {
193                 int pres;
194
195                 val = ast_strdupa(value);
196                 ast_trim_blanks(val);
197
198                 if (('0' <= val[0]) && (val[0] <= '9')) {
199                         pres = atoi(val);
200                 } else {
201                         pres = ast_parse_caller_presentation(val);
202                 }
203
204                 if (pres < 0) {
205                         ast_log(LOG_ERROR, "Unknown connectedline number presentation '%s', value unchanged\n", val);
206                 } else {
207                         connected.id.number_presentation = pres;
208                         set_it(chan, &connected);
209                 }
210         } else if (!strncasecmp("source", data, 6)) {
211                 int source;
212
213                 val = ast_strdupa(value);
214                 ast_trim_blanks(val);
215
216                 if (('0' <= val[0]) && (val[0] <= '9')) {
217                         source = atoi(val);
218                 } else {
219                         source = ast_connected_line_source_parse(val);
220                 }
221
222                 if (source < 0) {
223                         ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
224                 } else {
225                         connected.source = source;
226                         set_it(chan, &connected);
227                 }
228         } else if (!strncasecmp("subaddr", data, 7)) { /* outbound: set calling subaddress */
229                 /* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
230                 if (!strncasecmp(data + 7 ,"-valid", 6)) {              /* subaddr-valid */
231                         connected.id.subaddress.valid = atoi(value) ? 1 : 0;
232                 } else if (!strncasecmp(data + 7 ,"-type", 5)) {        /* subaddr-type */
233                         connected.id.subaddress.type = atoi(value) ? 2 : 0;
234                 } else if (!strncasecmp(data + 7 ,"-odd", 4)) {         /* subaddr-odd */
235                         connected.id.subaddress.odd_even_indicator = atoi(value) ? 1 : 0;
236                 } else {                                                /* subaddr */
237                         connected.id.subaddress.str = ast_strdupa(value);
238                         ast_trim_blanks(connected.id.subaddress.str);
239                 }
240                 set_it(chan, &connected);
241         } else {
242                 ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
243         }
244
245         return 0;
246 }
247
248 static struct ast_custom_function connectedline_function = {
249         .name = "CONNECTEDLINE",
250         .read = connectedline_read,
251         .write = connectedline_write,
252 };
253
254 static int unload_module(void)
255 {
256         return ast_custom_function_unregister(&connectedline_function);
257 }
258
259 static int load_module(void)
260 {
261         return ast_custom_function_register(&connectedline_function)
262                 ? AST_MODULE_LOAD_DECLINE
263                 : AST_MODULE_LOAD_SUCCESS;
264 }
265
266 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Connected Line dialplan function");