Exemplo n.º 1
0
/**
 * \brief This function tries to create link between parent and child. This
 * function does not check, if child had permission to be linked with parent
 * node. It has to be checked before this link. If link is successfully created,
 * then level of child node is updated. The link is not copied to the bucket!
 */
struct VSLink *vs_link_create(struct VSNode *parent, struct VSNode *child)
{
	struct VSLink *link = NULL;

	assert(parent != NULL);
	assert(child != NULL);

	link = (struct VSLink*)malloc(sizeof(struct VSLink));

	if( link != NULL ) {
		link->parent = parent;
		link->child = child;
		v_list_add_tail(&parent->children_links, link);
		child->parent_link = link;
		child->level = parent->level + 1;
		vs_node_inc_version(parent);
		vs_node_inc_version(child);
	} else {
		v_print_log(VRS_PRINT_WARNING,
				"Could not create link between %d and %d, not enough memory\n",
				parent->id, child->id);
	}

	return link;
}
Exemplo n.º 2
0
/**
 * \brief This function sends TagGroupCreate command to the client
 *
 * \param[in] *node_subscriber
 * \param[in] *node
 * \param[in] *tg
 *
 * \return This function return 1, when command was successfully created and
 * pushed to outgoing queue. When some error occur (already subscribed to
 * tag group, out of memory, etc.) then 0 is returned. When outgoing queue is
 * empty, then -1 is returned.
 */
int vs_taggroup_send_create(struct VSNodeSubscriber *node_subscriber,
		struct VSNode *node,
		struct VSTagGroup *tg)
{
	struct VSession			*vsession = node_subscriber->session;
	struct Generic_Cmd		*taggroup_create_cmd;
	struct VSEntityFollower	*taggroup_follower;

	/* Check if this tag group is in created/creating state */
	if(!(tg->state == ENTITY_CREATING || tg->state == ENTITY_CREATED)) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"This tag group: %d in node: %d is in %d state\n",
				tg->id, node->id, tg->state);
		return 0;
	}

	/* Check if this command, has not been already sent */
	taggroup_follower = tg->tg_folls.first;
	while(taggroup_follower != NULL) {
		if(taggroup_follower->node_sub->session->session_id == vsession->session_id ) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"Client already knows about this TagGroup: %d\n",
					tg->id);
			return 0;
		}
		taggroup_follower = taggroup_follower->next;
	}

	/* Create TagGroup create command */
	taggroup_create_cmd = v_taggroup_create_create(node->id, tg->id, tg->custom_type);

	/* Put this command to the outgoing queue */
	if(taggroup_create_cmd == NULL) {
		return 0;
	}

	if(v_out_queue_push_tail(vsession->out_queue,
			0,
			node_subscriber->prio,
			taggroup_create_cmd) == 0)
	{
		return -1;
	} else {
		/* Add this session to the list of session, that knows about this
		 * taggroup. Server could send them taggroup_destroy in the future. */
		taggroup_follower = (struct VSEntityFollower*)calloc(1, sizeof(struct VSEntityFollower));
		taggroup_follower->node_sub = node_subscriber;
		taggroup_follower->state = ENTITY_CREATING;
		v_list_add_tail(&tg->tg_folls, taggroup_follower);

		return 1;
	}

	return 0;
}
Exemplo n.º 3
0
/**
 * \brief This function sends Node_Create command to the subscriber of parent
 * node.
 */
int vs_node_send_create(struct VSNodeSubscriber *node_subscriber,
		struct VSNode *node,
		struct VSNode *avatar_node)
{
	struct Generic_Cmd		*node_create_cmd = NULL;
	struct VSEntityFollower	*node_follower;

	/* Check if this node is in created/creating state */
	if(!(node->state == ENTITY_CREATING || node->state == ENTITY_CREATED)) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"This node: %d is in %d state\n", node->id, node->state);
		return 0;
	}

	/* Check if this command, has not been already sent */
	node_follower = node->node_folls.first;
	while(node_follower != NULL) {
		if(node_follower->node_sub->session->session_id == node_subscriber->session->session_id &&
				(node_follower->state == ENTITY_CREATING ||
				 node_follower->state == ENTITY_CREATED))
		{
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"Client already knows about node: %d\n", node->id);
			return 0;
		}
		node_follower = node_follower->next;
	}

	if(avatar_node != NULL){
		node_create_cmd = v_node_create_create(node->id, avatar_node->id, node->owner->user_id, node->type);
	} else {
		node_create_cmd = v_node_create_create(node->id, node->parent_link->parent->id, node->owner->user_id, node->type);
	}

	if ( node_create_cmd != NULL &&
			v_out_queue_push_tail(node_subscriber->session->out_queue,
					node_subscriber->prio,
					node_create_cmd) == 1)
	{
		/* Add this session to the list of session, that knows about this
		 * node. Server could send them node_destroy in the future. */
		node_follower = (struct VSEntityFollower*)calloc(1, sizeof(struct VSEntityFollower));
		node_follower->node_sub = node_subscriber;
		node_follower->state = ENTITY_CREATING;
		v_list_add_tail(&node->node_folls, node_follower);

		return 1;
	}

	return 0;
}
Exemplo n.º 4
0
Arquivo: vs_tag.c Projeto: verse/verse
/**
 * \brief This function add TagCreate command to the queue of the session
 */
int vs_tag_send_create(struct VSEntitySubscriber *tg_subscriber,
                       struct VSNode *node,
                       struct VSTagGroup *tg,
                       struct VSTag *tag)
{
    struct Generic_Cmd *tag_create;
    struct VSEntityFollower	*tag_follower;

