X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-stub-ws.c;h=11cad076913e60b61c5dfb2eae145933cef66773;hb=65353dce81a629e042800bb7b86fcd869a76727e;hp=a41a9b024f3a8f74ea460de01ac6063edee8bca1;hpb=2991a2564bc5e21b04dcb3157ce38804080c0056;p=src%2Fapp-framework-binder.git diff --git a/src/afb-stub-ws.c b/src/afb-stub-ws.c index a41a9b02..11cad076 100644 --- a/src/afb-stub-ws.c +++ b/src/afb-stub-ws.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2018 "IoT.bzh" + * Copyright (C) 2015-2020 "IoT.bzh" * Author José Bollo * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,13 +43,15 @@ #include "afb-context.h" #include "afb-evt.h" #include "afb-xreq.h" +#include "afb-token.h" +#include "afb-error-text.h" #include "verbose.h" #include "fdev.h" #include "jobs.h" +#include "u16id.h" struct afb_stub_ws; - /** * structure for a ws request: requests on server side */ @@ -59,27 +61,6 @@ struct server_req { struct afb_proto_ws_call *call; /**< the incoming call */ }; -/** - * structure for recording events on client side - */ -struct client_event -{ - struct client_event *next; /**< link to the next */ - struct afb_event_x2 *event; /**< the local event */ - int id; /**< the identifier */ - int refcount; /**< a reference count */ -}; - -/** - * structure for recording describe requests on the client side - */ -struct client_describe -{ - struct afb_stub_ws *stubws; /**< the stub */ - struct jobloop *jobloop; /**< the jobloop to leave */ - struct json_object *result; /**< result */ -}; - /** * structure for jobs of describing */ @@ -89,15 +70,6 @@ struct server_describe struct afb_proto_ws_describe *describe; }; -/** - * structure for recording sessions - */ -struct server_session -{ - struct server_session *next; - struct afb_session *session; -}; - /******************* stub description for client or servers ******************/ struct afb_stub_ws @@ -122,12 +94,27 @@ struct afb_stub_ws /* credentials of the client */ struct afb_cred *cred; + + /* event from server */ + struct u16id2bool *event_flags; + + /* transmitted sessions */ + struct u16id2ptr *session_proxies; + + /* transmitted tokens */ + struct u16id2ptr *token_proxies; }; /* client side */ struct { - /* event replica */ - struct client_event *events; + /* event from server */ + struct u16id2ptr *event_proxies; + + /* transmitted sessions */ + struct u16id2bool *session_flags; + + /* transmitted tokens */ + struct u16id2bool *token_flags; /* robustify */ struct { @@ -145,7 +132,7 @@ struct afb_stub_ws uint8_t is_client; /* the api name */ - char apiname[1]; + char apiname[]; }; static struct afb_proto_ws *afb_stub_ws_create_proto(struct afb_stub_ws *stubws, struct fdev *fdev, uint8_t server); @@ -158,7 +145,6 @@ static void server_req_destroy_cb(struct afb_xreq *xreq) struct server_req *wreq = CONTAINER_OF_XREQ(struct server_req, xreq); afb_context_disconnect(&wreq->xreq.context); - afb_cred_unref(wreq->xreq.cred); json_object_put(wreq->xreq.json); afb_proto_ws_call_unref(wreq->call); afb_stub_ws_unref(wreq->stubws); @@ -181,9 +167,9 @@ static int server_req_subscribe_cb(struct afb_xreq *xreq, struct afb_event_x2 *e int rc; struct server_req *wreq = CONTAINER_OF_XREQ(struct server_req, xreq); - rc = afb_evt_event_x2_add_watch(wreq->stubws->listener, event); + rc = afb_evt_listener_watch_x2(wreq->stubws->listener, event); if (rc >= 0) - rc = afb_proto_ws_call_subscribe(wreq->call, afb_evt_event_x2_fullname(event), afb_evt_event_x2_id(event)); + rc = afb_proto_ws_call_subscribe(wreq->call, afb_evt_event_x2_id(event)); if (rc < 0) ERROR("error while subscribing event"); return rc; @@ -191,13 +177,10 @@ static int server_req_subscribe_cb(struct afb_xreq *xreq, struct afb_event_x2 *e static int server_req_unsubscribe_cb(struct afb_xreq *xreq, struct afb_event_x2 *event) { - int rc, rc2; + int rc; struct server_req *wreq = CONTAINER_OF_XREQ(struct server_req, xreq); - rc = afb_proto_ws_call_unsubscribe(wreq->call, afb_evt_event_x2_fullname(event), afb_evt_event_x2_id(event)); - rc2 = afb_evt_event_x2_remove_watch(wreq->stubws->listener, event); - if (rc >= 0 && rc2 < 0) - rc = rc2; + rc = afb_proto_ws_call_unsubscribe(wreq->call, afb_evt_event_x2_id(event)); if (rc < 0) ERROR("error while unsubscribing event"); return rc; @@ -212,32 +195,6 @@ static const struct afb_xreq_query_itf server_req_xreq_itf = { /******************* client part **********************************/ -/* destroy all events */ -static void client_drop_all_events(struct afb_stub_ws *stubws) -{ - struct client_event *ev, *nxt; - - nxt = __atomic_exchange_n(&stubws->events, NULL, __ATOMIC_RELAXED); - while (nxt) { - ev = nxt; - nxt = ev->next; - afb_evt_event_x2_unref(ev->event); - free(ev); - } -} - -/* search the event */ -static struct client_event *client_event_search(struct afb_stub_ws *stubws, uint32_t eventid, const char *name) -{ - struct client_event *ev; - - ev = stubws->events; - while (ev != NULL && (ev->id != eventid || 0 != strcmp(afb_evt_event_x2_fullname(ev->event), name))) - ev = ev->next; - - return ev; -} - static struct afb_proto_ws *client_get_proto(struct afb_stub_ws *stubws) { struct fdev *fdev; @@ -252,99 +209,133 @@ static struct afb_proto_ws *client_get_proto(struct afb_stub_ws *stubws) return proto; } +static int client_make_ids(struct afb_stub_ws *stubws, struct afb_proto_ws *proto, struct afb_context *context, uint16_t *sessionid, uint16_t *tokenid) +{ + int rc, rc2; + uint16_t sid, tid; + + rc = 0; + + /* get the session */ + if (!context->session) + sid = 0; + else { + sid = afb_session_id(context->session); + rc2 = u16id2bool_set(&stubws->session_flags, sid, 1); + if (rc2 < 0) + rc = rc2; + else if (rc2 == 0) + rc = afb_proto_ws_client_session_create(proto, sid, afb_session_uuid(context->session)); + } + + /* get the token */ + if (!context->token) + tid = 0; + else { + tid = afb_token_id(context->token); + rc2 = u16id2bool_set(&stubws->token_flags, tid, 1); + if (rc2 < 0) + rc = rc2; + else if (rc2 == 0) { + rc2 = afb_proto_ws_client_token_create(proto, tid, afb_token_string(context->token)); + if (rc2 < 0) + rc = rc2; + } + } + + *sessionid = sid; + *tokenid = tid; + return rc; +} + /* on call, propagate it to the ws service */ static void client_api_call_cb(void * closure, struct afb_xreq *xreq) { int rc; struct afb_stub_ws *stubws = closure; struct afb_proto_ws *proto; + uint16_t sessionid; + uint16_t tokenid; proto = client_get_proto(stubws); if (proto == NULL) { - afb_xreq_reply(xreq, NULL, "disconnected", "server hung up"); + afb_xreq_reply(xreq, NULL, afb_error_text_disconnected, NULL); return; } - rc = afb_proto_ws_client_call( - proto, - xreq->request.called_verb, - afb_xreq_json(xreq), - afb_session_uuid(xreq->context.session), - xreq, - xreq_on_behalf_cred_export(xreq)); - if (rc >= 0) + rc = client_make_ids(stubws, proto, &xreq->context, &sessionid, &tokenid); + if (rc >= 0) { afb_xreq_unhooked_addref(xreq); - else - afb_xreq_reply(xreq, NULL, "internal", "can't send message"); -} - -static void client_on_description_cb(void *closure, struct json_object *data) -{ - struct client_describe *desc = closure; - - desc->result = data; - jobs_leave(desc->jobloop); -} - -static void client_send_describe_cb(int signum, void *closure, struct jobloop *jobloop) -{ - struct client_describe *desc = closure; - struct afb_proto_ws *proto; - - proto = client_get_proto(desc->stubws); - if (signum || proto == NULL) - jobs_leave(jobloop); - else { - desc->jobloop = jobloop; - afb_proto_ws_client_describe(proto, client_on_description_cb, desc); + rc = afb_proto_ws_client_call( + proto, + xreq->request.called_verb, + afb_xreq_json(xreq), + sessionid, + tokenid, + xreq, + xreq_on_behalf_cred_export(xreq)); + } + if (rc < 0) { + afb_xreq_reply(xreq, NULL, afb_error_text_internal_error, "can't send message"); + afb_xreq_unhooked_unref(xreq); } } /* get the description */ -static struct json_object *client_api_describe_cb(void * closure) +static void client_api_describe_cb(void * closure, void (*describecb)(void *, struct json_object *), void *clocb) { - struct client_describe desc; + struct afb_stub_ws *stubws = closure; + struct afb_proto_ws *proto; - /* synchronous job: send the request and wait its result */ - desc.stubws = closure; - desc.result = NULL; - jobs_enter(NULL, 0, client_send_describe_cb, &desc); - return desc.result; + proto = client_get_proto(stubws); + if (proto) + afb_proto_ws_client_describe(proto, describecb, clocb); + else + describecb(clocb, NULL); } /******************* server part: manage events **********************************/ -static void server_event_add_cb(void *closure, const char *event, int eventid) +static void server_event_add_cb(void *closure, const char *event, uint16_t eventid) { + int rc; struct afb_stub_ws *stubws = closure; - if (stubws->proto != NULL) - afb_proto_ws_server_event_create(stubws->proto, event, eventid); + if (stubws->proto != NULL) { + rc = u16id2bool_set(&stubws->event_flags, eventid, 1); + if (rc == 0) { + rc = afb_proto_ws_server_event_create(stubws->proto, eventid, event); + if (rc < 0) + u16id2bool_set(&stubws->event_flags, eventid, 0); + } + } } -static void server_event_remove_cb(void *closure, const char *event, int eventid) +static void server_event_remove_cb(void *closure, const char *event, uint16_t eventid) { struct afb_stub_ws *stubws = closure; - if (stubws->proto != NULL) - afb_proto_ws_server_event_remove(stubws->proto, event, eventid); + if (stubws->proto != NULL) { + if (u16id2bool_set(&stubws->event_flags, eventid, 0)) + afb_proto_ws_server_event_remove(stubws->proto, eventid); + } } -static void server_event_push_cb(void *closure, const char *event, int eventid, struct json_object *object) +static void server_event_push_cb(void *closure, const char *event, uint16_t eventid, struct json_object *object) { struct afb_stub_ws *stubws = closure; - if (stubws->proto != NULL) - afb_proto_ws_server_event_push(stubws->proto, event, eventid, object); + if (stubws->proto != NULL && u16id2bool_get(stubws->event_flags, eventid)) + afb_proto_ws_server_event_push(stubws->proto, eventid, object); json_object_put(object); } -static void server_event_broadcast_cb(void *closure, const char *event, int eventid, struct json_object *object) +static void server_event_broadcast_cb(void *closure, const char *event, struct json_object *object, const uuid_binary_t uuid, uint8_t hop) { struct afb_stub_ws *stubws = closure; if (stubws->proto != NULL) - afb_proto_ws_server_event_broadcast(stubws->proto, event, object); + afb_proto_ws_server_event_broadcast(stubws->proto, event, object, uuid, hop); json_object_put(object); } @@ -358,159 +349,178 @@ static void client_on_reply_cb(void *closure, void *request, struct json_object afb_xreq_unhooked_unref(xreq); } -static void client_on_event_create_cb(void *closure, const char *event_name, int event_id) +static void client_on_event_create_cb(void *closure, uint16_t event_id, const char *event_name) { struct afb_stub_ws *stubws = closure; - struct client_event *ev; - + struct afb_event_x2 *event; + int rc; + /* check conflicts */ - ev = client_event_search(stubws, event_id, event_name); - if (ev != NULL) { - __atomic_add_fetch(&ev->refcount, 1, __ATOMIC_RELAXED); - return; - } - - /* no conflict, try to add it */ - ev = malloc(sizeof *ev); - if (ev != NULL) { - ev->event = afb_evt_event_x2_create(event_name); - if (ev->event != NULL) { - ev->refcount = 1; - ev->id = event_id; - ev->next = stubws->events; - stubws->events = ev; - return; + event = afb_evt_event_x2_create(event_name); + if (event == NULL) + ERROR("can't create event %s, out of memory", event_name); + else { + rc = u16id2ptr_add(&stubws->event_proxies, event_id, event); + if (rc < 0) { + ERROR("can't record event %s", event_name); + afb_evt_event_x2_unref(event); } - free(ev); } - ERROR("can't create event %s, out of memory", event_name); } -static void client_on_event_remove_cb(void *closure, const char *event_name, int event_id) +static void client_on_event_remove_cb(void *closure, uint16_t event_id) { struct afb_stub_ws *stubws = closure; - struct client_event *ev, **prv; - - /* check conflicts */ - ev = client_event_search(stubws, event_id, event_name); - if (ev == NULL) - return; - - /* decrease the reference count */ - - if (__atomic_sub_fetch(&ev->refcount, 1, __ATOMIC_RELAXED)) - return; - - /* unlinks the event */ - prv = &stubws->events; - while (*prv != ev) - prv = &(*prv)->next; - *prv = ev->next; + struct afb_event_x2 *event; + int rc; - /* destroys the event */ - afb_evt_event_x2_unref(ev->event); - free(ev); + rc = u16id2ptr_drop(&stubws->event_proxies, event_id, (void**)&event); + if (rc == 0 && event) + afb_evt_event_x2_unref(event); } -static void client_on_event_subscribe_cb(void *closure, void *request, const char *event_name, int event_id) +static void client_on_event_subscribe_cb(void *closure, void *request, uint16_t event_id) { struct afb_stub_ws *stubws = closure; struct afb_xreq *xreq = request; - struct client_event *ev; - - /* check conflicts */ - ev = client_event_search(stubws, event_id, event_name); - if (ev == NULL) - return; + struct afb_event_x2 *event; + int rc; - if (afb_xreq_subscribe(xreq, ev->event) < 0) + rc = u16id2ptr_get(stubws->event_proxies, event_id, (void**)&event); + if (rc < 0 || !event || afb_xreq_subscribe(xreq, event) < 0) ERROR("can't subscribe: %m"); } -static void client_on_event_unsubscribe_cb(void *closure, void *request, const char *event_name, int event_id) +static void client_on_event_unsubscribe_cb(void *closure, void *request, uint16_t event_id) { struct afb_stub_ws *stubws = closure; struct afb_xreq *xreq = request; - struct client_event *ev; - - /* check conflicts */ - ev = client_event_search(stubws, event_id, event_name); - if (ev == NULL) - return; + struct afb_event_x2 *event; + int rc; - if (afb_xreq_unsubscribe(xreq, ev->event) < 0) + rc = u16id2ptr_get(stubws->event_proxies, event_id, (void**)&event); + if (rc < 0 || !event || afb_xreq_unsubscribe(xreq, event) < 0) ERROR("can't unsubscribe: %m"); } -static void client_on_event_push_cb(void *closure, const char *event_name, int event_id, struct json_object *data) +static void client_on_event_push_cb(void *closure, uint16_t event_id, struct json_object *data) { struct afb_stub_ws *stubws = closure; - struct client_event *ev; + struct afb_event_x2 *event; + int rc; - /* check conflicts */ - ev = client_event_search(stubws, event_id, event_name); - if (ev) - afb_evt_event_x2_push(ev->event, data); + rc = u16id2ptr_get(stubws->event_proxies, event_id, (void**)&event); + if (rc >= 0 && event) + rc = afb_evt_event_x2_push(event, data); else ERROR("unreadable push event"); + if (rc <= 0) + afb_proto_ws_client_event_unexpected(stubws->proto, event_id); } -static void client_on_event_broadcast_cb(void *closure, const char *event_name, struct json_object *data) +static void client_on_event_broadcast_cb(void *closure, const char *event_name, struct json_object *data, const uuid_binary_t uuid, uint8_t hop) { - afb_evt_broadcast(event_name, data); + afb_evt_rebroadcast(event_name, data, uuid, hop); } /*****************************************************/ -static void server_record_session(struct afb_stub_ws *stubws, struct afb_session *session) +static struct afb_session *server_add_session(struct afb_stub_ws *stubws, uint16_t sessionid, const char *sessionstr) { - struct server_session *s, **prv; + struct afb_session *session; + int rc, created; - /* search */ - prv = &stubws->sessions; - while ((s = *prv)) { - if (s->session == session) - return; - if (afb_session_is_closed(s->session)) { - *prv = s->next; - afb_session_unref(s->session); - free(s); + session = afb_session_get(sessionstr, AFB_SESSION_TIMEOUT_DEFAULT, &created); + if (session == NULL) + ERROR("can't create session %s, out of memory", sessionstr); + else { + afb_session_set_autoclose(session, 1); + rc = u16id2ptr_add(&stubws->session_proxies, sessionid, session); + if (rc < 0) { + ERROR("can't record session %s", sessionstr); + afb_session_unref(session); + session = NULL; } - else - prv = &s->next; } + return session; +} - /* create */ - s = malloc(sizeof *s); - if (s) { - s->session = afb_session_addref(session); - s->next = stubws->sessions; - stubws->sessions = s; - } +static void server_on_session_create_cb(void *closure, uint16_t sessionid, const char *sessionstr) +{ + struct afb_stub_ws *stubws = closure; + + server_add_session(stubws, sessionid, sessionstr); } -static void server_release_all_sessions(struct afb_stub_ws *stubws) +static void server_on_session_remove_cb(void *closure, uint16_t sessionid) { - struct server_session *ses, *nses; + struct afb_stub_ws *stubws = closure; + struct afb_session *session; + int rc; + + rc = u16id2ptr_drop(&stubws->event_proxies, sessionid, (void**)&session); + if (rc == 0 && session) + afb_session_unref(session); +} - nses = __atomic_exchange_n(&stubws->sessions, NULL, __ATOMIC_RELAXED); - while(nses) { - ses = nses; - nses = ses->next; - afb_session_unref(ses->session); - free(ses); +static void server_on_token_create_cb(void *closure, uint16_t tokenid, const char *tokenstr) +{ + struct afb_stub_ws *stubws = closure; + struct afb_token *token; + int rc; + + rc = afb_token_get(&token, tokenstr); + if (rc < 0) + ERROR("can't create token %s, out of memory", tokenstr); + else { + rc = u16id2ptr_add(&stubws->token_proxies, tokenid, token); + if (rc < 0) { + ERROR("can't record token %s", tokenstr); + afb_token_unref(token); + } } } -/*****************************************************/ +static void server_on_token_remove_cb(void *closure, uint16_t tokenid) +{ + struct afb_stub_ws *stubws = closure; + struct afb_token *token; + int rc; + + rc = u16id2ptr_drop(&stubws->event_proxies, tokenid, (void**)&token); + if (rc == 0 && token) + afb_token_unref(token); +} + +static void server_on_event_unexpected_cb(void *closure, uint16_t eventid) +{ + struct afb_stub_ws *stubws = closure; + + afb_evt_listener_unwatch_id(stubws->listener, eventid); +} -static void server_on_call_cb(void *closure, struct afb_proto_ws_call *call, const char *verb, struct json_object *args, const char *sessionid, const char *user_creds) +static void server_on_call_cb(void *closure, struct afb_proto_ws_call *call, const char *verb, struct json_object *args, uint16_t sessionid, uint16_t tokenid, const char *user_creds) { struct afb_stub_ws *stubws = closure; struct server_req *wreq; + struct afb_session *session; + struct afb_token *token; + int rc; afb_stub_ws_addref(stubws); + /* get tokens and sessions */ + rc = u16id2ptr_get(stubws->session_proxies, sessionid, (void**)&session); + if (rc < 0) { + if (sessionid != 0) + goto no_session; + session = server_add_session(stubws, sessionid, NULL); + if (!session) + goto out_of_memory; + } + if (!tokenid || u16id2ptr_get(stubws->token_proxies, tokenid, (void**)&token) < 0) + token = NULL; + /* create the request */ wreq = malloc(sizeof *wreq); if (wreq == NULL) @@ -521,66 +531,37 @@ static void server_on_call_cb(void *closure, struct afb_proto_ws_call *call, con wreq->call = call; /* init the context */ - if (afb_context_connect(&wreq->xreq.context, sessionid, NULL) < 0) - goto unconnected; - wreq->xreq.context.validated = 1; - server_record_session(stubws, wreq->xreq.context.session); - if (wreq->xreq.context.created) - afb_session_set_autoclose(wreq->xreq.context.session, 1); + afb_context_init(&wreq->xreq.context, session, token, stubws->cred); + afb_context_on_behalf_import(&wreq->xreq.context, user_creds); /* makes the call */ - wreq->xreq.cred = afb_cred_mixed_on_behalf_import(stubws->cred, sessionid, user_creds); wreq->xreq.request.called_api = stubws->apiname; wreq->xreq.request.called_verb = verb; wreq->xreq.json = args; afb_xreq_process(&wreq->xreq, stubws->apiset); return; -unconnected: - free(wreq); out_of_memory: +no_session: json_object_put(args); afb_stub_ws_unref(stubws); - afb_proto_ws_call_reply(call, NULL, "internal-error", NULL); + afb_proto_ws_call_reply(call, NULL, afb_error_text_internal_error, NULL); afb_proto_ws_call_unref(call); } -static void server_describe_cb(int signum, void *closure) +static void server_on_description_cb(void *closure, struct json_object *description) { - struct json_object *obj; - struct server_describe *desc = closure; - - /* get the description if possible */ - obj = !signum ? afb_apiset_describe(desc->stubws->apiset, desc->stubws->apiname) : NULL; - - /* send it */ - afb_proto_ws_describe_put(desc->describe, obj); - json_object_put(obj); - afb_stub_ws_unref(desc->stubws); + struct afb_proto_ws_describe *describe = closure; + afb_proto_ws_describe_put(describe, description); + json_object_put(description); } -static void server_describe_job(int signum, void *closure) -{ - server_describe_cb(signum, closure); - free(closure); -} static void server_on_describe_cb(void *closure, struct afb_proto_ws_describe *describe) { - struct server_describe *desc, sdesc; struct afb_stub_ws *stubws = closure; - /* allocate (if possible) and init */ - desc = malloc(sizeof *desc); - if (desc == NULL) - desc = &sdesc; - desc->stubws = stubws; - desc->describe = describe; - afb_stub_ws_addref(stubws); - - /* process */ - if (desc == &sdesc || jobs_queue(NULL, 0, server_describe_job, desc) < 0) - jobs_call(NULL, 0, server_describe_cb, desc); + afb_apiset_describe(stubws->apiset, stubws->apiname, server_on_description_cb, describe); } /*****************************************************/ @@ -603,8 +584,13 @@ static struct afb_api_itf client_api_itf = { static const struct afb_proto_ws_server_itf server_itf = { + .on_session_create = server_on_session_create_cb, + .on_session_remove = server_on_session_remove_cb, + .on_token_create = server_on_token_create_cb, + .on_token_remove = server_on_token_remove_cb, .on_call = server_on_call_cb, - .on_describe = server_on_describe_cb + .on_describe = server_on_describe_cb, + .on_event_unexpected = server_on_event_unexpected_cb }; /* the interface for events pushing */ @@ -616,21 +602,61 @@ static const struct afb_evt_itf server_event_itf = { }; /*****************************************************/ +/*****************************************************/ + +static void release_all_sessions_cb(void*closure, uint16_t id, void *ptr) +{ + struct afb_session *session = ptr; + afb_session_unref(session); +} + +static void release_all_tokens_cb(void*closure, uint16_t id, void *ptr) +{ + struct afb_token *token = ptr; + afb_token_unref(token); +} + +static void release_all_events_cb(void*closure, uint16_t id, void *ptr) +{ + struct afb_event_x2 *eventid = ptr; + afb_evt_event_x2_unref(eventid); +} /* disconnect */ static void disconnect(struct afb_stub_ws *stubws) { + struct u16id2ptr *i2p; + struct u16id2bool *i2b; + afb_proto_ws_unref(__atomic_exchange_n(&stubws->proto, NULL, __ATOMIC_RELAXED)); - if (stubws->is_client) - client_drop_all_events(stubws); - else { + if (stubws->is_client) { + i2p = __atomic_exchange_n(&stubws->event_proxies, NULL, __ATOMIC_RELAXED); + if (i2p) { + u16id2ptr_forall(i2p, release_all_events_cb, NULL); + u16id2ptr_destroy(&i2p); + } + i2b = __atomic_exchange_n(&stubws->session_flags, NULL, __ATOMIC_RELAXED); + u16id2bool_destroy(&i2b); + i2b = __atomic_exchange_n(&stubws->token_flags, NULL, __ATOMIC_RELAXED); + u16id2bool_destroy(&i2b); + } else { afb_evt_listener_unref(__atomic_exchange_n(&stubws->listener, NULL, __ATOMIC_RELAXED)); afb_cred_unref(__atomic_exchange_n(&stubws->cred, NULL, __ATOMIC_RELAXED)); - server_release_all_sessions(stubws); + i2b = __atomic_exchange_n(&stubws->event_flags, NULL, __ATOMIC_RELAXED); + u16id2bool_destroy(&i2b); + i2p = __atomic_exchange_n(&stubws->session_proxies, NULL, __ATOMIC_RELAXED); + if (i2p) { + u16id2ptr_forall(i2p, release_all_sessions_cb, NULL); + u16id2ptr_destroy(&i2p); + } + i2p = __atomic_exchange_n(&stubws->token_proxies, NULL, __ATOMIC_RELAXED); + if (i2p) { + u16id2ptr_forall(i2p, release_all_tokens_cb, NULL); + u16id2ptr_destroy(&i2p); + } } } - /* callback when receiving a hangup */ static void on_hangup(void *closure) { @@ -645,9 +671,9 @@ static void on_hangup(void *closure) } } -static int enqueue_processing(void (*callback)(int signum, void* arg), void *arg) +static int enqueue_processing(struct afb_proto_ws *proto, void (*callback)(int signum, void* arg), void *arg) { - return jobs_queue(NULL, 0, callback, arg); + return jobs_queue(proto, 0, callback, arg); } /*****************************************************/ @@ -671,7 +697,7 @@ static struct afb_stub_ws *afb_stub_ws_create(struct fdev *fdev, const char *api { struct afb_stub_ws *stubws; - stubws = calloc(1, sizeof *stubws + strlen(apiname)); + stubws = calloc(1, sizeof *stubws + 1 + strlen(apiname)); if (stubws == NULL) errno = ENOMEM; else {