Merge branch 'master' of ssh://git.freeswitch.org:222/freeswitch

This commit is contained in:
David Yat Sin 2011-06-09 16:50:07 -04:00
commit 665f7656dc
15 changed files with 294 additions and 26 deletions

View File

@ -1908,6 +1908,8 @@ void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, const char
int on = 0;
int len = 0;
char *my_body = strdup(body);
char *my_body_base = my_body;
assert(handle != NULL);
assert(body != NULL);
@ -1952,7 +1954,9 @@ void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, const char
free(bdup);
}
free(my_body);
if (my_body_base) {
free(my_body_base);
}
apr_queue_push(handle->queue, msg);
msg = NULL;

View File

@ -1202,6 +1202,8 @@ SWITCH_DECLARE(switch_status_t) switch_socket_send(switch_socket_t *sock, const
*/
SWITCH_DECLARE(switch_status_t) switch_socket_sendto(switch_socket_t *sock, switch_sockaddr_t *where, int32_t flags, const char *buf,
switch_size_t *len);
SWITCH_DECLARE(switch_status_t) switch_socket_send_nonblock(switch_socket_t *sock, const char *buf, switch_size_t *len);
/**
* @param from The apr_sockaddr_t to fill in the recipient info

View File

@ -109,6 +109,8 @@ SWITCH_DECLARE(switch_size_t) switch_buffer_read(_In_ switch_buffer_t *buffer, _
*/
SWITCH_DECLARE(switch_size_t) switch_buffer_peek(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen);
SWITCH_DECLARE(switch_size_t) switch_buffer_peek_zerocopy(_In_ switch_buffer_t *buffer, _Out_ const void **ptr);
/*! \brief Read data endlessly from a switch_buffer_t
* \param buffer any buffer of type switch_buffer_t
* \param data pointer to the read data to be returned

View File

@ -1227,7 +1227,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_insert(_In_ switch_hash_t *hash
\note the string key must be a constant or a dynamic string
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ const void *data,
_In_ switch_mutex_t *mutex);
_In_opt_ switch_mutex_t *mutex);
/*!
\brief Retrieve data from a given hash
\param hash the hash to retrieve from
\param key the key to retrieve
\param mutex optional rwlock to wrlock
\return a pointer to the data held in the key
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_wrlock(switch_hash_t *hash, const char *key, const void *data, switch_thread_rwlock_t *rwlock);
/*!
\brief Delete data from a hash based on desired key
@ -1244,7 +1252,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete(_In_ switch_hash_t *hash
\param mutex optional mutex to lock
\return SWITCH_STATUS_SUCCESS if the data is deleted
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_ switch_mutex_t *mutex);
SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ switch_mutex_t *mutex);
/*!
\brief Delete data from a hash based on desired key
\param hash the hash to delete from
\param key the key from which to delete the data
\param mutex optional rwlock to wrlock
\return SWITCH_STATUS_SUCCESS if the data is deleted
*/
SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_wrlock(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ switch_thread_rwlock_t *rwlock);
/*!
\brief Delete data from a hash based on callback function
@ -1272,6 +1289,15 @@ SWITCH_DECLARE(void *) switch_core_hash_find(_In_ switch_hash_t *hash, _In_z_ co
*/
SWITCH_DECLARE(void *) switch_core_hash_find_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_ switch_mutex_t *mutex);
/*!
\brief Retrieve data from a given hash
\param hash the hash to retrieve from
\param key the key to retrieve
\param mutex optional rwlock to rdlock
\return a pointer to the data held in the key
*/
SWITCH_DECLARE(void *) switch_core_hash_find_rdlock(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_ switch_thread_rwlock_t *rwlock);
/*!
\brief Gets the first element of a hashtable
\param depricate_me [deprecated] NULL

View File

@ -1120,7 +1120,9 @@ typedef enum {
typedef enum {
CF_APP_TAGGED = (1 << 0),
CF_APP_T38 = (1 << 1)
CF_APP_T38 = (1 << 1),
CF_APP_T38_REQ = (1 << 2),
CF_APP_T38_FAIL = (1 << 3)
} switch_channel_app_flag_t;

View File

@ -141,7 +141,9 @@ typedef enum {
MFLAG_MINTWO = (1 << 13),
MFLAG_MUTE_DETECT = (1 << 14),
MFLAG_DIST_DTMF = (1 << 15),
MFLAG_MOD = (1 << 16)
MFLAG_MOD = (1 << 16),
MFLAG_INDICATE_MUTE = (1 << 17),
MFLAG_INDICATE_UNMUTE = (1 << 18)
} member_flag_t;
typedef enum {
@ -2745,6 +2747,30 @@ static void conference_loop_output(conference_member_t *member)
switch_mutex_unlock(member->write_mutex);
if (switch_test_flag(member, MFLAG_INDICATE_MUTE)) {
if (!zstr(member->conference->muted_sound)) {
conference_member_play_file(member, member->conference->muted_sound, 0);
} else {
char msg[512];
switch_snprintf(msg, sizeof(msg), "Muted");
conference_member_say(member, msg, 0);
}
switch_clear_flag(member, MFLAG_INDICATE_MUTE);
}
if (switch_test_flag(member, MFLAG_INDICATE_UNMUTE)) {
if (!zstr(member->conference->unmuted_sound)) {
conference_member_play_file(member, member->conference->unmuted_sound, 0);
} else {
char msg[512];
switch_snprintf(msg, sizeof(msg), "Un-Muted");
conference_member_say(member, msg, 0);
}
switch_clear_flag(member, MFLAG_INDICATE_UNMUTE);
}
if (switch_core_session_private_event_count(member->session)) {
switch_channel_set_app_flag(channel, CF_APP_TAGGED);
switch_ivr_parse_all_events(member->session);
@ -3608,18 +3634,12 @@ static switch_status_t conf_api_sub_mute(conference_member_t *member, switch_str
switch_clear_flag_locked(member, MFLAG_CAN_SPEAK);
switch_clear_flag_locked(member, MFLAG_TALKING);
switch_set_flag(member, MFLAG_INDICATE_MUTE);
if (!zstr(member->conference->muted_sound)) {
conference_member_play_file(member, member->conference->muted_sound, 0);
} else {
char msg[512];
switch_snprintf(msg, sizeof(msg), "Muted");
conference_member_say(member, msg, 0);
}
if (stream != NULL) {
stream->write_function(stream, "OK mute %u\n", member->id);
}
if (test_eflag(member->conference, EFLAG_MUTE_MEMBER) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_member_data(member, event);
@ -3684,17 +3704,12 @@ static switch_status_t conf_api_sub_unmute(conference_member_t *member, switch_s
return SWITCH_STATUS_GENERR;
switch_set_flag_locked(member, MFLAG_CAN_SPEAK);
switch_set_flag(member, MFLAG_INDICATE_UNMUTE);
if (stream != NULL) {
stream->write_function(stream, "OK unmute %u\n", member->id);
}
if (!zstr(member->conference->unmuted_sound)) {
conference_member_play_file(member, member->conference->unmuted_sound, 0);
} else {
char msg[512];
switch_snprintf(msg, sizeof(msg), "Un-Muted");
conference_member_say(member, msg, 0);
}
if (test_eflag(member->conference, EFLAG_UNMUTE_MEMBER) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_member_data(member, event);

View File

@ -904,6 +904,7 @@ static t38_mode_t request_t38(pvt_t *pvt)
switch_channel_set_private(channel, "t38_options", t38_options);
pvt->t38_mode = T38_MODE_REQUESTED;
switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_REQ);
/* This will send a request for t.38 mode */
msg.from = __FILE__;
@ -1173,7 +1174,10 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
switch (pvt->t38_mode) {
case T38_MODE_REQUESTED:
{
if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) {
if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38_FAIL)) {
pvt->t38_mode = T38_MODE_REFUSED;
continue;
} else if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) {
switch_core_session_message_t msg = { 0 };
pvt->t38_mode = T38_MODE_NEGOTIATED;
spanfax_init(pvt, T38_MODE);

View File

@ -524,6 +524,12 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *cid = generate_pai_str(tech_pvt);
if (sip_cause > 299) {
switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ);
switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_FAIL);
}
nua_respond(tech_pvt->nh, sip_cause, sip_status_phrase(sip_cause),
TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)), TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)), TAG_END());
@ -3273,6 +3279,19 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t
goto done;
}
if (!strcasecmp(argv[1], "check_sync")) {
if (argc > 2) {
sofia_reg_check_call_id(profile, argv[2]);
stream->write_function(stream, "+OK syncing all registrations matching specified call_id\n");
} else {
sofia_reg_check_sync(profile);
stream->write_function(stream, "+OK syncing all registrations\n");
}
goto done;
}
if (!strcasecmp(argv[1], "flush_inbound_reg")) {
int reboot = 0;
@ -3853,6 +3872,7 @@ SWITCH_STANDARD_API(sofia_function)
" watchdog <on|off>\n\n"
"sofia profile <name> [start | stop | restart | rescan]\n"
" flush_inbound_reg [<call_id> | <[user]@domain>] [reboot]\n"
" check_sync [<call_id> | <[user]@domain>]\n"
" [register | unregister] [<gateway name> | all]\n"
" killgw <gateway name>\n"
" [stun-auto-disable | stun-enabled] [true | false]]\n"
@ -5158,6 +5178,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
switch_console_set_complete("add sofia profile ::sofia::list_profiles restart");
switch_console_set_complete("add sofia profile ::sofia::list_profiles flush_inbound_reg");
switch_console_set_complete("add sofia profile ::sofia::list_profiles check_sync");
switch_console_set_complete("add sofia profile ::sofia::list_profiles register ::sofia::list_profile_gateway");
switch_console_set_complete("add sofia profile ::sofia::list_profiles unregister ::sofia::list_profile_gateway");
switch_console_set_complete("add sofia profile ::sofia::list_profiles killgw ::sofia::list_profile_gateway");

View File

@ -295,6 +295,7 @@ typedef enum {
TFLAG_NOTIMER_DURING_BRIDGE,
TFLAG_JB_PAUSED,
TFLAG_3PCC_INVITE,
TFLAG_NOREPLY,
/* No new flags below this line */
TFLAG_MAX
} TFLAGS;
@ -983,6 +984,8 @@ void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt);
switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt);
void sofia_presence_event_thread_start(void);
void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int reboot);
void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id);
void sofia_reg_check_sync(sofia_profile_t *profile);
switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt, int force);
switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force);
char *sofia_glue_get_register_host(const char *uri);

