[asterisk-commits] jdixon: branch jdixon/chan_usbradio-1.4 r139864 - /team/jdixon/chan_usbradio-...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Aug 25 13:45:44 CDT 2008


Author: jdixon
Date: Mon Aug 25 13:45:44 2008
New Revision: 139864

URL: http://svn.digium.com/view/asterisk?view=rev&rev=139864
Log:
Fixed directory download and segfault on re-connect bug

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=139864&r1=139863&r2=139864
==============================================================================
--- 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 Mon Aug 25 13:45:44 2008
@@ -31,7 +31,7 @@
 /*** MODULEINFO
  ***/
 
-/* Version 0.9, 08/23/2008
+/* Version 0.10, 08/25/2008
 Echolink channel driver for Asterisk/app_rpt.
 A lot more has to be added,
 Here is what comes to mind first:
@@ -98,6 +98,7 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <netdb.h>
+#include <zlib.h>
 
 #include "asterisk/lock.h"
 #include "asterisk/channel.h"
@@ -142,8 +143,12 @@
 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;
+static char db_active = 'a';
+static char db_loading = 0;
+static char snapshot_id[50] = {'0',0};
+static int el_net_get_index = 0;
+static int el_net_get_nread = 0;
+
 
 /* Echolink audio packet heafer */
 struct gsmVoice_t {
@@ -244,6 +249,7 @@
 	int txindex;
 	struct el_rxqast rxqast;
         struct el_rxqel rxqel;
+	char firstsent;
 	char firstheard;
 	struct ast_dsp *dsp;
 	struct ast_module_user *u;
@@ -296,6 +302,7 @@
   } r;
 };
 
+int debug = 0;
 struct el_instance *instances[EL_MAX_INSTANCES];
 int ninstances = 0;
 
@@ -576,8 +583,8 @@
 	}
 	/* When we call, it just works, really, there's no destination...  Just
 	   ring the phone and wait for someone to answer */
