]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lib: introduce lldpctl_watch_callback2() fix/locked-conn 388/head
authorVincent Bernat <vincent@bernat.ch>
Fri, 24 Apr 2020 17:29:36 +0000 (19:29 +0200)
committerVincent Bernat <vincent@bernat.ch>
Fri, 24 Apr 2020 17:31:53 +0000 (19:31 +0200)
This is similar to `lldpctl_watch_callback()` (which is getting
deprecated), except the callback won't receive the current connection.
This prevents a user to use the connection which is unusable because
it is now dedicated to watch events.

Minor ABI dump due to new function, but everything is
backward-compatible, except you may now get an error if you use the
connection while watching (but this was already not supported).

Fix #380

NEWS
src/client/display.c
src/client/show.c
src/lib/Makefile.am
src/lib/atom.c
src/lib/atom.h
src/lib/connection.c
src/lib/lldpctl.h
src/lib/lldpctl.map

diff --git a/NEWS b/NEWS
index f98609172652daa889355f733c0b7827ff93ad91..2f3bc551ad1cba0891a97e4c8fe9c143b45de56e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,9 @@
 lldpd (1.0.6)
   * Fix:
     + Do not loose chassis local information when interface status changes.
+  * Changes:
+    + Deprecate use of lldpctl_watch_callback(). Use
+      lldpctl_watch_callback2() instead.
 
 lldpd (1.0.5)
   * Changes:
