summaryrefslogtreecommitdiff
path: root/mobicore/MobiCoreDriverLib/Daemon/Server/Server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mobicore/MobiCoreDriverLib/Daemon/Server/Server.cpp')
-rw-r--r--mobicore/MobiCoreDriverLib/Daemon/Server/Server.cpp194
1 files changed, 104 insertions, 90 deletions
diff --git a/mobicore/MobiCoreDriverLib/Daemon/Server/Server.cpp b/mobicore/MobiCoreDriverLib/Daemon/Server/Server.cpp
index 418d8b0..dbd6240 100644
--- a/mobicore/MobiCoreDriverLib/Daemon/Server/Server.cpp
+++ b/mobicore/MobiCoreDriverLib/Daemon/Server/Server.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 TRUSTONIC LIMITED
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,32 +37,58 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <pthread.h>
//#define LOG_VERBOSE
#include "log.h"
#include "FSD.h"
+// Local headers
+#include "Queue.h"
+#include "Client.h"
+
+struct Server::Private : public CThread {
+ ConnectionHandler *connectionHandler;
+ std::list<Client*> clients;
+ pthread_mutex_t clients_mutex_;
+ Queue<Client*> queue;
+ Private(ConnectionHandler *ch): connectionHandler(ch) {
+ pthread_mutex_init(&clients_mutex_, NULL);
+ }
+ ~Private() {
+ pthread_mutex_destroy(&clients_mutex_);
+ }
+ void run() {
+ Client* client;
+ for (;;) {
+ client = queue.pop();
+ if (!client) {
+ break;
+ }
+ if (client->isDead()) {
+ if (!client->isDetached()) {
+ client->dropConnection();
+ }
+ client->setExiting();
+ } else {
+ connectionHandler->handleCommand(client->connection(), client->commandId());
+ }
+ client->unlock();
+ }
+ }
+};
//------------------------------------------------------------------------------
-Server::Server(
- ConnectionHandler *connectionHandler,
- const char *localAddr
-) : socketAddr(localAddr)
-{
- this->connectionHandler = connectionHandler;
- this->serverSock = -1;
-}
+Server::Server(ConnectionHandler *handler, const char *localAddr):
+ serverSock(-1), socketAddr(localAddr), connectionHandler(handler),
+ priv_(new Private(connectionHandler)) {}
//------------------------------------------------------------------------------
-void Server::run(
- void
-)
-{
+void Server::run() {
bool isFSDStarted=false;
FSD *FileStorageDaemon=NULL;
do {
-
LOG_I("Server: start listening on socket %s", socketAddr.c_str());
// Open a socket (a UNIX domain stream socket)
@@ -91,8 +117,7 @@ void Server::run(
}
LOG_I("\n********* successfully initialized Daemon *********\n");
-
-
+ priv_->start();
for (;;) {
fd_set fdReadSockets;
@@ -102,19 +127,6 @@ void Server::run(
// Select server socket descriptor
FD_SET(serverSock, &fdReadSockets);
- int maxSocketDescriptor = serverSock;
-
- // Select socket descriptor of all connections
- for (connectionIterator_t iterator = peerConnections.begin();
- iterator != peerConnections.end();
- ++iterator) {
- Connection *connection = (*iterator);
- int peerSocket = connection->socketDescriptor;
- FD_SET(peerSocket, &fdReadSockets);
- if (peerSocket > maxSocketDescriptor) {
- maxSocketDescriptor = peerSocket;
- }
- }
if (!isFSDStarted) {
// Create the <t-base File Storage Daemon
@@ -127,11 +139,8 @@ void Server::run(
// Wait for activities, select() returns the number of sockets
// which require processing
- LOG_V(" Server: waiting on sockets");
- int numSockets = select(
- maxSocketDescriptor + 1,
- &fdReadSockets,
- NULL, NULL, NULL);
+ LOG_V(" Server: waiting on server socket");
+ int numSockets = select(serverSock + 1, &fdReadSockets, NULL, NULL, NULL);
// Check if select failed
if (numSockets < 0) {
@@ -145,7 +154,7 @@ void Server::run(
continue;
}
- LOG_V(" Server: events on %d socket(s).", numSockets);
+ LOG_V(" Server: event on socket.");
// Check if a new client connected to the server socket
if (FD_ISSET(serverSock, &fdReadSockets)) {
@@ -165,9 +174,12 @@ void Server::run(
break;
}
- Connection *connection = new Connection(clientSock, &clientAddr);
- peerConnections.push_back(connection);
- LOG_I(" Server: new socket connection established and start listening.");
+ Client *client = new Client(connectionHandler, clientSock, &clientAddr, priv_->queue);
+ pthread_mutex_lock(&priv_->clients_mutex_);
+ priv_->clients.push_back(client);
+ pthread_mutex_unlock(&priv_->clients_mutex_);
+ client->start();
+ LOG_I(" Server: new socket client %p created and start listening.", client);
} while (false);
// we can ignore any errors from accepting a new connection.
@@ -175,87 +187,89 @@ void Server::run(
// and nothing has changed.
}
- // Handle traffic on existing client connections
- connectionIterator_t iterator = peerConnections.begin();
- while ( (iterator != peerConnections.end())
- && (numSockets > 0) ) {
- Connection *connection = (*iterator);
- int peerSocket = connection->socketDescriptor;
-
- if (!FD_ISSET(peerSocket, &fdReadSockets)) {
- ++iterator;
- continue;
+ // Take this opportunity to reap any dead clients
+ pthread_mutex_lock(&priv_->clients_mutex_);
+ std::list<Client*>::iterator it = priv_->clients.begin();
+ while (it != priv_->clients.end()) {
+ Client* client = *it;
+ if (client->isExiting()) {
+ it = priv_->clients.erase(it);
+ client->join();
+ delete client;
+ LOG_I(" Server: client %p destroyed.", client);
+ } else {
+ it++;
}
-
- numSockets--;
-
- // the connection will be terminated if command processing
- // fails
- if (!connectionHandler->handleConnection(connection)) {
- LOG_I(" Server: dropping connection.");
-
- //Inform the driver
- connectionHandler->dropConnection(connection);
-
- // Remove connection from list
- delete connection;
- iterator = peerConnections.erase(iterator);
- continue;
- }
-
- ++iterator;
}
+ pthread_mutex_unlock(&priv_->clients_mutex_);
}
+ // Exit worker thread
+ priv_->queue.push(NULL);
+ priv_->join();
} while (false);
+ // Change state to STOPPED, releases start() on failure
+ pthread_mutex_lock(&startup_mutex);
+ server_state = STOPPED;
+ pthread_cond_broadcast(&startup_cond);
+ pthread_mutex_unlock(&startup_mutex);
+
+
+
//Wait for File Storage Daemon to exit
if (FileStorageDaemon) {
- FileStorageDaemon->join();
- delete FileStorageDaemon;
+ FileStorageDaemon->join();
+ delete FileStorageDaemon;
}
LOG_ERRNO("Exiting Server, because");
+ kill(getpid(), SIGTERM);
+
}
//------------------------------------------------------------------------------
-void Server::detachConnection(
- Connection *connection
-)
-{
+void Server::detachConnection(Connection* connection) {
LOG_V(" Stopping to listen on notification socket.");
- for (connectionIterator_t iterator = peerConnections.begin();
- iterator != peerConnections.end();
- ++iterator) {
- Connection *tmpConnection = (*iterator);
- if (tmpConnection == connection) {
- peerConnections.erase(iterator);
+ pthread_mutex_lock(&priv_->clients_mutex_);
+ for (std::list<Client*>::iterator it = priv_->clients.begin(); it != priv_->clients.end(); it++) {
+ Client* client = *it;
+ if (client->connection() == connection) {
+ client->detachConnection();
LOG_I(" Stopped listening on notification socket.");
break;
}
}
+ pthread_mutex_unlock(&priv_->clients_mutex_);
}
//------------------------------------------------------------------------------
-Server::~Server(
- void
-)
-{
+Server::~Server() {
// Shut down the server socket
- if(serverSock != -1) {
+ if (serverSock != -1) {
close(serverSock);
- serverSock = -1;
}
-
// Destroy all client connections
- connectionIterator_t iterator = peerConnections.begin();
- while (iterator != peerConnections.end()) {
- Connection *tmpConnection = (*iterator);
- delete tmpConnection;
- iterator = peerConnections.erase(iterator);
+ for (std::list<Client*>::iterator it = priv_->clients.begin(); it != priv_->clients.end(); it++) {
+ Client* client = *it;
+ delete client;
+ }
+ delete priv_;
+}
+
+//------------------------------------------------------------------------------
+
+void Server::start(const char *name) {
+ server_state = STARTING;
+ CThread::start(name);
+ // Hang on till thread has started or stopped
+ pthread_mutex_lock(&startup_mutex);
+ while (server_state == STARTING) {
+ pthread_cond_wait(&startup_cond, &startup_mutex);
}
+ pthread_mutex_unlock(&startup_mutex);
}