Skip to content
Open
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4484398
Replace deprecated std::mem::uninitialized with std::mem::MaybeUninit
htrefil Jan 8, 2020
13e25f7
Remove dependency on byteorder, use functions from std for converting…
htrefil Jan 8, 2020
7f20c12
Implement From<SocketAddrV4> for Address
htrefil Jan 8, 2020
8751315
Make lazy_static a dev-dependency
htrefil Jan 8, 2020
855596d
Merge branch 'master' of github.com:futile/enet-rs
htrefil Jan 8, 2020
863054b
Make peers "unsized"
htrefil Jan 8, 2020
d9d9e36
Fix warnings
htrefil Jan 8, 2020
d87eaac
Add missing docs
htrefil Jan 8, 2020
cd8b9c8
Remove unnecessary lifetimes ('_)
htrefil Jan 8, 2020
a708198
Drop data on disconnected peers
htrefil Jan 8, 2020
bb88b65
Drop all peer data on Drop of Host structure
htrefil Jan 8, 2020
bcae5cf
Add missing docs
htrefil Jan 8, 2020
5f6dcf8
Implement Index, IndexMut for Host
htrefil Jan 8, 2020
09c2811
Add missing Debug implementations
htrefil Jan 8, 2020
e330de1
Update client example
htrefil Jan 8, 2020
f20b568
Make Host::service take std::time::Duration instead of u32
htrefil Jan 8, 2020
8e24687
Update server example
htrefil Jan 8, 2020
7d561be
Update both examples (again)
htrefil Jan 8, 2020
4e4b19b
Improve docs about peer data lifetime
htrefil Jan 8, 2020
dc531b3
Drop peer data on Peer::disconnect_now
htrefil Jan 8, 2020
82c8168
Rename user_data to data for consistency
htrefil Jan 8, 2020
62e346a
Make Packet::new take a Vec<u8>
htrefil Jan 8, 2020
d49a232
Fix index calculation
htrefil Jan 9, 2020
e21bd2c
Replace user_data with data again
htrefil Jan 9, 2020
ef071c8
Update docs
htrefil Jan 9, 2020
577d7bd
Make Address::from_hostname take a &CStr, rather than &CString
htrefil Jan 9, 2020
e9324cf
Gurantee that the data field of ENetPacket will always be a pointer t…
htrefil Jan 9, 2020
3080364
Change Packet::new to use Box<[u8]> instead of Vec
LeonMatthes Jul 26, 2020
4b25ddc
Create PeerID struct to increase type safety.
LeonMatthes Jul 26, 2020
4efa37f
Use PeerID in Event
LeonMatthes Jul 26, 2020
d21b063
Readd Peer::receive()
LeonMatthes Jul 26, 2020
01fe79d
Use PeerID for host.drop_disconnected
LeonMatthes Jul 27, 2020
da58586
Refactor drop_disconnected to use peer_mut()
LeonMatthes Jul 27, 2020
f77df67
Use Vec<u8> again for Packet construction
LeonMatthes Jul 29, 2020
5aad870
Merge branch 'master' of https://github.com/futile/enet-rs
LeonMatthes Apr 7, 2022
e765e0f
Remove Index and IndexMut from Host
LeonMatthes Apr 7, 2022
b448b18
Make PeerID generational
LeonMatthes Apr 7, 2022
62eb1d8
Incorporate feedback from @futile
LeonMatthes Jun 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::net::Ipv4Addr;

use anyhow::Context;
use enet::*;
use std::time::Duration;

fn main() -> anyhow::Result<()> {
let enet = Enet::new().context("could not initialize ENet")?;
Expand All @@ -21,8 +22,10 @@ fn main() -> anyhow::Result<()> {
host.connect(&Address::new(Ipv4Addr::LOCALHOST, 9001), 10, 0)
.context("connect failed")?;

let mut peer = loop {
let e = host.service(1000).context("service failed")?;
let peer_id = loop {
let e = host
.service(Duration::from_secs(1))
.expect("service failed");

let e = match e {
Some(ev) => ev,
Expand All @@ -31,23 +34,26 @@ fn main() -> anyhow::Result<()> {

println!("[client] event: {:#?}", e);

match e {
Event::Connect(ref p) => {
break p.clone();
}
Event::Disconnect(ref p, r) => {
println!("connection NOT successful, peer: {:?}, reason: {}", p, r);
match e.kind() {
EventKind::Connect => break e.peer_id(),
EventKind::Disconnect { data } => {
println!(
"connection NOT successful, peer: {:?}, reason: {}",
e.peer_id(),
data
);
std::process::exit(0);
}
Event::Receive { .. } => {
EventKind::Receive { .. } => {
anyhow::bail!("unexpected Receive-event while waiting for connection")
}
};
};

let peer = host.peer_mut(peer_id).unwrap();
// send a "hello"-like packet
peer.send_packet(
Packet::new(b"harro", PacketMode::ReliableSequenced).unwrap(),
Packet::new(b"harro".to_vec(), PacketMode::ReliableSequenced).unwrap(),
1,
)
.context("sending packet failed")?;
Expand All @@ -56,7 +62,9 @@ fn main() -> anyhow::Result<()> {
peer.disconnect_later(5);

loop {
let e = host.service(1000).context("service failed")?;
let e = host
.service(Duration::from_secs(1))
.context("service failed");
println!("received event: {:#?}", e);
}
}
34 changes: 19 additions & 15 deletions examples/server.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
extern crate enet;

use std::net::Ipv4Addr;

use anyhow::Context;
use enet::*;
use std::net::Ipv4Addr;
use std::time::Duration;

fn main() -> anyhow::Result<()> {
let enet = Enet::new().context("could not initialize ENet")?;
Expand All @@ -21,19 +21,23 @@ fn main() -> anyhow::Result<()> {
.context("could not create host")?;

loop {
match host.service(1000).context("service failed")? {
Some(Event::Connect(_)) => println!("new connection!"),
Some(Event::Disconnect(..)) => println!("disconnect!"),
Some(Event::Receive {
channel_id,
ref packet,
..
}) => println!(
"got packet on channel {}, content: '{}'",
channel_id,
std::str::from_utf8(packet.data()).unwrap()
),
_ => (),
// Wait 500 ms for any events.
if let Some(event) = host
.service(Duration::from_secs(1))
.context("service failed")?
{
match event.kind() {
&EventKind::Connect => println!("new connection!"),
&EventKind::Disconnect { .. } => println!("disconnect!"),
&EventKind::Receive {
ref channel_id,
ref packet,
} => println!(
"got packet on channel {}, content: '{}'",
channel_id,
std::str::from_utf8(packet.data()).unwrap()
),
}
}
}
}
4 changes: 2 additions & 2 deletions src/address.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
ffi::CString,
ffi::CStr,
net::{Ipv4Addr, SocketAddrV4},
};

Expand All @@ -22,7 +22,7 @@ impl Address {
}

/// Create a new address from a given hostname.
pub fn from_hostname(hostname: &CString, port: u16) -> Result<Address, Error> {
pub fn from_hostname(hostname: &CStr, port: u16) -> Result<Address, Error> {
use enet_sys::enet_address_set_host;

let mut addr = ENetAddress { host: 0, port };
Expand Down
127 changes: 89 additions & 38 deletions src/event.rs
Original file line number Diff line number Diff line change
@@ -1,64 +1,115 @@
#![allow(non_upper_case_globals)]
use enet_sys::{
ENetEvent, _ENetEventType_ENET_EVENT_TYPE_CONNECT, _ENetEventType_ENET_EVENT_TYPE_DISCONNECT,
_ENetEventType_ENET_EVENT_TYPE_NONE, _ENetEventType_ENET_EVENT_TYPE_RECEIVE,
};

use crate::{Packet, Peer};
use crate::{Host, Packet, Peer, PeerID};

/// This enum represents an event that can occur when servicing an `EnetHost`.
///
/// Also see the official ENet documentation for more information.
/// This struct represents an event that can occur when servicing an `Host`.
#[derive(Debug)]
pub enum Event<'a, T> {
/// This variant represents the connection of a peer, contained in the only
/// field.
Connect(Peer<'a, T>),
/// This variant represents the disconnection of a peer, either because it
/// was requested or due to a timeout.
///
/// The disconnected peer is contained in the first field, while the second
/// field contains the user-specified data for this disconnection.
Disconnect(Peer<'a, T>, u32),
/// This variants repersents a packet that was received.
pub struct Event<'a, T> {
peer: &'a mut Peer<T>,
peer_id: PeerID,
kind: EventKind,
}

/// The type of an event.
#[derive(Debug)]
pub enum EventKind {
/// Peer has connected.
Connect,
/// Peer has disconnected.
//
/// The data of the peer will be dropped when the received `Event` is dropped.
Disconnect {
/// The data associated with this event. Usually a reason for disconnection.
data: u32,
},
/// Peer has received a packet.
Receive {
/// The `Peer` that sent the packet.
sender: Peer<'a, T>,
/// The channel on which the packet was received.
/// ID of the channel that the packet was received on.
channel_id: u8,
/// The `Packet` that was received.
packet: Packet,
},
}

impl<'a, T> Event<'a, T> {
pub(crate) fn from_sys_event<'b>(event_sys: &'b ENetEvent) -> Option<Event<'a, T>> {
#[allow(non_upper_case_globals)]
match event_sys.type_ {
_ENetEventType_ENET_EVENT_TYPE_NONE => None,
_ENetEventType_ENET_EVENT_TYPE_CONNECT => {
Some(Event::Connect(Peer::new(event_sys.peer)))
}
_ENetEventType_ENET_EVENT_TYPE_DISCONNECT => {
Some(Event::Disconnect(Peer::new(event_sys.peer), event_sys.data))
}
_ENetEventType_ENET_EVENT_TYPE_RECEIVE => Some(Event::Receive {
sender: Peer::new(event_sys.peer),
pub(crate) fn from_sys_event(event_sys: ENetEvent, host: &'a Host<T>) -> Option<Event<'a, T>> {
if event_sys.type_ == _ENetEventType_ENET_EVENT_TYPE_NONE {
return None;
}

let peer = unsafe { Peer::new_mut(&mut *event_sys.peer) };
let peer_id = unsafe { host.peer_id(event_sys.peer) };
let kind = match event_sys.type_ {
_ENetEventType_ENET_EVENT_TYPE_CONNECT => EventKind::Connect,
_ENetEventType_ENET_EVENT_TYPE_DISCONNECT => EventKind::Disconnect {
data: event_sys.data,
},
_ENetEventType_ENET_EVENT_TYPE_RECEIVE => EventKind::Receive {
channel_id: event_sys.channelID,
packet: Packet::from_sys_packet(event_sys.packet),
}),
},
_ => panic!("unrecognized event type: {}", event_sys.type_),
};

Some(Event {
peer,
peer_id,
kind,
})
}

/// The peer that this event happened on.
pub fn peer(&'_ self) -> &'_ Peer<T> {
&*self.peer
}

/// The peer that this event happened on.
pub fn peer_mut(&'_ mut self) -> &'_ mut Peer<T> {
self.peer
}

/// The `PeerID` of the peer that this event happened on.
pub fn peer_id(&self) -> PeerID {
self.peer_id
}

/// The type of this event.
pub fn kind(&self) -> &EventKind {
&self.kind
}

/// Take the EventKind out of this event.
/// If this peer is a Disconnect event, it will clean up the Peer.
/// See the `Drop` implementation
pub fn take_kind(mut self) -> EventKind {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is your use case for requiring this method? I would guess you want to take out the packet from a Receive-event?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that was my use case.
I have one more layer of abstraction on top of enet-rs in my current application.

I'm sending all received event kinds for each peer through crossbeam channels, such that my Peers just boil down to a single crossbeam receiver. Which is very multi-threading friendly.

That's why I need to be able to take ownership of the EventKind.
This entire change did make my codebase better though, as I no longer had to check if the peers state was disconnected, or Zombie or any of the other intermediate states a Peer might be in.
I could simply check if its PeerID was still valid :)

// Unfortunately we can't simply take the `kind` out of the Event, as otherwise the `Drop`
// implementation would no longer work.
// We can however, swap the actual EventKind with an empty EventKind (in this case
// Connect).
// As the `Drop` implementation will then do nothing, we need to call cleanup_after_disconnect before we do the swap.
self.cleanup_after_disconnect();

let mut kind = EventKind::Connect;
std::mem::swap(&mut kind, &mut self.kind);
kind
}

fn cleanup_after_disconnect(&mut self) {
match self.kind {
EventKind::Disconnect { .. } => self.peer.cleanup_after_disconnect(),
EventKind::Connect | EventKind::Receive { .. } => {}
}
}
}

/// Dropping an `Event` with `EventKind::Disconnect` will clean up the Peer, by dropping
/// the data associated with the `Peer`, as well as invalidating the `PeerID`.
impl<'a, T> Drop for Event<'a, T> {
fn drop(&mut self) {
// Seemingly, the lifetime of an ENetPeer ends with the end of the Disconnect
// event. However, this is *not really clear* in the ENet docs!
// It looks like the Peer *might* live longer, but not shorter, so it should be
// safe to destroy the associated data (if any) here.
if let Event::Disconnect(peer, _) = self {
peer.set_data(None)
}
self.cleanup_after_disconnect();
}
}
Loading