diff --git a/CMakeLists.txt b/CMakeLists.txt index 54396e2d..499999bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -358,7 +358,7 @@ if (NOT CROSSTOOLS) pip_find_lib(sodium) if(sodium_FOUND) pip_module(crypt "sodium" "PIP crypt support" "" "") - pip_module(cloud "pip_crypt" "PIP cloud support" "" "") + pip_module(cloud "pip_io_utils" "PIP cloud support" "" "") endif() diff --git a/libs/cloud/picloudbase.cpp b/libs/cloud/picloudbase.cpp index 8ccd9f72..6873421e 100644 --- a/libs/cloud/picloudbase.cpp +++ b/libs/cloud/picloudbase.cpp @@ -1,6 +1,6 @@ #include "picloudbase.h" -PICloudBase::PICloudBase() : eth(PIEthernet::TCP_Client) { +PICloudBase::PICloudBase() : eth(PIEthernet::TCP_Client), streampacker(ð), tcp(&streampacker) { } diff --git a/libs/cloud/picloudclient.cpp b/libs/cloud/picloudclient.cpp index c5d960f6..b548adbc 100644 --- a/libs/cloud/picloudclient.cpp +++ b/libs/cloud/picloudclient.cpp @@ -21,10 +21,19 @@ #include "picloudtcp.h" -PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode) : PIIODevice(path, mode) { +PICloudClient::PICloudClient(const PIString & path, PIIODevice::DeviceMode mode) : PIIODevice(path, mode), PICloudBase() { tcp.setRole(PICloud::TCP::Client); setName("cloud_client"); is_connected = false; + CONNECTL(ð, connected, [this](){tcp.sendStart();}); + CONNECTU(&streampacker, packetReceiveEvent, this, _readed); + CONNECTL(ð, disconnected, [this](bool){ + piCoutObj << "disconnected"; + opened_ = false; + is_connected = false; + cond_connect.notifyOne(); + piMSleep(100); + }); } @@ -49,17 +58,17 @@ bool PICloudClient::openDevice() { piCout << "PICloudClient open device" << path(); bool op = eth.connect(path(), false); if (op) { - CONNECTL(ð, connected, [this](){tcp.sendStart(ð);}); - CONNECTU(ð, threadedReadEvent, this, readed); - CONNECTL(ð, disconnected, [this](bool){ - opened_ = false; - eth.close(); - piCoutObj << "disconnected";// << !isOpened() << isClosed(); - piMSleep(100); - }); + mutex_buff.lock(); eth.startThreadedRead(); - tcp.sendStart(ð); - return true; + bool conn_ok = cond_connect.waitFor(mutex_buff, (int)eth.readTimeout(), [this](){return isConnected();}); + piCoutObj << "conn_ok" << conn_ok; + mutex_buff.unlock(); + if (!conn_ok) { + eth.stop(); + eth.close(); + piMSleep(100); + } + return isConnected(); } else { eth.close(); return false; @@ -92,14 +101,16 @@ int PICloudClient::writeDevice(const void * data, int max_size) { } -void PICloudClient::readed(uchar *data, int size) { - PIByteArray ba(data, size); +void PICloudClient::_readed(PIByteArray & ba) { mutex_buff.lock(); PIPair hdr = tcp.parseHeader(ba); if (hdr.second == tcp.role()) { switch (hdr.first) { case PICloud::TCP::Connect: - if (tcp.parseConnect(ba) == 0) is_connected = true; + if (tcp.parseConnect(ba) == 1) { + is_connected = true; + cond_connect.notifyOne(); + } break; case PICloud::TCP::Disconnect: is_connected = false; @@ -107,7 +118,7 @@ void PICloudClient::readed(uchar *data, int size) { eth.close(); break; case PICloud::TCP::Data: - buff.append(data, size); + buff.append(ba); cond_buff.notifyOne(); break; default: diff --git a/libs/cloud/picloudserver.cpp b/libs/cloud/picloudserver.cpp index 51ce349a..eba14c78 100644 --- a/libs/cloud/picloudserver.cpp +++ b/libs/cloud/picloudserver.cpp @@ -21,10 +21,17 @@ PICloudServer::PICloudServer(const PIString & path, PIIODevice::DeviceMode mode) : PIIODevice(path, mode), PICloudBase() { - PIString name = "PCS_" + PIString::fromNumber(randomi()%1000); + PIString server_name = "PCS_" + PIString::fromNumber(randomi()%1000); tcp.setRole(PICloud::TCP::Server); - tcp.setServerName(name); - setName("cloud_server__" + name); + tcp.setServerName(server_name); + setName("cloud_server__" + server_name); + CONNECTU(&streampacker, packetReceiveEvent, this, _readed); + CONNECTL(ð, connected, [this](){tcp.sendStart();}); + CONNECTL(ð, disconnected, [this](bool){ + piCoutObj << "disconnected"; + opened_ = false; + piMSleep(100); + }); } @@ -49,15 +56,7 @@ bool PICloudServer::openDevice() { piCout << "PICloudServer open device" << path(); bool op = eth.connect(path(), false); if (op) { - CONNECTU(ð, threadedReadEvent, this, readed); - CONNECTL(ð, connected, [this](){tcp.sendStart(ð);}); - CONNECTL(ð, disconnected, [this](bool){ - opened_ = false; - eth.close(); - piCoutObj << "disconnected" << !isOpened() << isClosed(); - }); eth.startThreadedRead(); - tcp.sendStart(ð); return true; } eth.close(); @@ -87,12 +86,12 @@ int PICloudServer::writeDevice(const void * data, int max_size) { void PICloudServer::clientDisconnect(uint client_id) { - tcp.sendDisconnected(ð, client_id); + tcp.sendDisconnected(client_id); } int PICloudServer::sendData(const PIByteArray & data, uint client_id) { - return tcp.sendData(ð, data, client_id); + return tcp.sendData(data, client_id); } @@ -138,8 +137,7 @@ void PICloudServer::Client::pushBuffer(const PIByteArray & ba) { } -void PICloudServer::readed(uchar *data, int size) { - PIByteArray ba(data, size); +void PICloudServer::_readed(PIByteArray & ba) { PIPair hdr = tcp.parseHeader(ba); if (hdr.second == tcp.role()) { switch (hdr.first) { @@ -147,7 +145,7 @@ void PICloudServer::readed(uchar *data, int size) { uint id = tcp.parseConnect(ba); Client * oc = index_clients.value(id, nullptr); if (oc) { - tcp.sendDisconnected(ð, id); + tcp.sendDisconnected(id); } else { Client * c = new Client(this, id); clients << c; diff --git a/libs/cloud/picloudtcp.cpp b/libs/cloud/picloudtcp.cpp index 642f7024..10805070 100644 --- a/libs/cloud/picloudtcp.cpp +++ b/libs/cloud/picloudtcp.cpp @@ -21,6 +21,7 @@ #include "picrypt.h" #include "pichunkstream.h" #include "piethernet.h" +#include "pistreampacker.h" const char hash_def_key[] = "_picrypt_"; @@ -31,9 +32,9 @@ PICloud::TCP::Header::Header() { } -PICloud::TCP::TCP() { -} +PICloud::TCP::TCP(PIStreamPacker * s) : streampacker(s) { +} void PICloud::TCP::setRole(PICloud::TCP::Role r) { header.role = r; @@ -45,53 +46,55 @@ void PICloud::TCP::setServerName(const PIString & server_name) { } -void PICloud::TCP::sendStart(PIEthernet * eth) { +void PICloud::TCP::sendStart() { + piCout << "sendStart"; header.type = PICloud::TCP::Connect; PIByteArray ba; ba << header << sname; - eth->send(ba); + streampacker->send(ba); } -void PICloud::TCP::sendConnected(PIEthernet * eth, uint client_id) { +void PICloud::TCP::sendConnected(uint client_id) { header.type = PICloud::TCP::Connect; PIByteArray ba; ba << header << client_id; - eth->send(ba); + streampacker->send(ba); } -void PICloud::TCP::sendDisconnected(PIEthernet * eth, uint client_id) { +void PICloud::TCP::sendDisconnected(uint client_id) { header.type = PICloud::TCP::Disconnect; PIByteArray ba; ba << header << client_id; - eth->send(ba); + streampacker->send(ba); } -void PICloud::TCP::sendData(PIEthernet * eth, const PIByteArray & data) { +void PICloud::TCP::sendData(const PIByteArray & data) { header.type = PICloud::TCP::Data; PIByteArray ba; ba << header; ba.append(data); // piCout << "sendData" << ba.toHex(); - eth->send(ba); + streampacker->send(ba); } -int PICloud::TCP::sendData(PIEthernet * eth, const PIByteArray & data, uint client_id) { +int PICloud::TCP::sendData(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; + streampacker->send(ba); + return data.size_s(); } PIPair PICloud::TCP::parseHeader(PIByteArray & ba) { PIPair ret; - ret.first = Invalid; + ret.first = InvalidType; + ret.second = InvalidRole; if (ba.size() < sizeof(Header)) return ret; PICloud::TCP::Header hdr; ba >> hdr; diff --git a/libs/main/cloud/picloudbase.h b/libs/main/cloud/picloudbase.h index 7ad4b7dd..858846d8 100644 --- a/libs/main/cloud/picloudbase.h +++ b/libs/main/cloud/picloudbase.h @@ -25,6 +25,7 @@ #include "picloudtcp.h" #include "piethernet.h" +#include "pistreampacker.h" class PICloudBase @@ -34,6 +35,7 @@ public: protected: PIEthernet eth; + PIStreamPacker streampacker; PICloud::TCP tcp; }; diff --git a/libs/main/cloud/picloudclient.h b/libs/main/cloud/picloudclient.h index 08a0f0cd..c1bbfce7 100644 --- a/libs/main/cloud/picloudclient.h +++ b/libs/main/cloud/picloudclient.h @@ -41,14 +41,17 @@ public: protected: bool openDevice(); bool closeDevice(); + bool isConnected() const {return is_connected;} int readDevice(void * read_to, int max_size); int writeDevice(const void * data, int max_size); private: - EVENT_HANDLER2(void, readed, uchar * , data, int, size); + EVENT_HANDLER1(void, _readed, PIByteArray &, data); PIByteArray buff; PIMutex mutex_buff; + PIMutex mutex_connect; PIConditionVariable cond_buff; + PIConditionVariable cond_connect; std::atomic_bool is_connected; }; diff --git a/libs/main/cloud/picloudserver.h b/libs/main/cloud/picloudserver.h index cd762216..484fdb4c 100644 --- a/libs/main/cloud/picloudserver.h +++ b/libs/main/cloud/picloudserver.h @@ -66,7 +66,7 @@ protected: int writeDevice(const void * data, int max_size); private: - EVENT_HANDLER2(void, readed, uchar * , data, int, size); + EVENT_HANDLER1(void, _readed, PIByteArray &, ba); void clientDisconnect(uint client_id); int sendData(const PIByteArray & data, uint client_id); diff --git a/libs/main/cloud/picloudtcp.h b/libs/main/cloud/picloudtcp.h index a5201260..e62ca2e6 100644 --- a/libs/main/cloud/picloudtcp.h +++ b/libs/main/cloud/picloudtcp.h @@ -28,6 +28,7 @@ class PIEthernet; +class PIStreamPacker; namespace PICloud { @@ -40,27 +41,28 @@ public: }; enum Role { + InvalidRole = 0, Server = 1, Client = 2, }; enum Type { - Invalid = 0, + InvalidType = 0, Connect = 1, Disconnect = 2, Data = 3, }; - TCP(); + TCP(PIStreamPacker * s); void setRole(Role r); Role role() const {return (Role)header.role;} void setServerName(const PIString & server_name); - void sendStart(PIEthernet * eth); - void sendConnected(PIEthernet * eth, uint client_id); - void sendDisconnected(PIEthernet * eth, uint client_id); - void sendData(PIEthernet * eth, const PIByteArray & data); - int sendData(PIEthernet * eth, const PIByteArray & data, uint client_id); + void sendStart(); + void sendConnected(uint client_id); + void sendDisconnected(uint client_id); + void sendData(const PIByteArray & data); + int sendData(const PIByteArray & data, uint client_id); PIPair parseHeader(PIByteArray & ba); PIByteArray parseData(PIByteArray & ba); PIPair parseDataServer(PIByteArray & ba); @@ -78,6 +80,7 @@ private: Header header; PIString sname; + PIStreamPacker * streampacker; }; } diff --git a/libs/main/io_utils/pistreampacker.h b/libs/main/io_utils/pistreampacker.h index f9777ee4..9b6d2fbd 100644 --- a/libs/main/io_utils/pistreampacker.h +++ b/libs/main/io_utils/pistreampacker.h @@ -91,7 +91,7 @@ public: //! Returns \a Progress info about receiving Progress progressReceive() const; - EVENT1(packetReceiveEvent, PIByteArray, data) + EVENT1(packetReceiveEvent, PIByteArray &, data) EVENT1(sendRequest, PIByteArray, data) //! \handlers diff --git a/utils/cloud_dispatcher/cloudserver.cpp b/utils/cloud_dispatcher/cloudserver.cpp index 66343413..386c2b54 100644 --- a/utils/cloud_dispatcher/cloudserver.cpp +++ b/utils/cloud_dispatcher/cloudserver.cpp @@ -21,6 +21,7 @@ PIString CloudServer::serverName() const { void CloudServer::addClient(DispatcherClient * c) { clients << c; index_clients.insert(c->clientId(), c); + c->sendConnected(); } diff --git a/utils/cloud_dispatcher/dispatcherclient.cpp b/utils/cloud_dispatcher/dispatcherclient.cpp index 7388466f..fca8acd6 100644 --- a/utils/cloud_dispatcher/dispatcherclient.cpp +++ b/utils/cloud_dispatcher/dispatcherclient.cpp @@ -2,9 +2,9 @@ #include "picloudtcp.h" -DispatcherClient::DispatcherClient(PIEthernet * eth_, int id) : eth(eth_), authorised(false), client_id(id) { +DispatcherClient::DispatcherClient(PIEthernet * eth_, int id) : authorised(false), eth(eth_), streampacker(eth_), tcp(&streampacker), client_id(id) { CONNECTU(&disconnect_tm, tickEvent, eth, close); - CONNECTU(eth, threadedReadEvent, this, readed); + CONNECTU(&streampacker, packetReceiveEvent, this, readed); CONNECTU(eth, disconnected, this, disconnected); piCoutObj << "client connected" << eth->sendAddress(); } @@ -31,18 +31,19 @@ void DispatcherClient::close() { void DispatcherClient::sendConnected() { - tcp.sendConnected(eth, client_id); + piCoutObj << "sendConnected"; + tcp.sendConnected(1); } void DispatcherClient::sendData(const PIByteArray & data) { - if (tcp.role() == PICloud::TCP::Client) tcp.sendData(eth, data); + if (tcp.role() == PICloud::TCP::Client) tcp.sendData(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); + if (tcp.role() == PICloud::TCP::Server) tcp.sendData(data, client_id); else piCoutObj << "error sendDataToClient, invalid role"; } @@ -53,11 +54,10 @@ void DispatcherClient::disconnected(bool withError) { } -void DispatcherClient::readed(uchar *data, int size) { +void DispatcherClient::readed(PIByteArray & ba) { // piCout << size; - PIByteArray ba(data, size); PIPair hdr = tcp.parseHeader(ba); - if (hdr.first == PICloud::TCP::Invalid) { + if (hdr.first == PICloud::TCP::InvalidType) { disconnected(true); return; } diff --git a/utils/cloud_dispatcher/dispatcherclient.h b/utils/cloud_dispatcher/dispatcherclient.h index 2cd8acae..c4bc3534 100644 --- a/utils/cloud_dispatcher/dispatcherclient.h +++ b/utils/cloud_dispatcher/dispatcherclient.h @@ -3,6 +3,7 @@ #include "piethernet.h" #include "picloudtcp.h" +#include "pistreampacker.h" class DispatcherClient: public PIObject { @@ -23,12 +24,13 @@ public: EVENT1(dataReaded, PIByteArray, ba) private: - EVENT_HANDLER2(void, readed, uchar * , data, int, size); + EVENT_HANDLER1(void, readed, PIByteArray &, data); EVENT_HANDLER1(void, disconnected, bool, withError); - PIEthernet * eth; PITimer disconnect_tm; bool authorised; + PIEthernet * eth; + PIStreamPacker streampacker; PICloud::TCP tcp; uint client_id; };