1#![cfg(unix)]
15
16#[cfg(target_os = "linux")]
17mod memfd;
18
19use crate::common::InvitationAddress;
20use crate::protocol;
21use futures::FutureExt;
22use futures::StreamExt;
23use futures::channel::mpsc;
24use futures::future;
25use futures::future::BoxFuture;
26use io::ErrorKind;
27use mesh_channel::OneshotReceiver;
28use mesh_channel::OneshotSender;
29use mesh_channel::RecvError;
30use mesh_channel::channel;
31use mesh_channel::oneshot;
32use mesh_node::common::Address;
33use mesh_node::common::NodeId;
34use mesh_node::common::PortId;
35use mesh_node::local_node::Connect;
36use mesh_node::local_node::LocalNode;
37use mesh_node::local_node::OutgoingEvent;
38use mesh_node::local_node::Port;
39use mesh_node::local_node::RemoteNodeHandle;
40use mesh_node::local_node::SendEvent;
41use mesh_node::resource::OsResource;
42use mesh_node::resource::Resource;
43use mesh_protobuf::Protobuf;
44use pal_async::driver::SpawnDriver;
45use pal_async::interest::InterestSlot;
46use pal_async::interest::PollEvents;
47use pal_async::socket::PolledSocket;
48use pal_async::task::Spawn;
49use pal_async::task::Task;
50use parking_lot::Mutex;
51use socket2::Socket;
52use std::collections::HashMap;
53use std::collections::VecDeque;
54use std::fmt::Debug;
55use std::future::Future;
56use std::future::poll_fn;
57use std::io;
58use std::io::IoSlice;
59use std::os::unix::prelude::*;
60use std::pin::pin;
61use std::sync::Arc;
62use thiserror::Error;
63use tracing::instrument;
64use unicycle::FuturesUnordered;
65use zerocopy::FromBytes;
66use zerocopy::FromZeros;
67use zerocopy::IntoBytes;
68
69const USE_SEQPACKET: bool = cfg!(target_os = "linux");
76
77const MAX_PACKET_SIZE: usize = if cfg!(target_os = "linux") {
83 0x4000
84} else {
85 0x40000
86};
87
88const MAX_SMALL_EVENT_SIZE: usize = MAX_PACKET_SIZE - size_of::<protocol::PacketHeader>();
89
90pub struct UnixNode {
100 driver: Arc<dyn SpawnDriver>,
101 local_node: Arc<LocalNode>,
102 to_leader: Arc<mesh_channel::Sender<LeaderRequest>>,
103 tasks: Arc<mesh_channel::Sender<SmallTask>>,
104 io_task: Task<()>,
105 leader_resign_send:
107 Mutex<Option<Arc<mesh_channel::Sender<(NodeId, mesh_channel::Sender<Followers>)>>>>,
108
109 _drop_send: OneshotSender<()>,
111}
112
113#[derive(Debug, Error)]
115#[error("mesh node shut down before invitation could be created")]
116pub struct InviteError;
117
118#[derive(Clone)]
127pub(crate) struct UnixMeshInviter {
128 to_leader: mesh_channel::Sender<LeaderRequest>,
129}
130
131impl UnixMeshInviter {
132 pub(crate) async fn invite(&self, port: Port) -> Result<Invitation, InviteError> {
137 let (invitation_send, mut invitation_recv) = channel();
138 self.to_leader
139 .send(LeaderRequest::Invite(port, invitation_send));
140 invitation_recv.recv().await.map_err(|_| InviteError)
141 }
142}
143
144#[derive(Debug, Protobuf)]
145#[mesh(resource = "Resource")]
146enum LeaderRequest {
147 Connect(NodeId),
148 Invite(Port, mesh_channel::Sender<Invitation>),
149}
150
151#[derive(Debug, Protobuf)]
152#[mesh(resource = "Resource")]
153enum FollowerRequest {
154 Connect(
155 NodeId,
156 #[mesh(
157 encoding = "mesh_protobuf::encoding::OptionField<mesh_protobuf::encoding::ResourceField<OwnedFd>>"
158 )]
159 Option<Socket>,
160 ),
161}
162
163#[derive(Debug, Protobuf)]
164#[mesh(resource = "Resource")]
165pub struct Followers {
166 list: Vec<(
167 NodeId,
168 mesh_channel::Receiver<LeaderRequest>,
169 mesh_channel::Sender<FollowerRequest>,
170 )>,
171}
172
173#[derive(Debug, Protobuf)]
174#[mesh(resource = "Resource")]
175struct InitialMessage {
176 leader_send: mesh_channel::Sender<LeaderRequest>,
177 follower_recv: mesh_channel::Receiver<FollowerRequest>,
178 user_port: Port,
179}
180
181#[instrument(skip_all, fields(local_id = ?local_node.id()))]
184async fn run_follower(
185 driver: &dyn SpawnDriver,
186 local_node: &Arc<LocalNode>,
187 mut recv: mesh_channel::Receiver<FollowerRequest>,
188 pending_connections: Arc<Mutex<HashMap<NodeId, RemoteNodeHandle>>>,
189 tasks: &mesh_channel::Sender<SmallTask>,
190) {
191 while let Ok(req) = recv.recv().await {
192 match req {
193 FollowerRequest::Connect(target_id, fd) => {
194 tracing::debug!(?target_id, "got connection request from leader");
195 let handle = pending_connections.lock().remove(&target_id);
196 let handle = handle.unwrap_or_else(|| local_node.get_remote_handle(target_id));
197
198 if let Some(fd) = fd {
199 start_connection(
200 tasks,
201 local_node,
202 target_id,
203 handle,
204 UnixSocket::new(driver, fd),
205 );
206 } else {
207 tracing::warn!(?target_id, "leader provided failed connection");
208 }
209 }
210 }
211 }
212}
213
214#[instrument(skip_all, fields(local_id = ?local_node.id()))]
218async fn run_leader(
219 driver: &dyn SpawnDriver,
220 local_node: &Arc<LocalNode>,
221 mut resign_recv: mesh_channel::Receiver<(NodeId, mesh_channel::Sender<Followers>)>,
222 followers: Followers,
223 tasks: &mesh_channel::Sender<SmallTask>,
224) {
225 let mut senders = HashMap::new();
226 let mut receivers = Vec::new();
227 for (remote_id, recv, send) in followers.list {
228 receivers.push((remote_id, recv));
229 senders.insert(remote_id, send);
230 }
231
232 let new_leader_info = loop {
233 if receivers.is_empty() {
234 return;
235 }
236 let recvs = receivers
237 .iter_mut()
238 .map(|(_, recv)| poll_fn(|cx| recv.poll_recv(cx)));
239 let (req, index, _) = futures::select! { r = resign_recv.next() => break r,
241 r = future::select_all(recvs).fuse() => r,
242 };
243 let remote_id = receivers[index].0;
244 match req {
245 Ok(req) => match req {
246 LeaderRequest::Connect(target_id) => {
247 tracing::debug!(?target_id, ?remote_id, "connection request");
248 let remote = senders
249 .get(&remote_id)
250 .expect("sender must exist to receive from it");
251 let mut fd = None;
252 if let Some(target) = senders.get(&target_id) {
253 match new_socket_pair() {
254 Ok((left, right)) => {
255 tracing::trace!(?target, "send to");
256 target.send(FollowerRequest::Connect(remote_id, Some(left)));
257 fd = Some(right);
258 }
259 Err(err) => {
260 tracing::warn!(
261 ?target_id,
262 ?remote_id,
263 error = &err as &dyn std::error::Error,
264 "failed to create socket pair for connection request"
265 );
266 }
267 }
268 } else {
269 tracing::warn!(?target_id, ?remote_id, "could not find target for remote");
270 }
271 remote.send(FollowerRequest::Connect(target_id, fd));
272 }
273 LeaderRequest::Invite(port, send) => {
274 tracing::debug!(?remote_id, "invitation request");
275 match new_socket_pair() {
276 Ok((left, right)) => {
277 let (leader_send, leader_recv) = channel();
278 let (follower_send, follower_recv) = channel();
279 let remote_addr = Address {
280 node: NodeId::new(),
281 port: PortId::new(),
282 };
283 let local_port_id = PortId::new();
284 let handle = local_node.add_remote(remote_addr.node);
285 start_connection(
286 tasks,
287 local_node,
288 remote_addr.node,
289 handle,
290 UnixSocket::new(driver, left),
291 );
292 let init_send = OneshotSender::<InitialMessage>::from(
293 local_node.add_port(local_port_id, remote_addr),
294 );
295 init_send.send(InitialMessage {
296 leader_send,
297 follower_recv,
298 user_port: port,
299 });
300 let invitation = Invitation {
301 address: InvitationAddress {
302 local_addr: remote_addr,
303 remote_addr: Address {
304 node: local_node.id(),
305 port: local_port_id,
306 },
307 },
308 fd: right.into(),
309 };
310 tracing::debug!(
311 invite_id = ?invitation.address.local_addr.node,
312 ?remote_id,
313 "inviting",
314 );
315 send.send(invitation);
316 senders.insert(remote_addr.node, follower_send);
317 receivers.push((remote_addr.node, leader_recv));
318 }
319 Err(err) => {
320 tracing::error!(
321 error = &err as &dyn std::error::Error,
322 "failed to create socket pair",
323 );
324 }
325 }
326 }
327 },
328 Err(err) => {
329 if let RecvError::Error(err) = err {
330 tracing::debug!(
331 ?remote_id,
332 error = &err as &dyn std::error::Error,
333 "leader connection to remote failed"
334 );
335 }
336 senders.remove(&remote_id);
337 receivers.swap_remove(index);
338 }
339 }
340 };
341
342 if let Some((new_leader_id, new_leader_followers_sink)) = new_leader_info {
343 if let Some(new_leader_send) = senders.get(&new_leader_id) {
344 tracing::debug!(?new_leader_id, "resigning leadership");
345 for (remote_id, send) in senders.iter() {
348 if new_leader_id != *remote_id {
349 match new_socket_pair() {
350 Ok((left, right)) => {
351 send.send(FollowerRequest::Connect(new_leader_id, Some(left)));
352 new_leader_send.send(FollowerRequest::Connect(*remote_id, Some(right)));
353 }
354 Err(err) => {
355 tracing::error!(
356 ?new_leader_id,
357 error = &err as &dyn std::error::Error,
358 "failed to connect node to new leader, mesh is leaderless",
359 );
360 return;
361 }
362 }
363 }
364 }
365
366 let mut followers = Vec::new();
368 for (remote_id, recv) in receivers {
369 let send = senders
370 .remove(&remote_id)
371 .expect("should be in sync with receivers");
372 followers.push((remote_id, recv, send));
373 }
374 new_leader_followers_sink.send(Followers { list: followers });
375 } else {
376 tracing::error!(?new_leader_id, "new leader is unknown, mesh is leaderless");
377 }
378 }
379}
380
381struct SmallTask {
384 name: &'static str,
385 future: BoxFuture<'static, ()>,
386}
387
388impl Debug for SmallTask {
389 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
390 f.pad("SmallTask")
391 }
392}
393
394impl SmallTask {
395 fn new(name: &'static str, f: impl 'static + Send + Future<Output = ()>) -> Self {
396 Self {
397 name,
398 future: Box::pin(f),
399 }
400 }
401}
402
403#[derive(Debug, Protobuf)]
407#[mesh(resource = "Resource")]
408pub struct Invitation {
409 pub address: InvitationAddress,
411 pub fd: OwnedFd,
413}
414
415#[derive(Debug)]
416enum SenderCommand {
417 Send {
418 packet: Vec<u8>,
419 fds: Vec<OsResource>,
420 },
421 ReleaseFds {
422 count: usize,
423 },
424}
425
426#[derive(Clone)]
427struct PacketSender {
428 send: mpsc::UnboundedSender<SenderCommand>,
429 socket: Arc<UnixSocket>,
430}
431
432impl SendEvent for PacketSender {
433 fn event(&self, event: OutgoingEvent<'_>) {
434 let (packet, fds) = match serialize_event(event) {
435 Ok(r) => r,
436 Err(err) => {
437 tracing::error!(
439 error = &err as &dyn std::error::Error,
440 "failed to serialize event"
441 );
442 return;
443 }
444 };
445
446 if !USE_SEQPACKET
458 || unix_socket::send_with_fds(
459 self.socket.socket.lock().get().as_fd(),
460 &[IoSlice::new(&packet)],
461 fds.iter().map(|OsResource::Fd(fd)| fd.as_fd()),
462 )
463 .is_err()
464 {
465 let _ = self
466 .send
467 .unbounded_send(SenderCommand::Send { packet, fds });
468 }
469 }
470}
471
472fn serialize_event(event: OutgoingEvent<'_>) -> io::Result<(Vec<u8>, Vec<OsResource>)> {
473 if event.len() > MAX_SMALL_EVENT_SIZE {
475 return serialize_large_event(event);
476 }
477
478 let cap = size_of::<protocol::PacketHeader>() + event.len();
480 let mut packet = Vec::with_capacity(cap);
481 packet.extend_from_slice(
482 protocol::PacketHeader {
483 packet_type: protocol::PacketType::EVENT,
484 reserved: [0; 7],
485 }
486 .as_bytes(),
487 );
488 let mut fds = Vec::new();
489 event.write_to(&mut packet, &mut fds);
490 assert_eq!(packet.len(), cap);
491 Ok((packet, fds))
492}
493
494#[cfg(target_os = "linux")]
495fn serialize_large_event(event: OutgoingEvent<'_>) -> io::Result<(Vec<u8>, Vec<OsResource>)> {
496 let packet = protocol::PacketHeader {
497 packet_type: protocol::PacketType::LARGE_EVENT,
498 ..FromZeros::new_zeroed()
499 }
500 .as_bytes()
501 .to_vec();
502
503 let mut fds = Vec::new();
504
505 let mut memfd = memfd::MemfdBuilder::new(event.len())?;
506 event.write_to(&mut io::Cursor::new(&mut *memfd), &mut fds);
507 fds.insert(0, OsResource::Fd(memfd.seal()?.into()));
508
509 Ok((packet, fds))
510}
511
512#[cfg(not(target_os = "linux"))]
513fn serialize_large_event(_event: OutgoingEvent<'_>) -> io::Result<(Vec<u8>, Vec<OsResource>)> {
514 Err(io::Error::new(
515 ErrorKind::Unsupported,
516 "event too large for this OS",
517 ))
518}
519
520impl Drop for PacketSender {
521 fn drop(&mut self) {
522 self.send.close_channel();
525 }
526}
527
528fn start_connection(
530 tasks: &mesh_channel::Sender<SmallTask>,
531 local_node: &Arc<LocalNode>,
532 remote_id: NodeId,
533 handle: RemoteNodeHandle,
534 socket: UnixSocket,
535) {
536 #[expect(clippy::disallowed_methods)] let (send, recv) = mpsc::unbounded();
538 let socket = Arc::new(socket);
539 let sender = PacketSender {
540 send: send.clone(),
541 socket: socket.clone(),
542 };
543 if handle.connect(sender) {
544 let task = SmallTask::new("run_connection", {
545 let local_node = local_node.clone();
546 run_connection(local_node, remote_id, send, recv, socket, handle)
547 });
548 tasks.send(task);
549 tracing::debug!(?remote_id, "connected");
550 } else {
551 tracing::debug!(?remote_id, "duplicate connection");
555 }
556}
557
558#[instrument(skip_all, fields(local_id = ?local_node.id(), remote_id = ?remote_id))]
560async fn run_connection(
561 local_node: Arc<LocalNode>,
562 remote_id: NodeId,
563 send_send: mpsc::UnboundedSender<SenderCommand>,
564 send_recv: mpsc::UnboundedReceiver<SenderCommand>,
565 socket: Arc<UnixSocket>,
566 handle: RemoteNodeHandle,
567) {
568 let mut retained_fds = VecDeque::new();
569 let mut recv = pin!(
570 async {
571 let r = run_receive(&local_node, &remote_id, &socket, &send_send).await;
572 match &r {
573 Ok(_) => {
574 tracing::debug!("incoming socket disconnected");
575 }
576 Err(err) => {
577 tracing::error!(error = err as &dyn std::error::Error, "error receiving");
578 }
579 }
580 r
581 }
582 .fuse()
583 );
584 let mut send = pin!(
585 async {
586 match run_send(send_recv, &socket, &mut retained_fds).await {
587 Ok(_) => {
588 tracing::debug!("sending is done");
589 }
590 Err(err) => {
591 tracing::error!(error = &err as &dyn std::error::Error, "failed send");
592 }
593 }
594 }
595 .fuse()
596 );
597 let r = futures::select! { r = recv => {
599 tracing::trace!("read complete, shutting down writes");
601 let _ = socket.close_write().await;
602 r
603 }
604 _ = send => {
605 match socket.close_write().await {
606 Ok(()) => {
607 tracing::trace!("shutdown writes, waiting for reads");
608 recv.await
609 }
610 Err(err) => {
611 tracing::error!(
612 error = &err as &dyn std::error::Error,
613 "failed to shutdown writes, aborting connection",
614 );
615 Err(ReceiveError::Io(err))
616 }
617 }
618 }
619 };
620 tracing::trace!("connection done");
621 match r {
622 Ok(()) => handle.disconnect(),
623 Err(err) => handle.fail(err),
624 }
625}
626
627#[derive(Debug, Error)]
628enum ReceiveError {
629 #[error("i/o error")]
630 Io(#[from] io::Error),
631 #[error("missing packet header")]
632 NoHeader,
633 #[error("release fds packet too small")]
634 BadReleaseFds,
635 #[error("unknown packet type {0:?}")]
636 UnknownPacketType(protocol::PacketType),
637 #[cfg(target_os = "linux")]
638 #[error("memfd file descriptor not sent for large event")]
639 MissingMemfd,
640 #[cfg(target_os = "linux")]
641 #[error("failed to map memfd")]
642 Memfd(#[source] io::Error),
643}
644
645async fn run_receive(
647 local_node: &LocalNode,
648 remote_id: &NodeId,
649 socket: &UnixSocket,
650 send: &mpsc::UnboundedSender<SenderCommand>,
651) -> Result<(), ReceiveError> {
652 let mut buf = vec![0; MAX_PACKET_SIZE];
653 let mut fds = Vec::new();
654 let mut receiver = unix_socket::ScmReceiver::new(protocol::MAX_FDS_PER_MESSAGE);
655 loop {
656 let len = socket.recv(&mut buf, &mut fds, &mut receiver).await?;
657 if len == 0 {
658 break;
659 }
660 if cfg!(target_os = "macos") && !fds.is_empty() {
661 let _ = send.unbounded_send(SenderCommand::Send {
663 packet: protocol::ReleaseFds {
664 header: protocol::PacketHeader {
665 packet_type: protocol::PacketType::RELEASE_FDS,
666 ..FromZeros::new_zeroed()
667 },
668 count: fds.len() as u64,
669 }
670 .as_bytes()
671 .to_vec(),
672 fds: Vec::new(),
673 });
674 }
675
676 let buf = &buf[..len];
677 let header = protocol::PacketHeader::read_from_prefix(buf)
678 .map_err(|_| ReceiveError::NoHeader)?
679 .0; match header.packet_type {
681 protocol::PacketType::EVENT => {
682 local_node.event(remote_id, &buf[size_of_val(&header)..], &mut fds);
683 fds.clear();
684 }
685 protocol::PacketType::RELEASE_FDS => {
686 let release_fds = protocol::ReleaseFds::read_from_prefix(buf)
687 .map_err(|_| ReceiveError::BadReleaseFds)?
688 .0; let _ = send.unbounded_send(SenderCommand::ReleaseFds {
690 count: release_fds.count as usize,
691 });
692 }
693 #[cfg(target_os = "linux")]
694 protocol::PacketType::LARGE_EVENT => {
695 if fds.is_empty() {
696 return Err(ReceiveError::MissingMemfd);
697 }
698 let OsResource::Fd(fd) = fds.remove(0);
699 let memfd = memfd::SealedMemfd::new(fd.into()).map_err(ReceiveError::Memfd)?;
700 local_node.event(remote_id, &memfd, &mut fds);
701 fds.clear();
702 }
703 ty => {
704 return Err(ReceiveError::UnknownPacketType(ty));
705 }
706 }
707 }
708 Ok(())
709}
710
711#[derive(Debug, Error)]
712enum ProtocolError {
713 #[error("request to release too many fds")]
714 ReleasingTooManyFds,
715}
716
717async fn run_send(
719 mut recv: mpsc::UnboundedReceiver<SenderCommand>,
720 socket: &UnixSocket,
721 retained_fds: &mut VecDeque<OsResource>,
722) -> io::Result<()> {
723 while let Some(command) = recv.next().await {
724 match command {
725 SenderCommand::Send { packet, fds } => {
726 match socket.send(&packet, &fds).await {
727 Ok(_) => (),
728 Err(err) => {
729 tracing::error!(
730 fd_count = fds.len(),
731 packet_len = packet.len(),
732 "failed to send packet"
733 );
734 return Err(err);
735 }
736 }
737 if cfg!(target_os = "macos") {
738 if !fds.is_empty() {
744 retained_fds.extend(fds);
745 }
746 }
747 }
748 SenderCommand::ReleaseFds { count } => {
749 if retained_fds.len() < count {
750 return Err(io::Error::other(ProtocolError::ReleasingTooManyFds));
751 }
752 retained_fds.drain(..count);
753 }
754 }
755 }
756 Ok(())
757}
758
759#[derive(Debug, Protobuf)]
762#[mesh(resource = "Resource")]
763pub struct LeadershipOffer {
764 send: mesh_channel::Sender<(NodeId, mesh_channel::Sender<Followers>)>,
765}
766
767impl UnixNode {
768 pub fn new(driver: impl SpawnDriver) -> Self {
770 let (to_leader_send, to_leader_recv) = channel();
771 let (from_leader_send, from_leader_recv) = channel();
772 let this = Self::with_id(
773 Arc::new(driver),
774 NodeId::new(),
775 to_leader_send,
776 from_leader_recv,
777 );
778
779 let (resign_send, resign_recv) = channel();
781 let resign_send = Arc::new(resign_send);
782 let followers = Followers {
783 list: vec![(this.local_node.id(), to_leader_recv, from_leader_send)],
784 };
785 let task = SmallTask::new("run_leader", {
786 let local_node = this.local_node.clone();
787 let tasks = this.tasks.clone();
788 let driver = this.driver.clone();
789 async move { run_leader(driver.as_ref(), &local_node, resign_recv, followers, &tasks).await }
790 });
791 this.tasks.send(task);
792 *this.leader_resign_send.lock() = Some(resign_send);
793
794 this
795 }
796
797 pub fn id(&self) -> NodeId {
799 self.local_node.id()
800 }
801
802 fn with_id(
805 driver: Arc<dyn SpawnDriver>,
806 id: NodeId,
807 to_leader: mesh_channel::Sender<LeaderRequest>,
808 from_leader: mesh_channel::Receiver<FollowerRequest>,
809 ) -> Self {
810 let to_leader = Arc::new(to_leader);
811 let pending_connections: Arc<Mutex<HashMap<NodeId, RemoteNodeHandle>>> = Default::default();
812 let local_node = Arc::new(LocalNode::with_id(
813 id,
814 Box::new(Connector {
815 local_id: id,
816 conn_req_send: to_leader.clone(),
817 pending_connections: pending_connections.clone(),
818 }),
819 ));
820 let (task_send, mut task_recv) = channel::<SmallTask>();
821 let task_send = Arc::new(task_send);
822 let (drop_send, drop_recv) = oneshot();
823
824 let io_task = driver.spawn("unix-mesh-io", async move {
826 let process = async {
827 let mut futs = FuturesUnordered::new();
828 loop {
829 futures::select! { _ = futs.next() => {},
831 task = task_recv.select_next_some() => {
832 futs.push(async move {
833 tracing::trace!(?id, name = task.name, "task start");
834 task.future.await;
835 tracing::trace!(?id, name = task.name, "task end");
836 });
837 },
838 complete => break,
839 };
840 }
841 };
842 future::select(pin!(process), drop_recv).await;
843 });
844
845 task_send.send(SmallTask::new("run_follower", {
846 let local_node = local_node.clone();
847 let tasks = task_send.clone();
848 let driver = driver.clone();
849 async move {
850 run_follower(
851 driver.as_ref(),
852 &local_node,
853 from_leader,
854 pending_connections,
855 &tasks,
856 )
857 .await
858 }
859 }));
860
861 Self {
862 driver,
863 local_node,
864 tasks: task_send,
865 io_task,
866 to_leader,
867 leader_resign_send: Mutex::new(None),
868
869 _drop_send: drop_send,
870 }
871 }
872
873 pub fn offer_leadership(&self) -> LeadershipOffer {
878 let (send, mut recv) = channel();
879 if let Some(leader_send) = self.leader_resign_send.lock().clone() {
880 let task = SmallTask::new("offer_leadership", async move {
883 if let Ok(r) = recv.recv().await {
884 leader_send.send(r);
885 }
886 });
887 self.tasks.send(task);
888 }
889 LeadershipOffer { send }
890 }
891
892 pub fn accept_leadership(&self, offer: LeadershipOffer) {
894 let (send, mut recv) = channel();
895 offer.send.send((self.local_node.id(), send));
896
897 let (resign_send, resign_recv) = channel();
898 let resign_send = Arc::new(resign_send);
899 let task = SmallTask::new("accept_and_run_leader", {
900 let local_node = self.local_node.clone();
901 let tasks = self.tasks.clone();
902 let driver = self.driver.clone();
903 async move {
904 if let Ok(followers) = recv.recv().await {
905 drop(recv);
906 run_leader(driver.as_ref(), &local_node, resign_recv, followers, &tasks).await
907 }
908 }
909 });
910 self.tasks.send(task);
911 *self.leader_resign_send.lock() = Some(resign_send);
912 }
913
914 #[instrument(skip_all, fields(local_id = ?self.local_node.id()))]
917 pub async fn invite(&self, port: Port) -> Result<Invitation, InviteError> {
918 let (invitation_send, mut invitation_recv) = channel();
919 self.to_leader
920 .send(LeaderRequest::Invite(port, invitation_send));
921 let invitation = invitation_recv.recv().await.map_err(|_| InviteError)?;
922 tracing::debug!(
923 invite_id = ?invitation.address.local_addr.node,
924 "received invitation",
925 );
926 Ok(invitation)
927 }
928
929 pub(crate) fn inviter(&self) -> UnixMeshInviter {
934 UnixMeshInviter {
935 to_leader: (*self.to_leader).clone(),
936 }
937 }
938
939 pub async fn join(
942 driver: impl SpawnDriver,
943 invitation: Invitation,
944 port: Port,
945 ) -> Result<Self, JoinError> {
946 Self::join_generic(Arc::new(driver), invitation, port).await
947 }
948
949 #[instrument(skip_all, fields(local_id = ?invitation.address.local_addr.node, remote_id = ?invitation.address.remote_addr.node))]
950 async fn join_generic(
951 driver: Arc<dyn SpawnDriver>,
952 invitation: Invitation,
953 port: Port,
954 ) -> Result<Self, JoinError> {
955 let (to_leader_send, to_leader_recv) = channel();
956 let (from_leader_send, from_leader_recv) = channel();
957 let this = Self::with_id(
958 driver,
959 invitation.address.local_addr.node,
960 to_leader_send,
961 from_leader_recv,
962 );
963
964 let handle = this
965 .local_node
966 .add_remote(invitation.address.remote_addr.node);
967 let init_recv = OneshotReceiver::<InitialMessage>::from(this.local_node.add_port(
968 invitation.address.local_addr.port,
969 invitation.address.remote_addr,
970 ));
971
972 start_connection(
973 &this.tasks,
974 &this.local_node,
975 invitation.address.remote_addr.node,
976 handle,
977 UnixSocket::new(this.driver.as_ref(), invitation.fd.into()),
978 );
979
980 let init_message = init_recv.await.map_err(JoinError)?;
981 to_leader_recv.bridge(init_message.leader_send);
982 from_leader_send.bridge(init_message.follower_recv);
983 port.bridge(init_message.user_port);
984
985 Ok(this)
986 }
987
988 pub async fn shutdown(mut self) {
997 self.local_node.wait_for_ports(false).await;
999 drop(self.to_leader);
1001 self.local_node.drop_connector();
1002 self.leader_resign_send.get_mut().take();
1004 self.local_node.fail_all_nodes();
1006 drop(self.tasks);
1008 self.io_task.await;
1010 }
1011}
1012
1013#[derive(Debug, Error)]
1015#[error("failed to accept invitation")]
1016pub struct JoinError(#[source] RecvError);
1017
1018#[derive(Debug)]
1022struct Connector {
1023 local_id: NodeId,
1024 conn_req_send: Arc<mesh_channel::Sender<LeaderRequest>>,
1025 pending_connections: Arc<Mutex<HashMap<NodeId, RemoteNodeHandle>>>,
1026}
1027
1028impl Connect for Connector {
1029 fn connect(&self, node_id: NodeId, handle: RemoteNodeHandle) {
1030 tracing::trace!(local_id = ?self.local_id, remote_id = ?node_id, "connecting");
1031 let old_request = self.pending_connections.lock().insert(node_id, handle);
1032 if old_request.is_some() {
1033 panic!("duplicate connection request for {:?}", node_id);
1034 }
1035 self.conn_req_send.send(LeaderRequest::Connect(node_id))
1036 }
1037}
1038
1039fn new_socket_pair() -> Result<(Socket, Socket), io::Error> {
1041 let ty = if USE_SEQPACKET {
1042 socket2::Type::SEQPACKET
1043 } else {
1044 socket2::Type::STREAM
1045 };
1046 Socket::pair(socket2::Domain::UNIX, ty, None)
1047}
1048
1049struct UnixSocket {
1051 socket: Mutex<PolledSocket<Socket>>,
1052}
1053
1054impl UnixSocket {
1055 fn new(driver: &dyn SpawnDriver, fd: Socket) -> Self {
1056 let socket = PolledSocket::new(driver, fd).unwrap();
1057 UnixSocket {
1058 socket: Mutex::new(socket),
1059 }
1060 }
1061
1062 async fn send(&self, msg: &[u8], fds: &[OsResource]) -> io::Result<()> {
1063 if USE_SEQPACKET {
1064 self.send_raw(&mut [IoSlice::new(msg)], fds).await?;
1065 } else {
1066 let len = (msg.len() as u32).to_le_bytes();
1067 let mut iov = [IoSlice::new(&len), IoSlice::new(msg)];
1068 self.send_all_raw(&mut iov, fds).await?;
1069 }
1070 Ok(())
1071 }
1072
1073 async fn send_raw(
1074 &self,
1075 iov: &mut [IoSlice<'_>],
1076 fds: &[OsResource],
1077 ) -> Result<usize, io::Error> {
1078 if fds.len() > protocol::MAX_FDS_PER_MESSAGE {
1083 return Err(io::Error::new(
1084 ErrorKind::InvalidInput,
1085 format!(
1086 "too many file descriptors ({}, max {})",
1087 fds.len(),
1088 protocol::MAX_FDS_PER_MESSAGE
1089 ),
1090 ));
1091 }
1092 let n = poll_fn(|cx| {
1093 self.socket
1094 .lock()
1095 .poll_io(cx, InterestSlot::Write, PollEvents::OUT, |socket| {
1096 unix_socket::send_with_fds(
1097 socket.get().as_fd(),
1098 iov,
1099 fds.iter().map(|OsResource::Fd(fd)| fd.as_fd()),
1100 )
1101 })
1102 })
1103 .await?;
1104 Ok(n)
1105 }
1106
1107 async fn send_all_raw(
1108 &self,
1109 mut iov: &mut [IoSlice<'_>],
1110 mut fds: &[OsResource],
1111 ) -> Result<(), io::Error> {
1112 while !iov.is_empty() || !fds.is_empty() {
1113 let n = self.send_raw(iov, fds).await?;
1114 IoSlice::advance_slices(&mut iov, n);
1115 fds = &[];
1116 }
1117 Ok(())
1118 }
1119
1120 async fn recv(
1121 &self,
1122 buf: &mut [u8],
1123 fds: &mut Vec<OsResource>,
1124 receiver: &mut unix_socket::ScmReceiver,
1125 ) -> io::Result<usize> {
1126 if USE_SEQPACKET {
1127 self.recv_raw(buf, fds, receiver).await
1128 } else {
1129 let mut len = [0; 4];
1130 if !self.recv_all_raw(&mut len, fds, receiver).await? {
1131 return Ok(0);
1132 }
1133 let len = u32::from_le_bytes(len) as usize;
1134 let buf = buf
1135 .get_mut(..len)
1136 .ok_or_else(|| io::Error::from_raw_os_error(libc::EMSGSIZE))?;
1137 if !self.recv_all_raw(buf, fds, receiver).await? {
1138 return Err(ErrorKind::UnexpectedEof.into());
1139 }
1140 Ok(len)
1141 }
1142 }
1143
1144 async fn recv_all_raw(
1145 &self,
1146 buf: &mut [u8],
1147 fds: &mut Vec<OsResource>,
1148 receiver: &mut unix_socket::ScmReceiver,
1149 ) -> Result<bool, io::Error> {
1150 let mut read = 0;
1151 while read < buf.len() {
1152 let n = self.recv_raw(&mut buf[read..], fds, receiver).await?;
1153 if n == 0 {
1154 if read != 0 {
1155 return Err(ErrorKind::UnexpectedEof.into());
1156 } else {
1157 return Ok(false);
1158 }
1159 }
1160 read += n;
1161 }
1162 Ok(true)
1163 }
1164
1165 async fn recv_raw(
1166 &self,
1167 buf: &mut [u8],
1168 fds: &mut Vec<OsResource>,
1169 receiver: &mut unix_socket::ScmReceiver,
1170 ) -> Result<usize, io::Error> {
1171 let n = poll_fn(|cx| {
1172 self.socket
1173 .lock()
1174 .poll_io(cx, InterestSlot::Read, PollEvents::IN, |socket| {
1175 receiver.recv(socket.get().as_fd(), buf)
1176 })
1177 })
1178 .await?;
1179 fds.extend(receiver.drain().map(OsResource::Fd));
1180 Ok(n)
1181 }
1182
1183 async fn close_write(&self) -> io::Result<()> {
1184 self.socket.lock().get().shutdown(std::net::Shutdown::Write)
1185 }
1186}
1187
1188#[cfg(test)]
1189mod tests {
1190 use crate::unix::UnixNode;
1191 use mesh_channel::RecvError;
1192 use mesh_channel::channel;
1193 use pal_async::DefaultDriver;
1194 use pal_async::async_test;
1195 use test_with_tracing::test;
1196
1197 #[async_test]
1198 async fn test_basic(driver: DefaultDriver) {
1199 let leader = UnixNode::new(driver.clone());
1200 let (send, recv) = channel::<u32>();
1201 let invitation = leader.invite(recv.into()).await.unwrap();
1202 let (send2, mut recv2) = channel::<u32>();
1203 let follower = UnixNode::join(driver, invitation, send2.into())
1204 .await
1205 .unwrap();
1206 send.send(5);
1207 assert_eq!(recv2.recv().await.unwrap(), 5);
1208 drop(send);
1209 drop(recv2);
1210 follower.shutdown().await;
1211 leader.shutdown().await;
1212 }
1213
1214 #[cfg(target_os = "linux")]
1215 #[async_test]
1216 async fn test_huge_message(driver: DefaultDriver) {
1217 let leader = UnixNode::new(driver.clone());
1218 let (send, recv) = channel::<Vec<u8>>();
1219 let invitation = leader.invite(recv.into()).await.unwrap();
1220 let (send2, mut recv2) = channel::<Vec<u8>>();
1221 let follower = UnixNode::join(driver, invitation, send2.into())
1222 .await
1223 .unwrap();
1224
1225 let v = vec![0xcc; 16 << 20];
1226 send.send(v.clone());
1227 let v2 = recv2.recv().await.unwrap();
1228 assert_eq!(v, v2);
1229 follower.shutdown().await;
1230 leader.shutdown().await;
1231 }
1232
1233 #[cfg(target_os = "linux")]
1234 #[async_test]
1235 async fn test_message_sizes(driver: DefaultDriver) {
1236 let (p1, p2) = mesh_node::local_node::Port::new_pair();
1237 let (p3, p4) = mesh_node::local_node::Port::new_pair();
1238 let node1 = UnixNode::new(driver.clone());
1239 let invitation = node1.invite(p2).await.unwrap();
1240 let _node2 = UnixNode::join(driver.clone(), invitation, p3)
1241 .await
1242 .unwrap();
1243
1244 crate::test_common::test_message_sizes(p1, p4, 0..=super::MAX_SMALL_EVENT_SIZE + 0x1000)
1245 .await;
1246 }
1247
1248 #[async_test]
1249 async fn test_dropped_shutdown(driver: DefaultDriver) {
1250 let leader = UnixNode::new(driver.clone());
1251 {
1252 let (_send, recv) = channel::<u32>();
1253 let invitation = leader.invite(recv.into()).await.unwrap();
1254 let (send2, _recv2) = channel::<u32>();
1255 let _follower = UnixNode::join(driver, invitation, send2.into())
1256 .await
1257 .unwrap();
1258 }
1259 leader.shutdown().await;
1260 }
1261
1262 #[async_test]
1263 async fn test_send_shutdown(driver: DefaultDriver) {
1264 let leader = UnixNode::new(driver.clone());
1265 let (send, mut recv) = channel::<u32>();
1266 let invitation = leader.invite(send.into()).await.unwrap();
1267 let (send2, recv2) = channel::<u32>();
1268 let follower = UnixNode::join(driver, invitation, recv2.into())
1269 .await
1270 .unwrap();
1271 send2.send(5);
1272 drop(send2);
1273 follower.shutdown().await;
1274 assert_eq!(recv.recv().await.unwrap(), 5);
1275 }
1276
1277 #[async_test]
1278 async fn test_failed_invitation(driver: DefaultDriver) {
1279 let leader = UnixNode::new(driver);
1280 let (send, mut recv) = channel::<()>();
1281 leader.invite(send.into()).await.unwrap();
1282 assert!(matches!(
1283 recv.recv().await.unwrap_err(),
1284 RecvError::Error(_)
1285 ));
1286 drop(recv);
1287 leader.shutdown().await;
1288 }
1289
1290 #[async_test]
1291 async fn test_three(driver: DefaultDriver) {
1292 let (p1, p2) = channel::<u32>();
1293 let (p3, mut p4) = channel::<u32>();
1294 let (p5, p6) = channel::<u32>();
1295 let (p7, p8) = channel::<u32>();
1296
1297 let node1 = UnixNode::new(driver.clone());
1298
1299 let invitation = node1.invite(p2.into()).await.unwrap();
1300 let node2 = UnixNode::join(driver.clone(), invitation, p3.into())
1301 .await
1302 .unwrap();
1303
1304 let invitation = node1.invite(p5.into()).await.unwrap();
1305 let node3 = UnixNode::join(driver, invitation, p8.into()).await.unwrap();
1306
1307 p1.bridge(p6);
1308
1309 p7.send(5);
1310
1311 assert_eq!(p4.recv().await.unwrap(), 5);
1312 drop(p4);
1313 drop(p7);
1314 futures::join!(node2.shutdown(), node3.shutdown());
1315 node1.shutdown().await;
1316 }
1317
1318 #[async_test]
1319 async fn test_handoff_leader(driver: DefaultDriver) {
1320 let (p1, p2) = channel::<u32>();
1321 let (p3, p4) = channel::<u32>();
1322 let (p5, p6) = channel::<u32>();
1323 let (p7, p8) = channel::<u32>();
1324 let (p9, p10) = channel();
1325 let (p11, mut p12) = channel();
1326
1327 let node1 = UnixNode::new(driver.clone());
1328
1329 let invitation = node1.invite(p2.into()).await.unwrap();
1330 let node2 = UnixNode::join(driver.clone(), invitation, p3.into())
1331 .await
1332 .unwrap();
1333
1334 let invitation = node1.invite(p5.into()).await.unwrap();
1335 let node3 = UnixNode::join(driver.clone(), invitation, p8.into())
1336 .await
1337 .unwrap();
1338
1339 let invitation = node1.invite(p10.into()).await.unwrap();
1340 let node4 = UnixNode::join(driver, invitation, p11.into())
1341 .await
1342 .unwrap();
1343
1344 p9.send(node1.offer_leadership());
1345 node4.accept_leadership(p12.recv().await.unwrap());
1346 drop(p9);
1347 drop(p12);
1348 p1.bridge(p6);
1349
1350 std::thread::sleep(std::time::Duration::from_millis(200));
1351
1352 node1.shutdown().await;
1353 drop(p4);
1354 drop(p7);
1355 node2.shutdown().await;
1356 node3.shutdown().await;
1357
1358 std::thread::sleep(std::time::Duration::from_millis(200));
1359
1360 node4.shutdown().await;
1361 }
1362}