╭ changed ─────────────────╮ │src/serve_ssh_protocol.zig│ ╰──────────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │193 read_timeout: std.Io.Timeout = .none, │ │194 │ │195 fn readPacket(self: *Conn) ![]u8 { │ │196 - if (self.read_timeout != .none) { │ │196 + if (self.read_timeout != .none and !try self.cs_cipher.hasBufferedPacket(self.reader)) { │ │197 // peek keeps partial packets in the reader if the timer wins. │ │198 // join both tasks before consuming bytes or changing cipher state. │ │199 const Result = union(enum) { ready: anyerror!void, timeout: std.Io.Cancelable!void };│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │412 try parseChannelId(packet, self.channel.local_id); │ │413 self.incoming_eof = true; │ │414 self.remote_closed = true; │ │415 - try sendChannelClose(conn, self.channel); │ │415 + try sendChannelMessage(conn, self.channel, SSH_MSG_CHANNEL_CLOSE);│ │416 }, │ │417 SSH_MSG_GLOBAL_REQUEST => try handleGlobalRequest(conn, packet), │ │418 else => try sendUnimplemented(conn), │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │450 } │ │451 │ │452 // EOF then CLOSE │ │453 - { │ │454 - var eof: std.ArrayList(u8) = .empty; │ │455 - defer eof.deinit(conn.allocator); │ │456 - try eof.append(conn.allocator, SSH_MSG_CHANNEL_EOF); │ │457 - try writeU32(&eof, conn.allocator, self.channel.remote_id); │ │458 - try conn.sc_cipher.writePacket(conn.io, conn.writer, eof.items);│ │459 - } │ │460 - try sendChannelClose(conn, self.channel); │ │453 + try sendChannelMessage(conn, self.channel, SSH_MSG_CHANNEL_EOF); │ │454 + try sendChannelMessage(conn, self.channel, SSH_MSG_CHANNEL_CLOSE); │ │455 } │ │456 drainConnection(conn); │ │457 } │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ │1421 const len = 4 + (try self.bodyLength(try reader.peekArray(4))) + Poly1305.mac_length;│ │1422 if (len > reader.buffer.len) return error.ReadBufferTooSmall; │ │1423 _ = try reader.peek(len); │ │1424 + } │ │1425 + │ │1426 + fn hasBufferedPacket(self: *const Cipher, reader: *std.Io.Reader) !bool { │ │1427 + const bytes = reader.buffered(); │ │1428 + if (bytes.len < 4) return false; │ │1429 + return bytes.len >= 4 + (try self.bodyLength(bytes[0..4])) + Poly1305.mac_length; │ │1430 } │ │1431 │ │1432 pub fn writePacket( │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────╮ │1826 SSH_MSG_CHANNEL_CLOSE => { │ │1827 if (channel) |*c| { │ │1828 try parseChannelId(packet, c.local_id); │ │1829 - try sendChannelClose(conn, c); │ │1829 + try sendChannelMessage(conn, c, SSH_MSG_CHANNEL_CLOSE);│ │1830 drainConnection(conn); │ │1831 } │ │1832 return; │ ╰─────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1982 │ │1983 fn replyChannelRequest(conn: *Conn, ch: *Channel, want_reply: bool, success: bool) !void { │ │1984 if (!want_reply) return; │ │1985 - var reply: std.ArrayList(u8) = .empty; │ │1986 - defer reply.deinit(conn.allocator); │ │1987 - try reply.append(conn.allocator, if (success) SSH_MSG_CHANNEL_SUCCESS else SSH_MSG_CHANNEL_FAILURE);│ │1988 - try writeU32(&reply, conn.allocator, ch.remote_id); │ │1989 - try conn.sc_cipher.writePacket(conn.io, conn.writer, reply.items); │ │1985 + try sendChannelMessage(conn, ch, if (success) SSH_MSG_CHANNEL_SUCCESS else SSH_MSG_CHANNEL_FAILURE);│ │1986 } │ │1987 │ │1992 -fn sendChannelClose(conn: *Conn, ch: *Channel) !void { │ │1988 +fn sendChannelMessage(conn: *Conn, ch: *Channel, msg_type: u8) !void { │ │1989 var packet: [5]u8 = undefined; │ │1994 - packet[0] = SSH_MSG_CHANNEL_CLOSE; │ │1990 + packet[0] = msg_type; │ │1991 std.mem.writeInt(u32, packet[1..5], ch.remote_id, .big); │ │1992 try conn.sc_cipher.writePacket(conn.io, conn.writer, &packet); │ │1993 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