use std::sync::Arc;
use libc::c_int;
use crate::client::conn;
use crate::rt::Executor as _;
use super::error::hyper_code;
use super::http_types::{hyper_request, hyper_response};
use super::io::Io;
use super::task::{hyper_task_return_type, AsTaskType, Exec, Task, WeakExec};
pub struct hyper_clientconn_options {
builder: conn::Builder,
exec: WeakExec,
}
pub struct hyper_clientconn {
tx: conn::SendRequest<crate::Body>,
}
ffi_fn! {
fn hyper_clientconn_handshake(io: *mut Io, options: *mut hyper_clientconn_options) -> *mut Task {
if io.is_null() {
return std::ptr::null_mut();
}
if options.is_null() {
return std::ptr::null_mut();
}
let options = unsafe { Box::from_raw(options) };
let io = unsafe { Box::from_raw(io) };
Box::into_raw(Task::boxed(async move {
options.builder.handshake::<_, crate::Body>(io)
.await
.map(|(tx, conn)| {
options.exec.execute(Box::pin(async move {
let _ = conn.await;
}));
hyper_clientconn { tx }
})
}))
}
}
ffi_fn! {
fn hyper_clientconn_send(conn: *mut hyper_clientconn, req: *mut hyper_request) -> *mut Task {
if conn.is_null() {
return std::ptr::null_mut();
}
if req.is_null() {
return std::ptr::null_mut();
}
let mut req = unsafe { Box::from_raw(req) };
req.finalize_request();
let fut = unsafe { &mut *conn }.tx.send_request(req.0);
let fut = async move {
fut.await.map(hyper_response::wrap)
};
Box::into_raw(Task::boxed(fut))
}
}
ffi_fn! {
fn hyper_clientconn_free(conn: *mut hyper_clientconn) {
drop(unsafe { Box::from_raw(conn) });
}
}
unsafe impl AsTaskType for hyper_clientconn {
fn as_task_type(&self) -> hyper_task_return_type {
hyper_task_return_type::HYPER_TASK_CLIENTCONN
}
}
ffi_fn! {
fn hyper_clientconn_options_new() -> *mut hyper_clientconn_options {
Box::into_raw(Box::new(hyper_clientconn_options {
builder: conn::Builder::new(),
exec: WeakExec::new(),
}))
}
}
ffi_fn! {
fn hyper_clientconn_options_free(opts: *mut hyper_clientconn_options) {
drop(unsafe { Box::from_raw(opts) });
}
}
ffi_fn! {
fn hyper_clientconn_options_exec(opts: *mut hyper_clientconn_options, exec: *const Exec) {
let opts = unsafe { &mut *opts };
let exec = unsafe { Arc::from_raw(exec) };
let weak_exec = Exec::downgrade(&exec);
std::mem::forget(exec);
opts.builder.executor(weak_exec.clone());
opts.exec = weak_exec;
}
}
ffi_fn! {
fn hyper_clientconn_options_http2(opts: *mut hyper_clientconn_options, enabled: c_int) -> hyper_code {
#[cfg(feature = "http2")]
{
let opts = unsafe { &mut *opts };
opts.builder.http2_only(enabled != 0);
hyper_code::HYPERE_OK
}
#[cfg(not(feature = "http2"))]
{
drop(opts);
drop(enabled);
hyper_code::HYPERE_FEATURE_NOT_ENABLED
}
}
}