From a8a10b9ba429ed28fe5eefb84548aaa13d7718b5 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Thu, 2 Jul 2026 18:19:13 +0300 Subject: [PATCH 1/5] `libcurl`: refactor `curl_easy_setopt` Removes lying dead code here and simplifies `curl_easy_setopt` type checking. Also marks passed callbacks as with C calling convention in order to get away from additional function wrapping. --- src/sys/libcurl.zig | 175 ++++++++------------------------------------ 1 file changed, 29 insertions(+), 146 deletions(-) diff --git a/src/sys/libcurl.zig b/src/sys/libcurl.zig index 3774857fa..1bee2d2e7 100644 --- a/src/sys/libcurl.zig +++ b/src/sys/libcurl.zig @@ -19,6 +19,8 @@ const std = @import("std"); const builtin = @import("builtin"); +const crypto = @import("libcrypto.zig"); + const c = @cImport({ @cInclude("curl/curl.h"); }); @@ -31,9 +33,7 @@ pub const CurlCode = c.CURLcode; pub const CurlMCode = c.CURLMcode; pub const CurlSList = c.curl_slist; pub const CurlHeader = c.curl_header; -pub const CurlHttpPost = c.curl_httppost; pub const CurlSocket = c.curl_socket_t; -pub const CurlBlob = c.curl_blob; pub const CurlOffT = c.curl_off_t; pub const CURLE = struct { @@ -41,12 +41,14 @@ pub const CURLE = struct { pub const ABORTED_BY_CALLBACK = c.CURLE_ABORTED_BY_CALLBACK; }; -pub const CurlDebugFunction = fn (*Curl, CurlInfoType, [*c]u8, usize, *anyopaque) c_int; -pub const CurlHeaderFunction = fn ([*]const u8, usize, usize, *anyopaque) usize; -pub const CurlWriteFunction = fn ([*]const u8, usize, usize, *anyopaque) usize; +pub const HeaderFunction = *const fn ([*]const u8, usize, usize, *anyopaque) callconv(.c) usize; +pub const WriteFunction = *const fn ([*]const u8, usize, usize, *anyopaque) callconv(.c) usize; pub const curl_writefunc_error: usize = c.CURL_WRITEFUNC_ERROR; pub const curl_readfunc_pause: usize = c.CURL_READFUNC_PAUSE; -pub const CurlReadFunction = fn ([*]u8, usize, usize, *anyopaque) usize; +pub const ReadFunction = *const fn ([*]u8, usize, usize, *anyopaque) callconv(.c) usize; +pub const OpenSocketFunction = *const fn (?*anyopaque, c_uint, [*c]CurlSockAddr) callconv(.c) CurlSocket; +pub const SslCtxFunction = *const fn (*Curl, *anyopaque, *anyopaque) callconv(.c) CurlCode; +pub const DebugFunction = *const fn (*Curl, CurlInfoType, [*c]u8, usize, ?*anyopaque) callconv(.c) c_int; pub const CurlSockType = enum(c.curlsocktype) { ipcxn = c.CURLSOCKTYPE_IPCXN, @@ -200,12 +202,8 @@ pub const CurlOption = enum(c.CURLoption) { url = c.CURLOPT_URL, timeout_ms = c.CURLOPT_TIMEOUT_MS, connect_timeout_ms = c.CURLOPT_CONNECTTIMEOUT_MS, - max_redirs = c.CURLOPT_MAXREDIRS, follow_location = c.CURLOPT_FOLLOWLOCATION, - redir_protocols_str = c.CURLOPT_REDIR_PROTOCOLS_STR, proxy = c.CURLOPT_PROXY, - ca_info_blob = c.CURLOPT_CAINFO_BLOB, - proxy_ca_info_blob = c.CURLOPT_PROXY_CAINFO_BLOB, ssl_verify_host = c.CURLOPT_SSL_VERIFYHOST, ssl_verify_peer = c.CURLOPT_SSL_VERIFYPEER, proxy_ssl_verify_host = c.CURLOPT_PROXY_SSL_VERIFYHOST, @@ -215,7 +213,6 @@ pub const CurlOption = enum(c.CURLoption) { debug_function = c.CURLOPT_DEBUGFUNCTION, custom_request = c.CURLOPT_CUSTOMREQUEST, post = c.CURLOPT_POST, - http_post = c.CURLOPT_HTTPPOST, post_field_size = c.CURLOPT_POSTFIELDSIZE, copy_post_fields = c.CURLOPT_COPYPOSTFIELDS, http_get = c.CURLOPT_HTTPGET, @@ -595,43 +592,29 @@ pub fn curl_easy_perform(easy: *Curl) Error!void { } pub fn curl_easy_setopt(easy: *Curl, comptime option: CurlOption, value: anytype) Error!void { - const opt: c.CURLoption = @intFromEnum(option); - const code = switch (option) { + const v = switch (comptime option) { .verbose, .post, .upload, .http_get, - .ssl_verify_host, .ssl_verify_peer, - .proxy_ssl_verify_host, .proxy_ssl_verify_peer, - => blk: { - const n: c_long = switch (@typeInfo(@TypeOf(value))) { - .bool => switch (option) { - .ssl_verify_host, .proxy_ssl_verify_host => if (value) 2 else 0, - else => if (value) 1 else 0, - }, - else => @compileError("expected bool|integer for " ++ @tagName(option) ++ ", got " ++ @typeName(@TypeOf(value))), - }; - break :blk c.curl_easy_setopt(easy, opt, n); - }, + => @as(c_long, @intFromBool(value)), + + // VERIFYHOST takes 0 or 2 (1 is rejected since curl 7.66). + // https://curl.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html + .ssl_verify_host, + .proxy_ssl_verify_host, + => @as(c_long, if (value) 2 else 0), .timeout_ms, .connect_timeout_ms, - .max_redirs, .follow_location, .post_field_size, .connect_only, - => blk: { - const n: c_long = switch (@typeInfo(@TypeOf(value))) { - .comptime_int, .int => @intCast(value), - else => @compileError("expected integer for " ++ @tagName(option) ++ ", got " ++ @typeName(@TypeOf(value))), - }; - break :blk c.curl_easy_setopt(easy, opt, n); - }, + => @as(c_long, @intCast(value)), .url, - .redir_protocols_str, .proxy, .accept_encoding, .custom_request, @@ -639,128 +622,28 @@ pub fn curl_easy_setopt(easy: *Curl, comptime option: CurlOption, value: anytype .user_pwd, .proxy_user_pwd, .copy_post_fields, - => blk: { - const s: ?[*]const u8 = value; - break :blk c.curl_easy_setopt(easy, opt, s); - }, + => @as(?[*]const u8, value), - .ca_info_blob, - .proxy_ca_info_blob, - => blk: { - const blob: CurlBlob = value; - break :blk c.curl_easy_setopt(easy, opt, blob); - }, - - .http_post => blk: { - // CURLOPT_HTTPPOST expects ?*curl_httppost (multipart formdata) - const ptr: ?*CurlHttpPost = value; - break :blk c.curl_easy_setopt(easy, opt, ptr); - }, - - .http_header => blk: { - const list: ?*CurlSList = value; - break :blk c.curl_easy_setopt(easy, opt, list); - }, + .http_header => @as(?*CurlSList, value), .private, .header_data, .read_data, .write_data, .opensocket_data, - => blk: { - const ptr: ?*anyopaque = switch (@typeInfo(@TypeOf(value))) { - .null => null, - else => @ptrCast(value), - }; - break :blk c.curl_easy_setopt(easy, opt, ptr); - }, + => @as(?*anyopaque, @ptrCast(value)), - .debug_function => blk: { - const cb: c.curl_debug_callback = switch (@typeInfo(@TypeOf(value))) { - .null => null, - .@"fn" => struct { - fn cb(handle: ?*Curl, msg_type: c.curl_infotype, raw: [*c]u8, len: usize, user: ?*anyopaque) callconv(.c) c_int { - const h = handle orelse unreachable; - const u = user orelse unreachable; - return value(h, @enumFromInt(@intFromEnum(msg_type)), raw, len, u); - } - }.cb, - else => @compileError("expected Zig function or null for " ++ @tagName(option) ++ ", got " ++ @typeName(@TypeOf(value))), - }; - break :blk c.curl_easy_setopt(easy, opt, cb); - }, + .ssl_ctx_data => @as(*crypto.X509_STORE, value), - .opensocket_function => blk: { - const cb: c.curl_opensocket_callback = switch (@typeInfo(@TypeOf(value))) { - .null => null, - .@"fn" => struct { - fn cb(clientp: ?*anyopaque, purpose: c.curlsocktype, address: [*c]c.curl_sockaddr) callconv(.c) c.curl_socket_t { - const addr: *CurlSockAddr = @ptrCast(address orelse return CURL_SOCKET_BAD); - return value(@enumFromInt(purpose), addr, clientp); - } - }.cb, - else => @compileError("expected Zig function or null for " ++ @tagName(option) ++ ", got " ++ @typeName(@TypeOf(value))), - }; - break :blk c.curl_easy_setopt(easy, opt, cb); - }, - - .header_function => blk: { - const cb: c.curl_write_callback = switch (@typeInfo(@TypeOf(value))) { - .null => null, - .@"fn" => struct { - fn cb(buffer: [*c]u8, count: usize, len: usize, user: ?*anyopaque) callconv(.c) usize { - const u = user orelse unreachable; - return value(@ptrCast(buffer), count, len, u); - } - }.cb, - else => @compileError("expected Zig function or null for " ++ @tagName(option) ++ ", got " ++ @typeName(@TypeOf(value))), - }; - break :blk c.curl_easy_setopt(easy, opt, cb); - }, - - .read_function => blk: { - const cb: c.curl_write_callback = switch (@typeInfo(@TypeOf(value))) { - .null => null, - .@"fn" => |info| struct { - fn cb(buffer: [*c]u8, count: usize, len: usize, user: ?*anyopaque) callconv(.c) usize { - const user_arg = if (@typeInfo(info.params[3].type.?) == .optional) - user - else - user orelse unreachable; - return value(@ptrCast(buffer), count, len, user_arg); - } - }.cb, - else => @compileError("expected Zig function or null for " ++ @tagName(option) ++ ", got " ++ @typeName(@TypeOf(value))), - }; - break :blk c.curl_easy_setopt(easy, opt, cb); - }, - .write_function => blk: { - const cb: c.curl_write_callback = switch (@typeInfo(@TypeOf(value))) { - .null => null, - .@"fn" => |info| struct { - fn cb(buffer: [*c]u8, count: usize, len: usize, user: ?*anyopaque) callconv(.c) usize { - const user_arg = if (@typeInfo(info.params[3].type.?) == .optional) - user - else - user orelse unreachable; - return value(@ptrCast(buffer), count, len, user_arg); - } - }.cb, - else => @compileError("expected Zig function or null for " ++ @tagName(option) ++ ", got " ++ @typeName(@TypeOf(value))), - }; - break :blk c.curl_easy_setopt(easy, opt, cb); - }, - .ssl_ctx_function => blk: { - const cb: c.curl_ssl_ctx_callback = @ptrCast(value); - break :blk c.curl_easy_setopt(easy, opt, cb); - }, - .ssl_ctx_data => blk: { - // We can make sure that passed data is always X509_STORE since we - // don't require anything else throughout project. - break :blk c.curl_easy_setopt(easy, opt, value); - }, + .debug_function => @as(DebugFunction, value), + .opensocket_function => @as(OpenSocketFunction, value), + .header_function => @as(HeaderFunction, value), + .read_function => @as(ReadFunction, value), + .write_function => @as(WriteFunction, value), + .ssl_ctx_function => @as(SslCtxFunction, value), }; - try errorCheck(code); + const code = c.curl_easy_setopt(easy, @intFromEnum(option), v); + return errorCheck(code); } pub fn curl_easy_getinfo(easy: *Curl, comptime info: CurlInfo, out: anytype) Error!void { From f2fce9310c136e39efaab0f1feb0330af6f87c3b Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Thu, 2 Jul 2026 18:20:18 +0300 Subject: [PATCH 2/5] update all call-sites that are using `curl_easy_setopt` --- src/browser/HttpClient.zig | 7 ++++++- src/browser/webapi/net/WebSocket.zig | 23 +++++++++++++++++---- src/network/http.zig | 30 +++++++++++++++------------- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/browser/HttpClient.zig b/src/browser/HttpClient.zig index 7fb4864b0..b64c55f89 100644 --- a/src/browser/HttpClient.zig +++ b/src/browser/HttpClient.zig @@ -2098,7 +2098,12 @@ pub const Transfer = struct { return result; } - fn dataCallback(buffer: [*]const u8, chunk_count: usize, chunk_len: usize, data: *anyopaque) usize { + fn dataCallback( + buffer: [*]const u8, + chunk_count: usize, + chunk_len: usize, + data: *anyopaque, + ) callconv(.c) usize { // libcurl should only ever emit 1 chunk at a time if (comptime IS_DEBUG) { std.debug.assert(chunk_count == 1); diff --git a/src/browser/webapi/net/WebSocket.zig b/src/browser/webapi/net/WebSocket.zig index a98efc591..dd33d99a8 100644 --- a/src/browser/webapi/net/WebSocket.zig +++ b/src/browser/webapi/net/WebSocket.zig @@ -545,11 +545,16 @@ fn dispatchCloseEvent(self: *WebSocket, code: u16, reason: []const u8, was_clean } } -fn sendDataCallback(buffer: [*]u8, buf_count: usize, buf_len: usize, data: *anyopaque) usize { +fn sendDataCallback( + buffer: [*c]u8, + buf_count: usize, + buf_len: usize, + raw_connection: ?*anyopaque, +) callconv(.c) usize { if (comptime IS_DEBUG) { std.debug.assert(buf_count == 1); } - const conn: *http.Connection = @ptrCast(@alignCast(data)); + const conn: *http.Connection = @ptrCast(@alignCast(raw_connection)); return _sendDataCallback(conn, buffer[0..buf_len]) catch |err| { log.warn(.websocket, "send callback", .{ .err = err }); return http.readfunc_pause; @@ -624,7 +629,12 @@ fn writeContent(self: *WebSocket, conn: *http.Connection, buf: []u8, byte_msg: M return to_copy; } -fn receivedDataCallback(buffer: [*]const u8, buf_count: usize, buf_len: usize, data: *anyopaque) usize { +fn receivedDataCallback( + buffer: [*]const u8, + buf_count: usize, + buf_len: usize, + data: *anyopaque, +) callconv(.c) usize { if (comptime IS_DEBUG) { std.debug.assert(buf_count == 1); } @@ -695,7 +705,12 @@ fn _receivedDataCallback(conn: *http.Connection, data: []const u8) !void { // libcurl has no mechanism to signal that the connection is established. The // best option I could come up with was looking for an upgrade header response. -fn receivedHeaderCallback(buffer: [*]const u8, header_count: usize, buf_len: usize, data: *anyopaque) usize { +fn receivedHeaderCallback( + buffer: [*]const u8, + header_count: usize, + buf_len: usize, + data: *anyopaque, +) callconv(.c) usize { if (comptime IS_DEBUG) { std.debug.assert(header_count == 1); } diff --git a/src/network/http.zig b/src/network/http.zig index ace8fa270..337df8711 100644 --- a/src/network/http.zig +++ b/src/network/http.zig @@ -328,11 +328,13 @@ pub const ResponseHead = struct { /// Returns CURL_SOCKET_BAD to block; otherwise creates and returns a real socket fd. /// clientp is a *const IpFilter passed via CURLOPT_OPENSOCKETDATA. fn opensocketCallback( - purpose: libcurl.CurlSockType, - address: *libcurl.CurlSockAddr, - clientp: ?*anyopaque, -) libcurl.CurlSocket { - const filter: *const IpFilter = @ptrCast(@alignCast(clientp orelse return libcurl.CURL_SOCKET_BAD)); + raw_ip_filter: ?*anyopaque, + _: c_uint, + addr: [*c]libcurl.CurlSockAddr, +) callconv(.c) libcurl.CurlSocket { + const address: *libcurl.CurlSockAddr = @ptrCast(addr); + const filter: *const IpFilter = @ptrCast(@alignCast(raw_ip_filter orelse return libcurl.CURL_SOCKET_BAD)); + if (filter.isBlockedSockaddr(address)) { if (address.family == posix.AF.INET or address.family == posix.AF.INET6) { const ip = std.net.Address.initPosix(@ptrCast(&address.addr)); @@ -342,7 +344,7 @@ fn opensocketCallback( } return libcurl.CURL_SOCKET_BAD; } - _ = purpose; // purpose is informational; we always open the same socket type + const fd = posix.socket( @intCast(address.family), @intCast(address.socktype), @@ -464,7 +466,7 @@ pub const Connection = struct { pub fn setWriteCallback( self: *Connection, - comptime data_cb: libcurl.CurlWriteFunction, + comptime data_cb: libcurl.WriteFunction, ) !void { try libcurl.curl_easy_setopt(self._easy, .write_data, self); try libcurl.curl_easy_setopt(self._easy, .write_function, data_cb); @@ -472,7 +474,7 @@ pub const Connection = struct { pub fn setReadCallback( self: *Connection, - comptime data_cb: libcurl.CurlReadFunction, + comptime data_cb: libcurl.ReadFunction, upload: bool, ) !void { try libcurl.curl_easy_setopt(self._easy, .read_data, self); @@ -484,7 +486,7 @@ pub const Connection = struct { pub fn setHeaderCallback( self: *Connection, - comptime data_cb: libcurl.CurlHeaderFunction, + comptime data_cb: libcurl.HeaderFunction, ) !void { try libcurl.curl_easy_setopt(self._easy, .header_data, self); try libcurl.curl_easy_setopt(self._easy, .header_function, data_cb); @@ -576,7 +578,7 @@ pub const Connection = struct { } } - fn discardBody(_: [*]const u8, count: usize, len: usize, _: ?*anyopaque) usize { + fn discardBody(_: [*]const u8, count: usize, len: usize, _: ?*anyopaque) callconv(.c) usize { return count * len; } @@ -864,7 +866,7 @@ test "opensocketCallback: private IPv4 returns CURL_SOCKET_BAD" { const filter = IpFilter.init(true, null); var sa = makeSockAddrV4(.{ 127, 0, 0, 1 }); - const result = opensocketCallback(.ipcxn, &sa, @ptrCast(@constCast(&filter))); + const result = opensocketCallback(@ptrCast(@constCast(&filter)), @intFromEnum(libcurl.CurlSockType.ipcxn), &sa); try testing.expectEqual(libcurl.CURL_SOCKET_BAD, result); } @@ -873,7 +875,7 @@ test "opensocketCallback: public IPv4 opens a real socket" { const filter = IpFilter.init(true, null); var sa = makeSockAddrV4(.{ 8, 8, 8, 8 }); - const fd = opensocketCallback(.ipcxn, &sa, @ptrCast(@constCast(&filter))); + const fd = opensocketCallback(@ptrCast(@constCast(&filter)), @intFromEnum(libcurl.CurlSockType.ipcxn), &sa); defer posix.close(fd); // A real fd is always >= 0 @@ -882,7 +884,7 @@ test "opensocketCallback: public IPv4 opens a real socket" { test "opensocketCallback: null clientp returns CURL_SOCKET_BAD (fail-closed)" { var sa = makeSockAddrV4(.{ 8, 8, 8, 8 }); - const result = opensocketCallback(.ipcxn, &sa, null); + const result = opensocketCallback(null, @intFromEnum(libcurl.CurlSockType.ipcxn), &sa); try testing.expectEqual(libcurl.CURL_SOCKET_BAD, result); } @@ -890,7 +892,7 @@ test "opensocketCallback: block_private=false allows private IP" { // When block_private is false the filter blocks nothing const filter = IpFilter.init(false, null); var sa = makeSockAddrV4(.{ 127, 0, 0, 1 }); - const fd = opensocketCallback(.ipcxn, &sa, @ptrCast(@constCast(&filter))); + const fd = opensocketCallback(@ptrCast(@constCast(&filter)), @intFromEnum(libcurl.CurlSockType.ipcxn), &sa); defer posix.close(fd); try testing.expect(fd >= 0); From 0011f87d82d1963cb23386416695109be1de9605 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Sat, 4 Jul 2026 09:50:31 +0300 Subject: [PATCH 3/5] `libcurl`: fix VERIFYHOST comment --- src/sys/libcurl.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sys/libcurl.zig b/src/sys/libcurl.zig index 1bee2d2e7..4924b994f 100644 --- a/src/sys/libcurl.zig +++ b/src/sys/libcurl.zig @@ -601,7 +601,7 @@ pub fn curl_easy_setopt(easy: *Curl, comptime option: CurlOption, value: anytype .proxy_ssl_verify_peer, => @as(c_long, @intFromBool(value)), - // VERIFYHOST takes 0 or 2 (1 is rejected since curl 7.66). + // VERIFYHOST expects 0 or 2 (since 7.66.0, 1 is treated the same as 2). // https://curl.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html .ssl_verify_host, .proxy_ssl_verify_host, From f17569f6137da16ee49fa654241cf1562b080d3a Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Sat, 4 Jul 2026 09:59:54 +0300 Subject: [PATCH 4/5] revert changes in `HttpClient` and `WebSocket` --- src/browser/HttpClient.zig | 7 +------ src/browser/webapi/net/WebSocket.zig | 23 ++++------------------- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/src/browser/HttpClient.zig b/src/browser/HttpClient.zig index b64c55f89..06e2b22aa 100644 --- a/src/browser/HttpClient.zig +++ b/src/browser/HttpClient.zig @@ -2098,12 +2098,7 @@ pub const Transfer = struct { return result; } - fn dataCallback( - buffer: [*]const u8, - chunk_count: usize, - chunk_len: usize, - data: *anyopaque, - ) callconv(.c) usize { + fn dataCallback(buffer: [*]const u8, chunk_count: usize, chunk_len: usize, data: *anyopaque) callconv(.c) usize { // libcurl should only ever emit 1 chunk at a time if (comptime IS_DEBUG) { std.debug.assert(chunk_count == 1); diff --git a/src/browser/webapi/net/WebSocket.zig b/src/browser/webapi/net/WebSocket.zig index dd33d99a8..c94ae9235 100644 --- a/src/browser/webapi/net/WebSocket.zig +++ b/src/browser/webapi/net/WebSocket.zig @@ -545,16 +545,11 @@ fn dispatchCloseEvent(self: *WebSocket, code: u16, reason: []const u8, was_clean } } -fn sendDataCallback( - buffer: [*c]u8, - buf_count: usize, - buf_len: usize, - raw_connection: ?*anyopaque, -) callconv(.c) usize { +fn sendDataCallback(buffer: [*]u8, buf_count: usize, buf_len: usize, data: *anyopaque) callconv(.c) usize { if (comptime IS_DEBUG) { std.debug.assert(buf_count == 1); } - const conn: *http.Connection = @ptrCast(@alignCast(raw_connection)); + const conn: *http.Connection = @ptrCast(@alignCast(data)); return _sendDataCallback(conn, buffer[0..buf_len]) catch |err| { log.warn(.websocket, "send callback", .{ .err = err }); return http.readfunc_pause; @@ -629,12 +624,7 @@ fn writeContent(self: *WebSocket, conn: *http.Connection, buf: []u8, byte_msg: M return to_copy; } -fn receivedDataCallback( - buffer: [*]const u8, - buf_count: usize, - buf_len: usize, - data: *anyopaque, -) callconv(.c) usize { +fn receivedDataCallback(buffer: [*]const u8, buf_count: usize, buf_len: usize, data: *anyopaque) callconv(.c) usize { if (comptime IS_DEBUG) { std.debug.assert(buf_count == 1); } @@ -705,12 +695,7 @@ fn _receivedDataCallback(conn: *http.Connection, data: []const u8) !void { // libcurl has no mechanism to signal that the connection is established. The // best option I could come up with was looking for an upgrade header response. -fn receivedHeaderCallback( - buffer: [*]const u8, - header_count: usize, - buf_len: usize, - data: *anyopaque, -) callconv(.c) usize { +fn receivedHeaderCallback(buffer: [*]const u8, header_count: usize, buf_len: usize, data: *anyopaque) callconv(.c) usize { if (comptime IS_DEBUG) { std.debug.assert(header_count == 1); } From ca1b625d51d054b3c20cb4fa9251003b24b0f1d3 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Sat, 4 Jul 2026 10:00:46 +0300 Subject: [PATCH 5/5] `libcurl`: reintroduce `Curl*` prefix for function pointer types --- src/network/http.zig | 12 ++++++------ src/sys/libcurl.zig | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/network/http.zig b/src/network/http.zig index 337df8711..8baeaf24a 100644 --- a/src/network/http.zig +++ b/src/network/http.zig @@ -328,12 +328,12 @@ pub const ResponseHead = struct { /// Returns CURL_SOCKET_BAD to block; otherwise creates and returns a real socket fd. /// clientp is a *const IpFilter passed via CURLOPT_OPENSOCKETDATA. fn opensocketCallback( - raw_ip_filter: ?*anyopaque, + clientp: ?*anyopaque, _: c_uint, addr: [*c]libcurl.CurlSockAddr, ) callconv(.c) libcurl.CurlSocket { const address: *libcurl.CurlSockAddr = @ptrCast(addr); - const filter: *const IpFilter = @ptrCast(@alignCast(raw_ip_filter orelse return libcurl.CURL_SOCKET_BAD)); + const filter: *const IpFilter = @ptrCast(@alignCast(clientp orelse return libcurl.CURL_SOCKET_BAD)); if (filter.isBlockedSockaddr(address)) { if (address.family == posix.AF.INET or address.family == posix.AF.INET6) { @@ -466,7 +466,7 @@ pub const Connection = struct { pub fn setWriteCallback( self: *Connection, - comptime data_cb: libcurl.WriteFunction, + comptime data_cb: libcurl.CurlWriteFunction, ) !void { try libcurl.curl_easy_setopt(self._easy, .write_data, self); try libcurl.curl_easy_setopt(self._easy, .write_function, data_cb); @@ -474,7 +474,7 @@ pub const Connection = struct { pub fn setReadCallback( self: *Connection, - comptime data_cb: libcurl.ReadFunction, + comptime data_cb: libcurl.CurlReadFunction, upload: bool, ) !void { try libcurl.curl_easy_setopt(self._easy, .read_data, self); @@ -486,7 +486,7 @@ pub const Connection = struct { pub fn setHeaderCallback( self: *Connection, - comptime data_cb: libcurl.HeaderFunction, + comptime data_cb: libcurl.CurlHeaderFunction, ) !void { try libcurl.curl_easy_setopt(self._easy, .header_data, self); try libcurl.curl_easy_setopt(self._easy, .header_function, data_cb); @@ -762,7 +762,7 @@ pub const Handles = struct { } }; -fn debugCallback(_: *libcurl.Curl, msg_type: libcurl.CurlInfoType, raw: [*c]u8, len: usize, _: *anyopaque) c_int { +fn debugCallback(_: *libcurl.Curl, msg_type: libcurl.CurlInfoType, raw: [*c]u8, len: usize, _: ?*anyopaque) callconv(.c) c_int { const data = raw[0..len]; switch (msg_type) { .text => std.debug.print("libcurl [text]: {s}\n", .{data}), diff --git a/src/sys/libcurl.zig b/src/sys/libcurl.zig index 4924b994f..e473d5896 100644 --- a/src/sys/libcurl.zig +++ b/src/sys/libcurl.zig @@ -41,14 +41,14 @@ pub const CURLE = struct { pub const ABORTED_BY_CALLBACK = c.CURLE_ABORTED_BY_CALLBACK; }; -pub const HeaderFunction = *const fn ([*]const u8, usize, usize, *anyopaque) callconv(.c) usize; -pub const WriteFunction = *const fn ([*]const u8, usize, usize, *anyopaque) callconv(.c) usize; +pub const CurlHeaderFunction = *const fn ([*]const u8, usize, usize, *anyopaque) callconv(.c) usize; +pub const CurlWriteFunction = *const fn ([*]const u8, usize, usize, *anyopaque) callconv(.c) usize; pub const curl_writefunc_error: usize = c.CURL_WRITEFUNC_ERROR; pub const curl_readfunc_pause: usize = c.CURL_READFUNC_PAUSE; -pub const ReadFunction = *const fn ([*]u8, usize, usize, *anyopaque) callconv(.c) usize; -pub const OpenSocketFunction = *const fn (?*anyopaque, c_uint, [*c]CurlSockAddr) callconv(.c) CurlSocket; -pub const SslCtxFunction = *const fn (*Curl, *anyopaque, *anyopaque) callconv(.c) CurlCode; -pub const DebugFunction = *const fn (*Curl, CurlInfoType, [*c]u8, usize, ?*anyopaque) callconv(.c) c_int; +pub const CurlReadFunction = *const fn ([*]u8, usize, usize, *anyopaque) callconv(.c) usize; +pub const CurlOpenSocketFunction = *const fn (?*anyopaque, c_uint, [*c]CurlSockAddr) callconv(.c) CurlSocket; +pub const CurlSslCtxFunction = *const fn (*Curl, *anyopaque, *anyopaque) callconv(.c) CurlCode; +pub const CurlDebugFunction = *const fn (*Curl, CurlInfoType, [*c]u8, usize, ?*anyopaque) callconv(.c) c_int; pub const CurlSockType = enum(c.curlsocktype) { ipcxn = c.CURLSOCKTYPE_IPCXN, @@ -635,12 +635,12 @@ pub fn curl_easy_setopt(easy: *Curl, comptime option: CurlOption, value: anytype .ssl_ctx_data => @as(*crypto.X509_STORE, value), - .debug_function => @as(DebugFunction, value), - .opensocket_function => @as(OpenSocketFunction, value), - .header_function => @as(HeaderFunction, value), - .read_function => @as(ReadFunction, value), - .write_function => @as(WriteFunction, value), - .ssl_ctx_function => @as(SslCtxFunction, value), + .debug_function => @as(CurlDebugFunction, value), + .opensocket_function => @as(CurlOpenSocketFunction, value), + .header_function => @as(CurlHeaderFunction, value), + .read_function => @as(CurlReadFunction, value), + .write_function => @as(CurlWriteFunction, value), + .ssl_ctx_function => @as(CurlSslCtxFunction, value), }; const code = c.curl_easy_setopt(easy, @intFromEnum(option), v); return errorCheck(code);