bd595851e2
251 files: init, acpid, ipcd, netcfg, ihdgd, virtio-gpud, scheme-utils, inputd, block driver, ptyd, ramfs, randd, initfs bootstrap, path deps, version +rb0.3.1, author attribution
73 lines
2.0 KiB
Rust
73 lines
2.0 KiB
Rust
use std::collections::btree_map::{BTreeMap, Entry};
|
|
|
|
pub struct PortSet {
|
|
from: u16,
|
|
range: u16,
|
|
next: u16,
|
|
ports: BTreeMap<u16, usize>,
|
|
}
|
|
|
|
impl PortSet {
|
|
pub fn new(from: u16, to: u16) -> Option<PortSet> {
|
|
if from > to {
|
|
return None;
|
|
}
|
|
Some(PortSet {
|
|
from,
|
|
range: to - from + 1,
|
|
next: 0,
|
|
ports: BTreeMap::new(),
|
|
})
|
|
}
|
|
|
|
pub fn get_port(&mut self) -> Option<u16> {
|
|
if self.ports.len() >= self.range as usize {
|
|
return None;
|
|
}
|
|
|
|
let port = loop {
|
|
if let Entry::Vacant(entry) = self.ports.entry(self.next) {
|
|
entry.insert(1);
|
|
let port = self.from + self.next;
|
|
self.next = self.next.wrapping_add(1);
|
|
break port;
|
|
}
|
|
self.next = self.next.wrapping_add(1);
|
|
};
|
|
|
|
Some(port)
|
|
}
|
|
|
|
pub fn claim_port(&mut self, port: u16) -> bool {
|
|
if let Entry::Vacant(entry) = self.ports.entry(port) {
|
|
entry.insert(1);
|
|
true
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
|
|
/// Increment the reference count for an already-claimed port (SO_REUSEADDR).
|
|
/// Always succeeds: the caller has indicated SO_REUSEADDR is set, so
|
|
/// multiple sockets are allowed to bind to the same port. The actual
|
|
/// collision check (returning EADDRINUSE) is done by `claim_port` first.
|
|
/// Returns true on success.
|
|
pub fn claim_port_reuse(&mut self, port: u16) -> bool {
|
|
self.ports.entry(port).and_modify(|c| *c += 1).or_insert(1);
|
|
true
|
|
}
|
|
|
|
pub fn acquire_port(&mut self, port: u16) {
|
|
*self.ports.entry(port).or_insert(0) += 1;
|
|
}
|
|
|
|
pub fn release_port(&mut self, port: u16) {
|
|
if let Entry::Occupied(mut entry) = self.ports.entry(port) {
|
|
*entry.get_mut() -= 1;
|
|
if *entry.get() == 0 {
|
|
entry.remove();
|
|
}
|
|
}
|
|
}
|
|
}
|