示例#1
0
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);
    }
示例#3
0
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;
}
示例#4
0
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;
}