Prefer ast_set_qos() over ast_netsock_set_qos()
[asterisk/asterisk.git] / channels / chan_mgcp.c
index b39e1fb..9a49d00 100644 (file)
  *
  * \par See also
  * \arg \ref Config_mgcp
+ * \arg \ref res_pktccops
  *
  * \ingroup channel_drivers
  */
 
+/*** MODULEINFO
+        <use type="module">res_pktccops</use>
+       <support_level>extended</support_level>
+ ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
-#include <errno.h>
-#include <stdlib.h>
 #include <fcntl.h>
 #include <netdb.h>
 #include <sys/signal.h>
@@ -53,14 +54,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/lock.h"
 #include "asterisk/channel.h"
 #include "asterisk/config.h"
-#include "asterisk/logger.h"
 #include "asterisk/module.h"
 #include "asterisk/pbx.h"
-#include "asterisk/options.h"
-#include "asterisk/lock.h"
 #include "asterisk/sched.h"
 #include "asterisk/io.h"
-#include "asterisk/rtp.h"
+#include "asterisk/rtp_engine.h"
 #include "asterisk/acl.h"
 #include "asterisk/callerid.h"
 #include "asterisk/cli.h"
@@ -71,16 +69,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/musiconhold.h"
 #include "asterisk/utils.h"
+#include "asterisk/netsock2.h"
 #include "asterisk/causes.h"
 #include "asterisk/dsp.h"
 #include "asterisk/devicestate.h"
 #include "asterisk/stringfields.h"
 #include "asterisk/abstract_jb.h"
 #include "asterisk/event.h"
-
-#ifndef IPTOS_MINCOST
-#define IPTOS_MINCOST 0x02
-#endif
+#include "asterisk/chanvars.h"
+#include "asterisk/pktccops.h"
 
 /*
  * Define to work around buggy dlink MGCP phone firmware which
@@ -91,19 +88,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #define MGCPDUMPER
 #define DEFAULT_EXPIRY 120
 #define MAX_EXPIRY     3600
-#define CANREINVITE    1
+#define DIRECTMEDIA    1
 
 #ifndef INADDR_NONE
 #define INADDR_NONE (in_addr_t)(-1)
 #endif
 
-/*! Global jitterbuffer configuration - by default, jb is disabled */
+/*! Global jitterbuffer configuration - by default, jb is disabled
+ *  \note Values shown here match the defaults shown in mgcp.conf.sample */
 static struct ast_jb_conf default_jbconf =
 {
        .flags = 0,
-       .max_size = -1,
-       .resync_threshold = -1,
-       .impl = ""
+       .max_size = 200,
+       .resync_threshold = 1000,
+       .impl = "fixed",
+       .target_extra = 40,
 };
 static struct ast_jb_conf global_jbconf;
 
@@ -130,7 +129,7 @@ static const char config[] = "mgcp.conf";
 #define MGCP_CX_INACTIVE       4
 /*! } */
 
-static char *mgcp_cxmodes[] = {
+static const char * const mgcp_cxmodes[] = {
        "sendonly",
        "recvonly",
        "sendrecv",
@@ -154,16 +153,25 @@ static char context[AST_MAX_EXTENSION] = "default";
 
 static char language[MAX_LANGUAGE] = "";
 static char musicclass[MAX_MUSICCLASS] = "";
+static char parkinglot[AST_MAX_CONTEXT];
 static char cid_num[AST_MAX_EXTENSION] = "";
 static char cid_name[AST_MAX_EXTENSION] = "";
 
 static int dtmfmode = 0;
 static int nat = 0;
+static int ncs = 0;
+static int pktcgatealloc = 0;
+static int hangupongateremove = 0;
 
 static ast_group_t cur_callergroup = 0;
 static ast_group_t cur_pickupgroup = 0;
 
-static int tos = 0;
+static struct {
+       unsigned int tos;
+       unsigned int tos_audio;
+       unsigned int cos;
+       unsigned int cos_audio;
+} qos = { 0, 0, 0, 0 };
 
 static int immediate = 0;
 
@@ -182,7 +190,7 @@ static int cancallforward = 0;
 
 static int singlepath = 0;
 
-static int canreinvite = CANREINVITE;
+static int directmedia = DIRECTMEDIA;
 
 static char accountcode[AST_MAX_ACCOUNT_CODE] = "";
 
@@ -210,12 +218,13 @@ AST_MUTEX_DEFINE_STATIC(netlock);
 AST_MUTEX_DEFINE_STATIC(monlock);
 
 /*! This is the thread for the monitor which checks for input on the channels
-    which are not currently in use. */
+ *  which are not currently in use.
+ */
 static pthread_t monitor_thread = AST_PTHREADT_NULL;
 
 static int restart_monitor(void);
 
-static int capability = AST_FORMAT_ULAW;
+static struct ast_format_cap *global_capability;
 static int nonCodecCapability = AST_RTP_DTMF;
 
 static char ourhost[MAXHOSTNAMELEN];
@@ -224,11 +233,12 @@ static int ourport;
 
 static int mgcpdebug = 0;
 
-static struct sched_context *sched;
+static struct ast_sched_context *sched;
 static struct io_context *io;
-/*! The private structures of the  mgcp channels are linked for
-  ! selecting outgoing channels */
-   
+/*! The private structures of the mgcp channels are linked for
+ * selecting outgoing channels
+ */
+
 #define MGCP_MAX_HEADERS       64
 #define MGCP_MAX_LINES         64
 
@@ -276,20 +286,20 @@ struct mgcp_response {
 #define SUB_ALT  1
 
 struct mgcp_subchannel {
-       /*! subchannel magic string. 
-          Needed to prove that any subchannel pointer passed by asterisk 
+       /*! subchannel magic string.
+          Needed to prove that any subchannel pointer passed by asterisk
           really points to a valid subchannel memory area.
           Ugly.. But serves the purpose for the time being.
         */
 #define MGCP_SUBCHANNEL_MAGIC "!978!"
-       char magic[6]; 
+       char magic[6];
        ast_mutex_t lock;
        int id;
        struct ast_channel *owner;
        struct mgcp_endpoint *parent;
-       struct ast_rtp *rtp;
+       struct ast_rtp_instance *rtp;
        struct sockaddr_in tmpdest;
-       char txident[80]; /*! \todo FIXME txident is replaced by rqnt_ident in endpoint. 
+       char txident[80]; /*! \todo FIXME txident is replaced by rqnt_ident in endpoint.
                        This should be obsoleted */
        char cxident[80];
        char callid[80];
@@ -300,6 +310,8 @@ struct mgcp_subchannel {
        int iseq;                      /*!< Not used? RTP? */
        int outgoing;
        int alreadygone;
+       int sdpsent;
+       struct cops_gate *gate;
        struct mgcp_subchannel *next;  /*!< for out circular linked list */
 };
 
@@ -320,10 +332,12 @@ struct mgcp_endpoint {
        char cid_num[AST_MAX_EXTENSION];        /*!< Caller*ID number */
        char cid_name[AST_MAX_EXTENSION];       /*!< Caller*ID name */
        char lastcallerid[AST_MAX_EXTENSION];   /*!< Last Caller*ID */
+       char dtmf_buf[AST_MAX_EXTENSION];       /*!< place to collect digits be */
        char call_forward[AST_MAX_EXTENSION];   /*!< Last Caller*ID */
        char musicclass[MAX_MUSICCLASS];
        char curtone[80];                       /*!< Current tone */
        char mailbox[AST_MAX_EXTENSION];
+       char parkinglot[AST_MAX_CONTEXT];   /*!< Parkinglot */
        struct ast_event_sub *mwi_event_sub;
        ast_group_t callgroup;
        ast_group_t pickupgroup;
@@ -333,20 +347,23 @@ struct mgcp_endpoint {
        int threewaycalling;
        int singlepath;
        int cancallforward;
-       int canreinvite;
+       int directmedia;
        int callreturn;
        int dnd; /* How does this affect callwait? Do we just deny a mgcp_request if we're dnd? */
        int hascallerid;
        int hidecallerid;
        int dtmfmode;
        int amaflags;
+       int ncs;
+       int pktcgatealloc;
+       int hangupongateremove;
        int type;
        int slowsequence;                       /*!< MS: Sequence the endpoint as a whole */
        int group;
        int iseq; /*!< Not used? */
        int lastout; /*!< tracking this on the subchannels.  Is it needed here? */
        int needdestroy; /*!< Not used? */
-       int capability;
+       struct ast_format_cap *cap;
        int nonCodecCapability;
        int onhooktime;
        int msgstate; /*!< voicemail message state */
@@ -366,6 +383,7 @@ struct mgcp_endpoint {
        /* struct ast_rtp *rtp; */
        /* struct sockaddr_in tmpdest; */
        /* message go the the endpoint and not the channel so they stay here */
+       struct ast_variable *chanvars;          /*!< Variables to set for channel created by user */
        struct mgcp_endpoint *next;
        struct mgcp_gateway *parent;
 };
@@ -389,12 +407,13 @@ static struct mgcp_gateway {
 /* Wildcard endpoint name */
        char wcardep[30];
        struct mgcp_message *msgs; /*!< gw msg queue */
-       ast_mutex_t msgs_lock;     /*!< queue lock */  
+       ast_mutex_t msgs_lock;     /*!< queue lock */
        int retransid;             /*!< retrans timer id */
        int delme;                 /*!< needed for reload */
+       int realtime;
        struct mgcp_response *responses;
        struct mgcp_gateway *next;
-} *gateways;
+} *gateways = NULL;
 
 AST_MUTEX_DEFINE_STATIC(mgcp_reload_lock);
 static int mgcp_reloading = 0;
@@ -410,19 +429,20 @@ static struct ast_frame  *mgcp_read(struct ast_channel *ast);
 static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp_request *req, char *msgrest);
 static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone);
 static int transmit_modify_request(struct mgcp_subchannel *sub);
+static int transmit_connect(struct mgcp_subchannel *sub);
 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername);
-static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs);
+static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs);
 static int transmit_connection_del(struct mgcp_subchannel *sub);
 static int transmit_audit_endpoint(struct mgcp_endpoint *p);
 static void start_rtp(struct mgcp_subchannel *sub);
-static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,  
+static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
                             int result, unsigned int ident, struct mgcp_request *resp);
 static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub);
-static int mgcp_do_reload(void);
-static int mgcp_reload(int fd, int argc, char *argv[]);
+static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
+static int reload_config(int reload);
 
-static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause);
-static int mgcp_call(struct ast_channel *ast, char *dest, int timeout);
+static struct ast_channel *mgcp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, int *cause);
+static int mgcp_call(struct ast_channel *ast, const char *dest, int timeout);
 static int mgcp_hangup(struct ast_channel *ast);
 static int mgcp_answer(struct ast_channel *ast);
 static struct ast_frame *mgcp_read(struct ast_channel *ast);
@@ -431,12 +451,18 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz
 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
-static int mgcp_devicestate(void *data);
-
-static const struct ast_channel_tech mgcp_tech = {
+static int mgcp_devicestate(const char *data);
+static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone);
+static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp);
+static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v);
+static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub);
+static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen);
+static struct ast_variable *add_var(const char *buf, struct ast_variable *list);
+static struct ast_variable *copy_vars(struct ast_variable *src);
+
+static struct ast_channel_tech mgcp_tech = {
        .type = "MGCP",
        .description = tdesc,
-       .capabilities = AST_FORMAT_ULAW,
        .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
        .requester = mgcp_request,
        .devicestate = mgcp_devicestate,
@@ -449,7 +475,8 @@ static const struct ast_channel_tech mgcp_tech = {
        .fixup = mgcp_fixup,
        .send_digit_begin = mgcp_senddigit_begin,
        .send_digit_end = mgcp_senddigit_end,
-       .bridge = ast_rtp_bridge,
+       .bridge = ast_rtp_instance_bridge,
+       .func_channel_read = acf_channel_read,
 };
 
 static void mwi_event_cb(const struct ast_event *event, void *userdata)
@@ -464,10 +491,16 @@ static int has_voicemail(struct mgcp_endpoint *p)
 {
        int new_msgs;
        struct ast_event *event;
+       char *mbox, *cntx;
+
+       cntx = mbox = ast_strdupa(p->mailbox);
+       strsep(&cntx, "@");
+       if (ast_strlen_zero(cntx))
+               cntx = "default";
 
        event = ast_event_get_cached(AST_EVENT_MWI,
-               AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, p->mailbox,
-               AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+               AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
+               AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx,
                AST_EVENT_IE_END);
 
        if (event) {
@@ -486,8 +519,7 @@ static int unalloc_sub(struct mgcp_subchannel *sub)
                ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name, p->parent->name);
                return -1;
        }
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
+       ast_debug(1, "Released sub %d of channel %s@%s\n", sub->id, p->name, p->parent->name);
 
        sub->owner = NULL;
        if (!ast_strlen_zero(sub->cxident)) {
@@ -500,10 +532,10 @@ static int unalloc_sub(struct mgcp_subchannel *sub)
        sub->alreadygone = 0;
        memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
        if (sub->rtp) {
-               ast_rtp_destroy(sub->rtp);
+               ast_rtp_instance_destroy(sub->rtp);
                sub->rtp = NULL;
        }
-       dump_cmd_queues(NULL, sub); /* SC */
+       dump_cmd_queues(NULL, sub);
        return 0;
 }
 
@@ -513,7 +545,7 @@ static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len)
        int res;
        if (gw->addr.sin_addr.s_addr)
                res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));
-       else 
+       else
                res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));
        if (res != len) {
                ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));
@@ -525,9 +557,7 @@ static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *re
 {
        struct mgcp_endpoint *p = sub->parent;
        int res;
-       if (mgcpdebug) {
-               ast_verbose("Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
-       }
+       ast_debug(1, "Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
        res = __mgcp_xmit(p->parent, resp->buf, resp->len);
        if (res > 0)
                res = 0;
@@ -538,9 +568,7 @@ static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
 {
        struct mgcp_endpoint *p = sub->parent;
        int res;
-       if (mgcpdebug) {
-               ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
-       }
+       ast_debug(1, "Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
        res = __mgcp_xmit(p->parent, req->data, req->len);
        if (res > 0)
                res = 0;
@@ -553,27 +581,24 @@ static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
        struct mgcp_message *cur, *q = NULL, *w, *prev;
 
        ast_mutex_lock(&gw->msgs_lock);
-       prev = NULL, cur = gw->msgs;
-       while (cur) {
+       for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
                if (!p || cur->owner_ep == p) {
-                       if (prev)
+                       if (prev) {
                                prev->next = cur->next;
-                       else
+                       } else {
                                gw->msgs = cur->next;
+                       }
 
-                       ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 
+                       ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n",
                                gw->name, cur->seqno);
 
                        w = cur;
-                       cur = cur->next;
                        if (q) {
                                w->next = q;
                        } else {
                                w->next = NULL;
                        }
                        q = w;
-               } else {
-                       prev = cur, cur=cur->next;
                }
        }
        ast_mutex_unlock(&gw->msgs_lock);
@@ -581,54 +606,51 @@ static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p)
        while (q) {
                cur = q;
                q = q->next;
-               free(cur);
+               ast_free(cur);
        }
 }
 
 static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f)
 {
-       for(;;) {
+       for (;;) {
                if (sub->owner) {
-                       if (!ast_mutex_trylock(&sub->owner->lock)) {
+                       if (!ast_channel_trylock(sub->owner)) {
                                ast_queue_frame(sub->owner, f);
-                               ast_mutex_unlock(&sub->owner->lock);
+                               ast_channel_unlock(sub->owner);
                                break;
                        } else {
-                               ast_mutex_unlock(&sub->lock);
-                               usleep(1);
-                               ast_mutex_lock(&sub->lock);
+                               DEADLOCK_AVOIDANCE(&sub->lock);
                        }
-               } else
+               } else {
                        break;
+               }
        }
 }
 
 static void mgcp_queue_hangup(struct mgcp_subchannel *sub)
 {
-       for(;;) {
+       for (;;) {
                if (sub->owner) {
-                       if (!ast_mutex_trylock(&sub->owner->lock)) {
+                       if (!ast_channel_trylock(sub->owner)) {
                                ast_queue_hangup(sub->owner);
-                               ast_mutex_unlock(&sub->owner->lock);
+                               ast_channel_unlock(sub->owner);
                                break;
                        } else {
-                               ast_mutex_unlock(&sub->lock);
-                               usleep(1);
-                               ast_mutex_lock(&sub->lock);
+                               DEADLOCK_AVOIDANCE(&sub->lock);
                        }
-               } else
+               } else {
                        break;
+               }
        }
 }
 
 static void mgcp_queue_control(struct mgcp_subchannel *sub, int control)
 {
-       struct ast_frame f = { AST_FRAME_CONTROL, };
-       f.subclass = control;
+       struct ast_frame f = { AST_FRAME_CONTROL, { control } };
        return mgcp_queue_frame(sub, &f);
 }
 
-static int retrans_pkt(void *data)
+static int retrans_pkt(const void *data)
 {
        struct mgcp_gateway *gw = (struct mgcp_gateway *)data;
        struct mgcp_message *cur, *exq = NULL, *w, *prev;
@@ -637,18 +659,12 @@ static int retrans_pkt(void *data)
        /* find out expired msgs */
        ast_mutex_lock(&gw->msgs_lock);
 
-       prev = NULL, cur = gw->msgs;
-       while (cur) {
+       for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
                if (cur->retrans < MAX_RETRANS) {
                        cur->retrans++;
-                       if (mgcpdebug) {
-                               ast_verbose("Retransmitting #%d transaction %u on [%s]\n",
-                                       cur->retrans, cur->seqno, gw->name);
-                       }
+                       ast_debug(1, "Retransmitting #%d transaction %u on [%s]\n",
+                               cur->retrans, cur->seqno, gw->name);
                        __mgcp_xmit(gw, cur->buf, cur->len);
-
-                       prev = cur;
-                       cur = cur->next;
                } else {
                        if (prev)
                                prev->next = cur->next;
@@ -659,7 +675,6 @@ static int retrans_pkt(void *data)
                                cur->seqno, gw->name);
 
                        w = cur;
-                       cur = cur->next;
 
                        if (exq) {
                                w->next = exq;
@@ -681,37 +696,31 @@ static int retrans_pkt(void *data)
        while (exq) {
                cur = exq;
                /* time-out transaction */
-               handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 
+               handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL);
                exq = exq->next;
-               free(cur);
+               ast_free(cur);
        }
 
        return res;
 }
 
 /* modified for the new transaction mechanism */
-static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, 
+static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
                             char *data, int len, unsigned int seqno)
 {
-       struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);
+       struct mgcp_message *msg;
        struct mgcp_message *cur;
-       struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL);
-       struct timeval tv;
+       struct mgcp_gateway *gw;
+       struct timeval now;
 
-       if (!msg) {
+       if (!(msg = ast_malloc(sizeof(*msg) + len))) {
                return -1;
        }
-       if (!gw) {
+       if (!(gw = ((p && p->parent) ? p->parent : NULL))) {
+               ast_free(msg);
                return -1;
        }
-/* SC
-       time(&t);
-       if (gw->messagepending && (gw->lastouttime + 20 < t)) {
-               ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d,  lastouttime: %ld, now: %ld.  Dumping pending queue\n",
-                       gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);
-               dump_queue(sub->parent);
-       }
-*/
+
        msg->owner_sub = sub;
        msg->owner_ep = p;
        msg->seqno = seqno;
@@ -721,51 +730,33 @@ static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
        memcpy(msg->buf, data, msg->len);
 
        ast_mutex_lock(&gw->msgs_lock);
-       cur = gw->msgs;
+       for (cur = gw->msgs; cur && cur->next; cur = cur->next);
        if (cur) {
-               while(cur->next)
-                       cur = cur->next;
                cur->next = msg;
        } else {
                gw->msgs = msg;
        }
 
-       if (gettimeofday(&tv, NULL) < 0) {
-               /* This shouldn't ever happen, but let's be sure */
-               ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
-       } else {
-               msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;
+       now = ast_tvnow();
+       msg->expire = now.tv_sec * 1000 + now.tv_usec / 1000 + DEFAULT_RETRANS;
 
-               if (gw->retransid == -1)
-                       gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
-       }
+       if (gw->retransid == -1)
+               gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);
        ast_mutex_unlock(&gw->msgs_lock);
-/* SC
-       if (!gw->messagepending) {
-               gw->messagepending = 1;
-               gw->lastout = seqno;
-               gw->lastouttime = t;
-*/
        __mgcp_xmit(gw, msg->buf, msg->len);
-               /* XXX Should schedule retransmission XXX */
-/* SC
-       } else
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);
-*/
+       /* XXX Should schedule retransmission XXX */
        return 0;
 }
 
 /* modified for new transport */
-static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub, 
+static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
                         struct mgcp_request *req, unsigned int seqno)
 {
        int res = 0;
        struct mgcp_request **queue, *q, *r, *t;
        ast_mutex_t *l;
 
-       if (option_debug)
-               ast_log(LOG_DEBUG, "Slow sequence is %d\n", p->slowsequence);
+       ast_debug(1, "Slow sequence is %d\n", p->slowsequence);
        if (p->slowsequence) {
                queue = &p->cmd_queue;
                l = &p->cmd_queue_lock;
@@ -778,12 +769,15 @@ static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
                        ast_mutex_lock(l);
                        q = sub->cx_queue;
                        /* delete pending cx cmds */
-                       while (q) {
-                               r = q->next;
-                               free(q);
-                               q = r;
+                       /* buggy sb5120 */
+                       if (!sub->parent->ncs) {
+                               while (q) {
+                                       r = q->next;
+                                       ast_free(q);
+                                       q = r;
+                               }
+                               *queue = NULL;
                        }
-                       *queue = NULL;
                        break;
 
                case MGCP_CMD_CRCX:
@@ -807,26 +801,21 @@ static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
                }
        }
 
-       r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));
-       if (!r) {
+       if (!(r = ast_malloc(sizeof(*r)))) {
                ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");
                ast_mutex_unlock(l);
                return -1;
        }
-       memcpy(r, req, sizeof(struct mgcp_request));
+       memcpy(r, req, sizeof(*r));
 
        if (!(*queue)) {
-               if (mgcpdebug) {
-                       ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, 
-                               ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
-               }
+               ast_debug(1, "Posting Request:\n%s to %s:%d\n", req->data,
+                       ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
 
                res = mgcp_postrequest(p, sub, req->data, req->len, seqno);
        } else {
-               if (mgcpdebug) {
-                       ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data, 
-                               ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
-               }
+               ast_debug(1, "Queueing Request:\n%s to %s:%d\n", req->data,
+                       ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
        }
 
        /* XXX find tail. We could also keep tail in the data struct for faster access */
@@ -843,7 +832,7 @@ static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
        return res;
 }
 
-static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
+static int mgcp_call(struct ast_channel *ast, const char *dest, int timeout)
 {
        int res;
        struct mgcp_endpoint *p;
@@ -853,10 +842,8 @@ static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
        struct varshead *headp;
        struct ast_var_t *current;
 
-       if (mgcpdebug) {
-               ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name);
-       }
-       sub = ast->tech_pvt;
+       ast_debug(3, "MGCP mgcp_call(%s)\n", ast_channel_name(ast));
+       sub = ast_channel_tech_pvt(ast);
        p = sub->parent;
        headp = &ast->varshead;
        AST_LIST_TRAVERSE(headp,current,entries) {
@@ -871,34 +858,26 @@ static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
        case MGCP_OFFHOOK:
                if (!ast_strlen_zero(distinctive_ring)) {
                        snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);
-                       if (mgcpdebug) {
-                               ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive callwait %s\n", tone);
-                       }
+                       ast_debug(3, "MGCP distinctive callwait %s\n", tone);
                } else {
-                       snprintf(tone, sizeof(tone), "L/wt");
-                       if (mgcpdebug) {
-                               ast_verbose(VERBOSE_PREFIX_3 "MGCP normal callwait %s\n", tone);
-                       }
+                       ast_copy_string(tone, (p->ncs ? "L/wt1" : "L/wt"), sizeof(tone));
+                       ast_debug(3, "MGCP normal callwait %s\n", tone);
                }
                break;
        case MGCP_ONHOOK:
        default:
                if (!ast_strlen_zero(distinctive_ring)) {
                        snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);
-                       if (mgcpdebug) {
-                               ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive ring %s\n", tone);
-                       }
+                       ast_debug(3, "MGCP distinctive ring %s\n", tone);
                } else {
-                       snprintf(tone, sizeof(tone), "L/rg");
-                       if (mgcpdebug) {
-                               ast_verbose(VERBOSE_PREFIX_3 "MGCP default ring\n");
-                       }
+                       ast_copy_string(tone, "L/rg", sizeof(tone));
+                       ast_debug(3, "MGCP default ring\n");
                }
                break;
        }
 
