From d7fbe75c9e469a6c1a9db5a36fdd711f2e8d52fc Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Sun, 23 Sep 2018 17:50:19 +0200 Subject: [PATCH] added clixon_stream.[ch] --- lib/clixon/clixon_stream.h | 73 +++++++++++ lib/src/clixon_stream.c | 241 +++++++++++++++++++++++++++++++++++++ 2 files changed, 314 insertions(+) create mode 100644 lib/clixon/clixon_stream.h create mode 100644 lib/src/clixon_stream.c diff --git a/lib/clixon/clixon_stream.h b/lib/clixon/clixon_stream.h new file mode 100644 index 00000000..c2d2ba17 --- /dev/null +++ b/lib/clixon/clixon_stream.h @@ -0,0 +1,73 @@ +/* + * + ***** BEGIN LICENSE BLOCK ***** + + Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren + + This file is part of CLIXON. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + Alternatively, the contents of this file may be used under the terms of + the GNU General Public License Version 3 or later (the "GPL"), + in which case the provisions of the GPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of the GPL, and not to allow others to + use your version of this file under the terms of Apache License version 2, + indicate your decision by deleting the provisions above and replace them with + the notice and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the Apache License version 2 or the GPL. + + ***** END LICENSE BLOCK ***** + + * Event notification streams according to RFC5277 + */ +#ifndef _CLIXON_STREAM_H_ +#define _CLIXON_STREAM_H_ + +/* + * Types + */ +/* subscription callback */ +typedef int (*stream_fn_t)(clicon_handle, void *filter, void *arg); +typedef stream_fn_t subscription_fn_t; + +struct stream_subscription{ + struct stream_subscription *ss_next; + char *ss_stream; /* Name of associated stream */ + stream_fn_t ss_fn; /* Callback when event occurs */ + void *ss_arg; /* Callback argument */ +}; + +/* See RFC8040 9.3, stream list, no replay support for now + */ +struct event_stream{ + struct event_stream *es_next; + char *es_name; /* name of notification event stream */ + char *es_description; + struct stream_subscription *es_subscription; +}; +typedef struct event_stream event_stream_t; + +/* + * Prototypes + */ +event_stream_t *stream_find(clicon_handle h, const char *name); +int stream_register(clicon_handle h, const char *name, const char *description); +int stream_free(event_stream_t *es); +int stream_get_xml(clicon_handle h, int access, cbuf *cb); +int stream_cb_add(clicon_handle h, char *stream, stream_fn_t fn, void *arg); +int stream_cb_delete(clicon_handle h, char *stream, stream_fn_t fn); + +#endif /* _CLIXON_STREAM_H_ */ diff --git a/lib/src/clixon_stream.c b/lib/src/clixon_stream.c new file mode 100644 index 00000000..18eb6d50 --- /dev/null +++ b/lib/src/clixon_stream.c @@ -0,0 +1,241 @@ +/* + * + ***** BEGIN LICENSE BLOCK ***** + + Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren + + This file is part of CLIXON. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + Alternatively, the contents of this file may be used under the terms of + the GNU General Public License Version 3 or later (the "GPL"), + in which case the provisions of the GPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of the GPL, and not to allow others to + use your version of this file under the terms of Apache License version 2, + indicate your decision by deleting the provisions above and replace them with + the notice and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the Apache License version 2 or the GPL. + + ***** END LICENSE BLOCK ***** + + * Event notification streams according to RFC5277 + * See (old) subscription code in clixon_backend_handle.c and backend_client.c + */ + +#ifdef HAVE_CONFIG_H +#include "clixon_config.h" /* generated by config & autoconf */ +#endif + +#include +#include +#include +#include +#include + +/* cligen */ +#include + +/* clicon */ +#include "clixon_queue.h" +#include "clixon_err.h" +#include "clixon_hash.h" +#include "clixon_handle.h" +#include "clixon_stream.h" + +/*! Find an event notification stream given name + * @param[in] h Clicon handle + * @param[in] name Name of stream + * @retval es Event notification stream structure + * @retval NULL Not found + */ +event_stream_t * +stream_find(clicon_handle h, + const char *name) +{ + event_stream_t *es = NULL; + + for (es=clicon_stream(h); es; es=es->es_next) + if (strcmp(name, es->es_name)==0) + break; + return es; +} + +/*! Add notification event stream + */ +int +stream_register(clicon_handle h, + const char *name, + const char *description) +{ + int retval = -1; + event_stream_t *es; + + if ((es = stream_find(h, name)) != NULL) + goto ok; + if ((es = malloc(sizeof(event_stream_t))) == NULL){ + clicon_err(OE_XML, errno, "malloc"); + goto done; + } + memset(es, 0, sizeof(event_stream_t)); + if ((es->es_name = strdup(name)) == NULL){ + clicon_err(OE_XML, errno, "strdup"); + goto done; + } + if ((es->es_description = strdup(description)) == NULL){ + clicon_err(OE_XML, errno, "strdup"); + goto done; + } + clicon_stream_append(h, es); + ok: + retval = 0; + done: + return retval; +} + +/*! Delete complete notification event stream list + */ +int +stream_free(event_stream_t *es) +{ + event_stream_t *e_next; + + while (es){ + e_next = es->es_next; + if (es->es_name) + free(es->es_name); + if (es->es_description) + free(es->es_description); + free(es); + es = e_next; + } + return 0; +} + +/*! Return stream definition + * @param[in] h Clicon handle + * @param[in] access If set, include access/location + * @param[out] cb Output buffer containing XML on exit + * @retval 0 OK + * @retval -1 Error + */ +int +stream_get_xml(clicon_handle h, + int access, + cbuf *cb) +{ + event_stream_t *es = NULL; + + cprintf(cb, ""); + for (es=clicon_stream(h); es; es=es->es_next){ + cprintf(cb, ""); + cprintf(cb, "%s", es->es_name); + if (es->es_description) + cprintf(cb, "%s", es->es_description); + cprintf(cb, "false"); + if (access){ + cprintf(cb, ""); + cprintf(cb, "xml"); + /* Note /stream need to be in http proxy declaration */ + cprintf(cb, "https://example.com/stream/%s", es->es_name); + cprintf(cb, ""); + } + cprintf(cb, ""); + } + cprintf(cb, ""); + return 0; +} + +#ifdef NYI +/*! Delete single notification event stream + * XXX notused + */ +int +stream_del() +{ + return 0; +} +#endif + + +/*! Add an event notification callback to a stream given a callback function + * @param[in] h Clicon handle + * @param[in] stream Name of stream + * @param[in] fn Callback when event occurs + * @param[in] arg Argument to use with callback. Also handle when deleting + * @retval 0 OK + * @retval -1 Error + * XXX: from subscription_add and client_subscription_add + */ +int +stream_cb_add(clicon_handle h, + char *stream, + stream_fn_t fn, + void *arg) +{ + int retval = -1; + event_stream_t *es; + struct stream_subscription *ss; + + if ((es = stream_find(h, stream)) == NULL){ + clicon_err(OE_CFG, ENOENT, "Stream not found"); + goto done; + } + if ((ss = malloc(sizeof(*ss))) == NULL){ + clicon_err(OE_CFG, errno, "malloc"); + goto done; + } + memset(ss, 0, sizeof(*ss)); + ss->ss_stream = strdup(stream); + ss->ss_fn = fn; + ss->ss_arg = arg; + ss->ss_next = es->es_subscription; + es->es_subscription = ss; + retval = 0; + done: + return retval; +} + +/*! Delete event notification callback to a stream given a callback function + * Alt just send in an ss struct? + */ +int +stream_cb_delete(clicon_handle h, + char *stream, + stream_fn_t fn) +{ + int retval = -1; + event_stream_t *es; + struct stream_subscription *ss; + struct stream_subscription **ss_prev; + + if ((es = stream_find(h, stream)) == NULL) + goto ok; + ss_prev = &es->es_subscription; + for (ss = *ss_prev; ss; ss = ss->ss_next){ + if (ss->ss_fn == fn){ + *ss_prev = ss->ss_next; + free(ss->ss_stream); + if (ss->ss_arg) + free(ss->ss_arg); + free(ss); + break; + } + ss_prev = &ss->ss_next; + } + ok: + retval = 0; + return retval; +}