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$")
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 };
00094
00095
00096 static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data);
00097 static int multicast_rtp_activate(struct ast_rtp_instance *instance);
00098 static int multicast_rtp_destroy(struct ast_rtp_instance *instance);
00099 static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
00100 static struct ast_frame *multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp);
00101
00102
00103 static struct ast_rtp_engine multicast_rtp_engine = {
00104 .name = "multicast",
00105 .new = multicast_rtp_new,
00106 .activate = multicast_rtp_activate,
00107 .destroy = multicast_rtp_destroy,
00108 .write = multicast_rtp_write,
00109 .read = multicast_rtp_read,
00110 };
00111
00112
00113 static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data)
00114 {
00115 struct multicast_rtp *multicast;
00116 const char *type = data;
00117
00118 if (!(multicast = ast_calloc(1, sizeof(*multicast)))) {
00119 return -1;
00120 }
00121
00122 if (!strcasecmp(type, "basic")) {
00123 multicast->type = MULTICAST_TYPE_BASIC;
00124 } else if (!strcasecmp(type, "linksys")) {
00125 multicast->type = MULTICAST_TYPE_LINKSYS;
00126 } else {
00127 ast_free(multicast);
00128 return -1;
00129 }
00130
00131 if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
00132 ast_free(multicast);
00133 return -1;
00134 }
00135
00136 multicast->ssrc = ast_random();
00137
00138 ast_rtp_instance_set_data(instance, multicast);
00139
00140 return 0;
00141 }
00142
00143
00144 static int multicast_send_control_packet(struct ast_rtp_instance *instance, struct multicast_rtp *multicast, int command)
00145 {
00146 struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)),
00147 .command = htonl(command),
00148 };
00149 struct ast_sockaddr control_address, remote_address;
00150
00151 ast_rtp_instance_get_local_address(instance, &control_address);
00152 ast_rtp_instance_get_remote_address(instance, &remote_address);
00153
00154
00155 if (ast_sockaddr_isnull(&control_address) ||
00156 ast_sockaddr_isnull(&remote_address)) {
00157 return -1;
00158 }
00159
00160
00161 if (ast_sockaddr_is_ipv6(&remote_address)) {
00162 ast_log(LOG_WARNING, "Cannot send control packet for IPv6 "
00163 "remote address.\n");
00164 return -1;
00165 }
00166
00167 control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address));
00168 control_packet.port = htonl(ast_sockaddr_port(&remote_address));
00169
00170
00171 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
00172 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
00173
00174 return 0;
00175 }
00176
00177
00178 static int multicast_rtp_activate(struct ast_rtp_instance *instance)
00179 {
00180 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
00181
00182 if (multicast->type != MULTICAST_TYPE_LINKSYS) {
00183 return 0;
00184 }
00185
00186 return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD);
00187 }
00188
00189
00190 static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
00191 {
00192 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
00193
00194 if (multicast->type == MULTICAST_TYPE_LINKSYS) {
00195 multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STOPCMD);
00196 }
00197
00198 close(multicast->socket);
00199
00200 ast_free(multicast);
00201
00202 return 0;
00203 }
00204
00205
00206 static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
00207 {
00208 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
00209 struct ast_frame *f = frame;
00210 struct ast_sockaddr remote_address;
00211 int hdrlen = 12, res = 0, codec;
00212 unsigned char *rtpheader;
00213
00214
00215 if (frame->frametype != AST_FRAME_VOICE) {
00216 return 0;
00217 }
00218
00219
00220 if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.codec)) < 0) {
00221 return -1;
00222 }
00223
00224
00225 if (frame->offset < hdrlen) {
00226 f = ast_frdup(frame);
00227 }
00228
00229
00230 rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
00231 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno)));
00232 put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
00233 put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
00234
00235
00236 multicast->seqno = 0xFFFF & (multicast->seqno + 1);
00237
00238
00239 ast_rtp_instance_get_remote_address(instance, &remote_address);
00240
00241 if (ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address) < 0) {
00242 ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
00243 ast_sockaddr_stringify(&remote_address),
00244 strerror(errno));
00245 res = -1;
00246 }
00247
00248
00249 if (frame != f) {
00250 ast_frfree(f);
00251 }
00252
00253 return res;
00254 }
00255
00256
00257 static struct ast_frame *multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
00258 {
00259 return &ast_null_frame;
00260 }
00261
00262 static int load_module(void)
00263 {
00264 if (ast_rtp_engine_register(&multicast_rtp_engine)) {
00265 return AST_MODULE_LOAD_DECLINE;
00266 }
00267
00268 return AST_MODULE_LOAD_SUCCESS;
00269 }
00270
00271 static int unload_module(void)
00272 {
00273 ast_rtp_engine_unregister(&multicast_rtp_engine);
00274
00275 return 0;
00276 }
00277
00278 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Multicast RTP Engine",
00279 .load = load_module,
00280 .unload = unload_module,
00281 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
00282 );