-       if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
-               ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);
+       if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
+               ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
                ast_mutex_unlock(&sub->lock);
                return -1;
        }
@@ -906,6 +885,7 @@ static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
        res = 0;
        sub->outgoing = 1;
        sub->cxmode = MGCP_CX_RECVONLY;
+       ast_setstate(ast, AST_STATE_RINGING);
        if (p->type == TYPE_LINE) {
                if (!sub->rtp) {
                        start_rtp(sub);
@@ -919,7 +899,9 @@ static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
                        transmit_modify_request(sub->next);
                }
 
-               transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);
+               transmit_notify_request_with_callerid(sub, tone,
+                       S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""),
+                       S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""));
                ast_setstate(ast, AST_STATE_RINGING);
 
                if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
@@ -932,47 +914,55 @@ static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
                res = -1;
        }
        ast_mutex_unlock(&sub->lock);
-       ast_queue_control(ast, AST_CONTROL_RINGING);
        return res;
 }
 
 static int mgcp_hangup(struct ast_channel *ast)
 {
-       struct mgcp_subchannel *sub = ast->tech_pvt;
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
        struct mgcp_endpoint *p = sub->parent;
+       struct ast_channel *bridged;
 
-       if (option_debug) {
-               ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);
-       }
-       if (!ast->tech_pvt) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
+       ast_debug(1, "mgcp_hangup(%s)\n", ast_channel_name(ast));
+       if (!ast_channel_tech_pvt(ast)) {
+               ast_debug(1, "Asked to hangup channel not connected\n");
                return 0;
        }
        if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");
+               ast_debug(1, "Invalid magic. MGCP subchannel freed up already.\n");
                return 0;
        }
        ast_mutex_lock(&sub->lock);
-       if (mgcpdebug) {
-               ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);
-       }
+       ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s\n", ast_channel_name(ast), p->name, p->parent->name);
 
        if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {
                /* check whether other channel is active. */
                if (!sub->next->owner) {
-                       if (p->dtmfmode & MGCP_DTMF_HYBRID)
+                       if (p->dtmfmode & MGCP_DTMF_HYBRID) {
                                p->dtmfmode &= ~MGCP_DTMF_INBAND;
-                       if (mgcpdebug) {
-                               ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
                        }
+                       ast_debug(2, "MGCP free dsp on %s@%s\n", p->name, p->parent->name);
                        ast_dsp_free(p->dsp);
                        p->dsp = NULL;
                }
        }
 
        sub->owner = NULL;
+
+       /* for deleting gate */
+       if (p->pktcgatealloc && sub->gate) {
+               sub->gate->gate_open = NULL;
+               sub->gate->gate_remove = NULL;
+               sub->gate->got_dq_gi = NULL;
+               sub->gate->tech_pvt = NULL;
+               if (sub->gate->state == GATE_ALLOC_PROGRESS || sub->gate->state == GATE_ALLOCATED) {
+                       ast_pktccops_gate_alloc(GATE_DEL, sub->gate, 0, 0, 0, 0, 0, 0, NULL, NULL);
+               } else {
+                       sub->gate->deltimer = time(NULL) + 5;
+               }
+               sub->gate = NULL;
+       }
+
        if (!ast_strlen_zero(sub->cxident)) {
                transmit_connection_del(sub);
        }
@@ -980,7 +970,11 @@ static int mgcp_hangup(struct ast_channel *ast)
        if ((sub == p->sub) && sub->next->owner) {
                if (p->hookstate == MGCP_OFFHOOK) {
                        if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
-                               transmit_notify_request_with_callerid(p->sub, "L/wt", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name);
+                               /* ncs fix! */
+                               bridged = ast_bridged_channel(sub->next->owner);
+                               transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"),
+                                       S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""),
+                                       S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, ""));
                        }
                } else {
                        /* set our other connection as the primary and swith over to it */
@@ -988,27 +982,33 @@ static int mgcp_hangup(struct ast_channel *ast)
                        p->sub->cxmode = MGCP_CX_RECVONLY;
                        transmit_modify_request(p->sub);
                        if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
-                               transmit_notify_request_with_callerid(p->sub, "L/rg", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name);
+                               bridged = ast_bridged_channel(sub->next->owner);
+                               transmit_notify_request_with_callerid(p->sub, "L/rg",
+                                       S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""),
+                                       S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, ""));
                        }
                }
 
        } else if ((sub == p->sub->next) && p->hookstate == MGCP_OFFHOOK) {
-               transmit_notify_request(sub, "L/v");
+               transmit_notify_request(sub, p->ncs ? "" : "L/v");
        } else if (p->hookstate == MGCP_OFFHOOK) {
                transmit_notify_request(sub, "L/ro");
        } else {
                transmit_notify_request(sub, "");
        }
 
-       ast->tech_pvt = NULL;
+       ast_channel_tech_pvt_set(ast, NULL);
        sub->alreadygone = 0;
        sub->outgoing = 0;
        sub->cxmode = MGCP_CX_INACTIVE;
        sub->callid[0] = '\0';
+       if (p) {
+               memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
+       }
        /* Reset temporary destination */
        memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));
        if (sub->rtp) {
-               ast_rtp_destroy(sub->rtp);
+               ast_rtp_instance_destroy(sub->rtp);
                sub->rtp = NULL;
        }
 
@@ -1017,21 +1017,16 @@ static int mgcp_hangup(struct ast_channel *ast)
        if ((p->hookstate == MGCP_ONHOOK) && (!sub->next->rtp)) {
                p->hidecallerid = 0;
                if (p->hascallwaiting && !p->callwaiting) {
-                       if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on %s\n", ast->name);
+                       ast_verb(3, "Enabling call waiting on %s\n", ast_channel_name(ast));
                        p->callwaiting = -1;
                }
                if (has_voicemail(p)) {
-                       if (mgcpdebug) {
-                               ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n", 
-                                       ast->name, p->name, p->parent->name);
-                       }
+                       ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(+)\n",
+                               ast_channel_name(ast), p->name, p->parent->name);
                        transmit_notify_request(sub, "L/vmwi(+)");
                } else {
-                       if (mgcpdebug) {
-                               ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n", 
-                                       ast->name, p->name, p->parent->name);
-                       }
+                       ast_debug(3, "MGCP mgcp_hangup(%s) on %s@%s set vmwi(-)\n",
+                               ast_channel_name(ast), p->name, p->parent->name);
                        transmit_notify_request(sub, "L/vmwi(-)");
                }
        }
@@ -1039,154 +1034,148 @@ static int mgcp_hangup(struct ast_channel *ast)
        return 0;
 }
 
-static int mgcp_show_endpoints(int fd, int argc, char *argv[])
+static char *handle_mgcp_show_endpoints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       struct mgcp_gateway  *g;
-       struct mgcp_endpoint *e;
+       struct mgcp_gateway  *mg;
+       struct mgcp_endpoint *me;
        int hasendpoints = 0;
+       struct ast_variable * v = NULL;
+
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "mgcp show endpoints";
+               e->usage =
+                       "Usage: mgcp show endpoints\n"
+                       "       Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
 
-       if (argc != 3) 
-               return RESULT_SHOWUSAGE;
+       if (a->argc != 3) {
+               return CLI_SHOWUSAGE;
+       }
        ast_mutex_lock(&gatelock);
