Skip to content

Commit 5d425e2

Browse files
committed
feat: wrapper for ngx_connection_t
1 parent 52798f4 commit 5d425e2

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ rust-version.workspace = true
2626

2727
[dependencies]
2828
allocator-api2 = { version = "0.2.21", default-features = false }
29+
libc = "0.2"
2930
lock_api = "0.4.13"
3031
nginx-sys = { path = "nginx-sys", default-features=false, version = "0.5.0"}
3132

src/core/connection.rs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
use core::mem::MaybeUninit;
2+
use core::ops::{Deref, DerefMut};
3+
4+
use crate::ffi::{self, ngx_connection_t, ngx_err_t};
5+
6+
/// Wrapper struct for an [`ngx_connection_t`] pointer
7+
///
8+
/// [`ngx_connection_t`]: http://nginx.org/en/docs/dev/development_guide.html#connection
9+
#[repr(transparent)]
10+
pub struct Connection(ngx_connection_t);
11+
12+
impl AsRef<ngx_connection_t> for Connection {
13+
fn as_ref(&self) -> &ngx_connection_t {
14+
&self.0
15+
}
16+
}
17+
18+
impl AsMut<ngx_connection_t> for Connection {
19+
fn as_mut(&mut self) -> &mut ngx_connection_t {
20+
&mut self.0
21+
}
22+
}
23+
24+
impl Deref for Connection {
25+
type Target = ngx_connection_t;
26+
27+
fn deref(&self) -> &Self::Target {
28+
self.as_ref()
29+
}
30+
}
31+
32+
impl DerefMut for Connection {
33+
fn deref_mut(&mut self) -> &mut Self::Target {
34+
self.as_mut()
35+
}
36+
}
37+
38+
impl Connection {
39+
/// Creates a new connection wrapper.
40+
pub fn from_ptr_mut<'a>(c: *mut ngx_connection_t) -> &'a mut Self {
41+
unsafe { &mut *c.cast::<Self>() }
42+
}
43+
44+
/// Returns a connection pool reference
45+
pub fn pool(&mut self) -> &mut ffi::ngx_pool_t {
46+
debug_assert!(!self.0.pool.is_null());
47+
unsafe { &mut *self.0.pool }
48+
}
49+
50+
/// Returns a read event reference
51+
pub fn read(&mut self) -> &mut ffi::ngx_event_t {
52+
debug_assert!(!self.0.read.is_null());
53+
unsafe { &mut *self.0.read }
54+
}
55+
56+
/// Returns a write event reference
57+
pub fn write(&mut self) -> &mut ffi::ngx_event_t {
58+
debug_assert!(!self.0.write.is_null());
59+
unsafe { &mut *self.0.write }
60+
}
61+
62+
/// Check `connect` result
63+
pub fn test_connect(&mut self) -> Result<(), ngx_err_t> {
64+
#[cfg(ngx_feature = "have_kqueue")]
65+
if unsafe { ffi::ngx_event_flags } & (ffi::NGX_USE_KQUEUE_EVENT as usize) != 0 {
66+
if self.write().pending_eof() != 0 || self.read().pending_eof() != 0 {
67+
let err = if self.write().pending_eof() != 0 {
68+
self.write().kq_errno
69+
} else {
70+
self.read().kq_errno
71+
};
72+
73+
self.error(err, c"kevent() reported that connect() failed");
74+
return Err(err);
75+
} else {
76+
return Ok(());
77+
}
78+
}
79+
80+
let mut err: std::ffi::c_int = 0;
81+
let mut len: libc::socklen_t = std::mem::size_of_val(&err) as _;
82+
83+
// BSDs and Linux return 0 and set a pending error in err
84+
// Solaris returns -1 and sets errno
85+
if unsafe {
86+
libc::getsockopt(
87+
self.0.fd,
88+
libc::SOL_SOCKET as _,
89+
libc::SO_ERROR as _,
90+
std::ptr::addr_of_mut!(err).cast(),
91+
&mut len,
92+
) == -1
93+
} {
94+
err = ffi::ngx_socket_errno() as _;
95+
}
96+
97+
if err != 0 {
98+
self.error(err, c"connect() failed");
99+
Err(err)
100+
} else {
101+
Ok(())
102+
}
103+
}
104+
105+
/// Handle OS errors
106+
pub fn error(&mut self, err: ngx_err_t, msg: &std::ffi::CStr) -> ffi::ngx_int_t {
107+
unsafe { ffi::ngx_connection_error(self.as_mut(), err, msg.as_ptr().cast_mut()) }
108+
}
109+
110+
/// Receive data from the connection
111+
pub fn recv(&mut self, buf: &mut [MaybeUninit<u8>]) -> isize {
112+
// send and recv are always set
113+
unsafe {
114+
self.as_ref().recv.unwrap_unchecked()(self.as_mut(), buf.as_mut_ptr().cast(), buf.len())
115+
}
116+
}
117+
118+
/// Send data to the connection
119+
pub fn send(&mut self, buf: &[u8]) -> isize {
120+
// send and recv are always set
121+
unsafe {
122+
self.as_ref().send.unwrap_unchecked()(self.as_mut(), buf.as_ptr().cast_mut(), buf.len())
123+
}
124+
}
125+
126+
/// Shutdown the connection
127+
pub fn shutdown(&mut self, how: std::ffi::c_int) -> Result<(), ngx_err_t> {
128+
if unsafe { libc::shutdown(self.0.fd, how) } == -1 {
129+
return Err(ffi::ngx_socket_errno());
130+
}
131+
Ok(())
132+
}
133+
134+
/// Close the connection
135+
pub fn close(&mut self) {
136+
unsafe { ffi::ngx_close_connection(self.as_mut()) }
137+
}
138+
}

src/core/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
mod buffer;
2+
mod connection;
23
mod pool;
34
pub mod slab;
45
mod status;
56
mod string;
67

78
pub use buffer::*;
9+
pub use connection::*;
810
pub use pool::*;
911
pub use slab::SlabPool;
1012
pub use status::*;

0 commit comments

Comments
 (0)