1use crate::{error::Error, ffi::*};
2use std::time::Instant;
3
4use bytes::{Bytes, BytesMut};
5
6#[derive(Debug, Clone, Copy)]
7pub struct KcpConfig {
8 pub conv: IUINT32,
9 pub mtu: Option<i32>,
10
11 pub sndwnd: Option<i32>,
12 pub rcvwnd: Option<i32>,
13
14 pub nodelay: Option<i32>,
15 pub interval: Option<i32>,
16 pub resend: Option<i32>,
17 pub nc: Option<i32>,
18}
19
20impl KcpConfig {
21 pub fn new(conv: IUINT32) -> Self {
22 Self {
23 conv,
24 mtu: None,
25 sndwnd: None,
26 rcvwnd: None,
27 nodelay: None,
28 interval: None,
29 resend: None,
30 nc: None,
31 }
32 }
33
34 pub fn new_turbo(conv: IUINT32) -> Self {
35 Self {
36 conv,
37 mtu: Some(1200),
38 sndwnd: Some(1024),
39 rcvwnd: Some(1024),
40 nodelay: Some(1),
41 interval: Some(10),
42 resend: Some(2),
43 nc: Some(1),
44 }
45 }
46}
47
48pub type OutputCb = Box<dyn Fn(u32, BytesMut) -> Result<(), Error>>;
49
50pub struct Kcp {
51 kcp: *mut ikcpcb,
52 config: KcpConfig,
53 now: Instant,
54 output_cb: Option<Box<dyn Fn(u32, BytesMut) -> Result<(), Error>>>,
55
56 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
57}
58
59unsafe impl Send for Kcp {}
60
61unsafe extern "C" fn ikcp_output(
62 buf: *const ::std::os::raw::c_char,
63 len: ::std::os::raw::c_int,
64 kcp: *mut ikcpcb,
65 this: *mut ::std::os::raw::c_void,
66) -> i32 {
67 let kcp_connection = &mut *(this as *mut Kcp);
69 assert_eq!(kcp_connection.kcp, kcp);
70
71 let buf = BytesMut::from(std::slice::from_raw_parts(buf as *const u8, len as usize));
72
73 let _ = kcp_connection.handle_output_callback(buf);
75
76 0
78}
79
80impl Kcp {
81 pub fn new(config: KcpConfig) -> Result<Box<Self>, Error> {
82 unsafe {
83 let conv = config.conv;
84 let mut ret = Box::new(Self {
85 kcp: std::ptr::null_mut(),
86 config,
87 now: Instant::now(),
88 output_cb: None,
89 _marker: core::marker::PhantomData,
90 });
91
92 let kcp = ikcp_create(conv, &mut *ret as *mut Kcp as *mut ::std::os::raw::c_void);
93 if kcp.is_null() {
94 return Err(Error::CreateConnectionFailed);
95 }
96
97 (*kcp).stream = 1;
98
99 ret.kcp = kcp;
100
101 ikcp_setoutput(kcp, Some(ikcp_output));
102
103 ret.apply_config()?;
104
105 return Ok(ret);
106 }
107 }
108
109 pub fn set_output_cb(&mut self, output_cb: OutputCb) {
110 self.output_cb = Some(output_cb);
111 }
112
113 pub fn handle_input(&mut self, data: &[u8]) -> Result<(), Error> {
114 let ret = unsafe { ikcp_input(self.kcp, data.as_ptr() as *const _, data.len() as _) };
115 if ret < 0 {
116 return Err(anyhow::anyhow!("input failed, return: {}", ret).into());
117 } else {
118 return Ok(());
119 }
120 }
121
122 pub fn update(&mut self) {
123 unsafe {
124 ikcp_update(self.kcp, self.now.elapsed().as_millis() as IUINT32);
125 }
126 }
127
128 pub fn next_update_delay_ms(&mut self) -> IUINT32 {
129 let current = self.now.elapsed().as_millis() as IUINT32;
130 let next = unsafe { ikcp_check(self.kcp, current) };
131 next - current
132 }
133
134 pub fn send(&mut self, data: Bytes) -> Result<usize, Error> {
135 let ret = unsafe { ikcp_send(self.kcp, data.as_ptr() as *const _, data.len() as _) };
136 if ret < 0 {
137 return Err(anyhow::anyhow!("send failed, return: {}", ret).into());
138 } else {
139 return Ok(ret as usize);
140 }
141 }
142
143 pub fn flush(&mut self) {
144 unsafe {
145 ikcp_flush(self.kcp);
146 }
147 }
148
149 pub fn peeksize(&self) -> i32 {
150 unsafe { ikcp_peeksize(self.kcp) }
151 }
152
153 pub fn recv(&mut self, buf: &mut BytesMut) -> Result<(), Error> {
154 let ret = unsafe { ikcp_recv(self.kcp, buf.as_mut_ptr() as *mut _, buf.capacity() as _) };
155 if ret < 0 {
156 return Err(anyhow::anyhow!("recv failed, return: {}", ret).into());
157 } else {
158 unsafe {
159 buf.set_len(ret as usize);
160 }
161 return Ok(());
162 }
163 }
164
165 pub fn waitsnd(&self) -> i32 {
166 unsafe { ikcp_waitsnd(self.kcp) }
167 }
168
169 pub fn sendwnd(&self) -> i32 {
170 self.config.sndwnd.unwrap_or(32)
172 }
173
174 fn handle_output_callback(&self, buf: BytesMut) -> Result<(), Error> {
175 (self.output_cb.as_ref().unwrap())(self.config.conv, buf)
176 }
177
178 fn apply_config(&mut self) -> Result<(), Error> {
179 unsafe {
180 let ret = ikcp_setmtu(self.kcp, self.config.mtu.unwrap_or(1200));
181 if ret < 0 {
182 return Err(anyhow::anyhow!("setmtu failed, return: {}", ret).into());
183 }
184
185 let ret = ikcp_wndsize(
186 self.kcp,
187 self.config.sndwnd.unwrap_or(-1),
188 self.config.rcvwnd.unwrap_or(-1),
189 );
190 if ret < 0 {
191 return Err(anyhow::anyhow!("wndsize failed, return: {}", ret).into());
192 }
193
194 let ret = ikcp_nodelay(
195 self.kcp,
196 self.config.nodelay.unwrap_or(-1),
197 self.config.interval.unwrap_or(-1),
198 self.config.resend.unwrap_or(-1),
199 self.config.nc.unwrap_or(-1),
200 );
201 if ret < 0 {
202 return Err(anyhow::anyhow!("nodelay failed, return: {}", ret).into());
203 }
204
205 if let Some(interval) = self.config.interval {
206 if interval > 0 {
207 (*self.kcp).interval = interval as _;
208 }
209 }
210 }
211
212 return Ok(());
213 }
214}
215
216impl Drop for Kcp {
217 fn drop(&mut self) {
218 unsafe {
219 ikcp_release(self.kcp);
220 }
221 }
222}