#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 #include "Logging_Handler.h" #include "Reactor_Singleton.h" Logging_Handler::~Logging_Handler () { // 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); std::unique_ptr 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); std::unique_ptr payload (payload_p); // Ensure there's sufficient room for log record payload. ACE_CDR::grow (payload.get (), 8 + ACE_CDR::MAX_ALIGNMENT + length); // Use 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 . 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 () 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 (); }