18 Mar, 2010, donky wrote in the 61st comment:
Votes: 0
KaVir said:
Scandum said:
Or the fourth, detect windows telnet and echo the input back to the user as they type.

I'd rather avoid character mode.

Some notes based on quick experimentation..

I am not sure whether character mode is defined as where the client sends characters as they are entered, and the server echos them back. Or whether it is just the client sending the characters as they are entered, rather than as the user hits enter. But during my experiments just now, Windows Telnet seems to engage in the latter by default.

Experiment 1: The goal was to verify the correctness of the claim that Windows Telnet will stop its local echoing when server-side negotiation is attempted. I removed all negotiation and connected, the client was echoing correctly. I added back TTYPE negotiation and connected, the client had stopped echoing. I replaced TTYPE negotiation and connected, the client also stopped echoing.

Conclusion 1: When a server negotiates with Windows Telnet, it does turn off local echo.

Experiment 2: The goal was to see whether a fix applied by the client's user was practical and what it involved. This would not be an ideal solution, but it would be one regardless. I enabled only TTYPE negotiation and connected. Then I entered the Windows Telnet settings screen by pressing "CTRL-]". I then typed "st" (short for status) and saw nothing about the localecho setting. So I typed "set localecho" which gave a statement that it was set. Exiting the settings screen and typing, Windows Telnet was now doing local echo again.

Conclusion 2: The user of Windows Telnet in this situation can fix the problem. Given that it is possible to detect Windows Telnet, a MUD could tell a connecting user "Hey, look, your client is not the best one, but you can use it here if you do this.."

Experiment 3: The goal was to see if it was possible for a server to negotiate Windows Telnet back to doing local echo. I enabled NAWS and on receiving its response, I send a DO ECHO. I waited for the response in case handling of other options at approximately the same time negated the DO ECHO request. Windows Telnet responded with WILL ECHO, but did not do local echo.

Conclusion 3: This is a bug in Windows Telnet. It may be there is another way to work around it, but it is non-obvious. This is a pretty bad bug, but overall I am extremely impressed by Windows Telnet and the level of support it has for things like escape sequences.

So the result of this, is that it looks like conclusion 2 is the only workable option. Is it possible to do it in a way that doesn't discourage users? I don't see why not.
18 Mar, 2010, Scandum wrote in the 62nd comment:
Votes: 0
Handling character mode is about as easy as it gets, whenever you receive input you echo it back to the terminal. It's slow and sucky, but beats having no echo at all.

Only need to handle backspace and return.
switch (d->inbuf[nSkip])
{
case 8:
case 127:
d->inbuf[nSkip] = '\b';
write(d->descriptor, "\b \b", 3); // handle backspace.
break;

case '\n':
write(d->descriptor, "\r\n", 2);
break;

default:
if (IS_SET(d->comm_flags, COMM_FLAG_PASSWORD))
{
write(d->descriptor, "*", 1);
}
else
{
write(d->descriptor, d->inbuf + nSkip, 1);
}
break;
}
19 Mar, 2010, donky wrote in the 63rd comment:
Votes: 0
donky said:
Experiment 3: The goal was to see if it was possible for a server to negotiate Windows Telnet back to doing local echo. I enabled NAWS and on receiving its response, I send a DO ECHO. I waited for the response in case handling of other options at approximately the same time negated the DO ECHO request. Windows Telnet responded with WILL ECHO, but did not do local echo.

Conclusion 3: This is a bug in Windows Telnet. It may be there is another way to work around it, but it is non-obvious. This is a pretty bad bug, but overall I am extremely impressed by Windows Telnet and the level of support it has for things like escape sequences.

Actually, my brain was switched off, this makes no sense as a possible solution as it is not what DO ECHO is for (as I understand it). I know it was switched off, because I just spent two hours disassembling Windows Telnet when I have better things to do.

Here's what's going on with Windows Telnet and local echo. When Windows Telnet connects to a server, its local echo setting is off. But it also has another flag which overrides the local echo setting which is set. When an IAC is encountered, the override flag is cleared.

