Merge SIP changes from oej
authorMark Spencer <markster@digium.com>
Sat, 12 Feb 2005 20:14:21 +0000 (20:14 +0000)
committerMark Spencer <markster@digium.com>
Sat, 12 Feb 2005 20:14:21 +0000 (20:14 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5013 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
configs/sip.conf.sample

index cff4aaa..eb731db 100755 (executable)
@@ -203,7 +203,7 @@ static int tos = 0;
 
 static int videosupport = 0;
 
-static int compactheaders = 0;                                                 /* send compact sip headers */
+static int compactheaders = 0;                         /* send compact sip headers */
 
 static int recordhistory = 0;                          /* Record SIP history. Off by default */
 
@@ -260,7 +260,7 @@ struct sip_history {
 #define SIP_NEEDDESTROY                (1 << 1)        /* if we need to be destroyed */
 #define SIP_NOVIDEO            (1 << 2)        /* Didn't get video in invite, don't offer */
 #define SIP_RINGING            (1 << 3)        /* Have sent 180 ringing */
-#define SIP_PROGRESS_SENT              (1 << 4)        /* Have sent 183 message progress */
+#define SIP_PROGRESS_SENT      (1 << 4)        /* Have sent 183 message progress */
 #define SIP_NEEDREINVITE       (1 << 5)        /* Do we need to send another reinvite? */
 #define SIP_PENDINGBYE         (1 << 6)        /* Need to send bye after we ack? */
 #define SIP_GOTREFER           (1 << 7)        /* Got a refer? */
@@ -317,10 +317,10 @@ static struct sip_pvt {
        ast_mutex_t lock;                       /* Channel private lock */
        char callid[80];                        /* Global CallID */
        char randdata[80];                      /* Random data */
-       struct ast_codec_pref prefs; /* codec prefs */
+       struct ast_codec_pref prefs;            /* codec prefs */
        unsigned int ocseq;                     /* Current outgoing seqno */
        unsigned int icseq;                     /* Current incoming seqno */
-       ast_group_t callgroup;          /* Call group */
+       ast_group_t callgroup;                  /* Call group */
        ast_group_t pickupgroup;                /* Pickup group */
        int lastinvite;                         /* Last Cseq of invite */
        unsigned int flags;                     /* SIP_ flags */        
@@ -401,7 +401,7 @@ static struct sip_pvt {
        int stateid;
        int dialogver;
        
-       struct ast_dsp *vad;
+       struct ast_dsp *vad;                    /* Voice Activation Detection dsp */
        
        struct sip_peer *peerpoke;              /* If this calls is to poke a peer, which one */
        struct sip_registry *registry;          /* If this is a REGISTER call, to which registry */
@@ -409,7 +409,7 @@ static struct sip_pvt {
        struct ast_rtp *vrtp;                   /* Video RTP session */
        struct sip_pkt *packets;                /* Packets scheduled for re-transmission */
        struct sip_history *history;            /* History of this SIP dialog */
-       struct ast_variable *vars;
+       struct ast_variable *chanvars;
        struct sip_pvt *next;                   /* Next call in chain */
 } *iflist = NULL;
 
@@ -418,13 +418,13 @@ static struct sip_pvt {
 
 /* sip packet - read in sipsock_read, transmitted in send_request */
 struct sip_pkt {
-       struct sip_pkt *next;                           /* Next packet */
-       int retrans;                                    /* Retransmission number */
-       int seqno;                                      /* Sequence number */
-       unsigned int flags;                             /* non-zero if this is a response packet (e.g. 200 OK) */
-       struct sip_pvt *owner;                          /* Owner call */
-       int retransid;                                  /* Retransmission ID */
-       int packetlen;                                  /* Length of packet */
+       struct sip_pkt *next;                   /* Next packet */
+       int retrans;                            /* Retransmission number */
+       int seqno;                              /* Sequence number */
+       unsigned int flags;                     /* non-zero if this is a response packet (e.g. 200 OK) */
+       struct sip_pvt *owner;                  /* Owner call */
+       int retransid;                          /* Retransmission ID */
+       int packetlen;                          /* Length of packet */
        char data[0];
 };     
 
@@ -448,21 +448,23 @@ struct sip_user {
        int amaflags;                   /* AMA flags for billing */
        int callingpres;                /* Calling id presentation */
        int capability;                 /* Codec capability */
-       int inUse;
-       int incominglimit;
-       int outUse;
-       int outgoinglimit;
+       int inUse;                      /* Number of calls in use */
+       int incominglimit;              /* Limit of incoming calls */
+       int outUse;                     /* disabled */
+       int outgoinglimit;              /* disabled */
        struct ast_ha *ha;              /* ACL setting */
-       struct ast_variable *vars;
+       struct ast_variable *chanvars;  /* Variables to set for channel created by user */
 };
 
 /* Structure for SIP peer data, we place calls to peers if registred  or fixed IP address (host) */
 struct sip_peer {
-       ASTOBJ_COMPONENTS(struct sip_peer);
+       ASTOBJ_COMPONENTS(struct sip_peer);     /* name, refcount, objflags,  object pointers */
+                                       /* peer->name is the unique name of this object */
        char secret[80];                /* Password */
        char md5secret[80];             /* Password in MD5 */
        char context[80];               /* Default context for incoming calls */
-       char username[80];              /* Temporary username until registration */
+       char username[80];              /* Temporary username until registration */ 
+       char accountcode[20];           /* Account code */
        char tohost[80];                /* If not dynamic, IP address */
        char regexten[AST_MAX_EXTENSION]; /* Extension to register (if regcontext is used) */
        char fromuser[80];              /* From: user when calling this peer */
@@ -474,18 +476,18 @@ struct sip_peer {
        char language[MAX_LANGUAGE];    /* Default language for prompts */
        char musicclass[MAX_LANGUAGE];  /* Music on Hold class */
        char useragent[256];            /* User agent in SIP request (saved from registration) */
-       struct ast_codec_pref prefs; /* codec prefs */
+       struct ast_codec_pref prefs;    /* codec prefs */
        int lastmsgssent;
        time_t  lastmsgcheck;           /* Last time we checked for MWI */
        unsigned int flags;             /* SIP_ flags */        
-       struct ast_flags flags_page2; /* SIP_PAGE2 flags */
+       struct ast_flags flags_page2;   /* SIP_PAGE2 flags */
        int expire;                     /* Registration expiration */
        int expiry;
        int capability;                 /* Codec capability */
-       int rtptimeout;
-       int rtpholdtimeout;
-       int rtpkeepalive;                       /* Send RTP packets for keepalive */
-       ast_group_t callgroup;  /* Call group */
+       int rtptimeout;                 /* RTP timeout */
+       int rtpholdtimeout;             /* RTP Hold Timeout */
+       int rtpkeepalive;               /* Send RTP packets for keepalive */
+       ast_group_t callgroup;          /* Call group */
        ast_group_t pickupgroup;        /* Pickup group */
        struct sockaddr_in addr;        /* IP address of peer */
        struct in_addr mask;
@@ -499,6 +501,7 @@ struct sip_peer {
        
        struct sockaddr_in defaddr;     /* Default IP address, used until registration */
        struct ast_ha *ha;              /* Access control list */
+       struct ast_variable *chanvars;  /* Variables to set for channel created by user */
        int lastmsg;
 };
 
@@ -595,6 +598,8 @@ static void free_old_route(struct sip_route *route);
 static int build_reply_digest(struct sip_pvt *p, char *orig_header, char *digest, int digest_len);
 static int update_user_counter(struct sip_pvt *fup, int event);
 static void prune_peers(void);
+static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime);
+static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime);
 static int sip_do_reload(void);
 static int expire_register(void *data);
 static int callevents = 0;
@@ -1065,6 +1070,7 @@ static int sip_sendtext(struct ast_channel *ast, char *text)
        return 0;       
 }
 
+/*--- realtime_update_peer: Update peer object in realtime storage ---*/
 static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, const char *username, int expirey)
 {
        char port[10];
@@ -1080,6 +1086,7 @@ static void realtime_update_peer(const char *peername, struct sockaddr_in *sin,
        ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr, "port", port, "regseconds", regseconds, "username", username, NULL);
 }
 
+/*--- register_peer_exten: Automatically add peer extension to dial plan ---*/
 static void register_peer_exten(struct sip_peer *peer, int onoff)
 {
        unsigned char multi[256]="";
@@ -1096,11 +1103,16 @@ static void register_peer_exten(struct sip_peer *peer, int onoff)
        }
 }
 
+/*--- sip_destroy_peer: Destroy peer object from memory */
 static void sip_destroy_peer(struct sip_peer *peer)
 {
        /* Delete it, it needs to disappear */
        if (peer->call)
                sip_destroy(peer->call);
+       if(peer->chanvars) {
+               ast_variables_destroy(peer->chanvars);
+               peer->chanvars = NULL;
+       }
        if (peer->expire > -1)
                ast_sched_del(sched, peer->expire);
        if (peer->pokeexpire > -1)
@@ -1125,17 +1137,19 @@ static void update_peer(struct sip_peer *p, int expiry)
                realtime_update_peer(p->name, &p->addr, p->username, expiry);
 }
 
-static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime);
 
+/*--- realtime_peer: Get peer from realtime storage ---*/
+/* Checks the "sippeers" realtime family from extconfig.conf */
 static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
 {
        struct sip_peer *peer=NULL;
        struct ast_variable *var;
        struct ast_variable *tmp;
 
+       /* First check on peer name */
        if (peername) 
                var = ast_load_realtime("sippeers", "name", peername, NULL);
-       else if (sin) {
+       else if (sin) { /* Then check on IP address */
                char iabuf[80];
 
                ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr);
@@ -1147,6 +1161,7 @@ static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *
                return NULL;
 
        tmp = var;
+       /* If this is type=user, then skip this object. */
        while(tmp) {
                if (!strcasecmp(tmp->name, "type") &&
                    !strcasecmp(tmp->value, "user")) {
@@ -1157,6 +1172,7 @@ static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *
        }
 
        peer = build_peer(peername, var, ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS) ? 0 : 1);
+
        if (peer) {
                if(ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS)) {
                        ast_copy_flags((&peer->flags_page2),(&global_flags_page2), SIP_PAGE2_RTAUTOCLEAR|SIP_PAGE2_RTCACHEFRIENDS);
@@ -1172,6 +1188,7 @@ static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *
        return peer;
 }
 
+/*--- sip_addrcmp: Support routine for find_peer ---*/
 static int sip_addrcmp(char *name, struct sockaddr_in *sin)
 {
        /* We know name is the first field, so we can cast */
@@ -1198,12 +1215,13 @@ static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int
        return(p);
 }
 
+/*--- sip_destroy_user: Remove user object from in-memory storage ---*/
 static void sip_destroy_user(struct sip_user *user)
 {
        ast_free_ha(user->ha);
-       if(user->vars) {
-               ast_variables_destroy(user->vars);
-               user->vars = NULL;
+       if(user->chanvars) {
+               ast_variables_destroy(user->chanvars);
+               user->chanvars = NULL;
        }
        if (ast_test_flag(user, SIP_REALTIME))
                ruserobjs--;
@@ -1212,7 +1230,9 @@ static void sip_destroy_user(struct sip_user *user)
        free(user);
 }
 
-static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime);
+/*--- realtime_user: Load user from realtime storage ---*/
+/* Loads user from "sipusers" category in realtime (extconfig.conf) */
+/* Users are matched on From: user name (the domain in skipped) */
 static struct sip_user *realtime_user(const char *username)
 {
        struct ast_variable *var;
@@ -1255,7 +1275,10 @@ static struct sip_user *realtime_user(const char *username)
        return user;
 }
 
-/*--- find_user: Locate user by name */
+/*--- find_user: Locate user by name ---*/
+/* Locates user by name (From: sip uri user name part) first
+   from in-memory list (static configuration) then from 
+   realtime storage (defined in extconfig.conf) */
 static struct sip_user *find_user(const char *name)
 {
        struct sip_user *u = NULL;
@@ -1304,9 +1327,9 @@ static int create_addr(struct sip_pvt *r, char *opeer)
                }
                strncpy(r->peername, p->username, sizeof(r->peername)-1);
                strncpy(r->authname, p->username, sizeof(r->authname)-1);
+               strncpy(r->username, p->username, sizeof(r->username)-1);
                strncpy(r->peersecret, p->secret, sizeof(r->peersecret)-1);
                strncpy(r->peermd5secret, p->md5secret, sizeof(r->peermd5secret)-1);
-               strncpy(r->username, p->username, sizeof(r->username)-1);
                strncpy(r->tohost, p->tohost, sizeof(r->tohost)-1);
                strncpy(r->fullcontact, p->fullcontact, sizeof(r->fullcontact)-1);
                if (!r->initreq.headers && !ast_strlen_zero(p->fromdomain)) {
@@ -1473,6 +1496,8 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
        return res;
 }
 
+/*--- sip_registry_destroy: Destroy registry object ---*/
+/* Objects created with the register= statement in static configuration */
 static void sip_registry_destroy(struct sip_registry *reg)
 {
        /* Really delete */
@@ -1561,9 +1586,9 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
                        free(cp);
                }
                ast_mutex_destroy(&p->lock);
-               if(p->vars) {
-                       ast_variables_destroy(p->vars);
-                       p->vars = NULL;
+               if(p->chanvars) {
+                       ast_variables_destroy(p->chanvars);
+                       p->chanvars = NULL;
                }
                free(p);
        }
@@ -1647,6 +1672,7 @@ static void sip_destroy(struct sip_pvt *p)
 
 static int transmit_response_reliable(struct sip_pvt *p, char *msg, struct sip_request *req, int fatal);
 
+/*--- hangup_sip2cause: Convert SIP hangup causes to Asterisk hangup causes ---*/
 static int hangup_sip2cause(int cause)
 {
 /* Possible values from causes.h
@@ -1668,6 +1694,7 @@ static int hangup_sip2cause(int cause)
        return 0;
 }
 
+/*--- hangup_cause2sip: Convert Asterisk hangup causes to SIP codes ---*/
 static char *hangup_cause2sip(int cause)
 {
        switch(cause)
@@ -1685,7 +1712,8 @@ static char *hangup_cause2sip(int cause)
        return 0;
 }
 
-/*--- sip_hangup: Hangup SIP call */
+/*--- sip_hangup: Hangup SIP call ---*/
+/* Part of PBX interface */
 static int sip_hangup(struct ast_channel *ast)
 {
        struct sip_pvt *p = ast->pvt->pvt;
@@ -1775,7 +1803,8 @@ static int sip_hangup(struct ast_channel *ast)
        return 0;
 }
 
-/*--- sip_answer: Answer SIP call , send 200 OK on Invite */
+/*--- sip_answer: Answer SIP call , send 200 OK on Invite ---*/
+/* Part of PBX interface */
 static int sip_answer(struct ast_channel *ast)
 {
        int res = 0,fmt;
@@ -1901,6 +1930,7 @@ static int sip_transfer(struct ast_channel *ast, char *dest)
 {
        struct sip_pvt *p = ast->pvt->pvt;
        int res;
+
        ast_mutex_lock(&p->lock);
        res = transmit_refer(p, dest);
        ast_mutex_unlock(&p->lock);
@@ -2089,7 +2119,8 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
                                tmp = NULL;
                        }
                }
-               for (v = i->vars ; v ; v = v->next)
+               /* Set channel variables for this call from configuration */
+               for (v = i->chanvars ; v ; v = v->next)
                        pbx_builtin_setvar_helper(tmp,v->name,v->value);
                                
        } else
@@ -2097,6 +2128,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
        return tmp;
 }
 
+/* Structure for conversion between compressed SIP and "normal" SIP */
 static struct cfalias {
        char *fullname;
        char *shortname;
@@ -2325,9 +2357,9 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
        if (!p->rtp) {
                ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
                 ast_mutex_destroy(&p->lock);
-               if(p->vars) {
-                       ast_variables_destroy(p->vars);
-                       p->vars = NULL;
+               if(p->chanvars) {
+                       ast_variables_destroy(p->chanvars);
+                       p->chanvars = NULL;
                }
                free(p);
                return NULL;
@@ -3612,63 +3644,67 @@ static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_r
 }
 
 /*--- determine_firstline_parts: parse first line of incoming SIP request */
-static int determine_firstline_parts( struct sip_request *req ) {
-
-  char *e, *cmd;
-  int len;
+static int determine_firstline_parts( struct sip_request *req ) 
+{
+       char *e, *cmd;
+       int len;
   
-  cmd= req->header[0];
-  while(*cmd && (*cmd < 33)) {
-    cmd++;
-  }
-  if (!*cmd) {
-    return -1;
-  }
-  e= cmd;
-  while(*e && (*e > 32)) {
-    e++;
-  }
-  /* Get the command */
-  if (*e) {
-    *e = '\0';
-    e++;
-  }
-  req->rlPart1= cmd;
-  while( *e && ( *e < 33 ) ) {
-    e++; 
-  }
-  if( !*e ) {
-    return -1;
-  }
+       cmd = req->header[0];
+       while(*cmd && (*cmd < 33)) {
+               cmd++;
+       }
+       if (!*cmd) {
+               return -1;
+       }
+       e = cmd;
+       while(*e && (*e > 32)) {
+               e++;
+       }
+       /* Get the command */
+       if (*e) {
+               *e = '\0';
+               e++;
+       }
+       req->rlPart1 = cmd;
+       while( *e && ( *e < 33 ) ) {
+               e++; 
+       }
+       if( !*e ) {
+               return -1;
+       }
     
-  if ( !strcasecmp(cmd, "SIP/2.0") ) {
-    /* We have a response */
-    req->rlPart2= e;
-    len= strlen( req->rlPart2 );
-    if( len < 2 ) { return -1; }
-    e+= len - 1;
-    while( *e && *e<33 ) {
-      e--; 
-    }
-    *(++e)= '\0';
-  } else {
-    /* We have a request */
-    if( *e == '<' ) { 
-      e++;
-      if( !*e ) { return -1; }  
-    }
-    req->rlPart2= e;   /* URI */
-    if( ( e= strrchr( req->rlPart2, 'S' ) ) == NULL ) {
-      return -1;
-    }
-    while( isspace( *(--e) ) ) {}
-    if( *e == '>' ) {
-      *e= '\0';
-    } else {
-      *(++e)= '\0';
-    }
-  }
-  return 1;
+       if ( !strcasecmp(cmd, "SIP/2.0") ) {
+               /* We have a response */
+               req->rlPart2= e;
+               len= strlen( req->rlPart2 );
+               if( len < 2 ) { 
+                       return -1;
+               }
+               e+= len - 1;
+               while( *e && *e<33 ) {
+                       e--; 
+               }
+               *(++e)= '\0';
+       } else {
+               /* We have a request */
+               if( *e == '<' ) { 
+                       e++;
+                       if( !*e ) { 
+                               return -1; 
+                       }  
+               }
+               req->rlPart2= e;        /* URI */
+               if( ( e= strrchr( req->rlPart2, 'S' ) ) == NULL ) {
+                       return -1;
+               }
+               while( isspace( *(--e) ) ) {}
+               if( *e == '>' ) {
+                       *e= '\0';
+               } else {
+                       *(++e)= '\0';
+               }
+       }
+       return 1;
 }
 
 /*--- transmit_reinvite_with_sdp: Transmit reinvite with SDP :-) ---*/
@@ -3756,7 +3792,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, c
                if (p->username && p->username[0] == '+')
                        x=1;
 
-               for (;x<strlen(p->username);x++) {
+               for (; x<strlen(p->username); x++) {
                        if (!strchr(AST_DIGIT_ANY, p->username[x])) {
                                onlydigits = 0;
                                break;
@@ -4537,7 +4573,7 @@ static void reg_source_db(struct sip_peer *p)
                                                
                                        }
                                        if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "SIP Seeding '%s' at %s@%s:%d for %d\n", p->name, 
+                                               ast_verbose(VERBOSE_PREFIX_3 "SIP Seeding peers from Astdb: '%s' at %s@%s:%d for %d\n", p->name, 
                                                                        p->username, ast_inet_ntoa(iabuf, sizeof(iabuf), in), atoi(c), atoi(d));
                                        expiry = atoi(d);
                                        memset(&p->addr, 0, sizeof(p->addr));
@@ -4737,10 +4773,12 @@ static int parse_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_req
                   with */
                memcpy(&p->addr, &pvt->recv, sizeof(p->addr));
        }
-       if (c)
+
+       if (c)  /* Overwrite the default username from config at registration */
                strncpy(p->username, c, sizeof(p->username) - 1);
        else
                p->username[0] = '\0';
+
        if (p->expire > -1)
                ast_sched_del(sched, p->expire);
        if ((expiry < 1) || (expiry > max_expiry))
@@ -5629,11 +5667,11 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd
        /* Find user based on user name in the from header */
        if (!mailbox && user && ast_apply_ha(user->ha, sin)) {
                ast_copy_flags(p, user, SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_NAT | SIP_PROG_INBAND | SIP_OSPAUTH);
-               /* copy vars */
-               for (v = user->vars ; v ; v = v->next) {
+               /* copy channel vars */
+               for (v = user->chanvars ; v ; v = v->next) {
                        if((tmpvar = ast_variable_new(v->name, v->value))) {
-                               tmpvar->next = p->vars; 
-                               p->vars = tmpvar;
+                               tmpvar->next = p->chanvars; 
+                               p->chanvars = tmpvar;
                        }
                }
                p->prefs = user->prefs;
@@ -5734,10 +5772,18 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd
                                ast_copy_flags(p, peer, SIP_PROMISCREDIR | SIP_DTMF | SIP_REINVITE);
                                strncpy(p->peername, peer->name, sizeof(p->peername) - 1);
                                strncpy(p->authname, peer->name, sizeof(p->authname) - 1);
+                               /* copy channel vars */
+                               for (v = peer->chanvars ; v ; v = v->next) {
+                                       if((tmpvar = ast_variable_new(v->name, v->value))) {
+                                               tmpvar->next = p->chanvars; 
+                                               p->chanvars = tmpvar;
+                                       }
+                               }
                                if (mailbox)
                                        snprintf(mailbox, mailboxlen, ",%s,", peer->mailbox);
                                if (!ast_strlen_zero(peer->username)) {
                                        strncpy(p->username, peer->username, sizeof(p->username) - 1);
+                                       /* Use the default username for authentication on outbound calls */
                                        strncpy(p->authname, peer->username, sizeof(p->authname) - 1);
                                }
                                if (!ast_strlen_zero(peer->cid_num) && !ast_strlen_zero(p->cid_num))  {
@@ -5752,6 +5798,7 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd
                                strncpy(p->peersecret, peer->secret, sizeof(p->peersecret) - 1);
                                strncpy(p->peermd5secret, peer->md5secret, sizeof(p->peermd5secret) - 1);
                                strncpy(p->language, peer->language, sizeof(p->language)  -1);
+                               strncpy(p->accountcode, peer->accountcode, sizeof(p->accountcode) - 1);
                                p->callgroup = peer->callgroup;
                                p->pickupgroup = peer->pickupgroup;
                                p->capability = peer->capability;
@@ -6114,6 +6161,7 @@ static int sip_show_peer(int fd, int argc, char *argv[])
        struct sip_peer *peer;
        char codec_buf[512];
        struct ast_codec_pref *pref;
+       struct ast_variable *v;
        int x = 0, codec = 0, load_realtime = 0;
 
        if (argc < 4)
@@ -6128,8 +6176,12 @@ static int sip_show_peer(int fd, int argc, char *argv[])
                ast_cli(fd, "  MD5Secret    : %s\n", ast_strlen_zero(peer->md5secret)?"<Not set>":"<Set>");
                ast_cli(fd, "  Context      : %s\n", peer->context);
                ast_cli(fd, "  Language     : %s\n", peer->language);
-               ast_cli(fd, "  FromUser     : %s\n", peer->fromuser);
-               ast_cli(fd, "  FromDomain   : %s\n", peer->fromdomain);
+               if (!ast_strlen_zero(peer->accountcode))
+                       ast_cli(fd, "  Accountcode  : %s\n", peer->accountcode);
+               if (!ast_strlen_zero(peer->fromuser))
+                       ast_cli(fd, "  FromUser     : %s\n", peer->fromuser);
+               if (!ast_strlen_zero(peer->fromdomain))
+                       ast_cli(fd, "  FromDomain   : %s\n", peer->fromdomain);
                ast_cli(fd, "  Callgroup    : ");
                print_group(fd, peer->callgroup);
                ast_cli(fd, "  Pickupgroup  : ");
@@ -6153,7 +6205,7 @@ static int sip_show_peer(int fd, int argc, char *argv[])
                ast_cli(fd, "  ToHost       : %s\n", peer->tohost);
                ast_cli(fd, "  Addr->IP     : %s Port %d\n",  peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port));
                ast_cli(fd, "  Defaddr->IP  : %s Port %d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port));
-               ast_cli(fd, "  Username     : %s\n", peer->username);
+               ast_cli(fd, "  Def. Username: %s\n", peer->username);
                ast_cli(fd, "  Codecs       : ");
                ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability);
                ast_cli(fd, "%s\n", codec_buf);
@@ -6184,6 +6236,11 @@ static int sip_show_peer(int fd, int argc, char *argv[])
                ast_cli(fd, "%s\n",status);
                ast_cli(fd, "  Useragent    : %s\n", peer->useragent);
                ast_cli(fd, "  Full Contact : %s\n", peer->fullcontact);
+               if (peer->chanvars) {
+                       ast_cli(fd, "  Variables    :\n");
+                       for (v = peer->chanvars ; v ; v = v->next)
+                               ast_cli(fd, "                 %s = %s\n", v->name, v->value);
+               }
                ast_cli(fd,"\n");
                ASTOBJ_UNREF(peer,sip_destroy_peer);
        } else {
@@ -8797,8 +8854,8 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v, int
                                        *varval = '\0';
                                        varval++;
                                        if((tmpvar = ast_variable_new(varname, varval))) {
-                                               tmpvar->next = user->vars;
-                                               user->vars = tmpvar;
+                                               tmpvar->next = user->chanvars;
+                                               user->chanvars = tmpvar;
                                        }
 
                                }
@@ -8896,6 +8953,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
        int obproxyfound=0;
        int found=0;
        time_t regseconds;
+       char *varname = NULL, *varval = NULL;
+       struct ast_variable *tmpvar = NULL;
 
        if (!realtime)
                /* Note we do NOT use find_peer here, to avoid realtime recursion */
@@ -9041,6 +9100,8 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
                                strncpy(peer->language, v->value, sizeof(peer->language)-1);
                        } else if (!strcasecmp(v->name, "regexten")) {
                                strncpy(peer->regexten, v->value, sizeof(peer->regexten)-1);
+                       } else if (!strcasecmp(v->name, "accountcode")) {
+                               strncpy(peer->accountcode, v->value, sizeof(peer->accountcode)-1);
                        } else if (!strcasecmp(v->name, "musiconhold")) {
                                strncpy(peer->musicclass, v->value, sizeof(peer->musicclass)-1);
                        } else if (!strcasecmp(v->name, "mailbox")) {
@@ -9068,6 +9129,17 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
                                        ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d.  Using default.\n", v->value, v->lineno);
                                        peer->rtpkeepalive = global_rtpkeepalive;
                                }
+                       } else if (!strcasecmp(v->name, "setvar")) {
+                               /* Set peer channel variable */
+                               varname = ast_strdupa(v->value);
+                               if (varname && (varval = strchr(varname,'='))) {
+                                       *varval = '\0';
+                                       varval++;
+                                       if((tmpvar = ast_variable_new(varname, varval))) {
+                                               tmpvar->next = peer->chanvars;
+                                               peer->chanvars = tmpvar;
+                                       }
+                               }
                        } else if (!strcasecmp(v->name, "qualify")) {
                                if (!strcasecmp(v->value, "no")) {
                                        peer->maxms = 0;
@@ -9855,9 +9927,9 @@ int unload_module()
                        p = p->next;
                        /* Free associated memory */
                        ast_mutex_destroy(&pl->lock);
-                       if(pl->vars) {
-                               ast_variables_destroy(pl->vars);
-                               pl->vars = NULL;
+                       if(pl->chanvars) {
+                               ast_variables_destroy(pl->chanvars);
+                               pl->chanvars = NULL;
                        }
                        free(pl);
                }
index d2d02ed..b113f00 100755 (executable)
@@ -193,9 +193,9 @@ srvlookup=yes                       ; Enable DNS SRV lookups on outbound calls
 ; progressinband              progressinband
 ; promiscredir                promiscredir
 ; useclientcode               useclientcode
-; setvar
+; accountcode                 accountcode
+; setvar                      setvar
 ; callerid
-; accountcode
 ; amaflags
 ; incominglimit
 ; restrictcid