Okay, here's the background:
There's this chat room called CyanChat, which is run by Cyan Worlds, for the fans of their games (Myst, Riven, etc) to chat with each other.
The CyanChat server (nicknamed Cho, as it runs at cho.cyan.com) is very picky about packets you send it, and if you send it just one bad command, you get banned for 24 hours; the second offense is a permanent ban.
Cyan released their protocol specification for developers. The main port that Cho uses is 1812, but 1813 is the debug port, in which the server is tolerant of bad commands.
A while back, I programmed a Perl module called Net::CyanChat, which interfaces with Cho and it plays nice with it for the most part. I've never managed to get myself accidentally banned by sending bad commands. Net::CyanChat uses IO::Socket to deal with all the socket stuff.
I also went on to write a program called "Perl CyanChat Client", which is a Perl/Tk client for chatting on CC, which uses Net::CyanChat.
The Diagnosis
I've used my Perl CC Client quite frequently for months and never had a problem with it. I've had other users use it too.
Today one of my users said they got "randomly banned" from CyanChat, and when they e-mailed the chat admin about it, he said something about them sending bad end-of-line characters in one of the packets.
Up to this point, Net::CyanChat had simply been sending \n as the end-of-line character, and its been working fine for everybody, but this one incident somebody got banned because the server freaked out over it.
Another member of the chat was programming his own CC client in C#, and he said that his client sent CrLf as the end-of-lines (\r\n), and that my client should be sending those too. So, I decided to make that change in Net::CyanChat.
While I was at it, I decided I'd also dust off my old Net::CyanChat::Server module, which implemented a CC server following the CC protocol specs. Now, this is where things get weird...
Using only Line Feeds
Before I started editing, Net::CyanChat sent \n after each packet, and Net::CyanChat::Server sent only \n after each packet as well. The two modules could connect to eachother and trade data just fine.
When I changed them both over to use \r\n... this is where things messed up.
Using Carriage Returns + Line Feeds
For a quick overview of a couple of CC's commands...
So, when I called (from the client)...
The server saw, in two different messages...
The server and client both chomp() incoming packets, which takes care of the \n. However, for some reason the server was receiving the \r on its own packet, which was giving me all kinds of warnings.
On the CC protocol, the commands are numeric, so I use numeric eq == on them, and the warnings were because I was doing an == on "\r" which isn't a number.
Likewise, when the server would send to the client...
Perl CyanChat Client would show an "\x{d}" in the Who List, which is because it saw the "\r" and my Perl Tk install on Linux doesn't handle unicode.
So... when the two send \r\n's to eachother, the receiving end sees the \r's
So now I got back to thinking, maybe the official CyanChat server sees the \r's as well? And maybe I was actually right all along in sending \n to the server, because sending \r\n would make the server flip out because of the \r, and ban the client?
I really hate working at this kind of low level in which I have to be so careful about end-of-line characters, but I'm hoping somebody can shed some light onto this.
Does IO::Socket have some kind of special way of handling this, to where sending "\n" gets converted into a friendly "\r\n" for me automatically? I've never had any problems with end-of-lines with other servers before. Should I not even worry about \r\n and just use \n anyway?
Any insight into this would be appreciated.
-------------
Cuvou.com | The NEW Kirsle.net
There's this chat room called CyanChat, which is run by Cyan Worlds, for the fans of their games (Myst, Riven, etc) to chat with each other.
The CyanChat server (nicknamed Cho, as it runs at cho.cyan.com) is very picky about packets you send it, and if you send it just one bad command, you get banned for 24 hours; the second offense is a permanent ban.
Cyan released their protocol specification for developers. The main port that Cho uses is 1812, but 1813 is the debug port, in which the server is tolerant of bad commands.
A while back, I programmed a Perl module called Net::CyanChat, which interfaces with Cho and it plays nice with it for the most part. I've never managed to get myself accidentally banned by sending bad commands. Net::CyanChat uses IO::Socket to deal with all the socket stuff.
I also went on to write a program called "Perl CyanChat Client", which is a Perl/Tk client for chatting on CC, which uses Net::CyanChat.
The Diagnosis
I've used my Perl CC Client quite frequently for months and never had a problem with it. I've had other users use it too.
Today one of my users said they got "randomly banned" from CyanChat, and when they e-mailed the chat admin about it, he said something about them sending bad end-of-line characters in one of the packets.
Up to this point, Net::CyanChat had simply been sending \n as the end-of-line character, and its been working fine for everybody, but this one incident somebody got banned because the server freaked out over it.
Another member of the chat was programming his own CC client in C#, and he said that his client sent CrLf as the end-of-lines (\r\n), and that my client should be sending those too. So, I decided to make that change in Net::CyanChat.
While I was at it, I decided I'd also dust off my old Net::CyanChat::Server module, which implemented a CC server following the CC protocol specs. Now, this is where things get weird...
Using only Line Feeds
Before I started editing, Net::CyanChat sent \n after each packet, and Net::CyanChat::Server sent only \n after each packet as well. The two modules could connect to eachother and trade data just fine.
When I changed them both over to use \r\n... this is where things messed up.
Using Carriage Returns + Line Feeds
For a quick overview of a couple of CC's commands...
Code:
Client-to-Server Commands
=========================
10|nickname
Sends your nick to the server to enter the chat
Server-to-Client Commands
=========================
35|user,address|user,address|...|user,address
The server is sending the "Who's Online" list, with each user's mangled IP address
So, when I called (from the client)...
Code:
$sock->send ("10|Kirsle\r\n");
The server saw, in two different messages...
Code:
1 10|Kirsle\n
2 \r
The server and client both chomp() incoming packets, which takes care of the \n. However, for some reason the server was receiving the \r on its own packet, which was giving me all kinds of warnings.
On the CC protocol, the commands are numeric, so I use numeric eq == on them, and the warnings were because I was doing an == on "\r" which isn't a number.
Likewise, when the server would send to the client...
Code:
$sock->send ("35|\r\n"); # because no users are online...
Perl CyanChat Client would show an "\x{d}" in the Who List, which is because it saw the "\r" and my Perl Tk install on Linux doesn't handle unicode.
So... when the two send \r\n's to eachother, the receiving end sees the \r's
So now I got back to thinking, maybe the official CyanChat server sees the \r's as well? And maybe I was actually right all along in sending \n to the server, because sending \r\n would make the server flip out because of the \r, and ban the client?
I really hate working at this kind of low level in which I have to be so careful about end-of-line characters, but I'm hoping somebody can shed some light onto this.
Does IO::Socket have some kind of special way of handling this, to where sending "\n" gets converted into a friendly "\r\n" for me automatically? I've never had any problems with end-of-lines with other servers before. Should I not even worry about \r\n and just use \n anyway?
Any insight into this would be appreciated.
-------------
Cuvou.com | The NEW Kirsle.net