    /* Check if this tag is in created/creating state */
    if(!(tag->state == ENTITY_CREATING || tag->state == ENTITY_CREATED)) {
        v_print_log(VRS_PRINT_DEBUG_MSG,
                    "This tag: %d in node: %d and tg: %d, is in %d state\n",
                    tag->id, node->id, tg->id, tag->state);
        return 0;
    }

    /* Check if this command, has not been already sent */
    tag_follower = tag->tag_folls.first;
    while(tag_follower != NULL) {
        if(tag_follower->node_sub->session == tg_subscriber->node_sub->session) {
            return 0;
        }
        tag_follower = tag_follower->next;
    }

    /* Create new Tag_Create command */
    tag_create = v_tag_create_create(node->id, tg->id, tag->id, tag->data_type, tag->count, tag->custom_type);

    /* Put command to the outgoing queue */
    if(tag_create == NULL) {
        return 0;
    }

    if(v_out_queue_push_tail(tg_subscriber->node_sub->session->out_queue,
                             0,
                             tg_subscriber->node_sub->prio,
                             tag_create) == 0)
    {
        return -1;
    } else {
        tag_follower = (struct VSEntityFollower*)calloc(1, sizeof(struct VSEntityFollower));
        tag_follower->node_sub = tg_subscriber->node_sub;
        tag_follower->state = ENTITY_CREATING;
        v_list_add_tail(&tag->tag_folls, tag_follower);

        return 1;
    }

    return 0;
}
Exemplo n.º 5
0
int vs_layer_send_create(struct VSNodeSubscriber *node_subscriber,
		struct VSNode *node,
		struct VSLayer *layer)
{
	struct VSession			*vsession = node_subscriber->session;
	struct VSEntityFollower *layer_follower;
	struct Generic_Cmd		*layer_create_cmd;

	/* TODO: this could be more effective */
	/* Check if this command, has not been already sent */
	layer_follower = layer->layer_folls.first;
	while(layer_follower != NULL) {
		if(layer_follower->node_sub->session->session_id == node_subscriber->session->session_id) {
			v_print_log(VRS_PRINT_DEBUG_MSG, "Client already knows about this Layer: %d\n",
					layer->id);
			return 0;
		}
		layer_follower = layer_follower->next;
	}

	if(layer->parent != NULL) {
		layer_create_cmd = v_layer_create_create(node->id, layer->parent->id,
				layer->id, layer->data_type, layer->num_vec_comp, layer->type);
	} else {
		layer_create_cmd = v_layer_create_create(node->id, RESERVED_LAYER_ID,
				layer->id, layer->data_type, layer->num_vec_comp, layer->type);
	}

	if(layer_create_cmd != NULL &&
			v_out_queue_push_tail(vsession->out_queue, node_subscriber->prio, layer_create_cmd) == 1)
	{
		/* Add this session to the list of session, that knows about this
		 * layer. Server could send them layer_destroy in the future. */
		layer_follower = (struct VSEntityFollower*)calloc(1, sizeof(struct VSEntityFollower));
		layer_follower->node_sub = node_subscriber;
		layer_follower->state = ENTITY_CREATING;
		v_list_add_tail(&layer->layer_folls, layer_follower);

		return 1;
	}

	return 0;
}
Exemplo n.º 6
0
/**
 * \brief This function creates new layer
 *
 * \param[in]	*node		The pointer at node, where layer will be created
 * \param[in]	*parent		The pointer at parent layer
 * \param[in]	data_type	The type of values stored in layer
 * \param[in]	count		The count of values stored in one layer item
 * \param[in]	type		The client defined type of layer
 *
 * \return This function returns pointer at new created layer
 */
struct VSLayer *vs_layer_create(struct VSNode *node,
		struct VSLayer *parent,
		uint8 data_type,
		uint8 count,
		uint16 type)
{
	struct VSLayer *layer = calloc(1, sizeof(struct VSLayer));

	if(layer == NULL) {
		return NULL;
	}

	layer->prev = NULL;
	layer->next = NULL;
	layer->id = node->last_layer_id;
	node->last_layer_id++;
	layer->data_type = data_type;
	layer->type = type;
	layer->parent = parent;
	layer->num_vec_comp = count;

	v_hash_array_init(&layer->values,
				HASH_MOD_65536,
				offsetof(VSLayerValue, id),
				sizeof(uint32));

	/* When parent layer is not NULL, then add this layer to the linked list
	 * of child layers */
	if(parent != NULL) {
		v_list_add_tail(&parent->child_layers, layer);
	}
	/* Initialize linked list of child layers */
	layer->child_layers.first = layer->child_layers.last = NULL;

	layer->layer_folls.first = layer->layer_folls.last = NULL;
	layer->layer_subs.first = layer->layer_subs.last = NULL;

	layer->state = ENTITY_RESERVED;

	return layer;
}
Exemplo n.º 7
0
/**
 * \brief		This functions add empty packet to the history of the send packets.
 * \param[in]	*history	The structure with history of all sent packets and
 * commands.
 * \param[in]	id			The ID of packet, that will be add to the history of sent packets.
 * \return		This function returns pointer at structure VSent_Packet.
 */
struct VSent_Packet *v_packet_history_add_packet(struct VPacket_History *history,
		uint32 id)
{
	struct VSent_Packet *packet = NULL;

	packet = (struct VSent_Packet*)malloc(sizeof(struct VSent_Packet));

	/* Check if memory for sent packet was allocated */
	if(packet != NULL) {
		packet->cmds.first = NULL;
		packet->cmds.last = NULL;

		packet->id = id;

		v_print_log(VRS_PRINT_DEBUG_MSG, "Adding packet: %d to history\n", packet->id);

		v_list_add_tail(&history->packets, packet);
	} else {
		v_print_log(VRS_PRINT_DEBUG_MSG, "Unable to allocate enough memory for sent packet: %d\n", id);
	}

	return packet;
}
Exemplo n.º 8
0
/**
 * \brief This function add fake other users account to the list of user accounts
 */
