@@ 37,6 37,18 @@
#include "announce-impl.h"
+/*
+ * Number of entries per instance to keep around for dedup'ing of QSO
+ * announcements.
+ *
+ * We may receive more than one copy of the same announcement because we may
+ * share the same multiple subnets as the sending instance, or we may have
+ * more than one IP on a subnet. Either way, we don't want to spam the
+ * callbacks with duplicate QSO announcements. So, we keep a small circular
+ * buffer of last NUM_QSO_DEDUP uuids that we received for each instance.
+ */
+#define NUM_QSO_DEDUP 4
+
struct addr {
union xsockaddr addr;
uint64_t ts;
@@ 51,8 63,16 @@ struct instance {
/* the bulk of the data lives in the following sub-struct */
struct instance_info info;
+ struct str *hlog_version;
+
struct addr *addrs; /* announcement addresses & times */
/* TODO: RPC addresses & ports */
+
+ struct qso_dedup {
+ struct xuuid uuid;
+ enum announce_qso_msg_type type;
+ } qso_dedup[NUM_QSO_DEDUP];
+ size_t qso_dedup_next;
};
static struct rb_tree instances;
@@ 105,15 125,36 @@ static void invoke_callback(struct insta
const struct announce_msg *msg)
{
switch ((enum announce_msg_type) msg->major) {
- case ANNOUNCE_QSO:
- if (notify.qso) {
- struct xuuid uuid;
+ case ANNOUNCE_QSO: {
+ const size_t next = inst->qso_dedup_next;
+ struct xuuid uuid;
+ size_t i;
+
+ if (!notify.qso)
+ return; /* no callback */
+
+ memcpy(uuid.raw, msg->u.qso.uuid, sizeof(uuid));
+
+ for (i = 0; i < ARRAY_LEN(inst->qso_dedup); i++) {
+ struct qso_dedup *d = &inst->qso_dedup[i];
- memcpy(uuid.raw, msg->u.qso.uuid, sizeof(uuid));
+ if (xuuid_compare(&uuid, &d->uuid))
+ continue;
+
+ if (msg->minor != d->type)
+ continue;
+
+ return; /* ignore duplicate */
+ }
- notify.qso(msg->minor, &inst->info, &uuid);
- }
+ notify.qso(msg->minor, &inst->info, &uuid);
+
+ /* stash uuid & minor type for future dedup matching */
+ inst->qso_dedup[next].uuid = uuid;
+ inst->qso_dedup[next].type = msg->minor;
+ inst->qso_dedup_next = (next + 1) % NUM_QSO_DEDUP;
break;
+ }
case ANNOUNCE_LOC:
if (notify.loc)
notify.loc(msg->minor, &inst->info);