16 Mar, 2009, elanthis wrote in the 1st comment:
Votes: 0
I was finishing off the subwindow package spec and had a thought while working on the subwindow.set-input command. That command's 2nd argument is a boolean value – turn input on or turn it off.

The question is, what should boolean values be represented as? 0 and 1? off and on? no and yes? false and true? N and Y? red and green?

ZMP should have a "best practices" section in the spec for anyone designing a package or command of their own. One of the issues should be the preferred standard way of representing boolean fields. Another might be some number formatting guidelines. e.g., dont put comma separators or the like in there, use decimal notation for fractional parts instead of scientific, dont include leading 0s which can confuse some language's string->int routines (JavaScript, I mean you: so few people remember to pass the second argument to parseInt, and the default behavior is retarded). Text should be plain 7-bit ASCII or UTF-8 and shouldn't include any control characters except for newline.

For that matter, what should newlines be in ZMP argument data (for things like script editing or the like) ? Standard C uses \n and even automatically converts to/from that when writing files in text mode. TELNET mandates \r\n always and a lot of MUDs may have code explicitly designed for dealing with \r\n, and most I believe even store \r\n inside the actual text data for room descriptions and the like. So what should the "best practice" there be? Use \n? Use \r\n? Try to automatically figure it out? Add some kind of (pain in the ass) negotiation for it? Just ignore the issue and let implementations figure it out?

Any other best practices that should be mentioned? Any informational text to help make sure consistency is maintained is a plus in my book.
16 Mar, 2009, David Haley wrote in the 2nd comment:
Votes: 0
My opinions… mostly agreeing with yours:

Booleans: '0' or '1' – character 0 or character 1, not byte value.

Numbers: ([1-9][0-9]*)|0 (\.[0-9]+)? i.e. at least one non-zero digit, followed by any number of digits, OR just a zero, optionally followed by a period then at least one more digit

Text: 7-bit or UTF-8. Allow sane control characters like \t. No surrounding quotation marks.

Newlines: represent as \n and let either end do whatever they want with it. Potential problem if MUD devs don't realize they need to expand \n to \r\n before sending to the client. Definitely don't do anything automagic, or guess based on what you see. Either \n or \r\n. No need to negotiate, I would think, and it'd be a PITA as you say.
16 Mar, 2009, Scandum wrote in the 3rd comment:
Votes: 0
As has been discussed recently there are two main protocols, TELNET, and VT100. Telnet is primarily used for toggling local echo, and vt100 for cursor positioning and color.