int vs_add_other_users_account(struct VS_CTX *vs_ctx)
{
	struct VSUser *other_users;
	int ret = 0;

	other_users = (struct VSUser*)calloc(1, sizeof(struct VSUser));

	if(other_users != NULL) {
		other_users->username = strdup("others");
		other_users->password = NULL;
		other_users->password_hash = NULL;
		other_users->user_id = VRS_OTHER_USERS_UID;
		other_users->realname = strdup("Other Users");
		other_users->fake_user = 1;

		v_list_add_tail(&vs_ctx->users, other_users);

		vs_ctx->other_users = other_users;

		ret = 1;
	}

	return ret;
}
Exemplo n.º 9
0
/**
 * \brief This function handle node_subscribe command
 */
int vs_handle_taggroup_subscribe(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *taggroup_subscribe)
{
	struct VSNode	*node;
	uint32			node_id = UINT32(taggroup_subscribe->data[0]);
	uint16			taggroup_id = UINT16(taggroup_subscribe->data[UINT32_SIZE]);
	int				ret = 0;

	/* Try to find node */
	if((node = vs_node_find(vs_ctx, node_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() node (id: %d) not found\n",
				__FUNCTION__, node_id);
		return 0;
	}

	pthread_mutex_lock(&node->mutex);

	/* Node has to be created */
	if( vs_node_is_created(node) != 1 ) {
		goto end;
	}

	/* Is user owner of the node or can user read the node? */
	if(vs_node_can_read(vsession, node) == 1) {
		struct VSNodeSubscriber		*node_subscriber;
		struct VSTagGroup			*tg;
		struct VSTag				*tag;
		struct VSEntitySubscriber	*tg_subscriber;
		struct VBucket				*bucket;

		/* Try to find node subscriber */
		node_subscriber = node->node_subs.first;
		while(node_subscriber != NULL) {
			if(node_subscriber->session == vsession) {
				break;
			}
			node_subscriber = node_subscriber->next;
		}

		/* Client has to be subscribed to the node first */
		if(node_subscriber == NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"%s(): client has to be subscribed to the node: %d before subscribing to the tag_group: %d\n",
					__FUNCTION__, node_id, taggroup_id);
			goto end;
		}

		/* Try to find TagGroup */
		if( (tg = vs_taggroup_find(node, taggroup_id)) == NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"%s() tag_group (id: %d) in node (id: %d) not found\n",
					__FUNCTION__, taggroup_id, node_id);
			goto end;
		}

		/* Is Client already subscribed to this tag group? */
		tg_subscriber = tg->tg_subs.first;
		while(tg_subscriber != NULL) {
			if(tg_subscriber->node_sub->session->session_id == vsession->session_id) {
				v_print_log(VRS_PRINT_DEBUG_MSG,
						"%s() client already subscribed to the tag_group (id: %d) in node (id: %d)\n",
						__FUNCTION__, taggroup_id, node_id);
				goto end;
			}
			tg_subscriber = tg_subscriber->next;
		}

		ret = 1;

		/* Add new subscriber to the list of tag group subscribers */
		tg_subscriber = (struct VSEntitySubscriber*)malloc(sizeof(struct VSEntitySubscriber));
		tg_subscriber->node_sub = node_subscriber;
		v_list_add_tail(&tg->tg_subs, tg_subscriber);

		/* Send tag create for all tags in this tag group
		 * TODO: do not send all tags at once, when there is lot of tags in this
		 * tag group. Implement this, when queue limits will be finished. */
		bucket = tg->tags.lb.first;
		while(bucket != NULL) {
			tag = (struct VSTag*)bucket->data;
			if(tag->state == ENTITY_CREATING || tag->state == ENTITY_CREATED) {
				if(vs_tag_send_create(tg_subscriber, node, tg, tag) != 1) {
					ret = 0;
				}
			}
			bucket = bucket->next;
		}
	} else {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s(): user: %s doesn't have permissions to subscribe to taggroup: %d in node: %d\n",
				__FUNCTION__,
				((struct VSUser *)vsession->user)->username,
				taggroup_id, node->id);
	}

end:

	pthread_mutex_unlock(&node->mutex);

	return ret;
}
Exemplo n.º 10
0
/**
 * \brief This function handle changing link between nodes
 */