Conclusion: Windows Telnet appears to be using negotiation as an indication of how it is being used. If there is no negotiation, you are probably connecting to something for debugging purposes and want to see what you type. If there is negotiation, then the server is expected to echo. This kind of makes sense, as when I telnet to a web server to manually type in commands, it is useful in that scenario.
20 Mar, 2010, Barm wrote in the 64th comment:
Votes: 0
donky said:
If there is negotiation, then the server is expected to echo.


When I first started playing with Telnet I was surprised that most clients defaulted to 'line mode' with local echo, given the UNIX origins of the protocol. Typically, a terminal or teletype would use local echo in half-duplex mode and remote echo in full-duplex mode. Maybe the Microsoft programmers just assumed no one would ever use half-duplex communications with a Windows box. Which makes sense, given that half-duplex modems were ancient history at the time they wrote it.
20 Mar, 2010, KaVir wrote in the 65th comment:
Votes: 0
KaVir said:
Perhaps the second and third options could be combined though - at the login screen where the user is given a list of options (create, load, who) there could be another command for switching off negotiation. Then when they create or load their character the negotiation could be performed, unless they'd previously chosen to switch it off.

This is the option I went for. You can now view client statistics here: http://www.godwars2.org/mwi/statistics

The stats are updated as players connect, so it may take a few days to get some solid numbers.

Thanks for the links and suggestions.

Now I'm thinking about using the data in the dynamic help files - might be useful for things like MSP, for example, as I could give client-specific installation instructions.
20 Mar, 2010, KaVir wrote in the 66th comment:
Votes: 0
Following the sequence described at the end of donky's link, I start out by sending "IAC DO TERMINAL-TYPE". If the client responds with "IAC WILL TERMINAL-TYPE" then I send "IAC SB TERMINAL-TYPE SEND IAC SE". If it returns with a terminal type, I record it. I don't care if it supports multiple terminal types right now, as I'm mostly just interested in dedicated mud clients such as MUSHclient, TINTIN++, CMUD, etc.

But it looks as if I may have missed something, or done something wrong. The results mostly seem to be okay, but there are some oddities:

Unknown: 298 (85.8%)
MUSHCLIENT: 15 (4.3%)
TINTIN++: 10 (2.8%)
DUMB: 4 (1.1%)
ZMUD: 4 (1.1%)
ANSI: 3 (0.8%)
CMUD: 3 (0.8%)
ALCLIENT: 2 (0.5%)
TMC: 2 (0.5%)
ANSI,VT100,DEC-VT100: 1 (0.2%)
ATLANTIS: 1 (0.2%)
CYGWIN: 1 (0.2%)
MUDGAMERS: 1 (0.2%)
MUDLET-1.1 1: (0.2%)
WINTIN.NET-2.10: 1 (0.2%)


The person using "ANSI,VT100,DEC-VT100" said he's using Monkey Term. Another person claiming to use the same client shows up as "Unknown".

Barm's link showed TinyFugue as returning "TINYFUGUE". One of my admin uses Linux TinyFugue, but his client shows up as "Unknown".

Another player told me that she alternates between CMUD and and MUSHclient, but my mud was unable to retrieve any printable characters from her client when it responded to negotiation - either it was blank or gibberish. When she quit and reconnected it fixed it though, so it was probably a bug at my end.
21 Mar, 2010, Barm wrote in the 67th comment:
Votes: 0
KaVir said:
Barm's link showed TinyFugue as returning "TINYFUGUE". One of my admin uses Linux TinyFugue, but his client shows up as "Unknown".


