More 32->64 bit codec conversions.
[asterisk/asterisk.git] / channels / chan_skinny.c
index aba614d..79eb2fb 100644 (file)
@@ -49,7 +49,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/pbx.h"
 #include "asterisk/sched.h"
 #include "asterisk/io.h"
-#include "asterisk/rtp.h"
+#include "asterisk/rtp_engine.h"
 #include "asterisk/netsock.h"
 #include "asterisk/acl.h"
 #include "asterisk/callerid.h"
@@ -71,6 +71,63 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/indications.h"
 #include "asterisk/linkedlists.h"
 
+/*** DOCUMENTATION
+       <manager name="SKINNYdevices" language="en_US">
+               <synopsis>
+                       List SKINNY devices (text format).
+               </synopsis>
+               <syntax>
+                       <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+               </syntax>
+               <description>
+                       <para>Lists Skinny devices in text format with details on current status.
+                       Devicelist will follow as separate events, followed by a final event called
+                       DevicelistComplete.</para>
+               </description>
+       </manager>
+       <manager name="SKINNYshowdevice" language="en_US">
+               <synopsis>
+                       Show SKINNY device (text format).
+               </synopsis>
+               <syntax>
+                       <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+                       <parameter name="Device" required="true">
+                               <para>The device name you want to check.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Show one SKINNY device with details on current status.</para>
+               </description>
+       </manager>
+       <manager name="SKINNYlines" language="en_US">
+               <synopsis>
+                       List SKINNY lines (text format).
+               </synopsis>
+               <syntax>
+                       <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+               </syntax>
+               <description>
+                       <para>Lists Skinny lines in text format with details on current status.
+                       Linelist will follow as separate events, followed by a final event called
+                       LinelistComplete.</para>
+               </description>
+       </manager>
+       <manager name="SKINNYshowline" language="en_US">
+               <synopsis>
+                       Show SKINNY line (text format).
+               </synopsis>
+               <syntax>
+                       <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+                       <parameter name="Line" required="true">
+                               <para>The line name you want to check.</para>
+                       </parameter>
+               </syntax>
+               <description>
+                       <para>Show one SKINNY line with details on current status.</para>
+               </description>
+       </manager>
+ ***/
+
 #ifdef SKINNY_DEVMODE
 #define SKINNY_DEVONLY(code)   \
        code
@@ -84,7 +141,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 static const char tdesc[] = "Skinny Client Control Protocol (Skinny)";
 static const char config[] = "skinny.conf";
 
