Formatting fixes, proper locking and to shut bkw up. Bug #4185
authorJeremy McNamara <jj@nufone.net>
Wed, 11 May 2005 13:27:49 +0000 (13:27 +0000)
committerJeremy McNamara <jj@nufone.net>
Wed, 11 May 2005 13:27:49 +0000 (13:27 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5628 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_h323.c

index 1d8b08e..f4f5950 100755 (executable)
@@ -110,6 +110,7 @@ static int capability = AST_FORMAT_ULAW;
 static int tos = 0;
 static int dtmfmode = H323_DTMF_RFC2833;
 static char secret[50];
+static unsigned int unique = 0;
 
 static call_options_t global_options;
 
@@ -122,7 +123,7 @@ struct oh323_pvt {
        call_details_t cd;                                      /* Call details */
        struct ast_channel *owner;                              /* Who owns us */
        struct sockaddr_in sa;                                  /* Our peer */
-        struct sockaddr_in redirip;                            /* Where our RTP should be going if not to us */
+       struct sockaddr_in redirip;                             /* Where our RTP should be going if not to us */
        int capability;                                         /* audio capability */
        int nonCodecCapability;                                 /* non-audio capability */
        int outgoing;                                           /* Outgoing or incoming call? */
@@ -217,11 +218,9 @@ static const struct ast_channel_tech oh323_tech = {
 #endif
 };
 
-static void oh323_update_info(struct ast_channel *c)
+/* Channel and private structures should be already locked */
+static void __oh323_update_info(struct ast_channel *c, struct oh323_pvt *pvt)
 {
-       struct oh323_pvt *pvt = c->tech_pvt;
-
-       ast_mutex_lock(&pvt->lock);
        if (c->nativeformats != pvt->nativeformats) {
                if (h323debug)
                        ast_log(LOG_DEBUG, "Preparing %s for new native format\n", c->name);
@@ -237,7 +236,18 @@ static void oh323_update_info(struct ast_channel *c)
                ast_queue_hangup(c);
                pvt->needhangup = 0;
        }
-       ast_mutex_unlock(&pvt->lock);
+}
+
+/* Only channel structure should be locked */
+static void oh323_update_info(struct ast_channel *c)
+{
+       struct oh323_pvt *pvt = c->tech_pvt;
+
+       if (pvt) {
+               ast_mutex_lock(&pvt->lock);
+               __oh323_update_info(c, pvt);
+               ast_mutex_unlock(&pvt->lock);
+       }
 }
 
 static void cleanup_call_details(call_details_t *cd) 
@@ -272,30 +282,30 @@ static void cleanup_call_details(call_details_t *cd)
         }
 }
 
