diff options
Diffstat (limited to 'ACE/examples/Logger/simple-server')
8 files changed, 580 insertions, 0 deletions
diff --git a/ACE/examples/Logger/simple-server/Logger_Simple_Server.mpc b/ACE/examples/Logger/simple-server/Logger_Simple_Server.mpc new file mode 100644 index 00000000000..1e4d8240e38 --- /dev/null +++ b/ACE/examples/Logger/simple-server/Logger_Simple_Server.mpc @@ -0,0 +1,6 @@ +// -*- MPC -*- +// $Id$ + +project : aceexe { + exename = server_loggerd +}
\ No newline at end of file diff --git a/ACE/examples/Logger/simple-server/Logging_Acceptor.cpp b/ACE/examples/Logger/simple-server/Logging_Acceptor.cpp new file mode 100644 index 00000000000..7e5e0d0075c --- /dev/null +++ b/ACE/examples/Logger/simple-server/Logging_Acceptor.cpp @@ -0,0 +1,85 @@ +// $Id$ + +#include "ace/WFMO_Reactor.h" +#include "ace/Log_Msg.h" + +#include "Logging_Acceptor.h" +#include "Logging_Handler.h" +#include "Reactor_Singleton.h" + +ACE_RCSID(simple_server, Logging_Acceptor, "$Id$") + +// Initialize peer_acceptor object. + +int +Logging_Acceptor::open (const ACE_INET_Addr &addr) +{ + // Reuse addr if already in use. + if (this->peer_acceptor_.open (addr, 1) == -1) + return -1; + else + return 0; +} + +// Default constructor. + +Logging_Acceptor::Logging_Acceptor (void) +{ +} + +// Performs termination activities. + +int +Logging_Acceptor::handle_close (ACE_HANDLE, ACE_Reactor_Mask) +{ + this->peer_acceptor_.close (); + // Note, this object MUST be allocated dynamically! + delete this; + return 0; +} + +Logging_Acceptor::~Logging_Acceptor (void) +{ +} + +// Returns underlying device descriptor. + +ACE_HANDLE +Logging_Acceptor::get_handle (void) const +{ + return this->peer_acceptor_.get_handle (); +} + +// Accepts connections from client and registers new object with the +// ACE_Reactor. + +int +Logging_Acceptor::handle_input (ACE_HANDLE) +{ + Logging_Handler *svc_handler; + + ACE_NEW_RETURN (svc_handler, Logging_Handler, -1); + + // Accept the connection from a client client daemon. + + // Try to find out if the implementation of the reactor that we are + // using requires us to reset the event association for the newly + // created handle. This is because the newly created handle will + // inherit the properties of the listen handle, including its event + // associations. + int reset_new_handle = this->reactor ()->uses_event_associations (); + + if (this->peer_acceptor_.accept (svc_handler->peer (), // stream + 0, // remote address + 0, // timeout + 1, // restart + reset_new_handle // reset new handler + ) == -1 + || svc_handler->open () == -1) + { + svc_handler->close (); + ACE_ERROR_RETURN ((LM_ERROR, "%p", "accept/open failed"), -1); + } + + return 0; +} diff --git a/ACE/examples/Logger/simple-server/Logging_Acceptor.h b/ACE/examples/Logger/simple-server/Logging_Acceptor.h new file mode 100644 index 00000000000..0424a7c3889 --- /dev/null +++ b/ACE/examples/Logger/simple-server/Logging_Acceptor.h @@ -0,0 +1,59 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// examples +// +// = FILENAME +// Logging_Acceptor.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#ifndef _CLIENT_ACCEPTOR_H +#define _CLIENT_ACCEPTOR_H + +#include "ace/SOCK_Acceptor.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Event_Handler.h" + +class Logging_Acceptor : public ACE_Event_Handler + // = TITLE + // Handle connection requests from remote client clients. + // + // = DESCRIPTION + // Accepts client connection requests, creates Logging_Handler's + // to process them, and registers these Handlers with the + // ACE_Reactor Singleton. +{ +friend class Logging_Handler; +public: + Logging_Acceptor (void); + // Constructor. + + int open (const ACE_INET_Addr &a); + // Initialization. + +private: + // = Demuxing hooks. + virtual int handle_input (ACE_HANDLE); + virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask); + virtual ACE_HANDLE get_handle (void) const; + + ~Logging_Acceptor (void); + // By making this private we ensure that the <Logging_Acceptor> is + // allocated dynamically. + + ACE_SOCK_Acceptor peer_acceptor_; + // Passive connection acceptor factory. +}; + +#endif /* _CLIENT_ACCEPTOR_H */ diff --git a/ACE/examples/Logger/simple-server/Logging_Handler.cpp b/ACE/examples/Logger/simple-server/Logging_Handler.cpp new file mode 100644 index 00000000000..aacad00c3f1 --- /dev/null +++ b/ACE/examples/Logger/simple-server/Logging_Handler.cpp @@ -0,0 +1,202 @@ +// $Id$ + +#include "ace/Log_Msg.h" +#include "ace/Message_Block.h" +#include "ace/Log_Record.h" +#include "ace/OS_NS_string.h" +#include "ace/CDR_Stream.h" +#include "ace/Auto_Ptr.h" + +#include "Logging_Handler.h" +#include "Reactor_Singleton.h" + +ACE_RCSID(simple_server, Logging_Handler, "$Id$") + +// Default constructor. + +Logging_Handler::Logging_Handler (void) +{ +} + +Logging_Handler::~Logging_Handler (void) +{ + // Make sure there are no timers. + REACTOR::instance ()->cancel_timer (this); + + this->cli_stream_.close (); +} + +// Extract the underlying ACE_SOCK_Stream (e.g., for purposes of +// accept()). + +ACE_SOCK_Stream & +Logging_Handler::peer (void) +{ + return this->cli_stream_; +} + +int +Logging_Handler::handle_timeout (const ACE_Time_Value &, + const void *arg) +{ +#if defined (ACE_NDEBUG) + ACE_UNUSED_ARG (arg); +#endif /* ACE_NDEBUG */ + + ACE_ASSERT (arg == this); + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) handling timeout from this = %@\n"), + this)); + return 0; +} + +// Perform the logging record receive. + +int +Logging_Handler::handle_input (ACE_HANDLE) +{ + ACE_Log_Record log_record; + + // We need to use the old two-read trick here since TCP sockets + // don't support framing natively. Allocate a message block for the + // payload; initially at least large enough to hold the header, but + // needs some room for alignment. + ACE_Message_Block *payload_p = 0; + ACE_Message_Block *header_p = 0; + ACE_NEW_RETURN (header_p, + ACE_Message_Block (ACE_DEFAULT_CDR_BUFSIZE), + -1); + + auto_ptr <ACE_Message_Block> header (header_p); + + // Align the Message Block for a CDR stream + ACE_CDR::mb_align (header.get ()); + + ACE_CDR::Boolean byte_order; + ACE_CDR::ULong length; + + ssize_t count = ACE::recv_n (this->peer ().get_handle (), + header->wr_ptr (), + 8); + switch (count) + { + // Handle shutdown and error cases. + default: + case -1: + case 0: + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("server logging daemon closing down\n"))); + + return -1; + /* NOTREACHED */ + + case 8: + // Just fall through in this case.. + break; + } + + header->wr_ptr (8); // Reflect addition of 8 bytes. + + // Create a CDR stream to parse the 8-byte header. + ACE_InputCDR header_cdr (header.get ()); + + // Extract the byte-order and use helper methods to disambiguate + // octet, booleans, and chars. + header_cdr >> ACE_InputCDR::to_boolean (byte_order); + + // Set the byte-order on the stream... + header_cdr.reset_byte_order (byte_order); + + // Extract the length + header_cdr >> length; + + ACE_NEW_RETURN (payload_p, + ACE_Message_Block (length), + -1); + auto_ptr <ACE_Message_Block> payload (payload_p); + + // Ensure there's sufficient room for log record payload. + ACE_CDR::grow (payload.get (), 8 + ACE_CDR::MAX_ALIGNMENT + length); + + // Use <recv_n> to obtain the contents. + if (ACE::recv_n (this->peer ().get_handle (), + payload->wr_ptr (), + length) <= 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("recv_n()"))); + return -1; + } + + payload->wr_ptr (length); // Reflect additional bytes + + ACE_InputCDR payload_cdr (payload.get ()); + payload_cdr.reset_byte_order (byte_order); + payload_cdr >> log_record; // Finally extract the <ACE_log_record>. + + log_record.length (length); + + log_record.print (ACE_TEXT_CHAR_TO_TCHAR (this->host_name_), 1, stderr); + + return 0; +} + +// Extract underlying device descriptor. + +ACE_HANDLE +Logging_Handler::get_handle (void) const +{ + return this->cli_stream_.get_handle (); +} + +int +Logging_Handler::open (void) +{ + ACE_INET_Addr addr; + + if (this->cli_stream_.get_remote_addr (addr) == -1) + return -1; + else + { + ACE_OS::strncpy (this->host_name_, + addr.get_host_name (), + MAXHOSTNAMELEN + 1); + + if (REACTOR::instance ()->register_handler (this, READ_MASK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) can't register with reactor\n")), + -1); + else if (REACTOR::instance ()->schedule_timer + (this, (const void *) this, + ACE_Time_Value (2), + ACE_Time_Value (2)) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) can't register with reactor\n")), + -1); + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) connected with %C\n"), + this->host_name_)); + return 0; + } +} + +// Perform termination activities when deregistered from the +// ACE_Reactor. + +int +Logging_Handler::handle_close (ACE_HANDLE, ACE_Reactor_Mask) +{ + // Must have been allocated dynamically + delete this; + return 0; +} + +// Perform termination activities when close fails. + +int +Logging_Handler::close (void) +{ + return this->handle_close (); +} diff --git a/ACE/examples/Logger/simple-server/Logging_Handler.h b/ACE/examples/Logger/simple-server/Logging_Handler.h new file mode 100644 index 00000000000..633e04a167c --- /dev/null +++ b/ACE/examples/Logger/simple-server/Logging_Handler.h @@ -0,0 +1,71 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// examples +// +// = FILENAME +// Logging_Handler.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#ifndef _CLIENT_HANDLER_H +#define _CLIENT_HANDLER_H + +#include "ace/Event_Handler.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/INET_Addr.h" +#include "ace/SOCK_Stream.h" +#include "ace/os_include/os_netdb.h" + +class Logging_Handler : public ACE_Event_Handler + // = TITLE + // Receive client message from the remote clients. + // + // = DESCRIPTION + // This class demonstrates how to receive messages from remote + // clients using the notification mechanisms in the + // <ACE_Reactor>. In addition, it also illustrates how to + // utilize the <ACE_Reactor> timer mechanisms, as well. +{ +public: + Logging_Handler (void); + + // = Hooks for opening and closing handlers. + virtual int open (void); + virtual int close (void); + + ACE_SOCK_Stream &peer (void); + // Conversion operators. + +protected: + // = Demultiplexing hooks. + virtual ACE_HANDLE get_handle (void) const; + virtual int handle_input (ACE_HANDLE); + virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, + ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); + virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg); + + // = Really should be private... + virtual ~Logging_Handler (void); + // Ensure dynamic allocation. + +private: + char host_name_[MAXHOSTNAMELEN + 1]; + // Host we are connected to. + + ACE_SOCK_Stream cli_stream_; + // Connection with client +}; + +#endif /* _CLIENT_HANDLER_H */ diff --git a/ACE/examples/Logger/simple-server/Makefile.am b/ACE/examples/Logger/simple-server/Makefile.am new file mode 100644 index 00000000000..d9a43e17ee6 --- /dev/null +++ b/ACE/examples/Logger/simple-server/Makefile.am @@ -0,0 +1,39 @@ +## Process this file with automake to create Makefile.in +## +## $Id$ +## +## This file was generated by MPC. Any changes made directly to +## this file will be lost the next time it is generated. +## +## MPC Command: +## ./bin/mwc.pl -type automake -noreldefs ACE.mwc + +ACE_BUILDDIR = $(top_builddir) +ACE_ROOT = $(top_srcdir) + +## Makefile.Logger_Simple_Server.am + +noinst_PROGRAMS = server_loggerd + +server_loggerd_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) + +server_loggerd_SOURCES = \ + Logging_Acceptor.cpp \ + Logging_Handler.cpp \ + server_loggerd.cpp \ + Logging_Acceptor.h \ + Logging_Handler.h \ + Reactor_Singleton.h + +server_loggerd_LDADD = \ + $(ACE_BUILDDIR)/ace/libACE.la + +## Clean up template repositories, etc. +clean-local: + -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.* + -rm -f gcctemp.c gcctemp so_locations *.ics + -rm -rf cxx_repository ptrepository ti_files + -rm -rf templateregistry ir.out + -rm -rf ptrepository SunWS_cache Templates.DB diff --git a/ACE/examples/Logger/simple-server/Reactor_Singleton.h b/ACE/examples/Logger/simple-server/Reactor_Singleton.h new file mode 100644 index 00000000000..ec0653125a9 --- /dev/null +++ b/ACE/examples/Logger/simple-server/Reactor_Singleton.h @@ -0,0 +1,33 @@ +/* -*- C++ -*- */ +// $Id$ + + +// ============================================================================ +// +// = LIBRARY +// examples +// +// = FILENAME +// Reactor_Singleton.h +// +// = AUTHOR +// Doug Schmidt +// +// ============================================================================ + +#ifndef _REACTOR_SINGLETON_H +#define _REACTOR_SINGLETON_H + +#include "ace/Singleton.h" +#include "ace/Null_Mutex.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Reactor.h" + +// Our global Reactor Singleton. +typedef ACE_Singleton<ACE_Reactor, ACE_Null_Mutex> REACTOR; + +#endif /* _REACTOR_SINGLETON_H */ diff --git a/ACE/examples/Logger/simple-server/server_loggerd.cpp b/ACE/examples/Logger/simple-server/server_loggerd.cpp new file mode 100644 index 00000000000..f323a2f3826 --- /dev/null +++ b/ACE/examples/Logger/simple-server/server_loggerd.cpp @@ -0,0 +1,85 @@ +// $Id$ + +// This server daemon collects, formats, and displays logging +// information forwarded from client daemons running on other hosts in +// the network. +// +// In addition, it also illustrates how the ACE_Reactor framework is +// used. + +#include "ace/Get_Opt.h" +#include "ace/Log_Msg.h" +#include "ace/Signal.h" + +#include "Logging_Acceptor.h" +#include "Reactor_Singleton.h" + +ACE_RCSID(simple_server, server_loggerd, "$Id$") + +static sig_atomic_t finished = 0; + +extern "C" void +handler (int) +{ + finished = 1; +} + +// It doesn't get anymore const than this.... +static const u_short PORT = ACE_DEFAULT_SERVER_PORT; + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + // Register a signal handler. + ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); + ACE_UNUSED_ARG (sa); + + Logging_Acceptor *peer_acceptor; + ACE_NEW_RETURN (peer_acceptor, + Logging_Acceptor, + 1); + + ACE_INET_Addr addr (PORT); + + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:")); + + for (int c; (c = get_opt ()) != -1; ) + switch (c) + { + case 'p': + addr.set (ACE_OS::atoi (get_opt.opt_arg ())); + break; + default: + break; + } + + if (peer_acceptor->open (addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("open")), + -1); + else if (REACTOR::instance ()->register_handler + (peer_acceptor, + ACE_Event_Handler::ACCEPT_MASK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("registering service with ACE_Reactor\n")), + -1); + + // Run forever, performing the logging service. + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) starting up server logging daemon\n"))); + + while (!finished) + REACTOR::instance ()->handle_events (); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) shutting down server logging daemon\n"))); + return 0; +} + + +#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION) +template ACE_Singleton<ACE_Reactor, ACE_Null_Mutex> * + ACE_Singleton<ACE_Reactor, ACE_Null_Mutex>::singleton_; +#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */ |