Add a massive set of changes for converting to use the ast_debug() macro.
[asterisk/asterisk.git] / channels / chan_h323.c
index 607de74..85c912b 100644 (file)
  *
  * \par See also
  * \arg Config_h323
+ * \extref OpenH323 http://www.voxgratia.org/
  *
  * \ingroup channel_drivers
  */
 
 /*** MODULEINFO
        <depend>openh323</depend>
-       <defaultenabled>no</defaultenabled>
+       <defaultenabled>yes</defaultenabled>
  ***/
 
 #ifdef __cplusplus
@@ -117,11 +118,11 @@ rfc2833_cb on_set_rfc2833_payload;
 hangup_cb on_hangup;
 setcapabilities_cb on_setcapabilities;
 setpeercapabilities_cb on_setpeercapabilities;
+onhold_cb on_hold;
 
-/* global debug flag */
-int h323debug;
+int h323debug; /*!< global debug flag */
 
-/*! Global jitterbuffer configuration - by default, jb is disabled */
+/*! \brief Global jitterbuffer configuration - by default, jb is disabled */
 static struct ast_jb_conf default_jbconf =
 {
        .flags = 0,
@@ -148,84 +149,88 @@ static int gkroute = 0;
 /* Find user by alias (h.323 id) is default, alternative is the incomming call's source IP address*/
 static int userbyalias = 1;
 static int acceptAnonymous = 1;
-static int tos = 0;
+static unsigned int tos = 0;
+static unsigned int cos = 0;
 static char secret[50];
 static unsigned int unique = 0;
 
 static call_options_t global_options;
 
-/** Private structure of a OpenH323 channel */
+/*! \brief Private structure of a OpenH323 channel */
 struct oh323_pvt {
-       ast_mutex_t lock;                                       /* Channel private lock */
-       call_options_t options;                         /* Options to be used during call setup */
-       int alreadygone;                                        /* Whether or not we've already been destroyed by our peer */
-       int needdestroy;                                        /* if we need to be destroyed */
-       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 */
-       int nonCodecCapability;                         /* non-audio capability */
-       int outgoing;                                           /* Outgoing or incoming call? */
-       char exten[AST_MAX_EXTENSION];          /* Requested extension */
-       char context[AST_MAX_CONTEXT];          /* Context where to start */
-       char accountcode[256];                          /* Account code */
-       char rdnis[80];                                         /* Referring DNIS, if available */
-       int amaflags;                                           /* AMA Flags */
-       struct ast_rtp *rtp;                            /* RTP Session */
-       struct ast_dsp *vad;                            /* Used for in-band DTMF detection */
-       int nativeformats;                                      /* Codec formats supported by a channel */
-       int needhangup;                                         /* Send hangup when Asterisk is ready */
-       int hangupcause;                                        /* Hangup cause from OpenH323 layer */
-       int newstate;                                           /* Pending state change */
-       int newcontrol;                                         /* Pending control to send */
-       int newdigit;                                           /* Pending DTMF digit to send */
-       int newduration;                                        /* Pending DTMF digit duration to send */
-       int pref_codec;                                         /* Preferred codec */
-       int peercapability;                                     /* Capabilities learned from peer */
-       int jointcapability;                            /* Common capabilities for local and remote side */
-       struct ast_codec_pref peer_prefs;       /* Preferenced list of codecs which remote side supports */
-       int dtmf_pt[2];                                         /* Payload code used for RFC2833/CISCO messages */
-       int curDTMF;                                            /* DTMF tone being generated to Asterisk side */
-       int DTMFsched;                                          /* Scheduler descriptor for DTMF */
-       int update_rtp_info;                            /* Configuration of fd's array is pending */
-       int recvonly;                                           /* Peer isn't wish to receive our voice stream */
-       int txDtmfDigit;                                        /* DTMF digit being to send to H.323 side */
-       int noInbandDtmf;                                       /* Inband DTMF processing by DSP isn't available */
-       int connection_established;                     /* Call got CONNECT message */
-       struct oh323_pvt *next;                         /* Next channel in list */
+       ast_mutex_t lock;                       /*!< Channel private lock */
+       call_options_t options;                 /*!<!< Options to be used during call setup */
+       int alreadygone;                        /*!< Whether or not we've already been destroyed by our peer */
+       int needdestroy;                        /*!< if we need to be destroyed */
+       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 */
+       int nonCodecCapability;                 /*!< non-audio capability */
+       int outgoing;                           /*!< Outgoing or incoming call? */
+       char exten[AST_MAX_EXTENSION];          /*!< Requested extension */
+       char context[AST_MAX_CONTEXT];          /*!< Context where to start */
+       char accountcode[256];                  /*!< Account code */
+       char rdnis[80];                         /*!< Referring DNIS, if available */
+       int amaflags;                           /*!< AMA Flags */
+       struct ast_rtp *rtp;                    /*!< RTP Session */
+       struct ast_dsp *vad;                    /*!< Used for in-band DTMF detection */
+       int nativeformats;                      /*!< Codec formats supported by a channel */
+       int needhangup;                         /*!< Send hangup when Asterisk is ready */
+       int hangupcause;                        /*!< Hangup cause from OpenH323 layer */
+       int newstate;                           /*!< Pending state change */
+       int newcontrol;                         /*!< Pending control to send */
+       int newdigit;                           /*!< Pending DTMF digit to send */
+       int newduration;                        /*!< Pending DTMF digit duration to send */
+       int pref_codec;                         /*!< Preferred codec */
+       int peercapability;                     /*!< Capabilities learned from peer */
+       int jointcapability;                    /*!< Common capabilities for local and remote side */
+       struct ast_codec_pref peer_prefs;       /*!< Preferenced list of codecs which remote side supports */
+       int dtmf_pt[2];                         /*!< Payload code used for RFC2833/CISCO messages */
+       int curDTMF;                            /*!< DTMF tone being generated to Asterisk side */
+       int DTMFsched;                          /*!< Scheduler descriptor for DTMF */
+       int update_rtp_info;                    /*!< Configuration of fd's array is pending */
+       int recvonly;                           /*!< Peer isn't wish to receive our voice stream */
+       int txDtmfDigit;                        /*!< DTMF digit being to send to H.323 side */
+       int noInbandDtmf;                       /*!< Inband DTMF processing by DSP isn't available */
+       int connection_established;             /*!< Call got CONNECT message */
+       int got_progress;                       /*!< Call got PROGRESS message, pass inband audio */
+       struct oh323_pvt *next;                 /*!< Next channel in list */
 } *iflist = NULL;
 
-static struct ast_user_list {
+/*! \brief H323 User list */
+static struct h323_user_list {
        ASTOBJ_CONTAINER_COMPONENTS(struct oh323_user);
 } userl;
 
-static struct ast_peer_list {
+/*! \brief H323 peer list */
+static struct h323_peer_list {
        ASTOBJ_CONTAINER_COMPONENTS(struct oh323_peer);
 } peerl;
 
-static struct ast_alias_list {
+/*! \brief H323 alias list */
+static struct h323_alias_list {
        ASTOBJ_CONTAINER_COMPONENTS(struct oh323_alias);
 } aliasl;
 
-/** Asterisk RTP stuff */
+/* Asterisk RTP stuff */
 static struct sched_context *sched;
 static struct io_context *io;
 
-/** Protect the interface list (oh323_pvt) */
-AST_MUTEX_DEFINE_STATIC(iflock);
+AST_MUTEX_DEFINE_STATIC(iflock);       /*!< Protect the interface list (oh323_pvt) */
 
-/* Protect the monitoring thread, so only one process can kill or start it, and not
+/*! \brief  Protect the H.323 monitoring thread, so only one process can kill or start it, and not
    when it's doing something critical. */
 AST_MUTEX_DEFINE_STATIC(monlock);
 
-/* Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. */
+/*! \brief Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. */
 AST_MUTEX_DEFINE_STATIC(caplock);
 
-/* Protect the reload process */
+/*! \brief Protect the reload process */
 AST_MUTEX_DEFINE_STATIC(h323_reload_lock);
 static int h323_reloading = 0;
 
-/* This is the thread for the monitor which checks for input on the channels
+/*! \brief This is the thread for the monitor which checks for input on the channels
    which are not currently in use. */
 static pthread_t monitor_thread = AST_PTHREADT_NULL;
 static int restart_monitor(void);
@@ -233,7 +238,7 @@ static int h323_do_reload(void);
 
 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause);
 static int oh323_digit_begin(struct ast_channel *c, char digit);
-static int oh323_digit_end(struct ast_channel *c, char digit);
+static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration);
 static int oh323_call(struct ast_channel *c, char *dest, int timeout);
 static int oh323_hangup(struct ast_channel *c);
 static int oh323_answer(struct ast_channel *c);
@@ -282,24 +287,24 @@ static const char* redirectingreason2str(int redirectingreason)
 static void oh323_destroy_alias(struct oh323_alias *alias)
 {
        if (h323debug)
-               ast_log(LOG_DEBUG, "Destroying alias '%s'\n", alias->name);
-       free(alias);
+               ast_debug(1, "Destroying alias '%s'\n", alias->name);
+       ast_free(alias);
 }
 
 static void oh323_destroy_user(struct oh323_user *user)
 {
        if (h323debug)
-               ast_log(LOG_DEBUG, "Destroying user '%s'\n", user->name);
+               ast_debug(1, "Destroying user '%s'\n", user->name);
        ast_free_ha(user->ha);
-       free(user);
+       ast_free(user);
 }
 
 static void oh323_destroy_peer(struct oh323_peer *peer)
 {
        if (h323debug)
-               ast_log(LOG_DEBUG, "Destroying peer '%s'\n", peer->name);
+               ast_debug(1, "Destroying peer '%s'\n", peer->name);
        ast_free_ha(peer->ha);
-       free(peer);
+       ast_free(peer);
 }
 
 static int oh323_simulate_dtmf_end(void *data)
@@ -333,19 +338,19 @@ static int oh323_simulate_dtmf_end(void *data)
        return 0;
 }
 
-/* Channel and private structures should be already locked */
+/*! \brief Channel and private structures should be already locked */
 static void __oh323_update_info(struct ast_channel *c, struct oh323_pvt *pvt)
 {
        if (c->nativeformats != pvt->nativeformats) {
                if (h323debug)
-                       ast_log(LOG_DEBUG, "Preparing %s for new native format\n", c->name);
+                       ast_debug(1, "Preparing %s for new native format\n", c->name);
                c->nativeformats = pvt->nativeformats;
                ast_set_read_format(c, c->readformat);
                ast_set_write_format(c, c->writeformat);
        }
        if (pvt->needhangup) {
                if (h323debug)
-                       ast_log(LOG_DEBUG, "Process pending hangup for %s\n", c->name);
+                       ast_debug(1, "Process pending hangup for %s\n", c->name);
                c->_softhangup |= AST_SOFTHANGUP_DEV;
                c->hangupcause = pvt->hangupcause;
                ast_queue_hangup(c);
@@ -365,6 +370,7 @@ static void __oh323_update_info(struct ast_channel *c, struct oh323_pvt *pvt)
                        .frametype = AST_FRAME_DTMF_END,
                        .subclass = pvt->newdigit,
                        .samples = pvt->newduration * 8,
+                       .len = pvt->newduration,
                        .src = "UPDATE_INFO",
                };
                if (pvt->newdigit == ' ') {             /* signalUpdate message */
@@ -398,7 +404,7 @@ static void __oh323_update_info(struct ast_channel *c, struct oh323_pvt *pvt)
        }
 }
 
-/* Only channel structure should be locked */
+/*! \brief Only channel structure should be locked */
 static void oh323_update_info(struct ast_channel *c)
 {
        struct oh323_pvt *pvt = c->tech_pvt;
@@ -413,35 +419,35 @@ static void oh323_update_info(struct ast_channel *c)
 static void cleanup_call_details(call_details_t *cd)
 {
        if (cd->call_token) {
-               free(cd->call_token);
+               ast_free(cd->call_token);
                cd->call_token = NULL;
        }
        if (cd->call_source_aliases) {
-               free(cd->call_source_aliases);
+               ast_free(cd->call_source_aliases);
                cd->call_source_aliases = NULL;
        }
        if (cd->call_dest_alias) {
-               free(cd->call_dest_alias);
+               ast_free(cd->call_dest_alias);
                cd->call_dest_alias = NULL;
        }
        if (cd->call_source_name) {
-               free(cd->call_source_name);
+               ast_free(cd->call_source_name);
                cd->call_source_name = NULL;
        }
        if (cd->call_source_e164) {
-               free(cd->call_source_e164);
+               ast_free(cd->call_source_e164);
                cd->call_source_e164 = NULL;
        }
        if (cd->call_dest_e164) {
-               free(cd->call_dest_e164);
+               ast_free(cd->call_dest_e164);
                cd->call_dest_e164 = NULL;
        }
        if (cd->sourceIp) {
-               free(cd->sourceIp);
+               ast_free(cd->sourceIp);
                cd->sourceIp = NULL;
        }
        if (cd->redirect_number) {
-               free(cd->redirect_number);
+               ast_free(cd->redirect_number);
                cd->redirect_number = NULL;
        }
 }
@@ -469,7 +475,7 @@ static void __oh323_destroy(struct oh323_pvt *pvt)
        if (pvt->owner) {
                ast_channel_lock(pvt->owner);
                if (h323debug)
-                       ast_log(LOG_DEBUG, "Detaching from %s\n", pvt->owner->name);
+                       ast_debug(1, "Detaching from %s\n", pvt->owner->name);
                pvt->owner->tech_pvt = NULL;
                ast_channel_unlock(pvt->owner);
        }
@@ -490,14 +496,14 @@ static void __oh323_destroy(struct oh323_pvt *pvt)
        } else {
                ast_mutex_unlock(&pvt->lock);
                ast_mutex_destroy(&pvt->lock);
-               free(pvt);
+               ast_free(pvt);
        }
 }
 
 static void oh323_destroy(struct oh323_pvt *pvt)
 {
        if (h323debug) {
-               ast_log(LOG_DEBUG, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>"));
+               ast_debug(1, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>"));
        }
        ast_mutex_lock(&iflock);
        ast_mutex_lock(&pvt->lock);
@@ -534,7 +540,7 @@ static int oh323_digit_begin(struct ast_channel *c, char digit)
                ast_mutex_unlock(&pvt->lock);
                h323_send_tone(token, digit);
                if (token) {
-                       free(token);
+                       ast_free(token);
                }
        } else
                ast_mutex_unlock(&pvt->lock);
@@ -542,11 +548,11 @@ static int oh323_digit_begin(struct ast_channel *c, char digit)
        return 0;
 }
 
-/**
+/*! \brief
  * Send (play) the specified digit to the channel.
  *
  */
-static int oh323_digit_end(struct ast_channel *c, char digit)
+static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration)
 {
        struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
        char *token;
@@ -559,28 +565,28 @@ static int oh323_digit_end(struct ast_channel *c, char digit)
        if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && ((pvt->dtmf_pt[0] > 0) || (pvt->dtmf_pt[0] > 0))) {
                /* out-of-band DTMF */
                if (h323debug) {
-                       ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s\n", digit, c->name);
+                       ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, c->name, duration);
                }
                ast_rtp_senddigit_end(pvt->rtp, digit);
                ast_mutex_unlock(&pvt->lock);
        } else {
                /* in-band DTMF */
                if (h323debug) {
-                       ast_log(LOG_DTMF, "End sending inband digit %c on %s\n", digit, c->name);
+                       ast_log(LOG_DTMF, "End sending inband digit %c on %s, duration %d\n", digit, c->name, duration);
                }
                pvt->txDtmfDigit = ' ';
                token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
                ast_mutex_unlock(&pvt->lock);
                h323_send_tone(token, ' ');
                if (token) {
-                       free(token);
+                       ast_free(token);
                }
        }
        oh323_update_info(c);
        return 0;
 }
 