-static void __oh323_destroy(struct oh323_pvt *p)
+static void __oh323_destroy(struct oh323_pvt *pvt)
 {
        struct oh323_pvt *cur, *prev = NULL;
        
-       if (p->rtp) {
-               ast_rtp_destroy(p->rtp);
+       if (pvt->rtp) {
+               ast_rtp_destroy(pvt->rtp);
        }
        
        /* Free dsp used for in-band DTMF detection */
-       if (p->vad) {
-               ast_dsp_free(p->vad);
+       if (pvt->vad) {
+               ast_dsp_free(pvt->vad);
        }
-       cleanup_call_details(&p->cd);
+       cleanup_call_details(&pvt->cd);
 
        /* Unlink us from the owner if we have one */
-       if (p->owner) {
-               ast_mutex_lock(&p->owner->lock);
-               ast_log(LOG_DEBUG, "Detaching from %s\n", p->owner->name);
-               p->owner->tech_pvt = NULL;
-               ast_mutex_unlock(&p->owner->lock);
+       if (pvt->owner) {
+               ast_mutex_lock(&pvt->owner->lock);
+               ast_log(LOG_DEBUG, "Detaching from %s\n", pvt->owner->name);
+               pvt->owner->tech_pvt = NULL;
+               ast_mutex_unlock(&pvt->owner->lock);
        }
        cur = iflist;
        while(cur) {
-               if (cur == p) {
+               if (cur == pvt) {
                        if (prev)
                                prev->next = cur->next;
                        else
@@ -308,15 +318,15 @@ static void __oh323_destroy(struct oh323_pvt *p)
        if (!cur) {
                ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur);
        } else {
-                ast_mutex_destroy(&p->lock);
-               free(p);
-        }
+               ast_mutex_destroy(&pvt->lock);
+               free(pvt);
+       }
 }
 
-static void oh323_destroy(struct oh323_pvt *p)
+static void oh323_destroy(struct oh323_pvt *pvt)
 {
        ast_mutex_lock(&iflock);
-       __oh323_destroy(p);
+       __oh323_destroy(pvt);
        ast_mutex_unlock(&iflock);
 }
 
@@ -583,27 +593,27 @@ static struct oh323_peer *build_peer(char *name, struct ast_variable *v)
  */
 static int oh323_digit(struct ast_channel *c, char digit)
 {
-       struct oh323_pvt *p = (struct oh323_pvt *) c->tech_pvt;
+       struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
        char *token;
        if (h323debug)
                ast_log(LOG_DEBUG, "Sending digit %c on %s\n", digit, c->name);
-       if (!p)
+       if (!pvt)
                return -1;
-       ast_mutex_lock(&p->lock);
-       if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833)) {
-               ast_rtp_senddigit(p->rtp, digit);
+       ast_mutex_lock(&pvt->lock);
+       if (pvt->rtp && (pvt->dtmfmode & H323_DTMF_RFC2833)) {
+               ast_rtp_senddigit(pvt->rtp, digit);
        }
        /* If in-band DTMF is desired, send that */
-       if ((p->dtmfmode & H323_DTMF_INBAND)) {
-               token = p->cd.call_token ? strdup(p->cd.call_token) : NULL;
-               ast_mutex_unlock(&p->lock);
+       if ((pvt->dtmfmode & H323_DTMF_INBAND)) {
+               token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
+               ast_mutex_unlock(&pvt->lock);
                h323_send_tone(token, digit);
                if (token)
                        free(token);
                oh323_update_info(c);
        }
        else
-               ast_mutex_unlock(&p->lock);
+               ast_mutex_unlock(&pvt->lock);
        return 0;
 }
 
@@ -614,32 +624,32 @@ static int oh323_digit(struct ast_channel *c, char digit)
  */
 static int oh323_call(struct ast_channel *c, char *dest, int timeout)
 {  
-        int res = 0;
-        struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
-        char addr[INET_ADDRSTRLEN];
-        char called_addr[1024];
-  
-       if (h323debug) {
-               ast_log(LOG_DEBUG, "Calling to %s on %s\n", dest, c->name);
-        }
+       int res = 0;
+       struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
+       char addr[INET_ADDRSTRLEN];
+       char called_addr[1024];
+
+       if (h323debug) {
+               ast_log(LOG_DEBUG, "Calling to %s on %s\n", dest, c->name);
+       }
        if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
-                ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name);
-                return -1;
-        }
-        if (usingGk) {
-                pvt->options.port = h323_signalling_port;
-                if (ast_strlen_zero(pvt->exten)) {
-                       strncpy(called_addr, dest, sizeof(called_addr));
-                } else {
-                        snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest);
-               }
-        } else {
-                ast_inet_ntoa(addr, sizeof(addr), pvt->sa.sin_addr);
-                pvt->options.port = htons(pvt->sa.sin_port);
-                if (ast_strlen_zero(pvt->exten)) {
-                        snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, pvt->options.port);
-                } else {
-                        snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, pvt->options.port);
+               ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name);
+               return -1;
+       }
+       ast_mutex_lock(&pvt->lock);
+       if (usingGk) {
+               if (ast_strlen_zero(pvt->exten)) {
+                       strncpy(called_addr, dest, sizeof(called_addr));
+               } else {
+                       snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest);
+               }
+       } else {
+               ast_inet_ntoa(addr, sizeof(addr), pvt->sa.sin_addr);
+               res = htons(pvt->sa.sin_port);
+               if (ast_strlen_zero(pvt->exten)) {
+                       snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, res);
+               } else {
+                       snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, res);
                }
        }
        /* make sure null terminated */
@@ -656,6 +666,7 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
        pvt->outgoing = 1;
 
        ast_log(LOG_DEBUG, "Placing outgoing call to %s, %d\n", called_addr, pvt->options.dtmfcodec);