int vs_handle_link_change(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *node_link)
{
	struct VSUser			*user = (struct VSUser*)vsession->user;
	struct VSNode			*old_parent_node, *parent_node, *child_node;
	struct VSLink			*link;
	struct VSNodeSubscriber	*node_subscriber;
	struct VSEntityFollower *node_follower;
	uint32					parent_node_id = UINT32(node_link->data[0]);
	uint32					child_node_id = UINT32(node_link->data[UINT32_SIZE]);
	int						i;

	/* Try to find child node */
	if((child_node = vs_node_find(vs_ctx, child_node_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s():%d node (id: %d) not found\n",
				__FUNCTION__, __LINE__, child_node_id);
		return 0;
	}

	/* Child node has to be created */
	if(! (child_node->state == ENTITY_CREATED || child_node->state == ENTITY_CREATING)) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d node id: %d is not in NODE_CREATED state: %d\n",
				__FUNCTION__, __LINE__, child_node->id, child_node->state);
		return 0;
	}

	/* Is user owner of child node or can user write to child node? */
	if(vs_node_can_write(vsession, child_node) != 1) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d user: %s can't write to child node: %d (owner: %s)\n",
				__FUNCTION__, __LINE__, user->username, child_node->id,
				child_node->owner->username);
		return 0;
	}

	/* Old link */
	link = child_node->parent_link;

	/* Old parent node */
	old_parent_node = link->parent;

	/* Is user owner of old parent node or can user write to old parent node? */
	if(vs_node_can_write(vsession, old_parent_node) != 1) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d user: %s can't write to old parent node: %d (owner: %s)\n",
				__FUNCTION__, __LINE__, user->username, old_parent_node->id,
				old_parent_node->owner->username);
		return 0;
	}

	/* Try to find new parent node */
	if((parent_node = vs_node_find(vs_ctx, parent_node_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s():%d node (id: %d) not found\n",
				__FUNCTION__, __LINE__, parent_node_id);
		return 0;
	}

	/* Parent node has to be created */
	if(! (parent_node->state == ENTITY_CREATED || parent_node->state == ENTITY_CREATING)) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d node (id: %d) is not in NODE_CREATED state: %d\n",
				__FUNCTION__, __LINE__, parent_node->id, parent_node->state);
		return 0;
	}

	/* Test if client doesn't want to recreate existing link */
	if( parent_node == old_parent_node) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d link between nodes (parent_id: %d) (child_id: %d) already exists\n",
				__FUNCTION__, __LINE__, parent_node->id, child_node->id);
		return 0;
	}

	/* Is user owner of parent node or can user write to parent node? */
	if(vs_node_can_write(vsession, parent_node) != 1) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d user: %s can't write to parent node: %d (owner: %s)\n",
				__FUNCTION__, __LINE__, user->username, parent_node->id,
				parent_node->owner->username);
		return 0;
	}

	/* Test, if new link could be created */
	if(vs_link_test_nodes(parent_node, child_node) != 1) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d node: %d can't be child of node: %d\n",
				__FUNCTION__, __LINE__, child_node->id, parent_node->id);
		return 0;
	}

	/* Remove link from old parent node */
	v_list_rem_item(&old_parent_node->children_links, link);

	/* Add link to new parent node */
	v_list_add_tail(&parent_node->children_links, link);
	link->parent = parent_node;

	/* Update child node internal properties according new parent node */
	vs_link_update_child(parent_node, child_node);

	/* Update version in child node, parent node and old parent node */
	vs_node_inc_version(parent_node);
	vs_node_inc_version(child_node);
	vs_node_inc_version(old_parent_node);

	/* Subscribers of old and new parent node will receive information about
	 * changing link between nodes. Prevent double sending command Node_Link,
	 * when clients are subscribed to both nodes. */

	/* Set temporary value in all sessions */
	for(i=0; i<vs_ctx->max_sessions; i++) {
		vs_ctx->vsessions[i]->tmp = 0;
	}

	/* Send Node_Link command to subscribers of old parent node and set
	 * session temporary value */
	node_subscriber = old_parent_node->node_subs.first;
	while(node_subscriber != NULL) {
		if(vs_node_can_read(node_subscriber->session, old_parent_node) == 1) {
			node_subscriber->session->tmp = 1;
			vs_link_change_send(node_subscriber, link);
		}
		node_subscriber = node_subscriber->next;
	}

	/* When client is subscribed to the new parent node and aware of child
	 * node, then send to the client only node_link */
	node_follower = child_node->node_folls.first;
	while(node_follower != NULL) {
		if(node_follower->node_sub->session->tmp != 1) {
			vs_link_change_send(node_follower->node_sub, link);
			node_follower->node_sub->session->tmp = 1;
		}
		node_follower = node_follower->next;
	}

	/* Send Node_Create command to subscribers of new parent node, when
	 * subscribers were not subscribed to child node */
	node_subscriber = parent_node->node_subs.first;
	while(node_subscriber != NULL) {
		if(node_subscriber->session->tmp != 1) {
			if(vs_node_can_read(node_subscriber->session, parent_node) == 1) {
				vs_node_send_create(node_subscriber, child_node, NULL);
			}
		}
		node_subscriber = node_subscriber->next;
	}

	return 1;
}
Exemplo n.º 11
0
/**
 * \brief This function add VQueueCommand to the priority queue
 */
static void _v_out_queue_command_add(struct VPrioOutQueue *prio_queue,
		uint8 flag,
		uint8 share_addr,
		struct VOutQueueCommand *queue_cmd,
		struct Generic_Cmd *cmd)
{
	struct VOutQueueCommand *border_queue_cmd = NULL;

	/* Will be command added to then head or tail of queue? */
	if(flag & OUT_QUEUE_ADD_TAIL) {
		border_queue_cmd = prio_queue->cmds.last;
	} else if(flag & OUT_QUEUE_ADD_HEAD) {
		border_queue_cmd = prio_queue->cmds.first;
	}

	/* Add command to the end of new priority queue. If needed
	 * update counter of same commands in the queue */
	if(border_queue_cmd != NULL) {

		/* Is ID of this command same as ID of the last command
		 * in this priority queue? */
		if( (share_addr == 1) && (border_queue_cmd->id == queue_cmd->id)) {
			struct Generic_Cmd *border_cmd = (struct Generic_Cmd *)border_queue_cmd->vbucket->data;

			/* Is the last command in this priority queue and the
			 * first command with this ID? */
			if(border_queue_cmd->counter == NULL) {

				/* Set initial number of commands with same ID */
				border_queue_cmd->counter = (uint16*)malloc(sizeof(uint16));
				*border_queue_cmd->counter = 1;

				/* Compute size of address that could be shared */
				border_queue_cmd->share = (int8*)malloc(sizeof(int8));
				*border_queue_cmd->share = v_cmd_cmp_addr(border_cmd, cmd, 0xFF);

				/* Allocate memory for length of compressed commands */
				border_queue_cmd->len = (uint16*)malloc(sizeof(uint16));
				*border_queue_cmd->len = v_cmds_len(border_cmd, *border_queue_cmd->counter, *border_queue_cmd->share, 0);

			} else if(*border_queue_cmd->share > 0) {
				/* Try to update size of address that could be shared */
				*border_queue_cmd->share = v_cmd_cmp_addr(border_cmd, cmd, *border_queue_cmd->share);
			}

			/* Set up pointer */
			queue_cmd->counter = border_queue_cmd->counter;
			queue_cmd->share = border_queue_cmd->share;
			queue_cmd->len = border_queue_cmd->len;

			/* Update values */
			(*queue_cmd->counter)++;
			*queue_cmd->len = v_cmds_len(cmd, *queue_cmd->counter, *queue_cmd->share, *queue_cmd->len);
		} else {
			queue_cmd->counter = NULL;
			queue_cmd->share = NULL;
			queue_cmd->len = NULL;
		}
	}

