/** * \brief This function tries to handle Tag_Destroy command */ int vs_handle_tag_destroy(struct VS_CTX *vs_ctx, struct VSession *vsession, struct Generic_Cmd *tag_destroy) { struct VSNode *node; struct VSTagGroup *tg; struct VSTag *tag; uint32 node_id = UINT32(tag_destroy->data[0]); uint16 taggroup_id = UINT16(tag_destroy->data[UINT32_SIZE]); uint16 tag_id = UINT16(tag_destroy->data[UINT32_SIZE + UINT16_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 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 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; } /* Try to find Tag */ if ( (tag = vs_tag_find(tg, tag_id)) == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag (id: %d) in tag_group (id: %d), node (id: %d) not found\n", __FUNCTION__, tag_id, taggroup_id, node_id); goto end; } ret = vs_tag_send_destroy(node, tg, tag); end: pthread_mutex_unlock(&node->mutex); return ret; }
/** * \brief This function handle taggroup_unsubscribe command */ int vs_handle_taggroup_unsubscribe(struct VS_CTX *vs_ctx, struct VSession *vsession, struct Generic_Cmd *taggroup_unsubscribe) { struct VSNode *node; struct VSTagGroup *tg; uint32 node_id = UINT32(taggroup_unsubscribe->data[0]); uint16 taggroup_id = UINT16(taggroup_unsubscribe->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 ) { ret = 0; } else { /* 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); ret = 0; } else { ret = vs_taggroup_unsubscribe(tg, vsession); } } pthread_mutex_unlock(&node->mutex); return ret; }
/** * \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; }
/** * \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; }
/** * \brief This function tries to handle Tag_Set_Int8 command */ int vs_handle_tag_set(struct VS_CTX *vs_ctx, struct VSession *vsession, struct Generic_Cmd *tag_set, uint8 data_type, uint8 count) { struct VSNode *node; struct VSTagGroup *tg; struct VSTag *tag; struct VSEntitySubscriber *tg_subscriber; uint32 node_id; uint16 taggroup_id; uint16 tag_id; int ret = 0; node_id = UINT32(tag_set->data[0]); taggroup_id = UINT16(tag_set->data[UINT32_SIZE]); tag_id = UINT16(tag_set->data[UINT32_SIZE + UINT16_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; } pthread_mutex_lock(&node->mutex); /* Node has to be created */ if(vs_node_is_created(node) != 1) { goto end; } /* 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 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; } /* Try to find Tag */ if ( (tag = vs_tag_find(tg, tag_id)) == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag (id: %d) in tag_group (id: %d), node (id: %d) not found\n", __FUNCTION__, tag_id, taggroup_id, node_id); goto end; } /* Data type has to match */ if(data_type != tag->data_type) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() data type (%d) of tag (id: %d) in tg (id: %d) in node (id: %d) does not match data type of received command (%d)\n", __FUNCTION__, tag->data_type, tag_id, taggroup_id, node_id, data_type); goto end; } /* Count of values has to match */ if(count != tag->count) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() count of values (%d) of tag (id: %d) in tg (id: %d) in node (id: %d) does not match count of values of received command (%d)\n", __FUNCTION__, tag->count, tag_id, taggroup_id, node_id, count); goto end; } /* Set value in tag */ switch(tag->data_type) { case VRS_VALUE_TYPE_UINT8: memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], UINT8_SIZE*tag->count); break; case VRS_VALUE_TYPE_UINT16: memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], UINT16_SIZE*tag->count); break; case VRS_VALUE_TYPE_UINT32: memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], UINT32_SIZE*tag->count); break; case VRS_VALUE_TYPE_UINT64: memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], UINT64_SIZE*tag->count); break; case VRS_VALUE_TYPE_REAL16: memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], REAL16_SIZE*tag->count); break; case VRS_VALUE_TYPE_REAL32: memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], REAL32_SIZE*tag->count); break; case VRS_VALUE_TYPE_REAL64: memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], REAL64_SIZE*tag->count); break; case VRS_VALUE_TYPE_STRING8: if(tag->value == NULL) { tag->value = strdup(PTR(tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE])); } else { size_t new_str_len = strlen(PTR(tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE])); size_t old_str_len = strlen((char*)tag->value); /* Rewrite old string */ if(new_str_len == old_str_len) { strcpy((char*)tag->value, PTR(tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE])); } else { tag->value = (char*)realloc(tag->value, new_str_len*sizeof(char)); strcpy((char*)tag->value, PTR(tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE])); } } break; default: assert(0); break; } ret = 1; /* Set this tag as initialized, because value of this tag was set. */ tag->flag = TAG_INITIALIZED; vs_taggroup_inc_version(tg); /* Send this tag to all client subscribed to the TagGroup */ tg_subscriber = tg->tg_subs.first; while(tg_subscriber != NULL) { if(vs_tag_send_set(tg_subscriber->node_sub->session, tg_subscriber->node_sub->prio, node, tg, tag) != 1) { ret = 0; } tg_subscriber = tg_subscriber->next; } end: pthread_mutex_unlock(&node->mutex); return ret; }
/** * \brief This function tries to handle Tag_Create command */ int vs_handle_tag_create(struct VS_CTX *vs_ctx, struct VSession *vsession, struct Generic_Cmd *tag_create) { struct VSNode *node; struct VSTagGroup *tg; struct VSTag *tag; struct VBucket *vbucket; struct VSEntitySubscriber *tg_subscriber; uint32 node_id = UINT32(tag_create->data[0]); uint16 taggroup_id = UINT16(tag_create->data[UINT32_SIZE]); uint16 tag_id = UINT16(tag_create->data[UINT32_SIZE + UINT16_SIZE]); uint8 data_type = UINT8(tag_create->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE]); uint8 count = UINT8(tag_create->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE + UINT8_SIZE]); uint16 type = UINT16(tag_create->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE + UINT8_SIZE + UINT8_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; } /* User has to have permission to write to the 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 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; } /* Tag Group has to be created too (it can't be in DELETING or DELETED state ) */ if(!(tg->state == ENTITY_CREATED || tg->state == ENTITY_CREATING)) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag group (id: %d) from node (id: %d) is not in CREATING or CREATED state: %d\n", __FUNCTION__, tg->id, node->id, tg->state); goto end; } /* Client has to send tag_create command with tag_id equal to * the value 0xFFFF */ if(tag_id != RESERVED_TAG_ID) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag_id: %d is not 0xFFFF\n", __FUNCTION__, tag_id); goto end; } /* Is type of Tag supported? */ if(!(data_type>VRS_VALUE_TYPE_RESERVED && data_type<=VRS_VALUE_TYPE_STRING8)) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag_type: %d is not supported\n", __FUNCTION__, data_type); goto end; } vbucket = tg->tags.lb.first; /* Check, if there isn't tag with the same type */ while(vbucket != NULL) { tag = vbucket->data; if(tag->custom_type == type) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag type: %d is already used in taggroup: %d\n", __FUNCTION__, type, tg->id); goto end; } vbucket = vbucket->next; } if (v_hash_array_count_items(&tg->tags) > MAX_TAGS_COUNT) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() max number of tags in node: %d tag_group: %d was reached\n", tg->id); goto end; } /* Try to create new tag */ tag = vs_tag_create(tg, RESERVED_TAG_ID, data_type, count, type); if(tag == NULL) { goto end; } ret = 1; tag->state = ENTITY_CREATING; /* Send TagCreate to all subscribers of tag group */ tg_subscriber = tg->tg_subs.first; while(tg_subscriber != NULL) { if(vs_tag_send_create(tg_subscriber, node, tg, tag) != 1) { ret = 0; } tg_subscriber = tg_subscriber->next; } end: pthread_mutex_unlock(&node->mutex); return ret; }
/** * \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; }