picloud add server logics

This commit is contained in:
2021-04-06 17:49:07 +03:00
parent be0db84147
commit fcf9f0f80e
9 changed files with 178 additions and 26 deletions

View File

@@ -24,6 +24,7 @@
PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode) : PIIODevice(path, mode) { PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode) : PIIODevice(path, mode) {
tcp.setRole(PICloud::TCP::Client); tcp.setRole(PICloud::TCP::Client);
setName("cloud_client"); setName("cloud_client");
is_connected = false;
} }
@@ -67,6 +68,7 @@ bool PICloudClient::openDevice() {
bool PICloudClient::closeDevice() { bool PICloudClient::closeDevice() {
is_connected = false;
eth.stop(); eth.stop();
eth.close(); eth.close();
return true; return true;
@@ -95,11 +97,25 @@ void PICloudClient::readed(uchar *data, int size) {
mutex_buff.lock(); mutex_buff.lock();
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba); PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba);
if (hdr.second == tcp.role()) { if (hdr.second == tcp.role()) {
piCoutObj << "readed" << ba.toHex(); switch (hdr.first) {
buff.append(data, size); case PICloud::TCP::Connect:
cond_buff.notifyOne(); if (tcp.parseConnect(ba) == 0) is_connected = true;
break;
case PICloud::TCP::Disconnect:
is_connected = false;
eth.stop();
eth.close();
break;
case PICloud::TCP::Data:
buff.append(data, size);
cond_buff.notifyOne();
break;
default:
break;
}
//piCoutObj << "readed" << ba.toHex();
} }
mutex_buff.unlock(); mutex_buff.unlock();
while (buff.size() > threadedReadBufferSize()) piMSleep(100); while (buff.size_s() > threadedReadBufferSize()) piMSleep(100);
} }

View File

@@ -29,11 +29,12 @@ PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode)
PICloudServer::~PICloudServer() { PICloudServer::~PICloudServer() {
for (auto & c : clients) {
c.stop();
c.close();
}
stop(); stop();
eth.stop();
for (auto & c : clients) {
c->stop();
c->close();
}
close(); close();
} }
@@ -66,9 +67,9 @@ bool PICloudServer::openDevice() {
bool PICloudServer::closeDevice() { bool PICloudServer::closeDevice() {
eth.stop(); eth.stop();
for (auto & c : clients) { for (auto c : clients) {
c.stop(); c->stop();
c.close(); c->close();
} }
eth.close(); eth.close();
return true; return true;
@@ -85,7 +86,17 @@ int PICloudServer::writeDevice(const void * data, int max_size) {
} }
PICloudServer::Client::Client(PICloudServer * srv) : server(srv) { void PICloudServer::clientDisconnect(uint client_id) {
tcp.sendDisconnected(&eth, client_id);
}
int PICloudServer::sendData(const PIByteArray & data, uint client_id) {
return tcp.sendData(&eth, data, client_id);
}
PICloudServer::Client::Client(PICloudServer * srv, uint id) : server(srv), client_id(id) {
} }
@@ -95,10 +106,67 @@ bool PICloudServer::Client::openDevice() {
} }
bool PICloudServer::Client::closeDevice() {
server->clientDisconnect(client_id);
return true;
}
int PICloudServer::Client::readDevice(void * read_to, int max_size) {
//piCoutObj << "readDevice";
mutex_buff.lock();
cond_buff.wait(mutex_buff, [this](){return !buff.isEmpty();});
int sz = piMini(max_size, buff.size());
memcpy(read_to, buff.data(), sz);
buff.remove(0, sz);
mutex_buff.unlock();
return sz;
}
int PICloudServer::Client::writeDevice(const void * data, int max_size) {
return server->sendData(PIByteArray(data, max_size), client_id);
}
void PICloudServer::Client::pushBuffer(const PIByteArray & ba) {
mutex_buff.lock();
buff.append(ba);
cond_buff.notifyOne();
mutex_buff.unlock();
while (buff.size_s() > threadedReadBufferSize()) piMSleep(100);
}
void PICloudServer::readed(uchar *data, int size) { void PICloudServer::readed(uchar *data, int size) {
PIByteArray ba(data, size); PIByteArray ba(data, size);
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba); PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba);
if (hdr.second == tcp.role()) { if (hdr.second == tcp.role()) {
piCoutObj << "readed" << ba.toHex(); switch (hdr.first) {
case PICloud::TCP::Connect: {
uint id = tcp.parseConnect(ba);
Client * oc = index_clients.value(id, nullptr);
if (oc) {
tcp.sendDisconnected(&eth, id);
} else {
Client * c = new Client(this, id);
clients << c;
index_clients.insert(id, c);
newConnection(c);
}
} break;
case PICloud::TCP::Disconnect: {
uint id = tcp.parseDisconnect(ba);
Client * oc = index_clients.value(id, nullptr);
if (oc) oc->close();
} break;
case PICloud::TCP::Data: {
PIPair<uint, PIByteArray> d = tcp.parseDataServer(ba);
Client * oc = index_clients.value(d.first, nullptr);
if (oc && !d.second.isEmpty()) oc->pushBuffer(d.second);
} break;
default:
break;
}
} }
} }