View File

@ -4161,6 +4161,16 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
tech_pvt->last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data);
}
if (status > 299 && switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ)) {
switch_channel_set_private(channel, "t38_options", NULL);
switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ);
switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_FAIL);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 invite failed\n", switch_channel_get_name(tech_pvt->channel));
}
if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
if (channel && sip->sip_call_info) {
char *p;
@ -4462,6 +4472,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
switch_channel_set_private(other_channel, "t38_options", NULL);
sofia_clear_flag(tech_pvt, TFLAG_T38_PASSTHRU);
sofia_clear_flag(other_tech_pvt, TFLAG_T38_PASSTHRU);
switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ);
switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_FAIL);
} else if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38 && sip->sip_payload && sip->sip_payload->pl_data) {
switch_t38_options_t *t38_options = sofia_glue_extract_t38_options(session, sip->sip_payload->pl_data);
@ -5231,8 +5244,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (tech_pvt->num_codecs) {
match = sofia_glue_negotiate_sdp(session, r_sdp);
}
if (match && switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38)) {
if (match && sofia_test_flag(tech_pvt, TFLAG_NOREPLY)) {
sofia_clear_flag(tech_pvt, TFLAG_NOREPLY);
goto done;
}

View File

@ -4389,8 +4389,13 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
if (got_udptl && m->m_type == sdp_media_image && m->m_port) {
switch_t38_options_t *t38_options = tech_process_udptl(tech_pvt, sdp, m);
if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38)) {
sofia_set_flag(tech_pvt, TFLAG_NOREPLY);
}
if (switch_true(switch_channel_get_variable(channel, "refuse_t38"))) {
switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
match = 0;
goto done;
} else {

View File

@ -396,9 +396,30 @@ static void actual_sofia_presence_mwi_event_handler(switch_event_t *event)
if (!profile) {
if (!host || !(profile = sofia_glue_find_profile(host))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find profile %s\n", switch_str_nil(host));
switch_safe_free(dup_account);
return;
char *sql;
switch_hash_index_t *hi;
void *val;
const void *vvar;
char buf[512] = "";
sql = switch_mprintf("select profile_name from sip_registrations where sip_host='%s' or mwi_host='%s'", host, host);
switch_mutex_lock(mod_sofia_globals.hash_mutex);
for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &vvar, NULL, &val);
profile = (sofia_profile_t *) val;
sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf));
if (!zstr(buf)) {
break;
}
}
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
if (!(profile = sofia_glue_find_profile(buf))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find profile %s\n", switch_str_nil(host));
switch_safe_free(dup_account);
return;
}
}
}

