Skip to content

Commit 98fcc23

Browse files
committed
Fix client error handling with new code and some small compile error
1 parent beb467f commit 98fcc23

File tree

5 files changed

+182
-38
lines changed

5 files changed

+182
-38
lines changed

core/aclient.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#pragma once
2+
3+
#include <QObject>
4+
#include "adevice.h"
5+
#include "aclientprovider.h"
6+
#include "types.h"
7+
8+
class AClient : public QObject
9+
{
10+
Q_OBJECT
11+
12+
public:
13+
enum class ClientCommandState {
14+
NOCOMMAND,
15+
WAITINGREPLY, // The command want a reply
16+
WAITINGBDATAREPLY // The command want a binary reply
17+
};
18+
Q_ENUM(ClientCommandState)
19+
20+
AClient(AClientProvider* parent) : QObject(parent) {}
21+
22+
QString name;
23+
bool attached;
24+
ADevice* attachedTo;
25+
bool attachedToRemote = false;
26+
27+
/* This handle all the weird stuff needed for putaddress
28+
You can have straight forward put request like that
29+
putAddress, then data
30+
or weird stuff like putAddress1, putAddress2, data1, data2
31+
*/
32+
unsigned int currentPutSize;
33+
QByteArray recvData;
34+
unsigned int byteReceived;
35+
unsigned int expectedDataSize;
36+
37+
// IPS Stuff
38+
QByteArray ipsData;
39+
unsigned int ipsSize;
40+
41+
/* Attach not returning something, you can have for example
42+
Attach cmd then receive a getAddress before the Attach cmd is done
43+
for some device (like RA that check if RA is valable
44+
*/
45+
bool pendingAttach;
46+
47+
// This is to check if the client does what the current command
48+
// expect it to do
49+
ClientCommandState commandState;
50+
51+
/* This is used for 2 things:
52+
QUSB returns only its version if legacy if not, QUsb2snes-version
53+
For Websocket, this send a reply
54+
*/
55+
bool legacy;
56+
USB2SnesWS::opcode currentOpcode;
57+
58+
59+
virtual void sendData(QByteArray data) = 0;
60+
virtual void sendReply(QStringList list) = 0;
61+
virtual void sendError(Core::ErrorType errorType, QString errorMessage) = 0;
62+
virtual void close() = 0;
63+
64+
signals:
65+
void closed();
66+
void newRequest(Core::MRequest* req);
67+
void binaryData(QByteArray data);
68+
void errorOccured(Core::ErrorType err, QString message);
69+
70+
};

core/websocketprovider.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <QLoggingCategory>
2+
#include "websocketclient.h"
3+
#include "websocketprovider.h"
4+
5+
Q_LOGGING_CATEGORY(log_wsprovider, "WebSocketProvider")
6+
#define sDebug() qCDebug(log_wsprovider)
7+
#define sInfo() qCInfo(log_wsprovider)
8+
9+
WebSocketProvider::WebSocketProvider(QString wsname, QObject* parent) : AClientProvider(parent)
10+
{
11+
m_server = new QWebSocketServer(wsname, QWebSocketServer::NonSecureMode, this);
12+
wsname = "WebSocket Server";
13+
}
14+
15+
bool WebSocketProvider::listen(QHostAddress lAddress, quint16 port)
16+
{
17+
if (!m_server->listen(lAddress, port))
18+
return false;
19+
m_port = port;
20+
connect(m_server, &QWebSocketServer::newConnection, this, &WebSocketProvider::onNewConnection);
21+
connect(m_server, &QWebSocketServer::closed, this, &WebSocketProvider::onClosed);
22+
connect(m_server, &QWebSocketServer::serverError, this, &WebSocketProvider::onServerError);
23+
return true;
24+
}
25+
26+
QString WebSocketProvider::errorString() const
27+
{
28+
return m_server->errorString();
29+
}
30+
31+
void WebSocketProvider::close()
32+
{
33+
m_server->close();
34+
}
35+
36+
void WebSocketProvider::onNewConnection()
37+
{
38+
QWebSocket* newSocket = m_server->nextPendingConnection();
39+
WebSocketClient* newclient = new WebSocketClient(newSocket, this);
40+
emit newClient(newclient);
41+
}
42+
43+
void WebSocketProvider::onClosed()
44+
{
45+
sDebug() << "Webserver on port " << m_port << "Closed";
46+
emit closed();
47+
}
48+
49+
void WebSocketProvider::onServerError(QWebSocketProtocol::CloseCode code)
50+
{
51+
sDebug() << "Websocket error" << code;
52+
}
53+
54+
55+
void WebSocketProvider::deleteClient(AClient *client)
56+
{
57+
delete client;
58+
}

