Compare commits

...

3 Commits

Author SHA1 Message Date
cirospaciari
b1a3957562 more cleanup 2024-01-25 10:18:33 -03:00
cirospaciari
3aa664f314 cleanup 2024-01-25 10:18:33 -03:00
cirospaciari
ff93ec9d19 non-blocking api 2024-01-25 10:18:33 -03:00
3 changed files with 103 additions and 18 deletions

View File

@@ -86,6 +86,7 @@ const SendfileContext = struct {
has_listener: bool = false,
has_set_on_writable: bool = false,
auto_close: bool = false,
transmitFileContext: if (Environment.isWindows) ?bun.windows.TransmitFileContext else u0 = if (Environment.isWindows) null else 0,
};
const DateTime = bun.DateTime;
const linux = std.os.linux;
@@ -1886,13 +1887,27 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
return errcode != .SUCCESS;
}
} else if (Environment.isWindows) {
const win = std.os.windows;
const uv = bun.windows.libuv;
const socket = bun.socketcast(this.sendfile.socket_fd);
const file_handle = uv.uv_get_osfhandle(bun.uvfdcast(this.sendfile.fd));
this.sendfile.offset += this.sendfile.remain;
this.sendfile.remain = 0;
return win.ws2_32.TransmitFile(socket, file_handle, 0, 0, null, null, 0) == 1;
if (this.sendfile.transmitFileContext == null) {
this.sendfile.transmitFileContext = bun.windows.TransmitFileContext.init();
}
const transmitFileContext = &(this.sendfile.transmitFileContext.?);
const sended = transmitFileContext.sendfile(this.sendfile.socket_fd, this.sendfile.fd).unwrap() catch |err| {
Output.prettyErrorln("Error: {}", .{err});
Output.flush();
this.cleanupAndFinalizeAfterSendfile();
return false;
};
const start = this.sendfile.offset;
this.sendfile.offset += sended;
this.sendfile.remain -|= @as(Blob.SizeType, @intCast(this.sendfile.offset -| start));
if (this.sendfile.remain == 0) {
this.cleanupAndFinalizeAfterSendfile();
return true;
}
} else {
var sbytes: std.os.off_t = adjusted_count;
const signed_offset = @as(i64, @bitCast(@as(u64, this.sendfile.offset)));

View File

@@ -41,6 +41,7 @@ pub var http_thread: HTTPThread = undefined;
const HiveArray = @import("./hive_array.zig").HiveArray;
const Batch = bun.ThreadPool.Batch;
const TaggedPointerUnion = @import("./tagged_pointer.zig").TaggedPointerUnion;
const DeadSocket = opaque {};
var dead_socket = @as(*DeadSocket, @ptrFromInt(1));
//TODO: this needs to be freed when Worker Threads are implemented
@@ -115,12 +116,16 @@ pub const HTTPRequestBody = union(enum) {
}
};
const TransmitFileContext = bun.windows.TransmitFileContext;
pub const Sendfile = struct {
fd: bun.FileDescriptor,
remain: usize = 0,
offset: usize = 0,
content_size: usize = 0,
transmitFileContext: if (Environment.isWindows) ?TransmitFileContext else u0 = if (Environment.isWindows) null else 0,
pub fn isEligible(url: bun.URL) bool {
return url.isHTTP() and url.href.len > 0 and FeatureFlags.streaming_file_uploads_for_http_client;
}
@@ -153,17 +158,23 @@ pub const Sendfile = struct {
return .{ .err = bun.errnoToZigErr(errcode) };
}
} else if (Environment.isWindows) {
const win = std.os.windows;
const uv = bun.windows.libuv;
const wsocket = bun.socketcast(socket.fd());
const file_handle = uv.uv_get_osfhandle(bun.uvfdcast(this.fd));
if (win.ws2_32.TransmitFile(wsocket, file_handle, 0, 0, null, null, 0) == 1) {
if (this.transmitFileContext == null) {
this.transmitFileContext = TransmitFileContext.init();
}
const transmitFileContext = &(this.transmitFileContext.?);
const sended = transmitFileContext.sendfile(socket.fd(), this.fd).unwrap() catch |err| {
return .{ .err = err };
};
const begin = this.offset;
this.offset += sended;
this.remain -|= @as(u64, @intCast(this.offset -| begin));
if (this.remain == 0) {
return .{ .done = {} };
}
this.offset += this.remain;
this.remain = 0;
const errorno = win.ws2_32.WSAGetLastError();
return .{ .err = bun.errnoToZigErr(errorno) };
} else if (Environment.isPosix) {
var sbytes: std.os.off_t = adjusted_count;
const signed_offset = @as(i64, @bitCast(@as(u64, this.offset)));
@@ -186,7 +197,6 @@ pub const Sendfile = struct {
return .{ .err = bun.errnoToZigErr(errcode) };
}
}
return .{ .again = {} };
}

