Constify some more channel driver technology callback parameters.
[asterisk/asterisk.git] / channels / chan_multicast_rtp.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  * Andreas 'MacBrody' Brodmann <andreas.brodmann@gmail.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 /*! \file
21  *
22  * \author Joshua Colp <jcolp@digium.com>
23  * \author Andreas 'MacBrody' Broadmann <andreas.brodmann@gmail.com>
24  *
25  * \brief Multicast RTP Paging Channel
26  *
27  * \ingroup channel_drivers
28  */
29
30 /*** MODULEINFO
31         <support_level>core</support_level>
32  ***/
33
34 #include "asterisk.h"
35
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37
38 #include <fcntl.h>
39 #include <sys/signal.h>
40
41 #include "asterisk/lock.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/config.h"
44 #include "asterisk/module.h"
45 #include "asterisk/pbx.h"
46 #include "asterisk/sched.h"
47 #include "asterisk/io.h"
48 #include "asterisk/acl.h"
49 #include "asterisk/callerid.h"
50 #include "asterisk/file.h"
51 #include "asterisk/cli.h"
52 #include "asterisk/app.h"
53 #include "asterisk/rtp_engine.h"
54 #include "asterisk/causes.h"
55
56 static const char tdesc[] = "Multicast RTP Paging Channel Driver";
57
58 /* Forward declarations */
59 static struct ast_channel *multicast_rtp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
60 static int multicast_rtp_call(struct ast_channel *ast, const char *dest, int timeout);
61 static int multicast_rtp_hangup(struct ast_channel *ast);
62 static struct ast_frame *multicast_rtp_read(struct ast_channel *ast);
63 static int multicast_rtp_write(struct ast_channel *ast, struct ast_frame *f);
64
65 /* Channel driver declaration */
66 static struct ast_channel_tech multicast_rtp_tech = {
67         .type = "MulticastRTP",
68         .description = tdesc,
69         .requester = multicast_rtp_request,
70         .call = multicast_rtp_call,
71         .hangup = multicast_rtp_hangup,
72         .read = multicast_rtp_read,
73         .write = multicast_rtp_write,
74 };
75
76 /*! \brief Function called when we should read a frame from the channel */
77 static struct ast_frame  *multicast_rtp_read(struct ast_channel *ast)
78 {
79         return &ast_null_frame;
80 }
81
82 /*! \brief Function called when we should write a frame to the channel */
83 static int multicast_rtp_write(struct ast_channel *ast, struct ast_frame *f)
84 {
85         struct ast_rtp_instance *instance = ast->tech_pvt;
86
87         return ast_rtp_instance_write(instance, f);
88 }
89
90 /*! \brief Function called when we should actually call the destination */
91 static int multicast_rtp_call(struct ast_channel *ast, const char *dest, int timeout)
92 {
93         struct ast_rtp_instance *instance = ast->tech_pvt;
94
95         ast_queue_control(ast, AST_CONTROL_ANSWER);
96
97         return ast_rtp_instance_activate(instance);
98 }
99
100 /*! \brief Function called when we should hang the channel up */
101 static int multicast_rtp_hangup(struct ast_channel *ast)
102 {
103         struct ast_rtp_instance *instance = ast->tech_pvt;
104
105         ast_rtp_instance_destroy(instance);
106
107         ast->tech_pvt = NULL;
108
109         return 0;
110 }
111
112 /*! \brief Function called when we should prepare to call the destination */
113 static struct ast_channel *multicast_rtp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
114 {
115         char *tmp = ast_strdupa(data), *multicast_type = tmp, *destination, *control;
116         struct ast_rtp_instance *instance;
117         struct ast_sockaddr control_address;
118         struct ast_sockaddr destination_address;
119         struct ast_channel *chan;
120         struct ast_format fmt;
121         ast_best_codec(cap, &fmt);
122
123         ast_sockaddr_setnull(&control_address);
124
125         /* If no type was given we can't do anything */
126         if (ast_strlen_zero(multicast_type)) {
127                 goto failure;
128         }
129
130         if (!(destination = strchr(tmp, '/'))) {
131                 goto failure;
132         }
133         *destination++ = '\0';
134
135         if ((control = strchr(destination, '/'))) {
136                 *control++ = '\0';
137                 if (!ast_sockaddr_parse(&control_address, control,
138                                         PARSE_PORT_REQUIRE)) {
139                         goto failure;
140                 }
141         }
142
143         if (!ast_sockaddr_parse(&destination_address, destination,
144                                 PARSE_PORT_REQUIRE)) {
145                 goto failure;
146         }
147
148         if (!(instance = ast_rtp_instance_new("multicast", NULL, &control_address, multicast_type))) {
149                 goto failure;
150         }
151
152         if (!(chan = ast_channel_alloc(1, AST_STATE_DOWN, "", "", "", "", "", requestor ? ast_channel_linkedid(requestor) : "", 0, "MulticastRTP/%p", instance))) {
153                 ast_rtp_instance_destroy(instance);
154                 goto failure;
155         }
156
157         ast_rtp_instance_set_remote_address(instance, &destination_address);
158
159         chan->tech = &multicast_rtp_tech;
160
161         ast_format_cap_add(chan->nativeformats, &fmt);
162         ast_format_copy(&chan->writeformat, &fmt);
163         ast_format_copy(&chan->rawwriteformat, &fmt);
164         ast_format_copy(&chan->readformat, &fmt);
165         ast_format_copy(&chan->rawreadformat, &fmt);
166
167         chan->tech_pvt = instance;
168
169         return chan;
170
171 failure:
172         *cause = AST_CAUSE_FAILURE;
173         return NULL;
174 }
175
176 /*! \brief Function called when our module is loaded */
177 static int load_module(void)
178 {
179         if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc())) {
180                 return AST_MODULE_LOAD_DECLINE;
181         }
182         ast_format_cap_add_all(multicast_rtp_tech.capabilities);
183         if (ast_channel_register(&multicast_rtp_tech)) {
184                 ast_log(LOG_ERROR, "Unable to register channel class 'MulticastRTP'\n");
185                 return AST_MODULE_LOAD_DECLINE;
186         }
187
188         return AST_MODULE_LOAD_SUCCESS;
189 }
190
191 /*! \brief Function called when our module is unloaded */
192 static int unload_module(void)
193 {
194         ast_channel_unregister(&multicast_rtp_tech);
195         multicast_rtp_tech.capabilities = ast_format_cap_destroy(multicast_rtp_tech.capabilities);
196
197         return 0;
198 }
199
200 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Multicast RTP Paging Channel",
201         .load = load_module,
202         .unload = unload_module,
203         .load_pri = AST_MODPRI_CHANNEL_DRIVER,
204 );