-/**
+/*! \brief
  * Make a call over the specified channel to the specified
  * destination.
  * Returns -1 on error, 0 on success.
@@ -593,7 +599,7 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
        char called_addr[1024];
 
        if (h323debug) {
-               ast_log(LOG_DEBUG, "Calling to %s on %s\n", dest, c->name);
+               ast_debug(1, "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);
@@ -602,7 +608,7 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
        ast_mutex_lock(&pvt->lock);
        if (!gatekeeper_disable) {
                if (ast_strlen_zero(pvt->exten)) {
-                       strncpy(called_addr, dest, sizeof(called_addr));
+                       ast_copy_string(called_addr, dest, sizeof(called_addr));
                } else {
                        snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest);
                }
@@ -619,15 +625,18 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
        called_addr[sizeof(called_addr) - 1] = '\0';
 
        if (c->cid.cid_num)
-               strncpy(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));
+               ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));
 
        if (c->cid.cid_name)
-               strncpy(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
+               ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
 
        if (c->cid.cid_rdnis) {
-               strncpy(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));
+               ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));
        }
 
+       pvt->options.presentation = c->cid.cid_pres;
+       pvt->options.type_of_number = c->cid.cid_ton;
+
        if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
                if (!strcasecmp(addr, "UNKNOWN"))
                        pvt->options.redirect_reason = 0;
@@ -642,11 +651,15 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
        } else
                pvt->options.redirect_reason = -1;
 
+       pvt->options.transfer_capability = c->transfercapability;
+
        /* indicate that this is an outgoing call */
        pvt->outgoing = 1;
 
