[asterisk-commits] jdixon: branch jdixon/chan_usbradio-1.4 r140555 - /team/jdixon/chan_usbradio-...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Sep 2 03:33:49 CDT 2008
Author: jdixon
Date: Tue Sep 2 03:33:49 2008
New Revision: 140555
URL: http://svn.digium.com/view/asterisk?view=rev&rev=140555
Log:
More better and more working chan_irlp
Modified:
team/jdixon/chan_usbradio-1.4/dev-1.0/channels/chan_irlp.c
Modified: team/jdixon/chan_usbradio-1.4/dev-1.0/channels/chan_irlp.c
URL: http://svn.digium.com/view/asterisk/team/jdixon/chan_usbradio-1.4/dev-1.0/channels/chan_irlp.c?view=diff&rev=140555&r1=140554&r2=140555
==============================================================================
--- team/jdixon/chan_usbradio-1.4/dev-1.0/channels/chan_irlp.c (original)
+++ team/jdixon/chan_usbradio-1.4/dev-1.0/channels/chan_irlp.c Tue Sep 2 03:33:49 2008
@@ -29,7 +29,7 @@
/*** MODULEINFO
***/
-/* Version 0.2, 08/31/2008
+/* Version 0.3, 9/2/2008
irlp channel driver for Asterisk/app_rpt.
This is a first attempt.
@@ -40,28 +40,6 @@
(included in the rtpDir bridge package)
onto your local IRLP node, before using this driver.
-You will use this driver to connect to IRLP adpcm refXXXX reflectors.
-To connect to IRLP stnXXXX nodes or IRLP gsm refXXXX reflectors,
-use the irlpgsm driver.
-
-Lets say you know the adpcm IRLP reflector that you wish to connect
-this driver to, and lets assume it is IRLP reflector refXXX5
-and lets assume that the IRLP reflector refXXX5 which is channel 5,
-uses adpcm codec.
-
-Using the above example, the port to use for this driver would be
-(5 * 2) + 2074 = 2084
-So in the rxchannel specification in /etc/asterisk/rpt.conf
-under a node stanza, you will have this:
-
- rxchannel=irlp/0.0.0.0:2084
-
-and of course, this driver will open/lock UDP
-ports 2084(audio),2085(control)
-
-If the linux box is protected by a NAT router,
-leave the IP address as 0.0.0.0,
-do not use 127.0.0.1
You must also make sure that the IRLP ispeaker starts with:
@@ -83,9 +61,6 @@
might compete for the same port(s), so set irlpEnable=no in
the config file for rtpDir/rtpDir_tm bridge or use different port(s)
in this driver or rtpDir/rtpDir_tm bridge.
-
-It would be better to have written all this code
-in C++ instead of C, but Asterisk wants C only.
*/
@@ -138,8 +113,12 @@
#define LARGEST_PACKET_SIZE 1024
#define IRLP_ROOT "/home/irlp/local"
-
-enum {IRLP_ISADPCM,IRLP_ISGSM} ;
+#define IRLP_RESET "su - repeater /home/irlp/scripts/suwrap /home/irlp/scripts/irlp_reset"
+#define IRLP_END "su - repeater /home/irlp/scripts/suwrap /home/irlp/scripts/end &"
+#define IRLP_CALL_REFL "su - repeater /home/irlp/scripts/suwrap /home/irlp/scripts/connect_to_reflector ref%04d &"
+#define IRLP_CALL "su - repeater /home/irlp/scripts/suwrap /home/irlp/scripts/call stn%04d &"
+
+enum {IRLP_NOPROTO,IRLP_ISADPCM,IRLP_ISGSM} ;
struct irlp_audio
{
@@ -165,21 +144,12 @@
};
struct irlp_pvt {
- int audio_sock;
- int ctrl_sock;
struct ast_channel *owner;
char app[16];
- char stream[80];
- int proto;
char txkey;
int rxkey;
int keepalive;
struct ast_frame fr;
- int txindex;
- struct irlp_rxqast rxqast;
- char *outbuf_old;
- int rxlen;
- int rxidx;
struct ast_module_user *u;
};
@@ -195,20 +165,37 @@
*/
static char mycall[IRLP_CALL_SIZE + 1];
static char mynode[IRLP_NODE_SIZE + 1];
+static char astnode[20];
static short rtcptimeout = 10;
static short localispeakerport = 2174;
-
+static int radmode = 0;
+static int nodenum = 0;
static int audio_sock = -1;
static int ctrl_sock = -1;
-static uint16_t audio_port = 2084;
-static uint16_t ctrl_port = 2085;
-
+static int tx_audio_port = 0;
+static int alt_audio_sock = -1;
+static int alt_ctrl_sock = -1;
+static uint16_t audio_port_cfg = 2084;
+static uint16_t audio_port;
+static uint16_t ctrl_port;
static char *config = "irlp.conf";
-
static const char tdesc[] = "irlp channel driver by KI4LKF";
static int prefformat = AST_FORMAT_ADPCM;
static char context[AST_MAX_EXTENSION] = "default";
static char type[] = "irlp";
+static pthread_t irlp_reader_thread;
+static int run_forever = 1;
+static int proto = IRLP_NOPROTO;
+static int in_node = 0;
+static int txindex;
+static struct irlp_rxqast rxqast;
+static char *outbuf_old;
+static int rxlen;
+static int rxidx;
+static int ready = 0;
+static struct ast_channel *curcall = NULL;
+AST_MUTEX_DEFINE_STATIC(irlplock);
+static char stream[256];
#ifdef OLD_ASTERISK
#define ast_free free
@@ -224,9 +211,10 @@
static int irlp_digit_begin(struct ast_channel *c, char digit);
static int irlp_digit_end(struct ast_channel *c, char digit, unsigned int duratiion);
static int irlp_text(struct ast_channel *c, const char *text);
-
+static struct irlp_pvt *irlp_alloc(void *data);
static int is_rtcp_bye(unsigned char *p, int len);
static int is_valid_rtcp(unsigned char *p, int len);
+static struct ast_channel *irlp_new(struct irlp_pvt *i, int state);
static const struct ast_channel_tech irlp_tech = {
.type = type,
@@ -243,6 +231,34 @@
.send_digit_end = irlp_digit_end,
};
+void static reset_stuff(void)
+{
+
+ if (alt_audio_sock != -1) close(alt_audio_sock);
+ alt_audio_sock = -1;
+ if (alt_ctrl_sock != -1) close(alt_ctrl_sock);
+ alt_ctrl_sock = -1;
+ proto = IRLP_NOPROTO;
+ in_node = 0;
+ nodenum = 0;
+ txindex = 0;
+ ready = 0;
+ rxqast.qe_forw = &rxqast;
+ rxqast.qe_back = &rxqast;
+ remote_irlp_node_ip[0] = 0;
+ tx_audio_port = audio_port_cfg;
+ audio_port = audio_port_cfg;
+ ctrl_port = audio_port + 1;
+ if (curcall)
+ {
+ curcall->nativeformats = AST_FORMAT_ADPCM;
+ ast_set_read_format(curcall,curcall->readformat);
+ ast_set_write_format(curcall,curcall->writeformat);
+ }
+ return;
+}
+
+
static char *irlp_read_file(char *basename,char *fname)
{
char s[200],*str;
@@ -320,9 +336,30 @@
return (p == end)?1:0;
}
+static int do_new_call(void)
+{
+
+ struct irlp_pvt *p;
+
+ p = irlp_alloc((void *)"");
+ if (!p)
+ {
+ ast_log(LOG_ERROR,"Cannot alloc irlp channel\n");
+ return -1;
+ }
+ curcall = irlp_new(p,AST_STATE_RINGING);
+ if (!curcall)
+ {
+ ast_log(LOG_ERROR,"Cannot alloc irlp channel\n");
+ return -1;
+ }
+ return 0;
+}
+
static int irlp_call(struct ast_channel *ast, char *dest, int timeout)
{
struct irlp_pvt *p;
+ char *cp,str[100];
p = ast->tech_pvt;
@@ -330,104 +367,346 @@
ast_log(LOG_WARNING, "irlp_call called on %s, neither down nor reserved\n", ast->name);
return -1;
}
- /* 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);
-
- ast_setstate(ast,AST_STATE_UP);
+ cp = irlp_read_file(IRLP_ROOT,"active");
+ if (cp && *cp)
+ {
+ ast_safe_system(IRLP_END);
+ usleep(10000);
+ ast_safe_system(IRLP_RESET);
+ usleep(10000);
+ }
+ if (cp) free(cp);
+ if ((!radmode) && nodenum)
+ {
+ if (nodenum >= 9000)
+ snprintf(str,sizeof(str) - 1,IRLP_CALL_REFL,nodenum);
+ else
+ snprintf(str,sizeof(str) - 1,IRLP_CALL,nodenum);
+ ast_safe_system(str);
+ usleep(10000);
+ }
+
+ ast_setstate(ast,(radmode) ? AST_STATE_UP : AST_STATE_RINGING);
return 0;
}
static void irlp_destroy(struct irlp_pvt *p)
{
- if (p->audio_sock) {
- close(p->audio_sock);
- p->audio_sock = -1;
- }
-
- if (p->ctrl_sock) {
- close(p->ctrl_sock);
- p->ctrl_sock = -1;
- }
-
+ reset_stuff();
+ curcall = NULL;
ast_module_user_remove(p->u);
ast_free(p);
}
+static void process_codec_file(struct ast_channel *ast)
+{
+ char *cp;
+
+ if (!ready) return;
+ cp = irlp_read_file(IRLP_ROOT,"codec");
+ if (cp)
+ {
+ if (!strncasecmp(cp,"GSM",3))
+ {
+ if (proto == IRLP_NOPROTO)
+ ast_log(LOG_NOTICE,"irlp channel format set to GSM\n");
+ else if (proto != IRLP_ISGSM)
+ ast_log(LOG_NOTICE,"irlp channel format changed to GSM\n");
+ proto = IRLP_ISGSM;
+ ast->nativeformats = AST_FORMAT_GSM;
+ }
+ else
+ {
+ if (proto == IRLP_NOPROTO)
+ ast_log(LOG_NOTICE,"irlp channel format set to ADPCM\n");
+ else if (proto != IRLP_ISADPCM)
+ ast_log(LOG_NOTICE,"irlp channel format changed to GSM\n");
+ proto = IRLP_ISADPCM;
+ ast->nativeformats = AST_FORMAT_ADPCM;
+ }
+ ast_set_read_format(ast,ast->readformat);
+ ast_set_write_format(ast,ast->writeformat);
+ free(cp);
+ }
+ return;
+}
+
+
+static void *irlp_reader(void *nothing)
+{
+
+ fd_set fds[2];
+ struct timeval tmout;
+ int i,myaud,myctl,x;
+
+ char buf[LARGEST_PACKET_SIZE + 1];
+ struct sockaddr_in sin;
+ struct irlp_rxqast *qpast;
+ char ip[IRLP_IP_SIZE + 1],*cp;
+ socklen_t fromlen;
+ ssize_t recvlen;
+ size_t len;
+
+ ast_log(LOG_NOTICE, "IRLP reader thread started.\n");
+ while(run_forever)
+ {
+ if ((proto == IRLP_NOPROTO) && curcall) process_codec_file(curcall);
+ myaud = (alt_audio_sock != -1) ? alt_audio_sock : audio_sock;
+ myctl = (alt_ctrl_sock != -1) ? alt_ctrl_sock : ctrl_sock;
+ FD_ZERO(fds);
+ FD_SET(myaud,fds);
+ FD_SET(myctl,fds);
+ x = myaud;
+ if (myctl > x) x = myctl;
+ 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(myctl,fds)) /* if a ctrl packet */
+ {
+ fromlen = sizeof(struct sockaddr_in);
+ recvlen = recvfrom(myctl,
+ buf,
+ LARGEST_PACKET_SIZE,
+ 0,
+ (struct sockaddr *)&sin,&fromlen);
+
+ if (recvlen > 0)
+ {
+ buf[recvlen] = '\0';
+#ifdef OLD_ASTERISK
+ ast_inet_ntoa(ip,IRLP_IP_SIZE,sin.sin_addr);
+#else
+ strncpy(ip,ast_inet_ntoa(sin.sin_addr),IRLP_IP_SIZE);
+#endif
+ if (is_valid_rtcp((unsigned char *)buf,recvlen))
+ {
+ if (!is_rtcp_bye((unsigned char *)buf,recvlen))
+ {
+ if (strncmp(ip, "127.0.0.1",IRLP_IP_SIZE) != 0)
+ {
+ if (strncmp(remote_irlp_node_ip, ip, IRLP_IP_SIZE) != 0)
+ {
+ strncpy(remote_irlp_node_ip, ip, IRLP_IP_SIZE);
+ cp = irlp_read_file(IRLP_ROOT,"active");
+ if (cp && (strlen(cp) > 3))
+ {
+ in_node = atoi(cp + 3);
+ ast_log(LOG_NOTICE,"irlp node connected from %s node %s\n",ip,cp + 3);
+ if (!curcall) do_new_call();
+ if ((!ready) && curcall)
+ {
+ struct ast_frame fr;
+
+ fr.datalen = 0;
+ fr.samples = 0;
+ fr.frametype = AST_FRAME_CONTROL;
+ fr.subclass = AST_CONTROL_ANSWER;
+ fr.data = 0;
+ fr.src = type;
+ fr.offset = 0;
+ fr.mallocd=0;
+ fr.delivery.tv_sec = 0;
+ fr.delivery.tv_usec = 0;
+ ast_queue_frame(curcall,&fr);
+ }
+ ready = 1;
+ if (curcall && (proto == IRLP_NOPROTO)) process_codec_file(curcall);
+ } else ast_log(LOG_NOTICE,"irlp node connected from %s\n", ip);
+ if (cp) free(cp);
+ }
+ }
+ }
+ else
+ {
+ if (strncmp(ip, remote_irlp_node_ip, IRLP_IP_SIZE) == 0)
+ {
+ reset_stuff();
+ if ((!radmode) && curcall) ast_softhangup(curcall,AST_SOFTHANGUP_DEV);
+ ast_log(LOG_NOTICE, "received IRLP bye from %s\n",ip);
+ }
+ }
+ }
+ }
+ }
+ if (FD_ISSET(myaud,fds)) /* if a audio packet */
+ {
+ fromlen = sizeof(struct sockaddr_in);
+ recvlen = recvfrom(myaud,
+ buf,
+ LARGEST_PACKET_SIZE,
+ 0,
+ (struct sockaddr *)&sin,&fromlen);
+ if (recvlen > 0)
+ {
+ buf[recvlen] = '\0';
+#ifdef OLD_ASTERISK
+ ast_inet_ntoa(ip,IRLP_IP_SIZE,sin.sin_addr);
+#else
+ strncpy(ip,ast_inet_ntoa(sin.sin_addr),IRLP_IP_SIZE);
+#endif
+ len = ntohl(((struct irlp_audio *)buf)->buffer.buffer_len);
+ if (((strncmp(ip, remote_irlp_node_ip, IRLP_IP_SIZE) == 0) ||
+ (strncmp(ip, "127.0.0.1", IRLP_IP_SIZE) == 0)) &&
+ (len > IRLP_ADPCM_STATE_INFO_SIZE) &&
+ ((recvlen - IRLP_HEADER_INFO_SIZE) == len))
+ {
+
+ if (((struct irlp_audio *)buf)->compression == htonl(0x200 | 0x40000000))
+ {
+ if (proto == IRLP_NOPROTO)
+ ast_log(LOG_NOTICE,"irlp channel format set to ADPCM\n");
+ else if (proto != IRLP_ISADPCM)
+ ast_log(LOG_NOTICE,"irlp channel format changed to GSM\n");
+ proto = IRLP_ISADPCM;
+ if (curcall)
+ {
+ curcall->nativeformats = AST_FORMAT_ADPCM;
+ ast_set_read_format(curcall,curcall->readformat);
+ ast_set_write_format(curcall,curcall->writeformat);
+ }
+ }
+ if (((struct irlp_audio *)buf)->compression == htonl(0x20 | 0x40000000))
+ {
+ if (proto == IRLP_NOPROTO)
+ ast_log(LOG_NOTICE,"irlp channel format set to GSM\n");
+ else if (proto != IRLP_ISGSM)
+ ast_log(LOG_NOTICE,"irlp channel format changed to GSM\n");
+ proto = IRLP_ISGSM;
+ if (curcall)
+ {
+ curcall->nativeformats = AST_FORMAT_GSM;
+ ast_set_read_format(curcall,curcall->readformat);
+ ast_set_write_format(curcall,curcall->writeformat);
+ }
+ }
+ qpast = ast_malloc(sizeof(struct irlp_rxqast) + len);
+ if (!qpast)
+ {
+ ast_log(LOG_NOTICE,"Cannot malloc for qpast\n");
+ return NULL;
+ }
+ if (proto == IRLP_ISADPCM)
+ {
+ qpast->len = len;
+ memcpy(qpast->buf,((struct irlp_audio *)buf)->buffer.buffer_val,len);
+ }
+ else
+ {
+ qpast->len = len - 2;
+ memcpy(qpast->buf,((struct irlp_audio *)buf)->buffer.buffer_val + 2,len);
+ }
+ insque((struct qelem *)qpast,(struct qelem *)rxqast.qe_back);
+ if (strncmp(ip, "127.0.0.1", IRLP_IP_SIZE) == 0)
+ {
+ if (remote_irlp_node_ip[0] != '\0')
+ {
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = inet_addr(remote_irlp_node_ip);
+ sin.sin_port = htons(tx_audio_port);
+ sendto((alt_audio_sock != -1) ? alt_audio_sock : audio_sock,buf,recvlen,
+ 0,(struct sockaddr *)&sin,sizeof(struct sockaddr));
+ }
+ }
+ else
+ {
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+ sin.sin_port = htons(localispeakerport);
+ sendto(audio_sock,buf,recvlen,
+ 0,(struct sockaddr *)&sin,sizeof(struct sockaddr));
+ }
+ }
+ }
+ }
+ }
+ ast_mutex_unlock(&irlplock);
+ ast_log(LOG_NOTICE, "IRLP read thread exited.\n");
+ pthread_exit(NULL);
+}
+
+
static struct irlp_pvt *irlp_alloc(void *data)
{
struct irlp_pvt *p;
- /* int flags = 0; */
- char stream[256];
struct sockaddr_in si_me;
AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(myip);
- AST_APP_ARG(myport);
+ AST_APP_ARG(nodenum);
);
- if (ast_strlen_zero(data)) return NULL;
-
- AST_NONSTANDARD_APP_ARGS(args,data,':');
-
- if ((!args.myip) || (!args.myip[0])) args.myip = "127.0.0.1";
- if ((!args.myport) || (!args.myport[0])) args.myport = "2074";
+ args.nodenum = NULL;
+ if (!ast_strlen_zero(data))
+ AST_STANDARD_APP_ARGS(args,data);
p = ast_malloc(sizeof(struct irlp_pvt));
if (p) {
memset(p, 0, sizeof(struct irlp_pvt));
-
- sprintf(stream,"%s:%d",args.myip,atoi(args.myport));
- strcpy(p->stream,stream);
- p->rxqast.qe_forw = &p->rxqast;
- p->rxqast.qe_back = &p->rxqast;
-
- if ((p->audio_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
- ast_log(LOG_WARNING,
- "Unable to create new socket for irlp audio connection\n");
- ast_free(p);
- return(NULL);
- }
-
- if ((p->ctrl_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
- ast_log(LOG_WARNING,
- "Unable to create new socket for irlp control connection\n");
- close(p->audio_sock);
- p->audio_sock = -1;
- ast_free(p);
- return(NULL);
- }
- memset((char *) &si_me, 0, sizeof(si_me));
- si_me.sin_family = AF_INET;
- if (strcmp(args.myip,"0.0.0.0") == 0)
- si_me.sin_addr.s_addr = htonl(INADDR_ANY);
- else
- si_me.sin_addr.s_addr = inet_addr(args.myip);
- audio_port = atoi(args.myport);
- si_me.sin_port = htons(audio_port);
- if (bind(p->audio_sock, &si_me, sizeof(si_me))==-1) {
- ast_log(LOG_WARNING, "Unable to bind port for irlp audio connection\n");
- close(p->ctrl_sock); p->ctrl_sock = -1;
- close(p->audio_sock); p->audio_sock = -1;
- ast_free(p);
- return(NULL);
-
- }
- ctrl_port = audio_port + 1;
- si_me.sin_port = htons(ctrl_port);
- if (bind(p->ctrl_sock, &si_me, sizeof(si_me))==-1) {
- ast_log(LOG_WARNING, "Unable to bind port for irlp control connection\n");
- close(p->ctrl_sock); p->ctrl_sock = -1;
- close(p->audio_sock); p->audio_sock = -1;
- ast_free(p);
- return(NULL);
-
- }
- fcntl(p->audio_sock,F_SETFL,O_NONBLOCK);
- fcntl(p->ctrl_sock,F_SETFL,O_NONBLOCK);
- audio_sock = p->audio_sock;
- ctrl_sock = p->ctrl_sock;
+ nodenum = 0;
+ rxqast.qe_forw = &rxqast;
+ rxqast.qe_back = &rxqast;
+ sprintf(stream,"%d",audio_port);
+ tx_audio_port = audio_port_cfg;
+ if ((!radmode) && args.nodenum && *args.nodenum)
+ {
+ nodenum = atoi(args.nodenum);
+ if ((nodenum < 1000) || (nodenum > 9999))
+ {
+ ast_log(LOG_ERROR,"Requested node number %s invalid\n",args.nodenum);
+ ast_free(p);
+ return NULL;
+ }
+ if (nodenum >= 9000) tx_audio_port += (2 * (nodenum % 10));
+ }
+
+ if (tx_audio_port != audio_port)
+ {
+ if ((alt_audio_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+ {
+ ast_log(LOG_WARNING,
+ "Unable to create new socket for irlp audio connection\n");
+ ast_free(p);
+ return(NULL);
+ }
+ if ((alt_ctrl_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
+ ast_log(LOG_WARNING,
+ "Unable to create new socket for irlp control connection\n");
+ close(alt_audio_sock);
+ alt_audio_sock = -1;
+ ast_free(p);
+ return(NULL);
+ }
+ memset((char *) &si_me, 0, sizeof(si_me));
+ si_me.sin_family = AF_INET;
+ si_me.sin_addr.s_addr = htonl(INADDR_ANY);
+ si_me.sin_port = htons(tx_audio_port);
+ if (bind(alt_audio_sock, &si_me, sizeof(si_me))==-1)
+ {
+ ast_log(LOG_WARNING, "Unable to bind port for irlp audio connection\n");
+ close(alt_ctrl_sock); alt_ctrl_sock = -1;
+ close(alt_audio_sock); alt_audio_sock = -1;
+ ast_free(p);
+ return(NULL);
+ }
+ si_me.sin_port = htons(tx_audio_port + 1);
+ if (bind(alt_ctrl_sock, &si_me, sizeof(si_me))==-1) {
+ ast_log(LOG_WARNING, "Unable to bind port for irlp control connection\n");
+ close(alt_ctrl_sock); alt_ctrl_sock = -1;
+ close(alt_audio_sock); alt_audio_sock = -1;
+ ast_free(p);
+ return(NULL);
+ }
+ fcntl(alt_audio_sock,F_SETFL,O_NONBLOCK);
+ fcntl(alt_ctrl_sock,F_SETFL,O_NONBLOCK);
+ }
}
return p;
}
@@ -442,9 +721,13 @@
ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
return 0;
}
+ reset_stuff();
+ ast_safe_system(IRLP_END);
+ ast_safe_system(IRLP_RESET);
irlp_destroy(p);
ast->tech_pvt = NULL;
ast_setstate(ast, AST_STATE_DOWN);
+ curcall = 0;
return 0;
}
@@ -485,157 +768,8 @@
static struct ast_frame *irlp_xread(struct ast_channel *ast)
{
-
struct irlp_pvt *p = ast->tech_pvt;
- char buf[LARGEST_PACKET_SIZE + 1];
- struct sockaddr_in sin;
- struct irlp_rxqast *qpast;
- char ip[IRLP_IP_SIZE + 1],*cp;
- int i;
- socklen_t fromlen;
- ssize_t recvlen;
- size_t len;
-
- len = 0;
- ioctl(p->ctrl_sock,FIONREAD,&len);
- if (len > 0) {
- fromlen = sizeof(struct sockaddr_in);
- recvlen = recvfrom(p->ctrl_sock,
- buf,
- LARGEST_PACKET_SIZE,
- 0,
- (struct sockaddr *)&sin,&fromlen);
- if (recvlen > 0) {
- buf[recvlen] = '\0';
-#ifdef OLD_ASTERISK
- ast_inet_ntoa(ip,IRLP_IP_SIZE,sin.sin_addr);
-#else
- strncpy(ip,ast_inet_ntoa(sin.sin_addr),IRLP_IP_SIZE);
-#endif
- if (is_valid_rtcp((unsigned char *)buf,recvlen)) {
- if (!is_rtcp_bye((unsigned char *)buf,recvlen)) {
- if (strncmp(ip, "127.0.0.1",IRLP_IP_SIZE) != 0) {
- if (strncmp(remote_irlp_node_ip, ip, IRLP_IP_SIZE) != 0) {
- strncpy(remote_irlp_node_ip, ip, IRLP_IP_SIZE);
- p->proto = IRLP_ISADPCM;
- cp = irlp_read_file(IRLP_ROOT,"codec");
- if (!strncasecmp(cp,"GSM",3))
- {
- p->proto = IRLP_ISGSM;
- ast->nativeformats = AST_FORMAT_GSM;
- ast_log(LOG_NOTICE,"irlp channel format set to GSM\n");
- }
- else
- {
- ast->nativeformats = AST_FORMAT_ADPCM;
- ast_log(LOG_NOTICE,"irlp channel format set to ADPCM\n");
- }
- free(cp);
- ast_set_read_format(ast,ast->readformat);
- ast_set_write_format(ast,ast->writeformat);
- ast_log(LOG_NOTICE,"irlp node connected from %s\n", ip);
- }
- }
- }
- else {
- if (strncmp(ip, remote_irlp_node_ip, IRLP_IP_SIZE) == 0) {
- remote_irlp_node_ip[0] = '\0';
- p->proto = IRLP_ISADPCM;
- ast->nativeformats = AST_FORMAT_ADPCM;
- ast_set_read_format(ast,ast->readformat);
- ast_set_write_format(ast,ast->writeformat);
- ast_log(LOG_NOTICE, "received IRLP bye from %s\n",ip);
- }
- }
- }
- }
- }
-
- len = 0;
- ioctl(p->audio_sock,FIONREAD,&len);
- if (len > 0)
- {
- fromlen = sizeof(struct sockaddr_in);
- recvlen = recvfrom(p->audio_sock,
- buf,
- LARGEST_PACKET_SIZE,
- 0,
- (struct sockaddr *)&sin,&fromlen);
- if (recvlen > 0)
- {
- buf[recvlen] = '\0';
-#ifdef OLD_ASTERISK
- ast_inet_ntoa(ip,IRLP_IP_SIZE,sin.sin_addr);
-#else
- strncpy(ip,ast_inet_ntoa(sin.sin_addr),IRLP_IP_SIZE);
-#endif
- i = p->proto;
- len = ntohl(((struct irlp_audio *)buf)->buffer.buffer_len);
- if (((struct irlp_audio *)buf)->compression == htonl(0x200 | 0x40000000))
- {
- i = IRLP_ISADPCM;
- ast->nativeformats = AST_FORMAT_ADPCM;
- ast_set_read_format(ast,ast->readformat);
- ast_set_write_format(ast,ast->writeformat);
- }
- if (((struct irlp_audio *)buf)->compression == htonl(0x20 | 0x40000000))
- {
- i = IRLP_ISGSM;
- ast->nativeformats = AST_FORMAT_GSM;
- ast_set_read_format(ast,ast->readformat);
- ast_set_write_format(ast,ast->writeformat);
- }
- if (((strncmp(ip, remote_irlp_node_ip, IRLP_IP_SIZE) == 0) ||
- (strncmp(ip, "127.0.0.1", IRLP_IP_SIZE) == 0)) &&
- (len > IRLP_ADPCM_STATE_INFO_SIZE) &&
- ((recvlen - IRLP_HEADER_INFO_SIZE) == len)) {
-
- if (p->proto != i)
- {
- if (i == IRLP_ISADPCM)
- ast_log(LOG_NOTICE,"Proto changed to <ADPCM>\n");
- else
- ast_log(LOG_NOTICE,"Proto changed to <GSM>\n");
- }
- p->proto = i;
-
-
- qpast = ast_malloc(sizeof(struct irlp_rxqast) + len);
- if (!qpast) {
- ast_log(LOG_NOTICE,"Cannot malloc for qpast\n");
- return NULL;
- }
- if (p->proto == IRLP_ISADPCM)
- {
- qpast->len = len;
- memcpy(qpast->buf,((struct irlp_audio *)buf)->buffer.buffer_val,len);
- }
- else
- {
- qpast->len = len - 2;
- memcpy(qpast->buf,((struct irlp_audio *)buf)->buffer.buffer_val + 2,len);
- }
- insque((struct qelem *)qpast,(struct qelem *)p->rxqast.qe_back);
-
- if (strncmp(ip, "127.0.0.1", IRLP_IP_SIZE) == 0) {
- if (remote_irlp_node_ip[0] != '\0') {
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = inet_addr(remote_irlp_node_ip);
- sin.sin_port = htons(audio_port);
- sendto(p->audio_sock,buf,recvlen,
- 0,(struct sockaddr *)&sin,sizeof(struct sockaddr));
- }
- } else {
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = inet_addr("127.0.0.1");
- sin.sin_port = htons(localispeakerport);
- sendto(p->audio_sock,buf,recvlen,
- 0,(struct sockaddr *)&sin,sizeof(struct sockaddr));
- }
- }
- }
- }
-
+
p->fr.frametype = 0;
p->fr.subclass = 0;
p->fr.datalen = 0;
@@ -668,8 +802,10 @@
if (frame->frametype != AST_FRAME_VOICE)
return 0;
+ if (proto == IRLP_NOPROTO) return 0;
+
frame_samples = 160;
- if (p->proto == IRLP_ISGSM)
+ if (proto == IRLP_ISGSM)
{
blocking_factor = GSM_BLOCKING_FACTOR;
frame_size = GSM_FRAME_SIZE;
@@ -680,19 +816,19 @@
frame_size = ADPCM_FRAME_SIZE;
}
/* IRLP to Asterisk */
- if (p->rxqast.qe_forw != &p->rxqast) {
- for(n = 0,qpast = p->rxqast.qe_forw; qpast != &p->rxqast; qpast = qpast->qe_forw) {
+ if (rxqast.qe_forw != &rxqast) {
+ for(n = 0,qpast = rxqast.qe_forw; qpast != &rxqast; qpast = qpast->qe_forw) {
n++;
}
if (n > QUEUE_OVERLOAD_THRESHOLD_AST) {
- while(p->rxqast.qe_forw != &p->rxqast) {
- qpast = p->rxqast.qe_forw;
+ while(rxqast.qe_forw != &rxqast) {
+ qpast = rxqast.qe_forw;
remque((struct qelem *)qpast);
ast_free(qpast);
}
- if (p->outbuf_old) ast_free(p->outbuf_old);
- p->rxlen = 0;
- p->rxidx = 0;
+ if (outbuf_old) ast_free(outbuf_old);
+ rxlen = 0;
+ rxidx = 0;
if (p->rxkey) p->rxkey = 1;
} else {
if (!p->rxkey) {
@@ -714,10 +850,10 @@
len = 0;
gotone = 0;
dosync = 0;
- if ((p->rxqast.qe_forw != &p->rxqast) &&
- ((p->rxlen - p->rxidx) < frame_size))
- {
- qpast = p->rxqast.qe_forw;
+ if ((rxqast.qe_forw != &rxqast) &&
+ ((rxlen - rxidx) < frame_size))
+ {
+ qpast = rxqast.qe_forw;
remque((struct qelem *)qpast);
len = qpast->len;
outbuf_new = malloc(len);
@@ -728,49 +864,49 @@
}
memcpy(outbuf_new,qpast->buf,len);
ast_free(qpast);
- if (p->proto == IRLP_ISADPCM) len -= 3;
- i = (p->rxlen - p->rxidx);
- if ((p->proto == IRLP_ISADPCM) && (!p->rxidx) &&
+ if (proto == IRLP_ISADPCM) len -= 3;
+ i = (rxlen - rxidx);
+ if ((proto == IRLP_ISADPCM) && (!rxidx) &&
(len >= frame_size)) dosync = len;
/* if something to output */
if ((len + i) >= frame_size)
{
- if (i && p->outbuf_old)
+ if (i && outbuf_old)
{
memcpy(outbuf + AST_FRIENDLY_OFFSET,
- p->outbuf_old + p->rxidx,i);
- ast_free(p->outbuf_old);
+ outbuf_old + rxidx,i);
+ ast_free(outbuf_old);
}
memcpy(outbuf + i + AST_FRIENDLY_OFFSET,
outbuf_new,frame_size - i);
- p->rxlen = len;
- p->rxidx = frame_size - i;
- p->outbuf_old = outbuf_new;
+ rxlen = len;
+ rxidx = frame_size - i;
+ outbuf_old = outbuf_new;
gotone = 1;
}
else
{
- cp = malloc((p->rxlen - p->rxidx) + len);
+ cp = malloc((rxlen - rxidx) + len);
if (!cp)
{
ast_log(LOG_ERROR,"Cannot Malloc");
return -1;
}
- if (p->rxlen) memcpy(cp,p->outbuf_old + p->rxidx,i);
+ if (rxlen) memcpy(cp,outbuf_old + rxidx,i);
memcpy(cp + i,outbuf_new,len);
- p->rxlen = len + i;
- p->rxidx = 0;
+ rxlen = len + i;
+ rxidx = 0;
free(outbuf_new);
outbuf_new = NULL;
- free(p->outbuf_old);
- p->outbuf_old = cp;
- }
- }
- else if ((p->rxlen - p->rxidx) >= frame_size)
+ free(outbuf_old);
+ outbuf_old = cp;
+ }
+ }
+ else if ((rxlen - rxidx) >= frame_size)
{
memcpy(outbuf + AST_FRIENDLY_OFFSET,
- p->outbuf_old + p->rxidx,frame_size);
- p->rxidx += frame_size;
+ outbuf_old + rxidx,frame_size);
+ rxidx += frame_size;
gotone = 1;
}
if (gotone)
@@ -778,14 +914,14 @@
p->rxkey = MAX_RXKEY_TIME;
fr.datalen = frame_size;
fr.samples = frame_samples;
- if ((p->proto == IRLP_ISADPCM) && dosync)
+ if ((proto == IRLP_ISADPCM) && dosync)
{
fr.datalen += 3;
memcpy(outbuf + AST_FRIENDLY_OFFSET + frame_size,
outbuf_new + dosync,3);
}
fr.frametype = AST_FRAME_VOICE;
- if (p->proto == IRLP_ISADPCM)
+ if (proto == IRLP_ISADPCM)
{
fr.subclass = AST_FORMAT_ADPCM;
}
@@ -814,14 +950,14 @@
fr.delivery.tv_usec = 0;
ast_queue_frame(ast,&fr);
- if (p->outbuf_old) ast_free(p->outbuf_old);
- p->rxlen = 0;
- p->rxidx = 0;
+ if (outbuf_old) ast_free(outbuf_old);
+ rxlen = 0;
+ rxidx = 0;
}
if (p->rxkey) p->rxkey--;
i = AST_FORMAT_ADPCM;
- if (p->proto == IRLP_ISGSM) i = AST_FORMAT_GSM;
+ if (proto == IRLP_ISGSM) i = AST_FORMAT_GSM;
/* Asterisk to IRLP */
if (!(frame->subclass & i)) {
@@ -829,19 +965,19 @@
return 0;
}
cp = frame->data;
- if (p->txkey || p->txindex) {
+ if (p->txkey || txindex) {
p->keepalive = KEEPALIVE_TIME;
- if ((p->proto == IRLP_ISADPCM) && (!p->txindex))
+ if ((proto == IRLP_ISADPCM) && (!txindex))
memcpy(tx_buf + (frame_size *
blocking_factor),cp + frame_size,3);
- memcpy(tx_buf + (frame_size * p->txindex++),
+ memcpy(tx_buf + (frame_size * txindex++),
frame->data,frame_size);
}
- if (p->txindex >= blocking_factor) {
+ if (txindex >= blocking_factor) {
dp = (unsigned char *)irlp_audio_packet.buffer.buffer_val;
- if (p->proto == IRLP_ISADPCM)
+ if (proto == IRLP_ISADPCM)
{
irlp_audio_packet.compression = htonl(0x200 | 0x40000000);
}
@@ -852,7 +988,7 @@
snprintf(irlp_audio_packet.sendinghost,IRLP_IP_SIZE,
"%s-%s",mynode,mycall);
- if (p->proto == IRLP_ISADPCM)
+ if (proto == IRLP_ISADPCM)
{
memcpy((char *)dp,tx_buf,(blocking_factor * frame_size) + 3);
irlp_audio_packet.buffer.buffer_len = htonl((blocking_factor *
@@ -871,14 +1007,14 @@
sin.sin_addr.s_addr = inet_addr(remote_irlp_node_ip);
sin.sin_port = htons(audio_port);
- if (p->proto == IRLP_ISADPCM)
+ if (proto == IRLP_ISADPCM)
{
- sendto(p->audio_sock,(char *)&irlp_audio_packet,507,
+ sendto((alt_audio_sock != -1) ? alt_audio_sock : audio_sock,(char *)&irlp_audio_packet,507,
0,(struct sockaddr *)&sin,sizeof(struct sockaddr));
}
else
{
- sendto(p->audio_sock,(char *)&irlp_audio_packet,356,
+ sendto((alt_audio_sock != -1) ? alt_audio_sock : audio_sock,(char *)&irlp_audio_packet,356,
0,(struct sockaddr *)&sin,sizeof(struct sockaddr));
}
}
@@ -886,17 +1022,17 @@
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_port = htons(localispeakerport);
- if (p->proto == IRLP_ISADPCM)
+ if (proto == IRLP_ISADPCM)
{
- sendto(p->audio_sock,(char *)&irlp_audio_packet,507,
+ sendto(audio_sock,(char *)&irlp_audio_packet,507,
0,(struct sockaddr *)&sin,sizeof(struct sockaddr));
}
else
{
- sendto(p->audio_sock,(char *)&irlp_audio_packet,356,
+ sendto(audio_sock,(char *)&irlp_audio_packet,356,
0,(struct sockaddr *)&sin,sizeof(struct sockaddr));
}
- p->txindex = 0;
+ txindex = 0;
}
if (p->txkey) return 0;
@@ -916,11 +1052,11 @@
static struct ast_channel *irlp_new(struct irlp_pvt *i, int state)
{
struct ast_channel *tmp;
- tmp = ast_channel_alloc(1, state, 0, 0, "", "s", context, 0, "irlp/%s", i->stream);
+ char tmpstr[30];
+
+ tmp = ast_channel_alloc(1, state, 0, 0, "", astnode, context, 0, "irlp/%s", stream);
if (tmp) {
tmp->tech = &irlp_tech;
- tmp->fds[0] = i->audio_sock;
- tmp->fds[1] = i->ctrl_sock;
tmp->nativeformats = prefformat;
tmp->rawreadformat = prefformat;
tmp->rawwriteformat = prefformat;
@@ -930,8 +1066,10 @@
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->exten, astnode, sizeof(tmp->exten));
ast_string_field_set(tmp, language, "");
+ sprintf(tmpstr,"4%04u",(in_node) ? in_node : atoi(mynode));
+ ast_set_callerid(tmp,tmpstr,NULL,NULL);
i->owner = tmp;
i->u = ast_module_user_add(tmp);
if (state != AST_STATE_DOWN) {
@@ -952,23 +1090,40 @@
struct irlp_pvt *p;
struct ast_channel *tmp = NULL;
+ if (curcall)
+ {
+ ast_log(LOG_NOTICE,"Channel is busy!\n");
+ return NULL;
+ }
oldformat = format;
format &= (AST_FORMAT_ADPCM | AST_FORMAT_GSM);
if (!format) {
ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
return NULL;
}
+ reset_stuff();
p = irlp_alloc(data);
if (p) {
tmp = irlp_new(p, AST_STATE_DOWN);
if (!tmp)
irlp_destroy(p);
}
+ curcall = tmp;
return tmp;
}
static int unload_module(void)
{
+ run_forever = 0;
+ usleep(100000);
+ if (audio_sock != -1) close(audio_sock);
+ audio_sock = -1;
+ if (ctrl_sock != -1) close(ctrl_sock);
+ ctrl_sock = -1;
+ if (alt_audio_sock != -1) close(alt_audio_sock);
+ alt_audio_sock = -1;
+ if (alt_ctrl_sock != -1) close(alt_ctrl_sock);
+ alt_ctrl_sock = -1;
/* First, take us out of the channel loop */
ast_channel_unregister(&irlp_tech);
return 0;
@@ -978,6 +1133,9 @@
{
struct ast_config *cfg = NULL;
char *val = NULL;
+ pthread_attr_t attr;
+ struct sockaddr_in si_me;
+
#ifdef NEW_ASTERISK
struct ast_flags zeroflag = {0};
@@ -1007,7 +1165,7 @@
val = (char *)ast_variable_retrieve(cfg,"general","node");
if (!val)
- strncpy(mynode,"stnXXXX",IRLP_NODE_SIZE);
+ strncpy(mynode,"XXXX",IRLP_NODE_SIZE);
else
strncpy(mynode,val,IRLP_NODE_SIZE);
@@ -1017,12 +1175,80 @@
else
localispeakerport = atoi(val);
+ val = (char *)ast_variable_retrieve(cfg,"general","radmode");
+ if (val) radmode = ast_true(val);
+
+ val = (char *)ast_variable_retrieve(cfg,"general","audioport");
+ if (!val)
+ audio_port_cfg = 2074;
+ else
+ audio_port_cfg = atoi(val);
+
+ val = (char *)ast_variable_retrieve(cfg,"general","astnode");
+ if (!val)
+ astnode[0] = 0;
+ else
+ strncpy(astnode,val,sizeof(astnode) - 1);
+
+ val = (char *)ast_variable_retrieve(cfg,"general","context");
+ if (!val)
+ context[0] = 0;
+ else
+ strncpy(context,val,sizeof(context) - 1);
+
/* initialize local and remote IRLP node */
- remote_irlp_node_ip[0] = '\0';
+ reset_stuff();
+ curcall = 0;
ast_config_destroy(cfg);
+
+ ast_safe_system(IRLP_RESET);
+ usleep(10000);
+
+ audio_port = audio_port_cfg;
+ if ((audio_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
+ {
+ ast_log(LOG_WARNING,
+ "Unable to create new socket for irlp audio connection\n");
+ return -1;
+ }
+
+ if ((ctrl_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
+ {
+ ast_log(LOG_WARNING,
+ "Unable to create new socket for irlp control connection\n");
+ close(audio_sock);
+ return -1;
+ }
+ memset((char *) &si_me, 0, sizeof(si_me));
+ si_me.sin_family = AF_INET;
+ si_me.sin_addr.s_addr = htonl(INADDR_ANY);
+ si_me.sin_port = htons(audio_port);
+ if (bind(audio_sock, &si_me, sizeof(si_me))==-1)
+ {
+ ast_log(LOG_WARNING, "Unable to bind port for irlp audio connection\n");
+ close(ctrl_sock); ctrl_sock = -1;
+ close(audio_sock); audio_sock = -1;
+ return -1;
+ }
+ ctrl_port = audio_port + 1;
+ si_me.sin_port = htons(ctrl_port);
+ if (bind(ctrl_sock, &si_me, sizeof(si_me))==-1)
+ {
+ ast_log(LOG_WARNING, "Unable to bind port for irlp control connection\n");
+ close(ctrl_sock); ctrl_sock = -1;
+ close(audio_sock); audio_sock = -1;
+ }
+ fcntl(audio_sock,F_SETFL,O_NONBLOCK);
+ fcntl(ctrl_sock,F_SETFL,O_NONBLOCK);
+
+ ast_safe_system(IRLP_RESET);
+ usleep(100000);
cfg = NULL;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ast_pthread_create(&irlp_reader_thread,&attr,irlp_reader,NULL);
/* Make sure we can register our channel type */
if (ast_channel_register(&irlp_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
More information about the asterisk-commits
mailing list