#include <pthread.h>
#include <json-c/json.h>
+
#define AFB_BINDING_VERSION 0
#include <afb/afb-binding.h>
#include "afb-xreq.h"
#include "afb-export.h"
#include "afb-evt.h"
+#include "afb-session.h"
#include "afb-trace.h"
#include "wrap-json.h"
Trace_Type_Ditf, /* export hooks */
Trace_Type_Svc, /* export hooks */
Trace_Type_Evt, /* evt hooks */
+ Trace_Type_Session, /* session hooks */
Trace_Type_Global, /* global hooks */
Trace_Type_Count /* count of types of hooks */
};
{
int refcount; /* reference count */
pthread_mutex_t mutex; /* concurrency management */
- struct afb_daemon *daemon; /* daemon */
+ const char *apiname; /* api name for events */
struct afb_session *bound; /* bound to session */
struct event *events; /* list of events */
struct tag *tags; /* list of tags */
.hook_evt_unref = hook_evt_unref
};
+/*******************************************************************************/
+/***** trace the sessions *****/
+/*******************************************************************************/
+
+static struct flag session_flags[] = { /* must be sorted by names */
+ { "addref", afb_hook_flag_session_addref },
+ { "all", afb_hook_flags_session_all },
+ { "close", afb_hook_flag_session_close },
+ { "common", afb_hook_flags_session_common },
+ { "create", afb_hook_flag_session_create },
+ { "destroy", afb_hook_flag_session_destroy },
+ { "renew", afb_hook_flag_session_renew },
+ { "unref", afb_hook_flag_session_unref },
+};
+
+/* get the session value for flag of 'name' */
+static int get_session_flag(const char *name)
+{
+ return get_flag(name, session_flags, (int)(sizeof session_flags / sizeof *session_flags));
+}
+
+static void hook_session(void *closure, const struct afb_hookid *hookid, struct afb_session *session, const char *action, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ emit(closure, hookid, "session", "{ss ss}", format, ap,
+ "uuid", session,
+ "action", action);
+ va_end(ap);
+}
+
+static void hook_session_create(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+{
+ hook_session(closure, hookid, session, "create", "{ss}", "token", afb_session_token(session));
+}
+
+static void hook_session_close(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+{
+ hook_session(closure, hookid, session, "close", NULL);
+}
+
+static void hook_session_destroy(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+{
+ hook_session(closure, hookid, session, "destroy", NULL);
+}
+
+static void hook_session_renew(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+{
+ hook_session(closure, hookid, session, "renew", "{ss}", "token", afb_session_token(session));
+}
+
+static void hook_session_addref(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+{
+ hook_session(closure, hookid, session, "addref", NULL);
+}
+
+static void hook_session_unref(void *closure, const struct afb_hookid *hookid, struct afb_session *session)
+{
+ hook_session(closure, hookid, session, "unref", NULL);
+}
+
+static struct afb_hook_session_itf hook_session_itf = {
+ .hook_session_create = hook_session_create,
+ .hook_session_close = hook_session_close,
+ .hook_session_destroy = hook_session_destroy,
+ .hook_session_renew = hook_session_renew,
+ .hook_session_addref = hook_session_addref,
+ .hook_session_unref = hook_session_unref
+};
+
/*******************************************************************************/
/***** trace the globals *****/
/*******************************************************************************/
.unref = (void(*)(void*))afb_hook_unref_evt,
.get_flag = get_evt_flag
},
+ [Trace_Type_Session] =
+ {
+ .name = "session",
+ .unref = (void(*)(void*))afb_hook_unref_session,
+ .get_flag = get_session_flag
+ },
[Trace_Type_Global] =
{
.name = "global",
*/
static struct event *trace_get_event(struct afb_trace *trace, const char *name, int alloc)
{
- struct afb_event e;
struct event *event;
/* search the event */
if (!event && alloc) {
event = malloc(sizeof * event);
if (event) {
- e = afb_daemon_make_event_v1(*trace->daemon, name);
- event->evtid = afb_evt_eventid_to_evtid(afb_event_to_eventid(e));
+ event->evtid = afb_evt_evtid_create2(trace->apiname, name);
if (event->evtid) {
event->next = trace->events;
trace->events = event;
static struct afb_session *trace_get_session_by_uuid(struct afb_trace *trace, const char *uuid, int alloc)
{
struct cookie cookie;
- int created;
- cookie.session = afb_session_get(uuid, alloc ? &created : NULL);
- if (cookie.session) {
- cookie.trace = trace;
- afb_session_cookie(cookie.session, cookie.trace, session_open, session_closed, &cookie, 0);
+ if (!alloc)
+ cookie.session = afb_session_search(uuid);
+ else {
+ cookie.session = afb_session_get(uuid, AFB_SESSION_TIMEOUT_DEFAULT, NULL);
+ if (cookie.session) {
+ cookie.trace = trace;
+ afb_session_cookie(cookie.session, cookie.trace, session_open, session_closed, &cookie, 0);
+ }
}
return cookie.session;
}
struct context *context;
const char *name;
const char *tag;
- const char *session;
+ const char *uuid;
const char *api;
const char *verb;
const char *pattern;
ctxt_error(&desc->context->errors, "tracing %s is forbidden", abstracting[type].name);
return;
}
- if (desc->session) {
+ if (desc->uuid) {
ctxt_error(&desc->context->errors, "setting session is forbidden");
return;
}
/* create the hook handler */
switch (type) {
case Trace_Type_Xreq:
- if (desc->session) {
- session = trace_get_session_by_uuid(trace, desc->session, 1);
+ if (!desc->uuid)
+ session = afb_session_addref(bind);
+ else {
+ session = trace_get_session_by_uuid(trace, desc->uuid, 1);
if (!session) {
ctxt_error(&desc->context->errors, "allocation of session failed");
free(hook);
return;
}
- bind = session;
}
- hook->handler = afb_hook_create_xreq(desc->api, desc->verb, bind,
+ hook->handler = afb_hook_create_xreq(desc->api, desc->verb, session,
desc->flags[type], &hook_xreq_itf, hook);
+ afb_session_unref(session);
break;
case Trace_Type_Ditf:
hook->handler = afb_hook_create_ditf(desc->api, desc->flags[type], &hook_ditf_itf, hook);
case Trace_Type_Evt:
hook->handler = afb_hook_create_evt(desc->pattern, desc->flags[type], &hook_evt_itf, hook);
break;
+ case Trace_Type_Session:
+ hook->handler = afb_hook_create_session(desc->uuid, desc->flags[type], &hook_session_itf, hook);
+ break;
case Trace_Type_Global:
hook->handler = afb_hook_create_global(desc->flags[type], &hook_global_itf, hook);
break;
add_flags(closure, object, Trace_Type_Evt);
}
+static void add_session_flags(void *closure, struct json_object *object)
+{
+ add_flags(closure, object, Trace_Type_Session);
+}
+
static void add_global_flags(void *closure, struct json_object *object)
{
add_flags(closure, object, Trace_Type_Global);
{
int rc;
struct desc desc;
- struct json_object *request, *event, *daemon, *service, *sub, *global;
+ struct json_object *request, *event, *daemon, *service, *sub, *global, *session;
memcpy (&desc, closure, sizeof desc);
request = event = daemon = service = sub = global = NULL;
"tag", &desc.tag,
"api", &desc.api,
"verb", &desc.verb,
- "session", &desc.session,
+ "uuid", &desc.uuid,
"pattern", &desc.pattern,
"request", &request,
"daemon", &daemon,
"service", &service,
"event", &event,
+ "session", &session,
"global", &global,
"for", &sub);
if (desc.verb && desc.verb[0] == '*' && !desc.verb[1])
desc.verb = NULL;
- if (desc.session && desc.session[0] == '*' && !desc.session[1])
- desc.session = NULL;
+ if (desc.uuid && desc.uuid[0] == '*' && !desc.uuid[1])
+ desc.uuid = NULL;
/* get what is expected */
if (request)
if (event)
wrap_json_optarray_for_all(event, add_evt_flags, &desc);
+ if (session)
+ wrap_json_optarray_for_all(event, add_session_flags, &desc);
+
if (global)
wrap_json_optarray_for_all(global, add_global_flags, &desc);
session = trace_get_session_by_uuid(context->trace, uuid, 0);
if (!session)
ctxt_error(&context->errors, "session %s not found", uuid);
- else
+ else {
trace_unhook(context->trace, NULL, NULL, session);
+ afb_session_unref(session);
+ }
}
}
/*******************************************************************************/
/* allocates an afb_trace instance */
-struct afb_trace *afb_trace_create(struct afb_daemon *daemon, struct afb_session *bound)
+struct afb_trace *afb_trace_create(const char *apiname, struct afb_session *bound)
{
struct afb_trace *trace;
- assert(daemon);
+ assert(apiname);
trace = calloc(1, sizeof *trace);
if (trace) {
trace->refcount = 1;
trace->bound = bound;
- trace->daemon = daemon;
+ trace->apiname = apiname;
pthread_mutex_init(&trace->mutex, NULL);
}
return trace;
{
int rc;
struct context context;
- struct json_object *tags, *events, *sessions;
+ struct json_object *tags, *events, *uuids;
memset(&context, 0, sizeof context);
context.trace = trace;
return 0;
}
- tags = events = sessions = NULL;
+ tags = events = uuids = NULL;
rc = wrap_json_unpack(args, "{s?o s?o s?o}",
"event", &events,
"tag", &tags,
- "session", &sessions);
+ "uuid", &uuids);
- if (rc < 0 || !(events || tags || sessions)) {
+ if (rc < 0 || !(events || tags || uuids)) {
afb_req_fail(req, "error-detected", "bad drop arguments");
return -1;
}
if (events)
wrap_json_optarray_for_all(events, drop_event, &context);
- if (sessions)
- wrap_json_optarray_for_all(sessions, drop_session, &context);
+ if (uuids)
+ wrap_json_optarray_for_all(uuids, drop_session, &context);
trace_cleanup(trace);
free(context.errors);
return -1;
}
-