Function connectTunnel [src]

Connect to tunnel_host:tunnel_port using the specified proxy with HTTP CONNECT. This will reuse a connection if one is already open. This function is threadsafe.

Prototype

pub fn connectTunnel( client: *Client, proxy: *Proxy, tunnel_host: []const u8, tunnel_port: u16, ) !*Connection

Parameters

client: *Clientproxy: *Proxytunnel_host: []const u8tunnel_port: u16

Source

pub fn connectTunnel( client: *Client, proxy: *Proxy, tunnel_host: []const u8, tunnel_port: u16, ) !*Connection { if (!proxy.supports_connect) return error.TunnelNotSupported; if (client.connection_pool.findConnection(.{ .host = tunnel_host, .port = tunnel_port, .protocol = proxy.protocol, })) |node| return node; var maybe_valid = false; (tunnel: { const conn = try client.connectTcp(proxy.host, proxy.port, proxy.protocol); errdefer { conn.closing = true; client.connection_pool.release(client.allocator, conn); } var buffer: [8096]u8 = undefined; var req = client.open(.CONNECT, .{ .scheme = "http", .host = .{ .raw = tunnel_host }, .port = tunnel_port, }, .{ .redirect_behavior = .unhandled, .connection = conn, .server_header_buffer = &buffer, }) catch |err| { std.log.debug("err {}", .{err}); break :tunnel err; }; defer req.deinit(); req.send() catch |err| break :tunnel err; req.wait() catch |err| break :tunnel err; if (req.response.status.class() == .server_error) { maybe_valid = true; break :tunnel error.ServerError; } if (req.response.status != .ok) break :tunnel error.ConnectionRefused; // this connection is now a tunnel, so we can't use it for anything else, it will only be released when the client is de-initialized. req.connection = null; client.allocator.free(conn.host); conn.host = try client.allocator.dupe(u8, tunnel_host); errdefer client.allocator.free(conn.host); conn.port = tunnel_port; conn.closing = false; return conn; }) catch { // something went wrong with the tunnel proxy.supports_connect = maybe_valid; return error.TunnelNotSupported; }; }