	/* Will be command added to then head or tail of queue? */
	if(flag & OUT_QUEUE_ADD_TAIL) {
		v_list_add_tail(&prio_queue->cmds, queue_cmd);
	} else if(flag & OUT_QUEUE_ADD_HEAD) {
		v_list_add_head(&prio_queue->cmds, queue_cmd);
	}

}
static void cb_receive_node_create(const uint8 session_id,
		const uint32 node_id,
		const uint32 parent_id,
		const uint16 user_id,
		const uint16 custom_type)
{
#if NO_DEBUG_PRINT != 1
	printf("%s() session_id: %d, node_id: %d, parent_id: %d, user_id: %d, custom_type: %d\n",
			__FUNCTION__, session_id, node_id, parent_id, user_id, custom_type);
#endif

	if(user_id != ctx->verse.user_id) {
		return;
	}

	switch (custom_type) {
	case PARTICLE_SCENE_NODE:
		if(ctx->verse.particle_scene_node == NULL &&
				parent_id == VRS_SCENE_PARENT_NODE_ID ) {
			/* Create node of particle scene */
			ctx->verse.particle_scene_node = create_particle_scene_node(node_id);

			/* Add node to lookup table*/
			lu_add_item(ctx->verse.lu_table, node_id, ctx->verse.particle_scene_node);

			/* Subscribe to this node */
			vrs_send_node_subscribe(session_id, VRS_DEFAULT_PRIORITY, node_id, 0, 0);
		}
		break;
	case PARTICLE_SENDER_NODE:
		if(parent_id == ctx->verse.particle_scene_node->node_id &&
			v_list_count_items(&ctx->verse.particle_scene_node->senders) < (int32)ctx->sender_count)
		{
			struct ParticleSenderNode *sender_node = create_particle_sender_node(ctx->verse.particle_scene_node, node_id);
			struct Particle_Sender *sender;

			/* Find unassigned sender */
			sender = ctx->senders.first;
			while(sender != NULL) {
				if(sender->sender_node == NULL) {
					break;
				}
				sender = sender->next;
			}

			/* Set up references */
			if(sender != NULL) {
				printf("Info: setting up references\n");
				sender_node->sender = sender;
				sender->sender_node = sender_node;
			} else {
				printf("Error: no remaining free sender\n");
			}

			/* Add node to lookup table*/
			lu_add_item(ctx->verse.lu_table, node_id, sender_node);

			v_list_add_tail(&ctx->verse.particle_scene_node->senders, sender_node);

			vrs_send_node_subscribe(session_id, VRS_DEFAULT_PRIORITY, node_id, 0, 0);
		}
		break;
	}
}
Exemplo n.º 13
0
/**
 * \brief This function creates new node at verse server, when client sent
 * node_create command.
 */
static struct VSNode *vs_node_new(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		const uint16 type)
{
	struct VSNode *node = NULL;
	struct VSNode find_node, *avatar_node;
	struct VSUser *owner;
	struct VBucket *bucket;
	struct VSNodePermission *perm;
	struct VSNodeSubscriber *node_subscriber;

	/* Try to find avatar node to be able to create initial link to
	 * avatar node (initial parent of new created node) */
	find_node.id = vsession->avatar_id;
	bucket = v_hash_array_find_item(&vs_ctx->data.nodes, &find_node);
	if(bucket != NULL) {
		avatar_node = (struct VSNode*)bucket->data;
	} else {
		v_print_log(VRS_PRINT_DEBUG_MSG, "vsession->avatar_id: %d not found\n", vsession->avatar_id);
		goto end;
	}

