introduced optional HTTP port
This commit is contained in:
+62
-36
@@ -71,8 +71,8 @@ void Connection::run()
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
time_t listenSince = 0;
|
|
||||||
bool closed = false;
|
bool closed = false;
|
||||||
|
NetMessage message(m_isHttp);
|
||||||
|
|
||||||
while (!closed) {
|
while (!closed) {
|
||||||
#ifdef HAVE_PPOLL
|
#ifdef HAVE_PPOLL
|
||||||
@@ -109,37 +109,39 @@ void Connection::run()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newData || m_listening) {
|
if (newData || message.isListening()) {
|
||||||
char data[256];
|
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())
|
if (!m_socket->isValid())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
m_socket->send(result.c_str(), result.size());
|
if (newData) {
|
||||||
m_listening = message.isListening(listenSince);
|
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;
|
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)
|
: m_netQueue(netQueue), m_listening(false)
|
||||||
{
|
{
|
||||||
if (local)
|
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)
|
if (m_tcpServer != NULL && m_tcpServer->start() == 0)
|
||||||
m_listening = true;
|
m_listening = true;
|
||||||
|
|
||||||
|
if (httpPort>0) {
|
||||||
|
m_httpServer = new TCPServer(httpPort, "0.0.0.0");
|
||||||
|
m_httpServer->start();
|
||||||
|
} else
|
||||||
|
m_httpServer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Network::~Network()
|
Network::~Network()
|
||||||
@@ -192,9 +199,9 @@ void Network::run()
|
|||||||
// set timeout
|
// set timeout
|
||||||
tdiff.tv_sec = 1;
|
tdiff.tv_sec = 1;
|
||||||
tdiff.tv_nsec = 0;
|
tdiff.tv_nsec = 0;
|
||||||
|
int socketCount = m_httpServer ? 2 : 1;
|
||||||
#ifdef HAVE_PPOLL
|
#ifdef HAVE_PPOLL
|
||||||
int nfds = 2;
|
int nfds = 1+socketCount;
|
||||||
struct pollfd fds[nfds];
|
struct pollfd fds[nfds];
|
||||||
|
|
||||||
memset(fds, 0, sizeof(fds));
|
memset(fds, 0, sizeof(fds));
|
||||||
@@ -204,6 +211,11 @@ void Network::run()
|
|||||||
|
|
||||||
fds[1].fd = m_tcpServer->getFD();
|
fds[1].fd = m_tcpServer->getFD();
|
||||||
fds[1].events = POLLIN;
|
fds[1].events = POLLIN;
|
||||||
|
|
||||||
|
if (m_httpServer) {
|
||||||
|
fds[2].fd = m_httpServer->getFD();
|
||||||
|
fds[2].events = POLLIN;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#ifdef HAVE_PSELECT
|
#ifdef HAVE_PSELECT
|
||||||
int maxfd;
|
int maxfd;
|
||||||
@@ -212,9 +224,15 @@ void Network::run()
|
|||||||
FD_ZERO(&checkfds);
|
FD_ZERO(&checkfds);
|
||||||
FD_SET(m_notify.notifyFD(), &checkfds);
|
FD_SET(m_notify.notifyFD(), &checkfds);
|
||||||
FD_SET(m_tcpServer->getFD(), &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() > m_tcpServer->getFD()) ?
|
||||||
(maxfd = m_notify.notifyFD()) : (maxfd = m_tcpServer->getFD());
|
m_notify.notifyFD() : m_tcpServer->getFD();
|
||||||
|
if (m_httpServer && m_httpServer->getFD()>maxfd) {
|
||||||
|
maxfd = m_httpServer->getFD();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -236,7 +254,7 @@ void Network::run()
|
|||||||
cleanConnections();
|
cleanConnections();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
bool newData = false, isHttp = false;
|
||||||
#ifdef HAVE_PPOLL
|
#ifdef HAVE_PPOLL
|
||||||
// new data from notify
|
// new data from notify
|
||||||
if (fds[0].revents & POLLIN) {
|
if (fds[0].revents & POLLIN) {
|
||||||
@@ -245,6 +263,10 @@ void Network::run()
|
|||||||
|
|
||||||
// new data from socket
|
// new data from socket
|
||||||
if (fds[1].revents & POLLIN) {
|
if (fds[1].revents & POLLIN) {
|
||||||
|
newData = true;
|
||||||
|
} else if (m_httpServer && fds[2].revents & POLLIN) {
|
||||||
|
newData = isHttp = true;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
#ifdef HAVE_PSELECT
|
#ifdef HAVE_PSELECT
|
||||||
// new data from notify
|
// new data from notify
|
||||||
@@ -254,20 +276,24 @@ void Network::run()
|
|||||||
|
|
||||||
// new data from socket
|
// new data from socket
|
||||||
if (FD_ISSET(m_tcpServer->getFD(), &readfds)) {
|
if (FD_ISSET(m_tcpServer->getFD(), &readfds)) {
|
||||||
|
newData = true;
|
||||||
|
} else if (m_httpServer && FD_ISSET(m_httpServer->getFD(), &readfds)) {
|
||||||
|
newData = isHttp = true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
if (newData) {
|
||||||
TCPSocket* socket = m_tcpServer->newSocket();
|
TCPSocket* socket = (isHttp ? m_httpServer : m_tcpServer)->newSocket();
|
||||||
if (socket == NULL)
|
if (socket == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Connection* connection = new Connection(socket, m_netQueue);
|
Connection* connection = new Connection(socket, isHttp, m_netQueue);
|
||||||
if (connection == NULL)
|
if (connection == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
connection->start("connection");
|
connection->start("connection");
|
||||||
m_connections.push_back(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
@@ -26,36 +26,36 @@
|
|||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
/** \file network.h */
|
/** \file network.h */
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
/** forward declaration for class connection */
|
/** Forward declaration for @a Connection. */
|
||||||
class 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
|
class NetMessage
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* constructs a new instance with data received from the client.
|
* Constructor.
|
||||||
* @param data from client.
|
* @param isHttp whether this is a HTTP message.
|
||||||
* @param listening whether the client is in listening mode.
|
|
||||||
* @param listenSince start timestamp of listening update.
|
|
||||||
*/
|
*/
|
||||||
NetMessage(const string data, const bool listening, const time_t listenSince)
|
NetMessage(const bool isHttp)
|
||||||
: m_data(data), m_resultSet(false), m_disconnect(false), m_listening(listening), m_listenSince(listenSince)
|
: m_isHttp(isHttp), m_resultSet(false), m_disconnect(false), m_listening(false), m_listenSince(0)
|
||||||
{
|
{
|
||||||
pthread_mutex_init(&m_mutex, NULL);
|
pthread_mutex_init(&m_mutex, NULL);
|
||||||
pthread_cond_init(&m_cond, NULL);
|
pthread_cond_init(&m_cond, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* destructor.
|
* Destructor.
|
||||||
*/
|
*/
|
||||||
~NetMessage()
|
~NetMessage()
|
||||||
{
|
{
|
||||||
@@ -73,10 +73,55 @@ private:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the data string.
|
* Add request data received from the client.
|
||||||
* @return the data string.
|
* @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.
|
* Wait for the result being set and return the result string.
|
||||||
@@ -89,9 +134,13 @@ public:
|
|||||||
while (!m_resultSet)
|
while (!m_resultSet)
|
||||||
pthread_cond_wait(&m_cond, &m_mutex);
|
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);
|
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)
|
void setResult(const string result, const bool listening, const time_t listenUntil, const bool disconnect)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_lock(&m_mutex);
|
||||||
m_result = result;
|
m_result = result;
|
||||||
m_disconnect = disconnect;
|
m_disconnect = disconnect;
|
||||||
m_listening = listening;
|
m_listening = listening;
|
||||||
m_listenSince = listenUntil;
|
m_listenSince = listenUntil;
|
||||||
m_resultSet = true;
|
m_resultSet = true;
|
||||||
pthread_mutex_lock(&m_mutex);
|
|
||||||
pthread_cond_signal(&m_cond);
|
pthread_cond_signal(&m_cond);
|
||||||
pthread_mutex_unlock(&m_mutex);
|
pthread_mutex_unlock(&m_mutex);
|
||||||
}
|
}
|
||||||
@@ -118,7 +167,7 @@ public:
|
|||||||
* @param listenSince set to the start time from which to add updates (inclusive).
|
* @param listenSince set to the start time from which to add updates (inclusive).
|
||||||
* @return whether the client is in listening mode.
|
* @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.
|
* Return whether the client shall be disconnected.
|
||||||
@@ -127,28 +176,31 @@ public:
|
|||||||
bool isDisconnect() { return m_disconnect; }
|
bool isDisconnect() { return m_disconnect; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** the data string */
|
/** whether this is a HTTP message. */
|
||||||
string m_data;
|
const bool m_isHttp;
|
||||||
|
|
||||||
|
/** the request string. */
|
||||||
|
string m_request;
|
||||||
|
|
||||||
/** whether the result was already set. */
|
/** whether the result was already set. */
|
||||||
bool m_resultSet;
|
bool m_resultSet;
|
||||||
|
|
||||||
/** the result string */
|
/** the result string. */
|
||||||
string m_result;
|
string m_result;
|
||||||
|
|
||||||
/** set to true when the client shall be disconnected. */
|
/** set to true when the client shall be disconnected. */
|
||||||
bool m_disconnect;
|
bool m_disconnect;
|
||||||
|
|
||||||
/** mutex variable for exclusive lock */
|
/** mutex variable for exclusive lock. */
|
||||||
pthread_mutex_t m_mutex;
|
pthread_mutex_t m_mutex;
|
||||||
|
|
||||||
/** condition variable for exclusive lock */
|
/** condition variable for exclusive lock. */
|
||||||
pthread_cond_t m_cond;
|
pthread_cond_t m_cond;
|
||||||
|
|
||||||
/** whether the client is in listening mode */
|
/** whether the client is in listening mode. */
|
||||||
bool m_listening;
|
bool m_listening;
|
||||||
|
|
||||||
/** start timestamp of listening update */
|
/** start timestamp of listening update. */
|
||||||
time_t m_listenSince;
|
time_t m_listenSince;
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -161,12 +213,13 @@ class Connection : public Thread
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* create a new connection instance.
|
* Constructor.
|
||||||
* @param socket the tcp socket for communication.
|
* @param socket the @a TCPSocket for communication.
|
||||||
* @param netQueue the remote queue for network messages.
|
* @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)
|
Connection(TCPSocket* socket, const bool isHttp, WQueue<NetMessage*>* netQueue)
|
||||||
: m_socket(socket), m_netQueue(netQueue), m_listening(false)
|
: m_isHttp(isHttp), m_socket(socket), m_netQueue(netQueue)
|
||||||
{ m_id = ++m_ids; }
|
{ m_id = ++m_ids; }
|
||||||
|
|
||||||
virtual ~Connection() { if (m_socket) delete m_socket; }
|
virtual ~Connection() { if (m_socket) delete m_socket; }
|
||||||
@@ -176,35 +229,35 @@ public:
|
|||||||
virtual void run();
|
virtual void run();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* close active connection.
|
* Stop this connection.
|
||||||
*/
|
*/
|
||||||
virtual void stop() { m_notify.notify(); Thread::stop(); }
|
virtual void stop() { m_notify.notify(); Thread::stop(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return own connection id.
|
* Return the ID of this connection.
|
||||||
* @return id of current connection.
|
* @return the ID of this connection.
|
||||||
*/
|
*/
|
||||||
int getID() { return m_id; }
|
int getID() { return m_id; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** the tcp socket instance */
|
/** whether this is a HTTP connection. */
|
||||||
|
const bool m_isHttp;
|
||||||
|
|
||||||
|
/** the @a TCPSocket for communication. */
|
||||||
TCPSocket* m_socket;
|
TCPSocket* m_socket;
|
||||||
|
|
||||||
/** remote queue for network messages */
|
/** the remote @a WQueue for handling @a NetMessage instances. */
|
||||||
WQueue<NetMessage*>* m_netQueue;
|
WQueue<NetMessage*>* m_netQueue;
|
||||||
|
|
||||||
/** notification object for shutdown procedure */
|
/** notification object for shutdown procedure. */
|
||||||
Notify m_notify;
|
Notify m_notify;
|
||||||
|
|
||||||
/** id of current connection */
|
/** the ID of this connection. */
|
||||||
int m_id;
|
int m_id;
|
||||||
|
|
||||||
/** sumary for opened connections */
|
/** the IF of the last opened connection. */
|
||||||
static int m_ids;
|
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.
|
* create a network instance and listening for incoming connections.
|
||||||
* @param local true to accept connections only for local host.
|
* @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.
|
* @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.
|
* destructor.
|
||||||
@@ -244,9 +298,12 @@ private:
|
|||||||
/** the @a MainLoop queue for transferring @a NetMessage instances. */
|
/** the @a MainLoop queue for transferring @a NetMessage instances. */
|
||||||
WQueue<NetMessage*>* m_netQueue;
|
WQueue<NetMessage*>* m_netQueue;
|
||||||
|
|
||||||
/** the @a TCPServer instance. */
|
/** the command line @a TCPServer instance. */
|
||||||
TCPServer* m_tcpServer;
|
TCPServer* m_tcpServer;
|
||||||
|
|
||||||
|
/** the HTTP @a TCPServer instance, or NULL. */
|
||||||
|
TCPServer* m_httpServer;
|
||||||
|
|
||||||
/** @a Notify object for shutdown procedure. */
|
/** @a Notify object for shutdown procedure. */
|
||||||
Notify m_notify;
|
Notify m_notify;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user