]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
update
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 18 Jul 2008 16:18:31 +0000 (16:18 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 18 Jul 2008 16:18:31 +0000 (16:18 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9088 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_rtp.h
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_glue.c
src/switch_rtp.c
src/switch_stun.c

index 8b53de6c17590e842f6d7cf6215e94eb05babda6..7b017edab6e0a8368cd747cf51e1f5c9ab082e41 100644 (file)
@@ -418,6 +418,8 @@ SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_pay
 */
 SWITCH_DECLARE(void *) switch_rtp_get_private(switch_rtp_t *rtp_session);
 
+SWITCH_DECLARE(switch_status_t) switch_rtp_activate_stun_ping(switch_rtp_t *rtp_session, const char *stun_ip, uint32_t packet_count, switch_bool_t funny);
+
 /*!
   \}
 */
index 1228671ab701c26634fb8c1696700e27000db660..024b9f6077e3f0c42e0318c5c452933bf2927289 100644 (file)
@@ -156,7 +156,8 @@ typedef enum {
        PFLAG_RECIEVED_IN_NAT_REG_CONTACT = (1 << 22),
        PFLAG_3PCC = (1 << 23),
        PFLAG_DISABLE_RTP_AUTOADJ = (1 << 24),
-       PFLAG_DISABLE_SRTP_AUTH = (1 << 25)
+       PFLAG_DISABLE_SRTP_AUTH = (1 << 25),
+       PFLAG_FUNNY_STUN = (1 << 26)
 } PFLAGS;
 
 typedef enum {
@@ -164,6 +165,12 @@ typedef enum {
        PFLAG_NDLB_BROKEN_AUTH_HASH = (1 << 1)
 } sofia_NDLB_t;
 
+typedef enum {
+       STUN_FLAG_SET = (1 << 0),
+       STUN_FLAG_PING = (1 << 1),
+       STUN_FLAG_FUNNY = (1 << 2)
+} STUNFLAGS;
+
 typedef enum {
        TFLAG_IO = (1 << 0),
        TFLAG_CHANGE_MEDIA = (1 << 1),
@@ -417,6 +424,9 @@ struct private_object {
        char *local_crypto_key;
        char *remote_crypto_key;
        char *record_route;
+       char *extrtpip;
+       char *stun_ip;
+       uint32_t stun_flags;
        int crypto_tag;
        unsigned char local_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
        unsigned char remote_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN];
@@ -566,7 +576,7 @@ void sofia_glue_actually_execute_sql(sofia_profile_t *profile, switch_bool_t mas
 void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot);
 void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now);
 void sofia_reg_unregister(sofia_profile_t *profile);
-switch_status_t sofia_glue_ext_address_lookup(char **ip, switch_port_t *port, char *sourceip, switch_memory_pool_t *pool);
+switch_status_t sofia_glue_ext_address_lookup(sofia_profile_t *profile, private_object_t *tech_pvt, char **ip, switch_port_t *port, char *sourceip, switch_memory_pool_t *pool);
 
 void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp);
 int sofia_glue_get_user_host(char *in, char **user, char **host);
index 9e99fefa6c2454aac1b9bdcae6596583ffc82e3a..61636a7919789b1841104784eddc5dc771d46100 100644 (file)
@@ -1047,6 +1047,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile)
                                                } else {
                                                        profile->pflags &= ~PFLAG_DISABLE_SRTP_AUTH; 
                                                }