View File

@@ -64,7 +64,7 @@ pub const INVALID_FILE_ATTRIBUTES: u32 = std.math.maxInt(u32);
const std = @import("std");
pub const HANDLE = win32.HANDLE;
const Maybe = @import("./bun.js/node/types.zig").Maybe;
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfilevaliddata
pub extern "kernel32" fn SetFileValidData(
hFile: win32.HANDLE,
@@ -3016,3 +3016,63 @@ pub extern "kernel32" fn GetTempPath2W(
nBufferLength: DWORD, // [in]
lpBuffer: LPCWSTR, // [out]
) DWORD;
pub const TransmitFileContext = struct {
overlapped: std.os.windows.OVERLAPPED,
status: WindowsSendFileStatus,
const WindowsSendFileStatus = enum {
ready,
incomplete,
fail,
};
const log = bun.Output.scoped(.TransmitFile, false);
pub fn init() TransmitFileContext {
if (!bun.Environment.isWindows) {
@compileError("TransmitFileContext can only be used on windows");
}
var this = TransmitFileContext{
.overlapped = std.mem.zeroes(std.os.windows.OVERLAPPED),
.status = .ready,
};
this.overlapped.hEvent = std.os.windows.ws2_32.WSACreateEvent();
return this;
}
pub fn sendfile(this: *TransmitFileContext, socket: bun.FileDescriptor, file: bun.FileDescriptor) Maybe(u32) {
// if we already fail, we dont have nothing todo here
if (this.status == .fail) return .{ .err = bun.sys.Error.fromCodeInt(@intFromEnum(bun.windows.Win32Error.WSA_OPERATION_ABORTED), .sendfile) };
const wsocket = bun.socketcast(socket);
const file_handle = libuv.uv_get_osfhandle(bun.uvfdcast(file));
const overlapped_ptr = &this.overlapped;
// we are still waiting for OverlappedResult?
if (this.status == .ready) {
if (std.os.windows.ws2_32.TransmitFile(wsocket, file_handle, 0, 64 * 1024, overlapped_ptr, null, 0) == 0) {
const err = bun.windows.Win32Error.get();
if (err != bun.windows.Win32Error.WSA_IO_PENDING) {
this.status = .fail;
return .{ .err = bun.sys.Error.fromCodeInt(@intFromEnum(err), .sendfile) };
}
}
}
var sended: u32 = 0;
// check the overlapped status
if (std.os.windows.kernel32.GetOverlappedResult(wsocket, overlapped_ptr, &sended, 0) == 0) {
const err = bun.windows.Win32Error.get();
if (err != bun.windows.Win32Error.WSA_IO_INCOMPLETE) {
this.status = .fail;
return .{ .err = bun.sys.Error.fromCodeInt(@intFromEnum(err), .sendfile) };
}
// still need to wait more before continue
this.status = .incomplete;
} else {
// ready for the next TransmitFile call
this.status = .ready;
}
return .{ .result = sended };
}
};