Simple Proxy

Hi all,

This is my first post here, and if I have chosen the wrong spot, my
appologies.

I wish to make a simple proxy server. It will accept incoming
connections and then connect to a pre-defined foreign address/port.

It needs to transmit the information as it comes in, even if that is
character by character (or byte by byte) and does not necessarily
include line feeds, but if there is a large amount of data received, it
should transmit it again all at once, after the modifications.

I would like to modifying some of the information before passing it on.

I am new to ruby programming, but I have dealt with PHP, C++, and C#
pretty extensively. Unfortunately, network programming has never been
my thing.

I have come up with a few thoughts... Having the main thread accept the
incoming connection and create a new thread for the connection. that
thread would create a thread to handle user-to-server data and the
original thread would handle server-to-user data. If either sees a lost
connection, it would have to signal the other thread that it has
happened.

My concern on this approach is whether TCPSocket will freak out when
being read from 1 connection and written to by another, simultaneously.

I didn't see a way to use TCPSocket to check if data was present or not.
There were methods named 'nonblock' but the examples they showed looked
like they blocked anyhow. So I couldn't see a way to use just the
single thread to swap the data back and forth. (I can't imagine it's
not possible... Ruby is just too flexible to not have that.)

Or maybe there's some way that I haven't thought of?

I appreciate any input.

Thanks,

William

···

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

I would make a suggestion to check out the Event Machine library.

pth

···

On 8/17/06, William Crawford <wccrawford@gmail.com> wrote:

I wish to make a simple proxy server. It will accept incoming
connections and then connect to a pre-defined foreign address/port.

It needs to transmit the information as it comes in, even if that is
character by character (or byte by byte) and does not necessarily
include line feeds, but if there is a large amount of data received, it
should transmit it again all at once, after the modifications.

For a simple(?) pure-ruby HTTP proxy, you may have a look at MouseHole
(http://code.whytheluckystiff.net/mouseHole/\)

···

On 8/17/06, William Crawford <wccrawford@gmail.com> wrote:

Hi all,

This is my first post here, and if I have chosen the wrong spot, my
appologies.

I wish to make a simple proxy server. It will accept incoming
connections and then connect to a pre-defined foreign address/port.

It needs to transmit the information as it comes in, even if that is
character by character (or byte by byte) and does not necessarily
include line feeds, but if there is a large amount of data received, it
should transmit it again all at once, after the modifications.

I would like to modifying some of the information before passing it on.

I am new to ruby programming, but I have dealt with PHP, C++, and C#
pretty extensively. Unfortunately, network programming has never been
my thing.

I have come up with a few thoughts... Having the main thread accept the
incoming connection and create a new thread for the connection. that
thread would create a thread to handle user-to-server data and the
original thread would handle server-to-user data. If either sees a lost
connection, it would have to signal the other thread that it has
happened.

My concern on this approach is whether TCPSocket will freak out when
being read from 1 connection and written to by another, simultaneously.

I didn't see a way to use TCPSocket to check if data was present or not.
There were methods named 'nonblock' but the examples they showed looked
like they blocked anyhow. So I couldn't see a way to use just the
single thread to swap the data back and forth. (I can't imagine it's
not possible... Ruby is just too flexible to not have that.)

Or maybe there's some way that I haven't thought of?

I appreciate any input.

Thanks,

William

Patrick Hurley wrote:

I would make a suggestion to check out the Event Machine library.

pth

Took a minute to find it, but I found it here.
http://rubyforge.org/projects/eventmachine (in case anyone else cares)

This does indeed look like an awesome solution. Thanks!

···

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

What's funny about this is that I was just thinking the other other
day about how EventMachine needs to support TCP proxying
out-of-the-box. Depending on your requirements, this might be a good
excuse to do it.

Are you thinking about a simple passthrough proxy from one
address/port to another (possibly adding and/or subtracting SSL/TLS)?
O are you looking to do some protocol-specific transformations like
HTTP or SMTP proxying?

···

On 8/17/06, William Crawford <wccrawford@gmail.com> wrote:

Patrick Hurley wrote:
> I would make a suggestion to check out the Event Machine library.
>
> pth

Took a minute to find it, but I found it here.
http://rubyforge.org/projects/eventmachine (in case anyone else cares)

This does indeed look like an awesome solution. Thanks!

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

Francis Cianfrocca wrote:

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

What's funny about this is that I was just thinking the other other
day about how EventMachine needs to support TCP proxying
out-of-the-box. Depending on your requirements, this might be a good
excuse to do it.

Are you thinking about a simple passthrough proxy from one
address/port to another (possibly adding and/or subtracting SSL/TLS)?
O are you looking to do some protocol-specific transformations like
HTTP or SMTP proxying?

I hadn't planned to burden this group with all the details, but here we
go:

The input stream is from a MUD server (text-based multiplayer game) that
has 2 different proprietary formats and uses a seperate login server.

My 'proxy' will accept a connection from the user's mud client (or
telnet client, basically the same thing) and ask for their username and
password. It will then connect to the login server, hash the password,
submit it and pull a list of characters, which the user chooses, etc. A
login key is generated. And a game server is specified.

