00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "asterisk.h"
00036
00037 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 400393 $")
00038
00039 #include <sys/time.h>
00040 #include <signal.h>
00041 #include <fcntl.h>
00042 #include <math.h>
00043
00044 #include "asterisk/pbx.h"
00045 #include "asterisk/frame.h"
00046 #include "asterisk/channel.h"
00047 #include "asterisk/acl.h"
00048 #include "asterisk/config.h"
00049 #include "asterisk/lock.h"
00050 #include "asterisk/utils.h"
00051 #include "asterisk/cli.h"
00052 #include "asterisk/manager.h"
00053 #include "asterisk/unaligned.h"
00054 #include "asterisk/module.h"
00055 #include "asterisk/rtp_engine.h"
00056
00057
00058 #define LINKSYS_MCAST_STARTCMD 6
00059
00060
00061 #define LINKSYS_MCAST_STOPCMD 7
00062
00063
00064 enum multicast_type {
00065
00066 MULTICAST_TYPE_BASIC = 0,
00067
00068 MULTICAST_TYPE_LINKSYS,
00069 };
00070
00071
00072 struct multicast_control_packet {
00073
00074 uint32_t unique_id;
00075
00076 uint32_t command;
00077
00078 uint32_t ip;
00079
00080 uint32_t port;
00081 };
00082
00083
00084 struct multicast_rtp {
00085
00086 enum multicast_type type;
00087
00088 int socket;
00089
00090 unsigned int ssrc;
00091
00092 uint16_t seqno;
00093 unsigned int lastts;
00094 struct timeval txcore;
00095 };
00096
00097
00098 static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data);
00099 static int multicast_rtp_activate(struct ast_rtp_instance *instance);
00100 static int multicast_rtp_destroy(struct ast_rtp_instance *instance);
00101 static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
00102 static struct ast_frame *multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp);
00103
00104
00105 static struct ast_rtp_engine multicast_rtp_engine = {
00106 .name = "multicast",
00107 .new = multicast_rtp_new,
00108 .activate = multicast_rtp_activate,
00109 .destroy = multicast_rtp_destroy,
00110 .write = multicast_rtp_write,
00111 .read = multicast_rtp_read,
00112 };
00113
00114
00115 static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data)
00116 {
00117 struct multicast_rtp *multicast;
00118 const char *type = data;
00119
00120 if (!(multicast = ast_calloc(1, sizeof(*multicast)))) {
00121 return -1;
00122 }
00123
00124 if (!strcasecmp(type, "basic")) {
00125 multicast->type = MULTICAST_TYPE_BASIC;
00126 } else if (!strcasecmp(type, "linksys")) {
00127 multicast->type = MULTICAST_TYPE_LINKSYS;
00128 } else {
00129 ast_free(multicast);
00130 return -1;
00131 }
00132
00133 if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
00134 ast_free(multicast);
00135 return -1;
00136 }
00137
00138 multicast->ssrc = ast_random();
00139
00140 ast_rtp_instance_set_data(instance, multicast);
00141
00142 return 0;
00143 }
00144
00145 static int rtp_get_rate(format_t format)
00146 {
00147 return (format == AST_FORMAT_G722) ? 8000 : ast_format_rate(format);
00148 }
00149
00150 static unsigned int calc_txstamp(struct multicast_rtp *rtp, struct timeval *delivery)
00151 {
00152 struct timeval t;
00153 long ms;
00154
00155 if (ast_tvzero(rtp->txcore)) {
00156 rtp->txcore = ast_tvnow();
00157 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
00158 }
00159
00160 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
00161 if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
00162 ms = 0;
00163 }
00164 rtp->txcore = t;
00165
00166 return (unsigned int) ms;
00167 }
00168
00169
00170 static int multicast_send_control_packet(struct ast_rtp_instance *instance, struct multicast_rtp *multicast, int command)
00171 {
00172 struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)),
00173 .command = htonl(command),
00174 };
00175 struct ast_sockaddr control_address, remote_address;
00176
00177 ast_rtp_instance_get_local_address(instance, &control_address);
00178 ast_rtp_instance_get_remote_address(instance, &remote_address);
00179
00180
00181 if (ast_sockaddr_isnull(&control_address) ||
00182 ast_sockaddr_isnull(&remote_address)) {
00183 return -1;
00184 }
00185
00186
00187 if (ast_sockaddr_is_ipv6(&remote_address)) {
00188 ast_log(LOG_WARNING, "Cannot send control packet for IPv6 "
00189 "remote address.\n");
00190 return -1;
00191 }
00192
00193 control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address));
00194 control_packet.port = htonl(ast_sockaddr_port(&remote_address));
00195
00196
00197 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
00198 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
00199
00200 return 0;
00201 }
00202
00203
00204 static int multicast_rtp_activate(struct ast_rtp_instance *instance)
00205 {
00206 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
00207
00208 if (multicast->type != MULTICAST_TYPE_LINKSYS) {
00209 return 0;
00210 }
00211
00212 return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD);
00213 }
00214
00215
00216 static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
00217 {
00218 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
00219
00220 if (multicast->type == MULTICAST_TYPE_LINKSYS) {
00221 multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STOPCMD);
00222 }
00223
00224 close(multicast->socket);
00225
00226 ast_free(multicast);
00227
00228 return 0;
00229 }
00230
00231
00232 static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
00233 {
00234 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
00235 struct ast_frame *f = frame;
00236 struct ast_sockaddr remote_address;
00237 int hdrlen = 12, res = 0, codec;
00238 int rate;
00239 unsigned char *rtpheader;
00240 unsigned int ms = calc_txstamp(multicast, &frame->delivery);
00241
00242
00243 if (frame->frametype != AST_FRAME_VOICE) {
00244 return 0;
00245 }
00246 rate = rtp_get_rate(frame->subclass.codec) / 1000;
00247
00248
00249 if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.codec)) < 0) {
00250 return -1;
00251 }
00252
00253
00254 if (frame->offset < hdrlen) {
00255 f = ast_frdup(frame);
00256 }
00257
00258
00259 multicast->lastts = multicast->lastts + ms * rate;
00260
00261
00262 rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
00263 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno)));
00264
00265 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) {
00266 put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
00267 } else {
00268 put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
00269 }
00270
00271 put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
00272
00273
00274 multicast->seqno = 0xFFFF & (multicast->seqno + 1);
00275
00276
00277 ast_rtp_instance_get_remote_address(instance, &remote_address);
00278
00279 if (ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address) < 0) {
00280 ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
00281 ast_sockaddr_stringify(&remote_address),
00282 strerror(errno));
00283 res = -1;
00284 }
00285
00286
00287 if (frame != f) {
00288 ast_frfree(f);
00289 }
00290
00291 return res;
00292 }
00293
00294
00295 static struct ast_frame *multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
00296 {
00297 return &ast_null_frame;
00298 }
00299
00300 static int load_module(void)
00301 {
00302 if (ast_rtp_engine_register(&multicast_rtp_engine)) {
00303 return AST_MODULE_LOAD_DECLINE;
00304 }
00305
00306 return AST_MODULE_LOAD_SUCCESS;
00307 }
00308
00309 static int unload_module(void)
00310 {
00311 ast_rtp_engine_unregister(&multicast_rtp_engine);
00312
00313 return 0;
00314 }
00315
00316 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Multicast RTP Engine",
00317 .load = load_module,
00318 .unload = unload_module,
00319 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
00320 );