Date: Tue, 4 Sep 2001 13:02:50 -0700 (PDT) From: Roger Crew To: mcp-dev@research.att.com Subject: Re: mcp-negotiate-can 2.1 Sender: owner-mcp-dev@research.att.com Precedence: bulk In other news, there appears to be a somewhat nasty omission from the current mcp-negotiate 2.0 that leading to Sufficiently Bad Things that it's probably worth tweaking the spec independently of whatever else I've said this week. When I proposed, | (*) an implementation may begin sending messages in a given | package only after sending a mcp-negotiate-can message | advertising a range including the maximal common version. I was assuming that the current (MCP 2.1/mcp-negotiate 2.0) spec had a similar such provision, i.e., that you have to send your package messages out only after having SENT the corresponding mcp-negotiate-can. But just to be sure, I went back and looked for it. It's not there. The most I could find was an edit example given in 3.1 which seems to be assuming such a requirement in a parenthetical remark, but there's no explicit statement of it anywhere that I could find. The spec merely has the requirement that you send your package messages out only after having RECEIVED the corresponding mcp-negotiate-can. This, in the absence of the "having SENT" requirement, leads to the following Path of Evil: L<--P mcp-negotiate-can package: foo min-version: 1.0 max-version: 2.0 L-->P foo-whatever ... L-->P foo-whatever ... L-->P foo-whatever ... L-->P foo-whatever ... L-->P mcp-negotiate-can package: foo min-version: 1.0 max-version: 2.0 (here, L and P refer to 'local' and 'peer' respectively). The theory here is that once the L receives the first -can message it knows that the max common version is 2.0. Version negotiation having succeeded (as far as L is concerned), having received the requisite mcp-negotiate-can, and there being no "having SENT" requirement, it's okay to send the foo-whatevers. Worse yet, having advertised support for Foo 2.0, the peer is obligated to honor the foo-whatever messages even though at the time it receives them it has no idea that the local is even supporting foo. It could probably infer that something interesting is about to happen from the fact that it is receiving foo messages at all, but that doesn't help with knowing how to interpret them, let alone figuring out the exact version number in use. (While there IS a provision in the spec that the peer NOT count on the local having support for Foo, that only governs what the peer sends, not how to handle what it receives.) One could then conclude that the peer is REQUIRED to queue up the -whatevers for later processing once the latter mcp-negotiate-can message comes in. They can't be dropped on the floor because they're not errors --- version negotiation has succeeded; it's just that the peer doesn't know it, yet. I'm also guessing nobody implements this queuing, which would be a fair amount of work and almost completely pointless when you consider that (I hope) NOBODY is sending out package messages prior to sending their corresponding mcp-negotiate-cans. As for how to fix this for 2.1: (1) we could go the conservative route and just add back the "having SENT" requirement, which I'm pretty sure everbody thought was already there in the first place. i.e., the revised verbiage for my 2.1 proposal would be | (*) an implementation may begin sending messages in a given | package only after having sent AND having received an | mcp-negotiate-can message advertising a range including the | maximal common version (2) Having thought about it some more, I will assert that it's really the "having SENT" requirement that matters and that if stated in the right way, the need for even having a "having RECEIVED" requirement goes away. This version looks like | (*) an implementation may begin sending messages | in a given package at ANY TIME (***), | HOWEVER implementations MUST ignore (**) messages | in that package received prior to the first-received | 'mcp-negotiate-can' advertising the maximal common version. This establishes the "having SENT" requirement in a passive way (i.e., you can do what you like, but if you want your package messages to have any effect, you need to send them after your negotiate-can...) The 'however' part is important to ensure that the extra messages aren't doing damage. But it's already standard practice to drop unknown stuff on the floor. The only thing that's potentially new (and I'm guessing it isn't actually) is the idea of "unknown" including stuff that *is* supported by the implementation but hasn't version-negotiated yet --- i.e., not including the exceptional case of the mcp-negotiate package itself, which has to be functional from the very beginning. Beyond that, there's nothing new that a receiving implementation need do to conform to this. The fact that the sender used to be waiting to receive a mcp-negotiate-can and isn't anymore makes no difference because this is NOT something that can be observed from the other end of the connection (except in weird cases where the receiver has delaying sending its own mcp-negotiate-can... which it shouldn't be doing anyway...) (**) there is the small matter of defining "ignore". (***) well okay, "any time" here really means "any time after the mcp-negotiate version is established." And it occurs to me that being able to speculatively send could be useful. At least one article touts MCP's allowing both participants to just be able to start spewing mcp-negotiate-cans at each other with no need for synchronization. It seems like allowing individual packages to do this as well could only be a win. (...say you have a high-latency connection and you're 99% sure the other end supports the package you care about...) To be sure, any kind of speculative sending is more work for the sender, who has to ensure that whatever it's sending is intelligible in all version ranges it is advertising; but then nobody is being REQUIRED to speculatively send stuff...