-	if (option_debug)
-		ast_log(LOG_DEBUG, "Calling %s on %s\n", dest, ast->name);
+//	if (option_debug)
+		ast_log(LOG_NOTICE, "Calling %s on %s\n", dest, ast->name);
 	if (*dest)  /* if number specified */
 	{
 		char *str,*cp;
@@ -681,7 +688,11 @@
 
 	if (!instp->confmode)
 	{
-		ast_log(LOG_NOTICE,"Sent bye to IP address %s\n",p->ip);
+		if (debug) ast_log(LOG_DEBUG,"Sent bye to IP address %s\n",p->ip);
+		ast_mutex_lock(&instp->lock);
+		strcpy(instp->el_node_test.ip,p->ip);
+		find_delete(&instp->el_node_test);
+		ast_mutex_unlock(&instp->lock);
 		n = rtcp_make_bye(bye,"disconnected");
 		sin.sin_family = AF_INET;
 		sin.sin_addr.s_addr = inet_addr(p->ip);
@@ -917,7 +928,7 @@
 
    found_key = (struct el_node **)tfind(key, &el_node_list, compare_ip);
    if (found_key) {
-       ast_log(LOG_NOTICE,"...removing %s(%s)\n", (*found_key)->call, (*found_key)->ip); 
+       if (debug) ast_log(LOG_DEBUG,"...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);
@@ -1055,6 +1066,24 @@
 	char buf[GSM_FRAME_SIZE + AST_FRIENDLY_OFFSET];
 
 	if (frame->frametype != AST_FRAME_VOICE) return 0;
+
+	if (!p->firstsent)
+	{
+		struct sockaddr_in sin;
+		unsigned char  sdes_packet[256];
+		int sdes_length;
+
+		p->firstsent = 1;
+		memset(sdes_packet,0,sizeof(sdes_packet));
+		sdes_length = rtcp_make_sdes(sdes_packet,sizeof(sdes_packet),
+			instp->mycall,instp->myname);
+
+		sin.sin_family = AF_INET;
+		sin.sin_port = htons(instp->ctrl_port);
+		sin.sin_addr.s_addr = inet_addr(p->ip);
+		sendto(instp->ctrl_sock, sdes_packet, sdes_length, 
+			0,(struct sockaddr *)&sin,sizeof(sin));
+	}
 
         /* Echolink to Asterisk */
 	if (p->rxqast.qe_forw != &p->rxqast) {
@@ -1436,25 +1465,86 @@
   return 0;
 }
 
-static int net_get_line(int s,char *str, int max)
-{
-static int index = 0;
-static int nread = 0;
+#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 void el_zapcall(char loading,char *call)
+{
+char	node[50],ipaddr[50],str[150],dbstr[50];
+
+	sprintf(dbstr,"%c/call/%s",loading,call);
+	if (ast_db_get(EL_DB_ROOT,dbstr,str,sizeof(str) - 1)) return;
+	if (sscanf(str,"%s:%s",node,ipaddr) != 2) return;
+	ast_log(LOG_NOTICE,"Zapped %s\n",dbstr);
+	sprintf(dbstr,"%c/node/%s",loading,node);
+	ast_db_del(EL_DB_ROOT,dbstr);
+	sprintf(dbstr,"%c/ipaddr/%s",loading,ipaddr);
+	ast_db_del(EL_DB_ROOT,dbstr);
+	return;
+}
+
+static int el_net_read(int sock,unsigned char *buf1,int buf1len,
+	int compressed,struct z_stream_s *z)
+{
+unsigned char buf[512];
+int	n,i,r;
+
+	if (!compressed)
+	{
+		n = recv(sock,buf1,buf1len - 1,0);
+		if (n < 1) return(-1);
+		return(n);
+	}		
+	memset(buf1,0,buf1len);
+	memset(buf,0,sizeof(buf));
+	n = recv(sock,buf,sizeof(buf) - 1,0);
+	if (n < 1) return(-1); 
+	z->next_in = buf;
+	z->avail_in = n;
+	z->next_out = buf1;
+	z->avail_out = buf1len;
+	i = Z_NO_FLUSH;
+	if (n < (sizeof(buf) - 1)) i = Z_FINISH;
+	r = inflate(z,i);
+	if ((r != Z_OK) && (r != Z_STREAM_END))
+	{
+		if (z->msg)
+			fprintf(stderr,"Unable to inflate (Zlib): %s\n",z->msg);
+		else
+			fprintf(stderr,"Unable to inflate (Zlib)\n");
+		return -1;
+	}
+	return(buf1len - z->avail_out);
+}
+
+static int el_net_get_line(int s,char *str, int max, int compressed,
+	struct z_stream_s *z)
+{
 int nstr;
-static unsigned char buf[1024];
+static unsigned char buf[2048];
 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++];
+		if (el_net_get_index >= el_net_get_nread)
+		{
+			el_net_get_index = 0;
+			el_net_get_nread = el_net_read(s,buf,sizeof(buf),compressed,z);
+			if ((el_net_get_nread) < 1) return(el_net_get_nread);
+		}
+		if (buf[el_net_get_index] > 126) buf[el_net_get_index] = ' ';
+		c = buf[el_net_get_index++];
 		str[nstr++] = c & 0x7f;
 		str[nstr] = 0;
 		if (c < ' ') break;
@@ -1463,26 +1553,17 @@
 	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;
+char	dbstr1[100],call[50];
+int	n = 0,rep_lines,delmode;
+int	dir_compressed,dir_partial;
+struct	z_stream_s z;
+int	sock;
 
 	db_active = 'a';
 	db_loading = 'a';
@@ -1493,7 +1574,18 @@
 		db_active = *str;
 		if (db_active == 'a') db_loading = 'b';
 	}
-	if (sendcmd(hostname,instances[0])) return -1;	
+	sendcmd(hostname,instances[0]);
+	el_net_get_index = 0;
+	el_net_get_nread = 0;
+	memset(&z,0,sizeof(z));
+	if (inflateInit(&z) != Z_OK)
+	{
+		if (z.msg)
+			fprintf(stderr,"Unable to init Zlib: %s\n",z.msg);
+		else
+			fprintf(stderr,"Unable to init Zlib\n");
+		return -1;
+	}
 	host = ast_gethostbyname(hostname,&ah);
 	if (!host)
 	{
@@ -1518,30 +1610,104 @@
 		ast_log(LOG_NOTICE,"Unable to connect to directory server %s\n",hostname);
 		return -1;
 	}
-	strcpy(str,"s\n");
+	sprintf(str,"F%s\r",snapshot_id);
 	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))
+	str[strlen(str) - 1] = 0;
+printf("Sending: %s to %s\n",str,hostname);
+	if (recv(sock,str,4,0) != 4)
 	{
 		ast_log(LOG_NOTICE,"Error in directory download (header) on %s\n",hostname);
 		return -1;
-	}
-	el_zapem(db_loading);
+	} 
+	dir_compressed = 1;
+	dir_partial = 0;
+	if (!strncmp(str,"@@@",3))
+	{
+		dir_partial = 0;
+		dir_compressed = 0;
+	}
+	else if (!strncmp(str,"DDD",3))
+	{
+		dir_partial = 1;
+		dir_compressed = 0;
+	}
+	if (dir_compressed)
+	{
+		if (el_net_get_line(sock,str,sizeof(str) - 1,dir_compressed,&z) < 1)
+		{
+			ast_log(LOG_NOTICE,"Error in directory download (header) on %s\n",hostname);
+			return -1;
+		}
+printf("Line is: %s len %d\n",str,strlen(str));
+		if (!strncmp(str,"@@@",3))
+		{
+			dir_partial = 0;
+		}
+		else if (!strncmp(str,"DDD",3))
+		{
+			dir_partial = 1;
+		}
+		else
+		{
+			ast_log(LOG_NOTICE,"Error in header on %s\n",hostname);
+			return -1;
+		}
+	}
+	if (el_net_get_line(sock,str,sizeof(str) - 1,dir_compressed,&z) < 1)
+	{
+		ast_log(LOG_NOTICE,"Error in directory download (header) on %s\n",hostname);
+		return -1;
+	}
+	if (dir_compressed)
+	{
+		if(sscanf(str,"%d:%s",&rep_lines,snapshot_id) < 2)
+		{
+			ast_log(LOG_NOTICE,"Error in parsing header on %s\n",hostname);
+			return -1;
+		}	
+	}
+	else
+	{
+		if(sscanf(str,"%d",&rep_lines) < 1)
+		{
+			ast_log(LOG_NOTICE,"Error in parsing header on %s\n",hostname);
+			return -1;
+		}	
+	}
+	if (dir_partial) db_loading = db_active;
+	else el_zapem(db_loading);
+	delmode = 0;
 	for(;;)
 	{
-		if (net_get_line(sock,str,sizeof(str) - 1) < 1) break;
+		if (el_net_get_line(sock,str,sizeof(str) - 1,dir_compressed,&z) < 1) break;
 		if (*str <= ' ') break;
-		if (net_get_line(sock,str,sizeof(str) - 1) < 1)
+
+		if (!strncmp(str,"+++",3))
+		{
+			if (delmode) break;
+			if (!dir_partial) break;
+			delmode = 1;
+			continue;
+		}			
+		if (str[strlen(str) - 1] == '\n')
+			str[strlen(str) - 1] = 0;
+		strncpy(call,str,sizeof(call) - 1);
+		if (dir_partial)
+		{
+			el_zapcall(db_loading,call);
+			if (delmode) continue;
+		}
+		if (el_net_get_line(sock,str,sizeof(str) - 1,dir_compressed,&z) < 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)
+		if (el_net_get_line(sock,str,sizeof(str) - 1,dir_compressed,&z) < 1)
 		{
 			ast_log(LOG_NOTICE,"Error in directory download on %s\n",hostname);
 			el_zapem(db_loading);
@@ -1550,7 +1716,7 @@
 		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)
+		if (el_net_get_line(sock,str,sizeof(str) - 1,dir_compressed,&z) < 1)
 		{
 			ast_log(LOG_NOTICE,"Error in directory download on %s\n",hostname);
 			el_zapem(db_loading);
@@ -1571,6 +1737,13 @@
  			ast_log(LOG_NOTICE,"Error in putting nodenum record %s (ipaddr %s)",nodenum,ipaddr);
 			return -1;
 		}
+		sprintf(dbstr,"%c/call/%s",db_loading,call);
+		sprintf(dbstr1,"%s:%s",nodenum,ipaddr);
+		if (ast_db_put(EL_DB_ROOT,dbstr,dbstr1))
+		{
+ 			ast_log(LOG_NOTICE,"Error in putting call record %s (ipaddr %s)",nodenum,ipaddr);
+			return -1;
+		}
 		n++;
 	}
 	db_active = db_loading;
@@ -1582,44 +1755,39 @@
 		ast_log(LOG_NOTICE,"Error in finalizing DB process on %s\n",hostname);
 		return -1;
 	}