-       g = gateways;
-       while(g) {
-               e = g->endpoints;
-               ast_cli(fd, "Gateway '%s' at %s (%s)\n", g->name, g->addr.sin_addr.s_addr ? ast_inet_ntoa(g->addr.sin_addr) : ast_inet_ntoa(g->defaddr.sin_addr), g->dynamic ? "Dynamic" : "Static");
-               while(e) {
-                       /* Don't show wilcard endpoint */
-                       if (strcmp(e->name, g->wcardep) !=0)
-                               ast_cli(fd, "   -- '%s@%s in '%s' is %s\n", e->name, g->name, e->context, e->sub->owner ? "active" : "idle");
+       for (mg = gateways; mg; mg = mg->next) {
+               ast_cli(a->fd, "Gateway '%s' at %s (%s%s)\n", mg->name, mg->addr.sin_addr.s_addr ? ast_inet_ntoa(mg->addr.sin_addr) : ast_inet_ntoa(mg->defaddr.sin_addr), mg->realtime ? "Realtime, " : "", mg->dynamic ? "Dynamic" : "Static");
+               for (me = mg->endpoints; me; me = me->next) {
+                       ast_cli(a->fd, "   -- '%s@%s in '%s' is %s\n", me->name, mg->name, me->context, me->sub->owner ? "active" : "idle");
+                       if (me->chanvars) {
+                               ast_cli(a->fd, "  Variables:\n");
+                               for (v = me->chanvars ; v ; v = v->next) {
+                                       ast_cli(a->fd, "    %s = '%s'\n", v->name, v->value);
+                               }
+                       }
                        hasendpoints = 1;
-                       e = e->next;
                }
                if (!hasendpoints) {
-                       ast_cli(fd, "   << No Endpoints Defined >>     ");
+                       ast_cli(a->fd, "   << No Endpoints Defined >>     ");
                }
-               g = g->next;
        }
        ast_mutex_unlock(&gatelock);
-       return RESULT_SUCCESS;
+       return CLI_SUCCESS;
 }
 
-static const char show_endpoints_usage[] = 
-"Usage: mgcp show endpoints\n"
-"       Lists all endpoints known to the MGCP (Media Gateway Control Protocol) subsystem.\n";
-
-static const char audit_endpoint_usage[] = 
-"Usage: mgcp audit endpoint <endpointid>\n"
-"       Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
-"       mgcp debug MUST be on to see the results of this command.\n";
-
-static const char debug_usage[] = 
-"Usage: mgcp set debug\n"
-"       Enables dumping of MGCP packets for debugging purposes\n";
-
-static const char no_debug_usage[] = 
-"Usage: mgcp set debug off\n"
-"       Disables dumping of MGCP packets for debugging purposes\n";
-
-static const char mgcp_reload_usage[] =
-"Usage: mgcp reload\n"
-"       Reloads MGCP configuration from mgcp.conf\n"
-"       Deprecated:  please use 'reload chan_mgcp.so' instead.\n";
-
-static int mgcp_audit_endpoint(int fd, int argc, char *argv[])
+static char *handle_mgcp_audit_endpoint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       struct mgcp_gateway  *g;
-       struct mgcp_endpoint *e;
+       struct mgcp_gateway  *mg;
+       struct mgcp_endpoint *me;
        int found = 0;
        char *ename,*gname, *c;
 
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "mgcp audit endpoint";
+               e->usage =
+                       "Usage: mgcp audit endpoint <endpointid>\n"
+                       "       Lists the capabilities of an endpoint in the MGCP (Media Gateway Control Protocol) subsystem.\n"
+                       "       mgcp debug MUST be on to see the results of this command.\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
        if (!mgcpdebug) {
-               return RESULT_SHOWUSAGE;
+               return CLI_SHOWUSAGE;
        }
-       if (argc != 4) 
-               return RESULT_SHOWUSAGE;
+       if (a->argc != 4)
+               return CLI_SHOWUSAGE;
        /* split the name into parts by null */
-       ename = argv[3];
-       gname = ename;
-       while (*gname) {
+       ename = ast_strdupa(a->argv[3]);
+       for (gname = ename; *gname; gname++) {
                if (*gname == '@') {
                        *gname = 0;
                        gname++;
                        break;
                }
-               gname++;
        }
-       if (gname[0] == '[')
+       if (gname[0] == '[') {
                gname++;
-       if ((c = strrchr(gname, ']')))
+       }
+       if ((c = strrchr(gname, ']'))) {
                *c = '\0';
+       }
        ast_mutex_lock(&gatelock);
-       g = gateways;
-       while(g) {
-               if (!strcasecmp(g->name, gname)) {
-                       e = g->endpoints;
-                       while(e) {
-                               if (!strcasecmp(e->name, ename)) {
+       for (mg = gateways; mg; mg = mg->next) {
+               if (!strcasecmp(mg->name, gname)) {
+                       for (me = mg->endpoints; me; me = me->next) {
+                               if (!strcasecmp(me->name, ename)) {
                                        found = 1;
-                                       transmit_audit_endpoint(e);
+                                       transmit_audit_endpoint(me);
                                        break;
                                }
-                               e = e->next;
                        }
                        if (found) {
                                break;
                        }
                }
-               g = g->next;
        }
        if (!found) {
-               ast_cli(fd, "   << Could not find endpoint >>     ");
+               ast_cli(a->fd, "   << Could not find endpoint >>     ");
        }
        ast_mutex_unlock(&gatelock);
-       return RESULT_SUCCESS;
+       return CLI_SUCCESS;
 }
 
-static int mgcp_do_debug(int fd, int argc, char *argv[])
+static char *handle_mgcp_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-       if (argc != 3)
-               return RESULT_SHOWUSAGE;
-       mgcpdebug = 1;
-       ast_cli(fd, "MGCP Debugging Enabled\n");
-       return RESULT_SUCCESS;
-}
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "mgcp set debug {on|off}";
+               e->usage =
+                       "Usage: mgcp set debug {on|off}\n"
+                       "       Enables/Disables dumping of MGCP packets for debugging purposes\n";     
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
 
-static int mgcp_no_debug(int fd, int argc, char *argv[])
-{
-       if (argc != 4)
-               return RESULT_SHOWUSAGE;
-       mgcpdebug = 0;
-       ast_cli(fd, "MGCP Debugging Disabled\n");
-       return RESULT_SUCCESS;
+       if (a->argc != e->args)
+               return CLI_SHOWUSAGE;
+
+       if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
+               mgcpdebug = 1;
+               ast_cli(a->fd, "MGCP Debugging Enabled\n");
+       } else if (!strncasecmp(a->argv[3], "off", 3)) {
+               mgcpdebug = 0;
+               ast_cli(a->fd, "MGCP Debugging Disabled\n");
+       } else {
+               return CLI_SHOWUSAGE;
+       }
+       return CLI_SUCCESS;
 }
 
 static struct ast_cli_entry cli_mgcp[] = {
-       { { "mgcp", "audit", "endpoint", NULL },
-       mgcp_audit_endpoint, "Audit specified MGCP endpoint",
-       audit_endpoint_usage },
-
-       { { "mgcp", "show", "endpoints", NULL },
-       mgcp_show_endpoints, "List defined MGCP endpoints",
-       show_endpoints_usage },
-
-       { { "mgcp", "set", "debug", NULL },
-       mgcp_do_debug, "Enable MGCP debugging",
-       debug_usage },
-
-       { { "mgcp", "set", "debug", "off", NULL },
-       mgcp_no_debug, "Disable MGCP debugging",
-       no_debug_usage },
-
-       { { "mgcp", "reload", NULL },
-       mgcp_reload, "Reload MGCP configuration",
-       mgcp_reload_usage },
+       AST_CLI_DEFINE(handle_mgcp_audit_endpoint, "Audit specified MGCP endpoint"),
+       AST_CLI_DEFINE(handle_mgcp_show_endpoints, "List defined MGCP endpoints"),
+       AST_CLI_DEFINE(handle_mgcp_set_debug, "Enable/Disable MGCP debugging"),
+       AST_CLI_DEFINE(mgcp_reload, "Reload MGCP configuration"),
 };
 
 static int mgcp_answer(struct ast_channel *ast)
 {
        int res = 0;
-       struct mgcp_subchannel *sub = ast->tech_pvt;
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
        struct mgcp_endpoint *p = sub->parent;
 
        ast_mutex_lock(&sub->lock);
@@ -1196,15 +1185,11 @@ static int mgcp_answer(struct ast_channel *ast)
        } else {
                transmit_modify_request(sub);
        }
-       /* verbose level check */
-       if (option_verbose > 2) {
-               ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_answer(%s) on %s@%s-%d\n", 
-                       ast->name, p->name, p->parent->name, sub->id);
-       }
-       if (ast->_state != AST_STATE_UP) {
+       ast_verb(3, "MGCP mgcp_answer(%s) on %s@%s-%d\n",
+                       ast_channel_name(ast), p->name, p->parent->name, sub->id);
+       if (ast_channel_state(ast) != AST_STATE_UP) {
                ast_setstate(ast, AST_STATE_UP);
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "mgcp_answer(%s)\n", ast->name);
+               ast_debug(1, "mgcp_answer(%s)\n", ast_channel_name(ast));
                transmit_notify_request(sub, "");
                transmit_modify_request(sub);
        }
@@ -1217,19 +1202,18 @@ static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
        /* Retrieve audio/etc from channel.  Assumes sub->lock is already held. */
        struct ast_frame *f;
 
-       f = ast_rtp_read(sub->rtp);
+       f = ast_rtp_instance_read(sub->rtp, 0);
        /* Don't send RFC2833 if we're not supposed to */
        if (f && (f->frametype == AST_FRAME_DTMF) && !(sub->parent->dtmfmode & MGCP_DTMF_RFC2833))
                return &ast_null_frame;
        if (sub->owner) {
                /* We already hold the channel lock */
                if (f->frametype == AST_FRAME_VOICE) {
-                       if (f->subclass != sub->owner->nativeformats) {
-                               if (option_debug)
-                                       ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
-                               sub->owner->nativeformats = f->subclass;
-                               ast_set_read_format(sub->owner, sub->owner->readformat);
-                               ast_set_write_format(sub->owner, sub->owner->writeformat);
+                       if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format)) {
+                               ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(&f->subclass.format));
+                               ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format);
+                               ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner));
+                               ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner));
                        }
                        /* Courtesy fearnor aka alex@pilosoft.com */
                        if ((sub->parent->dtmfmode & MGCP_DTMF_INBAND) && (sub->parent->dsp)) {
@@ -1247,7 +1231,7 @@ static struct ast_frame *mgcp_rtp_read(struct mgcp_subchannel *sub)
 static struct ast_frame *mgcp_read(struct ast_channel *ast)
 {
        struct ast_frame *f;
-       struct mgcp_subchannel *sub = ast->tech_pvt;
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
        ast_mutex_lock(&sub->lock);
        f = mgcp_rtp_read(sub);
        ast_mutex_unlock(&sub->lock);
@@ -1256,8 +1240,10 @@ static struct ast_frame *mgcp_read(struct ast_channel *ast)
 
 static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
 {
-       struct mgcp_subchannel *sub = ast->tech_pvt;
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
        int res = 0;
+       char buf[256];
+
        if (frame->frametype != AST_FRAME_VOICE) {
                if (frame->frametype == AST_FRAME_IMAGE)
                        return 0;
@@ -1266,17 +1252,26 @@ static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
                        return 0;
                }
        } else {
-               if (!(frame->subclass & ast->nativeformats)) {
-                       ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
-                               frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
-                       return -1;
+               if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
+                       ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
+                               ast_getformatname(&frame->subclass.format),
+                               ast_getformatname_multiple(buf, sizeof(buf), ast_channel_nativeformats(ast)),
+                               ast_getformatname(ast_channel_readformat(ast)),
+                               ast_getformatname(ast_channel_writeformat(ast)));
+                       /* return -1; */
                }
        }
        if (sub) {
                ast_mutex_lock(&sub->lock);
+               if (!sub->sdpsent && sub->gate) {
+                       if (sub->gate->state == GATE_ALLOCATED) {
+                               ast_debug(1, "GATE ALLOCATED, sending sdp\n");
+                               transmit_modify_with_sdp(sub, NULL, 0);
+                       }
+               }
                if ((sub->parent->sub == sub) || !sub->parent->singlepath) {
                        if (sub->rtp) {
-                               res =  ast_rtp_write(sub->rtp, frame);
+                               res =  ast_rtp_instance_write(sub->rtp, frame);
                        }
                }
                ast_mutex_unlock(&sub->lock);
@@ -1286,10 +1281,10 @@ static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame)
 
 static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
 {
-       struct mgcp_subchannel *sub = newchan->tech_pvt;
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(newchan);
 
        ast_mutex_lock(&sub->lock);
-       ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", oldchan->name, newchan->name);
+       ast_log(LOG_NOTICE, "mgcp_fixup(%s, %s)\n", ast_channel_name(oldchan), ast_channel_name(newchan));
        if (sub->owner != oldchan) {
                ast_mutex_unlock(&sub->lock);
                ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
@@ -1302,23 +1297,55 @@ static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
 
 static int mgcp_senddigit_begin(struct ast_channel *ast, char digit)
 {
-       /* Let asterisk play inband indications */
-       return -1;
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
+       struct mgcp_endpoint *p = sub->parent;
+       int res = 0;
+
+       ast_mutex_lock(&sub->lock);
+       if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
+               ast_debug(1, "Sending DTMF using inband/hybrid\n");
+               res = -1; /* Let asterisk play inband indications */
+       } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
+               ast_debug(1, "Sending DTMF using RFC2833");
+               ast_rtp_instance_dtmf_begin(sub->rtp, digit);
+       } else {
+               ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
+       }
+       ast_mutex_unlock(&sub->lock);
+
+       return res;
 }
 
 static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
 {
-       struct mgcp_subchannel *sub = ast->tech_pvt;
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
+       struct mgcp_endpoint *p = sub->parent;
+       int res = 0;
        char tmp[4];
 
-       tmp[0] = 'D';
-       tmp[1] = '/';
-       tmp[2] = digit;
-       tmp[3] = '\0';
        ast_mutex_lock(&sub->lock);
-       transmit_notify_request(sub, tmp);
+       if (p->dtmfmode & MGCP_DTMF_INBAND || p->dtmfmode & MGCP_DTMF_HYBRID) {
+               ast_debug(1, "Stopping DTMF using inband/hybrid\n");
+               res = -1; /* Tell Asterisk to stop inband indications */
+       } else if (p->dtmfmode & MGCP_DTMF_RFC2833) {
+               ast_debug(1, "Stopping DTMF using RFC2833\n");
+               if (sub->parent->ncs) {
+                       tmp[0] = digit;
+                       tmp[1] = '\0';
+               } else {
+                       tmp[0] = 'D';
+                       tmp[1] = '/';
+                       tmp[2] = digit;
+                       tmp[3] = '\0';
+               }
+               transmit_notify_request(sub, tmp);
+               ast_rtp_instance_dtmf_end(sub->rtp, digit);
+       } else {
+               ast_log(LOG_ERROR, "Don't know about DTMF_MODE %d\n", p->dtmfmode);
+       }
        ast_mutex_unlock(&sub->lock);
-       return -1; /* Return non-zero so that Asterisk will stop the inband indications */
+
+       return res;
 }
 
 /*!
@@ -1330,7 +1357,7 @@ static int mgcp_senddigit_end(struct ast_channel *ast, char digit, unsigned int
  *
  *  \return device status result (from devicestate.h) AST_DEVICE_INVALID (not available) or AST_DEVICE_UNKNOWN (available but unknown state)
  */
-static int mgcp_devicestate(void *data)
+static int mgcp_devicestate(const char *data)
 {
        struct mgcp_gateway  *g;
        struct mgcp_endpoint *e = NULL;
@@ -1345,22 +1372,20 @@ static int mgcp_devicestate(void *data)
                goto error;
 
        ast_mutex_lock(&gatelock);
-       g = gateways;
-       while (g) {
+       for (g = gateways; g; g = g->next) {
                if (strcasecmp(g->name, gw) == 0) {
                        e = g->endpoints;
                        break;
                }
-               g = g->next;
        }
 
        if (!e)
                goto error;
 
-       while (e) {
-               if (strcasecmp(e->name, endpt) == 0)
+       for (; e; e = e->next) {
+               if (strcasecmp(e->name, endpt) == 0) {
                        break;
-               e = e->next;
+               }
        }
 
        if (!e)
@@ -1412,27 +1437,31 @@ static char *control2str(int ind) {
 
 static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen)
 {
-       struct mgcp_subchannel *sub = ast->tech_pvt;
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(ast);
        int res = 0;
 
-       if (mgcpdebug) {
-               ast_verbose(VERBOSE_PREFIX_3 "MGCP asked to indicate %d '%s' condition on channel %s\n",
-                       ind, control2str(ind), ast->name);
-       }
+       ast_debug(3, "MGCP asked to indicate %d '%s' condition on channel %s\n",
+               ind, control2str(ind), ast_channel_name(ast));
        ast_mutex_lock(&sub->lock);
        switch(ind) {
        case AST_CONTROL_RINGING:
 #ifdef DLINK_BUGGY_FIRMWARE    
                transmit_notify_request(sub, "rt");
 #else
-               transmit_notify_request(sub, "G/rt");
-#endif         
+               if (!sub->sdpsent) { /* will hide the inband progress!!! */
+                       transmit_notify_request(sub, sub->parent->ncs ? "L/rt" : "G/rt");
+               }
+#endif
                break;
        case AST_CONTROL_BUSY:
                transmit_notify_request(sub, "L/bz");
                break;
+       case AST_CONTROL_INCOMPLETE:
+               /* We do not currently support resetting of the Interdigit Timer, so treat
+                * Incomplete control frames as a congestion response
+                */
        case AST_CONTROL_CONGESTION:
-               transmit_notify_request(sub, "G/cg");
+               transmit_notify_request(sub, sub->parent->ncs ? "L/cg" : "G/cg");
                break;
        case AST_CONTROL_HOLD:
                ast_moh_start(ast, data, NULL);
@@ -1440,6 +1469,15 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz
        case AST_CONTROL_UNHOLD:
                ast_moh_stop(ast);
                break;
+       case AST_CONTROL_SRCUPDATE:
+               ast_rtp_instance_update_source(sub->rtp);
+               break;
+       case AST_CONTROL_SRCCHANGE:
+               ast_rtp_instance_change_source(sub->rtp);
+               break;
+       case AST_CONTROL_PROGRESS:
+       case AST_CONTROL_PROCEEDING:
+               transmit_modify_request(sub);
        case -1:
                transmit_notify_request(sub, "");
                break;
@@ -1451,84 +1489,94 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz
        return res;
 }
 
-static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
+static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, const char *linkedid)
 {
        struct ast_channel *tmp;
+       struct ast_variable *v = NULL;
        struct mgcp_endpoint *i = sub->parent;
-       int fmt;
+       struct ast_format tmpfmt;
 
-       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
+       tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, linkedid, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
        if (tmp) {
-               tmp->tech = &mgcp_tech;
-               tmp->nativeformats = i->capability;
-               if (!tmp->nativeformats)
-                       tmp->nativeformats = capability;
-               fmt = ast_best_codec(tmp->nativeformats);
-               ast_string_field_build(tmp, name, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
-               if (sub->rtp)
-                       tmp->fds[0] = ast_rtp_fd(sub->rtp);
+               ast_channel_tech_set(tmp, &mgcp_tech);
+               ast_format_cap_copy(ast_channel_nativeformats(tmp), i->cap);
+               if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
+                       ast_format_cap_copy(ast_channel_nativeformats(tmp), global_capability);
+               }
+               if (sub->rtp) {
+                       ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
+               }
                if (i->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID)) {
                        i->dsp = ast_dsp_new();
-                       ast_dsp_set_features(i->dsp,DSP_FEATURE_DTMF_DETECT);
+                       ast_dsp_set_features(i->dsp, DSP_FEATURE_DIGIT_DETECT);
                        /* this is to prevent clipping of dtmf tones during dsp processing */
-                       ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
+                       ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_NOQUELCH);
                } else {
                        i->dsp = NULL;
                }
                if (state == AST_STATE_RING)
-                       tmp->rings = 1;
-               tmp->writeformat = fmt;
-               tmp->rawwriteformat = fmt;
-               tmp->readformat = fmt;
-               tmp->rawreadformat = fmt;
-               tmp->tech_pvt = sub;
+                       ast_channel_rings_set(tmp, 1);
+
+               ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
+               ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
+               ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
+               ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
+               ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
+               ast_channel_tech_pvt_set(tmp, sub);
                if (!ast_strlen_zero(i->language))
-                       ast_string_field_set(tmp, language, i->language);
+                       ast_channel_language_set(tmp, i->language);
                if (!ast_strlen_zero(i->accountcode))
-                       ast_string_field_set(tmp, accountcode, i->accountcode);
+                       ast_channel_accountcode_set(tmp, i->accountcode);
                if (i->amaflags)
-                       tmp->amaflags = i->amaflags;
+                       ast_channel_amaflags_set(tmp, i->amaflags);
                sub->owner = tmp;
                ast_module_ref(ast_module_info->self);
                tmp->callgroup = i->callgroup;
                tmp->pickupgroup = i->pickupgroup;
-               ast_string_field_set(tmp, call_forward, i->call_forward);
-               ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
-               ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
+               ast_channel_call_forward_set(tmp, i->call_forward);
+               ast_channel_context_set(tmp, i->context);
+               ast_channel_exten_set(tmp, i->exten);
 
                /* Don't use ast_set_callerid() here because it will
                 * generate a needless NewCallerID event */
-               tmp->cid.cid_num = ast_strdup(i->cid_num);
-               tmp->cid.cid_ani = ast_strdup(i->cid_num);
-               tmp->cid.cid_name = ast_strdup(i->cid_name);
-               
-               if (!i->adsi)
-                       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
-               tmp->priority = 1;
-               if (sub->rtp)
+               if (!ast_strlen_zero(i->cid_num)) {
+                       tmp->caller.ani.number.valid = 1;
+                       tmp->caller.ani.number.str = ast_strdup(i->cid_num);
+               }
+
+               if (!i->adsi) {
+                       ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
+               }
+               ast_channel_priority_set(tmp, 1);
+
+               /* Set channel variables for this call from configuration */
+               for (v = i->chanvars ; v ; v = v->next) {
+                       char valuebuf[1024];
+                       pbx_builtin_setvar_helper(tmp, v->name, ast_get_encoded_str(v->value, valuebuf, sizeof(valuebuf)));
+               }
+
+               if (sub->rtp) {
                        ast_jb_configure(tmp, &global_jbconf);
+               }
                if (state != AST_STATE_DOWN) {
                        if (ast_pbx_start(tmp)) {
-                               ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
+                               ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
                                ast_hangup(tmp);
                                tmp = NULL;
                        }
                }
-               /* verbose level check */
-               if (option_verbose > 2) {
-                       ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_new(%s) created in state: %s\n",
-                               tmp->name, ast_state2str(state));
-               }
+               ast_verb(3, "MGCP mgcp_new(%s) created in state: %s\n",
+                               ast_channel_name(tmp), ast_state2str(state));
        } else {
                ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
        }
        return tmp;
 }
 
-static char* get_sdp_by_line(char* line, char *name, int nameLen)
+static char *get_sdp_by_line(char* line, char *name, int nameLen)
 {
        if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
-               char* r = line + nameLen + 1;
+               char *r = line + nameLen + 1;
                while (*r && (*r < 33)) ++r;
                return r;
        }
@@ -1541,19 +1589,19 @@ static char *get_sdp(struct mgcp_request *req, char *name)
        int len = strlen(name);
        char *r;
 
-       for (x=0; x<req->lines; x++) {
+       for (x = 0; x < req->lines; x++) {
                r = get_sdp_by_line(req->line[x], name, len);
                if (r[0] != '\0') return r;
        }
        return "";
 }
 
-static void sdpLineNum_iterator_init(int* iterator)
+static void sdpLineNum_iterator_init(int *iterator)
 {
        *iterator = 0;
 }
 
-static char* get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name)
+static char *get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name)
 {
        int len = strlen(name);
        char *r;
@@ -1564,53 +1612,148 @@ static char* get_sdp_iterate(int* iterator, struct mgcp_request *req, char *name
        return "";
 }
 
-static char *__get_header(struct mgcp_request *req, char *name, int *start)
+static char *__get_header(struct mgcp_request *req, char *name, int *start, char *def)
 {
        int x;
        int len = strlen(name);
        char *r;
-       for (x=*start;x<req->headers;x++) {
-               if (!strncasecmp(req->header[x], name, len) && 
+       for (x = *start; x < req->headers; x++) {
+               if (!strncasecmp(req->header[x], name, len) &&
                    (req->header[x][len] == ':')) {
                        r = req->header[x] + len + 1;
-                       while(*r && (*r < 33))
+                       while (*r && (*r < 33)) {
                                r++;
-                       *start = x+1;
+                       }
+                       *start = x + 1;
                        return r;
                }
        }
        /* Don't return NULL, so get_header is always a valid pointer */
-       return "";
+       return def;
 }
 
 static char *get_header(struct mgcp_request *req, char *name)
 {
        int start = 0;
-       return __get_header(req, name, &start);
+       return __get_header(req, name, &start, "");
 }
 
 /*! \brief get_csv: (SC:) get comma separated value */
-static char *get_csv(char *c, int *len, char **next) 
+static char *get_csv(char *c, int *len, char **next)
 {
        char *s;
 
        *next = NULL, *len = 0;
        if (!c) return NULL;
 
-       while (*c && (*c < 33 || *c == ','))
+       while (*c && (*c < 33 || *c == ',')) {
                c++;
+       }
 
        s = c;
-       while (*c && (*c >= 33 && *c != ','))
+       while (*c && (*c >= 33 && *c != ',')) {
                c++, (*len)++;
+       }
        *next = c;
 
-       if (*len == 0)
+       if (*len == 0) {
                s = NULL, *next = NULL;
+       }
 
        return s;
 }
 
+static struct mgcp_gateway *find_realtime_gw(char *name, char *at, struct sockaddr_in *sin)
+{
+       struct mgcp_gateway *g = NULL;
+       struct ast_variable *mgcpgwconfig = NULL;
+       struct ast_variable *gwv, *epname = NULL;
+       struct mgcp_endpoint *e;
+       char lines[256];
+       int i, j;
+
+       ast_debug(1, "*** find Realtime MGCPGW\n");
+
+       if (!(i = ast_check_realtime("mgcpgw")) || !(j = ast_check_realtime("mgcpep"))) {
+               return NULL;
+       }
+
+       if (ast_strlen_zero(at)) {
+               ast_debug(1, "null gw name\n");
+               return NULL;
+       }
+
+       if (!(mgcpgwconfig = ast_load_realtime("mgcpgw", "name", at, NULL))) {
+               return NULL;
+       }
+
+       /*!
+        * \note This is a fairly odd way of instantiating lines.  Instead of each
+        * line created by virtue of being in the database (and loaded via
+        * ast_load_realtime_multientry), this code forces a specific order with a
+        * "lines" entry in the "mgcpgw" record.  This has benefits, because as with
+        * chan_dahdi, values are inherited across definitions.  The downside is
+        * that it's not as clear what the values will be simply by looking at a
+        * single row in the database, and it's probable that the sanest configuration
+        * should have the first column in the "mgcpep" table be "clearvars", with a
+        * static value of "all", if any variables are set at all.  It may be worth
+        * making this assumption explicit in the code in the future, and then just
+        * using ast_load_realtime_multientry for the "mgcpep" records.
+        */
+       lines[0] = '\0';
+       for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
+               if (!strcasecmp(gwv->name, "lines")) {
+                       ast_copy_string(lines, gwv->value, sizeof(lines));
+                       break;
+               }
+       }
+       /* Position gwv at the end of the list */
+       for (gwv = gwv && gwv->next ? gwv : mgcpgwconfig; gwv->next; gwv = gwv->next);
+
+       if (!ast_strlen_zero(lines)) {
+               AST_DECLARE_APP_ARGS(args,
+                       AST_APP_ARG(line)[100];
+               );
+               AST_STANDARD_APP_ARGS(args, lines);
+               for (i = 0; i < args.argc; i++) {
+                       gwv->next = ast_load_realtime("mgcpep", "name", at, "line", args.line[i], NULL);
+
+                       /* Remove "line" AND position gwv at the end of the list. */
+                       for (epname = NULL; gwv->next; gwv = gwv->next) {
+                               if (!strcasecmp(gwv->next->name, "line")) {
+                                       /* Remove it from the list */
+                                       epname = gwv->next;
+                                       gwv->next = gwv->next->next;
+                               }
+                       }
+                       /* Since "line" instantiates the configuration, we have to move it to the end. */
+                       if (epname) {
+                               gwv->next = epname;
+                               epname->next = NULL;
+                               gwv = gwv->next;
+                       }
+               }
+       }
+       for (gwv = mgcpgwconfig; gwv; gwv = gwv->next) {
+               ast_debug(1, "MGCP Realtime var: %s => %s\n", gwv->name, gwv->value);
+       }
+
+       if (mgcpgwconfig) {
+               g = build_gateway(at, mgcpgwconfig);
+               ast_variables_destroy(mgcpgwconfig);
+       }
+       if (g) {
+               g->next = gateways;
+               g->realtime = 1;
+               gateways = g;
+               for (e = g->endpoints; e; e = e->next) {
+                       transmit_audit_endpoint(e);
+                       e->needaudit = 0;
+               }
+       }
+       return g;
+}
+
 static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, struct sockaddr_in *sin)
 {
        struct mgcp_endpoint *p = NULL;
@@ -1632,98 +1775,81 @@ static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, s
        if (at && (at[0] == '[')) {
                at++;
                c = strrchr(at, ']');
-               if (c)
+               if (c) {
                        *c = '\0';
+               }
        }
-       g = gateways;
-       while(g) {
-               if ((!name || !strcasecmp(g->name, at)) && 
+       for (g = gateways ? gateways : find_realtime_gw(name, at, sin); g; g = g->next ? g->next : find_realtime_gw(name, at, sin)) {
+               if ((!name || !strcasecmp(g->name, at)) &&
                    (sin || g->addr.sin_addr.s_addr || g->defaddr.sin_addr.s_addr)) {
                        /* Found the gateway.  If it's dynamic, save it's address -- now for the endpoint */
                        if (sin && g->dynamic && name) {
                                if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
                                        (g->addr.sin_port != sin->sin_port)) {
                                        memcpy(&g->addr, sin, sizeof(g->addr));
-                                       if (ast_ouraddrfor(&g->addr.sin_addr, &g->ourip))
-                                               memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
+                                       {
+                                               struct ast_sockaddr tmp1, tmp2;
+                                               struct sockaddr_in tmp3 = {0,};
+
+                                               tmp3.sin_addr = g->ourip;
+                                               ast_sockaddr_from_sin(&tmp1, &g->addr);
+                                               ast_sockaddr_from_sin(&tmp2, &tmp3);
+                                               if (ast_ouraddrfor(&tmp1, &tmp2)) {
+                                                       memcpy(&g->ourip, &__ourip, sizeof(g->ourip));
+                                               }
+                                               ast_sockaddr_to_sin(&tmp2, &tmp3);
+                                               g->ourip = tmp3.sin_addr;
+                                       }
+                                       ast_verb(3, "Registered MGCP gateway '%s' at %s port %d\n", g->name, ast_inet_ntoa(g->addr.sin_addr), ntohs(g->addr.sin_port));
                                }
-                       }
                        /* not dynamic, check if the name matches */
-                       else if (name) {
+                       } else if (name) {
                                if (strcasecmp(g->name, at)) {
                                        g = g->next;
                                        continue;
                                }
-                       }
                        /* not dynamic, no name, check if the addr matches */
-                       else if (!name && sin) {
-                               if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
+                       } else if (!name && sin) {
+                               if ((g->addr.sin_addr.s_addr != sin->sin_addr.s_addr) ||
                                    (g->addr.sin_port != sin->sin_port)) {
-                                       g = g->next;
+                                       if(!g->next)
+                                               g = find_realtime_gw(name, at, sin);
+                                       else
+                                               g = g->next;
                                        continue;
                                }
                        } else {
-                               g = g->next;
                                continue;
                        }
-                       /* SC */
-                       p = g->endpoints;
-                       while(p) {
-                               if (option_debug)
-                                       ast_log(LOG_DEBUG, "Searching on %s@%s for subchannel\n",
-                                               p->name, g->name);
+                       for (p = g->endpoints; p; p = p->next) {
+                               ast_debug(1, "Searching on %s@%s for subchannel\n", p->name, g->name);
                                if (msgid) {
-#if 0 /* new transport mech */
-                                       sub = p->sub;
-                                       do {
-                                               if (option_debug)
-                                                       ast_log(LOG_DEBUG, "Searching on %s@%s-%d for subchannel with lastout: %d\n",
-                                                               p->name, g->name, sub->id, msgid);
-                                               if (sub->lastout == msgid) {
-                                                       if (option_debug)
-                                                               ast_log(LOG_DEBUG, "Found subchannel sub%d to handle request %d sub->lastout: %d\n",
-                                                                       sub->id, msgid, sub->lastout);
-                                                       found = 1;
-                                                       break;
-                                               }
-                                               sub = sub->next;
-                                       } while (sub != p->sub);
-                                       if (found) {
-                                               break;
-                                       }
-#endif
-                                       /* SC */
                                        sub = p->sub;
                                        found = 1;
-                                       /* SC */
                                        break;
                                } else if (name && !strcasecmp(p->name, tmp)) {
-                                       if (option_debug)
-                                               ast_log(LOG_DEBUG, "Coundn't determine subchannel, assuming current master %s@%s-%d\n", 
-                                                       p->name, g->name, p->sub->id);
+                                       ast_debug(1, "Coundn't determine subchannel, assuming current master %s@%s-%d\n",
+                                               p->name, g->name, p->sub->id);
                                        sub = p->sub;
                                        found = 1;
                                        break;
                                }
-                               p = p->next;
                        }
                        if (sub && found) {
                                ast_mutex_lock(&sub->lock);
                                break;
                        }
                }
-               g = g->next;
        }
        ast_mutex_unlock(&gatelock);
        if (!sub) {
                if (name) {
-                       if (g)
+                       if (g) {
                                ast_log(LOG_NOTICE, "Endpoint '%s' not found on gateway '%s'\n", tmp, at);
-                       else
+                       } else {
                                ast_log(LOG_NOTICE, "Gateway '%s' (and thus its endpoint '%s') does not exist\n", at, tmp);
-               } 
+                       }
+               }
        }
        return sub;
 }
@@ -1737,13 +1863,11 @@ static void parse(struct mgcp_request *req)
 
        /* First header starts immediately */
        req->header[f] = c;
-       while(*c) {
+       for (; *c; c++) {
                if (*c == '\n') {
                        /* We've got a new header */
                        *c = 0;
-#if 0
-                       printf("Header: %s (%d)\n", req->header[f], strlen(req->header[f]));
-#endif                 
+                       ast_debug(3, "Header: %s (%d)\n", req->header[f], (int) strlen(req->header[f]));
                        if (ast_strlen_zero(req->header[f])) {
                                /* Line by itself means we're now in content */
                                c++;
@@ -1751,82 +1875,81 @@ static void parse(struct mgcp_request *req)
                        }
                        if (f >= MGCP_MAX_HEADERS - 1) {
                                ast_log(LOG_WARNING, "Too many MGCP headers...\n");
-                       } else
+                       } else {
                                f++;
+                       }
                        req->header[f] = c + 1;
                } else if (*c == '\r') {
                        /* Ignore but eliminate \r's */
                        *c = 0;
                }
-               c++;
        }
        /* Check for last header */
-       if (!ast_strlen_zero(req->header[f])) 
+       if (!ast_strlen_zero(req->header[f])) {
                f++;
+       }
        req->headers = f;
        /* Now we process any mime content */
        f = 0;
        req->line[f] = c;
-       while(*c) {
+       for (; *c; c++) {
                if (*c == '\n') {
                        /* We've got a new line */
                        *c = 0;
-#if 0
-                       printf("Line: %s (%d)\n", req->line[f], strlen(req->line[f]));
-#endif                 
+                       ast_debug(3, "Line: %s (%d)\n", req->line[f], (int) strlen(req->line[f]));
                        if (f >= MGCP_MAX_LINES - 1) {
                                ast_log(LOG_WARNING, "Too many SDP lines...\n");
-                       } else
+                       } else {
                                f++;
+                       }
                        req->line[f] = c + 1;
                } else if (*c == '\r') {
                        /* Ignore and eliminate \r's */
                        *c = 0;
                }
-               c++;
        }
        /* Check for last line */
-       if (!ast_strlen_zero(req->line[f])) 
+       if (!ast_strlen_zero(req->line[f])) {
                f++;
+       }
        req->lines = f;
        /* Parse up the initial header */
        c = req->header[0];
-       while(*c && *c < 33) c++;
+       while (*c && *c < 33) c++;
        /* First the verb */
        req->verb = c;
-       while(*c && (*c > 32)) c++;
+       while (*c && (*c > 32)) c++;
        if (*c) {
                *c = '\0';
                c++;
-               while(*c && (*c < 33)) c++;
+               while (*c && (*c < 33)) c++;
                req->identifier = c;
-               while(*c && (*c > 32)) c++;
+               while (*c && (*c > 32)) c++;
                if (*c) {
                        *c = '\0';
                        c++;
-                       while(*c && (*c < 33)) c++;
+                       while (*c && (*c < 33)) c++;
                        req->endpoint = c;
-                       while(*c && (*c > 32)) c++;
+                       while (*c && (*c > 32)) c++;
                        if (*c) {
                                *c = '\0';
                                c++;
-                               while(*c && (*c < 33)) c++;
+                               while (*c && (*c < 33)) c++;
                                req->version = c;
-                               while(*c && (*c > 32)) c++;
-                               while(*c && (*c < 33)) c++;
-                               while(*c && (*c > 32)) c++;
+                               while (*c && (*c > 32)) c++;
+                               while (*c && (*c < 33)) c++;
+                               while (*c && (*c > 32)) c++;
                                *c = '\0';
                        }
                }
        }
-               
-       if (mgcpdebug) {
-               ast_verbose("Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
+
+       ast_debug(1, "Verb: '%s', Identifier: '%s', Endpoint: '%s', Version: '%s'\n",
                        req->verb, req->identifier, req->endpoint, req->version);
-               ast_verbose("%d headers, %d lines\n", req->headers, req->lines);
-       }
-       if (*c) 
+       ast_debug(1, "%d headers, %d lines\n", req->headers, req->lines);
+       if (*c) {
                ast_log(LOG_WARNING, "Odd content, extra stuff left over ('%s')\n", c);
+       }
 }
 
 static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
@@ -1837,13 +1960,16 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
        char host[258];
        int len;
        int portno;
-       int peercapability, peerNonCodecCapability;
+       struct ast_format_cap *peercap;
+       int peerNonCodecCapability;
        struct sockaddr_in sin;
+       struct ast_sockaddr sin_tmp;
        char *codecs;
        struct ast_hostent ahp; struct hostent *hp;
        int codec, codec_count=0;
        int iterator;
        struct mgcp_endpoint *p = sub->parent;
+       char tmp1[256], tmp2[256], tmp3[256];
 
        /* Get codec and RTP info from SDP */
        m = get_sdp(req, "m");
@@ -1862,28 +1988,28 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
                ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
                return -1;
        }
-       if (sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) {
-               ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m); 
+       if (sscanf(m, "audio %30d RTP/AVP %n", &portno, &len) != 1) {
+               ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
                return -1;
        }
        sin.sin_family = AF_INET;
        memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
        sin.sin_port = htons(portno);
-       ast_rtp_set_peer(sub->rtp, &sin);
-#if 0
-       printf("Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
-#endif 
+       ast_sockaddr_from_sin(&sin_tmp, &sin);
+       ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
+       ast_debug(3, "Peer RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
        /* Scan through the RTP payload types specified in a "m=" line: */
-       ast_rtp_pt_clear(sub->rtp);
+       ast_rtp_codecs_payloads_clear(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp);
        codecs = ast_strdupa(m + len);
        while (!ast_strlen_zero(codecs)) {
-               if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
-                       if (codec_count)
+               if (sscanf(codecs, "%30d%n", &codec, &len) != 1) {
+                       if (codec_count) {
                                break;
+                       }
                        ast_log(LOG_WARNING, "Error in codec string '%s' at '%s'\n", m, codecs);
                        return -1;
                }
-               ast_rtp_set_m_type(sub->rtp, codec);
+               ast_rtp_codecs_payloads_set_m_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec);
                codec_count++;
                codecs += len;
        }
@@ -1893,29 +2019,34 @@ static int process_sdp(struct mgcp_subchannel *sub, struct mgcp_request *req)
        sdpLineNum_iterator_init(&iterator);
        while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
                char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
-               if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2)
+               if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) != 2)
                        continue;
                /* Note: should really look at the 'freq' and '#chans' params too */
-               ast_rtp_set_rtpmap_type(sub->rtp, codec, "audio", mimeSubtype, 0);
+               ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, codec, "audio", mimeSubtype, 0);
        }
 
        /* Now gather all of the codecs that were asked for: */
-       ast_rtp_get_current_formats(sub->rtp, &peercapability, &peerNonCodecCapability);
-       p->capability = capability & peercapability;
-       if (mgcpdebug) {
-               ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
-                       capability, peercapability, p->capability);
-               ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
-                       nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
-       }
-       if (!p->capability) {
+       if (!(peercap = ast_format_cap_alloc_nolock())) {
+               return -1;
+       }
+       ast_rtp_codecs_payload_formats(ast_rtp_instance_get_codecs(sub->rtp), peercap, &peerNonCodecCapability);
+       ast_format_cap_joint_copy(global_capability, peercap, p->cap);
+       ast_debug(1, "Capabilities: us - %s, them - %s, combined - %s\n",
+               ast_getformatname_multiple(tmp1, sizeof(tmp1), global_capability),
+               ast_getformatname_multiple(tmp2, sizeof(tmp2), peercap),
+               ast_getformatname_multiple(tmp3, sizeof(tmp3), p->cap));
+       peercap = ast_format_cap_destroy(peercap);
+
+       ast_debug(1, "Non-codec capabilities: us - %d, them - %d, combined - %d\n",
+               nonCodecCapability, peerNonCodecCapability, p->nonCodecCapability);
+       if (ast_format_cap_is_empty(p->cap)) {
                ast_log(LOG_WARNING, "No compatible codecs!\n");
                return -1;
        }
        return 0;
 }
 
