[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