-
+	close(sock);
 	ast_log(LOG_NOTICE,"Diretory pgm done downloading, %d records\n",n);
-	return 0;
+	printf("Compressed: %d, Partial: %d\n",dir_compressed,dir_partial);
+	if (dir_compressed) printf("Got snapshot_id: %s\n",snapshot_id);
+	return(dir_compressed);
 }
 
 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);
-}
-
+	int rc = 0,curdir;
+
+	curdir = 0;
+	while (run_forever)
+	{
+		if (!instances[0]->elservers[curdir][0])
+		{
+			if (++curdir >= EL_MAX_SERVERS) curdir = 0;
+			continue;
+		}
+		ast_log(LOG_NOTICE, "Trying to do directory downloa Echolink server %s\n", instances[0]->elservers[curdir]);
+		rc = do_el_directory(instances[0]->elservers[curdir]);
+		if (rc < 0)
+		{
+			if (++curdir >= EL_MAX_SERVERS) curdir = 0;
+			sleep(20);
+			continue;
+		}
+		if (rc == 1) sleep(240);
+		else if (rc == 0) sleep(1800);
+	}
+	ast_log(LOG_NOTICE, "Echolink directory thread exited.\n");
+	pthread_exit(NULL);
+}
 
 static void *el_register(void *data)
 {
@@ -1827,7 +1995,7 @@
 								fr.delivery.tv_sec = 0;
 								fr.delivery.tv_usec = 0;
 								ast_queue_frame((*found_key)->chan,&fr);
-								ast_log(LOG_NOTICE,"Channel %s answering\n",
+								if (debug) ast_log(LOG_DEBUG,"Channel %s answering\n",
 									(*found_key)->chan->name);
 							}
 							(*found_key)->countdown = instp->rtcptimeout;




More information about the asterisk-commits mailing list