-static int add_header(struct mgcp_request *req, char *var, char *value)
+static int add_header(struct mgcp_request *req, const char *var, const char *value)
 {
        if (req->len >= sizeof(req->data) - 4) {
                ast_log(LOG_WARNING, "Out of space, can't add anymore\n");
@@ -1928,13 +2059,13 @@ static int add_header(struct mgcp_request *req, char *var, char *value)
        req->header[req->headers] = req->data + req->len;
        snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s: %s\r\n", var, value);
        req->len += strlen(req->header[req->headers]);
-       if (req->headers < MGCP_MAX_HEADERS)
+       if (req->headers < MGCP_MAX_HEADERS) {
                req->headers++;
-       else {
+       } else {
                ast_log(LOG_WARNING, "Out of header space\n");
                return -1;
        }
-       return 0;       
+       return 0;
 }
 
 static int add_line(struct mgcp_request *req, char *line)
@@ -1945,19 +2076,19 @@ static int add_line(struct mgcp_request *req, char *line)
        }
        if (!req->lines) {
                /* Add extra empty return */
-               snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
+               ast_copy_string(req->data + req->len, "\r\n", sizeof(req->data) - req->len);
                req->len += strlen(req->data + req->len);
        }
        req->line[req->lines] = req->data + req->len;
        snprintf(req->line[req->lines], sizeof(req->data) - req->len, "%s", line);
        req->len += strlen(req->line[req->lines]);
-       if (req->lines < MGCP_MAX_LINES)
+       if (req->lines < MGCP_MAX_LINES) {
                req->lines++;
-       else {
+       } else {
                ast_log(LOG_WARNING, "Out of line space\n");
                return -1;
        }
-       return 0;       
+       return 0;
 }
 
 static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *orig, char *resprest)
@@ -1970,10 +2101,11 @@ static int init_resp(struct mgcp_request *req, char *resp, struct mgcp_request *
        req->header[req->headers] = req->data + req->len;
        snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %s %s\r\n", resp, orig->identifier, resprest);
        req->len += strlen(req->header[req->headers]);
-       if (req->headers < MGCP_MAX_HEADERS)
+       if (req->headers < MGCP_MAX_HEADERS) {
                req->headers++;
-       else
+       } else {
                ast_log(LOG_WARNING, "Out of header space\n");
+       }
        return 0;
 }
 
@@ -1986,15 +2118,17 @@ static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *ver
        }
        req->header[req->headers] = req->data + req->len;
        /* check if we need brackets around the gw name */
-       if (p->parent->isnamedottedip)
-               snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
-       else
-               snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0\r\n", verb, oseq, p->name, p->parent->name);
+       if (p->parent->isnamedottedip) {
+               snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@[%s] MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : "");
+       } else {
++              snprintf(req->header[req->headers], sizeof(req->data) - req->len, "%s %d %s@%s MGCP 1.0%s\r\n", verb, oseq, p->name, p->parent->name, p->ncs ? " NCS 1.0" : "");
+       }
        req->len += strlen(req->header[req->headers]);
-       if (req->headers < MGCP_MAX_HEADERS)
+       if (req->headers < MGCP_MAX_HEADERS) {
                req->headers++;
-       else
+       } else {
                ast_log(LOG_WARNING, "Out of header space\n");
+       }
        return 0;
 }
 
@@ -2010,8 +2144,9 @@ static int reqprep(struct mgcp_request *req, struct mgcp_endpoint *p, char *verb
 {
        memset(req, 0, sizeof(struct mgcp_request));
        oseq++;
-       if (oseq > 999999999)
+       if (oseq > 999999999) {
                oseq = 1;
+       }
        init_req(p, req, verb);
        return 0;
 }
@@ -2022,29 +2157,34 @@ static int transmit_response(struct mgcp_subchannel *sub, char *msg, struct mgcp
        struct mgcp_endpoint *p = sub->parent;
        struct mgcp_response *mgr;
 
-       respprep(&resp, p, msg, req, msgrest);
-       mgr = malloc(sizeof(struct mgcp_response) + resp.len + 1);
-       if (mgr) {
-               /* Store MGCP response in case we have to retransmit */
-               memset(mgr, 0, sizeof(struct mgcp_response));
-               sscanf(req->identifier, "%d", &mgr->seqno);
-               time(&mgr->whensent);
-               mgr->len = resp.len;
-               memcpy(mgr->buf, resp.data, resp.len);
-               mgr->buf[resp.len] = '\0';
-               mgr->next = p->parent->responses;
-               p->parent->responses = mgr;
+       if (!sub) {
+               return -1;
        }
+
+       respprep(&resp, p, msg, req, msgrest);
+       if (!(mgr = ast_calloc(1, sizeof(*mgr) + resp.len + 1))) {
+               return send_response(sub, &resp);
+       }
+       /* Store MGCP response in case we have to retransmit */
+       sscanf(req->identifier, "%30d", &mgr->seqno);
+       time(&mgr->whensent);
+       mgr->len = resp.len;
+       memcpy(mgr->buf, resp.data, resp.len);
+       mgr->buf[resp.len] = '\0';
+       mgr->next = p->parent->responses;
+       p->parent->responses = mgr;
+
        return send_response(sub, &resp);
 }
 
 
-static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp *rtp)
+static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
 {
        int len;
        int codec;
        char costr[80];
        struct sockaddr_in sin;
+       struct ast_sockaddr sin_tmp;
        char v[256];
        char s[256];
        char o[256];
@@ -2053,7 +2193,9 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
        char m[256] = "";
        char a[1024] = "";
        int x;
-       struct sockaddr_in dest;
+       struct ast_format tmpfmt;
+       struct sockaddr_in dest = { 0, };
+       struct ast_sockaddr dest_tmp;
        struct mgcp_endpoint *p = sub->parent;
        /* XXX We break with the "recommendation" and send our IP, in order that our
               peer doesn't have to ast_gethostbyname() us XXX */
@@ -2062,9 +2204,11 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
                ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
                return -1;
        }
-       ast_rtp_get_us(sub->rtp, &sin);
+       ast_rtp_instance_get_local_address(sub->rtp, &sin_tmp);
+       ast_sockaddr_to_sin(&sin_tmp, &sin);
        if (rtp) {
-               ast_rtp_get_peer(rtp, &dest);
+               ast_rtp_instance_get_remote_address(sub->rtp, &dest_tmp);
+               ast_sockaddr_to_sin(&dest_tmp, &dest);
        } else {
                if (sub->tmpdest.sin_addr.s_addr) {
                        dest.sin_addr = sub->tmpdest.sin_addr;
@@ -2076,39 +2220,41 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
                        dest.sin_port = sin.sin_port;
                }
        }
-       if (mgcpdebug) {
-               ast_verbose("We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
-       }
-       snprintf(v, sizeof(v), "v=0\r\n");
-       snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), ast_inet_ntoa(dest.sin_addr));
-       snprintf(s, sizeof(s), "s=session\r\n");
+       ast_debug(1, "We're at %s port %d\n", ast_inet_ntoa(p->parent->ourip), ntohs(sin.sin_port));
+       ast_copy_string(v, "v=0\r\n", sizeof(v));
+       snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", (int)getpid(), (int)getpid(), ast_inet_ntoa(dest.sin_addr));
+       ast_copy_string(s, "s=session\r\n", sizeof(s));
        snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
-       snprintf(t, sizeof(t), "t=0 0\r\n");
+       ast_copy_string(t, "t=0 0\r\n", sizeof(t));
        snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
-       for (x = 1; x <= AST_FORMAT_MAX_AUDIO; x <<= 1) {
-               if (p->capability & x) {
-                       if (mgcpdebug) {
-                               ast_verbose("Answering with capability %d\n", x);
-                       }
-                       codec = ast_rtp_lookup_code(sub->rtp, 1, x);
+
+       ast_format_cap_iter_start(p->cap);
+       while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
+               if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
+                       /* Audio is now discontiguous */
+                       continue;
+               }
+               if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
+                       ast_debug(1, "Answering with capability %s\n", ast_getformatname(&tmpfmt));
+                       codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, &tmpfmt, 0);
                        if (codec > -1) {
                                snprintf(costr, sizeof(costr), " %d", codec);
                                strncat(m, costr, sizeof(m) - strlen(m) - 1);
-                               snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x, 0));
+                               snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
                                strncat(a, costr, sizeof(a) - strlen(a) - 1);
                        }
                }
        }
-       for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
+       ast_format_cap_iter_end(p->cap);
+
+       for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) {
                if (p->nonCodecCapability & x) {
-                       if (mgcpdebug) {
-                               ast_verbose("Answering with non-codec capability %d\n", x);
-                       }
-                       codec = ast_rtp_lookup_code(sub->rtp, 0, x);
+                       ast_debug(1, "Answering with non-codec capability %d\n", (int) x);
+                       codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 0, NULL, x);
                        if (codec > -1) {
                                snprintf(costr, sizeof(costr), " %d", codec);
                                strncat(m, costr, sizeof(m) - strlen(m) - 1);
-                               snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(0, x, 0));
+                               snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype2(0, NULL, x, 0));
                                strncat(a, costr, sizeof(a) - strlen(a) - 1);
                                if (x == AST_RTP_DTMF) {
                                        /* Indicate we support DTMF...  Not sure about 16,
@@ -2132,31 +2278,50 @@ static int add_sdp(struct mgcp_request *resp, struct mgcp_subchannel *sub, struc
        return 0;
 }
 
-static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp, int codecs)
+static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp, const struct ast_format_cap *codecs)
 {
        struct mgcp_request resp;
        char local[256];
        char tmp[80];
-       int x;
-       int capability;
        struct mgcp_endpoint *p = sub->parent;
+       struct ast_format tmpfmt;
+       struct ast_sockaddr sub_tmpdest_tmp;
 
-       capability = p->capability;
-       if (codecs)
-               capability = codecs;
        if (ast_strlen_zero(sub->cxident) && rtp) {
                /* We don't have a CXident yet, store the destination and
                   wait a bit */
-               ast_rtp_get_peer(rtp, &sub->tmpdest);
+               ast_rtp_instance_get_remote_address(rtp, &sub_tmpdest_tmp);
+               ast_sockaddr_to_sin(&sub_tmpdest_tmp, &sub->tmpdest);
                return 0;
        }
-       snprintf(local, sizeof(local), "p:20");
-       for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
-               if (p->capability & x) {
-                       snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
+       ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
+       ast_format_cap_iter_start(p->cap);
+       while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
+               if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
+                       /* Audio is now discontiguous */
+                       continue;
+               }
+               if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
+                       snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
+                       strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+               }
+       }
+       ast_format_cap_iter_end(p->cap);
+
+       if (sub->gate) {
+               if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
+                       snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
                        strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+                       sub->sdpsent = 1;
+               } else {
+                       /* oops wait */
+                       ast_debug(1, "Waiting for opened gate...\n");
+                       sub->sdpsent = 0;
+                       return 0;
                }
        }
+
+
        reqprep(&resp, p, "MDCX");
        add_header(&resp, "C", sub->callid);
        add_header(&resp, "L", local);
@@ -2169,28 +2334,42 @@ static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp
        /* fill in new fields */
        resp.cmd = MGCP_CMD_MDCX;
        resp.trid = oseq;
-       return send_request(p, sub, &resp, oseq); /* SC */
+       return send_request(p, sub, &resp, oseq);
 }
 
-static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp *rtp)
+static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp_instance *rtp)
 {
        struct mgcp_request resp;
        char local[256];
        char tmp[80];
-       int x;
+       struct ast_format tmpfmt;
        struct mgcp_endpoint *p = sub->parent;
 
-       snprintf(local, sizeof(local), "p:20");
-       for (x=1;x<= AST_FORMAT_MAX_AUDIO; x <<= 1) {
-               if (p->capability & x) {
-                       snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype(1, x, 0));
+       ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
+                p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
+
+       ast_copy_string(local, "e:on, s:off, p:20", sizeof(local));
+
+       ast_format_cap_iter_start(p->cap);
+       while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
+               if (AST_FORMAT_GET_TYPE(tmpfmt.id) != AST_FORMAT_TYPE_AUDIO) {
+                       /* Audio is now discontiguous */
+                       continue;
+               }
+               if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
+                       snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
                        strncat(local, tmp, sizeof(local) - strlen(local) - 1);
                }
        }
-       if (mgcpdebug) {
-               ast_verbose(VERBOSE_PREFIX_3 "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n", 
-                       p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
+       ast_format_cap_iter_end(p->cap);
+
+       if (sub->gate) {
+               if(sub->gate->state == GATE_ALLOCATED) {
+                       snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
+                       strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+               }
        }
+       sub->sdpsent = 1;
        reqprep(&resp, p, "CRCX");
        add_header(&resp, "C", sub->callid);
        add_header(&resp, "L", local);
@@ -2202,27 +2381,110 @@ static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp
        /* fill in new fields */
        resp.cmd = MGCP_CMD_CRCX;
        resp.trid = oseq;
-       return send_request(p, sub, &resp, oseq);  /* SC */
+       return send_request(p, sub, &resp, oseq);
 }
 
-static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
+static int mgcp_pktcgate_remove(struct cops_gate *gate)
+{
+       struct mgcp_subchannel *sub = gate->tech_pvt;
+
+       if (!sub) {
+               return 1;
+       }
+
+       ast_mutex_lock(&sub->lock);
+       ast_debug(1, "Pktc: gate 0x%x deleted\n", gate->gateid);
+       if (sub->gate->state != GATE_CLOSED && sub->parent->hangupongateremove) {
+               sub->gate = NULL;
+               if (sub->owner) {
+                       ast_softhangup(sub->owner, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
+                       ast_channel_unlock(sub->owner);
+               }
+       } else {
+               sub->gate = NULL;
+       }
+       ast_mutex_unlock(&sub->lock);
+       return 1;
+}
+
+static int mgcp_pktcgate_open(struct cops_gate *gate)
+{
+       struct mgcp_subchannel *sub = gate->tech_pvt;
+       if (!sub) {
+               return 1;
+       }
+       ast_mutex_lock(&sub->lock);
+       ast_debug(1, "Pktc: gate 0x%x open\n", gate->gateid);
+       if (!sub->sdpsent) transmit_modify_with_sdp(sub, NULL, 0);
+       ast_mutex_unlock(&sub->lock);
+       return 1;
+}
+
+static int mgcp_alloc_pktcgate(struct mgcp_subchannel *sub)
+{
+       struct mgcp_endpoint *p = sub->parent;
+       sub->gate = ast_pktccops_gate_alloc(GATE_SET, NULL, ntohl(p->parent->addr.sin_addr.s_addr),
+                                       8, 128000, 232, 0, 0, NULL, &mgcp_pktcgate_remove);
+
+       if (!sub->gate) {
+               return 0;
+       }
+       sub->gate->tech_pvt = sub;
+       sub->gate->gate_open = &mgcp_pktcgate_open;
+       return 1;
+}
+
+static int transmit_connect(struct mgcp_subchannel *sub)
 {
        struct mgcp_request resp;
+       char local[256];
+       char tmp[80];
+       struct ast_format tmpfmt;
        struct mgcp_endpoint *p = sub->parent;
 
-       if (mgcpdebug) {
-               ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
-                       tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
+       ast_copy_string(local, "p:20, s:off, e:on", sizeof(local));
+
+       ast_format_cap_iter_start(p->cap);
+       while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
+               if (ast_format_cap_iscompatible(p->cap, &tmpfmt)) {
+                       snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
+                       strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+               }
        }
+       ast_format_cap_iter_end(p->cap);
+
+       ast_debug(3, "Creating connection for %s@%s-%d in cxmode: %s callid: %s\n",
+                   p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
+       sub->sdpsent = 0;
+       reqprep(&resp, p, "CRCX");
+       add_header(&resp, "C", sub->callid);
+       add_header(&resp, "L", local);
+       add_header(&resp, "M", "inactive");
+       /* X header should not be sent. kept for compatibility */
+       add_header(&resp, "X", sub->txident);
+       /*add_header(&resp, "S", "");*/
+       /* fill in new fields */
+       resp.cmd = MGCP_CMD_CRCX;
+       resp.trid = oseq;
+       return send_request(p, sub, &resp, oseq);
+}
+
+static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
+{
+       struct mgcp_request resp;
+       struct mgcp_endpoint *p = sub->parent;
+
+       ast_debug(3, "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n",
+               tone, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
        ast_copy_string(p->curtone, tone, sizeof(p->curtone));
        reqprep(&resp, p, "RQNT");
-       add_header(&resp, "X", p->rqnt_ident); /* SC */
+       add_header(&resp, "X", p->rqnt_ident);
        switch (p->hookstate) {
        case MGCP_ONHOOK:
                add_header(&resp, "R", "L/hd(N)");
                break;
        case MGCP_OFFHOOK:
-               add_header(&resp, "R", (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+               add_header_offhook(sub, &resp, tone);
                break;
        }
        if (!ast_strlen_zero(tone)) {
@@ -2231,7 +2493,7 @@ static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
        /* fill in new fields */
        resp.cmd = MGCP_CMD_RQNT;
        resp.trid = oseq;
-       return send_request(p, NULL, &resp, oseq); /* SC */
+       return send_request(p, NULL, &resp, oseq);
 }
 
 static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, char *tone, char *callernum, char *callername)
@@ -2239,12 +2501,11 @@ static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, ch
        struct mgcp_request resp;
        char tone2[256];
        char *l, *n;
-       time_t t;
-       struct tm tm;
+       struct timeval t = ast_tvnow();
+       struct ast_tm tm;
        struct mgcp_endpoint *p = sub->parent;
-       
-       time(&t);
-       localtime_r(&t,&tm);
+
+       ast_localtime(&t, &tm, NULL);
        n = callername;
        l = callernum;
        if (!n)
@@ -2255,48 +2516,78 @@ static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, ch
        /* Keep track of last callerid for blacklist and callreturn */
        ast_copy_string(p->lastcallerid, l, sizeof(p->lastcallerid));
 
-       snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone, 
+       snprintf(tone2, sizeof(tone2), "%s,L/ci(%02d/%02d/%02d/%02d,%s,%s)", tone,
                tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, l, n);
        ast_copy_string(p->curtone, tone, sizeof(p->curtone));
        reqprep(&resp, p, "RQNT");
-       add_header(&resp, "X", p->rqnt_ident); /* SC */
+       add_header(&resp, "X", p->rqnt_ident);
        switch (p->hookstate) {
        case MGCP_ONHOOK:
                add_header(&resp, "R", "L/hd(N)");
                break;
        case MGCP_OFFHOOK:
-               add_header(&resp, "R",  (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N),L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+               add_header_offhook(sub, &resp, tone);
                break;
        }
        if (!ast_strlen_zero(tone2)) {
                add_header(&resp, "S", tone2);
        }
-       if (mgcpdebug) {
-               ast_verbose(VERBOSE_PREFIX_3 "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n", 
-                       tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
-       }
+       ast_debug(3, "MGCP Asked to indicate tone: %s on  %s@%s-%d in cxmode: %s\n",
+               tone2, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode]);
        /* fill in new fields */
        resp.cmd = MGCP_CMD_RQNT;
        resp.trid = oseq;
-       return send_request(p, NULL, &resp, oseq);  /* SC */
+       return send_request(p, NULL, &resp, oseq);
 }
 
 static int transmit_modify_request(struct mgcp_subchannel *sub)
 {
        struct mgcp_request resp;
        struct mgcp_endpoint *p = sub->parent;
+       struct ast_format tmpfmt;
+       int fc = 1;
+       char local[256];
+       char tmp[80];
 
        if (ast_strlen_zero(sub->cxident)) {
                /* We don't have a CXident yet, store the destination and
                   wait a bit */
                return 0;
        }
-       if (mgcpdebug) {
-               ast_verbose(VERBOSE_PREFIX_3 "Modified %s@%s-%d with new mode: %s on callid: %s\n", 
-                       p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
+       ast_debug(3, "Modified %s@%s-%d with new mode: %s on callid: %s\n",
+               p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
+
+       ast_copy_string(local, "", sizeof(local));
+       ast_format_cap_iter_start(p->cap);
+       while (!(ast_format_cap_iter_next(p->cap, &tmpfmt))) {
+               if (p->ncs && !fc) {
+                       ast_format_cap_set(p->cap, &tmpfmt); /* sb5120e bug */
+                       break;
+               } else {
+                       fc = 0;
+                       snprintf(tmp, sizeof(tmp), ", a:%s", ast_rtp_lookup_mime_subtype2(1, &tmpfmt, 0, 0));
+               }
+               strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+       }
+       ast_format_cap_iter_end(p->cap);
+
+       if (!sub->sdpsent) {
+               if (sub->gate) {
+                       if (sub->gate->state == GATE_ALLOCATED || sub->gate->state == GATE_OPEN) {
+                               snprintf(tmp, sizeof(tmp), ", dq-gi:%x", sub->gate->gateid);
+                               strncat(local, tmp, sizeof(local) - strlen(local) - 1);
+                       } else {
+                                       /* we still don't have gateid wait */
+                               return 0;
+                       }
+               }
        }
+
        reqprep(&resp, p, "MDCX");
        add_header(&resp, "C", sub->callid);
+       if (!sub->sdpsent) {
+               add_header(&resp, "L", local);
+       }
        add_header(&resp, "M", mgcp_cxmodes[sub->cxmode]);
        /* X header should not be sent. kept for compatibility */
        add_header(&resp, "X", sub->txident);
@@ -2306,16 +2597,48 @@ static int transmit_modify_request(struct mgcp_subchannel *sub)
                add_header(&resp, "R", "L/hd(N)");
                break;
        case MGCP_OFFHOOK:
-               add_header(&resp, "R",  (sub->rtp && (p->dtmfmode & MGCP_DTMF_INBAND)) ? "L/hu(N), L/hf(N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)");
+               add_header_offhook(sub, &resp, "");
                break;
        }
+       if (!sub->sdpsent) {
+               add_sdp(&resp, sub, NULL);
+               sub->sdpsent = 1;
+       }
        /* fill in new fields */
        resp.cmd = MGCP_CMD_MDCX;
        resp.trid = oseq;
-       return send_request(p, sub, &resp, oseq); /* SC */
+       return send_request(p, sub, &resp, oseq);
 }
 
 
+static void add_header_offhook(struct mgcp_subchannel *sub, struct mgcp_request *resp, char *tone)
+{
+       struct mgcp_endpoint *p = sub->parent;
+       char tone_indicate_end = 0;
+
+       /* We also should check the tone to indicate, because it have no sense
+          to request notify D/[0-9#*] (dtmf keys) if we are sending congestion
+          tone for example G/cg */
+       if (p && (!strcasecmp(tone, (p->ncs ? "L/ro" : "G/cg")))) {
+               tone_indicate_end = 1;
+       }
+
+       if (p && p->sub && p->sub->owner &&
+                       ast_channel_state(p->sub->owner) >= AST_STATE_RINGING &&
+                       (p->dtmfmode & (MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID))) {
+           add_header(resp, "R", "L/hu(N),L/hf(N)");
+
+       } else if (!tone_indicate_end){
+           add_header(resp, "R", (p->ncs ? "L/hu(N),L/hf(N),L/[0-9#*](N)" : "L/hu(N),L/hf(N),D/[0-9#*](N)"));
+       } else {
+               ast_debug(1, "We don't want more digits if we will end the call\n");
+               add_header(resp, "R", "L/hu(N),L/hf(N)");
+       }
+}
+
+
+
+
 static int transmit_audit_endpoint(struct mgcp_endpoint *p)
 {
        struct mgcp_request resp;
@@ -2326,7 +2649,7 @@ static int transmit_audit_endpoint(struct mgcp_endpoint *p)
        /* fill in new fields */
        resp.cmd = MGCP_CMD_AUEP;
        resp.trid = oseq;
-       return send_request(p, NULL, &resp, oseq);  /* SC */
+       return send_request(p, NULL, &resp, oseq);
 }
 
 static int transmit_connection_del(struct mgcp_subchannel *sub)
@@ -2334,10 +2657,8 @@ static int transmit_connection_del(struct mgcp_subchannel *sub)
        struct mgcp_endpoint *p = sub->parent;
        struct mgcp_request resp;
 
-       if (mgcpdebug) {
-               ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n", 
-                       sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
-       }
+       ast_debug(3, "Delete connection %s %s@%s-%d with new mode: %s on callid: %s\n",
+               sub->cxident, p->name, p->parent->name, sub->id, mgcp_cxmodes[sub->cxmode], sub->callid);
        reqprep(&resp, p, "DLCX");
        /* check if call id is avail */
        if (sub->callid[0])
@@ -2350,17 +2671,15 @@ static int transmit_connection_del(struct mgcp_subchannel *sub)
        /* fill in new fields */
        resp.cmd = MGCP_CMD_DLCX;
        resp.trid = oseq;
-       return send_request(p, sub, &resp, oseq);  /* SC */
+       return send_request(p, sub, &resp, oseq);
 }
 
 static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *callid, char *cxident)
 {
        struct mgcp_request resp;
 
-       if (mgcpdebug) {
-               ast_verbose(VERBOSE_PREFIX_3 "Delete connection %s %s@%s on callid: %s\n", 
-                       cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
-       }
+       ast_debug(3, "Delete connection %s %s@%s on callid: %s\n",
+               cxident ? cxident : "", p->name, p->parent->name, callid ? callid : "");
        reqprep(&resp, p, "DLCX");
        /* check if call id is avail */
        if (callid && *callid)
@@ -2375,33 +2694,33 @@ static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *calli
 }
 
 /*! \brief  dump_cmd_queues: (SC:) cleanup pending commands */
-static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub) 
+static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
 {
        struct mgcp_request *t, *q;
 
        if (p) {
                ast_mutex_lock(&p->rqnt_queue_lock);
-               for (q = p->rqnt_queue; q; t = q->next, free(q), q=t);
+               for (q = p->rqnt_queue; q; t = q->next, ast_free(q), q=t);
                p->rqnt_queue = NULL;
                ast_mutex_unlock(&p->rqnt_queue_lock);
 
                ast_mutex_lock(&p->cmd_queue_lock);
-               for (q = p->cmd_queue; q; t = q->next, free(q), q=t);
+               for (q = p->cmd_queue; q; t = q->next, ast_free(q), q=t);
                p->cmd_queue = NULL;
                ast_mutex_unlock(&p->cmd_queue_lock);
 
                ast_mutex_lock(&p->sub->cx_queue_lock);
-               for (q = p->sub->cx_queue; q; t = q->next, free(q), q=t);
+               for (q = p->sub->cx_queue; q; t = q->next, ast_free(q), q=t);
                p->sub->cx_queue = NULL;
                ast_mutex_unlock(&p->sub->cx_queue_lock);
 
                ast_mutex_lock(&p->sub->next->cx_queue_lock);
-               for (q = p->sub->next->cx_queue; q; t = q->next, free(q), q=t);
+               for (q = p->sub->next->cx_queue; q; t = q->next, ast_free(q), q=t);
                p->sub->next->cx_queue = NULL;
                ast_mutex_unlock(&p->sub->next->cx_queue_lock);
        } else if (sub) {
                ast_mutex_lock(&sub->cx_queue_lock);
-               for (q = sub->cx_queue; q; t = q->next, free(q), q=t);
+               for (q = sub->cx_queue; q; t = q->next, ast_free(q), q=t);
                sub->cx_queue = NULL;
                ast_mutex_unlock(&sub->cx_queue_lock);
        }
@@ -2410,7 +2729,7 @@ static void dump_cmd_queues(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
 
 /*! \brief  find_command: (SC:) remove command transaction from queue */
 static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
-                                         struct mgcp_request **queue, ast_mutex_t *l, int ident)
+               struct mgcp_request **queue, ast_mutex_t *l, int ident)
 {
        struct mgcp_request *prev, *req;
 
@@ -2425,10 +2744,8 @@ static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_su
 
                        /* send next pending command */
                        if (*queue) {
-                               if (mgcpdebug) {
-                                       ast_verbose("Posting Queued Request:\n%s to %s:%d\n", (*queue)->data, 
-                                               ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
-                               }
+                               ast_debug(1, "Posting Queued Request:\n%s to %s:%d\n", (*queue)->data,
+                                       ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));
 
                                mgcp_postrequest(p, sub, (*queue)->data, (*queue)->len, (*queue)->trid);
                        }
@@ -2440,8 +2757,8 @@ static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_su
 }
 
 /* modified for new transport mechanism */
-static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,  
-                            int result, unsigned int ident, struct mgcp_request *resp)
+static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
+               int result, unsigned int ident, struct mgcp_request *resp)
 {
        char *c;
        struct mgcp_request *req;
@@ -2452,7 +2769,7 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
                return;
        }
 
-       if (p->slowsequence) 
+       if (p->slowsequence)
                req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
        else if (sub)
                req = find_command(p, sub, &sub->cx_queue, &sub->cx_queue_lock, ident);
@@ -2460,10 +2777,8 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
                req = find_command(p, sub, &p->cmd_queue, &p->cmd_queue_lock, ident);
 
        if (!req) {
-               if (option_verbose > 2) {
-                       ast_verbose(VERBOSE_PREFIX_3 "No command found on [%s] for transaction %d. Ignoring...\n", 
+               ast_verb(3, "No command found on [%s] for transaction %d. Ignoring...\n",
                                gw->name, ident);
-               }
                return;
        }
 
@@ -2483,20 +2798,24 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
                        break;
                }
                if (sub) {
+                       if (!sub->cxident[0] && (req->cmd == MGCP_CMD_CRCX)) {
+                           ast_log(LOG_NOTICE, "DLCX for all connections on %s due to error %d\n", gw->name, result);
+                           transmit_connection_del(sub);
+                       }
                        if (sub->owner) {
-                               ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
+                               ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
                                        result, p->name, p->parent->name, sub ? sub->id:-1);
                                mgcp_queue_hangup(sub);
                        }
                } else {
                        if (p->sub->next->owner) {
-                               ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
+                               ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
                                        result, p->name, p->parent->name, sub ? sub->id:-1);
                                mgcp_queue_hangup(p->sub);
                        }
 
                        if (p->sub->owner) {
-                               ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n", 
+                               ast_log(LOG_NOTICE, "Terminating on result %d from %s@%s-%d\n",
                                        result, p->name, p->parent->name, sub ? sub->id:-1);
                                mgcp_queue_hangup(p->sub);
                        }
@@ -2506,6 +2825,15 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
        }
 
        if (resp) {
+               /* responseAck: */
+               if (result == 200 && (req->cmd == MGCP_CMD_CRCX || req->cmd == MGCP_CMD_MDCX)) {
+                               if (sub) {
+                                       transmit_response(sub, "000", resp, "OK");
+                                       if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_RINGING) {
+                                               ast_queue_control(sub->owner, AST_CONTROL_RINGING);
+                                       }
+                               }
+               }
                if (req->cmd == MGCP_CMD_CRCX) {
                        if ((c = get_header(resp, "I"))) {
                                if (!ast_strlen_zero(c) && sub) {
@@ -2522,8 +2850,8 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
                                                }
                                        } else {
                                                /* XXX delete this one
-                                                  callid and conn id may already be lost. 
-                                                  so the following del conn may have a side effect of 
+                                                  callid and conn id may already be lost.
+                                                  so the following del conn may have a side effect of
                                                   cleaning up the next subchannel */
                                                transmit_connection_del(sub);
                                        }
@@ -2546,10 +2874,8 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
                                                        if (len > (sizeof(cxident) - 1))
                                                                len = sizeof(cxident) - 1;
                                                        ast_copy_string(cxident, v, len);
-                                                       if (option_verbose > 2) {
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Non existing connection id %s on %s@%s \n", 
+                                                       ast_verb(3, "Non existing connection id %s on %s@%s \n",
                                                                            cxident, p->name, gw->name);
-                                                       }
                                                        transmit_connection_del_w_params(p, NULL, cxident);
                                                }
                                        }
@@ -2563,7 +2889,7 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
                                        if (strstr(c, "hu")) {
                                                if (p->hookstate != MGCP_ONHOOK) {
                                                        /* XXX cleanup if we think we are offhook XXX */
-                                                       if ((p->sub->owner || p->sub->next->owner ) && 
+                                                       if ((p->sub->owner || p->sub->next->owner ) &&
                                                            p->hookstate == MGCP_OFFHOOK)
                                                                mgcp_queue_hangup(sub);
                                                        p->hookstate = MGCP_ONHOOK;
@@ -2571,11 +2897,8 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
                                                        /* update the requested events according to the new hookstate */
                                                        transmit_notify_request(p->sub, "");
 
-                                                       /* verbose level check */
-                                                       if (option_verbose > 2) {
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
+                                                       ast_verb(3, "Setting hookstate of %s@%s to ONHOOK\n", p->name, gw->name);
                                                        }
-                                               }
                                        } else if (strstr(c, "hd")) {
                                                if (p->hookstate != MGCP_OFFHOOK) {
                                                        p->hookstate = MGCP_OFFHOOK;
@@ -2583,15 +2906,12 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
                                                        /* update the requested events according to the new hookstate */
                                                        transmit_notify_request(p->sub, "");
 
-                                                       /* verbose level check */
-                                                       if (option_verbose > 2) {
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
+                                                       ast_verb(3, "Setting hookstate of %s@%s to OFFHOOK\n", p->name, gw->name);
                                                        }
                                                }
                                        }
                                }
                        }
