-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathunix_sockets.rs
137 lines (122 loc) · 4.52 KB
/
unix_sockets.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use std::{
os::unix::io::AsRawFd,
os::unix::io::RawFd,
os::unix::net::{UnixDatagram, UnixListener},
};
use log::trace;
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum UnixSocketConfig {
Stream(String),
Sequential(String),
Datagram(String),
}
#[derive(Debug)]
struct UnixSeqPacket(Option<i32>, std::path::PathBuf);
impl AsRawFd for UnixSeqPacket {
fn as_raw_fd(&self) -> i32 {
self.0.unwrap()
}
}
impl Drop for UnixSeqPacket {
fn drop(&mut self) {
if self.1.exists() {
self.close();
std::fs::remove_file(&self.1).unwrap();
}
}
}
impl UnixSeqPacket {
fn close(&mut self) {
if let Some(fd) = self.0 {
super::close_raw_fd(fd);
}
self.0 = None;
}
}
impl UnixSocketConfig {
pub fn close(&self, rawfd: RawFd) -> Result<(), String> {
let strpath = match self {
UnixSocketConfig::Stream(s) => s,
UnixSocketConfig::Datagram(s) => s,
UnixSocketConfig::Sequential(s) => s,
};
let path = std::path::PathBuf::from(strpath);
if path.exists() {
std::fs::remove_file(&path)
.map_err(|e| format!("Error removing file {:?}: {}", path, e))?;
}
super::close_raw_fd(rawfd);
Ok(())
}
pub fn open(&self) -> Result<Box<dyn AsRawFd + Send + Sync>, String> {
match self {
UnixSocketConfig::Stream(path) => {
let spath = std::path::Path::new(&path);
// Delete old socket if necessary
if spath.exists() {
std::fs::remove_file(&spath).unwrap();
}
if let Some(parent) = spath.parent() {
if !parent.exists() {
std::fs::create_dir_all(parent).map_err(|e| {
format!("Error creating UnixSocket directory {:?} : {}", parent, e)
})?;
}
}
trace!("opening streaming unix socket: {:?}", path);
// Bind to socket
let stream = match UnixListener::bind(&spath) {
Err(e) => panic!("failed to bind socket: {}", e),
Ok(stream) => stream,
};
//need to stop the listener to drop which would close the filedescriptor
Ok(Box::new(stream))
}
UnixSocketConfig::Datagram(path) => {
let spath = std::path::Path::new(&path);
// Delete old socket if necessary
if spath.exists() {
std::fs::remove_file(&spath).unwrap();
}
if let Some(parent) = spath.parent() {
if !parent.exists() {
std::fs::create_dir_all(parent).map_err(|e| {
format!("Error creating UnixSocket directory {:?} : {}", parent, e)
})?;
}
}
trace!("opening datagram unix socket: {:?}", path);
// Bind to socket
let stream = match UnixDatagram::bind(&spath) {
Err(e) => panic!("failed to bind socket: {}", e),
Ok(stream) => stream,
};
//need to stop the listener to drop which would close the filedescriptor
Ok(Box::new(stream))
}
UnixSocketConfig::Sequential(path) => {
let spath = std::path::Path::new(&path);
// Delete old socket if necessary
if spath.exists() {
std::fs::remove_file(&spath).unwrap();
}
if let Some(parent) = spath.parent() {
if !parent.exists() {
std::fs::create_dir_all(parent).map_err(|e| {
format!("Error creating UnixSocket directory {:?} : {}", parent, e)
})?;
}
}
let path = std::path::PathBuf::from(&path);
trace!("opening datagram unix socket: {:?}", path);
match crate::platform::make_seqpacket_socket(&path) {
Ok(fd) => {
// return our own type until the std supports sequential packet unix sockets
Ok(Box::new(UnixSeqPacket(Some(fd), path.clone())))
}
Err(e) => Err(e),
}
}
}
}
}