From bc38af3e79fbd6256c209a0673601832429e7418 Mon Sep 17 00:00:00 2001 From: Jose Bollo Date: Wed, 10 Jul 2019 15:18:02 +0200 Subject: afb-xreq: Forbids (un)subscribes after reply Allowing to subscribe to a request that was replied was possible and lead to problem revealed by issues SPEC-2542 and SPEC-2599 (these issues are more related to processing unordered incoming messages). The choice was - fix the bug and authorize (un)subscribe after reply - forbids to (un)subscribe after reply Second solution was chosen for its simplicity and its networking efficiency. Bug-AGL: SPEC-2542 Bug-AGL: SPEC-2599 Change-Id: I09f48b760b1fd6f70d42b80df3c8053696c45966 Signed-off-by: Jose Bollo --- docs/reference-v3/func-req.md | 4 ++++ include/afb/afb-req-x1.h | 2 ++ include/afb/afb-req-x2.h | 4 ++++ src/afb-xreq.c | 34 ++++++++++++++++++++++------------ 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/docs/reference-v3/func-req.md b/docs/reference-v3/func-req.md index a70fb750..c84077d1 100644 --- a/docs/reference-v3/func-req.md +++ b/docs/reference-v3/func-req.md @@ -531,6 +531,8 @@ int afb_req_subcall_sync( * Establishes for the client link identified by 'req' a subscription * to the 'event'. * + * Establishing subscription MUST be called BEFORE replying to the request. + * * @param req the request * @param event the event to subscribe * @@ -549,6 +551,8 @@ int afb_req_subscribe( * link identified by 'req'. * Returns 0 in case of successful subscription or -1 in case of error. * + * Revoking subscription MUST be called BEFORE replying to the request. + * * @param req the request * @param event the event to revoke * diff --git a/include/afb/afb-req-x1.h b/include/afb/afb-req-x1.h index 6761521e..97b14428 100644 --- a/include/afb/afb-req-x1.h +++ b/include/afb/afb-req-x1.h @@ -274,6 +274,7 @@ static inline int afb_req_x1_session_set_LOA(struct afb_req_x1 req, unsigned lev * * Establishes for the client link identified by 'req' a subscription * to the 'event'. + * Establishing subscriptions MUST be called BEFORE replying to the request. * Returns 0 in case of successful subscription or -1 in case of error. */ static inline int afb_req_x1_subscribe(struct afb_req_x1 req, struct afb_event_x1 event) @@ -286,6 +287,7 @@ static inline int afb_req_x1_subscribe(struct afb_req_x1 req, struct afb_event_x * * Revokes the subscription established to the 'event' for the client * link identified by 'req'. + * Revoking subscription MUST be called BEFORE replying to the request. * Returns 0 in case of successful subscription or -1 in case of error. */ static inline int afb_req_x1_unsubscribe(struct afb_req_x1 req, struct afb_event_x1 event) diff --git a/include/afb/afb-req-x2.h b/include/afb/afb-req-x2.h index 5111f2f0..21bbc095 100644 --- a/include/afb/afb-req-x2.h +++ b/include/afb/afb-req-x2.h @@ -458,6 +458,8 @@ int afb_req_x2_session_set_LOA( * Establishes for the client link identified by 'req' a subscription * to the 'event'. * + * Establishing subscription MUST be called BEFORE replying to the request. + * * @param req the request * @param event the event to subscribe * @@ -476,6 +478,8 @@ int afb_req_x2_subscribe( * link identified by 'req'. * Returns 0 in case of successful subscription or -1 in case of error. * + * Revoking subscription MUST be called BEFORE replying to the request. + * * @param req the request * @param event the event to revoke * diff --git a/src/afb-xreq.c b/src/afb-xreq.c index 8cc22c3f..790a384f 100644 --- a/src/afb-xreq.c +++ b/src/afb-xreq.c @@ -202,12 +202,17 @@ static int xreq_legacy_subscribe_event_x1_cb(struct afb_req_x2 *closure, struct int afb_xreq_subscribe(struct afb_xreq *xreq, struct afb_event_x2 *event) { - if (xreq->listener) - return afb_evt_event_x2_add_watch(xreq->listener, event); - if (xreq->queryitf->subscribe) - return xreq->queryitf->subscribe(xreq, event); - ERROR("no event listener, subscription impossible"); - errno = EINVAL; + if (xreq->replied) { + ERROR("request replied, subscription impossible"); + errno = EINVAL; + } else { + if (xreq->listener) + return afb_evt_event_x2_add_watch(xreq->listener, event); + if (xreq->queryitf->subscribe) + return xreq->queryitf->subscribe(xreq, event); + ERROR("no event listener, subscription impossible"); + errno = ENOTSUP; + } return -1; } @@ -224,12 +229,17 @@ static int xreq_legacy_unsubscribe_event_x1_cb(struct afb_req_x2 *closure, struc int afb_xreq_unsubscribe(struct afb_xreq *xreq, struct afb_event_x2 *event) { - if (xreq->listener) - return afb_evt_event_x2_remove_watch(xreq->listener, event); - if (xreq->queryitf->unsubscribe) - return xreq->queryitf->unsubscribe(xreq, event); - ERROR("no event listener, unsubscription impossible"); - errno = EINVAL; + if (xreq->replied) { + ERROR("request replied, unsubscription impossible"); + errno = EINVAL; + } else { + if (xreq->listener) + return afb_evt_event_x2_remove_watch(xreq->listener, event); + if (xreq->queryitf->unsubscribe) + return xreq->queryitf->unsubscribe(xreq, event); + ERROR("no event listener, unsubscription impossible"); + errno = ENOTSUP; + } return -1; } -- cgit 1.2.3-korg