blob: 4cd5d69c54b30d9100891e6b687f291e53631ad2 [file] [log] [blame]
/***************************************************************************
telnetappender.cpp - class TelnetAppender
-------------------
begin : jeu mai 8 2003
copyright : (C) 2003 by Michael CATANZARITI
email : mcatan@free.fr
***************************************************************************/
/***************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* *
* This software is published under the terms of the Apache Software *
* License version 1.1, a copy of which has been included with this *
* distribution in the LICENSE.txt file. *
***************************************************************************/
#include <log4cxx/net/telnetappender.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/socketoutputstream.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/helpers/stringhelper.h>
using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::net;
IMPLEMENT_LOG4CXX_OBJECT(TelnetAppender)
int TelnetAppender::DEFAULT_PORT = 23;
TelnetAppender::TelnetAppender() : port(23), sh(0)
{
}
TelnetAppender::~TelnetAppender()
{
finalize();
}
void TelnetAppender::activateOptions()
{
try
{
sh = new SocketHandler(port);
sh->start();
}
catch(Exception& e)
{
LogLog::error(_T("Caught exception"), e);
}
}
void TelnetAppender::setOption(const String& option,
const String& value)
{
if (StringHelper::equalsIgnoreCase(option, _T("port")))
{
setPort(OptionConverter::toInt(value, DEFAULT_PORT));
}
else
{
AppenderSkeleton::setOption(name, value);
}
}
void TelnetAppender::close()
{
if (sh != 0)
{
sh->finalize();
}
}
void TelnetAppender::append(const spi::LoggingEventPtr& event)
{
if (sh != 0)
{
StringBuffer os;
this->layout->format(os, event);
sh->send(os.str());
}
}
TelnetAppender::SocketHandler::SocketHandler(int port)
: done(false), MAX_CONNECTIONS(20), serverSocket(port)
{
}
void TelnetAppender::SocketHandler::finalize()
{
std::vector<helpers::SocketPtr>::iterator it, itEnd = connections.end();
for (it = connections.begin(); it != itEnd; it++)
{
try
{
(*it)->close();
}
catch(Exception&)
{
}
}
try
{
serverSocket.close();
}
catch(Exception&)
{
}
done = true;
}
void TelnetAppender::SocketHandler::send(const String& message)
{
std::vector<helpers::SocketOutputStreamPtr>::iterator it, itEnd;
std::vector<helpers::SocketPtr>::iterator itc, itEndc;
it = writers.begin();
itEnd = writers.end();
itc = connections.begin();
itEndc = connections.end();
bool bRemove = false;
while (it != itEnd/*| itc != itEndc*/)
{
SocketPtr& sock = *itc;
SocketOutputStreamPtr& writer = *it;
try
{
print(writer, message);
print(writer, _T("\r\n"));
writer->flush();
itc++;
it++;
}
catch(Exception&)
{
// The client has closed the connection, remove it from our list:
itc = connections.erase(itc);
it = writers.erase(it);
itEnd = writers.end();
itEndc = connections.end();
}
}
}
void TelnetAppender::SocketHandler::run()
{
while(!done)
{
try
{
SocketPtr newClient = serverSocket.accept();
SocketOutputStreamPtr os = newClient->getOutputStream();
if(connections.size() < MAX_CONNECTIONS)
{
connections.push_back(newClient);
writers.push_back(os);
StringBuffer oss;
oss << _T("TelnetAppender v1.0 (") << connections.size()
<< _T(" active connections)\r\n\r\n");
print(os, oss.str());
os->flush();
}
else
{
print(os, _T("Too many connections.\r\n"));
os->flush();
newClient->close();
}
}
catch(Exception& e)
{
LogLog::error(_T("Encountered error while in SocketHandler loop."), e);
}
}
}
void TelnetAppender::SocketHandler::print(helpers::SocketOutputStreamPtr& os, const String& sz)
{
USES_CONVERSION;
os->write((void *)T2A(sz.c_str()), sz.length());
}