olib 1.0.1 -- a simple set of re-useable c++ objects Copyright/General Information ----------------------------- Copyright 1998 Kyle R. Burton, All Rights Reserved Email: email@example.com Web: http://www.voicenet.com/~mortis/tcp_server This package can be freely distributed and used under the terms of the GNU General Public License, either version 2 or (at your opinion) any later version. See the file COPYING or see http://www.gnu.org/ for more detains on the GNU project. Send all comments and suggestions to the author: Kyle R. Burton firstname.lastname@example.org (I'd love to know if/how you're using this code) The most recent version(s) can currently be obtained from: http://www.voicenet.com/~mortis/projects/tcp_server Synopsis -------- This is just a set of small, mostly template based, generic C++ objects. This program provides a server that listens on a tcp socket, takes the first line of input from the client connection, and execs a predefined process to handle the connection. It ties the input/output of the handler process to the socket. This makes writing the handler processes extrememly simple -- all they need to do is read from standard in, and write to standard out. This even allows you to use anything that can use stdin/stdout to handle the connections, this includes: shell scripts, perl, python, lisp, C, C++, pascal, assembler, basic, expect, fortran, and just about any other programming language you can think of. Building the software --------------------- First off, you'll need to get my library: o'lib. You can get it from: http://www.voicenet.com/~mortis/projects/lib. Untar it into it's own directory. The best way to do this is at the same directory level that you put tcp_sever at. If you unarchive tcp_server in a directory /stuff, you'll end up with /stuff/tcp_server, unarchive olib in the same place, so you end up with /stuff/olib. All the code should be pretty much platform independant. I've just started using autoconf (the thing that creates the configure script), so it may or may not be what you expect. You'll have to have olib built before you try to run the configure script for tcp_server. The configure script looks for olib in '../olib'. If olib is not in '../olib' (e.g. it's in olib-1.0.1 because that's where it untarred to), you can set the following two enviornment variables: [mortis@warhammer tcp_server-1.0.1]$ export USER_OLIB_HEADERS=/home/mortis/projects/olib-1.0.1/include [mortis@warhammer tcp_server-1.0.1]$ export USER_OLIB_LIB=/home/mortis/projects/olib-1.0.1/src If all this stuff is set up, then just run configure, and then make. [mortis@warhammer tcp_server-1.0.1]$ ./configure [mortis@warhammer tcp_server-1.0.1]$ make To test it, you can cd into the test directory, and run it like this: [mortis@warhammer test]$ ../src/tcp_server Then from another terminal, telnet to the machine on port 4137, and type test_server and hit enter. The test server is a perl script that just echo's back whatever you send it - line by line. The only exception is a line that starts with quit, which causes it to exit. By defualt, there should be alot of output from the server. Oh, something else to keep in mind is that the default conf file restricts client connections to the local machine. Writing a Protocol Handler -------------------------- Just make something that reads from stdin, and writes to stdout! You should need to write exactly zero lines of socket code. See echo.pl for a simple example. Please be aware that there are a plethora of dangerous things you can do with this code. Special care should be taken when writing protocol handlers, as small mistakes could cause severe security issues with the machine you're running it on. Remember, there is no warranty with this software, all use is at YOUR OWN risk. The three standard file descriptors stdin - filedes 0 stdout - filedes 1 stderr - filedes 2 should all be bound to the socket by the time your handler starts. Problems/General Issues ---------------------------- Q: Why won't tcp_server/olib compile under compiler X? A: I've only tested it under the egcs version of g++: egcs-2.90.27 under linux, and aCC under HP-UX,. From what I know of using some other compilers (like g++ v2.7.2) is that they lack the ability to properly generate the specializations for the template code. Q: Why does the bind step always fail for ports < 1024? A: You need to be root to run a process that binds to a port less than 1024. This is a restriction imposed by most operating systems, and is for security reasons. tcp_server is not necessarily in and of itself insecure, but I wouldn't personaly run it on any of the standard ports... Q: Why does tcp_server fail with a message like "can't rebind to port WXYZ" during a restart after I kill it? A: There are 2 possible things happening here: 1 - if a client is still connected to the server, _or_ if the process forked() by the server doesn't exit, then the socket will never get closed. If this happens, then according to the IP stack, there is still something listening on the port in question. 2 - This behaviour has been observed under HP-UX. Something about the IP stack on HP doesn't free the port. I've never really investigated this issue on HP. If I wait a few minutes before trying to re-use the same port, HP seems fine. I'd appricate hearing any other input anyone has. Thanks to: email@example.com for helping me flesh this question out. Changes/Revisions ----------------- Sat Jan 2 21:08:47 EST 1999 1.0.2 - applied patch submitted by Kevin <firstname.lastname@example.org> to src/c_socket.cc and test/test.cc that fixed broken compiles on earlier versions of g++ than mentioned above. Mon Mar 29 09:53:37 EST 1999 1.0.4-SunOS - this version has 1 minor bug fix to c_socket::get_line(), and porting changes for SunOS. For now, the detection of SunOS isn't automatic via configure, so to get it to compile properly for SunOS, you'll have to add -D_SUN_OS to the CCFLAGS in the generated make file(s). When I've got time (and learn how to do it correctly), I'll merge these into the normal configure script. The bug in get_line() caused it to overrun the read buffer - it wasn't paying attention to the size that was passed in correctly.