laforge
/
openbts-osmo
Archived
1
0
Fork 0
This repository has been archived on 2022-03-30. You can view files and clone it, but cannot push or open issues or pull requests.
openbts-osmo/public-trunk/CLI/CLIServer.cpp

173 lines
4.4 KiB
C++

/*
* Copyright 2009, 2010 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//#include <vector>
#include <list>
#include <config.h>
#include <CLIServer.h>
#include <CLIConnection.h>
#include <CLIParser.h>
#include <Globals.h>
#include <Logger.h>
using namespace std;
using namespace CommandLine;
namespace CommandLine {
typedef std::list<CLIServerConnectionThread *> ServerThreadsList;
/** Free all finished threads from the given list */
void clearFinishedThreads(ServerThreadsList &threadsList)
{
ServerThreadsList::iterator it;
for (it = threadsList.begin(); it != threadsList.end(); )
{
CLIServerConnectionThread *pThread = *it;
if (pThread->state() == CLIServerConnectionThread::FINISHING) {
pThread->join();
delete pThread;
// This moves iterator forward, so we don't need to increment it.
it = threadsList.erase(it);
} else {
it++;
}
}
}
/** Stop all threads in the list */
void stopAllThreads(ServerThreadsList &threadsList)
{
while (threadsList.begin() != threadsList.end())
{
// Pop an element from the list.
CLIServerConnectionThread *pThread = threadsList.front();
threadsList.pop_front();
switch (pThread->state()) {
case CLIServerConnectionThread::IDLE:
delete pThread;
break;
case CLIServerConnectionThread::STARTING:
case CLIServerConnectionThread::STARTED:
pThread->stop();
// no break;
case CLIServerConnectionThread::FINISHING:
pThread->join();
delete pThread;
break;
}
}
}
};
void CommandLine::runCLIServer(ConnectionServerSocket *serverSock)
{
ServerThreadsList serverThreads;
// Step 1 -- Start listening at the given interface/port
if (!serverSock->bind()) {
int errsv = errno;
LOG(ERROR) << "serverSock->bind() failed with errno="
<< errsv << " (0x" << hex << errsv << dec << ")";
return;
}
// Step 2 -- Serve incoming connections
while (1) {
// Step 2.1 -- Wait for incoming connection
ConnectionSocket *newConn = serverSock->accept();
if (newConn == NULL)
{
int errsv = errno;
if (errsv == EINVAL) {
LOG(INFO) << "serverSock has been closed.";
} else {
LOG(INFO) << "serverSock->accept() failed with errno="
<< errsv << " (0x" << hex << errsv << dec << ")";
}
break;
}
LOG(INFO) << "New incoming connection: " << *newConn;
// Step 2.2 -- Add thread to our threads list and start it.
CLIServerConnectionThread *ipServerThread
= new CLIServerConnectionThread(newConn, serverSock);
LOG(DEEPDEBUG) << "New server thread: " << hex << ipServerThread << dec;
serverThreads.push_back(ipServerThread);
ipServerThread->start();
// Step 2.3 -- Clean up finished threads
clearFinishedThreads(serverThreads);
}
// Step 3 -- Cleanup
serverSock->close();
stopAllThreads(serverThreads);
}
void *CLIServerConnectionThread::startFunc(void *data)
{
CLIServerConnectionThread *threadObj = (CLIServerConnectionThread*)data;
// Simply forward the call to member function
threadObj->state(STARTED);
threadObj->run();
threadObj->state(FINISHING);
return NULL;
}
void CLIServerConnectionThread::run()
{
assert(mConnSock != NULL);
CLIConnection conn(mConnSock);
while (1) {
// Receive a command
std::string recvBlock;
if (!conn.receiveBlock(recvBlock))
break;
// Process command
ostringstream sendBlock;
int res = gParser.process(recvBlock, sendBlock);
if (res < 0) {
// Shutdown CLI server if process() returns -1
mServerSock->close();
break;
}
// Send result back to the client
if (!conn.sendBlock(sendBlock.str()))
break;
}
mConnSock->close();
}
// vim: ts=4 sw=4