[asterisk-commits] jdixon: branch jdixon/chan_usbradio-1.4 r139702 - /team/jdixon/chan_usbradio-...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun Aug 24 00:48:49 CDT 2008
Author: jdixon
Date: Sun Aug 24 00:48:48 2008
New Revision: 139702
URL: http://svn.digium.com/view/asterisk?view=rev&rev=139702
Log:
Got initial station database download working
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=139702&r1=139701&r2=139702
==============================================================================
--- 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 Sun Aug 24 00:48:48 2008
@@ -31,7 +31,7 @@
/*** MODULEINFO
***/
-/* Version 0.7, 08/22/2008
+/* Version 0.8, 08/23/2008
Echolink channel driver for Asterisk/app_rpt.
A lot more has to be added,
Here is what comes to mind first:
@@ -43,9 +43,7 @@
---> no capacity limits.
---> no banned or privare station list.
---> no admin list, only local 127.0.0.1 access.
----> node number unused.
---> no welcome text message.
----> no welcome audio message.
---> no login or connect timeouts.
---> no max TX time limit.
---> no activity reporting.
@@ -97,6 +95,9 @@
#include <sys/ioctl.h>
#include <ctype.h>
#include <search.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
@@ -109,6 +110,7 @@
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/translate.h"
+#include "asterisk/astdb.h"
#define MAX_RXKEY_TIME 4
@@ -140,6 +142,8 @@
static const char tdesc[] = "Echolink channel driver by KI4LKF";
static int prefformat = AST_FORMAT_GSM;
static char type[] = "echolink";
+char db_active = 'a';
+char db_loading = 0;
/* Echolink audio packet heafer */
struct gsmVoice_t {
@@ -240,7 +244,6 @@
int txindex;
struct el_rxqast rxqast;
struct el_rxqel rxqel;
- char firstsent;
char firstheard;
struct ast_dsp *dsp;
struct ast_module_user *u;
@@ -302,6 +305,7 @@
/* Echolink registration thread */
static pthread_t el_register_thread;
static pthread_t el_reader_thread;
+static pthread_t el_directory_thread;
static int run_forever = 1;
static char *config = "echolink.conf";
@@ -586,7 +590,7 @@
ast_mutex_lock(&instp->lock);
strcpy(instp->el_node_test.ip,cp);
do_new_call(instp,p,"OUTBOUND","OUTBOUND");
-// process_cmd(buf,"127.0.0.1",instp);
+ process_cmd(buf,"127.0.0.1",instp);
ast_mutex_unlock(&instp->lock);
}
ast_setstate(ast,AST_STATE_RINGING);
@@ -1052,14 +1056,6 @@
if (frame->frametype != AST_FRAME_VOICE) return 0;
- ast_mutex_lock(&instp->lock);
-
- 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) {
@@ -1163,7 +1159,9 @@
strncpy(instp->el_node_test.ip, qpel->fromip, EL_IP_SIZE);
ast_free(qpel);
+ ast_mutex_lock(&instp->lock);
twalk(el_node_list, send_audio_all_but_one);
+ ast_mutex_unlock(&instp->lock);
if (instp->fdr >= 0)
write(instp->fdr, instp->audio_all_but_one.data, BLOCKING_FACTOR * GSM_FRAME_SIZE);
@@ -1181,6 +1179,7 @@
memcpy(instp->audio_all.data + (GSM_FRAME_SIZE * p->txindex++), frame->data,GSM_FRAME_SIZE);
}
if (p->txindex >= BLOCKING_FACTOR) {
+ ast_mutex_lock(&instp->lock);
if (instp->confmode)
{
twalk(el_node_list, send_audio_all);
@@ -1190,18 +1189,16 @@
strcpy(instp->el_node_test.ip,p->ip);
twalk(el_node_list, send_audio_only_one);
}
+ ast_mutex_unlock(&instp->lock);
p->txindex = 0;
}
}
- if (p->keepalive--)
- {
- ast_mutex_unlock(&instp->lock);
- return 0;
- }
+ if (p->keepalive--) return 0;
p->keepalive = KEEPALIVE_TIME;
/* Echolink: send heartbeats and drop dead stations */
+ ast_mutex_unlock(&instp->lock);
instp->el_node_test.ip[0] = '\0';
twalk(el_node_list, send_heartbeat);
if (instp->el_node_test.ip[0] != '\0') {
@@ -1210,9 +1207,11 @@
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(instp->el_node_test.ip);
sin.sin_port = htons(instp->ctrl_port);
+ ast_mutex_lock(&instp->lock);
for (i = 0; i < 20; i++)
sendto(instp->ctrl_sock, bye, bye_length,
0,(struct sockaddr *)&sin,sizeof(sin));
+ ast_mutex_unlock(&instp->lock);
ast_log(LOG_NOTICE,"call=%s RTCP timeout, removing\n",instp->el_node_test.call);
}
instp->el_node_test.ip[0] = '\0';
@@ -1437,6 +1436,191 @@
return 0;
}
+static int net_get_line(int s,char *str, int max)
+{
+static int index = 0;
+static int nread = 0;
+int nstr;
+static unsigned char buf[1024];
+unsigned char c;
+
+ nstr = 0;
+ for(;;)
+ {
+ if (index >= nread)
+ {
+ index = 0;
+ nread = recv(s,buf,sizeof(buf) - 1,0);
+ if ((nread) < 1) return(nread);
+ }
+ if (buf[index] > 126) buf[index] = ' ';
+ c = buf[index++];
+ str[nstr++] = c & 0x7f;
+ str[nstr] = 0;
+ if (c < ' ') break;
+ if (nstr >= max) break;
+ }
+ return(nstr);
+}
+
+#define EL_DIRECTORY_PORT 5200
+#define EL_DB_ROOT "echolink"
+
+
+static void el_zapem(char loading)
+{
+char str[10];
+
+ str[0] = loading;
+ str[1] = 0;
+ ast_db_deltree(EL_DB_ROOT,str);
+}
+
+static int do_el_directory(char *hostname)
+{
+struct ast_hostent ah;
+struct hostent *host;
+struct sockaddr_in dirserver;
+char str[200],dbstr[100],ipaddr[50],nodenum[50];
+int sock,n = 0;
+
+ db_active = 'a';
+ db_loading = 'a';
+ dbstr[0] = db_active;
+ dbstr[1] = 0;
+ if (!ast_db_get(EL_DB_ROOT,dbstr,str,sizeof(str) - 1))
+ {
+ db_active = *str;
+ if (db_active == 'a') db_loading = 'b';
+ }
+ if (sendcmd(hostname,instances[0])) return -1;
+ host = ast_gethostbyname(hostname,&ah);
+ if (!host)
+ {
+ ast_log(LOG_NOTICE,"Unable to resolve name for directory server %s\n",hostname);
+ return -1;
+ }
+ memset(&dirserver, 0, sizeof(dirserver)); /* Clear struct */
+ dirserver.sin_family = AF_INET; /* Internet/IP */
+ dirserver.sin_addr.s_addr =
+ *(unsigned long *) host->h_addr_list[0];
+ dirserver.sin_port = htons(EL_DIRECTORY_PORT); /* server port */
+ sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock < 0)
+ {
+ ast_log(LOG_NOTICE,"Unable to obtain a socket for directory server %s\n",hostname);
+ return -1;
+ }
+ /* Establish connection */
+ if (connect(sock,(struct sockaddr *) &dirserver,
+ sizeof(dirserver)) < 0)
+ {
+ ast_log(LOG_NOTICE,"Unable to connect to directory server %s\n",hostname);
+ return -1;
+ }
+ strcpy(str,"s\n");
+ if (send(sock,str,strlen(str),0) < 0)
+ {
+ ast_log(LOG_NOTICE,"Unable to send to directory server %s\n",hostname);
+ return -1;
+ }
+ if ((net_get_line(sock,str,sizeof(str) - 1) < 1) ||
+ (net_get_line(sock,str,sizeof(str) - 1) < 1))
+ {
+ ast_log(LOG_NOTICE,"Error in directory download (header) on %s\n",hostname);
+ return -1;
+ }
+ el_zapem(db_loading);
+ for(;;)
+ {
+ if (net_get_line(sock,str,sizeof(str) - 1) < 1) break;
+ if (*str <= ' ') break;
+ if (net_get_line(sock,str,sizeof(str) - 1) < 1)
+ {
+ ast_log(LOG_NOTICE,"Error in directory download on %s\n",hostname);
+ el_zapem(db_loading);
+ return -1;
+ }
+ if (net_get_line(sock,str,sizeof(str) - 1) < 1)
+ {
+ ast_log(LOG_NOTICE,"Error in directory download on %s\n",hostname);
+ el_zapem(db_loading);
+ return -1;
+ }
+ if (str[strlen(str) - 1] == '\n')
+ str[strlen(str) - 1] = 0;
+ strncpy(nodenum,str,sizeof(nodenum) - 1);
+ if (net_get_line(sock,str,sizeof(str) - 1) < 1)
+ {
+ ast_log(LOG_NOTICE,"Error in directory download on %s\n",hostname);
+ el_zapem(db_loading);
+ return -1;
+ }
+ if (str[strlen(str) - 1] == '\n')
+ str[strlen(str) - 1] = 0;
+ strncpy(ipaddr,str,sizeof(ipaddr) - 1);
+ sprintf(dbstr,"%c/ipaddr/%s",db_loading,ipaddr);
+ if (ast_db_put(EL_DB_ROOT,dbstr,nodenum) != 0)
+ {
+ ast_log(LOG_NOTICE,"Error in putting ipaddr record %s (nodenum %s)",ipaddr,nodenum);
+ return -1;
+ }
+ sprintf(dbstr,"%c/nodenum/%s",db_loading,nodenum);
+ if (ast_db_put(EL_DB_ROOT,dbstr,ipaddr))
+ {
+ ast_log(LOG_NOTICE,"Error in putting nodenum record %s (ipaddr %s)",nodenum,ipaddr);
+ return -1;
+ }
+ n++;
+ }
+ db_active = db_loading;
+ db_loading = 0;
+ dbstr[0] = db_active;
+ dbstr[1] = 0;
+ if (ast_db_put(EL_DB_ROOT,"active",dbstr) != 0)
+ {
+ ast_log(LOG_NOTICE,"Error in finalizing DB process on %s\n",hostname);
+ return -1;
+ }
+
+ ast_log(LOG_NOTICE,"Diretory pgm done downloading, %d records\n",n);
+ return 0;
+}
+
+static void *el_directory(void *data)
+{
+ short i = 0;
+ int rc = 0;
+
+ while (run_forever)
+ {
+ if (i >= EL_MAX_SERVERS)
+ i = 0;
+
+ do {
+ if (instances[0]->elservers[i][0] != '\0')
+ break;
+ i++;
+ } while (i < EL_MAX_SERVERS);
+
+ if (i < EL_MAX_SERVERS) {
+ ast_log(LOG_NOTICE, "Trying to register with Echolink server %s\n", instances[0]->elservers[i]);
+ rc = do_el_directory(instances[0]->elservers[i++]);
+ }
+ if (rc == 0)
+ sleep(1800);
+ else
+ sleep(20);
+ }
+ /*
+ Send a de-register message, but what is the point,
+ Echolink deactivates this node within 6 minutes
+ */
+ ast_log(LOG_NOTICE, "Echolink directory thread exited.\n");
+ pthread_exit(NULL);
+}
+
+
static void *el_register(void *data)
{
short i = 0;
@@ -1475,6 +1659,7 @@
static int do_new_call(struct el_instance *instp, struct el_pvt *p, char *call, char *name)
{
struct el_node *el_node_key = NULL;
+ char dbstr[40],nodestr[30];
el_node_key = (struct el_node *)malloc(sizeof(struct el_node));
if (el_node_key)
@@ -1482,7 +1667,14 @@
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 = 123456;
+ snprintf(dbstr,sizeof(dbstr) - 1,"%c/ipaddr/%s",db_active,el_node_key->ip);
+ if (ast_db_get(EL_DB_ROOT,dbstr,nodestr,sizeof(nodestr) - 1))
+ {
+ ast_log(LOG_ERROR, "Cannot find DB entry for %s\n",dbstr);
+ free(el_node_key);
+ return -1;
+ }
+ el_node_key->nodenum = atoi(nodestr) + 3000000;
el_node_key->countdown = instp->rtcptimeout;
el_node_key->seqnum = 1;
el_node_key->instp = instp;
@@ -1984,6 +2176,7 @@
{
struct ast_config *cfg = NULL;
char *ctg = NULL;
+ pthread_attr_t attr;
#ifdef NEW_ASTERISK
struct ast_flags zeroflag = {0};
@@ -2012,6 +2205,9 @@
return AST_MODULE_LOAD_DECLINE;
}
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ast_pthread_create(&el_directory_thread,&attr,el_directory,NULL);
/* Make sure we can register our channel type */
if (ast_channel_register(&el_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
More information about the asterisk-commits
mailing list