View File

@ -733,6 +733,92 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
}
int sofia_reg_check_callback(void *pArg, int argc, char **argv, char **columnNames)
{
sofia_profile_t *profile = (sofia_profile_t *) pArg;
sofia_reg_send_reboot(profile, argv[1], argv[2], argv[3], argv[7], argv[11]);
return 0;
}
void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id)
{
char *sql = NULL;
char *sqlextra = NULL;
char *dup = strdup(call_id);
char *host = NULL, *user = NULL;
switch_assert(dup);
if ((host = strchr(dup, '@'))) {
*host++ = '\0';
user = dup;
} else {
host = dup;
}
if (!host) {
host = "none";
}
if (zstr(user)) {
sqlextra = switch_mprintf(" or (sip_host='%q')", host);
} else {
sqlextra = switch_mprintf(" or (sip_user='%q' and sip_host='%q')", user, host);
}
sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires"
",user_agent,server_user,server_host,profile_name,network_ip"
" from sip_registrations where call_id='%q' %s", call_id, sqlextra);
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_check_callback, profile);
switch_mutex_unlock(profile->ireg_mutex);
switch_safe_free(sql);
switch_safe_free(sqlextra);
switch_safe_free(dup);
}
void sofia_reg_check_sync(sofia_profile_t *profile)
{
char sql[1024];
switch_mutex_lock(profile->ireg_mutex);
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,expires"
",user_agent,server_user,server_host,profile_name,network_ip"
" from sip_registrations where expires > 0");
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile);
switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%s'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%s'",
mod_sofia_globals.hostname);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile);
switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname);
sofia_glue_actually_execute_sql(profile, sql, NULL);
switch_mutex_unlock(profile->ireg_mutex);
}
char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const char *host, char *val, switch_size_t len)
{
struct callback_t cbt = { 0 };

View File

@ -224,6 +224,22 @@ SWITCH_DECLARE(switch_size_t) switch_buffer_peek(switch_buffer_t *buffer, void *
return reading;
}
SWITCH_DECLARE(switch_size_t) switch_buffer_peek_zerocopy(switch_buffer_t *buffer, const void **ptr)
{
switch_size_t reading = 0;
if (buffer->used < 1) {
buffer->used = 0;
return 0;
} else {
reading = buffer->used;
}
*ptr = buffer->head;
return reading;
}
SWITCH_DECLARE(switch_size_t) switch_buffer_write(switch_buffer_t *buffer, const void *data, switch_size_t datalen)
{
switch_size_t freespace, actual_freespace;

View File

@ -96,6 +96,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_locked(switch_hash_t *ha
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_wrlock(switch_hash_t *hash, const char *key, const void *data, switch_thread_rwlock_t *rwlock)
{
if (rwlock) {
switch_thread_rwlock_wrlock(rwlock);
}
sqlite3HashInsert(&hash->table, key, (int) strlen(key) + 1, (void *) data);
if (rwlock) {
switch_thread_rwlock_unlock(rwlock);
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_delete(switch_hash_t *hash, const char *key)
{
sqlite3HashInsert(&hash->table, key, (int) strlen(key) + 1, NULL);
@ -117,6 +132,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(switch_hash_t *ha
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_wrlock(switch_hash_t *hash, const char *key, switch_thread_rwlock_t *rwlock)
{
if (rwlock) {
switch_thread_rwlock_wrlock(rwlock);
}
sqlite3HashInsert(&hash->table, key, (int) strlen(key) + 1, NULL);
if (rwlock) {
switch_thread_rwlock_unlock(rwlock);
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi(switch_hash_t *hash, switch_hash_delete_callback_t callback, void *pData) {
switch_hash_index_t *hi = NULL;
@ -175,6 +205,23 @@ SWITCH_DECLARE(void *) switch_core_hash_find_locked(switch_hash_t *hash, const c
return val;
}
SWITCH_DECLARE(void *) switch_core_hash_find_rdlock(switch_hash_t *hash, const char *key, switch_thread_rwlock_t *rwlock)
{
void *val;
if (rwlock) {
switch_thread_rwlock_rdlock(rwlock);
}
val = sqlite3HashFind(&hash->table, key, (int) strlen(key) + 1);
if (rwlock) {
switch_thread_rwlock_unlock(rwlock);
}
return val;
}
SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *depricate_me, switch_hash_t *hash)
{
return (switch_hash_index_t *) sqliteHashFirst(&hash->table);