From 623c7b720c731ce3c94cf65dc9607351b29a70a7 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 21 Sep 2018 13:16:38 +0100 Subject: [PATCH] Put an optional IdempotentCallback in packet queues. This means that someone putting things on a packet queue doesn't need to separately hold a pointer to someone who needs notifying about it, or remember to call the notification function every time they push things on the queue. It's all taken care of automatically, without having to put extra stuff at the call sites. The precise semantics are that the callback will be scheduled whenever _new_ packets appear on the queue, but not when packets are removed. (Because the expectation is that the callback is notifying whoever is consuming the queue.) --- ssh.h | 1 + sshcommon.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/ssh.h b/ssh.h index 40d2b762..e9db3219 100644 --- a/ssh.h +++ b/ssh.h @@ -85,6 +85,7 @@ typedef struct PktOut { typedef struct PacketQueueBase { PacketQueueNode end; + struct IdempotentCallback *ic; } PacketQueueBase; typedef struct PktInQueue { diff --git a/sshcommon.c b/sshcommon.c index 087dc081..932e6c46 100644 --- a/sshcommon.c +++ b/sshcommon.c @@ -33,6 +33,9 @@ void pq_base_push(PacketQueueBase *pqb, PacketQueueNode *node) node->prev = pqb->end.prev; node->next->prev = node; node->prev->next = node; + + if (pqb->ic) + queue_idempotent_callback(pqb->ic); } void pq_base_push_front(PacketQueueBase *pqb, PacketQueueNode *node) @@ -42,6 +45,9 @@ void pq_base_push_front(PacketQueueBase *pqb, PacketQueueNode *node) node->next = pqb->end.next; node->next->prev = node; node->prev->next = node; + + if (pqb->ic) + queue_idempotent_callback(pqb->ic); } static PacketQueueNode pktin_freeq_head = { @@ -102,12 +108,14 @@ static PktOut *pq_out_get(PacketQueueBase *pqb, int pop) void pq_in_init(PktInQueue *pq) { + pq->pqb.ic = NULL; pq->pqb.end.next = pq->pqb.end.prev = &pq->pqb.end; pq->get = pq_in_get; } void pq_out_init(PktOutQueue *pq) { + pq->pqb.ic = NULL; pq->pqb.end.next = pq->pqb.end.prev = &pq->pqb.end; pq->get = pq_out_get; } @@ -115,6 +123,7 @@ void pq_out_init(PktOutQueue *pq) void pq_in_clear(PktInQueue *pq) { PktIn *pkt; + pq->pqb.ic = NULL; while ((pkt = pq_pop(pq)) != NULL) { /* No need to actually free these packets: pq_pop on a * PktInQueue will automatically move them to the free @@ -125,6 +134,7 @@ void pq_in_clear(PktInQueue *pq) void pq_out_clear(PktOutQueue *pq) { PktOut *pkt; + pq->pqb.ic = NULL; while ((pkt = pq_pop(pq)) != NULL) ssh_free_pktout(pkt); } @@ -188,6 +198,9 @@ void pq_base_concatenate(PacketQueueBase *qdest, qdest->end.prev = tail2; head1->prev = &qdest->end; tail2->next = &qdest->end; + + if (qdest->ic) + queue_idempotent_callback(qdest->ic); } }