예제 #1
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;
}
예제 #2
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;
	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;
}