-               }
 
                if (resp && resp->lines) {
                        /* do not process sdp if we are hanging up. this may be a late response */
@@ -2604,77 +2924,88 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
                }
        }
 
-       free(req);
+       ast_free(req);
 }
 
 static void start_rtp(struct mgcp_subchannel *sub)
 {
+       struct ast_sockaddr bindaddr_tmp;
+
        ast_mutex_lock(&sub->lock);
        /* check again to be on the safe side */
        if (sub->rtp) {
-               ast_rtp_destroy(sub->rtp);
+               ast_rtp_instance_destroy(sub->rtp);
                sub->rtp = NULL;
        }
        /* Allocate the RTP now */
-       sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+       ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
+       sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
        if (sub->rtp && sub->owner)
-               sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
-       if (sub->rtp)
-               ast_rtp_setnat(sub->rtp, sub->nat);
-#if 0
-       ast_rtp_set_callback(p->rtp, rtpready);
-       ast_rtp_set_data(p->rtp, p);
-#endif         
+               ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
+       if (sub->rtp) {
+               ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "MGCP RTP");
+               ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->nat);
+       }
        /* Make a call*ID */
-        snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
+       snprintf(sub->callid, sizeof(sub->callid), "%08lx%s", ast_random(), sub->txident);
        /* Transmit the connection create */
-       transmit_connect_with_sdp(sub, NULL);
+       if(!sub->parent->pktcgatealloc) {
+               transmit_connect_with_sdp(sub, NULL);
+       } else {
+               transmit_connect(sub);
+               sub->gate = NULL;
+               if(!mgcp_alloc_pktcgate(sub))
+                       mgcp_queue_hangup(sub);
+       }
        ast_mutex_unlock(&sub->lock);
 }
 
 static void *mgcp_ss(void *data)
 {
        struct ast_channel *chan = data;
-       struct mgcp_subchannel *sub = chan->tech_pvt;
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
        struct mgcp_endpoint *p = sub->parent;
-       char exten[AST_MAX_EXTENSION] = "";
+       /* char exten[AST_MAX_EXTENSION] = ""; */
        int len = 0;
        int timeout = firstdigittimeout;
-       int res;
+       int res= 0;
        int getforward = 0;
+       int loop_pause = 100;
+
+       len = strlen(p->dtmf_buf);
+
+       while (len < AST_MAX_EXTENSION - 1) {
+               ast_debug(1, "Dtmf buffer '%s' for '%s@%s'\n", p->dtmf_buf, p->name, p->parent->name);
+               res = 1;  /* Assume that we will get a digit */
+               while (strlen(p->dtmf_buf) == len) {
+                       ast_safe_sleep(chan, loop_pause);
+                       timeout -= loop_pause;
+                       if (timeout <= 0){
+                               res = 0;
+                               break;
+                       }
+                       res = 1;
+               }
 
-       while(len < AST_MAX_EXTENSION-1) {
-               res = ast_waitfordigit(chan, timeout);
                timeout = 0;
-               if (res < 0) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
-                       /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
-                       ast_indicate(chan, -1);
-                       ast_hangup(chan);
-                       return NULL;
-               } else if (res) {
-                       exten[len++]=res;
-                       exten[len] = '\0';
-               }
-               if (!ast_ignore_pattern(chan->context, exten)) {
+               len = strlen(p->dtmf_buf);
+
+               if (!ast_ignore_pattern(ast_channel_context(chan), p->dtmf_buf)) {
                        /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
                        ast_indicate(chan, -1);
                } else {
                        /* XXX Redundant?  We should already be playing dialtone */
-                       /*tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
+                       /*tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/
                        transmit_notify_request(sub, "L/dl");
                }
-               if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
-                       if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
+               if (ast_exists_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1, p->cid_num)) {
+                       if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1, p->cid_num)) {
                                if (getforward) {
                                        /* Record this as the forwarding extension */
-                                       ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
-                                       if (option_verbose > 2) {
-                                               ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n", 
-                                                       p->call_forward, chan->name);
-                                       }
-                                       /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
+                                       ast_copy_string(p->call_forward, p->dtmf_buf, sizeof(p->call_forward));
+                                       ast_verb(3, "Setting call forward to '%s' on channel %s\n",
+                                                       p->call_forward, ast_channel_name(chan));
+                                       /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
                                        transmit_notify_request(sub, "L/sl");
                                        if (res)
                                                break;
@@ -2682,21 +3013,23 @@ static void *mgcp_ss(void *data)
                                        /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
                                        ast_indicate(chan, -1);
                                        sleep(1);
-                                       memset(exten, 0, sizeof(exten));
-                                       /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALTONE);*/
+                                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
+                                       /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);*/
                                        transmit_notify_request(sub, "L/dl");
                                        len = 0;
                                        getforward = 0;
                                } else {
                                        /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
                                        ast_indicate(chan, -1);
-                                       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
+                                       ast_channel_exten_set(chan, p->dtmf_buf);
+                                       chan->dialed.number.str = ast_strdup(p->dtmf_buf);
+                                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                                        ast_set_callerid(chan,
                                                p->hidecallerid ? "" : p->cid_num,
                                                p->hidecallerid ? "" : p->cid_name,
-                                               chan->cid.cid_ani ? NULL : p->cid_num);
+                                               chan->caller.ani.number.valid ? NULL : p->cid_num);
                                        ast_setstate(chan, AST_STATE_RING);
-                                       /*zt_enable_ec(p);*/
+                                       /*dahdi_enable_ec(p);*/
                                        if (p->dtmfmode & MGCP_DTMF_HYBRID) {
                                                p->dtmfmode |= MGCP_DTMF_INBAND;
                                                ast_indicate(chan, -1);
@@ -2704,9 +3037,9 @@ static void *mgcp_ss(void *data)
                                        res = ast_pbx_run(chan);
                                        if (res) {
                                                ast_log(LOG_WARNING, "PBX exited non-zero\n");
-                                               /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
+                                               /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
                                                /*transmit_notify_request(p, "nbz", 1);*/
-                                               transmit_notify_request(sub, "G/cg");
+                                               transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
                                        }
                                        return NULL;
                                }
@@ -2716,136 +3049,124 @@ static void *mgcp_ss(void *data)
                                timeout = matchdigittimeout;
                        }
                } else if (res == 0) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
-                       /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
-                       transmit_notify_request(sub, "G/cg");
-                       /*zt_wait_event(p->subs[index].zfd);*/
+                       ast_debug(1, "not enough digits (and no ambiguous match)...\n");
+                       /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
+                       transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
+                       /*dahdi_wait_event(p->subs[index].zfd);*/
                        ast_hangup(chan);
+                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                        return NULL;
-               } else if (p->hascallwaiting && p->callwaiting && !strcmp(exten, "*70")) {
-                       if (option_verbose > 2) {
-                               ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
-                       }
+               } else if (p->hascallwaiting && p->callwaiting && !strcmp(p->dtmf_buf, "*70")) {
+                       ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
                        /* Disable call waiting if enabled */
                        p->callwaiting = 0;
-                       /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
+                       /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
                        transmit_notify_request(sub, "L/sl");
                        len = 0;
-                       memset(exten, 0, sizeof(exten));
+                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                        timeout = firstdigittimeout;
-               } else if (!strcmp(exten,ast_pickup_ext())) {
+               } else if (!strcmp(p->dtmf_buf,ast_pickup_ext())) {
                        /* Scan all channels and see if any there
                         * ringing channqels with that have call groups
-                        * that equal this channels pickup group  
+                        * that equal this channels pickup group
                         */
                        if (ast_pickup_call(chan)) {
                                ast_log(LOG_WARNING, "No call pickup possible...\n");
-                               /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);*/
-                               transmit_notify_request(sub, "G/cg");
+                               /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);*/
+                               transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
                        }
+                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                        ast_hangup(chan);
                        return NULL;
-               } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
-                       if (option_verbose > 2) {
-                               ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
-                       }
+               } else if (!p->hidecallerid && !strcmp(p->dtmf_buf, "*67")) {
+                       ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
                        /* Disable Caller*ID if enabled */
                        p->hidecallerid = 1;
                        ast_set_callerid(chan, "", "", NULL);
-                       /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
+                       /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
                        transmit_notify_request(sub, "L/sl");
                        len = 0;
-                       memset(exten, 0, sizeof(exten));
+                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                        timeout = firstdigittimeout;
-               } else if (p->callreturn && !strcmp(exten, "*69")) {
+               } else if (p->callreturn && !strcmp(p->dtmf_buf, "*69")) {
                        res = 0;
                        if (!ast_strlen_zero(p->lastcallerid)) {
-                               res = ast_say_digit_str(chan, p->lastcallerid, "", chan->language);
+                               res = ast_say_digit_str(chan, p->lastcallerid, "", ast_channel_language(chan));
                        }
                        if (!res)
-                               /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
+                               /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
                                transmit_notify_request(sub, "L/sl");
                        break;
-               } else if (!strcmp(exten, "*78")) {
+               } else if (!strcmp(p->dtmf_buf, "*78")) {
                        /* Do not disturb */
-                       if (option_verbose > 2) {
-                               ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
-                       }
-                       /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
+                       ast_verb(3, "Enabled DND on channel %s\n", ast_channel_name(chan));
+                       /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
                        transmit_notify_request(sub, "L/sl");
                        p->dnd = 1;
                        getforward = 0;
-                       memset(exten, 0, sizeof(exten));
+                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                        len = 0;
-               } else if (!strcmp(exten, "*79")) {
+               } else if (!strcmp(p->dtmf_buf, "*79")) {
                        /* Do not disturb */
-                       if (option_verbose > 2) {
-                               ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
-                       }
-                       /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
+                       ast_verb(3, "Disabled DND on channel %s\n", ast_channel_name(chan));
+                       /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
                        transmit_notify_request(sub, "L/sl");
                        p->dnd = 0;
                        getforward = 0;
-                       memset(exten, 0, sizeof(exten));
+                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                        len = 0;
-               } else if (p->cancallforward && !strcmp(exten, "*72")) {
-                       /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
+               } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*72")) {
+                       /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
                        transmit_notify_request(sub, "L/sl");
                        getforward = 1;
-                       memset(exten, 0, sizeof(exten));
+                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                        len = 0;
-               } else if (p->cancallforward && !strcmp(exten, "*73")) {
-                       if (option_verbose > 2) {
-                               ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
-                       }
-                       /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
+               } else if (p->cancallforward && !strcmp(p->dtmf_buf, "*73")) {
+                       ast_verb(3, "Cancelling call forwarding on channel %s\n", ast_channel_name(chan));
+                       /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
                        transmit_notify_request(sub, "L/sl");
                        memset(p->call_forward, 0, sizeof(p->call_forward));
                        getforward = 0;
-                       memset(exten, 0, sizeof(exten));
+                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                        len = 0;
-               } else if (!strcmp(exten, ast_parking_ext()) && 
+               } else if (ast_parking_ext_valid(p->dtmf_buf, chan, ast_channel_context(chan)) &&
                        sub->next->owner && ast_bridged_channel(sub->next->owner)) {
-                       /* This is a three way call, the main call being a real channel, 
+                       /* This is a three way call, the main call being a real channel,
                           and we're parking the first call. */
-                       ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
-                       if (option_verbose > 2) {
-                               ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
-                       }
+                       ast_masq_park_call_exten(ast_bridged_channel(sub->next->owner), chan,
+                               p->dtmf_buf, ast_channel_context(chan), 0, NULL);
+                       ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
                        break;
-               } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(exten, "*60")) {
-                       if (option_verbose > 2) {
-                               ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcallerid);
-                       }
+               } else if (!ast_strlen_zero(p->lastcallerid) && !strcmp(p->dtmf_buf, "*60")) {
+                       ast_verb(3, "Blacklisting number %s\n", p->lastcallerid);
                        res = ast_db_put("blacklist", p->lastcallerid, "1");
                        if (!res) {
-                               /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
+                               /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
                                transmit_notify_request(sub, "L/sl");
-                               memset(exten, 0, sizeof(exten));
+                               memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                                len = 0;
                        }
-               } else if (p->hidecallerid && !strcmp(exten, "*82")) {
-                       if (option_verbose > 2) {
-                               ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
-                       }
+               } else if (p->hidecallerid && !strcmp(p->dtmf_buf, "*82")) {
+                       ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
                        /* Enable Caller*ID if enabled */
                        p->hidecallerid = 0;
                        ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
-                       /*res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);*/
+                       /*res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);*/
                        transmit_notify_request(sub, "L/sl");
                        len = 0;
-                       memset(exten, 0, sizeof(exten));
+                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                        timeout = firstdigittimeout;
-               } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
-                               ((exten[0] != '*') || (strlen(exten) > 2))) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
+               } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), p->dtmf_buf, 1,
+                       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
+                       && ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
+                       ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf,
+                               S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
+                               ast_channel_context(chan));
                        break;
                }
                if (!timeout)
                        timeout = gendigittimeout;
-               if (len && !ast_ignore_pattern(chan->context, exten))
+               if (len && !ast_ignore_pattern(ast_channel_context(chan), p->dtmf_buf))
                        /*tone_zone_play_tone(p->subs[index].zfd, -1);*/
                        ast_indicate(chan, -1);
        }
@@ -2853,13 +3174,11 @@ static void *mgcp_ss(void *data)
        for (;;) {
                res = ast_waitfordigit(chan, to);
                if (!res) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Timeout...\n");
+                       ast_debug(1, "Timeout...\n");
                        break;
                }
                if (res < 0) {
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "Got hangup...\n");
+                       ast_debug(1, "Got hangup...\n");
                        ast_hangup(chan);
                        break;
                }
@@ -2867,7 +3186,7 @@ static void *mgcp_ss(void *data)
                if (!ast_ignore_pattern(chan->context, exten))
                        ast_indicate(chan, -1);
                if (ast_matchmore_extension(chan, chan->context, exten, 1, chan->callerid)) {
-                       if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid)) 
+                       if (ast_exists_extension(chan, chan->context, exten, 1, chan->callerid))
                                to = 3000;
                        else
                                to = 8000;
@@ -2883,11 +3202,14 @@ static void *mgcp_ss(void *data)
                chan->rings = 1;
                if (ast_pbx_run(chan)) {
                        ast_log(LOG_WARNING, "Unable to launch PBX on %s\n", chan->name);
-               } else
+               } else {
+                       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
                        return NULL;
+               }
        }
 #endif
        ast_hangup(chan);
+       memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
        return NULL;
 }
 
@@ -2907,38 +3229,35 @@ static int attempt_transfer(struct mgcp_endpoint *p)
                   stop if now if appropriate */
                if (ast_bridged_channel(p->sub->next->owner))
                        ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
-               if (p->sub->owner->_state == AST_STATE_RINGING) {
+               if (ast_channel_state(p->sub->owner) == AST_STATE_RINGING) {
                        ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
                }
                if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
                        ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
-                               ast_bridged_channel(p->sub->owner)->name, p->sub->next->owner->name);
+                               ast_channel_name(ast_bridged_channel(p->sub->owner)), ast_channel_name(p->sub->next->owner));
                        return -1;
                }
                /* Orphan the channel */
                unalloc_sub(p->sub->next);
        } else if (ast_bridged_channel(p->sub->next->owner)) {
-               if (p->sub->owner->_state == AST_STATE_RINGING) {
+               if (ast_channel_state(p->sub->owner) == AST_STATE_RINGING) {
                        ast_indicate(ast_bridged_channel(p->sub->next->owner), AST_CONTROL_RINGING);
                }
                ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
                if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
                        ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
-                               ast_bridged_channel(p->sub->next->owner)->name, p->sub->owner->name);
+                               ast_channel_name(ast_bridged_channel(p->sub->next->owner)), ast_channel_name(p->sub->owner));
                        return -1;
                }
                /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
-               if (option_verbose > 2) {
-                       ast_verbose(VERBOSE_PREFIX_3 "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
-               }
+               ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
                p->sub = p->sub->next;
                unalloc_sub(p->sub->next);
                /* Tell the caller not to hangup */
                return 1;
        } else {
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
-                               p->sub->owner->name, p->sub->next->owner->name);
+               ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
+                       ast_channel_name(p->sub->owner), ast_channel_name(p->sub->next->owner));
                p->sub->next->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                if (p->sub->next->owner) {
                        p->sub->next->alreadygone = 1;
@@ -2948,14 +3267,11 @@ static int attempt_transfer(struct mgcp_endpoint *p)
        return 0;
 }
 
