introduced optional HTTP port

This commit is contained in:
john30
2015-05-01 08:34:27 +02:00
parent f1d76a64cc
commit 34efc9a5ae
2 changed files with 160 additions and 77 deletions
+62 -36
View File
@@ -71,8 +71,8 @@ void Connection::run()
#endif
#endif
time_t listenSince = 0;
bool closed = false;
NetMessage message(m_isHttp);
while (!closed) {
#ifdef HAVE_PPOLL
@@ -109,37 +109,39 @@ void Connection::run()
#endif
}
if (newData || m_listening) {
if (newData || message.isListening()) {
char data[256];
size_t datalen = 0;
if (newData) {
if (!m_socket->isValid())
break;
datalen = m_socket->recv(data, sizeof(data)-1);
// remove closed socket
if (datalen <= 0)
break;
}
// decode client data
data[datalen] = '\0';
NetMessage message(data, m_listening, listenSince);
m_netQueue->add(&message);
// wait for result
logDebug(lf_network, "[%05d] wait for result", getID());
string result = message.getResult();
if (!m_socket->isValid())
break;
m_socket->send(result.c_str(), result.size());
m_listening = message.isListening(listenSince);
if (newData) {
size_t datalen = m_socket->recv(data, sizeof(data)-1);
if (message.isDisconnect())
// remove closed socket
if (datalen <= 0)
break;
data[datalen] = '\0';
} else {
data[0] = '\0';
}
// decode client data
if (message.add(data)) {
m_netQueue->add(&message);
// wait for result
logDebug(lf_network, "[%05d] wait for result", getID());
string result = message.getResult();
if (!m_socket->isValid())
break;
m_socket->send(result.c_str(), result.size());
}
if (message.isDisconnect() || !m_socket->isValid())
break;
}
@@ -151,7 +153,7 @@ void Connection::run()
}
Network::Network(const bool local, const uint16_t port, WQueue<NetMessage*>* netQueue)
Network::Network(const bool local, const uint16_t port, const uint16_t httpPort, WQueue<NetMessage*>* netQueue)
: m_netQueue(netQueue), m_listening(false)
{
if (local)
@@ -162,6 +164,11 @@ Network::Network(const bool local, const uint16_t port, WQueue<NetMessage*>* net
if (m_tcpServer != NULL && m_tcpServer->start() == 0)
m_listening = true;
if (httpPort>0) {
m_httpServer = new TCPServer(httpPort, "0.0.0.0");
m_httpServer->start();
} else
m_httpServer = NULL;
}
Network::~Network()
@@ -192,9 +199,9 @@ void Network::run()
// set timeout
tdiff.tv_sec = 1;
tdiff.tv_nsec = 0;
int socketCount = m_httpServer ? 2 : 1;
#ifdef HAVE_PPOLL
int nfds = 2;
int nfds = 1+socketCount;
struct pollfd fds[nfds];
memset(fds, 0, sizeof(fds));
@@ -204,6 +211,11 @@ void Network::run()
fds[1].fd = m_tcpServer->getFD();
fds[1].events = POLLIN;
if (m_httpServer) {
fds[2].fd = m_httpServer->getFD();
fds[2].events = POLLIN;
}
#else
#ifdef HAVE_PSELECT
int maxfd;
@@ -212,9 +224,15 @@ void Network::run()
FD_ZERO(&checkfds);
FD_SET(m_notify.notifyFD(), &checkfds);
FD_SET(m_tcpServer->getFD(), &checkfds);
if (m_httpServer) {
FD_SET(m_httpServer->getFD(), &checkfds);
}
(m_notify.notifyFD() > m_tcpServer->getFD()) ?
(maxfd = m_notify.notifyFD()) : (maxfd = m_tcpServer->getFD());
maxfd = (m_notify.notifyFD() > m_tcpServer->getFD()) ?
m_notify.notifyFD() : m_tcpServer->getFD();
if (m_httpServer && m_httpServer->getFD()>maxfd) {
maxfd = m_httpServer->getFD();
}
#endif
#endif
@@ -236,7 +254,7 @@ void Network::run()
cleanConnections();
continue;
}
bool newData = false, isHttp = false;
#ifdef HAVE_PPOLL
// new data from notify
if (fds[0].revents & POLLIN) {
@@ -245,6 +263,10 @@ void Network::run()
// new data from socket
if (fds[1].revents & POLLIN) {
newData = true;
} else if (m_httpServer && fds[2].revents & POLLIN) {
newData = isHttp = true;
}
#else
#ifdef HAVE_PSELECT
// new data from notify
@@ -254,20 +276,24 @@ void Network::run()
// new data from socket
if (FD_ISSET(m_tcpServer->getFD(), &readfds)) {
newData = true;
} else if (m_httpServer && FD_ISSET(m_httpServer->getFD(), &readfds)) {
newData = isHttp = true;
}
#endif
#endif
TCPSocket* socket = m_tcpServer->newSocket();
if (newData) {
TCPSocket* socket = (isHttp ? m_httpServer : m_tcpServer)->newSocket();
if (socket == NULL)
continue;
Connection* connection = new Connection(socket, m_netQueue);
Connection* connection = new Connection(socket, isHttp, m_netQueue);
if (connection == NULL)
continue;
connection->start("connection");
m_connections.push_back(connection);
logInfo(lf_network, "[%05d] connection opened %s", connection->getID(), socket->getIP().c_str());
logInfo(lf_network, "[%05d] %s connection opened %s", connection->getID(), isHttp ? "HTTP" : "client", socket->getIP().c_str());
}
}
}
+98 -41
View File
@@ -26,36 +26,36 @@
#include "notify.h"
#include "thread.h"
#include <string>
#include <cstdio>
#include <algorithm>
/** \file network.h */
using namespace std;
/** forward declaration for class connection */
/** Forward declaration for @a Connection. */
class Connection;
/**
* class for data/message transfer between connection and baseloop.
* Class for data/message transfer between @a Connection and @a MainLoop.
*/
class NetMessage
{
public:
/**
* constructs a new instance with data received from the client.
* @param data from client.
* @param listening whether the client is in listening mode.
* @param listenSince start timestamp of listening update.
* Constructor.
* @param isHttp whether this is a HTTP message.
*/
NetMessage(const string data, const bool listening, const time_t listenSince)
: m_data(data), m_resultSet(false), m_disconnect(false), m_listening(listening), m_listenSince(listenSince)
NetMessage(const bool isHttp)
: m_isHttp(isHttp), m_resultSet(false), m_disconnect(false), m_listening(false), m_listenSince(0)
{
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL);
}
/**
* destructor.
* Destructor.
*/
~NetMessage()
{
@@ -73,10 +73,55 @@ private:
public:
/**
* get the data string.
* @return the data string.
* Add request data received from the client.
* @param request the request data from the client.
* @param listening whether the client is in listening mode.
* @param listenSince start timestamp of listening update.
* @return true when the request is complete and the response shall be prepared.
*/
string getData() const { return m_data; }
bool add(string request)
{
if (request.length()>0) {
request.erase(remove(request.begin(), request.end(), '\r'), request.end());
m_request.append(request);
}
size_t pos = m_request.find(m_isHttp ? "\n\n" : "\n");
if (pos!=string::npos) {
if (m_isHttp) {
pos = m_request.find("\n");
m_request.resize(pos); // reduce to first line
// typical first line: GET /ehp/outsidetemp HTTP/1.1
pos = m_request.rfind(" HTTP/");
if (pos!=string::npos) {
m_request.resize(pos); // remove "HTTP/x.x" suffix
}
pos = 0;
while ((pos=m_request.find('%', pos))!=string::npos && pos+2<=m_request.length()) {
unsigned int value1, value2;
if (sscanf("%1x%1x", m_request.c_str()+pos+1, &value1, &value2)<2)
break;
m_request[pos] = (char)(((value1&0x0f)<<4)|(value2&0x0f));
m_request.erase(pos+1, 2);
}
} else if (pos+1==m_request.length()) {
m_request.resize(pos); // reduce to complete lines
}
return true;
}
return m_request.length()==0 && m_listening;
}
/**
* Return whether this is a HTTP message.
* @return whether this is a HTTP message.
*/
bool isHttp() const { return m_isHttp; }
/**
* Return the request string.
* @return the request string.
*/
string getRequest() const { return m_request; }
/**
* Wait for the result being set and return the result string.
@@ -89,9 +134,13 @@ public:
while (!m_resultSet)
pthread_cond_wait(&m_cond, &m_mutex);
m_request.clear();
string result = m_result;
m_result.clear();
m_resultSet = false;
pthread_mutex_unlock(&m_mutex);
return m_result;
return result;
}
/**
@@ -103,12 +152,12 @@ public:
*/
void setResult(const string result, const bool listening, const time_t listenUntil, const bool disconnect)
{
pthread_mutex_lock(&m_mutex);
m_result = result;
m_disconnect = disconnect;
m_listening = listening;
m_listenSince = listenUntil;
m_resultSet = true;
pthread_mutex_lock(&m_mutex);
pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_mutex);
}
@@ -118,7 +167,7 @@ public:
* @param listenSince set to the start time from which to add updates (inclusive).
* @return whether the client is in listening mode.
*/
bool isListening(time_t& listenSince) { listenSince = m_listenSince; return m_listening; }
bool isListening(time_t* listenSince=NULL) { if (listenSince) *listenSince = m_listenSince; return m_listening; }
/**
* Return whether the client shall be disconnected.
@@ -127,28 +176,31 @@ public:
bool isDisconnect() { return m_disconnect; }
private:
/** the data string */
string m_data;
/** whether this is a HTTP message. */
const bool m_isHttp;
/** the request string. */
string m_request;
/** whether the result was already set. */
bool m_resultSet;
/** the result string */
/** the result string. */
string m_result;
/** set to true when the client shall be disconnected. */
bool m_disconnect;
/** mutex variable for exclusive lock */
/** mutex variable for exclusive lock. */
pthread_mutex_t m_mutex;
/** condition variable for exclusive lock */
/** condition variable for exclusive lock. */
pthread_cond_t m_cond;
/** whether the client is in listening mode */
/** whether the client is in listening mode. */
bool m_listening;
/** start timestamp of listening update */
/** start timestamp of listening update. */
time_t m_listenSince;
};
@@ -161,12 +213,13 @@ class Connection : public Thread
public:
/**
* create a new connection instance.
* @param socket the tcp socket for communication.
* @param netQueue the remote queue for network messages.
* Constructor.
* @param socket the @a TCPSocket for communication.
* @param isHttp whether this is a HTTP message.
* @param netQueue the remote @a WQueue for handling @a NetMessage instances.
*/
Connection(TCPSocket* socket, WQueue<NetMessage*>* netQueue)
: m_socket(socket), m_netQueue(netQueue), m_listening(false)
Connection(TCPSocket* socket, const bool isHttp, WQueue<NetMessage*>* netQueue)
: m_isHttp(isHttp), m_socket(socket), m_netQueue(netQueue)
{ m_id = ++m_ids; }
virtual ~Connection() { if (m_socket) delete m_socket; }
@@ -176,35 +229,35 @@ public:
virtual void run();
/**
* close active connection.
* Stop this connection.
*/
virtual void stop() { m_notify.notify(); Thread::stop(); }
/**
* return own connection id.
* @return id of current connection.
* Return the ID of this connection.
* @return the ID of this connection.
*/
int getID() { return m_id; }
private:
/** the tcp socket instance */
/** whether this is a HTTP connection. */
const bool m_isHttp;
/** the @a TCPSocket for communication. */
TCPSocket* m_socket;
/** remote queue for network messages */
/** the remote @a WQueue for handling @a NetMessage instances. */
WQueue<NetMessage*>* m_netQueue;
/** notification object for shutdown procedure */
/** notification object for shutdown procedure. */
Notify m_notify;
/** id of current connection */
/** the ID of this connection. */
int m_id;
/** sumary for opened connections */
/** the IF of the last opened connection. */
static int m_ids;
/** whether the client is in listening mode */
bool m_listening;
};
/**
@@ -217,10 +270,11 @@ public:
/**
* create a network instance and listening for incoming connections.
* @param local true to accept connections only for local host.
* @param port the tcp port to listening.
* @param port the port to listen for command line connections.
* @param httpPort the port to listen for HTTP connections, or 0.
* @param netQueue the remote queue for network messages.
*/
Network(const bool local, const uint16_t port, WQueue<NetMessage*>* netQueue);
Network(const bool local, const uint16_t port, const uint16_t httpPort, WQueue<NetMessage*>* netQueue);
/**
* destructor.
@@ -244,9 +298,12 @@ private:
/** the @a MainLoop queue for transferring @a NetMessage instances. */
WQueue<NetMessage*>* m_netQueue;
/** the @a TCPServer instance. */
/** the command line @a TCPServer instance. */
TCPServer* m_tcpServer;
/** the HTTP @a TCPServer instance, or NULL. */
TCPServer* m_httpServer;
/** @a Notify object for shutdown procedure. */
Notify m_notify;