Track the total size of every PacketQueue.

The queue-node structure shared between PktIn and PktOut now has a
'formal_size' field, which is initialised appropriately by the various
packet constructors. And the PacketQueue structure has a 'total_size'
field which tracks the sum of the formal sizes of all the packets on
the queue, and is automatically updated by the push, pop and
concatenate functions.

No functional change, and nothing uses the new fields yet: this is
infrastructure that will be used in the next commit.
This commit is contained in:
Simon Tatham 2020-02-05 19:32:22 +00:00
Родитель 563cb062b8
Коммит 0ff13ae773
5 изменённых файлов: 36 добавлений и 4 удалений

2
ssh.h
Просмотреть файл

@ -52,6 +52,7 @@ struct ssh_channel;
typedef struct PacketQueueNode PacketQueueNode;
struct PacketQueueNode {
PacketQueueNode *next, *prev;
size_t formal_size; /* contribution to PacketQueueBase's total_size */
bool on_free_queue; /* is this packet scheduled for freeing? */
};
@ -84,6 +85,7 @@ typedef struct PktOut {
typedef struct PacketQueueBase {
PacketQueueNode end;
size_t total_size; /* sum of all formal_size fields on the queue */
struct IdempotentCallback *ic;
} PacketQueueBase;

Просмотреть файл

@ -236,6 +236,7 @@ static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp)
NULL, 0, NULL);
}
s->pktin->qnode.formal_size = get_avail(s->pktin);
pq_push(&s->bpp.in_pq, s->pktin);
{

Просмотреть файл

@ -129,6 +129,7 @@ static void ssh2_bare_bpp_handle_input(BinaryPacketProtocol *bpp)
continue;
}
s->pktin->qnode.formal_size = get_avail(s->pktin);
pq_push(&s->bpp.in_pq, s->pktin);
s->pktin = NULL;
}

Просмотреть файл

@ -589,6 +589,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
continue;
}
s->pktin->qnode.formal_size = get_avail(s->pktin);
pq_push(&s->bpp.in_pq, s->pktin);
{

Просмотреть файл

@ -35,6 +35,7 @@ void pq_base_push(PacketQueueBase *pqb, PacketQueueNode *node)
node->prev = pqb->end.prev;
node->next->prev = node;
node->prev->next = node;
pqb->total_size += node->formal_size;
if (pqb->ic)
queue_idempotent_callback(pqb->ic);
@ -47,6 +48,7 @@ void pq_base_push_front(PacketQueueBase *pqb, PacketQueueNode *node)
node->next = pqb->end.next;
node->next->prev = node;
node->prev->next = node;
pqb->total_size += node->formal_size;
if (pqb->ic)
queue_idempotent_callback(pqb->ic);
@ -72,6 +74,23 @@ static IdempotentCallback ic_pktin_free = {
pktin_free_queue_callback, NULL, false
};
static inline void pq_unlink_common(PacketQueueBase *pqb,
PacketQueueNode *node)
{
node->next->prev = node->prev;
node->prev->next = node->next;
/* Check total_size doesn't drift out of sync downwards, by
* ensuring it doesn't underflow when we do this subtraction */
assert(pqb->total_size >= node->formal_size);
pqb->total_size -= node->formal_size;
/* Check total_size doesn't drift out of sync upwards, by checking
* that it's returned to exactly zero whenever a queue is
* emptied */
assert(pqb->end.next != &pqb->end || pqb->total_size == 0);
}
static PktIn *pq_in_after(PacketQueueBase *pqb,
PacketQueueNode *prev, bool pop)
{
@ -80,14 +99,14 @@ static PktIn *pq_in_after(PacketQueueBase *pqb,
return NULL;
if (pop) {
node->next->prev = node->prev;
node->prev->next = node->next;
pq_unlink_common(pqb, node);
node->prev = pktin_freeq_head.prev;
node->next = &pktin_freeq_head;
node->next->prev = node;
node->prev->next = node;
node->on_free_queue = true;
queue_idempotent_callback(&ic_pktin_free);
}
@ -102,8 +121,8 @@ static PktOut *pq_out_after(PacketQueueBase *pqb,
return NULL;
if (pop) {
node->next->prev = node->prev;
node->prev->next = node->next;
pq_unlink_common(pqb, node);
node->prev = node->next = NULL;
}
@ -115,6 +134,7 @@ void pq_in_init(PktInQueue *pq)
pq->pqb.ic = NULL;
pq->pqb.end.next = pq->pqb.end.prev = &pq->pqb.end;
pq->after = pq_in_after;
pq->pqb.total_size = 0;
}
void pq_out_init(PktOutQueue *pq)
@ -122,6 +142,7 @@ void pq_out_init(PktOutQueue *pq)
pq->pqb.ic = NULL;
pq->pqb.end.next = pq->pqb.end.prev = &pq->pqb.end;
pq->after = pq_out_after;
pq->pqb.total_size = 0;
}
void pq_in_clear(PktInQueue *pq)
@ -153,6 +174,8 @@ void pq_base_concatenate(PacketQueueBase *qdest,
{
struct PacketQueueNode *head1, *tail1, *head2, *tail2;
size_t total_size = q1->total_size + q2->total_size;
/*
* Extract the contents from both input queues, and empty them.
*/
@ -164,6 +187,7 @@ void pq_base_concatenate(PacketQueueBase *qdest,
q1->end.next = q1->end.prev = &q1->end;
q2->end.next = q2->end.prev = &q2->end;
q1->total_size = q2->total_size = 0;
/*
* Link the two lists together, handling the case where one or
@ -206,6 +230,8 @@ void pq_base_concatenate(PacketQueueBase *qdest,
if (qdest->ic)
queue_idempotent_callback(qdest->ic);
}
qdest->total_size = total_size;
}
/* ----------------------------------------------------------------------
@ -235,6 +261,7 @@ static void ssh_pkt_adddata(PktOut *pkt, const void *data, int len)
sgrowarrayn_nm(pkt->data, pkt->maxlen, pkt->length, len);
memcpy(pkt->data + pkt->length, data, len);
pkt->length += len;
pkt->qnode.formal_size = pkt->length;
}
static void ssh_pkt_BinarySink_write(BinarySink *bs,