core/websocketprovider.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef WEBSOCKETPROVIDER_H
2+
#define WEBSOCKETPROVIDER_H
3+
4+
#include "aclientprovider.h"
5+
6+
#include <QHostAddress>
7+
#include <QObject>
8+
#include <QStringLiteral>
9+
#include <QWebSocketServer>
10+
11+
class WebSocketProvider : public AClientProvider
12+
{
13+
Q_OBJECT
14+
public:
15+
WebSocketProvider(QString wsname, QObject* parent = nullptr);
16+
bool listen(QHostAddress lAddress, quint16 port);
17+
QString errorString() const;
18+
void close();
19+
20+
private:
21+
QWebSocketServer* m_server;
22+
quint16 m_port;
23+
void onNewConnection();
24+
void onClosed();
25+
void onServerError(QWebSocketProtocol::CloseCode code);
26+
27+
signals:
28+
void closed();
29+
// AClientProvider interface
30+
public:
31+
void deleteClient(AClient *client);
32+
};
33+
34+
#endif // WEBSOCKETPROVIDER_H

core/wsserver.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ void WSServer::onNewRequest(MRequest* req)
329329
(isFileCommand(req->opcode) && !dev->hasFileCommands()))
330330
{
331331
client->sendError(ErrorType::DeviceError, QString("The device does not support the command %1").arg(cmdMetaEnum.valueToKey(static_cast<int>(req->opcode))));
332+
return ;
332333
}
333334
currentRequests[dev] = req;
334335
devicesInfos[dev].currentCommand = req->opcode;
@@ -338,13 +339,10 @@ void WSServer::onNewRequest(MRequest* req)
338339
sDebug() << client->attachedTo->name() << "Adding request in queue " << *req << "(" << pendingRequests[client->attachedTo].size() << ")";
339340
addToPendingRequest(client->attachedTo, req);
340341
}
341-
342342
}
343343
if (isValidUnAttached(req->opcode))
344344
executeServerRequest(req);
345345
return ;
346-
LError:
347-
clientError(client); //FIXME
348346
}
349347

350348
void WSServer::addToPendingRequest(ADevice* device, MRequest *req)
@@ -372,8 +370,7 @@ void WSServer::onBinaryMessageReceived(const QByteArray& data)
372370
sDebug() << client->name << "Received binary data" << data.size() << "Expected size: " << client->expectedDataSize;
373371
if (client->commandState != AClient::ClientCommandState::WAITINGBDATAREPLY && client->expectedDataSize == 0)
374372
{
375-
setError(ErrorType::ProtocolError, "Sending binary data when nothing waiting for it");
376-
clientError(client);
373+
client->sendError(ErrorType::ProtocolError, "Sending binary data when nothing waiting for it");
377374
return;
378375
}
379376
// IPS stuff, please don't queue IPS data ~~
@@ -414,8 +411,7 @@ void WSServer::onBinaryMessageReceived(const QByteArray& data)
414411
dev->writeData(data);
415412
} else { // There is too much data
416413
dev->writeData(data.left(client->currentPutSize));
417-
setError(ErrorType::ProtocolError, "Sending too much binary data");
418-
clientError(client);
414+
client->sendError(ErrorType::ProtocolError, "Sending too much binary data");
419415
}
420416
return ;
421417
}
@@ -555,7 +551,7 @@ void WSServer::cleanUpDevice(ADevice* device)
555551
}
556552
for (AClient* client : toDiscard)
557553
{
558-
client->sendError(Core::ErrorType::DeviceError, "Device closed");
554+
client->sendError(m_errorType, m_errorString);
559555
}
560556
if (devInfo.currentClient != nullptr)
561557
devInfo.currentClient = nullptr;

