Skip to content

Commit

Permalink
The server can now accept connections using the new switch board.
Browse files Browse the repository at this point in the history
  • Loading branch information
misalcedo authored Dec 19, 2023
1 parent d98ee70 commit e5ae92f
Showing 1 changed file with 20 additions and 106 deletions.
126 changes: 20 additions & 106 deletions src/server.rs
Original file line number Diff line number Diff line change
@@ -1,109 +1,30 @@
use std::collections::LinkedList;
use std::io;
use std::net::SocketAddr;
use std::num::NonZeroUsize;
use std::ops::{Index, IndexMut};

use mio::net::{TcpListener, TcpStream};
use mio::{Events, Interest, Poll, Token};

const LISTENER: Token = Token(0);

enum Socket {
Request(Vec<u8>, TcpStream),
Response(usize, TcpStream),
}
use crate::board::SwitchBoard;

impl From<TcpStream> for Socket {
fn from(value: TcpStream) -> Self {
Self::Request(Vec::with_capacity(1024 * 16), value)
}
}
const LISTENER: Token = Token(0);

// A naturally indexed (starting at 1) slab of client sockets.
struct SwitchBoard {
slots: Vec<Option<Socket>>,
available: LinkedList<usize>,
struct Client {
stream: TcpStream,
buffer: Vec<u8>
}

impl Default for SwitchBoard {
fn default() -> Self {
SwitchBoard {
slots: Vec::new(),
available: LinkedList::new(),
}
}
}

impl SwitchBoard {
pub fn with_capacity(capacity: usize) -> Self {
impl From<TcpStream> for Client {
fn from(stream: TcpStream) -> Self {
Self {
slots: Vec::with_capacity(capacity),
available: LinkedList::new(),
}
}

pub fn set(&mut self, slot: NonZeroUsize, client: TcpStream) {
if let Some(s) = self.slots.get_mut(slot.get() - 1) {
*s = Some(Socket::Request(Vec::with_capacity(1024 * 16), client));
stream,
buffer: Vec::with_capacity(1024 * 16)
}
}

pub fn remove(&mut self, slot: usize) -> Option<bool> {
let length = self.slots.len();

if slot > length {
None
} else if slot == length {
Some(self.slots.pop().is_some())
} else {
let index = slot.checked_sub(1)?;

self.available.push_back(index);

Some(self.slots[index].take().is_some())
}
}

pub fn claim_slot(&mut self) -> NonZeroUsize {
self.available
.pop_front()
.and_then(NonZeroUsize::new)
.unwrap_or_else(|| {
let index = self.slots.len();

self.slots.reserve(1);
self.slots.push(None);

NonZeroUsize::new(index + 1).unwrap_or(NonZeroUsize::MIN)
})
}
}

impl Index<usize> for SwitchBoard {
type Output = Socket;

fn index(&self, index: usize) -> &Self::Output {
self.slots
.index(index)
.as_ref()
.expect("Indexed an empty slot.")
}
}

impl IndexMut<usize> for SwitchBoard {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.slots
.index_mut(index)
.as_mut()
.expect("Indexed an empty slot.")
}
}

pub struct Server {
listener: TcpListener,
poll: Poll,
switch_board: SwitchBoard,
switch_board: SwitchBoard<Client>,
events: Events,
}

Expand Down Expand Up @@ -131,23 +52,16 @@ impl Server {

for event in &self.events {
match event.token() {
LISTENER => loop {
match self.listener.accept() {
Ok((mut client, _)) => {
let slot = self.switch_board.claim_slot();

self.poll.registry().register(
&mut client,
Token(slot.get()),
Interest::READABLE,
)?;
self.switch_board.set(slot, client);
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
break;
}
Err(e) => {
return Err(e);
LISTENER => {
loop {
match self.listener.accept() {
Ok((mut client, _)) => {
let slot = self.switch_board.reserve();
self.poll.registry().register(&mut client, Token(slot.get()), Interest::READABLE)?;
self.switch_board[slot] = Some(Client::from(client));
}
Err(e) if e.kind() == io::ErrorKind::WouldBlock => { break; }
Err(e) => { return Err(e); }
}
}
},
Expand Down

0 comments on commit e5ae92f

Please sign in to comment.