	/* Try to find owner of the new node */
	if((owner = vs_user_find(vs_ctx, vsession->user_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "vsession->user_id: %d not found\n", vsession->user_id);
		goto end;
	}

	/* Try to create new verse node */
	if( (node = vs_node_create(vs_ctx, avatar_node, owner, VRS_RESERVED_NODE_ID, type)) == NULL) {
		goto end;
	}

	/* Set initial state of this node */
	node->state = ENTITY_CREATING;

	/* Find node representing fake user other_users */
	if( vs_ctx->other_users != NULL) {
		/* Set access permissions for other users */
		perm = (struct VSNodePermission *)calloc(1, sizeof(struct VSNodePermission));
		perm->user = vs_ctx->other_users;

		/* TODO: implement default session permissions and use them,
		 * when are available */

		perm->permissions = vs_ctx->default_perm;
		v_list_add_tail(&node->permissions, perm);
	}

	/* Send node_create to all subscribers of avatar node data */
	node_subscriber = avatar_node->node_subs.first;
	while(node_subscriber) {
		vs_node_send_create(node_subscriber, node, avatar_node);
		node_subscriber = node_subscriber->next;
	}


end:

	return node;
}
Exemplo n.º 14
0
/**
 * \brief This function add session (client) to the list of clients that are
 * subscribed this node.
 */
static int vs_node_subscribe(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct VSNode *node,
		uint32 version)
{
	struct VSNode				*child_node;
	struct VSNodePermission		*perm;
	struct VSNodeSubscriber		*node_subscriber;
	struct VSLink				*link;
	struct VBucket				*bucket;
	struct VSTagGroup			*tg;
	struct VSLayer				*layer;
	int							user_can_read = 0;

	/* Can user subscribe to this node? */
	user_can_read = vs_node_can_read(vs_ctx, vsession, node);

	/* Add current session to the list of node subscribers */
	node_subscriber = (struct VSNodeSubscriber*)calloc(1, sizeof(struct VSNodeSubscriber));
	node_subscriber->session = vsession;
	node_subscriber->prio = VRS_DEFAULT_PRIORITY;
	v_list_add_tail(&node->node_subs, node_subscriber);

	/* TODO: send node_subscribe with version and commands with difference
	 * between this version and current state, when versing will be supported */
	if(version != 0) {
		v_print_log(VRS_PRINT_WARNING, "Version: %d != 0, versing is not supported yet\n", version);
	}

	/* Send node_perm commands to the new subscriber */
	perm = node->permissions.first;
	while(perm != NULL) {
		vs_node_send_perm(node_subscriber, node, perm->user, perm->permissions);
		perm = perm->next;
	}

	/* If the node is locked, then send node_lock to the subscriber */
	if(node->lock.session != NULL) {
		vs_node_send_lock(node_subscriber, node->lock.session, node);
	}

	/* If user doesn't have permission to subscribe to this node, then send
	 * only node_perm command explaining, why user can't rest of this
	 * node */
	if(user_can_read == 0) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "Insufficient permission to read content of the node: %d\n", node->id);
		return 0;
	}

	/* Send node_create of all child nodes of this node and corresponding
	 * links */
	link = node->children_links.first;
	while(link!=NULL) {
		child_node = link->child;
		vs_node_send_create(node_subscriber, child_node, NULL);
		link = link->next;
	}

	/* Send taggroup_create of all tag_groups in this node */
	bucket = node->tag_groups.lb.first;
	while(bucket != NULL) {
		tg = (struct VSTagGroup*)bucket->data;
		if(tg->state == ENTITY_CREATING || tg->state == ENTITY_CREATED) {
			vs_taggroup_send_create(node_subscriber, node, tg);
		}
		bucket = bucket->next;
	}

	/* Send layer_create for all layers in this node */
	bucket = node->layers.lb.first;
	while(bucket != NULL) {
		layer = (struct VSLayer*)bucket->data;
		if(layer->state == ENTITY_CREATING || layer->state == ENTITY_CREATED) {
			vs_layer_send_create(node_subscriber, node, layer);
		}
		bucket = bucket->next;
	}

	return 1;
}
Exemplo n.º 15
0
/**
 * \brief This function add command to the history of sent command
 *
 * When this new added command updates some recent command with
 * the same address, then this command is set as obsolete. Pointer at this
 * command is set to NULL in previous packet.
 *
 * \param[in]	*history		The structure containing history of sent packets
 * and commands
 * \param[in]	*sent_packet	The current packet
 * \param[in]	*cmd			The data of command
 *
 * \return This function returns 1, when command was added to history.
 * When it wasn't able to add command to history, then zero is returned.
 */
