// -*- c++ -*- //------------------------------------------------------------------------------ // MonitorConn.cpp //------------------------------------------------------------------------------ // $Id: MonitorConn.cpp,v 1.2 2006/07/20 02:30:55 vlg Exp $ //------------------------------------------------------------------------------ // Copyright (c) 2003 by Vladislav Grinchenko // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version // 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ // Created: Thu Apr 17 23:22:39 EDT 2003 //------------------------------------------------------------------------------ #include #include "MonitorConn.h" #include "Conn.h" #include "LogServer-main.h" #include "LogServer.h" #include /** Convert user input to upper case */ template class ToUpper { public: void operator ()(T& elem_) const { elem_ = ::toupper (elem_); } }; MonitorConn:: MonitorConn (IPv4Socket* stream_) : ServiceHandler (stream_), m_iolen (0), m_current_conn (NULL) { trace ("MonitorConn::MonitorConn"); m_eor [0] = 0xA; // ASCII LF (line feed) m_eor [1] = 0xD; // ASCII CR (carrige return) } MonitorConn:: ~MonitorConn () { trace ("MonitorConn::~MonitorConn"); if (m_current_conn) { m_current_conn->unsubscribe (this); } /* no-op */ } int MonitorConn:: handle_close (int /* fd */) { trace("MonitorConn::handle_close"); DL((ASSA::APP,"=> Monitoring client disconnected\n")); delete (this); return 0; } int MonitorConn:: open () { trace("MonitorConn::open"); ASSA::IPv4Socket& s = *this; REACTOR->registerIOHandler (this, s.getHandler (), ASSA::READ_EVENT); DL((ASSA::APP,"=> Monitoring client connected\n")); set_id ("Logmon Client"); return 0; } void MonitorConn:: notify (const char* msg_) { trace("MonitorConn::notify"); ASSA::IPv4Socket& s = *this; static const char abort_msg [] = "DISCONNECTED\r\n"; if (msg_ == NULL) { s.write (abort_msg, strlen (abort_msg)); m_current_conn = NULL; } else { s.write (msg_, ::strlen (msg_)); } s << ASSA::flush; } int MonitorConn:: handle_read (int fd_) { trace("MonitorConn::handle_read"); ASSA::IPv4Socket& s = *this; if (s.getHandler () != fd_) { DL ((ASSA::ASSAERR,"FDs don't match (fd_=%d != %d)\n", fd_, s.getHandler ())); return (-1); } char c = 0; int ret = 0; bool seen_eor = false; // have we seen end-of-record? while ((ret = s.read (&c, 1)) == 1 && m_iolen < MAXMSGLEN) { if (c == '\n') { continue; } if (c == '\r') { seen_eor = true; m_iobuf [m_iolen] = '\0'; break; } m_iobuf [m_iolen++] = c; } if (m_iolen >= MAXMSGLEN) { DL((ASSA::ASSAERR,"Message length exceeded %d bytes!\n",MAXMSGLEN)); return -1; } if (seen_eor) { parse_record (); } return s.eof () ? -1 : s.in_avail (); } void MonitorConn:: parse_record () { trace("MonitorConn::parse_record"); DL((ASSA::APP,"=> Message from client:\n\n%s\n\n", m_iobuf)); std::vector tokens; ASSA::Utils::split (m_iobuf, tokens); for_each (tokens [0].begin (), tokens [0].end (), ToUpper ()); if (tokens [0] == "LIST") { process_list_cmd (); } else if (tokens [0] == "STOP") { m_current_conn->unsubscribe (this); } else if (tokens [0] == "GET") { process_get_cmd (tokens [1]); } else { DL((ASSA::APP,"Unknown command \"%s\"\n", m_iobuf)); } m_iolen = 0; } void MonitorConn:: process_list_cmd () { trace("MonitorConn::process_list_cmd"); ASSA::IPv4Socket& s = *this; ASSA::Repository::const_iterator cit = REPO->begin (); if (cit != REPO->end ()) { s.write ((*cit)->get_app_name().c_str(), (*cit)->get_app_name().size ()); cit++; } while (cit != REPO->end ()) { s.write (":", 1); s.write ((*cit)->get_app_name().c_str(), (*cit)->get_app_name().size ()); cit++; } s.write (m_eor, 2); s << ASSA::flush; } void MonitorConn:: process_get_cmd (const std::string& name_) { trace("MonitorConn::process_get_cmd"); ASSA::Repository::const_iterator cit = REPO->begin (); while (cit != REPO->end ()) { if ((*cit)->get_app_name() == name_) { m_current_conn = *cit; m_current_conn->subscribe (this); break; } cit++; } }