I think it's safe to assume that every terminal will support a primitive VT100 set that treats \n as a newline, and as such it's permissible to use a single \n. Like telnet ignores color codes, telnet should ignore a single \n and leave it up to the terminal to deal with it, which should always result in a newline in a proper terminal. (Windows 98 terminal doesn't handle this correctly, but as of XP it does.)

So technically a mud isn't breaking the telnet protocol by sending a \n, what telnet does instead is strictly define the meaning of \r\n so telnet clients can translate it to the proper newline for the underlining OS, which in practically all cases is \n.


I'm not exactly sure what the correct behavior is for sending commands to a mud, since technically you're not printing to a terminal, so vt100 and telnet do not apply. But assuming all telnet clients send \r\n on an enter it should be assumed that both \n and \r\n are valid, though \r\n seems like the better argument, even when in practice all muds strip out the \r first chance they get.

Edit:

Boolean values are probably best printed as "0" and "1" since that'll make conversion easy with atol.

I'd definitely avoid using NUL bytes inside the arguments and use string arguments if possible, that way I can simply plug an event handler in tintin so zmp can be dealt with by a script.

Maximum amount of arguments for tintin would be 99, excluding the variable. Possibly the same limitation for zMud.
16 Mar, 2009, elanthis wrote in the 4th comment:
Votes: 0
Scandum said:
I think it's safe to assume that every terminal will support a primitive VT100 set that treats \n as a newline, and as such it's permissible to use a single \n. Like telnet ignores color codes, telnet should ignore a single \n and leave it up to the terminal to deal with it, which should always result in a newline in a proper terminal. (Windows 98 terminal doesn't handle this correctly, but as of XP it does.)


Good to know. Might be worth noting that by the TELNET standard, \r (rarely used in MUDs, but common enough elsewhere) has to be sent as \r\0. I wonder how many clients or servers do that properly (probably close to none).

Quote
So technically a mud isn't breaking the telnet protocol by sending a \n, what telnet does instead is strictly define the meaning of \r\n so telnet clients can translate it to the proper newline for the underlining OS, which in practically all cases is \n.


It's definitely not against the protocol. It just that technically \n in the NVT is supposed to mean something different than it does to UNIX terminals. TELNET intended for \n to literally mean "line feed" without a carriage return. e.g., move the cursor down a line but not to the start of the line. A fully correct TELNET client will put the terminal in a mode where \n does exactly that, or translate a received \n into the proper control codes to achieve that result. (Setting the terminal to that state is a pain in the ass, as I found out when I wrote the telnet-client test of libtelnet, which still doesn't get fully correct behavior. But it works as a test case and supports Vim sessions with no major problems, which is all I really needed.)

I'm sure just sending a LF works for most MUD clients and even many terminal types, but it is not technically correct. A server should still always be sending newlines as CRLF and a CR as CRNUL. So should clients. Making your client (or server) support non-standard behavior is of course totally cool. :) I cant' for the life of me think of any software I've seen that actually tries to use \n as a pure line feed. The only time I even see that happen is when the terminal gets accidentally set to a funny state (e.g., what the telnet utility sets it to) and then the results are obviously not correct.

That has relatively little to do with ZMP, though. The data inside of the command is not technically a TELNET line terminator, because it is not (usually) intended to be spit out to a terminal. It has no real need to follow the NVT rules about newlines and such because it's not data being displayed by the NVT. The only reason I'm thinking about it at all is that I know that some MUDs just use \r\n internally so that they can just dump a room description out over the socket with no translation or escaping or anything done at all.

I just want to have something to say in the spec about best practice. e.g., "You SHOULD represent newlines in command argument data as LF (\n) which is the standard newline representation in C and most other programming environments. Note that this differs from the TELNET behavior which requires CRLF (\r\n) for line termination."

side note: I very much plan on adding a flag to libtelnet to just handle \n -> \r\n and \r -> \r\0 automatically. When I'm writing my code, I much prefer just having a regular \n in any text and let the link layer figure out the specifics for me. MUDs that already manually put the \r\n everywhere can just leave the flag off (default behavior).

Quote
I'd definitely avoid using NUL bytes inside the arguments


Not even possible, same as 0x01 and 0x02 are completely impossible to use in MSSP variable names/values. :)

Quote
and use string arguments if possible, that way I can simply plug an event handler in tintin so zmp can be dealt with by a script.


Yeah, that's the intended behavior.

Quote
Maximum amount of arguments for tintin would be 99, excluding the variable. Possibly the same limitation for zMud.


Out of curiosity, why? Are arrays in tintin's script language limited in maximum size, or are you just trying to avoid dynamic allocation? (This is why I asked earlier about people's thoughts on argument count limits…)
16 Mar, 2009, elanthis wrote in the 5th comment:
Votes: 0
update: actually, scratch the auto CRLF translation thing for now, I guess. I just realized that actually complicates things a lot, as it then requires a whole set of functions that operates with it off, e.g. for sending NAWS data (otherwise sending info for a terminal with only 10 rows would get screwed up) and it would force \r\n into ZMP args even if we say you should use \n. :/ TELNET really is a pain in the ass. I already had a libtelnet_printf helper, so I just made libtelnet_printf2 variant (can't think of a better name right now) that does the crlf/cr magic. Apps can just use whichever they want, and I'll make sure to clearly document that printf2 should not be used for subnegotiation data. I think just adding a couple helpers for the common subnegotiation types will alleviate the problem anyway, though. ZMP, TTYPE, NEW-ENVIRON, MSSP, and MCCP2 are the only ones MUDs ever use, right?
16 Mar, 2009, Scandum wrote in the 6th comment:
Votes: 0
elanthis said:
Good to know. Might be worth noting that by the TELNET standard, \r (rarely used in MUDs, but common enough elsewhere) has to be sent as \r\0. I wonder how many clients or servers do that properly (probably close to none).

Hard to tell, the telnet protocol doesn't specify how a single \r should be treated, and as far as I know telnet just passes everything along to the terminal with the possible exception of changing \r\0 to \r, never looked at the code.

elanthis said:
TELNET intended for \n to literally mean "line feed" without a carriage return. e.g., move the cursor down a line but not to the start of the line. A fully correct TELNET client will put the terminal in a mode where \n does exactly that, or translate a received \n into the proper control codes to achieve that result.

I don't see that defined anywhere in the protocol however, so I'd say that telnet only says that \r must be send as \r\0 and that \r\n must be treated as a new line, so in that regard I think a client would be wrong to make any changes, other than properly emulating \r\0 and \r\n.

elanthis said:
Quote
Maximum amount of arguments for tintin would be 99, excluding the variable. Possibly the same limitation for zMud.


Out of curiosity, why? Are arrays in tintin's script language limited in maximum size, or are you just trying to avoid dynamic allocation? (This is why I asked earlier about people's thoughts on argument count limits…)