int v_packet_history_add_cmd(struct VPacket_History *history,
		struct VSent_Packet *sent_packet,
		struct Generic_Cmd *cmd,
		uint8 prio)
{
	struct VSent_Command *sent_cmd;
	struct VBucket *vbucket;
	void *_cmd = (void*)cmd;
	uint8 cmd_id = cmd->id;
	uint16 cmd_size = v_cmd_struct_size(cmd);
	int ret = 0;

	/* Are duplications allowed for this type of commands? */
	if(history->cmd_hist[cmd_id]->flag & REMOVE_HASH_DUPS) {
		/* Try to find command with the same address */
		vbucket = v_hash_array_find_item(&history->cmd_hist[cmd_id]->cmds, _cmd);
		if(vbucket != NULL) {
			struct Generic_Cmd *obsolete_cmd = (struct Generic_Cmd*)vbucket->data;

			/* Bucket has to include not NULL pointer */
			assert(vbucket->ptr!=NULL);
			assert(vbucket->data!=NULL);

			/* Debug print */
#if 0
			v_print_log(VRS_PRINT_INFO, "Replacing obsolete command\n");
			v_cmd_print(VRS_PRINT_INFO, obsolete_cmd);
			v_cmd_print(VRS_PRINT_INFO, cmd);
#endif

			/* When old data are obsolete, then set pointer at command in old
			 * command to the NULL (obsolete command would not be re-send) */
			((struct VSent_Command*)(vbucket->ptr))->vbucket = NULL;

			/* Remove data with the same key as cmd_data has from hashed linked
			 * list */
			ret = v_hash_array_remove_item(&history->cmd_hist[cmd_id]->cmds, vbucket->data);

			if(ret == 1) {
				/* Destroy original command */
				v_cmd_destroy(&obsolete_cmd);
			} else {
				v_print_log(VRS_PRINT_DEBUG_MSG, "Could not remove obsolete command (id: %d) from history\n", cmd_id);
				ret = 0;
			}
		}
	}

	/* Add own command data to the hashed linked list */
	vbucket = v_hash_array_add_item(&history->cmd_hist[cmd_id]->cmds, _cmd, cmd_size);

	if(vbucket != NULL) {
		/* Create new command */
		sent_cmd = (struct VSent_Command*)malloc(sizeof(struct VSent_Command));
		/* Check if it was possible to allocate enough memory for sent command */
		if(sent_cmd != NULL) {
			sent_cmd->id = cmd_id;
			/* Add command to the linked list of sent packet */
			v_list_add_tail(&sent_packet->cmds, sent_cmd);
			/* Set up pointer at command data */
			sent_cmd->vbucket = vbucket;
			/* Set up pointer at owner of this command item to be able to obsolete
			 * this command in future */
			vbucket->ptr = (void*)sent_cmd;
			/* Store information about command priority. Lost commands should
			 * be re-send with same priority*/
			sent_cmd->prio = prio;

			ret = 1;
		} else {
			/* When memory wasn't allocated, then free bucket from hashed
			 * linked list */
			v_print_log(VRS_PRINT_ERROR, "Unable allocate enough memory for sent command\n");
			ret = v_hash_array_remove_item(&history->cmd_hist[cmd_id]->cmds, _cmd);
			if(ret == 1) {
				v_cmd_destroy(_cmd);
			}
			ret = 0;
		}
	} else {
		v_print_log(VRS_PRINT_ERROR, "Unable to add command (id: %d) to packet history\n", cmd_id);
		ret = 0;
	}

	return ret;
}
Exemplo n.º 16
0
int vs_handle_layer_subscribe(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *layer_subscribe_cmd)
{
	struct VSNode *node;
	struct VSUser *user;
	struct VSLayer *layer;
	struct VSNodeSubscriber *node_subscriber;
	struct VSEntitySubscriber *layer_subscriber;
	struct VBucket *vbucket;
	struct VSLayerValue *value;

	uint32 node_id = UINT32(layer_subscribe_cmd->data[0]);
	uint16 layer_id = UINT16(layer_subscribe_cmd->data[UINT32_SIZE]);
/*
	uint32 version = UINT32(layer_subscribe_cmd->data[UINT32_SIZE+UINT16_SIZE]);
	uint32 crc32 = UINT32(layer_subscribe_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE]);
*/

	/* Try to find node */
	if((node = vs_node_find(vs_ctx, node_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() node (id: %d) not found\n",
				__FUNCTION__, node_id);
		return 0;
	}

	/* Node has to be created */
	if(!(node->state == ENTITY_CREATED || node->state == ENTITY_CREATING)) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() node (id: %d) is not in CREATING or CREATED state: %d\n",
				__FUNCTION__, node->id, node->state);
		return 0;
	}

	/* Try to find user */
	if((user = vs_user_find(vs_ctx, vsession->user_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() vsession->user_id: %d not found\n",
				__FUNCTION__, vsession->user_id);
		return 0;
	}

	/* User has to have permission to read the node */
	if(vs_node_can_read(vs_ctx, vsession, node) != 1) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s(): user: %s can't read the node: %d\n",
				__FUNCTION__, user->username, node->id);
		return 0;
	}

	/* Try to find node subscriber */
	node_subscriber = node->node_subs.first;
	while(node_subscriber != NULL) {
		if(node_subscriber->session == vsession) {
			break;
		}
		node_subscriber = node_subscriber->next;
	}

	/* Client has to be subscribed to the node first */
	if(node_subscriber == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s(): client has to be subscribed to the node: %d before subscribing to the layer: %d\n",
				__FUNCTION__, node_id, layer_id);
		return 0;
	}

	/* Try to find layer */
	if( (layer = vs_layer_find(node, layer_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() layer (id: %d) in node (id: %d) not found\n",
				__FUNCTION__, layer_id, node_id);
		return 0;
	}

	/* Layer has to be created */
	if(! (layer->state == ENTITY_CREATING || layer->state == ENTITY_CREATED)) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() layer (id: %u) in node (id: %d) is not in CREATED state: %d\n",
				__FUNCTION__, layer->id, node->id, node->state);
		return 0;
	}

	/* Try to find layer subscriber (client can't be subscribed twice) */
	layer_subscriber = layer->layer_subs.first;
	while(layer_subscriber != NULL) {
		if(layer_subscriber->node_sub->session->session_id == vsession->session_id) {
			v_print_log(VRS_PRINT_DEBUG_MSG, "%s() client already subscribed to the layer (id: %d) in node (id: %d)\n",
									__FUNCTION__, layer_id, node_id);
			return 0;
		}
		layer_subscriber = layer_subscriber->next;
	}

	/* Add new subscriber to the list of layer subscribers */
	layer_subscriber = (struct VSEntitySubscriber*)malloc(sizeof(struct VSEntitySubscriber));
	layer_subscriber->node_sub = node_subscriber;
	v_list_add_tail(&layer->layer_subs, layer_subscriber);

	/* Send value set for all items in this layer
	 * TODO: do not push all values to outgoing queue at once, when there is lot
	 * of values in this layer. Implement this, when queue limits will be
	 * finished. */
	vbucket = layer->values.lb.first;
	while(vbucket != NULL) {
		value = (struct VSLayerValue*)vbucket->data;
		vs_layer_send_set_value(layer_subscriber, node, layer, value);
		vbucket = vbucket->next;
	}

	return 1;
}
static void cb_receive_node_create(const uint8 session_id,
		const uint32 node_id,
		const uint32 parent_id,
		const uint16 user_id,
		const uint16 custom_type)
{
	struct ParticleSenderNode *sender_node;
	struct Particle_Sender *sender;

#if NO_DEBUG_PRINT != 1
	printf("%s() session_id: %d, node_id: %d, parent_id: %d, user_id: %d, custom_type: %d\n",
			__FUNCTION__, session_id, node_id, parent_id, user_id, custom_type);
#endif

	if(user_id != ctx->verse.user_id) {
		return;
	}

	if(parent_id == ctx->verse.avatar_id) {
		switch(custom_type) {
		case PARTICLE_SCENE_NODE:
			if(ctx->verse.particle_scene_node == NULL) {
				/* Create node of particle scene */
				ctx->verse.particle_scene_node = create_particle_scene_node(node_id);

				/* Add node to lookup table*/
				lu_add_item(ctx->verse.lu_table, node_id, ctx->verse.particle_scene_node);

				vrs_send_node_link(session_id, VRS_DEFAULT_PRIORITY, VRS_SCENE_PARENT_NODE_ID, node_id);
				vrs_send_node_subscribe(session_id, VRS_DEFAULT_PRIORITY, node_id, 0, 0);
				vrs_send_taggroup_create(session_id, VRS_DEFAULT_PRIORITY, node_id, PARTICLE_SCENE_TG);
			}
			break;
		case PARTICLE_SENDER_NODE:
			if(v_list_count_items(&ctx->verse.particle_scene_node->senders) < (int32)ctx->sender_count) {
				sender_node = create_particle_sender_node(ctx->verse.particle_scene_node, node_id);

				/* Find unassigned sender */
				sender = ctx->senders.first;
				while(sender != NULL) {
					if(sender->sender_node == NULL) {
						break;
					}
					sender = sender->next;
				}

				/* Create reference */
				if(sender != NULL) {
					sender->sender_node = sender_node;
					sender_node->sender = sender;
				}

				/* Is it sender node created by this client */
				if(parent_id == ctx->verse.avatar_id) {
					ctx->sender = sender;
				}

				/* Add node to lookup table*/
				lu_add_item(ctx->verse.lu_table, node_id, sender_node);

				v_list_add_tail(&ctx->verse.particle_scene_node->senders, sender_node);

				vrs_send_node_subscribe(session_id, VRS_DEFAULT_PRIORITY,
						node_id, 0, 0);
				vrs_send_node_link(session_id, VRS_DEFAULT_PRIORITY,
						ctx->verse.particle_scene_node->node_id, node_id);
				vrs_send_taggroup_create(session_id, VRS_DEFAULT_PRIORITY,
						node_id, PARTICLE_SENDER_TG);
				vrs_send_layer_create(session_id, VRS_DEFAULT_PRIORITY,
						node_id, 0xFFFF, VRS_VALUE_TYPE_REAL32, 3, PARTICLE_POS_LAYER);
			}
			break;
		}
	}
}
Exemplo n.º 18
0
/**
 * \brief This function handle node_subscribe command
 */
