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 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00034
00035 #include <sys/time.h>
00036 #include <signal.h>
00037 #include <fcntl.h>
00038 #include <math.h>
00039
00040 #include "asterisk/pbx.h"
00041 #include "asterisk/frame.h"
00042 #include "asterisk/channel.h"
00043 #include "asterisk/acl.h"
00044 #include "asterisk/config.h"
00045 #include "asterisk/lock.h"
00046 #include "asterisk/utils.h"
00047 #include "asterisk/cli.h"
00048 #include "asterisk/manager.h"
00049 #include "asterisk/unaligned.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/rtp_engine.h"
00052
00053
00054 #define LINKSYS_MCAST_STARTCMD 6
00055
00056
00057 #define LINKSYS_MCAST_STOPCMD 7
00058
00059
00060 enum multicast_type {
00061
00062 MULTICAST_TYPE_BASIC = 0,
00063
00064 MULTICAST_TYPE_LINKSYS,
00065 };
00066
00067
00068 struct multicast_control_packet {
00069
00070 uint32_t unique_id;
00071
00072 uint32_t command;
00073
00074 uint32_t ip;
00075
00076 uint32_t port;
00077 };
00078
00079
00080 struct multicast_rtp {
00081
00082 enum multicast_type type;
00083
00084 int socket;
00085
00086 unsigned int ssrc;
00087
00088 unsigned int seqno;
00089 };
00090
00091
00092 static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data);
00093 static int multicast_rtp_activate(struct ast_rtp_instance *instance);
00094 static int multicast_rtp_destroy(struct ast_rtp_instance *instance);
00095 static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
00096 static struct ast_frame *multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp);
00097
00098
00099 static struct ast_rtp_engine multicast_rtp_engine = {
00100 .name = "multicast",
00101 .new = multicast_rtp_new,
00102 .activate = multicast_rtp_activate,
00103 .destroy = multicast_rtp_destroy,
00104 .write = multicast_rtp_write,
00105 .read = multicast_rtp_read,
00106 };
00107
00108
00109 static int multicast_rtp_new(struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data)
00110 {
00111 struct multicast_rtp *multicast;
00112 const char *type = data;
00113
00114 if (!(multicast = ast_calloc(1, sizeof(*multicast)))) {
00115 return -1;
00116 }
00117
00118 if (!strcasecmp(type, "basic")) {
00119 multicast->type = MULTICAST_TYPE_BASIC;
00120 } else if (!strcasecmp(type, "linksys")) {
00121 multicast->type = MULTICAST_TYPE_LINKSYS;
00122 } else {
00123 ast_free(multicast);
00124 return -1;
00125 }
00126
00127 if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
00128 ast_free(multicast);
00129 return -1;
00130 }
00131
00132 multicast->ssrc = ast_random();
00133
00134 ast_rtp_instance_set_data(instance, multicast);
00135
00136 return 0;
00137 }
00138
00139
00140 static int multicast_send_control_packet(struct ast_rtp_instance *instance, struct multicast_rtp *multicast, int command)
00141 {
00142 struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)),
00143 .command = htonl(command),
00144 };
00145 struct ast_sockaddr control_address, remote_address;
00146
00147 ast_rtp_instance_get_local_address(instance, &control_address);
00148 ast_rtp_instance_get_remote_address(instance, &remote_address);
00149
00150
00151 if (ast_sockaddr_isnull(&control_address) ||
00152 ast_sockaddr_isnull(&remote_address)) {
00153 return -1;
00154 }
00155
00156
00157 if (ast_sockaddr_is_ipv6(&remote_address)) {
00158 ast_log(LOG_WARNING, "Cannot send control packet for IPv6 "
00159 "remote address.\n");
00160 return -1;
00161 }
00162
00163 control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address));
00164 control_packet.port = htonl(ast_sockaddr_port(&remote_address));
00165
00166
00167 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
00168 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
00169
00170 return 0;
00171 }
00172
00173
00174 static int multicast_rtp_activate(struct ast_rtp_instance *instance)
00175 {
00176 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
00177
00178 if (multicast->type != MULTICAST_TYPE_LINKSYS) {
00179 return 0;
00180 }
00181
00182 return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD);
00183 }
00184
00185
00186 static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
00187 {
00188 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
00189
00190 if (multicast->type == MULTICAST_TYPE_LINKSYS) {
00191 multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STOPCMD);
00192 }
00193
00194 close(multicast->socket);
00195
00196 ast_free(multicast);
00197
00198 return 0;
00199 }
00200
00201
00202 static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
00203 {
00204 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
00205 struct ast_frame *f = frame;
00206 struct ast_sockaddr remote_address;
00207 int hdrlen = 12, res, codec;
00208 unsigned char *rtpheader;
00209
00210
00211 if (frame->frametype != AST_FRAME_VOICE) {
00212 return 0;
00213 }
00214
00215
00216 if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.codec)) < 0) {
00217 return -1;
00218 }
00219
00220
00221 if (frame->offset < hdrlen) {
00222 f = ast_frdup(frame);
00223 }
00224
00225
00226 rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
00227 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno++) | (0 << 23)));
00228 put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
00229 put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
00230
00231
00232 ast_rtp_instance_get_remote_address(instance, &remote_address);
00233 res = ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address);
00234
00235 if (res < 0) {
00236 ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
00237 ast_sockaddr_stringify(&remote_address),
00238 strerror(errno));
00239 }
00240
00241
00242 if (frame != f) {
00243 ast_frfree(f);
00244 }
00245
00246 return res;
00247 }
00248
00249
00250 static struct ast_frame *multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
00251 {
00252 return &ast_null_frame;
00253 }
00254
00255 static int load_module(void)
00256 {
00257 if (ast_rtp_engine_register(&multicast_rtp_engine)) {
00258 return AST_MODULE_LOAD_DECLINE;
00259 }
00260
00261 return AST_MODULE_LOAD_SUCCESS;
00262 }
00263
00264 static int unload_module(void)
00265 {
00266 ast_rtp_engine_unregister(&multicast_rtp_engine);
00267
00268 return 0;
00269 }
00270
00271 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Multicast RTP Engine",
00272 .load = load_module,
00273 .unload = unload_module,
00274 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
00275 );