-static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev) 
+static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
 {
        struct mgcp_endpoint *p = sub->parent;
        struct ast_channel *c;
        pthread_t t;
-       pthread_attr_t attr;
-       pthread_attr_init(&attr);
-       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);    
 
        /* Off hook / answer */
        if (sub->outgoing) {
@@ -2984,15 +3300,15 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
                        }
                        if (p->immediate) {
                                /* The channel is immediately up. Start right away */
-#ifdef DLINK_BUGGY_FIRMWARE    
+#ifdef DLINK_BUGGY_FIRMWARE
                                transmit_notify_request(sub, "rt");
 #else
-                               transmit_notify_request(sub, "G/rt");
-#endif         
-                               c = mgcp_new(sub, AST_STATE_RING);
+                               transmit_notify_request(sub, p->ncs ? "L/rt" : "G/rt");
+#endif
+                               c = mgcp_new(sub, AST_STATE_RING, NULL);
                                if (!c) {
                                        ast_log(LOG_WARNING, "Unable to start PBX on channel %s@%s\n", p->name, p->parent->name);
-                                       transmit_notify_request(sub, "G/cg");
+                                       transmit_notify_request(sub, p->ncs ? "L/cg" : "G/cg");
                                        ast_hangup(c);
                                }
                        } else {
@@ -3001,9 +3317,9 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
                                } else {
                                        transmit_notify_request(sub, "L/dl");
                                }
-                               c = mgcp_new(sub, AST_STATE_DOWN);
+                               c = mgcp_new(sub, AST_STATE_DOWN, NULL);
                                if (c) {
-                                       if (ast_pthread_create(&t, &attr, mgcp_ss, c)) {
+                                       if (ast_pthread_create_detached(&t, NULL, mgcp_ss, c)) {
                                                ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
                                                ast_hangup(c);
                                        }
@@ -3031,7 +3347,6 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
                        /*ast_queue_control(sub->owner, AST_CONTROL_ANSWER);*/
                }
        }
-       pthread_attr_destroy(&attr);
 }
 
 static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, struct sockaddr_in *sin)
@@ -3042,38 +3357,32 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
        struct mgcp_gateway *g = NULL;
        int res;
 
