mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-08-20 20:08:30 -04:00

- Set request method to GET by default in ApiLocalConnectionHandler to avoid /peers request fail randomly - Use TabView instead of SwipeView to not depend on Qt 5.7.0 (latest version) - AddTrustedNode simplified layout to avoid unexpected behaviour on some phones - Locations add sslid property to root Item to avoid unexpected behaviour when multiple locations are available - TrustedNodesView color connected friends with green and offline with grey - Ignore kdevelop 4 files
127 lines
4.4 KiB
C++
127 lines
4.4 KiB
C++
/*
|
|
* libresapi local socket server
|
|
* Copyright (C) 2016 Gioacchino Mazzurco <gio@eigenlab.org>
|
|
*
|
|
* 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 "ApiServerLocal.h"
|
|
#include "JsonStream.h"
|
|
|
|
namespace resource_api{
|
|
|
|
ApiServerLocal::ApiServerLocal(ApiServer* server, const QString &listenPath, QObject *parent) :
|
|
QObject(parent), serverThread(this),
|
|
localListener(server, listenPath) // Must have no parent to be movable to other thread
|
|
{
|
|
localListener.moveToThread(&serverThread);
|
|
serverThread.start();
|
|
}
|
|
|
|
ApiServerLocal::~ApiServerLocal() { serverThread.quit(); }
|
|
|
|
ApiLocalListener::ApiLocalListener(ApiServer *server,
|
|
const QString &listenPath,
|
|
QObject *parent) :
|
|
QObject(parent), mApiServer(server), mLocalServer(this)
|
|
{
|
|
mLocalServer.removeServer(listenPath);
|
|
#if QT_VERSION >= 0x050000
|
|
mLocalServer.setSocketOptions(QLocalServer::UserAccessOption);
|
|
#endif
|
|
connect(&mLocalServer, SIGNAL(newConnection()), this, SLOT(handleConnection()));
|
|
mLocalServer.listen(listenPath);
|
|
}
|
|
|
|
void ApiLocalListener::handleConnection()
|
|
{
|
|
new ApiLocalConnectionHandler(mApiServer,
|
|
mLocalServer.nextPendingConnection(), this);
|
|
}
|
|
|
|
ApiLocalConnectionHandler::ApiLocalConnectionHandler(
|
|
ApiServer* apiServer, QLocalSocket* sock, QObject *parent) :
|
|
QObject(parent), mApiServer(apiServer), mLocalSocket(sock),
|
|
mState(WAITING_PATH)
|
|
{
|
|
connect(mLocalSocket, SIGNAL(disconnected()), this, SLOT(deleteLater()));
|
|
connect(sock, SIGNAL(readyRead()), this, SLOT(handlePendingRequests()));
|
|
}
|
|
|
|
ApiLocalConnectionHandler::~ApiLocalConnectionHandler()
|
|
{
|
|
mLocalSocket->close();
|
|
delete mLocalSocket;
|
|
}
|
|
|
|
void ApiLocalConnectionHandler::handlePendingRequests()
|
|
{
|
|
switch(mState)
|
|
{
|
|
case WAITING_PATH:
|
|
{
|
|
if(mLocalSocket->canReadLine())
|
|
{
|
|
readPath:
|
|
QString rString(mLocalSocket->readLine());
|
|
rString = rString.simplified();
|
|
if (!rString.isEmpty())
|
|
{
|
|
if(rString.startsWith("PUT", Qt::CaseInsensitive)) reqMeth = resource_api::Request::PUT;
|
|
else if (rString.startsWith("DELETE", Qt::CaseInsensitive)) reqMeth = resource_api::Request::DELETE_AA;
|
|
else reqMeth = resource_api::Request::GET;
|
|
if(rString.contains(' ')) rString = rString.split(' ')[1];
|
|
|
|
reqPath = rString.toStdString();
|
|
mState = WAITING_DATA;
|
|
|
|
/* Because QLocalSocket is SOCK_STREAM some clients implementations
|
|
* like the one based on QLocalSocket feel free to send the whole
|
|
* request (PATH + DATA) in a single write(), causing readyRead()
|
|
* signal being emitted only once, in that case we should continue
|
|
* processing without waiting for readyRead() being fired again, so
|
|
* we don't break here as there may be more lines to read */
|
|
}
|
|
else break;
|
|
}
|
|
}
|
|
case WAITING_DATA:
|
|
{
|
|
if(mLocalSocket->canReadLine())
|
|
{
|
|
resource_api::JsonStream reqJson;
|
|
reqJson.setJsonString(std::string(mLocalSocket->readLine().constData()));
|
|
resource_api::Request req(reqJson);
|
|
req.mMethod = reqMeth;
|
|
req.setPath(reqPath);
|
|
std::string resultString = mApiServer->handleRequest(req);
|
|
mLocalSocket->write(resultString.c_str(), resultString.length());
|
|
mLocalSocket->write("\n\0");
|
|
mState = WAITING_PATH;
|
|
|
|
/* Because QLocalSocket is SOCK_STREAM some clients implementations
|
|
* like the one based on QLocalSocket feel free to coalesce multiple
|
|
* upper level write() into a single socket write(), causing
|
|
* readyRead() signal being emitted only once, in that case we should
|
|
* keep processing without waiting for readyRead() being fired again */
|
|
if(mLocalSocket->canReadLine()) goto readPath;
|
|
|
|
// Now there are no more requests to process we can break
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace resource_api
|