Exemple #1
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;
}
Exemple #2
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;
}
Exemple #3
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;
}
Exemple #4
0
/**
 * \brief This function tries to handle node_create command
 */
int vs_handle_taggroup_create(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *taggroup_create_cmd)
{
	struct VSNode			*node;
	struct VSTagGroup		*tg;
	struct VBucket			*vbucket;
	uint32 					node_id = UINT32(taggroup_create_cmd->data[0]);
	uint16 					taggroup_id = UINT16(taggroup_create_cmd->data[UINT32_SIZE]);
	uint16 					type = UINT16(taggroup_create_cmd->data[UINT32_SIZE+UINT16_SIZE]);
	int						ret = 0;

	/* Client has to send taggroup_create command with taggroup_id equal to
	 * the value 0xFFFF */
	if(taggroup_id != VRS_RESERVED_TAGGROUP_ID) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() taggroup_id: %d is not 0xFFFF\n",
				__FUNCTION__, taggroup_id);
		return 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;
	}

	vbucket = node->tag_groups.lb.first;
	/* Check, if there isn't tag group with the same type */
	while(vbucket != NULL) {
		tg = vbucket->data;
		if(tg->custom_type == type) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"%s() taggroup type: %d is already used in node: %d\n",
					__FUNCTION__, type, node->id);
			goto end;
		}
		vbucket = vbucket->next;
	}

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

	/* Try to create new tag group */
	tg = vs_taggroup_create(node, VRS_RESERVED_TAGGROUP_ID, type);
	if(tg == NULL) {
		goto end;
	} else {
		struct VSNodeSubscriber *node_subscriber;

		/* Set state for this entity */
		tg->state = ENTITY_CREATING;

		ret = 1;

		/* Send tag group create command to all subscribers to the node
		 * that can read this node */
		for(node_subscriber = node->node_subs.first;
				node_subscriber != NULL;
				node_subscriber = node_subscriber->next)
		{
			if( vs_node_can_read(node_subscriber->session, node) == 1) {
				if(vs_taggroup_send_create(node_subscriber, node, tg) != 1) {
					ret = 0;
				}
			}
		}
	}

end:

	pthread_mutex_unlock(&node->mutex);

	return ret;
}
Exemple #5
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;
}
Exemple #6
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;
}