-       if (mgcpdebug) {
-               ast_verbose("Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
-       }
+       ast_debug(1, "Handling request '%s' on %s@%s\n", req->verb, p->name, p->parent->name);
        /* Clear out potential response */
        if (!strcasecmp(req->verb, "RSIP")) {
                /* Test if this RSIP request is just a keepalive */
-               if(!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
-                       if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_3 "Received keepalive request from %s@%s\n", p->name, p->parent->name);
+               if (!strcasecmp( get_header(req, "RM"), "X-keepalive")) {
+                       ast_verb(3, "Received keepalive request from %s@%s\n", p->name, p->parent->name);
                        transmit_response(sub, "200", req, "OK");
                } else {
                        dump_queue(p->parent, p);
                        dump_cmd_queues(p, NULL);
-                       
-                       if (option_verbose > 2 && (strcmp(p->name, p->parent->wcardep) != 0)) {
-                               ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", p->name, p->parent->name);
+
+                       if ((strcmp(p->name, p->parent->wcardep) != 0)) {
+                               ast_verb(3, "Resetting interface %s@%s\n", p->name, p->parent->name);
                        }
                        /* For RSIP on wildcard we reset all endpoints */
                        if (!strcmp(p->name, p->parent->wcardep)) {
                                /* Reset all endpoints */
                                struct mgcp_endpoint *tmp_ep;
-                               
+
                                g = p->parent;
-                               tmp_ep = g->endpoints;
-                               while (tmp_ep) {
+                               for (tmp_ep = g->endpoints; tmp_ep; tmp_ep = tmp_ep->next) {
                                        /*if ((strcmp(tmp_ep->name, "*") != 0) && (strcmp(tmp_ep->name, "aaln/" "*") != 0)) {*/
                                        if (strcmp(tmp_ep->name, g->wcardep) != 0) {
                                                struct mgcp_subchannel *tmp_sub, *first_sub;
-                                               if (option_verbose > 2) {
-                                                       ast_verbose(VERBOSE_PREFIX_3 "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
-                                               }
-                                               
+                                               ast_verb(3, "Resetting interface %s@%s\n", tmp_ep->name, p->parent->name);
+
                                                first_sub = tmp_ep->sub;
                                                tmp_sub = tmp_ep->sub;
                                                while (tmp_sub) {
@@ -3083,17 +3392,16 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
                                                                break;
                                                }
                                        }
-                                       tmp_ep = tmp_ep->next;
                                }
                        } else if (sub->owner) {
                                mgcp_queue_hangup(sub);
                        }
                        transmit_response(sub, "200", req, "OK");
-                       /* We dont send NTFY or AUEP to wildcard ep */
+                       /* We don't send NTFY or AUEP to wildcard ep */
                        if (strcmp(p->name, p->parent->wcardep) != 0) {
                                transmit_notify_request(sub, "");
-                               /* Audit endpoint. 
-                                Idea is to prevent lost lines due to race conditions 
+                               /* Audit endpoint.
+                                Idea is to prevent lost lines due to race conditions
                                */
                                transmit_audit_endpoint(p);
                        }
@@ -3105,8 +3413,7 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
                ev = get_header(req, "O");
                s = strchr(ev, '/');
                if (s) ev = s + 1;
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
+               ast_debug(1, "Endpoint '%s@%s-%d' observed '%s'\n", p->name, p->parent->name, sub->id, ev);
                /* Keep looking for events unless this was a hangup */
                if (strcasecmp(ev, "hu") && strcasecmp(ev, "hd") && strcasecmp(ev, "ping")) {
                        transmit_notify_request(sub, p->curtone);
@@ -3114,6 +3421,13 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
                if (!strcasecmp(ev, "hd")) {
                        p->hookstate = MGCP_OFFHOOK;
                        sub->cxmode = MGCP_CX_SENDRECV;
+
+                       if (p) {
+                         /* When the endpoint have a Off hook transition we allways
+                            starts without any previous dtmfs */
+                         memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
+                       }
+
                        handle_hd_hf(sub, ev);
                } else if (!strcasecmp(ev, "hf")) {
                        /* We can assume we are offhook if we received a hookflash */
@@ -3124,23 +3438,19 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
                                /* Thanks to point on IRC for pointing this out */
                                return -1;
                        }
-                       /* do not let * conference two down channels */  
-                       if (sub->owner && sub->owner->_state == AST_STATE_DOWN && !sub->next->owner)
+                       /* do not let * conference two down channels */
+                       if (sub->owner && ast_channel_state(sub->owner) == AST_STATE_DOWN && !sub->next->owner)
                                return -1;
 
                        if (p->callwaiting || p->transfer || p->threewaycalling) {
-                               if (option_verbose > 2) {
-                                       ast_verbose(VERBOSE_PREFIX_3 "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
-                               }
+                               ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
                                p->sub = p->sub->next;
 
                                /* transfer control to our next subchannel */
                                if (!sub->next->owner) {
                                        /* plave the first call on hold and start up a new call */
                                        sub->cxmode = MGCP_CX_MUTE;
-                                       if (option_verbose > 2) {
-                                               ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
-                                       }
+                                       ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
                                        transmit_modify_request(sub);
                                        if (sub->owner && ast_bridged_channel(sub->owner))
                                                ast_queue_control(sub->owner, AST_CONTROL_HOLD);
@@ -3150,10 +3460,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
                                        /* We've got two active calls lets decide whether or not to conference or just flip flop */
                                        if ((!sub->outgoing) && (!sub->next->outgoing)) {
                                                /* We made both calls lets conferenct */
-                                               if (option_verbose > 2) {
-                                                       ast_verbose(VERBOSE_PREFIX_3 "MGCP Conferencing %d and %d on %s@%s\n", 
+                                               ast_verb(3, "MGCP Conferencing %d and %d on %s@%s\n",
                                                                sub->id, sub->next->id, p->name, p->parent->name);
-                                               }
                                                sub->cxmode = MGCP_CX_CONF;
                                                sub->next->cxmode = MGCP_CX_CONF;
                                                if (ast_bridged_channel(sub->next->owner))
@@ -3164,21 +3472,17 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
                                                /* Let's flipflop between calls */
                                                /* XXX Need to check for state up ??? */
                                                /* XXX Need a way to indicate the current call, or maybe the call that's waiting */
-                                               if (option_verbose > 2) {
-                                                       ast_verbose(VERBOSE_PREFIX_3 "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n", 
+                                               ast_verb(3, "We didn't make one of the calls FLIPFLOP %d and %d on %s@%s\n",
                                                                sub->id, sub->next->id, p->name, p->parent->name);
-                                               }
                                                sub->cxmode = MGCP_CX_MUTE;
-                                               if (option_verbose > 2) {
-                                                       ast_verbose(VERBOSE_PREFIX_3 "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
-                                               }
+                                               ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name);
                                                transmit_modify_request(sub);
                                                if (ast_bridged_channel(sub->owner))
                                                        ast_queue_control(sub->owner, AST_CONTROL_HOLD);
-                        
-                                               if (ast_bridged_channel(sub->next->owner)) 
+
+                                               if (ast_bridged_channel(sub->next->owner))
                                                        ast_queue_control(sub->next->owner, AST_CONTROL_HOLD);
-                        
+
                                                handle_hd_hf(sub->next, ev);
                                        }
                                } else {
@@ -3198,14 +3502,13 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
                                        transmit_modify_request(p->sub);
                                }
                        } else {
-                               ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n", 
+                               ast_log(LOG_WARNING, "Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s\n",
                                        p->name, p->parent->name);
                        }
                } else if (!strcasecmp(ev, "hu")) {
                        p->hookstate = MGCP_ONHOOK;
                        sub->cxmode = MGCP_CX_RECVONLY;
-                       if (option_debug)
-                               ast_log(LOG_DEBUG, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
+                       ast_debug(1, "MGCP %s@%s Went on hook\n", p->name, p->parent->name);
                        /* Do we need to send MDCX before a DLCX ?
                        if (sub->rtp) {
                                transmit_modify_request(sub);
@@ -3234,11 +3537,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
                                        sub->alreadygone = 1;
                                        mgcp_queue_hangup(sub);
                                } else {
-                                       /* verbose level check */
-                                       if (option_verbose > 2) {
-                                               ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
+                                       ast_verb(3, "MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX.\n",
                                                        p->name, p->parent->name, sub->id);
-                                       }
                                        /* Instruct the other side to remove the connection since it apparently *
                                         * still thinks the channel is active. *
                                         * For Cisco IAD2421 /BAK/ */
@@ -3248,40 +3548,37 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
                        if ((p->hookstate == MGCP_ONHOOK) && (!sub->rtp) && (!sub->next->rtp)) {
                                p->hidecallerid = 0;
                                if (p->hascallwaiting && !p->callwaiting) {
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
+                                       ast_verb(3, "Enabling call waiting on MGCP/%s@%s-%d\n", p->name, p->parent->name, sub->id);
                                        p->callwaiting = -1;
                                }
                                if (has_voicemail(p)) {
-                                       if (option_verbose > 2) {
-                                               ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
-                                       }
+                                       ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(+)\n", p->name, p->parent->name);
                                        transmit_notify_request(sub, "L/vmwi(+)");
                                } else {
-                                       if (option_verbose > 2) {
-                                               ast_verbose(VERBOSE_PREFIX_3 "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
-                                       }
+                                       ast_verb(3, "MGCP handle_request(%s@%s) set vmwi(-)\n", p->name, p->parent->name);
                                        transmit_notify_request(sub, "L/vmwi(-)");
                                }
                        }
-               } else if ((strlen(ev) == 1) && 
+               } else if ((strlen(ev) == 1) &&
                                (((ev[0] >= '0') && (ev[0] <= '9')) ||
                                 ((ev[0] >= 'A') && (ev[0] <= 'D')) ||
                                  (ev[0] == '*') || (ev[0] == '#'))) {
-                       f.frametype = AST_FRAME_DTMF;
-                       f.subclass = ev[0];
-                       f.src = "mgcp";
-                       if (sub->owner) {
+                       if (sub && sub->owner && (ast_channel_state(sub->owner) >=  AST_STATE_UP)) {
+                               f.frametype = AST_FRAME_DTMF;
+                               f.subclass.integer = ev[0];
+                               f.src = "mgcp";
                                /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
                                mgcp_queue_frame(sub, &f);
                                ast_mutex_lock(&sub->next->lock);
-                               if (sub->next->owner) {
+                               if (sub->next->owner)
                                        mgcp_queue_frame(sub->next, &f);
-                               }
                                ast_mutex_unlock(&sub->next->lock);
-                       }
-                       if (strstr(p->curtone, "wt") && (ev[0] == 'A')) {
-                               memset(p->curtone, 0, sizeof(p->curtone));
+                               if (strstr(p->curtone, (p->ncs ? "wt1" : "wt")) && (ev[0] == 'A')) {
+                                       memset(p->curtone, 0, sizeof(p->curtone));
+                               }
+                       } else {
+                               p->dtmf_buf[strlen(p->dtmf_buf)] = ev[0];
+                               p->dtmf_buf[strlen(p->dtmf_buf)] = '\0';
                        }
                } else if (!strcasecmp(ev, "T")) {
                        /* Digit timeout -- unimportant */
@@ -3301,26 +3598,24 @@ static int find_and_retrans(struct mgcp_subchannel *sub, struct mgcp_request *re
 {
        int seqno=0;
        time_t now;
-       struct mgcp_response *prev = NULL, *cur, *next, *answer=NULL;
+       struct mgcp_response *prev = NULL, *cur, *next, *answer = NULL;
        time(&now);
-       if (sscanf(req->identifier, "%d", &seqno) != 1) 
+       if (sscanf(req->identifier, "%30d", &seqno) != 1) {
                seqno = 0;
-       cur = sub->parent->parent->responses;
-       while(cur) {
-               next = cur->next;
+       }
+       for (cur = sub->parent->parent->responses, next = cur ? cur->next : NULL; cur; cur = next, next = cur ? cur->next : NULL) {
                if (now - cur->whensent > RESPONSE_TIMEOUT) {
                        /* Delete this entry */
                        if (prev)
                                prev->next = next;
                        else
                                sub->parent->parent->responses = next;
-                       free(cur);
+                       ast_free(cur);
                } else {
                        if (seqno == cur->seqno)
                                answer = cur;
                        prev = cur;
                }
-               cur = next;
        }
        if (answer) {
                resend_response(sub, answer);
@@ -3348,9 +3643,7 @@ static int mgcpsock_read(int *id, int fd, short events, void *ignore)
        }
        req.data[res] = '\0';
        req.len = res;
-       if (mgcpdebug) {
-               ast_verbose("MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
-       }
+       ast_debug(1, "MGCP read: \n%s\nfrom %s:%d\n", req.data, ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
        parse(&req);
        if (req.headers < 1) {
                /* Must have at least one header */
@@ -3361,7 +3654,11 @@ static int mgcpsock_read(int *id, int fd, short events, void *ignore)
                return 1;
        }
 
-       if (sscanf(req.verb, "%d", &result) && sscanf(req.identifier, "%d", &ident)) {
+       if (sscanf(req.verb, "%30d", &result) && sscanf(req.identifier, "%30d", &ident)) {
+               if (result < 200) {
+                       ast_debug(1, "Ignoring provisional response on transaction %d\n", ident);
+                       return 1;
+               }
                /* Try to find who this message is for, if it's important */
                sub = find_subchannel_and_lock(NULL, ident, &sin);
                if (sub) {
@@ -3372,8 +3669,7 @@ static int mgcpsock_read(int *id, int fd, short events, void *ignore)
                        ast_mutex_lock(&gw->msgs_lock);
                        for (prev = NULL, cur = gw->msgs; cur; prev = cur, cur = cur->next) {
                                if (cur->seqno == ident) {
-                                       if (option_debug)
-                                               ast_log(LOG_DEBUG, "Got response back on transaction %d\n", ident);
+                                       ast_debug(1, "Got response back on transaction %d\n", ident);
                                        if (prev)
                                                prev->next = cur->next;
                                        else
@@ -3383,24 +3679,23 @@ static int mgcpsock_read(int *id, int fd, short events, void *ignore)
                        }
 
                        /* stop retrans timer if the queue is empty */
-                       if (!gw->msgs && (gw->retransid != -1)) {
-                               ast_sched_del(sched, gw->retransid);
-                               gw->retransid = -1;
+                       if (!gw->msgs) {
+                               AST_SCHED_DEL(sched, gw->retransid);
                        }
 
                        ast_mutex_unlock(&gw->msgs_lock);
                        if (cur) {
                                handle_response(cur->owner_ep, cur->owner_sub, result, ident, &req);
-                               free(cur);
+                               ast_free(cur);
                                return 1;
                        }
 
-                       ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n", 
+                       ast_log(LOG_NOTICE, "Got response back on [%s] for transaction %d we aren't sending?\n",
                                gw->name, ident);
                }
        } else {
-               if (ast_strlen_zero(req.endpoint) || 
-                       ast_strlen_zero(req.version) || 
+               if (ast_strlen_zero(req.endpoint) ||
+                       ast_strlen_zero(req.version) ||
                        ast_strlen_zero(req.verb)) {
                        ast_log(LOG_NOTICE, "Message must have a verb, an idenitifier, version, and endpoint\n");
                        return 1;
@@ -3420,34 +3715,94 @@ static int mgcpsock_read(int *id, int fd, short events, void *ignore)
 
 static int *mgcpsock_read_id = NULL;
 
+static int mgcp_prune_realtime_gateway(struct mgcp_gateway *g)
+{
+       struct mgcp_endpoint *enext, *e;
+       struct mgcp_subchannel *s, *sub;
+       int i, prune = 1;
+
+       if (g->ha || !g->realtime || ast_mutex_trylock(&g->msgs_lock) || g->msgs) {
+               ast_mutex_unlock(&g->msgs_lock);
+               return 0;
+       }
+
+       for (e = g->endpoints; e; e = e->next) {
+               ast_mutex_lock(&e->lock);
+               if (e->dsp || ast_mutex_trylock(&e->rqnt_queue_lock) || ast_mutex_trylock(&e->cmd_queue_lock)) {
+                       prune = 0;
+               } else if (e->rqnt_queue || e->cmd_queue) {
+                       prune = 0;
+               }
+               s = e->sub;
+               for (i = 0; (i < MAX_SUBS) && s; i++) {
+                       ast_mutex_lock(&s->lock);
+                       if (!ast_strlen_zero(s->cxident) || s->rtp || ast_mutex_trylock(&s->cx_queue_lock) || s->gate) {
+                               prune = 0;
+                       } else if (s->cx_queue) {
+                               prune = 0;
+                       }
+                       s = s->next;
+               }
+       }
+
+       for (e = g->endpoints, sub = e->sub, enext = e->next; e; e = enext, enext = e->next) {
+               for (i = 0; (i < MAX_SUBS) && sub; i++) {
+                       s = sub;
+                       sub = sub->next;
+                       ast_mutex_unlock(&s->lock);
+                       ast_mutex_unlock(&s->cx_queue_lock);
+                       if (prune) {
+                               ast_mutex_destroy(&s->lock);
+                               ast_mutex_destroy(&s->cx_queue_lock);
+                               free(s);
+                       }
+               }
+               ast_mutex_unlock(&e->lock);
+               ast_mutex_unlock(&e->rqnt_queue_lock);
+               ast_mutex_unlock(&e->cmd_queue_lock);
+               if (prune) {
+                       ast_mutex_destroy(&e->lock);
+                       ast_mutex_destroy(&e->rqnt_queue_lock);
+                       ast_mutex_destroy(&e->cmd_queue_lock);
+                       free(e);
+               }
+       }
+       if (prune) {
+               ast_debug(1, "***** MGCP REALTIME PRUNE GW: %s\n", g->name);
+       }
+       return prune;
+}
+
 static void *do_monitor(void *data)
 {
        int res;
        int reloading;
+       struct mgcp_gateway *g, *gprev;
        /*struct mgcp_gateway *g;*/
        /*struct mgcp_endpoint *e;*/
        /*time_t thispass = 0, lastpass = 0;*/
+       time_t lastrun = 0;
 
        /* Add an I/O event to our UDP socket */
-       if (mgcpsock > -1) 
+       if (mgcpsock > -1) {
                mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
-       
+       }
        /* This thread monitors all the frame relay interfaces which are not yet in use
           (and thus do not have a separate thread) indefinitely */
        /* From here on out, we die whenever asked */
-       for(;;) {
+       for (;;) {
                /* Check for a reload request */
                ast_mutex_lock(&mgcp_reload_lock);
                reloading = mgcp_reloading;
                mgcp_reloading = 0;
                ast_mutex_unlock(&mgcp_reload_lock);
                if (reloading) {
-                       if (option_verbose > 0)
-                               ast_verbose(VERBOSE_PREFIX_1 "Reloading MGCP\n");
-                       mgcp_do_reload();
+                       ast_verb(1, "Reloading MGCP\n");
+                       reload_config(1);
                        /* Add an I/O event to our UDP socket */
-                       if (mgcpsock > -1) 
+                       if (mgcpsock > -1 && !mgcpsock_read_id) {
                                mgcpsock_read_id = ast_io_add(io, mgcpsock, mgcpsock_read, AST_IO_IN, NULL);
+                       }
                }
 
                /* Check for interfaces needing to be killed */
@@ -3486,6 +3841,34 @@ static void *do_monitor(void *data)
                        g = g->next;
                }
 #endif
+               /* pruning unused realtime gateways, running in every 60 seconds*/
+               if(time(NULL) > (lastrun + 60)) {
+                       ast_mutex_lock(&gatelock);
+                       g = gateways;
+                       gprev = NULL;
+                       while(g) {
+                               if(g->realtime) {
+                                       if(mgcp_prune_realtime_gateway(g)) {
+                                               if(gprev) {
+                                                       gprev->next = g->next;
+                                               } else {
+                                                       gateways = g->next;
+                                               }
+                                               ast_mutex_unlock(&g->msgs_lock);
+                                               ast_mutex_destroy(&g->msgs_lock);
+                                               free(g);
+                                       } else {
+                                               ast_mutex_unlock(&g->msgs_lock);
+                                               gprev = g;
+                                       }
+                               } else {
+                                       gprev = g;
+                               }
+                               g = g->next;
+                       }
+                       ast_mutex_unlock(&gatelock);
+                       lastrun = time(NULL);
+               }
                /* Okay, now that we know what to do, release the network lock */
                ast_mutex_unlock(&netlock);
                /* And from now on, we're okay to be killed, so release the monitor lock as well */
@@ -3494,12 +3877,14 @@ static void *do_monitor(void *data)
                /* Wait for sched or io */
                res = ast_sched_wait(sched);
                /* copied from chan_sip.c */
-               if ((res < 0) || (res > 1000))
+               if ((res < 0) || (res > 1000)) {
                        res = 1000;
+               }
                res = ast_io_wait(io, res);
                ast_mutex_lock(&monlock);
-               if (res >= 0) 
+               if (res >= 0) {
                        ast_sched_runq(sched);
+               }
                ast_mutex_unlock(&monlock);
        }
        /* Never reached */
@@ -3535,37 +3920,30 @@ static int restart_monitor(void)
        return 0;
 }
 
-static struct ast_channel *mgcp_request(const char *type, int format, void *data, int *cause)
+static struct ast_channel *mgcp_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, int *cause)
 {
-       int oldformat;
        struct mgcp_subchannel *sub;
        struct ast_channel *tmpc = NULL;
        char tmp[256];
-       char *dest = data;
 
-       oldformat = format;
-       format &= capability;
-       if (!format) {
-               ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
-               return NULL;
+       if (!(ast_format_cap_has_joint(cap, global_capability))) {
+               ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+               /*return NULL;*/
        }
        ast_copy_string(tmp, dest, sizeof(tmp));
        if (ast_strlen_zero(tmp)) {
                ast_log(LOG_NOTICE, "MGCP Channels require an endpoint\n");
                return NULL;
        }
-       sub = find_subchannel_and_lock(tmp, 0, NULL);
-       if (!sub) {
+       if (!(sub = find_subchannel_and_lock(tmp, 0, NULL))) {
                ast_log(LOG_WARNING, "Unable to find MGCP endpoint '%s'\n", tmp);
                *cause = AST_CAUSE_UNREGISTERED;
                return NULL;
        }
-       
-       if (option_verbose > 2) {
-               ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_request(%s)\n", tmp);
-               ast_verbose(VERBOSE_PREFIX_3 "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n", 
+
+       ast_verb(3, "MGCP mgcp_request(%s)\n", tmp);
+       ast_verb(3, "MGCP cw: %d, dnd: %d, so: %d, sno: %d\n",
                        sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
-       }
        /* Must be busy */
        if (((sub->parent->callwaiting) && ((sub->owner) && (sub->next->owner))) ||
                ((!sub->parent->callwaiting) && (sub->owner)) ||
@@ -3581,7 +3959,7 @@ static struct ast_channel *mgcp_request(const char *type, int format, void *data
                ast_mutex_unlock(&sub->lock);
                return NULL;
        }
-       tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
+       tmpc = mgcp_new(sub->owner ? sub->next : sub, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
        ast_mutex_unlock(&sub->lock);
        if (!tmpc)
                ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
@@ -3596,418 +3974,508 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
        struct mgcp_gateway *gw;
        struct mgcp_endpoint *e;
        struct mgcp_subchannel *sub;
+       struct ast_variable *chanvars = NULL;
+
        /*char txident[80];*/
        int i=0, y=0;
        int gw_reload = 0;
        int ep_reload = 0;
-       canreinvite = CANREINVITE;
+       directmedia = DIRECTMEDIA;
 
        /* locate existing gateway */
-       gw = gateways;
-       while (gw) {
+       for (gw = gateways; gw; gw = gw->next) {
                if (!strcasecmp(cat, gw->name)) {
                        /* gateway already exists */
                        gw->delme = 0;
                        gw_reload = 1;
                        break;
                }
-               gw = gw->next;
        }
 
-       if (!gw)
-               gw = malloc(sizeof(struct mgcp_gateway));
+       if (!gw && !(gw = ast_calloc(1, sizeof(*gw)))) {
+               return NULL;
+       }
 
-       if (gw) {
-               if (!gw_reload) {
-                       memset(gw, 0, sizeof(struct mgcp_gateway));
-                       gw->expire = -1;
-                       gw->retransid = -1; /* SC */
-                       ast_mutex_init(&gw->msgs_lock);
-                       ast_copy_string(gw->name, cat, sizeof(gw->name));
-                       /* check if the name is numeric ip */
-                       if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
-                               gw->isnamedottedip = 1;
-               }
-               while(v) {
-                       if (!strcasecmp(v->name, "host")) {
-                               if (!strcasecmp(v->value, "dynamic")) {
-                                       /* They'll register with us */
-                                       gw->dynamic = 1;
-                                       memset(&gw->addr.sin_addr, 0, 4);
-                                       if (gw->addr.sin_port) {
-                                               /* If we've already got a port, make it the default rather than absolute */
-                                               gw->defaddr.sin_port = gw->addr.sin_port;
-                                               gw->addr.sin_port = 0;
-                                       }
-                               } else {
-                                       /* Non-dynamic.  Make sure we become that way if we're not */
-                                       if (gw->expire > -1)
-                                               ast_sched_del(sched, gw->expire);
-                                       gw->expire = -1;
-                                       gw->dynamic = 0;
-                                       if (ast_get_ip(&gw->addr, v->value)) {
+       if (!gw_reload) {
+               gw->expire = -1;
+               gw->realtime = 0;
+               gw->retransid = -1;
+               ast_mutex_init(&gw->msgs_lock);
+               ast_copy_string(gw->name, cat, sizeof(gw->name));
+               /* check if the name is numeric ip */
+               if ((strchr(gw->name, '.')) && inet_addr(gw->name) != INADDR_NONE)
+                       gw->isnamedottedip = 1;
+       }
+       for (; v; v = v->next) {
+               if (!strcasecmp(v->name, "host")) {
+                       if (!strcasecmp(v->value, "dynamic")) {
+                               /* They'll register with us */
+                               gw->dynamic = 1;
+                               memset(&gw->addr.sin_addr, 0, 4);
+                               if (gw->addr.sin_port) {
+                                       /* If we've already got a port, make it the default rather than absolute */
+                                       gw->defaddr.sin_port = gw->addr.sin_port;
+                                       gw->addr.sin_port = 0;
+                               }
+                       } else {
+                               /* Non-dynamic.  Make sure we become that way if we're not */
+                               AST_SCHED_DEL(sched, gw->expire);
+                               gw->dynamic = 0;
+                               {
+                                       struct ast_sockaddr tmp;
+
+                                       ast_sockaddr_from_sin(&tmp, &gw->addr);
+                                       if (ast_get_ip(&tmp, v->value)) {
                                                if (!gw_reload) {
                                                        ast_mutex_destroy(&gw->msgs_lock);
-                                                       free(gw);
+                                                       ast_free(gw);
                                                }
                                                return NULL;
                                        }
+                                       ast_sockaddr_to_sin(&tmp, &gw->addr);
                                }
-                       } else if (!strcasecmp(v->name, "defaultip")) {
-                               if (ast_get_ip(&gw->defaddr, v->value)) {
-                                       if (!gw_reload) {
-                                               ast_mutex_destroy(&gw->msgs_lock);
-                                               free(gw);
-                                       }
-                                       return NULL;
-                               }
-                       } else if (!strcasecmp(v->name, "permit") ||
-                               !strcasecmp(v->name, "deny")) {
-                               gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL);
-                       } else if (!strcasecmp(v->name, "port")) {
-                               gw->addr.sin_port = htons(atoi(v->value));
-                       } else if (!strcasecmp(v->name, "context")) {
-                               ast_copy_string(context, v->value, sizeof(context));
-                       } else if (!strcasecmp(v->name, "dtmfmode")) {
-                               if (!strcasecmp(v->value, "inband"))
-                                       dtmfmode = MGCP_DTMF_INBAND;
-                               else if (!strcasecmp(v->value, "rfc2833")) 
-                                       dtmfmode = MGCP_DTMF_RFC2833;
-                               else if (!strcasecmp(v->value, "hybrid"))
-                                       dtmfmode = MGCP_DTMF_HYBRID;
-                               else if (!strcasecmp(v->value, "none")) 
-                                       dtmfmode = 0;
-                               else
-                                       ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
-                       } else if (!strcasecmp(v->name, "nat")) {
-                               nat = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "callerid")) {
-                               if (!strcasecmp(v->value, "asreceived")) {
-                                       cid_num[0] = '\0';
-                                       cid_name[0] = '\0';
-                               } else {
-                                       ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
-                               }
-                       } else if (!strcasecmp(v->name, "language")) {
-                               ast_copy_string(language, v->value, sizeof(language));
-                       } else if (!strcasecmp(v->name, "accountcode")) {
-                               ast_copy_string(accountcode, v->value, sizeof(accountcode));
-                       } else if (!strcasecmp(v->name, "amaflags")) {
-                               y = ast_cdr_amaflags2int(v->value);
-                               if (y < 0) {
-                                       ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
-                               } else {
-                                       amaflags = y;
-                               }
-                       } else if (!strcasecmp(v->name, "musiconhold")) {
-                               ast_copy_string(musicclass, v->value, sizeof(musicclass));
-                       } else if (!strcasecmp(v->name, "callgroup")) {
-                               cur_callergroup = ast_get_group(v->value);
-                       } else if (!strcasecmp(v->name, "pickupgroup")) {
-                               cur_pickupgroup = ast_get_group(v->value);
-                       } else if (!strcasecmp(v->name, "immediate")) {
-                               immediate = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "cancallforward")) {
-                               cancallforward = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "singlepath")) {
-                               singlepath = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "canreinvite")) {
-                               canreinvite = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "mailbox")) {
-                               ast_copy_string(mailbox, v->value, sizeof(mailbox));
-                       } else if (!strcasecmp(v->name, "adsi")) {
-                               adsi = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "callreturn")) {
-                               callreturn = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "callwaiting")) {
-                               callwaiting = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "slowsequence")) {
-                               slowsequence = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "transfer")) {
-                               transfer = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "threewaycalling")) {
-                               threewaycalling = ast_true(v->value);
-                       } else if (!strcasecmp(v->name, "wcardep")) {
-                               /* locate existing endpoint */
-                               e = gw->endpoints;
-                               while (e) {
-                                       if (!strcasecmp(v->value, e->name)) {
-                                               /* endpoint already exists */
-                                               e->delme = 0;
-                                               ep_reload = 1;
-                                               break;
-                                       }
-                                       e = e->next;
+                       }
+               } else if (!strcasecmp(v->name, "defaultip")) {
+                       struct ast_sockaddr tmp;
+
+                       ast_sockaddr_from_sin(&tmp, &gw->defaddr);
+                       if (ast_get_ip(&tmp, v->value)) {
+                               if (!gw_reload) {
+                                       ast_mutex_destroy(&gw->msgs_lock);
+                                       ast_free(gw);
                                }
-
-                               if (!e) {
-                                       /* Allocate wildcard endpoint */
-                                       e = malloc(sizeof(struct mgcp_endpoint));
-                                       ep_reload = 0;
+                               return NULL;
+                       }
+                       ast_sockaddr_to_sin(&tmp, &gw->defaddr);
+               } else if (!strcasecmp(v->name, "permit") ||
+                       !strcasecmp(v->name, "deny")) {
+                       gw->ha = ast_append_ha(v->name, v->value, gw->ha, NULL);
+               } else if (!strcasecmp(v->name, "port")) {
+                       gw->addr.sin_port = htons(atoi(v->value));
+               } else if (!strcasecmp(v->name, "context")) {
+                       ast_copy_string(context, v->value, sizeof(context));
+               } else if (!strcasecmp(v->name, "dtmfmode")) {
+                       if (!strcasecmp(v->value, "inband"))
+                               dtmfmode = MGCP_DTMF_INBAND;
+                       else if (!strcasecmp(v->value, "rfc2833"))
+                               dtmfmode = MGCP_DTMF_RFC2833;
+                       else if (!strcasecmp(v->value, "hybrid"))
+                               dtmfmode = MGCP_DTMF_HYBRID;
+                       else if (!strcasecmp(v->value, "none"))
+                               dtmfmode = 0;
+                       else
+                               ast_log(LOG_WARNING, "'%s' is not a valid DTMF mode at line %d\n", v->value, v->lineno);
+               } else if (!strcasecmp(v->name, "nat")) {
+                       nat = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "ncs")) {
+                       ncs = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "hangupongateremove")) {
+                       hangupongateremove = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "pktcgatealloc")) {
+                       pktcgatealloc = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "callerid")) {
+                       if (!strcasecmp(v->value, "asreceived")) {
+                               cid_num[0] = '\0';
+                               cid_name[0] = '\0';
+                       } else {
+                               ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
+                       }
+               } else if (!strcasecmp(v->name, "language")) {
+                       ast_copy_string(language, v->value, sizeof(language));
+               } else if (!strcasecmp(v->name, "accountcode")) {
+                       ast_copy_string(accountcode, v->value, sizeof(accountcode));
+               } else if (!strcasecmp(v->name, "amaflags")) {
+                       y = ast_cdr_amaflags2int(v->value);
+                       if (y < 0) {
+                               ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
+                       } else {
+                               amaflags = y;
+                       }
+               } else if (!strcasecmp(v->name, "setvar")) {
+                       chanvars = add_var(v->value, chanvars);
+               } else if (!strcasecmp(v->name, "clearvars")) {
+                       if (chanvars) {
+                               ast_variables_destroy(chanvars);
+                               chanvars = NULL;
+                       }
+               } else if (!strcasecmp(v->name, "musiconhold")) {
+                       ast_copy_string(musicclass, v->value, sizeof(musicclass));
+               } else if (!strcasecmp(v->name, "parkinglot")) {
+                       ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
+               } else if (!strcasecmp(v->name, "callgroup")) {
+                       cur_callergroup = ast_get_group(v->value);
+               } else if (!strcasecmp(v->name, "pickupgroup")) {
+                       cur_pickupgroup = ast_get_group(v->value);
+               } else if (!strcasecmp(v->name, "immediate")) {
+                       immediate = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "cancallforward")) {
+                       cancallforward = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "singlepath")) {
+                       singlepath = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
+                       directmedia = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "mailbox")) {
+                       ast_copy_string(mailbox, v->value, sizeof(mailbox));
+               } else if (!strcasecmp(v->name, "hasvoicemail")) {
+                       if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
+                               ast_copy_string(mailbox, gw->name, sizeof(mailbox));
+                       }
+               } else if (!strcasecmp(v->name, "adsi")) {
+                       adsi = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "callreturn")) {
+                       callreturn = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "callwaiting")) {
+                       callwaiting = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "slowsequence")) {
+                       slowsequence = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "transfer")) {
+                       transfer = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "threewaycalling")) {
+                       threewaycalling = ast_true(v->value);
+               } else if (!strcasecmp(v->name, "wcardep")) {
+                       /* locate existing endpoint */
+                       for (e = gw->endpoints; e; e = e->next) {
+                               if (!strcasecmp(v->value, e->name)) {
+                                       /* endpoint already exists */
+                                       e->delme = 0;
+                                       ep_reload = 1;
+                                       break;
                                }
+                       }
 
-                               if (e) {
-                                       if (!ep_reload) {
-                                               memset(e, 0, sizeof(struct mgcp_endpoint));
-                                               ast_mutex_init(&e->lock);
-                                               ast_mutex_init(&e->rqnt_queue_lock);
-                                               ast_mutex_init(&e->cmd_queue_lock);
-                                               ast_copy_string(e->name, v->value, sizeof(e->name));
-                                               e->needaudit = 1;
-                                       }
-                                       ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
-                                       /* XXX Should we really check for uniqueness?? XXX */
-                                       ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
-                                       ast_copy_string(e->context, context, sizeof(e->context));
-                                       ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
-                                       ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
-                                       ast_copy_string(e->language, language, sizeof(e->language));
-                                       ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
-                                       ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
-                                       if (!ast_strlen_zero(e->mailbox)) {
-                                               e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
-                                                       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, e->mailbox,
-                                                       AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
-                                                       AST_EVENT_IE_END);
-                                       }
-                                       snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
-                                       e->msgstate = -1;
-                                       e->amaflags = amaflags;
-                                       e->capability = capability;
-                                       e->parent = gw;
-                                       e->dtmfmode = dtmfmode;
-                                       if (!ep_reload && e->sub && e->sub->rtp)
-                                               e->dtmfmode |= MGCP_DTMF_INBAND;
-                                       e->adsi = adsi;
-                                       e->type = TYPE_LINE;
-                                       e->immediate = immediate;
-                                       e->callgroup=cur_callergroup;
-                                       e->pickupgroup=cur_pickupgroup;
-                                       e->callreturn = callreturn;
-                                       e->cancallforward = cancallforward;
-                                       e->singlepath = singlepath;
-                                       e->canreinvite = canreinvite;
-                                       e->callwaiting = callwaiting;
-                                       e->hascallwaiting = callwaiting;
-                                       e->slowsequence = slowsequence;
-                                       e->transfer = transfer;
-                                       e->threewaycalling = threewaycalling;
-                                       e->onhooktime = time(NULL);
-                                       /* ASSUME we're onhook */
-                                       e->hookstate = MGCP_ONHOOK;
-                                       if (!ep_reload) {
-                                               /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/
-                                               for (i = 0; i < MAX_SUBS; i++) {
-                                                       sub = malloc(sizeof(struct mgcp_subchannel));
-                                                       if (sub) {
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
-                                                               memset(sub, 0, sizeof(struct mgcp_subchannel));
-                                                               ast_mutex_init(&sub->lock);
-                                                               ast_mutex_init(&sub->cx_queue_lock);
-                                                               sub->parent = e;
-                                                               sub->id = i;
-                                                               snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
-                                                               /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/
-                                                               sub->cxmode = MGCP_CX_INACTIVE;
-                                                               sub->nat = nat;
-                                                               sub->next = e->sub;
-                                                               e->sub = sub;
-                                                       } else {
-                                                               /* XXX Should find a way to clean up our memory */
-                                                               ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
-                                                               return NULL;
-                                                       }
-                                               }
-                                               /* Make out subs a circular linked list so we can always sping through the whole bunch */
-                                               sub = e->sub;
-                                               /* find the end of the list */
-                                               while(sub->next){
-                                                       sub = sub->next;
-                                               }
-                                               /* set the last sub->next to the first sub */
-                                               sub->next = e->sub;
+                       if (!e) {
+                               /* Allocate wildcard endpoint */
+                               e = ast_calloc(1, sizeof(*e));
+                               ep_reload = 0;
+                       }
 
-                                               e->next = gw->endpoints;
-                                               gw->endpoints = e;
-                                       }
+                       if (e) {
+                               if (!ep_reload) {
+                                       memset(e, 0, sizeof(struct mgcp_endpoint));
+                                       ast_mutex_init(&e->lock);
+                                       ast_mutex_init(&e->rqnt_queue_lock);
+                                       ast_mutex_init(&e->cmd_queue_lock);
+                                       e->cap = ast_format_cap_alloc_nolock();
+                                       ast_copy_string(e->name, v->value, sizeof(e->name));
+                                       e->needaudit = 1;
                                }
-                       } else if (!strcasecmp(v->name, "trunk") ||
-                                  !strcasecmp(v->name, "line")) {
-
-                               /* locate existing endpoint */
-                               e = gw->endpoints;
-                               while (e) {
-                                       if (!strcasecmp(v->value, e->name)) {
-                                               /* endpoint already exists */
-                                               e->delme = 0;
-                                               ep_reload = 1;
-                                               break;
+                               ast_copy_string(gw->wcardep, v->value, sizeof(gw->wcardep));
+                               /* XXX Should we really check for uniqueness?? XXX */
+                               ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
+                               ast_copy_string(e->context, context, sizeof(e->context));
+                               ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
+                               ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
+                               ast_copy_string(e->language, language, sizeof(e->language));
+                               ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
+                               ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
+                               ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
+                               if (!ast_strlen_zero(e->mailbox)) {
+                                       char *mbox, *cntx;
+                                       cntx = mbox = ast_strdupa(e->mailbox);
+                                       strsep(&cntx, "@");
+                                       if (ast_strlen_zero(cntx)) {
+                                               cntx = "default";
                                        }
-                                       e = e->next;
+                                       e->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "MGCP MWI subscription", NULL,
+                                               AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
+                                               AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx,
+                                               AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+                                               AST_EVENT_IE_END);
                                }
-
-                               if (!e) {
-                                       e = malloc(sizeof(struct mgcp_endpoint));
-                                       ep_reload = 0;
+                               snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
+                               e->msgstate = -1;
+                               e->amaflags = amaflags;
+                               ast_format_cap_copy(e->cap, global_capability);
+                               e->parent = gw;
+                               e->ncs = ncs;
+                               e->dtmfmode = dtmfmode;
+                               if (!ep_reload && e->sub && e->sub->rtp) {
+                                       e->dtmfmode |= MGCP_DTMF_INBAND;
                                }
-
-                               if (e) {
-                                       if (!ep_reload) {
-                                               memset(e, 0, sizeof(struct mgcp_endpoint));
-                                               ast_mutex_init(&e->lock);
-                                               ast_mutex_init(&e->rqnt_queue_lock);
-                                               ast_mutex_init(&e->cmd_queue_lock);
-                                               ast_copy_string(e->name, v->value, sizeof(e->name));
-                                               e->needaudit = 1;
-                                       }
-                                       /* XXX Should we really check for uniqueness?? XXX */
-                                       ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
-                                       ast_copy_string(e->context, context, sizeof(e->context));
-                                       ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
-                                       ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
-                                       ast_copy_string(e->language, language, sizeof(e->language));
-                                       ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
-                                       ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
-                                       if (!ast_strlen_zero(mailbox)) {
-                                               ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
-                                       }
-                                       if (!ep_reload) {
-                                               /* XXX potential issue due to reload */
-                                               e->msgstate = -1;
-                                               e->parent = gw;
-                                       }
-                                       e->amaflags = amaflags;
-                                       e->capability = capability;
-                                       e->dtmfmode = dtmfmode;
-                                       e->adsi = adsi;
-                                       if (!strcasecmp(v->name, "trunk"))
-                                               e->type = TYPE_TRUNK;
-                                       else
-                                               e->type = TYPE_LINE;
-
-                                       e->immediate = immediate;
-                                       e->callgroup=cur_callergroup;
-                                       e->pickupgroup=cur_pickupgroup;
-                                       e->callreturn = callreturn;
-                                       e->cancallforward = cancallforward;
-                                       e->canreinvite = canreinvite;
-                                       e->singlepath = singlepath;
-                                       e->callwaiting = callwaiting;
-                                       e->hascallwaiting = callwaiting;
-                                       e->slowsequence = slowsequence;
-                                       e->transfer = transfer;
-                                       e->threewaycalling = threewaycalling;
-                                       if (!ep_reload) {
-                                               e->onhooktime = time(NULL);
-                                               /* ASSUME we're onhook */
-                                               e->hookstate = MGCP_ONHOOK;
-                                               snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
-                                       }
-
-                                       for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
-                                               if (!ep_reload) {
-                                                       sub = malloc(sizeof(struct mgcp_subchannel));
-                                               } else {
-                                                       if (!sub)
-                                                               sub = e->sub;
-                                                       else
-                                                               sub = sub->next;
-                                               }
-
+                               e->adsi = adsi;
+                               e->type = TYPE_LINE;
+                               e->immediate = immediate;
+                               e->callgroup=cur_callergroup;
+                               e->pickupgroup=cur_pickupgroup;
+                               e->callreturn = callreturn;
+                               e->cancallforward = cancallforward;
+                               e->singlepath = singlepath;
+                               e->directmedia = directmedia;
+                               e->callwaiting = callwaiting;
+                               e->hascallwaiting = callwaiting;
+                               e->slowsequence = slowsequence;
+                               e->transfer = transfer;
+                               e->threewaycalling = threewaycalling;
+                               e->onhooktime = time(NULL);
+                               /* ASSUME we're onhook */
+                               e->hookstate = MGCP_ONHOOK;
+                               e->chanvars = copy_vars(chanvars);
+                               if (!ep_reload) {
+                                       /*snprintf(txident, sizeof(txident), "%08lx", ast_random());*/
+                                       for (i = 0; i < MAX_SUBS; i++) {
+                                               sub = ast_calloc(1, sizeof(*sub));
                                                if (sub) {
-                                                       if (!ep_reload) {
-                                                               ast_verbose(VERBOSE_PREFIX_3 "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
-                                                               memset(sub, 0, sizeof(struct mgcp_subchannel));
-                                                               ast_mutex_init(&sub->lock);
-                                                               ast_mutex_init(&sub->cx_queue_lock);
-                                                               ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
-                                                               sub->parent = e;
-                                                               sub->id = i;
-                                                               snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
-                                                               sub->cxmode = MGCP_CX_INACTIVE;
-                                                               sub->next = e->sub;
-                                                               e->sub = sub;
-                                                       }
+                                                       ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
+                                                       ast_mutex_init(&sub->lock);
+                                                       ast_mutex_init(&sub->cx_queue_lock);
+                                                       sub->parent = e;
+                                                       sub->id = i;
+                                                       snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
+                                                       /*stnrcpy(sub->txident, txident, sizeof(sub->txident) - 1);*/
+                                                       sub->cxmode = MGCP_CX_INACTIVE;
                                                        sub->nat = nat;
+                                                       sub->gate = NULL;
+                                                       sub->sdpsent = 0;
+                                                       sub->next = e->sub;
+                                                       e->sub = sub;
                                                } else {
                                                        /* XXX Should find a way to clean up our memory */
                                                        ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
                                                        return NULL;
                                                }
                                        }
+                                       /* Make out subs a circular linked list so we can always sping through the whole bunch */
+                                       /* find the end of the list */
+                                       for (sub = e->sub; sub && sub->next; sub = sub->next);
+                                       /* set the last sub->next to the first sub */
+                                       sub->next = e->sub;
+
+                                       e->next = gw->endpoints;
+                                       gw->endpoints = e;
+                               }
+                       }
+               } else if (!strcasecmp(v->name, "trunk") ||
+                          !strcasecmp(v->name, "line")) {
+
+                       /* locate existing endpoint */
+                       for (e = gw->endpoints; e; e = e->next) {
+                               if (!strcasecmp(v->value, e->name)) {
+                                       /* endpoint already exists */
+                                       e->delme = 0;
+                                       ep_reload = 1;
+                                       break;
+                               }
+                       }
+
+                       if (!e) {
+                               e = ast_calloc(1, sizeof(*e));
+                               ep_reload = 0;
+                       }
+
+                       if (e) {
+                               if (!ep_reload) {
+                                       ast_mutex_init(&e->lock);
+                                       ast_mutex_init(&e->rqnt_queue_lock);
+                                       ast_mutex_init(&e->cmd_queue_lock);
+                                       e->cap = ast_format_cap_alloc_nolock();
+                                       ast_copy_string(e->name, v->value, sizeof(e->name));
+                                       e->needaudit = 1;
+                               }
+                               /* XXX Should we really check for uniqueness?? XXX */
+                               ast_copy_string(e->accountcode, accountcode, sizeof(e->accountcode));
+                               ast_copy_string(e->context, context, sizeof(e->context));
+                               ast_copy_string(e->cid_num, cid_num, sizeof(e->cid_num));
+                               ast_copy_string(e->cid_name, cid_name, sizeof(e->cid_name));
+                               ast_copy_string(e->language, language, sizeof(e->language));
+                               ast_copy_string(e->musicclass, musicclass, sizeof(e->musicclass));
+                               ast_copy_string(e->mailbox, mailbox, sizeof(e->mailbox));
+                               ast_copy_string(e->parkinglot, parkinglot, sizeof(e->parkinglot));
+                               if (!ast_strlen_zero(mailbox)) {
+                                       ast_verb(3, "Setting mailbox '%s' on %s@%s\n", mailbox, gw->name, e->name);
+                               }
+                               if (!ep_reload) {
+                                       /* XXX potential issue due to reload */
+                                       e->msgstate = -1;
+                                       e->parent = gw;
+                               }
+                               e->amaflags = amaflags;
+                               ast_format_cap_copy(e->cap, global_capability);
+                               e->dtmfmode = dtmfmode;
+                               e->ncs = ncs;
+                               e->pktcgatealloc = pktcgatealloc;
+                               e->hangupongateremove = hangupongateremove;
+                               e->adsi = adsi;
+                               e->type = (!strcasecmp(v->name, "trunk")) ? TYPE_TRUNK : TYPE_LINE;
+                               e->immediate = immediate;
+                               e->callgroup=cur_callergroup;
+                               e->pickupgroup=cur_pickupgroup;
+                               e->callreturn = callreturn;
+                               e->cancallforward = cancallforward;
+                               e->directmedia = directmedia;
+                               e->singlepath = singlepath;
+                               e->callwaiting = callwaiting;
+                               e->hascallwaiting = callwaiting;
+                               e->slowsequence = slowsequence;
+                               e->transfer = transfer;
+                               e->threewaycalling = threewaycalling;
+
+                               /* If we already have a valid chanvars, it's not a new endpoint (it's a reload),
+                                  so first, free previous mem
+                                */
+                               if (e->chanvars) {
+                                       ast_variables_destroy(e->chanvars);
+                                       e->chanvars = NULL;
+                               }
+                               e->chanvars = copy_vars(chanvars);
+
+                               if (!ep_reload) {
+                                       e->onhooktime = time(NULL);
+                                       /* ASSUME we're onhook */
+                                       e->hookstate = MGCP_ONHOOK;
+                                       snprintf(e->rqnt_ident, sizeof(e->rqnt_ident), "%08lx", ast_random());
+                               }
+
+                               for (i = 0, sub = NULL; i < MAX_SUBS; i++) {
                                        if (!ep_reload) {
-                                               /* Make out subs a circular linked list so we can always sping through the whole bunch */
-                                               sub = e->sub;
-                                               /* find the end of the list */
-                                               while (sub->next) {
+                                               sub = ast_calloc(1, sizeof(*sub));
+                                       } else {
+                                               if (!sub) {
+                                                       sub = e->sub;
+                                               } else {
                                                        sub = sub->next;
                                                }
-                                               /* set the last sub->next to the first sub */
-                                               sub->next = e->sub;
+                                       }
 
-                                               e->next = gw->endpoints;
-                                               gw->endpoints = e;
+                                       if (sub) {
+                                               if (!ep_reload) {
+                                                       ast_verb(3, "Allocating subchannel '%d' on %s@%s\n", i, e->name, gw->name);
+                                                       ast_mutex_init(&sub->lock);
+                                                       ast_mutex_init(&sub->cx_queue_lock);
+                                                       ast_copy_string(sub->magic, MGCP_SUBCHANNEL_MAGIC, sizeof(sub->magic));
+                                                       sub->parent = e;
+                                                       sub->id = i;
+                                                       snprintf(sub->txident, sizeof(sub->txident), "%08lx", ast_random());
+                                                       sub->cxmode = MGCP_CX_INACTIVE;
+                                                       sub->next = e->sub;
+                                                       e->sub = sub;
+                                               }
+                                               sub->nat = nat;
+                                       } else {
+                                               /* XXX Should find a way to clean up our memory */
+                                               ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
+                                               return NULL;
                                        }
                                }
-                       } else
-                               ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
-                       v = v->next;
+                               if (!ep_reload) {
+                                       /* Make out subs a circular linked list so we can always sping through the whole bunch */
+                                       /* find the end of the list */
+                                       for (sub = e->sub; sub && sub->next; sub = sub->next);
+                                       /* set the last sub->next to the first sub */
+                                       sub->next = e->sub;
+
+                                       e->next = gw->endpoints;
+                                       gw->endpoints = e;
+                               }
+                       }
+               } else if (!strcasecmp(v->name, "name") || !strcasecmp(v->name, "lines")) {
+                       /* just eliminate realtime warnings */
+               } else {
+                       ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
                }
        }
        if (!ntohl(gw->addr.sin_addr.s_addr) && !gw->dynamic) {
                ast_log(LOG_WARNING, "Gateway '%s' lacks IP address and isn't dynamic\n", gw->name);
                if (!gw_reload) {
                        ast_mutex_destroy(&gw->msgs_lock);
-                       free(gw);
+                       ast_free(gw);
+               }
+
+               /* Return NULL */
+               gw_reload = 1;
+       } else {
+               gw->defaddr.sin_family = AF_INET;
+               gw->addr.sin_family = AF_INET;
+               if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) {
+                       gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
+               }
+               if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port)) {
+                       gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
+               }
+               {
+                       struct ast_sockaddr tmp1, tmp2;
+                       struct sockaddr_in tmp3 = {0,};
+
+                       tmp3.sin_addr = gw->ourip;
+                       ast_sockaddr_from_sin(&tmp1, &gw->addr);
+                       ast_sockaddr_from_sin(&tmp2, &tmp3);
+                       if (gw->addr.sin_addr.s_addr && ast_ouraddrfor(&tmp1, &tmp2)) {
+                               memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
+                       } else {
+                               ast_sockaddr_to_sin(&tmp2, &tmp3);
+                               gw->ourip = tmp3.sin_addr;
+                       }
                }
-               return NULL;
        }
-       gw->defaddr.sin_family = AF_INET;
-       gw->addr.sin_family = AF_INET;
-       if (gw->defaddr.sin_addr.s_addr && !ntohs(gw->defaddr.sin_port)) 
-               gw->defaddr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
-       if (gw->addr.sin_addr.s_addr && !ntohs(gw->addr.sin_port))
-               gw->addr.sin_port = htons(DEFAULT_MGCP_GW_PORT);
-       if (gw->addr.sin_addr.s_addr)
-               if (ast_ouraddrfor(&gw->addr.sin_addr, &gw->ourip))
-                       memcpy(&gw->ourip, &__ourip, sizeof(gw->ourip));
 
+       if (chanvars) {
+               ast_variables_destroy(chanvars);
+               chanvars = NULL;
+       }
        return (gw_reload ? NULL : gw);
 }
 
-static enum ast_rtp_get_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
+static enum ast_rtp_glue_result mgcp_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
 {
        struct mgcp_subchannel *sub = NULL;
 
-       if (!(sub = chan->tech_pvt) || !(sub->rtp))
-               return AST_RTP_GET_FAILED;
+       if (!(sub = ast_channel_tech_pvt(chan)) || !(sub->rtp))
+               return AST_RTP_GLUE_RESULT_FORBID;
 
-       *rtp = sub->rtp;
+       *instance = sub->rtp ? ao2_ref(sub->rtp, +1), sub->rtp : NULL;
 
-       if (sub->parent->canreinvite)
-               return AST_RTP_TRY_NATIVE;
+       if (sub->parent->directmedia)
+               return AST_RTP_GLUE_RESULT_REMOTE;
        else
-               return AST_RTP_TRY_PARTIAL;
+               return AST_RTP_GLUE_RESULT_LOCAL;
 }
 
-static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
+static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *cap, int nat_active)
 {
        /* XXX Is there such thing as video support with MGCP? XXX */
        struct mgcp_subchannel *sub;
-       sub = chan->tech_pvt;
+       sub = ast_channel_tech_pvt(chan);
        if (sub && !sub->alreadygone) {
-               transmit_modify_with_sdp(sub, rtp, codecs);
+               transmit_modify_with_sdp(sub, rtp, cap);
                return 0;
        }
        return -1;
 }
 
-static struct ast_rtp_protocol mgcp_rtp = {
+static void mgcp_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
+{
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
+       struct mgcp_endpoint *p = sub->parent;
+       ast_format_cap_copy(result, p->cap);
+}
+
+static struct ast_rtp_glue mgcp_rtp_glue = {
        .type = "MGCP",
        .get_rtp_info = mgcp_get_rtp_peer,
-       .set_rtp_peer = mgcp_set_rtp_peer,
+       .update_peer = mgcp_set_rtp_peer,
+       .get_codec = mgcp_get_codec,
 };
 
+
+static int acf_channel_read(struct ast_channel *chan, const char *funcname, char *args, char *buf, size_t buflen)
+{
+       struct mgcp_subchannel *sub = ast_channel_tech_pvt(chan);
+       int res = 0;
+
+       /* Sanity check */
+       if (!chan || ast_channel_tech(chan) != &mgcp_tech) {
+               ast_log(LOG_ERROR, "This function requires a valid MGCP channel\n");
+               return -1;
+       }
+
+       if (!strcasecmp(args, "ncs")) {
+               snprintf(buf, buflen, "%s", sub->parent->ncs ?  "yes":"no");
+       } else {
+               res = -1;
+       }
+       return res;
+}
+
+
 static void destroy_endpoint(struct mgcp_endpoint *e)
 {
        struct mgcp_subchannel *sub = e->sub->next, *s;
@@ -4019,12 +4487,18 @@ static void destroy_endpoint(struct mgcp_endpoint *e)
                        transmit_connection_del(sub);
                }
                if (sub->rtp) {
-                       ast_rtp_destroy(sub->rtp);
+                       ast_rtp_instance_destroy(sub->rtp);
                        sub->rtp = NULL;
                }
                memset(sub->magic, 0, sizeof(sub->magic));
                mgcp_queue_hangup(sub);
                dump_cmd_queues(NULL, sub);
+               if(sub->gate) {
+                       sub->gate->tech_pvt = NULL;
+                       sub->gate->got_dq_gi = NULL;
+                       sub->gate->gate_remove = NULL;
+                       sub->gate->gate_open = NULL;
+               }
                ast_mutex_unlock(&sub->lock);
                sub = sub->next;
        }
@@ -4042,16 +4516,22 @@ static void destroy_endpoint(struct mgcp_endpoint *e)
                sub = sub->next;
                ast_mutex_destroy(&s->lock);
                ast_mutex_destroy(&s->cx_queue_lock);
-               free(s);
+               ast_free(s);
        }
 
        if (e->mwi_event_sub)
                ast_event_unsubscribe(e->mwi_event_sub);
 
+       if (e->chanvars) {
+               ast_variables_destroy(e->chanvars);
+               e->chanvars = NULL;
+       }
+
        ast_mutex_destroy(&e->lock);
        ast_mutex_destroy(&e->rqnt_queue_lock);
        ast_mutex_destroy(&e->cmd_queue_lock);
-       free(e);
+       e->cap = ast_format_cap_destroy(e->cap);
+       ast_free(e);
 }
 
 static void destroy_gateway(struct mgcp_gateway *g)
@@ -4061,7 +4541,7 @@ static void destroy_gateway(struct mgcp_gateway *g)
 
        dump_queue(g, NULL);
 
-       free (g);
+       ast_free(g);
 }
 
 static void prune_gateways(void)
@@ -4075,7 +4555,7 @@ static void prune_gateways(void)
        for (z = NULL, g = gateways; g;) {
                /* prune endpoints */
                for (p = NULL, e = g->endpoints; e; ) {
-                       if (e->delme || g->delme) {
+                       if (!g->realtime && (e->delme || g->delme)) {
                                t = e;
                                e = e->next;
                                if (!p)
@@ -4107,7 +4587,39 @@ static void prune_gateways(void)
        ast_mutex_unlock(&gatelock);
 }
 
-static int reload_config(void)
+static struct ast_variable *add_var(const char *buf, struct ast_variable *list)
+{
+       struct ast_variable *tmpvar = NULL;
+       char *varname = ast_strdupa(buf), *varval = NULL;
+
+       if ((varval = strchr(varname, '='))) {
+               *varval++ = '\0';
+               if ((tmpvar = ast_variable_new(varname, varval, ""))) {
+                       tmpvar->next = list;
+                       list = tmpvar;
+               }
+       }
+       return list;
+}
+
+/*! \brief
+ * duplicate a list of channel variables, \return the copy.
+ */
+static struct ast_variable *copy_vars(struct ast_variable *src)
+{
+       struct ast_variable *res = NULL, *tmp, *v = NULL;
+
+       for (v = src ; v ; v = v->next) {
+               if ((tmp = ast_variable_new(v->name, v->value, v->file))) {
+                       tmp->next = res;
+                       res = tmp;
+               }
+       }
+       return res;
+}
+
+
+static int reload_config(int reload)
 {
        struct ast_config *cfg;
        struct ast_variable *v;
@@ -4116,30 +4628,35 @@ static int reload_config(void)
        char *cat;
        struct ast_hostent ahp;
        struct hostent *hp;
-       int format;
+       struct ast_format format;
+       struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
        
        if (gethostname(ourhost, sizeof(ourhost)-1)) {
                ast_log(LOG_WARNING, "Unable to get hostname, MGCP disabled\n");
                return 0;
        }
-       cfg = ast_config_load(config);
+       cfg = ast_config_load(config, config_flags);
 
        /* We *must* have a config file otherwise stop immediately */
        if (!cfg) {
                ast_log(LOG_NOTICE, "Unable to load config %s, MGCP disabled\n", config);
                return 0;
+       } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
+               return 0;
+       } else if (cfg == CONFIG_STATUS_FILEINVALID) {
+               ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
+               return 0;
        }
+
        memset(&bindaddr, 0, sizeof(bindaddr));
        dtmfmode = 0;
 
        /* Copy the default jb config over global_jbconf */
        memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
 
-       v = ast_variable_browse(cfg, "general");
-       while (v) {
+       for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
                /* handle jb conf */
                if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
-                       v = v->next;
                        continue;
                }
 
@@ -4151,65 +4668,62 @@ static int reload_config(void)
                                memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
                        }
                } else if (!strcasecmp(v->name, "allow")) {
-                       format = ast_getformatbyname(v->value);
-                       if (format < 1) 
+                       ast_getformatbyname(v->value, &format);
+                       if (!format.id) {
                                ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
-                       else
-                               capability |= format;
+                       } else {
+                               ast_format_cap_add(global_capability, &format);
+                       }
                } else if (!strcasecmp(v->name, "disallow")) {
-                       format = ast_getformatbyname(v->value);
-                       if (format < 1) 
-                               ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
-                       else
-                               capability &= ~format;
+                       ast_getformatbyname(v->value, &format);
+                       if (!format.id) {
+                               ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
+                       } else {
+                               ast_format_cap_remove(global_capability, &format);
+                       }
                } else if (!strcasecmp(v->name, "tos")) {
-                       if (sscanf(v->value, "%d", &format) == 1)
-                               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, &qos.tos)) {
+                           ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
+                       }
+               } else if (!strcasecmp(v->name, "tos_audio")) {
+                       if (ast_str2tos(v->value, &qos.tos_audio))
+                           ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
+               } else if (!strcasecmp(v->name, "cos")) {
+                       if (ast_str2cos(v->value, &qos.cos))
+                           ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
+               } else if (!strcasecmp(v->name, "cos_audio")) {
+                       if (ast_str2cos(v->value, &qos.cos_audio))
+                           ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
                } else if (!strcasecmp(v->name, "port")) {
-                       if (sscanf(v->value, "%d", &ourport) == 1) {
+                       if (sscanf(v->value, "%5d", &ourport) == 1) {
                                bindaddr.sin_port = htons(ourport);
                        } else {
                                ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
                        }
+               } else if (!strcasecmp(v->name, "firstdigittimeout")) {
+                       firstdigittimeout = atoi(v->value);
+               } else if (!strcasecmp(v->name, "gendigittimeout")) {
+                       gendigittimeout = atoi(v->value);
+               } else if (!strcasecmp(v->name, "matchdigittimeout")) {
+                       matchdigittimeout = atoi(v->value);
                }
-               v = v->next;
        }
 
        /* mark existing entries for deletion */
        ast_mutex_lock(&gatelock);
-       g = gateways;
-       while (g) {
+       for (g = gateways; g; g = g->next) {
                g->delme = 1;
-               e = g->endpoints;
-               while (e) {
+               for (e = g->endpoints; e; e = e->next) {
                        e->delme = 1;
-                       e = e->next;
                }
-               g = g->next;
        }
        ast_mutex_unlock(&gatelock);
-       
-       cat = ast_category_browse(cfg, NULL);
-       while(cat) {
+
+       for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
                if (strcasecmp(cat, "general")) {
                        ast_mutex_lock(&gatelock);
-                       g = build_gateway(cat, ast_variable_browse(cfg, cat));
-                       if (g) {
-                               if (option_verbose > 2) {
-                                       ast_verbose(VERBOSE_PREFIX_3 "Added gateway '%s'\n", g->name);
-                               }
+                       if ((g = build_gateway(cat, ast_variable_browse(cfg, cat)))) {
+                               ast_verb(3, "Added gateway '%s'\n", g->name);
                                g->next = gateways;
                                gateways = g;
                        }
@@ -4221,11 +4735,10 @@ static int reload_config(void)
                                if (io) ast_io_wait(io, 10);
                        }
                }
-               cat = ast_category_browse(cfg, cat);
        }
 
-       /* prune deleted entries etc. */
-       prune_gateways();
+       /* prune deleted entries etc. */
+       prune_gateways();
 
        if (ntohl(bindaddr.sin_addr.s_addr)) {
                memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
@@ -4239,7 +4752,7 @@ static int reload_config(void)
                memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
        }
        if (!ntohs(bindaddr.sin_port))
-               bindaddr.sin_port = ntohs(DEFAULT_MGCP_CA_PORT);
+               bindaddr.sin_port = htons(DEFAULT_MGCP_CA_PORT);
        bindaddr.sin_family = AF_INET;
        ast_mutex_lock(&netlock);
        if (mgcpsock > -1)
@@ -4260,29 +4773,21 @@ static int reload_config(void)
                        close(mgcpsock);
                        mgcpsock = -1;
                } else {
-                       if (option_verbose > 1) {
-                               ast_verbose(VERBOSE_PREFIX_2 "MGCP Listening on %s:%d\n", 
+                       ast_verb(2, "MGCP Listening on %s:%d\n",
                                        ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
-                               ast_verbose(VERBOSE_PREFIX_2 "Using TOS bits %d\n", tos);
-                       }
-                       if (setsockopt(mgcpsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))) 
-                               ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
+                       ast_set_qos(mgcpsock, qos.tos, qos.cos, "MGCP");
                }
        }
        ast_mutex_unlock(&netlock);
        ast_config_destroy(cfg);
 
        /* send audit only to the new endpoints */
-       g = gateways;
-       while (g) {
-               e = g->endpoints;
-               while (e && e->needaudit) {
+       for (g = gateways; g; g = g->next) {
+               for (e = g->endpoints; e && e->needaudit; e = e->next) {
                        e->needaudit = 0;
                        transmit_audit_endpoint(e);
-                       ast_verbose(VERBOSE_PREFIX_3 "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
-                       e = e->next;
+                       ast_verb(3, "MGCP Auditing endpoint %s@%s for hookstate\n", e->name, g->name);
                }
-               g = g->next;
        }
 
        return 0;
@@ -4291,48 +4796,66 @@ static int reload_config(void)
 /*! \brief  load_module: PBX load module - initialization ---*/
 static int load_module(void)
 {
-       if (!(sched = sched_context_create())) {
+       struct ast_format tmpfmt;
+
+       if (!(global_capability = ast_format_cap_alloc())) {
+               return AST_MODULE_LOAD_FAILURE;
+       }
+       if (!(mgcp_tech.capabilities = ast_format_cap_alloc())) {
+               return AST_MODULE_LOAD_FAILURE;
+       }
+       ast_format_cap_add(global_capability, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
+       ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
+       ast_format_cap_add(mgcp_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
+       if (!(sched = ast_sched_context_create())) {
                ast_log(LOG_WARNING, "Unable to create schedule context\n");
                return AST_MODULE_LOAD_FAILURE;
        }
 
        if (!(io = io_context_create())) {
                ast_log(LOG_WARNING, "Unable to create I/O context\n");
-               sched_context_destroy(sched);
+               ast_sched_context_destroy(sched);
                return AST_MODULE_LOAD_FAILURE;
        }
 
-       if (reload_config())
+       if (reload_config(0))
                return AST_MODULE_LOAD_DECLINE;
 
        /* Make sure we can register our mgcp channel type */
        if (ast_channel_register(&mgcp_tech)) {
                ast_log(LOG_ERROR, "Unable to register channel class 'MGCP'\n");
                io_context_destroy(io);
-               sched_context_destroy(sched);
+               ast_sched_context_destroy(sched);
                return AST_MODULE_LOAD_FAILURE;
        }
 
-       ast_rtp_proto_register(&mgcp_rtp);
+       ast_rtp_glue_register(&mgcp_rtp_glue);
        ast_cli_register_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
-       
+
        /* And start the monitor for the first time */
        restart_monitor();
 
        return AST_MODULE_LOAD_SUCCESS;
 }
 
-/*! \brief  mgcp_do_reload: Reload module */
-static int mgcp_do_reload(void)
-{
-       reload_config();
-       return 0;
-}
-
-static int mgcp_reload(int fd, int argc, char *argv[])
+static char *mgcp_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        static int deprecated = 0;
-       if (!deprecated && argc > 0) {
+
+       if (e) {
+               switch (cmd) {
+               case CLI_INIT:
+                       e->command = "mgcp reload";
+                       e->usage =
+                               "Usage: mgcp reload\n"
+                               "       'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n";
+                       return NULL;
+               case CLI_GENERATE:
+                       return NULL;
+               }
+       }
+
+       if (!deprecated && a && a->argc > 0) {
                ast_log(LOG_WARNING, "'mgcp reload' is deprecated.  Please use 'reload chan_mgcp.so' instead.\n");
                deprecated = 1;
        }
@@ -4340,16 +4863,17 @@ static int mgcp_reload(int fd, int argc, char *argv[])
        ast_mutex_lock(&mgcp_reload_lock);
        if (mgcp_reloading) {
                ast_verbose("Previous mgcp reload not yet done\n");
-       } else
+       } else {
                mgcp_reloading = 1;
+       }
        ast_mutex_unlock(&mgcp_reload_lock);
        restart_monitor();
-       return 0;
+       return CLI_SUCCESS;
 }
 
 static int reload(void)
 {
-       mgcp_reload(0, 0, NULL);
+       mgcp_reload(NULL, 0, NULL);
        return 0;
 }
 
@@ -4384,15 +4908,16 @@ static int unload_module(void)
                /* We always want to leave this in a consistent state */
                ast_channel_register(&mgcp_tech);
                mgcp_reloading = 0;
-               mgcp_reload(0, 0, NULL);
+               mgcp_reload(NULL, 0, NULL);
                return -1;
        }
 
        if (!ast_mutex_lock(&gatelock)) {
                for (g = gateways; g; g = g->next) {
                        g->delme = 1;
-                       for (e = g->endpoints; e; e = e->next)
+                       for (e = g->endpoints; e; e = e->next) {
                                e->delme = 1;
+                       }
                }
 
                prune_gateways();
@@ -4404,20 +4929,25 @@ static int unload_module(void)
                /* Allow the monitor to restart */
                monitor_thread = AST_PTHREADT_NULL;
                mgcp_reloading = 0;
-               mgcp_reload(0, 0, NULL);
+               mgcp_reload(NULL, 0, NULL);
                return -1;
        }
 
        close(mgcpsock);
-       ast_rtp_proto_unregister(&mgcp_rtp);
+       ast_rtp_glue_unregister(&mgcp_rtp_glue);
        ast_cli_unregister_multiple(cli_mgcp, sizeof(cli_mgcp) / sizeof(struct ast_cli_entry));
-       sched_context_destroy(sched);
+       ast_sched_context_destroy(sched);
+
+       global_capability = ast_format_cap_destroy(global_capability);
+       mgcp_tech.capabilities = ast_format_cap_destroy(mgcp_tech.capabilities);
 
        return 0;
 }
 
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Media Gateway Control Protocol (MGCP)",
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Media Gateway Control Protocol (MGCP)",
                .load = load_module,
                .unload = unload_module,
                .reload = reload,
+               .load_pri = AST_MODPRI_CHANNEL_DRIVER,
+               .nonoptreq = "res_pktccops",
               );