Telnet Server in Ruby

Does anyone know of a Telnet Server written purely in Ruby? It doesn't
have to be fully featured. I just need a remote shell for control of an
application that I am working on. Telnet is the preferred method since
the users of the system are used to using Telnet for network application
control and allows simple scripting via a socket.

I thought about writing my own using GServer and IO.popen, but before
embark on that I wanted to avoid re-inventing the wheel.

Thanks in advance.

Dale Martenson

···

--
Posted with http://DevLists.com. Sign up and save your mailbox.

It's super easy to get something going with GServer, but my new favorite is actually EventMachine. I just built a server application with that library last week and it really rocks. Definitely look it over.

If all you need is bare bones Telnet handling you can use something like this:

     def parse_telnet(data) # minimal Telnet
       data.gsub!(/([^\015])\012/, "\\1") # ignore bare LFs
       data.gsub!(/\015\0/, "") # ignore bare CRs
       data.gsub!(/\0/, "") # ignore bare NULs

       while data.index("\377") # parse Telnet codes
         if data.sub!(/(^|[^\377])\377[\375\376](.)/, "\\1")
           # answer DOs and DON'Ts with WON'Ts
           send_data("\377\374#{$2}")
         elsif data.sub!(/(^|[^\377])\377[\373\374](.)/, "\\1")
           # answer WILLs and WON'Ts with DON'Ts
           send_data("\377\376#{$2}")
         elsif data.sub!(/(^|[^\377])\377\366/, "\\1")
           # answer "Are You There" codes
           send_data("Still here, yes.")
         elsif data.sub!(/(^|[^\377])\377\364/, "\\1")
           # do nothing - ignore IP Telnet codes
         elsif data.sub!(/(^|[^\377])\377[^\377]/, "\\1")
           # do nothing - ignore other Telnet codes
         elsif data.sub!(/\377\377/, "\377")
           # do nothing - handle escapes
         end
       end

       data
     end

Maybe you could expand that to meet your needs.

Hope that helps.

James Edward Gray II

···

On Jul 31, 2006, at 9:27 PM, Dale Martenson wrote:

I thought about writing my own using GServer and IO.popen, but before
embark on that I wanted to avoid re-inventing the wheel.

Does anyone know of a Telnet Server written purely in Ruby? It doesn't have to be fully featured. I just need a remote shell for control of an application that I am working on. Telnet is the preferred method since the users of the system are used to using Telnet for network application control and allows simple scripting via a socket.

I thought about writing my own using GServer and IO.popen, but before embark on that I wanted to avoid re-inventing the wheel.

Hi,

For what it's worth... I have some ANSI/VT100 telnet libraries that support
partitioning the display into horizontal scrolling regions, and some reasonably
full featured line-editing handling insert, delete, scrolling long lines, command
history, scrollback buffers with PgUp/PgDn, etc...

Part of this project:
http://rubyforge.org/cgi-bin/viewvc.cgi/dorkbuster/dbcore/?root=dorkbuster

The relevant files would be:
ansi.rb
ansi-term.rb
term-keys.rb
windowed-term.rb
line-edit.rb

On the plus side, they have unit tests. And on the plus side, each module
is relatively loosely coupled... On the downside, the lowest level module,
buffered-io.rb, uses kind of a weird approach I developed back under
ruby 1.6.8 when nonblocking I/O wasn't well-supported on win32 ruby,
and so buffered-io was an experiment that technically works (it runs over
thirty servers now, for years with no problems); but it's more
complicated than it needs to be.

These days, instead of buffered-io, I'd have likely started with something
something like the EventMachine library JEGII mentioned in his reply
on this thread.

But anyway, that said, ansi-term only relies on a few methods of
the buffered-io object passed into it, mainly #send_nonblock,
#recv_nonblock, and #recv_ready? ... hmm, also #eof, #peeraddr,
#wait_recv_ready, #flush ... It might not be _too_ hard to adapt.

Well ... anyway, maybe the code might be of some use, even if
it could take some massaging to fit into a different I/O model.

The license for the source files mentioned here is LGPL preferably,
or Ruby's license if LGPL won't work for you.

Hope this helps,

Bill

···

From: "Dale Martenson" <devlists-ruby-talk@devlists.com>

To both JEGII and Bill Kelly:

I'd really like to see a telnet server capability built into and shipped
with EM. Although there hasn't been a release lately (my fault, just
gotta do it), if you look into the SVN you'll see where things are
going. We've added thread-pools (for handling locally-blocking things
like database calls) and also a "Deferred" object that acts just like
the one in Twisted (you add arbitrary callbacks and errbacks to it). And
there is some structure in the source tree for adding specific
network-protocol handlers. That's where a telnet server would fit in.
Another possibility, possibly better, is to treat EM as a platform, and
then people can ship servers as separate packages, like RoR.