index faaa8b15afb5dbdb5e7cad765f97633e3dff5371..5dd914c3d0187df2b1094c2730298b80958175bb 100644 (file)
@@ -714,7 +714,7 @@ display_interface(lldpctl_conn_t *conn, struct writer *w, int hidden,
 
        display_chassis(w, chassis, details);
        display_port(w, port, details);
-       if (details && local)
+       if (details && local && conn)
                display_local_ttl(w, conn, details);
        if (details == DISPLAY_DETAILS) {
                display_vlans(w, port);
index 8ba8acb44e277396c598f4575d003aaa1a173c21..139a3cb3f18be1a43d9ff89abd1f30cc8b13d9f0 100644 (file)
@@ -154,8 +154,7 @@ struct watcharg {
  * Callback for the next function to display a new neighbor.
  */
 static void
-watchcb(lldpctl_conn_t *conn,
-    lldpctl_change_t type,
+watchcb(lldpctl_change_t type,
     lldpctl_atom_t *interface,
     lldpctl_atom_t *neighbor,
     void *data)
@@ -201,7 +200,7 @@ watchcb(lldpctl_conn_t *conn,
                break;
        default: return;
        }
-       display_interface(conn, w, 1, interface, neighbor,
+       display_interface(NULL, w, 1, interface, neighbor,
            cmdenv_get(env, "summary")?DISPLAY_BRIEF:
            cmdenv_get(env, "detailed")?DISPLAY_DETAILS:
            DISPLAY_NORMAL, protocol);
@@ -234,7 +233,7 @@ cmd_watch_neighbors(struct lldpctl_conn_t *conn, struct writer *w,
        }
 
        log_debug("lldpctl", "watch for neighbor changes");
-       if (lldpctl_watch_callback(conn, watchcb, &wa) < 0) {
+       if (lldpctl_watch_callback2(conn, watchcb, &wa) < 0) {
                log_warnx("lldpctl", "unable to watch for neighbors. %s",
                    lldpctl_last_strerror(conn));
                return 0;
index 2a5cdb3e997222ed5f189abf13f23eee1d0853f0..f98103929eda24011f697506742d9748a16f5e48 100644 (file)
@@ -54,7 +54,7 @@ CLEANFILES = atom-glue.c
 # -version-number could be computed from -version-info, mostly major
 # is `current` - `age`, minor is `age` and revision is `revision' and
 # major.minor should be used when updaing lldpctl.map.
-liblldpctl_la_LDFLAGS = $(AM_LDFLAGS) -version-info 12:0:8
+liblldpctl_la_LDFLAGS = $(AM_LDFLAGS) -version-info 13:0:9
 liblldpctl_la_DEPENDENCIES = libfixedpoint.la
 
 if HAVE_LD_VERSION_SCRIPT
index 54e94ae63c1c214dbc8e0f2a4c75665e7ac18682..39ea5f8757c98cfc4c51ab78fdbfcd8bfbc1f00c 100644 (file)
@@ -380,6 +380,26 @@ lldpctl_watch_callback(lldpctl_conn_t *conn,
        return rc;
 }
 
+int
+lldpctl_watch_callback2(lldpctl_conn_t *conn,
+    lldpctl_change_callback2 cb,
+    void *data)
+{
+       int rc;
+
+       RESET_ERROR(conn);
+
+       rc = _lldpctl_do_something(conn,
+           CONN_STATE_SET_WATCH_SEND, CONN_STATE_SET_WATCH_RECV, NULL,
+           SUBSCRIBE, NULL, NULL, NULL, NULL);
+       if (rc == 0) {
+               conn->watch_cb2 = cb;
+               conn->watch_data = data;
+               conn->state = CONN_STATE_WATCHING;
+       }
+       return rc;
+}
+
 int
 lldpctl_watch(lldpctl_conn_t *conn)
 {
index d6ae218fafbdeb93796f85d0d394984df97de641..0b1d4bc0002897d01d35eaf140c6e5687d31d330 100644 (file)
@@ -65,6 +65,7 @@ struct lldpctl_conn_t {
 
        /* Handling notifications */
        lldpctl_change_callback watch_cb;
+       lldpctl_change_callback2 watch_cb2;
        void *watch_data;
        int watch_triggered;
 };
index 191d7c6a02f04aaf6c5c5d681e638ee68cf99aa0..03107440a7b22595c17e88e4d46e6e46e0a9c1c5 100644 (file)
@@ -196,7 +196,7 @@ check_for_notification(lldpctl_conn_t *conn)
        change = p;
 
        /* We have a notification, call the callback */
-       if (conn->watch_cb) {
+       if (conn->watch_cb || conn->watch_cb2) {
                switch (change->state) {
                case NEIGHBOR_CHANGE_DELETED: type = lldpctl_c_deleted; break;
                case NEIGHBOR_CHANGE_ADDED: type = lldpctl_c_added; break;
@@ -212,7 +212,10 @@ check_for_notification(lldpctl_conn_t *conn)
                neighbor = _lldpctl_new_atom(conn, atom_port, 0,
                    NULL, change->neighbor, NULL);
                if (neighbor == NULL) goto end;
-               conn->watch_cb(conn, type, interface, neighbor, conn->watch_data);
+               if (conn->watch_cb)
+                       conn->watch_cb(conn, type, interface, neighbor, conn->watch_data);
+               else
+                       conn->watch_cb2(type, interface, neighbor, conn->watch_data);
                conn->watch_triggered = 1;
                goto end;
        }
index 2369bf20fed449c7544e7e37ebbbbbc28f9358a7..21222bb3dd9b1d42b20a407f47448b4f4338ebb6 100644 (file)
@@ -449,7 +449,7 @@ void lldpctl_atom_dec_ref(lldpctl_atom_t *atom);
 /**
  * Possible events for a change (notification).
  *
- * @see lldpctl_watch_callback
+ * @see lldpctl_watch_callback2
  */
 typedef enum {
        lldpctl_c_deleted,      /**< The neighbor has been deleted */
@@ -482,6 +482,25 @@ typedef void (*lldpctl_change_callback)(lldpctl_conn_t *conn,
     lldpctl_atom_t *neighbor,
     void *data);
 
+/**
+ * Callback function invoked when a change is detected.
+ *
+ * @param type      Type of change detected.
+ * @param interface Physical interface on which the change has happened.
+ * @param neighbor  Changed neighbor.
+ * @param data      Data provided when registering the callback.
+ *
+ * The provided interface and neighbor atoms are stolen by the callback: their
+ * reference count are decremented when the callback ends. If you want to keep a
+ * reference to it, be sure to increment the reference count in the callback.
+ *
+ * @see lldpctl_watch_callback2
+ */
+typedef void (*lldpctl_change_callback2)(lldpctl_change_t type,
+    lldpctl_atom_t *interface,
+    lldpctl_atom_t *neighbor,
+    void *data);
+
 /**
  * Register a callback to be called on changes.
  *
@@ -497,9 +516,32 @@ typedef void (*lldpctl_change_callback)(lldpctl_conn_t *conn,
  * @warning Once a callback is registered, the connection shouldn't be used for
  * anything else than receiving notifications. If you do, you will get a @c
  * LLDPCTL_ERR_INVALID_STATE error.
+ *
+ * @deprecated This function is deprecated and lldpctl_watch_callback2 should be
+ * used instead.
  */
 int lldpctl_watch_callback(lldpctl_conn_t *conn,
     lldpctl_change_callback cb,
+    void *data) __attribute__ ((deprecated));
+
+/**
+ * Register a callback to be called on changes.
+ *
+ * @param conn Connection with lldpd.
+ * @param cb   Replace the current callback with the provided one.
+ * @param data Data that will be passed to the callback.
+ * @return 0 in case of success or -1 in case of errors.
+ *
+ * This function will register the necessity to push neighbor changes to lldpd
+ * and therefore will issue IO operations. The error code could then be @c
+ * LLDPCTL_ERR_WOULDBLOCK.
+ *
+ * @warning Once a callback is registered, the connection shouldn't be used for
+ * anything else than receiving notifications. If you do, you will get a @c
+ * LLDPCTL_ERR_INVALID_STATE error.
+ */
+int lldpctl_watch_callback2(lldpctl_conn_t *conn,
+    lldpctl_change_callback2 cb,
     void *data);
 
 /**
index c725381a09e99e1947e4f12e1e83068f97017ded..c602b641aff1ee22f7a4c1b21d093c1b20ce4a75 100644 (file)
@@ -1,3 +1,8 @@
+LIBLLDPCTL_4.9 {
+ global:
+  lldpctl_watch_callback2;
+};
+
 LIBLLDPCTL_4.8 {
  global:
   lldpctl_get_default_port;