Code change:
Add some normative text and requires both client and server to send their role. I can also see the argument for removing this entirely, but it's in the current draft, so if we're going to keep it, I'd like to define it better.
Having a flag in SETUP doesn't stop from someone sending unsupported messages. A faulty implementation or intentionally malicious endpoint can send unsupported messages. A receiver should be prepared to handle unsupported messages regardless.
Right, an implementation is still going to crash if it receives an unsupported message, but there's a difference between signaling that upfront and yolo. A one-sided implementation will look something like this: The purpose of the ROLE parameter is to avoid accidentally triggering that default, as it will close the connection. For example, I absolutely want to have a way to get per-viewer feedback: a track produced by each viewer. Without this ROLE field, a viewer might cause a crash if it sends an to the server, or the server might cause a crash if it sends a to the viewer. It will only work if both endpoints explicitly flag . The only alternative to the ROLE field is to implement the entire protocol, but that's unnecessarily restrictive. Take HTTP for example, it's almost taken for granted that an implementation is for a client or a server, but rarely both. I imagine that will also be the case with MoQ with the sole exception of relays. OBS is not going to implement subscribing, and VLC is not going to implement publishing. Even in my URL library that does support both modes, I ran into a deadlock because of ROLE=both. My publisher was not consuming ANNOUNCE messages because it was not expecting them. Explicitly signaling ROLE=publisher would have prevented this, making it a protocol violation to send half of the messages in the draft.
A resilient implementation state machine will be something like Since for unsupported messages, you don't want a protocol action as it will be DOS surface, for example. Also, Many of the conferencing examples will mostly always be send and receive by default. Our client for example does pub and subscribe always. I personally feel the implementation constraints are resolvable and I feel still unconvinced for a ROLE parameter.
Heh, please don't do that. This is exactly why we have version/extension negotiation; not supporting a message after negotiating it is a protocol violation. Otherwise, my endpoint has to assume that your endpoint could ignore messages, and the MoQ draft in general, on a whim. Just tell me that you don't support ANNOUNCE via ROLE. Otherwise I would have to send an ANNOUNCE, start a timer, and guess that no OK/ERROR means no support? Probing for support is miserable. You close the connection on an unsupported message. Just send ROLE=both then. Not every conferencing is bidirectional though, for example clubhouse-style. At Discord we also have a dedicated connection for screen sharing (don't ask) and a very explicit role=publisher vs role=subscriber flag.
I don't think this is necessarily true. Without ROLE, you can still choose to only implement half the protocol and reject the messages you don't support. Every client has to be built to be resilient to arbitrary incoming messages. It can't break because the other side said their role was subscriber but then they send you an ANNOUCE. Therefore sending an upfront role seems like a promise to behave in a certain way. A system that relies on promises to not break will be brittle. I agree that ROLE seems superfluous.
I want publisher and subscriber support to be optional. That way it's only necessary to implement half of the draft on many cases. A CDN distribution edge would be one such situation. In fact, it's a hardening measure to ensure the edge cannot receive a ANNOUNCE which might otherwise cause a vulnerability. And generally speaking, if something is optional, then it should be negotiated. Otherwise you end up with Schroeder's extension. Silently ignoring unknown/unsupported messages is just terrible protocol design and it's s far better to close the connection with a protocol violation instead. That's the point of the ROLE parameter. But yeah let's chat about it on Wed.
Individual Comment: Every implementation has to have that switch statement and some not-crash action when it receives a message it doesn't support. Some logical options are: Ignore the message Send the corresponding error message (eg SUBSCRIBEERROR, ANNOUNCEERROR) with an error code like "not-implemented" Close the entire connection I think the value of ROLE is that it gives a consistent behavior early in the life of the session. If I want to send subscribes and the peer says they are subscriber only, I close the connection. But I still have to have the switch statement because of broken or malicious peers. The MUST in this PR can be improved by explaining what happens when you don't like the value you see, or the peer sends messages inconsistent with its advertised role.
In that case the peer will close the connection since it knows that it is subscribe only implementation and the role in the setup is supreflous
This is the type of things where I don't think we need it but it does not break anything, is not a big deal to implement, and does not hit performance. Given other people feel strongly this is needed, I can easily live with this. If this helps us get to consensus, I'm fine with adding it. I think the rewrite makes things clearer than they were before.
Discussion concluded that supporting this was not that difficult and it's a clear signal of what's supported, to so AI is to fix up the PR to clarify behavior.
Sec 6.1.1.1 specifies client sending or ROLE, and says nothing of server-sent. I guess server-sent ROLE is not needed, but maybe we should fail if it is sent?
I filed about the role parameter. The client doesn't actually know what the server intends to do. The server should be able to reply with its functionality, which might be a subset of what the client can support.
The SETUP message contains a ROLE parameter. In the current draft, the client specifies the value, indicating if the client will send data (0x1), if the server will send data (0x2), or if both endpoints will send data (0x3). A conferencing client supports the ability to send and receive media, and would always send role=0x3 because it supports both functionalities. However, it's unaware of the server functionality, and the server has no way of informing the client if it intends to send media. This matters because a generic client needs to know if it shows a black screen and/or should send a SUBSCRIBE message (ex. for /catalog). I propose that both endpoints send the ROLE parameter: 0x1 = publisher, 0x2 = consumer, 0x3 = both. This gives the server the ability to specify its own functionality.
Wondering if we even need Role in the first place .. can it be changed mid-session ? Say the use-case Participant in media conference joins as subscriber only since he is driving and want to listen in Then at some point mid session , he wants to contribute and he now becomes as publisher and subscriber what is the expected flow in this case ?
Current draft doesn't really explain what ROLE parameter is for, only that client needs to send it - what was original idea? Why not just always allow everyone to send and receive data?
It seems a better way to control if you can send and receive might just be if the client has the appropriate auth tokens for each role. I lean towards remove this if we don't need it, but if we need it, I have would be fine with a design where the client says which roles it is capable of , and the server response contains which roles it is allowed to do.
I think ROLE is good for negotiating half-functionality. If the remote endpoint cannot send media (ex. player), then sending a SUBSCRIBE is invalid. If the remote endpoint cannot receive media (ex. OBS), then sending a ANNOUNCE/OBJECT is invalid. This removes a burden on implementations, as most will only care about specific role. NAME brings up a good point. If an endpoint could switch roles, then it should advertise full functionality. That would include publishing an empty catalog which it can append it later when it wishes to publish tracks.
I don't think I seem much use for the Role - it seems like something the application would know at a higher layer. But I have no objection to including it if others do see a need for it. It's not like it makes life harder for applications that don't use it.
If the ROLE is used to enforce the half-functionality, then it needs to be clear what should be done when invalid message is received. Sending a GOAWAY? Sending a generic error message? Does the connection need to be terminated? I think most of the time, application will just choose the full functionality in case of role switching on the fly and avoid the invalid response code(just ignore the invalid message).
Oh hey, I found a good use-case for ROLE. If my client connects with ROLE=publisher, then the server knows that it should not send ANNOUNCE messages. The messages are useless and actually triggered a deadlock in my broadcaster, since the application was not reading them and overflowed the receive channel. The same would be true with the reverse; a subscriber will not be able to process any SUBSCRIBE messages. I like the ability to specify half-functionality. At the very least the library should support half-functionality (ex. automatically reply with ANNOUNCE_ERROR) but it's even better if it's enforced by the protocol.
LGTM me. Ship it!I wonder if it helps to discuss the role of role parameter during authors call for a short bit NAME

Related discussion:
text: dependent on the congestion response.  A subscription remains active until it expires, until the publisher of the track terminates the track with a SUBSCRIBE_FIN (see message-subscribe-fin) or a <del> SUBSCRIBE_RST (see message-subscribe-rst). </del> <ins> SUBSCRIBE_RESET (see message-subscribe-reset). Objects MUST NOT be sent for unsuccessful subscriptions, and if a subscriber receives a SUBSCRIBE_ERROR after receiving objects, it MUST close the session with a 'Protocol Violation'. </ins> A relay MUST not reorder or drop objects received on a multi-object stream when forwarding to subscribers, unless it has application