Function connectTcp [src]
Connect to host:port using the specified protocol. This will reuse a connection if one is already open.
This function is threadsafe.
Prototype
pub fn connectTcp(client: *Client, host: []const u8, port: u16, protocol: Connection.Protocol) ConnectTcpError!*Connection
Parameters
client: *Client
host: []const u8
port: u16
protocol: Connection.Protocol
Possible Errors
Source
pub fn connectTcp(client: *Client, host: []const u8, port: u16, protocol: Connection.Protocol) ConnectTcpError!*Connection {
if (client.connection_pool.findConnection(.{
.host = host,
.port = port,
.protocol = protocol,
})) |node| return node;
if (disable_tls and protocol == .tls)
return error.TlsInitializationFailed;
const conn = try client.allocator.create(ConnectionPool.Node);
errdefer client.allocator.destroy(conn);
conn.* = .{ .data = undefined };
const stream = net.tcpConnectToHost(client.allocator, host, port) catch |err| switch (err) {
error.ConnectionRefused => return error.ConnectionRefused,
error.NetworkUnreachable => return error.NetworkUnreachable,
error.ConnectionTimedOut => return error.ConnectionTimedOut,
error.ConnectionResetByPeer => return error.ConnectionResetByPeer,
error.TemporaryNameServerFailure => return error.TemporaryNameServerFailure,
error.NameServerFailure => return error.NameServerFailure,
error.UnknownHostName => return error.UnknownHostName,
error.HostLacksNetworkAddresses => return error.HostLacksNetworkAddresses,
else => return error.UnexpectedConnectFailure,
};
errdefer stream.close();
conn.data = .{
.stream = stream,
.tls_client = undefined,
.protocol = protocol,
.host = try client.allocator.dupe(u8, host),
.port = port,
};
errdefer client.allocator.free(conn.data.host);
if (protocol == .tls) {
if (disable_tls) unreachable;
conn.data.tls_client = try client.allocator.create(std.crypto.tls.Client);
errdefer client.allocator.destroy(conn.data.tls_client);
const ssl_key_log_file: ?std.fs.File = if (std.options.http_enable_ssl_key_log_file) ssl_key_log_file: {
const ssl_key_log_path = std.process.getEnvVarOwned(client.allocator, "SSLKEYLOGFILE") catch |err| switch (err) {
error.EnvironmentVariableNotFound, error.InvalidWtf8 => break :ssl_key_log_file null,
error.OutOfMemory => return error.OutOfMemory,
};
defer client.allocator.free(ssl_key_log_path);
break :ssl_key_log_file std.fs.cwd().createFile(ssl_key_log_path, .{
.truncate = false,
.mode = switch (builtin.os.tag) {
.windows, .wasi => 0,
else => 0o600,
},
}) catch null;
} else null;
errdefer if (ssl_key_log_file) |key_log_file| key_log_file.close();
conn.data.tls_client.* = std.crypto.tls.Client.init(stream, .{
.host = .{ .explicit = host },
.ca = .{ .bundle = client.ca_bundle },
.ssl_key_log_file = ssl_key_log_file,
}) catch return error.TlsInitializationFailed;
// This is appropriate for HTTPS because the HTTP headers contain
// the content length which is used to detect truncation attacks.
conn.data.tls_client.allow_truncation_attacks = true;
}
client.connection_pool.addUsed(conn);
return &conn.data;
}