I tested it again. I have a Windows box with TinyFugue 5.0 that responds with "TINYFUGUE". My coding machine is running Ubuntu and has TinyFugue 4.0s1-17 which does not respond. I was running Fedora back when I made that list and I'd guess it probably had the 5.0 beta (which is dated 2007).
21 Mar, 2010, donky wrote in the 68th comment:
Votes: 0
Given our previous discussions, because negotiation in Windows Telnet had undesirable side-effects, I decided to look for other options for identifying clients and determining what was safe to use. There is other crap you can throw at a client to get a response back, the byte 5 for instance might result in an answerback string being displayed. And then there are escape sequences which might result in the server getting information back without the user knowing. For the purpose of these experiments, I disabled server-side negotiation effects.. the commands are simply queued as data for the duration of the client identification stage, should the client not be a passive negotiator. Another potential problem might be user input, like pre-emptive login name entry, but it should be possible for the server to only parse negotiation, escape sequences and expected answerback strings and buffer the rest for when this process is complete.

So, my first attempt was with "\x1bGiven our previous discussions, because negotiation in Windows Telnet had undesirable side-effects, I decided to look for other options for identifying clients and determining what was safe to use. There is other crap you can throw at a client to get a response back, the byte 5 for instance might result in an answerback string being displayed. And then there are escape sequences which might result in the server getting information back without the user knowing. For the purpose of these experiments, I disabled server-side negotiation effects.. the commands are simply queued as data for the duration of the client identification stage, should the client not be a passive negotiator. Another potential problem might be user input, like pre-emptive login name entry, but it should be possible for the server to only parse negotiation, escape sequences and expected answerback strings and buffer the rest for when this process is complete.

So, my first attempt was with "\x1b[0x". Windows Telnet responds with "\x1b[3;1;1;128;128;1;0x". Putty responds with "\x1b[2;1;1;112;112;1;0x", but it doesn't send it, instead displaying it as unsent line mode content. GMud simply displays the "\x1b[0x" with no response. It looks like using any escape sequences are out of the question, not just because GMud displays this one at least, but because Putty will display all of its responses. UNSUITABLE as a frontline client detection solution.

Another approach might be based around Putty responding to 5 with "PuTTY". So if other clients are happy ignoring 5, Putty can be detected, and worked around through that. GMud does not react to, or display this character. Neither does Windows Telnet. However, Putty operates in linemode by default and as with the escape sequences, places the answerback string in the line to be displayed to the user, and to be sent when they enter the current line. UNSUITABLE as a frontline client detection solution.

Now this reminds me, one thing Putty does do, is actively engage in negotiation. So regardless of whether I want them, it sends me:
[quote]WILL NAWS
WILL TERMINAL-SPEED
WILL TERMINAL-TYPE
WILL NEW-ENVIRON
DO ECHO
WILL SGA
DO SGA
[/quote]
This is a pretty good identifier. So that gives me a way to immediately identify Putty. I know I can then identify Windows Telnet through the response to "\x1b[0x", as it returns "\x1b[3;1;1;128;128;1;0x" rather than the correct response of "\x1b[2;1;1;128;128;1;0x". But I also know that GMud will display crap if I send this.

So given I can identify Putty by this stage, and avoid the following for it, I can try some other escape sequences. Another like "\x1b[0x" is "\x1b[0c". The expected response is an escape code, which varies depending on VT support. GMud ignores it and does not display junk characters. Windows Telnet responds with "\x1b[?1;0c". So now I have a way of identifying non-Putty, non-GMud clients which include Windows Telnet. Ideally at this point I would send "\x1b[0x" and process the response in order to specifically identify Windows Telnet. But for it to be safe, I think more clients need to be put through this process to be sure junk characters are not displayed.
21 Mar, 2010, Scandum wrote in the 69th comment:
Votes: 0
Think I mentioned this before, but you can use NEW ENVIRON and request SYSTEMTYPE to uniquely identify windows telnet. Should be possible to use it to detect other clients as well.
21 Mar, 2010, donky wrote in the 70th comment:
Votes: 0
Scandum said:
Think I mentioned this before, but you can use NEW ENVIRON and request SYSTEMTYPE to uniquely identify windows telnet. Should be possible to use it to detect other clients as well.

Yeah, you did. But the problem with that, is that it disables the client-side echoing, as Kavir pointed out. So if this is important to the MUD server developer, then a way to indentify what client is, or just as good - is not, being used.. without negotiating is useful.
60.0/70