JEGII: may I use your code posted above to make a first attempt? I'll
come back to you with annoying questions if I have trouble, of course
;-).

Bill: ditto with your windowing libraries. EM is licensed under either
Ruby terms or LGPL so you would need to allow a relaxation of terms in
order for your stuff to be included. If that's not poss, then maybe it
could be an outboard library.

Thoughts from anyone?

···

--
Posted via http://www.ruby-forum.com/.

I will. It sounds like EventMachine maybe the best way to proceed.

Thanks,
Dale Martenson

···

On Tuesday, August 01, 2006, at 12:26 PM, James Edward Gray II wrote:

On Jul 31, 2006, at 9:27 PM, Dale Martenson wrote:

I thought about writing my own using GServer and IO.popen, but before
embark on that I wanted to avoid re-inventing the wheel.

It's super easy to get something going with GServer, but my new
favorite is actually EventMachine. I just built a server
application with that library last week and it really rocks.
Definitely look it over.

--
Posted with http://DevLists.com. Sign up and save your mailbox.

Fantastic. This is beyond my original intent, but since this is
available, I will look at utilizing what I can.

Thank you,
Dale Martenson

···

On Tuesday, August 01, 2006, at 2:11 PM, Bill Kelly wrote:

From: "Dale Martenson" <devlists-ruby-talk@devlists.com>

Does anyone know of a Telnet Server written purely in Ruby? It doesn't
have to be fully featured. I just need a remote shell for control of an
application that I am working on. Telnet is the preferred method since
the users of the system are used to using Telnet for network
application
control and allows simple scripting via a socket.

I thought about writing my own using GServer and IO.popen, but before
embark on that I wanted to avoid re-inventing the wheel.

Hi,

For what it's worth... I have some ANSI/VT100 telnet libraries that support
partitioning the display into horizontal scrolling regions, and some
reasonably
full featured line-editing handling insert, delete, scrolling long
lines, command
history, scrollback buffers with PgUp/PgDn, etc...

--
Posted with http://DevLists.com. Sign up and save your mailbox.

You can use whatever you like. Bill's stuff is much farther along though!

James Edward Gray II

···

On Aug 1, 2006, at 7:01 AM, Francis Cianfrocca wrote:

JEGII: may I use your code posted above to make a first attempt? I'll
come back to you with annoying questions if I have trouble, of course
;-).

Dale Martenson wrote:
> I will. It sounds like EventMachine maybe the best way to proceed.

If you go for it and need support, send me email (here or private).

···

--
Posted via http://www.ruby-forum.com/.

Bill: ditto with your windowing libraries. EM is licensed under either Ruby terms or LGPL so you would need to allow a relaxation of terms in order for your stuff to be included.

No problem!

As of now, consider them "Ruby or LGPL".

I'll make a pass through the source and add some sort of header at
the top of the files stating this.

Regards,

Bill

···

From: "Francis Cianfrocca" <garbagecat10@gmail.com>

Bill Kelly wrote:

From: "Francis Cianfrocca" <garbagecat10@gmail.com>

Bill: ditto with your windowing libraries. EM is licensed under either
Ruby terms or LGPL so you would need to allow a relaxation of terms in
order for your stuff to be included.

No problem!

As of now, consider them "Ruby or LGPL".

I'll make a pass through the source and add some sort of header at
the top of the files stating this.

Regards,

Bill

Thanks Bill. I took a look through your code and it's neat,
there's a lot of stuff there. When I get a moment I'll take a pass at
figuring out how to make it run under EM. Seems so far like I can get
away primarily with changes in ansi-term.rb for a start, then
windowed-term.rb later.

Can you give me a hello-world program that runs your code as a telnet
server, that can (for example) serve a remote login? I started figuring
it out from your test cases, but I figure you can rattle it off the top
of your head.

···

--
Posted via http://www.ruby-forum.com/\.

Can you give me a hello-world program that runs your code as a telnet
server, that can (for example) serve a remote login? I started figuring
it out from your test cases, but I figure you can rattle it off the top
of your head.

I've added a windowed-term-example.rb to the project:

http://rubyforge.org/cgi-bin/viewvc.cgi/dorkbuster/dbcore/windowed-term-example.rb?root=dorkbuster&view=co

It accepts clients, and partitions the client's window into three regions.
Lines of text can be entered into the bottom region, with line editing and
command history, and the data entered is echoed to all clients in the
middle region. PgUp/PgDn should scroll through that data in the middle
region as it accumulates. The top region gets a timestamp printed to it
every second or so.

NOTE: You'll need to put your telnet into character mode (mode ch)
before connecting. I know there must be a telnet escape sequence
I could send from the server to do that automatically, but, I didn't know
what it was.

Hope this helps,

Bill

···

From: "Francis Cianfrocca" <garbagecat10@gmail.com>