+       ast_mutex_unlock(&pvt->lock);
        res = h323_make_call(called_addr, &(pvt->cd), &pvt->options);
        if (res) {
                ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name);
@@ -814,7 +825,7 @@ static struct ast_frame  *oh323_read(struct ast_channel *c)
        struct ast_frame *fr;
        struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
        ast_mutex_lock(&pvt->lock);
-       oh323_update_info(c);
+       __oh323_update_info(c, pvt);
        fr = oh323_rtp_read(pvt);
        ast_mutex_unlock(&pvt->lock);
        return fr;
@@ -882,7 +893,9 @@ static int oh323_indicate(struct ast_channel *c, int condition)
        case AST_CONTROL_BUSY:
                if (c->_state != AST_STATE_UP) {
                        h323_answering_call(token, 1);
-                       pvt->alreadygone = 1;
+                       ast_mutex_lock(&pvt->lock);
+                       pvt->alreadygone = 1;
+                       ast_mutex_unlock(&pvt->lock);
                        ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);                   
                        break;
                }
@@ -892,7 +905,9 @@ static int oh323_indicate(struct ast_channel *c, int condition)
        case AST_CONTROL_CONGESTION:
                if (c->_state != AST_STATE_UP) {
                        h323_answering_call(token, 1);
+                       ast_mutex_lock(&pvt->lock);
                        pvt->alreadygone = 1;
+                       ast_mutex_unlock(&pvt->lock);
                        ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
                        break;
                }
@@ -934,7 +949,8 @@ static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
        return 0;
 }
 
-static struct ast_channel *oh323_new(struct oh323_pvt *pvt, int state, const char *host)
+/* Private structure should be locked on a call */
+static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const char *host)
 {
        struct ast_channel *ch;
        int fmt;
@@ -1058,45 +1074,47 @@ static struct oh323_pvt *oh323_alloc(int callid)
        return pvt;
 }
 
-static struct oh323_pvt *find_call(int call_reference, const char *token)
+static struct oh323_pvt *find_call_locked(int call_reference, const char *token)
 {  
-        struct oh323_pvt *pvt;
+       struct oh323_pvt *pvt;
 
        ast_mutex_lock(&iflock);
-        pvt = iflist; 
-        while(pvt) {
-                if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
-                        /* Found the call */             
-                        if ((token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
-                               ast_mutex_unlock(&iflock);
-                               return pvt;
-                        } else if (token == NULL) {
-                                ast_log(LOG_DEBUG, "Call Token is NULL\n");
-                                ast_mutex_unlock(&iflock);
-                                return pvt;
-                        }
-                }
-                pvt = pvt->next; 
-        }
-        ast_mutex_unlock(&iflock);
+       pvt = iflist; 
+       while(pvt) {
+               if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
+                       /* Found the call */             
+                       if ((token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
+                               ast_mutex_lock(&pvt->lock);
+                               ast_mutex_unlock(&iflock);
+                               return pvt;
+                       } else if (token == NULL) {
+                               ast_log(LOG_WARNING, "Call Token is NULL\n");
+                               ast_mutex_lock(&pvt->lock);
+                               ast_mutex_unlock(&iflock);
+                               return pvt;
+                       }
+               }
+               pvt = pvt->next; 
+       }
+       ast_mutex_unlock(&iflock);
        return NULL;
 }
 