View File

@@ -61,6 +61,14 @@ void PICloud::TCP::sendConnected(PIEthernet * eth, uint client_id) {
} }
void PICloud::TCP::sendDisconnected(PIEthernet * eth, uint client_id) {
header.type = PICloud::TCP::Disconnect;
PIByteArray ba;
ba << header << client_id;
eth->send(ba);
}
void PICloud::TCP::sendData(PIEthernet * eth, const PIByteArray & data) { void PICloud::TCP::sendData(PIEthernet * eth, const PIByteArray & data) {
header.type = PICloud::TCP::Data; header.type = PICloud::TCP::Data;
PIByteArray ba; PIByteArray ba;
@@ -71,6 +79,16 @@ void PICloud::TCP::sendData(PIEthernet * eth, const PIByteArray & data) {
} }
int PICloud::TCP::sendData(PIEthernet * eth, const PIByteArray & data, uint client_id) {
header.type = PICloud::TCP::Data;
PIByteArray ba;
ba << header << client_id;
ba.append(data);
if (eth->send(ba)) return data.size_s();
else return -1;
}
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> PICloud::TCP::parseHeader(PIByteArray & ba) { PIPair<PICloud::TCP::Type, PICloud::TCP::Role> PICloud::TCP::parseHeader(PIByteArray & ba) {
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> ret; PIPair<PICloud::TCP::Type, PICloud::TCP::Role> ret;
ret.first = Invalid; ret.first = Invalid;
@@ -88,11 +106,6 @@ PIPair<PICloud::TCP::Type, PICloud::TCP::Role> PICloud::TCP::parseHeader(PIByteA
PIByteArray PICloud::TCP::parseData(PIByteArray & ba) { PIByteArray PICloud::TCP::parseData(PIByteArray & ba) {
if (header.role == Server) {
PIString client;
ba >> client;
return ba;
}
if (header.role == Client) { if (header.role == Client) {
return ba; return ba;
} }
@@ -100,8 +113,33 @@ PIByteArray PICloud::TCP::parseData(PIByteArray & ba) {
} }
PIString PICloud::TCP::parseConnect(PIByteArray & ba) { PIPair<uint, PIByteArray> PICloud::TCP::parseDataServer(PIByteArray & ba) {
PIPair<uint, PIByteArray> ret;
ret.first = 0;
if (header.role == Server) {
ba >> ret.first;
ret.second = ba;
}
return ret;
}
PIString PICloud::TCP::parseConnect_d(PIByteArray & ba) {
PIString ret; PIString ret;
ba >> ret; ba >> ret;
return ret; return ret;
} }
uint PICloud::TCP::parseConnect(PIByteArray & ba) {
uint ret;
ba >> ret;
return ret;
}
uint PICloud::TCP::parseDisconnect(PIByteArray & ba) {
uint ret;
ba >> ret;
return ret;
}

View File

@@ -49,6 +49,7 @@ private:
PIByteArray buff; PIByteArray buff;
PIMutex mutex_buff; PIMutex mutex_buff;
PIConditionVariable cond_buff; PIConditionVariable cond_buff;
std::atomic_bool is_connected;
}; };
#endif // PICLOUDCLIENT_H #endif // PICLOUDCLIENT_H

View File

@@ -24,6 +24,7 @@
#define PICLOUDSERVER_H #define PICLOUDSERVER_H
#include "picloudbase.h" #include "picloudbase.h"
#include "piconditionvar.h"
class PIP_CLOUD_EXPORT PICloudServer : public PIIODevice, private PICloudBase class PIP_CLOUD_EXPORT PICloudServer : public PIIODevice, private PICloudBase
@@ -36,12 +37,22 @@ public:
class Client : public PIIODevice { class Client : public PIIODevice {
PIIODEVICE(PICloudServer::Client) PIIODEVICE(PICloudServer::Client)
friend class PICloudServer;
public: public:
Client(PICloudServer * srv = nullptr); Client(PICloudServer * srv = nullptr, uint id = 0);
protected: protected:
bool openDevice(); bool openDevice();
bool closeDevice();
int readDevice(void * read_to, int max_size);
int writeDevice(const void * data, int max_size);
private: private:
void pushBuffer(const PIByteArray & ba);
PICloudServer * server; PICloudServer * server;
uint client_id;
PIByteArray buff;
PIMutex mutex_buff;
PIConditionVariable cond_buff;
}; };
void setServerName(const PIString & server_name); void setServerName(const PIString & server_name);
@@ -56,8 +67,11 @@ protected:
private: private:
EVENT_HANDLER2(void, readed, uchar * , data, int, size); EVENT_HANDLER2(void, readed, uchar * , data, int, size);
void clientDisconnect(uint client_id);
int sendData(const PIByteArray & data, uint client_id);
PIVector<Client> clients; PIVector<Client *> clients;
PIMap<uint, Client *> index_clients;
}; };
#endif // PICLOUDSERVER_H #endif // PICLOUDSERVER_H

View File

@@ -58,10 +58,15 @@ public:
void sendStart(PIEthernet * eth); void sendStart(PIEthernet * eth);
void sendConnected(PIEthernet * eth, uint client_id); void sendConnected(PIEthernet * eth, uint client_id);
void sendDisconnected(PIEthernet * eth, uint client_id);
void sendData(PIEthernet * eth, const PIByteArray & data); void sendData(PIEthernet * eth, const PIByteArray & data);
int sendData(PIEthernet * eth, const PIByteArray & data, uint client_id);
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba); PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba);
PIByteArray parseData(PIByteArray & ba); PIByteArray parseData(PIByteArray & ba);
PIString parseConnect(PIByteArray & ba); PIPair<uint, PIByteArray> parseDataServer(PIByteArray & ba);
PIString parseConnect_d(PIByteArray & ba);
uint parseConnect(PIByteArray & ba);
uint parseDisconnect(PIByteArray & ba);
private: private:
struct Header { struct Header {

View File

@@ -40,7 +40,9 @@ void CloudServer::printStatus() {
for (auto c: clients) { for (auto c: clients) {
piCout << " " << c->address() << c->clientId(); piCout << " " << c->address() << c->clientId();
} }
for (auto c: clients) c->sendData(PIByteArray::fromHex("000000")); for (auto c: clients) {
server->sendData(PIByteArray::fromHex("000000")); c->sendData(PIByteArray::fromHex("000000"));
server->sendDataToClient(PIByteArray::fromHex("000000"), c->clientId());
}
} }

View File

@@ -36,7 +36,14 @@ void DispatcherClient::sendConnected() {
void DispatcherClient::sendData(const PIByteArray & data) { void DispatcherClient::sendData(const PIByteArray & data) {
tcp.sendData(eth, data); if (tcp.role() == PICloud::TCP::Client) tcp.sendData(eth, data);
else piCoutObj << "error sendData, invalid role";
}
void DispatcherClient::sendDataToClient(const PIByteArray & data, uint client_id) {
if (tcp.role() == PICloud::TCP::Server) tcp.sendData(eth, data, client_id);
else piCoutObj << "error sendDataToClient, invalid role";
} }
@@ -72,7 +79,7 @@ void DispatcherClient::readed(uchar *data, int size) {
switch (hdr.first) { switch (hdr.first) {
case PICloud::TCP::Connect: { case PICloud::TCP::Connect: {
tcp.setRole(hdr.second); tcp.setRole(hdr.second);
PIString sn = tcp.parseConnect(ba); PIString sn = tcp.parseConnect_d(ba);
if (hdr.second == PICloud::TCP::Server) registerServer(sn, this); if (hdr.second == PICloud::TCP::Server) registerServer(sn, this);
if (hdr.second == PICloud::TCP::Client) registerClient(sn, this); if (hdr.second == PICloud::TCP::Client) registerClient(sn, this);
return;} return;}

View File

@@ -14,6 +14,7 @@ public:
void close(); void close();
void sendConnected(); void sendConnected();
void sendData(const PIByteArray & data); void sendData(const PIByteArray & data);
void sendDataToClient(const PIByteArray & data, uint client_id);
PIString address(); PIString address();
uint clientId() const {return client_id;} uint clientId() const {return client_id;}
EVENT1(disconnectEvent, DispatcherClient *, client) EVENT1(disconnectEvent, DispatcherClient *, client)