gavv / webrtc-cli

WebRTC command-line peer.
MIT License
225 stars 24 forks source link

Add support for data channels #3

Open normanr opened 4 years ago

normanr commented 4 years ago

It would be great to also have support for (ordered and unordered) data channels.

gavv commented 4 years ago

Hi, thanks for your interest.

Could your describe the desired use case?

What will be the data source and destination? In case of audio, it is an audio device. And in case of data channels? Files and pipes? I guess in this case we'll have to implement our own protocol to delimit individual messages?

normanr commented 4 years ago

I was mostly thinking that it could just connect a single data channel to stdin/stdout for debugging. I guess you could support a file or pipe too (which would then allow files to be copied over the connection).

WebRTC does message delimitation, but I assume you mean on the fd side. I'd be tempted to say don't require any framing and just forwards the data as it arrives. That would be fine for naturally stream based data, but not messages (which WebRTC is often transporting).

If it's really needed there are many options: Text: encoding (eg: json, text protobuf), delimiter (eg: newline, or double-newline), Binary: Either encode (eg: json) or "encode-and-treat-as-text" (eg: Base64), or add a "length-of-message" header to the binary data (fixed or variable width), or encode as binary protobuf. I'd be tempted to say pick something that's easy to support in go that will work for both text and binary data - encoding/json would support text and base64 binary data.

Another idea was tcp/udp connect/listen like ssh -L/-R or socat. In fact it might just be simpler to support cmd.Exec and then any subprocess can be used (and then socat could be used if you wanted a tcp/udp proxy for example).

gavv commented 4 years ago

I'd be tempted to say don't require any framing and just forwards the data as it arrives.

But what do you mean by "as it arrives"? The data arrives from file or stdin (which is essentially the same thing) as a continuous stream, and we should split it into WebRTC messages.

Send every read() result as a message? This may be:

Send every input line as an individual message? This is better, but what about multi-line JSON objects? Not very convenient.

If it's really needed there are many options: [...]

Yeah, that's what I'm talking about. We need to specify some custom input format. If the primary goal is debugging, we need some text format.

Using JSON is not ideal if you want to send non-JSON messages. Or for example invalid-encoded JSON messages (for debugging / testing). In this case you'll have to encode your message to be a valid JSON string, which is inconvenient.

Just using some delimiters is not enough BTW, we also need to specify some quoting syntax in this case. Or you can allow the user to specify the delimiter, like in HTTP chunked encoding. In this case the quoting is not necessary.

base64 is probably a good idea too.

length-of-message field would be inconvenient for debugging as well.

Another idea was tcp/udp connect/listen like ssh -L/-R or socat. In fact it might just be simpler to support cmd.Exec and then any subprocess can be used

Do you mean specifying a command from which stdout webrtc-cli will continuously read messages? In this case I see no difference from reading messages from stdin (which may be a pipe connected to another program).

Or do you mean specifying a command which webrtc-cli will execute each time to read a single message?

normanr commented 4 years ago

blegh. It sounded like a good idea at the time, but there's no obvious solution for the general case.

The only realistic use case (that I can think of and would have a use for) is ssh-like port forwarding: Instead of --source/sink for pulseaudio, I imagine --listen/connect would be used for net.Conn. Protocols like tcp, unix & unixpacket would use reliable ordered data channels, udp & unixgram could use unreliable unordered data channels.