+                                       } else if (!strcasecmp(var, "NDLB-funny-stun")) {
+                                               if (switch_true(val)) {
+                                                       profile->pflags |= PFLAG_FUNNY_STUN; 
+                                               } else {
+                                                       profile->pflags &= ~PFLAG_FUNNY_STUN; 
+                                               }
                                        } else if (!strcasecmp(var, "rfc2833-pt")) {
                                                profile->te = (switch_payload_t) atoi(val);
                                        } else if (!strcasecmp(var, "cng-pt")) {
@@ -1380,6 +1386,12 @@ switch_status_t config_sofia(int reload, char *profile_name)
                                                profile->pflags |= PFLAG_DISABLE_RTP_AUTOADJ;
                                        } else if (!strcasecmp(var, "NDLB-support-asterisk-missing-srtp-auth") && switch_true(val)) {
                                                profile->pflags |= PFLAG_DISABLE_SRTP_AUTH;
+                                       } else if (!strcasecmp(var, "NDLB-funny-stun")) {
+                                               if (switch_true(val)) {
+                                                       profile->pflags |= PFLAG_FUNNY_STUN; 
+                                               } else {
+                                                       profile->pflags &= ~PFLAG_FUNNY_STUN; 
+                                               }
                                        } else if (!strcasecmp(var, "rfc2833-pt")) {
                                                profile->te = (switch_payload_t) atoi(val);
                                        } else if (!strcasecmp(var, "cng-pt")) {
@@ -1435,7 +1447,7 @@ switch_status_t config_sofia(int reload, char *profile_name)
                                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invald IP 0.0.0.0 replaced with %s\n", mod_sofia_globals.guess_ip);
                                                } else if (strcasecmp(val, "auto")) {
                                                        switch_port_t port = 0;
-                                                       if (sofia_glue_ext_address_lookup(&myip, &port, val, profile->pool) == SWITCH_STATUS_SUCCESS) {
+                                                       if (sofia_glue_ext_address_lookup(profile, NULL, &myip, &port, val, profile->pool) == SWITCH_STATUS_SUCCESS) {
                                                                ip = myip;
                                                        } else {
                                                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get external ip.\n");
index e682575b3f3e9bde9d4fbb428b99987e148580aa..aa110af76503b5262f44a4c97d1133a9dee47f75 100644 (file)
@@ -425,11 +425,14 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *
        switch_channel_set_name(tech_pvt->channel, name);
 }
 
-switch_status_t sofia_glue_ext_address_lookup(char **ip, switch_port_t *port, char *sourceip, switch_memory_pool_t *pool)
+switch_status_t sofia_glue_ext_address_lookup(sofia_profile_t *profile, private_object_t *tech_pvt, char **ip, switch_port_t *port, char *sourceip, switch_memory_pool_t *pool)
 {
        char *error = "";
        switch_status_t status = SWITCH_STATUS_FALSE;
        int x;
+       switch_port_t myport = *port;
+       const char *var;
+       int funny = 0;
 
        if (!sourceip) {
                return status;
@@ -442,6 +445,11 @@ switch_status_t sofia_glue_ext_address_lookup(char **ip, switch_port_t *port, ch
                        return status;
                }
                for (x = 0; x < 5; x++) {
+                       if ((profile->pflags & PFLAG_FUNNY_STUN) || 
+                               (tech_pvt && (var = switch_channel_get_variable(tech_pvt->channel, "funny_stun")) && switch_true(var))) {
+                               error = "funny";
+                               funny++;
+                       }
                        if ((status = switch_stun_lookup(ip, port, stun_ip, SWITCH_STUN_DEFAULT_PORT, &error, pool)) != SWITCH_STATUS_SUCCESS) {
                                switch_yield(100000);
                        } else {
@@ -456,7 +464,18 @@ switch_status_t sofia_glue_ext_address_lookup(char **ip, switch_port_t *port, ch
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Stun Failed! No IP returned\n");
                        return SWITCH_STATUS_FALSE;
                }
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stun Success [%s]:[%d]\n", *ip, *port);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stun Success [%s]:[%d] [%s][%d]\n", *ip, *port, tech_pvt->profile->rtpip, myport);
+               if (tech_pvt) {
+                       if (myport == *port && !strcmp(*ip, tech_pvt->profile->rtpip)) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stun Not Required ip and port match. [%s]:[%d]\n", *ip, *port);
+                       } else {
+                               tech_pvt->stun_ip = switch_core_session_strdup(tech_pvt->session, stun_ip);
+                               tech_pvt->stun_flags |= STUN_FLAG_SET;
+                               if (funny) {
+                                       tech_pvt->stun_flags |= STUN_FLAG_FUNNY;
+                               }
+                       }
+               }
        } else {
                *ip = sourceip;
        }
@@ -482,6 +501,7 @@ switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt, int forc
        char *ip = tech_pvt->profile->rtpip;
        switch_port_t sdp_port;
        char tmp[50];
+       const char *use_ip = NULL;
 
        if (!force) {
                if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) ||
@@ -502,12 +522,19 @@ switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt, int forc
        }
        sdp_port = tech_pvt->local_sdp_audio_port;
 
-       if (tech_pvt->profile->extrtpip) {
-               if (sofia_glue_ext_address_lookup(&ip, &sdp_port, tech_pvt->profile->extrtpip, switch_core_session_get_pool(tech_pvt->session)) !=
-                       SWITCH_STATUS_SUCCESS) {
+       if (!(use_ip = switch_channel_get_variable(tech_pvt->channel, "rtp_adv_audio_ip"))) {
+               if (tech_pvt->profile->extrtpip) {
+                       use_ip = tech_pvt->profile->extrtpip;
+               }
+       }
+
+       if (use_ip) {
+               tech_pvt->extrtpip = switch_core_session_strdup(tech_pvt->session, use_ip);
+               if (sofia_glue_ext_address_lookup(tech_pvt->profile, tech_pvt, &ip, &sdp_port, tech_pvt->extrtpip, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
                        return SWITCH_STATUS_FALSE;
                }
        }
+       
 
        tech_pvt->adv_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, ip);
        tech_pvt->adv_sdp_audio_port = sdp_port;
@@ -544,7 +571,7 @@ switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt, in
 
 
        if (tech_pvt->profile->extrtpip) {
-               if (sofia_glue_ext_address_lookup(&ip, &sdp_port, tech_pvt->profile->extrtpip, switch_core_session_get_pool(tech_pvt->session)) !=
+               if (sofia_glue_ext_address_lookup(tech_pvt->profile, tech_pvt, &ip, &sdp_port, tech_pvt->profile->extrtpip, switch_core_session_get_pool(tech_pvt->session)) !=
                        SWITCH_STATUS_SUCCESS) {
                        return SWITCH_STATUS_FALSE;
                }
@@ -1730,7 +1757,8 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
                uint8_t vad_in = switch_test_flag(tech_pvt, TFLAG_VAD_IN) ? 1 : 0;
                uint8_t vad_out = switch_test_flag(tech_pvt, TFLAG_VAD_OUT) ? 1 : 0;
                uint8_t inb = switch_test_flag(tech_pvt, TFLAG_OUTBOUND) ? 0 : 1;
-
+               uint32_t stun_ping = 0;
+               
                if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_enable_vad_in")) && switch_true(val)) {
                        vad_in = 1;
                }
@@ -1745,6 +1773,18 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
                        vad_out = 0;
                }
 
+               if ((tech_pvt->stun_flags & STUN_FLAG_SET) && (val = switch_channel_get_variable(tech_pvt->channel, "rtp_stun_ping"))) {
+                       int ival = atoi(val);
+                       
+                       if (ival <= 0) {
+                               if (switch_true(val)) {
+                                       ival = 6;
+                               }
+                       }
+
+                       stun_ping = (ival * tech_pvt->read_codec.implementation->samples_per_second) / tech_pvt->read_codec.implementation->samples_per_frame;
+               }
+
                tech_pvt->ssrc = switch_rtp_get_ssrc(tech_pvt->rtp_session);
                switch_set_flag(tech_pvt, TFLAG_RTP);
                switch_set_flag(tech_pvt, TFLAG_IO);
@@ -1756,6 +1796,11 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
                                                          switch_channel_get_name(switch_core_session_get_channel(tech_pvt->session)), vad_in ? "in" : "", vad_out ? "out" : "");
                }
 
+               if (stun_ping) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Setting stun ping to %s:%d\n", tech_pvt->stun_ip, stun_ping);
+                       switch_rtp_activate_stun_ping(tech_pvt->rtp_session, tech_pvt->stun_ip, stun_ping, (tech_pvt->stun_flags & STUN_FLAG_FUNNY) ? 1 : 0);
+               }
+
                if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec"))) {
                        int len = atoi(val);
 
index a9c6de0361e34b1234ebe50b23991ff68515cb68..6243d75110221d9f3cc5112621bd48cce26bf86d 100644 (file)
@@ -135,6 +135,9 @@ struct switch_rtp {
        switch_sockaddr_t *remote_addr;
        rtp_msg_t recv_msg;
 
+
+       switch_sockaddr_t *remote_stun_addr;
+
        uint32_t autoadj_window;
        uint32_t autoadj_tally;
 
@@ -169,7 +172,9 @@ struct switch_rtp {
        uint32_t rsamples_per_interval;
        uint32_t ms_per_packet;
        uint32_t remote_port;
-       uint8_t stuncount;
+       uint32_t stuncount;
+       uint32_t funny_stun;
+       uint32_t default_stuncount;
        struct switch_rtp_vad_data vad_data;
        struct switch_rtp_rfc2833_data dtmf_data;
        switch_payload_t te;
@@ -188,6 +193,7 @@ struct switch_rtp {
        switch_rtp_crypto_key_t *crypto_keys[SWITCH_RTP_CRYPTO_MAX];
        int reading;
        int writing;
+       char *stun_ip;
 };
 
 static int global_init = 0;
@@ -195,6 +201,52 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
                                                        rtp_msg_t *send_msg, void *data, uint32_t datalen, switch_payload_t payload, uint32_t timestamp, switch_frame_flag_t *flags);
 
 
+static switch_status_t do_stun_ping(switch_rtp_t *rtp_session)
+{
+       uint8_t buf[256] = { 0 };
+       uint8_t *start = buf;
+       switch_stun_packet_t *packet;
+       unsigned int elapsed;
+       switch_size_t bytes;
+       switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+       switch_assert(rtp_session != NULL);
+
+       WRITE_INC(rtp_session);
+
+       if (rtp_session->stuncount != 0) {
+               rtp_session->stuncount--;
+               goto end;
+       }
+
+       if (rtp_session->last_stun) {
+               elapsed = (unsigned int) ((switch_timestamp_now() - rtp_session->last_stun) / 1000);
+               
+               if (elapsed > 30000) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No stun for a long time (PUNT!)\n");
+                       status = SWITCH_STATUS_FALSE;
+                       goto end;
+               }
+       }
+
+       if (rtp_session->funny_stun) {
+               *start++ = 0;
+               *start++ = 0;
+               *start++ = 0x22;
+               *start++ = 0x22;
+       }
+
+       packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, start);
+       bytes = switch_stun_packet_length(packet);
+       switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_stun_addr, 0, (void *) packet, &bytes);
+       rtp_session->stuncount = rtp_session->default_stuncount;
+       
+  end:
+       WRITE_DEC(rtp_session);
+
+       return status;
+}
+
 static switch_status_t ice_out(switch_rtp_t *rtp_session)
 {
        uint8_t buf[256] = { 0 };
@@ -214,7 +266,7 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session)
        }
 
        if (rtp_session->last_stun) {
-               elapsed = (unsigned int) ((switch_time_now() - rtp_session->last_stun) / 1000);
+               elapsed = (unsigned int) ((switch_timestamp_now() - rtp_session->last_stun) / 1000);
 
                if (elapsed > 30000) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No stun for a long time (PUNT!)\n");
@@ -227,12 +279,22 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session)
        switch_stun_packet_attribute_add_username(packet, rtp_session->ice_user, 32);
        bytes = switch_stun_packet_length(packet);
        switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) packet, &bytes);
