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; char hash[100]; int arity; const void *key; void *val; session_elem_t *se; switch_hash_index_t *iter; ei_decode_tuple_header(buf->buff, &buf->index, &arity); if (ei_decode_ref(buf->buff, &buf->index, &ref)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid reference\n"); 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)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid pid in a reference/pid tuple\n"); return SWITCH_STATUS_FALSE; } ei_hash_ref(&ref, hash); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Hashed ref to %s\n", hash); 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); se = (session_elem_t*)val; 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; switch_thread_cond_broadcast(se->spawn_reply->ready_or_found); ei_x_encode_atom(rbuf, "ok"); switch_thread_rwlock_unlock(listener->session_rwlock); switch_mutex_unlock(se->spawn_reply->mutex); return SWITCH_STATUS_SUCCESS; } switch_mutex_unlock(se->spawn_reply->mutex); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "get_pid came in too late for %s; %s\n", hash, se->uuid_str); break; } } switch_thread_rwlock_unlock(listener->session_rwlock); ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "notfound"); switch_safe_free(pid); /* don't need it */ return SWITCH_STATUS_SUCCESS; }
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; char hash[100]; int arity; const void *key; void *val; session_elem_t *se; switch_hash_index_t *iter; int found = 0; ei_decode_tuple_header(buf->buff, &buf->index, &arity); if (ei_decode_ref(buf->buff, &buf->index, &ref)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid reference\n"); return SWITCH_STATUS_FALSE; } 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; } ei_hash_ref(&ref, hash); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Hashed ref to %s\n", hash); 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); se = (session_elem_t*)val; 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); 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); switch_mutex_unlock(se->spawn_reply->mutex); found++; break; } } switch_thread_rwlock_unlock(listener->session_rwlock); if (found) { ei_x_encode_atom(rbuf, "ok"); } else { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "notfound"); } return SWITCH_STATUS_SUCCESS; }