[asterisk-commits] jdixon: branch jdixon/chan_usbradio-1.4 r139280 - /team/jdixon/chan_usbradio-...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Aug 21 01:03:26 CDT 2008
Author: jdixon
Date: Thu Aug 21 01:03:26 2008
New Revision: 139280
URL: http://svn.digium.com/view/asterisk?view=rev&rev=139280
Log:
Added more stuff, like confmode and it works in both modes rudimentarily
Modified:
team/jdixon/chan_usbradio-1.4/dev-1.0/channels/chan_echolink.c
Modified: team/jdixon/chan_usbradio-1.4/dev-1.0/channels/chan_echolink.c
URL: http://svn.digium.com/view/asterisk/team/jdixon/chan_usbradio-1.4/dev-1.0/channels/chan_echolink.c?view=diff&rev=139280&r1=139279&r2=139280
==============================================================================
--- team/jdixon/chan_usbradio-1.4/dev-1.0/channels/chan_echolink.c (original)
+++ team/jdixon/chan_usbradio-1.4/dev-1.0/channels/chan_echolink.c Thu Aug 21 01:03:26 2008
@@ -31,9 +31,9 @@
/*** MODULEINFO
***/
-/* Version 0.2, 08/19/2008
+/* Version 0.3, 08/20/2008
Echolink channel driver for Asterisk/app_rpt.
-This is a second attempt.
+This is a third attempt.
A lot more has to be added,
Here is what comes to mind first:
@@ -80,9 +80,6 @@
leave the IP address as 0.0.0.0,
do not use 127.0.0.1
-It would be better to have written all this code
-in C++ classes instead of C, but Asterisk wants C only.
-
*/
#include "asterisk.h"
@@ -141,105 +138,7 @@
static const char tdesc[] = "Echolink channel driver by KI4LKF";
static int prefformat = AST_FORMAT_GSM;
-static char context[AST_MAX_EXTENSION] = "default";
static char type[] = "echolink";
-
-struct el_instance
-{
- char name[EL_NAME_SIZE + 1];
- char mycall[EL_CALL_SIZE + 1];
- char myname[EL_NAME_SIZE + 1];
- char mypwd[EL_PWD_SIZE + 1];
- char myemail[EL_EMAIL_SIZE + 1];
- char myqth[EL_QTH_SIZE + 1];
- char elservers[EL_MAX_SERVERS][EL_SERVERNAME_SIZE + 1];
- char ipaddr[EL_IP_SIZE + 1];
- char port[EL_IP_SIZE + 1];
- int maxstns;
- /* missed 10 heartbeats, you're out */
- short rtcptimeout;
- unsigned int mynode;
- char fdr_file[FILENAME_MAX];
- int audio_sock;
- int ctrl_sock;
- uint16_t audio_port;
- uint16_t ctrl_port;
- int fdr;
- unsigned long seqno;
-} ;
-
-struct el_rxqast {
- struct el_rxqast *qe_forw;
- struct el_rxqast *qe_back;
- char buf[GSM_FRAME_SIZE];
-};
-
-struct el_rxqel {
- struct el_rxqel *qe_forw;
- struct el_rxqel *qe_back;
- char buf[BLOCKING_FACTOR * GSM_FRAME_SIZE];
- char fromip[EL_IP_SIZE + 1];
-};
-
-struct el_pvt {
- struct ast_channel *owner;
- struct el_instance *instp;
- char app[16];
- char stream[80];
- char txkey;
- int rxkey;
- int keepalive;
- struct ast_frame fr;
- int txindex;
- struct el_rxqast rxqast;
- struct el_rxqel rxqel;
- struct ast_module_user *u;
-};
-
-struct rtcp_sdes_request_item {
- unsigned char r_item;
- char *r_text;
-};
-
-struct rtcp_sdes_request {
- int nitems;
- unsigned char ssrc[4];
- struct rtcp_sdes_request_item item[10];
-};
-
-struct rtcp_common_t {
-#ifdef RTP_BIG_ENDIAN
- uint8_t version:2;
- uint8_t p:1;
- uint8_t count:5;
-#else
- uint8_t count:5;
- uint8_t p:1;
- uint8_t version:2;
-#endif
- uint8_t pt:8;
- uint16_t length;
-};
-
-struct rtcp_sdes_item_t {
- uint8_t type;
- uint8_t length;
- char data[1];
-};
-
-struct rtcp_t {
- struct rtcp_common_t common;
- union {
- struct {
- uint32_t src[1];
- } bye;
-
- struct rtcp_sdes_t {
- uint32_t src;
- struct rtcp_sdes_item_t item[1];
- } sdes;
- } r;
-};
/* Echolink audio packet heafer */
struct gsmVoice_t {
@@ -263,8 +162,9 @@
uint32_t ssrc;
unsigned char data[BLOCKING_FACTOR * GSM_FRAME_SIZE];
};
-static struct gsmVoice_t audio_all_but_one;
-static struct gsmVoice_t audio_all;
+
+struct el_instance;
+struct el_pvt;
/* Echolink node details */
/* Also each node in binary tree in memory */
@@ -276,20 +176,127 @@
short countdown;
uint16_t seqnum;
struct el_instance *instp;
+ struct el_pvt *p;
+ struct ast_channel *chan;
+};
+
+struct el_instance
+{
+ char name[EL_NAME_SIZE + 1];
+ char mycall[EL_CALL_SIZE + 1];
+ char myname[EL_NAME_SIZE + 1];
+ char mypwd[EL_PWD_SIZE + 1];
+ char myemail[EL_EMAIL_SIZE + 1];
+ char myqth[EL_QTH_SIZE + 1];
+ char elservers[EL_MAX_SERVERS][EL_SERVERNAME_SIZE + 1];
+ char ipaddr[EL_IP_SIZE + 1];
+ char port[EL_IP_SIZE + 1];
+ char astnode[EL_NAME_SIZE + 1];
+ char context[EL_NAME_SIZE + 1];
+ int maxstns;
+ /* missed 10 heartbeats, you're out */
+ short rtcptimeout;
+ unsigned int mynode;
+ char fdr_file[FILENAME_MAX];
+ int audio_sock;
+ int ctrl_sock;
+ uint16_t audio_port;
+ uint16_t ctrl_port;
+ int fdr;
+ unsigned long seqno;
+ int confmode;
+ struct el_pvt *confp;
+ struct gsmVoice_t audio_all_but_one;
+ struct gsmVoice_t audio_all;
+ struct el_node el_node_test;
+
+} ;
+
+struct el_rxqast {
+ struct el_rxqast *qe_forw;
+ struct el_rxqast *qe_back;
+ char buf[GSM_FRAME_SIZE];
+};
+
+struct el_rxqel {
+ struct el_rxqel *qe_forw;
+ struct el_rxqel *qe_back;
+ char buf[BLOCKING_FACTOR * GSM_FRAME_SIZE];
+ char fromip[EL_IP_SIZE + 1];
+};
+
+struct el_pvt {
+ struct ast_channel *owner;
+ struct el_instance *instp;
+ char app[16];
+ char stream[80];
+ char ip[EL_IP_SIZE + 1];
+ char txkey;
+ int rxkey;
+ int keepalive;
+ struct ast_frame fr;
+ int txindex;
+ struct el_rxqast rxqast;
+ struct el_rxqel rxqel;
+ char firstsent;
+ struct ast_module_user *u;
+};
+
+struct rtcp_sdes_request_item {
+ unsigned char r_item;
+ char *r_text;
+};
+
+struct rtcp_sdes_request {
+ int nitems;
+ unsigned char ssrc[4];
+ struct rtcp_sdes_request_item item[10];
+};
+
+struct rtcp_common_t {
+#ifdef RTP_BIG_ENDIAN
+ uint8_t version:2;
+ uint8_t p:1;
+ uint8_t count:5;
+#else
+ uint8_t count:5;
+ uint8_t p:1;
+ uint8_t version:2;
+#endif
+ uint8_t pt:8;
+ uint16_t length;
+};
+
+struct rtcp_sdes_item_t {
+ uint8_t type;
+ uint8_t length;
+ char data[1];
+};
+
+struct rtcp_t {
+ struct rtcp_common_t common;
+ union {
+ struct {
+ uint32_t src[1];
+ } bye;
+
+ struct rtcp_sdes_t {
+ uint32_t src;
+ struct rtcp_sdes_item_t item[1];
+ } sdes;
+ } r;
};
struct el_instance *instances[EL_MAX_INSTANCES];
int ninstances = 0;
-/* testing existence of a node ... */
-static struct el_node el_node_test;
-
/* binary search tree in memory, root node */
static void *el_node_list = NULL;
/* Echolink registration thread */
static pthread_t el_register_thread;
-static char run_forever = (char)1;
+static pthread_t el_reader_thread;
+static int run_forever = 1;
static char *config = "echolink.conf";
@@ -500,6 +507,7 @@
unsigned char *end;
int sawbye = 0;
+
if ((((p[0] >> 6) & 3) != 3 && ((p[0] >> 6) & 3) != 1) ||
((p[0] & 0x20) != 0) ||
((p[1] != 200) && (p[1] != 201)))
@@ -597,14 +605,32 @@
p->rxqel.qe_back = &p->rxqel;
p->instp = instances[n];
+ p->instp->confp = p; /* save for conference mode */
}
return p;
}
static int el_hangup(struct ast_channel *ast)
{
- struct el_pvt *p;
- p = ast->tech_pvt;
+ struct el_pvt *p = ast->tech_pvt;
+ struct el_instance *instp = p->instp;
+ int i,n;
+ unsigned char bye[50];
+ struct sockaddr_in sin;
+
+ if (!instp->confmode)
+ {
+ n = rtcp_make_bye(bye,"disconnected");
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = inet_addr(p->ip);
+ sin.sin_port = htons(instp->ctrl_port);
+ for (i = 0; i < 20; i++)
+ {
+ sendto(instp->ctrl_sock, bye, n,
+ 0,(struct sockaddr *)&sin,sizeof(sin));
+ }
+ ast_log(LOG_NOTICE,"Sent bye to IP address %s\n",p->ip);
+ }
if (option_debug)
ast_log(LOG_DEBUG, "el_hangup(%s)\n", ast->name);
if (!ast->tech_pvt) {
@@ -664,28 +690,59 @@
struct el_instance *instp = (*(struct el_node **)nodep)->instp;
if ((which == leaf) || (which == postorder)) {
- if (strncmp((*(struct el_node **)nodep)->ip, el_node_test.ip,EL_IP_SIZE) != 0) {
+ if (strncmp((*(struct el_node **)nodep)->ip, instp->el_node_test.ip,EL_IP_SIZE) != 0) {
sin.sin_family = AF_INET;
sin.sin_port = htons(instp->audio_port);
sin.sin_addr.s_addr = inet_addr((*(struct el_node **)nodep)->ip);
- audio_all_but_one.version = 3;
- audio_all_but_one.pad = 0;
- audio_all_but_one.ext = 0;
- audio_all_but_one.csrc = 0;
- audio_all_but_one.marker = 0;
- audio_all_but_one.payt = 3;
- audio_all_but_one.seqnum = htons((*(struct el_node **)nodep)->seqnum++);
- audio_all_but_one.time = htonl(0);
- audio_all_but_one.ssrc = instp->mynode;
+ instp->audio_all_but_one.version = 3;
+ instp->audio_all_but_one.pad = 0;
+ instp->audio_all_but_one.ext = 0;
+ instp->audio_all_but_one.csrc = 0;
+ instp->audio_all_but_one.marker = 0;
+ instp->audio_all_but_one.payt = 3;
+ instp->audio_all_but_one.seqnum = htons((*(struct el_node **)nodep)->seqnum++);
+ instp->audio_all_but_one.time = htonl(0);
+ instp->audio_all_but_one.ssrc = instp->mynode;
/*
ast_log(LOG_NOTICE, "sending to %s(%s)\n",
(*(struct el_node **)nodep)->call, (*(struct el_node **)nodep)->ip);
*/
- sendto(instp->audio_sock, (char *)&audio_all_but_one, sizeof(audio_all_but_one),
+ sendto(instp->audio_sock, (char *)&instp->audio_all_but_one, sizeof(instp->audio_all_but_one),
0,(struct sockaddr *)&sin,sizeof(sin));
+ }
+ }
+}
+
+static void send_audio_only_one(const void *nodep, const VISIT which, const int depth)
+{
+ struct sockaddr_in sin;
+ struct el_instance *instp = (*(struct el_node **)nodep)->instp;
+
+ if ((which == leaf) || (which == postorder)) {
+ if (strncmp((*(struct el_node **)nodep)->ip, instp->el_node_test.ip,EL_IP_SIZE) == 0) {
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(instp->audio_port);
+ sin.sin_addr.s_addr = inet_addr((*(struct el_node **)nodep)->ip);
+
+ instp->audio_all.version = 3;
+ instp->audio_all.pad = 0;
+ instp->audio_all.ext = 0;
+ instp->audio_all.csrc = 0;
+ instp->audio_all.marker = 0;
+ instp->audio_all.payt = 3;
+ instp->audio_all.seqnum = htons((*(struct el_node **)nodep)->seqnum++);
+ instp->audio_all.time = htonl(0);
+ instp->audio_all.ssrc = instp->mynode;
+
+ /*
+ ast_log(LOG_NOTICE, "sending to %s(%s)\n",
+ (*(struct el_node **)nodep)->call, (*(struct el_node **)nodep)->ip);
+ */
+ sendto(instp->audio_sock, (char *)&instp->audio_all, sizeof(instp->audio_all),
+ 0,(struct sockaddr *)&sin,sizeof(sin));
}
}
}
@@ -701,21 +758,21 @@
sin.sin_port = htons(instp->audio_port);
sin.sin_addr.s_addr = inet_addr((*(struct el_node **)nodep)->ip);
- audio_all.version = 3;
- audio_all.pad = 0;
- audio_all.ext = 0;
- audio_all.csrc = 0;
- audio_all.marker = 0;
- audio_all.payt = 3;
- audio_all.seqnum = htons((*(struct el_node **)nodep)->seqnum++);
- audio_all.time = htonl(0);
- audio_all.ssrc = instp->mynode;
+ instp->audio_all.version = 3;
+ instp->audio_all.pad = 0;
+ instp->audio_all.ext = 0;
+ instp->audio_all.csrc = 0;
+ instp->audio_all.marker = 0;
+ instp->audio_all.payt = 3;
+ instp->audio_all.seqnum = htons((*(struct el_node **)nodep)->seqnum++);
+ instp->audio_all.time = htonl(0);
+ instp->audio_all.ssrc = instp->mynode;
/*
ast_log(LOG_NOTICE, "sending to %s(%s)\n",
(*(struct el_node **)nodep)->call, (*(struct el_node **)nodep)->ip);
*/
- sendto(instp->audio_sock, (char *)&audio_all, sizeof(audio_all),
+ sendto(instp->audio_sock, (char *)&instp->audio_all, sizeof(instp->audio_all),
0,(struct sockaddr *)&sin,sizeof(sin));
}
}
@@ -742,9 +799,9 @@
(*(struct el_node **)nodep)->countdown --;
if ((*(struct el_node **)nodep)->countdown < 0) {
- strncpy(el_node_test.ip,(*(struct el_node **)nodep)->ip,EL_IP_SIZE);
- strncpy(el_node_test.call,(*(struct el_node **)nodep)->call,EL_CALL_SIZE);
- ast_log(LOG_NOTICE,"countdown for %s(%s) negative\n",el_node_test.call,el_node_test.ip);
+ strncpy(instp->el_node_test.ip,(*(struct el_node **)nodep)->ip,EL_IP_SIZE);
+ strncpy(instp->el_node_test.call,(*(struct el_node **)nodep)->call,EL_CALL_SIZE);
+ ast_log(LOG_NOTICE,"countdown for %s(%s) negative\n",instp->el_node_test.call,instp->el_node_test.ip);
}
sdes_length = rtcp_make_sdes(sdes_packet,sizeof(sdes_packet),
instp->mycall,instp->myname);
@@ -770,6 +827,8 @@
if (found_key) {
ast_log(LOG_NOTICE,"...removing %s(%s)\n", (*found_key)->call, (*found_key)->ip);
found = 1;
+ if (!(*found_key)->instp->confmode)
+ ast_softhangup((*found_key)->chan,AST_SOFTHANGUP_DEV);
tdelete(key, &el_node_list, compare_ip);
}
return found;
@@ -871,164 +930,6 @@
static struct ast_frame *el_xread(struct ast_channel *ast)
{
struct el_pvt *p = ast->tech_pvt;
- struct el_instance *instp = p->instp;
- char buf[1024];
- struct sockaddr_in sin;
- int i;
- /* struct ast_frame fr; */
- struct el_rxqast *qpast;
- struct el_rxqel *qpel;
-
- socklen_t fromlen;
- ssize_t recvlen;
- size_t len;
-
- struct el_node *el_node_key = NULL;
- struct el_node **found_key = NULL;
- struct rtcp_sdes_request items;
- char call_name[128];
- char *call = NULL;
- char *name = NULL;
- char *ptr = NULL;
-
- len = 0;
- ioctl(instp->ctrl_sock,FIONREAD,&len);
- if (len > 0) {
- fromlen = sizeof(struct sockaddr_in);
- recvlen = recvfrom(instp->ctrl_sock,
- buf,
- sizeof(buf) - 1,
- 0,
- (struct sockaddr *)&sin,&fromlen);
- if (recvlen > 0) {
- buf[recvlen] = '\0';
-#ifdef OLD_ASTERISK
- ast_inet_ntoa(el_node_test.ip,EL_IP_SIZE,sin.sin_addr);
-#else
- strncpy(el_node_test.ip,ast_inet_ntoa(sin.sin_addr),EL_IP_SIZE);
-#endif
- if (is_rtcp_sdes((unsigned char *)buf,recvlen)) {
- call_name[0] = '\0';
- items.nitems = 1;
- items.item[0].r_item = 2;
- items.item[0].r_text = NULL;
- parse_sdes((unsigned char *)buf,&items);
- if (items.item[0].r_text != NULL)
- copy_sdes_item(items.item[0].r_text, call_name, 127);
-
- if (call_name[0] != '\0') {
- ptr = strchr(call_name, (int)' ');
- if (ptr) {
- *ptr = '\0';
- call = call_name;
- name = ptr + 1;
- found_key = (struct el_node **)tfind(&el_node_test, &el_node_list, compare_ip);
- if (found_key) {
- (*found_key)->countdown = instp->rtcptimeout;
-
- /* different callsigns behind a NAT router, running -L, -R, ... */
- if (strncmp((*found_key)->call,call,EL_CALL_SIZE) != 0) {
- ast_log(LOG_NOTICE,"Call changed from %s to %s\n",
- (*found_key)->call,call);
- strncpy((*found_key)->call,call,EL_CALL_SIZE);
- }
-
- if (strncmp((*found_key)->name, name, EL_NAME_SIZE) != 0)
- strncpy((*found_key)->name,name,EL_NAME_SIZE);
- }
- else {
- el_node_key = (struct el_node *)malloc(sizeof(struct el_node));
- if (el_node_key) {
- strncpy(el_node_key->call,call,EL_CALL_SIZE);
- strncpy(el_node_key->ip, el_node_test.ip, EL_IP_SIZE);
-
- strncpy(el_node_key->name,name,EL_NAME_SIZE);
- el_node_key->nodenum = 0;
- el_node_key->countdown = instp->rtcptimeout;
- el_node_key->seqnum = 1;
- el_node_key->instp = instp;
-
- if (tsearch(el_node_key, &el_node_list, compare_ip))
- ast_log(LOG_NOTICE, "new CALL=%s,ip=%s,name=%s\n",
- el_node_key->call,el_node_key->ip,el_node_key->name);
- else {
- ast_log(LOG_ERROR, "tsearch() failed to add CALL=%s,ip=%s,name=%s\n",
- el_node_key->call,el_node_key->ip,el_node_key->name);
- free(el_node_key);
- }
- }
- else
- ast_log(LOG_ERROR,"malloc() failed for new CALL=%s, ip=%s\n",
- call,el_node_test.ip);
- }
- }
- }
- }
- else
- if (is_rtcp_bye((unsigned char *)buf,recvlen))
- {
- if (find_delete(&el_node_test))
- ast_log(LOG_NOTICE,"disconnect from ip=%s\n",el_node_test.ip);
- else
- ast_log(LOG_NOTICE, "ip=%s,busy, denied or multiple disconnects\n",el_node_test.ip);
- }
- }
- }
-
- len = 0;
- ioctl(instp->audio_sock,FIONREAD,&len);
- if (len > 0)
- {
- fromlen = sizeof(struct sockaddr_in);
- recvlen = recvfrom(instp->audio_sock,
- buf,
- sizeof(buf) - 1,
- 0,
- (struct sockaddr *)&sin,&fromlen);
- if (recvlen > 0) {
- buf[recvlen] = '\0';
-#ifdef OLD_ASTERISK
- ast_inet_ntoa(el_node_test.ip,EL_IP_SIZE,sin.sin_addr);
-#else
- strncpy(el_node_test.ip,ast_inet_ntoa(sin.sin_addr),EL_IP_SIZE);
-#endif
- if (buf[0] == 0x6f) {
- process_cmd(buf,recvlen,&el_node_test,instp);
- }
- else {
- found_key = (struct el_node **)tfind(&el_node_test, &el_node_list, compare_ip);
- if (found_key) {
- (*found_key)->countdown = instp->rtcptimeout;
- if (recvlen == sizeof(struct gsmVoice_t)) {
- if ((((struct gsmVoice_t *)buf)->version == 3) &&
- (((struct gsmVoice_t *)buf)->payt == 3)) {
-
- /* break them up for Asterisk */
- for (i = 0; i < BLOCKING_FACTOR; i++) {
- qpast = ast_malloc(sizeof(struct el_rxqast));
- if (!qpast) {
- ast_log(LOG_NOTICE,"Cannot malloc for qpast\n");
- break;
- }
- memcpy(qpast->buf,((struct gsmVoice_t *)buf)->data + (GSM_FRAME_SIZE * i),GSM_FRAME_SIZE);
- insque((struct qelem *)qpast,(struct qelem *)p->rxqast.qe_back);
- }
-
- /* need complete packet and IP address for Echolink */
- qpel = ast_malloc(sizeof(struct el_rxqel));
- if (!qpel)
- ast_log(LOG_NOTICE,"Cannot malloc for qpel\n");
- else {
- memcpy(qpel->buf,((struct gsmVoice_t *)buf)->data,BLOCKING_FACTOR * GSM_FRAME_SIZE);
- strncpy(qpel->fromip,el_node_test.ip,EL_IP_SIZE);
- insque((struct qelem *)qpel,(struct qelem *)p->rxqel.qe_back);
- }
- }
- }
- }
- }
- }
- }
p->fr.frametype = 0;
p->fr.subclass = 0;
@@ -1064,6 +965,12 @@
if (frame->frametype != AST_FRAME_VOICE) return 0;
+ if ((!p->firstsent) && (!instp->confmode))
+ {
+ instp->el_node_test.ip[0] = '\0';
+ twalk(el_node_list, send_heartbeat);
+ p->firstsent = 1;
+ }
/* Echolink to Asterisk */
if (p->rxqast.qe_forw != &p->rxqast) {
for(n = 0,qpast = p->rxqast.qe_forw; qpast != &p->rxqast; qpast = qpast->qe_forw) {
@@ -1124,7 +1031,7 @@
}
if (p->rxkey) p->rxkey--;
- if (p->rxqel.qe_forw != &p->rxqel)
+ if (instp->confmode && (p->rxqel.qe_forw != &p->rxqel))
{
for(m = 0,qpel = p->rxqel.qe_forw; qpel != &p->rxqel; qpel = qpel->qe_forw)
m++;
@@ -1143,15 +1050,15 @@
qpel = p->rxqel.qe_forw;
remque((struct qelem *)qpel);
- memcpy(audio_all_but_one.data,qpel->buf,BLOCKING_FACTOR * GSM_FRAME_SIZE);
- strncpy(el_node_test.ip, qpel->fromip, EL_IP_SIZE);
+ memcpy(instp->audio_all_but_one.data,qpel->buf,BLOCKING_FACTOR * GSM_FRAME_SIZE);
+ strncpy(instp->el_node_test.ip, qpel->fromip, EL_IP_SIZE);
ast_free(qpel);
p->keepalive = KEEPALIVE_TIME;
twalk(el_node_list, send_audio_all_but_one);
if (instp->fdr >= 0)
- write(instp->fdr, audio_all_but_one.data, BLOCKING_FACTOR * GSM_FRAME_SIZE);
+ write(instp->fdr, instp->audio_all_but_one.data, BLOCKING_FACTOR * GSM_FRAME_SIZE);
}
}
else
@@ -1163,10 +1070,18 @@
}
if (p->txkey || p->txindex) {
p->keepalive = KEEPALIVE_TIME;
- memcpy(audio_all.data + (GSM_FRAME_SIZE * p->txindex++), frame->data,GSM_FRAME_SIZE);
+ memcpy(instp->audio_all.data + (GSM_FRAME_SIZE * p->txindex++), frame->data,GSM_FRAME_SIZE);
}
if (p->txindex >= BLOCKING_FACTOR) {
- twalk(el_node_list, send_audio_all);
+ if (instp->confmode)
+ {
+ twalk(el_node_list, send_audio_all);
+ }
+ else
+ {
+ strcpy(instp->el_node_test.ip,p->ip);
+ twalk(el_node_list, send_audio_only_one);
+ }
p->txindex = 0;
}
}
@@ -1176,33 +1091,31 @@
p->keepalive = KEEPALIVE_TIME;
/* Echolink: send heartbeats and drop dead stations */
- el_node_test.ip[0] = '\0';
+ instp->el_node_test.ip[0] = '\0';
twalk(el_node_list, send_heartbeat);
- if (el_node_test.ip[0] != '\0') {
- if (find_delete(&el_node_test)) {
+ if (instp->el_node_test.ip[0] != '\0') {
+ if (find_delete(&instp->el_node_test)) {
bye_length = rtcp_make_bye(bye,"rtcp timeout");
sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = inet_addr(el_node_test.ip);
+ sin.sin_addr.s_addr = inet_addr(instp->el_node_test.ip);
sin.sin_port = htons(instp->ctrl_port);
for (i = 0; i < 20; i++)
sendto(instp->ctrl_sock, bye, bye_length,
0,(struct sockaddr *)&sin,sizeof(sin));
- ast_log(LOG_NOTICE,"call=%s RTCP timeout, removing\n",el_node_test.call);
+ ast_log(LOG_NOTICE,"call=%s RTCP timeout, removing\n",instp->el_node_test.call);
}
- el_node_test.ip[0] = '\0';
+ instp->el_node_test.ip[0] = '\0';
}
return 0;
}
-static struct ast_channel *el_new(struct el_pvt *i, int state)
+static struct ast_channel *el_new(struct el_pvt *i, int state, unsigned int nodenum)
{
struct ast_channel *tmp;
struct el_instance *instp = i->instp;
- tmp = ast_channel_alloc(1, state, 0, 0, "", "s", context, 0, "echolink/%s", i->stream);
+ tmp = ast_channel_alloc(1, state, 0, 0, "", instp->astnode, instp->context, 0, "echolink/%s", i->stream);
if (tmp) {
tmp->tech = &el_tech;
- tmp->fds[0] = instp->audio_sock;
- tmp->fds[1] = instp->ctrl_sock;
tmp->nativeformats = prefformat;
tmp->rawreadformat = prefformat;
tmp->rawwriteformat = prefformat;
@@ -1211,9 +1124,16 @@
if (state == AST_STATE_RING)
tmp->rings = 1;
tmp->tech_pvt = i;
- ast_copy_string(tmp->context, context, sizeof(tmp->context));
- ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
+ ast_copy_string(tmp->context, instp->context, sizeof(tmp->context));
+ ast_copy_string(tmp->exten, instp->astnode, sizeof(tmp->exten));
ast_string_field_set(tmp, language, "");
+ if (nodenum > 0)
+ {
+ char tmpstr[30];
+
+ sprintf(tmpstr,"3%u",nodenum);
+ ast_set_callerid(tmp,tmpstr,NULL,NULL);
+ }
i->owner = tmp;
i->u = ast_module_user_add(tmp);
if (state != AST_STATE_DOWN) {
@@ -1242,7 +1162,7 @@
}
p = el_alloc(data);
if (p) {
- tmp = el_new(p, AST_STATE_DOWN);
+ tmp = el_new(p, AST_STATE_DOWN,0);
if (!tmp)
el_destroy(p);
}
@@ -1253,7 +1173,7 @@
{
int n;
- run_forever = (char)0;
+ run_forever = 0;
tdestroy(el_node_list, free_node);
for(n = 0; n < ninstances; n++)
{
@@ -1402,7 +1322,7 @@
int rc = 0;
struct el_instance *instp = (struct el_instance *)data;
- ast_log(LOG_NOTICE, "Echolink registration thread started.\n");
+ ast_log(LOG_NOTICE, "Echolink registration thread started on %s.\n",instp->name);
while (run_forever)
{
if (i >= EL_MAX_SERVERS)
@@ -1427,8 +1347,225 @@
Send a de-register message, but what is the point,
Echolink deactivates this node within 6 minutes
*/
+ ast_log(LOG_NOTICE, "Echolink registration thread exited.\n");
pthread_exit(NULL);
- ast_log(LOG_NOTICE, "Echolink registration thread exited.\n");
+}
+
+static void *el_reader(void *data)
+{
+ struct el_instance *instp = (struct el_instance *)data;
+ char buf[1024];
+ struct sockaddr_in sin;
+ int i,x;
+ struct el_rxqast *qpast;
+ struct el_rxqel *qpel;
+
+ socklen_t fromlen;
+ ssize_t recvlen;
+
+ struct el_node *el_node_key = NULL;
+ struct el_node **found_key = NULL;
+ struct rtcp_sdes_request items;
+ char call_name[128];
+ char *call = NULL;
+ char *name = NULL;
+ char *ptr = NULL;
+ fd_set fds[2];
+ struct timeval tmout;
+
+ ast_log(LOG_NOTICE, "Echolink reader thread started on %s.\n",instp->name);
+ while(run_forever)
+ {
+ FD_ZERO(fds);
+ FD_SET(instp->audio_sock,fds);
+ FD_SET(instp->ctrl_sock,fds);
+ x = instp->audio_sock;
+ if (instp->ctrl_sock > x) x = instp->ctrl_sock;
+ tmout.tv_sec = 0;
+ tmout.tv_usec = 50000;
+ i = select(x + 1,fds,NULL,NULL,&tmout);
+ if (i == 0) continue;
+ if (i < 0)
+ {
+ ast_log(LOG_ERROR,"Error in select()\n");
+ pthread_exit(NULL);
+ }
+ if (FD_ISSET(instp->ctrl_sock,fds)) /* if a ctrl packet */
+ {
+ fromlen = sizeof(struct sockaddr_in);
+ recvlen = recvfrom(instp->ctrl_sock,buf,sizeof(buf) - 1,
+ 0,(struct sockaddr *)&sin,&fromlen);
+ if (recvlen > 0)
+ {
+ buf[recvlen] = '\0';
+#ifdef OLD_ASTERISK
+ ast_inet_ntoa(instp->el_node_test.ip,EL_IP_SIZE,sin.sin_addr);
+#else
+ strncpy(instp->el_node_test.ip,ast_inet_ntoa(sin.sin_addr),
+ EL_IP_SIZE);
+#endif
+ if (is_rtcp_sdes((unsigned char *)buf,recvlen))
+ {
+ call_name[0] = '\0';
+ items.nitems = 1;
+ items.item[0].r_item = 2;
+ items.item[0].r_text = NULL;
+ parse_sdes((unsigned char *)buf,&items);
+ if (items.item[0].r_text != NULL)
+ copy_sdes_item(items.item[0].r_text,call_name, 127);
+ if (call_name[0] != '\0')
+ {
+ ptr = strchr(call_name, (int)' ');
+ if (ptr)
+ {
+ *ptr = '\0';
+ call = call_name;
+ name = ptr + 1;
+ found_key = (struct el_node **)tfind(&instp->el_node_test,
+ &el_node_list, compare_ip);
+ if (found_key)
+ {
+ (*found_key)->countdown = instp->rtcptimeout;
+ /* different callsigns behind a NAT router, running -L, -R, ... */
+ if (strncmp((*found_key)->call,call,EL_CALL_SIZE) != 0)
+ {
+ ast_log(LOG_NOTICE,"Call changed from %s to %s\n",
+ (*found_key)->call,call);
+ strncpy((*found_key)->call,call,EL_CALL_SIZE);
+ }
+ if (strncmp((*found_key)->name, name, EL_NAME_SIZE) != 0)
+ strncpy((*found_key)->name,name,EL_NAME_SIZE);
+ }
+ else /* otherwise its a new request */
+ {
+ el_node_key = (struct el_node *)malloc(sizeof(struct el_node));
+ if (el_node_key)
+ {
+ strncpy(el_node_key->call,call,EL_CALL_SIZE);
+ strncpy(el_node_key->ip, instp->el_node_test.ip, EL_IP_SIZE);
+ strncpy(el_node_key->name,name,EL_NAME_SIZE);
+ el_node_key->nodenum = 385239;
+ el_node_key->countdown = instp->rtcptimeout;
+ el_node_key->seqnum = 1;
+ el_node_key->instp = instp;
+ if (tsearch(el_node_key, &el_node_list, compare_ip))
+ {
+ ast_log(LOG_NOTICE, "new CALL=%s,ip=%s,name=%s\n",
+ el_node_key->call,el_node_key->ip,
+ el_node_key->name);
+ if (instp->confmode)
+ {
+ el_node_key->p = instp->confp;
+ }
+ else
+ {
+ el_node_key->p = el_alloc((void *)instp);
+ strncpy(el_node_key->p->ip, instp->el_node_test.ip,
+ EL_IP_SIZE);
+ if (el_node_key->p)
+ {
+ el_node_key->chan = el_new(el_node_key->p,
+ AST_STATE_UP,el_node_key->nodenum);
+ if (!el_node_key->chan)
+ el_destroy(el_node_key->p);
+ }
+ }
+ }
+ else
+ {
+ ast_log(LOG_ERROR, "tsearch() failed to add CALL=%s,ip=%s,name=%s\n",
+ el_node_key->call,el_node_key->ip,el_node_key->name);
+ free(el_node_key);
+ }
+ }
+ else
+ {
+ ast_log(LOG_ERROR,"malloc() failed for new CALL=%s, ip=%s\n",
+ call,instp->el_node_test.ip);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (is_rtcp_bye((unsigned char *)buf,recvlen))
+ {
+ if (find_delete(&instp->el_node_test))
+ ast_log(LOG_NOTICE,"disconnect from ip=%s\n",instp->el_node_test.ip);
+ else
+ ast_log(LOG_NOTICE, "ip=%s,busy, denied or multiple disconnects\n",instp->el_node_test.ip);
+ }
+ }
+ }
+ }
+ if (FD_ISSET(instp->audio_sock,fds)) /* if an audio packet */
+ {
+ fromlen = sizeof(struct sockaddr_in);
+ recvlen = recvfrom(instp->audio_sock,buf,sizeof(buf) - 1,0,
+ (struct sockaddr *)&sin,&fromlen);
+ if (recvlen > 0)
+ {
+ buf[recvlen] = '\0';
+#ifdef OLD_ASTERISK
+ ast_inet_ntoa(instp->el_node_test.ip,EL_IP_SIZE,sin.sin_addr);
+#else
+ strncpy(instp->el_node_test.ip,ast_inet_ntoa(sin.sin_addr),EL_IP_SIZE);
+#endif
+ if (buf[0] == 0x6f)
+ {
+ process_cmd(buf,recvlen,&instp->el_node_test,instp);
+ }
+ else
+ {
+ found_key = (struct el_node **)tfind(&instp->el_node_test, &el_node_list, compare_ip);
+ if (found_key)
+ {
+ struct el_pvt *p = (*found_key)->p;
+ (*found_key)->countdown = instp->rtcptimeout;
+ if (recvlen == sizeof(struct gsmVoice_t))
+ {
+ if ((((struct gsmVoice_t *)buf)->version == 3) &&
+ (((struct gsmVoice_t *)buf)->payt == 3))
+ {
+ /* break them up for Asterisk */
+ for (i = 0; i < BLOCKING_FACTOR; i++)
+ {
+ qpast = ast_malloc(sizeof(struct el_rxqast));
+ if (!qpast)
+ {
+ ast_log(LOG_NOTICE,"Cannot malloc for qpast\n");
+ pthread_exit(NULL);
+ }
+ memcpy(qpast->buf,((struct gsmVoice_t *)buf)->data +
+ (GSM_FRAME_SIZE * i),GSM_FRAME_SIZE);
+ insque((struct qelem *)qpast,(struct qelem *)
+ p->rxqast.qe_back);
+ }
+ }
+ if (!instp->confmode) continue;
+ /* need complete packet and IP address for Echolink */
+ qpel = ast_malloc(sizeof(struct el_rxqel));
+ if (!qpel)
+ {
+ ast_log(LOG_NOTICE,"Cannot malloc for qpel\n");
+ }
+ else
+ {
+ memcpy(qpel->buf,((struct gsmVoice_t *)buf)->data,
+ BLOCKING_FACTOR * GSM_FRAME_SIZE);
+ strncpy(qpel->fromip,instp->el_node_test.ip,EL_IP_SIZE);
+ insque((struct qelem *)qpel,(struct qelem *)
+ p->rxqel.qe_back);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ ast_log(LOG_NOTICE, "Echolink read thread exited.\n");
+ pthread_exit(NULL);
}
static int store_config(struct ast_config *cfg,char *ctg)
@@ -1436,6 +1573,7 @@
char *val;
struct el_instance *instp;
struct sockaddr_in si_me;
+pthread_attr_t attr;
if (ninstances >= EL_MAX_INSTANCES)
{
@@ -1492,6 +1630,24 @@
else
instp->mynode = atol(val);
+ val = (char *) ast_variable_retrieve(cfg,ctg,"astnode");
+ if (val)
+ {
+ strncpy(instp->astnode,val,EL_NAME_SIZE);
+ }
+ else
+ {
+ strcpy(instp->astnode,"1999");
+ }
+ val = (char *) ast_variable_retrieve(cfg,ctg,"context");
+ if (val)
+ {
+ strncpy(instp->context,val,EL_NAME_SIZE);
+ }
+ else
+ {
+ strcpy(instp->context,"echolink-in");
+ }
val = (char *) ast_variable_retrieve(cfg,ctg,"call");
if (!val)
strncpy(instp->mycall,"INVALID",EL_CALL_SIZE);
@@ -1532,6 +1688,9 @@
strncpy(instp->myemail, "INVALID", EL_EMAIL_SIZE);
else
strncpy(instp->myemail,val,EL_EMAIL_SIZE);
+
+ val = (char *) ast_variable_retrieve(cfg,ctg,"confmode");
+ if (val) instp->confmode = ast_true(val); else instp->confmode = 0;
val = (char *) ast_variable_retrieve(cfg,ctg,"server1");
if (!val)
@@ -1606,7 +1765,10 @@
fcntl(instp->audio_sock,F_SETFL,O_NONBLOCK);
fcntl(instp->ctrl_sock,F_SETFL,O_NONBLOCK);
strncpy(instp->name,ctg,EL_NAME_SIZE);
- ast_pthread_create(&el_register_thread,NULL,el_register,(void *)instp);
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ast_pthread_create(&el_register_thread,&attr,el_register,(void *)instp);
+ ast_pthread_create(&el_reader_thread,&attr,el_reader,(void *)instp);
instances[ninstances++] = instp;
ast_log(LOG_NOTICE, "Echolink/%s listening on %s port %s\n", instp->name, instp->ipaddr,instp->port);
More information about the asterisk-commits
mailing list