switch_status_t fetch_reply(char *uuid_str, char *xml_str, switch_xml_binding_t *binding) { ei_xml_agent_t *agent; xml_fetch_reply_t *reply; switch_status_t status = SWITCH_STATUS_NOTFOUND; agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding); switch_mutex_lock(agent->replies_mutex); reply = agent->replies; while (reply != NULL) { if (!strncmp(reply->uuid_str, uuid_str, SWITCH_UUID_FORMATTED_LENGTH)) { if (!reply->xml_str) { reply->xml_str = xml_str; switch_thread_cond_broadcast(agent->new_reply); status = SWITCH_STATUS_SUCCESS; } break; } reply = reply->next; } switch_mutex_unlock(agent->replies_mutex); return status; }
void broadcast(void) { switch_mutex_lock(_mutex); _signaled = true; switch_thread_cond_broadcast(_condition); switch_mutex_unlock(_mutex); }
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_msg_fetch_reply(listener_t *listener, ei_x_buff * buf, ei_x_buff * rbuf) { char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; fetch_reply_t *p; if (ei_decode_string_or_binary(buf->buff, &buf->index, SWITCH_UUID_FORMATTED_LENGTH, uuid_str)) { ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "badarg"); } else { ei_x_buff *nbuf = malloc(sizeof(nbuf)); nbuf->buff = malloc(buf->buffsz); memcpy(nbuf->buff, buf->buff, buf->buffsz); nbuf->index = buf->index; nbuf->buffsz = buf->buffsz; switch_mutex_lock(globals.fetch_reply_mutex); if ((p = switch_core_hash_find(globals.fetch_reply_hash, uuid_str))) { /* Get the status and release the lock ASAP. */ enum { is_timeout, is_waiting, is_filled } status; if (p->state == reply_not_ready) { switch_thread_cond_wait(p->ready_or_found, globals.fetch_reply_mutex); } if (p->state == reply_waiting) { /* update the key with a reply */ status = is_waiting; p->reply = nbuf; p->state = reply_found; strncpy(p->winner, listener->peer_nodename, MAXNODELEN); switch_thread_cond_broadcast(p->ready_or_found); } else if (p->state == reply_timeout) { status = is_timeout; } else { status = is_filled; } put_reply_unlock(p, uuid_str); /* Relay the status back to the fetch responder. */ if (status == is_waiting) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found waiting slot for %s\n", uuid_str); ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "ok"); _ei_x_encode_string(rbuf, uuid_str); /* Return here to avoid freeing the reply. */ return SWITCH_STATUS_SUCCESS; } else if (status == is_timeout) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Handler for %s timed out\n", uuid_str); ei_x_encode_tuple_header(rbuf, 3); ei_x_encode_atom(rbuf, "error"); _ei_x_encode_string(rbuf, uuid_str); ei_x_encode_atom(rbuf, "timeout"); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found filled slot for %s\n", uuid_str); ei_x_encode_tuple_header(rbuf, 3); ei_x_encode_atom(rbuf, "error"); _ei_x_encode_string(rbuf, uuid_str); ei_x_encode_atom(rbuf, "duplicate_response"); } } else { /* nothing in the hash */ switch_mutex_unlock(globals.fetch_reply_mutex); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Empty slot for %s\n", uuid_str); ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "invalid_uuid"); } switch_safe_free(nbuf->buff); switch_safe_free(nbuf); } return SWITCH_STATUS_SUCCESS; }