[svn-commits] jdixon: branch jdixon/chan_usbradio-1.4 r139702 - /team/jdixon/chan_usbradio-...

SVN commits to the Digium repositories svn-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 svn-commits mailing list