Review Board 1.7.16


chan_rtp: Add unicast RTP support to chan_multicast_rtp.

Review Request #3981 - Created Sept. 7, 2014 and submitted

Joshua Colp
Reviewers
asterisk-dev
Asterisk
The chan_multicast_rtp module currently allows sending an RTP stream as multicast but not unicast. Using unicast allows the channel to become a thin protocol-less transport mechanism for media. To that end I've added unicast RTP support and moved both into a single channel driver (chan_rtp) as they shared most of the code. Cleanup of some code also occurred.
Originated a call to a UnicastRTP channel and sent it to a Playback. Confirmed that RTP was sent to the provided IP address/port with the given format.

Diff revision 1 (Latest)

  1. /trunk/channels/chan_multicast_rtp.c: Loading...
  2. /trunk/channels/chan_rtp.c: Loading...
/trunk/channels/chan_multicast_rtp.c
Revision 422835 New Change
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_assigned_ids *assignedids, 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_channel_tech_pvt(ast);

   
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_channel_tech_pvt(ast);

   
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_channel_tech_pvt(ast);

   
104

    
   

   
105
	ast_rtp_instance_destroy(instance);

   
106

    
   

   
107
	ast_channel_tech_pvt_set(ast, 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_assigned_ids *assignedids, 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_cap *caps = NULL;

   
121
	struct ast_format *fmt = NULL;

   
122

    
   

   
123
	fmt = ast_format_cap_get_format(cap, 0);

   
124

    
   

   
125
	ast_sockaddr_setnull(&control_address);

   
126

    
   

   
127
	/* If no type was given we can't do anything */

   
128
	if (ast_strlen_zero(multicast_type)) {

   
129
		goto failure;

   
130
	}

   
131

    
   

   
132
	if (!(destination = strchr(tmp, '/'))) {

   
133
		goto failure;

   
134
	}

   
135
	*destination++ = '\0';

   
136

    
   

   
137
	if ((control = strchr(destination, '/'))) {

   
138
		*control++ = '\0';

   
139
		if (!ast_sockaddr_parse(&control_address, control,

   
140
					PARSE_PORT_REQUIRE)) {

   
141
			goto failure;

   
142
		}

   
143
	}

   
144

    
   

   
145
	if (!ast_sockaddr_parse(&destination_address, destination,

   
146
				PARSE_PORT_REQUIRE)) {

   
147
		goto failure;

   
148
	}

   
149

    
   

   
150
	caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);

   
151
	if (!caps) {

   
152
		goto failure;

   
153
	}

   
154

    
   

   
155
	if (!(instance = ast_rtp_instance_new("multicast", NULL, &control_address, multicast_type))) {

   
156
		goto failure;

   
157
	}

   
158

    
   

   
159
	if (!(chan = ast_channel_alloc(1, AST_STATE_DOWN, "", "", "", "", "", assignedids, requestor, 0, "MulticastRTP/%p", instance))) {

   
160
		ast_rtp_instance_destroy(instance);

   
161
		goto failure;

   
162
	}

   
163
	ast_rtp_instance_set_channel_id(instance, ast_channel_uniqueid(chan));

   
164
	ast_rtp_instance_set_remote_address(instance, &destination_address);

   
165

    
   

   
166
	ast_channel_tech_set(chan, &multicast_rtp_tech);

   
167

    
   

   
168
	ast_format_cap_append(caps, fmt, 0);

   
169
	ast_channel_nativeformats_set(chan, caps);

   
170
	ast_channel_set_writeformat(chan, fmt);

   
171
	ast_channel_set_rawwriteformat(chan, fmt);

   
172
	ast_channel_set_readformat(chan, fmt);

   
173
	ast_channel_set_rawreadformat(chan, fmt);

   
174

    
   

   
175
	ast_channel_tech_pvt_set(chan, instance);

   
176

    
   

   
177
	ast_channel_unlock(chan);

   
178

    
   

   
179
	ao2_ref(fmt, -1);

   
180
	ao2_ref(caps, -1);

   
181

    
   

   
182
	return chan;

   
183

    
   

   
184
failure:

   
185
	ao2_cleanup(fmt);

   
186
	ao2_cleanup(caps);

   
187
	*cause = AST_CAUSE_FAILURE;

   
188
	return NULL;

   
189
}

   
190

    
   

   
191
/*! \brief Function called when our module is loaded */

   
192
static int load_module(void)

   
193
{

   
194
	if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {

   
195
		return AST_MODULE_LOAD_DECLINE;

   
196
	}

   
197
	ast_format_cap_append_by_type(multicast_rtp_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);

   
198
	if (ast_channel_register(&multicast_rtp_tech)) {

   
199
		ast_log(LOG_ERROR, "Unable to register channel class 'MulticastRTP'\n");

   
200
		ao2_ref(multicast_rtp_tech.capabilities, -1);

   
201
		multicast_rtp_tech.capabilities = NULL;

   
202
		return AST_MODULE_LOAD_DECLINE;

   
203
	}

   
204

    
   

   
205
	return AST_MODULE_LOAD_SUCCESS;

   
206
}

   
207

    
   

   
208
/*! \brief Function called when our module is unloaded */

   
209
static int unload_module(void)

   
210
{

   
211
	ast_channel_unregister(&multicast_rtp_tech);

   
212
	ao2_ref(multicast_rtp_tech.capabilities, -1);

   
213
	multicast_rtp_tech.capabilities = NULL;

   
214

    
   

   
215
	return 0;

   
216
}

   
217

    
   

   
218
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Multicast RTP Paging Channel",

   
219
	.support_level = AST_MODULE_SUPPORT_CORE,

   
220
	.load = load_module,

   
221
	.unload = unload_module,

   
222
	.load_pri = AST_MODPRI_CHANNEL_DRIVER,

   
223
);

   
/trunk/channels/chan_rtp.c
New File
 
  1. /trunk/channels/chan_multicast_rtp.c: Loading...
  2. /trunk/channels/chan_rtp.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.