diff --git a/src/shared/mgmt.c b/src/shared/mgmt.c
index 41457b4..95229c2 100644
--- a/src/shared/mgmt.c
+++ b/src/shared/mgmt.c
#include "src/shared/queue.h"
#include "src/shared/util.h"
#include "src/shared/mgmt.h"
+#include "src/shared/timeout.h"
struct mgmt {
int ref_count;
};
struct mgmt_request {
+ struct mgmt *mgmt;
unsigned int id;
uint16_t opcode;
uint16_t index;
mgmt_request_func_t callback;
mgmt_destroy_func_t destroy;
void *user_data;
+ int timeout;
+ unsigned int timeout_id;
};
struct mgmt_notify {
if (request->destroy)
request->destroy(request->user_data);
+ if (request->timeout_id)
+ timeout_remove(request->timeout_id);
+
free(request->buf);
free(request);
}
mgmt->writer_active = false;
}
+static bool request_timeout(void *data)
+{
+ struct mgmt_request *request = data;
+
+ if (!request)
+ return false;
+
+ request->timeout_id = 0;
+
+ queue_remove_if(request->mgmt->pending_list, NULL, request);
+
+ if (request->callback)
+ request->callback(MGMT_STATUS_TIMEOUT, 0, NULL,
+ request->user_data);
+
+ destroy_request(request);
+
+ return false;
+}
+
static bool send_request(struct mgmt *mgmt, struct mgmt_request *request)
{
struct iovec iov;
return false;
}
+ if (request->timeout)
+ request->timeout_id = timeout_add_seconds(request->timeout,
+ request_timeout,
+ request,
+ NULL);
+
util_debug(mgmt->debug_callback, mgmt->debug_data,
"[0x%04x] command 0x%04x",
request->index, request->opcode);
static struct mgmt_request *create_request(struct mgmt *mgmt, uint16_t opcode,
uint16_t index, uint16_t length,
const void *param, mgmt_request_func_t callback,
- void *user_data, mgmt_destroy_func_t destroy)
+ void *user_data, mgmt_destroy_func_t destroy,
+ int timeout)
{
struct mgmt_request *request;
struct mgmt_hdr *hdr;
hdr->index = htobs(index);
hdr->len = htobs(length);
+ /* Use a weak reference so requests don't prevent mgmt_unref to
+ * cancel requests and free in case of the last reference is dropped by
+ * the user.
+ */
+ request->mgmt = mgmt;
request->opcode = opcode;
request->index = index;
request->callback = callback;
request->destroy = destroy;
request->user_data = user_data;
+ request->timeout = timeout;
return request;
}
return ret;
}
-unsigned int mgmt_send(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
- uint16_t length, const void *param,
- mgmt_request_func_t callback,
- void *user_data, mgmt_destroy_func_t destroy)
+unsigned int mgmt_send_timeout(struct mgmt *mgmt, uint16_t opcode,
+ uint16_t index, uint16_t length,
+ const void *param, mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy,
+ int timeout)
{
struct mgmt_request *request;
return 0;
request = create_request(mgmt, opcode, index, length, param,
- callback, user_data, destroy);
+ callback, user_data, destroy, timeout);
if (!request)
return 0;
return request->id;
}
+unsigned int mgmt_send(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
+ uint16_t length, const void *param,
+ mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy)
+{
+ return mgmt_send_timeout(mgmt, opcode, index, length, param, callback,
+ user_data, destroy, 0);
+}
+
unsigned int mgmt_send_nowait(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
return 0;
request = create_request(mgmt, opcode, index, length, param,
- callback, user_data, destroy);
+ callback, user_data, destroy,
+ 0);
if (!request)
return 0;
return request->id;
}
-unsigned int mgmt_reply(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
- uint16_t length, const void *param,
- mgmt_request_func_t callback,
- void *user_data, mgmt_destroy_func_t destroy)
+unsigned int mgmt_reply_timeout(struct mgmt *mgmt, uint16_t opcode,
+ uint16_t index, uint16_t length,
+ const void *param, mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy,
+ int timeout)
{
struct mgmt_request *request;
return 0;
request = create_request(mgmt, opcode, index, length, param,
- callback, user_data, destroy);
+ callback, user_data, destroy, timeout);
if (!request)
return 0;
return request->id;
}
+unsigned int mgmt_reply(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
+ uint16_t length, const void *param,
+ mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy)
+{
+ return mgmt_reply_timeout(mgmt, opcode, index, length, param, callback,
+ user_data, destroy, 0);
+}
+
bool mgmt_cancel(struct mgmt *mgmt, unsigned int id)
{
struct mgmt_request *request;
diff --git a/src/shared/mgmt.h b/src/shared/mgmt.h
index 56add61..b413cea 100644
--- a/src/shared/mgmt.h
+++ b/src/shared/mgmt.h
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy);
+unsigned int mgmt_send_timeout(struct mgmt *mgmt, uint16_t opcode,
+ uint16_t index, uint16_t length,
+ const void *param, mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy,
+ int timeout);
unsigned int mgmt_send_nowait(struct mgmt *mgmt, uint16_t opcode, uint16_t index,
uint16_t length, const void *param,
mgmt_request_func_t callback,
uint16_t length, const void *param,
mgmt_request_func_t callback,
void *user_data, mgmt_destroy_func_t destroy);
+unsigned int mgmt_reply_timeout(struct mgmt *mgmt, uint16_t opcode,
+ uint16_t index, uint16_t length,
+ const void *param, mgmt_request_func_t callback,
+ void *user_data, mgmt_destroy_func_t destroy,
+ int timeout);
bool mgmt_cancel(struct mgmt *mgmt, unsigned int id);
bool mgmt_cancel_index(struct mgmt *mgmt, uint16_t index);
bool mgmt_cancel_all(struct mgmt *mgmt);