-struct oh323_user *find_user(const call_details_t cd)
+struct oh323_user *find_user(const call_details_t *cd)
 {
        struct oh323_user *u;
        char iabuf[INET_ADDRSTRLEN];
        u = userl.users;
        if (userbyalias) {
                while(u) {
-                       if (!strcasecmp(u->name, cd.call_source_aliases)) {
+                       if (!strcasecmp(u->name, cd->call_source_aliases)) {
                                break;
                        }
                        u = u->next;
                }
        } else {
                while(u) {
-                       if (!strcasecmp(cd.sourceIp, ast_inet_ntoa(iabuf, sizeof(iabuf), u->addr.sin_addr))) {
+                       if (!strcasecmp(cd->sourceIp, ast_inet_ntoa(iabuf, sizeof(iabuf), u->addr.sin_addr))) {
                                break;
                        }
                        u = u->next;
@@ -1212,7 +1230,7 @@ static struct ast_channel *oh323_request(const char *type, int format, void *dat
        char *dest = (char *)data;
        char *ext, *host;
        char *h323id = NULL;
-       char tmp[256];
+       char tmp[256], tmp1[256];
        
        ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
        pvt = oh323_alloc(0);
@@ -1256,10 +1274,13 @@ static struct ast_channel *oh323_request(const char *type, int format, void *dat
        /* pass on our capabilites to the H.323 stack */
        ast_mutex_lock(&caplock);
        h323_set_capability(pvt->capability, pvt->dtmfmode);
+       /* Generate unique channel identifier */
+       snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
+       tmp1[sizeof(tmp1)-1] = '\0';
        ast_mutex_unlock(&caplock);
-       
+
        ast_mutex_lock(&pvt->lock);
-       tmpc = oh323_new(pvt, AST_STATE_DOWN, host);
+       tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1);
        ast_mutex_unlock(&pvt->lock);
        if (!tmpc) {
                oh323_destroy(pvt);
@@ -1292,9 +1313,10 @@ int send_digit(unsigned call_reference, char digit, const char *token)
 {
        struct oh323_pvt *pvt;
        struct ast_frame f;
+       int res;
 
-       ast_log(LOG_DEBUG, "Recieved Digit: %c\n", digit);
-       pvt = find_call(call_reference, token); 
+       ast_log(LOG_DEBUG, "Received Digit: %c\n", digit);
+       pvt = find_call_locked(call_reference, token); 
        if (!pvt) {
                ast_log(LOG_ERROR, "Private structure not found in send_digit.\n");
                return -1;
@@ -1305,10 +1327,12 @@ int send_digit(unsigned call_reference, char digit, const char *token)
        f.datalen = 0;
        f.samples = 800;
        f.offset = 0;
-       f.data = NULL;
-       f.mallocd = 0;
-       f.src = "SEND_DIGIT";   
-       return ast_queue_frame(pvt->owner, &f); 
+       f.data = NULL;
+       f.mallocd = 0;
+       f.src = "SEND_DIGIT";   
+       res = ast_queue_frame(pvt->owner, &f);
+       ast_mutex_unlock(&pvt->lock);
+       return res;
 }
 
 /**
@@ -1327,20 +1351,20 @@ struct rtp_info *external_rtp_create(unsigned call_reference, const char * token
                ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
                return NULL;
        }
-       pvt = find_call(call_reference, token); 
+       pvt = find_call_locked(call_reference, token); 
        if (!pvt) {
                free(info);
                ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
                return NULL;
        }
-       ast_mutex_lock(&pvt->lock);
        /* figure out our local RTP port and tell the H.323 stack about it */
        ast_rtp_get_us(pvt->rtp, &us);
        ast_mutex_unlock(&pvt->lock);
        /* evil hack, until I (or someone?) figures out a better way */
        ast_inet_ntoa(info->addr, sizeof(info->addr), bindaddr.sin_addr);
        info->port = ntohs(us.sin_port);
-       ast_log(LOG_DEBUG, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
+       if (h323debug)
+               ast_log(LOG_DEBUG, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
        return info;
 }
 
@@ -1361,19 +1385,19 @@ struct rtpPayloadType {
   */
 void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
 {
-       struct oh323_pvt *pvt = NULL;
+       struct oh323_pvt *pvt;
        struct sockaddr_in them;
        struct rtpPayloadType rtptype;
 
        if (h323debug)
                ast_log(LOG_DEBUG, "Setting up RTP connection for %s\n", token);
+
        /* Find the call or allocate a private structure if call not found */
-       pvt = find_call(call_reference, token); 
+       pvt = find_call_locked(call_reference, token); 
        if (!pvt) {
                ast_log(LOG_ERROR, "Something is wrong: rtp\n");
                return;
        }
-       ast_mutex_lock(&pvt->lock);
        if (pvt->alreadygone) {
                ast_mutex_unlock(&pvt->lock);
                return;
@@ -1386,6 +1410,8 @@ void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int rem
                ast_set_write_format(pvt->owner, pvt->owner->writeformat);
                ast_mutex_unlock(&pvt->owner->lock);
        }
+       else if (h323debug)
+               ast_log(LOG_DEBUG, "RTP connection preparation for %s is pending...\n", token);
 
        them.sin_family = AF_INET;
        /* only works for IPv4 */
@@ -1412,19 +1438,17 @@ void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int rem
 void connection_made(unsigned call_reference, const char *token)
 {
        struct ast_channel *c = NULL;
-       struct oh323_pvt *pvt = NULL;
+       struct oh323_pvt *pvt;
 
        if (h323debug)
                ast_log(LOG_DEBUG, "Call %s answered\n", token);
-       
-       pvt = find_call(call_reference, token); 
-       
+
+       pvt = find_call_locked(call_reference, token); 
        if (!pvt) {
                ast_log(LOG_ERROR, "Something is wrong: connection\n");
                return;
        }
 
-       ast_mutex_lock(&pvt->lock);
        /* Inform asterisk about remote party connected only on outgoing calls */
        if (!pvt->outgoing) {
                ast_mutex_unlock(&pvt->lock);
@@ -1446,25 +1470,24 @@ void connection_made(unsigned call_reference, const char *token)
 
 int progress(unsigned call_reference, const char *token, int inband)
 {
-       struct oh323_pvt *p;
+       struct oh323_pvt *pvt;
 
        ast_log(LOG_DEBUG, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
-       p = find_call(call_reference, token);
 
-       if (!p) {
+       pvt = find_call_locked(call_reference, token);
+       if (!pvt) {
                ast_log(LOG_ERROR, "Private structure not found in progress.\n");
                return -1;
        }
-       ast_mutex_lock(&p->lock);
-       if (!p->owner) {
-               ast_mutex_unlock(&p->lock);
+       if (!pvt->owner) {
+               ast_mutex_unlock(&pvt->lock);
                ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
                return -1;
        }
-       ast_mutex_lock(&p->owner->lock);
-       ast_queue_control(p->owner, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
-       ast_mutex_unlock(&p->owner->lock);
-       ast_mutex_unlock(&p->lock);
+       ast_mutex_lock(&pvt->owner->lock);
+       ast_queue_control(pvt->owner, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
+       ast_mutex_unlock(&pvt->owner->lock);
+       ast_mutex_unlock(&pvt->lock);
 
        return 0;
 }
@@ -1476,10 +1499,9 @@ int progress(unsigned call_reference, const char *token, int inband)
  */
 call_options_t *setup_incoming_call(call_details_t cd)
 {
-       struct oh323_pvt *pvt = NULL;
+       struct oh323_pvt *pvt;
        struct oh323_user *user = NULL;
        struct oh323_alias *alias = NULL;
-       call_options_t *call_options;
        char iabuf[INET_ADDRSTRLEN];
 
        if (h323debug)
@@ -1500,7 +1522,6 @@ call_options_t *setup_incoming_call(call_details_t cd)
        pvt->cd.call_source_name = strdup(cd.call_source_name);
        pvt->cd.call_source_e164 = strdup(cd.call_source_e164);
        pvt->cd.call_dest_e164 = strdup(cd.call_dest_e164);
-       call_options = &pvt->options;
 
        if (h323debug) {
                ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");
@@ -1512,7 +1533,7 @@ call_options_t *setup_incoming_call(call_details_t cd)
        }
 
        /* Decide if we are allowing Gatekeeper routed calls*/
-       if ((!strcasecmp(cd.sourceIp, gatekeeper)) && (gkroute == -1) && (usingGk)) {           
+       if ((!strcasecmp(cd.sourceIp, gatekeeper)) && (gkroute == -1) && (usingGk)) {
                if (!ast_strlen_zero(cd.call_dest_e164)) {
                        strncpy(pvt->exten, cd.call_dest_e164, sizeof(pvt->exten) - 1);
                        strncpy(pvt->context, default_context, sizeof(pvt->context) - 1); 
@@ -1525,10 +1546,10 @@ call_options_t *setup_incoming_call(call_details_t cd)
                        strncpy(pvt->exten, alias->name, sizeof(pvt->exten) - 1);
                        strncpy(pvt->context, alias->context, sizeof(pvt->context) - 1);
                }
-       } else { 
+       } else {
                /* Either this call is not from the Gatekeeper 
                   or we are not allowing gk routed calls */
-               user  = find_user(cd);
+               user  = find_user(&cd);
                if (!user) {
                        if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
                                strncpy(pvt->exten, cd.call_dest_e164, sizeof(pvt->exten) - 1);
@@ -1544,9 +1565,9 @@ call_options_t *setup_incoming_call(call_details_t cd)
                        memset(&pvt->options, 0, sizeof(pvt->options));
                } else {                                        
                        if (user->host) {
-                               if (strcasecmp(cd.sourceIp, ast_inet_ntoa(iabuf, sizeof(iabuf), user->addr.sin_addr))){                                 
+                               if (strcasecmp(cd.sourceIp, ast_inet_ntoa(iabuf, sizeof(iabuf), user->addr.sin_addr))) {
                                        if (ast_strlen_zero(user->context)) {
-                                               if (ast_strlen_zero(default_context)) {                                 
+                                               if (ast_strlen_zero(default_context)) {
                                                        ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd.sourceIp);
                                                        return NULL;
                                                }
@@ -1563,6 +1584,7 @@ call_options_t *setup_incoming_call(call_details_t cd)
                        strncpy(pvt->context, user->context, sizeof(pvt->context) - 1);
                        pvt->bridge = user->bridge;
                        pvt->nat = user->nat;
+                       memcpy(&pvt->options, &user->options, sizeof(pvt->options));
                        if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
                                strncpy(pvt->exten, cd.call_dest_e164, sizeof(pvt->exten) - 1);
                        } else {
@@ -1574,10 +1596,9 @@ call_options_t *setup_incoming_call(call_details_t cd)
                        if (user->amaflags) {
                                pvt->amaflags = user->amaflags;
                        } 
-                       call_options = &user->options;
                } 
        }
-       return call_options;
+       return &pvt->options;
 }
 
 /**
@@ -1587,23 +1608,20 @@ call_options_t *setup_incoming_call(call_details_t cd)
  */
 static int answer_call(unsigned call_reference, const char *token)
 {
-       struct oh323_pvt *pvt = NULL;
+       struct oh323_pvt *pvt;
        struct ast_channel *c = NULL;
 
        if (h323debug)
                ast_log(LOG_DEBUG, "Preparing Asterisk to answer for %s\n", token);
 
        /* Find the call or allocate a private structure if call not found */
-       pvt = find_call(call_reference, token); 
+       pvt = find_call_locked(call_reference, token); 
        if (!pvt) {
                ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
                return 0;
        }
-       /* Briefly lock call for oh323_new() */
-       ast_mutex_lock(&pvt->lock);
-
        /* allocate a channel and tell asterisk about it */
-       c = oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token);
+       c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token);
 
        /* And release when done */
        ast_mutex_unlock(&pvt->lock);
@@ -1631,16 +1649,15 @@ int setup_outgoing_call(call_details_t cd)
 void chan_ringing(unsigned call_reference, const char *token)
 {
         struct ast_channel *c = NULL;
-        struct oh323_pvt *pvt = NULL;
+        struct oh323_pvt *pvt;
 
        if (h323debug)
                ast_log(LOG_DEBUG, "Ringing on %s\n", token);
 
-        pvt = find_call(call_reference, token); 
+        pvt = find_call_locked(call_reference, token); 
         if (!pvt) {
                 ast_log(LOG_ERROR, "Something is wrong: ringing\n");
        }
-       ast_mutex_lock(&pvt->lock);
         if (!pvt->owner) {
                ast_mutex_unlock(&pvt->lock);
                 ast_log(LOG_ERROR, "Channel has no owner\n");
@@ -1661,17 +1678,18 @@ void chan_ringing(unsigned call_reference, const char *token)
   */
 static void cleanup_connection(call_details_t cd)
 {      
-       struct oh323_pvt *pvt = NULL;
+       struct oh323_pvt *pvt;
        struct ast_rtp *rtp = NULL;
 
        ast_log(LOG_DEBUG, "Cleaning connection to %s\n", cd.call_token);
        
        while (1) {
-               pvt = find_call(cd.call_reference, cd.call_token); 
+               pvt = find_call_locked(cd.call_reference, cd.call_token); 
                if (!pvt) {
+                       if (h323debug)
+                               ast_log(LOG_DEBUG, "No connection for %s\n", cd.call_token);
                        return;
                }
-               ast_mutex_lock(&pvt->lock);
                if (!pvt->owner || !ast_mutex_trylock(&pvt->owner->lock))
                        break;
 #if 1
@@ -1704,20 +1722,21 @@ static void cleanup_connection(call_details_t cd)
                ast_mutex_unlock(&pvt->owner->lock);
        }
        ast_mutex_unlock(&pvt->lock);
+       if (h323debug)
+               ast_log(LOG_DEBUG, "Connection to %s cleaned\n", cd.call_token);
        return; 
 }
 
 static void hangup_connection(unsigned int call_reference, const char *token, int cause)
 {
-       struct oh323_pvt *pvt = NULL;
+       struct oh323_pvt *pvt;
 
        ast_log(LOG_DEBUG, "Hanging up connection to %s with cause %d\n", token, cause);
        
-       pvt = find_call(call_reference, token); 
+       pvt = find_call_locked(call_reference, token); 
        if (!pvt) {
                return;
        }
-       ast_mutex_lock(&pvt->lock);
        if (pvt->owner && !ast_mutex_trylock(&pvt->owner->lock)) {
                pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                pvt->owner->hangupcause = pvt->hangupcause = cause;
@@ -1734,16 +1753,15 @@ static void hangup_connection(unsigned int call_reference, const char *token, in
 
 void set_dtmf_payload(unsigned call_reference, const char *token, int payload)
 {
-       struct oh323_pvt *pvt = NULL;
+       struct oh323_pvt *pvt;
 
        if (h323debug)
                ast_log(LOG_DEBUG, "Setting DTMF payload to %d on %s\n", payload, token);
 
-       pvt = find_call(call_reference, token);
+       pvt = find_call_locked(call_reference, token);
        if (!pvt) {
                return;
        }
-       ast_mutex_lock(&pvt->lock);
        if (pvt->rtp) {
                ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", "telephone-event");
        }
@@ -1876,7 +1894,6 @@ static int h323_no_debug(int fd, int argc, char *argv[])
 
 static int h323_gk_cycle(int fd, int argc, char *argv[])
 {
-       return RESULT_SUCCESS;
 #if 0
        if (argc != 3) {
                return RESULT_SHOWUSAGE;
@@ -1889,8 +1906,8 @@ static int h323_gk_cycle(int fd, int argc, char *argv[])
                        ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
                }
        }
-       return RESULT_SUCCESS;
 #endif
+       return RESULT_SUCCESS;
 }
 
 static int h323_ep_hangup(int fd, int argc, char *argv[])
@@ -2250,10 +2267,10 @@ static struct ast_cli_entry  cli_h323_reload =
 
 static struct ast_rtp *oh323_get_rtp_peer(struct ast_channel *chan)
 {
-       struct oh323_pvt *p;
-       p = (struct oh323_pvt *) chan->tech_pvt;
-       if (p && p->rtp && p->bridge) {
-               return p->rtp;
+       struct oh323_pvt *pvt;
+       pvt = (struct oh323_pvt *) chan->tech_pvt;
+       if (pvt && pvt->rtp && pvt->bridge) {
+               return pvt->rtp;
        }
        return NULL;
 }
@@ -2291,7 +2308,7 @@ static char *convertcap(int cap)
 static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs)
 {
        /* XXX Deal with Video */
-       struct oh323_pvt *p;
+       struct oh323_pvt *pvt;
        struct sockaddr_in them;
        struct sockaddr_in us;
        char *mode;
@@ -2302,14 +2319,14 @@ static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, str
        }
 
        mode = convertcap(chan->writeformat); 
-       p = (struct oh323_pvt *) chan->tech_pvt;
-       if (!p) {
+       pvt = (struct oh323_pvt *) chan->tech_pvt;
+       if (!pvt) {
                ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
                return -1;
        }
        ast_rtp_get_peer(rtp, &them);   
        ast_rtp_get_us(rtp, &us);
-       h323_native_bridge(p->cd.call_token, ast_inet_ntoa(iabuf, sizeof(iabuf), them.sin_addr), mode);
+       h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(iabuf, sizeof(iabuf), them.sin_addr), mode);
        return 0;
 }
 
@@ -2323,9 +2340,9 @@ static struct ast_rtp_protocol oh323_rtp = {
 int load_module()
 {
        int res;
-        ast_mutex_init(&userl.lock);
-        ast_mutex_init(&peerl.lock);
-        ast_mutex_init(&aliasl.lock);
+       ast_mutex_init(&userl.lock);
+       ast_mutex_init(&peerl.lock);
+       ast_mutex_init(&aliasl.lock);
        sched = sched_context_create();
        if (!sched) {
                ast_log(LOG_WARNING, "Unable to create schedule context\n");
@@ -2358,17 +2375,17 @@ int load_module()
 
                /* Register our callback functions */
                h323_callback_register(setup_incoming_call, 
-                                      setup_outgoing_call,                                                      
-                                      external_rtp_create, 
-                                      setup_rtp_connection, 
-                                      cleanup_connection, 
-                                      chan_ringing,
-                                      connection_made, 
-                                      send_digit,
-                                      answer_call,
-                                      progress,
-                                      set_dtmf_payload,
-                                      hangup_connection);
+                                               setup_outgoing_call,                                                     
+                                               external_rtp_create, 
+                                               setup_rtp_connection, 
+                                               cleanup_connection, 
+                                               chan_ringing,
+                                               connection_made, 
+                                               send_digit,
+                                               answer_call,
+                                               progress,
+                                               set_dtmf_payload,
+                                               hangup_connection);
                /* start the h.323 listener */
                if (h323_start_listener(h323_signalling_port, bindaddr)) {
                        ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
@@ -2392,15 +2409,15 @@ int unload_module()
        struct oh323_pvt *p, *pl;
 
        /* unregister commands */
-        ast_cli_unregister(&cli_debug);
-        ast_cli_unregister(&cli_no_debug);
-        ast_cli_unregister(&cli_trace);
-        ast_cli_unregister(&cli_no_trace);   
-        ast_cli_unregister(&cli_show_codecs);
-        ast_cli_unregister(&cli_gk_cycle);
-        ast_cli_unregister(&cli_hangup_call);
-        ast_cli_unregister(&cli_show_tokens);
-        ast_cli_unregister(&cli_h323_reload);
+       ast_cli_unregister(&cli_debug);
+       ast_cli_unregister(&cli_no_debug);
+       ast_cli_unregister(&cli_trace);
+       ast_cli_unregister(&cli_no_trace);   
+       ast_cli_unregister(&cli_show_codecs);
+       ast_cli_unregister(&cli_gk_cycle);
+       ast_cli_unregister(&cli_hangup_call);
+       ast_cli_unregister(&cli_show_tokens);
+       ast_cli_unregister(&cli_h323_reload);
        ast_rtp_proto_unregister(&oh323_rtp);
        ast_channel_unregister(&oh323_tech);
                
@@ -2420,18 +2437,18 @@ int unload_module()
                return -1;
        }
        if (!ast_mutex_lock(&monlock)) {
-                if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
-                        /* this causes a seg, anyone know why? */
+               if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
+                       /* this causes a seg, anyone know why? */
                        pthread_cancel(monitor_thread);
-                        pthread_kill(monitor_thread, SIGURG);
-                        pthread_join(monitor_thread, NULL);
-                 }
-                monitor_thread = AST_PTHREADT_STOP;
-                ast_mutex_unlock(&monlock);
-        } else {
-                ast_log(LOG_WARNING, "Unable to lock the monitor\n");
-                return -1;
-        }
+                       pthread_kill(monitor_thread, SIGURG);
+                       pthread_join(monitor_thread, NULL);
+               }
+               monitor_thread = AST_PTHREADT_STOP;
+               ast_mutex_unlock(&monlock);
+       } else {
+               ast_log(LOG_WARNING, "Unable to lock the monitor\n");
+               return -1;
+       }
        if (!ast_mutex_lock(&iflock)) {
                /* destroy all the interfaces and free their memory */
                p = iflist;