-static int default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW;
+static format_t default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW;
 static struct ast_codec_pref default_prefs;
 
 enum skinny_codecs {
@@ -585,7 +642,7 @@ struct soft_key_template_definition {
 #define SOFTKEY_DND 0x13
 #define SOFTKEY_IDIVERT 0x14
 
-struct soft_key_template_definition soft_key_template_default[] = {
+static struct soft_key_template_definition soft_key_template_default[] = {
        { "\200\001", SOFTKEY_REDIAL },
        { "\200\002", SOFTKEY_NEWCALL },
        { "\200\003", SOFTKEY_HOLD },
@@ -963,7 +1020,7 @@ struct skinny_req {
 /* XXX This is the combined size of the variables above.  (len, res, e)
    If more are added, this MUST change.
    (sizeof(skinny_req) - sizeof(skinny_data)) DOES NOT WORK on all systems (amd64?). */
-int skinny_header_size = 12;
+static int skinny_header_size = 12;
 
 /*****************************
  * Asterisk specific globals *
@@ -977,8 +1034,8 @@ static struct sockaddr_in bindaddr;
 static char ourhost[256];
 static int ourport;
 static struct in_addr __ourip;
-struct ast_hostent ahp;
-struct hostent *hp;
+static struct ast_hostent ahp;
+static struct hostent *hp;
 static int skinnysock = -1;
 static pthread_t accept_t;
 static int callnums = 1;
@@ -1076,7 +1133,7 @@ static int callnums = 1;
 #define SKINNY_CX_INACTIVE 4
 
 #if 0
-static char *skinny_cxmodes[] = {
+static const char * const skinny_cxmodes[] = {
        "sendonly",
        "recvonly",
        "sendrecv",
@@ -1111,8 +1168,8 @@ static int matchdigittimeout = 3000;
 struct skinny_subchannel {
        ast_mutex_t lock;
        struct ast_channel *owner;
-       struct ast_rtp *rtp;
-       struct ast_rtp *vrtp;
+       struct ast_rtp_instance *rtp;
+       struct ast_rtp_instance *vrtp;
        unsigned int callid;
        /* time_t lastouttime; */ /* Unused */
        int progress;
@@ -1172,9 +1229,9 @@ struct skinny_subchannel {
        int instance;                                   \
        int group;                                      \
        int needdestroy;                                \
-       int confcapability;                             \
+       format_t confcapability;                                \
        struct ast_codec_pref confprefs;                \
-       int capability;                                 \
+       format_t capability;                                    \
        struct ast_codec_pref prefs;                    \
        int nonCodecCapability;                         \
        int onhooktime;                                 \
@@ -1182,7 +1239,7 @@ struct skinny_subchannel {
        int immediate;                                  \
        int hookstate;                                  \
        int nat;                                        \
-       int canreinvite;                                \
+       int directmedia;                                \
        int prune;
 
 struct skinny_line {
@@ -1198,7 +1255,7 @@ struct skinny_line {
        int newmsgs;
 };
 
-struct skinny_line_options{
+static struct skinny_line_options{
        SKINNY_LINE_OPTIONS
 } default_line_struct = {
        .callwaiting = 1,
@@ -1208,7 +1265,7 @@ struct skinny_line_options{
        .hidecallerid = 0,
        .amaflags = 0,
        .instance = 0,
-       .canreinvite = 0,
+       .directmedia = 0,
        .nat = 0,
        .confcapability = AST_FORMAT_ULAW | AST_FORMAT_ALAW,
        .capability = 0,
@@ -1217,7 +1274,7 @@ struct skinny_line_options{
        .prune = 0,
        .hookstate = SKINNY_ONHOOK,
 };
-struct skinny_line_options *default_line = &default_line_struct;
+static struct skinny_line_options *default_line = &default_line_struct;
 
 static AST_LIST_HEAD_STATIC(lines, skinny_line);
 
@@ -1252,9 +1309,9 @@ struct skinny_addon {
        int registered;                                         \
        int lastlineinstance;                                   \
        int lastcallreference;                                  \
-       int confcapability;                                     \
+       format_t confcapability;                                        \
        struct ast_codec_pref confprefs;                        \
-       int capability;                                         \
+       format_t capability;                                            \
        int earlyrtp;                                           \
        int transfer;                                           \
        int callwaiting;                                        \
@@ -1278,7 +1335,7 @@ struct skinny_device {
        AST_LIST_ENTRY(skinny_device) list;
 };
 
-struct skinny_device_options{
+static struct skinny_device_options {
        SKINNY_DEVICE_OPTIONS
 } default_device_struct = {
        .transfer = 1,
@@ -1290,7 +1347,7 @@ struct skinny_device_options{
        .capability = 0,
        .prune = 0,
 };
-struct skinny_device_options *default_device = &default_device_struct;
+static struct skinny_device_options *default_device = &default_device_struct;
        
 static AST_LIST_HEAD_STATIC(devices, skinny_device);
 
@@ -1314,9 +1371,9 @@ struct skinnysession {
        AST_LIST_ENTRY(skinnysession) list;
 };
 
+static struct ast_channel *skinny_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
 static AST_LIST_HEAD_STATIC(sessions, skinnysession);
 
-static struct ast_channel *skinny_request(const char *type, int format, void *data, int *cause);
 static int skinny_devicestate(void *data);
 static int skinny_call(struct ast_channel *ast, char *dest, int timeout);
 static int skinny_hangup(struct ast_channel *ast);
@@ -1347,7 +1404,7 @@ static const struct ast_channel_tech skinny_tech = {
        .fixup = skinny_fixup,
        .send_digit_begin = skinny_senddigit_begin,
        .send_digit_end = skinny_senddigit_end,
-       .bridge = ast_rtp_bridge,  
+       .bridge = ast_rtp_instance_bridge, 
 };
 
 static int skinny_extensionstate_cb(char *context, char* exten, int state, void *data);
@@ -1658,7 +1715,7 @@ static struct skinny_speeddial *find_speeddial_by_instance(struct skinny_device
        return sd;
 }
 
-static int codec_skinny2ast(enum skinny_codecs skinnycodec)
+static format_t codec_skinny2ast(enum skinny_codecs skinnycodec)
 {
        switch (skinnycodec) {
        case SKINNY_CODEC_ALAW:
@@ -1680,7 +1737,7 @@ static int codec_skinny2ast(enum skinny_codecs skinnycodec)
        }
 }
 
-static int codec_ast2skinny(int astcodec)
+static int codec_ast2skinny(format_t astcodec)
 {
        switch (astcodec) {
        case AST_FORMAT_ALAW:
@@ -1847,6 +1904,7 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
                        AST_LIST_TRAVERSE(&d->lines, l, list) {
                                /* FIXME: All sorts of issues will occur if this line is already connected to a device */
                                if (l->device) {
+                                       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Rejected\r\nCause: LINE_ALREADY_CONNECTED\r\n", l->name, l->device->name); 
                                        ast_verb(1, "Line %s already connected to %s. Not connecting to %s.\n", l->name, l->device->name, d->name);
                                } else {
                                        l->device = d;
@@ -1860,6 +1918,7 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
                                        l->instance = instance;
                                        l->newmsgs = ast_app_has_voicemail(l->mailbox, NULL);
                                        set_callforwards(l, NULL, 0);
+                                       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Registered\r\n", l->name, d->name);
                                        register_exten(l);
                                        /* initialize MWI on line and device */
                                        mwi_event_cb(0, l);
@@ -1899,6 +1958,7 @@ static int skinny_unregister(struct skinny_req *req, struct skinnysession *s)
                                l->capability = 0;
                                ast_parse_allow_disallow(&l->prefs, &l->capability, "all", 0);                  
                                l->instance = 0;
+                               manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
                                unregister_exten(l);
                                ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Skinny/%s@%s", l->name, d->name);
                        }
@@ -2516,6 +2576,43 @@ static int skinny_extensionstate_cb(char *context, char *exten, int state, void
        return 0;
 }
 
+static void update_connectedline(struct skinny_subchannel *sub, const void *data, size_t datalen)
+{
+       struct ast_channel *c = sub->owner;
+       struct skinny_line *l = sub->parent;
+       struct skinny_device *d = l->device;
+
+       if (ast_strlen_zero(c->cid.cid_num) || ast_strlen_zero(c->connected.id.number))
+               return;
+
+       if (sub->owner->_state == AST_STATE_UP) {
+               transmit_callstate(d, l->instance, SKINNY_CONNECTED, sub->callid);
+               transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
+               if (sub->outgoing)
+                       transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+               else
+                       transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
+       } else {
+               if (sub->outgoing) {
+                       transmit_callstate(d, l->instance, SKINNY_RINGIN, sub->callid);
+                       transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
+                       transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+               } else {
+                       if (!sub->ringing) {
+                               transmit_callstate(d, l->instance, SKINNY_RINGOUT, sub->callid);
+                               transmit_displaypromptstatus(d, "Ring-Out", 0, l->instance, sub->callid);
+                               sub->ringing = 1;
+                       } else {
+                               transmit_callstate(d, l->instance, SKINNY_PROGRESS, sub->callid);
+                               transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
+                               sub->progress = 1;
+                       }
+
+                       transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
+               }
+       }
+}
+
 static void mwi_event_cb(const struct ast_event *event, void *userdata)
 {
        struct skinny_line *l = userdata;
@@ -2557,46 +2654,48 @@ static void mwi_event_cb(const struct ast_event *event, void *userdata)
 /* I do not believe skinny can deal with video.
    Anyone know differently? */
 /* Yes, it can.  Currently 7985 and Cisco VT Advantage do video. */
-static enum ast_rtp_get_result skinny_get_vrtp_peer(struct ast_channel *c, struct ast_rtp **rtp)
+static enum ast_rtp_glue_result skinny_get_vrtp_peer(struct ast_channel *c, struct ast_rtp_instance **instance)
 {
        struct skinny_subchannel *sub = NULL;
 
        if (!(sub = c->tech_pvt) || !(sub->vrtp))
-               return AST_RTP_GET_FAILED;
+               return AST_RTP_GLUE_RESULT_FORBID;
 
-       *rtp = sub->vrtp;
+       ao2_ref(sub->vrtp, +1);
+       *instance = sub->vrtp;
 
-       return AST_RTP_TRY_NATIVE;
+       return AST_RTP_GLUE_RESULT_REMOTE;
 }
 
-static enum ast_rtp_get_result skinny_get_rtp_peer(struct ast_channel *c, struct ast_rtp **rtp)
+static enum ast_rtp_glue_result skinny_get_rtp_peer(struct ast_channel *c, struct ast_rtp_instance **instance)
 {
        struct skinny_subchannel *sub = NULL;
        struct skinny_line *l;
-       enum ast_rtp_get_result res = AST_RTP_TRY_NATIVE;
+       enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;
 
        if (skinnydebug)
                ast_verb(1, "skinny_get_rtp_peer() Channel = %s\n", c->name);
 
 
        if (!(sub = c->tech_pvt))
-               return AST_RTP_GET_FAILED;
+               return AST_RTP_GLUE_RESULT_FORBID;
 
        ast_mutex_lock(&sub->lock);
 
        if (!(sub->rtp)){
                ast_mutex_unlock(&sub->lock);
-               return AST_RTP_GET_FAILED;
+               return AST_RTP_GLUE_RESULT_FORBID;
        }
-       
-       *rtp = sub->rtp;
+
+       ao2_ref(sub->rtp, +1);
+       *instance = sub->rtp;
 
        l = sub->parent;
 
-       if (!l->canreinvite || l->nat){
-               res = AST_RTP_TRY_PARTIAL;
+       if (!l->directmedia || l->nat){
+               res = AST_RTP_GLUE_RESULT_LOCAL;
                if (skinnydebug)
-                       ast_verb(1, "skinny_get_rtp_peer() Using AST_RTP_TRY_PARTIAL \n");
+                       ast_verb(1, "skinny_get_rtp_peer() Using AST_RTP_GLUE_RESULT_LOCAL \n");
        }
 
        ast_mutex_unlock(&sub->lock);
@@ -2605,15 +2704,15 @@ static enum ast_rtp_get_result skinny_get_rtp_peer(struct ast_channel *c, struct
 
 }
 
-static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
+static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active)
 {
        struct skinny_subchannel *sub;
        struct skinny_line *l;
        struct skinny_device *d;
        struct skinnysession *s;
        struct ast_format_list fmt;
-       struct sockaddr_in us;
-       struct sockaddr_in them;
+       struct sockaddr_in us = { 0, };
+       struct sockaddr_in them = { 0, };
        struct skinny_req *req;
        
        sub = c->tech_pvt;
@@ -2630,7 +2729,7 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp *rtp, struc
        s = d->session;
 
        if (rtp){
-               ast_rtp_get_peer(rtp, &them);
+               ast_rtp_instance_get_remote_address(rtp, &them);
 
                /* Shutdown any early-media or previous media on re-invite */
                if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
@@ -2649,12 +2748,12 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp *rtp, struc
                fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
 
                if (skinnydebug)
-                       ast_verb(1, "Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms);
+                       ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(fmt.bits), fmt.cur_ms);
 
                req->data.startmedia.conferenceId = htolel(sub->callid);
                req->data.startmedia.passThruPartyId = htolel(sub->callid);
-               if (!(l->canreinvite) || (l->nat)){
-                       ast_rtp_get_us(rtp, &us);
+               if (!(l->directmedia) || (l->nat)){
+                       ast_rtp_instance_get_local_address(rtp, &us);
                        req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
                        req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
                } else {
@@ -2675,11 +2774,11 @@ static int skinny_set_rtp_peer(struct ast_channel *c, struct ast_rtp *rtp, struc
        return 0;
 }
 
-static struct ast_rtp_protocol skinny_rtp = {
+static struct ast_rtp_glue skinny_rtp_glue = {
        .type = "Skinny",
        .get_rtp_info = skinny_get_rtp_peer,
        .get_vrtp_info = skinny_get_vrtp_peer,
-       .set_rtp_peer = skinny_set_rtp_peer,
+       .update_peer = skinny_set_rtp_peer,
 };
 
 static char *handle_skinny_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -3010,13 +3109,6 @@ static char *_skinny_show_devices(int fd, int *total, struct mansession *s, cons
        return CLI_SUCCESS;
 }
 
-static char mandescr_show_devices[] =
-"Description: Lists Skinny devices in text format with details on current status.\n"
-"Devicelist will follow as separate events, followed by a final event called\n"
-"DevicelistComplete.\n"
-"Variables: \n"
-"  ActionID: <id>      Action ID for this transaction. Will be returned.\n";
-
 /*! \brief  Show SKINNY devices in the manager API */
 /*    Inspired from chan_sip */
 static int manager_skinny_show_devices(struct mansession *s, const struct message *m)
@@ -3155,12 +3247,6 @@ static char *_skinny_show_device(int type, int fd, struct mansession *s, const s
        return CLI_SUCCESS;
 }
 
-static char mandescr_show_device[] =
-"Description: Show one SKINNY device with details on current status.\n"
-"Variables: \n"
-"  Device: <name>           The device name you want to check.\n"
-"  ActionID: <id>        Optional action ID for this AMI transaction.\n";
-
 static int manager_skinny_show_device(struct mansession *s, const struct message *m)
 {
        const char *a[4];
@@ -3271,13 +3357,6 @@ static char *_skinny_show_lines(int fd, int *total, struct mansession *s, const
        return CLI_SUCCESS;
 }
 
-static char mandescr_show_lines[] =
-"Description: Lists Skinny lines in text format with details on current status.\n"
-"Linelist will follow as separate events, followed by a final event called\n"
-"LinelistComplete.\n"
-"Variables: \n"
-"  ActionID: <id>      Action ID for this transaction. Will be returned.\n";
-
 /*! \brief  Show Skinny lines in the manager API */
 /*    Inspired from chan_sip */
 static int manager_skinny_show_lines(struct mansession *s, const struct message *m)
@@ -3397,6 +3476,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
                                ast_cli(fd, "NAT:              %s\n", (l->nat ? "Yes" : "No"));
                                ast_cli(fd, "immediate:        %s\n", (l->immediate ? "Yes" : "No"));
                                ast_cli(fd, "Group:            %d\n", l->group);
+                               ast_cli(fd, "Parkinglot:       %s\n", S_OR(l->parkinglot, "<not set>"));
                                ast_cli(fd, "Conf Codecs:      ");
                                ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcapability);
                                ast_cli(fd, "%s\n", codec_buf);
@@ -3442,6 +3522,7 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
                                astman_append(s, "NAT: %s\r\n", (l->nat ? "Yes" : "No"));
                                astman_append(s, "immediate: %s\r\n", (l->immediate ? "Yes" : "No"));
                                astman_append(s, "Group: %d\r\n", l->group);
+                               astman_append(s, "Parkinglot: %s\r\n", S_OR(l->parkinglot, "<not set>"));
                                ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcapability);
                                astman_append(s, "Codecs: %s\r\n", codec_buf);
                                astman_append(s, "CodecOrder: ");
@@ -3463,12 +3544,6 @@ static char *_skinny_show_line(int type, int fd, struct mansession *s, const str
        return CLI_SUCCESS;
 }
 
-static char mandescr_show_line[] =
-"Description: Show one SKINNY line with details on current status.\n"
-"Variables: \n"
-"  Line: <name>           The line name you want to check.\n"
-"  ActionID: <id>        Optional action ID for this AMI transaction.\n";
-
 static int manager_skinny_show_line(struct mansession *s, const struct message *m)
 {
        const char *a[4];
@@ -3559,29 +3634,36 @@ static void start_rtp(struct skinny_subchannel *sub)
 
        ast_mutex_lock(&sub->lock);
        /* Allocate the RTP */
-       sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+       sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL);
        if (hasvideo)
-               sub->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
-       
+               sub->vrtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL);
+
+       if (sub->rtp) {
+               ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
+       }
+       if (sub->vrtp) {
+               ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_RTCP, 1);
+       }
+
        if (sub->rtp && sub->owner) {
-               ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
-               ast_channel_set_fd(sub->owner, 1, ast_rtcp_fd(sub->rtp));
+               ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
+               ast_channel_set_fd(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
        }
        if (hasvideo && sub->vrtp && sub->owner) {
-               ast_channel_set_fd(sub->owner, 2, ast_rtp_fd(sub->vrtp));
-               ast_channel_set_fd(sub->owner, 3, ast_rtcp_fd(sub->vrtp));
+               ast_channel_set_fd(sub->owner, 2, ast_rtp_instance_fd(sub->vrtp, 0));
+               ast_channel_set_fd(sub->owner, 3, ast_rtp_instance_fd(sub->vrtp, 1));
        }
        if (sub->rtp) {
-               ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
-               ast_rtp_setnat(sub->rtp, l->nat);
+               ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
+               ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, l->nat);
        }
        if (sub->vrtp) {
-               ast_rtp_setqos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
-               ast_rtp_setnat(sub->vrtp, l->nat);
+               ast_rtp_instance_set_qos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
+               ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_NAT, l->nat);
        }
        /* Set Frame packetization */
        if (sub->rtp)
-               ast_rtp_codec_setpref(sub->rtp, &l->prefs);
+               ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, &l->prefs);
 
        /* Create the RTP connection */
        transmit_connect(d, sub);
@@ -3601,6 +3683,8 @@ static void *skinny_newcall(void *data)
                l->hidecallerid ? "" : l->cid_num,
                l->hidecallerid ? "" : l->cid_name,
                c->cid.cid_ani ? NULL : l->cid_num);
+       c->connected.id.number = ast_strdup(c->exten);
+       c->connected.id.name = NULL;
        ast_setstate(c, AST_STATE_RING);
        if (!sub->rtp) {
                start_rtp(sub);
@@ -3764,7 +3848,7 @@ static int skinny_call(struct ast_channel *ast, char *dest, int timeout)
        transmit_callstateonly(d, sub, SKINNY_RINGIN);
        transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
        transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
-       transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+       transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
        transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
        transmit_ringer_mode(d, SKINNY_RING_INSIDE);
 
@@ -3852,7 +3936,7 @@ static int skinny_hangup(struct ast_channel *ast)
        sub->alreadygone = 0;
        sub->outgoing = 0;
        if (sub->rtp) {
-               ast_rtp_destroy(sub->rtp);
+               ast_rtp_instance_destroy(sub->rtp);
                sub->rtp = NULL;
        }
        ast_mutex_unlock(&sub->lock);
@@ -3891,7 +3975,7 @@ static int skinny_answer(struct ast_channel *ast)
        /* order matters here...
           for some reason, transmit_callinfo must be before transmit_callstate,
           or you won't get keypad messages in some situations. */
-       transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
+       transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
        transmit_callstateonly(d, sub, SKINNY_CONNECTED);
        transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
        transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
@@ -3913,16 +3997,16 @@ static struct ast_frame *skinny_rtp_read(struct skinny_subchannel *sub)
 
        switch(ast->fdno) {
        case 0:
-               f = ast_rtp_read(sub->rtp); /* RTP Audio */
+               f = ast_rtp_instance_read(sub->rtp, 0); /* RTP Audio */
                break;
        case 1:
-               f = ast_rtcp_read(sub->rtp); /* RTCP Control Channel */
+               f = ast_rtp_instance_read(sub->rtp, 1); /* RTCP Control Channel */
                break;
        case 2:
-               f = ast_rtp_read(sub->vrtp); /* RTP Video */
+               f = ast_rtp_instance_read(sub->vrtp, 0); /* RTP Video */
                break;
        case 3:
-               f = ast_rtcp_read(sub->vrtp); /* RTCP Control Channel for video */
+               f = ast_rtp_instance_read(sub->vrtp, 1); /* RTCP Control Channel for video */
                break;
 #if 0
        case 5:
@@ -3937,9 +4021,9 @@ static struct ast_frame *skinny_rtp_read(struct skinny_subchannel *sub)
        if (ast) {
                /* We already hold the channel lock */
                if (f->frametype == AST_FRAME_VOICE) {
-                       if (f->subclass != ast->nativeformats) {
-                               ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
-                               ast->nativeformats = f->subclass;
+                       if (f->subclass.codec != ast->nativeformats) {
+                               ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec));
+                               ast->nativeformats = f->subclass.codec;
                                ast_set_read_format(ast, ast->readformat);
                                ast_set_write_format(ast, ast->writeformat);
                        }
@@ -3970,16 +4054,20 @@ static int skinny_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);
+               if (!(frame->subclass.codec & ast->nativeformats)) {
+                       char buf[256];
+                       ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
+                               ast_getformatname(frame->subclass.codec),
+                               ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats),
+                               ast_getformatname(ast->readformat),
+                               ast_getformatname(ast->writeformat));
                        return -1;
                }
        }
        if (sub) {
                ast_mutex_lock(&sub->lock);
                if (sub->rtp) {
-                       res = ast_rtp_write(sub->rtp, frame);
+                       res = ast_rtp_instance_write(sub->rtp, frame);
                }
                ast_mutex_unlock(&sub->lock);
        }
@@ -4086,6 +4174,10 @@ static char *control2str(int ind) {
                return "Unhold";
        case AST_CONTROL_SRCUPDATE:
                return "Media Source Update";
+       case AST_CONTROL_CONNECTED_LINE:
+               return "Connected Line";
+       case AST_CONTROL_REDIRECTING:
+               return "Redirecting";
        case -1:
                return "Stop tone";
        default:
@@ -4193,7 +4285,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
                                transmit_callstateonly(d, sub, SKINNY_RINGOUT);
                                transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
                                transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
-                               transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
+                               transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
                                sub->ringing = 1;
                                if (!d->earlyrtp) {
                                        break;
@@ -4234,7 +4326,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
                        }
                        transmit_callstateonly(d, sub, SKINNY_PROGRESS);
                        transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
-                       transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
+                       transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
                        sub->progress = 1;
                        if (!d->earlyrtp) {
                                break;
@@ -4253,7 +4345,10 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
        case AST_CONTROL_PROCEEDING:
                break;
        case AST_CONTROL_SRCUPDATE:
-               ast_rtp_new_source(sub->rtp);
+               ast_rtp_instance_new_source(sub->rtp);
+               break;
+       case AST_CONTROL_CONNECTED_LINE:
+               update_connectedline(sub, data, datalen);
                break;
        default:
                ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
@@ -4262,7 +4357,7 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
        return 0;
 }
 
-static struct ast_channel *skinny_new(struct skinny_line *l, int state)
+static struct ast_channel *skinny_new(struct skinny_line *l, int state, const char *linkedid)
 {
        struct ast_channel *tmp;
        struct skinny_subchannel *sub;
@@ -4275,7 +4370,7 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state)
                return NULL;
        }
 
-       tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, l->accountcode, l->exten, l->context, l->amaflags, "Skinny/%s@%s-%d", l->name, d->name, callnums);
+       tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, l->accountcode, l->exten, l->context, linkedid, l->amaflags, "Skinny/%s@%s-%d", l->name, d->name, callnums);
        if (!tmp) {
                ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
                return NULL;
@@ -4309,10 +4404,14 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state)
                        // Should throw an error
                        tmp->nativeformats = default_capability;
                fmt = ast_best_codec(tmp->nativeformats);
-               if (skinnydebug)
-                       ast_verb(1, "skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
+               if (skinnydebug) {
+                       char buf[256];
+                       ast_verb(1, "skinny_new: tmp->nativeformats=%s fmt=%s\n",
+                               ast_getformatname_multiple(buf, sizeof(buf), tmp->nativeformats),
+                               ast_getformatname(fmt));
+               }
                if (sub->rtp) {
-                       ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
+                       ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
                }
                if (state == AST_STATE_RING) {
                        tmp->rings = 1;
@@ -4325,6 +4424,8 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state)
                        ast_string_field_set(tmp, language, l->language);
                if (!ast_strlen_zero(l->accountcode))
                        ast_string_field_set(tmp, accountcode, l->accountcode);
+               if (!ast_strlen_zero(l->parkinglot))
+                       ast_string_field_set(tmp, parkinglot, l->parkinglot);
                if (l->amaflags)
                        tmp->amaflags = l->amaflags;
 
@@ -4458,7 +4559,7 @@ static int handle_transfer_button(struct skinny_subchannel *sub)
                if (!sub->onhold) {
                        skinny_hold(sub);
                }
-               c = skinny_new(l, AST_STATE_DOWN);
+               c = skinny_new(l, AST_STATE_DOWN, NULL);
                if (c) {
                        newsub = c->tech_pvt;
                        /* point the sub and newsub at each other so we know they are related */
@@ -4653,7 +4754,7 @@ static int handle_keypad_button_message(struct skinny_req *req, struct skinnyses
                ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
        }
 
-       f.subclass = dgt;
+       f.subclass.integer = dgt;
 
        f.src = "skinny";
 
@@ -4736,7 +4837,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
                        break;
                }
 
-               c = skinny_new(l, AST_STATE_DOWN);
+               c = skinny_new(l, AST_STATE_DOWN, NULL);
                if (!c) {
                        ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
                } else {
@@ -4774,7 +4875,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
                }
 
                if (!sub || !sub->owner)
-                       c = skinny_new(l, AST_STATE_DOWN);
+                       c = skinny_new(l, AST_STATE_DOWN, NULL);
                else
                        c = sub->owner;
 
@@ -4834,7 +4935,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
                        ast_verb(1, "Received Stimulus: Voicemail(%d/%d)\n", instance, callreference);
 
                if (!sub || !sub->owner) {
-                       c = skinny_new(l, AST_STATE_DOWN);
+                       c = skinny_new(l, AST_STATE_DOWN, NULL);
                } else {
                        c = sub->owner;
                }
@@ -4919,7 +5020,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
                        ast_verb(1, "Received Stimulus: Forward All(%d/%d)\n", instance, callreference);
 
                if (!sub || !sub->owner) {
-                       c = skinny_new(l, AST_STATE_DOWN);
+                       c = skinny_new(l, AST_STATE_DOWN, NULL);
                } else {
                        c = sub->owner;
                }
@@ -4936,7 +5037,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
                        ast_verb(1, "Received Stimulus: Forward Busy (%d/%d)\n", instance, callreference);
 
                if (!sub || !sub->owner) {
-                       c = skinny_new(l, AST_STATE_DOWN);
+                       c = skinny_new(l, AST_STATE_DOWN, NULL);
                } else {
                        c = sub->owner;
                }
@@ -4954,7 +5055,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
 
 #if 0 /* Not sure how to handle this yet */
                if (!sub || !sub->owner) {
-                       c = skinny_new(l, AST_STATE_DOWN);
+                       c = skinny_new(l, AST_STATE_DOWN, NULL);
                } else {
                        c = sub->owner;
                }
@@ -5005,7 +5106,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession
                        if (sub && sub->owner) {
                                ast_debug(1, "Current subchannel [%s] already has owner\n", sub->owner->name);
                        } else {
-                               c = skinny_new(l, AST_STATE_DOWN);
+                               c = skinny_new(l, AST_STATE_DOWN, NULL);
                                if (c) {
                                        sub = c->tech_pvt;
                                        l->activesub = sub;
@@ -5103,7 +5204,7 @@ static int handle_offhook_message(struct skinny_req *req, struct skinnysession *
                if (sub && sub->owner) {
                        ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
                } else {
-                       c = skinny_new(l, AST_STATE_DOWN);
+                       c = skinny_new(l, AST_STATE_DOWN, NULL);
                        if (c) {
                                sub = c->tech_pvt;
                                l->activesub = sub;
@@ -5206,8 +5307,9 @@ static int handle_capabilities_res_message(struct skinny_req *req, struct skinny
        struct skinny_device *d = s->device;
        struct skinny_line *l;
        uint32_t count = 0;
-       int codecs = 0;
+       format_t codecs = 0;
        int i;
+       char buf[256];
 
        count = letohl(req->data.caps.count);
        if (count > SKINNY_MAX_CAPABILITIES) {
@@ -5216,17 +5318,17 @@ static int handle_capabilities_res_message(struct skinny_req *req, struct skinny
        }
 
        for (i = 0; i < count; i++) {
-               int acodec = 0;
+               format_t acodec = 0;
                int scodec = 0;
                scodec = letohl(req->data.caps.caps[i].codec);
                acodec = codec_skinny2ast(scodec);
                if (skinnydebug)
-                       ast_verb(1, "Adding codec capability '%d (%d)'\n", acodec, scodec);
+                       ast_verb(1, "Adding codec capability '%" PRId64 " (%d)'\n", acodec, scodec);
                codecs |= acodec;
        }
 
        d->capability = d->confcapability & codecs;
-       ast_verb(0, "Device capability set to '%d'\n", d->capability);
+       ast_verb(0, "Device capability set to '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), d->capability));
        AST_LIST_TRAVERSE(&d->lines, l, list) {
                ast_mutex_lock(&l->lock);
                l->capability = l->confcapability & d->capability;
@@ -5509,8 +5611,8 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
        struct skinny_line *l;
        struct skinny_subchannel *sub;
        struct ast_format_list fmt;
-       struct sockaddr_in sin;
-       struct sockaddr_in us;
+       struct sockaddr_in sin = { 0, };
+       struct sockaddr_in us = { 0, };
        uint32_t addr;
        int port;
        int status;
@@ -5537,8 +5639,8 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
        l = sub->parent;
 
        if (sub->rtp) {
-               ast_rtp_set_peer(sub->rtp, &sin);
-               ast_rtp_get_us(sub->rtp, &us);
+               ast_rtp_instance_set_remote_address(sub->rtp, &sin);
+               ast_rtp_instance_get_local_address(sub->rtp, &us);
        } else {
                ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
                return 0;
@@ -5553,7 +5655,7 @@ static int handle_open_receive_channel_ack_message(struct skinny_req *req, struc
        fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
 
        if (skinnydebug)
-               ast_verb(1, "Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms);
+               ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(fmt.bits), fmt.cur_ms);
 
        req->data.startmedia.conferenceId = htolel(sub->callid);
        req->data.startmedia.passThruPartyId = htolel(sub->callid);
@@ -5592,7 +5694,7 @@ static int handle_enbloc_call_message(struct skinny_req *req, struct skinnysessi
                l = sub->parent;
        }
 
-       c = skinny_new(l, AST_STATE_DOWN);
+       c = skinny_new(l, AST_STATE_DOWN, NULL);
 
        if(!c) {
                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
@@ -5706,7 +5808,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
                }
 
                if (!sub || !sub->owner) {
-                       c = skinny_new(l, AST_STATE_DOWN);
+                       c = skinny_new(l, AST_STATE_DOWN, NULL);
                } else {
                        c = sub->owner;
                }
@@ -5742,7 +5844,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
                        ast_verb(1, "Received Softkey Event: New Call(%d/%d)\n", instance, callreference);
 
                /* New Call ALWAYS gets a new sub-channel */
-               c = skinny_new(l, AST_STATE_DOWN);
+               c = skinny_new(l, AST_STATE_DOWN, NULL);
                sub = c->tech_pvt;
        
                /* transmit_ringer_mode(d, SKINNY_RING_OFF);
@@ -5812,7 +5914,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
                        ast_verb(1, "Received Softkey Event: Forward All(%d/%d)\n", instance, callreference);
 
                if (!sub || !sub->owner) {
-                       c = skinny_new(l, AST_STATE_DOWN);
+                       c = skinny_new(l, AST_STATE_DOWN, NULL);
                } else {
                        c = sub->owner;
                }
@@ -5830,7 +5932,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
                        ast_verb(1, "Received Softkey Event: Forward Busy (%d/%d)\n", instance, callreference);
 
                if (!sub || !sub->owner) {
-                       c = skinny_new(l, AST_STATE_DOWN);
+                       c = skinny_new(l, AST_STATE_DOWN, NULL);
                } else {
                        c = sub->owner;
                }
@@ -5849,7 +5951,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse
 
 #if 0 /* Not sure how to handle this yet */
                if (!sub || !sub->owner) {
-                       c = skinny_new(l, AST_STATE_DOWN);
+                       c = skinny_new(l, AST_STATE_DOWN, NULL);
                } else {
                        c = sub->owner;
                }
@@ -6243,12 +6345,13 @@ static int get_input(struct skinnysession *s)
 {
        int res;
        int dlen = 0;
+       int *bufaddr;
        struct pollfd fds[1];
 
        fds[0].fd = s->fd;
        fds[0].events = POLLIN;
        fds[0].revents = 0;
-       res = poll(fds, 1, (keep_alive * 1100)); /* If nothing has happen, client is dead */
+       res = ast_poll(fds, 1, (keep_alive * 1100)); /* If nothing has happen, client is dead */
                                                 /* we add 10% to the keep_alive to deal */
                                                 /* with network delays, etc */
        if (res < 0) {
@@ -6289,7 +6392,8 @@ static int get_input(struct skinnysession *s)
                        return -1;
                }
 
-               dlen = letohl(*(int *)s->inbuf);
+               bufaddr = (int *)s->inbuf;
+               dlen = letohl(*bufaddr);
                if (dlen < 4) {
                        ast_debug(1, "Skinny Client sent invalid data.\n");
                        ast_mutex_unlock(&s->lock);
@@ -6298,7 +6402,7 @@ static int get_input(struct skinnysession *s)
                if (dlen+8 > sizeof(s->inbuf)) {
                        dlen = sizeof(s->inbuf) - 8;
                }
-               *(int *)s->inbuf = htolel(dlen);
+               *bufaddr = htolel(dlen);
 
                res = read(s->fd, s->inbuf+4, dlen+4);
                ast_mutex_unlock(&s->lock);
@@ -6317,13 +6421,15 @@ static int get_input(struct skinnysession *s)
 static struct skinny_req *skinny_req_parse(struct skinnysession *s)
 {
        struct skinny_req *req;
+       int *bufaddr;
 
        if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
                return NULL;
 
        ast_mutex_lock(&s->lock);
        memcpy(req, s->inbuf, skinny_header_size);
-       memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*(int*)(s->inbuf))-4);
+       bufaddr = (int *)(s->inbuf);
+       memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*bufaddr)-4);
 
        ast_mutex_unlock(&s->lock);
 
@@ -6479,9 +6585,9 @@ static int skinny_devicestate(void *data)
        return get_devicestate(l);
 }
 
-static struct ast_channel *skinny_request(const char *type, int format, void *data, int *cause)
+static struct ast_channel *skinny_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
 {
-       int oldformat;
+       format_t oldformat;
        
        struct skinny_line *l;
        struct ast_channel *tmpc = NULL;
@@ -6491,7 +6597,7 @@ static struct ast_channel *skinny_request(const char *type, int format, void *da
        oldformat = format;
        
        if (!(format &= AST_FORMAT_AUDIO_MASK)) {
-               ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
+               ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format));
                return NULL;
        }
 
@@ -6506,7 +6612,7 @@ static struct ast_channel *skinny_request(const char *type, int format, void *da
                return NULL;
        }
        ast_verb(3, "skinny_request(%s)\n", tmp);
-       tmpc = skinny_new(l, AST_STATE_DOWN);
+       tmpc = skinny_new(l, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
        if (!tmpc) {
                ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
        }
@@ -6596,7 +6702,7 @@ static struct ast_channel *skinny_request(const char *type, int format, void *da
                                        ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno);
                                continue;
                        } else if (!strcasecmp(v->name, "bindport")) {
-                               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 bindport '%s' at line %d of %s\n", v->value, v->lineno, config);
@@ -6627,9 +6733,9 @@ static struct ast_channel *skinny_request(const char *type, int format, void *da
                                CLINE_OPTS->callwaiting = ast_true(v->value);
                                continue;
                        }
-               } else if (!strcasecmp(v->name, "canreinvite")) {
+               } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
                        if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
-                               CLINE_OPTS->canreinvite = ast_true(v->value);
+                               CLINE_OPTS->directmedia = ast_true(v->value);
                                continue;
                        }
                } else if (!strcasecmp(v->name, "nat")) {
@@ -6934,7 +7040,7 @@ static struct ast_channel *skinny_request(const char *type, int format, void *da
                strsep(&cfg_context, "@");
                if (ast_strlen_zero(cfg_context))
                         cfg_context = "default";
-               l->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, l,
+               l->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "skinny MWI subsciption", l,
                        AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, cfg_mailbox,
                        AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cfg_context,
                        AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
@@ -7073,7 +7179,7 @@ static struct ast_channel *skinny_request(const char *type, int format, void *da
        /* load the general section */
        cat = ast_category_browse(cfg, "general");
        config_parse_variables(TYPE_GENERAL, NULL, ast_variable_browse(cfg, "general"));
-               
+
        if (ntohl(bindaddr.sin_addr.s_addr)) {
                __ourip = bindaddr.sin_addr;
        } else {
@@ -7289,17 +7395,13 @@ static int load_module(void)
                return -1;
        }
 
-       ast_rtp_proto_register(&skinny_rtp);
+       ast_rtp_glue_register(&skinny_rtp_glue);
        ast_cli_register_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
 
-       ast_manager_register2("SKINNYdevices", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_devices,
-                       "List SKINNY devices (text format)", mandescr_show_devices);
-       ast_manager_register2("SKINNYshowdevice", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_device,
-                       "Show SKINNY device (text format)", mandescr_show_device);
-       ast_manager_register2("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines,
-                       "List SKINNY lines (text format)", mandescr_show_lines);
-       ast_manager_register2("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line,
-                       "Show SKINNY line (text format)", mandescr_show_line);
+       ast_manager_register_xml("SKINNYdevices", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_devices);
+       ast_manager_register_xml("SKINNYshowdevice", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_device);
+       ast_manager_register_xml("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines);
+       ast_manager_register_xml("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line);
 
        sched = sched_context_create();
        if (!sched) {
@@ -7323,7 +7425,7 @@ static int unload_module(void)
        struct skinny_subchannel *sub;
        struct ast_context *con;
 
-       ast_rtp_proto_unregister(&skinny_rtp);
+       ast_rtp_glue_unregister(&skinny_rtp_glue);
        ast_channel_unregister(&skinny_tech);
        ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
 
@@ -7349,6 +7451,7 @@ static int unload_module(void)
                        if (l->mwi_event_sub)
                                ast_event_unsubscribe(l->mwi_event_sub);
                        ast_mutex_unlock(&l->lock);
+                       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
                        unregister_exten(l);
                }
                if (s->fd > -1)