-       rtp_session->stuncount = 25;
+       rtp_session->stuncount = rtp_session->default_stuncount;
 
   end:
        WRITE_DEC(rtp_session);
 
-       return SWITCH_STATUS_SUCCESS;
+       return status;
+}
+
+
+static void handle_stun_ping_reply(switch_rtp_t *rtp_session, void *data, switch_size_t len)
+{
+       if (!switch_rtp_ready(rtp_session)) {
+               return;
+       }
+
+       rtp_session->last_stun = switch_timestamp_now();
 }
 
 static void handle_ice(switch_rtp_t *rtp_session, void *data, switch_size_t len)
@@ -268,7 +330,7 @@ static void handle_ice(switch_rtp_t *rtp_session, void *data, switch_size_t len)
        }
        end_buf = buf + ((sizeof(buf) > packet->header.length) ? packet->header.length : sizeof(buf));
 
-       rtp_session->last_stun = switch_time_now();
+       rtp_session->last_stun = switch_timestamp_now();
 
        switch_stun_packet_first_attribute(packet, attr);
 
@@ -828,6 +890,26 @@ SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_pay
        rtp_session->cng_pt = pt;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_rtp_activate_stun_ping(switch_rtp_t *rtp_session, const char *stun_ip, uint32_t packet_count, switch_bool_t funny)
