From fbcb86226581cdcc66fc7b633b505906c207a4cd Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 09:35:23 +0200 Subject: [PATCH 001/101] add thread safe hash multi delete function and make callback optional --- src/include/switch_core.h | 22 +++++++++++++++++++++- src/switch_core_hash.c | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 9803c6708b..6e67989b90 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1277,7 +1277,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(_In_ switch_hash_ \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 + \param rwlock 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); @@ -1290,6 +1290,26 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_wrlock(_In_ switch_hash_ */ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi(_In_ switch_hash_t *hash, _In_ switch_hash_delete_callback_t callback, _In_opt_ void *pData); +/*! + \brief Delete data from a hash based on callback function + \param hash the hash to delete from + \param callback the function to call which returns SWITCH_TRUE to delete, SWITCH_FALSE to preserve + \param rwlock optional rwlock to wrlock + \return SWITCH_STATUS_SUCCESS if any data is deleted +*/ + +SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi_wrlock(_In_ switch_hash_t *hash, _In_ switch_hash_delete_callback_t callback, _In_opt_ void *pData, _In_ switch_thread_rwlock_t *rwlock); + +/*! + \brief Delete data from a hash based on callback function + \param hash the hash to delete from + \param callback the function to call which returns SWITCH_TRUE to delete, SWITCH_FALSE to preserve + \param mutex optional mutex to lock + \return SWITCH_STATUS_SUCCESS if any data is deleted +*/ + +SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi_locked(_In_ switch_hash_t *hash, _In_ switch_hash_delete_callback_t callback, _In_opt_ void *pData, _In_ switch_mutex_t *mutex); + /*! \brief Retrieve data from a given hash \param hash the hash to retrieve from diff --git a/src/switch_core_hash.c b/src/switch_core_hash.c index 4ac3d2620e..ed5c4c2ca4 100644 --- a/src/switch_core_hash.c +++ b/src/switch_core_hash.c @@ -157,7 +157,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi(switch_hash_t *has switch_event_create_subclass(&event, SWITCH_EVENT_CLONE, NULL); switch_assert(event); - /* iterate through the hash, call callback, if callback returns true, put the key on the list (event) + /* iterate through the hash, call callback, if callback is NULL or returns true, put the key on the list (event) When done, iterate through the list deleting hash entries */ @@ -165,7 +165,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi(switch_hash_t *has const void *key; void *val; switch_hash_this(hi, &key, NULL, &val); - if (callback(key, val, pData)) { + if (!callback || callback(key, val, pData)) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delete", (const char *) key); } } @@ -182,6 +182,40 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi(switch_hash_t *has return status; } +SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi_wrlock(switch_hash_t *hash, switch_hash_delete_callback_t callback, void *pData, switch_thread_rwlock_t *rwlock) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + + if (rwlock) { + switch_thread_rwlock_wrlock(rwlock); + } + + status = switch_core_hash_delete_multi(hash, callback, pData); + + if (rwlock) { + switch_thread_rwlock_unlock(rwlock); + } + + return status; +} + +SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi_locked(switch_hash_t *hash, switch_hash_delete_callback_t callback, void *pData, switch_mutex_t *mutex) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + + if (mutex) { + switch_mutex_lock(mutex); + } + + status = switch_core_hash_delete_multi(hash, callback, pData); + + if (mutex) { + switch_mutex_unlock(mutex); + } + + return status; +} + SWITCH_DECLARE(void *) switch_core_hash_find(switch_hash_t *hash, const char *key) { From 8f4c5bc49240e69c938644a7da4b1632e74d9e95 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 09:37:41 +0200 Subject: [PATCH 002/101] add Andrew's patch from FS-3432 as a starting point with todo markers --- .../mod_erlang_event/handle_msg.c | 59 +++--- .../mod_erlang_event/mod_erlang_event.c | 195 +++++++++++++----- .../mod_erlang_event/mod_erlang_event.h | 4 +- 3 files changed, 187 insertions(+), 71 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c index 46e9e67e85..0b083cd0c0 100644 --- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c +++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c @@ -286,6 +286,7 @@ static switch_status_t handle_msg_event(listener_t *listener, int arity, ei_x_bu switch_set_flag_locked(listener, LFLAG_EVENTS); } + /* TODO - listener write lock */ for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { @@ -335,6 +336,7 @@ static switch_status_t handle_msg_session_event(listener_t *listener, erlang_msg for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { + /* TODO session write locking */ if (custom) { switch_core_hash_insert(session->event_hash, atom, MARKER); } else if (switch_name_event(atom, &type) == SWITCH_STATUS_SUCCESS) { @@ -380,10 +382,12 @@ static switch_status_t handle_msg_nixevent(listener_t *listener, int arity, ei_x int i = 0; switch_event_types_t type; + /* TODO listener write lock */ for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { if (custom) { + switch_core_hash_delete(listener->event_hash, atom); } else if (switch_name_event(atom, &type) == SWITCH_STATUS_SUCCESS) { uint32_t x = 0; @@ -426,6 +430,7 @@ static switch_status_t handle_msg_session_nixevent(listener_t *listener, erlang_ int i = 0; switch_event_types_t type; + /* TODO session write lock */ for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { @@ -480,6 +485,8 @@ static switch_status_t handle_msg_setevent(listener_t *listener, erlang_msg *msg switch_event_types_t type; int i = 0; + /* TODO listener write lock */ + /* clear any previous event registrations */ for( x = 0; x <= SWITCH_EVENT_ALL; x++){ event_list[x] = 0; @@ -517,6 +524,7 @@ static switch_status_t handle_msg_setevent(listener_t *listener, erlang_msg *msg /* update the event subscriptions with the new ones */ memcpy(listener->event_list, event_list, sizeof(uint8_t) * (SWITCH_EVENT_ALL + 1)); /* wipe the old hash, and point the pointer at the new one */ + /* TODO make thread safe */ switch_core_hash_destroy(&listener->event_hash); listener->event_hash = event_hash; @@ -544,12 +552,14 @@ static switch_status_t handle_msg_session_setevent(listener_t *listener, erlang_ switch_event_types_t type; uint32_t x = 0; + /* TODO session write lock */ /* clear any previous event registrations */ for (x = 0; x <= SWITCH_EVENT_ALL; x++){ event_list[x] = 0; } /* create new hash */ + /* TODO make thread safe*/ switch_core_hash_init(&event_hash, session->pool); for (i = 1; i < arity; i++){ @@ -576,6 +586,7 @@ static switch_status_t handle_msg_session_setevent(listener_t *listener, erlang_ /* update the event subscriptions with the new ones */ memcpy(session->event_list, event_list, sizeof(uint8_t) * (SWITCH_EVENT_ALL + 1)); /* wipe the old hash, and point the pointer at the new one */ + /* TODO make thread safe*/ switch_core_hash_destroy(&session->event_hash); session->event_hash = event_hash; /* TODO - we should flush any non-matching events from the queue */ @@ -601,13 +612,13 @@ static switch_status_t handle_msg_api(listener_t *listener, erlang_msg * msg, in fail = SWITCH_TRUE; } - ei_get_type(buf->buff, &buf->index, &type, &size); + ei_get_type(buf->buff, &buf->index, &type, &size); if ((size > (sizeof(api_cmd) - 1)) || ei_decode_atom(buf->buff, &buf->index, api_cmd)) { fail = SWITCH_TRUE; } - ei_get_type(buf->buff, &buf->index, &type, &size); + ei_get_type(buf->buff, &buf->index, &type, &size); arg = malloc(size + 1); if (ei_decode_string(buf->buff, &buf->index, arg)) { @@ -706,29 +717,29 @@ static switch_status_t handle_msg_sendevent(listener_t *listener, int arity, ei_ while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; - ei_get_type(buf->buff, &buf->index, &type, &size); + ei_get_type(buf->buff, &buf->index, &type, &size); if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) { fail = SWITCH_TRUE; break; } - ei_get_type(buf->buff, &buf->index, &type, &size); - value = malloc(size + 1); + ei_get_type(buf->buff, &buf->index, &type, &size); + value = malloc(size + 1); if (ei_decode_string(buf->buff, &buf->index, value)) { fail = SWITCH_TRUE; break; } - if (!fail && !strcmp(key, "body")) { - switch_safe_free(event->body); - event->body = value; - } else if (!fail) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); - } - - /* Do not free malloc here! The above commands utilize the raw allocated memory and skip any copying/duplication. Faster. */ + if (!fail && !strcmp(key, "body")) { + switch_safe_free(event->body); + event->body = value; + } else if (!fail) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); + } + + /* Do not free malloc here! The above commands utilize the raw allocated memory and skip any copying/duplication. Faster. */ } if (headerlength != i || fail) { @@ -763,22 +774,22 @@ static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_ char key[1024]; char *value; - int type; - int size; + int type; + int size; int i = 0; switch_bool_t fail = SWITCH_FALSE; while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; - ei_get_type(buf->buff, &buf->index, &type, &size); + ei_get_type(buf->buff, &buf->index, &type, &size); if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) { fail = SWITCH_TRUE; break; } - - ei_get_type(buf->buff, &buf->index, &type, &size); - value = malloc(size + 1); + + ei_get_type(buf->buff, &buf->index, &type, &size); + value = malloc(size + 1); if (ei_decode_string(buf->buff, &buf->index, value)) { fail = SWITCH_TRUE; @@ -786,7 +797,7 @@ static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_ } if (!fail) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); } } @@ -1024,6 +1035,7 @@ static switch_status_t handle_msg_atom(listener_t *listener, erlang_msg * msg, e listener->event_list[x] = 0; } /* wipe the hash */ + /* TODO make thread safe*/ switch_core_hash_destroy(&listener->event_hash); switch_core_hash_init(&listener->event_hash, listener->pool); ei_x_encode_atom(rbuf, "ok"); @@ -1044,6 +1056,7 @@ static switch_status_t handle_msg_atom(listener_t *listener, erlang_msg * msg, e session->event_list[x] = 0; } /* wipe the hash */ + /* TODO make thread safe*/ switch_core_hash_destroy(&session->event_hash); switch_core_hash_init(&session->event_hash, session->pool); ei_x_encode_atom(rbuf, "ok"); @@ -1240,6 +1253,7 @@ int handle_msg(listener_t *listener, erlang_msg * msg, ei_x_buff * buf, ei_x_buf buf->index = 0; ei_decode_version(buf->buff, &buf->index, &version); ei_get_type(buf->buff, &buf->index, &type, &size); + switch (type) { case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: @@ -1288,11 +1302,8 @@ int handle_msg(listener_t *listener, erlang_msg * msg, ei_x_buff * buf, ei_x_buf #ifdef EI_DEBUG ei_x_print_msg(rbuf, &msg->from, 1); #endif + return SWITCH_STATUS_SUCCESS != ret; - if (SWITCH_STATUS_SUCCESS == ret) - return 0; - else /* SWITCH_STATUS_TERM */ - return 1; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Empty reply, supressing\n"); return 0; diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index 12cf01a650..cfa1d63115 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -59,6 +59,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l switch_thread_rwlock_rdlock(globals.listener_rwlock); for (l = listen_list.listeners; l; l = l->next) { + /* TODO listener read lock */ if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level) { switch_log_node_t *dnode = switch_log_node_dup(node); @@ -131,9 +132,10 @@ static void send_event_to_attached_sessions(listener_t *listener, switch_event_t return; } + switch_thread_rwlock_rdlock(listener->session_rwlock); s = (session_elem_t*)switch_core_hash_find(listener->sessions, uuid); - switch_thread_rwlock_unlock(listener->session_rwlock); + /* TODO - we don't need to hold the lock, we need to lock the session */ if (s) { int send = 0; @@ -162,6 +164,7 @@ static void send_event_to_attached_sessions(listener_t *listener, switch_event_t switch_event_name(event->event_id), s->uuid_str); } } + switch_thread_rwlock_unlock(listener->session_rwlock); } static void event_handler(switch_event_t *event) @@ -175,9 +178,10 @@ static void event_handler(switch_event_t *event) return; } + switch_thread_rwlock_rdlock(globals.listener_rwlock); + lp = listen_list.listeners; - switch_thread_rwlock_rdlock(globals.listener_rwlock); while (lp) { uint8_t send = 0; @@ -188,6 +192,8 @@ static void event_handler(switch_event_t *event) one of them should receive the event as well */ + /* TODO need read locking */ + send_event_to_attached_sessions(l, event); if (!switch_test_flag(l, LFLAG_EVENTS)) { @@ -249,21 +255,21 @@ static void close_socket(int *sock) } -static void add_listener(listener_t *listener) -{ +/*static void add_listener(listener_t *listener)*/ +/*{*/ /* add me to the listeners so I get events */ - switch_thread_rwlock_wrlock(globals.listener_rwlock); - listener->next = listen_list.listeners; - listen_list.listeners = listener; - switch_thread_rwlock_unlock(globals.listener_rwlock); -} + /*switch_thread_rwlock_wrlock(globals.listener_rwlock);*/ + /*listener->next = listen_list.listeners;*/ + /*listen_list.listeners = listener;*/ + /*switch_thread_rwlock_unlock(globals.listener_rwlock);*/ +/*}*/ +/* TODO lock */ static void remove_listener(listener_t *listener) { listener_t *l, *last = NULL; - switch_thread_rwlock_wrlock(globals.listener_rwlock); for (l = listen_list.listeners; l; l = l->next) { if (l == listener) { if (last) { @@ -274,7 +280,6 @@ static void remove_listener(listener_t *listener) } last = l; } - switch_thread_rwlock_unlock(globals.listener_rwlock); } /* Search for a listener already talking to the specified node */ @@ -285,6 +290,7 @@ static listener_t *find_listener(char *nodename) switch_thread_rwlock_rdlock(globals.listener_rwlock); for (l = listen_list.listeners; l; l = l->next) { if (!strncmp(nodename, l->peer_nodename, MAXNODELEN)) { + /* TODO listener rwlock */ break; } } @@ -301,11 +307,19 @@ static void add_session_elem_to_listener(listener_t *listener, session_elem_t *s } +/* TODO lock */ static void remove_session_elem_from_listener(listener_t *listener, session_elem_t *session_element) { switch_core_hash_delete(listener->sessions, session_element->uuid_str); } +static void remove_session_elem_from_listener_locked(listener_t *listener, session_elem_t *session_element) +{ + switch_thread_rwlock_wrlock(listener->session_rwlock); + remove_session_elem_from_listener(listener, session_element); + switch_thread_rwlock_unlock(listener->session_rwlock); +} + static void destroy_session_elem(session_elem_t *session_element) { switch_core_session_t *session; @@ -315,16 +329,10 @@ static void destroy_session_elem(session_elem_t *session_element) switch_core_session_rwunlock(session); } switch_core_destroy_memory_pool(&session_element->pool); + session_element = NULL; /*switch_safe_free(s); */ } -static void remove_session_elem_from_listener_locked(listener_t *listener, session_elem_t *session_element) -{ - switch_thread_rwlock_wrlock(listener->session_rwlock); - remove_session_elem_from_listener(listener, session_element); - switch_thread_rwlock_unlock(listener->session_rwlock); -} - session_elem_t *find_session_elem_by_pid(listener_t *listener, erlang_pid *pid) { @@ -362,6 +370,7 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c switch_xml_t xml = NULL; ei_x_buff *rep; ei_x_buff buf; + ei_x_new_with_version(&buf); switch_uuid_get(&uuid); @@ -403,6 +412,7 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c /* Create a new fetch object. */ p = malloc(sizeof(*p)); switch_thread_cond_create(&p->ready_or_found, module_pool); + /* TODO module pool */ switch_mutex_init(&p->mutex, SWITCH_MUTEX_UNNESTED, module_pool); p->state = reply_not_ready; p->reply = NULL; @@ -430,8 +440,7 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c /* Tell the threads to be ready, and wait five seconds for a reply. */ switch_mutex_lock(p->mutex); //p->state = reply_waiting; - switch_thread_cond_timedwait(p->ready_or_found, - p->mutex, 5000000); + switch_thread_cond_timedwait(p->ready_or_found, p->mutex, 5000000); if (!p->reply) { p->state = reply_timeout; switch_mutex_unlock(p->mutex); @@ -516,6 +525,7 @@ static switch_status_t notify_new_session(listener_t *listener, session_elem_t * switch_caller_profile_event_set_data(switch_channel_get_caller_profile(channel), "Channel", call_event); switch_channel_event_set_data(channel, call_event); switch_core_session_rwunlock(session); + /* TODO reply? sure? */ switch_event_add_header_string(call_event, SWITCH_STACK_BOTTOM, "Content-Type", "command/reply"); switch_event_add_header_string(call_event, SWITCH_STACK_BOTTOM, "Reply-Text", "+OK\n"); @@ -551,6 +561,7 @@ static switch_status_t check_attached_sessions(listener_t *listener) /* event used to track sessions to remove */ switch_event_t *event = NULL; switch_event_header_t *header = NULL; + switch_event_create_subclass(&event, SWITCH_EVENT_CLONE, NULL); switch_assert(event); /* check up on all the attached sessions - @@ -558,6 +569,8 @@ static switch_status_t check_attached_sessions(listener_t *listener) if they have pending events in their queues then send them if the session has finished then clean it up */ + + /* TODO try to minimize critical section */ switch_thread_rwlock_rdlock(listener->session_rwlock); for (iter = switch_hash_first(NULL, listener->sessions); iter; iter = switch_hash_next(iter)) { switch_hash_this(iter, &key, NULL, &value); @@ -643,6 +656,8 @@ static switch_status_t check_attached_sessions(listener_t *listener) /* release the read lock and get a write lock */ switch_thread_rwlock_wrlock(listener->session_rwlock); /* do the deferred remove */ + + /* TODO refactor find_session_elem_by_uuid*/ for (header = event->headers; header; header = header->next) { if ((sp = (session_elem_t*)switch_core_hash_find(listener->sessions, header->value))) { remove_session_elem_from_listener(listener, sp); @@ -762,6 +777,7 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) switch_core_session_rwunlock(session); } /* TODO - if a spawned process that was handling an outbound call fails.. what do we do with the call? */ + /* TODO hangup and let the state handler set the complete flag and destroy as usual*/ } remove_session_elem_from_listener_locked(listener, s); destroy_session_elem(s); @@ -772,6 +788,7 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Log handler process for node %s exited\n", pid->node); /*purge the log queue */ + /* TODO don't we want to clear flag first? */ while (switch_queue_trypop(listener->log_queue, &pop) == SWITCH_STATUS_SUCCESS) { switch_log_node_t *dnode = (switch_log_node_t *) pop; switch_log_node_free(&dnode); @@ -787,6 +804,7 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Event handler process for node %s exited\n", pid->node); /*purge the event queue */ + /* TODO don't we want to clear flag first? */ while (switch_queue_trypop(listener->event_queue, &pop) == SWITCH_STATUS_SUCCESS) { switch_event_t *pevent = (switch_event_t *) pop; switch_event_destroy(&pevent); @@ -795,10 +813,13 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) if (switch_test_flag(listener, LFLAG_EVENTS)) { uint8_t x = 0; switch_clear_flag_locked(listener, LFLAG_EVENTS); + for (x = 0; x <= SWITCH_EVENT_ALL; x++) { listener->event_list[x] = 0; } /* wipe the hash */ + /* XXX this needs to be locked */ + /* TODO switch_core_hash_delete_multi_locked */ switch_core_hash_destroy(&listener->event_hash); switch_core_hash_init(&listener->event_hash, listener->pool); } @@ -865,7 +886,16 @@ static void listener_main_loop(listener_t *listener) case ERL_EXIT: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "erl_exit from %s <%d.%d.%d>\n", msg.from.node, msg.from.creation, msg.from.num, msg.from.serial); - handle_exit(listener, &msg.from); + + switch_thread_rwlock_rdlock(globals.listener_rwlock); + if (listener) { + /* get the listener lock */ + switch_thread_rwlock_wrlock(listener->rwlock); + /* wipe event hash */ + handle_exit(listener, &msg.from); + switch_thread_rwlock_unlock(listener->rwlock); + } + switch_thread_rwlock_unlock(globals.listener_rwlock); break; default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unexpected msg type %d\n", (int) (msg.msgtype)); @@ -874,7 +904,7 @@ static void listener_main_loop(listener_t *listener) break; case ERL_ERROR: if (erl_errno != ETIMEDOUT && erl_errno != EAGAIN) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "erl_error\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "erl_error: status=%d, erl_errno=%d errno=%d\n", status, erl_errno, errno); } break; default: @@ -892,6 +922,11 @@ static void listener_main_loop(listener_t *listener) return; } } + if (prefs.done) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "shutting down listener\n"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "listener exit: status=%d, erl_errno=%d errno=%d\n", status, erl_errno, errno); + } } static switch_bool_t check_inbound_acl(listener_t *listener) @@ -941,7 +976,7 @@ static switch_bool_t check_inbound_acl(listener_t *listener) static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) { listener_t *listener = (listener_t *) obj; - session_elem_t *s; + session_elem_t *s = NULL; const void *key; void *value; switch_hash_index_t *iter; @@ -959,24 +994,29 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Open from %s\n", listener->remote_ip); /*, listener->remote_port); */ } - add_listener(listener); + /*add_listener(listener);*/ listener_main_loop(listener); } /* clean up */ - remove_listener(listener); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session complete, waiting for children\n"); + listener->dead = 1; /* mark it as dead */ + + /* TODO - release write lock */ + switch_thread_rwlock_wrlock(globals.listener_rwlock); + remove_listener(listener); + switch_thread_rwlock_unlock(globals.listener_rwlock); + switch_thread_rwlock_wrlock(listener->rwlock); if (listener->sockfd) { close_socket(&listener->sockfd); } - switch_thread_rwlock_unlock(listener->rwlock); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Closed\n"); + /* TODO make listener destroy function and move there */ switch_core_hash_destroy(&listener->event_hash); /* remove any bindings for this connection */ @@ -987,9 +1027,12 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) for (iter = switch_hash_first(NULL, listener->sessions); iter; iter = switch_hash_next(iter)) { switch_hash_this(iter, &key, NULL, &value); s = (session_elem_t*)value; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Orphaning call %s\n", s->uuid_str); + remove_session_elem_from_listener(listener, s); destroy_session_elem(s); } switch_thread_rwlock_unlock(listener->session_rwlock); + switch_thread_rwlock_unlock(listener->rwlock); if (listener->pool) { switch_memory_pool_t *pool = listener->pool; @@ -1156,30 +1199,31 @@ static int config(void) return 0; } - static listener_t *new_listener(struct ei_cnode_s *ec, int clientfd) { - switch_memory_pool_t *listener_pool = NULL; + switch_memory_pool_t *pool = NULL; listener_t *listener = NULL; - if (switch_core_new_memory_pool(&listener_pool) != SWITCH_STATUS_SUCCESS) { + if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n"); return NULL; } - if (!(listener = switch_core_alloc(listener_pool, sizeof(*listener)))) { + if (!(listener = switch_core_alloc(pool, sizeof(*listener)))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error\n"); + switch_core_destroy_memory_pool(&pool); return NULL; } memset(listener, 0, sizeof(*listener)); - switch_thread_rwlock_create(&listener->rwlock, listener_pool); - switch_queue_create(&listener->event_queue, SWITCH_CORE_QUEUE_LEN, listener_pool); - switch_queue_create(&listener->log_queue, SWITCH_CORE_QUEUE_LEN, listener_pool); + switch_thread_rwlock_create(&listener->rwlock, pool); + switch_queue_create(&listener->event_queue, SWITCH_CORE_QUEUE_LEN, pool); + switch_queue_create(&listener->log_queue, SWITCH_CORE_QUEUE_LEN, pool); + /* TODO remove */ + listener->dead = 0; /* born alive */ listener->sockfd = clientfd; - listener->pool = listener_pool; - listener_pool = NULL; + listener->pool = pool; listener->ec = switch_core_alloc(listener->pool, sizeof(ei_cnode)); memcpy(listener->ec, ec, sizeof(ei_cnode)); listener->level = SWITCH_LOG_DEBUG; @@ -1189,15 +1233,49 @@ static listener_t *new_listener(struct ei_cnode_s *ec, int clientfd) switch_core_hash_init(&listener->event_hash, listener->pool); switch_core_hash_init(&listener->sessions, listener->pool); + /* TODO listener rdlock */ + listener->next = listen_list.listeners; + listen_list.listeners = listener; + return listener; } -static listener_t *new_outbound_listener(char *node) +/*TODO we don't need bottleneck*/ +static listener_t *new_listener_locked(struct ei_cnode_s *ec, int clientfd) +{ + listener_t *res; + switch_thread_rwlock_wrlock(globals.listener_rwlock); + res = new_listener(ec, clientfd); + switch_thread_rwlock_unlock(globals.listener_rwlock); + return res; +} + +/* TODO new session??? */ +static listener_t *new_outbound_listener(char *node, switch_bool_t *new_session) { listener_t *listener = NULL; struct ei_cnode_s ec; int clientfd; + /* TODO find listener func */ + switch_thread_rwlock_wrlock(globals.listener_rwlock); + for (listener = listen_list.listeners; listener; listener = listener->next) { + if (!strncmp(node, listener->peer_nodename, MAXNODELEN)) { + break; + } + } + + if (listener && listener->dead) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "found dead listener for %s\n", node); + remove_listener(listener); /* remove the dead listener and continue adding one */ + } else if (listener) { + switch_thread_rwlock_unlock(globals.listener_rwlock); + + *new_session = SWITCH_FALSE; + return listener; + } + + if (SWITCH_STATUS_SUCCESS == initialise_ei(&ec)) { #ifdef WIN32 WSASetLastError(0); @@ -1206,11 +1284,17 @@ static listener_t *new_outbound_listener(char *node) #endif if ((clientfd = ei_connect(&ec, node)) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error connecting to node %s (erl_errno=%d, errno=%d)!\n", node, erl_errno, errno); + switch_thread_rwlock_unlock(globals.listener_rwlock); return NULL; } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "new listener for %s\n", node); listener = new_listener(&ec, clientfd); listener->peer_nodename = switch_core_strdup(listener->pool, node); } + + switch_thread_rwlock_unlock(globals.listener_rwlock); + *new_session = SWITCH_TRUE; + return listener; } @@ -1226,6 +1310,7 @@ static switch_status_t state_handler(switch_core_session_t *session) if (state == CS_DESTROY) { /* indicate that once all the events in the event queue are done * we can throw this away */ + /* TODO locked? */ switch_set_flag(session_element, LFLAG_SESSION_COMPLETE); } } else { @@ -1298,6 +1383,7 @@ session_elem_t *attach_call_to_pid(listener_t *listener, erlang_pid * pid, switc memcpy(&session_element->process.pid, pid, sizeof(erlang_pid)); /* attach the session to the listener */ add_session_elem_to_listener(listener, session_element); + /* TODO link before added to listener? */ ei_link(listener, ei_self(listener->ec), pid); return session_element; @@ -1361,8 +1447,7 @@ session_elem_t *attach_call_to_spawned_process(listener_t *listener, char *modul */ } - switch_thread_cond_timedwait(p->ready_or_found, - p->mutex, 5000000); + switch_thread_cond_timedwait(p->ready_or_found, p->mutex, 5000000); if (!p->pid) { p->state = reply_timeout; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Timed out when waiting for outbound pid %s %s\n", hash, session_element->uuid_str); @@ -1460,13 +1545,23 @@ SWITCH_STANDARD_APP(erlang_outbound_function) /* if there is no listener, then create one */ if (!listener) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating new listener for session\n"); - new_session = SWITCH_TRUE; - listener = new_outbound_listener(node); + listener = new_outbound_listener(node, &new_session); + /* XXX new_session isn't accurate now */ } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Using existing listener for session\n"); + /* TODO don't we need to connect ? */ } - if (listener) { + /* TODO it's too late */ + switch_thread_rwlock_rdlock(globals.listener_rwlock); + + if (listener && !listener->dead) { + /* prevent the listener_run thread from destroying the listener out from under us */ + /* get the listener lock */ + switch_thread_rwlock_rdlock(listener->rwlock); + /* release the global listener lock, since the listener can't be freed without the listener lock */ + switch_thread_rwlock_unlock(globals.listener_rwlock); + if (new_session == SWITCH_TRUE) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Launching new listener\n"); launch_listener_thread(listener); @@ -1480,11 +1575,18 @@ SWITCH_STANDARD_APP(erlang_outbound_function) session_element = attach_call_to_registered_process(listener, reg_name, session); } + /* should be safe now */ + switch_thread_rwlock_unlock(listener->rwlock); + + if (session_element) { switch_ivr_park(session, NULL); } + } else { + switch_thread_rwlock_unlock(globals.listener_rwlock); } + switch_log_printf(SWITCH_CHANNEL_UUID_LOG(uuid), SWITCH_LOG_DEBUG, "exit erlang_outbound_function\n"); } @@ -1498,6 +1600,7 @@ SWITCH_STANDARD_APP(erlang_sendmsg_function) char *mydata; ei_x_buff buf; listener_t *listener; + switch_bool_t new_session; ei_x_new_with_version(&buf); @@ -1523,12 +1626,12 @@ SWITCH_STANDARD_APP(erlang_sendmsg_function) listener = find_listener(node); if (!listener) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating new listener for sendmsg %s\n", node); - listener = new_outbound_listener(node); + listener = new_outbound_listener(node, &new_session); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Using existing listener for sendmsg to %s\n", node); } - if (listener) { + if (listener && !listener->dead) { ei_reg_send(listener->ec, listener->sockfd, reg_name, buf.buff, buf.index); } } @@ -1598,11 +1701,11 @@ SWITCH_STANDARD_API(erlang_cmd) stream->write_function(stream, "Outbound session for %s in state %s\n", sp->uuid_str, switch_channel_state_name(sp->channel_state)); } + switch_thread_rwlock_unlock(l->session_rwlock); if (empty) { stream->write_function(stream, "No active sessions for %s\n", argv[1]); } - switch_thread_rwlock_unlock(l->session_rwlock); break; } } @@ -1824,7 +1927,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_erlang_event_runtime) continue; } - listener = new_listener(&ec, clientfd); + listener = new_listener_locked(&ec, clientfd); if (listener) { /* store the IP and node name we are talking with */ switch_inet_ntop(AF_INET, conn.ipadr, listener->remote_ip, sizeof(listener->remote_ip)); diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h index 1721d496fb..775cdf74f3 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h @@ -39,7 +39,8 @@ typedef enum { } session_flag_t; typedef enum { - ERLANG_PID = 0, + NONE = 0, + ERLANG_PID, ERLANG_REG_PROCESS } process_type; @@ -113,6 +114,7 @@ struct listener { #else int sockfd; #endif + uint8_t dead; struct ei_cnode_s *ec; struct erlang_process log_process; struct erlang_process event_process; From eade6572253e3d86ccdb16bc7b23228ecf63aad0 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 10:30:48 +0200 Subject: [PATCH 003/101] listener r/w locking FS-3432 --- .../mod_erlang_event/mod_erlang_event.c | 197 +++++++----------- .../mod_erlang_event/mod_erlang_event.h | 1 - 2 files changed, 73 insertions(+), 125 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index cfa1d63115..c2f204ef0a 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -44,6 +44,7 @@ SWITCH_MODULE_DEFINITION(mod_erlang_event, mod_erlang_event_load, mod_erlang_eve static switch_memory_pool_t *module_pool = NULL; static void remove_listener(listener_t *listener); +static void destroy_listener(listener_t *listener); static switch_status_t state_handler(switch_core_session_t *session); SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, prefs.ip); @@ -59,7 +60,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l switch_thread_rwlock_rdlock(globals.listener_rwlock); for (l = listen_list.listeners; l; l = l->next) { - /* TODO listener read lock */ + if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level) { switch_log_node_t *dnode = switch_log_node_dup(node); @@ -80,6 +81,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l l->lost_logs++; } } + } switch_thread_rwlock_unlock(globals.listener_rwlock); @@ -192,8 +194,6 @@ static void event_handler(switch_event_t *event) one of them should receive the event as well */ - /* TODO need read locking */ - send_event_to_attached_sessions(l, event); if (!switch_test_flag(l, LFLAG_EVENTS)) { @@ -255,21 +255,21 @@ static void close_socket(int *sock) } -/*static void add_listener(listener_t *listener)*/ -/*{*/ - /* add me to the listeners so I get events */ - /*switch_thread_rwlock_wrlock(globals.listener_rwlock);*/ - /*listener->next = listen_list.listeners;*/ - /*listen_list.listeners = listener;*/ - /*switch_thread_rwlock_unlock(globals.listener_rwlock);*/ -/*}*/ +static void add_listener(listener_t *listener) +{ + /* add me to the listeners so I get events */ + switch_thread_rwlock_wrlock(globals.listener_rwlock); + listener->next = listen_list.listeners; + listen_list.listeners = listener; + switch_thread_rwlock_unlock(globals.listener_rwlock); +} -/* TODO lock */ static void remove_listener(listener_t *listener) { listener_t *l, *last = NULL; + switch_thread_rwlock_wrlock(globals.listener_rwlock); for (l = listen_list.listeners; l; l = l->next) { if (l == listener) { if (last) { @@ -280,17 +280,18 @@ static void remove_listener(listener_t *listener) } last = l; } + switch_thread_rwlock_unlock(globals.listener_rwlock); } -/* Search for a listener already talking to the specified node */ -static listener_t *find_listener(char *nodename) +/* Search for a listener already talking to the specified node and lock for reading*/ +static listener_t *find_listener_locked(char *nodename) { listener_t *l = NULL; switch_thread_rwlock_rdlock(globals.listener_rwlock); for (l = listen_list.listeners; l; l = l->next) { if (!strncmp(nodename, l->peer_nodename, MAXNODELEN)) { - /* TODO listener rwlock */ + switch_thread_rwlock_rdlock(l->rwlock); break; } } @@ -976,10 +977,6 @@ static switch_bool_t check_inbound_acl(listener_t *listener) static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) { listener_t *listener = (listener_t *) obj; - session_elem_t *s = NULL; - const void *key; - void *value; - switch_hash_index_t *iter; switch_mutex_lock(globals.listener_count_mutex); prefs.threads++; @@ -994,50 +991,14 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Open from %s\n", listener->remote_ip); /*, listener->remote_port); */ } - /*add_listener(listener);*/ + add_listener(listener); listener_main_loop(listener); } - /* clean up */ - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session complete, waiting for children\n"); - - listener->dead = 1; /* mark it as dead */ - - /* TODO - release write lock */ - switch_thread_rwlock_wrlock(globals.listener_rwlock); - remove_listener(listener); - switch_thread_rwlock_unlock(globals.listener_rwlock); - - switch_thread_rwlock_wrlock(listener->rwlock); - - if (listener->sockfd) { - close_socket(&listener->sockfd); - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Closed\n"); - /* TODO make listener destroy function and move there */ - switch_core_hash_destroy(&listener->event_hash); - /* remove any bindings for this connection */ - remove_binding(listener, NULL); - - /* clean up all the attached sessions */ - switch_thread_rwlock_wrlock(listener->session_rwlock); - for (iter = switch_hash_first(NULL, listener->sessions); iter; iter = switch_hash_next(iter)) { - switch_hash_this(iter, &key, NULL, &value); - s = (session_elem_t*)value; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Orphaning call %s\n", s->uuid_str); - remove_session_elem_from_listener(listener, s); - destroy_session_elem(s); - } - switch_thread_rwlock_unlock(listener->session_rwlock); - switch_thread_rwlock_unlock(listener->rwlock); - - if (listener->pool) { - switch_memory_pool_t *pool = listener->pool; - switch_core_destroy_memory_pool(&pool); - } + remove_listener(listener); + destroy_listener(listener); switch_mutex_lock(globals.listener_count_mutex); prefs.threads--; @@ -1220,8 +1181,6 @@ static listener_t *new_listener(struct ei_cnode_s *ec, int clientfd) switch_queue_create(&listener->event_queue, SWITCH_CORE_QUEUE_LEN, pool); switch_queue_create(&listener->log_queue, SWITCH_CORE_QUEUE_LEN, pool); - /* TODO remove */ - listener->dead = 0; /* born alive */ listener->sockfd = clientfd; listener->pool = pool; listener->ec = switch_core_alloc(listener->pool, sizeof(ei_cnode)); @@ -1233,49 +1192,16 @@ static listener_t *new_listener(struct ei_cnode_s *ec, int clientfd) switch_core_hash_init(&listener->event_hash, listener->pool); switch_core_hash_init(&listener->sessions, listener->pool); - /* TODO listener rdlock */ - listener->next = listen_list.listeners; - listen_list.listeners = listener; - return listener; } -/*TODO we don't need bottleneck*/ -static listener_t *new_listener_locked(struct ei_cnode_s *ec, int clientfd) -{ - listener_t *res; - switch_thread_rwlock_wrlock(globals.listener_rwlock); - res = new_listener(ec, clientfd); - switch_thread_rwlock_unlock(globals.listener_rwlock); - return res; -} -/* TODO new session??? */ -static listener_t *new_outbound_listener(char *node, switch_bool_t *new_session) +static listener_t *new_outbound_listener_locked(char *node) { listener_t *listener = NULL; struct ei_cnode_s ec; int clientfd; - /* TODO find listener func */ - switch_thread_rwlock_wrlock(globals.listener_rwlock); - for (listener = listen_list.listeners; listener; listener = listener->next) { - if (!strncmp(node, listener->peer_nodename, MAXNODELEN)) { - break; - } - } - - if (listener && listener->dead) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "found dead listener for %s\n", node); - remove_listener(listener); /* remove the dead listener and continue adding one */ - } else if (listener) { - switch_thread_rwlock_unlock(globals.listener_rwlock); - - *new_session = SWITCH_FALSE; - return listener; - } - - if (SWITCH_STATUS_SUCCESS == initialise_ei(&ec)) { #ifdef WIN32 WSASetLastError(0); @@ -1284,7 +1210,7 @@ static listener_t *new_outbound_listener(char *node, switch_bool_t *new_session) #endif if ((clientfd = ei_connect(&ec, node)) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error connecting to node %s (erl_errno=%d, errno=%d)!\n", node, erl_errno, errno); - switch_thread_rwlock_unlock(globals.listener_rwlock); + return NULL; } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "new listener for %s\n", node); @@ -1292,12 +1218,49 @@ static listener_t *new_outbound_listener(char *node, switch_bool_t *new_session) listener->peer_nodename = switch_core_strdup(listener->pool, node); } - switch_thread_rwlock_unlock(globals.listener_rwlock); - *new_session = SWITCH_TRUE; + switch_thread_rwlock_rdlock(listener->rwlock); return listener; } +void destroy_listener(listener_t * listener) +{ + session_elem_t *s = NULL; + const void *key; + void *value; + switch_hash_index_t *iter; + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session complete, waiting for children\n"); + switch_thread_rwlock_wrlock(listener->rwlock); + + if (listener->sockfd) { + close_socket(&listener->sockfd); + } + + switch_core_hash_destroy(&listener->event_hash); + + /* remove any bindings for this connection */ + remove_binding(listener, NULL); + + /* clean up all the attached sessions */ + switch_thread_rwlock_wrlock(listener->session_rwlock); + for (iter = switch_hash_first(NULL, listener->sessions); iter; iter = switch_hash_next(iter)) { + switch_hash_this(iter, &key, NULL, &value); + s = (session_elem_t*)value; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Orphaning call %s\n", s->uuid_str); + remove_session_elem_from_listener(listener, s); + destroy_session_elem(s); + } + switch_thread_rwlock_unlock(listener->session_rwlock); + switch_thread_rwlock_unlock(listener->rwlock); + + if (listener->pool) { + switch_memory_pool_t *pool = listener->pool; + switch_core_destroy_memory_pool(&pool); + } + +} + static switch_status_t state_handler(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); @@ -1499,7 +1462,6 @@ SWITCH_STANDARD_APP(erlang_outbound_function) char *argv[80] = { 0 }, *argv2[80] = { 0 }; char *mydata, *myarg; char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1]; - switch_bool_t new_session = SWITCH_FALSE; session_elem_t *session_element = NULL; /* process app arguments */ @@ -1541,31 +1503,19 @@ SWITCH_STANDARD_APP(erlang_outbound_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "enter erlang_outbound_function %s %s\n", argv[0], node); /* first work out if there is a listener already talking to the node we want to talk to */ - listener = find_listener(node); + listener = find_listener_locked(node); /* if there is no listener, then create one */ if (!listener) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating new listener for session\n"); - listener = new_outbound_listener(node, &new_session); - /* XXX new_session isn't accurate now */ - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Using existing listener for session\n"); - /* TODO don't we need to connect ? */ - } - - /* TODO it's too late */ - switch_thread_rwlock_rdlock(globals.listener_rwlock); - - if (listener && !listener->dead) { - /* prevent the listener_run thread from destroying the listener out from under us */ - /* get the listener lock */ - switch_thread_rwlock_rdlock(listener->rwlock); - /* release the global listener lock, since the listener can't be freed without the listener lock */ - switch_thread_rwlock_unlock(globals.listener_rwlock); - - if (new_session == SWITCH_TRUE) { + if ((listener = new_outbound_listener_locked(node))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Launching new listener\n"); launch_listener_thread(listener); } + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Using existing listener for session\n"); + } + + if (listener) { if (module && function) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating new spawned session for listener\n"); @@ -1575,10 +1525,8 @@ SWITCH_STANDARD_APP(erlang_outbound_function) session_element = attach_call_to_registered_process(listener, reg_name, session); } - /* should be safe now */ switch_thread_rwlock_unlock(listener->rwlock); - if (session_element) { switch_ivr_park(session, NULL); } @@ -1600,7 +1548,6 @@ SWITCH_STANDARD_APP(erlang_sendmsg_function) char *mydata; ei_x_buff buf; listener_t *listener; - switch_bool_t new_session; ei_x_new_with_version(&buf); @@ -1623,16 +1570,18 @@ SWITCH_STANDARD_APP(erlang_sendmsg_function) ei_x_encode_atom(&buf, "freeswitch_sendmsg"); _ei_x_encode_string(&buf, argv[2]); - listener = find_listener(node); + listener = find_listener_locked(node); if (!listener) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating new listener for sendmsg %s\n", node); - listener = new_outbound_listener(node, &new_session); + listener = new_outbound_listener_locked(node); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Using existing listener for sendmsg to %s\n", node); } - if (listener && !listener->dead) { + if (listener) { ei_reg_send(listener->ec, listener->sockfd, reg_name, buf.buff, buf.index); + + switch_thread_rwlock_unlock(listener->rwlock); } } @@ -1927,7 +1876,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_erlang_event_runtime) continue; } - listener = new_listener_locked(&ec, clientfd); + listener = new_listener(&ec, clientfd); if (listener) { /* store the IP and node name we are talking with */ switch_inet_ntop(AF_INET, conn.ipadr, listener->remote_ip, sizeof(listener->remote_ip)); diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h index 775cdf74f3..016734dd80 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h @@ -114,7 +114,6 @@ struct listener { #else int sockfd; #endif - uint8_t dead; struct ei_cnode_s *ec; struct erlang_process log_process; struct erlang_process event_process; From 4e6b56c53d83c643b2d590da100c70c02dc3f993 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 10:57:28 +0200 Subject: [PATCH 004/101] add listener event r/w locking FS-3432 --- .../mod_erlang_event/handle_msg.c | 24 +++++++++++++------ .../mod_erlang_event/mod_erlang_event.c | 17 ++++++++----- .../mod_erlang_event/mod_erlang_event.h | 1 + 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c index 0b083cd0c0..8e6ba46a62 100644 --- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c +++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c @@ -28,6 +28,7 @@ * Rob Charlton * Darren Schreiber * Mike Jerris + * Tamas Cseke * * * handle_msg.c -- handle messages received from erlang nodes @@ -286,7 +287,8 @@ static switch_status_t handle_msg_event(listener_t *listener, int arity, ei_x_bu switch_set_flag_locked(listener, LFLAG_EVENTS); } - /* TODO - listener write lock */ + switch_thread_rwlock_wrlock(listener->event_rwlock); + for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { @@ -312,6 +314,8 @@ static switch_status_t handle_msg_event(listener_t *listener, int arity, ei_x_bu switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "enable event %s\n", atom); } } + switch_thread_rwlock_unlock(listener->event_rwlock); + ei_x_encode_atom(rbuf, "ok"); } return SWITCH_STATUS_SUCCESS; @@ -382,7 +386,8 @@ static switch_status_t handle_msg_nixevent(listener_t *listener, int arity, ei_x int i = 0; switch_event_types_t type; - /* TODO listener write lock */ + switch_thread_rwlock_wrlock(listener->event_rwlock); + for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { @@ -410,6 +415,8 @@ static switch_status_t handle_msg_nixevent(listener_t *listener, int arity, ei_x } } } + + switch_thread_rwlock_unlock(listener->event_rwlock); ei_x_encode_atom(rbuf, "ok"); } return SWITCH_STATUS_SUCCESS; @@ -522,11 +529,11 @@ static switch_status_t handle_msg_setevent(listener_t *listener, erlang_msg *msg } } /* update the event subscriptions with the new ones */ + switch_thread_rwlock_wrlock(listener->event_rwlock); memcpy(listener->event_list, event_list, sizeof(uint8_t) * (SWITCH_EVENT_ALL + 1)); - /* wipe the old hash, and point the pointer at the new one */ - /* TODO make thread safe */ switch_core_hash_destroy(&listener->event_hash); listener->event_hash = event_hash; + switch_thread_rwlock_unlock(listener->event_rwlock); /* TODO - we should flush any non-matching events from the queue */ ei_x_encode_atom(rbuf, "ok"); @@ -1031,13 +1038,16 @@ static switch_status_t handle_msg_atom(listener_t *listener, erlang_msg * msg, e if (switch_test_flag(listener, LFLAG_EVENTS)) { uint8_t x = 0; switch_clear_flag_locked(listener, LFLAG_EVENTS); + + switch_thread_rwlock_wrlock(listener->event_rwlock); for (x = 0; x <= SWITCH_EVENT_ALL; x++) { listener->event_list[x] = 0; } - /* wipe the hash */ - /* TODO make thread safe*/ - switch_core_hash_destroy(&listener->event_hash); + + switch_core_hash_delete_multi(listener->event_hash, NULL, NULL); switch_core_hash_init(&listener->event_hash, listener->pool); + + switch_thread_rwlock_unlock(listener->event_rwlock); ei_x_encode_atom(rbuf, "ok"); } else { ei_x_encode_tuple_header(rbuf, 2); diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index c2f204ef0a..f690fe6453 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -26,6 +26,7 @@ * Anthony Minessale II * Andrew Thompson * Rob Charlton + * Tamas Cseke * * * mod_erlang_event.c -- Erlang Event Handler derived from mod_event_socket @@ -200,6 +201,8 @@ static void event_handler(switch_event_t *event) continue; } + switch_thread_rwlock_rdlock(l->event_rwlock); + if (l->event_list[SWITCH_EVENT_ALL]) { send = 1; } else if ((l->event_list[event->event_id])) { @@ -208,6 +211,7 @@ static void event_handler(switch_event_t *event) } } + switch_thread_rwlock_unlock(l->event_rwlock); if (send) { if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) { @@ -815,14 +819,12 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) uint8_t x = 0; switch_clear_flag_locked(listener, LFLAG_EVENTS); + switch_thread_rwlock_wrlock(listener->event_rwlock); for (x = 0; x <= SWITCH_EVENT_ALL; x++) { listener->event_list[x] = 0; } - /* wipe the hash */ - /* XXX this needs to be locked */ - /* TODO switch_core_hash_delete_multi_locked */ - switch_core_hash_destroy(&listener->event_hash); - switch_core_hash_init(&listener->event_hash, listener->pool); + switch_core_hash_delete_multi(listener->event_hash, NULL, NULL); + switch_thread_rwlock_unlock(listener->event_rwlock); } } } @@ -1177,7 +1179,6 @@ static listener_t *new_listener(struct ei_cnode_s *ec, int clientfd) } memset(listener, 0, sizeof(*listener)); - switch_thread_rwlock_create(&listener->rwlock, pool); switch_queue_create(&listener->event_queue, SWITCH_CORE_QUEUE_LEN, pool); switch_queue_create(&listener->log_queue, SWITCH_CORE_QUEUE_LEN, pool); @@ -1188,7 +1189,11 @@ static listener_t *new_listener(struct ei_cnode_s *ec, int clientfd) listener->level = SWITCH_LOG_DEBUG; switch_mutex_init(&listener->flag_mutex, SWITCH_MUTEX_NESTED, listener->pool); switch_mutex_init(&listener->sock_mutex, SWITCH_MUTEX_NESTED, listener->pool); + + switch_thread_rwlock_create(&listener->rwlock, pool); + switch_thread_rwlock_create(&listener->event_rwlock, pool); switch_thread_rwlock_create(&listener->session_rwlock, listener->pool); + switch_core_hash_init(&listener->event_hash, listener->pool); switch_core_hash_init(&listener->sessions, listener->pool); diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h index 016734dd80..5383922782 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h @@ -129,6 +129,7 @@ struct listener { uint8_t event_list[SWITCH_EVENT_ALL + 1]; switch_hash_t *event_hash; switch_thread_rwlock_t *rwlock; + switch_thread_rwlock_t *event_rwlock; switch_thread_rwlock_t *session_rwlock; //session_elem_t *session_list; switch_hash_t *sessions; From fdd3a8d3339145d41310d453ce5f046bc575162c Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 11:16:26 +0200 Subject: [PATCH 005/101] set and clear session flags locked FS-3432 --- .../mod_erlang_event/mod_erlang_event.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index f690fe6453..4fc383e4e7 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -592,7 +592,7 @@ static switch_status_t check_attached_sessions(listener_t *listener) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delete", (const char *) key); continue; } - switch_set_flag(sp, LFLAG_OUTBOUND_INIT); + switch_set_flag_locked(sp, LFLAG_OUTBOUND_INIT); } if (switch_test_flag(sp, LFLAG_SESSION_COMPLETE)) { @@ -1278,8 +1278,7 @@ static switch_status_t state_handler(switch_core_session_t *session) if (state == CS_DESTROY) { /* indicate that once all the events in the event queue are done * we can throw this away */ - /* TODO locked? */ - switch_set_flag(session_element, LFLAG_SESSION_COMPLETE); + switch_set_flag_locked(session_element, LFLAG_SESSION_COMPLETE); } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to update channel state for %s to %s\n", switch_core_session_get_uuid(session), @@ -1366,7 +1365,7 @@ session_elem_t *attach_call_to_spawned_process(listener_t *listener, char *modul spawn_reply_t *p; erlang_ref ref; - switch_set_flag(session_element, LFLAG_WAITING_FOR_PID); + switch_set_flag_locked(session_element, LFLAG_WAITING_FOR_PID); /* attach the session to the listener */ add_session_elem_to_listener(listener, session_element); @@ -1430,8 +1429,8 @@ session_elem_t *attach_call_to_spawned_process(listener_t *listener, char *modul memcpy(&session_element->process.pid, p->pid, sizeof(erlang_pid)); session_element->spawn_reply = NULL; - switch_clear_flag(session_element, LFLAG_OUTBOUND_INIT); - switch_clear_flag(session_element, LFLAG_WAITING_FOR_PID); + switch_clear_flag_locked(session_element, LFLAG_OUTBOUND_INIT); + switch_clear_flag_locked(session_element, LFLAG_WAITING_FOR_PID); ei_link(listener, ei_self(listener->ec), &session_element->process.pid); From 87f65f178496200047ba03d506a7289dc442b390 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 11:32:15 +0200 Subject: [PATCH 006/101] add session r/w locking FS-3432 --- .../mod_erlang_event/mod_erlang_event.c | 27 +++++++++---------- .../mod_erlang_event/mod_erlang_event.h | 1 + 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index 4fc383e4e7..daa31d773a 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -137,8 +137,10 @@ static void send_event_to_attached_sessions(listener_t *listener, switch_event_t switch_thread_rwlock_rdlock(listener->session_rwlock); - s = (session_elem_t*)switch_core_hash_find(listener->sessions, uuid); - /* TODO - we don't need to hold the lock, we need to lock the session */ + if ((s = (session_elem_t*)switch_core_hash_find(listener->sessions, uuid))) { + switch_thread_rwlock_rdlock(s->rwlock); + } + switch_thread_rwlock_unlock(listener->session_rwlock); if (s) { int send = 0; @@ -166,8 +168,9 @@ static void send_event_to_attached_sessions(listener_t *listener, switch_event_t switch_log_printf(SWITCH_CHANNEL_UUID_LOG(s->uuid_str), SWITCH_LOG_DEBUG, "Ignoring event %s for attached session %s\n", switch_event_name(event->event_id), s->uuid_str); } + switch_thread_rwlock_unlock(s->rwlock); } - switch_thread_rwlock_unlock(listener->session_rwlock); + } static void event_handler(switch_event_t *event) @@ -329,13 +332,15 @@ static void destroy_session_elem(session_elem_t *session_element) { switch_core_session_t *session; + /* wait for readers */ + switch_thread_rwlock_wrlock(session_element->rwlock); + switch_thread_rwlock_unlock(session_element->rwlock); + if ((session = switch_core_session_locate(session_element->uuid_str))) { switch_channel_clear_flag(switch_core_session_get_channel(session), CF_CONTROLLED); switch_core_session_rwunlock(session); } switch_core_destroy_memory_pool(&session_element->pool); - session_element = NULL; - /*switch_safe_free(s); */ } @@ -890,15 +895,7 @@ static void listener_main_loop(listener_t *listener) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "erl_exit from %s <%d.%d.%d>\n", msg.from.node, msg.from.creation, msg.from.num, msg.from.serial); - switch_thread_rwlock_rdlock(globals.listener_rwlock); - if (listener) { - /* get the listener lock */ - switch_thread_rwlock_wrlock(listener->rwlock); - /* wipe event hash */ - handle_exit(listener, &msg.from); - switch_thread_rwlock_unlock(listener->rwlock); - } - switch_thread_rwlock_unlock(globals.listener_rwlock); + handle_exit(listener, &msg.from); break; default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "unexpected msg type %d\n", (int) (msg.msgtype)); @@ -1318,6 +1315,8 @@ session_elem_t *session_elem_create(listener_t *listener, switch_core_session_t session_element->event_list[x] = 0; } + switch_thread_rwlock_create(&session_element->rwlock, session_element->pool); + session_element->event_list[SWITCH_EVENT_ALL] = 1; /* defaults to everything */ switch_channel_set_private(channel, "_erlang_session_", session_element); diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h index 5383922782..2e9fed865f 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h @@ -83,6 +83,7 @@ struct session_elem { uint32_t flags; struct erlang_process process; switch_queue_t *event_queue; + switch_thread_rwlock_t *rwlock; switch_channel_state_t channel_state; switch_memory_pool_t *pool; uint8_t event_list[SWITCH_EVENT_ALL + 1]; From 85656c31afa2c2f80700730a64cb3ff71768556a Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 11:44:12 +0200 Subject: [PATCH 007/101] add session event r/w locking FS-3432 --- .../mod_erlang_event/handle_msg.c | 25 +++++++++++++------ .../mod_erlang_event/mod_erlang_event.c | 6 +++++ .../mod_erlang_event/mod_erlang_event.h | 1 + 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c index 8e6ba46a62..944263b2f5 100644 --- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c +++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c @@ -337,10 +337,11 @@ static switch_status_t handle_msg_session_event(listener_t *listener, erlang_msg switch_event_types_t type; int i = 0; + switch_thread_rwlock_wrlock(session->event_rwlock); + for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { - /* TODO session write locking */ if (custom) { switch_core_hash_insert(session->event_hash, atom, MARKER); } else if (switch_name_event(atom, &type) == SWITCH_STATUS_SUCCESS) { @@ -363,6 +364,9 @@ static switch_status_t handle_msg_session_event(listener_t *listener, erlang_msg switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "enable event %s for session %s\n", atom, session->uuid_str); } } + + switch_thread_rwlock_unlock(session->event_rwlock); + ei_x_encode_atom(rbuf, "ok"); } else { ei_x_encode_tuple_header(rbuf, 2); @@ -437,7 +441,8 @@ static switch_status_t handle_msg_session_nixevent(listener_t *listener, erlang_ int i = 0; switch_event_types_t type; - /* TODO session write lock */ + switch_thread_rwlock_wrlock(session->event_rwlock); + for (i = 1; i < arity; i++) { if (!ei_decode_atom(buf->buff, &buf->index, atom)) { @@ -464,6 +469,8 @@ static switch_status_t handle_msg_session_nixevent(listener_t *listener, erlang_ } } } + switch_thread_rwlock_unlock(session->event_rwlock); + ei_x_encode_atom(rbuf, "ok"); } else { /* no session for this pid */ ei_x_encode_tuple_header(rbuf, 2); @@ -590,12 +597,15 @@ static switch_status_t handle_msg_session_setevent(listener_t *listener, erlang_ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "enable event %s for session %s\n", atom, session->uuid_str); } } + /* update the event subscriptions with the new ones */ + switch_thread_rwlock_wrlock(session->event_rwlock); memcpy(session->event_list, event_list, sizeof(uint8_t) * (SWITCH_EVENT_ALL + 1)); /* wipe the old hash, and point the pointer at the new one */ - /* TODO make thread safe*/ switch_core_hash_destroy(&session->event_hash); session->event_hash = event_hash; + switch_thread_rwlock_unlock(session->event_rwlock); + /* TODO - we should flush any non-matching events from the queue */ ei_x_encode_atom(rbuf, "ok"); } else { /* no session for this pid */ @@ -1045,7 +1055,6 @@ static switch_status_t handle_msg_atom(listener_t *listener, erlang_msg * msg, e } switch_core_hash_delete_multi(listener->event_hash, NULL, NULL); - switch_core_hash_init(&listener->event_hash, listener->pool); switch_thread_rwlock_unlock(listener->event_rwlock); ei_x_encode_atom(rbuf, "ok"); @@ -1062,13 +1071,15 @@ static switch_status_t handle_msg_atom(listener_t *listener, erlang_msg * msg, e /*purge the event queue */ while (switch_queue_trypop(session->event_queue, &pop) == SWITCH_STATUS_SUCCESS); + + switch_thread_rwlock_wrlock(session->event_rwlock); for (x = 0; x <= SWITCH_EVENT_ALL; x++) { session->event_list[x] = 0; } /* wipe the hash */ - /* TODO make thread safe*/ - switch_core_hash_destroy(&session->event_hash); - switch_core_hash_init(&session->event_hash, session->pool); + switch_core_hash_delete_multi(session->event_hash, NULL, NULL); + switch_thread_rwlock_unlock(session->event_rwlock); + ei_x_encode_atom(rbuf, "ok"); } else { ei_x_encode_tuple_header(rbuf, 2); diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index daa31d773a..fa1ea86982 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -144,6 +144,9 @@ static void send_event_to_attached_sessions(listener_t *listener, switch_event_t if (s) { int send = 0; + + switch_thread_rwlock_rdlock(s->event_rwlock); + if (s->event_list[SWITCH_EVENT_ALL]) { send = 1; } else if ((s->event_list[event->event_id])) { @@ -152,6 +155,8 @@ static void send_event_to_attached_sessions(listener_t *listener, switch_event_t } } + switch_thread_rwlock_unlock(s->event_rwlock); + if (send) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(s->uuid_str), SWITCH_LOG_DEBUG, "Sending event %s to attached session %s\n", switch_event_name(event->event_id), s->uuid_str); @@ -1316,6 +1321,7 @@ session_elem_t *session_elem_create(listener_t *listener, switch_core_session_t } switch_thread_rwlock_create(&session_element->rwlock, session_element->pool); + switch_thread_rwlock_create(&session_element->event_rwlock, session_element->pool); session_element->event_list[SWITCH_EVENT_ALL] = 1; /* defaults to everything */ diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h index 2e9fed865f..d5f890d0a1 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h @@ -84,6 +84,7 @@ struct session_elem { struct erlang_process process; switch_queue_t *event_queue; switch_thread_rwlock_t *rwlock; + switch_thread_rwlock_t *event_rwlock; switch_channel_state_t channel_state; switch_memory_pool_t *pool; uint8_t event_list[SWITCH_EVENT_ALL + 1]; From 78641d4264355872de73817dd06da00593d33f47 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 14:55:29 +0200 Subject: [PATCH 008/101] cleanup process spawning, remove mutex lock and add session to listener only if reply state and session flag is set to waiting FS-3432 --- .../mod_erlang_event/handle_msg.c | 3 --- .../mod_erlang_event/mod_erlang_event.c | 17 +++++++---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c index 944263b2f5..5ff207e1a1 100644 --- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c +++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c @@ -1149,9 +1149,6 @@ static switch_status_t handle_ref_tuple(listener_t *listener, erlang_msg * msg, if (se->spawn_reply && !strncmp(se->spawn_reply->hash, hash, 100)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found matching session for %s : %s\n", hash, se->uuid_str); switch_mutex_lock(se->spawn_reply->mutex); - if (se->spawn_reply->state == reply_not_ready) { - switch_thread_cond_wait(se->spawn_reply->ready_or_found, se->spawn_reply->mutex); - } if (se->spawn_reply->state == reply_waiting) { se->spawn_reply->pid = pid; diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index fa1ea86982..e24b30bb6d 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -1366,30 +1366,28 @@ session_elem_t *attach_call_to_spawned_process(listener_t *listener, char *modul /* create a session list element */ session_elem_t *session_element = session_elem_create(listener, session); char hash[100]; - //void *p = NULL; spawn_reply_t *p; erlang_ref ref; - switch_set_flag_locked(session_element, LFLAG_WAITING_FOR_PID); - - /* attach the session to the listener */ - add_session_elem_to_listener(listener, session_element); ei_init_ref(listener->ec, &ref); ei_hash_ref(&ref, hash); - /* insert the waiting marker */ p = switch_core_alloc(session_element->pool, sizeof(*p)); switch_thread_cond_create(&p->ready_or_found, session_element->pool); switch_mutex_init(&p->mutex, SWITCH_MUTEX_UNNESTED, session_element->pool); - p->state = reply_not_ready; + p->state = reply_waiting; p->hash = hash; p->pid = NULL; session_element->spawn_reply = p; - switch_mutex_lock(p->mutex); - p->state = reply_waiting; + /* insert the waiting marker */ + switch_set_flag(session_element, LFLAG_WAITING_FOR_PID); + + /* attach the session to the listener */ + add_session_elem_to_listener(listener, session_element); + if (!strcmp(function, "!")) { /* send a message to request a pid */ @@ -1434,7 +1432,6 @@ session_elem_t *attach_call_to_spawned_process(listener_t *listener, char *modul memcpy(&session_element->process.pid, p->pid, sizeof(erlang_pid)); session_element->spawn_reply = NULL; - switch_clear_flag_locked(session_element, LFLAG_OUTBOUND_INIT); switch_clear_flag_locked(session_element, LFLAG_WAITING_FOR_PID); ei_link(listener, ei_self(listener->ec), &session_element->process.pid); From 2be25c6a5693a8dafc866fb8158fc0c80da413f1 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 15:14:14 +0200 Subject: [PATCH 009/101] remove removal while traversing the hash and and lock to elimate race FS-3432 --- .../mod_erlang_event/mod_erlang_event.c | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index e24b30bb6d..a3f3acc08a 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -356,18 +356,16 @@ session_elem_t *find_session_elem_by_pid(listener_t *listener, erlang_pid *pid) void *val = NULL; session_elem_t *session = NULL; - switch_thread_rwlock_rdlock(listener->session_rwlock); for (iter = switch_hash_first(NULL, listener->sessions); iter; iter = switch_hash_next(iter)) { switch_hash_this(iter, &key, NULL, &val); - session = (session_elem_t*)val; - if (session->process.type == ERLANG_PID && !ei_compare_pids(pid, &session->process.pid)) { - switch_thread_rwlock_unlock(listener->session_rwlock); - return session; + + if (((session_elem_t*)val)->process.type == ERLANG_PID && !ei_compare_pids(pid, &((session_elem_t*)val)->process.pid)) { + session = (session_elem_t*)val; + break; } } - switch_thread_rwlock_unlock(listener->session_rwlock); - return NULL; + return session; } @@ -779,6 +777,9 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) session_elem_t *s; remove_binding(NULL, pid); /* TODO - why don't we pass the listener as the first argument? */ + + /* TODO - eliminate session destroy races and we shouldn't lock the session hash */ + switch_thread_rwlock_wrlock(listener->session_rwlock); if ((s = find_session_elem_by_pid(listener, pid))) { if (s->channel_state < CS_HANGUP) { switch_core_session_t *session; @@ -794,9 +795,12 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) /* TODO - if a spawned process that was handling an outbound call fails.. what do we do with the call? */ /* TODO hangup and let the state handler set the complete flag and destroy as usual*/ } - remove_session_elem_from_listener_locked(listener, s); - destroy_session_elem(s); + if (remove_session_elem_from_listener(listener, s) == SWITCH_STATUS_SUCCESS) { + destroy_session_elem(s); + } } + switch_thread_rwlock_wrlock(listener->session_rwlock); + if (listener->log_process.type == ERLANG_PID && !ei_compare_pids(&listener->log_process.pid, pid)) { void *pop; @@ -1255,7 +1259,6 @@ void destroy_listener(listener_t * listener) switch_hash_this(iter, &key, NULL, &value); s = (session_elem_t*)value; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Orphaning call %s\n", s->uuid_str); - remove_session_elem_from_listener(listener, s); destroy_session_elem(s); } switch_thread_rwlock_unlock(listener->session_rwlock); @@ -1275,6 +1278,7 @@ static switch_status_t state_handler(switch_core_session_t *session) session_elem_t *session_element = switch_channel_get_private(channel, "_erlang_session_"); /*listener_t* listener = switch_channel_get_private(channel, "_erlang_listener_"); */ + /* TODO make thread safe */ if (session_element) { session_element->channel_state = state; if (state == CS_DESTROY) { From 377f6a9ef6906e1be7bb589d44340c3ab32b79e3 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 16:12:55 +0200 Subject: [PATCH 010/101] remove channel private, state handler and clear controlled flag on destroy FS-3432 --- .../mod_erlang_event/mod_erlang_event.c | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index a3f3acc08a..dd84d8de11 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -342,7 +342,15 @@ static void destroy_session_elem(session_elem_t *session_element) switch_thread_rwlock_unlock(session_element->rwlock); if ((session = switch_core_session_locate(session_element->uuid_str))) { - switch_channel_clear_flag(switch_core_session_get_channel(session), CF_CONTROLLED); + switch_channel_t *channel = switch_core_session_get_channel(session); + + if (switch_channel_get_state(channel) < CS_HANGUP) { + switch_log_printf(SWITCH_CHANNEL_UUID_LOG(session_element->uuid_str), SWITCH_LOG_WARNING, "Outbound session for %s exited unexpectedly!\n", session_element->uuid_str); + } + + switch_channel_set_private(channel, "_erlang_session_", NULL); + switch_core_event_hook_remove_state_change(session, state_handler); + switch_channel_clear_flag(channel, CF_CONTROLLED); switch_core_session_rwunlock(session); } switch_core_destroy_memory_pool(&session_element->pool); @@ -781,20 +789,6 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) /* TODO - eliminate session destroy races and we shouldn't lock the session hash */ switch_thread_rwlock_wrlock(listener->session_rwlock); if ((s = find_session_elem_by_pid(listener, pid))) { - if (s->channel_state < CS_HANGUP) { - switch_core_session_t *session; - switch_log_printf(SWITCH_CHANNEL_UUID_LOG(s->uuid_str), SWITCH_LOG_WARNING, "Outbound session for %s exited unexpectedly!\n", s->uuid_str); - - if ((session = switch_core_session_locate(s->uuid_str))) { - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_channel_set_private(channel, "_erlang_session_", NULL); - switch_channel_set_private(channel, "_erlang_listener_", NULL); - switch_core_event_hook_remove_state_change(session, state_handler); - switch_core_session_rwunlock(session); - } - /* TODO - if a spawned process that was handling an outbound call fails.. what do we do with the call? */ - /* TODO hangup and let the state handler set the complete flag and destroy as usual*/ - } if (remove_session_elem_from_listener(listener, s) == SWITCH_STATUS_SUCCESS) { destroy_session_elem(s); } @@ -1276,9 +1270,7 @@ static switch_status_t state_handler(switch_core_session_t *session) switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_state_t state = switch_channel_get_state(channel); session_elem_t *session_element = switch_channel_get_private(channel, "_erlang_session_"); - /*listener_t* listener = switch_channel_get_private(channel, "_erlang_listener_"); */ - /* TODO make thread safe */ if (session_element) { session_element->channel_state = state; if (state == CS_DESTROY) { @@ -1330,7 +1322,6 @@ session_elem_t *session_elem_create(listener_t *listener, switch_core_session_t session_element->event_list[SWITCH_EVENT_ALL] = 1; /* defaults to everything */ switch_channel_set_private(channel, "_erlang_session_", session_element); - switch_channel_set_private(channel, "_erlang_listener_", listener); switch_core_event_hook_add_state_change(session, state_handler); From 9dc9ee974c3de9246daff6551c46a14ffeefa61c Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Thu, 24 May 2012 16:19:01 +0200 Subject: [PATCH 011/101] doh FS-3423 --- src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index dd84d8de11..fc38f9e2b2 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -320,7 +320,6 @@ static void add_session_elem_to_listener(listener_t *listener, session_elem_t *s } -/* TODO lock */ static void remove_session_elem_from_listener(listener_t *listener, session_elem_t *session_element) { switch_core_hash_delete(listener->sessions, session_element->uuid_str); @@ -789,9 +788,8 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) /* TODO - eliminate session destroy races and we shouldn't lock the session hash */ switch_thread_rwlock_wrlock(listener->session_rwlock); if ((s = find_session_elem_by_pid(listener, pid))) { - if (remove_session_elem_from_listener(listener, s) == SWITCH_STATUS_SUCCESS) { - destroy_session_elem(s); - } + remove_session_elem_from_listener(listener, s); + destroy_session_elem(s); } switch_thread_rwlock_wrlock(listener->session_rwlock); From 82b00ecbc8bfb9e9e389b7a2bf8fe43a2e390520 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Wed, 30 May 2012 15:10:00 +0000 Subject: [PATCH 012/101] don't build mod_ilbc or mod_siren by default Our default build probably shouldn't include non-free software. With mod_ilbc, the licensing situation is merely ambiguous. With mod_siren, the user can't use this code without getting explicit permission from Polycom (though it is apparently easily given). --- build/modules.conf.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/modules.conf.in b/build/modules.conf.in index 534c1f0ec2..fdb631927a 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -58,12 +58,12 @@ codecs/mod_bv codecs/mod_g723_1 codecs/mod_g729 codecs/mod_h26x -codecs/mod_ilbc +#codecs/mod_ilbc #codecs/mod_isac #codecs/mod_opus #codecs/mod_sangoma_codec #codecs/mod_silk -codecs/mod_siren +#codecs/mod_siren codecs/mod_speex dialplans/mod_dialplan_asterisk #dialplans/mod_dialplan_directory From 192030c57898bce8b3df805ea1b21ad436c015b9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 30 May 2012 13:05:05 -0500 Subject: [PATCH 013/101] add metadata col to internal registrations table --- src/include/switch_core.h | 4 +- src/mod/endpoints/mod_skinny/skinny_server.c | 3 +- src/mod/endpoints/mod_sofia/sofia_reg.c | 7 ++- src/switch_core_sqldb.c | 50 ++++++++++++++------ 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 9803c6708b..05d6e0aa48 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2300,10 +2300,12 @@ SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number) \param [in] network_ip \param [in] network_port \param [in] network_proto - one of tls, tcp, udp + \param [in] metadata - generic metadata supplied by module \param [out] err - Error if it exists */ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires, - const char *network_ip, const char *network_port, const char *network_proto); + const char *network_ip, const char *network_port, const char *network_proto, + const char *metadata); /*! \brief Delete user registration \param [in] user diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index 0957739455..95f7e6c83e 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -1007,6 +1007,7 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r const char *value = switch_xml_attr_soft(xbutton, "value"); if(type == SKINNY_BUTTON_LINE) { const char *caller_name = switch_xml_attr_soft(xbutton, "caller-name"); + const char *reg_metadata = switch_xml_attr_soft(xbutton, "registration-metadata"); uint32_t ring_on_idle = atoi(switch_xml_attr_soft(xbutton, "ring-on-idle")); uint32_t ring_on_active = atoi(switch_xml_attr_soft(xbutton, "ring-on-active")); uint32_t busy_trigger = atoi(switch_xml_attr_soft(xbutton, "busy-trigger")); @@ -1030,7 +1031,7 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r switch_safe_free(sql); token = switch_mprintf("skinny/%q/%q/%q:%d", profile->name, value, request->data.reg.device_name, request->data.reg.instance); url = switch_mprintf("skinny/%q/%q", profile->name, value); - switch_core_add_registration(value, profile->domain, token, url, 0, network_ip, network_port_c, "tcp"); + switch_core_add_registration(value, profile->domain, token, url, 0, network_ip, network_port_c, "tcp", reg_metadata); switch_safe_free(token); switch_safe_free(url); } diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index e358c8f228..7ec9f1f93a 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1028,6 +1028,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand sip_contact_t const *contact = NULL; char *sql; switch_event_t *s_event; + const char *reg_meta = NULL; const char *to_user = NULL; const char *to_host = NULL; char *mwi_account = NULL; @@ -1485,6 +1486,10 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand to_user = var; } + if (v_event && *v_event && (var = switch_event_get_header(*v_event, "registration_metadata"))) { + reg_meta = var; + } + if (v_event && *v_event && (mwi_account = switch_event_get_header(*v_event, "mwi-account"))) { dup_mwi_account = strdup(mwi_account); switch_assert(dup_mwi_account != NULL); @@ -1559,7 +1564,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand url = switch_mprintf("sofia/%q/sip:%q", profile->name, sofia_glue_strip_proto(contact)); switch_core_add_registration(to_user, reg_host, call_id, url, (long) switch_epoch_time_now(NULL) + (long) exptime + 60, - network_ip, network_port_c, is_tls ? "tls" : is_tcp ? "tcp" : "udp"); + network_ip, network_port_c, is_tls ? "tls" : is_tcp ? "tcp" : "udp", reg_meta); switch_safe_free(url); switch_safe_free(contact); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 85d38160ed..9b40674065 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1713,7 +1713,8 @@ static char create_registrations_sql[] = " network_ip VARCHAR(256),\n" " network_port VARCHAR(256),\n" " network_proto VARCHAR(256),\n" - " hostname VARCHAR(256)\n" + " hostname VARCHAR(256),\n" + " metadata VARCHAR(256)\n" ");\n"; @@ -1843,7 +1844,8 @@ static char basic_calls_sql[] = SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires, - const char *network_ip, const char *network_port, const char *network_proto) + const char *network_ip, const char *network_port, const char *network_proto, + const char *metadata) { char *sql; @@ -1860,19 +1862,35 @@ SWITCH_DECLARE(switch_status_t) switch_core_add_registration(const char *user, c } switch_queue_push(sql_manager.sql_queue[0], sql); - - sql = switch_mprintf("insert into registrations (reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname) " - "values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q')", - switch_str_nil(user), - switch_str_nil(realm), - switch_str_nil(token), - switch_str_nil(url), - expires, - switch_str_nil(network_ip), - switch_str_nil(network_port), - switch_str_nil(network_proto), - switch_core_get_switchname() - ); + + if ( !zstr(metadata) ) { + sql = switch_mprintf("insert into registrations (reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname,metadata) " + "values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%q')", + switch_str_nil(user), + switch_str_nil(realm), + switch_str_nil(token), + switch_str_nil(url), + expires, + switch_str_nil(network_ip), + switch_str_nil(network_port), + switch_str_nil(network_proto), + switch_core_get_switchname(), + metadata + ); + } else { + sql = switch_mprintf("insert into registrations (reg_user,realm,token,url,expires,network_ip,network_port,network_proto,hostname) " + "values ('%q','%q','%q','%q',%ld,'%q','%q','%q','%q')", + switch_str_nil(user), + switch_str_nil(realm), + switch_str_nil(token), + switch_str_nil(url), + expires, + switch_str_nil(network_ip), + switch_str_nil(network_port), + switch_str_nil(network_proto), + switch_core_get_switchname() + ); + } switch_queue_push(sql_manager.sql_queue[0], sql); @@ -2007,6 +2025,8 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_cache_db_test_reactive(dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", "DROP TABLE registrations", create_registrations_sql); + switch_cache_db_test_reactive(dbh, "select metadata from registrations", NULL, "ALTER TABLE registrations ADD COLUMN metadata VARCHAR(256)"); + switch (dbh->type) { case SCDB_TYPE_ODBC: From 3e1d68b0a6900b582154bbb72a8149ea1a357c9b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 30 May 2012 13:08:31 -0500 Subject: [PATCH 014/101] FS-4250 --resolve erase replaces header after using it --- src/mod/endpoints/mod_sofia/sofia_glue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index cb091daf8e..2cb2fdd551 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2087,7 +2087,9 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) } - rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER); + if ((rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER))) { + switch_channel_set_variable(channel, SOFIA_REPLACES_HEADER, NULL); + } switch_assert(tech_pvt != NULL); From 39bad5b13ef8a85608a6783a9ebdaed3713da04d Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 30 May 2012 15:58:48 -0500 Subject: [PATCH 015/101] vs2010 reswig for last commit --- .../mod_managed/freeswitch_wrap.2010.cxx | 28 +++++++++++++++++-- .../mod_managed/managed/swig.2010.cs | 18 ++++++++++-- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index 65b4eedf3c..a11d584f49 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -1550,6 +1550,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_SIGNAL_BOND_VARIABLE_get() { } +SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE_get() { + char * jresult ; + char *result = 0 ; + + result = (char *)("originate_signal_bond"); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_ORIGINATOR_VARIABLE_get() { char * jresult ; char *result = 0 ; @@ -11108,7 +11118,7 @@ SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_default_ptime(char * jarg1, u } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_add_registration(char * jarg1, char * jarg2, char * jarg3, char * jarg4, unsigned long jarg5, char * jarg6, char * jarg7, char * jarg8) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_add_registration(char * jarg1, char * jarg2, char * jarg3, char * jarg4, unsigned long jarg5, char * jarg6, char * jarg7, char * jarg8, char * jarg9) { int jresult ; char *arg1 = (char *) 0 ; char *arg2 = (char *) 0 ; @@ -11118,6 +11128,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_add_registration(char * jarg1, cha char *arg6 = (char *) 0 ; char *arg7 = (char *) 0 ; char *arg8 = (char *) 0 ; + char *arg9 = (char *) 0 ; switch_status_t result; arg1 = (char *)jarg1; @@ -11128,7 +11139,8 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_add_registration(char * jarg1, cha arg6 = (char *)jarg6; arg7 = (char *)jarg7; arg8 = (char *)jarg8; - result = (switch_status_t)switch_core_add_registration((char const *)arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5,(char const *)arg6,(char const *)arg7,(char const *)arg8); + arg9 = (char *)jarg9; + result = (switch_status_t)switch_core_add_registration((char const *)arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,arg5,(char const *)arg6,(char const *)arg7,(char const *)arg8,(char const *)arg9); jresult = result; return jresult; } @@ -25772,6 +25784,18 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_transfer_to_extension(void * j } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_partner_uuid(void * jarg1) { + char * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + char *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (char *)switch_channel_get_partner_uuid(arg1); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_buffer_create(void * jarg1, void * jarg2, void * jarg3) { int jresult ; switch_memory_pool_t *arg1 = (switch_memory_pool_t *) 0 ; diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index 0654085a50..3a1cc13d6b 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -2671,8 +2671,8 @@ public class freeswitch { return ret; } - public static switch_status_t switch_core_add_registration(string user, string realm, string token, string url, uint expires, string network_ip, string network_port, string network_proto) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_add_registration(user, realm, token, url, expires, network_ip, network_port, network_proto); + public static switch_status_t switch_core_add_registration(string user, string realm, string token, string url, uint expires, string network_ip, string network_port, string network_proto, string metadata) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_add_registration(user, realm, token, url, expires, network_ip, network_port, network_proto, metadata); return ret; } @@ -4118,6 +4118,11 @@ public class freeswitch { freeswitchPINVOKE.switch_channel_transfer_to_extension(SWIGTYPE_p_switch_channel.getCPtr(channel), switch_caller_extension.getCPtr(caller_extension)); } + public static string switch_channel_get_partner_uuid(SWIGTYPE_p_switch_channel channel) { + string ret = freeswitchPINVOKE.switch_channel_get_partner_uuid(SWIGTYPE_p_switch_channel.getCPtr(channel)); + return ret; + } + public static switch_status_t switch_buffer_create(SWIGTYPE_p_apr_pool_t pool, SWIGTYPE_p_p_switch_buffer buffer, SWIGTYPE_p_switch_size_t max_len) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_buffer_create(SWIGTYPE_p_apr_pool_t.getCPtr(pool), SWIGTYPE_p_p_switch_buffer.getCPtr(buffer), SWIGTYPE_p_switch_size_t.getCPtr(max_len)); if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); @@ -6130,6 +6135,7 @@ public class freeswitch { public static readonly string SWITCH_LAST_BRIDGE_VARIABLE = freeswitchPINVOKE.SWITCH_LAST_BRIDGE_VARIABLE_get(); public static readonly string SWITCH_SIGNAL_BRIDGE_VARIABLE = freeswitchPINVOKE.SWITCH_SIGNAL_BRIDGE_VARIABLE_get(); public static readonly string SWITCH_SIGNAL_BOND_VARIABLE = freeswitchPINVOKE.SWITCH_SIGNAL_BOND_VARIABLE_get(); + public static readonly string SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE = freeswitchPINVOKE.SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE_get(); public static readonly string SWITCH_ORIGINATOR_VARIABLE = freeswitchPINVOKE.SWITCH_ORIGINATOR_VARIABLE_get(); public static readonly string SWITCH_ORIGINATOR_CODEC_VARIABLE = freeswitchPINVOKE.SWITCH_ORIGINATOR_CODEC_VARIABLE_get(); public static readonly string SWITCH_ORIGINATOR_VIDEO_CODEC_VARIABLE = freeswitchPINVOKE.SWITCH_ORIGINATOR_VIDEO_CODEC_VARIABLE_get(); @@ -6780,6 +6786,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_SIGNAL_BOND_VARIABLE_get")] public static extern string SWITCH_SIGNAL_BOND_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE_get")] + public static extern string SWITCH_ORIGINATE_SIGNAL_BOND_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_ORIGINATOR_VARIABLE_get")] public static extern string SWITCH_ORIGINATOR_VARIABLE_get(); @@ -9094,7 +9103,7 @@ class freeswitchPINVOKE { public static extern uint switch_default_ptime(string jarg1, uint jarg2); [DllImport("mod_managed", EntryPoint="CSharp_switch_core_add_registration")] - public static extern int switch_core_add_registration(string jarg1, string jarg2, string jarg3, string jarg4, uint jarg5, string jarg6, string jarg7, string jarg8); + public static extern int switch_core_add_registration(string jarg1, string jarg2, string jarg3, string jarg4, uint jarg5, string jarg6, string jarg7, string jarg8, string jarg9); [DllImport("mod_managed", EntryPoint="CSharp_switch_core_del_registration")] public static extern int switch_core_del_registration(string jarg1, string jarg2, string jarg3); @@ -12705,6 +12714,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_transfer_to_extension")] public static extern void switch_channel_transfer_to_extension(HandleRef jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_partner_uuid")] + public static extern string switch_channel_get_partner_uuid(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_buffer_create")] public static extern int switch_buffer_create(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3); From 07bc7ba7639726985daa571ea20490c7d3dc75ce Mon Sep 17 00:00:00 2001 From: Giovanni Maruzzelli Date: Thu, 31 May 2012 07:40:59 +0200 Subject: [PATCH 016/101] gsmopen and skypopen: updated License headers --- src/mod/endpoints/mod_gsmopen/gsmopen.h | 12 +++---- .../mod_gsmopen/gsmopen_protocol.cpp | 36 +++++++++++++++++++ src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp | 11 +++--- src/mod/endpoints/mod_skypopen/mod_skypopen.c | 12 +++---- src/mod/endpoints/mod_skypopen/skypopen.h | 11 +++--- .../mod_skypopen/skypopen_protocol.c | 34 ++++++++++++++++++ 6 files changed, 89 insertions(+), 27 deletions(-) diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen.h b/src/mod/endpoints/mod_gsmopen/gsmopen.h index 2b4c619783..fd56fd4963 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen.h +++ b/src/mod/endpoints/mod_gsmopen/gsmopen.h @@ -1,6 +1,6 @@ /* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005/2012, Anthony Minessale II + * Copyright (C) 2005-2011, Anthony Minessale II * * Version: MPL 1.1 * @@ -23,17 +23,15 @@ * * This module (mod_gsmopen) has been contributed by: * - * Giovanni Maruzzelli (gmaruzz@gmail.com) + * Giovanni Maruzzelli * + * Maintainer: Giovanni Maruzzelli * - * Further Contributors: - * - * - * - * mod_gsmopen.c -- GSM compatible Endpoint Module + * mod_gsmopen.cpp -- GSM Modem compatible Endpoint Module * */ + #define __STDC_LIMIT_MACROS #ifdef WIN32 diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp index 391dade93a..ffa4e3d014 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp +++ b/src/mod/endpoints/mod_gsmopen/gsmopen_protocol.cpp @@ -1,3 +1,39 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * This module (mod_gsmopen) has been contributed by: + * + * Giovanni Maruzzelli + * + * Maintainer: Giovanni Maruzzelli + * + * gsmopen_protocol.cpp -- Low Level Interface for mod_gamopen + * + */ + + + + #include "gsmopen.h" #ifdef WIN32 #include "win_iconv.c" diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp index f48d299e0a..837d20ed30 100644 --- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp +++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp @@ -1,6 +1,6 @@ /* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005/2012, Anthony Minessale II + * Copyright (C) 2005-2011, Anthony Minessale II * * Version: MPL 1.1 * @@ -23,14 +23,11 @@ * * This module (mod_gsmopen) has been contributed by: * - * Giovanni Maruzzelli (gmaruzz@gmail.com) + * Giovanni Maruzzelli * + * Maintainer: Giovanni Maruzzelli * - * Further Contributors: - * - * - * - * mod_gsmopen.c -- GSM compatible Endpoint Module + * mod_gsmopen.cpp -- GSM Modem compatible Endpoint Module * */ diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index 25539fa81e..ce89211b83 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -1,6 +1,6 @@ /* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2012, Anthony Minessale II + * Copyright (C) 2005-2011, Anthony Minessale II * * Version: MPL 1.1 * @@ -21,19 +21,17 @@ * Portions created by the Initial Developer are Copyright (C) * the Initial Developer. All Rights Reserved. * - * This module (mod_skypopen) has been contributed by: - * - * Giovanni Maruzzelli (gmaruzz@gmail.com) - * - * - * Further Contributors: + * This module (mod_gsmopen) has been contributed by: * + * Giovanni Maruzzelli * + * Maintainer: Giovanni Maruzzelli * * mod_skypopen.c -- Skype compatible Endpoint Module * */ + #include "skypopen.h" #define SKYPE_CHAT_PROTO "skype" diff --git a/src/mod/endpoints/mod_skypopen/skypopen.h b/src/mod/endpoints/mod_skypopen/skypopen.h index d2dd51bd37..864a22c3e4 100644 --- a/src/mod/endpoints/mod_skypopen/skypopen.h +++ b/src/mod/endpoints/mod_skypopen/skypopen.h @@ -1,6 +1,6 @@ /* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005/2012, Anthony Minessale II + * Copyright (C) 2005-2011, Anthony Minessale II * * Version: MPL 1.1 * @@ -21,18 +21,17 @@ * Portions created by the Initial Developer are Copyright (C) * the Initial Developer. All Rights Reserved. * - * This module (mod_skypopen) has been contributed by: + * This module (mod_gsmopen) has been contributed by: * - * Giovanni Maruzzelli (gmaruzz@gmail.com) - * - * - * Further Contributors: + * Giovanni Maruzzelli * + * Maintainer: Giovanni Maruzzelli * * mod_skypopen.c -- Skype compatible Endpoint Module * */ + #include #include diff --git a/src/mod/endpoints/mod_skypopen/skypopen_protocol.c b/src/mod/endpoints/mod_skypopen/skypopen_protocol.c index 5aa113c3bf..2126955452 100644 --- a/src/mod/endpoints/mod_skypopen/skypopen_protocol.c +++ b/src/mod/endpoints/mod_skypopen/skypopen_protocol.c @@ -1,3 +1,37 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * This module (mod_gsmopen) has been contributed by: + * + * Giovanni Maruzzelli + * + * Maintainer: Giovanni Maruzzelli + * + * skypopen_protocol.c -- Low Level Interface for mod_skypopen + * + */ + + #include "skypopen.h" #ifdef ASTERISK From be2ec2928214718978551b1419759e6fa13709da Mon Sep 17 00:00:00 2001 From: Christopher Rienzo Date: Thu, 31 May 2012 13:24:24 +0000 Subject: [PATCH 017/101] Add Maintainer to mod_posix_timer, mod_unimrcp, mod_http_cache --- src/mod/applications/mod_http_cache/mod_http_cache.c | 4 +++- src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c | 2 ++ src/mod/timers/mod_posix_timer/mod_posix_timer.c | 4 +++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_http_cache/mod_http_cache.c b/src/mod/applications/mod_http_cache/mod_http_cache.c index 1e40ce2e15..fb2b4e09a2 100644 --- a/src/mod/applications/mod_http_cache/mod_http_cache.c +++ b/src/mod/applications/mod_http_cache/mod_http_cache.c @@ -23,7 +23,9 @@ * * Contributor(s): * - * Chris Rienzo + * Christopher M. Rienzo + * + * Maintainer: Christopher M. Rienzo * * mod_http_cache.c -- HTTP GET with caching * -- designed for downloading audio files from a webserver for playback diff --git a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c index 80fa3f2001..e53964277c 100644 --- a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c +++ b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c @@ -28,6 +28,8 @@ * Christopher M. Rienzo * Luke Dashjr (OpenMethods, LLC) * + * Maintainer: Christopher M. Rienzo + * * mod_unimrcp.c -- UniMRCP module (MRCP client) * */ diff --git a/src/mod/timers/mod_posix_timer/mod_posix_timer.c b/src/mod/timers/mod_posix_timer/mod_posix_timer.c index 04d694b5f7..cfb6584701 100644 --- a/src/mod/timers/mod_posix_timer/mod_posix_timer.c +++ b/src/mod/timers/mod_posix_timer/mod_posix_timer.c @@ -22,9 +22,11 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Chris Rienzo + * Christopher M. Rienzo * Timo Teräs (based on mod_timerfd.c) * + * Maintainer: Christopher M. Rienzo + * * mod_posix_timer.c -- soft timer implemented with POSIX timers (timer_create/timer_settime/timer_getoverrun) * */ From 5be9857af249705b96c1235d778b317cc0b99afa Mon Sep 17 00:00:00 2001 From: Ken Rice Date: Thu, 31 May 2012 10:25:49 -0500 Subject: [PATCH 018/101] remove mod_fax. this has been deprecated for quite a while --- src/mod/applications/mod_fax/Makefile.am | 24 - .../applications/mod_fax/mod_fax.2008.vcproj | 299 --- src/mod/applications/mod_fax/mod_fax.c | 1945 ----------------- src/mod/applications/mod_fax/udptl.c | 563 ----- src/mod/applications/mod_fax/udptl.h | 153 -- 5 files changed, 2984 deletions(-) delete mode 100644 src/mod/applications/mod_fax/Makefile.am delete mode 100644 src/mod/applications/mod_fax/mod_fax.2008.vcproj delete mode 100644 src/mod/applications/mod_fax/mod_fax.c delete mode 100644 src/mod/applications/mod_fax/udptl.c delete mode 100644 src/mod/applications/mod_fax/udptl.h diff --git a/src/mod/applications/mod_fax/Makefile.am b/src/mod/applications/mod_fax/Makefile.am deleted file mode 100644 index c71c5b9da5..0000000000 --- a/src/mod/applications/mod_fax/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -include $(top_srcdir)/build/modmake.rulesam -MODNAME=mod_fax - -TIFF_DIR=$(switch_srcdir)/libs/tiff-3.8.2 -TIFF_BUILDDIR=$(switch_builddir)/libs/tiff-3.8.2 -TIFF_LA=$(TIFF_BUILDDIR)/libtiff/libtiff.la - -SPANDSP_DIR=$(switch_srcdir)/libs/spandsp -SPANDSP_BUILDDIR=$(switch_builddir)/libs/spandsp -SPANDSP_LA=$(SPANDSP_BUILDDIR)/src/libspandsp.la - -mod_LTLIBRARIES = mod_fax.la -mod_fax_la_SOURCES = mod_fax.c udptl.c -mod_fax_la_CFLAGS = $(AM_CFLAGS) -I$(SPANDSP_DIR)/src -I$(TIFF_DIR)/libtiff -I$(SPANDSP_BUILDDIR)/src -I$(TIFF_BUILDDIR)/libtiff -I. -mod_fax_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SPANDSP_LA) $(TIFF_LA) -mod_fax_la_LDFLAGS = -avoid-version -module -no-undefined -shared -ljpeg - -$(SPANDSP_LA): $(TIFF_LA) $(SPANDSP_DIR) $(SPANDSP_DIR)/.update - cd $(SPANDSP_BUILDDIR) && $(MAKE) -j1 - $(TOUCH_TARGET) - -$(TIFF_LA): $(TIFF_DIR) $(TIFF_DIR)/.update - cd $(TIFF_BUILDDIR) && $(MAKE) -j1 - $(TOUCH_TARGET) diff --git a/src/mod/applications/mod_fax/mod_fax.2008.vcproj b/src/mod/applications/mod_fax/mod_fax.2008.vcproj deleted file mode 100644 index dd10ca8a93..0000000000 --- a/src/mod/applications/mod_fax/mod_fax.2008.vcproj +++ /dev/null @@ -1,299 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/mod/applications/mod_fax/mod_fax.c b/src/mod/applications/mod_fax/mod_fax.c deleted file mode 100644 index 7eac2520b3..0000000000 --- a/src/mod/applications/mod_fax/mod_fax.c +++ /dev/null @@ -1,1945 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2012, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH mod_fax. - * - * The Initial Developer of the Original Code is - * Massimo Cetra - * - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Brian West - * Anthony Minessale II - * Steve Underwood - * Antonio Gallo - * mod_fax.c -- Fax applications provided by SpanDSP - * - */ - -#include -#ifdef WIN32 -#define FAX_INVALID_SOCKET INVALID_HANDLE_VALUE -typedef HANDLE zap_socket_t; -#else -#define FAX_INVALID_SOCKET -1 -typedef int zap_socket_t; -#endif - -#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES -#include -#include - -#include "udptl.h" - -#define LOCAL_FAX_MAX_DATAGRAM 400 -#define MAX_FEC_ENTRIES 4 -#define MAX_FEC_SPAN 4 - -/***************************************************************************** - OUR DEFINES AND STRUCTS -*****************************************************************************/ - -typedef enum { - FUNCTION_TX, - FUNCTION_RX, - FUNCTION_GW -} application_mode_t; - -typedef enum { - T38_MODE, - AUDIO_MODE, - T38_GATEWAY_MODE -} transport_mode_t; - -typedef enum { - T38_MODE_UNKNOWN = 0, - T38_MODE_NEGOTIATED = 1, - T38_MODE_REQUESTED = 2, - T38_MODE_REFUSED = -1, -} t38_mode_t; - -/* The global stuff */ -static struct { - switch_memory_pool_t *pool; - switch_mutex_t *mutex; - - uint32_t total_sessions; - - short int use_ecm; - short int verbose; - short int disable_v17; - short int enable_t38; - short int enable_t38_request; - short int enable_t38_insist; - char ident[20]; - char header[50]; - char *prepend_string; - char *spool; -} globals; - -struct pvt_s { - switch_core_session_t *session; - - application_mode_t app_mode; - - fax_state_t *fax_state; - t38_terminal_state_t *t38_state; - t38_gateway_state_t *t38_gateway_state; - t38_core_state_t *t38_core; - - udptl_state_t *udptl_state; - - char *filename; - char *ident; - char *header; - - int use_ecm; - int disable_v17; - int verbose; - int caller; - - int tx_page_start; - int tx_page_end; - - int done; - - t38_mode_t t38_mode; - - struct pvt_s *next; -}; - -typedef struct pvt_s pvt_t; - -static void launch_timer_thread(void); - -static struct { - pvt_t *head; - switch_mutex_t *mutex; - switch_thread_t *thread; - int thread_running; -} t38_state_list; - -static int add_pvt(pvt_t *pvt) -{ - int r = 0; - uint32_t sanity = 50; - - switch_mutex_lock(t38_state_list.mutex); - if (!t38_state_list.thread_running) { - - launch_timer_thread(); - - while(--sanity && !t38_state_list.thread_running) { - switch_yield(10000); - } - } - switch_mutex_unlock(t38_state_list.mutex); - - if (t38_state_list.thread_running) { - switch_mutex_lock(t38_state_list.mutex); - pvt->next = t38_state_list.head; - t38_state_list.head = pvt; - switch_mutex_unlock(t38_state_list.mutex); - } - - return r; - -} - - -static int del_pvt(pvt_t *del_pvt) -{ - pvt_t *p, *l = NULL; - int r = 0; - - if (!t38_state_list.thread_running) goto end; - - switch_mutex_lock(t38_state_list.mutex); - for (p = t38_state_list.head; p; p = p->next) { - if (p == del_pvt) { - if (l) { - l->next = p->next; - } else { - t38_state_list.head = p->next; - } - p->next = NULL; - r = 1; - goto end; - } - - l = p; - } - - end: - - switch_mutex_unlock(t38_state_list.mutex); - - return r; - -} - -static void *SWITCH_THREAD_FUNC timer_thread_run(switch_thread_t *thread, void *obj) -{ - switch_timer_t timer = { 0 }; - pvt_t *pvt; - int samples = 240; - int ms = 30; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "timer thread started.\n"); - - if (switch_core_timer_init(&timer, "soft", ms, samples, NULL) != SWITCH_STATUS_SUCCESS) { - return NULL; - } - - t38_state_list.thread_running = 1; - - while(t38_state_list.thread_running) { - - switch_mutex_lock(t38_state_list.mutex); - - if (!t38_state_list.head) { - switch_mutex_unlock(t38_state_list.mutex); - goto end; - } - - for (pvt = t38_state_list.head; pvt; pvt = pvt->next) { - if (pvt->udptl_state) { - t38_terminal_send_timeout(pvt->t38_state, samples); - } - } - - switch_mutex_unlock(t38_state_list.mutex); - - switch_core_timer_next(&timer); - } - - end: - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "timer thread ended.\n"); - - t38_state_list.thread_running = 0; - switch_core_timer_destroy(&timer); - - return NULL; -} - -static void launch_timer_thread(void) -{ - - switch_threadattr_t *thd_attr = NULL; - - switch_threadattr_create(&thd_attr, globals.pool); - switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_thread_create(&t38_state_list.thread, thd_attr, timer_thread_run, NULL, globals.pool); -} - - -/***************************************************************************** - LOGGING AND HELPER FUNCTIONS -*****************************************************************************/ - -static void counter_increment(void) -{ - switch_mutex_lock(globals.mutex); - globals.total_sessions++; - switch_mutex_unlock(globals.mutex); -} - -static void spanfax_log_message(int level, const char *msg) -{ - int fs_log_level; - - switch (level) { - case SPAN_LOG_NONE: - return; - case SPAN_LOG_ERROR: - case SPAN_LOG_PROTOCOL_ERROR: - fs_log_level = SWITCH_LOG_ERROR; - break; - case SPAN_LOG_WARNING: - case SPAN_LOG_PROTOCOL_WARNING: - fs_log_level = SWITCH_LOG_WARNING; - break; - case SPAN_LOG_FLOW: - case SPAN_LOG_FLOW_2: - case SPAN_LOG_FLOW_3: - default: /* SPAN_LOG_DEBUG, SPAN_LOG_DEBUG_2, SPAN_LOG_DEBUG_3 */ - fs_log_level = SWITCH_LOG_DEBUG; - break; - } - - if (!zstr(msg)) { - switch_log_printf(SWITCH_CHANNEL_LOG, fs_log_level, "%s", msg); - } -} - -/* - * Called at the end of the document - */ -static void phase_e_handler(t30_state_t *s, void *user_data, int result) -{ - t30_stats_t t; - const char *local_ident; - const char *far_ident; - switch_core_session_t *session; - switch_channel_t *channel; - pvt_t *pvt; - char *tmp; - - pvt = (pvt_t *) user_data; - switch_assert(pvt); - - session = pvt->session; - switch_assert(session); - - channel = switch_core_session_get_channel(session); - switch_assert(channel); - - t30_get_transfer_statistics(s, &t); - local_ident = switch_str_nil(t30_get_tx_ident(s)); - far_ident = switch_str_nil(t30_get_rx_ident(s)); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "==============================================================================\n"); - - if (result == T30_ERR_OK) { - if (pvt->app_mode == FUNCTION_TX) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fax successfully sent.\n"); - } else if (pvt->app_mode == FUNCTION_RX) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fax successfully received.\n"); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fax successfully managed. How ?\n"); - } - switch_channel_set_variable(channel, "fax_success", "1"); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fax processing not successful - result (%d) %s.\n", result, - t30_completion_code_to_str(result)); - switch_channel_set_variable(channel, "fax_success", "0"); - } - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote station id: %s\n", far_ident); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Local station id: %s\n", local_ident); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Pages transferred: %i\n", - pvt->app_mode == FUNCTION_TX ? t.pages_tx : t.pages_rx); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Total fax pages: %i\n", t.pages_in_file); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image resolution: %ix%i\n", t.x_resolution, t.y_resolution); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "ECM status %s\n", (t.error_correcting_mode) ? "on" : "off"); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote country: %s\n", switch_str_nil(t30_get_rx_country(s))); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote vendor: %s\n", switch_str_nil(t30_get_rx_vendor(s))); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote model: %s\n", switch_str_nil(t30_get_rx_model(s))); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "==============================================================================\n"); - - /* - Set our channel variables - */ - - tmp = switch_mprintf("%i", result); - if (tmp) { - switch_channel_set_variable(channel, "fax_result_code", tmp); - switch_safe_free(tmp); - } - - switch_channel_set_variable(channel, "fax_result_text", t30_completion_code_to_str(result)); - - switch_channel_set_variable(channel, "fax_ecm_used", (t.error_correcting_mode) ? "on" : "off"); - switch_channel_set_variable(channel, "fax_local_station_id", local_ident); - switch_channel_set_variable(channel, "fax_remote_station_id", far_ident); - - tmp = switch_mprintf("%i", pvt->app_mode == FUNCTION_TX ? t.pages_tx : t.pages_rx); - if (tmp) { - switch_channel_set_variable(channel, "fax_document_transferred_pages", tmp); - switch_safe_free(tmp); - } - - tmp = switch_mprintf("%i", t.pages_in_file); - if (tmp) { - switch_channel_set_variable(channel, "fax_document_total_pages", tmp); - switch_safe_free(tmp); - } - - tmp = switch_mprintf("%ix%i", t.x_resolution, t.y_resolution); - if (tmp) { - switch_channel_set_variable(channel, "fax_image_resolution", tmp); - switch_safe_free(tmp); - } - - tmp = switch_mprintf("%d", t.image_size); - if (tmp) { - switch_channel_set_variable(channel, "fax_image_size", tmp); - switch_safe_free(tmp); - } - - tmp = switch_mprintf("%d", t.bad_rows); - if (tmp) { - switch_channel_set_variable(channel, "fax_bad_rows", tmp); - switch_safe_free(tmp); - } - - tmp = switch_mprintf("%i", t.bit_rate); - if (tmp) { - switch_channel_set_variable(channel, "fax_transfer_rate", tmp); - switch_safe_free(tmp); - } - - /* switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); */ - - pvt->done = 1; - - /* - TODO Fire events - */ -} - -static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count) -{ - switch_frame_t out_frame = { 0 }; - switch_core_session_t *session; - switch_channel_t *channel; - pvt_t *pvt; - uint8_t pkt[LOCAL_FAX_MAX_DATAGRAM]; - int x; - int r = 0; - - pvt = (pvt_t *) user_data; - session = pvt->session; - channel = switch_core_session_get_channel(session); - - /* we need to build a real packet here and make write_frame.packet and write_frame.packetlen point to it */ - out_frame.flags = SFF_UDPTL_PACKET | SFF_PROXY_PACKET; - out_frame.packet = pkt; - out_frame.packetlen = udptl_build_packet(pvt->udptl_state, pkt, buf, len); - - //switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "WRITE %d udptl bytes\n", out_frame.packetlen); - - for (x = 0; x < count; x++) { - if (switch_core_session_write_frame(session, &out_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { - r = -1; - break; - } - } - - return r; -} - -static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode) -{ - - switch_core_session_t *session; - switch_channel_t *channel; - fax_state_t *fax; - t38_terminal_state_t *t38; - t30_state_t *t30; - - - session = (switch_core_session_t *) pvt->session; - switch_assert(session); - - channel = switch_core_session_get_channel(session); - switch_assert(channel); - - - switch (trans_mode) { - case AUDIO_MODE: - if (pvt->fax_state == NULL) { - pvt->fax_state = (fax_state_t *) switch_core_session_alloc(pvt->session, sizeof(fax_state_t)); - } - if (pvt->fax_state == NULL) { - return SWITCH_STATUS_FALSE; - } - - fax = pvt->fax_state; - t30 = fax_get_t30_state(fax); - - memset(fax, 0, sizeof(fax_state_t)); - if (fax_init(fax, pvt->caller) == NULL) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my fax structs\n"); - return SWITCH_STATUS_FALSE; - } - - fax_set_transmit_on_idle(fax, TRUE); - - span_log_set_message_handler(&fax->logging, spanfax_log_message); - span_log_set_message_handler(&t30->logging, spanfax_log_message); - - if (pvt->verbose) { - span_log_set_level(&fax->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); - span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); - } - break; - case T38_MODE: - if (pvt->t38_state == NULL) { - pvt->t38_state = (t38_terminal_state_t *) switch_core_session_alloc(pvt->session, sizeof(t38_terminal_state_t)); - } - if (pvt->t38_state == NULL) { - return SWITCH_STATUS_FALSE; - } - if (pvt->udptl_state == NULL) { - pvt->udptl_state = (udptl_state_t *) switch_core_session_alloc(pvt->session, sizeof(udptl_state_t)); - } - if (pvt->udptl_state == NULL) { - t38_terminal_free(pvt->t38_state); - pvt->t38_state = NULL; - return SWITCH_STATUS_FALSE; - } - - /* add to timer thread processing */ - add_pvt(pvt); - - t38 = pvt->t38_state; - t30 = t38_terminal_get_t30_state(t38); - - memset(t38, 0, sizeof(t38_terminal_state_t)); - - if (t38_terminal_init(t38, pvt->caller, t38_tx_packet_handler, pvt) == NULL) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my T.38 structs\n"); - return SWITCH_STATUS_FALSE; - } - - pvt->t38_core = t38_terminal_get_t38_core_state(pvt->t38_state); - - if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, - (udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n"); - return SWITCH_STATUS_FALSE; - } - - span_log_set_message_handler(&t38->logging, spanfax_log_message); - span_log_set_message_handler(&t30->logging, spanfax_log_message); - - if (pvt->verbose) { - span_log_set_level(&t38->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); - span_log_set_level(&t30->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); - } - break; - case T38_GATEWAY_MODE: - if (pvt->t38_gateway_state == NULL) { - pvt->t38_gateway_state = (t38_gateway_state_t *) switch_core_session_alloc(pvt->session, sizeof(t38_gateway_state_t)); - } - - if (pvt->udptl_state == NULL) { - pvt->udptl_state = (udptl_state_t *) switch_core_session_alloc(pvt->session, sizeof(udptl_state_t)); - } - - if (t38_gateway_init(pvt->t38_gateway_state, t38_tx_packet_handler, pvt) == NULL) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my T.38 structs\n"); - t38_gateway_free(pvt->t38_gateway_state); - pvt->t38_gateway_state = NULL; - - return SWITCH_STATUS_FALSE; - } - - pvt->t38_core = t38_gateway_get_t38_core_state(pvt->t38_gateway_state); - - if (udptl_init(pvt->udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, - (udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet, (void *) pvt->t38_core) == NULL) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize my UDPTL structs\n"); - t38_gateway_free(pvt->t38_gateway_state); - udptl_release(pvt->udptl_state); - pvt->udptl_state = NULL; - return SWITCH_STATUS_FALSE; - } - - t38_gateway_set_transmit_on_idle(pvt->t38_gateway_state, TRUE); - - if (switch_true(switch_channel_get_variable(channel, "fax_v17_disabled"))) { - t38_gateway_set_supported_modems(pvt->t38_gateway_state, T30_SUPPORT_V29 | T30_SUPPORT_V27TER); - } else { - t38_gateway_set_supported_modems(pvt->t38_gateway_state, T30_SUPPORT_V17 | T30_SUPPORT_V29 | T30_SUPPORT_V27TER); - } - - t38_gateway_set_ecm_capability(pvt->t38_gateway_state, pvt->use_ecm); - switch_channel_set_variable(channel, "fax_ecm_requested", pvt->use_ecm ? "true" : "false"); - - if (switch_true(switch_channel_get_variable(channel, "FAX_DISABLE_ECM"))) { - t38_gateway_set_ecm_capability(pvt->t38_gateway_state, FALSE); - } else { - t38_gateway_set_ecm_capability(pvt->t38_gateway_state, TRUE); - } - - - span_log_set_message_handler(&pvt->t38_gateway_state->logging, spanfax_log_message); - span_log_set_message_handler(&pvt->t38_core->logging, spanfax_log_message); - - if (pvt->verbose) { - span_log_set_level(&pvt->t38_gateway_state->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); - span_log_set_level(&pvt->t38_core->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); - } - - t38_set_t38_version(pvt->t38_core, 0); - t38_gateway_set_ecm_capability(pvt->t38_gateway_state, 1); - - return SWITCH_STATUS_SUCCESS; - - default: - assert(0); /* What? */ - return SWITCH_STATUS_SUCCESS; - } /* Switch trans mode */ - - /* All the things which are common to audio and T.38 FAX setup */ - t30_set_tx_ident(t30, pvt->ident); - t30_set_tx_page_header_info(t30, pvt->header); - - t30_set_phase_e_handler(t30, phase_e_handler, pvt); - - t30_set_supported_image_sizes(t30, - T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH - | T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH); - t30_set_supported_resolutions(t30, - T30_SUPPORT_STANDARD_RESOLUTION | T30_SUPPORT_FINE_RESOLUTION | T30_SUPPORT_SUPERFINE_RESOLUTION - | T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION); - - if (pvt->disable_v17) { - t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER); - switch_channel_set_variable(channel, "fax_v17_disabled", "1"); - } else { - t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER | T30_SUPPORT_V17); - switch_channel_set_variable(channel, "fax_v17_disabled", "0"); - } - - if (pvt->use_ecm) { - t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); - t30_set_ecm_capability(t30, TRUE); - switch_channel_set_variable(channel, "fax_ecm_requested", "1"); - } else { - t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION); - switch_channel_set_variable(channel, "fax_ecm_requested", "0"); - } - - if (pvt->app_mode == FUNCTION_TX) { - t30_set_tx_file(t30, pvt->filename, pvt->tx_page_start, pvt->tx_page_end); - } else { - t30_set_rx_file(t30, pvt->filename, -1); - } - switch_channel_set_variable(channel, "fax_filename", pvt->filename); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t spanfax_destroy(pvt_t *pvt) -{ - int terminate; - t30_state_t *t30; - - if (!pvt) return SWITCH_STATUS_FALSE; - - if (pvt->fax_state) { - if (pvt->t38_state) { - terminate = 0; - } else { - terminate = 1; - } - - t30 = fax_get_t30_state(pvt->fax_state); - if (terminate && t30) { - t30_terminate(t30); - } - - fax_release(pvt->fax_state); - } - - if (pvt->t38_state) { - - /* remove from timer thread processing */ - del_pvt(pvt); - - if (pvt->t38_state) { - terminate = 1; - } else { - terminate = 0; - } - - t30 = t38_terminal_get_t30_state(pvt->t38_state); - - if (terminate && t30) { - t30_terminate(t30); - } - - t38_terminal_release(pvt->t38_state); - } - - if (pvt->t38_gateway_state) { - t38_gateway_release(pvt->t38_gateway_state); - } - - if (pvt->udptl_state) { - udptl_release(pvt->udptl_state); - } - return SWITCH_STATUS_SUCCESS; -} - -static t38_mode_t configure_t38(pvt_t *pvt) -{ - switch_core_session_t *session = pvt->session; - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_t38_options_t *t38_options = switch_channel_get_private(channel, "t38_options"); - int method = 2; - - if (!t38_options || !pvt || !pvt->t38_core) { - pvt->t38_mode = T38_MODE_REFUSED; - return pvt->t38_mode; - } - - t38_set_t38_version(pvt->t38_core, t38_options->T38FaxVersion); - t38_set_max_buffer_size(pvt->t38_core, t38_options->T38FaxMaxBuffer); - t38_set_fastest_image_data_rate(pvt->t38_core, t38_options->T38MaxBitRate); - t38_set_fill_bit_removal(pvt->t38_core, t38_options->T38FaxFillBitRemoval); - t38_set_mmr_transcoding(pvt->t38_core, t38_options->T38FaxTranscodingMMR); - t38_set_jbig_transcoding(pvt->t38_core, t38_options->T38FaxTranscodingJBIG); - t38_set_max_datagram_size(pvt->t38_core, t38_options->T38FaxMaxDatagram); - - if (t38_options->T38FaxRateManagement) { - if (!strcasecmp(t38_options->T38FaxRateManagement, "transferredTCF")) { - method = 2; - } else { - method = 1; - } - } - - t38_set_data_rate_management_method(pvt->t38_core, method); - - - //t38_set_data_transport_protocol(pvt->t38_core, int data_transport_protocol); - //t38_set_redundancy_control(pvt->t38_core, int category, int setting); - - return pvt->t38_mode; -} - -static t38_mode_t negotiate_t38(pvt_t *pvt) -{ - switch_core_session_t *session = pvt->session; - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_core_session_message_t msg = { 0 }; - switch_t38_options_t *t38_options = switch_channel_get_private(channel, "t38_options"); - int enabled = 0, insist = 0; - const char *v; - - pvt->t38_mode = T38_MODE_REFUSED; - - if (pvt->app_mode == FUNCTION_GW) { - enabled = 1; - } else if ((v = switch_channel_get_variable(channel, "fax_enable_t38"))) { - enabled = switch_true(v); - } else { - enabled = globals.enable_t38; - } - - if (!(enabled && t38_options)) { - /* if there is no t38_options the endpoint will refuse the transition */ - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s NO T38 options detected.\n", switch_channel_get_name(channel)); - switch_channel_set_private(channel, "t38_options", NULL); - } else { - pvt->t38_mode = T38_MODE_NEGOTIATED; - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38FaxVersion = %d\n", t38_options->T38FaxVersion); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38MaxBitRate = %d\n", t38_options->T38MaxBitRate); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38FaxFillBitRemoval = %d\n", t38_options->T38FaxFillBitRemoval); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38FaxTranscodingMMR = %d\n", t38_options->T38FaxTranscodingMMR); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38FaxTranscodingJBIG = %d\n", t38_options->T38FaxTranscodingJBIG); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38FaxRateManagement = '%s'\n", t38_options->T38FaxRateManagement); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38FaxMaxBuffer = %d\n", t38_options->T38FaxMaxBuffer); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38FaxMaxDatagram = %d\n", t38_options->T38FaxMaxDatagram); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38FaxUdpEC = '%s'\n", t38_options->T38FaxUdpEC); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38VendorInfo = '%s'\n", switch_str_nil(t38_options->T38VendorInfo)); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "ip = '%s'\n", t38_options->remote_ip ? t38_options->remote_ip : "Not specified"); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "port = %d\n", t38_options->remote_port); - - /* Time to practice our negotiating skills, by editing the t38_options */ - - if (t38_options->T38FaxVersion > 3) { - t38_options->T38FaxVersion = 3; - } - t38_options->T38MaxBitRate = (pvt->disable_v17) ? 9600 : 14400; - t38_options->T38FaxFillBitRemoval = 1; - t38_options->T38FaxTranscodingMMR = 0; - t38_options->T38FaxTranscodingJBIG = 0; - t38_options->T38FaxRateManagement = "transferredTCF"; - t38_options->T38FaxMaxBuffer = 2000; - t38_options->T38FaxMaxDatagram = LOCAL_FAX_MAX_DATAGRAM; - if (strcasecmp(t38_options->T38FaxUdpEC, "t38UDPRedundancy") == 0 - || - strcasecmp(t38_options->T38FaxUdpEC, "t38UDPFEC") == 0) { - t38_options->T38FaxUdpEC = "t38UDPRedundancy"; - } else { - t38_options->T38FaxUdpEC = NULL; - } - t38_options->T38VendorInfo = "0 0 0"; - } - - if ((v = switch_channel_get_variable(channel, "fax_enable_t38_insist"))) { - insist = switch_true(v); - } else { - insist = globals.enable_t38_insist; - } - - /* This will send the options back in a response */ - msg.from = __FILE__; - msg.message_id = SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION; - msg.numeric_arg = insist; - switch_core_session_receive_message(session, &msg); - - return pvt->t38_mode; -} - - - -static t38_mode_t request_t38(pvt_t *pvt) -{ - switch_core_session_t *session = pvt->session; - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_core_session_message_t msg = { 0 }; - switch_t38_options_t *t38_options = NULL; - int enabled = 0, insist = 0; - const char *v; - - pvt->t38_mode = T38_MODE_UNKNOWN; - - if (pvt->app_mode == FUNCTION_GW) { - enabled = 1; - } else if ((v = switch_channel_get_variable(channel, "fax_enable_t38"))) { - enabled = switch_true(v); - } else { - enabled = globals.enable_t38; - } - - if (enabled) { - if ((v = switch_channel_get_variable(channel, "fax_enable_t38_request"))) { - enabled = switch_true(v); - } else { - enabled = globals.enable_t38_request; - } - } - - - if ((v = switch_channel_get_variable(channel, "fax_enable_t38_insist"))) { - insist = switch_true(v); - } else { - insist = globals.enable_t38_insist; - } - - if (enabled) { - t38_options = switch_core_session_alloc(session, sizeof(*t38_options)); - - t38_options->T38MaxBitRate = (pvt->disable_v17) ? 9600 : 14400; - t38_options->T38FaxVersion = 0; - t38_options->T38FaxFillBitRemoval = 1; - t38_options->T38FaxTranscodingMMR = 0; - t38_options->T38FaxTranscodingJBIG = 0; - t38_options->T38FaxRateManagement = "transferredTCF"; - t38_options->T38FaxMaxBuffer = 2000; - t38_options->T38FaxMaxDatagram = LOCAL_FAX_MAX_DATAGRAM; - t38_options->T38FaxUdpEC = "t38UDPRedundancy"; - t38_options->T38VendorInfo = "0 0 0"; - - switch_channel_set_private(channel, "t38_options", t38_options); - pvt->t38_mode = T38_MODE_REQUESTED; - - /* This will send a request for t.38 mode */ - msg.from = __FILE__; - msg.message_id = SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA; - msg.numeric_arg = insist; - switch_core_session_receive_message(session, &msg); - } - - return pvt->t38_mode; -} - -/***************************************************************************** - MAIN FAX PROCESSING -*****************************************************************************/ - -static pvt_t *pvt_init(switch_core_session_t *session, application_mode_t app_mode) -{ - switch_channel_t *channel; - pvt_t *pvt = NULL; - const char *tmp; - - /* Make sure we have a valid channel when starting the FAX application */ - channel = switch_core_session_get_channel(session); - switch_assert(channel != NULL); - - if (!switch_channel_media_ready(channel)) { - switch_channel_answer(channel); - } - - /* Allocate our structs */ - pvt = switch_core_session_alloc(session, sizeof(pvt_t)); - pvt->session = session; - - pvt->app_mode = app_mode; - - pvt->tx_page_start = -1; - pvt->tx_page_end = -1; - - - switch(pvt->app_mode) { - - case FUNCTION_TX: - pvt->caller = 1; - break; - case FUNCTION_RX: - pvt->caller = 0; - break; - case FUNCTION_GW: - break; - } - - /* Retrieving our settings from the channel variables */ - - if ((tmp = switch_channel_get_variable(channel, "fax_use_ecm"))) { - pvt->use_ecm = switch_true(tmp); - } else { - pvt->use_ecm = globals.use_ecm; - } - - if ((tmp = switch_channel_get_variable(channel, "fax_disable_v17"))) { - pvt->disable_v17 = switch_true(tmp); - } else { - pvt->disable_v17 = globals.disable_v17; - } - - if ((tmp = switch_channel_get_variable(channel, "fax_verbose"))) { - pvt->verbose = switch_true(tmp); - } else { - pvt->verbose = globals.verbose; - } - - if ((tmp = switch_channel_get_variable(channel, "fax_force_caller"))) { - if (switch_true(tmp)) { - pvt->caller = 1; - } else { - pvt->caller = 0; - } - } - - if ((tmp = switch_channel_get_variable(channel, "fax_ident"))) { - pvt->ident = switch_core_session_strdup(session, tmp); - } else { - pvt->ident = switch_core_session_strdup(session, globals.ident); - } - - if ((tmp = switch_channel_get_variable(channel, "fax_header"))) { - pvt->header = switch_core_session_strdup(session, tmp); - } else { - pvt->header = switch_core_session_strdup(session, globals.header); - } - - if (pvt->app_mode == FUNCTION_TX) { - if ((tmp = switch_channel_get_variable(channel, "fax_start_page"))) { - pvt->tx_page_start = atoi(tmp); - } - - if ((tmp = switch_channel_get_variable(channel, "fax_end_page"))) { - pvt->tx_page_end = atoi(tmp); - } - - if (pvt->tx_page_end < -1) { - pvt->tx_page_end = -1; - } - - if (pvt->tx_page_start < -1) { - pvt->tx_page_start = -1; - } - - if ((pvt->tx_page_end < pvt->tx_page_start) && (pvt->tx_page_end != -1)) { - pvt->tx_page_end = pvt->tx_page_start; - } - } - - return pvt; -} - -void process_fax(switch_core_session_t *session, const char *data, application_mode_t app_mode) -{ - pvt_t *pvt; - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_codec_t read_codec = { 0 }; - switch_codec_t write_codec = { 0 }; - switch_frame_t *read_frame = { 0 }; - switch_frame_t write_frame = { 0 }; - switch_codec_implementation_t read_impl = { 0 }; - int16_t *buf = NULL; - - switch_core_session_get_read_impl(session, &read_impl); - - counter_increment(); - - - pvt = pvt_init(session, app_mode); - - - buf = switch_core_session_alloc(session, SWITCH_RECOMMENDED_BUFFER_SIZE); - - if (!zstr(data)) { - pvt->filename = switch_core_session_strdup(session, data); - if (pvt->app_mode == FUNCTION_TX) { - if ((switch_file_exists(pvt->filename, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot send inexistant fax file [%s]\n", - switch_str_nil(pvt->filename)); - goto done; - } - } - } else { - if (pvt->app_mode == FUNCTION_TX) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Fax TX filename not set.\n"); - goto done; - } else if (pvt->app_mode == FUNCTION_RX) { - char *fname; - const char *prefix; - switch_time_t time; - - time = switch_time_now(); - - if (!(prefix = switch_channel_get_variable(channel, "fax_prefix"))) { - prefix = globals.prepend_string; - } - - fname = switch_mprintf("%s/%s-%ld-%ld.tif", globals.spool, prefix, globals.total_sessions, time); - if (fname) { - pvt->filename = switch_core_session_strdup(session, fname); - switch_safe_free(fname); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot automatically set fax RX destination file\n"); - goto done; - } - } else { - assert(0); /* UH ?? */ - } - } - - /* - *** Initialize the SpanDSP elements *** - - Note: we could analyze if a fax was already detected in previous stages - and if so, when T.38 will be supported, send a reinvite in T38_MODE, - bypassing AUDIO_MODE. - */ - - if ((spanfax_init(pvt, AUDIO_MODE) != SWITCH_STATUS_SUCCESS)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize Fax engine\n"); - return; - } - - /* - Note: Disable echocan on the channel, remember to call app "disable_ec" in the dialplan - before invoking fax applications - */ - - /* - Note: we are disabling the Jitterbuffer, here, before we answer. - If you have set it to something else and the channel is pre-answered, - it will have no effect. Make sure that if you want more reliable - faxes, it is disabled. - */ - switch_channel_set_variable(channel, "jitterbuffer_msec", "0"); - - - /* We store the original channel codec before switching both - * legs of the calls to a linear 16 bit codec that is the one - * used internally by spandsp and FS will do the transcoding - * from G.711 or any other original codec - */ - if (switch_core_codec_init(&read_codec, - "L16", - NULL, - read_impl.samples_per_second, - read_impl.microseconds_per_packet / 1000, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw read codec activation Success L16 %u\n", - read_codec.implementation->microseconds_per_packet); - switch_core_session_set_read_codec(session, &read_codec); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Raw read codec activation Failed L16\n"); - goto done; - } - - if (switch_core_codec_init(&write_codec, - "L16", - NULL, - read_impl.samples_per_second, - read_impl.microseconds_per_packet / 1000, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw write codec activation Success L16\n"); - write_frame.codec = &write_codec; - write_frame.data = buf; - write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Raw write codec activation Failed L16\n"); - goto done; - } - - switch_ivr_sleep(session, 250, SWITCH_TRUE, NULL); - - - /* If you have the means, I highly recommend picking one up. ...*/ - request_t38(pvt); - - - while (switch_channel_ready(channel)) { - int tx = 0; - switch_status_t status; - - /* - if we are in T.38 mode, we should: 1- initialize the ptv->t38_state stuff, if not done - and then set some callbacks when reading frames. - The only thing we need, then, in this loop, is: - - read a frame without blocking - - eventually feed that frame in spandsp, - - call t38_terminal_send_timeout(), sleep for a while - - The T.38 stuff can be placed here (and the audio stuff can be skipped) - */ - - /* read new audio frame from the channel */ - status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); - - if (!SWITCH_READ_ACCEPTABLE(status) || pvt->done) { - /* Our duty is over */ - goto done; - } - - switch (pvt->t38_mode) { - case T38_MODE_REQUESTED: - { - 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); - configure_t38(pvt); - - /* This will change the rtp stack to udptl mode */ - msg.from = __FILE__; - msg.message_id = SWITCH_MESSAGE_INDICATE_UDPTL_MODE; - switch_core_session_receive_message(session, &msg); - } - continue; - } - break; - case T38_MODE_UNKNOWN: - { - if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) { - if (negotiate_t38(pvt) == T38_MODE_NEGOTIATED) { - /* is is safe to call this again, it was already called above in AUDIO_MODE */ - /* but this is the only way to set up the t38 stuff */ - spanfax_init(pvt, T38_MODE); - continue; - } - } - } - break; - case T38_MODE_NEGOTIATED: - { - /* do what we need to do when we are in t38 mode */ - if (switch_test_flag(read_frame, SFF_CNG)) { - /* dunno what to do, most likely you will not get too many of these since we turn off the timer in udptl mode */ - continue; - } - - if (switch_test_flag(read_frame, SFF_UDPTL_PACKET)) { - /* now we know we can cast frame->packet to a udptl structure */ - //switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "READ %d udptl bytes\n", read_frame->packetlen); - - udptl_rx_packet(pvt->udptl_state, read_frame->packet, read_frame->packetlen); - - - } - } - continue; - default: - break; - } - - /* Skip CNG frames (auto-generated by FreeSWITCH, usually) */ - if (switch_test_flag(read_frame, SFF_CNG)) { - /* We have no real signal data for the FAX software, but we have a space in time if we have a CNG indication. - Do a fill-in operation in the FAX machine, to keep things rolling along. */ - if (fax_rx_fillin(pvt->fax_state, read_frame->samples)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "fax_rx_fillin reported an error\n"); - goto done; - } - } else { - /* Pass the new incoming audio frame to the fax_rx function */ - if (fax_rx(pvt->fax_state, (int16_t *) read_frame->data, read_frame->samples)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "fax_rx reported an error\n"); - goto done; - } - } - - if ((tx = fax_tx(pvt->fax_state, buf, write_codec.implementation->samples_per_packet)) < 0) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "fax_tx reported an error\n"); - goto done; - } - - if (!tx) { - /* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No audio samples to send\n"); */ - continue; - } else { - /* Set our write_frame data */ - write_frame.datalen = tx * sizeof(int16_t); - write_frame.samples = tx; - } - - if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { - goto done; - } - - } - - done: - /* Destroy the SpanDSP structures */ - spanfax_destroy(pvt); - - /* restore the original codecs over the channel */ - - switch_core_session_set_read_codec(session, NULL); - - if (switch_core_codec_ready(&read_codec)) { - switch_core_codec_destroy(&read_codec); - } - - if (switch_core_codec_ready(&write_codec)) { - switch_core_codec_destroy(&write_codec); - } -} - -/* ************************************************************************** - CONFIGURATION - ************************************************************************* */ - -void load_configuration(switch_bool_t reload) -{ - switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL; - - if ((xml = switch_xml_open_cfg("fax.conf", &cfg, NULL))) { - if ((x_lists = switch_xml_child(cfg, "settings"))) { - for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) { - const char *name = switch_xml_attr(x_list, "name"); - const char *value = switch_xml_attr(x_list, "value"); - - if (zstr(name)) { - continue; - } - - if (zstr(value)) { - continue; - } - - if (!strcmp(name, "use-ecm")) { - if (switch_true(value)) - globals.use_ecm = 1; - else - globals.use_ecm = 0; - } else if (!strcmp(name, "verbose")) { - if (switch_true(value)) - globals.verbose = 1; - else - globals.verbose = 0; - } else if (!strcmp(name, "disable-v17")) { - if (switch_true(value)) - globals.disable_v17 = 1; - else - globals.disable_v17 = 0; - } else if (!strcmp(name, "enable-t38")) { - if (switch_true(value)) { - globals.enable_t38= 1; - } else { - globals.enable_t38 = 0; - } - } else if (!strcmp(name, "enable-t38-request")) { - if (switch_true(value)) { - globals.enable_t38_request = 1; - } else { - globals.enable_t38_request = 0; - } - } else if (!strcmp(name, "ident")) { - strncpy(globals.ident, value, sizeof(globals.ident) - 1); - } else if (!strcmp(name, "header")) { - strncpy(globals.header, value, sizeof(globals.header) - 1); - } else if (!strcmp(name, "spool-dir")) { - globals.spool = switch_core_strdup(globals.pool, value); - } else if (!strcmp(name, "file-prefix")) { - globals.prepend_string = switch_core_strdup(globals.pool, value); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown parameter %s\n", name); - } - - } - } - - switch_xml_free(xml); - } -} - -static void event_handler(switch_event_t *event) -{ - load_configuration(1); -} - - - - - - -typedef struct { - switch_core_session_t *session; - dtmf_rx_state_t *dtmf_detect; -} switch_inband_dtmf_t; - -static switch_bool_t inband_dtmf_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) -{ - switch_inband_dtmf_t *pvt = (switch_inband_dtmf_t *) user_data; - switch_frame_t *frame = NULL; - char digit_str[80]; - switch_channel_t *channel = switch_core_session_get_channel(pvt->session); - - switch (type) { - case SWITCH_ABC_TYPE_INIT: - pvt->dtmf_detect = dtmf_rx_init(NULL, NULL, NULL); - break; - case SWITCH_ABC_TYPE_CLOSE: - if (pvt->dtmf_detect) { - dtmf_rx_free(pvt->dtmf_detect); - } - break; - case SWITCH_ABC_TYPE_READ_REPLACE: - if ((frame = switch_core_media_bug_get_read_replace_frame(bug))) { - dtmf_rx(pvt->dtmf_detect, frame->data, frame->samples); - dtmf_rx_get(pvt->dtmf_detect, digit_str, sizeof(digit_str)); - if (digit_str[0]) { - char *p = digit_str; - while (p && *p) { - switch_dtmf_t dtmf = {0}; - dtmf.digit = *p; - dtmf.duration = switch_core_default_dtmf_duration(0); - switch_channel_queue_dtmf(channel, &dtmf); - p++; - } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_DEBUG, "DTMF DETECTED: [%s]\n", - digit_str); - } - switch_core_media_bug_set_read_replace_frame(bug, frame); - } - break; - case SWITCH_ABC_TYPE_WRITE: - default: - break; - } - - return SWITCH_TRUE; -} - -switch_status_t spandsp_stop_inband_dtmf_session(switch_core_session_t *session) -{ - switch_media_bug_t *bug; - switch_channel_t *channel = switch_core_session_get_channel(session); - - if ((bug = switch_channel_get_private(channel, "dtmf"))) { - switch_channel_set_private(channel, "dtmf", NULL); - switch_core_media_bug_remove(session, &bug); - return SWITCH_STATUS_SUCCESS; - } - return SWITCH_STATUS_FALSE; -} - -switch_status_t spandsp_inband_dtmf_session(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_media_bug_t *bug; - switch_status_t status; - switch_inband_dtmf_t *pvt; - switch_codec_implementation_t read_impl = { 0 }; - - switch_core_session_get_read_impl(session, &read_impl); - - if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) { - return SWITCH_STATUS_MEMERR; - } - - - pvt->session = session; - - - if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_FALSE; - } - - if ((status = switch_core_media_bug_add(session, "spandsp_dtmf_detect", NULL, - inband_dtmf_callback, pvt, 0, SMBF_READ_REPLACE, &bug)) != SWITCH_STATUS_SUCCESS) { - return status; - } - - switch_channel_set_private(channel, "dtmf", bug); - - return SWITCH_STATUS_SUCCESS; -} - -/* ************************************************************************** - FREESWITCH MODULE DEFINITIONS - ************************************************************************* */ - -#define SPANFAX_RX_USAGE "" -#define SPANFAX_TX_USAGE "" - -SWITCH_MODULE_LOAD_FUNCTION(mod_fax_init); -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fax_shutdown); -SWITCH_MODULE_DEFINITION(mod_fax, mod_fax_init, mod_fax_shutdown, NULL); - -static switch_event_node_t *NODE = NULL; - -SWITCH_STANDARD_APP(spanfax_tx_function) -{ - process_fax(session, data, FUNCTION_TX); -} - -SWITCH_STANDARD_APP(spanfax_rx_function) -{ - process_fax(session, data, FUNCTION_RX); -} - - -SWITCH_STANDARD_APP(dtmf_session_function) -{ - spandsp_inband_dtmf_session(session); -} - -SWITCH_STANDARD_APP(stop_dtmf_session_function) -{ - spandsp_stop_inband_dtmf_session(session); -} - -static const switch_state_handler_table_t t38_gateway_state_handlers; - -static switch_status_t t38_gateway_on_soft_execute(switch_core_session_t *session) -{ - switch_core_session_t *other_session; - - switch_channel_t *other_channel, *channel = switch_core_session_get_channel(session); - pvt_t *pvt; - const char *peer_uuid = switch_channel_get_variable(channel, "t38_peer"); - switch_core_session_message_t msg = { 0 }; - switch_status_t status; - switch_frame_t *read_frame = { 0 }; - - if (!(other_session = switch_core_session_locate(peer_uuid))) { - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s Cannot locate channel with uuid %s", - switch_channel_get_name(channel), peer_uuid); - goto end; - } - - other_channel = switch_core_session_get_channel(other_session); - - pvt = pvt_init(session, FUNCTION_GW); - request_t38(pvt); - - msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE; - msg.from = __FILE__; - msg.string_arg = peer_uuid; - switch_core_session_receive_message(session, &msg); - - while (switch_channel_ready(channel) && switch_channel_up(other_channel) && !switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) { - status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); - - if (!SWITCH_READ_ACCEPTABLE(status) || pvt->done) { - /* Our duty is over */ - goto end_unlock; - } - - if (switch_test_flag(read_frame, SFF_CNG)) { - continue; - } - - if (switch_core_session_write_frame(other_session, read_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { - goto end_unlock; - } - } - - if (!(switch_channel_ready(channel) && switch_channel_up(other_channel))) { - goto end_unlock; - } - - if (!switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) { - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s Could not negotiate T38\n", switch_channel_get_name(channel)); - goto end_unlock; - } - - if (pvt->t38_mode == T38_MODE_REQUESTED) { - spanfax_init(pvt, T38_GATEWAY_MODE); - configure_t38(pvt); - pvt->t38_mode = T38_MODE_NEGOTIATED; - } else { - if (negotiate_t38(pvt) != T38_MODE_NEGOTIATED) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s Could not negotiate T38\n", switch_channel_get_name(channel)); - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - goto end_unlock; - } - - spanfax_init(pvt, T38_GATEWAY_MODE); - } - - /* This will change the rtp stack to udptl mode */ - msg.from = __FILE__; - msg.message_id = SWITCH_MESSAGE_INDICATE_UDPTL_MODE; - switch_core_session_receive_message(session, &msg); - - - /* wake up the audio side */ - switch_channel_set_private(channel, "_t38_pvt", pvt); - switch_channel_set_app_flag_key("T38", other_channel, CF_APP_T38); - - - while (switch_channel_ready(channel) && switch_channel_up(other_channel)) { - - status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); - - if (!SWITCH_READ_ACCEPTABLE(status) || pvt->done) { - /* Our duty is over */ - goto end_unlock; - } - - if (switch_test_flag(read_frame, SFF_CNG)) { - continue; - } - - if (switch_test_flag(read_frame, SFF_UDPTL_PACKET)) { - udptl_rx_packet(pvt->udptl_state, read_frame->packet, read_frame->packetlen); - } - } - - end_unlock: - - - msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE; - msg.from = __FILE__; - msg.string_arg = peer_uuid; - switch_core_session_receive_message(session, &msg); - - switch_channel_hangup(other_channel, SWITCH_CAUSE_NORMAL_CLEARING); - switch_core_session_rwunlock(other_session); - - end: - - switch_channel_clear_state_handler(channel, &t38_gateway_state_handlers); - switch_channel_set_variable(channel, "t38_peer", NULL); - - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t t38_gateway_on_consume_media(switch_core_session_t *session) -{ - switch_core_session_t *other_session; - switch_channel_t *other_channel, *channel = switch_core_session_get_channel(session); - const char *peer_uuid = switch_channel_get_variable(channel, "t38_peer"); - pvt_t *pvt = NULL; - switch_codec_t read_codec = { 0 }; - switch_codec_t write_codec = { 0 }; - switch_frame_t *read_frame = { 0 }; - switch_frame_t write_frame = { 0 }; - switch_codec_implementation_t read_impl = { 0 }; - int16_t *buf = NULL; - switch_status_t status; - switch_size_t tx; - const char *t38_trace = switch_channel_get_variable(channel, "t38_trace"); - char *trace_read, *trace_write; - zap_socket_t read_fd = FAX_INVALID_SOCKET, write_fd = FAX_INVALID_SOCKET; - switch_core_session_message_t msg = { 0 }; - switch_event_t *event; - - switch_core_session_get_read_impl(session, &read_impl); - - buf = switch_core_session_alloc(session, SWITCH_RECOMMENDED_BUFFER_SIZE); - - if (!(other_session = switch_core_session_locate(peer_uuid))) { - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - goto end; - } - - other_channel = switch_core_session_get_channel(other_session); - - msg.message_id = SWITCH_MESSAGE_INDICATE_BRIDGE; - msg.from = __FILE__; - msg.string_arg = peer_uuid; - switch_core_session_receive_message(session, &msg); - - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_BRIDGE) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(channel, event); - switch_event_fire(&event); - } - - while (switch_channel_ready(channel) && switch_channel_up(other_channel) && !switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) { - status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); - - if (!SWITCH_READ_ACCEPTABLE(status)) { - /* Our duty is over */ - goto end_unlock; - } - - if (switch_test_flag(read_frame, SFF_CNG)) { - continue; - } - - if (switch_core_session_write_frame(other_session, read_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { - goto end_unlock; - } - } - - if (!(switch_channel_ready(channel) && switch_channel_up(other_channel))) { - goto end_unlock; - } - - if (!switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) { - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - goto end_unlock; - } - - if (!(pvt = switch_channel_get_private(other_channel, "_t38_pvt"))) { - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - goto end_unlock; - } - - if (switch_core_codec_init(&read_codec, - "L16", - NULL, - read_impl.samples_per_second, - read_impl.microseconds_per_packet / 1000, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw read codec activation Success L16 %u\n", - read_codec.implementation->microseconds_per_packet); - switch_core_session_set_read_codec(session, &read_codec); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Raw read codec activation Failed L16\n"); - goto end_unlock; - } - - if (switch_core_codec_init(&write_codec, - "L16", - NULL, - read_impl.samples_per_second, - read_impl.microseconds_per_packet / 1000, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw write codec activation Success L16\n"); - write_frame.codec = &write_codec; - write_frame.data = buf; - write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Raw write codec activation Failed L16\n"); - goto end_unlock; - } - - switch_ivr_sleep(session, 0, SWITCH_TRUE, NULL); - - if (switch_true(t38_trace)) { - trace_read = switch_core_session_sprintf(session, "%s%s%s_read.raw", SWITCH_GLOBAL_dirs.temp_dir, - SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session)); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Tracing inbound audio to %s\n", trace_read); - switch_channel_set_variable(channel, "t38_trace_read", trace_read); - - trace_write = switch_core_session_sprintf(session, "%s%s%s_write.raw", SWITCH_GLOBAL_dirs.temp_dir, - SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session)); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Tracing outbound audio to %s\n", trace_write); - switch_channel_set_variable(channel, "t38_trace_read", trace_write); - - - if ((write_fd = open(trace_read, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) != FAX_INVALID_SOCKET) { - if ((read_fd = open(trace_write, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == FAX_INVALID_SOCKET) { - close(write_fd); - write_fd = FAX_INVALID_SOCKET; - } - } - } - - while (switch_channel_ready(channel) && switch_channel_up(other_channel)) { - status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); - - if (!SWITCH_READ_ACCEPTABLE(status) || pvt->done) { - /* Our duty is over */ - goto end_unlock; - } - - - /* Skip CNG frames (auto-generated by FreeSWITCH, usually) */ - if (!switch_test_flag(read_frame, SFF_CNG)) { - - if (read_fd != FAX_INVALID_SOCKET) { - int w = write(read_fd, read_frame->data, read_frame->datalen); - if (w <= 0) { - close(read_fd); - read_fd = FAX_INVALID_SOCKET; - } - } - if (t38_gateway_rx(pvt->t38_gateway_state, (int16_t *) read_frame->data, read_frame->samples)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "fax_rx reported an error\n"); - goto end_unlock; - } - } - - if ((tx = t38_gateway_tx(pvt->t38_gateway_state, buf, write_codec.implementation->samples_per_packet)) < 0) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "fax_tx reported an error\n"); - goto end_unlock; - } - - if (!tx) { - /* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No audio samples to send\n"); */ - continue; - } else { - /* Set our write_frame data */ - write_frame.datalen = tx * sizeof(int16_t); - write_frame.samples = tx; - } - - if (write_fd != FAX_INVALID_SOCKET) { - int w = write(write_fd, write_frame.data, write_frame.datalen); - if (w <= 0) { - close(write_fd); - write_fd = FAX_INVALID_SOCKET; - } - } - - if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { - goto end_unlock; - } - } - - end_unlock: - - msg.message_id = SWITCH_MESSAGE_INDICATE_UNBRIDGE; - msg.from = __FILE__; - msg.string_arg = peer_uuid; - switch_core_session_receive_message(session, &msg); - - - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(channel, event); - switch_event_fire(&event); - } - - if (read_fd != FAX_INVALID_SOCKET) { - close(read_fd); - read_fd = FAX_INVALID_SOCKET; - } - - if (write_fd != FAX_INVALID_SOCKET) { - close(write_fd); - write_fd = FAX_INVALID_SOCKET; - } - - - switch_channel_hangup(other_channel, SWITCH_CAUSE_NORMAL_CLEARING); - switch_core_session_rwunlock(other_session); - - switch_core_session_set_read_codec(session, NULL); - - if (switch_core_codec_ready(&read_codec)) { - switch_core_codec_destroy(&read_codec); - } - - if (switch_core_codec_ready(&write_codec)) { - switch_core_codec_destroy(&write_codec); - } - - - end: - - switch_channel_clear_state_handler(channel, &t38_gateway_state_handlers); - switch_channel_set_variable(channel, "t38_peer", NULL); - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t t38_gateway_on_reset(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - - switch_channel_set_variable(channel, "rtp_autoflush_during_bridge", "false"); - - switch_channel_clear_flag(channel, CF_REDIRECT); - - if (switch_channel_test_app_flag(channel, CF_APP_TAGGED)) { - switch_channel_clear_app_flag(channel, CF_APP_TAGGED); - switch_channel_set_state(channel, CS_CONSUME_MEDIA); - } else { - switch_channel_set_state(channel, CS_SOFT_EXECUTE); - } - - return SWITCH_STATUS_SUCCESS; -} - -static const switch_state_handler_table_t t38_gateway_state_handlers = { - /*.on_init */ NULL, - /*.on_routing */ NULL, - /*.on_execute */ NULL, - /*.on_hangup */ NULL, - /*.on_exchange_media */ NULL, - /*.on_soft_execute */ t38_gateway_on_soft_execute, - /*.on_consume_media */ t38_gateway_on_consume_media, - /*.on_hibernate */ NULL, - /*.on_reset */ t38_gateway_on_reset, - /*.on_park */ NULL, - /*.on_reporting */ NULL, - /*.on_destroy */ NULL, - SSH_FLAG_STICKY -}; - -static switch_bool_t t38_gateway_start(switch_core_session_t *session, const char *app, const char *data) -{ - switch_channel_t *other_channel = NULL, *channel = switch_core_session_get_channel(session); - switch_core_session_t *other_session = NULL; - int peer = app && !strcasecmp(app, "peer"); - - if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) { - other_channel = switch_core_session_get_channel(other_session); - - switch_channel_set_variable(channel, "t38_peer", switch_core_session_get_uuid(other_session)); - switch_channel_set_variable(other_channel, "t38_peer", switch_core_session_get_uuid(session)); - - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s starting gateway mode to %s\n", - switch_channel_get_name(peer ? channel : other_channel), - switch_channel_get_name(peer ? other_channel : channel)); - - - switch_channel_clear_state_handler(channel, NULL); - switch_channel_clear_state_handler(other_channel, NULL); - - switch_channel_add_state_handler(channel, &t38_gateway_state_handlers); - switch_channel_add_state_handler(other_channel, &t38_gateway_state_handlers); - - switch_channel_set_app_flag(peer ? channel : other_channel, CF_APP_TAGGED); - switch_channel_clear_app_flag(peer ? other_channel : channel, CF_APP_TAGGED); - - switch_channel_set_flag(channel, CF_REDIRECT); - switch_channel_set_state(channel, CS_RESET); - - switch_channel_set_flag(other_channel, CF_REDIRECT); - switch_channel_set_state(other_channel, CS_RESET); - - switch_core_session_rwunlock(other_session); - - } - - return SWITCH_FALSE; -} - - -SWITCH_STANDARD_APP(t38_gateway_function) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - time_t timeout = switch_epoch_time_now(NULL) + 20; - const char *var; - - if (zstr(data) || strcasecmp(data, "self")) { - data = "peer"; - } - - switch_channel_set_variable(channel, "t38_leg", data); - - if ((var = switch_channel_get_variable(channel, "t38_gateway_detect_timeout"))) { - long to = atol(var); - if (to > -1) { - timeout = (time_t) (switch_epoch_time_now(NULL) + to); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s invalid timeout value.\n", switch_channel_get_name(channel)); - } - } - - switch_ivr_tone_detect_session(session, "t38", "1100.0", "rw", timeout, 1, data, NULL, t38_gateway_start); -} - - -SWITCH_MODULE_LOAD_FUNCTION(mod_fax_init) -{ - switch_application_interface_t *app_interface; - - *module_interface = switch_loadable_module_create_module_interface(pool, modname); - - SWITCH_ADD_APP(app_interface, "t38_gateway", "Convert to T38 Gateway if tones are heard", "Convert to T38 Gateway if tones are heard", - t38_gateway_function, "", SAF_MEDIA_TAP); - - SWITCH_ADD_APP(app_interface, "rxfax", "FAX Receive Application", "FAX Receive Application", spanfax_rx_function, SPANFAX_RX_USAGE, - SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "txfax", "FAX Transmit Application", "FAX Transmit Application", spanfax_tx_function, SPANFAX_TX_USAGE, - SAF_SUPPORT_NOMEDIA); - - SWITCH_ADD_APP(app_interface, "spandsp_stop_dtmf", "stop inband dtmf", "Stop detecting inband dtmf.", stop_dtmf_session_function, "", SAF_NONE); - SWITCH_ADD_APP(app_interface, "spandsp_start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_MEDIA_TAP); - - memset(&globals, 0, sizeof(globals)); - memset(&t38_state_list, 0, sizeof(t38_state_list)); - switch_core_new_memory_pool(&globals.pool); - switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool); - switch_mutex_init(&t38_state_list.mutex, SWITCH_MUTEX_NESTED, globals.pool); - - globals.enable_t38 = 1; - globals.total_sessions = 0; - globals.verbose = 1; - globals.use_ecm = 1; - globals.disable_v17 = 0; - globals.prepend_string = switch_core_strdup(globals.pool, "fax"); - globals.spool = switch_core_strdup(globals.pool, "/tmp"); - strncpy(globals.ident, "SpanDSP Fax Ident", sizeof(globals.ident) - 1); - strncpy(globals.header, "SpanDSP Fax Header", sizeof(globals.header) - 1); - - load_configuration(0); - - if ((switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL, &NODE) != SWITCH_STATUS_SUCCESS)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our reloadxml handler!\n"); - /* Not such severe to prevent loading */ - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "mod_fax loaded, using spandsp library version [%s]\n", SPANDSP_RELEASE_DATETIME_STRING); - - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fax_shutdown) -{ - switch_memory_pool_t *pool = globals.pool; - - switch_event_unbind(&NODE); - - switch_core_destroy_memory_pool(&pool); - memset(&globals, 0, sizeof(globals)); - - return SWITCH_STATUS_UNLOAD; -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:nil - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: - */ diff --git a/src/mod/applications/mod_fax/udptl.c b/src/mod/applications/mod_fax/udptl.c deleted file mode 100644 index a2651513f0..0000000000 --- a/src/mod/applications/mod_fax/udptl.c +++ /dev/null @@ -1,563 +0,0 @@ -//#define UDPTL_DEBUG -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2009, Steve Underwood - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * Contributor(s): - * - * Steve Underwood - * - * udptl.c -- UDPTL handling for T.38 - * - */ - -#include -#include -#include -#include -#include - -#include "udptl.h" - -#define FALSE 0 -#define TRUE (!FALSE) - -static int decode_length(const uint8_t *buf, int limit, int *len, int *pvalue) -{ - if (*len >= limit) - return -1; - if ((buf[*len] & 0x80) == 0) { - *pvalue = buf[(*len)++]; - return 0; - } - if ((buf[*len] & 0x40) == 0) { - if (*len >= limit - 1) - return -1; - *pvalue = (buf[(*len)++] & 0x3F) << 8; - *pvalue |= buf[(*len)++]; - return 0; - } - *pvalue = (buf[(*len)++] & 0x3F) << 14; - /* Indicate we have a fragment */ - return 1; -} - -/*- End of function --------------------------------------------------------*/ - -static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8_t ** p_object, int *p_num_octets) -{ - int octet_cnt; - int octet_idx; - int stat; - int i; - const uint8_t **pbuf; - - for (octet_idx = 0, *p_num_octets = 0;; octet_idx += octet_cnt) { - if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0) - return -1; - if (octet_cnt > 0) { - *p_num_octets += octet_cnt; - - pbuf = &p_object[octet_idx]; - i = 0; - /* Make sure the buffer contains at least the number of bits requested */ - if ((*len + octet_cnt) > limit) - return -1; - - *pbuf = &buf[*len]; - *len += octet_cnt; - } - if (stat == 0) - break; - } - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -static int encode_length(uint8_t *buf, int *len, int value) -{ - int multiplier; - - if (value < 0x80) { - /* 1 octet */ - buf[(*len)++] = value; - return value; - } - if (value < 0x4000) { - /* 2 octets */ - /* Set the first bit of the first octet */ - buf[(*len)++] = ((0x8000 | value) >> 8) & 0xFF; - buf[(*len)++] = value & 0xFF; - return value; - } - /* Fragmentation */ - multiplier = (value < 0x10000) ? (value >> 14) : 4; - /* Set the first 2 bits of the octet */ - buf[(*len)++] = 0xC0 | multiplier; - return multiplier << 14; -} - -/*- End of function --------------------------------------------------------*/ - -static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num_octets) -{ - int enclen; - int octet_idx; - uint8_t zero_byte; - - /* If open type is of zero length, add a single zero byte (10.1) */ - if (num_octets == 0) { - zero_byte = 0; - data = &zero_byte; - num_octets = 1; - } - /* Encode the open type */ - for (octet_idx = 0;; num_octets -= enclen, octet_idx += enclen) { - if ((enclen = encode_length(buf, len, num_octets)) < 0) - return -1; - if (enclen > 0) { - memcpy(&buf[*len], &data[octet_idx], enclen); - *len += enclen; - } - if (enclen >= num_octets) - break; - } - - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len) -{ - int stat; - int stat2; - int i; - int j; - int k; - int l; - int m; - int x; - int limit; - int which; - int ptr; - int count; - int total_count; - int seq_no; - const uint8_t *msg; - const uint8_t *data; - int msg_len; - int repaired[16]; - const uint8_t *bufs[16]; - int lengths[16]; - int span; - int entries; - - ptr = 0; - /* Decode seq_number */ - if (ptr + 2 > len) - return -1; - seq_no = (buf[0] << 8) | buf[1]; - ptr += 2; - /* Break out the primary packet */ - if ((stat = decode_open_type(buf, len, &ptr, &msg, &msg_len)) != 0) - return -1; - /* Decode error_recovery */ - if (ptr + 1 > len) - return -1; - /* Our buffers cannot tolerate overlength packets */ - if (msg_len > LOCAL_FAX_MAX_DATAGRAM) - return -1; - /* Update any missed slots in the buffer */ - for (i = s->rx_seq_no; seq_no > i; i++) { - x = i & UDPTL_BUF_MASK; - s->rx[x].buf_len = -1; - s->rx[x].fec_len[0] = 0; - s->rx[x].fec_span = 0; - s->rx[x].fec_entries = 0; - } - /* Save the new packet. Pure redundancy mode won't use this, but some systems will switch - into FEC mode after sending some redundant packets. */ - x = seq_no & UDPTL_BUF_MASK; - memcpy(s->rx[x].buf, msg, msg_len); - s->rx[x].buf_len = msg_len; - s->rx[x].fec_len[0] = 0; - s->rx[x].fec_span = 0; - s->rx[x].fec_entries = 0; - if ((buf[ptr++] & 0x80) == 0) { - /* Secondary packet mode for error recovery */ - /* We might have the packet we want, but we need to check through - the redundant stuff, and verify the integrity of the UDPTL. - This greatly reduces our chances of accepting garbage. */ - total_count = 0; - do { - if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0) - return -1; - for (i = 0; i < count; i++) { - if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0) - return -1; - } - total_count += count; - } - while (stat2 > 0); - /* We should now be exactly at the end of the packet. If not, this is a fault. */ - if (ptr != len) - return -1; - if (seq_no > s->rx_seq_no) { - /* We received a later packet than we expected, so we need to check if we can fill in the gap from the - secondary packets. */ - /* Step through in reverse order, so we go oldest to newest */ - for (i = total_count; i > 0; i--) { - if (seq_no - i >= s->rx_seq_no) { - /* This one wasn't seen before */ - /* Decode the secondary packet */ -#if defined(UDPTL_DEBUG) - fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]); -#endif - /* Save the new packet. Redundancy mode won't use this, but some systems will switch into - FEC mode after sending some redundant packets, and this may then be important. */ - x = (seq_no - i) & UDPTL_BUF_MASK; - memcpy(s->rx[x].buf, bufs[i - 1], lengths[i - 1]); - s->rx[x].buf_len = lengths[i - 1]; - s->rx[x].fec_len[0] = 0; - s->rx[x].fec_span = 0; - s->rx[x].fec_entries = 0; - if (s->rx_packet_handler(s->user_data, bufs[i - 1], lengths[i - 1], seq_no - i) < 0) - fprintf(stderr, "Bad IFP\n"); - } - } - } - } else { - /* FEC mode for error recovery */ - - /* Decode the FEC packets */ - /* The span is defined as an unconstrained integer, but will never be more - than a small value. */ - if (ptr + 2 > len) - return -1; - if (buf[ptr++] != 1) - return -1; - span = buf[ptr++]; - - x = seq_no & UDPTL_BUF_MASK; - - s->rx[x].fec_span = span; - - memset(repaired, 0, sizeof(repaired)); - repaired[x] = TRUE; - - /* The number of entries is defined as a length, but will only ever be a small - value. Treat it as such. */ - if (ptr + 1 > len) - return -1; - entries = buf[ptr++]; - s->rx[x].fec_entries = entries; - - /* Decode the elements */ - for (i = 0; i < entries; i++) { - if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0) - return -1; - if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM) - return -1; - - /* Save the new FEC data */ - memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]); -#if 0 - fprintf(stderr, "FEC: "); - for (j = 0; j < s->rx[x].fec_len[i]; j++) - fprintf(stderr, "%02X ", data[j]); - fprintf(stderr, "\n"); -#endif - } - /* We should now be exactly at the end of the packet. If not, this is a fault. */ - if (ptr != len) - return -1; - /* See if we can reconstruct anything which is missing */ - /* TODO: this does not comprehensively hunt back and repair everything that is possible */ - for (l = x; l != ((x - (16 - span * entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) { - if (s->rx[l].fec_len[0] <= 0) - continue; - for (m = 0; m < s->rx[l].fec_entries; m++) { - limit = (l + m) & UDPTL_BUF_MASK; - for (which = -1, k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; - k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) { - if (s->rx[k].buf_len <= 0) - which = (which == -1) ? k : -2; - } - if (which >= 0) { - /* Repairable */ - for (j = 0; j < s->rx[l].fec_len[m]; j++) { - s->rx[which].buf[j] = s->rx[l].fec[m][j]; - for (k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; - k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) - s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0; - } - s->rx[which].buf_len = s->rx[l].fec_len[m]; - repaired[which] = TRUE; - } - } - } - /* Now play any new packets forwards in time */ - for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) { - if (repaired[l]) { -#if defined(UDPTL_DEBUG) - fprintf(stderr, "Fixed packet %d, len %d\n", j, l); -#endif - if (s->rx_packet_handler(s->user_data, s->rx[l].buf, s->rx[l].buf_len, j) < 0) - fprintf(stderr, "Bad IFP\n"); - } - } - } - /* If packets are received out of sequence, we may have already processed this packet from the error - recovery information in a packet already received. */ - if (seq_no >= s->rx_seq_no) { - /* Decode the primary packet */ -#if defined(UDPTL_DEBUG) - fprintf(stderr, "Primary packet %d, len %d\n", seq_no, msg_len); -#endif - if (s->rx_packet_handler(s->user_data, msg, msg_len, seq_no) < 0) - fprintf(stderr, "Bad IFP\n"); - } - - s->rx_seq_no = (seq_no + 1) & 0xFFFF; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int msg_len) -{ - uint8_t fec[LOCAL_FAX_MAX_DATAGRAM]; - int i; - int j; - int seq; - int entry; - int entries; - int span; - int m; - int len; - int limit; - int high_tide; - - /* UDPTL cannot cope with zero length messages, and our buffering for redundancy limits their - maximum length. */ - if (msg_len < 1 || msg_len > LOCAL_FAX_MAX_DATAGRAM) - return -1; - seq = s->tx_seq_no & 0xFFFF; - - /* Map the sequence number to an entry in the circular buffer */ - entry = seq & UDPTL_BUF_MASK; - - /* We save the message in a circular buffer, for generating FEC or - redundancy sets later on. */ - s->tx[entry].buf_len = msg_len; - memcpy(s->tx[entry].buf, msg, msg_len); - - /* Build the UDPTL packet */ - - len = 0; - /* Encode the sequence number */ - buf[len++] = (seq >> 8) & 0xFF; - buf[len++] = seq & 0xFF; - - /* Encode the primary packet */ - if (encode_open_type(buf, &len, msg, msg_len) < 0) - return -1; - - /* Encode the appropriate type of error recovery information */ - switch (s->error_correction_scheme) { - case UDPTL_ERROR_CORRECTION_NONE: - /* Encode the error recovery type */ - buf[len++] = 0x00; - /* The number of entries will always be zero, so it is pointless allowing - for the fragmented case here. */ - if (encode_length(buf, &len, 0) < 0) - return -1; - break; - case UDPTL_ERROR_CORRECTION_REDUNDANCY: - /* Encode the error recovery type */ - buf[len++] = 0x00; - if (s->tx_seq_no > s->error_correction_entries) - entries = s->error_correction_entries; - else - entries = s->tx_seq_no; - /* The number of entries will always be small, so it is pointless allowing - for the fragmented case here. */ - if (encode_length(buf, &len, entries) < 0) - return -1; - /* Encode the elements */ - for (i = 0; i < entries; i++) { - j = (entry - i - 1) & UDPTL_BUF_MASK; - if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0) - return -1; - } - break; - case UDPTL_ERROR_CORRECTION_FEC: - span = s->error_correction_span; - entries = s->error_correction_entries; - if (seq < s->error_correction_span * s->error_correction_entries) { - /* In the initial stages, wind up the FEC smoothly */ - entries = seq / s->error_correction_span; - if (seq < s->error_correction_span) - span = 0; - } - /* Encode the error recovery type */ - buf[len++] = 0x80; - /* Span is defined as an inconstrained integer, which it dumb. It will only - ever be a small value. Treat it as such. */ - buf[len++] = 1; - buf[len++] = span; - /* The number of entries is defined as a length, but will only ever be a small - value. Treat it as such. */ - buf[len++] = entries; - for (m = 0; m < entries; m++) { - /* Make an XOR'ed entry the maximum length */ - limit = (entry + m) & UDPTL_BUF_MASK; - high_tide = 0; - for (i = (limit - span * entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) { - if (high_tide < s->tx[i].buf_len) { - for (j = 0; j < high_tide; j++) - fec[j] ^= s->tx[i].buf[j]; - for (; j < s->tx[i].buf_len; j++) - fec[j] = s->tx[i].buf[j]; - high_tide = s->tx[i].buf_len; - } else { - for (j = 0; j < s->tx[i].buf_len; j++) - fec[j] ^= s->tx[i].buf[j]; - } - } - if (encode_open_type(buf, &len, fec, high_tide) < 0) - return -1; - } - break; - } - - if (s->verbose) - fprintf(stderr, "\n"); - s->tx_seq_no++; - return len; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_set_error_correction(udptl_state_t *s, int ec_scheme, int span, int entries) -{ - switch (ec_scheme) { - case UDPTL_ERROR_CORRECTION_FEC: - case UDPTL_ERROR_CORRECTION_REDUNDANCY: - case UDPTL_ERROR_CORRECTION_NONE: - s->error_correction_scheme = ec_scheme; - break; - case -1: - /* Just don't change the scheme */ - break; - default: - return -1; - } - if (span >= 0) - s->error_correction_span = span; - if (entries >= 0) - s->error_correction_entries = entries; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_get_error_correction(udptl_state_t *s, int *ec_scheme, int *span, int *entries) -{ - if (ec_scheme) - *ec_scheme = s->error_correction_scheme; - if (span) - *span = s->error_correction_span; - if (entries) - *entries = s->error_correction_entries; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_set_local_max_datagram(udptl_state_t *s, int max_datagram) -{ - s->local_max_datagram_size = max_datagram; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_get_local_max_datagram(udptl_state_t *s) -{ - return s->local_max_datagram_size; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_set_far_max_datagram(udptl_state_t *s, int max_datagram) -{ - s->far_max_datagram_size = max_datagram; - return 0; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_get_far_max_datagram(udptl_state_t *s) -{ - return s->far_max_datagram_size; -} - -/*- End of function --------------------------------------------------------*/ - -udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries, udptl_rx_packet_handler_t rx_packet_handler, void *user_data) -{ - int i; - - if (rx_packet_handler == NULL) - return NULL; - - if (s == NULL) { - if ((s = (udptl_state_t *) malloc(sizeof(*s))) == NULL) - return NULL; - } - memset(s, 0, sizeof(*s)); - - s->error_correction_scheme = ec_scheme; - s->error_correction_span = span; - s->error_correction_entries = entries; - - s->far_max_datagram_size = LOCAL_FAX_MAX_DATAGRAM; - s->local_max_datagram_size = LOCAL_FAX_MAX_DATAGRAM; - - memset(&s->rx, 0, sizeof(s->rx)); - memset(&s->tx, 0, sizeof(s->tx)); - for (i = 0; i <= UDPTL_BUF_MASK; i++) { - s->rx[i].buf_len = -1; - s->tx[i].buf_len = -1; - } - - s->rx_packet_handler = rx_packet_handler; - s->user_data = user_data; - - return s; -} - -/*- End of function --------------------------------------------------------*/ - -int udptl_release(udptl_state_t *s) -{ - return 0; -} - -/*- End of function --------------------------------------------------------*/ -/*- End of file ------------------------------------------------------------*/ diff --git a/src/mod/applications/mod_fax/udptl.h b/src/mod/applications/mod_fax/udptl.h deleted file mode 100644 index 39740353d1..0000000000 --- a/src/mod/applications/mod_fax/udptl.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2009, Steve Underwood - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * Contributor(s): - * - * Steve Underwood - * - * udptl.h -- UDPTL handling for T.38 - * - */ - -#if !defined(FREESWITCH_UDPTL_H) -#define FREESWITCH_UDPTL_H - -#define LOCAL_FAX_MAX_DATAGRAM 400 -#define LOCAL_FAX_MAX_FEC_PACKETS 5 - -#define UDPTL_BUF_MASK 15 - -typedef int (udptl_rx_packet_handler_t) (void *user_data, const uint8_t msg[], int len, int seq_no); - -typedef struct { - int buf_len; - uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]; -} udptl_fec_tx_buffer_t; - -typedef struct { - int buf_len; - uint8_t buf[LOCAL_FAX_MAX_DATAGRAM]; - int fec_len[LOCAL_FAX_MAX_FEC_PACKETS]; - uint8_t fec[LOCAL_FAX_MAX_FEC_PACKETS][LOCAL_FAX_MAX_DATAGRAM]; - int fec_span; - int fec_entries; -} udptl_fec_rx_buffer_t; - -struct udptl_state_s { - udptl_rx_packet_handler_t *rx_packet_handler; - void *user_data; - - /*! This option indicates the error correction scheme used in transmitted UDPTL - packets. */ - int error_correction_scheme; - - /*! This option indicates the number of error correction entries transmitted in - UDPTL packets. */ - int error_correction_entries; - - /*! This option indicates the span of the error correction entries in transmitted - UDPTL packets (FEC only). */ - int error_correction_span; - - /*! This option indicates the maximum size of a datagram that can be accepted by - the remote device. */ - int far_max_datagram_size; - - /*! This option indicates the maximum size of a datagram that we are prepared to - accept. */ - int local_max_datagram_size; - - int verbose; - - int tx_seq_no; - int rx_seq_no; - int rx_expected_seq_no; - - udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1]; - udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1]; -}; - -enum { - UDPTL_ERROR_CORRECTION_NONE, - UDPTL_ERROR_CORRECTION_FEC, - UDPTL_ERROR_CORRECTION_REDUNDANCY -}; - -typedef struct udptl_state_s udptl_state_t; - -#if defined(__cplusplus) -extern "C" { -#endif - -/*! \brief Process an arriving UDPTL packet. - \param s The UDPTL context. - \param buf The UDPTL packet buffer. - \param len The length of the packet. - \return 0 for OK. */ - int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len); - -/*! \brief Construct a UDPTL packet, ready for transmission. - \param s The UDPTL context. - \param buf The UDPTL packet buffer. - \param msg The primary packet. - \param len The length of the primary packet. - \return The length of the constructed UDPTL packet. */ - int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int msg_len); - -/*! \brief Change the error correction settings of a UDPTL context. - \param s The UDPTL context. - \param ec_scheme One of the optional error correction schemes. - \param span The packet span over which error correction should be applied. - \param entries The number of error correction entries to include in packets. - \return 0 for OK. */ - int udptl_set_error_correction(udptl_state_t *s, int ec_scheme, int span, int entries); - -/*! \brief Check the error correction settings of a UDPTL context. - \param s The UDPTL context. - \param ec_scheme One of the optional error correction schemes. - \param span The packet span over which error correction is being applied. - \param entries The number of error correction being included in packets. - \return 0 for OK. */ - int udptl_get_error_correction(udptl_state_t *s, int *ec_scheme, int *span, int *entries); - - int udptl_set_local_max_datagram(udptl_state_t *s, int max_datagram); - - int udptl_get_local_max_datagram(udptl_state_t *s); - - int udptl_set_far_max_datagram(udptl_state_t *s, int max_datagram); - - int udptl_get_far_max_datagram(udptl_state_t *s); - -/*! \brief Initialise a UDPTL context. - \param s The UDPTL context. - \param ec_scheme One of the optional error correction schemes. - \param span The packet span over which error correction should be applied. - \param entries The number of error correction entries to include in packets. - \param rx_packet_handler The callback function, used to report arriving IFP packets. - \param user_data An opaque pointer supplied to rx_packet_handler. - \return A pointer to the UDPTL context, or NULL if there was a problem. */ - udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries, udptl_rx_packet_handler_t rx_packet_handler, void *user_data); - -/*! \brief Release a UDPTL context. - \param s The UDPTL context. - \return 0 for OK. */ - int udptl_release(udptl_state_t *s); - -#if defined(__cplusplus) -} -#endif -#endif -/*- End of file ------------------------------------------------------------*/ From 693e04a7dedf6dbae14fd65ecfbaf77bb96879f6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 31 May 2012 09:04:08 -0500 Subject: [PATCH 019/101] FS-4250 please post a new log if this does not work --- src/mod/endpoints/mod_sofia/mod_sofia.c | 2 ++ src/mod/endpoints/mod_sofia/sofia.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 2b44018665..6d28bc01f9 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1587,6 +1587,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi case SWITCH_MESSAGE_INDICATE_BRIDGE: { + + switch_channel_set_variable(channel, SOFIA_REPLACES_HEADER, NULL); sofia_glue_tech_track(tech_pvt->profile, session); sofia_set_flag(tech_pvt, TFLAG_SIMPLIFY); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index dc4fcfb0f0..281aa511da 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -6797,6 +6797,9 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_EXPIRES_STR("60"), TAG_END()); + + switch_channel_set_variable(tech_pvt->channel, SOFIA_REPLACES_HEADER, NULL); + if (sip->sip_referred_by) { full_ref_by = sip_header_as_string(home, (void *) sip->sip_referred_by); } From 24f6c4056b1bfec94020eeb9611b3fcb0f4f72b4 Mon Sep 17 00:00:00 2001 From: Ken Rice Date: Thu, 31 May 2012 11:25:28 -0500 Subject: [PATCH 020/101] missed a spot removing mod_fax --- configure.in | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.in b/configure.in index 5dbe6d9e12..83cb4144eb 100644 --- a/configure.in +++ b/configure.in @@ -993,7 +993,6 @@ AC_CONFIG_FILES([Makefile src/Makefile src/mod/Makefile src/mod/applications/mod_expr/Makefile - src/mod/applications/mod_fax/Makefile src/mod/applications/mod_spandsp/Makefile src/mod/applications/mod_osp/Makefile src/mod/applications/mod_stress/Makefile From afeb7f327c88ab166f656ce59839ed18e61eb1c6 Mon Sep 17 00:00:00 2001 From: Brian West Date: Thu, 31 May 2012 14:18:58 -0500 Subject: [PATCH 021/101] OpenCNAM frontend so you can feed it 10 or 11 digits and cache the results. --- scripts/perl/cnam.cgi | 63 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100755 scripts/perl/cnam.cgi diff --git a/scripts/perl/cnam.cgi b/scripts/perl/cnam.cgi new file mode 100755 index 0000000000..d7acaa9b49 --- /dev/null +++ b/scripts/perl/cnam.cgi @@ -0,0 +1,63 @@ +#!/usr/bin/perl +# +# OpenCNAM front end because they only take 10 digits and can't filter 11 on their side. +# + +use Data::Dumper; +use CGI qw/:standard/; +use LWP::UserAgent; +use SDBM_File; +use Fcntl; + +my %params = map { $_ => get_data( $_ ) } param; + +$ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 }); + +sub get_data { + my $name = shift; + my @values = param( $name ); + return @values > 1 + ? \@values + : $values[0]; +} + +print "Content-Type: text/plain\n\n"; + +tie (my %cache, 'SDBM_File', 'cnam.dbm', O_RDWR|O_CREAT, 0640) || die $!; + +my $number = $params{number}; + + +if($number =~ m/1?\d{10}/) { + + + if($number =~ m/^1(\d{10})$/) { + $number = $1; + } + + if($cache{"$number"}) { + print $cache{"$number"}; + untie %cache; + exit; + } + + my $url = "https://api.opencnam.com/v1/phone/$number?format=text"; + + + my $res = $ua->get( $url ); + + if ($res->is_success) { + my $content = $res->decoded_content; + if ($content =~ m/^Invalid/) { + # API shouldn't return this crap. + print "UNKNOWN"; + } else { + # Cache the entry. + $cache{"$number"} = $content; + # print the entry. + print $content; + } + } +} + +untie %cache; From 5165e4071ee4d32c3990e681417caae6b7408efa Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Thu, 31 May 2012 23:59:45 +0200 Subject: [PATCH 022/101] FreeSWITCH: Remove -arch i386/x86_64 from PYTHON_CFLAGS Speculative fix for a mod_python build issue on OSX, which is caused by '-arch i386 -arch x86_64' in the final PYTHON_CFLAGS. Filter both flags and hope OSX's universal binary toolchain is smart enough to choose a sane default. Reported-by: neilp9 in #freeswitch @ irc.freenode.net Signed-off-by: Stefan Knoblich --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 83cb4144eb..d609c4eef5 100644 --- a/configure.in +++ b/configure.in @@ -925,7 +925,7 @@ then # # python distutils found, get settings from python directly # - PYTHON_CFLAGS="`$PYTHON -c 'from distutils import sysconfig; flags = [[\"-I\" + sysconfig.get_python_inc(0), \"-I\" + sysconfig.get_python_inc(1), \" \".join(sysconfig.get_config_var(\"CFLAGS\").split())]]; print(\" \".join(flags));'`" + PYTHON_CFLAGS="`$PYTHON -c 'from distutils import sysconfig; flags = [[\"-I\" + sysconfig.get_python_inc(0), \"-I\" + sysconfig.get_python_inc(1), \" \".join(sysconfig.get_config_var(\"CFLAGS\").split())]]; print(\" \".join(flags));' | sed -e 's:-arch \(i386\|x86_64\)\+::g'`" PYTHON_LDFLAGS="`$PYTHON -c 'from distutils import sysconfig; libs = sysconfig.get_config_var(\"LIBS\").split() + sysconfig.get_config_var(\"SYSLIBS\").split(); libs.append(\"-lpython\"+sysconfig.get_config_var(\"VERSION\")); print(\" \".join(libs));'`" PYTHON_LIB="`$PYTHON -c 'from distutils import sysconfig; print(\"python\" + sysconfig.get_config_var(\"VERSION\"));'`" PYTHON_LIBDIR="`$PYTHON -c 'from distutils import sysconfig; print(sysconfig.get_config_var(\"LIBDIR\"));'`" From ba4a210ced2922e0bb6be1a58eb2c27c9a0ed7ea Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Fri, 1 Jun 2012 00:24:43 +0200 Subject: [PATCH 023/101] FreeSWITCH: Fix copy&paste error in last commit Signed-off-by: Stefan Knoblich --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index d609c4eef5..f37ba4c8bc 100644 --- a/configure.in +++ b/configure.in @@ -925,7 +925,7 @@ then # # python distutils found, get settings from python directly # - PYTHON_CFLAGS="`$PYTHON -c 'from distutils import sysconfig; flags = [[\"-I\" + sysconfig.get_python_inc(0), \"-I\" + sysconfig.get_python_inc(1), \" \".join(sysconfig.get_config_var(\"CFLAGS\").split())]]; print(\" \".join(flags));' | sed -e 's:-arch \(i386\|x86_64\)\+::g'`" + PYTHON_CFLAGS="`$PYTHON -c 'from distutils import sysconfig; flags = [[\"-I\" + sysconfig.get_python_inc(0), \"-I\" + sysconfig.get_python_inc(1), \" \".join(sysconfig.get_config_var(\"CFLAGS\").split())]]; print(\" \".join(flags));' | sed -e 's:-arch \(i386\|x86_64\)::g'`" PYTHON_LDFLAGS="`$PYTHON -c 'from distutils import sysconfig; libs = sysconfig.get_config_var(\"LIBS\").split() + sysconfig.get_config_var(\"SYSLIBS\").split(); libs.append(\"-lpython\"+sysconfig.get_config_var(\"VERSION\")); print(\" \".join(libs));'`" PYTHON_LIB="`$PYTHON -c 'from distutils import sysconfig; print(\"python\" + sysconfig.get_config_var(\"VERSION\"));'`" PYTHON_LIBDIR="`$PYTHON -c 'from distutils import sysconfig; print(sysconfig.get_config_var(\"LIBDIR\"));'`" From b2d183099f23a70655bfee7f0ea33e1166b64e4a Mon Sep 17 00:00:00 2001 From: Marc Olivier Chouinard Date: Thu, 31 May 2012 23:36:37 -0400 Subject: [PATCH 024/101] mod_voicemail: Remove the Goodbye prompt when voicemail is disabled when trying to leave a message --- src/mod/applications/mod_voicemail/mod_voicemail.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 0bbea275d5..d3438aacfc 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -3489,7 +3489,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p switch_safe_free(file_path); - if (switch_channel_ready(channel)) { + if (switch_channel_ready(channel) && vm_enabled) { status = switch_ivr_phrase_macro(session, VM_GOODBYE_MACRO, NULL, NULL, NULL); } From f685e4c5049f92d76f55f272c2754c45ac7f4fb9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 1 Jun 2012 10:06:28 -0500 Subject: [PATCH 025/101] allow ep_codec_string to draw from absolute_codec_string before the profile prefs --- src/mod/endpoints/mod_sofia/sofia.c | 2 +- src/mod/endpoints/mod_sofia/sofia_glue.c | 26 ++++++++++++++---------- src/switch_ivr_originate.c | 6 ++++-- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 281aa511da..d865be6ee7 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5815,7 +5815,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, tech_pvt->remote_sdp_str = switch_core_session_strdup(session, r_sdp); switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp); - if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && (parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) { + if ((sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) && (parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) { if ((sdp = sdp_session(parser))) { sofia_glue_set_r_sdp_codec_string(session, sofia_glue_get_codec_string(tech_pvt), sdp); } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 2cb2fdd551..e96f1e1802 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -776,19 +776,23 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch const char *sofia_glue_get_codec_string(private_object_t *tech_pvt) { - const char *codec_string = NULL, *preferred = NULL, *fallback = NULL; - - if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { - preferred = tech_pvt->profile->outbound_codec_string; - fallback = tech_pvt->profile->inbound_codec_string; - } else { - preferred = tech_pvt->profile->inbound_codec_string; - fallback = tech_pvt->profile->outbound_codec_string; + const char *preferred = NULL, *fallback = NULL; + + if (!(preferred = switch_channel_get_variable(tech_pvt->channel, "absolute_codec_string"))) { + preferred = switch_channel_get_variable(tech_pvt->channel, "codec_string"); + } + + if (!preferred) { + if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + preferred = tech_pvt->profile->outbound_codec_string; + fallback = tech_pvt->profile->inbound_codec_string; + } else { + preferred = tech_pvt->profile->inbound_codec_string; + fallback = tech_pvt->profile->outbound_codec_string; + } } - codec_string = !zstr(preferred) ? preferred : fallback; - - return codec_string; + return !zstr(preferred) ? preferred : fallback; } void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt) diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index c18da450a6..72d0ab0393 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -384,8 +384,10 @@ static void inherit_codec(switch_channel_t *caller_channel, switch_core_session_ { const char *var = switch_channel_get_variable(caller_channel, "inherit_codec"); switch_channel_t *channel = switch_core_session_get_channel(session); - - if (switch_true(var)) { + + if (!zstr(var) && !strcasecmp(var, "passthru")) { + switch_channel_set_variable(caller_channel, "absolute_codec_string", switch_channel_get_variable(channel, "ep_codec_string")); + } else if (switch_true(var)) { switch_codec_implementation_t impl = { 0 }; switch_codec_implementation_t video_impl = { 0 }; char tmp[128] = ""; From 75aab0ee6cda0c63177fca2a99d313894d068438 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 1 Jun 2012 13:21:12 -0500 Subject: [PATCH 026/101] put presence data in state events --- src/switch_channel.c | 17 +++++++++++++++++ src/switch_core_sqldb.c | 14 ++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/switch_channel.c b/src/switch_channel.c index 138123f3eb..94c9a35cfe 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1928,6 +1928,8 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state( if (state == CS_ROUTING) { switch_channel_event_set_data(channel, event); } else { + const char *v; + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-State", switch_channel_state_name(state)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-State", switch_channel_callstate2str(channel->callstate)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-State-Number", "%d", state); @@ -1951,6 +1953,21 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state( } else { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "ringing"); } + + + if ((v = switch_channel_get_variable(channel, "presence_id"))) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Presence-ID", v); + } + + if ((v = switch_channel_get_variable(channel, "presence_data"))) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Presence-Data", v); + } + + if ((v = switch_channel_get_variable(channel, "presence_data_cols"))) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Presence-Data-Cols", v); + switch_event_add_presence_data_cols(channel, event, "PD-"); + } + } switch_event_fire(&event); } diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 9b40674065..eea6a4372d 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1407,6 +1407,20 @@ static void core_event_handler(switch_event_t *event) case CS_DESTROY: case CS_REPORTING: break; + case CS_EXECUTE: + if ((extra_cols = parse_presence_data_cols(event))) { + new_sql() = switch_mprintf("update channels set state='%s',%s where uuid='%q'", + switch_event_get_header_nil(event, "channel-state"), + extra_cols, + switch_event_get_header_nil(event, "unique-id")); + free(extra_cols); + + } else { + new_sql() = switch_mprintf("update channels set state='%s' where uuid='%s'", + switch_event_get_header_nil(event, "channel-state"), + switch_event_get_header_nil(event, "unique-id")); + } + break; case CS_ROUTING: if ((extra_cols = parse_presence_data_cols(event))) { new_sql() = switch_mprintf("update channels set state='%s',cid_name='%q',cid_num='%q',callee_name='%q',callee_num='%q'," From 6d02716ac595302bc8e683ab59ecb3c162bcd600 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 1 Jun 2012 13:28:30 -0500 Subject: [PATCH 027/101] last commit part 2 --- src/switch_core_sqldb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index eea6a4372d..50ba871e7b 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1193,7 +1193,7 @@ static char *parse_presence_data_cols(switch_event_t *event) for (i = 0; i < col_count; i++) { const char *val = NULL; - switch_snprintfv(col_name, sizeof(col_name), "variable_%q", cols[i]); + switch_snprintfv(col_name, sizeof(col_name), "PD-%q", cols[i]); val = switch_event_get_header_nil(event, col_name); if (zstr(val)) { stream.write_function(&stream, "%q=NULL,", cols[i]); From 241bdf4166aafb46bb87824d0f8109b1804c5305 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 1 Jun 2012 13:56:55 -0500 Subject: [PATCH 028/101] FS-4279 FS-3279 --resolve --- src/mod/endpoints/mod_sofia/sofia_glue.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index e96f1e1802..65a6caf1e6 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4703,10 +4703,6 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s goto done; } - 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; @@ -4715,6 +4711,11 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s const char *var = switch_channel_get_variable(channel, "t38_passthru"); int pass = sofia_test_pflag(tech_pvt->profile, PFLAG_T38_PASSTHRU); + + if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38)) { + sofia_set_flag(tech_pvt, TFLAG_NOREPLY); + } + if (var) { if (!(pass = switch_true(var))) { if (!strcasecmp(var, "once")) { From 410040218aea5d3a423f5ebf30b878ff8335cce6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 1 Jun 2012 14:11:21 -0500 Subject: [PATCH 029/101] add warning so users know inbound-zrtp-passthru will enable late negotiation --- src/mod/endpoints/mod_sofia/sofia.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index d865be6ee7..c6ab7dd76a 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4814,6 +4814,7 @@ switch_status_t config_sofia(int reload, char *profile_name) } if (sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "ZRTP Passthru implictly sets inbound-late-negotiation to true.\n"); sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION); } From c6aa2f14ece4367f445df3f6fc4567fb5f78b6f3 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 1 Jun 2012 21:25:55 +0000 Subject: [PATCH 030/101] add config comments about zrtp-passthru and late negotiation --- conf/insideout/sip_profiles/external.xml | 2 +- conf/insideout/sip_profiles/internal-ipv6.xml | 2 +- conf/insideout/sip_profiles/internal.xml | 2 +- conf/sbc/sbc_profiles/external.xml | 2 +- conf/sbc/sbc_profiles/internal-ipv6.xml | 2 +- conf/sbc/sbc_profiles/internal.xml | 2 +- conf/vanilla/sip_profiles/external.xml | 2 +- conf/vanilla/sip_profiles/internal-ipv6.xml | 2 +- conf/vanilla/sip_profiles/internal.xml | 2 +- src/mod/endpoints/mod_sofia/conf/sofia.conf.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/conf/insideout/sip_profiles/external.xml b/conf/insideout/sip_profiles/external.xml index f021a4c3c6..22fd155434 100644 --- a/conf/insideout/sip_profiles/external.xml +++ b/conf/insideout/sip_profiles/external.xml @@ -48,7 +48,7 @@ - + diff --git a/conf/insideout/sip_profiles/internal-ipv6.xml b/conf/insideout/sip_profiles/internal-ipv6.xml index b9907a78ad..525554f4b8 100644 --- a/conf/insideout/sip_profiles/internal-ipv6.xml +++ b/conf/insideout/sip_profiles/internal-ipv6.xml @@ -69,7 +69,7 @@ - + diff --git a/conf/insideout/sip_profiles/internal.xml b/conf/insideout/sip_profiles/internal.xml index e406cd5e72..666f7de5ab 100644 --- a/conf/insideout/sip_profiles/internal.xml +++ b/conf/insideout/sip_profiles/internal.xml @@ -104,7 +104,7 @@ - + diff --git a/conf/sbc/sbc_profiles/external.xml b/conf/sbc/sbc_profiles/external.xml index 0f15159f58..7bf024658b 100644 --- a/conf/sbc/sbc_profiles/external.xml +++ b/conf/sbc/sbc_profiles/external.xml @@ -49,7 +49,7 @@ - + diff --git a/conf/sbc/sbc_profiles/internal-ipv6.xml b/conf/sbc/sbc_profiles/internal-ipv6.xml index b9907a78ad..525554f4b8 100644 --- a/conf/sbc/sbc_profiles/internal-ipv6.xml +++ b/conf/sbc/sbc_profiles/internal-ipv6.xml @@ -69,7 +69,7 @@ - + diff --git a/conf/sbc/sbc_profiles/internal.xml b/conf/sbc/sbc_profiles/internal.xml index 3081052c88..d4b2efd37b 100644 --- a/conf/sbc/sbc_profiles/internal.xml +++ b/conf/sbc/sbc_profiles/internal.xml @@ -110,7 +110,7 @@ - + diff --git a/conf/vanilla/sip_profiles/external.xml b/conf/vanilla/sip_profiles/external.xml index 4f18e84be7..5070c87913 100644 --- a/conf/vanilla/sip_profiles/external.xml +++ b/conf/vanilla/sip_profiles/external.xml @@ -57,7 +57,7 @@ - + diff --git a/conf/vanilla/sip_profiles/internal-ipv6.xml b/conf/vanilla/sip_profiles/internal-ipv6.xml index 18274faa4f..62b9708e8b 100644 --- a/conf/vanilla/sip_profiles/internal-ipv6.xml +++ b/conf/vanilla/sip_profiles/internal-ipv6.xml @@ -70,7 +70,7 @@ - + diff --git a/conf/vanilla/sip_profiles/internal.xml b/conf/vanilla/sip_profiles/internal.xml index 0f4cabe32d..7d37da863e 100644 --- a/conf/vanilla/sip_profiles/internal.xml +++ b/conf/vanilla/sip_profiles/internal.xml @@ -222,7 +222,7 @@ - + diff --git a/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml b/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml index 30d8063a67..2e66602f1b 100644 --- a/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml +++ b/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml @@ -266,7 +266,7 @@ - + From 879830f61c220b517dda4c74be56e8ef3930cbe0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 1 Jun 2012 14:33:02 -0500 Subject: [PATCH 031/101] FS-4167 --resolve --- .../mod_conference/mod_conference.c | 104 +++++++++++++++++- 1 file changed, 99 insertions(+), 5 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 8b4be69b2c..c5a05c7fa7 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -48,9 +48,23 @@ typedef struct conference_cdr_node_s { char *record_path; switch_time_t join_time; switch_time_t leave_time; + uint32_t flags; struct conference_cdr_node_s *next; } conference_cdr_node_t; +typedef enum { + CDRR_LOCKED = 1, + CDRR_PIN, + CDRR_MAXMEMBERS +} cdr_reject_reason_t; + +typedef struct conference_cdr_reject_s { + switch_caller_profile_t *cp; + switch_time_t reject_time; + cdr_reject_reason_t reason; + struct conference_cdr_reject_s *next; +} conference_cdr_reject_t; + typedef enum { @@ -175,7 +189,8 @@ typedef enum { CFLAG_EXIT_SOUND = (1 << 12), CFLAG_ENTER_SOUND = (1 << 13), CFLAG_VIDEO_BRIDGE = (1 << 14), - CFLAG_AUDIO_ALWAYS = (1 << 15) + CFLAG_AUDIO_ALWAYS = (1 << 15), + CFLAG_ENDCONF_FORCED = (1 << 16) } conf_flag_t; typedef enum { @@ -332,6 +347,7 @@ typedef struct conference_obj { uint32_t originating; switch_call_cause_t cancel_cause; conference_cdr_node_t *cdr_nodes; + conference_cdr_reject_t *cdr_rejected; switch_time_t start_time; switch_time_t end_time; char *log_dir; @@ -505,6 +521,7 @@ static switch_status_t conference_add_event_member_data(conference_member_t *mem static void conference_cdr_del(conference_member_t *member) { member->cdr_node->leave_time = switch_epoch_time_now(NULL); + member->cdr_node->flags = member->flags; } static void conference_cdr_add(conference_member_t *member) @@ -533,10 +550,30 @@ static void conference_cdr_add(conference_member_t *member) member->cdr_node->cp = switch_caller_profile_dup(member->conference->pool, cp); } +static void conference_cdr_rejected(conference_obj_t *conference, switch_channel_t *channel, cdr_reject_reason_t reason) +{ + conference_cdr_reject_t *rp; + switch_caller_profile_t *cp; + + rp = switch_core_alloc(conference->pool, sizeof(*rp)); + + rp->next = conference->cdr_rejected; + conference->cdr_rejected = rp; + rp->reason = reason; + rp->reject_time = switch_epoch_time_now(NULL); + + if (!(cp = switch_channel_get_caller_profile(channel))) { + return; + } + + rp->cp = switch_caller_profile_dup(conference->pool, cp); +} + static void conference_cdr_render(conference_obj_t *conference) { - switch_xml_t cdr, x_ptr, x_member, x_members, x_conference, x_cp; + switch_xml_t cdr, x_ptr, x_member, x_members, x_conference, x_cp, x_flags, x_tag, x_rejected, x_attempt; conference_cdr_node_t *np; + conference_cdr_reject_t *rp; int cdr_off = 0, conf_off = 0; char str[512]; char *path, *xml_text; @@ -544,7 +581,7 @@ static void conference_cdr_render(conference_obj_t *conference) if (zstr(conference->log_dir)) return; - if (!conference->cdr_nodes) return; + if (!conference->cdr_nodes && !conference->cdr_rejected) return; if (!(cdr = switch_xml_new("cdr"))) { abort(); @@ -583,18 +620,20 @@ static void conference_cdr_render(conference_obj_t *conference) if (!(x_ptr = switch_xml_add_child_d(x_conference, "end_time", conf_off++))) { abort(); } + switch_xml_set_attr_d(x_ptr, "endconf_forced", switch_test_flag(conference, CFLAG_ENDCONF_FORCED) ? "true" : "false"); switch_xml_set_attr_d(x_ptr, "type", "UNIX-epoch"); switch_snprintf(str, sizeof(str), "%ld", (long)conference->end_time); switch_xml_set_txt_d(x_ptr, str); + if (!(x_members = switch_xml_add_child_d(x_conference, "members", conf_off++))) { abort(); } - for (np = conference->cdr_nodes; np; np = np->next) { int member_off = 0; + int flag_off = 0; if (!(x_member = switch_xml_add_child_d(x_members, "member", conf_off++))) { @@ -619,6 +658,18 @@ static void conference_cdr_render(conference_obj_t *conference) switch_xml_set_txt_d(x_ptr, str); if (np->cp) { + x_flags = switch_xml_add_child_d(x_member, "flags", member_off++); + switch_assert(x_flags); + + x_tag = switch_xml_add_child_d(x_flags, "is_moderator", flag_off++); + switch_xml_set_txt_d(x_tag, switch_test_flag(np, MFLAG_MOD) ? "true" : "false"); + + x_tag = switch_xml_add_child_d(x_flags, "end_conference", flag_off++); + switch_xml_set_txt_d(x_tag, switch_test_flag(np, MFLAG_ENDCONF) ? "true" : "false"); + + x_tag = switch_xml_add_child_d(x_flags, "was_kicked", flag_off++); + switch_xml_set_txt_d(x_tag, switch_test_flag(np, MFLAG_KICKED) ? "true" : "false"); + if (!(x_cp = switch_xml_add_child_d(x_member, "caller_profile", member_off++))) { abort(); } @@ -631,8 +682,47 @@ static void conference_cdr_render(conference_obj_t *conference) } switch_xml_set_txt_d(x_ptr, np->record_path); } + + } + if (!(x_rejected = switch_xml_add_child_d(x_conference, "rejected", conf_off++))) { + abort(); + } + + for (rp = conference->cdr_rejected; rp; rp = rp->next) { + int attempt_off = 0; + int tag_off = 0; + + if (!(x_attempt = switch_xml_add_child_d(x_rejected, "attempt", attempt_off++))) { + abort(); + } + + if (!(x_ptr = switch_xml_add_child_d(x_attempt, "reason", tag_off++))) { + abort(); + } + if (rp->reason == CDRR_LOCKED) { + switch_xml_set_txt_d(x_ptr, "conference_locked"); + } else if (rp->reason == CDRR_MAXMEMBERS) { + switch_xml_set_txt_d(x_ptr, "max_members_reached"); + } else if (rp->reason == CDRR_PIN) { + switch_xml_set_txt_d(x_ptr, "invalid_pin"); + } + + if (!(x_ptr = switch_xml_add_child_d(x_attempt, "reject_time", tag_off++))) { + abort(); + } + switch_xml_set_attr_d(x_ptr, "type", "UNIX-epoch"); + switch_snprintf(str, sizeof(str), "%ld", (long) rp->reject_time); + switch_xml_set_txt_d(x_ptr, str); + + if (rp->cp) { + if (!(x_cp = switch_xml_add_child_d(x_attempt, "caller_profile", attempt_off++))) { + abort(); + } + switch_ivr_set_xml_profile_data(x_cp, rp->cp, 0); + } + } xml_text = switch_xml_toxml(cdr, SWITCH_TRUE); @@ -1835,7 +1925,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v switch_epoch_time_now(NULL) - conference->endconf_time > conference->endconf_grace_time) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Conference %s: endconf grace time exceeded (%u)\n", conference->name, conference->endconf_grace_time); - switch_set_flag(conference, CFLAG_DESTRUCT); + switch_set_flag(conference, CFLAG_DESTRUCT | CFLAG_ENDCONF_FORCED); } switch_mutex_unlock(conference->mutex); @@ -4595,6 +4685,7 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer x_member = switch_xml_add_child_d(x_members, "member", moff++); switch_assert(x_member); + switch_xml_set_attr_d(x_member, "type", "caller"); switch_snprintf(i, sizeof(i), "%d", member->id); @@ -6616,6 +6707,7 @@ SWITCH_STANDARD_APP(conference_function) } if (!pin_valid) { + conference_cdr_rejected(conference, channel, CDRR_PIN); goto done; } } @@ -6627,6 +6719,7 @@ SWITCH_STANDARD_APP(conference_function) /* don't allow more callers if the conference is locked, unless we invited them */ if (switch_test_flag(conference, CFLAG_LOCKED) && enforce_security) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Conference %s is locked.\n", conf_name); + conference_cdr_rejected(conference, channel, CDRR_LOCKED); if (conference->locked_sound) { /* Answer the channel */ switch_channel_answer(channel); @@ -6641,6 +6734,7 @@ SWITCH_STANDARD_APP(conference_function) */ if ((conference->max_members > 0) && (conference->count >= conference->max_members)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Conference %s is full.\n", conf_name); + conference_cdr_rejected(conference, channel, CDRR_MAXMEMBERS); if (conference->maxmember_sound) { /* Answer the channel */ switch_channel_answer(channel); From c98cdb4e0414b512f75c4ae5d56c4b3991653da9 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 1 Jun 2012 21:43:41 +0000 Subject: [PATCH 032/101] avoid warning if late negotiation is enabled anyway --- src/mod/endpoints/mod_sofia/sofia.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index c6ab7dd76a..658a7f0b0b 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4813,8 +4813,8 @@ switch_status_t config_sofia(int reload, char *profile_name) } } - if (sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "ZRTP Passthru implictly sets inbound-late-negotiation to true.\n"); + if (sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU) && !sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "ZRTP passthrough implictly enables inbound-late-negotiation\n"); sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION); } From 93129e32d3849f232d3317dbbb85e39a9ac0cfb6 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Sat, 2 Jun 2012 00:12:34 +0200 Subject: [PATCH 033/101] FreeSWITCH: FS-4276 - Use a POSIX compatible set of regexes to filter -arch flags in PYTHON_CFLAGS. POSIX sed doesn't support grouping, so split the regex in two. Reference-URL: http://jira.freeswitch.org/browse/FS-4276 Signed-off-by: Stefan Knoblich --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index f37ba4c8bc..0599a0c6b7 100644 --- a/configure.in +++ b/configure.in @@ -925,7 +925,7 @@ then # # python distutils found, get settings from python directly # - PYTHON_CFLAGS="`$PYTHON -c 'from distutils import sysconfig; flags = [[\"-I\" + sysconfig.get_python_inc(0), \"-I\" + sysconfig.get_python_inc(1), \" \".join(sysconfig.get_config_var(\"CFLAGS\").split())]]; print(\" \".join(flags));' | sed -e 's:-arch \(i386\|x86_64\)::g'`" + PYTHON_CFLAGS="`$PYTHON -c 'from distutils import sysconfig; flags = [[\"-I\" + sysconfig.get_python_inc(0), \"-I\" + sysconfig.get_python_inc(1), \" \".join(sysconfig.get_config_var(\"CFLAGS\").split())]]; print(\" \".join(flags));' | sed -e 's/-arch i386//g;s/-arch x86_64//g'`" PYTHON_LDFLAGS="`$PYTHON -c 'from distutils import sysconfig; libs = sysconfig.get_config_var(\"LIBS\").split() + sysconfig.get_config_var(\"SYSLIBS\").split(); libs.append(\"-lpython\"+sysconfig.get_config_var(\"VERSION\")); print(\" \".join(libs));'`" PYTHON_LIB="`$PYTHON -c 'from distutils import sysconfig; print(\"python\" + sysconfig.get_config_var(\"VERSION\"));'`" PYTHON_LIBDIR="`$PYTHON -c 'from distutils import sysconfig; print(sysconfig.get_config_var(\"LIBDIR\"));'`" From c1b2472781753a1f78967c0cbe2e987a48297ac6 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 1 Jun 2012 22:11:22 +0000 Subject: [PATCH 034/101] SWITCH_VERSION_REVISION includes the dash or dot itself --- src/include/switch_version.h.cmake | 2 +- src/include/switch_version.h.template | 2 +- src/mod/endpoints/mod_sofia/mod_sofia.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/include/switch_version.h.cmake b/src/include/switch_version.h.cmake index 6e36b0b1da..7cec6489b3 100644 --- a/src/include/switch_version.h.cmake +++ b/src/include/switch_version.h.cmake @@ -41,7 +41,7 @@ extern "C" { #define SWITCH_VERSION_MINOR "@freeswitch_MINOR_VERSION@" #define SWITCH_VERSION_MICRO "@freeswitch_PATCH_LEVEL@" #define SWITCH_VERSION_REVISION "@Project_WC_REVISION@" -#define SWITCH_VERSION_FULL SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO " (" SWITCH_VERSION_REVISION ")" +#define SWITCH_VERSION_FULL SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO SWITCH_VERSION_REVISION #ifdef __cplusplus } diff --git a/src/include/switch_version.h.template b/src/include/switch_version.h.template index 2f75d75266..e0c13811d8 100644 --- a/src/include/switch_version.h.template +++ b/src/include/switch_version.h.template @@ -41,7 +41,7 @@ extern "C" { #define SWITCH_VERSION_MINOR "@SWITCH_VERSION_MINOR@" #define SWITCH_VERSION_MICRO "@SWITCH_VERSION_MICRO@" #define SWITCH_VERSION_REVISION "@SWITCH_VERSION_REVISION@" -#define SWITCH_VERSION_FULL SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO " (" SWITCH_VERSION_REVISION ")" +#define SWITCH_VERSION_FULL SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO SWITCH_VERSION_REVISION #ifdef __cplusplus } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 67d513cf27..4a8fb5b890 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -92,7 +92,7 @@ typedef struct private_object private_object_t; #define MULTICAST_EVENT "multicast::event" #define SOFIA_REPLACES_HEADER "_sofia_replaces_" -#define SOFIA_USER_AGENT "FreeSWITCH-mod_sofia/" SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO "-" SWITCH_VERSION_REVISION +#define SOFIA_USER_AGENT "FreeSWITCH-mod_sofia/" SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO SWITCH_VERSION_REVISION #define SOFIA_CHAT_PROTO "sip" #define SOFIA_MULTIPART_PREFIX "sip_mp_" #define SOFIA_MULTIPART_PREFIX_T "~sip_mp_" From 49ac9090654fa5ee0814b539a8b69d687bd86b2f Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 1 Jun 2012 22:16:30 +0000 Subject: [PATCH 035/101] skypopen/gsmopen should use SWITCH_VERSION_FULL here --- .../mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/gsmopen.h | 2 +- src/mod/endpoints/mod_gsmopen/gsmopen.h | 2 +- src/mod/endpoints/mod_skypopen/skypopen.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/gsmopen.h b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/gsmopen.h index 03c14283b4..01388575b0 100644 --- a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/gsmopen.h +++ b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/gsmopen.h @@ -132,7 +132,7 @@ //#define SAMPLES_PER_FRAME SAMPLERATE_GSMOPEN/50 #ifndef GSMOPEN_SVN_VERSION -#define GSMOPEN_SVN_VERSION SWITCH_VERSION_REVISION +#define GSMOPEN_SVN_VERSION SWITCH_VERSION_FULL #endif /* GSMOPEN_SVN_VERSION */ typedef enum { diff --git a/src/mod/endpoints/mod_gsmopen/gsmopen.h b/src/mod/endpoints/mod_gsmopen/gsmopen.h index fd56fd4963..b5404ae6a9 100644 --- a/src/mod/endpoints/mod_gsmopen/gsmopen.h +++ b/src/mod/endpoints/mod_gsmopen/gsmopen.h @@ -113,7 +113,7 @@ #endif #ifndef GSMOPEN_SVN_VERSION -#define GSMOPEN_SVN_VERSION SWITCH_VERSION_REVISION +#define GSMOPEN_SVN_VERSION SWITCH_VERSION_FULL #endif /* GSMOPEN_SVN_VERSION */ #include "ctb-0.16/ctb.h" diff --git a/src/mod/endpoints/mod_skypopen/skypopen.h b/src/mod/endpoints/mod_skypopen/skypopen.h index 864a22c3e4..d5f01f85e6 100644 --- a/src/mod/endpoints/mod_skypopen/skypopen.h +++ b/src/mod/endpoints/mod_skypopen/skypopen.h @@ -85,7 +85,7 @@ #endif #ifndef SKYPOPEN_SVN_VERSION -#define SKYPOPEN_SVN_VERSION SWITCH_VERSION_REVISION +#define SKYPOPEN_SVN_VERSION SWITCH_VERSION_FULL #endif /* SKYPOPEN_SVN_VERSION */ typedef enum { From 00e32e4ec2d3f762772464f2919ff11956114164 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 1 Jun 2012 22:21:48 +0000 Subject: [PATCH 036/101] use SWITCH_VERSION_FULL for the sofia user agent --- src/mod/endpoints/mod_sofia/mod_sofia.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 4a8fb5b890..247616d41c 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -92,7 +92,7 @@ typedef struct private_object private_object_t; #define MULTICAST_EVENT "multicast::event" #define SOFIA_REPLACES_HEADER "_sofia_replaces_" -#define SOFIA_USER_AGENT "FreeSWITCH-mod_sofia/" SWITCH_VERSION_MAJOR "." SWITCH_VERSION_MINOR "." SWITCH_VERSION_MICRO SWITCH_VERSION_REVISION +#define SOFIA_USER_AGENT "FreeSWITCH-mod_sofia/" SWITCH_VERSION_FULL #define SOFIA_CHAT_PROTO "sip" #define SOFIA_MULTIPART_PREFIX "sip_mp_" #define SOFIA_MULTIPART_PREFIX_T "~sip_mp_" From f3c2180c529bd2dc1cf1c5184c79fe8254edf758 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 2 Jun 2012 01:10:11 +0000 Subject: [PATCH 037/101] add usage help to debian/util.sh --- debian/util.sh | 57 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/debian/util.sh b/debian/util.sh index de1496a950..1692fcadab 100755 --- a/debian/util.sh +++ b/debian/util.sh @@ -328,14 +328,66 @@ build_all () { cat ../log/changes } -while getopts 'd' o "$@"; do +usage () { + cat >&2 < + + -d Enable cowbuilder debug hook + + create-dbg-pkgs + + create-dsc + + -m [ quicktest ] + Choose custom list of modules to build + -s [ paranoid | reckless ] + Set FS bootstrap/build -j flags + + create-orig + + -b Bundle downloaded libraries in source package + -n Nightly build + -v Set version + -z Set compression level + +EOF + exit 1 +} + +while getopts 'dh' o "$@"; do case "$o" in d) set -vx;; + h) usage;; esac done shift $(($OPTIND-1)) -cmd="$1" +cmd="$1"; [ -n "$cmd" ] || usage shift case "$cmd" in archive-orig) archive_orig "$@" ;; @@ -344,5 +396,6 @@ case "$cmd" in create-dbg-pkgs) create_dbg_pkgs ;; create-dsc) create_dsc "$@" ;; create-orig) create_orig "$@" ;; + *) usage ;; esac From ad2da59a6d850dae38a9cf82a8491bdec0e137dc Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 2 Jun 2012 03:07:12 +0000 Subject: [PATCH 038/101] debian: don't build mod_managed It's broken too many of my recent builds. We can add it back in when things stabilize or perhaps after we get it to swig with a recent version of swig that we can make part of the clean bootstrap/build process. --- debian/bootstrap.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index deed9f5c07..a724948577 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -31,6 +31,7 @@ avoid_mods=( endpoints/mod_reference endpoints/mod_unicall formats/mod_shout + languages/mod_managed languages/mod_spidermonkey sdk/autotools xml_int/mod_xml_ldap From cf68dc731a15f805fcb810c3eaf20cbc49eb400f Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 2 Jun 2012 04:20:52 +0000 Subject: [PATCH 039/101] debian: only build binary-indep packages once for each distro --- debian/util.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/debian/util.sh b/debian/util.sh index 1692fcadab..850558b1f4 100755 --- a/debian/util.sh +++ b/debian/util.sh @@ -234,9 +234,10 @@ EOF build_debs () { { set -e - local OPTIND OPTARG debug_hook=false hookdir="" - while getopts 'd' o "$@"; do + local OPTIND OPTARG debug_hook=false hookdir="" cow_build_opts="" + while getopts 'Bd' o "$@"; do case "$o" in + B) cow_build_opts="--debbuildopts '-B'";; d) debug_hook=true;; esac done @@ -261,7 +262,7 @@ build_debs () { } if ! [ -d $cow_img ]; then announce "Creating base $distro-$arch image..." - cow --create + cow --create $cow_build_opts fi announce "Updating base $distro-$arch image..." cow --update @@ -310,10 +311,12 @@ build_all () { local dsc="$(create_dsc $dsc_opts $distro $orig 2>../log/$distro | tail -n1)" echo "Done creating $distro dsc." >&2 if [ "${dsc:0:2}" = ".." ]; then + local lopts="" for arch in $archs; do { echo "Building $distro-$arch debs..." >&2 - local changes="$(build_debs $deb_opts $distro $dsc $arch 2>../log/$distro-$arch | tail -n1)" + local changes="$(build_debs $lopts $deb_opts $distro $dsc $arch 2>../log/$distro-$arch | tail -n1)" + lopts="-B" echo "Done building $distro-$arch debs." >&2 if [ "${changes:0:2}" = ".." ]; then echo "$changes" >> ../log/changes @@ -357,6 +360,7 @@ commands: build-debs + -B Binary architecture-dependent build -d Enable cowbuilder debug hook create-dbg-pkgs From 73b34cb373f94ec083bda2a5d4a96f486f3dfebe Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 2 Jun 2012 04:33:16 +0000 Subject: [PATCH 040/101] debian: kill children if we exit unexpectedly --- debian/util.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/util.sh b/debian/util.sh index 850558b1f4..2f7362a26c 100755 --- a/debian/util.sh +++ b/debian/util.sh @@ -305,6 +305,7 @@ build_all () { mkdir -p ../log > ../log/changes echo; echo; echo; echo + trap 'echo "Killing children...">&2; for x in $(jobs -p); do kill $x; done' EXIT if [ "${orig:0:2}" = ".." ]; then for distro in $distros; do echo "Creating $distro dsc..." >&2 @@ -328,6 +329,7 @@ build_all () { done ! $par || wait fi + trap - EXIT cat ../log/changes } From 337c9d43653a01667a53ec911dd262f7cffc96b9 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 2 Jun 2012 15:17:10 +0000 Subject: [PATCH 041/101] debian: output the correct name of the .changes file --- debian/util.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/util.sh b/debian/util.sh index 2f7362a26c..ec041be4bd 100755 --- a/debian/util.sh +++ b/debian/util.sh @@ -277,7 +277,7 @@ build_debs () { --hookdir "$hookdir" \ --buildresult ../ } 1>&2 - echo ${dsc}_${arch}.changes + echo ${dsc%.dsc}_${arch}.changes } build_all () { From c15613e0657285641fb6d550eed5065938b9258d Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 2 Jun 2012 16:09:39 +0000 Subject: [PATCH 042/101] debian: set variable outside fork --- debian/util.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/util.sh b/debian/util.sh index ec041be4bd..7844ff0de1 100755 --- a/debian/util.sh +++ b/debian/util.sh @@ -317,13 +317,13 @@ build_all () { { echo "Building $distro-$arch debs..." >&2 local changes="$(build_debs $lopts $deb_opts $distro $dsc $arch 2>../log/$distro-$arch | tail -n1)" - lopts="-B" echo "Done building $distro-$arch debs." >&2 if [ "${changes:0:2}" = ".." ]; then echo "$changes" >> ../log/changes fi } & $par || wait + lopts="-B" done fi done From ed9ff6e3755e607037ef8b8dd33cd19524ea1aad Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 2 Jun 2012 16:18:53 +0000 Subject: [PATCH 043/101] debian: don't rebuild dsc files --- debian/util.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/debian/util.sh b/debian/util.sh index 7844ff0de1..9d87cde130 100755 --- a/debian/util.sh +++ b/debian/util.sh @@ -235,9 +235,10 @@ build_debs () { { set -e local OPTIND OPTARG debug_hook=false hookdir="" cow_build_opts="" - while getopts 'Bd' o "$@"; do + while getopts 'Bbd' o "$@"; do case "$o" in B) cow_build_opts="--debbuildopts '-B'";; + b) cow_build_opts="--debbuildopts '-b'";; d) debug_hook=true;; esac done @@ -312,7 +313,7 @@ build_all () { local dsc="$(create_dsc $dsc_opts $distro $orig 2>../log/$distro | tail -n1)" echo "Done creating $distro dsc." >&2 if [ "${dsc:0:2}" = ".." ]; then - local lopts="" + local lopts="-b" for arch in $archs; do { echo "Building $distro-$arch debs..." >&2 @@ -363,6 +364,7 @@ commands: build-debs -B Binary architecture-dependent build + -b Binary-only build -d Enable cowbuilder debug hook create-dbg-pkgs From 992e05667cbf72251504d93625f0c01ef20ac792 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Sat, 2 Jun 2012 17:30:48 +0000 Subject: [PATCH 044/101] debian: put the build options in the right place --- debian/util.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/debian/util.sh b/debian/util.sh index 9d87cde130..3f4fea312d 100755 --- a/debian/util.sh +++ b/debian/util.sh @@ -263,7 +263,7 @@ build_debs () { } if ! [ -d $cow_img ]; then announce "Creating base $distro-$arch image..." - cow --create $cow_build_opts + cow --create fi announce "Updating base $distro-$arch image..." cow --update @@ -276,7 +276,8 @@ build_debs () { fi cow --build $dsc \ --hookdir "$hookdir" \ - --buildresult ../ + --buildresult ../ \ + $cow_build_opts } 1>&2 echo ${dsc%.dsc}_${arch}.changes } From 6a7fe5411f6906cb4298af7cc445f2860450ea67 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 4 Jun 2012 09:24:42 -0500 Subject: [PATCH 045/101] FS-4285 --resolve --- src/switch_json.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/switch_json.c b/src/switch_json.c index 83b34704e6..4bef601f8e 100644 --- a/src/switch_json.c +++ b/src/switch_json.c @@ -50,10 +50,11 @@ static char* cJSON_strdup(const char* str) { size_t len; char* copy; + const char *s = str ? str : ""; - len = strlen(str) + 1; + len = strlen(s) + 1; if (!(copy = (char*)cJSON_malloc(len))) return 0; - memcpy(copy,str,len); + memcpy(copy,s,len); return copy; } From d2bc9a2b12261d6b63174f3a09a61115b8fcd52e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 4 Jun 2012 09:41:46 -0500 Subject: [PATCH 046/101] FS-4137 --- src/mod/endpoints/mod_sofia/sofia_glue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 65a6caf1e6..35e7ddf149 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4161,6 +4161,7 @@ int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly) int changed = 0; if (sofia_test_flag(tech_pvt, TFLAG_SLA_BARGE) || sofia_test_flag(tech_pvt, TFLAG_SLA_BARGING)) { + switch_channel_mark_hold(tech_pvt->channel, sendonly); return 0; } From 9b488fbffd6a3cd8ff370abe1404b93cd0ac21ec Mon Sep 17 00:00:00 2001 From: Raymond Chandler Date: Mon, 4 Jun 2012 15:16:30 -0400 Subject: [PATCH 047/101] pnp --- src/mod/endpoints/mod_sofia/mod_sofia.h | 6 +++- src/mod/endpoints/mod_sofia/sofia.c | 24 +++++++++++++ src/mod/endpoints/mod_sofia/sofia_presence.c | 38 ++++++++++++++++++-- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 247616d41c..8379c4bf93 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -28,6 +28,7 @@ * Paul D. Tinsley * Bret McDanel * Marcel Barbulescu + * Raymond Chandler * * * mod_sofia.h -- SOFIA SIP Endpoint @@ -517,7 +518,8 @@ struct sofia_gateway { typedef enum { PRES_TYPE_NONE = 0, PRES_TYPE_FULL = 1, - PRES_TYPE_PASSIVE = 2 + PRES_TYPE_PASSIVE = 2, + PRES_TYPE_PNP = 3 } sofia_presence_type_t; typedef enum { @@ -586,6 +588,8 @@ struct sofia_profile { char *rtcp_audio_interval_msec; char *rtcp_video_interval_msec; char *jb_msec; + char *pnp_prov_url; + char *pnp_notify_profile; sofia_cid_type_t cid_type; sofia_dtmf_t dtmf_type; int auto_restart; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 658a7f0b0b..1317963647 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2138,6 +2138,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("include-session-description")), TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("presence.winfo")), TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("message-summary")), + TAG_IF(profile->pres_type == PRES_TYPE_PNP, NUTAG_ALLOW_EVENTS("ua-profile")), NUTAG_ALLOW_EVENTS("refer"), SIPTAG_SUPPORTED_STR(supported), SIPTAG_USER_AGENT_STR(profile->user_agent), TAG_END()); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set params for %s\n", profile->name); @@ -4417,10 +4418,16 @@ switch_status_t config_sofia(int reload, char *profile_name) } else if (!strcasecmp(val, "bypass-media-after-att-xfer")) { profile->media_options |= MEDIA_OPT_BYPASS_AFTER_ATT_XFER; } + } else if (!strcasecmp(var, "pnp-provision-url")) { + profile->pnp_prov_url = switch_core_strdup(profile->pool, val); + } else if (!strcasecmp(var, "pnp-notify-profile")) { + profile->pnp_notify_profile = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "manage-presence")) { if (!strcasecmp(val, "passive")) { profile->pres_type = PRES_TYPE_PASSIVE; + } else if (!strcasecmp(val, "pnp")) { + profile->pres_type = PRES_TYPE_PNP; } else if (switch_true(val)) { profile->pres_type = PRES_TYPE_FULL; } @@ -4875,6 +4882,23 @@ switch_status_t config_sofia(int reload, char *profile_name) profile->sipdomain = switch_core_strdup(profile->pool, profile->sipip); } + if (profile->pres_type == PRES_TYPE_PNP) { + if (!profile->pnp_prov_url) { + profile->pnp_prov_url = switch_core_sprintf(profile->pool, "http://%s/provision/", mod_sofia_globals.guess_ip); + } + + if (!profile->pnp_notify_profile) { + profile->pnp_notify_profile = switch_core_strdup(profile->pool, mod_sofia_globals.guess_ip); + } + + if (!profile->extsipip) { + profile->extsipip = switch_core_strdup(profile->pool, mod_sofia_globals.guess_ip); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "we're configured to provision to [%s] on profile [%s]\n", + profile->pnp_prov_url, profile->pnp_notify_profile); + } + config_sofia_profile_urls(profile); if (sofia_test_pflag(profile, PFLAG_TLS) && !profile->tls_cert_dir) { diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 23ae017531..c6ade27e1b 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -27,6 +27,7 @@ * Ken Rice * Paul D. Tinsley * Bret McDanel + * Raymond Chandler * * * sofia_presence.c -- SOFIA SIP Endpoint (presence code) @@ -3273,7 +3274,9 @@ void sofia_presence_handle_sip_i_subscribe(int status, int sent_reply = 0; sip_contact_t const *contact; const char *ipv6; - const char *contact_user; + const char *contact_user = NULL; + const char *contact_host = NULL; + const char *contact_port = NULL; sofia_nat_parse_t np = { { 0 } }; int found_proto = 0; char to_tag[13] = ""; @@ -3295,8 +3298,11 @@ void sofia_presence_handle_sip_i_subscribe(int status, switch_stun_random_string(to_tag, 12, NULL); - //contact_host = sip->sip_contact->m_url->url_host; - contact_user = sip->sip_contact->m_url->url_user; + if ( sip->sip_contact && sip->sip_contact->m_url ) { + contact_host = sip->sip_contact->m_url->url_host; + contact_port = sip->sip_contact->m_url->url_port; + contact_user = sip->sip_contact->m_url->url_user; + } //tl_gets(tags, NUTAG_SUBSTATE_REF(sub_state), TAG_END()); @@ -3645,6 +3651,32 @@ void sofia_presence_handle_sip_i_subscribe(int status, } } + if ( sip->sip_event && sip->sip_event->o_type && !strcasecmp(sip->sip_event->o_type, "ua-profile") && contact_host ) { + switch_event_t *params; + char *uri = NULL; + + if ( contact_port ) { + uri = switch_mprintf("sip:%s:%s", contact_host, contact_port); + } else { + uri = switch_mprintf("sip:%s", contact_host); + } + + if ( uri ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sending pnp NOTIFY to %s\n", uri); + + switch_event_create(¶ms, SWITCH_EVENT_NOTIFY); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "profile", profile->pnp_notify_profile); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "event-string", sip->sip_event->o_type); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "to-uri", uri); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "from-uri", uri); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "content-type", "application/url"); + switch_event_add_body(params, profile->pnp_prov_url); + switch_event_fire(¶ms); + + switch_safe_free(uri); + } + } + end: if (strcasecmp(event, "call-info") && strcasecmp(event, "line-seize")) { From e4caea6ffd75b8674c9c5f96555c08ed7eea506b Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 4 Jun 2012 16:40:32 -0400 Subject: [PATCH 048/101] fix build error --- src/mod/endpoints/mod_sofia/sofia_presence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index c6ade27e1b..25daa18f8c 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -3670,7 +3670,7 @@ void sofia_presence_handle_sip_i_subscribe(int status, switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "to-uri", uri); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "from-uri", uri); switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "content-type", "application/url"); - switch_event_add_body(params, profile->pnp_prov_url); + switch_event_add_body(params, "%s", profile->pnp_prov_url); switch_event_fire(¶ms); switch_safe_free(uri); From a065cf8631c9fe5b6d4350c061b6e5dcd671fa9f Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 5 Jun 2012 08:44:22 -0500 Subject: [PATCH 049/101] FS-4219 --resolve correct windows version --- libs/win32/util.vbs | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/libs/win32/util.vbs b/libs/win32/util.vbs index 29a7be5715..cbaf96a7b0 100644 --- a/libs/win32/util.vbs +++ b/libs/win32/util.vbs @@ -271,36 +271,38 @@ Sub CreateVersion(tmpFolder, VersionDir, includebase, includedest) strVerRev = FindVersionStringInConfigure(VersionDir & "configure.in", "SWITCH_VERSION_REVISION") 'Set version to the one reported by configure.in - if strVerRev <> "" Then + If strVerRev <> "" Then VERSION = strVerRev End If Dim sLastFile Const ForReading = 1 - 'Try To read revision from git, if it's found, use this instead of strVerRev found above - If FSO.FolderExists(VersionDir & ".git") Then - VersionCmd="git log --format=" & quote & "%%h %%ci" & quote & " -1 HEAD" - Set MyFile = FSO.CreateTextFile(tmpFolder & "tmpVersion.Bat", True) - MyFile.WriteLine("@" & "cd " & quote & VersionDir & quote) - MyFile.WriteLine("@" & VersionCmd) - MyFile.Close - Set oExec = WshShell.Exec("cmd /C " & quote & tmpFolder & "tmpVersion.Bat" & quote) - Do - strFromProc = Trim(OExec.StdOut.ReadLine()) - VERSION="git-" & strFromProc - Loop While Not OExec.StdOut.atEndOfStream - sLastVersion = "" - Set sLastFile = FSO.OpenTextFile(tmpFolder & "lastversion", ForReading, true, OpenAsASCII) - If Not sLastFile.atEndOfStream Then - sLastVersion = sLastFile.ReadLine() + 'Try To read revision from git, if it was not found in "configure.in" already + If strVerRev = "" Then + If FSO.FolderExists(VersionDir & ".git") Then + VersionCmd="git log --format=" & quote & "%%h %%ci" & quote & " -1 HEAD" + Set MyFile = FSO.CreateTextFile(tmpFolder & "tmpVersion.Bat", True) + MyFile.WriteLine("@" & "cd " & quote & VersionDir & quote) + MyFile.WriteLine("@" & VersionCmd) + MyFile.Close + Set oExec = WshShell.Exec("cmd /C " & quote & tmpFolder & "tmpVersion.Bat" & quote) + Do + strFromProc = Trim(OExec.StdOut.ReadLine()) + VERSION="git-" & strFromProc + Loop While Not OExec.StdOut.atEndOfStream + sLastVersion = "" + Set sLastFile = FSO.OpenTextFile(tmpFolder & "lastversion", ForReading, true, OpenAsASCII) + If Not sLastFile.atEndOfStream Then + sLastVersion = sLastFile.ReadLine() + End If + sLastFile.Close + VERSION = Replace(VERSION, ":", "-") End If - sLastFile.Close - VERSION = Replace(VERSION, ":", "-") End If If VERSION = "" Then - VERSION = "UNKNOWN" + VERSION = "-UNKNOWN" End If If VERSION <> sLastVersion Then From 2983003f95bc7d2f3949ef4146b0c809a70d5fdd Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 5 Jun 2012 13:19:34 -0400 Subject: [PATCH 050/101] do update to state on channels table at hangup --- src/switch_core_sqldb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 50ba871e7b..ee726500ac 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1403,7 +1403,6 @@ static void core_event_handler(switch_event_t *event) switch (state_i) { case CS_NEW: - case CS_HANGUP: case CS_DESTROY: case CS_REPORTING: break; From b4bd30816e25be750f4b199d9cd3df2254c197db Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 5 Jun 2012 12:29:53 -0500 Subject: [PATCH 051/101] FS-4290 --resolve --- src/switch_time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_time.c b/src/switch_time.c index 381d2dc5ad..d4f5454d3b 100644 --- a/src/switch_time.c +++ b/src/switch_time.c @@ -941,7 +941,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) runtime.timestamp = ts; current_ms += (runtime.microseconds_per_tick / 1000); - tick += (runtime.microseconds_per_tick / 1000); + tick++; if (time_sync < runtime.time_sync) { time_sync++; /* Only step once for each loop, we want to make sure to keep this thread safe */ From 2c9e1454fe421de5fa2668ac1dfcc43a9f369909 Mon Sep 17 00:00:00 2001 From: Viktor Krykun Date: Tue, 5 Jun 2012 23:24:37 +0300 Subject: [PATCH 052/101] various bug fixes in libzrtp * fixed bug with remote hello-hash buffer being too small * removed unused hello-hash storage in zrtp stream context * fixed bug with libzrtp rendered "empty" SAS hash from incoming SasRelay packet * incremented libzrtp version number to 1.15 Signed-off-by: Travis Cross --- libs/libzrtp/include/zrtp_types.h | 16 ++++------ libs/libzrtp/include/zrtp_version.h | 6 ++-- libs/libzrtp/projects/gnu/configure.in | 2 +- libs/libzrtp/src/zrtp.c | 8 ++--- libs/libzrtp/src/zrtp_pbx.c | 44 ++++++++++++++++++-------- libs/libzrtp/src/zrtp_utils.c | 2 +- 6 files changed, 46 insertions(+), 32 deletions(-) diff --git a/libs/libzrtp/include/zrtp_types.h b/libs/libzrtp/include/zrtp_types.h index a38d118591..c5c7654d68 100644 --- a/libs/libzrtp/include/zrtp_types.h +++ b/libs/libzrtp/include/zrtp_types.h @@ -527,7 +527,12 @@ typedef struct zrtp_stream_mescache_t zrtp_retry_task_t errorack_task; zrtp_retry_task_t sasrelay_task; - zrtp_string16_t signaling_hash; + /*! + * Hash pre-image of the remote party Hello retrieved from Signaling. When + * user calls zrtp_signaling_hash_set() libzrtp stores hash value in this + * variable and checks all incoming Hello-s to prevent DOS attacks. + */ + zrtp_string64_t signaling_hash; } zrtp_stream_mescache_t; @@ -722,14 +727,7 @@ struct zrtp_stream_t * crypto sources and performs traffic encryption/decryption. */ zrtp_protocol_t *protocol; - - /*! - * Hash pre-image of the remote party Hello retrieved from Signaling. When - * user calls zrtp_signaling_hash_set() libzrtp stores hash value in this - * variable and checks all incoming Hellos to prevent DOS attacks. - */ - zrtp_string128_t signaling_hash; - + /*!< Holder for RTP/ZRTP media stream options. */ zrtp_media_context_t media_ctx; diff --git a/libs/libzrtp/include/zrtp_version.h b/libs/libzrtp/include/zrtp_version.h index 5afc3b76af..e666e42cb9 100644 --- a/libs/libzrtp/include/zrtp_version.h +++ b/libs/libzrtp/include/zrtp_version.h @@ -12,8 +12,8 @@ #define LIBZRTP_VERSION_MAJOR 1 -#define LIBZRTP_VERSION_MINOR 13 -#define LIBZRTP_VERSION_BUILD 604 -#define LIBZRTP_VERSION_STR "v1.13 604" +#define LIBZRTP_VERSION_MINOR 15 +#define LIBZRTP_VERSION_BUILD 607 +#define LIBZRTP_VERSION_STR "v1.15 607" #endif /*__ZRTP_VERSION_H__*/ diff --git a/libs/libzrtp/projects/gnu/configure.in b/libs/libzrtp/projects/gnu/configure.in index d25d41771a..7d97319a76 100644 --- a/libs/libzrtp/projects/gnu/configure.in +++ b/libs/libzrtp/projects/gnu/configure.in @@ -32,7 +32,7 @@ case $target_os in esac -AM_INIT_AUTOMAKE([libzrtp], [1.14]) +AM_INIT_AUTOMAKE([libzrtp], [1.15]) AX_PREFIX_CONFIG_H(../../include/zrtp_config_unix.h,ZRTP,config/config.h) CFLAGS="$CFLAGS -Wno-unused-parameter -fno-strict-aliasing -fPIC -DZRTP_AUTOMAKE=1" diff --git a/libs/libzrtp/src/zrtp.c b/libs/libzrtp/src/zrtp.c index d0002a7d3d..c69b5e9692 100644 --- a/libs/libzrtp/src/zrtp.c +++ b/libs/libzrtp/src/zrtp.c @@ -418,8 +418,6 @@ zrtp_status_t zrtp_stream_attach(zrtp_session_t *session, zrtp_stream_t** stream return zrtp_status_alloc_fail; } - ZSTR_SET_EMPTY(new_stream->signaling_hash); - /* * Initialize the private data stream with default initial values */ @@ -437,6 +435,8 @@ zrtp_status_t zrtp_stream_attach(zrtp_session_t *session, zrtp_stream_t** stream ZSTR_SET_EMPTY(new_stream->cc.zrtp_key); ZSTR_SET_EMPTY(new_stream->cc.peer_zrtp_key); + ZSTR_SET_EMPTY(new_stream->messages.signaling_hash); + new_stream->dh_cc.initialized_with = ZRTP_COMP_UNKN; bnBegin(&new_stream->dh_cc.peer_pv); ZSTR_SET_EMPTY(new_stream->dh_cc.dhss); @@ -638,8 +638,8 @@ zrtp_status_t zrtp_signaling_hash_set( zrtp_stream_t* ctx, ctx->messages.signaling_hash.length = ZRTP_MESSAGE_HASH_SIZE; { - char buff[66]; - ZRTP_LOG(3, (_ZTU_,"SIGNALLING HAS was ADDED for the comparing. ID=%u\n", ctx->id)); + char buff[64]; + ZRTP_LOG(3, (_ZTU_,"SIGNALLING HAS was ADDED for the comparision. ID=%u\n", ctx->id)); ZRTP_LOG(3, (_ZTU_,"Hash=%s.\n", hex2str(hash_buff, hash_buff_length, buff, sizeof(buff)))); } diff --git a/libs/libzrtp/src/zrtp_pbx.c b/libs/libzrtp/src/zrtp_pbx.c index 3567d4a47b..cc25c46b3e 100644 --- a/libs/libzrtp/src/zrtp_pbx.c +++ b/libs/libzrtp/src/zrtp_pbx.c @@ -128,13 +128,15 @@ zrtp_status_t _zrtp_machine_process_sasrelay(zrtp_stream_t *stream, zrtp_rtp_inf zrtp_status_t s = zrtp_status_fail; zrtp_string128_t hmac = ZSTR_INIT_EMPTY(hmac); char zerosashash[32]; + unsigned sas_scheme_did_change = 0; + unsigned sas_hash_did_change = 0; /* (padding + sig_len + flags) + SAS scheme and SAS hash */ const uint8_t encrypted_body_size = (2 + 1 + 1) + 4 + 32; zrtp_memset(zerosashash, 0, sizeof(zerosashash)); - /* Check if the remote endpoint is assiggneed to relay the SAS values */ + /* Check if the remote endpoint is assigned to relay the SAS values */ if (!stream->peer_mitm_flag) { ZRTP_LOG(2,(_ZTU_, ZRTP_RELAYED_SAS_FROM_NONMITM_STR)); return zrtp_status_fail; @@ -157,7 +159,7 @@ zrtp_status_t _zrtp_machine_process_sasrelay(zrtp_stream_t *stream, zrtp_rtp_inf return zrtp_status_fail; } - ZRTP_LOG(3,(_ZTU_, "\tHMAC value for the SASRELAY is correct - decryptiong...\n")); + ZRTP_LOG(3,(_ZTU_, "\tHMAC value for the SASRELAY is correct - decrypting...\n")); /* Then we need to decrypt Confirm body */ do @@ -217,9 +219,14 @@ zrtp_status_t _zrtp_machine_process_sasrelay(zrtp_stream_t *stream, zrtp_rtp_inf _zrtp_machine_enter_initiatingerror(stream, zrtp_error_invalid_packet, 1); return zrtp_status_fail; } - session->sasscheme = zrtp_comp_find(ZRTP_CC_SAS, rendering_id, session->zrtp ); - ZRTP_LOG(3,(_ZTU_,"\tSasrelay: New Rendering scheme %.4s.\n", session->sasscheme->base.type)); + /* Check is SAS rendering did change */ + if (rendering_id != session->sasscheme->base.id) { + session->sasscheme = zrtp_comp_find(ZRTP_CC_SAS, rendering_id, session->zrtp ); + + sas_scheme_did_change = 1; + ZRTP_LOG(3,(_ZTU_,"\tSasrelay: Rendering scheme was updated to %.4s.\n", session->sasscheme->base.type)); + } if (session->secrets.matches & ZRTP_BIT_PBX) { if ( ( ((uint32_t) *sasrelay->sas_scheme) != (uint32_t)0x0L ) && @@ -231,7 +238,8 @@ zrtp_status_t _zrtp_machine_process_sasrelay(zrtp_stream_t *stream, zrtp_rtp_inf zrtp_memcpy(session->sasbin.buffer, sasrelay->sashash, session->sasbin.length); stream->mitm_mode = ZRTP_MITM_MODE_RECONFIRM_CLIENT; - ZRTP_LOG(3,(_ZTU_,"\tSasRelay: SAS value was updated bin=%s.\n", + sas_hash_did_change = 1; + ZRTP_LOG(3,(_ZTU_,"\tSasRelay: SAS value was updated to bin=%s.\n", hex2str(buff, sizeof(buff), session->sasbin.buffer, session->sasbin.length))); } } else if (0 != zrtp_memcmp(sasrelay->sashash, zerosashash, sizeof(sasrelay->sashash))) { @@ -242,16 +250,24 @@ zrtp_status_t _zrtp_machine_process_sasrelay(zrtp_stream_t *stream, zrtp_rtp_inf ZRTP_LOG(1,(_ZTU_, "\rERROR! For SasRelay Other secret doesn't match. ID=%u\n", stream->id)); } - s = session->sasscheme->compute(session->sasscheme, stream, session->hash, 1); - if (zrtp_status_ok != s) { - _zrtp_machine_enter_initiatingerror(stream, zrtp_error_software, 1); - return s; - } - ZRTP_LOG(3,(_ZTU_,"\tSasRelay: Updated SAS is <%s> <%s>.\n", session->sas1.buffer, session->sas2.buffer)); + /* Generate new SAS if hash or rendering scheme did change. + * Note: latest libzrtp may send "empty" SasRelay with the same SAS rendering + * scheme and empty Hello hash for consistency reasons, we should ignore + * such packets. + */ + if (sas_scheme_did_change || sas_hash_did_change) { + s = session->sasscheme->compute(session->sasscheme, stream, session->hash, 1); + if (zrtp_status_ok != s) { + _zrtp_machine_enter_initiatingerror(stream, zrtp_error_software, 1); + return s; + } - if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) { - session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_LOCAL_SAS_UPDATED); + ZRTP_LOG(3,(_ZTU_,"\tSasRelay: Updated SAS is <%s> <%s>.\n", session->sas1.buffer, session->sas2.buffer)); + + if (session->zrtp->cb.event_cb.on_zrtp_protocol_event) { + session->zrtp->cb.event_cb.on_zrtp_protocol_event(stream, ZRTP_EVENT_LOCAL_SAS_UPDATED); + } } return zrtp_status_ok; @@ -492,7 +508,7 @@ zrtp_status_t zrtp_update_remote_options( zrtp_stream_t* stream, return zrtp_status_bad_param; } - /* Don't allow to transfer the SAS if the library wasn't initalized as MiTM endpoint */ + /* Don't allow to transfer the SAS if the library wasn't initialized as MiTM endpoint */ if (!stream->zrtp->is_mitm) { ZRTP_LOG(3,(_ZTU_,"\tERROR! The endpoint can't transfer SAS values to other endpoints" " without introducing itself by M-flag in Hello. see zrtp_init().\n")); diff --git a/libs/libzrtp/src/zrtp_utils.c b/libs/libzrtp/src/zrtp_utils.c index 7b61aac146..45b5290d85 100644 --- a/libs/libzrtp/src/zrtp_utils.c +++ b/libs/libzrtp/src/zrtp_utils.c @@ -488,7 +488,7 @@ zrtp_status_t _zrtp_packet_preparse( zrtp_stream_t* stream, (const char*) info->message, zrtp_ntoh16(((zrtp_packet_Hello_t*) info->message)->hdr.length)*4, ZSTR_GV(hash_str) ); - if (!zrtp_memcmp(stream->messages.signaling_hash.buffer, hash_str.buffer, ZRTP_MESSAGE_HASH_SIZE)) { + if (zrtp_memcmp(stream->messages.signaling_hash.buffer, hash_str.buffer, ZRTP_MESSAGE_HASH_SIZE)) { if (stream->zrtp->cb.event_cb.on_zrtp_security_event) { stream->zrtp->cb.event_cb.on_zrtp_security_event(stream, ZRTP_EVENT_WRONG_SIGNALING_HASH); } From 20f20c8a5ce75ba0c6c1fcf6fa2d274144762fb4 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 7 Jun 2012 10:06:09 -0500 Subject: [PATCH 053/101] FS-4248 prevent seg for unsupported say method --- src/switch_ivr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 08d1fcd5a4..8f50fe1257 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2976,7 +2976,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say_string(switch_core_session_t *ses } } - if ((si = switch_loadable_module_get_say_interface(module_name))) { + if ((si = switch_loadable_module_get_say_interface(module_name)) && si->say_string_function) { /* should go back and proto all the say mods to const.... */ switch_say_args_t say_args = {0}; From a6bb4545ebf7ffc773e6bc7ab399a3863ca09246 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 7 Jun 2012 13:00:52 -0500 Subject: [PATCH 054/101] FS-4293 --- src/mod/endpoints/mod_sofia/sofia_glue.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 35e7ddf149..105262977c 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -350,7 +350,7 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, tech_pvt->local_sdp_audio_zrtp_hash); } - if (sr) { + if (!zsttr(sr)) { switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=%s\n", sr); } } @@ -434,7 +434,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch verbose_sdp = 1; } - if (!force && !ip && !sr + if (!force && !ip && zstr(sr) && (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA))) { return; } @@ -465,7 +465,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch sofia_glue_sdp_map(b_sdp, &map, &ptmap); } - if (!sr) { + if (zstr(sr)) { if ((var_val = switch_channel_get_variable(tech_pvt->channel, "media_audio_mode"))) { sr = var_val; } else { @@ -485,7 +485,9 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch if ((tech_pvt->profile->ndlb & PFLAG_NDLB_SENDRECV_IN_SESSION) || ((var_val = switch_channel_get_variable(tech_pvt->channel, "ndlb_sendrecv_in_session")) && switch_true(var_val))) { - switch_snprintf(srbuf, sizeof(srbuf), "a=%s\n", sr); + if (!zstr(sr)) { + switch_snprintf(srbuf, sizeof(srbuf), "a=%s\n", sr); + } sr = NULL; } @@ -554,7 +556,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch tech_pvt->local_sdp_audio_zrtp_hash); } - if (sr) { + if (!zstr(sr)) { switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=%s\n", sr); } From 49666cee8d537929f5432da6bc080f4c94a55abd Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 7 Jun 2012 19:49:30 +0000 Subject: [PATCH 055/101] add some sofia debugging for the local SDP Related to issue FS-4293. --- src/mod/endpoints/mod_sofia/sofia_glue.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 105262977c..c0f4001da6 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2598,6 +2598,11 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session) tech_pvt->session_refresher = nua_no_refresher; } + if (tech_pvt->local_sdp_str) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, + "Local SDP:\n%s\n", tech_pvt->local_sdp_str); + } + if (sofia_use_soa(tech_pvt)) { nua_invite(tech_pvt->nh, NUTAG_AUTOANSWER(0), From 9c463fdbdc7ceac84d7fc28cfcebeb4c15e87c14 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 7 Jun 2012 20:12:04 +0000 Subject: [PATCH 056/101] fix typo This amends commit a6bb4545ebf7ffc773e6bc7ab399a3863ca09246. --- src/mod/endpoints/mod_sofia/sofia_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index c0f4001da6..3a215c3529 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -350,7 +350,7 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, tech_pvt->local_sdp_audio_zrtp_hash); } - if (!zsttr(sr)) { + if (!zstr(sr)) { switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=%s\n", sr); } } From 19db96d2ba9053558ac1d21362f5270b9383e097 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Fri, 8 Jun 2012 17:23:07 +0200 Subject: [PATCH 057/101] channel private is already removed we don't need to remove the state handler FS-3432 --- src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index fc38f9e2b2..5d2c516e2c 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -348,7 +348,6 @@ static void destroy_session_elem(session_elem_t *session_element) } switch_channel_set_private(channel, "_erlang_session_", NULL); - switch_core_event_hook_remove_state_change(session, state_handler); switch_channel_clear_flag(channel, CF_CONTROLLED); switch_core_session_rwunlock(session); } From ae4d3acbb38fa481467a63526a90fdea7f211a84 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Fri, 8 Jun 2012 17:24:23 +0200 Subject: [PATCH 058/101] cleanup FS-3432 --- src/mod/event_handlers/mod_erlang_event/handle_msg.c | 6 +----- src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c index 5ff207e1a1..c1c682c867 100644 --- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c +++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c @@ -499,10 +499,8 @@ static switch_status_t handle_msg_setevent(listener_t *listener, erlang_msg *msg switch_event_types_t type; int i = 0; - /* TODO listener write lock */ - /* clear any previous event registrations */ - for( x = 0; x <= SWITCH_EVENT_ALL; x++){ + for(x = 0; x <= SWITCH_EVENT_ALL; x++) { event_list[x] = 0; } @@ -566,14 +564,12 @@ static switch_status_t handle_msg_session_setevent(listener_t *listener, erlang_ switch_event_types_t type; uint32_t x = 0; - /* TODO session write lock */ /* clear any previous event registrations */ for (x = 0; x <= SWITCH_EVENT_ALL; x++){ event_list[x] = 0; } /* create new hash */ - /* TODO make thread safe*/ switch_core_hash_init(&event_hash, session->pool); for (i = 1; i < arity; i++){ diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index 5d2c516e2c..b1caa67e3a 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -676,7 +676,6 @@ static switch_status_t check_attached_sessions(listener_t *listener) switch_thread_rwlock_wrlock(listener->session_rwlock); /* do the deferred remove */ - /* TODO refactor find_session_elem_by_uuid*/ for (header = event->headers; header; header = header->next) { if ((sp = (session_elem_t*)switch_core_hash_find(listener->sessions, header->value))) { remove_session_elem_from_listener(listener, sp); From dc30013360d28bcdb73a287f4420dcc13dd4ea1c Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 8 Jun 2012 16:09:26 +0000 Subject: [PATCH 059/101] fix buffer length calculation in call to generate_m This error was causing us to call generate_m with a buffer length that was less than the strlen of the buffer we were passing. The result was truncated local SDP which would cause sofia to fail if the truncation was in a particularly bad place. Thanks to Anthony Minessale for the fix and working with me to diagnose the issue. FS-4293 --resolve --- src/mod/endpoints/mod_sofia/sofia_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 3a215c3529..9bc9ae02ff 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -621,7 +621,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch cur_ptime = this_ptime; if ((!zstr(tech_pvt->local_crypto_key) && sofia_test_flag(tech_pvt, TFLAG_SECURE))) { - generate_m(tech_pvt, buf, sizeof(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1); + generate_m(tech_pvt, bp, sizeof(buf) - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1); bp = (buf + strlen(buf)); /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/ From 086f6174422b68ea180e5db8880f5f1a6882f2af Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 8 Jun 2012 16:13:50 +0000 Subject: [PATCH 060/101] increase buffer size for local SDP There are a lot of codecs these days, and some clients offer all of them. If we run out of space in this buffer our local SDP will get silently truncated, which will cause a difficult to diagnose error in Sofia-SIP. Thanks to Anthony Minessale. FS-4293 --resolve --- src/mod/endpoints/mod_sofia/sofia_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 9bc9ae02ff..6376e86149 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -375,7 +375,7 @@ void sofia_glue_check_dtmf_type(private_object_t *tech_pvt) void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch_port_t port, const char *sr, int force) { - char buf[2048]; + char buf[65536]; int ptime = 0; uint32_t rate = 0; uint32_t v_port; From 9c94ac312e62b201b6af1cd86bab0c7f891009d5 Mon Sep 17 00:00:00 2001 From: Christopher Rienzo Date: Fri, 8 Jun 2012 18:12:33 +0000 Subject: [PATCH 061/101] Fix Ubuntu 11.10 compiler error on unchecked write() return value. --- src/mod/timers/mod_posix_timer/mod_posix_timer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/timers/mod_posix_timer/mod_posix_timer.c b/src/mod/timers/mod_posix_timer/mod_posix_timer.c index cfb6584701..3d33b864db 100644 --- a/src/mod/timers/mod_posix_timer/mod_posix_timer.c +++ b/src/mod/timers/mod_posix_timer/mod_posix_timer.c @@ -113,7 +113,9 @@ static void timer_signal_handler(int sig, siginfo_t *si, void *cu) if (val >= 0 && val <= MAX_ACTIVE_TIMERS) { uint8_t active_id = (uint8_t)val; /* notify runtime thread that timer identified by active_id has ticked */ - write(globals.timer_tick_pipe[1], &active_id, 1); + if (write(globals.timer_tick_pipe[1], &active_id, 1) == -1) { + /* don't actually care about this error- this is only to make the compiler happy */ + } } } } From a17027959dc84748a5fdc38ce9a6e3ed51992c41 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 8 Jun 2012 12:06:35 -0500 Subject: [PATCH 062/101] use a dummy event here --- src/mod/event_handlers/mod_event_socket/mod_event_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index d71a6fa70e..c2862d8ab2 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -1185,7 +1185,7 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, } count++; if (count == 1) { - switch_event_create(event, SWITCH_EVENT_SOCKET_DATA); + switch_event_create(event, SWITCH_EVENT_CLONE); switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Command", mbuf); } else if (cur) { char *var, *val; From fc2bb00eb19edc245ae6e9bcdff814c07f1e603b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 8 Jun 2012 12:43:50 -0500 Subject: [PATCH 063/101] FS-4298 --resolve var is called execute_on_sip_reinvite --- src/mod/endpoints/mod_sofia/sofia.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 1317963647..78036c1895 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -7669,6 +7669,11 @@ void sofia_handle_sip_i_reinvite(switch_core_session_t *session, tagi_t tags[]) { char *call_info = NULL; + switch_channel_t *channel = NULL; + + if (session) { + channel = switch_core_session_get_channel(session); + } if (session && profile && sip && sofia_test_pflag(profile, PFLAG_TRACK_CALLS)) { switch_channel_t *channel = switch_core_session_get_channel(session); @@ -7693,7 +7698,6 @@ void sofia_handle_sip_i_reinvite(switch_core_session_t *session, } if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) { - switch_channel_t *channel = switch_core_session_get_channel(session); if (channel && sip->sip_call_info) { char *p; if ((call_info = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_call_info))) { @@ -7707,6 +7711,11 @@ void sofia_handle_sip_i_reinvite(switch_core_session_t *session, } } } + + if (channel) { + switch_channel_execute_on(channel, "execute_on_sip_reinvite"); + } + } void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, From 83f230cce6e0d9a54631ee29c91c7661120eaf34 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Mon, 11 Jun 2012 15:00:32 +0200 Subject: [PATCH 064/101] fix possible memory leak FS-3432 --- src/mod/event_handlers/mod_erlang_event/handle_msg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c index c1c682c867..527828f1f7 100644 --- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c +++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c @@ -805,7 +805,7 @@ static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_ value = malloc(size + 1); if (ei_decode_string(buf->buff, &buf->index, value)) { - fail = SWITCH_TRUE; + fail = SWITCH_TRUE; break; } @@ -818,6 +818,7 @@ static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_ ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); + switch_event_destroy(&event); } else { if (switch_core_session_queue_private_event(session, &event, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { ei_x_encode_atom(rbuf, "ok"); @@ -825,6 +826,7 @@ static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_ ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badmem"); + switch_event_destroy(&event); } } From d2e9e46eb6fd1a603c52727d1a77df9638899e7c Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Mon, 11 Jun 2012 15:03:58 +0200 Subject: [PATCH 065/101] move session destroy to one place and hangup in others to eliminate races and minimize session hash wrlocks FS-3432 --- .../mod_erlang_event/mod_erlang_event.c | 80 +++++++++++-------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index b1caa67e3a..9960e2499d 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -55,6 +55,8 @@ SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_nodename, prefs.nodename); static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj); static void launch_listener_thread(listener_t *listener); +session_elem_t *find_session_elem_by_uuid(listener_t *listener, const char *uuid); + static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_level_t level) { listener_t *l; @@ -135,14 +137,7 @@ static void send_event_to_attached_sessions(listener_t *listener, switch_event_t return; } - - switch_thread_rwlock_rdlock(listener->session_rwlock); - if ((s = (session_elem_t*)switch_core_hash_find(listener->sessions, uuid))) { - switch_thread_rwlock_rdlock(s->rwlock); - } - switch_thread_rwlock_unlock(listener->session_rwlock); - - if (s) { + if ((s = (session_elem_t*)find_session_elem_by_uuid(listener, uuid))) { int send = 0; switch_thread_rwlock_rdlock(s->event_rwlock); @@ -296,7 +291,7 @@ static void remove_listener(listener_t *listener) } /* Search for a listener already talking to the specified node and lock for reading*/ -static listener_t *find_listener_locked(char *nodename) +static listener_t *find_listener(char *nodename) { listener_t *l = NULL; @@ -321,14 +316,9 @@ static void add_session_elem_to_listener(listener_t *listener, session_elem_t *s static void remove_session_elem_from_listener(listener_t *listener, session_elem_t *session_element) -{ - switch_core_hash_delete(listener->sessions, session_element->uuid_str); -} - -static void remove_session_elem_from_listener_locked(listener_t *listener, session_elem_t *session_element) { switch_thread_rwlock_wrlock(listener->session_rwlock); - remove_session_elem_from_listener(listener, session_element); + switch_core_hash_delete(listener->sessions, session_element->uuid_str); switch_thread_rwlock_unlock(listener->session_rwlock); } @@ -343,10 +333,6 @@ static void destroy_session_elem(session_elem_t *session_element) if ((session = switch_core_session_locate(session_element->uuid_str))) { switch_channel_t *channel = switch_core_session_get_channel(session); - if (switch_channel_get_state(channel) < CS_HANGUP) { - switch_log_printf(SWITCH_CHANNEL_UUID_LOG(session_element->uuid_str), SWITCH_LOG_WARNING, "Outbound session for %s exited unexpectedly!\n", session_element->uuid_str); - } - switch_channel_set_private(channel, "_erlang_session_", NULL); switch_channel_clear_flag(channel, CF_CONTROLLED); switch_core_session_rwunlock(session); @@ -354,6 +340,19 @@ static void destroy_session_elem(session_elem_t *session_element) switch_core_destroy_memory_pool(&session_element->pool); } +session_elem_t *find_session_elem_by_uuid(listener_t *listener, const char *uuid) +{ + session_elem_t *session = NULL; + + switch_thread_rwlock_rdlock(listener->session_rwlock); + if ((session = (session_elem_t*)switch_core_hash_find(listener->sessions, uuid))) { + switch_thread_rwlock_rdlock(session->rwlock); + } + + switch_thread_rwlock_unlock(listener->session_rwlock); + + return session; + } session_elem_t *find_session_elem_by_pid(listener_t *listener, erlang_pid *pid) { @@ -362,14 +361,17 @@ session_elem_t *find_session_elem_by_pid(listener_t *listener, erlang_pid *pid) void *val = NULL; session_elem_t *session = NULL; + switch_thread_rwlock_rdlock(listener->session_rwlock); for (iter = switch_hash_first(NULL, listener->sessions); iter; iter = switch_hash_next(iter)) { switch_hash_this(iter, &key, NULL, &val); if (((session_elem_t*)val)->process.type == ERLANG_PID && !ei_compare_pids(pid, &((session_elem_t*)val)->process.pid)) { session = (session_elem_t*)val; + switch_thread_rwlock_rdlock(session->rwlock); break; } } + switch_thread_rwlock_unlock(listener->session_rwlock); return session; } @@ -536,6 +538,7 @@ static switch_status_t notify_new_session(listener_t *listener, session_elem_t * if (!(session = switch_core_session_locate(session_element->uuid_str))) { switch_log_printf(SWITCH_CHANNEL_UUID_LOG(session_element->uuid_str), SWITCH_LOG_WARNING, "Can't locate session %s\n", session_element->uuid_str); + switch_event_destroy(&call_event); return SWITCH_STATUS_FALSE; } @@ -672,19 +675,16 @@ static switch_status_t check_attached_sessions(listener_t *listener) } } switch_thread_rwlock_unlock(listener->session_rwlock); - /* release the read lock and get a write lock */ - switch_thread_rwlock_wrlock(listener->session_rwlock); - /* do the deferred remove */ + /* do the deferred remove */ for (header = event->headers; header; header = header->next) { - if ((sp = (session_elem_t*)switch_core_hash_find(listener->sessions, header->value))) { + if ((sp = (session_elem_t*)find_session_elem_by_uuid(listener, header->value))) { remove_session_elem_from_listener(listener, sp); + switch_thread_rwlock_unlock(sp->rwlock); destroy_session_elem(sp); } } - switch_thread_rwlock_unlock(listener->session_rwlock); - /* remove the temporary event */ switch_event_destroy(&event); @@ -783,13 +783,23 @@ static void handle_exit(listener_t *listener, erlang_pid * pid) remove_binding(NULL, pid); /* TODO - why don't we pass the listener as the first argument? */ - /* TODO - eliminate session destroy races and we shouldn't lock the session hash */ - switch_thread_rwlock_wrlock(listener->session_rwlock); if ((s = find_session_elem_by_pid(listener, pid))) { - remove_session_elem_from_listener(listener, s); - destroy_session_elem(s); + switch_core_session_t *session = NULL; + + if ((session = switch_core_session_locate(s->uuid_str))) { + switch_channel_t *channel = switch_core_session_get_channel(session); + + if (switch_channel_get_state(channel) < CS_HANGUP) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Outbound session exited unexpectedly %s!\n", s->uuid_str); + } + + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_core_session_rwunlock(session); + } + + switch_thread_rwlock_unlock(s->rwlock); + } - switch_thread_rwlock_wrlock(listener->session_rwlock); if (listener->log_process.type == ERLANG_PID && !ei_compare_pids(&listener->log_process.pid, pid)) { @@ -1214,7 +1224,6 @@ static listener_t *new_outbound_listener_locked(char *node) return NULL; } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "new listener for %s\n", node); listener = new_listener(&ec, clientfd); listener->peer_nodename = switch_core_strdup(listener->pool, node); } @@ -1410,10 +1419,11 @@ session_elem_t *attach_call_to_spawned_process(listener_t *listener, char *modul switch_thread_cond_timedwait(p->ready_or_found, p->mutex, 5000000); if (!p->pid) { + switch_channel_t *channel = switch_core_session_get_channel(session); + p->state = reply_timeout; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Timed out when waiting for outbound pid %s %s\n", hash, session_element->uuid_str); - remove_session_elem_from_listener_locked(listener, session_element); - destroy_session_elem(session_element); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); return NULL; } @@ -1500,7 +1510,7 @@ SWITCH_STANDARD_APP(erlang_outbound_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "enter erlang_outbound_function %s %s\n", argv[0], node); /* first work out if there is a listener already talking to the node we want to talk to */ - listener = find_listener_locked(node); + listener = find_listener(node); /* if there is no listener, then create one */ if (!listener) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating new listener for session\n"); @@ -1567,7 +1577,7 @@ SWITCH_STANDARD_APP(erlang_sendmsg_function) ei_x_encode_atom(&buf, "freeswitch_sendmsg"); _ei_x_encode_string(&buf, argv[2]); - listener = find_listener_locked(node); + listener = find_listener(node); if (!listener) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating new listener for sendmsg %s\n", node); listener = new_outbound_listener_locked(node); From 187fe4e14e651d52dd9f0866ac6a2246fb6f9086 Mon Sep 17 00:00:00 2001 From: Christopher Rienzo Date: Mon, 11 Jun 2012 13:05:29 +0000 Subject: [PATCH 066/101] update name/e-mail address --- src/mod/applications/mod_dptools/mod_dptools.c | 2 +- src/mod/applications/mod_http_cache/mod_http_cache.c | 4 ++-- src/mod/applications/mod_spandsp/mod_spandsp.c | 2 +- src/mod/applications/mod_spandsp/mod_spandsp_dsp.c | 2 +- src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c | 6 +++--- src/mod/codecs/mod_speex/mod_speex.c | 2 +- src/mod/timers/mod_posix_timer/mod_posix_timer.c | 4 ++-- src/switch_core_asr.c | 2 +- src/switch_core_codec.c | 2 +- src/switch_core_speech.c | 2 +- src/switch_ivr_async.c | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 009088e9f9..12cab2cf66 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -30,7 +30,7 @@ * Bret McDanel * Luke Dashjr (OpenMethods, LLC) * Cesar Cepeda - * Chris Rienzo + * Christopher M. Rienzo * * mod_dptools.c -- Raw Audio File Streaming Application Module * diff --git a/src/mod/applications/mod_http_cache/mod_http_cache.c b/src/mod/applications/mod_http_cache/mod_http_cache.c index fb2b4e09a2..381b30bddd 100644 --- a/src/mod/applications/mod_http_cache/mod_http_cache.c +++ b/src/mod/applications/mod_http_cache/mod_http_cache.c @@ -23,9 +23,9 @@ * * Contributor(s): * - * Christopher M. Rienzo + * Christopher M. Rienzo * - * Maintainer: Christopher M. Rienzo + * Maintainer: Christopher M. Rienzo * * mod_http_cache.c -- HTTP GET with caching * -- designed for downloading audio files from a webserver for playback diff --git a/src/mod/applications/mod_spandsp/mod_spandsp.c b/src/mod/applications/mod_spandsp/mod_spandsp.c index c210e02c0e..8cfe9d1e24 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp.c @@ -29,7 +29,7 @@ * Brian West * Steve Underwood * Antonio Gallo - * Christopher M. Rienzo + * Christopher M. Rienzo * mod_spandsp.c -- Module implementing spandsp fax, dsp, and codec functionality * */ diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c b/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c index 144d02ef8d..cc4d4964e2 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c @@ -28,7 +28,7 @@ * Anthony Minessale II * Steve Underwood * Antonio Gallo - * Christopher M. Rienzo + * Christopher M. Rienzo * mod_spandsp_dsp.c -- dsp applications provided by SpanDSP * */ diff --git a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c index e53964277c..aaf8f8764a 100644 --- a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c +++ b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c @@ -17,7 +17,7 @@ * The Original Code is FreeSWITCH mod_unimrcp * * The Initial Developer of the Original Code is - * Christopher M. Rienzo + * Christopher M. Rienzo * * Portions created by the Initial Developer are Copyright (C) * the Initial Developer. All Rights Reserved. @@ -25,10 +25,10 @@ * Contributor(s): * * Brian West - * Christopher M. Rienzo + * Christopher M. Rienzo * Luke Dashjr (OpenMethods, LLC) * - * Maintainer: Christopher M. Rienzo + * Maintainer: Christopher M. Rienzo * * mod_unimrcp.c -- UniMRCP module (MRCP client) * diff --git a/src/mod/codecs/mod_speex/mod_speex.c b/src/mod/codecs/mod_speex/mod_speex.c index ab9a044b53..8416686373 100644 --- a/src/mod/codecs/mod_speex/mod_speex.c +++ b/src/mod/codecs/mod_speex/mod_speex.c @@ -24,7 +24,7 @@ * Contributor(s): * * Anthony Minessale II - * Chris Rienzo + * Christopher M. Rienzo * * * mod_speex.c -- Speex Codec Module diff --git a/src/mod/timers/mod_posix_timer/mod_posix_timer.c b/src/mod/timers/mod_posix_timer/mod_posix_timer.c index 3d33b864db..1cd4586cdc 100644 --- a/src/mod/timers/mod_posix_timer/mod_posix_timer.c +++ b/src/mod/timers/mod_posix_timer/mod_posix_timer.c @@ -22,10 +22,10 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Christopher M. Rienzo + * Christopher M. Rienzo * Timo Teräs (based on mod_timerfd.c) * - * Maintainer: Christopher M. Rienzo + * Maintainer: Christopher M. Rienzo * * mod_posix_timer.c -- soft timer implemented with POSIX timers (timer_create/timer_settime/timer_getoverrun) * diff --git a/src/switch_core_asr.c b/src/switch_core_asr.c index 4db889929c..e10928f29d 100644 --- a/src/switch_core_asr.c +++ b/src/switch_core_asr.c @@ -26,7 +26,7 @@ * Anthony Minessale II * Michael Jerris * Paul D. Tinsley - * Christopher M. Rienzo + * Christopher M. Rienzo * Luke Dashjr (OpenMethods, LLC) * * diff --git a/src/switch_core_codec.c b/src/switch_core_codec.c index e7fa3f3fe7..1a529501ad 100644 --- a/src/switch_core_codec.c +++ b/src/switch_core_codec.c @@ -26,7 +26,7 @@ * Anthony Minessale II * Michael Jerris * Paul D. Tinsley - * Chris Rienzo + * Christopher M. Rienzo * * * switch_core_codec.c -- Main Core Library (codec functions) diff --git a/src/switch_core_speech.c b/src/switch_core_speech.c index f0e97f8b28..b75c9f843b 100644 --- a/src/switch_core_speech.c +++ b/src/switch_core_speech.c @@ -26,7 +26,7 @@ * Anthony Minessale II * Michael Jerris * Paul D. Tinsley - * Christopher M. Rienzo + * Christopher M. Rienzo * * * switch_core_speech.c -- Main Core Library (speech functions) diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 37da4f0486..c684c8f14c 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -27,7 +27,7 @@ * Michael Jerris * Bret McDanel * Luke Dashjr (OpenMethods, LLC) - * Chris Rienzo + * Christopher M. Rienzo * * switch_ivr_async.c -- IVR Library (async operations) * From ec27618fc8821af1446540d4963869a1f9be6572 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 11 Jun 2012 10:43:42 -0400 Subject: [PATCH 067/101] don't segfault after starting sofia, upon xml_open_config lookup failure for the profile from launch_sofia_worker_thread --- src/mod/endpoints/mod_sofia/sofia.c | 6 +++++- src/switch_apr.c | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 78036c1895..13e632af9f 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2252,7 +2252,11 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void sofia_clear_pflag_locked(profile, PFLAG_SHUTDOWN); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Waiting for worker thread\n"); - switch_thread_join(&st, worker_thread); + if ( worker_thread ) { + switch_thread_join(&st, worker_thread); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: Sofia worker thead failed to start\n"); + } sanity = 4; while (profile->inuse) { diff --git a/src/switch_apr.c b/src/switch_apr.c index 426bed59f5..5936c7223e 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -1169,6 +1169,11 @@ SWITCH_DECLARE(switch_status_t) switch_thread_exit(switch_thread_t *thd, switch_ */ SWITCH_DECLARE(switch_status_t) switch_thread_join(switch_status_t *retval, switch_thread_t *thd) { + if ( !thd ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: Attempting to join thread that does not exist\n"); + return SWITCH_STATUS_FALSE; + } + return apr_thread_join((apr_status_t *) retval, (apr_thread_t *) thd); } From 3f6b5a5c013f6f80544c5b35ec5032c53cad5738 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Mon, 11 Jun 2012 17:25:28 +0200 Subject: [PATCH 068/101] fix reply timeout: move hash and pid to session pool FS-3432 --- .../mod_erlang_event/handle_msg.c | 18 +++++------------- .../mod_erlang_event/mod_erlang_event.c | 4 +--- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c index 527828f1f7..0e8d472585 100644 --- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c +++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c @@ -1108,7 +1108,7 @@ static switch_status_t handle_msg_atom(listener_t *listener, erlang_msg * msg, e static switch_status_t handle_ref_tuple(listener_t *listener, erlang_msg * msg, ei_x_buff * buf, ei_x_buff * rbuf) { erlang_ref ref; - erlang_pid *pid; + erlang_pid pid; char hash[100]; int arity; const void *key; @@ -1123,15 +1123,7 @@ static switch_status_t handle_ref_tuple(listener_t *listener, erlang_msg * msg, return SWITCH_STATUS_FALSE; } - if (!(pid = malloc(sizeof(erlang_pid)))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error\n"); - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "error"); - ei_x_encode_atom(rbuf, "badmem"); - return SWITCH_STATUS_SUCCESS; - } - - if (ei_decode_pid(buf->buff, &buf->index, pid)) { + if (ei_decode_pid(buf->buff, &buf->index, &pid)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid pid in a reference/pid tuple\n"); return SWITCH_STATUS_FALSE; } @@ -1149,7 +1141,9 @@ static switch_status_t handle_ref_tuple(listener_t *listener, erlang_msg * msg, switch_mutex_lock(se->spawn_reply->mutex); if (se->spawn_reply->state == reply_waiting) { - se->spawn_reply->pid = pid; + se->spawn_reply->pid = switch_core_alloc(se->pool, sizeof(erlang_pid)); + switch_assert(se->spawn_reply->pid != NULL); + memcpy(se->spawn_reply->pid, &pid, sizeof(erlang_pid)); switch_thread_cond_signal(se->spawn_reply->ready_or_found); ei_x_encode_atom(rbuf, "ok"); switch_thread_rwlock_unlock(listener->session_rwlock); @@ -1167,8 +1161,6 @@ static switch_status_t handle_ref_tuple(listener_t *listener, erlang_msg * msg, ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "notfound"); - switch_safe_free(pid); /* don't need it */ - return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index 9960e2499d..4b3eaa7ecd 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -1377,7 +1377,7 @@ session_elem_t *attach_call_to_spawned_process(listener_t *listener, char *modul switch_thread_cond_create(&p->ready_or_found, session_element->pool); switch_mutex_init(&p->mutex, SWITCH_MUTEX_UNNESTED, session_element->pool); p->state = reply_waiting; - p->hash = hash; + p->hash = switch_core_strdup(session_element->pool, hash); p->pid = NULL; session_element->spawn_reply = p; @@ -1437,8 +1437,6 @@ session_elem_t *attach_call_to_spawned_process(listener_t *listener, char *modul ei_link(listener, ei_self(listener->ec), &session_element->process.pid); - switch_safe_free(p->pid); - return session_element; } From 034d4153c401dc77b38db6aff73c1d6c5654f4ad Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 11 Jun 2012 16:16:50 +0000 Subject: [PATCH 069/101] Improve SWITCH_VERSION_REVISION generation The revision was no longer picking up the last git commit. Instead, it was showing the last release. This commit appends the last git commit hash to the last release if a git repository is available. Further, it checks whether there are uncommitted changes in the git repository and adds an unclean tag to the version if this is the case. Note that currently this will append the git commit hash even on a tagged release if built directly from a git repository. Perhaps this isn't such a bad thing, but if it turns out not to be desired, I have an idea on how to squelch this without making unwarranted assumptions about the remote layout of someone's local repository. --- .version.in | 1 - Makefile.am | 37 +++++++++++++------------------------ configure.in | 1 - 3 files changed, 13 insertions(+), 26 deletions(-) delete mode 100644 .version.in diff --git a/.version.in b/.version.in deleted file mode 100644 index 449460b02e..0000000000 --- a/.version.in +++ /dev/null @@ -1 +0,0 @@ -@SWITCH_VERSION_REVISION@ diff --git a/Makefile.am b/Makefile.am index 12dc3fa05a..ca539ec6ae 100644 --- a/Makefile.am +++ b/Makefile.am @@ -415,29 +415,19 @@ $(OUR_MODULES): $(switch_builddir)/modules.conf libfreeswitch.la $(switch_builddir)/quiet_libtool: $(switch_builddir)/libtool @cat libtool | sed -e 's|$$show "$$command"|if test -z "$$suppress_output" ; then $$show "Compiling $$srcfile ..." ; fi|' > $(switch_builddir)/quiet_libtool -src/include/switch_version.h: src/include/switch_version.h.in .version $(libfreeswitch_la_SOURCES) $(library_include_HEADERS) - @have_version=1 ; \ - force=0 ; \ - grep -- "@SWITCH_VERSION_REVISION@" src/include/switch_version.h.in > /dev/null || have_version=0 ; \ - test ! -f src/include/switch_version.h || grep -- "@SWITCH_VERSION_REVISION@" src/include/switch_version.h > /dev/null && force=1 ; \ - if test $$have_version = 1 ; then \ - cat src/include/switch_version.h.in > src/include/switch_version.h ; \ - touch .version ; \ - else \ - if [ -d .git ] ; then \ - version=`git log --pretty=format:"%h %ci" -1 HEAD | head -1 | sed -e 's|:|-|g' || echo hacked` ; \ - if [ "x$$version" = "xhacked" ] ; then \ - version="hacked-`date -u +%Y%m%dT%H%M%SZ`" ; \ - else \ - version="git-$$version" ; \ - fi ;\ - fi ; \ - oldversion=`cat .version 2>/dev/null || echo "0"` ; \ - if test "$$oldversion" != "$$version" || test $$force = 1 ; then \ - cat src/include/switch_version.h.in | sed "s/@SWITCH_VERSION_REVISION@/$$version/g" > src/include/switch_version.h ; \ - echo $$version > .version ; \ - fi ; \ - fi ; +src/include/switch_version.h: src/include/switch_version.h.in Makefile $(libfreeswitch_la_SOURCES) $(library_include_HEADERS) + @cat $< > $@; \ + if [ -d .git ]; then \ + xdate="$$(date -d "$$(git log -n1 --format='%ci' HEAD)" -u '+%Y%m%dT%H%M%SZ')"; \ + xcommit="$$(git rev-list -n1 --abbrev=10 --abbrev-commit HEAD)"; \ + xver="+git~$$xdate~$$xcommit"; \ + if ! git diff-index --quiet HEAD; then \ + xver="$$xver+unclean~$$(date -u +%Y%m%dT%H%M%SZ)"; \ + fi; \ + sed \ + -e "/#define *SWITCH_VERSION_REVISION/{s/\"\([^\"]*\)\"/\"\1$$xver\"/; :l n; b l}" \ + $< > $@; \ + fi; ## ## Dependency targets @@ -544,7 +534,6 @@ is-scm: update: is-scm @if test -d .git ; then \ - test ! -f .version || rm -f .version ; \ echo "Pulling updates..." ; \ git pull ; \ else \ diff --git a/configure.in b/configure.in index 0599a0c6b7..514a9151e4 100644 --- a/configure.in +++ b/configure.in @@ -10,7 +10,6 @@ AC_SUBST(SWITCH_VERSION_MICRO, [0]) AC_SUBST(SWITCH_VERSION_REVISION, [-rc2]) AC_CONFIG_FILES([src/include/switch_version.h.in:src/include/switch_version.h.template]) -AC_CONFIG_FILES([.version:.version.in]) AC_CONFIG_AUX_DIR(build/config) AM_INIT_AUTOMAKE(libfreeswitch,0.1) From b735735ea18cb129053a9093349b767b7391b9b6 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 11 Jun 2012 18:06:00 +0000 Subject: [PATCH 070/101] gitignore a symlink we're creating in ldns --- libs/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/.gitignore b/libs/.gitignore index e39b1f4bf1..48bfc1f814 100644 --- a/libs/.gitignore +++ b/libs/.gitignore @@ -225,6 +225,7 @@ missing /ldns/doc/ldns_manpages /ldns/include/ /ldns/ldns/config.h +/ldns/ldns/ldns /ldns/ldns/net.h /ldns/ldns/util.h /ldns/lib From 56325e8c710f12233b156ec912636410b5ff8cf3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 11 Jun 2012 11:13:19 -0500 Subject: [PATCH 071/101] FS-4079 possible fix --- src/mod/endpoints/mod_sofia/mod_sofia.c | 292 +++++++++++++----------- 1 file changed, 153 insertions(+), 139 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 6d28bc01f9..5766eff62d 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -2339,151 +2339,165 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi break; case SWITCH_MESSAGE_INDICATE_RESPOND: - if (msg->numeric_arg || msg->string_arg) { - int code = msg->numeric_arg; - const char *reason = NULL; + { + int status = 0; - if (code) { - reason = msg->string_arg; - } else { - if (!zstr(msg->string_arg)) { - if ((code = atoi(msg->string_arg))) { - if ((reason = strchr(msg->string_arg, ' '))) { - reason++; - } - } - } + if (tech_pvt->nh && tech_pvt->nh->nh_ds && tech_pvt->nh->nh_ds->ds_sr && nua_server_request_is_pending(tech_pvt->nh->nh_ds->ds_sr)) { + status = tech_pvt->nh->nh_ds->ds_sr->sr_status; } - if (!code) { - code = 488; - } - - if (!switch_channel_test_flag(channel, CF_ANSWERED) && code >= 300) { - if (sofia_test_flag(tech_pvt, TFLAG_BYE)) { - goto end_lock; - } - } - - if (zstr(reason) && code != 407 && code != 302) { - reason = sip_status_phrase(code); - if (zstr(reason)) { - reason = "Because"; - } - } - - if (code == 407 && !msg->numeric_arg) { - const char *to_uri = switch_channel_get_variable(channel, "sip_to_uri"); - const char *to_host = reason; - - if (zstr(to_host)) { - to_host = switch_channel_get_variable(channel, "sip_to_host"); - } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Challenging call %s\n", to_uri); - sofia_reg_auth_challenge(tech_pvt->profile, tech_pvt->nh, NULL, REG_INVITE, to_host, 0); - switch_channel_hangup(channel, SWITCH_CAUSE_USER_CHALLENGE); - } else if (code == 484 && msg->numeric_arg) { - const char *to = switch_channel_get_variable(channel, "sip_to_uri"); - const char *max_forwards = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE); - char *cid = generate_pai_str(tech_pvt); - char *to_uri = NULL; - - if (to) { - char *p; - to_uri = switch_core_session_sprintf(session, "sip:%s", to); - if ((p = strstr(to_uri, ":5060"))) { - *p = '\0'; - } - } - - if (!switch_channel_test_flag(channel, CF_ANSWERED) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) { - char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Overlap Dial with %d %s\n", code, reason); - - nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), TAG_IF(to_uri, SIPTAG_CONTACT_STR(to_uri)), - SIPTAG_SUPPORTED_STR(NULL), SIPTAG_ACCEPT_STR(NULL), - TAG_IF(cid, SIPTAG_HEADER_STR(cid)), - TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), - TAG_IF(!zstr(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards)), TAG_END()); - - sofia_set_flag_locked(tech_pvt, TFLAG_BYE); - switch_safe_free(extra_headers); - } - } else if (code == 302 && !zstr(msg->string_arg)) { - char *p; - - if ((p = strchr(msg->string_arg, ' '))) { - *p = '\0'; - msg->string_arg = p; - } - - msg->message_id = SWITCH_MESSAGE_INDICATE_REDIRECT; - switch_core_session_receive_message(session, msg); + if (status == 0 || status > 199 || tech_pvt->nh->nh_destroyed) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s Cannot call respond on handle at status %d\n", + switch_channel_get_name(channel), status); goto end_lock; - } else { - if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) { - char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX); - char *sdp = (char *) msg->pointer_arg; - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Responding with %d [%s]\n", code, reason); - sofia_clear_flag(tech_pvt, TFLAG_REINVITED); - - if (!zstr((sdp))) { - if (!strcasecmp(sdp, "t38")) { - switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options"); - if (t38_options) { - sofia_glue_set_image_sdp(tech_pvt, t38_options, 0); - if (switch_rtp_ready(tech_pvt->rtp_session)) { - sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE); - switch_rtp_udptl_mode(tech_pvt->rtp_session); - } - } - } else { - sofia_glue_tech_set_local_sdp(tech_pvt, sdp, SWITCH_TRUE); - } - - if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { - sofia_glue_tech_patch_sdp(tech_pvt); - sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL); - } - if (sofia_use_soa(tech_pvt)) { - nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact), - SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), - SOATAG_REUSE_REJECTED(1), - SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), - TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_END()); - } else { - nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact), - NUTAG_MEDIA_ENABLE(0), - SIPTAG_CONTENT_TYPE_STR("application/sdp"), - SIPTAG_PAYLOAD_STR(tech_pvt->local_sdp_str), - TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_END()); - } - if (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC)) { - /* Unlock the session signal to allow the ack to make it in */ - // Maybe we should timeout? - switch_mutex_unlock(tech_pvt->sofia_mutex); - - while (switch_channel_ready(channel) && !sofia_test_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)) { - switch_cond_next(); - } - - /* Regain lock on sofia */ - switch_mutex_lock(tech_pvt->sofia_mutex); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n"); - sofia_clear_flag(tech_pvt, TFLAG_3PCC); - sofia_clear_flag(tech_pvt, TFLAG_3PCC_HAS_ACK); - switch_core_session_pass_indication(session, SWITCH_MESSAGE_INDICATE_ANSWER); - } - } else { - nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact), - TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_END()); - } - switch_safe_free(extra_headers); - } } + if (msg->numeric_arg || msg->string_arg) { + int code = msg->numeric_arg; + const char *reason = NULL; + + if (code) { + reason = msg->string_arg; + } else { + if (!zstr(msg->string_arg)) { + if ((code = atoi(msg->string_arg))) { + if ((reason = strchr(msg->string_arg, ' '))) { + reason++; + } + } + } + } + + if (!code) { + code = 488; + } + + if (!switch_channel_test_flag(channel, CF_ANSWERED) && code >= 300) { + if (sofia_test_flag(tech_pvt, TFLAG_BYE)) { + goto end_lock; + } + } + + if (zstr(reason) && code != 407 && code != 302) { + reason = sip_status_phrase(code); + if (zstr(reason)) { + reason = "Because"; + } + } + + if (code == 407 && !msg->numeric_arg) { + const char *to_uri = switch_channel_get_variable(channel, "sip_to_uri"); + const char *to_host = reason; + + if (zstr(to_host)) { + to_host = switch_channel_get_variable(channel, "sip_to_host"); + } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Challenging call %s\n", to_uri); + sofia_reg_auth_challenge(tech_pvt->profile, tech_pvt->nh, NULL, REG_INVITE, to_host, 0); + switch_channel_hangup(channel, SWITCH_CAUSE_USER_CHALLENGE); + } else if (code == 484 && msg->numeric_arg) { + const char *to = switch_channel_get_variable(channel, "sip_to_uri"); + const char *max_forwards = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE); + char *cid = generate_pai_str(tech_pvt); + char *to_uri = NULL; + + if (to) { + char *p; + to_uri = switch_core_session_sprintf(session, "sip:%s", to); + if ((p = strstr(to_uri, ":5060"))) { + *p = '\0'; + } + } + + if (!switch_channel_test_flag(channel, CF_ANSWERED) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) { + char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Overlap Dial with %d %s\n", code, reason); + + nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), TAG_IF(to_uri, SIPTAG_CONTACT_STR(to_uri)), + SIPTAG_SUPPORTED_STR(NULL), SIPTAG_ACCEPT_STR(NULL), + TAG_IF(cid, SIPTAG_HEADER_STR(cid)), + TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), + TAG_IF(!zstr(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards)), TAG_END()); + + sofia_set_flag_locked(tech_pvt, TFLAG_BYE); + switch_safe_free(extra_headers); + } + } else if (code == 302 && !zstr(msg->string_arg)) { + char *p; + + if ((p = strchr(msg->string_arg, ' '))) { + *p = '\0'; + msg->string_arg = p; + } + + msg->message_id = SWITCH_MESSAGE_INDICATE_REDIRECT; + switch_core_session_receive_message(session, msg); + goto end_lock; + } else { + if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) { + char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX); + char *sdp = (char *) msg->pointer_arg; + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Responding with %d [%s]\n", code, reason); + sofia_clear_flag(tech_pvt, TFLAG_REINVITED); + + if (!zstr((sdp))) { + if (!strcasecmp(sdp, "t38")) { + switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options"); + if (t38_options) { + sofia_glue_set_image_sdp(tech_pvt, t38_options, 0); + if (switch_rtp_ready(tech_pvt->rtp_session)) { + sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE); + switch_rtp_udptl_mode(tech_pvt->rtp_session); + } + } + } else { + sofia_glue_tech_set_local_sdp(tech_pvt, sdp, SWITCH_TRUE); + } + + if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) { + sofia_glue_tech_patch_sdp(tech_pvt); + sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL); + } + if (sofia_use_soa(tech_pvt)) { + nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact), + SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str), + SOATAG_REUSE_REJECTED(1), + SOATAG_ORDERED_USER(1), SOATAG_AUDIO_AUX("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1), + TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_END()); + } else { + nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact), + NUTAG_MEDIA_ENABLE(0), + SIPTAG_CONTENT_TYPE_STR("application/sdp"), + SIPTAG_PAYLOAD_STR(tech_pvt->local_sdp_str), + TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_END()); + } + if (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY) && sofia_test_flag(tech_pvt, TFLAG_3PCC)) { + /* Unlock the session signal to allow the ack to make it in */ + // Maybe we should timeout? + switch_mutex_unlock(tech_pvt->sofia_mutex); + + while (switch_channel_ready(channel) && !sofia_test_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)) { + switch_cond_next(); + } + + /* Regain lock on sofia */ + switch_mutex_lock(tech_pvt->sofia_mutex); + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n"); + sofia_clear_flag(tech_pvt, TFLAG_3PCC); + sofia_clear_flag(tech_pvt, TFLAG_3PCC_HAS_ACK); + switch_core_session_pass_indication(session, SWITCH_MESSAGE_INDICATE_ANSWER); + } + } else { + nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact), + TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)), TAG_END()); + } + switch_safe_free(extra_headers); + } + } + + } } break; case SWITCH_MESSAGE_INDICATE_RINGING: From a10ec2b991f83bb28b2a927796cc494c5d9b0d63 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 11 Jun 2012 13:30:00 -0500 Subject: [PATCH 072/101] FS-4299 --resolve regression from 23f8967c the code was not making sure both endpoints were type 'sofia' and dereferencing dingaling channel into sofia and causing memory corruption --- src/mod/endpoints/mod_sofia/sofia_glue.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 6376e86149..b08d7efc17 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3869,10 +3869,21 @@ static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size void sofia_glue_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session) { - switch_channel_t *aleg_channel = switch_core_session_get_channel(aleg_session); - private_object_t *aleg_tech_pvt = switch_core_session_get_private(aleg_session); - switch_channel_t *bleg_channel = switch_core_session_get_channel(bleg_session); - private_object_t *bleg_tech_pvt = switch_core_session_get_private(bleg_session); + switch_channel_t *aleg_channel; + private_object_t *aleg_tech_pvt; + switch_channel_t *bleg_channel; + private_object_t *bleg_tech_pvt; + + if (!switch_core_session_compare(aleg_session, bleg_session)) { + /* since this digs into channel internals its only compatible with sofia sessions*/ + return; + } + + aleg_channel = switch_core_session_get_channel(aleg_session); + aleg_tech_pvt = switch_core_session_get_private(aleg_session); + bleg_channel = switch_core_session_get_channel(bleg_session); + bleg_tech_pvt = switch_core_session_get_private(bleg_session); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Deciding whether to pass zrtp-hash between a-leg and b-leg\n"); if (!(switch_channel_test_flag(aleg_tech_pvt->channel, CF_ZRTP_PASSTHRU_REQ))) { switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "CF_ZRTP_PASSTHRU_REQ not set on a-leg, so not propagating zrtp-hash\n"); From 45fdf0db193f59417b0df76d6faadc5101ac0f59 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 11 Jun 2012 21:25:05 +0000 Subject: [PATCH 073/101] Add a .version file to nightly tarballs --- scripts/ci/debsrcbuilder.sh | 1 + scripts/ci/src_tarball.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/scripts/ci/debsrcbuilder.sh b/scripts/ci/debsrcbuilder.sh index e64093d120..1b81566fe8 100755 --- a/scripts/ci/debsrcbuilder.sh +++ b/scripts/ci/debsrcbuilder.sh @@ -28,6 +28,7 @@ mkdir -p $ddir git clone . $bdir cd $bdir set_fs_ver "$gver" "$gmajor" "$gminor" "$gmicro" "$grev" +echo "$gver" > .version cd libs getlib () { f="${1##*/}" diff --git a/scripts/ci/src_tarball.sh b/scripts/ci/src_tarball.sh index 0cab5f5d58..1c79f2fca1 100755 --- a/scripts/ci/src_tarball.sh +++ b/scripts/ci/src_tarball.sh @@ -22,6 +22,7 @@ cp -r . $dst_dir cd $dst_dir set_fs_ver "$gver" "$gmajor" "$gminor" "$gmicro" "$grev" +echo "$gver" > .version gnuize cd .. ls From c85c8d7bbd7602e6ae6e35d74224e31e3533a771 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Fri, 8 Jun 2012 22:06:55 +0000 Subject: [PATCH 074/101] Add mechanism to set OpenSSL session timeout In a sofia profile, you can now set the parameter tls-timeout to a positive integer value which represents the maximum time in seconds that OpenSSL will keep a TLS session (and its ephemeral keys) alive. This value is passed to OpenSSL's SSL_CTX_set_timeout(3). OpenSSL's default value is 300 seconds, but the relevant standard (RFC 2246) suggests that much longer session lifetimes are acceptable (it recommends values less than 24 hours). Longer values can be useful for extending battery life on mobile devices. Signed-off-by: Travis Cross --- libs/sofia-sip/.update | 2 +- .../libsofia-sip-ua/tport/sofia-sip/tport_tag.h | 6 ++++++ libs/sofia-sip/libsofia-sip-ua/tport/tport_tag.c | 13 +++++++++++++ libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c | 2 ++ libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h | 1 + .../libsofia-sip-ua/tport/tport_type_tls.c | 3 +++ src/mod/endpoints/mod_sofia/conf/sofia.conf.xml | 2 ++ src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia.c | 6 ++++++ 9 files changed, 35 insertions(+), 1 deletion(-) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index ade22984f2..cfded9d9e2 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Thu May 3 16:30:20 CDT 2012 +Sat Jun 9 03:24:47 UTC 2012 diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport_tag.h b/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport_tag.h index 6745cff1af..3abbbcbac4 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport_tag.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport_tag.h @@ -198,6 +198,12 @@ enum tport_tls_verify_policy { TPTLS_VERIFY_SUBJECTS_ALL = 0xF, }; +TPORT_DLL extern tag_typedef_t tptag_tls_timeout; +#define TPTAG_TLS_TIMEOUT(x) tptag_tls_timeout, tag_uint_v((x)) + +TPORT_DLL extern tag_typedef_t tptag_tls_timeout_ref; +#define TPTAG_TLS_TIMEOUT_REF(x) tptag_tls_timeout_ref, tag_uint_vr(&(x)) + TPORT_DLL extern tag_typedef_t tptag_tls_passphrase; #define TPTAG_TLS_PASSPHRASE(x) tptag_tls_passphrase, tag_str_v(x) diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tag.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tag.c index c10958a41f..495eaaf997 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tag.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tag.c @@ -280,6 +280,19 @@ tag_typedef_t tptag_compartment = PTRTAG_TYPEDEF(compartment); */ tag_typedef_t tptag_tls_version = UINTTAG_TYPEDEF(tls_version); +/**@def TPTAG_TLS_TIMEOUT(x) + * + * Sets the maximum TLS session lifetime in seconds. + * + * The default value is 300 seconds. + * + * Use with tport_tbind(), nua_create(), nta_agent_create(), + * nta_agent_add_tport(), nth_engine_create(), or initial nth_site_create(). + * + * @NEW_UNRELEASED. + */ +tag_typedef_t tptag_tls_timeout = UINTTAG_TYPEDEF(tls_timeout); + /**@def TPTAG_TLS_VERIFY_PEER(x) * @par Depreciated: * Alias for TPTAG_TLS_VERIFY_POLICY(TPTLS_VERIFY_IN|TPTLS_VERIFY_OUT) diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c index 2fffbde110..2facb30d0d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c @@ -311,6 +311,8 @@ int tls_init_context(tls_t *tls, tls_issues_t const *ti) return -1; } + SSL_CTX_set_timeout(tls->ctx, ti->timeout); + /* Set callback if we have a passphrase */ if (ti->passphrase != NULL) { SSL_CTX_set_default_passwd_cb(tls->ctx, passwd_cb); diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h index dbf6517196..702dcc9040 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.h @@ -65,6 +65,7 @@ typedef struct tls_issues_s { */ int version; /* For tls1, version is 1. When ssl3/ssl2 is * used, it is 0. */ + unsigned timeout; /* Maximum session lifetime in seconds */ } tls_issues_t; typedef struct tport_tls_s { diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c index 24f5d1b0fb..cd2ac9a9b6 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c @@ -181,6 +181,7 @@ static int tport_tls_init_master(tport_primary_t *pri, char *tbf = NULL; char const *path = NULL; unsigned tls_version = 1; + unsigned tls_timeout = 300; unsigned tls_verify = 0; char const *passphrase = NULL; unsigned tls_policy = TPTLS_VERIFY_NONE; @@ -198,6 +199,7 @@ static int tport_tls_init_master(tport_primary_t *pri, tl_gets(tags, TPTAG_CERTIFICATE_REF(path), TPTAG_TLS_VERSION_REF(tls_version), + TPTAG_TLS_TIMEOUT_REF(tls_timeout), TPTAG_TLS_VERIFY_PEER_REF(tls_verify), TPTAG_TLS_PASSPHRASE_REF(passphrase), TPTAG_TLS_VERIFY_POLICY_REF(tls_policy), @@ -224,6 +226,7 @@ static int tport_tls_init_master(tport_primary_t *pri, ti.cert = ti.key; ti.CAfile = su_sprintf(autohome, "%s/%s", path, "cafile.pem"); ti.version = tls_version; + ti.timeout = tls_timeout; ti.CApath = su_strdup(autohome, path); SU_DEBUG_9(("%s(%p): tls key = %s\n", __func__, (void *)pri, ti.key)); diff --git a/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml b/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml index 2e66602f1b..39c53d56d4 100644 --- a/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml +++ b/src/mod/endpoints/mod_sofia/conf/sofia.conf.xml @@ -242,6 +242,8 @@ + +