-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added packet reliability processing. #79
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks ok with a quick skim, but it would take hours to do a proper PR with this. As long as the tests have been updated and pass, and they work with my docker-compose stuff, I'm ok with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking really good! Honestly, great work! A lot of comments but mostly questions. I want to take some time to think about the channels. I'm not totally a fan just yet.
mod reliable_channel; | ||
|
||
use infrastructure::DeliveryMethod; | ||
use error::NetworkResult; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may have missed this before, but this should be called Result
to be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be moved into another issue for error handling. We have to error types and Result already exists.
seq_num: u16, | ||
waiting_packets: LocalAckRecord, | ||
their_acks: ExternalAcks, | ||
dropped_packets: Vec<Box<[u8]>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since vec is already on the heap, could you move a slice into it, instead of a double allocation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is somewhat complicated, and could better be moved to another issue. This is complicated because LocalAckRecord
are gathering dropped ack's and returning them.
use error::NetworkResult; | ||
|
||
/// Contains the raw data this packet exists of. Note that a packet can be divided into separate fragments | ||
#[derive(Debug, Default)] | ||
pub struct PacketData { | ||
parts: Vec<RawPacketData>, | ||
parts: Vec<Vec<u8>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vec of a vec? could you explain this more and why you choose the inner as a vec?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I removed RawPacketData
this was just some unnecessarily code which could be worked away. First I did it since I thought I could have slices here. But I could not accomplish that.
is this pr still WIP? if not please update the title |
- Channels for processing packets of different reliabilities. - Changed header format a little to fit current design. - Moved fragmentation logic to it's own type. - Global performance improvements by preventing unnecesary alocations with vectors. - Removed 'SocketState' and 'PacketProcesor' types.
bors r+ |
79: Added packet reliability processing. r=fhaynes a=TimonPost This PR is about packet processing described in RFC #65. **!!Note!!** This PR seems big (it is) but there are just a few files needing your attention. They are located in `infrastructure` module, everything else are just secondary concerns caused by fixing broken tests and moving code to the new channels. `net::connection::virtual_connection.rs` and `net::udp.rs` are also important files where some things have changed. ## Channel A channel processes a packet with a certain reliability. A channel could be responsible for ordering, resending, handling dropped packets etc. _Channel Trait_ ```rust /// This provides an abstraction for processing packets to their given reliability. pub trait Channel { /// Process an packet before send and return an packet data instance with the given raw packet data. fn pre_process(&mut self, payload: &[u8], delivery_method: DeliveryMethod) -> NetworkResult<PacketData>; /// Progress an packet on receive and receive the processed data. fn process_packet(&mut self, cursor: &mut Cursor<&[u8]>) -> NetworkResult<Vec<u8>>; } ``` So we have different instances of channels. 1. ReliableChannel This channel should be used for reliable processing of packets. This channel also has an ordering option for ordering packet, however, this is not implemented yet. 2. SequencedChannel This channel should be used for sequenced packets. Sequenced means only the newest data will be accepted. This channel has the option to be reliable. 3. UnreliableChannel This channel should be used for unreliable processing of packets. This is just bear UDP with some basic header on top of it. I suggest you look at the code for more information on how I implemented the channels in the code. ## Packet Header change. I also had changed the packet format a little. It was needed for implementing the channels got stuck at the old design. The nice thing now is that the header parser takes in a mutable buffer to which will be written to. It is some kind the same but the following table will show you how the packets are. Standard header, which will be included in each packet. ```rust pub struct StandardHeader { /// crc32 of the protocol version. pub protocol_version: u32, /// specifies the packet type. pub packet_type_id: PacketTypeId, /// specifies how this packet should be processed. pub delivery_method: DeliveryMethod, } ``` Fragment header, this is the header containing header fragment information. Witch also contains the standard header and the first fragment will also contain ```rust pub struct FragmentHeader { standard_header: StandardHeader, sequence: u16, id: u8, num_fragments: u8, packet_header: Option<AckedPacketHeader>, } ``` Acked packet header wich will be used for reliable packets. ```rust standard_header: StandardHeader, seq_num: u16, last_seq: u16, bit_field: u32, ``` ## Overall changes - Overal perfromance improvements - HeaderParser's `parse` function takes in mutalble buffer witch is more optimal performance wise than generating them local and return an clone of them. - Moved fragmentation stuff into it's own type. - Removed `SocketState` and `PacketProcessor` this logic can now be found in the `ReliableChannel` and `Fragmenting` type. ![bonus](https://media.discordapp.net/attachments/425694112973586452/506815279125495843/DjaXbaVW4AInQXP.png?width=601&height=664) Co-authored-by: Timon Post <timonpost@hotmail.nl>
Build succeeded |
This PR is about packet processing described in RFC #65.
!!Note!!
This PR seems big (it is) but there are just a few files needing your attention. They are located in
infrastructure
module, everything else are just secondary concerns caused by fixing broken tests and moving code to the new channels.net::connection::virtual_connection.rs
andnet::udp.rs
are also important files where some things have changed.Channel
A channel processes a packet with a certain reliability. A channel could be responsible for ordering, resending, handling dropped packets etc.
Channel Trait
So we have different instances of channels.
This channel should be used for reliable processing of packets. This channel also has an ordering option for ordering packet, however, this is not implemented yet.
This channel should be used for sequenced packets. Sequenced means only the newest data will be accepted. This channel has the option to be reliable.
This channel should be used for unreliable processing of packets. This is just bear UDP with some basic header on top of it.
I suggest you look at the code for more information on how I implemented the channels in the code.
Packet Header change.
I also had changed the packet format a little. It was needed for implementing the channels got stuck at the old design. The nice thing now is that the header parser takes in a mutable buffer to which will be written to. It is some kind the same but the following table will show you how the packets are.
Standard header, which will be included in each packet.
Fragment header, this is the header containing header fragment information.
Witch also contains the standard header and the first fragment will also contain
Acked packet header wich will be used for reliable packets.
Overall changes
parse
function takes in mutalble buffer witch is more optimal performance wise than generating them local and return an clone of them.SocketState
andPacketProcessor
this logic can now be found in theReliableChannel
andFragmenting
type.