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:
parent
04226693e3
commit
6a5d4d083a
4
ssh.c
4
ssh.c
@ -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
11
ssh.h
@ -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
|
||||
|
68
sshcommon.c
68
sshcommon.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user