Version 0.1.11 from FTP
authorMark Spencer <markster@digium.com>
Mon, 11 Mar 2002 02:00:09 +0000 (02:00 +0000)
committerMark Spencer <markster@digium.com>
Mon, 11 Mar 2002 02:00:09 +0000 (02:00 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@425 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_iax.c
channels/chan_phone.c

index 679ba65..74c7539 100755 (executable)
 
 #include "iax.h"
 
+/*
+ * Uncomment to try experimental IAX bridge optimization,
+ * designed to reduce latency when IAX calls cannot
+ * be trasnferred
+ */
+
+#define BRIDGE_OPTIMIZATION 
+
+
 #define DEFAULT_RETRY_TIME 1000
 #define MEMORY_SIZE 100
 #define DEFAULT_DROP 3
@@ -161,7 +170,10 @@ struct iax_peer {
        char inkeys[80];                                /* Key(s) this peer can use to authenticate to us */
 
        int hascallerid;
+       /* Suggested caller id if registering */
        char callerid[AST_MAX_EXTENSION];
+       /* Whether or not to send ANI */
+       int sendani;
        int expire;                                             /* Schedule entry for expirey */
        int expirey;                                    /* How soon to expire */
        int capability;                                 /* Capability */
@@ -268,8 +280,10 @@ struct chan_iax_pvt {
        char context[80];
        /* Caller ID if available */
        char callerid[80];
-       /* Hidden Caller ID if appropriate */
-       char hidden_callerid[80];
+       /* Hidden Caller ID (i.e. ANI) if appropriate */
+       char ani[80];
+       /* Whether or not ani should be transmitted in addition to Caller*ID */
+       int sendani;
        /* DNID */
        char dnid[80];
        /* Requested Extension */
@@ -519,8 +533,12 @@ static unsigned int calc_timestamp(struct chan_iax_pvt *p, unsigned int ts);
 static int send_ping(void *data)
 {
        int callno = (long)data;
+       /* Ping only if it's real, not if it's bridged */
        if (iaxs[callno]) {
-               send_command(iaxs[callno], AST_FRAME_IAX, AST_IAX_COMMAND_PING, 0, NULL, 0, -1);
+#ifdef BRIDGE_OPTIMIZATION
+               if (iaxs[callno]->bridgecallno < 0)
+#endif         
+                       send_command(iaxs[callno], AST_FRAME_IAX, AST_IAX_COMMAND_PING, 0, NULL, 0, -1);
                return 1;
        } else
                return 0;
@@ -529,8 +547,12 @@ static int send_ping(void *data)
 static int send_lagrq(void *data)
 {
        int callno = (long)data;
+       /* Ping only if it's real not if it's bridged */
        if (iaxs[callno]) {
-               send_command(iaxs[callno], AST_FRAME_IAX, AST_IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
+#ifdef BRIDGE_OPTIMIZATION
+               if (iaxs[callno]->bridgecallno < 0)
+#endif         
+                       send_command(iaxs[callno], AST_FRAME_IAX, AST_IAX_COMMAND_LAGRQ, 0, NULL, 0, -1);
                return 1;
        } else
                return 0;
@@ -734,7 +756,7 @@ static int find_callno(short callno, short dcallno ,struct sockaddr_in *sin, int
        if ((res < 0) && (new >= NEW_ALLOW)) {
                /* Create a new one */
                start = nextcallno;
-               for (x = nextcallno + 1; iaxs[x] && (x != start); x = (x + 1) % AST_IAX_MAX_CALLS) 
+               for (x = (nextcallno + 1) % AST_IAX_MAX_CALLS; iaxs[x] && (x != start); x = (x + 1) % AST_IAX_MAX_CALLS) 
                if (x == start) {
                        ast_log(LOG_WARNING, "Unable to accept more calls\n");
                        return -1;
@@ -1106,6 +1128,22 @@ static struct ast_cli_entry cli_show_cache =
 
 static unsigned int calc_rxstamp(struct chan_iax_pvt *p);
 
+#ifdef BRIDGE_OPTIMIZATION
+static unsigned int calc_fakestamp(struct chan_iax_pvt *from, struct chan_iax_pvt *to, unsigned int ts);
+
+static int forward_delivery(struct ast_iax_frame *fr)
+{
+       struct chan_iax_pvt *p1, *p2;
+       p1 = iaxs[fr->callno];
+       p2 = iaxs[p1->bridgecallno];
+       /* Fix relative timestamp */
+       fr->ts = calc_fakestamp(p1, p2, fr->ts);
+       /* Now just send it send on the 2nd one 
+          with adjusted timestamp */
+       return iax_send(p2, fr->f, fr->ts, -1, 0, 0, 0);
+}
+#endif
+
 static int schedule_delivery(struct ast_iax_frame *fr, int reallydeliver)
 {
        int ms,x;
@@ -1114,6 +1152,7 @@ static int schedule_delivery(struct ast_iax_frame *fr, int reallydeliver)
        /* ms is a measure of the "lateness" of the packet relative to the first
           packet we received, which always has a lateness of 1.  */
        ms = calc_rxstamp(iaxs[fr->callno]) - fr->ts;
+
        if (ms > 32768) {
                /* What likely happened here is that our counter has circled but we haven't
                   gotten the update from the main packet.  We'll just pretend that we did, and
@@ -1292,11 +1331,13 @@ static int iax_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan
        return 0;
 }
 
-static int create_addr(struct sockaddr_in *sin, int *capability, char *peer)
+static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, char *peer)
 {
        struct hostent *hp;
        struct iax_peer *p;
        int found=0;
+       if (sendani)
+               *sendani = 0;
        sin->sin_family = AF_INET;
        ast_pthread_mutex_lock(&peerl.lock);
        p = peerl.peers;
@@ -1306,6 +1347,8 @@ static int create_addr(struct sockaddr_in *sin, int *capability, char *peer)
                        if (capability)
                                *capability = p->capability;
                        if (p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) {
+                               if (sendani)
+                                       *sendani = p->sendani;
                                if (p->addr.sin_addr.s_addr) {
                                        sin->sin_addr = p->addr.sin_addr;
                                        sin->sin_port = p->addr.sin_port;
@@ -1376,7 +1419,7 @@ static int iax_call(struct ast_channel *c, char *dest, int timeout)
                strtok(hname, ":");
                portno = strtok(hname, ":");
        }
-       if (create_addr(&sin, NULL, hname)) {
+       if (create_addr(&sin, NULL, NULL, hname)) {
                ast_log(LOG_WARNING, "No address associated with '%s'\n", hname);
                return -1;
        }
@@ -1389,6 +1432,8 @@ static int iax_call(struct ast_channel *c, char *dest, int timeout)
        MYSNPRINTF "exten=%s;", rdest);
        if (c->callerid)
                MYSNPRINTF "callerid=%s;", c->callerid);
+       if (p->sendani && c->ani)
+               MYSNPRINTF "ani=%s;", c->ani);
        if (c->language && strlen(c->language))
                MYSNPRINTF "language=%s;", c->language);
        if (c->dnid)
@@ -1548,8 +1593,11 @@ static int iax_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
        cs[1] = c1;
        for (/* ever */;;) {
                /* Check in case we got masqueraded into */
-               if ((c0->type != type) || (c1->type != type))
+               if ((c0->type != type) || (c1->type != type)) {
+                       if (option_verbose > 2)
+                               ast_verbose(VERBOSE_PREFIX_3 "Can't masquerade, we're different...\n");
                        return -2;
+               }
                if (!transferstarted) {
                        /* Try the transfer */
                        if (iax_start_transfer(c0, c1))
@@ -1708,8 +1756,8 @@ static struct ast_channel *ast_iax_new(struct chan_iax_pvt *i, int state, int ca
                tmp->pvt->bridge = iax_bridge;
                if (strlen(i->callerid))
                        tmp->callerid = strdup(i->callerid);
-               if (strlen(i->hidden_callerid))
-                       tmp->hidden_callerid = strdup(i->hidden_callerid);
+               if (strlen(i->ani))
+                       tmp->ani = strdup(i->ani);
                if (strlen(i->language))
                        strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
                if (strlen(i->dnid))
@@ -1758,13 +1806,42 @@ static unsigned int calc_timestamp(struct chan_iax_pvt *p, unsigned int ts)
        return ms;
 }
 
+#ifdef BRIDGE_OPTIMIZATION
+static unsigned int calc_fakestamp(struct chan_iax_pvt *p1, struct chan_iax_pvt *p2, unsigned int fakets)
+{
+       int ms;
+       /* Receive from p1, send to p2 */
+       
+       /* Setup rxcore if necessary on outgoing channel */
+       if (!p1->rxcore.tv_sec && !p1->rxcore.tv_usec)
+               gettimeofday(&p1->rxcore, NULL);
+
+       /* Setup txcore if necessary on outgoing channel */
+       if (!p2->offset.tv_sec && !p2->offset.tv_usec)
+               gettimeofday(&p2->offset, NULL);
+       
+       /* Now, ts is the timestamp of the original packet in the orignal context.
+          Adding rxcore to it gives us when we would want the packet to be delivered normally.
+          Subtracting txcore of the outgoing channel gives us what we'd expect */
+       
+       ms = (p1->rxcore.tv_sec - p2->offset.tv_sec) * 1000 + (p1->rxcore.tv_usec - p1->offset.tv_usec) / 1000;
+       fakets += ms;
+       if (fakets <= p2->lastsent)
+               fakets = p2->lastsent + 1;
+       p2->lastsent = fakets;
+       return fakets;
+}
+#endif
+
 static unsigned int calc_rxstamp(struct chan_iax_pvt *p)
 {
        /* Returns where in "receive time" we are */
        struct timeval tv;
        unsigned int ms;
+       /* Setup rxcore if necessary */
        if (!p->rxcore.tv_sec && !p->rxcore.tv_usec)
                gettimeofday(&p->rxcore, NULL);
+
        gettimeofday(&tv, NULL);
        ms = (tv.tv_sec - p->rxcore.tv_sec) * 1000 + (tv.tv_usec - p->rxcore.tv_usec) / 1000;
        return ms;
@@ -2099,6 +2176,13 @@ static int send_command(struct chan_iax_pvt *i, char type, int command, unsigned
        return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
 }
 
+#ifdef BRIDGE_OPTIMIZATION
+static int forward_command(struct chan_iax_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
+{
+       return __send_command(iaxs[i->bridgecallno], type, command, ts, data, datalen, seqno, 0, 0, 0);
+}
+#endif
+
 static int send_command_final(struct chan_iax_pvt *i, char type, int command, unsigned int ts, char *data, int datalen, int seqno)
 {
        iax_predestroy(i);
@@ -2183,6 +2267,8 @@ static int check_access(int callno, struct sockaddr_in *sin, char *orequest, int
                                strncpy(iaxs[callno]->exten, value, sizeof(iaxs[callno]->exten)-1);
                        else if (!strcmp(var, "callerid"))
                                strncpy(iaxs[callno]->callerid, value, sizeof(iaxs[callno]->callerid)-1);
+                       else if (!strcmp(var, "ani"))
+                               strncpy(iaxs[callno]->ani, value, sizeof(iaxs[callno]->ani) - 1);
                        else if (!strcmp(var, "dnid"))
                                strncpy(iaxs[callno]->dnid, value, sizeof(iaxs[callno]->dnid)-1);
                        else if (!strcmp(var, "context"))
@@ -2239,11 +2325,11 @@ static int check_access(int callno, struct sockaddr_in *sin, char *orequest, int
                        strncpy(iaxs[callno]->inkeys, user->inkeys, sizeof(iaxs[callno]->inkeys));
                        /* And the permitted authentication methods */
                        strncpy(iaxs[callno]->methods, user->methods, sizeof(iaxs[callno]->methods)-1);
-                       /* If they have callerid, override the given caller id.  Always store the hidden */
+                       /* If they have callerid, override the given caller id.  Always store the ANI */
                        if (strlen(iaxs[callno]->callerid)) {
                                if (user->hascallerid)
                                        strncpy(iaxs[callno]->callerid, user->callerid, sizeof(iaxs[callno]->callerid)-1);
-                               strncpy(iaxs[callno]->hidden_callerid, user->callerid, sizeof(iaxs[callno]->hidden_callerid)-1);
+                               strncpy(iaxs[callno]->ani, user->callerid, sizeof(iaxs[callno]->ani)-1);
                        }
                        if (strlen(user->accountcode))
                                strncpy(iaxs[callno]->accountcode, user->accountcode, sizeof(iaxs[callno]->accountcode)-1);
@@ -2332,7 +2418,7 @@ static int authenticate_verify(struct chan_iax_pvt *p, char *orequest)
                                res = 0;
                                break;
                        } else if (!key)
-                               ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n");
+                               ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n", keyn);
                        keyn = strtok(NULL, ":");
                }
        } else if (strstr(p->methods, "md5")) {
@@ -3364,24 +3450,53 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
                                ast_pthread_mutex_unlock(&dpcache_lock);
                                break;
                        case AST_IAX_COMMAND_PING:
+#ifdef BRIDGE_OPTIMIZATION
+                               if (iaxs[fr.callno]->bridgecallno > -1) {
+                                       /* If we're in a bridged call, just forward this */
+                                       forward_command(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_PING, fr.ts, NULL, 0, -1);
+                               } else {
+                                       /* Send back a pong packet with the original timestamp */
+                                       send_command(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_PONG, fr.ts, NULL, 0, -1);
+                               }
+#else                          
                                /* Send back a pong packet with the original timestamp */
                                send_command(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_PONG, fr.ts, NULL, 0, -1);
+#endif                         
                                break;
                        case AST_IAX_COMMAND_PONG:
+#ifdef BRIDGE_OPTIMIZATION
+                               if (iaxs[fr.callno]->bridgecallno > -1) {
+                                       /* Forward to the other side of the bridge */
+                                       forward_command(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_PONG, fr.ts, NULL, 0, -1);
+                               } else {
+                                       /* Calculate ping time */
+                                       iaxs[fr.callno]->pingtime =  calc_timestamp(iaxs[fr.callno], 0) - fr.ts;
+                               }
+#else
+                               /* Calculate ping time */
                                iaxs[fr.callno]->pingtime =  calc_timestamp(iaxs[fr.callno], 0) - fr.ts;
+#endif                                 
                                break;
                        case AST_IAX_COMMAND_LAGRQ:
                        case AST_IAX_COMMAND_LAGRP:
-                               /* A little strange -- We have to actually go through the motions of
-                                  delivering the packet.  In the very last step, it will be properly
-                                  handled by do_deliver */
-                               snprintf(src, sizeof(src), "LAGRQ-IAX/%s/%d", inet_ntoa(sin.sin_addr),fr.callno);
-                               f.src = src;
-                               f.mallocd = 0;
-                               f.offset = 0;
-                               fr.f = &f;
-                               f.timelen = 0;
-                               schedule_delivery(iaxfrdup2(&fr, 0), 1);
+#ifdef BRIDGE_OPTIMIZATION
+                               if (iaxs[fr.callno]->bridgecallno > -1) {
+                                       forward_command(iaxs[fr.callno], AST_FRAME_IAX, f.subclass, fr.ts, NULL, 0, -1);
+                               } else {
+#endif                         
+                                       /* A little strange -- We have to actually go through the motions of
+                                          delivering the packet.  In the very last step, it will be properly
+                                          handled by do_deliver */
+                                       snprintf(src, sizeof(src), "LAGRQ-IAX/%s/%d", inet_ntoa(sin.sin_addr),fr.callno);
+                                       f.src = src;
+                                       f.mallocd = 0;
+                                       f.offset = 0;
+                                       fr.f = &f;
+                                       f.timelen = 0;
+                                       schedule_delivery(iaxfrdup2(&fr, 0), 1);
+#ifdef BRIDGE_OPTIMIZATION
+                               }
+#endif                         
                                break;
                        case AST_IAX_COMMAND_AUTHREQ:
                                if (iaxs[fr.callno]->state & (IAX_STATE_STARTED | IAX_STATE_TBD)) {
@@ -3632,7 +3747,15 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
                        ast_log(LOG_DEBUG, "Received out of order packet... (type=%d, subclass %d, ts = %d, last = %d)\n", f.frametype, f.subclass, fr.ts, iaxs[fr.callno]->last);
                fr.outoforder = -1;
        }
+#ifdef BRIDGE_OPTIMIZATION
+       if (iaxs[fr.callno]->bridgecallno > -1) {
+               forward_delivery(&fr);
+       } else {
+               schedule_delivery(iaxfrdup2(&fr, 0), 1);
+       }
+#else
        schedule_delivery(iaxfrdup2(&fr, 0), 1);
+#endif
        /* Always run again */
        ast_pthread_mutex_unlock(&iaxs_lock);
        return 1;
@@ -3690,6 +3813,7 @@ static struct ast_channel *iax_request(char *type, int format, void *data)
 {
        int callno;
        int res;
+       int sendani;
        int fmt, native;
        struct sockaddr_in sin;
        char s[256];
@@ -3703,7 +3827,7 @@ static struct ast_channel *iax_request(char *type, int format, void *data)
        if (!st)
                st = s;
        /* Populate our address from the given */
-       if (create_addr(&sin, &capability, st)) {
+       if (create_addr(&sin, &capability, &sendani, st)) {
                return NULL;
        }
        ast_pthread_mutex_lock(&iaxs_lock);
@@ -3712,6 +3836,8 @@ static struct ast_channel *iax_request(char *type, int format, void *data)
                ast_log(LOG_WARNING, "Unable to create call\n");
                return NULL;
        }
+       /* Keep track of sendani flag */
+       iaxs[callno]->sendani = sendani;
        c = ast_iax_new(iaxs[callno], AST_STATE_DOWN, capability);
        if (c) {
                /* Choose a format we can live with */
@@ -3963,6 +4089,8 @@ static struct iax_peer *build_peer(char *name, struct ast_variable *v)
                        } else if (!strcasecmp(v->name, "callerid")) {
                                strncpy(peer->callerid, v->value, sizeof(peer->callerid)-1);
                                peer->hascallerid=1;
+                       } else if (!strcasecmp(v->name, "sendani")) {
+                               peer->sendani = ast_true(v->value);
                        } else if (!strcasecmp(v->name, "inkeys")) {
                                strncpy(peer->inkeys, v->value, sizeof(peer->inkeys));
                        } else if (!strcasecmp(v->name, "outkey")) {
@@ -4293,7 +4421,7 @@ static int cache_get_callno(char *data)
                host = st;
        }
        /* Populate our address from the given */
-       if (create_addr(&sin, NULL, host)) {
+       if (create_addr(&sin, NULL, NULL, host)) {
                return -1;
        }
        ast_log(LOG_DEBUG, "host: %s, user: %s, password: %s, context: %s\n", host, username, password, context);
index c481abb..7300646 100755 (executable)
@@ -588,6 +588,8 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
                tmp->fds[0] = i->fd;
                /* XXX Switching formats silently causes kernel panics XXX */
                tmp->nativeformats = prefformat;
+               tmp->pvt->rawreadformat = prefformat;
+               tmp->pvt->rawwriteformat = prefformat;
                tmp->state = state;
                if (state == AST_STATE_RING)
                        tmp->rings = 1;
@@ -911,7 +913,7 @@ static struct phone_pvt *mkif(char *iface, int mode, int txgain, int rxgain)
                                ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");
                } else {
                        if (ioctl(tmp->fd, IXJCTL_PORT, PORT_POTS)) 
-                               ast_log(LOG_DEBUG, "Unable to set port to PSTN\n");
+                               ast_log(LOG_DEBUG, "Unable to set port to POTS\n");
                }
                ioctl(tmp->fd, PHONE_PLAY_STOP);
                ioctl(tmp->fd, PHONE_REC_STOP);
@@ -1088,7 +1090,7 @@ int load_module()
        ast_pthread_mutex_unlock(&iflock);
        /* Make sure we can register our Adtranphone channel type */
        if (ast_channel_register(type, tdesc, 
-                       AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW, phone_request)) {
+                        AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW, phone_request)) {
                ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
                ast_destroy(cfg);
                unload_module();