Function writeEnd [src]

Sends TLS-encrypted data to stream, which must conform to StreamInterface. Returns the number of cleartext bytes sent, which may be fewer than bytes.len. If end is true, then this function additionally sends a close_notify alert, which is necessary for the server to distinguish between a properly finished TLS session, or a truncation attack.

Prototype

pub fn writeEnd(c: *Client, stream: anytype, bytes: []const u8, end: bool) !usize

Parameters

c: *Clientbytes: []const u8end: bool

Source

pub fn writeEnd(c: *Client, stream: anytype, bytes: []const u8, end: bool) !usize { var ciphertext_buf: [tls.max_ciphertext_record_len * 4]u8 = undefined; var iovecs_buf: [6]std.posix.iovec_const = undefined; var prepared = prepareCiphertextRecord(c, &iovecs_buf, &ciphertext_buf, bytes, .application_data); if (end) { prepared.iovec_end += prepareCiphertextRecord( c, iovecs_buf[prepared.iovec_end..], ciphertext_buf[prepared.ciphertext_end..], &tls.close_notify_alert, .alert, ).iovec_end; } const iovec_end = prepared.iovec_end; const overhead_len = prepared.overhead_len; // Ideally we would call writev exactly once here, however, we must ensure // that we don't return with a record partially written. var i: usize = 0; var total_amt: usize = 0; while (true) { var amt = try stream.writev(iovecs_buf[i..iovec_end]); while (amt >= iovecs_buf[i].len) { const encrypted_amt = iovecs_buf[i].len; total_amt += encrypted_amt - overhead_len; amt -= encrypted_amt; i += 1; // Rely on the property that iovecs delineate records, meaning that // if amt equals zero here, we have fortunately found ourselves // with a short read that aligns at the record boundary. if (i >= iovec_end) return total_amt; // We also cannot return on a vector boundary if the final close_notify is // not sent; otherwise the caller would not know to retry the call. if (amt == 0 and (!end or i < iovec_end - 1)) return total_amt; } iovecs_buf[i].base += amt; iovecs_buf[i].len -= amt; } }