Commit 99048c1cbf0e97b4906a75462ece3f7db4979387
0 parents
Initial commit. dependencies not resolved yet.
Showing
15 changed files
with
1661 additions
and
0 deletions
.gitignore
0 → 100644
CMakeLists.txt
0 → 100644
1 | +++ a/CMakeLists.txt | |
1 | +cmake_minimum_required(VERSION 3.0) | |
2 | + | |
3 | +# Check to see where cmake is located. | |
4 | +if( IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake ) | |
5 | + LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) | |
6 | +elseif( IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../cmake ) | |
7 | + LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) | |
8 | +else() | |
9 | + return() | |
10 | +endif() | |
11 | + | |
12 | +# Check to see if there is versioning information available | |
13 | +if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/osdev_versioning/cmake) | |
14 | + LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/osdev_versioning/cmake) | |
15 | + include(osdevversion) | |
16 | +endif() | |
17 | + | |
18 | +include(projectheader) | |
19 | +project_header(osdev_network) | |
20 | + | |
21 | +add_subdirectory(src) | |
22 | +add_subdirectory(tests) | |
23 | + | |
24 | +# include(packaging) | |
25 | +# package_component() | ... | ... |
README.md
0 → 100644
1 | +++ a/README.md | ... | ... |
src/CMakeLists.txt
0 → 100644
1 | +++ a/src/CMakeLists.txt | |
1 | +cmake_minimum_required(VERSION 3.0) | |
2 | +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake) | |
3 | +include(projectheader) | |
4 | +project_header(network) | |
5 | + | |
6 | +find_package( Qt5Core REQUIRED ) | |
7 | +find_package( Qt5Network REQUIRED ) | |
8 | + | |
9 | +include_directories( SYSTEM | |
10 | + ${Qt5Core_INCLUDE_DIRS} | |
11 | + ${Qt5Network_INCLUDE_DIRS} | |
12 | +) | |
13 | + | |
14 | +include(compiler) | |
15 | + | |
16 | +include_directories( | |
17 | + ${CMAKE_CURRENT_SOURCE_DIR}/../config | |
18 | + ${CMAKE_CURRENT_SOURCE_DIR}/../global | |
19 | + ${CMAKE_CURRENT_SOURCE_DIR}/../logutils | |
20 | + ${CMAKE_CURRENT_SOURCE_DIR}/../datatypes | |
21 | +) | |
22 | + | |
23 | +set(SRC_LIST | |
24 | + ${CMAKE_CURRENT_SOURCE_DIR}/poolmanager.cpp | |
25 | + ${CMAKE_CURRENT_SOURCE_DIR}/socketcontainer.cpp | |
26 | + ${CMAKE_CURRENT_SOURCE_DIR}/tcpinterface.cpp | |
27 | + ${CMAKE_CURRENT_SOURCE_DIR}/tcpsocket.cpp | |
28 | + | |
29 | +) | |
30 | + | |
31 | +include(qtmoc) | |
32 | +create_mocs( SRC_LIST MOC_LIST | |
33 | + ${CMAKE_CURRENT_SOURCE_DIR}/poolmanager.h | |
34 | + ${CMAKE_CURRENT_SOURCE_DIR}/tcpinterface.h | |
35 | + ${CMAKE_CURRENT_SOURCE_DIR}/tcpsocket.h | |
36 | +) | |
37 | + | |
38 | +link_directories( | |
39 | + ${CMAKE_BINARY_DIR}/lib | |
40 | +) | |
41 | + | |
42 | +include(library) | |
43 | +add_libraries( | |
44 | + ${Qt5Core_LIBRARIES} | |
45 | + ${Qt5Network_LIBRARIES} | |
46 | + global | |
47 | + logutils | |
48 | + datatypes | |
49 | +) | |
50 | + | |
51 | +include(installation) | |
52 | +install_component() | ... | ... |
src/msgparser.cpp
0 → 100644
1 | +++ a/src/msgparser.cpp | |
1 | +/* **************************************************************************** | |
2 | + * Copyright 2019 Open Systems Development BV * | |
3 | + * * | |
4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
5 | + * copy of this software and associated documentation files (the "Software"), * | |
6 | + * to deal in the Software without restriction, including without limitation * | |
7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
9 | + * Software is furnished to do so, subject to the following conditions: * | |
10 | + * * | |
11 | + * The above copyright notice and this permission notice shall be included in * | |
12 | + * all copies or substantial portions of the Software. * | |
13 | + * * | |
14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
20 | + * DEALINGS IN THE SOFTWARE. * | |
21 | + * ***************************************************************************/ | |
22 | +#include "msgparser.h" | |
23 | + | |
24 | +namespace osdev { | |
25 | +namespace components { | |
26 | + | |
27 | +const QString MsgParser::s_messageElementTag = "message"; | |
28 | +const QString MsgParser::s_sourceElementTag = "source"; | |
29 | +const QString MsgParser::s_destElementTag = "dest"; | |
30 | +const QString MsgParser::s_actionElementTag = "action"; | |
31 | +const QString MsgParser::s_dataElementTag = "data"; | |
32 | +const QString MsgParser::s_idAttributeTag = "id"; | |
33 | + | |
34 | +MsgParser::MsgParser(QObject* _parent) | |
35 | + : QObject(_parent) | |
36 | + , m_message() | |
37 | + , m_sourceId() | |
38 | + , m_destId() | |
39 | + , m_actionId(-1) | |
40 | + , m_actionData() | |
41 | +{ | |
42 | +} | |
43 | + | |
44 | +MsgParser::~MsgParser() | |
45 | +{ | |
46 | +} | |
47 | + | |
48 | +void MsgParser::createMsg(const QString& sourceId, const QString& destId, | |
49 | + int actionId, const QString& actionData) | |
50 | +{ | |
51 | + static const QString xmlVar("<%1 %2='%3'/>"); | |
52 | + static const QString xmlData("<%1>%2</%1>"); | |
53 | + static const QString xmlMessage("<%1>%2 %3 %4 %5</%1>"); | |
54 | + | |
55 | + QString src = xmlVar.arg(s_sourceElementTag).arg(s_idAttributeTag).arg(sourceId); | |
56 | + QString dst = xmlVar.arg(s_destElementTag).arg(s_idAttributeTag).arg(destId); | |
57 | + QString action = xmlVar.arg(s_actionElementTag).arg(s_idAttributeTag).arg(actionId); | |
58 | + QString data = xmlData.arg(s_dataElementTag).arg(actionData); | |
59 | + | |
60 | + m_message = xmlMessage.arg(s_messageElementTag).arg(src).arg(dst).arg(action).arg(data); | |
61 | +} | |
62 | + | |
63 | +void MsgParser::createMsg(const QString& sourceId, const QString& destId, | |
64 | + int actionId, xercesc_2_7::DOMDocument* actionData) | |
65 | +{ | |
66 | + QString msgData; | |
67 | + | |
68 | + CXmlParser* pSerializer = new CXmlParser(); | |
69 | + // Store the complete message. | |
70 | + msgData = pSerializer->serialize(actionData); | |
71 | + delete pSerializer; | |
72 | + | |
73 | + static const QString xmlVar("<%1 %2='%3'/>"); | |
74 | + static const QString xmlData("<%1>%2</%1>"); | |
75 | + static const QString xmlMessage("<%1>%2 %3 %4 %5</%1>"); | |
76 | + | |
77 | + QString src = xmlVar.arg(s_sourceElementTag).arg(s_idAttributeTag).arg(sourceId); | |
78 | + QString dst = xmlVar.arg(s_destElementTag).arg(s_idAttributeTag).arg(destId); | |
79 | + QString action = xmlVar.arg(s_actionElementTag).arg(s_idAttributeTag).arg(actionId); | |
80 | + QString data = xmlData.arg(s_dataElementTag).arg(msgData); | |
81 | + | |
82 | + m_message = xmlMessage.arg(s_messageElementTag).arg(src).arg(dst).arg(action).arg(data); | |
83 | +} | |
84 | + | |
85 | +void MsgParser::parseMsg(const QString& msg) | |
86 | +{ | |
87 | + CXmlParser parser; | |
88 | + | |
89 | + DOMDocument* domDocument = parser.parse(msg); | |
90 | + DOMNode* rootNode = domDocument->getDocumentElement(); | |
91 | + | |
92 | + DOMNode* node = rootNode->getFirstChild(); | |
93 | + if (CXerces::nodeName(node) == sourceElementTag) | |
94 | + { | |
95 | + m_sourceId = CXerces::getNodeAttribute(node, qPrintable(s_idAttributeTag)); | |
96 | + } | |
97 | + | |
98 | + node = node->getNextSibling(); | |
99 | + if (CXerces::nodeName(node) == destElementTag) | |
100 | + { | |
101 | + m_destId = CXerces::getNodeAttribute(node, qPrintable(s_idAttributeTag)); | |
102 | + } | |
103 | + | |
104 | + node = node->getNextSibling(); | |
105 | + if (CXerces::nodeName(node) == s_actionElementTag) | |
106 | + { | |
107 | + m_actionId = CXerces::getNodeAttribute(node, qPrintable(s_idAttributeTag)).toInt(); | |
108 | + } | |
109 | + | |
110 | + node = node->getNextSibling(); | |
111 | + if (CXerces::nodeName(node) == s_dataElementTag) | |
112 | + { | |
113 | + m_actionData = parser.serialize(node); | |
114 | + } | |
115 | +} | |
116 | + | |
117 | +QString MsgParser::getMsg() const | |
118 | +{ | |
119 | + return m_message; | |
120 | +} | |
121 | + | |
122 | +QString MsgParser::getSourceId() const | |
123 | +{ | |
124 | + return m_sourceId; | |
125 | +} | |
126 | + | |
127 | +QString MsgParser::getDestId() const | |
128 | +{ | |
129 | + return m_destId; | |
130 | +} | |
131 | + | |
132 | +int MsgParser::getActionId() const | |
133 | +{ | |
134 | + return m_actionId; | |
135 | +} | |
136 | + | |
137 | +QString MsgParser::getActionData() const | |
138 | +{ | |
139 | + return m_actionData; | |
140 | +} | |
141 | + | |
142 | +} | |
143 | +} | ... | ... |
src/msgparser.h
0 → 100644
1 | +++ a/src/msgparser.h | |
1 | +/* **************************************************************************** | |
2 | + * Copyright 2019 Open Systems Development BV * | |
3 | + * * | |
4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
5 | + * copy of this software and associated documentation files (the "Software"), * | |
6 | + * to deal in the Software without restriction, including without limitation * | |
7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
9 | + * Software is furnished to do so, subject to the following conditions: * | |
10 | + * * | |
11 | + * The above copyright notice and this permission notice shall be included in * | |
12 | + * all copies or substantial portions of the Software. * | |
13 | + * * | |
14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
20 | + * DEALINGS IN THE SOFTWARE. * | |
21 | + * ***************************************************************************/ | |
22 | +// | |
23 | +// Description : | |
24 | +// Revision : | |
25 | +// Confidentiality : | |
26 | +// Dependencies : | |
27 | +// | |
28 | + | |
29 | +#ifndef OSDEV_COMPONENTS_CMSGPARSER_H | |
30 | +#define OSDEV_COMPONENTS_CMSGPARSER_H | |
31 | + | |
32 | +#include <QObject> | |
33 | +#include <QString> | |
34 | +#include <QUuid> | |
35 | + | |
36 | +namespace osdev { | |
37 | +namespace components { | |
38 | + | |
39 | +/** | |
40 | + * @brief The MsgParser class | |
41 | + */ | |
42 | +class MsgParser : public QObject | |
43 | +{ | |
44 | + Q_OBJECT | |
45 | + | |
46 | +public: | |
47 | + /** | |
48 | + * @brief Constructor | |
49 | + * @param _parent Parent QObject | |
50 | + */ | |
51 | + MsgParser(QObject* _parent = nullptr); | |
52 | + /// @brief Destructor | |
53 | + ~MsgParser(); | |
54 | + | |
55 | + /** | |
56 | + * @brief Create a message with the given parameters | |
57 | + * \param sourceID The source ID of the interface calling this function. | |
58 | + * \param destID The destination ID of the interface receiving the data. | |
59 | + * \param actionId The action to be performed on the data. | |
60 | + * \param actionData The actual data (This must be XML formatted) | |
61 | + */ | |
62 | + void createMsg(const QString& sourceID, const QString& destID, | |
63 | + int actionId, const QString& actionData); | |
64 | + | |
65 | + /** | |
66 | + * @brief Retrieve the fields from the specified message | |
67 | + * @param msg Message to parse | |
68 | + */ | |
69 | + void parseMsg(const QString& msg); | |
70 | + | |
71 | + /// @return Message to parse | |
72 | + QString getMsg() const; | |
73 | + /// @return Source ID from the message | |
74 | + QString getSourceId() const; | |
75 | + /// @return Destination ID from the message | |
76 | + QString getDestId() const; | |
77 | + /// @return Action ID from the message | |
78 | + int getActionId() const; | |
79 | + /// @return Action data from the message | |
80 | + QString getActionData() const; | |
81 | + | |
82 | +// void createMsg(const QString& sourceID, const QString& destID, | |
83 | +// int actionId, xercesc_2_7::DOMDocument* actionData); | |
84 | + | |
85 | +private: | |
86 | + QString m_message; ///< Full message | |
87 | + QString m_sourceId; ///< Source ID in the message | |
88 | + QString m_destId; ///< Destination ID in the message | |
89 | + int m_actionId; ///< Action ID in the message | |
90 | + QString m_actionData; ///< Action Data in the message | |
91 | + | |
92 | + static const QString s_messageElementTag; | |
93 | + static const QString s_sourceElementTag; | |
94 | + static const QString s_destElementTag; | |
95 | + static const QString s_actionElementTag; | |
96 | + static const QString s_dataElementTag; | |
97 | + static const QString s_idAttributeTag; | |
98 | +}; | |
99 | + | |
100 | +} // End namespace components | |
101 | +} // End namespace osdev | |
102 | + | |
103 | +#endif /* OSDEV_COMPONENTS_CMSGPARSER_H */ | ... | ... |
src/poolmanager.cpp
0 → 100644
1 | +++ a/src/poolmanager.cpp | |
1 | +/* **************************************************************************** | |
2 | + * Copyright 2019 Open Systems Development BV * | |
3 | + * * | |
4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
5 | + * copy of this software and associated documentation files (the "Software"), * | |
6 | + * to deal in the Software without restriction, including without limitation * | |
7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
9 | + * Software is furnished to do so, subject to the following conditions: * | |
10 | + * * | |
11 | + * The above copyright notice and this permission notice shall be included in * | |
12 | + * all copies or substantial portions of the Software. * | |
13 | + * * | |
14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
20 | + * DEALINGS IN THE SOFTWARE. * | |
21 | + * ***************************************************************************/ | |
22 | +#include "poolmanager.h" | |
23 | +#include "log.h" | |
24 | +#include <QCoreApplication> | |
25 | + | |
26 | +namespace osdev { | |
27 | +namespace components { | |
28 | + | |
29 | +PoolManager::PoolManager(bool bServer, | |
30 | + const QString& ipAddress, | |
31 | + int portNumber, | |
32 | + int maxTcpConnections, | |
33 | + int maxUdpConnections, | |
34 | + QObject *_parent ) | |
35 | + : QObject( _parent ) | |
36 | + , m_pServer( nullptr ) | |
37 | + , m_pSocketContainer( new SocketContainer() ) | |
38 | + , m_pSocket( nullptr ) | |
39 | + , m_inputBuffer() | |
40 | + , m_outputBuffer() | |
41 | + , m_bServer( bServer ) | |
42 | + , m_ipAddress( ipAddress ) | |
43 | + , m_portNumber( portNumber ) | |
44 | + , m_maxTcpConnections( maxTcpConnections ) | |
45 | + , m_maxUdpConnections( maxUdpConnections ) | |
46 | +{ | |
47 | +} | |
48 | + | |
49 | +PoolManager::~PoolManager() | |
50 | +{ | |
51 | + delete m_pSocketContainer; | |
52 | + m_pSocketContainer = nullptr; | |
53 | +} | |
54 | +/*************************************************************************** | |
55 | + * Server Section | |
56 | + ***************************************************************************/ | |
57 | +void PoolManager::slotNewConnection() | |
58 | +{ | |
59 | + // Create the socket, pass the pendingconnection and add it to our channelList. | |
60 | + | |
61 | + QTcpSocket* nextConnection = m_pServer->nextPendingConnection(); | |
62 | + if( nextConnection ) | |
63 | + { | |
64 | + m_pSocket = new TcpSocket( nextConnection ); | |
65 | + m_pSocketContainer->addSocket( m_pSocket ); | |
66 | + | |
67 | + // Connect the socket to the poolmanager | |
68 | + this->connectSocketSignals( m_pSocket ); | |
69 | + } | |
70 | +} | |
71 | + | |
72 | +bool PoolManager::startNetworkLayer() | |
73 | +{ | |
74 | + bool bResult = false; | |
75 | + | |
76 | + if( m_bServer ) | |
77 | + { | |
78 | + m_pServer = new QTcpServer; // Create our server object | |
79 | + | |
80 | + connect( m_pServer, SIGNAL( newConnection() ), | |
81 | + this, SLOT( slotNewConnection() ) ); | |
82 | + | |
83 | + m_pServer->setMaxPendingConnections( m_maxTcpConnections ); | |
84 | + bResult = m_pServer->listen( QHostAddress(m_ipAddress), static_cast<quint16>(m_portNumber) ); | |
85 | + if( bResult ) | |
86 | + { | |
87 | + LogDebug("interfaceplugin", "Server started"); | |
88 | + } | |
89 | + else | |
90 | + { | |
91 | + LogError("interfaceplugin", "Server error : " + m_pServer->errorString()); | |
92 | + } | |
93 | + } | |
94 | + else | |
95 | + { | |
96 | + // Here we start a couple of client connections. | |
97 | + for( int nCounter = 0; nCounter < m_maxTcpConnections; nCounter++ ) | |
98 | + { | |
99 | + m_pSocket = new TcpSocket( m_ipAddress, m_portNumber ); | |
100 | + bResult = m_pSocket->isConnected(); | |
101 | + if( bResult ) | |
102 | + { | |
103 | + m_pSocketContainer->addSocket( m_pSocket ); | |
104 | + this->connectSocketSignals( m_pSocket ); | |
105 | + emit message( 0, 0, osdev::components::gEventConnectionEstablished, 0 ); | |
106 | + } | |
107 | + else | |
108 | + { | |
109 | + LogDebug("[PoolManager::startNetworkLayer()]", QString( "Socket Error : %1" ).arg( m_pSocket->showError() ) ); | |
110 | + delete m_pSocket; | |
111 | + } | |
112 | + } | |
113 | + } | |
114 | + return bResult; | |
115 | +} | |
116 | + | |
117 | +void PoolManager::slotDataSent( TcpSocket *pSocket ) | |
118 | +{ | |
119 | + m_pSocketContainer->setChannelFree( pSocket ); | |
120 | + | |
121 | + // Check for delayed messages and send the first one. | |
122 | + this->resendDelayedMessages(); | |
123 | +} | |
124 | + | |
125 | +void PoolManager::slotReceivingData( TcpSocket *pSocket ) | |
126 | +{ | |
127 | + m_pSocketContainer->setChannelBusy( pSocket ); | |
128 | +} | |
129 | + | |
130 | +void PoolManager::slotDataReceived( const QString &sData, TcpSocket *pSocket ) | |
131 | +{ | |
132 | + // Create a unique ticket | |
133 | + QString l_sTicket = createBufferTicket(); | |
134 | + | |
135 | + // Store the dat with the ticket as key | |
136 | + m_outputBuffer.insert( l_sTicket, sData ); | |
137 | + | |
138 | + // Free the channel. | |
139 | + m_pSocketContainer->setChannelFree( pSocket ); | |
140 | + | |
141 | + // Signal the upper layer we have new data available. | |
142 | + emit dataPresent( l_sTicket ); | |
143 | + | |
144 | + // Resend first delayed messages if there are any. | |
145 | + this->resendDelayedMessages(); | |
146 | +} | |
147 | + | |
148 | +void PoolManager::sendData( const QString &sData ) | |
149 | +{ | |
150 | + // Get a free channel and signal the data we want to send. | |
151 | + TcpSocket *pSocket = m_pSocketContainer->getFreeSocket(); | |
152 | + if( pSocket ) | |
153 | + { | |
154 | + m_pSocketContainer->setChannelBusy( pSocket ); | |
155 | + emit signalSendData( sData, pSocket ); | |
156 | + QCoreApplication::processEvents(); | |
157 | + } | |
158 | + else | |
159 | + { | |
160 | + LogError("NetworkInterface", QString("No free channel available. Storing for delayed send. Message number: %1").arg(m_inputBuffer.size() + 1)); | |
161 | + m_inputBuffer.append( sData ); | |
162 | + } | |
163 | +} | |
164 | + | |
165 | +QString PoolManager::createBufferTicket() | |
166 | +{ | |
167 | + return QUuid::createUuid().toString(); | |
168 | +} | |
169 | + | |
170 | +QString PoolManager::getData(const QString& sTicket ) | |
171 | +{ | |
172 | + if( m_outputBuffer.contains( sTicket ) ) | |
173 | + { | |
174 | + return m_outputBuffer.take( sTicket ); | |
175 | + } | |
176 | + else | |
177 | + { | |
178 | + return QString( "[ERROR : ] No data present in outputbuffer under ticket : %1 " ).arg( sTicket ); | |
179 | + } | |
180 | +} | |
181 | + | |
182 | +void PoolManager::connectSocketSignals( TcpSocket* l_pSocket) | |
183 | +{ | |
184 | + // First we connect the socket -> poolmanager | |
185 | + connect( l_pSocket, SIGNAL( signalDataReceived( const QString&, TcpSocket* ) ), | |
186 | + this, SLOT( slotDataReceived( const QString&, TcpSocket* ) ) ); | |
187 | + | |
188 | + connect( l_pSocket, SIGNAL( signalDataSent( TcpSocket* ) ), | |
189 | + this, SLOT( slotDataSent( TcpSocket* ) ) ); | |
190 | + | |
191 | + connect( l_pSocket, SIGNAL( signalReceivingData( TcpSocket* ) ), | |
192 | + this, SLOT( slotReceivingData( TcpSocket* ) ) ); | |
193 | + | |
194 | + connect( l_pSocket, SIGNAL( signalConnected( TcpSocket* ) ), | |
195 | + this, SLOT( slotConnected( TcpSocket* ) ) ); | |
196 | + | |
197 | + connect( l_pSocket, SIGNAL( signalDisconnected( TcpSocket* ) ), | |
198 | + this, SLOT( slotDisconnected( TcpSocket* ) ) ); | |
199 | + | |
200 | + // And now the poolmanager -> socket | |
201 | + connect( this, SIGNAL( signalSendData( const QString&, TcpSocket* ) ), | |
202 | + l_pSocket, SLOT( slotSendData( const QString&, TcpSocket* ) ) ); | |
203 | + | |
204 | +} | |
205 | + | |
206 | +void PoolManager::resendDelayedMessages() | |
207 | +{ | |
208 | + while( m_inputBuffer.size() > 0 ) // Check for delayed messages | |
209 | + { | |
210 | + if( m_pSocketContainer->getFreeSocket() ) // Check if there is a free channel | |
211 | + { | |
212 | + // Always send the first available message (FIFO) | |
213 | + this->sendData( m_inputBuffer.takeFirst() ); | |
214 | + LogDebug("[PoolManager::resendDelayedMessages]", QString( "Number of queued messages : %1 ").arg( m_inputBuffer.size() ) ); | |
215 | + } | |
216 | + else | |
217 | + { | |
218 | + // Warn if there is a socket available.... | |
219 | + LogDebug( "[PoolManager::resendDelayedMessages]", QString( "No free Socket Available (yet)" ) ); | |
220 | + } | |
221 | + } | |
222 | +} | |
223 | + | |
224 | +void PoolManager::slotConnected( TcpSocket *pSocket ) | |
225 | +{ | |
226 | + Q_UNUSED( pSocket ); | |
227 | + | |
228 | + emit message( 0, 0, osdev::components::gEventConnectionEstablished, 0 ); | |
229 | +} | |
230 | + | |
231 | +void PoolManager::slotDisconnected( TcpSocket *pSocket ) | |
232 | +{ | |
233 | + LogError("NetworkInterface", "Socket disconnected unexpectantly."); | |
234 | + LogError("NetworkInterface", pSocket->showError()); | |
235 | + | |
236 | + // emit message( 0, 0, gEventConnectionLost, 0 ); | |
237 | + | |
238 | + m_pSocketContainer->removeSocket( pSocket ); | |
239 | + delete pSocket; | |
240 | +} | |
241 | + | |
242 | +} /* End namespace components */ | |
243 | +} /* End namespace osdev */ | ... | ... |
src/poolmanager.h
0 → 100644
1 | +++ a/src/poolmanager.h | |
1 | +/* **************************************************************************** | |
2 | + * Copyright 2019 Open Systems Development BV * | |
3 | + * * | |
4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
5 | + * copy of this software and associated documentation files (the "Software"), * | |
6 | + * to deal in the Software without restriction, including without limitation * | |
7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
9 | + * Software is furnished to do so, subject to the following conditions: * | |
10 | + * * | |
11 | + * The above copyright notice and this permission notice shall be included in * | |
12 | + * all copies or substantial portions of the Software. * | |
13 | + * * | |
14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
20 | + * DEALINGS IN THE SOFTWARE. * | |
21 | + * ***************************************************************************/ | |
22 | +#ifndef OSDEV_COMPONENTS_CPOOLMANAGER_H | |
23 | +#define OSDEV_COMPONENTS_CPOOLMANAGER_H | |
24 | + | |
25 | +/*************************************************************************** | |
26 | + * Global Includes | |
27 | + ***************************************************************************/ | |
28 | +#include <QObject> | |
29 | +#include <QString> | |
30 | +#include <QUuid> | |
31 | +#include <QHash> | |
32 | +#include <QTcpServer> | |
33 | +#include <QList> | |
34 | + | |
35 | +/*************************************************************************** | |
36 | + * Local Includes | |
37 | + ***************************************************************************/ | |
38 | +#include "eventcodes.h" // Make the codes known. | |
39 | + | |
40 | +#include "socketcontainer.h" | |
41 | +#include "tcpsocket.h" | |
42 | + | |
43 | +namespace osdev { | |
44 | +namespace components { | |
45 | + | |
46 | +/** | |
47 | + * @brief Handles a pool of network connections | |
48 | + */ | |
49 | +class PoolManager : public QObject | |
50 | +{ | |
51 | + Q_OBJECT | |
52 | + | |
53 | +public: | |
54 | + /** | |
55 | + * @brief Constructor | |
56 | + * @param bServer True for server-mode, false for client-mode (Server is default). | |
57 | + * @param ipAddress IP-address to listen at (server-mode) or to connect to | |
58 | + * (client-mode) | |
59 | + * @param portNumber Portnumber to listen at (server-mode) or to connect to | |
60 | + * (server-mode) | |
61 | + * @param maxTcpConnections Maximum number of TCP connections accepted | |
62 | + * @param maxUdpConnections Maximum number of UDP connections accepted | |
63 | + * (currently unused) | |
64 | + * @param _parent Parent object | |
65 | + */ | |
66 | + PoolManager(bool bServer = false, | |
67 | + const QString& ipAddress = "0.0.0.0", | |
68 | + int portNumber = 3500, | |
69 | + int maxTcpConnections = 10, // The maximum number of connections we accept. | |
70 | + int maxUdpConnections = 10, | |
71 | + QObject *_parent = nullptr ); | |
72 | + | |
73 | + /// @brief Destructor | |
74 | + ~PoolManager(); | |
75 | + | |
76 | + /// Deleted copy-constructor | |
77 | + PoolManager(const PoolManager&) = delete; | |
78 | + /// Deleted assignment operator | |
79 | + PoolManager& operator=(const PoolManager&) = delete; | |
80 | + /// Deleted move-constructor | |
81 | + PoolManager(PoolManager&&) = delete; | |
82 | + /// Deleted move operator | |
83 | + PoolManager& operator=(PoolManager&&) = delete; | |
84 | + | |
85 | + /** | |
86 | + * @brief Get the data for a specified ticket | |
87 | + * @param sTicket Ticket ID | |
88 | + * @return Available data | |
89 | + */ | |
90 | + QString getData( const QString& sTicket ); | |
91 | + | |
92 | + /** | |
93 | + * @brief Start the actual server (server-mode) or build the client | |
94 | + * connection (client-mode) | |
95 | + * @return True on success, false on failure | |
96 | + */ | |
97 | + bool startNetworkLayer(); | |
98 | + | |
99 | + /** | |
100 | + * @brief Send data through the interface | |
101 | + * @param sData Data to send | |
102 | + */ | |
103 | + void sendData( const QString &sData ); | |
104 | + | |
105 | +public slots: | |
106 | + /// @brief Slot called when a new server-connection is available | |
107 | + void slotNewConnection(); | |
108 | + | |
109 | + /** | |
110 | + * @brief Slot called when data was sent through the specified socket | |
111 | + * @param pSocket Socket through which data was sent | |
112 | + */ | |
113 | + void slotDataSent( TcpSocket *pSocket ); | |
114 | + | |
115 | + /** | |
116 | + * @brief Slot called when data is being received by the specified socket | |
117 | + * @param pSocket Socket which is receiving data | |
118 | + */ | |
119 | + void slotReceivingData( TcpSocket *pSocket ); | |
120 | + | |
121 | + /** | |
122 | + * @brief Slot called when data was received through the specified socket | |
123 | + * @param sData Data received | |
124 | + * @param pSocket Socket through which data was sent | |
125 | + */ | |
126 | + void slotDataReceived( const QString &sData, TcpSocket *pSocket ); | |
127 | + | |
128 | + /** | |
129 | + * @brief Slot called when the specified socket was connected | |
130 | + * @param pSocket Socket through which data was sent | |
131 | + */ | |
132 | + void slotConnected( TcpSocket *pSocket ); | |
133 | + | |
134 | + /** | |
135 | + * @brief Slot called when the specified socket was disconnected | |
136 | + * @param pSocket Socket that was disconnected | |
137 | + * | |
138 | + * Also removes the socket from the list of known sockets and deletes it | |
139 | + */ | |
140 | + void slotDisconnected( TcpSocket *pSocket ); | |
141 | + | |
142 | +signals: | |
143 | + /** | |
144 | + * @brief Signal emitted when data is sent through a specified socket | |
145 | + * @param sData Data to be sent | |
146 | + * @param pSocket Socket that sends the data | |
147 | + */ | |
148 | + void signalSendData( const QString &sData, TcpSocket *pSocket ); | |
149 | + | |
150 | + /** | |
151 | + * @brief Signal emitted when data is present for the specified ticket | |
152 | + * @param sTicket Ticket ID | |
153 | + */ | |
154 | + void dataPresent( const QString &sTicket ); | |
155 | + | |
156 | + /** | |
157 | + * @brief Relay the message signal to the eventmanager | |
158 | + * @todo Check parameter meanings! | |
159 | + * @param i1 sourceID ? | |
160 | + * @param i2 DestID ? | |
161 | + * @param i3 Connection status ? | |
162 | + * @param i4 data ? | |
163 | + */ | |
164 | + void message( int i1, int i2, int i3, int i4 ); | |
165 | + | |
166 | +private: | |
167 | + /** | |
168 | + * @brief Create a new unique buffer ticket ID | |
169 | + * @return New ticket ID | |
170 | + */ | |
171 | + QString createBufferTicket(); | |
172 | + | |
173 | + /** | |
174 | + * @brief Connect all signals and slots for the socket | |
175 | + * @param l_pSocket Socket to connect | |
176 | + */ | |
177 | + void connectSocketSignals( TcpSocket *l_pSocket ); | |
178 | + | |
179 | + /// @brief Resend messages that are still in the buffer | |
180 | + void resendDelayedMessages(); | |
181 | + | |
182 | + QTcpServer *m_pServer; ///< The pointer to the server object. | |
183 | + SocketContainer *m_pSocketContainer; ///< Administration which keeps track of the Sockets. | |
184 | + TcpSocket *m_pSocket; | |
185 | + | |
186 | + QList< QString > m_inputBuffer; ///< Messages that can not be send yet will be stored here. | |
187 | + QHash< QString, QString > m_outputBuffer; ///< The hashtable we use for databuffering. | |
188 | + | |
189 | + bool m_bServer; ///< True for server-mode, false for client-mode | |
190 | + QString m_ipAddress; ///< The ipAddress the clients are connecting to. | |
191 | + int m_portNumber; ///< The portnumber our server is listening on. | |
192 | + int m_maxTcpConnections;///< The number of TCP connections we accept and make. | |
193 | + int m_maxUdpConnections;///< The number of UDP connections we accept and make. | |
194 | +}; | |
195 | + | |
196 | +} // End namespace components | |
197 | +} // End namespace osdev | |
198 | + | |
199 | +#endif /* OSDEV_COMPONENTS_CPOOLMANAGER_H */ | ... | ... |
src/socketcontainer.cpp
0 → 100644
1 | +++ a/src/socketcontainer.cpp | |
1 | +/* **************************************************************************** | |
2 | + * Copyright 2019 Open Systems Development BV * | |
3 | + * * | |
4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
5 | + * copy of this software and associated documentation files (the "Software"), * | |
6 | + * to deal in the Software without restriction, including without limitation * | |
7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
9 | + * Software is furnished to do so, subject to the following conditions: * | |
10 | + * * | |
11 | + * The above copyright notice and this permission notice shall be included in * | |
12 | + * all copies or substantial portions of the Software. * | |
13 | + * * | |
14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
20 | + * DEALINGS IN THE SOFTWARE. * | |
21 | + * ***************************************************************************/ | |
22 | + | |
23 | +#include "socketcontainer.h" | |
24 | + | |
25 | +#include "tcpsocket.h" | |
26 | +#include "log.h" | |
27 | + | |
28 | +namespace osdev { | |
29 | +namespace components { | |
30 | + | |
31 | +SocketContainer::SocketContainer() | |
32 | + : m_hshFreeBySocket() | |
33 | +{ | |
34 | +} | |
35 | + | |
36 | +SocketContainer::~SocketContainer() | |
37 | +{ | |
38 | + // qDeleteAll( hshFreeBySocket.begin(), hshFreeBySocket.end() ); | |
39 | +} | |
40 | + | |
41 | +void SocketContainer::addSocket( TcpSocket *pSocket ) | |
42 | +{ | |
43 | + if( pSocket ) | |
44 | + { | |
45 | + // We store a channel in a ready state. | |
46 | + m_hshFreeBySocket.insert( pSocket, true ); | |
47 | + } | |
48 | +} | |
49 | + | |
50 | +void SocketContainer::removeSocket( TcpSocket *pSocket ) | |
51 | +{ | |
52 | + if( pSocket ) | |
53 | + { | |
54 | + // Remove the channel from the list. | |
55 | + m_hshFreeBySocket.remove( pSocket ); | |
56 | + } | |
57 | +} | |
58 | + | |
59 | +void SocketContainer::setChannelFree( TcpSocket *pSocket ) | |
60 | +{ | |
61 | + if( pSocket ) | |
62 | + { | |
63 | + auto socketIt = m_hshFreeBySocket.find(pSocket); | |
64 | + if( m_hshFreeBySocket.end() != socketIt ) | |
65 | + { | |
66 | + socketIt.value() = true; | |
67 | + } | |
68 | + } | |
69 | +} | |
70 | + | |
71 | +void SocketContainer::setChannelBusy(TcpSocket *pSocket) | |
72 | +{ | |
73 | + if( pSocket ) | |
74 | + { | |
75 | + auto socketIt = m_hshFreeBySocket.find(pSocket); | |
76 | + if( m_hshFreeBySocket.end() != socketIt ) | |
77 | + { | |
78 | + socketIt.value() = false; | |
79 | + | |
80 | + // printStatus(); | |
81 | + } | |
82 | + } | |
83 | +} | |
84 | + | |
85 | +TcpSocket* SocketContainer::getFreeSocket() const | |
86 | +{ | |
87 | + // printStatus(); | |
88 | + | |
89 | + // Return a random socket with a free channel | |
90 | + return m_hshFreeBySocket.key( true ); | |
91 | +} | |
92 | + | |
93 | +void SocketContainer::printStatus() const | |
94 | +{ | |
95 | + LogDebug("interfaceplugin", QString("getFreeSocket counts : ") + m_hshFreeBySocket.count()); | |
96 | + LogDebug("interfaceplugin", QString("===========================================================")); | |
97 | + | |
98 | + for(auto it = m_hshFreeBySocket.begin(); it != m_hshFreeBySocket.end(); ++it) | |
99 | + { | |
100 | + LogDebug("interfaceplugin", it.key()->objectName()+" : "+it.value()); | |
101 | + } | |
102 | +} | |
103 | + | |
104 | +} // End namespace components | |
105 | +} // End namespace osdev | ... | ... |
src/socketcontainer.h
0 → 100644
1 | +++ a/src/socketcontainer.h | |
1 | +/* **************************************************************************** | |
2 | + * Copyright 2019 Open Systems Development BV * | |
3 | + * * | |
4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
5 | + * copy of this software and associated documentation files (the "Software"), * | |
6 | + * to deal in the Software without restriction, including without limitation * | |
7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
9 | + * Software is furnished to do so, subject to the following conditions: * | |
10 | + * * | |
11 | + * The above copyright notice and this permission notice shall be included in * | |
12 | + * all copies or substantial portions of the Software. * | |
13 | + * * | |
14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
20 | + * DEALINGS IN THE SOFTWARE. * | |
21 | + * ***************************************************************************/ | |
22 | + | |
23 | +#ifndef OSDEV_COMPONENTS_CTHREADCONTAINER_H | |
24 | +#define OSDEV_COMPONENTS_CTHREADCONTAINER_H | |
25 | + | |
26 | +/*************************************************************************** | |
27 | + * Global Includes | |
28 | + ***************************************************************************/ | |
29 | +#include <QHash> | |
30 | + | |
31 | +/*************************************************************************** | |
32 | + * Local Includes | |
33 | + ***************************************************************************/ | |
34 | + | |
35 | +namespace osdev { | |
36 | +namespace components { | |
37 | + | |
38 | +class TcpSocket; | |
39 | + | |
40 | +/** | |
41 | + * @brief Maintains a collection of sockets | |
42 | + * | |
43 | + * @note This class does NOT take ownership of the provided sockets | |
44 | + */ | |
45 | +class SocketContainer | |
46 | +{ | |
47 | +public: | |
48 | + /// Constructor | |
49 | + SocketContainer(); | |
50 | + /// Destructor | |
51 | + ~SocketContainer(); | |
52 | + | |
53 | + /// Deleted copy-constructor | |
54 | + SocketContainer(const SocketContainer&) = delete; | |
55 | + /// Deleted assignment operator | |
56 | + SocketContainer& operator=(const SocketContainer&) = delete; | |
57 | + /// Deleted move-constructor | |
58 | + SocketContainer(SocketContainer&&) = delete; | |
59 | + /// Deleted move operator | |
60 | + SocketContainer& operator=(SocketContainer&&) = delete; | |
61 | + | |
62 | + //! This function will set the given thread to free | |
63 | + //! \param pSocket Socket to set to free | |
64 | + void setChannelFree( TcpSocket *pSocket ); | |
65 | + | |
66 | + //! This function will set the given thread to busy | |
67 | + //! \param pSocket Socket to set to busy | |
68 | + void setChannelBusy( TcpSocket *pSocket ); | |
69 | + | |
70 | + //! This function will add a newly created thread to the container | |
71 | + //! \param pSocket Add a new socket to the list | |
72 | + void addSocket( TcpSocket *pSocket ); | |
73 | + | |
74 | + //! This function removes a thread from the list for whatever reason there might be | |
75 | + //! \param pSocket Removes the socket from the list | |
76 | + void removeSocket( TcpSocket *pSocket ); | |
77 | + | |
78 | + //! @return This function will return the first free thread. | |
79 | + TcpSocket* getFreeSocket() const; | |
80 | + | |
81 | +private: | |
82 | + /// Dump the status to debug log | |
83 | + void printStatus() const; | |
84 | + | |
85 | + /// Contains all managed sockets | |
86 | + QHash< TcpSocket*, bool > m_hshFreeBySocket; | |
87 | +}; | |
88 | + | |
89 | +} // End namespace components | |
90 | +} // End namespace osdev | |
91 | + | |
92 | +#endif /* OSDEV_COMPONENTS_CTHREADCONTAINER_H */ | ... | ... |
src/tcpinterface.cpp
0 → 100644
1 | +++ a/src/tcpinterface.cpp | |
1 | +/* **************************************************************************** | |
2 | + * Copyright 2019 Open Systems Development BV * | |
3 | + * * | |
4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
5 | + * copy of this software and associated documentation files (the "Software"), * | |
6 | + * to deal in the Software without restriction, including without limitation * | |
7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
9 | + * Software is furnished to do so, subject to the following conditions: * | |
10 | + * * | |
11 | + * The above copyright notice and this permission notice shall be included in * | |
12 | + * all copies or substantial portions of the Software. * | |
13 | + * * | |
14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
20 | + * DEALINGS IN THE SOFTWARE. * | |
21 | + * ***************************************************************************/ | |
22 | + | |
23 | +#include "tcpinterface.h" | |
24 | +#include "log.h" | |
25 | + | |
26 | +#include <QHostAddress> | |
27 | +#include <QTcpServer> | |
28 | +#include <QTcpSocket> | |
29 | +#include <QDataStream> | |
30 | + | |
31 | +namespace osdev { | |
32 | +namespace components { | |
33 | + | |
34 | +TcpInterface::TcpInterface(const QString& hostName, int port, bool i_bServer) | |
35 | + : m_bServer( i_bServer ), | |
36 | + m_active(false), | |
37 | + m_tcpServer( nullptr ), | |
38 | + m_tcpSocket( nullptr ), | |
39 | + m_clientConnection( nullptr ), | |
40 | + m_blockSize( 0 ), | |
41 | + m_dataList() | |
42 | +{ | |
43 | + QHostAddress hostAddress(hostName); | |
44 | + | |
45 | + if (m_bServer) | |
46 | + { // This interface is a server | |
47 | + m_tcpServer = new QTcpServer(this); | |
48 | + connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); | |
49 | + m_active = m_tcpServer->listen(hostAddress, static_cast<quint16>(port)); | |
50 | + if (!m_active) | |
51 | + { | |
52 | + LogWarning("interfaceplugin", | |
53 | + "Unable to start the server: " + m_tcpServer->errorString()); | |
54 | + } | |
55 | + } | |
56 | + else | |
57 | + { // This interface is a client | |
58 | + m_tcpSocket = new QTcpSocket(this); | |
59 | + m_tcpSocket->connectToHost(hostAddress, static_cast<quint16>(port)); | |
60 | + m_active = m_tcpSocket->waitForConnected(1000); | |
61 | + if (m_active) | |
62 | + { | |
63 | + connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(readData())); | |
64 | + } | |
65 | + } | |
66 | +} | |
67 | + | |
68 | + | |
69 | +TcpInterface::~TcpInterface() | |
70 | +{ | |
71 | +} | |
72 | + | |
73 | +QString TcpInterface::getData() | |
74 | +{ | |
75 | + QString qsResult; | |
76 | + if(!m_dataList.isEmpty()) | |
77 | + { | |
78 | + qsResult = m_dataList.takeFirst(); | |
79 | + } | |
80 | + return qsResult; | |
81 | +} | |
82 | + | |
83 | +void TcpInterface::readData() | |
84 | +{ | |
85 | + QTcpSocket* pSocket = nullptr; | |
86 | + /* Retrieve the correct Socket, depending on connection-type */ | |
87 | + if (m_bServer) | |
88 | + { | |
89 | + pSocket = m_clientConnection; | |
90 | + } | |
91 | + else | |
92 | + { | |
93 | + pSocket = m_tcpSocket; | |
94 | + } | |
95 | + | |
96 | + /* Construct a DataStream from the Socket */ | |
97 | + QDataStream in(pSocket); | |
98 | + in.setVersion(QDataStream::Qt_5_4); | |
99 | + | |
100 | + // Process while there is a following message in this same buffer. | |
101 | + do { | |
102 | + LogDebug("TcpInterface", "read bytes"); | |
103 | + /* The size of the message in bytes is required */ | |
104 | + if (m_blockSize == 0) | |
105 | + { | |
106 | + /* | |
107 | + * The size of the message should be available as the first four | |
108 | + * blocks of the message; i.e. (sizeof(quint32)) | |
109 | + */ | |
110 | + if (pSocket->bytesAvailable() < static_cast<int>(sizeof(quint32))) | |
111 | + { | |
112 | + return; | |
113 | + } | |
114 | + /* Retrieve the blocksize if it is fully available from the socket */ | |
115 | + in >> m_blockSize; | |
116 | + LogDebug("TcpInterface", QString("block size is %1").arg(m_blockSize)); | |
117 | + } | |
118 | + | |
119 | + if (pSocket->bytesAvailable() < m_blockSize) | |
120 | + { | |
121 | + return; | |
122 | + } | |
123 | + | |
124 | + /* | |
125 | + * Retrieve the message if it is completely available from the socket. | |
126 | + * I.e.: The number of available bytes must be at least the retrieved | |
127 | + * message-size. | |
128 | + */ | |
129 | + QByteArray pDataStore; | |
130 | + /* | |
131 | + * Using an empty QByteArray the operator>> can be used, because it then | |
132 | + * reads in everything until the first '\0' character. | |
133 | + * It is then required that all messages are ended by a '\0'. This is | |
134 | + * standard when sending QByteArrays. | |
135 | + */ | |
136 | + in >> pDataStore; | |
137 | + /* | |
138 | + * An entire message is stored in a new QByteArray and must be pushed on | |
139 | + * the stack of available messages | |
140 | + */ | |
141 | + m_dataList.append( pDataStore ); | |
142 | + m_blockSize = 0; // reset blocksize for next read | |
143 | + emit dataPresent(); | |
144 | + } while (pSocket->bytesAvailable() > 0); | |
145 | +} | |
146 | + | |
147 | +void TcpInterface::sendData(const QString& i_qsData) | |
148 | +{ | |
149 | + QByteArray block; | |
150 | + QDataStream out(&block, QIODevice::WriteOnly); | |
151 | + | |
152 | + out.setVersion(QDataStream::Qt_5_4); | |
153 | + | |
154 | + out << block.size(); | |
155 | + out << i_qsData.toLatin1(); | |
156 | + | |
157 | + if (m_bServer) | |
158 | + { | |
159 | + m_clientConnection->write(block); | |
160 | + m_clientConnection->flush(); | |
161 | + } | |
162 | + else | |
163 | + { | |
164 | + m_tcpSocket->write(block); | |
165 | + m_tcpSocket->flush(); | |
166 | + } | |
167 | +} | |
168 | + | |
169 | +void TcpInterface::newConnection() | |
170 | +{ | |
171 | + m_clientConnection = m_tcpServer->nextPendingConnection(); | |
172 | + connect(m_clientConnection, SIGNAL(readyRead()), this, SLOT(readData())); | |
173 | +} | |
174 | + | |
175 | +} | |
176 | +} | ... | ... |
src/tcpinterface.h
0 → 100644
1 | +++ a/src/tcpinterface.h | |
1 | +/* **************************************************************************** | |
2 | + * Copyright 2019 Open Systems Development BV * | |
3 | + * * | |
4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
5 | + * copy of this software and associated documentation files (the "Software"), * | |
6 | + * to deal in the Software without restriction, including without limitation * | |
7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
9 | + * Software is furnished to do so, subject to the following conditions: * | |
10 | + * * | |
11 | + * The above copyright notice and this permission notice shall be included in * | |
12 | + * all copies or substantial portions of the Software. * | |
13 | + * * | |
14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
20 | + * DEALINGS IN THE SOFTWARE. * | |
21 | + * ***************************************************************************/ | |
22 | + | |
23 | +#ifndef OSDEV_COMPONENTS_CTCPINTERFACE_H | |
24 | +#define OSDEV_COMPONENTS_CTCPINTERFACE_H | |
25 | + | |
26 | +#include <QObject> | |
27 | +#include <QList> | |
28 | + | |
29 | +class QTcpServer; | |
30 | +class QTcpSocket; | |
31 | + | |
32 | +namespace osdev { | |
33 | +namespace components { | |
34 | + | |
35 | +/** | |
36 | + * @brief Handles a generic client or server point-to-point connection | |
37 | + * | |
38 | + * This class can be instantiated as a client or a server. | |
39 | + * | |
40 | + * @note The server can currently only handle one client at a time. | |
41 | + */ | |
42 | +class TcpInterface : public QObject | |
43 | +{ | |
44 | + Q_OBJECT | |
45 | + | |
46 | +public: | |
47 | + /** | |
48 | + * @brief Constructor | |
49 | + * @param hostName Host to connect with (client-mode), or interface to | |
50 | + * connect at (server-mode) | |
51 | + * @param port Selected port-number | |
52 | + * @param i_bServer False for client-mode, true for server-mode | |
53 | + */ | |
54 | + TcpInterface(const QString& hostName, int port = 2776, bool i_bServer = false); | |
55 | + /// @brief Destructor | |
56 | + ~TcpInterface(); | |
57 | + | |
58 | + /// Deleted copy-constructor | |
59 | + TcpInterface(const TcpInterface&) = delete; | |
60 | + /// Deleted assignment operator | |
61 | + TcpInterface& operator=(const TcpInterface&) = delete; | |
62 | + /// Deleted move-constructor | |
63 | + TcpInterface(TcpInterface&&) = delete; | |
64 | + /// Deleted move operator | |
65 | + TcpInterface& operator=(TcpInterface&&) = delete; | |
66 | + | |
67 | + /** | |
68 | + * @return if the interface is active. | |
69 | + * In server mode the interface is listening or connected to and in | |
70 | + * client mode the interface is connected. | |
71 | + */ | |
72 | + bool active() const | |
73 | + { | |
74 | + return m_active; | |
75 | + } | |
76 | + | |
77 | + /** | |
78 | + * @brief Reads the first block of data from the received data | |
79 | + * @return First block of data, as a QString | |
80 | + */ | |
81 | + QString getData(); | |
82 | + | |
83 | +public slots: | |
84 | + | |
85 | + /** | |
86 | + * @brief Called when data is ready to be read into the buffer | |
87 | + */ | |
88 | + void readData(); | |
89 | + | |
90 | + /** | |
91 | + * @brief Send a block of data to the other party | |
92 | + * @param i_qsData Data to be sent | |
93 | + */ | |
94 | + void sendData(const QString& i_qsData); | |
95 | + | |
96 | +signals: | |
97 | + /// @brief Emitted when data is present on the connection | |
98 | + void dataPresent(); | |
99 | + | |
100 | +private slots: | |
101 | + /// @brief Slot called when a new connection is made | |
102 | + void newConnection(); | |
103 | + | |
104 | +private: | |
105 | + bool m_bServer; ///< True for server-mode, false for client-mode | |
106 | + bool m_active; ///< True if in server mode the server is listening or connected to and in client mode when the client is connected. | |
107 | + | |
108 | + QTcpServer* m_tcpServer; ///< Server object instance | |
109 | + QTcpSocket* m_tcpSocket; ///< Client object instance | |
110 | + | |
111 | + QTcpSocket* m_clientConnection; ///< Current client connection | |
112 | + | |
113 | + quint32 m_blockSize; ///< Maximum size of a data-block | |
114 | + QList<QByteArray> m_dataList; ///< Blocks of data read from the counterpart | |
115 | +}; | |
116 | + | |
117 | +} // End namespace components | |
118 | +} // End namespace osdev | |
119 | + | |
120 | +#endif /* OSDEV_COMPONENTS_CTCPINTERFACE_H */ | ... | ... |
src/tcpsocket.cpp
0 → 100644
1 | +++ a/src/tcpsocket.cpp | |
1 | +/* **************************************************************************** | |
2 | + * Copyright 2019 Open Systems Development BV * | |
3 | + * * | |
4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
5 | + * copy of this software and associated documentation files (the "Software"), * | |
6 | + * to deal in the Software without restriction, including without limitation * | |
7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
9 | + * Software is furnished to do so, subject to the following conditions: * | |
10 | + * * | |
11 | + * The above copyright notice and this permission notice shall be included in * | |
12 | + * all copies or substantial portions of the Software. * | |
13 | + * * | |
14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
20 | + * DEALINGS IN THE SOFTWARE. * | |
21 | + * ***************************************************************************/ | |
22 | +#include "tcpsocket.h" | |
23 | + | |
24 | +#include "log.h" | |
25 | + | |
26 | +#include <QHostAddress> | |
27 | +#include <QTcpSocket> | |
28 | +#include <QTimer> | |
29 | +#include <QDataStream> | |
30 | + | |
31 | +namespace osdev { | |
32 | +namespace components { | |
33 | + | |
34 | +TcpSocket::TcpSocket( const QString& ipAddress, int portNumber ) | |
35 | + : m_pSocket(new QTcpSocket(this)) | |
36 | + , m_blockSize(0) | |
37 | + , m_dataBuffer() | |
38 | + , m_pTimer( new QTimer() ) | |
39 | +{ | |
40 | + // First we connect the timer to this class | |
41 | + connect(m_pTimer.get(), SIGNAL(timeout()), this, SLOT(chkSendBuffer())); | |
42 | + | |
43 | + this->connectSocketSignals(); | |
44 | + | |
45 | + m_pSocket->connectToHost( QHostAddress( ipAddress ), static_cast<quint16>(portNumber) ); | |
46 | + if( !m_pSocket->waitForConnected( 3000 ) ) | |
47 | + { | |
48 | + LogDebug("interfaceplugin", "Socket failed to connect."); | |
49 | + LogObject("interfaceplugin", this); | |
50 | + } | |
51 | + else | |
52 | + { | |
53 | + LogDebug("interfaceplugin", "Client connected : "); | |
54 | + LogObject("interfaceplugin", m_pSocket); | |
55 | + } | |
56 | +} | |
57 | + | |
58 | +TcpSocket::TcpSocket(QTcpSocket *pSocket) | |
59 | + : m_pSocket(pSocket) | |
60 | + , m_blockSize(0) | |
61 | + , m_dataBuffer() | |
62 | + , m_pTimer( new QTimer() ) | |
63 | +{ | |
64 | + Q_ASSERT(pSocket); | |
65 | + | |
66 | + connect(m_pTimer.get(), SIGNAL(timeout()), this, SLOT(chkSendBuffer())); | |
67 | + | |
68 | + this->connectSocketSignals(); | |
69 | +} | |
70 | + | |
71 | +TcpSocket::~TcpSocket() | |
72 | +{ | |
73 | + // Implicitly deletes m_pSocket if this object is its parent | |
74 | +} | |
75 | + | |
76 | +void TcpSocket::slotReadyRead() | |
77 | +{ | |
78 | + // Let the poolmanager know we are busy receiving data at the moment and are | |
79 | + // unavailable for anything else. | |
80 | + emit signalReceivingData( this ); | |
81 | + | |
82 | + QDataStream in( m_pSocket ); | |
83 | + in.setVersion( QDataStream::Qt_5_4 ); | |
84 | + | |
85 | + if( m_blockSize == 0 ) | |
86 | + { | |
87 | + if( m_pSocket->bytesAvailable() < static_cast<int>(sizeof( quint32 ) ) ) | |
88 | + { | |
89 | + return; | |
90 | + } | |
91 | + | |
92 | + in >> m_blockSize; | |
93 | + } | |
94 | + | |
95 | + if( m_pSocket->bytesAvailable() < m_blockSize ) | |
96 | + { | |
97 | + return; | |
98 | + } | |
99 | + | |
100 | + in >> m_dataBuffer; | |
101 | + | |
102 | + emit signalDataReceived( m_dataBuffer, this ); | |
103 | + | |
104 | + m_blockSize = 0; // Reset the blockSize for next read. | |
105 | + m_dataBuffer.clear(); // Reset the buffer for the next read. | |
106 | +} | |
107 | + | |
108 | +void TcpSocket::slotSendData( const QString &sData, TcpSocket *pSocket ) | |
109 | +{ | |
110 | + if( pSocket != this || sData.isNull() ) { | |
111 | + return; | |
112 | + } | |
113 | + | |
114 | + QByteArray block; | |
115 | + QDataStream out( &block, QIODevice::WriteOnly ); | |
116 | + | |
117 | + out.setVersion( QDataStream::Qt_5_4 ); | |
118 | + out << block.size(); | |
119 | + out << sData; | |
120 | + | |
121 | + m_pSocket->write( block ); | |
122 | + chkSendBuffer(); | |
123 | +} | |
124 | + | |
125 | +void TcpSocket::slotSetSocket(QTcpSocket* pSocket ) | |
126 | +{ | |
127 | + if(m_pSocket) { | |
128 | + disconnectSocketSignals(); | |
129 | + } | |
130 | + m_pSocket = pSocket; | |
131 | + connectSocketSignals(); | |
132 | +} | |
133 | + | |
134 | +void TcpSocket::chkSendBuffer() | |
135 | +{ | |
136 | + m_pTimer->stop(); | |
137 | + | |
138 | + if( m_pSocket->bytesToWrite() > 0 ) | |
139 | + { | |
140 | + m_pSocket->flush(); | |
141 | + m_pTimer->start( 500 ); | |
142 | + } | |
143 | + else | |
144 | + { | |
145 | + emit signalDataSent( this ); | |
146 | + } | |
147 | +} | |
148 | + | |
149 | +void TcpSocket::slotConnected() | |
150 | +{ | |
151 | + emit signalConnected( this ); | |
152 | +} | |
153 | + | |
154 | +void TcpSocket::slotDisconnected() | |
155 | +{ | |
156 | + emit signalDisconnected( this ); | |
157 | +} | |
158 | + | |
159 | +QString TcpSocket::showError() | |
160 | +{ | |
161 | + if( m_pSocket ) | |
162 | + { | |
163 | + return m_pSocket->errorString(); | |
164 | + } | |
165 | + else | |
166 | + { | |
167 | + return "No socket available"; | |
168 | + } | |
169 | +} | |
170 | + | |
171 | +void TcpSocket::connectSocketSignals() | |
172 | +{ | |
173 | + Q_ASSERT(m_pSocket); | |
174 | + // Connect the required signals and slots to gain control. | |
175 | + // First for receiving data. | |
176 | + connect( m_pSocket, SIGNAL( readyRead() ), | |
177 | + this, SLOT( slotReadyRead() ) ); | |
178 | + | |
179 | + connect( m_pSocket, SIGNAL( connected() ), | |
180 | + this, SLOT( slotConnected() ) ); | |
181 | + | |
182 | + connect( m_pSocket, SIGNAL( disconnected() ), | |
183 | + this, SLOT( slotDisconnected() ) ); | |
184 | +} | |
185 | + | |
186 | +void TcpSocket::disconnectSocketSignals() | |
187 | +{ | |
188 | + Q_ASSERT(m_pSocket); | |
189 | + // Connect the required signals and slots to gain control. | |
190 | + // First for receiving data. | |
191 | + disconnect( m_pSocket, SIGNAL( readyRead() ), | |
192 | + this, SLOT( slotReadyRead() ) ); | |
193 | + | |
194 | + disconnect( m_pSocket, SIGNAL( connected() ), | |
195 | + this, SLOT( slotConnected() ) ); | |
196 | + | |
197 | + disconnect( m_pSocket, SIGNAL( disconnected() ), | |
198 | + this, SLOT( slotDisconnected() ) ); | |
199 | +} | |
200 | + | |
201 | +bool TcpSocket::isConnected() | |
202 | +{ | |
203 | + return m_pSocket && m_pSocket->state() == QTcpSocket::ConnectedState; | |
204 | +} | |
205 | + | |
206 | +} | |
207 | +} | ... | ... |
src/tcpsocket.h
0 → 100644
1 | +++ a/src/tcpsocket.h | |
1 | +/* **************************************************************************** | |
2 | + * Copyright 2019 Open Systems Development BV * | |
3 | + * * | |
4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
5 | + * copy of this software and associated documentation files (the "Software"), * | |
6 | + * to deal in the Software without restriction, including without limitation * | |
7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
9 | + * Software is furnished to do so, subject to the following conditions: * | |
10 | + * * | |
11 | + * The above copyright notice and this permission notice shall be included in * | |
12 | + * all copies or substantial portions of the Software. * | |
13 | + * * | |
14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
20 | + * DEALINGS IN THE SOFTWARE. * | |
21 | + * ***************************************************************************/ | |
22 | + | |
23 | +#ifndef OSDEV_COMPONENTS_CTCPSOCKET_H | |
24 | +#define OSDEV_COMPONENTS_CTCPSOCKET_H | |
25 | + | |
26 | +#include <QObject> | |
27 | +//#include <QTimer> | |
28 | +//#include <QTcpSocket> | |
29 | +//#include <QHostAddress> | |
30 | +//#include <QDataStream> | |
31 | +//#include <QString> | |
32 | + | |
33 | +#include <memory> | |
34 | + | |
35 | +class QTcpSocket; | |
36 | +class QTimer; | |
37 | + | |
38 | +namespace osdev { | |
39 | +namespace components { | |
40 | + | |
41 | +/** | |
42 | + * @brief Wrapper around QTcpSocket | |
43 | + */ | |
44 | +class TcpSocket : public QObject | |
45 | +{ | |
46 | + Q_OBJECT | |
47 | + | |
48 | +public: | |
49 | + /** | |
50 | + * @brief Create a TcpSocket connecting to the given address | |
51 | + * @param ipAddress Host to connect to | |
52 | + * @param portNumber Port number to connect at | |
53 | + */ | |
54 | + TcpSocket( const QString& ipAddress, int portNumber ); | |
55 | + | |
56 | + /** | |
57 | + * @brief Create a TcpSocket based on an existing QTcpSocket | |
58 | + * @param pSocket Socket used. This class does NOT take ownership of the | |
59 | + * provided socket. | |
60 | + */ | |
61 | + TcpSocket( QTcpSocket *pSocket ); | |
62 | + | |
63 | + /// Deleted copy-constructor | |
64 | + TcpSocket(const TcpSocket&) = delete; | |
65 | + /// Deleted assignment operator | |
66 | + TcpSocket& operator=(const TcpSocket&) = delete; | |
67 | + /// Deleted move-constructor | |
68 | + TcpSocket(TcpSocket&&) = delete; | |
69 | + /// Deleted move operator | |
70 | + TcpSocket& operator=(TcpSocket&&) = delete; | |
71 | + | |
72 | + /// @brief Destructor | |
73 | + ~TcpSocket(); | |
74 | + | |
75 | + /** | |
76 | + * @brief Retrieve the last error registered in the socket | |
77 | + * @return Error string | |
78 | + */ | |
79 | + QString showError(); | |
80 | + | |
81 | + /** | |
82 | + * @brief See if a connection is available | |
83 | + * @return True if a connection is available, false otherwise | |
84 | + */ | |
85 | + bool isConnected(); | |
86 | + | |
87 | +public slots: | |
88 | + /** | |
89 | + * @brief Slot called to send data | |
90 | + * @param sData Data to send | |
91 | + * @param pSocket Socket to which to send. If it is not equal to this, the | |
92 | + * slot does nothing and returns | |
93 | + */ | |
94 | + void slotSendData( const QString &sData, TcpSocket *pSocket ); | |
95 | + | |
96 | + /** | |
97 | + * @brief Updates the current QTcpSocket used | |
98 | + * @param pSocket New socket | |
99 | + */ | |
100 | + void slotSetSocket( QTcpSocket *pSocket ); | |
101 | + | |
102 | + /// @brief Slot called when a socket gets connected | |
103 | + void slotConnected(); | |
104 | + | |
105 | + /// @brief Slot called when a socket gets disconnected | |
106 | + void slotDisconnected(); | |
107 | + | |
108 | +signals: | |
109 | + /** | |
110 | + * @brief Signal emitted when data is received | |
111 | + * @param sData Block of data received | |
112 | + * @param pSocket Receiving socket | |
113 | + */ | |
114 | + void signalDataReceived( const QString &sData, TcpSocket *pSocket ); | |
115 | + | |
116 | + /** | |
117 | + * @brief Signal emitted when data was sent | |
118 | + * @param pSocket Sending socket | |
119 | + */ | |
120 | + void signalDataSent( TcpSocket *pSocket ); | |
121 | + | |
122 | + /** | |
123 | + * @brief Signal emitted when data is being received | |
124 | + * @param pSocket Receiving socket | |
125 | + */ | |
126 | + void signalReceivingData( TcpSocket *pSocket ); | |
127 | + | |
128 | + /** | |
129 | + * @brief Signal emitted when a socket gets connected | |
130 | + * @param pSocket Socket that gets connected | |
131 | + */ | |
132 | + void signalConnected( TcpSocket *pSocket ); | |
133 | + | |
134 | + /** | |
135 | + * @brief Signal emitted when a socket gets disconnected | |
136 | + * @param pSocket Socket that gets disconnected | |
137 | + */ | |
138 | + void signalDisconnected( TcpSocket *pSocket ); | |
139 | + | |
140 | +private slots: | |
141 | + /// @brief Slot called when a socket is ready to read | |
142 | + void slotReadyRead(); | |
143 | + | |
144 | + /// @brief Emits the signalDataSent when all data was sent | |
145 | + void chkSendBuffer(); | |
146 | + | |
147 | +private: | |
148 | + /// @brief Connects the socket signals to the slots of this class | |
149 | + void connectSocketSignals(); | |
150 | + | |
151 | + /// @brief Disconnects the socket signals to the slots of this class | |
152 | + void disconnectSocketSignals(); | |
153 | + | |
154 | + QTcpSocket *m_pSocket; ///< Current communication socket | |
155 | + int m_blockSize; ///< Maximum block size | |
156 | + QString m_dataBuffer; ///< Data to be sent | |
157 | + | |
158 | + std::unique_ptr<QTimer> m_pTimer; ///< Periodic check if all data was sent | |
159 | +}; | |
160 | + | |
161 | +} // End namespace components | |
162 | +} // End namespace osdev | |
163 | + | |
164 | +#endif // OSDEV_COMPONENTS_CTCPSOCKET_H | ... | ... |
tests/CMakeLists.txt
0 → 100644
1 | +++ a/tests/CMakeLists.txt | |
1 | +cmake_minimum_required(VERSION 3.0) | |
2 | +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) | |
3 | + | |
4 | +include(projectheader) | |
5 | +project_header(test_logutils) | |
6 | + | |
7 | +include_directories( SYSTEM | |
8 | + ${CMAKE_CURRENT_SOURCE_DIR}/../../src | |
9 | +) | |
10 | + | |
11 | +include(compiler) | |
12 | +set(SRC_LIST | |
13 | +) | |
14 | + | |
15 | +# add_executable( ${PROJECT_NAME} | |
16 | +# ${SRC_LIST} | |
17 | +# ) | |
18 | + | |
19 | +# target_link_libraries( | |
20 | +# ${PROJECT_NAME} | |
21 | +# ) | |
22 | + | |
23 | +# set_target_properties( ${PROJECT_NAME} PROPERTIES | |
24 | +# RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin | |
25 | +# LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib | |
26 | +# ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/archive | |
27 | +# ) | |
28 | + | |
29 | +# include(installation) | |
30 | +# install_application() | ... | ... |