Skip to content
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

Separate (underlying) datachannels for unreliable and reliable messages #269

Open
yandeu opened this issue Oct 3, 2023 Discussed in #263 · 2 comments
Open

Separate (underlying) datachannels for unreliable and reliable messages #269

yandeu opened this issue Oct 3, 2023 Discussed in #263 · 2 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@yandeu
Copy link
Member

yandeu commented Oct 3, 2023

Discussed in #263

Originally posted by reececomo July 25, 2023
I think Geckos.io would benefit from creating two separate datachannels per connection, one for unreliable and one for reliable.

That would allow certain messages to leverage the existing (super fast) reliable mode at the network layer instead of reimplementing it at the application layer.

// UDP-like channel for realtime data (e.g. binary, serialized game state packets).
const unreliable = RTCPeerConnection.createDataChannel("unreliable", {
    ordered: false,
    maxRetransmits: 0
});

// TCP-like channel for reliable data (e.g. chat message, ad-hoc game state events).
const reliable = RTCPeerConnection.createDataChannel("reliable", {
    ordered: true, // optional?
    maxRetransmits: 10 // Use constant
});
@yandeu yandeu added enhancement New feature or request help wanted Extra attention is needed labels Oct 3, 2023
@reececomo
Copy link

reececomo commented Oct 9, 2023

This might be tough to do elegantly within Geckos.io's existing abstraction/conventions.

A: Keep current abstraction

const channel = geckos({ /* ... */ });
channel.sendReliable('msg', { ...data });

where

public async sendReliable(msg: string, data?: any): void
{
  // Wait for first-time setup if needed.
  this._reliableDataChannel = this._reliableDataChannel ?? await this.createReliableChannel();
  this._reliableDataChannel.emit(msg, data);
}

and integrate both channels with existing event handlers.

B: User Creates/Manages Non-Default DataChannels

You could either expose or hide the "threading"/channels.

Maybe something like:

const connection = geckos({
  // ...
});

connection.main.on('event1', () => {});
connection.dataChannel('2').on('event2', () => {});

or have data channel be a separate argument, like:

channel.on('event', (e) => this.handle(e), { dataChannel: '2' });

@reececomo
Copy link

Just an update @yandeu, our game has been running a hacked-together version of this for some time and it appears to work great.

Previously on the geckos default implementation of reliable (with default settings) we did see the occasional hitch. Mostly when sending or recv too many reliable packets at once. In fairness we probably could have done some version of Nagle's/batching and sent multiple json blobs in one packet (i.e. what Glenn Fielder suggests).

We were a little worried using a seperate reliable channel might block or interrupt the main (unreliable) channel, but it seems to work great.

No idea if there are any SCTP/DTLS congestion control or scaling issues to be aware of, but after a couple months can highly recommend making the switch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants