mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Revert premature queuing of channel messages.
At the point where the do_ssh2_connection coroutine rewrites lots of dispatch table entries to point to things other than itself, there's a possibility that it's too late, because some packets of those types have already arrived and been put into pq_ssh2_connection. So you'd get weird errors like 'Strange packet received: type 94', in which the only thing that's strange is why packet 94 might conceivably be unexpected, since it's SSH_MSG_CHANNEL_DATA! (I observed this when 'plink host -nc otherhost:port' became a sharing downstream, but I have no reason to think that's the only circumstance where this can possibly occur, or even a reliable one. It just happened to have the right timing.) I'm not completely sure this is the _best_ solution, but it seems to work: at the point when I rewrite the dispatch table, I also return the whole of the connection packet queue to the main queue, so that it'll be run through the dispatch table a second time which will effectively filter out any packets that we've just installed new handlers for.
This commit is contained in:
parent
8c7eddc9a1
commit
b95a6dece6
29
ssh.c
29
ssh.c
@ -805,6 +805,25 @@ static void pq_clear(struct PacketQueue *pq)
|
||||
ssh_unref_packet(pkt);
|
||||
}
|
||||
|
||||
static int pq_empty_on_to_front_of(struct PacketQueue *src,
|
||||
struct PacketQueue *dest)
|
||||
{
|
||||
struct PacketQueueNode *srcfirst, *srclast;
|
||||
|
||||
if (src->end.next == &src->end)
|
||||
return FALSE;
|
||||
|
||||
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;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct rdpkt1_state_tag {
|
||||
long len, pad, biglen;
|
||||
unsigned long realcrc, gotcrc;
|
||||
@ -11471,6 +11490,16 @@ static void do_ssh2_connection(void *vctx)
|
||||
ssh->packet_dispatch[SSH2_MSG_CHANNEL_SUCCESS] = ssh2_msg_channel_response;
|
||||
ssh->packet_dispatch[SSH2_MSG_CHANNEL_FAILURE] = ssh2_msg_channel_response;
|
||||
|
||||
/*
|
||||
* Put our current pending packet queue back to the front of
|
||||
* pq_full, and then schedule a callback to re-process those
|
||||
* packets (if any). That way, anything already in our queue that
|
||||
* 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))
|
||||
queue_idempotent_callback(&ssh->pq_full_consumer);
|
||||
|
||||
/*
|
||||
* Now the connection protocol is properly up and running, with
|
||||
* all those dispatch table entries, so it's safe to let
|
||||
|
Loading…
Reference in New Issue
Block a user