Historically %0 to %9 was used for arguments in tintin triggers, both zMud and tintin later extended this to %99. It's more of a practical consideration. Given that the zmp variable would likely be part of the event name exactly 100 arguments could be used. It could be upped to 1000 arguments, but I'd rather not unless there's a good practical reason to do so.
17 Mar, 2009, David Haley wrote in the 7th comment:
Votes: 0
The idea of limiting argument lists to 100 or even 1000 just because tt++ can't handle it makes me feel really jittery. Surely Scandum can whip up some kind of simple extended format, dynamically allocated argument list in just a few minutes…
17 Mar, 2009, Scandum wrote in the 8th comment:
Votes: 0
David Haley said:
The idea of limiting argument lists to 100 or even 1000 just because tt++ can't handle it makes me feel really jittery. Surely Scandum can whip up some kind of simple extended format, dynamically allocated argument list in just a few minutes…

Nobody is speaking of limiting anything, it could just be a recommendation or even notice that some clients are limited to 100 arguments.
17 Mar, 2009, elanthis wrote in the 9th comment:
Votes: 0
Quote
Hard to tell, the telnet protocol doesn't specify how a single \r should be treated,


You may wish to actually read the RFC in depth instead of quickly skimming it. The behavior is very clearly stated. From RFC854:

RFC854 said:
Therefore, the sequence "CR LF" must be treated as a single "new
line" character and used whenever their combined action is
intended; the sequence "CR NUL" must be used where a carriage
return alone is actually desired; and the CR character must be
avoided in other contexts.


Quote
I don't see that defined anywhere in the protocol however,


Again, from the TELNET specification:

RFC854 said:
Line Feed (LF) 10 Moves the printer to the
next print line, keeping the
same horizontal position.


Quote
The idea of limiting argument lists to 100 or even 1000 just because tt++ can't handle it makes me feel really jittery. Surely Scandum can whip up some kind of simple extended format, dynamically allocated argument list in just a few minutes…


Looking at the code… no, it would definitely be more than a quick hack. Even upping the limit to 1000 would take far more work than just changing a MAX_ARGS constant, unfortunately. I'm trying to play nice so I'll limit myself to commenting that the majority of tintin's code is remarkably clever.
17 Mar, 2009, David Haley wrote in the 10th comment:
Votes: 0
This is like a textbook case of why programs shouldn't use homegrown scripting languages unless they have a really good reason to. :sad:
(For whatever it's worth, I don't believe Scandum is the original author of the client, so some decisions very well might not have been his, including this one)
17 Mar, 2009, Scandum wrote in the 11th comment:
Votes: 0
elanthis said:
You may wish to actually read the RFC in depth instead of quickly skimming it. The behavior is very clearly stated.


It looks like the telnet protocol defines the NVT (Network Virtual Terminal) and specifies the following requirements for it:
NAME                  CODE         MEANING

NULL (NUL) 0 No Operation
Line Feed (LF) 10 Moves the printer to the
next print line, keeping the
same horizontal position.
Carriage Return (CR) 13 Moves the printer to the left
margin of the current line.