+       if (option_verbose > 2)
+               ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", c->transfercapability, ast_transfercapability2str(c->transfercapability));
        if (h323debug)
-               ast_log(LOG_DEBUG, "Placing outgoing call to %s, %d/%d\n", called_addr, pvt->options.dtmfcodec[0], pvt->options.dtmfcodec[1]);
+               ast_debug(1, "Placing outgoing call to %s, %d/%d\n", called_addr, pvt->options.dtmfcodec[0], pvt->options.dtmfcodec[1]);
        ast_mutex_unlock(&pvt->lock);
        res = h323_make_call(called_addr, &(pvt->cd), &pvt->options);
        if (res) {
@@ -664,14 +677,14 @@ static int oh323_answer(struct ast_channel *c)
        char *token;
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Answering on %s\n", c->name);
+               ast_debug(1, "Answering on %s\n", c->name);
 
        ast_mutex_lock(&pvt->lock);
        token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
        ast_mutex_unlock(&pvt->lock);
        res = h323_answering_call(token, 0);
        if (token)
-               free(token);
+               ast_free(token);
 
        oh323_update_info(c);
        if (c->_state != AST_STATE_UP) {
@@ -688,7 +701,7 @@ static int oh323_hangup(struct ast_channel *c)
 
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Hanging up and scheduling destroy of call %s\n", c->name);
+               ast_debug(1, "Hanging up and scheduling destroy of call %s\n", c->name);
 
        if (!c->tech_pvt) {
                ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
@@ -733,7 +746,7 @@ static int oh323_hangup(struct ast_channel *c)
                        if (h323_clear_call(call_token, q931cause)) {
                                ast_log(LOG_WARNING, "ClearCall failed.\n");
                        }
-                       free(call_token);
+                       ast_free(call_token);
                        ast_mutex_lock(&pvt->lock);
                }
        }
@@ -746,9 +759,9 @@ static int oh323_hangup(struct ast_channel *c)
        return 0;
 }
 
+/*! \brief Retrieve audio/etc from channel. Assumes pvt->lock is already held. */
 static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt)
 {
-       /* Retrieve audio/etc from channel. Assumes pvt->lock is already held. */
        struct ast_frame *f;
 
        /* Only apply it for the first packet, we just need the correct ip/port */
@@ -772,7 +785,7 @@ static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt)
                                        return &ast_null_frame;
                                }
                                if (h323debug)
-                                       ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
+                                       ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
                                pvt->owner->nativeformats = f->subclass;
                                pvt->nativeformats = f->subclass;
                                ast_set_read_format(pvt->owner, pvt->owner->readformat);
@@ -860,84 +873,76 @@ static int oh323_indicate(struct ast_channel *c, int condition, const void *data
 
        struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
        char *token = (char *)NULL;
+       int res = -1;
+       int got_progress;
 
        ast_mutex_lock(&pvt->lock);
        token = (pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL);
+       got_progress = pvt->got_progress;
+       if (condition == AST_CONTROL_PROGRESS)
+               pvt->got_progress = 1;
+       else if ((condition == AST_CONTROL_BUSY) || (condition == AST_CONTROL_CONGESTION))
+               pvt->alreadygone = 1;
        ast_mutex_unlock(&pvt->lock);
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "OH323: Indicating %d on %s\n", condition, token);
+               ast_debug(1, "OH323: Indicating %d on %s (%s)\n", condition, token, c->name);
 
        switch(condition) {
        case AST_CONTROL_RINGING:
                if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) {
                        h323_send_alerting(token);
-                       break;
+                       res = (got_progress ? 0 : -1);  /* Do not simulate any audio tones if we got PROGRESS message */
                }
-               if (token)
-                       free(token);
-               return -1;
+               break;
        case AST_CONTROL_PROGRESS:
                if (c->_state != AST_STATE_UP) {
-                       h323_send_progress(token);
-                       break;
+                       /* Do not send PROGRESS message more than once */
+                       if (!got_progress)
+                               h323_send_progress(token);
+                       res = 0;
                }
-               if (token)
-                       free(token);
-               return -1;
+               break;
        case AST_CONTROL_BUSY:
                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;
+                       res = 0;
                }
-               if (token)
-                       free(token);
-               return -1;
+               break;
        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;
+                       res = 0;
                }
-               if (token)
-                       free(token);
-               return -1;
+               break;
        case AST_CONTROL_HOLD:
+               h323_hold_call(token, 1);
+               /* We should start MOH only if remote party isn't provide audio for us */
                ast_moh_start(c, data, NULL);
-               if (token)
-                       free(token);
-               return 0;
+               res = 0;
+               break;
        case AST_CONTROL_UNHOLD:
+               h323_hold_call(token, 0);
                ast_moh_stop(c);
-               if (token)
-                       free(token);
-               return 0;
+               res = 0;
+               break;
        case AST_CONTROL_PROCEEDING:
        case -1:
-               if (token)
-                       free(token);
-               return -1;
+               break;
        default:
-               ast_log(LOG_WARNING, "Don't know how to indicate condition %d on %s\n", condition, token);
-               if (token)
-                       free(token);
-               return -1;
+               ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token);
+               break;
        }
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "OH323: Indicated %d on %s\n", condition, token);
+               ast_debug(1, "OH323: Indicated %d on %s, res=%d\n", condition, token, res);
        if (token)
-               free(token);
+               ast_free(token);
        oh323_update_info(c);
 
-       return -1;
+       return res;
 }
 
 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
@@ -973,12 +978,12 @@ static int __oh323_rtp_create(struct oh323_pvt *pvt)
                return -1;
        }
        if (h323debug)
-               ast_log(LOG_DEBUG, "Created RTP channel\n");
+               ast_debug(1, "Created RTP channel\n");
 
-       ast_rtp_settos(pvt->rtp, tos);
+       ast_rtp_setqos(pvt->rtp, tos, cos);
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
+               ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat);
        ast_rtp_setnat(pvt->rtp, pvt->options.nat);
 
        if (pvt->dtmf_pt[0] > 0)
@@ -1001,21 +1006,31 @@ static int __oh323_rtp_create(struct oh323_pvt *pvt)
        return 0;
 }
 
-/* Private structure should be locked on a call */
+/*! \brief 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;
+       char *cid_num, *cid_name;
        int fmt;
 
+       if (!ast_strlen_zero(pvt->options.cid_num))
+               cid_num = pvt->options.cid_num;
+       else
+               cid_num = pvt->cd.call_source_e164;
+
+       if (!ast_strlen_zero(pvt->options.cid_name))
+               cid_name = pvt->options.cid_name;
+       else
+               cid_name = pvt->cd.call_source_name;
+       
        /* Don't hold a oh323_pvt lock while we allocate a chanel */
        ast_mutex_unlock(&pvt->lock);
-       ch = ast_channel_alloc(1);
+       ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, pvt->amaflags, "H323/%s", host);
        /* Update usage counter */
        ast_module_ref(ast_module_info->self);
        ast_mutex_lock(&pvt->lock);
        if (ch) {
                ch->tech = &oh323_tech;
-               ast_string_field_build(ch, name, "H323/%s", host);
                if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability))
                        fmt = global_options.capability;
                ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/;