core/wsservercommands.cpp

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ bool WSServer::isControlCommand(USB2SnesWS::opcode opcode)
4747

4848
#define CMD_TAKE_ONE_ARG(cmd) if (req->arguments.size() != 1) \
4949
{ \
50-
setError(ErrorType::CommandError, QString("%1 command take one argument").arg(cmd)); \
51-
clientError(client); \
50+
client->sendError(ErrorType::CommandError, QString("%1 command take one argument").arg(cmd)); \
5251
return ; \
5352
}
5453

@@ -169,8 +168,7 @@ void WSServer::executeRequest(MRequest *req)
169168
case USB2SnesWS::PutFile : {
170169
if (req->arguments.size() != 2)
171170
{
172-
setError(ErrorType::CommandError, "PutFile command take 2 arguments (file1, SizeInHex)");
173-
clientError(client);
171+
client->sendError(ErrorType::CommandError, "PutFile command take 2 arguments (file1, SizeInHex)");
174172
return ;
175173
}
176174
bool ok;
@@ -183,8 +181,7 @@ void WSServer::executeRequest(MRequest *req)
183181
case USB2SnesWS::Rename : {
184182
if (req->arguments.size() != 2)
185183
{
186-
setError(ErrorType::CommandError, "Rename command take 2 arguments (file1, file2)");
187-
clientError(client);
184+
client->sendError(ErrorType::CommandError, "Rename command take 2 arguments (file1, file2)");
188185
return ;
189186
}
190187
device->fileCommand(SD2Snes::opcode::MV, QVector<QByteArray>() << req->arguments.at(0).toLatin1()
@@ -211,8 +208,7 @@ void WSServer::executeRequest(MRequest *req)
211208
case USB2SnesWS::GetAddress : {
212209
if (req->arguments.size() < 2)
213210
{
214-
setError(ErrorType::CommandError, "GetAddress commands take at least 2 arguments (AddressInHex, SizeInHex)");
215-
clientError(client);
211+
client->sendError(ErrorType::CommandError, "GetAddress commands take at least 2 arguments (AddressInHex, SizeInHex)");
216212
return ;
217213
}
218214
connect(device, &ADevice::getDataReceived, this, &WSServer::onDeviceGetDataReceived, Qt::UniqueConnection);
@@ -222,8 +218,7 @@ void WSServer::executeRequest(MRequest *req)
222218
{
223219
if (req->arguments.at(1).toUInt(&ok, 16) == 0)
224220
{
225-
setError(ErrorType::CommandError, "GetAddress - trying to read 0 byte");
226-
clientError(client);
221+
client->sendError(ErrorType::CommandError, "GetAddress - trying to read 0 byte");
227222
return ;
228223
}
229224
device->getAddrCommand(req->space, req->arguments.at(0).toUInt(&ok, 16), req->arguments.at(1).toUInt(&ok, 16));
@@ -239,8 +234,7 @@ void WSServer::executeRequest(MRequest *req)
239234
unsigned usize = req->arguments.at(i + 1).toUInt(&ok, 16);
240235
if (usize == 0)
241236
{
242-
setError(ErrorType::CommandError, "GetAddress - trying to read 0 byte");
243-
clientError(client);
237+
client->sendError(ErrorType::CommandError, "GetAddress - trying to read 0 byte");
244238
return ;
245239
}
246240
if (usize > 255)
@@ -249,8 +243,7 @@ void WSServer::executeRequest(MRequest *req)
249243
{
250244
split = true;
251245
} else {
252-
setError(ErrorType::CommandError, "GetAddress - VGet with a size > 255");
253-
clientError(client);
246+
client->sendError(ErrorType::CommandError, "GetAddress - VGet with a size > 255");
254247
return ;
255248
}
256249
}
@@ -288,8 +281,7 @@ void WSServer::executeRequest(MRequest *req)
288281
case USB2SnesWS::PutAddress : {
289282
if (req->arguments.size() < 2)
290283
{
291-
setError(ErrorType::CommandError, "PutAddress command take at least 2 arguments (AddressInHex, SizeInHex)");
292-
clientError(client);
284+
client->sendError(ErrorType::CommandError, "PutAddress command take at least 2 arguments (AddressInHex, SizeInHex)");
293285
return ;
294286
}
295287
bool ok;
@@ -302,8 +294,7 @@ void WSServer::executeRequest(MRequest *req)
302294
putSize = req->arguments.at(1).toUInt(&ok, 16);
303295
if (putSize == 0)
304296
{
305-
setError(ErrorType::CommandError, "PutAddress - trying to write 0 byte");
306-
clientError(client);
297+
client->sendError(ErrorType::CommandError, "PutAddress - trying to write 0 byte");
307298
return ;
308299
}
309300
if (req->flags.isEmpty())
@@ -322,8 +313,7 @@ void WSServer::executeRequest(MRequest *req)
322313
{
323314
if (req->arguments.at(i + 1).toUInt(&ok, 16) == 0)
324315
{
325-
setError(ErrorType::CommandError, "PutAddress - trying to write 0 byte");
326-
clientError(client);
316+
client->sendError(ErrorType::CommandError, "PutAddress - trying to write 0 byte");
327317
return ;
328318
}
329319
vputArgs.append(QPair<unsigned int, quint8>(req->arguments.at(i).toUInt(&ok, 16), req->arguments.at(i + 1).toUShort(&ok, 16)));
@@ -379,8 +369,7 @@ void WSServer::executeRequest(MRequest *req)
379369
case USB2SnesWS::PutIPS : {
380370
if (req->arguments.size() < 2)
381371
{
382-
setError(ErrorType::CommandError, "PutIPS command take at least 2 arguments (Name, SizeInHex)");
383-
clientError(client);
372+
client->sendError(ErrorType::CommandError, "PutIPS command take at least 2 arguments (Name, SizeInHex)");
384373
return ;
385374
}
386375
bool ok;
@@ -391,8 +380,8 @@ void WSServer::executeRequest(MRequest *req)
391380
}
392381
default:
393382
{
394-
setError(ErrorType::ProtocolError, "Invalid command or non implemented");
395-
clientError(client);
383+
client->sendError(ErrorType::ProtocolError, "Invalid command or non implemented");
384+
return ;
396385
}
397386
}
398387

@@ -607,8 +596,7 @@ void WSServer::cmdAttach(MRequest *req)
607596
}
608597
if (devFact->attachError().isEmpty() == false)
609598
{
610-
setError(ErrorType::CommandError, "Attach Error with " + deviceToAttach + " - " + devFact->attachError());
611-
clientError(req->owner);
599+
req->owner->sendError(ErrorType::CommandError, "Attach Error with " + deviceToAttach + " - " + devFact->attachError());
612600
return ;
613601
}
614602
}
@@ -621,8 +609,7 @@ void WSServer::cmdAttach(MRequest *req)
621609
sDebug() << "Trying to open device";
622610
if (devGet->open() == false)
623611
{
624-
setError(ErrorType::CommandError, "Attach: Can't open the device on " + deviceToAttach);
625-
clientError(req->owner);
612+
req->owner->sendError(ErrorType::CommandError, "Attach: Can't open the device on " + deviceToAttach);
626613
return;
627614
}
628615
}
@@ -636,8 +623,7 @@ void WSServer::cmdAttach(MRequest *req)
636623
processCommandQueue(devGet);
637624
return ;
638625
} else {
639-
setError(ErrorType::CommandError, "Trying to Attach to an unknow device");
640-
clientError(req->owner);
626+
req->owner->sendError(ErrorType::CommandError, "Trying to Attach to an unknow device");
641627
return ;
642628
}
643629
}

0 commit comments

Comments
 (0)