js8call/MessageServer.cpp

226 lines
4.9 KiB
C++
Raw Normal View History

#include "MessageServer.h"
2018-02-08 21:28:33 -05:00
#include <QDebug>
2018-02-08 21:28:33 -05:00
MessageServer::MessageServer(QObject *parent) :
QTcpServer(parent)
{
}
2018-02-08 21:28:33 -05:00
MessageServer::~MessageServer(){
stop();
}
2018-02-08 21:28:33 -05:00
bool MessageServer::start()
2018-02-08 21:28:33 -05:00
{
if(isListening()){
qDebug() << "MessageServer already listening:" << m_host << m_port;
return false;
2018-02-08 21:28:33 -05:00
}
auto address = QHostAddress();
2020-04-04 14:58:30 -04:00
if(m_host.isEmpty() || !address.setAddress(m_host)){
qDebug() << "MessageServer address invalid:" << m_host << m_port;
return false;
}
2018-02-08 21:28:33 -05:00
2020-04-04 14:58:30 -04:00
if(m_port <= 0){
qDebug() << "MessageServer port invalid:" << m_host << m_port;
return false;
}
bool listening = listen(address, m_port);
qDebug() << "MessageServer listening:" << listening << m_host << m_port;
2018-02-08 21:28:33 -05:00
return listening;
}
2018-02-08 21:28:33 -05:00
void MessageServer::stop()
2018-02-08 21:28:33 -05:00
{
// disconnect all clients
foreach(auto client, m_clients){
client->close();
2018-02-08 21:28:33 -05:00
}
// then close the server
close();
2018-02-08 21:28:33 -05:00
}
void MessageServer::setServer(QString host, quint16 port){
bool listening = isListening();
if(listening && (m_host != host || m_port != port)){
stop();
2018-02-08 21:28:33 -05:00
}
m_host = host;
m_port = port;
if(listening){
start();
2018-02-08 21:28:33 -05:00
}
}
void MessageServer::setPause(bool paused)
2018-02-08 21:28:33 -05:00
{
m_paused = paused;
if(paused){
pauseAccepting();
} else {
resumeAccepting();
2018-02-08 21:28:33 -05:00
}
}
2020-04-04 14:58:30 -04:00
void MessageServer::setMaxConnections(int n){
// set the maximum number of connections allowed
m_maxConnections = n;
// then, prune old ones greater than the max (fifo)
pruneConnections();
}
int MessageServer::activeConnections(){
int i = 0;
foreach(auto client, m_clients){
if(client->isConnected()) i++;
}
return i;
}
void MessageServer::pruneConnections(){
// keep only the n most recent connections (fifo)
if(m_maxConnections && m_maxConnections < activeConnections()){
for(int i = m_maxConnections; i < activeConnections(); i++){
auto client = m_clients.first();
client->close();
m_clients.removeFirst();
}
}
}
void MessageServer::send(const Message &message){
foreach(auto client, m_clients){
if(!client->awaitingResponse(message.id())){
continue;
2018-02-08 21:28:33 -05:00
}
client->send(message);
2018-02-08 21:28:33 -05:00
}
}
void MessageServer::incomingConnection(qintptr handle)
2018-02-08 21:28:33 -05:00
{
qDebug() << "MessageServer incomingConnection" << handle;
auto client = new Client(this, this);
client->setSocket(handle);
#if JS8_MESSAGESERVER_IS_SINGLE_CLIENT
while(!m_clients.isEmpty()){
auto client = m_clients.first();
client->close();
m_clients.removeFirst();
2018-02-08 21:28:33 -05:00
}
#endif
2020-04-04 14:58:30 -04:00
if(m_maxConnections && m_maxConnections <= activeConnections()){
qDebug() << "MessageServer connections full, dropping incoming connection";
client->send(Message("API.ERROR", "Connections Full"));
client->close();
return;
}
m_clients.append(client);
2018-02-08 21:28:33 -05:00
}
Client::Client(MessageServer * server, QObject *parent):
QObject(parent),
m_server {server}
2018-02-08 21:28:33 -05:00
{
setConnected(true);
2018-02-08 21:28:33 -05:00
}
void Client::setSocket(qintptr handle){
m_socket = new QTcpSocket(this);
connect(m_socket, &QTcpSocket::disconnected, this, &Client::onDisconnected);
connect(m_socket, &QTcpSocket::readyRead, this, &Client::readyRead);
m_socket->setSocketDescriptor(handle);
2018-02-08 21:28:33 -05:00
}
void Client::setConnected(bool connected){
m_connected = connected;
2018-02-08 21:28:33 -05:00
}
void Client::close(){
if(!m_socket){
return;
2018-02-08 21:28:33 -05:00
}
m_socket->close();
m_socket = nullptr;
2018-02-08 21:28:33 -05:00
}
void Client::send(const Message &message){
if(!isConnected()){
return;
2018-02-08 21:28:33 -05:00
}
if(!m_socket){
return;
}
if(!m_socket->isOpen()){
qDebug() << "client socket isn't open";
return;
}
qDebug() << "client writing" << message.toJson();
m_socket->write(message.toJson());
m_socket->write("\n");
m_socket->flush();
// remove if needed
if(m_requests.contains(message.id())){
m_requests.remove(message.id());
2018-02-08 21:28:33 -05:00
}
}
2018-03-05 14:49:51 -05:00
void Client::onDisconnected(){
qDebug() << "MessageServer client disconnected";
setConnected(false);
2018-03-05 14:49:51 -05:00
}
2018-08-05 11:33:30 -04:00
void Client::readyRead(){
qDebug() << "MessageServer client readyRead";
while(m_socket->canReadLine()){
auto msg = m_socket->readLine().trimmed();
qDebug() << "-> Client" << m_socket->socketDescriptor() << msg;
if(msg.isEmpty()){
return;
}
QJsonParseError e;
QJsonDocument d = QJsonDocument::fromJson(msg, &e);
if(e.error != QJsonParseError::NoError){
2020-04-04 14:58:30 -04:00
send({"API.ERROR", "Invalid JSON (unparsable)"});
return;
}
if(!d.isObject()){
2020-04-04 14:58:30 -04:00
send({"API.ERROR", "Invalid JSON (not an object)"});
return;
}
Message m;
m.read(d.object());
auto id = m.ensureId();
m_requests[id] = m;
emit m_server->message(m);
}
2018-08-05 11:33:30 -04:00
}