chan_rtp.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2009 - 2014, Digium, Inc.
00005  *
00006  * Joshua Colp <jcolp@digium.com>
00007  * Andreas 'MacBrody' Brodmann <andreas.brodmann@gmail.com>
00008  *
00009  * See http://www.asterisk.org for more information about
00010  * the Asterisk project. Please do not directly contact
00011  * any of the maintainers of this project for assistance;
00012  * the project provides a web site, mailing lists and IRC
00013  * channels for your use.
00014  *
00015  * This program is free software, distributed under the terms of
00016  * the GNU General Public License Version 2. See the LICENSE file
00017  * at the top of the source tree.
00018  */
00019 
00020 /*! \file
00021  *
00022  * \author Joshua Colp <jcolp@digium.com>
00023  * \author Andreas 'MacBrody' Broadmann <andreas.brodmann@gmail.com>
00024  *
00025  * \brief RTP (Multicast and Unicast) Media Channel
00026  *
00027  * \ingroup channel_drivers
00028  */
00029 
00030 /*** MODULEINFO
00031    <support_level>core</support_level>
00032  ***/
00033 
00034 #include "asterisk.h"
00035 
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 423004 $")
00037 
00038 #include "asterisk/channel.h"
00039 #include "asterisk/module.h"
00040 #include "asterisk/pbx.h"
00041 #include "asterisk/acl.h"
00042 #include "asterisk/app.h"
00043 #include "asterisk/rtp_engine.h"
00044 #include "asterisk/causes.h"
00045 #include "asterisk/format_cache.h"
00046 
00047 /* Forward declarations */
00048 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);
00049 static struct ast_channel *unicast_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);
00050 static int rtp_call(struct ast_channel *ast, const char *dest, int timeout);
00051 static int rtp_hangup(struct ast_channel *ast);
00052 static struct ast_frame *rtp_read(struct ast_channel *ast);
00053 static int rtp_write(struct ast_channel *ast, struct ast_frame *f);
00054 
00055 /* Multicast channel driver declaration */
00056 static struct ast_channel_tech multicast_rtp_tech = {
00057    .type = "MulticastRTP",
00058    .description = "Multicast RTP Paging Channel Driver",
00059    .requester = multicast_rtp_request,
00060    .call = rtp_call,
00061    .hangup = rtp_hangup,
00062    .read = rtp_read,
00063    .write = rtp_write,
00064 };
00065 
00066 /* Unicast channel driver declaration */
00067 static struct ast_channel_tech unicast_rtp_tech = {
00068    .type = "UnicastRTP",
00069    .description = "Unicast RTP Media Channel Driver",
00070    .requester = unicast_rtp_request,
00071    .call = rtp_call,
00072    .hangup = rtp_hangup,
00073    .read = rtp_read,
00074    .write = rtp_write,
00075 };
00076 
00077 /*! \brief Function called when we should read a frame from the channel */
00078 static struct ast_frame  *rtp_read(struct ast_channel *ast)
00079 {
00080    struct ast_rtp_instance *instance = ast_channel_tech_pvt(ast);
00081    int fdno = ast_channel_fdno(ast);
00082 
00083    switch (fdno) {
00084    case 0:
00085       return ast_rtp_instance_read(instance, 0);
00086    default:
00087       return &ast_null_frame;
00088    }
00089 }
00090 
00091 /*! \brief Function called when we should write a frame to the channel */
00092 static int rtp_write(struct ast_channel *ast, struct ast_frame *f)
00093 {
00094    struct ast_rtp_instance *instance = ast_channel_tech_pvt(ast);
00095 
00096    return ast_rtp_instance_write(instance, f);
00097 }
00098 
00099 /*! \brief Function called when we should actually call the destination */
00100 static int rtp_call(struct ast_channel *ast, const char *dest, int timeout)
00101 {
00102    struct ast_rtp_instance *instance = ast_channel_tech_pvt(ast);
00103 
00104    ast_queue_control(ast, AST_CONTROL_ANSWER);
00105 
00106    return ast_rtp_instance_activate(instance);
00107 }
00108 
00109 /*! \brief Function called when we should hang the channel up */
00110 static int rtp_hangup(struct ast_channel *ast)
00111 {
00112    struct ast_rtp_instance *instance = ast_channel_tech_pvt(ast);
00113 
00114    ast_rtp_instance_destroy(instance);
00115 
00116    ast_channel_tech_pvt_set(ast, NULL);
00117 
00118    return 0;
00119 }
00120 
00121 /*! \brief Function called when we should prepare to call the multicast destination */
00122 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)
00123 {
00124    char *parse;
00125    struct ast_rtp_instance *instance;
00126    struct ast_sockaddr control_address;
00127    struct ast_sockaddr destination_address;
00128    struct ast_channel *chan;
00129    struct ast_format_cap *caps = NULL;
00130    struct ast_format *fmt = NULL;
00131    AST_DECLARE_APP_ARGS(args,
00132       AST_APP_ARG(type);
00133       AST_APP_ARG(destination);
00134       AST_APP_ARG(control);
00135    );
00136 
00137    if (ast_strlen_zero(data)) {
00138       ast_log(LOG_ERROR, "A multicast type and destination must be given to the 'MulticastRTP' channel\n");
00139       goto failure;
00140    }
00141    parse = ast_strdupa(data);
00142    AST_NONSTANDARD_APP_ARGS(args, parse, '/');
00143 
00144    fmt = ast_format_cap_get_format(cap, 0);
00145 
00146    ast_sockaddr_setnull(&control_address);
00147 
00148    if (!ast_strlen_zero(args.control) &&
00149       !ast_sockaddr_parse(&control_address, args.control, PARSE_PORT_REQUIRE)) {
00150       ast_log(LOG_ERROR, "Control address '%s' could not be parsed\n", args.control);
00151       goto failure;
00152    }
00153 
00154    if (!ast_sockaddr_parse(&destination_address, args.destination,
00155             PARSE_PORT_REQUIRE)) {
00156       ast_log(LOG_ERROR, "Destination address '%s' could not be parsed\n", args.destination);
00157       goto failure;
00158    }
00159 
00160    caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
00161    if (!caps) {
00162       goto failure;
00163    }
00164 
00165    if (!(instance = ast_rtp_instance_new("multicast", NULL, &control_address, args.type))) {
00166       ast_log(LOG_ERROR, "Could not create RTP instance for sending media to '%s'\n", args.destination);
00167       goto failure;
00168    }
00169 
00170    if (!(chan = ast_channel_alloc(1, AST_STATE_DOWN, "", "", "", "", "", assignedids, requestor, 0, "MulticastRTP/%p", instance))) {
00171       ast_rtp_instance_destroy(instance);
00172       goto failure;
00173    }
00174    ast_rtp_instance_set_channel_id(instance, ast_channel_uniqueid(chan));
00175    ast_rtp_instance_set_remote_address(instance, &destination_address);
00176 
00177    ast_channel_tech_set(chan, &multicast_rtp_tech);
00178 
00179    ast_format_cap_append(caps, fmt, 0);
00180    ast_channel_nativeformats_set(chan, caps);
00181    ast_channel_set_writeformat(chan, fmt);
00182    ast_channel_set_rawwriteformat(chan, fmt);
00183    ast_channel_set_readformat(chan, fmt);
00184    ast_channel_set_rawreadformat(chan, fmt);
00185 
00186    ast_channel_tech_pvt_set(chan, instance);
00187 
00188    ast_channel_unlock(chan);
00189 
00190    ao2_ref(fmt, -1);
00191    ao2_ref(caps, -1);
00192 
00193    return chan;
00194 
00195 failure:
00196    ao2_cleanup(fmt);
00197    ao2_cleanup(caps);
00198    *cause = AST_CAUSE_FAILURE;
00199    return NULL;
00200 }
00201 
00202 /*! \brief Function called when we should prepare to call the unicast destination */
00203 static struct ast_channel *unicast_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)
00204 {
00205    char *parse;
00206    struct ast_rtp_instance *instance;
00207    struct ast_sockaddr address;
00208    struct ast_sockaddr local_address;
00209    struct ast_channel *chan;
00210    struct ast_format_cap *caps = NULL;
00211    struct ast_format *fmt = NULL;
00212    AST_DECLARE_APP_ARGS(args,
00213       AST_APP_ARG(destination);
00214       AST_APP_ARG(engine);
00215       AST_APP_ARG(format);
00216    );
00217 
00218    if (ast_strlen_zero(data)) {
00219       goto failure;
00220    }
00221    parse = ast_strdupa(data);
00222    AST_NONSTANDARD_APP_ARGS(args, parse, '/');
00223 
00224    if (!ast_strlen_zero(args.format)) {
00225       fmt = ast_format_cache_get(args.format);
00226    } else {
00227       fmt = ast_format_cap_get_format(cap, 0);
00228    }
00229 
00230    if (!fmt) {
00231       ast_log(LOG_ERROR, "No format specified for sending RTP to '%s'\n", args.destination);
00232       goto failure;
00233    }
00234 
00235    if (!ast_sockaddr_parse(&address, args.destination,
00236             PARSE_PORT_REQUIRE)) {
00237       ast_log(LOG_ERROR, "Destination '%s' could not be parsed\n", args.destination);
00238       goto failure;
00239    }
00240 
00241    caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
00242    if (!caps) {
00243       goto failure;
00244    }
00245 
00246    ast_ouraddrfor(&address, &local_address);
00247    if (!(instance = ast_rtp_instance_new(args.engine, NULL, &local_address, NULL))) {
00248       ast_log(LOG_ERROR, "Could not create RTP instance for sending media to '%s'\n", args.destination);
00249       goto failure;
00250    }
00251 
00252    if (!(chan = ast_channel_alloc(1, AST_STATE_DOWN, "", "", "", "", "", assignedids, requestor, 0, "UnicastRTP/%s-%p", args.destination, instance))) {
00253       ast_rtp_instance_destroy(instance);
00254       goto failure;
00255    }
00256    ast_rtp_instance_set_channel_id(instance, ast_channel_uniqueid(chan));
00257    ast_rtp_instance_set_remote_address(instance, &address);
00258    ast_channel_set_fd(chan, 0, ast_rtp_instance_fd(instance, 0));
00259 
00260    ast_channel_tech_set(chan, &unicast_rtp_tech);
00261 
00262    ast_format_cap_append(caps, fmt, 0);
00263    ast_channel_nativeformats_set(chan, caps);
00264    ast_channel_set_writeformat(chan, fmt);
00265    ast_channel_set_rawwriteformat(chan, fmt);
00266    ast_channel_set_readformat(chan, fmt);
00267    ast_channel_set_rawreadformat(chan, fmt);
00268 
00269    ast_channel_tech_pvt_set(chan, instance);
00270 
00271    pbx_builtin_setvar_helper(chan, "UNICASTRTP_LOCAL_ADDRESS", ast_sockaddr_stringify_addr(&local_address));
00272    ast_rtp_instance_get_local_address(instance, &local_address);
00273    pbx_builtin_setvar_helper(chan, "UNICASTRTP_LOCAL_PORT", ast_sockaddr_stringify_port(&local_address));
00274 
00275    ast_channel_unlock(chan);
00276 
00277    ao2_ref(fmt, -1);
00278    ao2_ref(caps, -1);
00279 
00280    return chan;
00281 
00282 failure:
00283    ao2_cleanup(fmt);
00284    ao2_cleanup(caps);
00285    *cause = AST_CAUSE_FAILURE;
00286    return NULL;
00287 }
00288 
00289 /*! \brief Function called when our module is unloaded */
00290 static int unload_module(void)
00291 {
00292    ast_channel_unregister(&multicast_rtp_tech);
00293    ao2_cleanup(multicast_rtp_tech.capabilities);
00294    multicast_rtp_tech.capabilities = NULL;
00295 
00296    ast_channel_unregister(&unicast_rtp_tech);
00297    ao2_cleanup(unicast_rtp_tech.capabilities);
00298    unicast_rtp_tech.capabilities = NULL;
00299 
00300    return 0;
00301 }
00302 
00303 /*! \brief Function called when our module is loaded */
00304 static int load_module(void)
00305 {
00306    if (!(multicast_rtp_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
00307       return AST_MODULE_LOAD_DECLINE;
00308    }
00309    ast_format_cap_append_by_type(multicast_rtp_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
00310    if (ast_channel_register(&multicast_rtp_tech)) {
00311       ast_log(LOG_ERROR, "Unable to register channel class 'MulticastRTP'\n");
00312       unload_module();
00313       return AST_MODULE_LOAD_DECLINE;
00314    }
00315 
00316    if (!(unicast_rtp_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
00317       unload_module();
00318       return AST_MODULE_LOAD_DECLINE;
00319    }
00320    ast_format_cap_append_by_type(unicast_rtp_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
00321    if (ast_channel_register(&unicast_rtp_tech)) {
00322       ast_log(LOG_ERROR, "Unable to register channel class 'UnicastRTP'\n");
00323       unload_module();
00324       return AST_MODULE_LOAD_DECLINE;
00325    }
00326 
00327    return AST_MODULE_LOAD_SUCCESS;
00328 }
00329 
00330 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "RTP Media Channel",
00331    .support_level = AST_MODULE_SUPPORT_CORE,
00332    .load = load_module,
00333    .unload = unload_module,
00334    .load_pri = AST_MODPRI_CHANNEL_DRIVER,
00335 );

Generated on Thu Apr 16 06:27:24 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6