So for 'correct' behavior you'd probably want to change \n to \v. Linux telnet however doesn't do this, so this creates a bit of a paradox because Linux to a degree defines the standard.

Telnet is kind of obsolete aside from mudding, so some kind of redefinition or new rfc of the NVT might be preferable. I'd fully support the unofficial acceptance of \n as a replacement for \r\n.

Quote
Looking at the code… no, it would definitely be more than a quick hack. Even upping the limit to 1000 would take far more work than just changing a MAX_ARGS constant, unfortunately. I'm trying to play nice so I'll limit myself to commenting that the majority of tintin's code is remarkably clever.

I should probably get it to dynamically allocate vars so changing MAX_ARGS and a recompile would be all that is needed. I have the bad habit to leave issues be until someone complains about it.
17 Mar, 2009, quixadhal wrote in the 12th comment:
Votes: 0
Scandum said:
So for 'correct' behavior you'd probably want to change \n to \v. Linux telnet however doesn't do this, so this creates a bit of a paradox because Linux to a degree defines the standard.


A vertical tab is NOT the same as a line feed. The \v token (ASCII 11) does the same thing with vertical space that \t (ASCII 9) does with horizontal space. On the particular terminal (or emulator) you're using, this *MIGHT* equate to moving down one line, however it is NOT guarenteed nor required… any more than it's required for a horizontal tab to be 8 spaces.

I agree that telnet is obsolete. However, as long as the community insists on clinging to it as the method to connect clients to their servers, I would argue that it should be followed as correctly as possible. If a custom client is an acceptable solution, then do what you will with that client, but don't bastardize telnet and then claim you're using it.
17 Mar, 2009, Guest wrote in the 13th comment:
Votes: 0
So if telnet is obsolete, what superseded it and why isn't anyone lobbying for MUD servers and codebases to use that instead? :)
17 Mar, 2009, Scandum wrote in the 14th comment:
Votes: 0
Looks like you'd have to use VT100 and send \eD for a line feed, and \eE for a new line. But once again, I think it's silly to actually implement this when Linux telnet does not translate \n to \eD.
17 Mar, 2009, Scandum wrote in the 15th comment:
Votes: 0
Samson said:
So if telnet is obsolete, what superseded it and why isn't anyone lobbying for MUD servers and codebases to use that instead? :)

SSH superseded it around 1999 or so?
17 Mar, 2009, Guest wrote in the 16th comment:
Votes: 0
So we're arguing obsolescence solely on the basis of it being non-secure?
17 Mar, 2009, Tyche wrote in the 17th comment:
Votes: 0
I'm not sure best practices is important. I don't think it makes a difference whether a package uses Y/N or 1/0 or true false to indicate boolean value, nor what it uses for newlines.

I'm having trouble with zmp.check. What possible use is there for checking for a package when the specification says respond affirmatively when ANY command in that package is implemented? An affirmative response is still inconclusive.
17 Mar, 2009, elanthis wrote in the 18th comment:
Votes: 0
I think it's important only because of consistency. It is a pain in the ass to have to keep checking whether this particular command used Y/N or this other command used 1/0. We can't actually _stop_ them from doing so because ZMP doesn't serialize actual types. I just figured it'd be nice to say "if you're going to use a boolean value, you should use this, so we're all on the same page." If they use something else anyhow, well, alright then.

Checking for packages is pretty pointless. If you're interested in a short cut to see if a package is implemented you could just check to see if any command in that package is implemented (and then hope the rest of the ones you need are too). I have no problem removing the package check feature. It would _greatly_ simplify the implementation of zmp.check.
17 Mar, 2009, Scandum wrote in the 19th comment:
Votes: 0
Samson said:
So we're arguing obsolescence solely on the basis of it being non-secure?

Not exactly, around 2001 I noticed the first Linux servers starting to block port 23 and requiring people to use ssh. That's what making telnet obsolete.
17 Mar, 2009, David Haley wrote in the 20th comment:
Votes: 0
Scandum said:
Not exactly, around 2001 I noticed the first Linux servers starting to block port 23 and requiring people to use ssh. That's what making telnet obsolete.

Big difference between the telnet protocol being obsolete in general, and people no longer using it for remote administration of servers over an untrusted network…!
0.0/54