diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 0440205a53..932e4da087 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Wed Jun 26 12:43:51 EDT 2013 +Thu Jun 27 14:04:11 CDT 2013 diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c index d9ed0b6980..8b7ecfaa7b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_ws.c @@ -432,26 +432,43 @@ int tport_ws_init_secondary(tport_t *self, int socket, int accepted, int one = 1; tport_ws_primary_t *wspri = (tport_ws_primary_t *)self->tp_pri; tport_ws_t *wstp = (tport_ws_t *)self; + char *buffer, *wbuffer; self->tp_has_connection = 1; if (setsockopt(socket, SOL_TCP, TCP_NODELAY, (void *)&one, sizeof one) == -1) - return *return_reason = "TCP_NODELAY", -1; + return *return_reason = "TCP_NODELAY", -1; + +#if defined(SO_KEEPALIVE) + setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof one); +#endif + one = 30; +#if defined(TCP_KEEPIDLE) + setsockopt(socket, SOL_TCP, TCP_KEEPIDLE, (void *)&one, sizeof one); +#endif +#if defined(TCP_KEEPINTVL) + setsockopt(socket, SOL_TCP, TCP_KEEPINTVL, (void *)&one, sizeof one); +#endif + if (!accepted) tport_ws_setsndbuf(socket, 64 * 1024); if ( wspri->ws_secure ) wstp->ws_secure = 1; - memset(&wstp->ws, 0, sizeof(wstp->ws)); - if (ws_init(&wstp->ws, socket, 65336, wstp->ws_secure ? wspri->ssl_ctx : NULL, 0) < 0) { + + buffer = (char *) su_alloc((su_home_t *)self, 65536); + wbuffer = (char *) su_alloc((su_home_t *)self, 65536); + + if (ws_init(&wstp->ws, socket, buffer, wbuffer, 65336, wstp->ws_secure ? wspri->ssl_ctx : NULL, 0) < 0) { return *return_reason = "WS_INIT", -1; } wstp->ws_initialized = 1; self->tp_pre_framed = 1; + return 0; } diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c index 46e41d133b..6ee35e54a3 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c @@ -352,7 +352,7 @@ issize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes) return r; } -int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, SSL_CTX *ssl_ctx, int close_sock) +int ws_init(wsh_t *wsh, ws_socket_t sock, char *buffer, char *wbuffer, size_t buflen, SSL_CTX *ssl_ctx, int close_sock) { memset(wsh, 0, sizeof(*wsh)); wsh->sock = sock; @@ -372,14 +372,26 @@ int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, SSL_CTX *ssl_ctx, int c wsh->buflen = buflen; wsh->secure = ssl_ctx ? 1 : 0; - if (!wsh->buffer) { + if (buffer) { + wsh->buffer = buffer; + } else if (!wsh->buffer) { wsh->buffer = malloc(wsh->buflen); assert(wsh->buffer); + wsh->free_buffer = 1; + } + + if (wbuffer) { + wsh->wbuffer = wbuffer; + } else if (!wsh->wbuffer) { + wsh->wbuffer = malloc(wsh->buflen); + assert(wsh->wbuffer); + wsh->free_wbuffer = 1; } if (wsh->secure) { int code; - + int sanity = 500; + wsh->ssl = SSL_new(ssl_ctx); assert(wsh->ssl); @@ -387,8 +399,32 @@ int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, SSL_CTX *ssl_ctx, int c do { code = SSL_accept(wsh->ssl); - } while (code == -1 && SSL_get_error(wsh->ssl, code) == SSL_ERROR_WANT_READ); + if (code == 1) { + break; + } + + if (code == 0) { + return -1; + } + + if (code < 0) { + if (code == -1 && SSL_get_error(wsh->ssl, code) != SSL_ERROR_WANT_READ) { + return -1; + } + } +#ifndef _MSC_VER + usleep(10000); +#else + Sleep(10); +#endif + + } while (--sanity > 0); + + if (!sanity) { + return -1; + } + } while (!wsh->down && !wsh->handshake) { @@ -429,12 +465,12 @@ void ws_destroy(wsh_t *wsh) wsh->ssl = NULL; } - if (wsh->buffer) { + if (wsh->free_buffer && wsh->buffer) { free(wsh->buffer); wsh->buffer = NULL; } - if (wsh->wbuffer) { + if (wsh->free_wbuffer && wsh->wbuffer) { free(wsh->wbuffer); wsh->wbuffer = NULL; } @@ -628,13 +664,6 @@ issize_t ws_feed_buf(wsh_t *wsh, void *data, size_t bytes) return -1; } - - if (!wsh->wbuffer) { - wsh->wbuffer = malloc(wsh->buflen); - assert(wsh->wbuffer); - } - - memcpy(wsh->wbuffer + wsh->wdatalen, data, bytes); wsh->wdatalen += bytes; diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/ws.h b/libs/sofia-sip/libsofia-sip-ua/tport/ws.h index 13e5c27b2b..84aa46fceb 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/ws.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/ws.h @@ -71,8 +71,9 @@ typedef struct wsh_s { int handshake; uint8_t down; int secure; - unsigned close_sock:1; - unsigned :0; + uint8_t free_buffer; + uint8_t free_wbuffer; + uint8_t close_sock; } wsh_t; issize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc); @@ -83,7 +84,7 @@ issize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes); issize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes); issize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data); issize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes); -int ws_init(wsh_t *wsh, ws_socket_t sock, size_t buflen, SSL_CTX *ssl_ctx, int close_sock); +int ws_init(wsh_t *wsh, ws_socket_t sock, char *buffer, char *wbuffer, size_t buflen, SSL_CTX *ssl_ctx, int close_sock); issize_t ws_close(wsh_t *wsh, int16_t reason); void ws_destroy(wsh_t *wsh); void init_ssl(void); diff --git a/src/include/switch_stun.h b/src/include/switch_stun.h index fdf1fbd74d..b6de510159 100644 --- a/src/include/switch_stun.h +++ b/src/include/switch_stun.h @@ -142,6 +142,27 @@ typedef struct { } switch_stun_ip_t; +#if SWITCH_BYTE_ORDER == __BIG_ENDIAN + +typedef struct { + unsigned padding:21; + unsigned code:3; + unsigned number:8; + char reason[764]; +} switch_stun_error_code_t; + +#else + +typedef struct { + unsigned number:8; + unsigned code:3; + unsigned padding:21; + char reason[764]; +} switch_stun_error_code_t; + +#endif + + /*! \brief Writes random characters into a buffer \param buf the buffer diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 5df93f60b9..50bf670aad 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -7354,7 +7354,7 @@ SWITCH_STANDARD_APP(conference_function) char *bridgeto = NULL; char *profile_name = NULL; switch_xml_t cxml = NULL, cfg = NULL, profiles = NULL; - const char *flags_str; + const char *flags_str, *v_flags_str; member_flag_t mflags = 0; switch_core_session_message_t msg = { 0 }; uint8_t rl = 0, isbr = 0; @@ -7406,8 +7406,14 @@ SWITCH_STANDARD_APP(conference_function) if ((p = strchr(flags_str, '}'))) { *p = '\0'; } - } else { - flags_str = switch_channel_get_variable(channel, "conference_member_flags"); + } + + if ((v_flags_str = switch_channel_get_variable(channel, "conference_member_flags"))) { + if (zstr(flags_str)) { + flags_str = v_flags_str; + } else { + flags_str = switch_core_session_sprintf(session, "%s|%s", flags_str, v_flags_str); + } } /* is this a bridging conference ? */ diff --git a/src/mod/applications/mod_httapi/docs/mod_httapi_doc.txt b/src/mod/applications/mod_httapi/docs/mod_httapi_doc.txt index f659db39af..b313dc5e15 100644 --- a/src/mod/applications/mod_httapi/docs/mod_httapi_doc.txt +++ b/src/mod/applications/mod_httapi/docs/mod_httapi_doc.txt @@ -230,6 +230,19 @@ action : Change url to submit to. temp-action : Change url to submit to. just for the next loop. + + : Answer the call + +ATTRS: +is-conference : true|false (set the conference flag for RFC4579 stuff. + + + + : Establish media on the call without answering. + + + : Indicate ringing to an unaswered channel. + : Hangup the call diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c index 005f66bdbd..52e4a21a6b 100644 --- a/src/mod/applications/mod_httapi/mod_httapi.c +++ b/src/mod/applications/mod_httapi/mod_httapi.c @@ -877,6 +877,26 @@ static switch_status_t parse_hangup(const char *tag_name, client_t *client, swit return SWITCH_STATUS_FALSE; } +static switch_status_t parse_answer(const char *tag_name, client_t *client, switch_xml_t tag, const char *body) +{ + + if (!strcasecmp(tag_name, "answer")) { + const char *conf = switch_xml_attr(tag, "is-conference"); + + if (conf && switch_true(conf)) { + switch_channel_set_flag(client->channel, CF_CONFERENCE); + } + + switch_channel_answer(client->channel); + } else if (!strcasecmp(tag_name, "preAnswer")) { + switch_channel_pre_answer(client->channel); + } else if (!strcasecmp(tag_name, "ringReady")) { + switch_channel_ring_ready(client->channel); + } + + return SWITCH_STATUS_FALSE; +} + static switch_status_t parse_record_call(const char *tag_name, client_t *client, switch_xml_t tag, const char *body) { const char *limit_ = switch_xml_attr(tag, "limit"); @@ -2997,6 +3017,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_httapi_load) bind_parser("sms", parse_sms); bind_parser("dial", parse_dial); bind_parser("pause", parse_playback); + bind_parser("answer", parse_answer); + bind_parser("preAnswer", parse_answer); + bind_parser("ringReady", parse_answer); bind_parser("hangup", parse_hangup); bind_parser("record", parse_record); bind_parser("recordCall", parse_record_call); diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 6ad806ac00..83bb8eaf23 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1596,7 +1596,7 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t args.input_callback = cancel_on_dtmf; - switch_snprintf(key_buf, sizeof(key_buf), "%s:%s:%s:%s:%s:%s%s%s", profile->listen_file_key, profile->save_file_key, + switch_snprintf(key_buf, sizeof(key_buf), "%s:%s:%s:%s:%s:%s%s%s", profile->repeat_msg_key, profile->save_file_key, profile->delete_file_key, profile->email_key, profile->callback_key, profile->forward_key, cbt->email ? ":" : "", cbt->email ? cbt->email : ""); diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 889af65001..f5c01481d4 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -1051,27 +1051,40 @@ switch_status_t channel_receive_message(switch_core_session_t *session, switch_c private_t *tech_pvt = switch_core_session_get_private(session); switch (msg->message_id) { - case SWITCH_MESSAGE_INDICATE_ANSWER: - switch_clear_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA); + case SWITCH_MESSAGE_INDICATE_ANSWER: + switch_clear_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA); + return channel_answer_channel(session); + + case SWITCH_MESSAGE_INDICATE_DISPLAY: + skinny_session_send_call_info_all(session); + break; + + case SWITCH_MESSAGE_INDICATE_PROGRESS: + if (!switch_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)) { + /* early media */ + switch_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA); return channel_answer_channel(session); - - case SWITCH_MESSAGE_INDICATE_DISPLAY: - skinny_session_send_call_info_all(session); - return SWITCH_STATUS_SUCCESS; - - case SWITCH_MESSAGE_INDICATE_PROGRESS: - if (!switch_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)) { - /* early media */ - switch_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA); - return channel_answer_channel(session); - } - return SWITCH_STATUS_SUCCESS; - - default: - return SWITCH_STATUS_SUCCESS; - + } + break; + + case SWITCH_MESSAGE_INDICATE_BRIDGE: + if (switch_rtp_ready(tech_pvt->rtp_session)) { + rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_STICK); + } + break; + case SWITCH_MESSAGE_INDICATE_UNBRIDGE: + if (switch_rtp_ready(tech_pvt->rtp_session)) { + rtp_flush_read_buffer(tech_pvt->rtp_session, SWITCH_RTP_FLUSH_UNSTICK); + } + break; + + default: + break; + } + return SWITCH_STATUS_SUCCESS; + } /* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines @@ -1982,10 +1995,10 @@ static switch_status_t load_skinny_config(void) if ((dbh = skinny_get_db_handle(profile))) { - switch_cache_db_test_reactive(dbh, "DELETE FROM skinny_devices", "DROP TABLE skinny_devices", devices_sql); - switch_cache_db_test_reactive(dbh, "DELETE FROM skinny_lines", "DROP TABLE skinny_lines", lines_sql); - switch_cache_db_test_reactive(dbh, "DELETE FROM skinny_buttons", "DROP TABLE skinny_buttons", buttons_sql); - switch_cache_db_test_reactive(dbh, "DELETE FROM skinny_active_lines", "DROP TABLE skinny_active_lines", active_lines_sql); + switch_cache_db_test_reactive(dbh, "select count(*) from skinny_devices", NULL, devices_sql); + switch_cache_db_test_reactive(dbh, "select count(*) from skinny_lines", NULL, lines_sql); + switch_cache_db_test_reactive(dbh, "select count(*) from skinny_buttons", NULL, buttons_sql); + switch_cache_db_test_reactive(dbh, "select count(*) from skinny_active_lines", NULL, active_lines_sql); switch_cache_db_release_db_handle(&dbh); } diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index 6d1f4b765d..0cbde82e47 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -58,6 +58,8 @@ uint32_t soft_key_template_default_textids[] = { SKINNY_TEXTID_IDIVERT }; +#define TEXT_ID_LEN 20 + uint32_t soft_key_template_default_events[] = { SOFTKEY_REDIAL, SOFTKEY_NEWCALL, @@ -984,9 +986,9 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r request->data.reg.device_name, request->data.reg.instance, &listener2); if (listener2) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Device %s:%d is already registred on another listener.\n", + "Device %s:%d is already registered on another listener.\n", request->data.reg.device_name, request->data.reg.instance); - send_register_reject(listener, "Device is already registred on another listener"); + send_register_reject(listener, "Device is already registered on another listener"); status = SWITCH_STATUS_FALSE; goto end; } @@ -1732,6 +1734,10 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste struct in_addr addr; switch_rtp_flag_t flags[SWITCH_RTP_FLAG_INVALID] = {0}; + flags[SWITCH_RTP_FLAG_DATAWAIT]++; + flags[SWITCH_RTP_FLAG_AUTOADJ]++; + flags[SWITCH_RTP_FLAG_RAW_WRITE]++; + tech_pvt = switch_core_session_get_private(session); channel = switch_core_session_get_channel(session); @@ -1955,7 +1961,7 @@ switch_status_t skinny_handle_unregister(listener_t *listener, skinny_message_t switch_status_t skinny_handle_soft_key_template_request(listener_t *listener, skinny_message_t *request) { - int i; + size_t i; skinny_message_t *message; switch_assert(listener->profile); @@ -1970,7 +1976,7 @@ switch_status_t skinny_handle_soft_key_template_request(listener_t *listener, sk message->data.soft_key_template.total_soft_key_count = 21; memset(message->data.soft_key_template.soft_key, 0, sizeof(message->data.soft_key_template)); - for (i=0; idata.soft_key_template.soft_key[i].soft_key_label, skinny_textid2raw(soft_key_template_default_textids[i])); switch_safe_free(label); diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index e6b2d20322..66f59c9def 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -3674,6 +3674,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_rayo_load) "0123456789]]>" "" ""); + rayo_add_cmd_alias("input", "" + "" + "0123456789*#]]>" + ""); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/event_handlers/mod_rayo/nlsml.c b/src/mod/event_handlers/mod_rayo/nlsml.c index 81f45dc6fb..e446d1bfd0 100644 --- a/src/mod/event_handlers/mod_rayo/nlsml.c +++ b/src/mod/event_handlers/mod_rayo/nlsml.c @@ -363,6 +363,37 @@ iks *nlsml_normalize(const char *result) return result_xml; } +/** + * @return true if digit is a DTMF + */ +static int isdtmf(const char digit) +{ + switch(digit) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '*': + case '#': + case 'a': + case 'A': + case 'b': + case 'B': + case 'c': + case 'C': + case 'd': + case 'D': + return 1; + } + return 0; +} + /** * Construct an NLSML result for digit match * @param digits the matching digits @@ -387,7 +418,7 @@ iks *nlsml_create_dtmf_match(const char *digits) SWITCH_STANDARD_STREAM(stream); for (i = 0; i < num_digits; i++) { - if (isdigit(digits[i])) { + if (isdtmf(digits[i])) { if (first) { stream.write_function(&stream, "%c", digits[i]); first = 0; diff --git a/src/switch_core_media_bug.c b/src/switch_core_media_bug.c index 0ad3f11183..9831d0099f 100644 --- a/src/switch_core_media_bug.c +++ b/src/switch_core_media_bug.c @@ -430,6 +430,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t if (punt) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Only one bug of this type allowed!\n"); + return SWITCH_STATUS_GENERR; } diff --git a/src/switch_rtp.c b/src/switch_rtp.c index cc73563968..821c375384 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -227,7 +227,6 @@ typedef struct { uint8_t ready; uint8_t rready; int missed_count; - int flips; char last_sent_id[12]; } switch_rtp_ice_t; @@ -784,27 +783,6 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d } - - if (packet->header.type == SWITCH_STUN_BINDING_ERROR_RESPONSE) { - if ((ice->type & ICE_VANILLA)) { - if (ice->flips < 4) { - if ((ice->type & ICE_CONTROLLED)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "Changing role to CONTROLLING\n"); - ice->type &= ~ICE_CONTROLLED; - ice->flips++; - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "Changing role to CONTROLLED\n"); - ice->type |= ICE_CONTROLLED; - ice->flips++; - } - packet->header.type = SWITCH_STUN_BINDING_RESPONSE; - } - } - - } else { - ice->flips = 0; - } - end_buf = buf + ((sizeof(buf) > packet->header.length) ? packet->header.length : sizeof(buf)); rtp_session->last_stun = switch_micro_time_now(); @@ -813,6 +791,30 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d do { switch (attr->type) { + case SWITCH_STUN_ATTR_ERROR_CODE: + { + switch_stun_error_code_t *err = (switch_stun_error_code_t *) attr->value; + uint32_t code = (err->code * 100) + err->number; + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "%s got stun binding response %u %s\n", + switch_core_session_get_name(rtp_session->session), + code, + err->reason + ); + + if ((ice->type & ICE_VANILLA) && code == 487) { + if ((ice->type & ICE_CONTROLLED)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "Changing role to CONTROLLING\n"); + ice->type &= ~ICE_CONTROLLED; + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, "Changing role to CONTROLLED\n"); + ice->type |= ICE_CONTROLLED; + } + packet->header.type = SWITCH_STUN_BINDING_RESPONSE; + } + + } + break; case SWITCH_STUN_ATTR_MAPPED_ADDRESS: if (attr->type) { char ip[16]; diff --git a/src/switch_stun.c b/src/switch_stun.c index f2af463f15..8be191e782 100644 --- a/src/switch_stun.c +++ b/src/switch_stun.c @@ -257,11 +257,16 @@ SWITCH_DECLARE(switch_stun_packet_t *) switch_stun_packet_parse(uint8_t *buf, ui *val = ntohl(*val); /* should we do this here? */ } break; + case SWITCH_STUN_ATTR_ERROR_CODE: /* ErrorCode */ + { + uint32_t *u = (uint32_t *) attr->value; + *u = htonl(*u); + } + break; case SWITCH_STUN_ATTR_USERNAME: /* ByteString, multiple of 4 bytes */ case SWITCH_STUN_ATTR_PASSWORD: /* ByteString, multiple of 4 bytes */ case SWITCH_STUN_ATTR_DATA: /* ByteString */ - case SWITCH_STUN_ATTR_ERROR_CODE: /* ErrorCode */ case SWITCH_STUN_ATTR_TRANSPORT_PREFERENCES: /* TransportPrefs */ /* * No length checking here, since we already checked against the padded length