// -*- c++ -*- //------------------------------------------------------------------------------ // $Id: echoxdr_tests.cpp,v 1.8 2006/07/20 02:30:55 vlg Exp $ //------------------------------------------------------------------------------ // // Copyright (c) 1999,2005 by Vladislav Grinchenko // // Permission to use, copy, modify, and distribute this software // and its documentation for any purpose and without fee is hereby // granted, provided that the above copyright notice appear in all // copies. The author makes no representations about the suitability // of this software for any purpose. It is provided "as is" without // express or implied warranty. // //------------------------------------------------------------------------------ // Date: June 12, 1999 //------------------------------------------------------------------------------ static const char help_msg[]= " \n" " NAME: \n" " \n" " echoxdr \n" " \n" " DESCRIPTION: \n" " \n" " Server-side of the test program for IPv4Socket class. Tests \n" " basic types XDR-encoded transmission. They are: \n" " CHAR, SHORT, INT, UINT, LONG, ULONG, FLOAT, DOUBLE. \n" " See client-side is 'echoxdr_testc' for further details. \n" " \n" " USAGE: \n" " \n" " shell> echoxdr_tests [OPTIONS] \n" " \n" " OPTIONS: \n" " \n" " -b, --daemon - run process as true UNIX daemon \n" " -d, --log-stdout - write debug to standard output \n" " -D, --log-file NAME - write debug to NAME file \n" " -h, --help - print this message \n" " -m, --mask MASK - mask (default: ALL = 0x7fffffff) \n" " -p, --port NAME - tcp/ip port NAME (default - procname) \n" " -v, --version - print version number \n" " -z, --log-size NUM - maximum size debug file can reach (dflt: 10Mb) \n" " \n"; //------------------------------------------------------------------------------ #if !defined (WIN32) #include #include #include using std::string; #include "assa/GenServer.h" #include "assa/Singleton.h" #include "assa/INETAddress.h" #include "assa/IPv4Socket.h" #include "assa/Reactor.h" #include "assa/ServiceHandler.h" #include "assa/Acceptor.h" using namespace ASSA; class EchoProcessor : public ServiceHandler { public: enum { CHAR, STRING, SHORT, INT, UINT, LONG, ULONG, FLOAT, DOUBLE, EOT }; EchoProcessor (IPv4Socket* s_) : ServiceHandler (s_), m_count (0) { // Called by Acceptor upon creation. trace("EchoProcessor::EchoProcessor"); } int handle_close (int /* fd */) { // Called by Reactor when client drops // connection. trace("EchoProcessor::handle_close"); delete (this); return 0; } int open (void); // Called by Acceptor when new client // connection is established. int handle_read (int fd); // Called by Reactor when data from client // arrives. private: int m_count; }; /******************************************************************************* Class EchoXdr *******************************************************************************/ class EchoXdr : public GenServer, public Singleton { public: EchoXdr () { /* no-op */ } void init_service () { m_acc = new Acceptor (&m_reactor); string port = get_port (); INETAddress la (port.c_str()); // listening port Assure_exit (!la.bad ()); Assure_exit (m_acc->open (la) == 0); } void process_events () { while (service_is_active ()) { m_reactor.waitForEvents (); } } private: Acceptor* m_acc; }; ASSA_DECL_SINGLETON(EchoXdr); #define ECHOXDR EchoXdr::get_instance() #define REACTOR ECHOXDR->get_reactor() /******************************************************************************* Member functions *******************************************************************************/ int EchoProcessor:: open (void) { trace("EchoProcessor::open"); IPv4Socket& s = *this; REACTOR->registerIOHandler (this, s.getHandler (), READ_EVENT); return 0; } int EchoProcessor:: handle_read (int fd_) { trace("EchoProcessor::handle_read"); DL((APP,"--------------------\n")); IPv4Socket& stream = *this; if (stream.getHandler () != fd_) return -1; switch (m_count++) { case CHAR: { char c; stream >> c; stream << c << flush; DL((TRACE,"char: %c\n", c)); break; } case STRING: { std::string s; stream >> s; stream << s << flush; DL((TRACE,"string: \"%s\"\n", s.c_str ())); break; } case SHORT: { short sh; stream >> sh; stream << sh << flush; DL((TRACE,"short int: %d\n", sh)); break; } case INT: { int i; stream >> i; stream << i << flush; DL((TRACE,"int: %d\n", i)); break; } case UINT: { u_int ui; stream >> ui; stream << ui << flush; DL((TRACE,"u_int: %d\n", ui)); break; } case LONG: { long l; stream >> l; stream << l << flush; DL((TRACE,"long: %d\n", l)); break; } case ULONG: { u_long ul; stream >> ul; stream << ul << flush; DL((TRACE,"u_long: %d\n", ul)); break; } case FLOAT: { float f; stream >> f; stream << f << flush; DL((TRACE,"float: %f\n", f)); break; } case DOUBLE: { double d; stream >> d; stream << d << flush; DL((TRACE,"double: %f\n", d)); break; } } // switch () if (m_count >= EOT) { m_count = 0; } return BYTES_LEFT_IN_SOCKBUF(stream); } #endif /* !defined WIN32 */ int main (int argc, char* argv[]) { #if !defined (WIN32) trace("echoxdr_tests"); int Revision = 0; ECHOXDR->set_version ("1.1", Revision); ECHOXDR->set_author ("Vladislav Grinchenko"); ECHOXDR->set_flags (GenServer::RMLOG); ECHOXDR->init (&argc, argv, help_msg); ECHOXDR->init_service (); ECHOXDR->process_events (); #endif /* !defined WIN32 */ return 0; }