1 // -*- c++ -*-
2 //------------------------------------------------------------------------------
3 // MonitorConn.cpp
4 //------------------------------------------------------------------------------
5 // $Id: MonitorConn.cpp,v 1.2 2006/07/20 02:30:55 vlg Exp $
6 //------------------------------------------------------------------------------
7 // Copyright (c) 2003 by Vladislav Grinchenko
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version
12 // 2 of the License, or (at your option) any later version.
13 //------------------------------------------------------------------------------
14 // Created: Thu Apr 17 23:22:39 EDT 2003
15 //------------------------------------------------------------------------------
16
17 #include <assa/CommonUtils.h>
18 #include "MonitorConn.h"
19 #include "Conn.h"
20 #include "LogServer-main.h"
21 #include "LogServer.h"
22
23 /** Convert user input to upper case
24 */
25 template <class T>
26 class ToUpper {
27 public:
operator ()(T & elem_) const28 void operator ()(T& elem_) const { elem_ = ::toupper (elem_); }
29 };
30
31 MonitorConn::
MonitorConn(IPv4Socket * stream_)32 MonitorConn (IPv4Socket* stream_) :
33 ServiceHandler<IPv4Socket> (stream_),
34 m_iolen (0),
35 m_current_conn (NULL)
36 {
37 trace ("MonitorConn::MonitorConn");
38
39 m_eor [0] = 0xA; // ASCII LF (line feed)
40 m_eor [1] = 0xD; // ASCII CR (carrige return)
41 }
42
43 MonitorConn::
~MonitorConn()44 ~MonitorConn ()
45 {
46 trace ("MonitorConn::~MonitorConn");
47 if (m_current_conn) {
48 m_current_conn->unsubscribe (this);
49 }
50 /* no-op */
51 }
52
53 int
54 MonitorConn::
handle_close(int)55 handle_close (int /* fd */)
56 {
57 trace("MonitorConn::handle_close");
58
59 DL((ASSA::APP,"=> Monitoring client disconnected\n"));
60 delete (this);
61 return 0;
62 }
63
64 int
65 MonitorConn::
open()66 open ()
67 {
68 trace("MonitorConn::open");
69
70 ASSA::IPv4Socket& s = *this;
71 REACTOR->registerIOHandler (this, s.getHandler (), ASSA::READ_EVENT);
72 DL((ASSA::APP,"=> Monitoring client connected\n"));
73 set_id ("Logmon Client");
74 return 0;
75 }
76
77 void
78 MonitorConn::
notify(const char * msg_)79 notify (const char* msg_)
80 {
81 trace("MonitorConn::notify");
82
83 ASSA::IPv4Socket& s = *this;
84 static const char abort_msg [] = "DISCONNECTED\r\n";
85
86 if (msg_ == NULL) {
87 s.write (abort_msg, strlen (abort_msg));
88 m_current_conn = NULL;
89 }
90 else {
91 s.write (msg_, ::strlen (msg_));
92 }
93 s << ASSA::flush;
94 }
95
96 int
97 MonitorConn::
handle_read(int fd_)98 handle_read (int fd_)
99 {
100 trace("MonitorConn::handle_read");
101
102 ASSA::IPv4Socket& s = *this;
103 if (s.getHandler () != fd_) {
104 DL ((ASSA::ASSAERR,"FDs don't match (fd_=%d != %d)\n",
105 fd_, s.getHandler ()));
106 return (-1);
107 }
108
109 char c = 0;
110 int ret = 0;
111 bool seen_eor = false; // have we seen end-of-record?
112
113 while ((ret = s.read (&c, 1)) == 1 && m_iolen < MAXMSGLEN) {
114 if (c == '\n') {
115 continue;
116 }
117 if (c == '\r') {
118 seen_eor = true;
119 m_iobuf [m_iolen] = '\0';
120 break;
121 }
122 m_iobuf [m_iolen++] = c;
123 }
124
125 if (m_iolen >= MAXMSGLEN) {
126 DL((ASSA::ASSAERR,"Message length exceeded %d bytes!\n",MAXMSGLEN));
127 return -1;
128 }
129
130 if (seen_eor) {
131 parse_record ();
132 }
133
134 return s.eof () ? -1 : s.in_avail ();
135 }
136
137 void
138 MonitorConn::
parse_record()139 parse_record ()
140 {
141 trace("MonitorConn::parse_record");
142
143 DL((ASSA::APP,"=> Message from client:\n\n%s\n\n", m_iobuf));
144 std::vector<std::string> tokens;
145 ASSA::Utils::split (m_iobuf, tokens);
146 for_each (tokens [0].begin (), tokens [0].end (), ToUpper<char> ());
147
148 if (tokens [0] == "LIST") {
149 process_list_cmd ();
150 }
151 else if (tokens [0] == "STOP") {
152 m_current_conn->unsubscribe (this);
153 }
154 else if (tokens [0] == "GET") {
155 process_get_cmd (tokens [1]);
156 }
157 else {
158 DL((ASSA::APP,"Unknown command \"%s\"\n", m_iobuf));
159 }
160 m_iolen = 0;
161 }
162
163 void
164 MonitorConn::
process_list_cmd()165 process_list_cmd ()
166 {
167 trace("MonitorConn::process_list_cmd");
168
169 ASSA::IPv4Socket& s = *this;
170 ASSA::Repository<Conn>::const_iterator cit = REPO->begin ();
171 if (cit != REPO->end ()) {
172 s.write ((*cit)->get_app_name().c_str(),
173 (*cit)->get_app_name().size ());
174 cit++;
175 }
176 while (cit != REPO->end ()) {
177 s.write (":", 1);
178 s.write ((*cit)->get_app_name().c_str(),
179 (*cit)->get_app_name().size ());
180 cit++;
181 }
182 s.write (m_eor, 2);
183 s << ASSA::flush;
184 }
185
186 void
187 MonitorConn::
process_get_cmd(const std::string & name_)188 process_get_cmd (const std::string& name_)
189 {
190 trace("MonitorConn::process_get_cmd");
191
192 ASSA::Repository<Conn>::const_iterator cit = REPO->begin ();
193 while (cit != REPO->end ()) {
194 if ((*cit)->get_app_name() == name_) {
195 m_current_conn = *cit;
196 m_current_conn->subscribe (this);
197 break;
198 }
199 cit++;
200 }
201 }
202