int vs_handle_taggroup_subscribe(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *taggroup_subscribe)
{
	struct VSNode	*node;
	uint32			node_id = UINT32(taggroup_subscribe->data[0]);
	uint16			taggroup_id = UINT16(taggroup_subscribe->data[UINT32_SIZE]);
	int				ret = 0;

	/* Try to find node */
	if((node = vs_node_find(vs_ctx, node_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() node (id: %d) not found\n",
				__func__, node_id);
		return 0;
	}

	pthread_mutex_lock(&node->mutex);

	/* Node has to be created */
	if( vs_node_is_created(node) != 1 ) {
		goto end;
	}

	/* Is user owner of the node or can user read the node? */
	if(vs_node_can_read(vsession, node) == 1) {
		struct VSNodeSubscriber		*node_subscriber;
		struct VSTagGroup			*tg;
		struct VSTag				*tag;
		struct VSEntitySubscriber	*tg_subscriber;
		struct VBucket				*bucket;

		/* Try to find node subscriber */
		node_subscriber = node->node_subs.first;
		while(node_subscriber != NULL) {
			if(node_subscriber->session == vsession) {
				break;
			}
			node_subscriber = node_subscriber->next;
		}

		/* Client has to be subscribed to the node first */
		if(node_subscriber == NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"%s(): client has to be subscribed to the node: %d before subscribing to the tag_group: %d\n",
					__func__, node_id, taggroup_id);
			goto end;
		}

		/* Try to find TagGroup */
		if( (tg = vs_taggroup_find(node, taggroup_id)) == NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"%s() tag_group (id: %d) in node (id: %d) not found\n",
					__func__, taggroup_id, node_id);
			goto end;
		}

		/* Is Client already subscribed to this tag group? */
		tg_subscriber = tg->tg_subs.first;
		while(tg_subscriber != NULL) {
			if(tg_subscriber->node_sub->session->session_id == vsession->session_id) {
				v_print_log(VRS_PRINT_DEBUG_MSG,
						"%s() client already subscribed to the tag_group (id: %d) in node (id: %d)\n",
						__func__, taggroup_id, node_id);
				goto end;
			}
			tg_subscriber = tg_subscriber->next;
		}

		ret = 1;

		/* Add new subscriber to the list of tag group subscribers */
		tg_subscriber = (struct VSEntitySubscriber*)malloc(sizeof(struct VSEntitySubscriber));
		tg_subscriber->node_sub = node_subscriber;
		v_list_add_tail(&tg->tg_subs, tg_subscriber);

		/* Try to send tag_create for all tags in this tag group */
		bucket = tg->tags.lb.first;
		while(bucket != NULL) {
			tag = (struct VSTag*)bucket->data;
			vs_tag_send_create(tg_subscriber, node, tg, tag);
			/* When TCP/WebSocket is used and tag is initialized, then it
			 * is possible (necessary) to send value too. */
			if( ((vsession->flags & VRS_TP_TCP) ||
					(vsession->flags & VRS_TP_WEBSOCKET)) &&
					(tag->flag & TAG_INITIALIZED))
			{
				vs_tag_send_set(vsession, node_subscriber->prio, node, tg, tag);
			}
			bucket = bucket->next;
		}
	} else {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s(): user: %s doesn't have permissions to subscribe to taggroup: %d in node: %d\n",
				__func__,
				((struct VSUser *)vsession->user)->username,
				taggroup_id, node->id);
	}

end:

	pthread_mutex_unlock(&node->mutex);

	return ret;
}