+{
+       
+       if (switch_sockaddr_info_get(&rtp_session->remote_stun_addr, stun_ip, SWITCH_UNSPEC, 
+                                                                SWITCH_STUN_DEFAULT_PORT, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS || !rtp_session->remote_stun_addr) {
+               
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error resolving stun ping addr\n");
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (funny) {
+               rtp_session->funny_stun++;
+       }
+
+       rtp_session->default_stuncount = packet_count;
+
+       rtp_session->stun_ip = switch_core_strdup(rtp_session->pool, stun_ip);
+       return SWITCH_STATUS_SUCCESS;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session, uint32_t queue_frames)
 {
        rtp_session->jb = stfu_n_init(queue_frames);
@@ -843,6 +925,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio
        switch_snprintf(user_ice, sizeof(user_ice), "%s%s", rlogin, login);
        rtp_session->ice_user = switch_core_strdup(rtp_session->pool, ice_user);
        rtp_session->user_ice = switch_core_strdup(rtp_session->pool, user_ice);
+       rtp_session->default_stuncount = 25;
 
        if (rtp_session->ice_user) {
                if (ice_out(rtp_session) != SWITCH_STATUS_SUCCESS) {
@@ -1218,8 +1301,12 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 
                if (bytes && rtp_session->recv_msg.header.version != 2) {
                        uint8_t *data = (uint8_t *) rtp_session->recv_msg.body;
-                       if (rtp_session->recv_msg.header.version == 0 && rtp_session->ice_user) {
-                               handle_ice(rtp_session, (void *) &rtp_session->recv_msg, bytes);
+                       if (rtp_session->recv_msg.header.version == 0) {
+                               if (rtp_session->ice_user) {
+                                       handle_ice(rtp_session, (void *) &rtp_session->recv_msg, bytes);
+                               } else if (rtp_session->remote_stun_addr) {
+                                       handle_stun_ping_reply(rtp_session, (void *) &rtp_session->recv_msg, bytes);
+                               }
                        }
 
                        if (rtp_session->invalid_handler) {
@@ -1834,6 +1921,10 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
                rtp_session->last_write_ts = this_ts;
        }
 
+       if (rtp_session->remote_stun_addr) {
+               do_stun_ping(rtp_session);
+       }
+
        if (rtp_session->ice_user) {
                if (ice_out(rtp_session) != SWITCH_STATUS_SUCCESS) {
                        ret = -1;
index e85ac236cc36686158a4b8f2e17fd9e393fdca12..5ed6b6862df22eca86f0773f6a030839c68e789e 100644 (file)
@@ -433,7 +433,8 @@ SWITCH_DECLARE(switch_status_t) switch_stun_lookup(char **ip,
 {
        switch_sockaddr_t *local_addr = NULL, *remote_addr = NULL, *from_addr = NULL;
        switch_socket_t *sock = NULL;
-       uint8_t buf[256] = { 0 };
+       uint8_t buf[260] = { 0 };
+       uint8_t *start = buf;
        void *end_buf;
        switch_stun_packet_t *packet;
        switch_stun_packet_attribute_t *attr;
@@ -443,6 +444,14 @@ SWITCH_DECLARE(switch_status_t) switch_stun_lookup(char **ip,
        uint16_t rport = 0;
        switch_time_t started = 0;
        unsigned int elapsed = 0;
+       int funny = 0;
+       int size = sizeof(buf);
+
+       switch_assert(err);
+
+       if (!strcmp(*err, "funny")) {
+               funny = 1;
+       }
 
        *err = "Success";
 
@@ -468,8 +477,15 @@ SWITCH_DECLARE(switch_status_t) switch_stun_lookup(char **ip,
                return SWITCH_STATUS_FALSE;
        }
 
+       if (funny) {
+               *start++ = 0;
+               *start++ = 0;
+               *start++ = 0x22;
+               *start++ = 0x22;
+       }
+
        switch_socket_opt_set(sock, SWITCH_SO_NONBLOCK, TRUE);
-       packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, buf);
+       packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, start);
        switch_stun_random_string(username, 32, NULL);
        switch_stun_packet_attribute_add_username(packet, username, 32);
        bytes = switch_stun_packet_length(packet);
@@ -496,7 +512,11 @@ SWITCH_DECLARE(switch_status_t) switch_stun_lookup(char **ip,
        }
        switch_socket_close(sock);
 
-       packet = switch_stun_packet_parse(buf, sizeof(buf));
+       if (funny) {
+               size -= 4;
+       }
+
+       packet = switch_stun_packet_parse(start, size);
        if (!packet) {
                *err = "Invalid STUN/ICE packet";
                return SWITCH_STATUS_FALSE;