The proxy then drops the connection to the login server and connects to
the game server. Then sends the login key and then a line specifying
the front end being used. (this is the point that picks between the 2
protocols.)

The mud server then sends either a stream with unprintable characters
and various codes, mixed with the real output, or an XML-like stream.

I would then like to have the option of parsing either of these streams
and having the cleaned/transformed output be sent to the user.

This is a project that will be released under the BSD license and placed
on RubyForge, once I'm happy it's minimally working.

I appreciate the immediately interest, Francis. Especially if you can
make this stupidly easy for me!

I've already got the code working that handles the login server stuff.
(Well, minor details left.) It generates the proper info and I can log
into the mud server with a standard telnet client, with the info
provided.

BTW, the MUD in question (in case anyone has wondered) is DragonRealms,
and it's not free. :frowning: It makes up for that by being the best MUD I've
ever played. (I've quite and come back several times over about 8-10
years.) There is an Open Source Gnome client called Warlock, but every
other client is for Windows. (And I run KDE. Warlock displays its main
screen and then just crashes.) I -far- prefer a console-only client and
I plan to use Muby. (And probaby integrate the proxy solution I develop
as an add-on, but I also want a generic proxy for any client to use,
regardless of OS and client used.)

Feel free to contact me by email if you'd rather discuss it more
privately.

And thanks!

···

On 8/17/06, William Crawford <wccrawford@gmail.com> wrote:

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

That's not a simple proxy at all, but a quite complex little application!
You'll find you have to deal with a lot of little edges to get this to
production quality. When your "proxy" runs, will it be running on behalf of
just one client? Or many clients?

I think EventMachine can be effective for this application, especially since
it will wrap all the I/O and timing issues for you, but check out the
development version and look at the Deferrable class. Even though it's not
released, this code is stable and you will want it to simplify your access
to the login server.

If you need help designing this, let me know. It would be a pretty
interesting case study.

If the two MUD protocols are proprietary, then how do you know what you need
to know about them? Did you reverse-engineer them?

···

On 8/17/06, William Crawford <wccrawford@gmail.com> wrote:

I hadn't planned to burden this group with all the details, but here we
go:

The input stream is from a MUD server (text-based multiplayer game)
that...

Francis Cianfrocca wrote:

I hadn't planned to burden this group with all the details, but here we
go:

The input stream is from a MUD server (text-based multiplayer game)
that...

That's not a simple proxy at all, but a quite complex little
application!

Seemed pretty simple to me, hehe. The first version will simply do the
login and pass the exact data back and forth. From there, it's just a
matter of massaging the stream.

You'll find you have to deal with a lot of little edges to get this to
production quality. When your "proxy" runs, will it be running on behalf
of
just one client? Or many clients?

If you have multiple accounts, you can log in multiple times, so
multiple clients.

Also, eventually, I would like to modify the proxy so that multiple
clients can log in and get different views of the same stream. (Yikes!,
I know.)

I think EventMachine can be effective for this application, especially
since
it will wrap all the I/O and timing issues for you, but check out the
development version and look at the Deferrable class. Even though it's
not
released, this code is stable and you will want it to simplify your
access
to the login server.

Actually, my access to the login server is just a couple dozen lines of
code. I haven't implemented proper character choosing and stuff, but I
don't expect to have problems there.

If you need help designing this, let me know. It would be a pretty
interesting case study.

Thanks for the offer. I'm -not- network-programming-inclined... It has
always been tough to wrap my head around it, for some reason. Once I
get the streams passing info back and forth, I don't expect to have to
worry about the network stuff until I try to connect multiple clients to
the same stream. Heh. (Oh, and I'll want to use different filtering on
each output on that stream. Why think small?) But that's for later.

If the two MUD protocols are proprietary, then how do you know what you
need
to know about them? Did you reverse-engineer them?

Simutronics (the owners) contracted with Zuggsoft to make zMud
compatible, and announced at the same time that they had always intended
to release the specs for the protocols, but nobody ever found the time.
Using various sources around the net, I learned the login sequence and
the 'GSL Codes' are pretty well documented for version 1 of the stream.
The XML-like version of the stream is pretty obvious since they used tag
names that actually make sense. They have publicly (on their forum)
stated that they intended to release this information so that third
parties could create clients.

···

On 8/17/06, William Crawford <wccrawford@gmail.com> wrote:

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

Best of luck, send me private email if you need help.