╭ changed ─────────────────╮ │src/serve_ssh_protocol.zig│ ╰──────────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭───────────────────────────────────────────────╮ │325 }, │ │326 else => return err, │ │327 }; │ │319 - defer self.allocator.free(packet);│ │328 + defer conn.allocator.free(packet);│ │329 if (packet.len < 1) return; │ │330 │ │331 switch (packet[0]) { │ ╰───────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │338 try self.maybeRefillRecvWindowForBufferedInput(); │ │339 }, │ │340 SSH_MSG_CHANNEL_EXTENDED_DATA => { │ │332 - try discardChannelData(self.io, self.allocator, self.sc_cipher, self.writer, self.channel, packet, true);│ │341 + try discardChannelData(conn, self.channel, packet, true); │ │342 }, │ │343 SSH_MSG_CHANNEL_WINDOW_ADJUST => try handleWindowAdjust(self.channel, packet), │ │344 SSH_MSG_CHANNEL_REQUEST => { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────╮ │345 var r = std.Io.Reader.fixed(packet[1..]); │ │346 const recipient_channel = try r.takeInt(u32, .big); │ │347 if (recipient_channel != self.channel.local_id) return error.UnknownChannel;│ │339 - const req_type = try takeStringField(self.allocator, &r, 64); │ │340 - defer self.allocator.free(req_type); │ │348 + const req_type = try takeStringField(conn.allocator, &r, 64); │ │349 + defer conn.allocator.free(req_type); │ │350 const want_reply = (try r.takeByte()) != 0; │ │351 if (std.mem.eql(u8, req_type, "window-change")) { │ │352 const sz = try takePtySize(&r); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │353 if (self.channel.pty != null) self.channel.pty = sz; │ │354 self.pending_resize = sz; │ │346 - try replyChannelRequest(self.io, self.allocator, self.sc_cipher, self.writer, self.channel, want_reply, true); │ │355 + try replyChannelRequest(conn, self.channel, want_reply, true); │ │356 } else { │ │357 // other mid-session channel requests aren't honored — fail them │ │349 - try replyChannelRequest(self.io, self.allocator, self.sc_cipher, self.writer, self.channel, want_reply, false);│ │358 + try replyChannelRequest(conn, self.channel, want_reply, false); │ │359 } │ │360 }, │ │361 SSH_MSG_CHANNEL_EOF, SSH_MSG_CHANNEL_CLOSE => { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │362 try parseChannelId(packet, self.channel.local_id); │ │363 self.incoming_eof = true; │ │364 }, │ │356 - SSH_MSG_GLOBAL_REQUEST => try handleGlobalRequest(self.io, self.allocator, self.sc_cipher, self.writer, packet),│ │365 + SSH_MSG_GLOBAL_REQUEST => try handleGlobalRequest(conn, packet), │ │366 else => {}, │ │367 } │ │368 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │369 │ │370 fn maybeRefillRecvWindowForBufferedInput(self: *SessionCtx) !void { │ │371 if (self.incomingBytes().len >= incoming_refill_threshold) return; │ │363 - try maybeRefillRecvWindow(self.io, self.allocator, self.sc_cipher, self.writer, self.channel);│ │372 + try maybeRefillRecvWindow(self.conn, self.channel); │ │373 } │ │374 │ │375 /// signal the consumer's exit status and tear the channel down. │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────╮ │376 pub fn exit(self: *SessionCtx, status: u32) !void { │ │377 if (self.closed) return; │ │378 self.closed = true; │ │379 + const conn = self.conn; │ │380 │ │381 // exit-status request (informational; client uses it as the│ │382 // command's exit code) │ ╰─────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────╮ │383 { │ │384 var req: std.ArrayList(u8) = .empty; │ │375 - defer req.deinit(self.allocator); │ │376 - try req.append(self.allocator, SSH_MSG_CHANNEL_REQUEST); │ │377 - try writeU32(&req, self.allocator, self.channel.remote_id); │ │378 - try writeStringField(&req, self.allocator, "exit-status"); │ │379 - try req.append(self.allocator, 0); // want_reply MUST be false │ │380 - try writeU32(&req, self.allocator, status); │ │381 - try self.sc_cipher.writePacket(self.io, self.writer, req.items);│ │385 + defer req.deinit(conn.allocator); │ │386 + try req.append(conn.allocator, SSH_MSG_CHANNEL_REQUEST); │ │387 + try writeU32(&req, conn.allocator, self.channel.remote_id); │ │388 + try writeStringField(&req, conn.allocator, "exit-status"); │ │389 + try req.append(conn.allocator, 0); // want_reply MUST be false │ │390 + try writeU32(&req, conn.allocator, status); │ │391 + try conn.sc_cipher.writePacket(conn.io, conn.writer, req.items);│ │392 } │ │393 │ │394 // EOF then CLOSE │ ╰─────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │395 var eof: std.ArrayList(u8) = .empty; │ │386 - defer eof.deinit(self.allocator); │ │387 - try eof.append(self.allocator, SSH_MSG_CHANNEL_EOF); │ │388 - try writeU32(&eof, self.allocator, self.channel.remote_id); │ │389 - try self.sc_cipher.writePacket(self.io, self.writer, eof.items); │ │396 + defer eof.deinit(conn.allocator); │ │397 + try eof.append(conn.allocator, SSH_MSG_CHANNEL_EOF); │ │398 + try writeU32(&eof, conn.allocator, self.channel.remote_id); │ │399 + try conn.sc_cipher.writePacket(conn.io, conn.writer, eof.items); │ │400 │ │401 var close: std.ArrayList(u8) = .empty; │ │392 - defer close.deinit(self.allocator); │ │393 - try close.append(self.allocator, SSH_MSG_CHANNEL_CLOSE); │ │394 - try writeU32(&close, self.allocator, self.channel.remote_id); │ │395 - try self.sc_cipher.writePacket(self.io, self.writer, close.items); │ │402 + defer close.deinit(conn.allocator); │ │403 + try close.append(conn.allocator, SSH_MSG_CHANNEL_CLOSE); │ │404 + try writeU32(&close, conn.allocator, self.channel.remote_id); │ │405 + try conn.sc_cipher.writePacket(conn.io, conn.writer, close.items); │ │406 │ │407 // read and discard until the peer closes (TCP FIN) before letting the │ │408 // caller close the socket. a git client, after our CHANNEL_CLOSE, still│ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ │414 // contents don't matter — just get them off the socket. │ │415 var drain_packets: u32 = 0; │ │416 while (drain_packets < max_exit_drain_packets) : (drain_packets += 1) { │ │407 - const packet = self.cs_cipher.readPacket(self.allocator, self.reader) catch break;│ │408 - self.allocator.free(packet); │ │417 + const packet = conn.cs_cipher.readPacket(conn.allocator, conn.reader) catch break;│ │418 + conn.allocator.free(packet); │ │419 } │ │420 } │ │421 }; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