Implemented SWID REST API

This commit is contained in:
Andreas Steffen 2014-05-23 15:21:38 +02:00
parent 8c26db8c62
commit 344c9f91f3
6 changed files with 511 additions and 106 deletions

View File

@ -12,10 +12,12 @@ imcv_LTLIBRARIES = imv-swid.la
imv_swid_la_LIBADD = \
$(top_builddir)/src/libimcv/libimcv.la \
$(top_builddir)/src/libpts/libpts.la \
$(top_builddir)/src/libstrongswan/libstrongswan.la
$(top_builddir)/src/libstrongswan/libstrongswan.la \
-ljson
imv_swid_la_SOURCES = \
imv_swid.c imv_swid_state.h imv_swid_state.c \
imv_swid_agent.h imv_swid_agent.c
imv_swid_agent.h imv_swid_agent.c \
imv_swid_rest.h imv_swid_rest.c
imv_swid_la_LDFLAGS = -module -avoid-version -no-undefined

View File

@ -13,8 +13,12 @@
* for more details.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include "imv_swid_agent.h"
#include "imv_swid_state.h"
#include "imv_swid_rest.h"
#include "libpts.h"
#include "swid/swid_error.h"
@ -67,6 +71,11 @@ struct private_imv_swid_agent_t {
*/
imv_agent_t *agent;
/**
* REST API to strongTNC manager
*/
imv_swid_rest_t *rest_api;
};
METHOD(imv_agent_if_t, bind_functions, TNC_Result,
@ -101,7 +110,6 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
{
imv_swid_state_t *swid_state;
imv_msg_t *out_msg;
imv_session_t *session;
enumerator_t *enumerator;
pa_tnc_attr_t *attr;
TNC_Result result;
@ -115,20 +123,15 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
}
swid_state = (imv_swid_state_t*)state;
session = state->get_session(state);
/* analyze PA-TNC attributes */
enumerator = in_msg->create_attribute_enumerator(in_msg);
while (enumerator->enumerate(enumerator, &attr))
{
pen_type_t type;
uint32_t request_id, last_eid, eid_epoch;
uint32_t request_id = 0, last_eid, eid_epoch;
swid_inventory_t *inventory;
int tag_count;
char *tag_item;
imv_workitem_t *workitem, *found = NULL;
enumerator_t *et, *ew;
pen_type_t type;
type = attr->get_type(attr);
if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
@ -137,7 +140,7 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
pen_type_t error_code;
chunk_t msg_info, description;
bio_reader_t *reader;
uint32_t request_id = 0, max_attr_size;
uint32_t max_attr_size;
bool success;
error_attr = (ietf_attr_pa_tnc_error_t*)attr;
@ -200,8 +203,7 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
case TCG_SWID_TAG_ID_INVENTORY:
{
tcg_swid_attr_tag_id_inv_t *attr_cast;
swid_tag_id_t *tag_id;
chunk_t tag_creator, unique_sw_id;
int tag_id_count;
state->set_action_flags(state, IMV_SWID_ATTR_TAG_ID_INV);
@ -209,26 +211,21 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
request_id = attr_cast->get_request_id(attr_cast);
last_eid = attr_cast->get_last_eid(attr_cast, &eid_epoch);
inventory = attr_cast->get_inventory(attr_cast);
tag_item = "tag ID";
DBG2(DBG_IMV, "received SWID %s inventory for request %d "
"at eid %d of epoch 0x%08x", tag_item,
request_id, last_eid, eid_epoch);
tag_id_count = inventory->get_count(inventory);
et = inventory->create_enumerator(inventory);
while (et->enumerate(et, &tag_id))
DBG2(DBG_IMV, "received SWID tag ID inventory with %d items "
"for request %d at eid %d of epoch 0x%08x",
tag_id_count, request_id, last_eid, eid_epoch);
if (request_id == swid_state->get_request_id(swid_state))
{
tag_creator = tag_id->get_tag_creator(tag_id);
unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
DBG3(DBG_IMV, " %.*s_%.*s",
tag_creator.len, tag_creator.ptr,
unique_sw_id.len, unique_sw_id.ptr);
swid_state->set_swid_inventory(swid_state, inventory);
swid_state->set_count(swid_state, tag_id_count, 0);
}
et->destroy(et);
if (request_id == 0)
else
{
/* TODO handle subscribed messages */
break;
DBG1(DBG_IMV, "no workitem found for SWID tag ID inventory "
"with request ID %d", request_id);
}
break;
}
@ -237,6 +234,10 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
tcg_swid_attr_tag_inv_t *attr_cast;
swid_tag_t *tag;
chunk_t tag_encoding;
json_object *jarray, *jstring;
char *tag_str;
int tag_count;
enumerator_t *e;
state->set_action_flags(state, IMV_SWID_ATTR_TAG_INV);
@ -244,51 +245,50 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
request_id = attr_cast->get_request_id(attr_cast);
last_eid = attr_cast->get_last_eid(attr_cast, &eid_epoch);
inventory = attr_cast->get_inventory(attr_cast);
tag_item = "tag";
DBG2(DBG_IMV, "received SWID %s inventory for request %d "
"at eid %d of epoch 0x%08x", tag_item,
request_id, last_eid, eid_epoch);
tag_count = inventory->get_count(inventory);
et = inventory->create_enumerator(inventory);
while (et->enumerate(et, &tag))
{
tag_encoding = tag->get_encoding(tag);
DBG3(DBG_IMV, "%.*s", tag_encoding.len, tag_encoding.ptr);
}
et->destroy(et);
DBG2(DBG_IMV, "received SWID tag inventory with %d items for "
"request %d at eid %d of epoch 0x%08x",
tag_count, request_id, last_eid, eid_epoch);
if (request_id == 0)
if (request_id == swid_state->get_request_id(swid_state))
{
/* TODO handle subscribed messages */
break;
swid_state->set_count(swid_state, 0, tag_count);
if (this->rest_api)
{
jarray = json_object_new_array();
e = inventory->create_enumerator(inventory);
while (e->enumerate(e, &tag))
{
tag_encoding = tag->get_encoding(tag);
tag_str = strndup(tag_encoding.ptr, tag_encoding.len);
DBG3(DBG_IMV, "%s", tag_str);
jstring = json_object_new_string(tag_str);
json_object_array_add(jarray, jstring);
free(tag_str);
}
e->destroy(e);
if (this->rest_api->post(this->rest_api,
"swid/add-tags/", jarray, NULL) != SUCCESS)
{
DBG1(DBG_IMV, "error in REST API add-tags request");
}
json_object_put(jarray);
}
}
else
{
DBG1(DBG_IMV, "no workitem found for SWID tag inventory "
"with request ID %d", request_id);
}
break;
}
default:
continue;
}
ew = session->create_workitem_enumerator(session);
while (ew->enumerate(ew, &workitem))
{
if (workitem->get_id(workitem) == request_id)
{
found = workitem;
break;
}
}
if (found)
{
/* accumulate the swid tag [ID] count */
tag_count = inventory->get_count(inventory);
swid_state->set_count(swid_state, tag_count);
}
else
{
DBG1(DBG_IMV, "no workitem found for SWID %s inventory "
"with request ID %d", tag_item, request_id);
}
ew->destroy(ew);
}
enumerator->destroy(enumerator);
@ -382,7 +382,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
return TNC_RESULT_SUCCESS;
}
/* create an empty out message - we might need it */
/* Create an empty out message - we might need it */
out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
msg_types[0]);
@ -403,6 +403,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
return this->agent->provide_recommendation(this->agent, state);
}
/* Look for SWID tag workitem and create SWID tag request */
if (handshake_state == IMV_SWID_STATE_INIT &&
session->get_policy_started(session))
{
@ -431,13 +432,14 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
flags |= TCG_SWID_ATTR_REQ_FLAG_C;
}
request_id = workitem->get_id(workitem);
swid_state->set_request_id(swid_state, request_id);
attr = tcg_swid_attr_req_create(flags, request_id, 0);
out_msg->add_attribute(out_msg, attr);
workitem->set_imv_id(workitem, imv_id);
no_workitems = FALSE;
DBG2(DBG_IMV, "IMV %d issues SWID request %d",
imv_id, request_id);
break;
}
enumerator->destroy(enumerator);
@ -462,30 +464,140 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
{
TNC_IMV_Evaluation_Result eval;
TNC_IMV_Action_Recommendation rec;
char result_str[BUF_LEN], *tag_item;
int tag_count;
char result_str[BUF_LEN], *error_str = "", *command;
char *target, *separator;
int tag_id_count, tag_count, i;
chunk_t tag_creator, unique_sw_id;
json_object *jrequest, *jresponse, *jvalue;
tcg_swid_attr_req_t *cast_attr;
swid_tag_id_t *tag_id;
status_t status = SUCCESS;
enumerator = session->create_workitem_enumerator(session);
while (enumerator->enumerate(enumerator, &workitem))
if (this->rest_api)
{
if (workitem->get_type(workitem) == IMV_WORKITEM_SWID_TAGS)
if (asprintf(&command, "sessions/%d/swid_measurement/",
session->get_session_id(session, NULL, NULL)) < 0)
{
swid_state->get_count(swid_state, &tag_count);
tag_item = (received & IMV_SWID_ATTR_TAG_INV) ? "" : " ID";
snprintf(result_str, BUF_LEN, "received inventory of %d "
"SWID tag%s%s", tag_count, tag_item,
(tag_count == 1) ? "" : "s");
session->remove_workitem(session, enumerator);
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
rec = workitem->set_result(workitem, result_str, eval);
state->update_recommendation(state, rec, eval);
imcv_db->finalize_workitem(imcv_db, workitem);
workitem->destroy(workitem);
break;
error_str = "allocation of command string failed";
status = FAILED;
}
else
{
jrequest = swid_state->get_swid_inventory(swid_state);
status = this->rest_api->post(this->rest_api, command,
jrequest, &jresponse);
if (status == FAILED)
{
error_str = "error in REST API swid_measurement request";
}
free(command);
}
}
enumerator->destroy(enumerator);
switch (status)
{
case SUCCESS:
enumerator = session->create_workitem_enumerator(session);
while (enumerator->enumerate(enumerator, &workitem))
{
if (workitem->get_type(workitem) == IMV_WORKITEM_SWID_TAGS)
{
swid_state->get_count(swid_state, &tag_id_count,
&tag_count);
snprintf(result_str, BUF_LEN, "received inventory of "
"%d SWID tag ID%s and %d SWID tag%s",
tag_id_count, (tag_id_count == 1) ? "" : "s",
tag_count, (tag_count == 1) ? "" : "s");
session->remove_workitem(session, enumerator);
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
rec = workitem->set_result(workitem, result_str, eval);
state->update_recommendation(state, rec, eval);
imcv_db->finalize_workitem(imcv_db, workitem);
workitem->destroy(workitem);
break;
}
}
enumerator->destroy(enumerator);
break;
case NEED_MORE:
if (received & IMV_SWID_ATTR_TAG_INV)
{
error_str = "not all requested SWID tags were received";
status = FAILED;
json_object_put(jresponse);
break;
}
if (json_object_get_type(jresponse) != json_type_array)
{
error_str = "response was not a json_array";
status = FAILED;
json_object_put(jresponse);
break;
}
attr = tcg_swid_attr_req_create(TCG_SWID_ATTR_REQ_FLAG_NONE,
swid_state->get_request_id(swid_state), 0);
cast_attr = (tcg_swid_attr_req_t*)attr;
tag_id_count = json_object_array_length(jresponse);
DBG1(DBG_IMV, "%d SWID tag targets", tag_id_count);
for (i = 0; i < tag_id_count; i++)
{
jvalue = json_object_array_get_idx(jresponse, i);
if (json_object_get_type(jvalue) != json_type_string)
{
error_str = "json_string element expected in json_array";
status = FAILED;
json_object_put(jresponse);
break;
}
target = json_object_get_string(jvalue);
DBG1(DBG_IMV, " %s", target);
/* Separate target into tag_creator and unique_sw_id */
separator = strchr(target, '_');
if (!separator)
{
error_str = "separation of regid from "
"unique software ID failed";
break;
}
tag_creator = chunk_create(target, separator - target);
separator++;
unique_sw_id = chunk_create(separator, strlen(target) -
tag_creator.len - 1);
tag_id = swid_tag_id_create(tag_creator, unique_sw_id,
chunk_empty);
cast_attr->add_target(cast_attr, tag_id);
}
json_object_put(jresponse);
out_msg->add_attribute(out_msg, attr);
break;
case FAILED:
default:
break;
}
if (status == FAILED)
{
enumerator = session->create_workitem_enumerator(session);
while (enumerator->enumerate(enumerator, &workitem))
{
if (workitem->get_type(workitem) == IMV_WORKITEM_SWID_TAGS)
{
session->remove_workitem(session, enumerator);
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
rec = workitem->set_result(workitem, error_str, eval);
state->update_recommendation(state, rec, eval);
imcv_db->finalize_workitem(imcv_db, workitem);
workitem->destroy(workitem);
break;
}
}
enumerator->destroy(enumerator);
}
}
/* finalized all workitems ? */
@ -528,6 +640,7 @@ METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
METHOD(imv_agent_if_t, destroy, void,
private_imv_swid_agent_t *this)
{
DESTROY_IF(this->rest_api);
this->agent->destroy(this->agent);
free(this);
libpts_deinit();
@ -541,6 +654,7 @@ imv_agent_if_t *imv_swid_agent_create(const char *name, TNC_IMVID id,
{
private_imv_swid_agent_t *this;
imv_agent_t *agent;
char *rest_api_uri;
agent = imv_agent_create(name, msg_types, countof(msg_types), id,
actual_version);
@ -562,6 +676,12 @@ imv_agent_if_t *imv_swid_agent_create(const char *name, TNC_IMVID id,
.agent = agent,
);
rest_api_uri = lib->settings->get_str(lib->settings,
"%s.plugins.imv-swid.rest_api_uri", NULL, lib->ns);
if (rest_api_uri)
{
this->rest_api = imv_swid_rest_create(rest_api_uri);
}
libpts_init();
return &this->public;

View File

@ -0,0 +1,115 @@
/*
* Copyright (C) 2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include "imv_swid_rest.h"
typedef struct private_imv_swid_rest_t private_imv_swid_rest_t;
/**
* Private data of an imv_swid_rest_t object.
*/
struct private_imv_swid_rest_t {
/**
* Public members of imv_swid_rest_t
*/
imv_swid_rest_t public;
/**
* URI of REST API
*/
char *uri;
};
#define HTTP_STATUS_CODE_PRECONDITION_FAILED 412
METHOD(imv_swid_rest_t, post, status_t,
private_imv_swid_rest_t *this, char *command, json_object *jrequest,
json_object **jresponse)
{
struct json_tokener *tokener;
chunk_t data, response = chunk_empty;
u_int timeout = 30;
status_t status;
char *uri;
int code;
if (asprintf(&uri, "%s%s",this->uri, command) < 0)
{
return FAILED;
}
data = chunk_from_str(json_object_to_json_string(jrequest));
status = lib->fetcher->fetch(lib->fetcher, uri, &response,
FETCH_TIMEOUT, timeout,
FETCH_REQUEST_DATA, data,
FETCH_REQUEST_TYPE, "application/json; charset=utf-8",
FETCH_REQUEST_HEADER, "Accept: application/json",
FETCH_REQUEST_HEADER, "Expect:",
FETCH_RESPONSE_CODE, &code,
FETCH_END);
free(uri);
if (status == SUCCESS)
{
return SUCCESS;
}
if (code != HTTP_STATUS_CODE_PRECONDITION_FAILED || !response.ptr)
{
return FAILED;
}
if (jresponse)
{
/* Parse HTTP response into a JSON object */
tokener = json_tokener_new();
*jresponse = json_tokener_parse_ex(tokener, response.ptr, response.len);
json_tokener_free(tokener);
}
free(response.ptr);
return NEED_MORE;
}
METHOD(imv_swid_rest_t, destroy, void,
private_imv_swid_rest_t *this)
{
free(this->uri);
free(this);
}
/**
* Described in header.
*/
imv_swid_rest_t *imv_swid_rest_create(char *uri)
{
private_imv_swid_rest_t *this;
INIT(this,
.public = {
.post = _post,
.destroy = _destroy,
},
.uri = strdup(uri),
);
return &this->public;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup imv_swid imv_swid
* @ingroup libimcv_plugins
*
* @defgroup imv_swid_rest_t imv_swid_rest
* @{ @ingroup imv_swid
*/
#ifndef IMV_SWID_REST_H_
#define IMV_SWID_REST_H_
#include <library.h>
#include <json/json.h>
typedef struct imv_swid_rest_t imv_swid_rest_t;
/**
* Public REST interface
*/
struct imv_swid_rest_t {
/**
* Post a HTTP request including a JSON object
*
* @param jreq JSON object in HTTP request
* @param jresp JSON object in HTTP response if NEED_MORE
* @return Status (SUCCESS, NEED_MORE or FAILED)
*/
status_t (*post)(imv_swid_rest_t *this, char *command, json_object *jreq,
json_object **jresp);
/**
* Destroy imv_swid_rest_t object
*/
void (*destroy)(imv_swid_rest_t *this);
};
/**
* Create an imv_swid_rest_t instance
*
* @param uri REST URI (http://username:password@hostname[:port]/api/)
*/
imv_swid_rest_t* imv_swid_rest_create(char *uri);
#endif /** IMV_SWID_REST_H_ @}*/

View File

@ -14,9 +14,11 @@
*/
#include "imv_swid_state.h"
#include "imv/imv_lang_string.h"
#include "imv/imv_reason_string.h"
#include "imv/imv_remediation_string.h"
#include <imv/imv_lang_string.h>
#include <imv/imv_reason_string.h>
#include <imv/imv_remediation_string.h>
#include <swid/swid_tag_id.h>
#include <tncif_policy.h>
@ -96,9 +98,24 @@ struct private_imv_swid_state_t {
imv_remediation_string_t *remediation_string;
/**
* Number of processed SWID Tags or SWID Tag IDs
* SWID Tag Request ID
*/
int count;
uint32_t request_id;
/**
* Number of processed SWID Tag IDs
*/
int tag_id_count;
/**
* Number of processed SWID Tags
*/
int tag_count;
/**
* JSON array containing an inventory of SWID Tag IDs
*/
json_object *jarray;
/**
* Angel count
@ -215,6 +232,7 @@ METHOD(imv_state_t, get_remediation_instructions, bool,
METHOD(imv_state_t, destroy, void,
private_imv_swid_state_t *this)
{
json_object_put(this->jarray);
DESTROY_IF(this->session);
DESTROY_IF(this->reason_string);
DESTROY_IF(this->remediation_string);
@ -233,18 +251,68 @@ METHOD(imv_swid_state_t, get_handshake_state, imv_swid_handshake_state_t,
return this->handshake_state;
}
METHOD(imv_swid_state_t, set_count, void,
private_imv_swid_state_t *this, int count)
METHOD(imv_swid_state_t, set_request_id, void,
private_imv_swid_state_t *this, uint32_t request_id)
{
this->count += count;
this->request_id = request_id;
}
METHOD(imv_swid_state_t, get_request_id, uint32_t,
private_imv_swid_state_t *this)
{
return this->request_id;
}
METHOD(imv_swid_state_t, set_swid_inventory, void,
private_imv_swid_state_t *this, swid_inventory_t *inventory)
{
chunk_t tag_creator, unique_sw_id;
char software_id[256];
json_object *jstring;
swid_tag_id_t *tag_id;
enumerator_t *enumerator;
enumerator = inventory->create_enumerator(inventory);
while (enumerator->enumerate(enumerator, &tag_id))
{
/* Construct software ID from tag creator and unique software ID */
tag_creator = tag_id->get_tag_creator(tag_id);
unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
snprintf(software_id, 256, "%.*s_%.*s",
tag_creator.len, tag_creator.ptr,
unique_sw_id.len, unique_sw_id.ptr);
DBG3(DBG_IMV, " %s", software_id);
/* Add software ID to JSON array */
jstring = json_object_new_string(software_id);
json_object_array_add(this->jarray, jstring);
}
enumerator->destroy(enumerator);
}
METHOD(imv_swid_state_t, get_swid_inventory, json_object*,
private_imv_swid_state_t *this)
{
return this->jarray;
}
METHOD(imv_swid_state_t, set_count, void,
private_imv_swid_state_t *this, int tag_id_count, int tag_count)
{
this->tag_id_count += tag_id_count;
this->tag_count += tag_count;
}
METHOD(imv_swid_state_t, get_count, void,
private_imv_swid_state_t *this, int *count)
private_imv_swid_state_t *this, int *tag_id_count, int *tag_count)
{
if (count)
if (tag_id_count)
{
*count = this->count;
*tag_id_count = this->tag_id_count;
}
if (tag_count)
{
*tag_count = this->tag_count;
}
}
@ -290,6 +358,10 @@ imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id)
},
.set_handshake_state = _set_handshake_state,
.get_handshake_state = _get_handshake_state,
.set_request_id = _set_request_id,
.get_request_id = _get_request_id,
.set_swid_inventory = _set_swid_inventory,
.get_swid_inventory = _get_swid_inventory,
.set_count = _set_count,
.get_count = _get_count,
.set_angel_count = _set_angel_count,
@ -299,6 +371,7 @@ imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id)
.rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
.eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
.connection_id = connection_id,
.jarray = json_object_new_array(),
);
return &this->public.interface;

