1use std::{
9 collections::HashMap,
10 marker::PhantomData,
11 sync::{Arc, Mutex},
12};
13
14use spin_connection_semaphore::{ConnectionPermit, ConnectionSemaphore};
15use wasmtime::component::{HasData, Resource};
16use wasmtime_wasi::p2::bindings::sockets::tcp::{self as p2_tcp, IpSocketAddress, ShutdownType};
17use wasmtime_wasi::p2::bindings::sockets::tcp_create_socket as p2_tcp_create;
18use wasmtime_wasi::p2::bindings::sockets::udp as p2_udp;
19use wasmtime_wasi::p2::bindings::sockets::udp_create_socket as p2_udp_create;
20use wasmtime_wasi::p2::{DynInputStream, DynOutputStream, DynPollable};
21use wasmtime_wasi::p2::{TcpSocket, UdpSocket};
22use wasmtime_wasi::{
23 p2::bindings::sockets::network::{ErrorCode as SocketErrorCode, Host as NetworkHost, Network},
24 sockets::{WasiSockets, WasiSocketsCtxView},
25};
26
27pub struct SocketPermitState {
31 semaphore: ConnectionSemaphore,
32 active: Mutex<HashMap<u32, ConnectionPermit>>,
34}
35
36impl SocketPermitState {
37 pub fn new(semaphore: ConnectionSemaphore) -> Arc<Self> {
38 Arc::new(Self {
39 semaphore,
40 active: Mutex::new(HashMap::new()),
41 })
42 }
43}
44
45pub struct SpinSocketsView<'a, T> {
48 pub(crate) inner: WasiSocketsCtxView<'a>,
49 pub(crate) permit_state: Option<Arc<SocketPermitState>>,
50 pub(crate) getter: fn(&mut T) -> WasiSocketsCtxView<'_>,
51}
52
53impl<'a, T> std::ops::Deref for SpinSocketsView<'a, T> {
54 type Target = WasiSocketsCtxView<'a>;
55 fn deref(&self) -> &Self::Target {
56 &self.inner
57 }
58}
59
60impl<T> std::ops::DerefMut for SpinSocketsView<'_, T> {
61 fn deref_mut(&mut self) -> &mut Self::Target {
62 &mut self.inner
63 }
64}
65
66pub struct SpinSockets<T>(PhantomData<fn() -> T>);
70
71impl<T: 'static> HasData for SpinSockets<T> {
72 type Data<'a> = SpinSocketsView<'a, T>;
73}
74
75impl<'a, T> SpinSocketsView<'a, T> {
76 pub fn into_wasi(self) -> WasiSocketsCtxView<'a> {
78 self.inner
79 }
80}
81
82impl<T> SpinSocketsView<'_, T> {
83 pub(crate) fn try_acquire(&self) -> Result<Option<ConnectionPermit>, ()> {
91 let Some(state) = &self.permit_state else {
92 return Ok(None);
93 };
94 state.semaphore.try_acquire().map(Some).ok_or(())
95 }
96
97 pub(crate) fn register_permit(&self, socket_rep: u32, permit: Option<ConnectionPermit>) {
100 let (Some(state), Some(permit)) = (&self.permit_state, permit) else {
101 return;
102 };
103 state
104 .active
105 .lock()
106 .unwrap_or_else(|e| e.into_inner())
107 .insert(socket_rep, permit);
108 }
109
110 pub(crate) fn release_permit(&self, socket_rep: u32) {
112 if let Some(state) = &self.permit_state {
113 state
114 .active
115 .lock()
116 .unwrap_or_else(|e| e.into_inner())
117 .remove(&socket_rep);
118 }
119 }
120}
121
122impl<T> p2_tcp::Host for SpinSocketsView<'_, T> {}
123
124impl<T> p2_tcp::HostTcpSocket for SpinSocketsView<'_, T> {
125 async fn start_bind(
126 &mut self,
127 this: Resource<TcpSocket>,
128 network: Resource<Network>,
129 local_address: IpSocketAddress,
130 ) -> wasmtime_wasi::p2::SocketResult<()> {
131 p2_tcp::HostTcpSocket::start_bind(&mut self.inner, this, network, local_address).await
132 }
133
134 fn finish_bind(&mut self, this: Resource<TcpSocket>) -> wasmtime_wasi::p2::SocketResult<()> {
135 p2_tcp::HostTcpSocket::finish_bind(&mut self.inner, this)
136 }
137
138 fn start_connect(
139 &mut self,
140 this: Resource<TcpSocket>,
141 network: Resource<Network>,
142 remote_address: IpSocketAddress,
143 ) -> wasmtime_wasi::p2::SocketResult<()> {
144 p2_tcp::HostTcpSocket::start_connect(&mut self.inner, this, network, remote_address)
145 }
146
147 fn finish_connect(
148 &mut self,
149 this: Resource<TcpSocket>,
150 ) -> wasmtime_wasi::p2::SocketResult<(Resource<DynInputStream>, Resource<DynOutputStream>)>
151 {
152 p2_tcp::HostTcpSocket::finish_connect(&mut self.inner, this)
153 }
154
155 async fn start_listen(
156 &mut self,
157 this: Resource<TcpSocket>,
158 ) -> wasmtime_wasi::p2::SocketResult<()> {
159 p2_tcp::HostTcpSocket::start_listen(&mut self.inner, this).await
160 }
161
162 fn finish_listen(&mut self, this: Resource<TcpSocket>) -> wasmtime_wasi::p2::SocketResult<()> {
163 p2_tcp::HostTcpSocket::finish_listen(&mut self.inner, this)
164 }
165
166 fn accept(
167 &mut self,
168 this: Resource<TcpSocket>,
169 ) -> wasmtime_wasi::p2::SocketResult<(
170 Resource<TcpSocket>,
171 Resource<DynInputStream>,
172 Resource<DynOutputStream>,
173 )> {
174 p2_tcp::HostTcpSocket::accept(&mut self.inner, this)
175 }
176
177 fn local_address(
178 &mut self,
179 this: Resource<TcpSocket>,
180 ) -> wasmtime_wasi::p2::SocketResult<IpSocketAddress> {
181 p2_tcp::HostTcpSocket::local_address(&mut self.inner, this)
182 }
183
184 fn remote_address(
185 &mut self,
186 this: Resource<TcpSocket>,
187 ) -> wasmtime_wasi::p2::SocketResult<IpSocketAddress> {
188 p2_tcp::HostTcpSocket::remote_address(&mut self.inner, this)
189 }
190
191 fn is_listening(&mut self, this: Resource<TcpSocket>) -> wasmtime::Result<bool> {
192 p2_tcp::HostTcpSocket::is_listening(&mut self.inner, this)
193 }
194
195 fn address_family(
196 &mut self,
197 this: Resource<TcpSocket>,
198 ) -> wasmtime::Result<wasmtime_wasi::p2::bindings::sockets::network::IpAddressFamily> {
199 p2_tcp::HostTcpSocket::address_family(&mut self.inner, this)
200 }
201
202 fn set_listen_backlog_size(
203 &mut self,
204 this: Resource<TcpSocket>,
205 value: u64,
206 ) -> wasmtime_wasi::p2::SocketResult<()> {
207 p2_tcp::HostTcpSocket::set_listen_backlog_size(&mut self.inner, this, value)
208 }
209
210 fn keep_alive_enabled(
211 &mut self,
212 this: Resource<TcpSocket>,
213 ) -> wasmtime_wasi::p2::SocketResult<bool> {
214 p2_tcp::HostTcpSocket::keep_alive_enabled(&mut self.inner, this)
215 }
216
217 fn set_keep_alive_enabled(
218 &mut self,
219 this: Resource<TcpSocket>,
220 value: bool,
221 ) -> wasmtime_wasi::p2::SocketResult<()> {
222 p2_tcp::HostTcpSocket::set_keep_alive_enabled(&mut self.inner, this, value)
223 }
224
225 fn keep_alive_idle_time(
226 &mut self,
227 this: Resource<TcpSocket>,
228 ) -> wasmtime_wasi::p2::SocketResult<u64> {
229 p2_tcp::HostTcpSocket::keep_alive_idle_time(&mut self.inner, this)
230 }
231
232 fn set_keep_alive_idle_time(
233 &mut self,
234 this: Resource<TcpSocket>,
235 value: u64,
236 ) -> wasmtime_wasi::p2::SocketResult<()> {
237 p2_tcp::HostTcpSocket::set_keep_alive_idle_time(&mut self.inner, this, value)
238 }
239
240 fn keep_alive_interval(
241 &mut self,
242 this: Resource<TcpSocket>,
243 ) -> wasmtime_wasi::p2::SocketResult<u64> {
244 p2_tcp::HostTcpSocket::keep_alive_interval(&mut self.inner, this)
245 }
246
247 fn set_keep_alive_interval(
248 &mut self,
249 this: Resource<TcpSocket>,
250 value: u64,
251 ) -> wasmtime_wasi::p2::SocketResult<()> {
252 p2_tcp::HostTcpSocket::set_keep_alive_interval(&mut self.inner, this, value)
253 }
254
255 fn keep_alive_count(
256 &mut self,
257 this: Resource<TcpSocket>,
258 ) -> wasmtime_wasi::p2::SocketResult<u32> {
259 p2_tcp::HostTcpSocket::keep_alive_count(&mut self.inner, this)
260 }
261
262 fn set_keep_alive_count(
263 &mut self,
264 this: Resource<TcpSocket>,
265 value: u32,
266 ) -> wasmtime_wasi::p2::SocketResult<()> {
267 p2_tcp::HostTcpSocket::set_keep_alive_count(&mut self.inner, this, value)
268 }
269
270 fn hop_limit(&mut self, this: Resource<TcpSocket>) -> wasmtime_wasi::p2::SocketResult<u8> {
271 p2_tcp::HostTcpSocket::hop_limit(&mut self.inner, this)
272 }
273
274 fn set_hop_limit(
275 &mut self,
276 this: Resource<TcpSocket>,
277 value: u8,
278 ) -> wasmtime_wasi::p2::SocketResult<()> {
279 p2_tcp::HostTcpSocket::set_hop_limit(&mut self.inner, this, value)
280 }
281
282 fn receive_buffer_size(
283 &mut self,
284 this: Resource<TcpSocket>,
285 ) -> wasmtime_wasi::p2::SocketResult<u64> {
286 p2_tcp::HostTcpSocket::receive_buffer_size(&mut self.inner, this)
287 }
288
289 fn set_receive_buffer_size(
290 &mut self,
291 this: Resource<TcpSocket>,
292 value: u64,
293 ) -> wasmtime_wasi::p2::SocketResult<()> {
294 p2_tcp::HostTcpSocket::set_receive_buffer_size(&mut self.inner, this, value)
295 }
296
297 fn send_buffer_size(
298 &mut self,
299 this: Resource<TcpSocket>,
300 ) -> wasmtime_wasi::p2::SocketResult<u64> {
301 p2_tcp::HostTcpSocket::send_buffer_size(&mut self.inner, this)
302 }
303
304 fn set_send_buffer_size(
305 &mut self,
306 this: Resource<TcpSocket>,
307 value: u64,
308 ) -> wasmtime_wasi::p2::SocketResult<()> {
309 p2_tcp::HostTcpSocket::set_send_buffer_size(&mut self.inner, this, value)
310 }
311
312 fn subscribe(&mut self, this: Resource<TcpSocket>) -> wasmtime::Result<Resource<DynPollable>> {
313 p2_tcp::HostTcpSocket::subscribe(&mut self.inner, this)
314 }
315
316 fn shutdown(
317 &mut self,
318 this: Resource<TcpSocket>,
319 shutdown_type: ShutdownType,
320 ) -> wasmtime_wasi::p2::SocketResult<()> {
321 p2_tcp::HostTcpSocket::shutdown(&mut self.inner, this, shutdown_type)
322 }
323
324 fn drop(&mut self, this: Resource<TcpSocket>) -> wasmtime::Result<()> {
325 self.release_permit(this.rep());
326 p2_tcp::HostTcpSocket::drop(&mut self.inner, this)
327 }
328}
329
330impl<T> NetworkHost for SpinSocketsView<'_, T> {
331 fn convert_error_code(
332 &mut self,
333 error: wasmtime_wasi::p2::SocketError,
334 ) -> wasmtime::Result<wasmtime_wasi::p2::bindings::sockets::network::ErrorCode> {
335 NetworkHost::convert_error_code(&mut self.inner, error)
336 }
337
338 fn network_error_code(
339 &mut self,
340 err: Resource<wasmtime::Error>,
341 ) -> wasmtime::Result<Option<wasmtime_wasi::p2::bindings::sockets::network::ErrorCode>> {
342 NetworkHost::network_error_code(&mut self.inner, err)
343 }
344}
345
346impl<T> wasmtime_wasi::p2::bindings::sockets::network::HostNetwork for SpinSocketsView<'_, T> {
347 fn drop(&mut self, this: Resource<Network>) -> wasmtime::Result<()> {
348 wasmtime_wasi::p2::bindings::sockets::network::HostNetwork::drop(&mut self.inner, this)
349 }
350}
351
352impl<T> p2_tcp_create::Host for SpinSocketsView<'_, T> {
353 fn create_tcp_socket(
354 &mut self,
355 address_family: wasmtime_wasi::p2::bindings::sockets::network::IpAddressFamily,
356 ) -> wasmtime_wasi::p2::SocketResult<Resource<TcpSocket>> {
357 let Ok(permit) = self.try_acquire() else {
360 tracing::warn!("TCP socket creation refused: connection quota exhausted");
361 return Err(SocketErrorCode::NewSocketLimit.into());
362 };
363 let socket = p2_tcp_create::Host::create_tcp_socket(&mut self.inner, address_family)?;
364 self.register_permit(socket.rep(), permit);
365 Ok(socket)
366 }
367}
368
369impl<T> p2_udp::Host for SpinSocketsView<'_, T> {}
370
371impl<T> p2_udp::HostUdpSocket for SpinSocketsView<'_, T> {
372 async fn start_bind(
373 &mut self,
374 this: Resource<p2_udp::UdpSocket>,
375 network: Resource<p2_udp::Network>,
376 local_address: p2_udp::IpSocketAddress,
377 ) -> wasmtime_wasi::p2::SocketResult<()> {
378 p2_udp::HostUdpSocket::start_bind(&mut self.inner, this, network, local_address).await
379 }
380
381 fn finish_bind(
382 &mut self,
383 this: Resource<p2_udp::UdpSocket>,
384 ) -> wasmtime_wasi::p2::SocketResult<()> {
385 p2_udp::HostUdpSocket::finish_bind(&mut self.inner, this)
386 }
387
388 async fn stream(
389 &mut self,
390 this: Resource<p2_udp::UdpSocket>,
391 remote_address: Option<p2_udp::IpSocketAddress>,
392 ) -> wasmtime_wasi::p2::SocketResult<(
393 Resource<p2_udp::IncomingDatagramStream>,
394 Resource<p2_udp::OutgoingDatagramStream>,
395 )> {
396 p2_udp::HostUdpSocket::stream(&mut self.inner, this, remote_address).await
397 }
398
399 fn local_address(
400 &mut self,
401 this: Resource<p2_udp::UdpSocket>,
402 ) -> wasmtime_wasi::p2::SocketResult<p2_udp::IpSocketAddress> {
403 p2_udp::HostUdpSocket::local_address(&mut self.inner, this)
404 }
405
406 fn remote_address(
407 &mut self,
408 this: Resource<p2_udp::UdpSocket>,
409 ) -> wasmtime_wasi::p2::SocketResult<p2_udp::IpSocketAddress> {
410 p2_udp::HostUdpSocket::remote_address(&mut self.inner, this)
411 }
412
413 fn address_family(
414 &mut self,
415 this: Resource<p2_udp::UdpSocket>,
416 ) -> wasmtime::Result<p2_udp::IpAddressFamily> {
417 p2_udp::HostUdpSocket::address_family(&mut self.inner, this)
418 }
419
420 fn unicast_hop_limit(
421 &mut self,
422 this: Resource<p2_udp::UdpSocket>,
423 ) -> wasmtime_wasi::p2::SocketResult<u8> {
424 p2_udp::HostUdpSocket::unicast_hop_limit(&mut self.inner, this)
425 }
426
427 fn set_unicast_hop_limit(
428 &mut self,
429 this: Resource<p2_udp::UdpSocket>,
430 value: u8,
431 ) -> wasmtime_wasi::p2::SocketResult<()> {
432 p2_udp::HostUdpSocket::set_unicast_hop_limit(&mut self.inner, this, value)
433 }
434
435 fn receive_buffer_size(
436 &mut self,
437 this: Resource<p2_udp::UdpSocket>,
438 ) -> wasmtime_wasi::p2::SocketResult<u64> {
439 p2_udp::HostUdpSocket::receive_buffer_size(&mut self.inner, this)
440 }
441
442 fn set_receive_buffer_size(
443 &mut self,
444 this: Resource<p2_udp::UdpSocket>,
445 value: u64,
446 ) -> wasmtime_wasi::p2::SocketResult<()> {
447 p2_udp::HostUdpSocket::set_receive_buffer_size(&mut self.inner, this, value)
448 }
449
450 fn send_buffer_size(
451 &mut self,
452 this: Resource<p2_udp::UdpSocket>,
453 ) -> wasmtime_wasi::p2::SocketResult<u64> {
454 p2_udp::HostUdpSocket::send_buffer_size(&mut self.inner, this)
455 }
456
457 fn set_send_buffer_size(
458 &mut self,
459 this: Resource<p2_udp::UdpSocket>,
460 value: u64,
461 ) -> wasmtime_wasi::p2::SocketResult<()> {
462 p2_udp::HostUdpSocket::set_send_buffer_size(&mut self.inner, this, value)
463 }
464
465 fn subscribe(
466 &mut self,
467 this: Resource<p2_udp::UdpSocket>,
468 ) -> wasmtime::Result<Resource<DynPollable>> {
469 p2_udp::HostUdpSocket::subscribe(&mut self.inner, this)
470 }
471
472 fn drop(&mut self, this: Resource<p2_udp::UdpSocket>) -> wasmtime::Result<()> {
473 self.release_permit(this.rep());
474 p2_udp::HostUdpSocket::drop(&mut self.inner, this)
475 }
476}
477
478impl<T> p2_udp::HostIncomingDatagramStream for SpinSocketsView<'_, T> {
479 fn receive(
480 &mut self,
481 this: Resource<p2_udp::IncomingDatagramStream>,
482 max_results: u64,
483 ) -> wasmtime_wasi::p2::SocketResult<Vec<p2_udp::IncomingDatagram>> {
484 p2_udp::HostIncomingDatagramStream::receive(&mut self.inner, this, max_results)
485 }
486
487 fn subscribe(
488 &mut self,
489 this: Resource<p2_udp::IncomingDatagramStream>,
490 ) -> wasmtime::Result<Resource<DynPollable>> {
491 p2_udp::HostIncomingDatagramStream::subscribe(&mut self.inner, this)
492 }
493
494 async fn drop(
495 &mut self,
496 this: Resource<p2_udp::IncomingDatagramStream>,
497 ) -> wasmtime::Result<()> {
498 p2_udp::HostIncomingDatagramStream::drop(&mut self.inner, this).await
499 }
500}
501
502impl<T> p2_udp::HostOutgoingDatagramStream for SpinSocketsView<'_, T> {
503 fn check_send(
504 &mut self,
505 this: Resource<p2_udp::OutgoingDatagramStream>,
506 ) -> wasmtime_wasi::p2::SocketResult<u64> {
507 p2_udp::HostOutgoingDatagramStream::check_send(&mut self.inner, this)
508 }
509
510 fn send(
511 &mut self,
512 this: Resource<p2_udp::OutgoingDatagramStream>,
513 datagrams: Vec<p2_udp::OutgoingDatagram>,
514 ) -> wasmtime_wasi::p2::SocketResult<u64> {
515 p2_udp::HostOutgoingDatagramStream::send(&mut self.inner, this, datagrams)
516 }
517
518 fn subscribe(
519 &mut self,
520 this: Resource<p2_udp::OutgoingDatagramStream>,
521 ) -> wasmtime::Result<Resource<DynPollable>> {
522 p2_udp::HostOutgoingDatagramStream::subscribe(&mut self.inner, this)
523 }
524
525 async fn drop(
526 &mut self,
527 this: Resource<p2_udp::OutgoingDatagramStream>,
528 ) -> wasmtime::Result<()> {
529 p2_udp::HostOutgoingDatagramStream::drop(&mut self.inner, this).await
530 }
531}
532
533impl<T> p2_udp_create::Host for SpinSocketsView<'_, T> {
534 async fn create_udp_socket(
535 &mut self,
536 address_family: wasmtime_wasi::p2::bindings::sockets::network::IpAddressFamily,
537 ) -> wasmtime_wasi::p2::SocketResult<Resource<UdpSocket>> {
538 let Ok(permit) = self.try_acquire() else {
541 tracing::warn!("UDP socket creation refused: connection quota exhausted");
542 return Err(SocketErrorCode::NewSocketLimit.into());
543 };
544 let sock = p2_udp_create::Host::create_udp_socket(&mut self.inner, address_family).await?;
545 self.register_permit(sock.rep(), permit);
546 Ok(sock)
547 }
548}
549
550use wasmtime::AsContextMut as _;
553use wasmtime::component::{Access, Accessor};
554use wasmtime_wasi::p3::bindings::sockets::types::{
555 self as p3_types, Duration as p3_Duration, ErrorCode as p3_ErrorCode, Host as p3_Host,
556 HostTcpSocket as p3_HostTcpSocket, HostTcpSocketWithStore, HostUdpSocket as p3_HostUdpSocket,
557 HostUdpSocketWithStore, IpAddressFamily as p3_IpAddressFamily,
558 IpSocketAddress as p3_IpSocketAddress,
559};
560use wasmtime_wasi::p3::sockets::SocketResult as P3SocketResult;
561
562impl<T> p3_Host for SpinSocketsView<'_, T> {
563 fn convert_error_code(
564 &mut self,
565 error: wasmtime_wasi::p3::sockets::SocketError,
566 ) -> wasmtime::Result<p3_ErrorCode> {
567 p3_Host::convert_error_code(&mut self.inner, error)
568 }
569}
570
571impl<T> p3_HostTcpSocket for SpinSocketsView<'_, T> {
572 async fn bind(
573 &mut self,
574 socket: Resource<p3_types::TcpSocket>,
575 local_address: p3_IpSocketAddress,
576 ) -> P3SocketResult<()> {
577 p3_HostTcpSocket::bind(&mut self.inner, socket, local_address).await
578 }
579
580 fn create(
581 &mut self,
582 address_family: p3_IpAddressFamily,
583 ) -> P3SocketResult<Resource<p3_types::TcpSocket>> {
584 let Ok(permit) = self.try_acquire() else {
585 tracing::warn!("TCP socket creation refused: connection quota exhausted");
586 return Err(p3_ErrorCode::Other(Some("connection quota exhausted".into())).into());
587 };
588 let socket = p3_HostTcpSocket::create(&mut self.inner, address_family)?;
589 self.register_permit(socket.rep(), permit);
590 Ok(socket)
591 }
592
593 fn get_local_address(
594 &mut self,
595 socket: Resource<p3_types::TcpSocket>,
596 ) -> P3SocketResult<p3_IpSocketAddress> {
597 p3_HostTcpSocket::get_local_address(&mut self.inner, socket)
598 }
599
600 fn get_remote_address(
601 &mut self,
602 socket: Resource<p3_types::TcpSocket>,
603 ) -> P3SocketResult<p3_IpSocketAddress> {
604 p3_HostTcpSocket::get_remote_address(&mut self.inner, socket)
605 }
606
607 fn get_is_listening(
608 &mut self,
609 socket: Resource<p3_types::TcpSocket>,
610 ) -> wasmtime::Result<bool> {
611 p3_HostTcpSocket::get_is_listening(&mut self.inner, socket)
612 }
613
614 fn get_address_family(
615 &mut self,
616 socket: Resource<p3_types::TcpSocket>,
617 ) -> wasmtime::Result<p3_IpAddressFamily> {
618 p3_HostTcpSocket::get_address_family(&mut self.inner, socket)
619 }
620
621 fn set_listen_backlog_size(
622 &mut self,
623 socket: Resource<p3_types::TcpSocket>,
624 value: u64,
625 ) -> P3SocketResult<()> {
626 p3_HostTcpSocket::set_listen_backlog_size(&mut self.inner, socket, value)
627 }
628
629 fn get_keep_alive_enabled(
630 &mut self,
631 socket: Resource<p3_types::TcpSocket>,
632 ) -> P3SocketResult<bool> {
633 p3_HostTcpSocket::get_keep_alive_enabled(&mut self.inner, socket)
634 }
635
636 fn set_keep_alive_enabled(
637 &mut self,
638 socket: Resource<p3_types::TcpSocket>,
639 value: bool,
640 ) -> P3SocketResult<()> {
641 p3_HostTcpSocket::set_keep_alive_enabled(&mut self.inner, socket, value)
642 }
643
644 fn get_keep_alive_idle_time(
645 &mut self,
646 socket: Resource<p3_types::TcpSocket>,
647 ) -> P3SocketResult<p3_Duration> {
648 p3_HostTcpSocket::get_keep_alive_idle_time(&mut self.inner, socket)
649 }
650
651 fn set_keep_alive_idle_time(
652 &mut self,
653 socket: Resource<p3_types::TcpSocket>,
654 value: p3_Duration,
655 ) -> P3SocketResult<()> {
656 p3_HostTcpSocket::set_keep_alive_idle_time(&mut self.inner, socket, value)
657 }
658
659 fn get_keep_alive_interval(
660 &mut self,
661 socket: Resource<p3_types::TcpSocket>,
662 ) -> P3SocketResult<p3_Duration> {
663 p3_HostTcpSocket::get_keep_alive_interval(&mut self.inner, socket)
664 }
665
666 fn set_keep_alive_interval(
667 &mut self,
668 socket: Resource<p3_types::TcpSocket>,
669 value: p3_Duration,
670 ) -> P3SocketResult<()> {
671 p3_HostTcpSocket::set_keep_alive_interval(&mut self.inner, socket, value)
672 }
673
674 fn get_keep_alive_count(
675 &mut self,
676 socket: Resource<p3_types::TcpSocket>,
677 ) -> P3SocketResult<u32> {
678 p3_HostTcpSocket::get_keep_alive_count(&mut self.inner, socket)
679 }
680
681 fn set_keep_alive_count(
682 &mut self,
683 socket: Resource<p3_types::TcpSocket>,
684 value: u32,
685 ) -> P3SocketResult<()> {
686 p3_HostTcpSocket::set_keep_alive_count(&mut self.inner, socket, value)
687 }
688
689 fn get_hop_limit(&mut self, socket: Resource<p3_types::TcpSocket>) -> P3SocketResult<u8> {
690 p3_HostTcpSocket::get_hop_limit(&mut self.inner, socket)
691 }
692
693 fn set_hop_limit(
694 &mut self,
695 socket: Resource<p3_types::TcpSocket>,
696 value: u8,
697 ) -> P3SocketResult<()> {
698 p3_HostTcpSocket::set_hop_limit(&mut self.inner, socket, value)
699 }
700
701 fn get_receive_buffer_size(
702 &mut self,
703 socket: Resource<p3_types::TcpSocket>,
704 ) -> P3SocketResult<u64> {
705 p3_HostTcpSocket::get_receive_buffer_size(&mut self.inner, socket)
706 }
707
708 fn set_receive_buffer_size(
709 &mut self,
710 socket: Resource<p3_types::TcpSocket>,
711 value: u64,
712 ) -> P3SocketResult<()> {
713 p3_HostTcpSocket::set_receive_buffer_size(&mut self.inner, socket, value)
714 }
715
716 fn get_send_buffer_size(
717 &mut self,
718 socket: Resource<p3_types::TcpSocket>,
719 ) -> P3SocketResult<u64> {
720 p3_HostTcpSocket::get_send_buffer_size(&mut self.inner, socket)
721 }
722
723 fn set_send_buffer_size(
724 &mut self,
725 socket: Resource<p3_types::TcpSocket>,
726 value: u64,
727 ) -> P3SocketResult<()> {
728 p3_HostTcpSocket::set_send_buffer_size(&mut self.inner, socket, value)
729 }
730
731 fn drop(&mut self, sock: Resource<p3_types::TcpSocket>) -> wasmtime::Result<()> {
732 self.release_permit(sock.rep());
733 p3_HostTcpSocket::drop(&mut self.inner, sock)
734 }
735}
736
737impl<T> p3_HostUdpSocket for SpinSocketsView<'_, T> {
738 async fn bind(
739 &mut self,
740 socket: Resource<p3_types::UdpSocket>,
741 local_address: p3_IpSocketAddress,
742 ) -> P3SocketResult<()> {
743 p3_HostUdpSocket::bind(&mut self.inner, socket, local_address).await
744 }
745
746 async fn connect(
747 &mut self,
748 socket: Resource<p3_types::UdpSocket>,
749 remote_address: p3_IpSocketAddress,
750 ) -> P3SocketResult<()> {
751 p3_HostUdpSocket::connect(&mut self.inner, socket, remote_address).await
752 }
753
754 async fn create(
755 &mut self,
756 address_family: p3_IpAddressFamily,
757 ) -> P3SocketResult<Resource<p3_types::UdpSocket>> {
758 let Ok(permit) = self.try_acquire() else {
761 tracing::warn!("UDP socket creation refused: connection quota exhausted");
762 return Err(p3_ErrorCode::Other(Some("connection quota exhausted".into())).into());
763 };
764 let sock = p3_HostUdpSocket::create(&mut self.inner, address_family).await?;
765 self.register_permit(sock.rep(), permit);
766 Ok(sock)
767 }
768
769 fn disconnect(&mut self, socket: Resource<p3_types::UdpSocket>) -> P3SocketResult<()> {
770 p3_HostUdpSocket::disconnect(&mut self.inner, socket)
771 }
772
773 fn get_local_address(
774 &mut self,
775 socket: Resource<p3_types::UdpSocket>,
776 ) -> P3SocketResult<p3_IpSocketAddress> {
777 p3_HostUdpSocket::get_local_address(&mut self.inner, socket)
778 }
779
780 fn get_remote_address(
781 &mut self,
782 socket: Resource<p3_types::UdpSocket>,
783 ) -> P3SocketResult<p3_IpSocketAddress> {
784 p3_HostUdpSocket::get_remote_address(&mut self.inner, socket)
785 }
786
787 fn get_address_family(
788 &mut self,
789 socket: Resource<p3_types::UdpSocket>,
790 ) -> wasmtime::Result<p3_IpAddressFamily> {
791 p3_HostUdpSocket::get_address_family(&mut self.inner, socket)
792 }
793
794 fn get_unicast_hop_limit(
795 &mut self,
796 socket: Resource<p3_types::UdpSocket>,
797 ) -> P3SocketResult<u8> {
798 p3_HostUdpSocket::get_unicast_hop_limit(&mut self.inner, socket)
799 }
800
801 fn set_unicast_hop_limit(
802 &mut self,
803 socket: Resource<p3_types::UdpSocket>,
804 value: u8,
805 ) -> P3SocketResult<()> {
806 p3_HostUdpSocket::set_unicast_hop_limit(&mut self.inner, socket, value)
807 }
808
809 fn get_receive_buffer_size(
810 &mut self,
811 socket: Resource<p3_types::UdpSocket>,
812 ) -> P3SocketResult<u64> {
813 p3_HostUdpSocket::get_receive_buffer_size(&mut self.inner, socket)
814 }
815
816 fn set_receive_buffer_size(
817 &mut self,
818 socket: Resource<p3_types::UdpSocket>,
819 value: u64,
820 ) -> P3SocketResult<()> {
821 p3_HostUdpSocket::set_receive_buffer_size(&mut self.inner, socket, value)
822 }
823
824 fn get_send_buffer_size(
825 &mut self,
826 socket: Resource<p3_types::UdpSocket>,
827 ) -> P3SocketResult<u64> {
828 p3_HostUdpSocket::get_send_buffer_size(&mut self.inner, socket)
829 }
830
831 fn set_send_buffer_size(
832 &mut self,
833 socket: Resource<p3_types::UdpSocket>,
834 value: u64,
835 ) -> P3SocketResult<()> {
836 p3_HostUdpSocket::set_send_buffer_size(&mut self.inner, socket, value)
837 }
838
839 fn drop(&mut self, sock: Resource<p3_types::UdpSocket>) -> wasmtime::Result<()> {
840 self.release_permit(sock.rep());
841 p3_HostUdpSocket::drop(&mut self.inner, sock)
842 }
843}
844
845impl<T: Send + 'static> HostTcpSocketWithStore<T> for SpinSockets<T> {
846 async fn connect(
847 store: &Accessor<T, Self>,
848 socket: Resource<p3_types::TcpSocket>,
849 remote_address: p3_IpSocketAddress,
850 ) -> P3SocketResult<()> {
851 let getter = store.with(|mut store| store.get().getter);
852 let wasi_accessor = store.with_getter::<WasiSockets>(getter);
853 <WasiSockets as HostTcpSocketWithStore<T>>::connect(&wasi_accessor, socket, remote_address)
854 .await
855 }
856
857 async fn listen(
858 mut store: Access<'_, T, Self>,
859 socket: Resource<p3_types::TcpSocket>,
860 ) -> P3SocketResult<wasmtime::component::StreamReader<Resource<p3_types::TcpSocket>>> {
861 let getter = store.get().getter;
862 let wasi_store = Access::<T, WasiSockets>::new(store.as_context_mut(), getter);
863 <WasiSockets as HostTcpSocketWithStore<T>>::listen(wasi_store, socket).await
864 }
865
866 fn send(
867 mut store: Access<'_, T, Self>,
868 socket: Resource<p3_types::TcpSocket>,
869 data: wasmtime::component::StreamReader<u8>,
870 ) -> wasmtime::Result<wasmtime::component::FutureReader<Result<(), p3_ErrorCode>>> {
871 let getter = store.get().getter;
872 let wasi_store = Access::<T, WasiSockets>::new(store.as_context_mut(), getter);
873 <WasiSockets as HostTcpSocketWithStore<T>>::send(wasi_store, socket, data)
874 }
875
876 fn receive(
877 mut store: Access<'_, T, Self>,
878 socket: Resource<p3_types::TcpSocket>,
879 ) -> wasmtime::Result<(
880 wasmtime::component::StreamReader<u8>,
881 wasmtime::component::FutureReader<Result<(), p3_ErrorCode>>,
882 )> {
883 let getter = store.get().getter;
884 let wasi_store = Access::<T, WasiSockets>::new(store.as_context_mut(), getter);
885 <WasiSockets as HostTcpSocketWithStore<T>>::receive(wasi_store, socket)
886 }
887}
888
889impl<T: 'static> HostUdpSocketWithStore<T> for SpinSockets<T> {
890 async fn send(
891 store: &Accessor<T, Self>,
892 socket: Resource<p3_types::UdpSocket>,
893 data: Vec<u8>,
894 remote_address: Option<p3_IpSocketAddress>,
895 ) -> P3SocketResult<()> {
896 let getter = store.with(|mut store| store.get().getter);
897 let wasi_accessor = store.with_getter::<WasiSockets>(getter);
898 <WasiSockets as HostUdpSocketWithStore<T>>::send(
899 &wasi_accessor,
900 socket,
901 data,
902 remote_address,
903 )
904 .await
905 }
906
907 async fn receive(
908 store: &Accessor<T, Self>,
909 socket: Resource<p3_types::UdpSocket>,
910 ) -> P3SocketResult<(Vec<u8>, p3_IpSocketAddress)> {
911 let getter = store.with(|mut store| store.get().getter);
912 let wasi_accessor = store.with_getter::<WasiSockets>(getter);
913 <WasiSockets as HostUdpSocketWithStore<T>>::receive(&wasi_accessor, socket).await
914 }
915}