1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Make pq_empty_on_to_front_of more general.

It's really just a concatenator for a pair of linked lists, but
unhelpfully restricted in which of the lists it replaces with the
output. Better to have a three-argument function that puts the output
wherever you like, whether it overlaps either or neither one of the
inputs.
This commit is contained in:
Simon Tatham 2018-09-19 20:30:40 +01:00
parent 04226693e3
commit 6a5d4d083a
3 changed files with 66 additions and 17 deletions

4
ssh.c
View File

@ -8846,8 +8846,10 @@ static void do_ssh2_connection(void *vctx)
* matches any of the table entries we've just modified will go to
* the right handler function, and won't come here to confuse us.
*/
if (pq_empty_on_to_front_of(&ssh->pq_ssh2_connection, &ssh->pq_full))
if (pq_peek(&ssh->pq_ssh2_connection)) {
pq_concatenate(&ssh->pq_full, &ssh->pq_ssh2_connection, &ssh->pq_full);
queue_idempotent_callback(&ssh->pq_full_consumer);
}
/*
* Now the connection protocol is properly up and running, with

11
ssh.h
View File

@ -102,7 +102,8 @@ typedef struct PktOutQueue {
void pq_base_init(PacketQueueBase *pqb);
void pq_base_push(PacketQueueBase *pqb, PacketQueueNode *node);
void pq_base_push_front(PacketQueueBase *pqb, PacketQueueNode *node);
int pq_base_empty_on_to_front_of(PacketQueueBase *src, PacketQueueBase *dest);
void pq_base_concatenate(PacketQueueBase *dest,
PacketQueueBase *q1, PacketQueueBase *q2);
void pq_in_init(PktInQueue *pq);
void pq_out_init(PktOutQueue *pq);
@ -117,10 +118,12 @@ void pq_out_clear(PktOutQueue *pq);
pq_base_push_front(&(pq)->pqb, &(pkt)->qnode))
#define pq_peek(pq) ((pq)->get(&(pq)->pqb, FALSE))
#define pq_pop(pq) ((pq)->get(&(pq)->pqb, TRUE))
#define pq_empty_on_to_front_of(src, dst) \
TYPECHECK((src)->get(&(src)->pqb, FALSE) == \
#define pq_concatenate(dst, q1, q2) \
TYPECHECK((q1)->get(&(q1)->pqb, FALSE) == \
(dst)->get(&(dst)->pqb, FALSE) && \
(q2)->get(&(q2)->pqb, FALSE) == \
(dst)->get(&(dst)->pqb, FALSE), \
pq_base_empty_on_to_front_of(&(src)->pqb, &(dst)->pqb))
pq_base_concatenate(&(dst)->pqb, &(q1)->pqb, &(q2)->pqb))
/*
* Packet type contexts, so that ssh2_pkt_type can correctly decode

View File

@ -88,22 +88,66 @@ void pq_out_clear(PktOutQueue *pq)
ssh_free_pktout(pkt);
}
int pq_base_empty_on_to_front_of(PacketQueueBase *src, PacketQueueBase *dest)
/*
* Concatenate the contents of the two queues q1 and q2, and leave the
* result in qdest. qdest must be either empty, or one of the input
* queues.
*/
void pq_base_concatenate(PacketQueueBase *qdest,
PacketQueueBase *q1, PacketQueueBase *q2)
{
struct PacketQueueNode *srcfirst, *srclast;
struct PacketQueueNode *head1, *tail1, *head2, *tail2;
if (src->end.next == &src->end)
return FALSE;
/*
* Extract the contents from both input queues, and empty them.
*/
srcfirst = src->end.next;
srclast = src->end.prev;
srcfirst->prev = &dest->end;
srclast->next = dest->end.next;
srcfirst->prev->next = srcfirst;
srclast->next->prev = srclast;
src->end.next = src->end.prev = &src->end;
head1 = (q1->end.next == &q1->end ? NULL : q1->end.next);
tail1 = (q1->end.prev == &q1->end ? NULL : q1->end.prev);
head2 = (q2->end.next == &q2->end ? NULL : q2->end.next);
tail2 = (q2->end.prev == &q2->end ? NULL : q2->end.prev);
return TRUE;
q1->end.next = q1->end.prev = &q1->end;
q2->end.next = q2->end.prev = &q2->end;
/*
* Link the two lists together, handling the case where one or
* both is empty.
*/
if (tail1)
tail1->next = head2;
else
head1 = head2;
if (head2)
head2->prev = tail1;
else
tail2 = head1;
/*
* Check the destination queue is currently empty. (If it was one
* of the input queues, then it will be, because we emptied both
* of those just a moment ago.)
*/
assert(qdest->end.next == &qdest->end);
assert(qdest->end.prev == &qdest->end);
/*
* If our concatenated list has anything in it, then put it in
* dest.
*/
if (!head1) {
assert(!tail2);
} else {
assert(tail2);
qdest->end.next = head1;
qdest->end.prev = tail2;
head1->prev = &qdest->end;
tail2->next = &qdest->end;
}
}
/* ----------------------------------------------------------------------