View File

@ -25,8 +25,11 @@
#define IMV_SWID_STATE_H_
#include <imv/imv_state.h>
#include <swid/swid_inventory.h>
#include <library.h>
#include <json/json.h>
typedef struct imv_swid_state_t imv_swid_state_t;
typedef enum imv_swid_handshake_state_t imv_swid_handshake_state_t;
@ -65,30 +68,60 @@ struct imv_swid_state_t {
imv_swid_handshake_state_t (*get_handshake_state)(imv_swid_state_t *this);
/**
* Set [or with multiple attributes increment] SWID Tag [ID] counters
* Set the SWID request ID
*
* @param count Number of received SWID Tags or SWID Tag IDs
* @param request_id SWID request ID to be set
*/
void (*set_count)(imv_swid_state_t *this, int count);
void (*set_request_id)(imv_swid_state_t *this, uint32_t request_id);
/**
* Get the SWID request ID
*
* @return SWID request ID
*/
uint32_t (*get_request_id)(imv_swid_state_t *this);
/**
* Set or extend the SWID Tag ID inventory in the state
*
* @param inventory SWID Tags ID inventory to be added
*/
void (*set_swid_inventory)(imv_swid_state_t *this, swid_inventory_t *inventory);
/**
* Get the encoding of the complete SWID Tag ID inventory
*
* @return SWID Tags ID inventory as a JSON array
*/
json_object* (*get_swid_inventory)(imv_swid_state_t *this);
/**
* Set [or with multiple attributes increment] SWID Tag [ID] counters
*
* @param count Number of received SWID Tags or SWID Tag IDs
* @param tag_id_count Number of received SWID Tag IDs
* @param tag_count Number of received SWID Tags
*/
void (*get_count)(imv_swid_state_t *this, int *count);
void (*set_count)(imv_swid_state_t *this, int tag_id_count, int tag_count);
/**
* Set [or with multiple attributes increment] SWID Tag [ID] counters
*
* @param tag_id_count Number of received SWID Tag IDs
* @param tag_count Number of received SWID Tags
*/
void (*get_count)(imv_swid_state_t *this, int *tag_id_count, int *tag_count);
/**
* Increase/Decrease the ITA Angel count
*
* @param start TRUE increases and FALSE decreases count by one
* @param start TRUE increases and FALSE decreases count by one
*/
void (*set_angel_count)(imv_swid_state_t *this, bool start);
/**
* Get the ITA Angel count
*
* @return ITA Angel count
* @return ITA Angel count
*/
int (*get_angel_count)(imv_swid_state_t *this);