From oleg Wed Feb 1 09:11:48 CST 1995 Newsgroups: comp.lang.c++ Subject: async relaying of TCP packets by a Finite Automaton [small example] Summary: a small TCP classlib and Finite SM to async relay TCP packets Followup-To: Distribution: Organization: University of North Texas, Denton Keywords: signals, interrupt-driven i/o, C++ classlib, finite state machine Cc: Status: RO This is a primitive advanced (but working) code to relay TCP packets between two different computers (and/or ports). The "advanced" part is in using of a signal-driven i/o and finite state machines. The rest is primitive: the program listens on port Listen_port. After it got a connection, it connects itself to Target_host:Target_port, and, if everything goes well, the code relays packets between the two connections, keeping the log of all received/sent packets. After the connections are closed (normally or semi-normally) the program listens again. Possible applications of the program: relaying packets from one port to another (say, some netnazi sites, in a stupid attempt to prevent people from playing MUD, firewall all connections to "suspicious" ports, usually ones above 6000). So, one can run this program on some computer (outside the firewall) and have it take packets from some legitimate port, say, 25 or 119, and relay them to a "real" port, 9000 or so, on a MUD machine. Another possible application (which actually I had in mind writing this program) is to snoop on the protocol, say, get a "carbon copy" of the http chat between two hosts (it was rather revealing, btw). The feature of this program is an asynchronous (upon SIGIO) reading of communication channels. Most of the time the program sleeps (without taking of any CPU time) and wakes up only when some packet shows up in one of the channels. The code also contains a fairly complete class library for the TCP (stream) sockets. Another feature of the code is using a Finite State Machine to do relay and handle all possible special situations. The following TCP class hierarchy is implemented: IPaddress -> SocketAddr -> StreamSocket -> {Listen,ConnectingSocket} Name domain resolution, creating a socket, binding it and listening on are all done appropriately and transparently when those objects are constructed. So the classes above can save a few boring chores. The "advanced" features of the code are class methods as SIGIO signal handlers and method pointers in the Finite State machine "program" (as "actors" of a FSM step). Besides, the code is strewn with things like StreamSocket::ReadResult read_result = (id == id_sock1 ? sock1 : sock2).read(buffer,IO_buffer_size); (which I wrote in reminiscence of Algol-68 or ML). The code is posted to comp.sources.misc, and is also available from ftp://replicant.csci.unt.edu/pub/oleg/tcp_relay.shar Anyway, I hope it would be useful as a small illustration and/or example. In any case, I'll really try to answer any comment/question/problem (if any: please mail them to me at oleg@ponder.csci.unt.edu or oleg@unt.edu)