1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-03 20:42:48 -05:00

Extend PacketQueue to take PktOut as well.

Some upcoming restructuring I've got planned will need to pass output
packets back and forth on queues, as well as input ones. So here's a
change that arranges that we can have a PktInQueue and a PktOutQueue,
sharing most of their implementation via a PacketQueueBase structure
which links together the PacketQueueNode fields in the two packet
structures.

There's a tricksy bit of macro manoeuvring to get all of this
type-checked, so that I can't accidentally link a PktOut on to a
PktInQueue or vice versa. It works by having the main queue functions
wrapped by macros; when receiving a packet structure on input, they
type-check it against the queue structure and then automatically look
up its qnode field to pass to the underlying PacketQueueBase function;
on output, they translate a returned PacketQueueNode back to its
containing packet type by calling a 'get' function pointer.
This commit is contained in:
Simon Tatham
2018-09-19 21:56:11 +01:00
parent 63a14f26f7
commit 6e24b7d589
3 changed files with 113 additions and 85 deletions

44
ssh.h
View File

@ -81,20 +81,46 @@ typedef struct PktOut {
unsigned downstream_id;
const char *additional_log_text;
PacketQueueNode qnode; /* for linking this packet on to a queue */
BinarySink_IMPLEMENTATION;
} PktOut;
typedef struct PacketQueue {
typedef struct PacketQueueBase {
PacketQueueNode end;
} PacketQueue;
} PacketQueueBase;
void pq_init(struct PacketQueue *pq);
void pq_push(struct PacketQueue *pq, PktIn *pkt);
void pq_push_front(struct PacketQueue *pq, PktIn *pkt);
PktIn *pq_peek(struct PacketQueue *pq);
PktIn *pq_pop(struct PacketQueue *pq);
void pq_clear(struct PacketQueue *pq);
int pq_empty_on_to_front_of(struct PacketQueue *src, struct PacketQueue *dest);
typedef struct PktInQueue {
PacketQueueBase pqb;
PktIn *(*get)(PacketQueueBase *, int pop);
} PktInQueue;
typedef struct PktOutQueue {
PacketQueueBase pqb;
PktOut *(*get)(PacketQueueBase *, int pop);
} 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_in_init(PktInQueue *pq);
void pq_out_init(PktOutQueue *pq);
void pq_in_clear(PktInQueue *pq);
void pq_out_clear(PktOutQueue *pq);
#define pq_push(pq, pkt) \
TYPECHECK((pq)->get(&(pq)->pqb, FALSE) == pkt, \
pq_base_push(&(pq)->pqb, &(pkt)->qnode))
#define pq_push_front(pq, pkt) \
TYPECHECK((pq)->get(&(pq)->pqb, FALSE) == pkt, \
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) == \
(dst)->get(&(dst)->pqb, FALSE), \
pq_base_empty_on_to_front_of(&(src)->pqb, &(dst)->pqb))
/*
* Packet type contexts, so that ssh2_pkt_type can correctly decode