@@ -1053,8 +1068,8 @@ static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const c
                /* Set the owner of this channel */
                pvt->owner = ch;
 
-               strncpy(ch->context, pvt->context, sizeof(ch->context) - 1);
-               strncpy(ch->exten, pvt->exten, sizeof(ch->exten) - 1);
+               ast_copy_string(ch->context, pvt->context, sizeof(ch->context));
+               ast_copy_string(ch->exten, pvt->exten, sizeof(ch->exten));
                ch->priority = 1;
                if (!ast_strlen_zero(pvt->accountcode)) {
                        ast_string_field_set(ch, accountcode, pvt->accountcode);
@@ -1064,27 +1079,23 @@ static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const c
                }
 
                /* Don't use ast_set_callerid() here because it will
-                * generate a NewCallerID event before the NewChannel event */
-               if (!ast_strlen_zero(pvt->options.cid_num)) {
-                       ch->cid.cid_num = ast_strdup(pvt->options.cid_num);
-                       ch->cid.cid_ani = ast_strdup(pvt->options.cid_num);
-               } else {
-                       ch->cid.cid_num = ast_strdup(pvt->cd.call_source_e164);
-                       ch->cid.cid_ani = ast_strdup(pvt->cd.call_source_e164);
-               }
-               if (!ast_strlen_zero(pvt->options.cid_name))
-                       ch->cid.cid_name = ast_strdup(pvt->options.cid_name);
-               else
-                       ch->cid.cid_name = ast_strdup(pvt->cd.call_source_name);
+                * generate a needless NewCallerID event */
+               ch->cid.cid_num = ast_strdup(cid_num);
+               ch->cid.cid_ani = ast_strdup(cid_num);
+               ch->cid.cid_name = ast_strdup(cid_name);
+
                if (pvt->cd.redirect_reason >= 0) {
                        ch->cid.cid_rdnis = ast_strdup(pvt->cd.redirect_number);
                        pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
                }
+               ch->cid.cid_pres = pvt->cd.presentation;
+               ch->cid.cid_ton = pvt->cd.type_of_number;
 
                if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
                        ch->cid.cid_dnid = strdup(pvt->exten);
                }
