/** * \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; }
/** * \brief This function is called, when server receives command layer_create * * \param[in] *vs_ctx The pointer at verse server context * \param[in] *vsession The pointer at session of client that sent this command * \param[in] *layer_create_cmd The pointer at received command * * \return This function returns 0, when parameters of received command are * wrong. When all parameters are right, then it returns 1. */ int vs_handle_layer_create(struct VS_CTX *vs_ctx, struct VSession *vsession, struct Generic_Cmd *layer_create_cmd) { struct VSNode *node; struct VSUser *user; struct VSLayer *parent_layer; struct VSLayer *layer; struct VBucket *vbucket; struct VSNodeSubscriber *node_subscriber; uint32 node_id = UINT32(layer_create_cmd->data[0]); uint16 parent_layer_id = UINT16(layer_create_cmd->data[UINT32_SIZE]); uint16 layer_id = UINT16(layer_create_cmd->data[UINT32_SIZE+UINT16_SIZE]); uint8 data_type = UINT16(layer_create_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT16_SIZE]); uint8 count = UINT16(layer_create_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT16_SIZE+UINT8_SIZE]); uint16 type = UINT16(layer_create_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT16_SIZE+UINT8_SIZE+UINT8_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; } /* When parent layer id is not -1, then try to find this parent layer */ if(parent_layer_id == RESERVED_LAYER_ID) { parent_layer = NULL; } else { parent_layer = vs_layer_find(node, parent_layer_id); if(parent_layer == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() parent layer (id: %d) in node (id: %d) not found\n", __FUNCTION__, parent_layer_id, 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 write to the node */ if(vs_node_can_write(vs_ctx, vsession, node) != 1) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s(): user: %s can't write to node: %d\n", __FUNCTION__, user->username, node->id); return 0; } /* Client has to send layer_create command with layer_id equal to * the value 0xFFFF */ if(layer_id != RESERVED_LAYER_ID) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() layer_id: %d is not 0xFFFF\n", __FUNCTION__, layer_id); return 0; } /* Is type of Layer supported? */ if(!(data_type>VRS_VALUE_TYPE_RESERVED && data_type<=VRS_VALUE_TYPE_REAL64)) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() data_type: %d is not supported\n", __FUNCTION__, data_type); return 0; } vbucket = node->layers.lb.first; /* Check, if there isn't tag with the same type */ while(vbucket != NULL) { layer = vbucket->data; if(layer->type == type) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() layer type: %d is already used in layer: %d\n", __FUNCTION__, type, layer->id); return 0; } vbucket = vbucket->next; } if (v_hash_array_count_items(&node->layers) > MAX_LAYERS_COUNT) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() max number of layers in node: %d was reached\n", node->id); return 0; } layer = vs_layer_create(node, parent_layer, data_type, count, type); /* Try to find first free id for layer */ /* TODO: this could be more effective */ layer->id = node->last_layer_id; while( v_hash_array_find_item(&node->layers, layer) != NULL ) { layer->id++; if(layer->id > LAST_LAYER_ID) { layer->id = FIRST_LAYER_ID; } } node->last_layer_id = layer->id; /* Try to add new Tag to the hashed linked list of tags */ vbucket = v_hash_array_add_item(&node->layers, (void*)layer, sizeof(struct VSLayer)); if(vbucket==NULL) { free(layer); return 0; } layer->state = ENTITY_CREATING; /* Send layer_create to all node subscribers */ node_subscriber = node->node_subs.first; while(node_subscriber != NULL) { vs_layer_send_create(node_subscriber, node, layer); node_subscriber = node_subscriber->next; } return 0; }