-               ast_setstate(ch, state);
+               if (pvt->cd.transfer_capability >= 0)
+                       ch->transfercapability = pvt->cd.transfer_capability;
                if (state != AST_STATE_DOWN) {
                        if (ast_pbx_start(ch)) {
                                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
@@ -1102,22 +1113,22 @@ static struct oh323_pvt *oh323_alloc(int callid)
 {
        struct oh323_pvt *pvt;
 
-       pvt = (struct oh323_pvt *) malloc(sizeof(struct oh323_pvt));
+       pvt = ast_calloc(1, sizeof(*pvt));
        if (!pvt) {
                ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
                return NULL;
        }
-       memset(pvt, 0, sizeof(struct oh323_pvt));
        pvt->cd.redirect_reason = -1;
+       pvt->cd.transfer_capability = -1;
        /* Ensure the call token is allocated for outgoing call */
        if (!callid) {
                if ((pvt->cd).call_token == NULL) {
-                       (pvt->cd).call_token = (char *)malloc(128);
+                       (pvt->cd).call_token = ast_calloc(1, 128);
                }
                if (!pvt->cd.call_token) {
                        ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
                        ast_rtp_destroy(pvt->rtp);
-                       free(pvt);
+                       ast_free(pvt);
                        return NULL;
                }
                memset((char *)(pvt->cd).call_token, 0, 128);
@@ -1130,7 +1141,7 @@ static struct oh323_pvt *oh323_alloc(int callid)
        } else {
                pvt->nonCodecCapability &= ~AST_RTP_DTMF;
        }
-       strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
+       ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
        pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1;
        ast_mutex_init(&pvt->lock);
        /* Add to interface list */
@@ -1198,21 +1209,21 @@ static struct oh323_alias *build_alias(const char *name, struct ast_variable *v,
        if (alias)
                found++;
        else {
-               if (!(alias = (struct oh323_alias *)calloc(1, sizeof(*alias))))
+               if (!(alias = ast_calloc(1, sizeof(*alias))))
                        return NULL;
                ASTOBJ_INIT(alias);
        }
        if (!found && name)
-               strncpy(alias->name, name, sizeof(alias->name) - 1);
+               ast_copy_string(alias->name, name, sizeof(alias->name));
        for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
                if (!strcasecmp(v->name, "e164")) {
-                       strncpy(alias->e164, v->value, sizeof(alias->e164) - 1);
+                       ast_copy_string(alias->e164, v->value, sizeof(alias->e164));
                } else if (!strcasecmp(v->name, "prefix")) {
-                       strncpy(alias->prefix, v->value, sizeof(alias->prefix) - 1);
+                       ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix));
                } else if (!strcasecmp(v->name, "context")) {
-                       strncpy(alias->context, v->value, sizeof(alias->context) - 1);
+                       ast_copy_string(alias->context, v->value, sizeof(alias->context));
                } else if (!strcasecmp(v->name, "secret")) {
-                       strncpy(alias->secret, v->value, sizeof(alias->secret) - 1);
+                       ast_copy_string(alias->secret, v->value, sizeof(alias->secret));
                } else {
                        if (strcasecmp(v->value, "h323")) {
                                ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name);
@@ -1258,7 +1269,7 @@ static int update_common_options(struct ast_variable *v, struct call_options *op
        } else if (!strcasecmp(v->name, "disallow")) {
                ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
        } else if (!strcasecmp(v->name, "dtmfmode")) {
-               val = strdupa(v->value);
+               val = ast_strdupa(v->value);
                if ((opt = strchr(val, ':')) != (char *)NULL) {
                        *opt++ = '\0';
                        tmp = atoi(opt);
@@ -1338,6 +1349,17 @@ static int update_common_options(struct ast_variable *v, struct call_options *op
                        options->tunnelOptions |= H323_TUNNEL_QSIG;
                else
                        ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
+       } else if (!strcasecmp(v->name, "hold")) {
+               if (!strcasecmp(v->value, "none"))
+                       options->holdHandling = ~0;
+               else if (!strcasecmp(v->value, "notify"))
+                       options->holdHandling |= H323_HOLD_NOTIFY;
+               else if (!strcasecmp(v->value, "q931only"))
+                       options->holdHandling |= H323_HOLD_NOTIFY | H323_HOLD_Q931ONLY;
+               else if (!strcasecmp(v->value, "h450"))
+                       options->holdHandling |= H323_HOLD_H450;
+               else
+                       ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
        } else
                return 1;
 
@@ -1356,7 +1378,7 @@ static struct oh323_user *build_user(char *name, struct ast_variable *v, struct
        if (user)
                found++;
        else {
-               if (!(user = (struct oh323_user *)calloc(1, sizeof(*user))))
+               if (!(user = ast_calloc(1, sizeof(*user))))
                        return NULL;
                ASTOBJ_INIT(user);
        }
@@ -1364,10 +1386,11 @@ static struct oh323_user *build_user(char *name, struct ast_variable *v, struct
        user->ha = (struct ast_ha *)NULL;
        memcpy(&user->options, &global_options, sizeof(user->options));
        user->options.dtmfmode = 0;
+       user->options.holdHandling = 0;
        /* Set default context */
-       strncpy(user->context, default_context, sizeof(user->context) - 1);
+       ast_copy_string(user->context, default_context, sizeof(user->context));
        if (user && !found)
-               strncpy(user->name, name, sizeof(user->name) - 1);
+               ast_copy_string(user->name, name, sizeof(user->name));
 
 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
        if (user->chanvars) {
@@ -1380,11 +1403,11 @@ static struct oh323_user *build_user(char *name, struct ast_variable *v, struct
                if (!update_common_options(v, &user->options))
                        continue;
                if (!strcasecmp(v->name, "context")) {
-                       strncpy(user->context, v->value, sizeof(user->context) - 1);
+                       ast_copy_string(user->context, v->value, sizeof(user->context));
                } else if (!strcasecmp(v->name, "secret")) {
-                       strncpy(user->secret, v->value, sizeof(user->secret) - 1);
+                       ast_copy_string(user->secret, v->value, sizeof(user->secret));
                } else if (!strcasecmp(v->name, "accountcode")) {
-                       strncpy(user->accountcode, v->value, sizeof(user->accountcode) - 1);
+                       ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
                } else if (!strcasecmp(v->name, "host")) {
                        if (!strcasecmp(v->value, "dynamic")) {
                                ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
@@ -1405,11 +1428,19 @@ static struct oh323_user *build_user(char *name, struct ast_variable *v, struct
                        }
                } else if (!strcasecmp(v->name, "permit") ||
                                        !strcasecmp(v->name, "deny")) {
-                       user->ha = ast_append_ha(v->name, v->value, user->ha);
+                       int ha_error = 0;
+
+                       user->ha = ast_append_ha(v->name, v->value, user->ha, &ha_error);
+                       if (ha_error)
+                               ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
                }
        }
        if (!user->options.dtmfmode)
                user->options.dtmfmode = global_options.dtmfmode;
+       if (user->options.holdHandling == ~0)
+               user->options.holdHandling = 0;
+       else if (!user->options.holdHandling)
+               user->options.holdHandling = global_options.holdHandling;
        ASTOBJ_UNMARK(user);
        ast_free_ha(oldha);
        return user;
@@ -1464,7 +1495,7 @@ static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, s
        if (peer)
                found++;
        else {
-               if (!(peer = (struct oh323_peer*)calloc(1, sizeof(*peer))))
+               if (!(peer = ast_calloc(1, sizeof(*peer))))
                        return NULL;
                ASTOBJ_INIT(peer);
        }
@@ -1472,10 +1503,11 @@ static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, s
        peer->ha = NULL;
        memcpy(&peer->options, &global_options, sizeof(peer->options));
        peer->options.dtmfmode = 0;
+       peer->options.holdHandling = 0;
        peer->addr.sin_port = htons(h323_signalling_port);
        peer->addr.sin_family = AF_INET;
        if (!found && name)
-               strncpy(peer->name, name, sizeof(peer->name) - 1);
+               ast_copy_string(peer->name, name, sizeof(peer->name));
 
 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
        if (peer->chanvars) {
@@ -1504,13 +1536,21 @@ static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, s
                        peer->addr.sin_port = htons(atoi(v->value));
                } else if (!strcasecmp(v->name, "permit") ||
                                        !strcasecmp(v->name, "deny")) {
-                       peer->ha = ast_append_ha(v->name, v->value, peer->ha);
+                       int ha_error = 0;
+
+                       peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error);
+                       if (ha_error)
+                               ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
                } else if (!strcasecmp(v->name, "mailbox")) {
                        ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
                }
        }
        if (!peer->options.dtmfmode)
                peer->options.dtmfmode = global_options.dtmfmode;
+       if (peer->options.holdHandling == ~0)
+               peer->options.holdHandling = 0;
+       else if (!peer->options.holdHandling)
+               peer->options.holdHandling = global_options.holdHandling;
        ASTOBJ_UNMARK(peer);
        ast_free_ha(oldha);
        return peer;
@@ -1577,7 +1617,7 @@ static struct oh323_user *find_user(const call_details_t *cd, int realtime)
                u = realtime_user(cd);
 
        if (!u && h323debug)
-               ast_log(LOG_DEBUG, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
+               ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
 
        return u;
 }
@@ -1607,7 +1647,7 @@ static struct oh323_peer *find_peer(const char *peer, struct sockaddr_in *sin, i
                p = realtime_peer(peer, sin);
 
        if (!p && h323debug)
-               ast_log(LOG_DEBUG, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>"));
+               ast_debug(1, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>"));
 
        return p;
 }
@@ -1623,7 +1663,7 @@ static int create_addr(struct oh323_pvt *pvt, char *opeer)
        char *hostn;
        char peer[256] = "";
 
-       strncpy(peer, opeer, sizeof(peer) - 1);
+       ast_copy_string(peer, opeer, sizeof(peer));
        port = strchr(peer, ':');
        if (port) {
                *port = '\0';
@@ -1695,7 +1735,7 @@ static struct ast_channel *oh323_request(const char *type, int format, void *dat
        char tmp[256], tmp1[256];
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
+               ast_debug(1, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
 
        pvt = oh323_alloc(0);
        if (!pvt) {
@@ -1711,7 +1751,7 @@ static struct ast_channel *oh323_request(const char *type, int format, void *dat
                        *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
                return NULL;
        }
-       strncpy(tmp, dest, sizeof(tmp) - 1);
+       ast_copy_string(tmp, dest, sizeof(tmp));
        host = strchr(tmp, '@');
        if (host) {
                *host = '\0';
@@ -1728,10 +1768,10 @@ static struct ast_channel *oh323_request(const char *type, int format, void *dat
                h323_set_id(h323id);
        }
        if (ext) {
-               strncpy(pvt->exten, ext, sizeof(pvt->exten) - 1);
+               ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
        }
        if (h323debug)
-               ast_log(LOG_DEBUG, "Extension: %s Host: %s\n", pvt->exten, host);
+               ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host);
 
        if (gatekeeper_disable) {
                if (create_addr(pvt, host)) {
@@ -1772,7 +1812,7 @@ static struct ast_channel *oh323_request(const char *type, int format, void *dat
        return tmpc;
 }
 
-/** Find a call by alias */
+/*! \brief Find a call by alias */
 static struct oh323_alias *find_alias(const char *source_aliases, int realtime)
 {
        struct oh323_alias *a;
@@ -1785,7 +1825,7 @@ static struct oh323_alias *find_alias(const char *source_aliases, int realtime)
        return a;
 }
 
-/**
+/*! \brief
   * Callback for sending digits from H.323 up to asterisk
   *
   */
@@ -1810,6 +1850,7 @@ static int receive_digit(unsigned call_reference, char digit, const char *token,
                                .frametype = AST_FRAME_DTMF_END,
                                .subclass = digit,
                                .samples = duration * 8,
+                               .len = duration,
                                .src = "SEND_DIGIT",
                        };
                        if (digit == ' ') {             /* signalUpdate message */
@@ -1819,10 +1860,20 @@ static int receive_digit(unsigned call_reference, char digit, const char *token,
                                        pvt->DTMFsched = -1;
                                }
                        } else {                                /* Regular input or signal message */
+                               if (pvt->DTMFsched >= 0) {
+                                       /* We still don't send DTMF END from previous event, send it now */
+                                       ast_sched_del(sched, pvt->DTMFsched);
+                                       pvt->DTMFsched = -1;
+                                       f.subclass = pvt->curDTMF;
+                                       f.samples = f.len = 0;
+                                       ast_queue_frame(pvt->owner, &f);
+                                       /* Restore values */
+                                       f.subclass = digit;
+                                       f.samples = duration * 8;
+                                       f.len = duration;
+                               }
                                if (duration) {         /* This is a signal, signalUpdate follows */
                                        f.frametype = AST_FRAME_DTMF_BEGIN;
-                                       if (pvt->DTMFsched >= 0)
-                                               ast_sched_del(sched, pvt->DTMFsched);
                                        pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
                                        if (h323debug)
                                                ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
@@ -1845,10 +1896,10 @@ static int receive_digit(unsigned call_reference, char digit, const char *token,
        return res;
 }
 
-/**
+/*! \brief
   * Callback function used to inform the H.323 stack of the local rtp ip/port details
   *
-  * Returns the local RTP information
+  * \return Returns the local RTP information
   */
 static struct rtp_info *external_rtp_create(unsigned call_reference, const char * token)
 {
@@ -1856,14 +1907,14 @@ static struct rtp_info *external_rtp_create(unsigned call_reference, const char
        struct sockaddr_in us;
        struct rtp_info *info;
 
-       info = (struct rtp_info *)malloc(sizeof(struct rtp_info));
+       info = ast_calloc(1, sizeof(*info));
        if (!info) {
                ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
                return NULL;
        }
        pvt = find_call_locked(call_reference, token);
        if (!pvt) {
-               free(info);
+               ast_free(info);
                ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
                return NULL;
        }
@@ -1871,7 +1922,7 @@ static struct rtp_info *external_rtp_create(unsigned call_reference, const char
                __oh323_rtp_create(pvt);
        if (!pvt->rtp) {
                ast_mutex_unlock(&pvt->lock);
-               free(info);
+               ast_free(info);
                ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
                return NULL;
        }
@@ -1879,23 +1930,23 @@ static struct rtp_info *external_rtp_create(unsigned call_reference, const char
        ast_rtp_get_us(pvt->rtp, &us);
        ast_mutex_unlock(&pvt->lock);
 
-       strncpy(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
-       info->addr[sizeof(info->addr)-1] = '\0';
+       ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
        info->port = ntohs(us.sin_port);
        if (h323debug)
-               ast_log(LOG_DEBUG, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
+               ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
        return info;
 }
 
-/**
+/* 
  * Definition taken from rtp.c for rtpPayloadType because we need it here.
  */
+
 struct rtpPayloadType {
        int isAstFormat;        /* whether the following code is an AST_FORMAT */
        int code;
 };
 
-/**
+/*! \brief
   * Call-back function passing remote ip/port information from H.323 to asterisk
   *
   * Returns nothing
@@ -1909,7 +1960,7 @@ static void setup_rtp_connection(unsigned call_reference, const char *remoteIp,
        enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Setting up RTP connection for %s\n", token);
+               ast_debug(1, "Setting up RTP connection for %s\n", token);
 
        /* Find the call or allocate a private structure if call not found */
        pvt = find_call_locked(call_reference, token);
@@ -1953,7 +2004,7 @@ static void setup_rtp_connection(unsigned call_reference, const char *remoteIp,
        if (pt != 128 && pvt->rtp) {    /* Payload type is invalid, so try to use previously decided */
                rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);
                if (h323debug)
-                       ast_log(LOG_DEBUG, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt);
+                       ast_debug(1, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt);
                if (pvt->nativeformats != rtptype.code) {
                        pvt->nativeformats = rtptype.code;
                        nativeformats_changed = 1;
@@ -1967,7 +2018,7 @@ static void setup_rtp_connection(unsigned call_reference, const char *remoteIp,
                        /* Re-build translation path only if native format(s) has been changed */
                        if (pvt->owner->nativeformats != pvt->nativeformats) {
                                if (h323debug)
-                                       ast_log(LOG_DEBUG, "Native format changed to %d from %d, read format is %d, write format is %d\n", pvt->nativeformats, pvt->owner->nativeformats, pvt->owner->readformat, pvt->owner->writeformat);
+                                       ast_debug(1, "Native format changed to %d from %d, read format is %d, write format is %d\n", pvt->nativeformats, pvt->owner->nativeformats, pvt->owner->readformat, pvt->owner->writeformat);
                                pvt->owner->nativeformats = pvt->nativeformats;
                                ast_set_read_format(pvt->owner, pvt->owner->readformat);
                                ast_set_write_format(pvt->owner, pvt->owner->writeformat);
@@ -1994,18 +2045,18 @@ static void setup_rtp_connection(unsigned call_reference, const char *remoteIp,
                        else if (rtp_change == NEED_UNHOLD)
                                pvt->newcontrol = AST_CONTROL_UNHOLD;
                        if (h323debug)
-                               ast_log(LOG_DEBUG, "RTP connection preparation for %s is pending...\n", token);
+                               ast_debug(1, "RTP connection preparation for %s is pending...\n", token);
                }
        }
        ast_mutex_unlock(&pvt->lock);
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "RTP connection prepared for %s\n", token);
+               ast_debug(1, "RTP connection prepared for %s\n", token);
 
        return;
 }
 
-/**
+/*! \brief
   *    Call-back function to signal asterisk that the channel has been answered
   * Returns nothing
   */
@@ -2014,7 +2065,7 @@ static void connection_made(unsigned call_reference, const char *token)
        struct oh323_pvt *pvt;
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Call %s answered\n", token);
+               ast_debug(1, "Call %s answered\n", token);
 
        pvt = find_call_locked(call_reference, token);
        if (!pvt) {
@@ -2041,7 +2092,7 @@ static int progress(unsigned call_reference, const char *token, int inband)
        struct oh323_pvt *pvt;
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
+               ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
 
        pvt = find_call_locked(call_reference, token);
        if (!pvt) {
@@ -2059,7 +2110,7 @@ static int progress(unsigned call_reference, const char *token, int inband)
        return 0;
 }
 
-/**
+/*! \brief
  *  Call-back function for incoming calls
  *
  *  Returns 1 on success
@@ -2071,7 +2122,7 @@ static call_options_t *setup_incoming_call(call_details_t *cd)
        struct oh323_alias *alias = NULL;
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Setting up incoming call for %s\n", cd->call_token);
+               ast_debug(1, "Setting up incoming call for %s\n", cd->call_token);
 
        /* allocate the call*/
        pvt = oh323_alloc(cd->call_reference);
@@ -2102,8 +2153,8 @@ static 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) && !gatekeeper_disable) {
                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);
+                       ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
+                       ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
                } else {
                        alias = find_alias(cd->call_dest_alias, 1);
                        if (!alias) {
@@ -2111,8 +2162,8 @@ static call_options_t *setup_incoming_call(call_details_t *cd)
                                oh323_destroy(pvt);
                                return NULL;
                        }
-                       strncpy(pvt->exten, alias->name, sizeof(pvt->exten) - 1);
-                       strncpy(pvt->context, alias->context, sizeof(pvt->context) - 1);
+                       ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
+                       ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
                }
        } else {
                /* Either this call is not from the Gatekeeper
@@ -2129,14 +2180,14 @@ static call_options_t *setup_incoming_call(call_details_t *cd)
                                oh323_destroy(pvt);
                                return NULL;
                        }
-                       strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
+                       ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
                        if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
-                               strncpy(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten) - 1);
+                               ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
                        } else {
-                               strncpy(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten) - 1);
+                               ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
                        }
                        if (h323debug)
-                               ast_log(LOG_DEBUG, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
+                               ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
                } else {
                        if (user->host) {
                                if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
@@ -2147,9 +2198,9 @@ static call_options_t *setup_incoming_call(call_details_t *cd)
                                                        ASTOBJ_UNREF(user, oh323_destroy_user);
                                                        return NULL;
                                                }
-                                               strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
+                                               ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
                                        } else {
-                                               strncpy(pvt->context, user->context, sizeof(pvt->context) - 1);
+                                               ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
                                        }
                                        pvt->exten[0] = 'i';
                                        pvt->exten[1] = '\0';
@@ -2159,16 +2210,16 @@ static call_options_t *setup_incoming_call(call_details_t *cd)
                                        return NULL;    /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
                                }
                        }
-                       strncpy(pvt->context, user->context, sizeof(pvt->context) - 1);
+                       ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
                        memcpy(&pvt->options, &user->options, sizeof(pvt->options));
                        pvt->jointcapability = pvt->options.capability;
                        if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
-                               strncpy(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten) - 1);
+                               ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
                        } else {
-                               strncpy(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten) - 1);
+                               ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
                        }
                        if (!ast_strlen_zero(user->accountcode)) {
-                               strncpy(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode) - 1);
+                               ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
                        }
                        if (user->amaflags) {
                                pvt->amaflags = user->amaflags;
@@ -2179,7 +2230,7 @@ static call_options_t *setup_incoming_call(call_details_t *cd)
        return &pvt->options;
 }
 
-/**
+/*! \brief
  * Call-back function to start PBX when OpenH323 ready to serve incoming call
  *
  * Returns 1 on success
@@ -2192,7 +2243,7 @@ static int answer_call(unsigned call_reference, const char *token)
        char tmp_exten[sizeof(pvt->exten)];
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Preparing Asterisk to answer for %s\n", token);
+               ast_debug(1, "Preparing Asterisk to answer for %s\n", token);
 
        /* Find the call or allocate a private structure if call not found */
        pvt = find_call_locked(call_reference, token);
@@ -2201,7 +2252,7 @@ static int answer_call(unsigned call_reference, const char *token)
                return 0;
        }
        /* Check if requested extension@context pair exists in the dialplan */
-       strncpy(tmp_exten, pvt->exten, sizeof(tmp_exten));
+       ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
 
        /* Try to find best extension in specified context */
        if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
@@ -2242,8 +2293,8 @@ static int answer_call(unsigned call_reference, const char *token)
                return 0;
        } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
                if (h323debug)
-                       ast_log(LOG_DEBUG, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
-               strncpy(pvt->exten, tmp_exten, sizeof(pvt->exten));
+                       ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
+               ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
        }
 
        /* allocate a channel and tell asterisk about it */
@@ -2258,7 +2309,7 @@ static int answer_call(unsigned call_reference, const char *token)
        return 1;
 }
 
-/**
+/*! \brief
  * Call-back function to establish an outgoing H.323 call
  *
  * Returns 1 on success
@@ -2271,7 +2322,7 @@ static int setup_outgoing_call(call_details_t *cd)
        return 1;
 }
 
-/**
+/*! \brief
   *  Call-back function to signal asterisk that the channel is ringing
   *  Returns nothing
   */
@@ -2280,7 +2331,7 @@ static void chan_ringing(unsigned call_reference, const char *token)
        struct oh323_pvt *pvt;
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Ringing on %s\n", token);
+               ast_debug(1, "Ringing on %s\n", token);
 
        pvt = find_call_locked(call_reference, token);
        if (!pvt) {
@@ -2297,7 +2348,7 @@ static void chan_ringing(unsigned call_reference, const char *token)
        return;
 }
 
-/**
+/*! \brief
   * Call-back function to cleanup communication
   * Returns nothing,
   */
@@ -2306,13 +2357,13 @@ static void cleanup_connection(unsigned call_reference, const char *call_token)
        struct oh323_pvt *pvt;
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Cleaning connection to %s\n", call_token);
+               ast_debug(1, "Cleaning connection to %s\n", call_token);
 
        while (1) {
                pvt = find_call_locked(call_reference, call_token);
                if (!pvt) {
                        if (h323debug)
-                               ast_log(LOG_DEBUG, "No connection for %s\n", call_token);
+                               ast_debug(1, "No connection for %s\n", call_token);
                        return;
                }
                if (!pvt->owner || !ast_channel_trylock(pvt->owner))
@@ -2347,7 +2398,7 @@ static void cleanup_connection(unsigned call_reference, const char *call_token)
        }
        ast_mutex_unlock(&pvt->lock);
        if (h323debug)
-               ast_log(LOG_DEBUG, "Connection to %s cleaned\n", call_token);
+               ast_debug(1, "Connection to %s cleaned\n", call_token);
        return;
 }
 
@@ -2355,15 +2406,13 @@ static void hangup_connection(unsigned int call_reference, const char *token, in
 {
        struct oh323_pvt *pvt;
 
-       if (h323debug) {
-               ast_log(LOG_DEBUG, "Hanging up connection to %s with cause %d\n", token, cause);
-       }
+       if (h323debug)
+               ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause);
 
        pvt = find_call_locked(call_reference, token);
        if (!pvt) {
-               if (h323debug) {
-                       ast_log(LOG_DEBUG, "Connection to %s already cleared\n", token);
-               }
+               if (h323debug)
+                       ast_debug(1, "Connection to %s already cleared\n", token);
                return;
        }
        if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
@@ -2376,7 +2425,7 @@ static void hangup_connection(unsigned int call_reference, const char *token, in
                pvt->needhangup = 1;
                pvt->hangupcause = cause;
                if (h323debug)
-                       ast_log(LOG_DEBUG, "Hangup for %s is pending\n", token);
+                       ast_debug(1, "Hangup for %s is pending\n", token);
        }
        ast_mutex_unlock(&pvt->lock);
 }
@@ -2386,7 +2435,7 @@ static void set_dtmf_payload(unsigned call_reference, const char *token, int pay
        struct oh323_pvt *pvt;
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
+               ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
 
        pvt = find_call_locked(call_reference, token);
        if (!pvt) {
@@ -2398,7 +2447,7 @@ static void set_dtmf_payload(unsigned call_reference, const char *token, int pay
        pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
        ast_mutex_unlock(&pvt->lock);
        if (h323debug)
-               ast_log(LOG_DEBUG, "DTMF payload on %s set to %d\n", token, payload);
+               ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
 }
 
 static void set_peer_capabilities(unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs)
@@ -2406,7 +2455,7 @@ static void set_peer_capabilities(unsigned call_reference, const char *token, in
        struct oh323_pvt *pvt;
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Got remote capabilities from connection %s\n", token);
+               ast_debug(1, "Got remote capabilities from connection %s\n", token);
 
        pvt = find_call_locked(call_reference, token);
        if (!pvt)
@@ -2418,7 +2467,9 @@ static void set_peer_capabilities(unsigned call_reference, const char *token, in
                if (h323debug) {
                        int i;
                        for (i = 0; i < 32; ++i) {
-                               ast_log(LOG_DEBUG, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
+                               if (!prefs->order[i])
+                                       break;
+                               ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
                        }
                }
                if (pvt->rtp)
@@ -2434,7 +2485,7 @@ static void set_local_capabilities(unsigned call_reference, const char *token)
        struct ast_codec_pref prefs;
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Setting capabilities for connection %s\n", token);
+               ast_debug(1, "Setting capabilities for connection %s\n", token);
 
        pvt = find_call_locked(call_reference, token);
        if (!pvt)
@@ -2447,7 +2498,33 @@ static void set_local_capabilities(unsigned call_reference, const char *token)
        h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
 
        if (h323debug)
-               ast_log(LOG_DEBUG, "Capabilities for connection %s is set\n", token);
+               ast_debug(1, "Capabilities for connection %s is set\n", token);
+}
+
+static void remote_hold(unsigned call_reference, const char *token, int is_hold)
+{
+       struct oh323_pvt *pvt;
+
+       if (h323debug)
+               ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
+
+       pvt = find_call_locked(call_reference, token);
+       if (!pvt)
+               return;
+       if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
+               if (is_hold)
+                       ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
+               else
+                       ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
+               ast_channel_unlock(pvt->owner);
+       }
+       else {
+               if (is_hold)
+                       pvt->newcontrol = AST_CONTROL_HOLD;
+               else
+                       pvt->newcontrol = AST_CONTROL_UNHOLD;
+       }
+       ast_mutex_unlock(&pvt->lock);
 }
 
 static void *do_monitor(void *data)
@@ -2522,7 +2599,6 @@ restartsearch:
 
 static int restart_monitor(void)
 {
-       pthread_attr_t attr;
        /* If we're supposed to be stopped -- stay stopped */
        if (ast_mutex_lock(&monlock)) {
                ast_log(LOG_WARNING, "Unable to lock monitor\n");
@@ -2541,10 +2617,8 @@ static int restart_monitor(void)
                /* Wake up the thread */
                pthread_kill(monitor_thread, SIGURG);
        } else {
-               pthread_attr_init(&attr);
-               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                /* Start a new monitor */
-               if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
+               if (ast_pthread_create_detached_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
                        monitor_thread = AST_PTHREADT_NULL;
                        ast_mutex_unlock(&monlock);
                        ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
@@ -2557,17 +2631,17 @@ static int restart_monitor(void)
 
 static int h323_do_trace(int fd, int argc, char *argv[])
 {
-       if (argc != 3) {
+       if (argc != 4) {
                return RESULT_SHOWUSAGE;
        }
-       h323_debug(1, atoi(argv[2]));
+       h323_debug(1, atoi(argv[3]));
        ast_cli(fd, "H.323 trace set to level %s\n", argv[2]);
        return RESULT_SUCCESS;
 }
 
 static int h323_no_trace(int fd, int argc, char *argv[])
 {
-       if (argc != 3) {
+       if (argc < 3 || argc > 4) {
                return RESULT_SHOWUSAGE;
        }
        h323_debug(0,0);
@@ -2577,7 +2651,7 @@ static int h323_no_trace(int fd, int argc, char *argv[])
 
 static int h323_do_debug(int fd, int argc, char *argv[])
 {
-       if (argc != 2) {
+       if (argc < 2 || argc > 3) {
                return RESULT_SHOWUSAGE;
        }
        h323debug = 1;
@@ -2587,7 +2661,7 @@ static int h323_do_debug(int fd, int argc, char *argv[])
 
 static int h323_no_debug(int fd, int argc, char *argv[])
 {
-       if (argc != 3) {
+       if (argc < 3 || argc > 4) {
                return RESULT_SHOWUSAGE;
        }
        h323debug = 0;
@@ -2701,23 +2775,23 @@ static struct ast_cli_entry cli_h323_show_tokens_deprecated =
        show_tokens_usage };
 
 static struct ast_cli_entry cli_h323[] = {
-       { { "h323", "trace", NULL },
+       { { "h323", "set", "trace", NULL },
        h323_do_trace, "Enable H.323 Stack Tracing",
        trace_usage, NULL, &cli_h323_trace_deprecated },
 
-       { { "h323", "no", "trace", NULL },
+       { { "h323", "set", "trace", "off", NULL },
        h323_no_trace, "Disable H.323 Stack Tracing",
        no_trace_usage, NULL, &cli_h323_no_trace_deprecated },
 
-       { { "h323", "debug", NULL },
+       { { "h323", "set", "debug", NULL },
        h323_do_debug, "Enable H.323 debug",
        debug_usage, NULL, &cli_h323_debug_deprecated },
 
-       { { "h323", "no", "debug", NULL },
+       { { "h323", "set", "debug", "off", NULL },
        h323_no_debug, "Disable H.323 debug",
        no_debug_usage, NULL, &cli_h323_no_debug_deprecated },
 
-       { { "h323", "gk", "cycle", NULL },
+       { { "h323", "cycle", "gk", NULL },
        h323_gk_cycle, "Manually re-register with the Gatekeper",
        show_cycle_usage, NULL, &cli_h323_gk_cycle_deprecated },
 
@@ -2732,7 +2806,6 @@ static struct ast_cli_entry cli_h323[] = {
 
 static int reload_config(int is_reload)
 {
-       int format;
        struct ast_config *cfg, *ucfg;
        struct ast_variable *v;
        struct oh323_peer *peer = NULL;
@@ -2757,7 +2830,7 @@ static int reload_config(int is_reload)
        if (!h323_end_point_exist()) {
                h323_end_point_create();
        }
-       strncpy(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
+       ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
        gk_discover = gatekeeper_discover;
        gk_disable = gatekeeper_disable;
        memset(&bindaddr, 0, sizeof(bindaddr));
@@ -2767,9 +2840,10 @@ static int reload_config(int is_reload)
        global_options.dtmfcodec[0] = H323_DTMF_RFC2833_PT;
        global_options.dtmfcodec[1] = H323_DTMF_CISCO_PT;
        global_options.dtmfmode = 0;
+       global_options.holdHandling = 0;
        global_options.capability = GLOBAL_CAPABILITY;
        global_options.bridge = 1;              /* Do native bridging by default */
-       strncpy(default_context, "default", sizeof(default_context) - 1);
+       strcpy(default_context, "default");
        h323_signalling_port = 1720;
        gatekeeper_disable = 1;
        gatekeeper_discover = 0;
@@ -2777,6 +2851,7 @@ static int reload_config(int is_reload)
        userbyalias = 1;
        acceptAnonymous = 1;
        tos = 0;
+       cos = 0;
 
        /* Copy the default jb config over global_jbconf */
        memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
@@ -2819,20 +2894,12 @@ static int reload_config(int is_reload)
                                memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
                        }
                } else if (!strcasecmp(v->name, "tos")) {
-                       if (sscanf(v->value, "%d", &format)) {
-                               tos = format & 0xff;
-                       } else if (!strcasecmp(v->value, "lowdelay")) {
-                               tos = IPTOS_LOWDELAY;
-                       } else if (!strcasecmp(v->value, "throughput")) {
-                               tos = IPTOS_THROUGHPUT;
-                       } else if (!strcasecmp(v->value, "reliability")) {
-                               tos = IPTOS_RELIABILITY;
-                       } else if (!strcasecmp(v->value, "mincost")) {
-                               tos = IPTOS_MINCOST;
-                       } else if (!strcasecmp(v->value, "none")) {
-                               tos = 0;
-                       } else {
-                               ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
+                       if (ast_str2tos(v->value, &tos)) {
+                               ast_log(LOG_WARNING, "Invalid tos value at line %d, for more info read doc/qos.tex\n", v->lineno);                      
+                       }
+               } else if (!strcasecmp(v->name, "cos")) {               
+                       if (ast_str2cos(v->value, &cos)) {
+                               ast_log(LOG_WARNING, "Invalid cos value at line %d, for more info read doc/qos.tex\n", v->lineno);                      
                        }
                } else if (!strcasecmp(v->name, "gatekeeper")) {
                        if (!strcasecmp(v->value, "DISABLE")) {
@@ -2842,14 +2909,14 @@ static int reload_config(int is_reload)
                                gatekeeper_discover = 1;
                        } else {
                                gatekeeper_disable = 0;
-                               strncpy(gatekeeper, v->value, sizeof(gatekeeper) - 1);
+                               ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper));
                        }
                } else if (!strcasecmp(v->name, "secret")) {
-                       strncpy(secret, v->value, sizeof(secret) - 1);
+                       ast_copy_string(secret, v->value, sizeof(secret));
                } else if (!strcasecmp(v->name, "AllowGKRouted")) {
                        gkroute = ast_true(v->value);
                } else if (!strcasecmp(v->name, "context")) {
-                       strncpy(default_context, v->value, sizeof(default_context) - 1);
+                       ast_copy_string(default_context, v->value, sizeof(default_context));
                        ast_verbose(VERBOSE_PREFIX_2 "Setting default context to %s\n", default_context);
                } else if (!strcasecmp(v->name, "UserByAlias")) {
                        userbyalias = ast_true(v->value);
@@ -2861,6 +2928,10 @@ static int reload_config(int is_reload)
        }
        if (!global_options.dtmfmode)
                global_options.dtmfmode = H323_DTMF_RFC2833;
+       if (global_options.holdHandling == ~0)
+               global_options.holdHandling = 0;
+       else if (!global_options.holdHandling)
+               global_options.holdHandling = H323_HOLD_H450;
 
        for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
                if (strcasecmp(cat, "general")) {
@@ -3064,6 +3135,8 @@ static char *convertcap(int cap)
                return "ULAW";
        case AST_FORMAT_ALAW:
                return "ALAW";
+       case AST_FORMAT_G722:
+               return "G.722";
        case AST_FORMAT_ADPCM:
                return "G.728";
        case AST_FORMAT_G729A:
@@ -3078,7 +3151,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, int nat_active)
+static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
 {
        /* XXX Deal with Video */
        struct oh323_pvt *pvt;
@@ -3132,13 +3205,17 @@ static enum ast_module_load_result load_module(void)
        ASTOBJ_CONTAINER_INIT(&aliasl);
        res = reload_config(0);
        if (res) {
+               /* No config entry */
+               ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
                ast_cli_unregister(&cli_h323_reload);
                io_context_destroy(io);
+               io = NULL;
                sched_context_destroy(sched);
+               sched = NULL;
                ASTOBJ_CONTAINER_DESTROY(&userl);
                ASTOBJ_CONTAINER_DESTROY(&peerl);
                ASTOBJ_CONTAINER_DESTROY(&aliasl);
-               return /*AST_MODULE_LOAD_DECLINE*/AST_MODULE_LOAD_FAILURE;
+               return AST_MODULE_LOAD_DECLINE;
        } else {
                /* Make sure we can register our channel type */
                if (ast_channel_register(&oh323_tech)) {
@@ -3175,7 +3252,8 @@ static enum ast_module_load_result load_module(void)
                                                set_dtmf_payload,
                                                hangup_connection,
                                                set_local_capabilities,
-                                               set_peer_capabilities);
+                                               set_peer_capabilities,
+                                               remote_hold);
                /* start the h.323 listener */
                if (h323_start_listener(h323_signalling_port, bindaddr)) {
                        ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
@@ -3257,7 +3335,7 @@ static int unload_module(void)
                        p = p->next;
                        /* free associated memory */
                        ast_mutex_destroy(&pl->lock);
-                       free(pl);
+                       ast_free(pl);
                }
                iflist = NULL;
                ast_mutex_unlock(&iflock);
@@ -3268,8 +3346,10 @@ static int unload_module(void)
        if (!gatekeeper_disable)
                h323_gk_urq();
        h323_end_process();
-       io_context_destroy(io);
-       sched_context_destroy(sched);
+       if (io)
+               io_context_destroy(io);
+       if (sched)
+               sched_context_destroy(sched);
 
        ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
        ASTOBJ_CONTAINER_DESTROY(&userl);