mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
synced 2026-03-20 03:41:02 +00:00
Compare commits
262 Commits
v2.6.0-RC4
...
v2.6.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a45d351081 | ||
|
|
7f291914bd | ||
|
|
3edbb02187 | ||
|
|
27beb0bd5d | ||
|
|
24ec3259c6 | ||
|
|
b09cec0bc2 | ||
|
|
d14ca95010 | ||
|
|
2df1100795 | ||
|
|
2f961f992a | ||
|
|
ecdc5b3531 | ||
|
|
5f08a581f2 | ||
|
|
87b4a5d626 | ||
|
|
6aa2ef2878 | ||
|
|
9267a36529 | ||
|
|
72db313d8d | ||
|
|
93f0b2500e | ||
|
|
76b7aba5bd | ||
|
|
0585884033 | ||
|
|
c31fa08579 | ||
|
|
d9c3fea93d | ||
|
|
6325476325 | ||
|
|
054e172b64 | ||
|
|
7ae51f0fec | ||
|
|
531c0e24ba | ||
|
|
d97a31e002 | ||
|
|
70e5b1d0db | ||
|
|
63516e85db | ||
|
|
35b1dbdc2e | ||
|
|
c9abe16cfe | ||
|
|
aee7530b2b | ||
|
|
ceda99fa84 | ||
|
|
ce78b144e6 | ||
|
|
3fd3717978 | ||
|
|
9be3f1dfa9 | ||
|
|
2249367696 | ||
|
|
b68af82771 | ||
|
|
884d2e323b | ||
|
|
5a21b6f197 | ||
|
|
62c0178aa9 | ||
|
|
041452cf93 | ||
|
|
89ebaf78bc | ||
|
|
295a6496ef | ||
|
|
48fb10bcec | ||
|
|
525e464592 | ||
|
|
5f20866a31 | ||
|
|
05f60cd08b | ||
|
|
bd7b56757d | ||
|
|
bc3c85fe2d | ||
|
|
22c87decdc | ||
|
|
d13216e0e2 | ||
|
|
992d977312 | ||
|
|
9cb789d0b0 | ||
|
|
b4e9747bfa | ||
|
|
351633f215 | ||
|
|
5ec9d6a2c8 | ||
|
|
3abb24919f | ||
|
|
089446c3b4 | ||
|
|
345195dd1e | ||
|
|
21db12bcc6 | ||
|
|
be01cfb142 | ||
|
|
55645c5da4 | ||
|
|
aa0316462f | ||
|
|
ebb3c8fed0 | ||
|
|
4fb788def4 | ||
|
|
5b1e048be3 | ||
|
|
03ebc88672 | ||
|
|
80bb7ffa07 | ||
|
|
1776a70a0e | ||
|
|
3a0de1fee9 | ||
|
|
8414ed719b | ||
|
|
eebb18fccf | ||
|
|
1e59b8e160 | ||
|
|
6da673e754 | ||
|
|
ee4cb53517 | ||
|
|
61da6aa317 | ||
|
|
bbbadd3a23 | ||
|
|
855eb0dc13 | ||
|
|
0601aaf340 | ||
|
|
100d0302be | ||
|
|
1fe4dbf49f | ||
|
|
720222137c | ||
|
|
d464b8a6f4 | ||
|
|
019a995bdd | ||
|
|
f70a8f1732 | ||
|
|
0c79d2a632 | ||
|
|
1d16bd352a | ||
|
|
88564f2a77 | ||
|
|
1907ab9623 | ||
|
|
60e50b2af4 | ||
|
|
cd24a45c87 | ||
|
|
cab25f6fd7 | ||
|
|
23c5879a4b | ||
|
|
4e90422e7c | ||
|
|
e75983019a | ||
|
|
a6afef5f8e | ||
|
|
15e45f32a1 | ||
|
|
4c7e1807a2 | ||
|
|
301b24415c | ||
|
|
da0698ab9b | ||
|
|
f8454e6b83 | ||
|
|
cfaab404e9 | ||
|
|
e5f98cda04 | ||
|
|
bd8fece423 | ||
|
|
68a707fe57 | ||
|
|
e02a5595a1 | ||
|
|
744c1143fb | ||
|
|
41423a6d5f | ||
|
|
060c8673e7 | ||
|
|
1210ae821b | ||
|
|
1a2e4cc184 | ||
|
|
e32ace120b | ||
|
|
3f2c046a96 | ||
|
|
9459bb022c | ||
|
|
9526a2639a | ||
|
|
2051467c0b | ||
|
|
bacaa9959c | ||
|
|
875ee6bfd1 | ||
|
|
8f966fa80c | ||
|
|
d9ac843134 | ||
|
|
4abedcddf0 | ||
|
|
c14abf8aa0 | ||
|
|
d779fca535 | ||
|
|
7e1d545f26 | ||
|
|
9c2d60ed3a | ||
|
|
b8516cad84 | ||
|
|
eba979d9da | ||
|
|
d163f7522d | ||
|
|
132fdafd32 | ||
|
|
3d6527f30b | ||
|
|
dc114de8fa | ||
|
|
0592537b71 | ||
|
|
eddaaa0cd6 | ||
|
|
46e72369ae | ||
|
|
3fc3af68ee | ||
|
|
58648d7dc5 | ||
|
|
b2bd6aab9e | ||
|
|
3781f5283f | ||
|
|
7b990a7d2f | ||
|
|
eca43e1d57 | ||
|
|
c1347fc3b8 | ||
|
|
888fcbbcd3 | ||
|
|
4e4156c420 | ||
|
|
ee98a7b8a5 | ||
|
|
0b5518d265 | ||
|
|
7bc0656f25 | ||
|
|
177a8b40ee | ||
|
|
85ee78f35e | ||
|
|
9043b3a558 | ||
|
|
4d2d488812 | ||
|
|
adf226f2e8 | ||
|
|
749d425d80 | ||
|
|
a6f9deb315 | ||
|
|
f4236408fc | ||
|
|
377c7bfc0b | ||
|
|
2e3efd97e4 | ||
|
|
58abf04e42 | ||
|
|
5e002899b5 | ||
|
|
d43c8f63ab | ||
|
|
07a64877bb | ||
|
|
a00ba50920 | ||
|
|
c2fa87d6bd | ||
|
|
ab0b36a96f | ||
|
|
89f8047e2f | ||
|
|
1515c9bb6a | ||
|
|
b53e6f44fa | ||
|
|
769c9c90f6 | ||
|
|
dc0eb35376 | ||
|
|
e6b497f0b4 | ||
|
|
bab9d869b1 | ||
|
|
a9127d4fcf | ||
|
|
fea78abe9b | ||
|
|
bd72993fa5 | ||
|
|
7d74694bf9 | ||
|
|
8e84a0f1f3 | ||
|
|
98c8f29555 | ||
|
|
42a4ee0864 | ||
|
|
fcce86acf4 | ||
|
|
31aad8b41b | ||
|
|
a828039445 | ||
|
|
6905aeaeec | ||
|
|
3293b7b71d | ||
|
|
2d6df5ea29 | ||
|
|
e466f76b75 | ||
|
|
170b97514b | ||
|
|
a463bb60dd | ||
|
|
9bbb12b674 | ||
|
|
46cc41e065 | ||
|
|
1776643579 | ||
|
|
c0d9aca88a | ||
|
|
88018335da | ||
|
|
7ce7927c95 | ||
|
|
5b797cf937 | ||
|
|
cd615e8f2b | ||
|
|
cf3f0fe67f | ||
|
|
b80e92f3dc | ||
|
|
11034bd4fd | ||
|
|
01980892b1 | ||
|
|
f4d4405663 | ||
|
|
a8370dc8dd | ||
|
|
861c4d0dee | ||
|
|
8c70e833ea | ||
|
|
f8928bbec2 | ||
|
|
0b7e474e01 | ||
|
|
14f0bb75d1 | ||
|
|
32d37a3b9c | ||
|
|
24391c5ac4 | ||
|
|
7ac47dfaa0 | ||
|
|
fd77d6ef37 | ||
|
|
04c9deffd3 | ||
|
|
f8bc00cb55 | ||
|
|
f2ae0b6bd4 | ||
|
|
1904b34c84 | ||
|
|
23ea21d2b4 | ||
|
|
276572a8a5 | ||
|
|
b9bd5ca6a5 | ||
|
|
201a4dd6e7 | ||
|
|
769eb83744 | ||
|
|
66a30c4f37 | ||
|
|
2a744e2fde | ||
|
|
f212aa2e8c | ||
|
|
fc478bd304 | ||
|
|
6e8a2478c4 | ||
|
|
eceb5a9034 | ||
|
|
782acea8c7 | ||
|
|
524d392e83 | ||
|
|
885f1affeb | ||
|
|
50abf75a0a | ||
|
|
4af6427814 | ||
|
|
2a6ec50ce1 | ||
|
|
4497dc655b | ||
|
|
1e2d04ad07 | ||
|
|
5874d3f1fd | ||
|
|
a4abbe6ef3 | ||
|
|
41e3cbb2b2 | ||
|
|
1f77083973 | ||
|
|
b08f993a20 | ||
|
|
113baa625e | ||
|
|
3765d22815 | ||
|
|
24d492903b | ||
|
|
3b4fd70522 | ||
|
|
19cf9101fe | ||
|
|
004319e7ad | ||
|
|
94893d1185 | ||
|
|
13dce2f3e8 | ||
|
|
ea7bc3c52f | ||
|
|
0235a13841 | ||
|
|
be33c88337 | ||
|
|
0456f638c9 | ||
|
|
83ada79ca3 | ||
|
|
913d1e571d | ||
|
|
8f98e510db | ||
|
|
fb0da90b63 | ||
|
|
1e1dec51ab | ||
|
|
c35602e30e | ||
|
|
4c90a777e0 | ||
|
|
9abfa4bad5 | ||
|
|
7ecd0c9891 | ||
|
|
6e25ccdd87 | ||
|
|
a8f970eaf2 | ||
|
|
9f4d362a6d | ||
|
|
c84f05cd22 | ||
|
|
a532520044 |
@@ -118,7 +118,7 @@ add_executable( owgw
|
||||
src/TelemetryStream.cpp src/TelemetryStream.h
|
||||
src/framework/ConfigurationValidator.cpp src/framework/ConfigurationValidator.h
|
||||
src/ConfigurationCache.h
|
||||
src/CapabilitiesCache.h src/FindCountry.h src/rttys/RTTYS_server.cpp src/rttys/RTTYS_server.h src/rttys/RTTYS_device.cpp src/rttys/RTTYS_device.h src/rttys/RTTYS_ClientConnection.cpp src/rttys/RTTYS_ClientConnection.h src/rttys/RTTYS_WebServer.cpp src/rttys/RTTYS_WebServer.h src/RESTAPI/RESTAPI_device_helper.h src/SDKcalls.cpp src/SDKcalls.h src/StateUtils.cpp src/StateUtils.h src/WS_ReactorPool.h src/WS_Connection.h src/WS_Connection.cpp src/TelemetryClient.h src/TelemetryClient.cpp src/RESTAPI/RESTAPI_iptocountry_handler.cpp src/RESTAPI/RESTAPI_iptocountry_handler.h src/framework/ow_constants.h src/GwWebSocketClient.cpp src/GwWebSocketClient.h src/framework/WebSocketClientNotifications.h src/RADIUS_proxy_server.cpp src/RADIUS_proxy_server.h src/RESTAPI/RESTAPI_radiusProxyConfig_handler.cpp src/RESTAPI/RESTAPI_radiusProxyConfig_handler.h src/ParseWifiScan.h src/RADIUS_helpers.h)
|
||||
src/CapabilitiesCache.h src/FindCountry.h src/rttys/RTTYS_server.cpp src/rttys/RTTYS_server.h src/rttys/RTTYS_device.cpp src/rttys/RTTYS_device.h src/rttys/RTTYS_ClientConnection.cpp src/rttys/RTTYS_ClientConnection.h src/rttys/RTTYS_WebServer.cpp src/rttys/RTTYS_WebServer.h src/RESTAPI/RESTAPI_device_helper.h src/SDKcalls.cpp src/SDKcalls.h src/StateUtils.cpp src/StateUtils.h src/WS_ReactorPool.h src/WS_Connection.h src/WS_Connection.cpp src/TelemetryClient.h src/TelemetryClient.cpp src/RESTAPI/RESTAPI_iptocountry_handler.cpp src/RESTAPI/RESTAPI_iptocountry_handler.h src/framework/ow_constants.h src/GwWebSocketClient.cpp src/GwWebSocketClient.h src/framework/WebSocketClientNotifications.h src/RADIUS_proxy_server.cpp src/RADIUS_proxy_server.h src/RESTAPI/RESTAPI_radiusProxyConfig_handler.cpp src/RESTAPI/RESTAPI_radiusProxyConfig_handler.h src/ParseWifiScan.h src/RADIUS_helpers.h src/VenueBroadcaster.h src/sdks/sdk_prov.h)
|
||||
|
||||
if(NOT SMALL_BUILD)
|
||||
|
||||
|
||||
15
PROTOCOL.md
15
PROTOCOL.md
@@ -184,6 +184,21 @@ The device should answer:
|
||||
}
|
||||
```
|
||||
|
||||
#### Device requests a venue broadcast message
|
||||
Device send this message when it wants to reach out to all other APs in the same venue. The GW will find the
|
||||
venue where this device belongs and resend the same message to all other devices in the venue.
|
||||
```json
|
||||
{ "jsonrpc" : "2.0" ,
|
||||
"method" : "venue_broadcast" ,
|
||||
"params" : {
|
||||
"serial" : <serial number> ,
|
||||
"timestamp" : <the UTC timestamp when the message was sent>,
|
||||
"data" : <an opaque string from the AP. This could be Zipped and so on and most likely base64 encoded>
|
||||
}
|
||||
}
|
||||
```
|
||||
Upon receiving a `venue_broadcast` message, the GW will simply resent the message to all the APs in the venue.
|
||||
|
||||
### Controller commands
|
||||
Most controller commands include a `when` member. This is a UTC clock time asking the AP
|
||||
to perform the command at that time. This is a suggestion only. The AP may ignore this
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,10 @@ if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
|
||||
SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16002"} \
|
||||
SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
|
||||
SIMULATORID=${SIMULATORID:-""} \
|
||||
IPTOCOUNTRY_PROVIDER=${IPTOCOUNTRY_PROVIDER:-"ipinfo"} \
|
||||
IPTOCOUNTRY_IPINFO_TOKEN=${IPTOCOUNTRY_IPINFO_TOKEN:-""} \
|
||||
IPTOCOUNTRY_IPDATA_APIKEY=${IPTOCOUNTRY_IPDATA_APIKEY:-""} \
|
||||
AUTOPROVISIONING_PROCESS=${AUTOPROVISIONING_PROCESS:-"prov,default"} \
|
||||
RTTY_INTERNAL=${RTTY_INTERNAL:-"true"} \
|
||||
RTTY_ENABLED=${RTTY_ENABLED:-"true"} \
|
||||
RTTY_SERVER=${RTTY_SERVER:-"localhost"} \
|
||||
|
||||
@@ -9,7 +9,7 @@ fullnameOverride: ""
|
||||
images:
|
||||
owgw:
|
||||
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
|
||||
tag: v2.6.0-RC4
|
||||
tag: v2.6.2
|
||||
pullPolicy: Always
|
||||
# regcred:
|
||||
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
|
||||
|
||||
@@ -52,8 +52,8 @@ openwifi.fileuploader.host.0.cert = ${FILEUPLOADER_HOST_CERT}
|
||||
openwifi.fileuploader.host.0.key = ${FILEUPLOADER_HOST_KEY}
|
||||
openwifi.fileuploader.host.0.key.password = ${FILEUPLOADER_HOST_KEY_PASSWORD}
|
||||
openwifi.fileuploader.path = ${FILEUPLOADER_PATH}
|
||||
openwifi.fileuploader.uri = ${FILEUPLOADER_URI}
|
||||
openwifi.fileuploader.maxsize = 10000
|
||||
openwifi.fileuploader.uri = ${FILEUPLOADER_URI}
|
||||
|
||||
#
|
||||
# Generic section that all microservices must have
|
||||
@@ -75,8 +75,13 @@ openwifi.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
|
||||
openwifi.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
|
||||
openwifi.devicetypes.2 = IOT:esp32
|
||||
oui.download.uri = https://standards-oui.ieee.org/oui/oui.txt
|
||||
firmware.autoupdate.policy.default = auto
|
||||
simulatorid = ${SIMULATORID}
|
||||
iptocountry.default = US
|
||||
iptocountry.provider = ${IPTOCOUNTRY_PROVIDER}
|
||||
iptocountry.ipinfo.token = ${IPTOCOUNTRY_IPINFO_TOKEN}
|
||||
iptocountry.ipdata.apikey = ${IPTOCOUNTRY_IPDATA_APIKEY}
|
||||
|
||||
autoprovisioning.process = ${AUTOPROVISIONING_PROCESS}
|
||||
|
||||
#
|
||||
# rtty
|
||||
@@ -108,6 +113,7 @@ openwifi.kafka.enable = ${KAFKA_ENABLE}
|
||||
openwifi.kafka.brokerlist = ${KAFKA_BROKERLIST}
|
||||
openwifi.kafka.auto.commit = false
|
||||
openwifi.kafka.queue.buffering.max.ms = 50
|
||||
|
||||
openwifi.kafka.ssl.ca.location = ${KAFKA_SSL_CA_LOCATION}
|
||||
openwifi.kafka.ssl.certificate.location = ${KAFKA_SSL_CERTIFICATE_LOCATION}
|
||||
openwifi.kafka.ssl.key.location = ${KAFKA_SSL_KEY_LOCATION}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
namespace OpenWifi {
|
||||
|
||||
void CommandManager::run() {
|
||||
Utils::SetThreadName("command-mgr");
|
||||
Utils::SetThreadName("cmd-mgr");
|
||||
Running_ = true;
|
||||
Poco::AutoPtr<Poco::Notification> NextMsg(ResponseQueue_.waitDequeueNotification());
|
||||
while(NextMsg && Running_) {
|
||||
@@ -32,42 +32,32 @@ namespace OpenWifi {
|
||||
std::ostringstream SS;
|
||||
Payload.stringify(SS);
|
||||
|
||||
// std::cout << SerialNumber << ": " << __LINE__ << std::endl;
|
||||
// std::cout << "Got RPC Answer: " << SerialNumber << " Payload:" << SS.str() << std::endl;
|
||||
Logger().debug(fmt::format("({}): RPC Response received.", SerialNumber));
|
||||
if(!Payload.has(uCentralProtocol::ID)){
|
||||
// std::cout << SerialNumber << ": " << __LINE__ << std::endl;
|
||||
Logger().error(fmt::format("({}): Invalid RPC response.", SerialNumber));
|
||||
} else {
|
||||
uint64_t ID = Payload.get(uCentralProtocol::ID);
|
||||
if (ID < 2) {
|
||||
// std::cout << SerialNumber << ": " << __LINE__ << std::endl;
|
||||
Logger().debug(fmt::format("({}): Ignoring RPC response.", SerialNumber));
|
||||
} else {
|
||||
auto Idx = CommandTagIndex{.Id = ID, .SerialNumber = SerialNumber};
|
||||
std::lock_guard G(Mutex_);
|
||||
auto RPC = OutStandingRequests_.find(Idx);
|
||||
if (RPC == OutStandingRequests_.end()) {
|
||||
// std::cout << SerialNumber << ": " << __LINE__ << std::endl;
|
||||
Logger().warning(
|
||||
fmt::format("({}): Outdated RPC {}", SerialNumber, ID));
|
||||
} else {
|
||||
// std::cout << SerialNumber << ": " << __LINE__ << std::endl;
|
||||
std::chrono::duration<double, std::milli> rpc_execution_time =
|
||||
std::chrono::high_resolution_clock::now() - RPC->second->submitted;
|
||||
StorageService()->CommandCompleted(RPC->second->uuid, Payload,
|
||||
rpc_execution_time, true);
|
||||
// std::cout << SerialNumber << ": " << __LINE__ << std::endl;
|
||||
if (RPC->second->rpc_entry) {
|
||||
// std::cout << SerialNumber << ": " << __LINE__ << std::endl;
|
||||
RPC->second->rpc_entry->set_value(Payload);
|
||||
}
|
||||
// std::cout << SerialNumber << ": " << __LINE__ << std::endl;
|
||||
OutstandingUUIDs_.erase(RPC->second->uuid);
|
||||
OutStandingRequests_.erase(Idx);
|
||||
Logger().information(
|
||||
fmt::format("({}): Received RPC answer {}", SerialNumber, ID));
|
||||
// std::cout << SerialNumber << ": " << __LINE__ << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,7 +68,6 @@ namespace OpenWifi {
|
||||
|
||||
int CommandManager::Start() {
|
||||
Logger().notice("Starting...");
|
||||
ManagerThread.setStackSize(2000000);
|
||||
ManagerThread.start(*this);
|
||||
JanitorCallback_ = std::make_unique<Poco::TimerCallback<CommandManager>>(*this,&CommandManager::onJanitorTimer);
|
||||
JanitorTimer_.setStartInterval( 10000 );
|
||||
@@ -90,15 +79,11 @@ namespace OpenWifi {
|
||||
CommandRunnerTimer_.setPeriodicInterval(30 * 1000); // 1 hours
|
||||
CommandRunnerTimer_.start(*CommandRunnerCallback_);
|
||||
|
||||
// RPCResponseQueue_->Readable_ += Poco::delegate(this,&CommandManager::onRPCAnswer);
|
||||
// RPCResponseQueue_->Writable_ += Poco::delegate(this,&CommandManager::onRPCAnswer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CommandManager::Stop() {
|
||||
Logger().notice("Stopping...");
|
||||
// RPCResponseQueue_->Readable_ -= Poco::delegate(this,&CommandManager::onRPCAnswer);
|
||||
// RPCResponseQueue_->Writable_ -= Poco::delegate(this,&CommandManager::onRPCAnswer);
|
||||
Running_ = false;
|
||||
JanitorTimer_.stop();
|
||||
CommandRunnerTimer_.stop();
|
||||
@@ -114,26 +99,29 @@ namespace OpenWifi {
|
||||
|
||||
void CommandManager::onJanitorTimer([[maybe_unused]] Poco::Timer & timer) {
|
||||
std::lock_guard G(Mutex_);
|
||||
Utils::SetThreadName("command-janitor");
|
||||
Logger().information(
|
||||
Utils::SetThreadName("cmd-janitor");
|
||||
Poco::Logger & MyLogger = Poco::Logger::get("CMD-MGR-JANITOR");
|
||||
MyLogger.information(
|
||||
fmt::format("Removing expired commands: start. {} outstanding-requests {} outstanding-uuids commands.",
|
||||
OutStandingRequests_.size(), OutstandingUUIDs_.size() ));
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
for(auto i=OutStandingRequests_.begin();i!=OutStandingRequests_.end();) {
|
||||
std::chrono::duration<double, std::milli> delta = now - i->second->submitted;
|
||||
if(delta > 6000000ms) {
|
||||
Logger().debug(fmt::format("{}: Timed out.", i->second->uuid));
|
||||
MyLogger.debug(fmt::format("{}: Timed out.", i->second->uuid));
|
||||
OutstandingUUIDs_.erase(i->second->uuid);
|
||||
i = OutStandingRequests_.erase(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
Logger().information("Removing expired commands: done.");
|
||||
MyLogger.information("Removing expired commands: done.");
|
||||
}
|
||||
|
||||
void CommandManager::onCommandRunnerTimer([[maybe_unused]] Poco::Timer &timer) {
|
||||
Utils::SetThreadName("command-runner");
|
||||
Utils::SetThreadName("cmd-schdlr");
|
||||
Poco::Logger & MyLogger = Poco::Logger::get("CMD-MGR-SCHEDULER");
|
||||
|
||||
std::vector<GWObjects::CommandDetails> Commands;
|
||||
if(StorageService()->GetReadyToExecuteCommands(0,200,Commands))
|
||||
{
|
||||
@@ -150,7 +138,7 @@ namespace OpenWifi {
|
||||
|
||||
Poco::JSON::Parser P;
|
||||
bool Sent;
|
||||
Logger().information(fmt::format("{}: Preparing execution of {} for {}.", Cmd.UUID, Cmd.Command, Cmd.SerialNumber));
|
||||
MyLogger.information(fmt::format("{}: Preparing execution of {} for {}.", Cmd.UUID, Cmd.Command, Cmd.SerialNumber));
|
||||
auto Params = P.parse(Cmd.Details).extract<Poco::JSON::Object::Ptr>();
|
||||
auto Result = PostCommandDisk( Cmd.SerialNumber,
|
||||
Cmd.Command,
|
||||
@@ -161,16 +149,16 @@ namespace OpenWifi {
|
||||
StorageService()->SetCommandExecuted(Cmd.UUID);
|
||||
std::lock_guard M(Mutex_);
|
||||
OutstandingUUIDs_.insert(Cmd.UUID);
|
||||
Logger().information(fmt::format("{}: Queued command.", Cmd.UUID));
|
||||
MyLogger.information(fmt::format("{}: Queued command.", Cmd.UUID));
|
||||
} else {
|
||||
Logger().information(fmt::format("{}: Could queue command.", Cmd.UUID));
|
||||
MyLogger.information(fmt::format("{}: Could queue command.", Cmd.UUID));
|
||||
}
|
||||
} catch (const Poco::Exception &E) {
|
||||
Logger().information(fmt::format("{}: Failed. Command marked as completed.", Cmd.UUID));
|
||||
Logger().log(E);
|
||||
MyLogger.information(fmt::format("{}: Failed. Command marked as completed.", Cmd.UUID));
|
||||
MyLogger.log(E);
|
||||
StorageService()->SetCommandExecuted(Cmd.UUID);
|
||||
} catch (...) {
|
||||
Logger().information(fmt::format("{}: Hard failure.", Cmd.UUID));
|
||||
MyLogger.information(fmt::format("{}: Hard failure.", Cmd.UUID));
|
||||
StorageService()->SetCommandExecuted(Cmd.UUID);
|
||||
}
|
||||
}
|
||||
@@ -221,11 +209,13 @@ namespace OpenWifi {
|
||||
}
|
||||
}
|
||||
|
||||
Logger().information(fmt::format("{}: Sending command. ID: {}", UUID, Idx.Id));
|
||||
if(DeviceRegistry()->SendFrame(SerialNumber, ToSend.str())) {
|
||||
Logger().information(fmt::format("{}: Sent command. ID: {}", UUID, Idx.Id));
|
||||
Sent=true;
|
||||
return Object->rpc_entry;
|
||||
}
|
||||
Logger().information(fmt::format("{}: Failed to send command. ID: {}", UUID, Idx.Id));
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace
|
||||
@@ -154,16 +154,15 @@ namespace OpenWifi {
|
||||
void onRPCAnswer(bool& b);
|
||||
|
||||
private:
|
||||
mutable std::atomic_bool Running_ = false;
|
||||
volatile bool Running_ = false;
|
||||
Poco::Thread ManagerThread;
|
||||
mutable uint64_t Id_=3; // do not start @1. We ignore ID=1 & 0 is illegal..
|
||||
volatile uint64_t Id_=3; // do not start @1. We ignore ID=1 & 0 is illegal..
|
||||
std::map<CommandTagIndex,std::shared_ptr<RpcObject>> OutStandingRequests_;
|
||||
std::set<std::string> OutstandingUUIDs_;
|
||||
Poco::Timer JanitorTimer_;
|
||||
std::unique_ptr<Poco::TimerCallback<CommandManager>> JanitorCallback_;
|
||||
Poco::Timer CommandRunnerTimer_;
|
||||
std::unique_ptr<Poco::TimerCallback<CommandManager>> CommandRunnerCallback_;
|
||||
// std::unique_ptr<FIFO<RPCResponse>> RPCResponseQueue_=std::make_unique<FIFO<RPCResponse>>(100);
|
||||
Poco::NotificationQueue ResponseQueue_;
|
||||
|
||||
std::shared_ptr<promise_type_t> PostCommand(
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "FindCountry.h"
|
||||
#include "rttys/RTTYS_server.h"
|
||||
#include "RADIUS_proxy_server.h"
|
||||
#include "VenueBroadcaster.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class Daemon *Daemon::instance() {
|
||||
@@ -47,7 +48,8 @@ namespace OpenWifi {
|
||||
TelemetryStream(),
|
||||
RTTYS_server(),
|
||||
WebSocketServer(),
|
||||
RADIUS_proxy_server()
|
||||
RADIUS_proxy_server(),
|
||||
VenueBroadcaster()
|
||||
});
|
||||
return &instance;
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace OpenWifi {
|
||||
uint64_t LastUpdate_ = 0 ;
|
||||
bool Initialized_ = false;
|
||||
OUIMap OUIs_;
|
||||
mutable std::atomic_bool Updating_=false;
|
||||
mutable std::atomic_bool Running_=false;
|
||||
volatile std::atomic_bool Updating_=false;
|
||||
volatile std::atomic_bool Running_=false;
|
||||
Poco::Timer Timer_;
|
||||
std::unique_ptr<Poco::TimerCallback<OUIServer>> UpdaterCallBack_;
|
||||
std::string LatestOUIFileName_,CurrentOUIFileName_;
|
||||
|
||||
@@ -1741,7 +1741,6 @@ namespace OpenWifi {
|
||||
std::cout << "Start of parsing wifi" << std::endl;
|
||||
if (D.contains("status")) {
|
||||
auto Status = D["status"];
|
||||
|
||||
if (Status.contains("scan") && Status["scan"].is_array()) {
|
||||
nlohmann::json ScanArray = Status["scan"];
|
||||
nlohmann::json ParsedScan = nlohmann::json::array();
|
||||
|
||||
@@ -818,7 +818,6 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
|
||||
}
|
||||
|
||||
Logger_.information(fmt::format("RTTY: user={} serial={}. Getting configuration.", UserInfo_.userinfo.email,SerialNumber_));
|
||||
if (MicroService::instance().ConfigGetBool("rtty.enabled", false)) {
|
||||
GWObjects::Device Device;
|
||||
|
||||
@@ -839,11 +838,8 @@ namespace OpenWifi {
|
||||
};
|
||||
|
||||
if(RTTYS_server()->UseInternal()) {
|
||||
Logger_.information(fmt::format("RTTY: user={} serial={}. Creating hash.", UserInfo_.userinfo.email,SerialNumber_));
|
||||
Rtty.Token = MicroService::instance().CreateHash(UserInfo_.webtoken.refresh_token_ + std::to_string(OpenWifi::Now())).substr(0,32);
|
||||
Logger_.information(fmt::format("RTTY: user={} serial={}. Creating endpoint.", UserInfo_.userinfo.email,SerialNumber_));
|
||||
RTTYS_server()->CreateEndPoint(Rtty.ConnectionId,Rtty.Token, UserInfo_.userinfo.email, SerialNumber_);
|
||||
Logger_.information(fmt::format("RTTY: user={} serial={}. Created endpoint.", UserInfo_.userinfo.email,SerialNumber_));
|
||||
RTTYS_server()->CreateEndPoint(Rtty.ConnectionId, Rtty.Token, UserInfo_.userinfo.email, SerialNumber_);
|
||||
}
|
||||
|
||||
Poco::JSON::Object ReturnedObject;
|
||||
@@ -872,11 +868,9 @@ namespace OpenWifi {
|
||||
Params.stringify(ParamStream);
|
||||
Cmd.Details = ParamStream.str();
|
||||
|
||||
Logger_.information(fmt::format("RTTY: user={} serial={}. Sending RPC request.", UserInfo_.userinfo.email,SerialNumber_));
|
||||
|
||||
Logger_.information(fmt::format("RTTY: user={} serial={} id={}.", UserInfo_.userinfo.email,SerialNumber_,Rtty.ConnectionId));
|
||||
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000ms, &ReturnedObject, this, Logger_);
|
||||
}
|
||||
Logger_.information(fmt::format("RTTY: user={} serial={}. Device does not exist.", UserInfo_.userinfo.email,SerialNumber_));
|
||||
return NotFound();
|
||||
}
|
||||
Logger_.information(fmt::format("RTTY: user={} serial={}. Internal error.", UserInfo_.userinfo.email,SerialNumber_));
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace OpenWifi {
|
||||
void onMessage(bool& b);
|
||||
|
||||
private:
|
||||
mutable std::atomic_bool Running_=false;
|
||||
volatile std::atomic_bool Running_=false;
|
||||
std::map<std::string, TelemetryClient *> Clients_; // uuid -> client
|
||||
std::map<uint64_t, std::set<std::string>> SerialNumbers_; // serialNumber -> uuid
|
||||
Poco::Net::SocketReactor Reactor_;
|
||||
|
||||
142
src/VenueBroadcaster.h
Normal file
142
src/VenueBroadcaster.h
Normal file
@@ -0,0 +1,142 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-07-16.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/MicroService.h"
|
||||
#include "sdks/sdk_prov.h"
|
||||
#include "DeviceRegistry.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class VenueBroadcastNotification : public Poco::Notification {
|
||||
public:
|
||||
VenueBroadcastNotification(const std::string &SourceSerialNumber, const std::string &Data, uint64_t TimeStamp) :
|
||||
SourceSerialNumber_(SourceSerialNumber),
|
||||
Data_(Data),
|
||||
TimeStamp_(TimeStamp) {
|
||||
|
||||
}
|
||||
std::string SourceSerialNumber_;
|
||||
std::string Data_;
|
||||
uint64_t TimeStamp_=OpenWifi::Now();
|
||||
};
|
||||
|
||||
class VenueBroadcaster : public SubSystemServer, Poco::Runnable {
|
||||
public:
|
||||
static auto instance() {
|
||||
static auto instance_ = new VenueBroadcaster;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
inline int Start() override {
|
||||
Enabled_ = MicroService::instance().ConfigGetBool("venue_broadcast.enabled",true);
|
||||
if(Enabled_) {
|
||||
BroadcastManager_.start(*this);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void Stop() override {
|
||||
if(Enabled_ && Running_) {
|
||||
BroadcastQueue_.wakeUpAll();
|
||||
BroadcastManager_.wakeUp();
|
||||
BroadcastManager_.join();
|
||||
}
|
||||
}
|
||||
|
||||
inline void reinitialize([[maybe_unused]] Poco::Util::Application &self) override {
|
||||
Logger().information("Reinitializing.");
|
||||
}
|
||||
|
||||
|
||||
struct VenueInfo {
|
||||
uint64_t timestamp=OpenWifi::Now();
|
||||
Types::StringVec serialNumbers;
|
||||
};
|
||||
|
||||
inline bool FindSerialNumberList(const std::string &Source, OpenWifi::Types::StringVec & SerialNumbers) {
|
||||
// Can we find our serial number in any of the lists so far...
|
||||
for(const auto &venue:Venues_) {
|
||||
auto entry = std::find(venue.second.serialNumbers.begin(),venue.second.serialNumbers.end(),Source);
|
||||
if(entry!=venue.second.serialNumbers.end() && (OpenWifi::Now()-venue.second.timestamp)<600) {
|
||||
SerialNumbers = venue.second.serialNumbers;
|
||||
auto entry2 = std::find(SerialNumbers.begin(),SerialNumbers.end(),Source);
|
||||
SerialNumbers.erase(entry2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// get the venue from Prov and the serial numbers.
|
||||
Types::UUID_t Venue;
|
||||
Types::StringVec TmpSerialNumbers;
|
||||
if(OpenWifi::SDK::Prov::GetSerialNumbersForVenueOfSerialNumber(Source,Venue,TmpSerialNumbers,Logger())) {
|
||||
std::sort(TmpSerialNumbers.begin(),TmpSerialNumbers.end());
|
||||
VenueInfo V{.timestamp=OpenWifi::Now(), .serialNumbers=TmpSerialNumbers};
|
||||
Venues_[Venue] = V;
|
||||
auto p = std::find(TmpSerialNumbers.begin(),TmpSerialNumbers.end(),Source);
|
||||
if(p!=TmpSerialNumbers.end()) {
|
||||
TmpSerialNumbers.erase(p);
|
||||
SerialNumbers = TmpSerialNumbers;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void SendToDevice(const std::string &SerialNumber,const std::string &Payload) {
|
||||
DeviceRegistry()->SendFrame(SerialNumber,Payload);
|
||||
}
|
||||
|
||||
inline void run() final {
|
||||
Running_ = true;
|
||||
Utils::SetThreadName("venue-bcast");
|
||||
Poco::AutoPtr<Poco::Notification> NextNotification(BroadcastQueue_.waitDequeueNotification());
|
||||
while (NextNotification && Running_) {
|
||||
auto Notification = dynamic_cast<VenueBroadcastNotification *>(NextNotification.get());
|
||||
if (Notification != nullptr) {
|
||||
Types::StringVec SerialNumbers;
|
||||
if(FindSerialNumberList(Notification->SourceSerialNumber_,SerialNumbers)) {
|
||||
Poco::JSON::Object Payload;
|
||||
Payload.set("jsonrpc","2.0");
|
||||
Payload.set("method","venue_broadcast");
|
||||
Poco::JSON::Object ParamBlock;
|
||||
ParamBlock.set("serial",Notification->SourceSerialNumber_);
|
||||
ParamBlock.set("timestamp",Notification->TimeStamp_);
|
||||
ParamBlock.set("data",Notification->Data_);
|
||||
Payload.set("params", ParamBlock);
|
||||
std::ostringstream o;
|
||||
Payload.stringify(o);
|
||||
for(const auto &Device:SerialNumbers) {
|
||||
SendToDevice(Device,o.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
NextNotification = BroadcastQueue_.waitDequeueNotification();
|
||||
}
|
||||
Running_=false;
|
||||
}
|
||||
|
||||
inline void Broadcast(const std::string &SourceSerial, const std::string &Data, uint64_t TimeStamp) {
|
||||
BroadcastQueue_.enqueueNotification(new VenueBroadcastNotification(SourceSerial,Data,TimeStamp));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::atomic_bool Running_=false;
|
||||
bool Enabled_=false;
|
||||
Poco::NotificationQueue BroadcastQueue_;
|
||||
Poco::Thread BroadcastManager_;
|
||||
|
||||
std::map<OpenWifi::Types::UUID_t,VenueInfo> Venues_;
|
||||
|
||||
VenueBroadcaster() noexcept:
|
||||
SubSystemServer("VenueBroadcaster", "VENUE-BCAST", "venue.broacast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline auto VenueBroadcaster() { return VenueBroadcaster::instance(); }
|
||||
}
|
||||
@@ -5,11 +5,13 @@
|
||||
#include "WS_Connection.h"
|
||||
|
||||
#include "Poco/Net/SecureStreamSocketImpl.h"
|
||||
#include "Poco/Net/SecureServerSocketImpl.h"
|
||||
#include "Poco/Net/HTTPServerResponseImpl.h"
|
||||
#include "Poco/Net/HTTPServerSession.h"
|
||||
#include "Poco/Net/HTTPServerRequestImpl.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/SSLException.h"
|
||||
#include "Poco/Net/Context.h"
|
||||
#include "Poco/Base64Decoder.h"
|
||||
#include "Poco/Base64Encoder.h"
|
||||
|
||||
@@ -24,6 +26,7 @@
|
||||
#include "TelemetryStream.h"
|
||||
#include "CentralConfig.h"
|
||||
#include "FindCountry.h"
|
||||
#include "VenueBroadcaster.h"
|
||||
#include "framework/WebSocketClientNotifications.h"
|
||||
|
||||
#include "RADIUS_proxy_server.h"
|
||||
@@ -358,7 +361,8 @@ namespace OpenWifi {
|
||||
auto Firmware = ParamsObj->get(uCentralProtocol::FIRMWARE).toString();
|
||||
auto Capabilities = ParamsObj->get(uCentralProtocol::CAPABILITIES).toString();
|
||||
|
||||
SerialNumber_ = Serial;
|
||||
//// change this
|
||||
CN_ = SerialNumber_ = Serial;
|
||||
SerialNumberInt_ = Utils::SerialNumberToInt(SerialNumber_);
|
||||
Conn_ = DeviceRegistry()->Register(SerialNumberInt_, this, ConnectionId_);
|
||||
Conn_->Conn_.UUID = UUID;
|
||||
@@ -753,6 +757,14 @@ namespace OpenWifi {
|
||||
}
|
||||
} break;
|
||||
|
||||
case uCentralProtocol::Events::ET_VENUEBROADCAST: {
|
||||
if(ParamsObj->has("data") && ParamsObj->has("serial") && ParamsObj->has("timestamp")) {
|
||||
VenueBroadcaster()->Broadcast(
|
||||
ParamsObj->get("serial").toString(),
|
||||
ParamsObj->get("data").toString(),
|
||||
ParamsObj->get("timestamp"));
|
||||
}
|
||||
} break;
|
||||
// this will never be called but some compilers will complain if we do not have a case for
|
||||
// every single values of an enum
|
||||
case uCentralProtocol::Events::ET_UNKNOWN: {
|
||||
|
||||
@@ -17,81 +17,81 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class WSConnection {
|
||||
static constexpr int BufSize = 128000;
|
||||
public:
|
||||
WSConnection(Poco::Net::StreamSocket& Socket, Poco::Net::SocketReactor& Reactor);
|
||||
~WSConnection();
|
||||
class WSConnection {
|
||||
static constexpr int BufSize = 128000;
|
||||
public:
|
||||
WSConnection(Poco::Net::StreamSocket& Socket, Poco::Net::SocketReactor& Reactor);
|
||||
~WSConnection();
|
||||
|
||||
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr & Doc);
|
||||
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
|
||||
void ProcessIncomingFrame();
|
||||
void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
|
||||
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr & Doc);
|
||||
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
|
||||
void ProcessIncomingFrame();
|
||||
void ProcessIncomingRadiusData(const Poco::JSON::Object::Ptr &Doc);
|
||||
|
||||
bool Send(const std::string &Payload);
|
||||
bool Send(const std::string &Payload);
|
||||
|
||||
bool SendRadiusAuthenticationData(const unsigned char * buffer, std::size_t size);
|
||||
bool SendRadiusAccountingData(const unsigned char * buffer, std::size_t size);
|
||||
bool SendRadiusCoAData(const unsigned char * buffer, std::size_t size);
|
||||
bool SendRadiusAuthenticationData(const unsigned char * buffer, std::size_t size);
|
||||
bool SendRadiusAccountingData(const unsigned char * buffer, std::size_t size);
|
||||
bool SendRadiusCoAData(const unsigned char * buffer, std::size_t size);
|
||||
|
||||
void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
|
||||
void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf);
|
||||
void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf);
|
||||
bool LookForUpgrade(const uint64_t UUID, uint64_t & UpgradedUUID);
|
||||
static bool ExtractBase64CompressedData(const std::string & CompressedData, std::string & UnCompressedData, uint64_t compress_sz);
|
||||
void LogException(const Poco::Exception &E);
|
||||
inline Poco::Logger & Logger() { return Logger_; }
|
||||
bool SetWebSocketTelemetryReporting(uint64_t interval, uint64_t TelemetryWebSocketTimer);
|
||||
bool SetKafkaTelemetryReporting(uint64_t interval, uint64_t TelemetryKafkaTimer);
|
||||
bool StopWebSocketTelemetry();
|
||||
bool StopKafkaTelemetry();
|
||||
inline bool GetTelemetryParameters(bool & Reporting, uint64_t & Interval,
|
||||
uint64_t & WebSocketTimer, uint64_t & KafkaTimer,
|
||||
uint64_t &WebSocketCount, uint64_t & KafkaCount,
|
||||
uint64_t &WebSocketPackets,
|
||||
uint64_t &KafkaPackets ) const {
|
||||
Reporting = TelemetryReporting_;
|
||||
WebSocketTimer = TelemetryWebSocketTimer_;
|
||||
KafkaTimer = TelemetryKafkaTimer_;
|
||||
WebSocketCount = TelemetryWebSocketRefCount_;
|
||||
KafkaCount = TelemetryKafkaRefCount_;
|
||||
Interval = TelemetryInterval_;
|
||||
WebSocketPackets = TelemetryWebSocketPackets_;
|
||||
KafkaPackets = TelemetryKafkaPackets_;
|
||||
return true;
|
||||
}
|
||||
void OnSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
|
||||
void OnSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf);
|
||||
void OnSocketError(const Poco::AutoPtr<Poco::Net::ErrorNotification>& pNf);
|
||||
bool LookForUpgrade(const uint64_t UUID, uint64_t & UpgradedUUID);
|
||||
static bool ExtractBase64CompressedData(const std::string & CompressedData, std::string & UnCompressedData, uint64_t compress_sz);
|
||||
void LogException(const Poco::Exception &E);
|
||||
inline Poco::Logger & Logger() { return Logger_; }
|
||||
bool SetWebSocketTelemetryReporting(uint64_t interval, uint64_t TelemetryWebSocketTimer);
|
||||
bool SetKafkaTelemetryReporting(uint64_t interval, uint64_t TelemetryKafkaTimer);
|
||||
bool StopWebSocketTelemetry();
|
||||
bool StopKafkaTelemetry();
|
||||
inline bool GetTelemetryParameters(bool & Reporting, uint64_t & Interval,
|
||||
uint64_t & WebSocketTimer, uint64_t & KafkaTimer,
|
||||
uint64_t &WebSocketCount, uint64_t & KafkaCount,
|
||||
uint64_t &WebSocketPackets,
|
||||
uint64_t &KafkaPackets ) const {
|
||||
Reporting = TelemetryReporting_;
|
||||
WebSocketTimer = TelemetryWebSocketTimer_;
|
||||
KafkaTimer = TelemetryKafkaTimer_;
|
||||
WebSocketCount = TelemetryWebSocketRefCount_;
|
||||
KafkaCount = TelemetryKafkaRefCount_;
|
||||
Interval = TelemetryInterval_;
|
||||
WebSocketPackets = TelemetryWebSocketPackets_;
|
||||
KafkaPackets = TelemetryKafkaPackets_;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::recursive_mutex Mutex_;
|
||||
Poco::Logger &Logger_;
|
||||
Poco::Net::StreamSocket Socket_;
|
||||
Poco::Net::SocketReactor & Reactor_;
|
||||
std::unique_ptr<Poco::Net::WebSocket> WS_;
|
||||
std::string SerialNumber_;
|
||||
uint64_t SerialNumberInt_=0;
|
||||
std::string Compatible_;
|
||||
std::shared_ptr<DeviceRegistry::ConnectionEntry> Conn_;
|
||||
mutable bool Registered_ = false ;
|
||||
std::string CId_;
|
||||
std::string CN_;
|
||||
GWObjects::CertificateValidation CertValidation_ = GWObjects::CertificateValidation::NO_CERTIFICATE;
|
||||
uint64_t Errors_=0;
|
||||
mutable bool Connected_=false;
|
||||
uint64_t ConnectionId_=0;
|
||||
Poco::Net::IPAddress PeerAddress_;
|
||||
mutable std::atomic_bool TelemetryReporting_ = false;
|
||||
mutable uint64_t TelemetryWebSocketRefCount_ = 0;
|
||||
mutable uint64_t TelemetryKafkaRefCount_ = 0;
|
||||
mutable uint64_t TelemetryWebSocketTimer_ = 0;
|
||||
mutable uint64_t TelemetryKafkaTimer_ = 0 ;
|
||||
mutable uint64_t TelemetryInterval_ = 0;
|
||||
mutable uint64_t TelemetryWebSocketPackets_=0;
|
||||
mutable uint64_t TelemetryKafkaPackets_=0;
|
||||
private:
|
||||
std::recursive_mutex Mutex_;
|
||||
Poco::Logger &Logger_;
|
||||
Poco::Net::StreamSocket Socket_;
|
||||
Poco::Net::SocketReactor & Reactor_;
|
||||
std::unique_ptr<Poco::Net::WebSocket> WS_;
|
||||
std::string SerialNumber_;
|
||||
uint64_t SerialNumberInt_=0;
|
||||
std::string Compatible_;
|
||||
std::shared_ptr<DeviceRegistry::ConnectionEntry> Conn_;
|
||||
volatile bool Registered_ = false ;
|
||||
std::string CId_;
|
||||
std::string CN_;
|
||||
GWObjects::CertificateValidation CertValidation_ = GWObjects::CertificateValidation::NO_CERTIFICATE;
|
||||
uint64_t Errors_=0;
|
||||
volatile bool Connected_=false;
|
||||
uint64_t ConnectionId_=0;
|
||||
Poco::Net::IPAddress PeerAddress_;
|
||||
volatile std::atomic_bool TelemetryReporting_ = false;
|
||||
volatile uint64_t TelemetryWebSocketRefCount_ = 0;
|
||||
volatile uint64_t TelemetryKafkaRefCount_ = 0;
|
||||
uint64_t TelemetryWebSocketTimer_ = 0;
|
||||
uint64_t TelemetryKafkaTimer_ = 0 ;
|
||||
uint64_t TelemetryInterval_ = 0;
|
||||
volatile uint64_t TelemetryWebSocketPackets_=0;
|
||||
volatile uint64_t TelemetryKafkaPackets_=0;
|
||||
|
||||
void CompleteStartup();
|
||||
bool StartTelemetry();
|
||||
bool StopTelemetry();
|
||||
void UpdateCounts();
|
||||
};
|
||||
void CompleteStartup();
|
||||
bool StartTelemetry();
|
||||
bool StopTelemetry();
|
||||
void UpdateCounts();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -8,75 +8,77 @@
|
||||
|
||||
#include "Poco/Net/HTTPHeaderStream.h"
|
||||
#include "Poco/JSON/Array.h"
|
||||
#include "Poco/Net/Context.h"
|
||||
|
||||
#include "ConfigurationCache.h"
|
||||
#include "TelemetryStream.h"
|
||||
#include "WS_Server.h"
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
bool WebSocketServer::ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate) {
|
||||
if(IsCertOk()) {
|
||||
Logger().debug(fmt::format("CERTIFICATE({}): issuer='{}' cn='{}'", ConnectionId, Certificate.issuerName(),Certificate.commonName()));
|
||||
if(!Certificate.issuedBy(*IssuerCert_)) {
|
||||
Logger().debug(fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'", ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName()));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
bool WebSocketServer::ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate) {
|
||||
if(IsCertOk()) {
|
||||
Logger().debug(fmt::format("CERTIFICATE({}): issuer='{}' cn='{}'", ConnectionId, Certificate.issuerName(),Certificate.commonName()));
|
||||
if(!Certificate.issuedBy(*IssuerCert_)) {
|
||||
Logger().debug(fmt::format("CERTIFICATE({}): issuer mismatch. Local='{}' Incoming='{}'", ConnectionId, IssuerCert_->issuerName(), Certificate.issuerName()));
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int WebSocketServer::Start() {
|
||||
// ReactorPool_.Start("DeviceReactorPool_");
|
||||
for(const auto & Svr : ConfigServersList_ ) {
|
||||
Logger().notice( fmt::format("Starting: {}:{} Keyfile:{} CertFile: {}",
|
||||
Svr.Address(),
|
||||
Svr.Port(),
|
||||
Svr.KeyFile(),Svr.CertFile()));
|
||||
|
||||
Svr.LogCert(Logger());
|
||||
if(!Svr.RootCA().empty())
|
||||
Svr.LogCas(Logger());
|
||||
|
||||
auto Sock{Svr.CreateSecureSocket(Logger())};
|
||||
|
||||
if(!IsCertOk()) {
|
||||
IssuerCert_ = std::make_unique<Poco::Crypto::X509Certificate>(Svr.IssuerCertFile());
|
||||
Logger().information( fmt::format("Certificate Issuer Name:{}",IssuerCert_->issuerName()));
|
||||
}
|
||||
auto NewSocketAcceptor = std::make_unique<ws_server_reactor_type_t>(Sock, Reactor_); // , 2 /*Poco::Environment::processorCount()*2) */ );
|
||||
Acceptors_.push_back(std::move(NewSocketAcceptor));
|
||||
}
|
||||
|
||||
int WebSocketServer::Start() {
|
||||
// ReactorPool_.Start("DeviceReactorPool_");
|
||||
for(const auto & Svr : ConfigServersList_ ) {
|
||||
Logger().notice( fmt::format("Starting: {}:{} Keyfile:{} CertFile: {}",
|
||||
Svr.Address(),
|
||||
Svr.Port(),
|
||||
Svr.KeyFile(),Svr.CertFile()));
|
||||
|
||||
Svr.LogCert(Logger());
|
||||
if(!Svr.RootCA().empty())
|
||||
Svr.LogCas(Logger());
|
||||
|
||||
auto Sock{Svr.CreateSecureSocket(Logger())};
|
||||
|
||||
if(!IsCertOk()) {
|
||||
IssuerCert_ = std::make_unique<Poco::Crypto::X509Certificate>(Svr.IssuerCertFile());
|
||||
Logger().information( fmt::format("Certificate Issuer Name:{}",IssuerCert_->issuerName()));
|
||||
}
|
||||
auto NewSocketAcceptor = std::make_unique<ws_server_reactor_type_t>(Sock, Reactor_); // , 2 /*Poco::Environment::processorCount()*2) */ );
|
||||
Acceptors_.push_back(std::move(NewSocketAcceptor));
|
||||
}
|
||||
|
||||
auto ProvString = MicroService::instance().ConfigGetString("autoprovisioning.process","default");
|
||||
if(ProvString!="default") {
|
||||
auto Tokens = Poco::StringTokenizer(ProvString, ",");
|
||||
for (const auto &i : Tokens) {
|
||||
if (i == "prov")
|
||||
LookAtProvisioning_ = true;
|
||||
else
|
||||
UseDefaultConfig_ = true;
|
||||
}
|
||||
} else {
|
||||
UseDefaultConfig_ = true;
|
||||
auto ProvString = MicroService::instance().ConfigGetString("autoprovisioning.process","default");
|
||||
if(ProvString!="default") {
|
||||
auto Tokens = Poco::StringTokenizer(ProvString, ",");
|
||||
for (const auto &i : Tokens) {
|
||||
if (i == "prov")
|
||||
LookAtProvisioning_ = true;
|
||||
else
|
||||
UseDefaultConfig_ = true;
|
||||
}
|
||||
} else {
|
||||
UseDefaultConfig_ = true;
|
||||
}
|
||||
|
||||
SimulatorId_ = MicroService::instance().ConfigGetString("simulatorid","");
|
||||
SimulatorEnabled_ = !SimulatorId_.empty();
|
||||
SimulatorId_ = MicroService::instance().ConfigGetString("simulatorid","");
|
||||
SimulatorEnabled_ = !SimulatorId_.empty();
|
||||
|
||||
ReactorThread_.setStackSize(3000000);
|
||||
ReactorThread_.start(Reactor_);
|
||||
Utils::SetThreadName(ReactorThread_,"device-reactor");
|
||||
ReactorThread_.setStackSize(3000000);
|
||||
ReactorThread_.start(Reactor_);
|
||||
Utils::SetThreadName(ReactorThread_,"device-reactor");
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WebSocketServer::Stop() {
|
||||
Logger().notice("Stopping reactors...");
|
||||
// ReactorPool_.Stop();
|
||||
Reactor_.stop();
|
||||
ReactorThread_.join();
|
||||
}
|
||||
void WebSocketServer::Stop() {
|
||||
Logger().notice("Stopping reactors...");
|
||||
// ReactorPool_.Stop();
|
||||
Reactor_.stop();
|
||||
ReactorThread_.join();
|
||||
}
|
||||
|
||||
} //namespace
|
||||
} //namespace
|
||||
@@ -25,52 +25,52 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class WebSocketServer : public SubSystemServer {
|
||||
public:
|
||||
static auto instance() {
|
||||
static auto instance_ = new WebSocketServer;
|
||||
return instance_;
|
||||
}
|
||||
class WebSocketServer : public SubSystemServer {
|
||||
public:
|
||||
static auto instance() {
|
||||
static auto instance_ = new WebSocketServer;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
bool IsCertOk() { return IssuerCert_!= nullptr; }
|
||||
bool ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate);
|
||||
// Poco::Net::SocketReactor & GetNextReactor() { return ReactorPool_.NextReactor(); }
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
bool IsCertOk() { return IssuerCert_!= nullptr; }
|
||||
bool ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate);
|
||||
// Poco::Net::SocketReactor & GetNextReactor() { return ReactorPool_.NextReactor(); }
|
||||
|
||||
inline bool IsSimSerialNumber(const std::string & SerialNumber) const {
|
||||
return IsSim(SerialNumber) && SerialNumber == SimulatorId_;
|
||||
}
|
||||
inline bool IsSimSerialNumber(const std::string & SerialNumber) const {
|
||||
return IsSim(SerialNumber) && SerialNumber == SimulatorId_;
|
||||
}
|
||||
|
||||
inline static bool IsSim(const std::string & SerialNumber) {
|
||||
return SerialNumber.substr(0,6) == "53494d";
|
||||
}
|
||||
inline static bool IsSim(const std::string & SerialNumber) {
|
||||
return SerialNumber.substr(0,6) == "53494d";
|
||||
}
|
||||
|
||||
inline bool IsSimEnabled() const {
|
||||
return SimulatorEnabled_;
|
||||
}
|
||||
inline bool IsSimEnabled() const {
|
||||
return SimulatorEnabled_;
|
||||
}
|
||||
|
||||
inline bool UseProvisioning() const { return LookAtProvisioning_; }
|
||||
inline bool UseDefaults() const { return UseDefaultConfig_; }
|
||||
inline bool UseProvisioning() const { return LookAtProvisioning_; }
|
||||
inline bool UseDefaults() const { return UseDefaultConfig_; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
|
||||
// typedef std::unique_ptr<Poco::Net::ParallelSocketAcceptor<WSConnection, Poco::Net::SocketReactor>> ws_server_reactor_type_t;
|
||||
typedef Poco::Net::SocketAcceptor<WSConnection> ws_server_reactor_type_t;
|
||||
std::vector<std::unique_ptr<ws_server_reactor_type_t>> Acceptors_;
|
||||
Poco::Net::SocketReactor Reactor_;
|
||||
Poco::Thread ReactorThread_;
|
||||
std::string SimulatorId_;
|
||||
bool LookAtProvisioning_ = false;
|
||||
bool UseDefaultConfig_ = true;
|
||||
bool SimulatorEnabled_=false;
|
||||
private:
|
||||
std::unique_ptr<Poco::Crypto::X509Certificate> IssuerCert_;
|
||||
// typedef std::unique_ptr<Poco::Net::ParallelSocketAcceptor<WSConnection, Poco::Net::SocketReactor>> ws_server_reactor_type_t;
|
||||
typedef Poco::Net::SocketAcceptor<WSConnection> ws_server_reactor_type_t;
|
||||
std::vector<std::unique_ptr<ws_server_reactor_type_t>> Acceptors_;
|
||||
Poco::Net::SocketReactor Reactor_;
|
||||
Poco::Thread ReactorThread_;
|
||||
std::string SimulatorId_;
|
||||
bool LookAtProvisioning_ = false;
|
||||
bool UseDefaultConfig_ = true;
|
||||
bool SimulatorEnabled_=false;
|
||||
|
||||
WebSocketServer() noexcept:
|
||||
SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") {
|
||||
WebSocketServer() noexcept:
|
||||
SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
inline auto WebSocketServer() { return WebSocketServer::instance(); }
|
||||
inline auto WebSocketServer() { return WebSocketServer::instance(); }
|
||||
|
||||
} //namespace
|
||||
} //namespace
|
||||
@@ -27,6 +27,11 @@ namespace OpenWifi {
|
||||
inline uint64_t Now() { return std::time(nullptr); };
|
||||
}
|
||||
|
||||
namespace OpenWifi::Utils {
|
||||
std::vector<unsigned char> base64decode(const std::string& input);
|
||||
std::string base64encode(const unsigned char *input, uint32_t size);
|
||||
}
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#include "Poco/Util/Application.h"
|
||||
@@ -238,6 +243,11 @@ namespace OpenWifi::RESTAPI_utils {
|
||||
Obj.set(Field,Value);
|
||||
}
|
||||
|
||||
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Poco::Data::BLOB &Value) {
|
||||
auto Result = Utils::base64encode((const unsigned char *)Value.rawContent(),Value.size());
|
||||
Obj.set(Field,Result);
|
||||
}
|
||||
|
||||
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::StringPairVec & S) {
|
||||
Poco::JSON::Array Array;
|
||||
for(const auto &i:S) {
|
||||
@@ -334,12 +344,12 @@ namespace OpenWifi::RESTAPI_utils {
|
||||
|
||||
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, double & Value) {
|
||||
if(Obj->has(Field) && !Obj->isNull(Field))
|
||||
Value = (double) Obj->get(Field);
|
||||
Value = (double)Obj->get(Field);
|
||||
}
|
||||
|
||||
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, float & Value) {
|
||||
if(Obj->has(Field) && !Obj->isNull(Field))
|
||||
Value = (float) Obj->get(Field);
|
||||
Value = (float)Obj->get(Field);
|
||||
}
|
||||
|
||||
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, bool &Value) {
|
||||
@@ -374,7 +384,14 @@ namespace OpenWifi::RESTAPI_utils {
|
||||
|
||||
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, uint64_t &Value) {
|
||||
if(Obj->has(Field) && !Obj->isNull(Field))
|
||||
Value = (uint64_t ) Obj->get(Field);
|
||||
Value = (uint64_t)Obj->get(Field);
|
||||
}
|
||||
|
||||
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, Poco::Data::BLOB &Value) {
|
||||
if(Obj->has(Field) && !Obj->isNull(Field)) {
|
||||
auto Result = Utils::base64decode(Obj->get(Field).toString());
|
||||
Value.assignRaw((const unsigned char *)&Result[0],Result.size());
|
||||
}
|
||||
}
|
||||
|
||||
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, Types::StringPairVec &Vec) {
|
||||
@@ -2064,6 +2081,17 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, Poco::Data::BLOB &Value) {
|
||||
if(O->has(Field)) {
|
||||
std::string Content = O->get(Field).toString();
|
||||
auto DecodedBlob = Utils::base64decode(Content);
|
||||
Value.assignRaw((const unsigned char *)&DecodedBlob[0],DecodedBlob.size());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template <typename T> bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, const T &value, T & assignee) {
|
||||
if(O->has(Field)) {
|
||||
assignee = value;
|
||||
@@ -3236,7 +3264,12 @@ namespace OpenWifi {
|
||||
return Poco::Logger::get(Name);
|
||||
}
|
||||
|
||||
static inline void Exit(int Reason);
|
||||
virtual void GetExtraConfiguration(Poco::JSON::Object & Cfg) {
|
||||
Cfg.set("additionalConfiguration",false);
|
||||
}
|
||||
|
||||
|
||||
static inline void Exit(int Reason);
|
||||
inline void BusMessageReceived(const std::string &Key, const std::string & Payload);
|
||||
inline MicroServiceMetaVec GetServices(const std::string & Type);
|
||||
inline MicroServiceMetaVec GetServices();
|
||||
@@ -4327,6 +4360,11 @@ namespace OpenWifi {
|
||||
Answer.set("certificates", Certificates);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
if(GetBoolParameter("extraConfiguration")) {
|
||||
Poco::JSON::Object Answer;
|
||||
MicroService::instance().GetExtraConfiguration(Answer);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
BadRequest(RESTAPI::Errors::InvalidCommand);
|
||||
}
|
||||
|
||||
|
||||
@@ -445,6 +445,7 @@ namespace OpenWifi::uCentralProtocol::Events {
|
||||
static const char *RECOVERY = "recovery";
|
||||
static const char *TELEMETRY = "telemetry";
|
||||
static const char *DEVICEUPDATE = "deviceupdate";
|
||||
static const char *VENUE_BROADCAST = "venue_broadcast";
|
||||
|
||||
enum EVENT_MSG {
|
||||
ET_UNKNOWN,
|
||||
@@ -457,7 +458,8 @@ namespace OpenWifi::uCentralProtocol::Events {
|
||||
ET_CFGPENDING,
|
||||
ET_RECOVERY,
|
||||
ET_DEVICEUPDATE,
|
||||
ET_TELEMETRY
|
||||
ET_TELEMETRY,
|
||||
ET_VENUEBROADCAST
|
||||
};
|
||||
|
||||
inline EVENT_MSG EventFromString(const std::string & Method) {
|
||||
@@ -481,6 +483,8 @@ namespace OpenWifi::uCentralProtocol::Events {
|
||||
return ET_RECOVERY;
|
||||
else if(strcmp(TELEMETRY,Method.c_str())==0)
|
||||
return ET_TELEMETRY;
|
||||
else if(strcmp(VENUE_BROADCAST,Method.c_str())==0)
|
||||
return ET_VENUEBROADCAST;
|
||||
return ET_UNKNOWN;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,204 +8,158 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
RTTYS_ClientConnection::RTTYS_ClientConnection(Poco::Net::WebSocket *WS,
|
||||
Poco::Logger &L,
|
||||
std::string &Id)
|
||||
RTTYS_ClientConnection::RTTYS_ClientConnection(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response,
|
||||
Poco::Net::SocketReactor &reactor,
|
||||
const std::string &Id)
|
||||
:
|
||||
WS_(WS),
|
||||
Logger_(L),
|
||||
Id_(std::move(Id))
|
||||
Reactor_(reactor),
|
||||
Id_(Id),
|
||||
Logger_(Poco::Logger::get(fmt::format("RTTY-client({})",Id_)))
|
||||
{
|
||||
|
||||
//WS_ = new Poco::Net::WebSocket(Request, Response);
|
||||
RTTYS_server()->Register(Id_, this);
|
||||
Logger().information(fmt::format("{}: Client starting connection, session: {}.",
|
||||
Id_, RTTYS_server()->DeviceSessionID(Id_)));
|
||||
RTTYS_server()->ClientReactor().addEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketReadable));
|
||||
RTTYS_server()->ClientReactor().addEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketShutdown));
|
||||
|
||||
std::thread T([=]() { CompleteLogin(); });
|
||||
T.detach();
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::CompleteLogin() {
|
||||
int tries = 0;
|
||||
completing_connection_ = true;
|
||||
try {
|
||||
while (!aborting_connection_ && tries < 20) {
|
||||
if (RTTYS_server()->Login(this->Id_)) {
|
||||
Logger().information(fmt::format("{}: Client connected to device, session: {}.",
|
||||
Id_, RTTYS_server()->DeviceSessionID(Id_)));
|
||||
this->Connected_ = true;
|
||||
completing_connection_ = false;
|
||||
return;
|
||||
}
|
||||
std::this_thread::sleep_for(2000ms);
|
||||
tries++;
|
||||
Logger().information(fmt::format(
|
||||
"{}: Waiting for device to connect to start session. (try={})", Id_, tries));
|
||||
}
|
||||
Logger().information(fmt::format("{}: Client could not connect to device, session: {}.",
|
||||
Id_, RTTYS_server()->DeviceSessionID(Id_)));
|
||||
delete this;
|
||||
} catch (...) {
|
||||
completing_connection_ = false;
|
||||
delete this;
|
||||
Logger_.information("Starting connection");
|
||||
Valid_ = true;
|
||||
WS_ = std::make_unique<Poco::Net::WebSocket>(request,response);
|
||||
Reactor_.addEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketReadable));
|
||||
Reactor_.addEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketShutdown));
|
||||
}
|
||||
}
|
||||
|
||||
RTTYS_ClientConnection::~RTTYS_ClientConnection() {
|
||||
// std::lock_guard G(Mutex_);
|
||||
try {
|
||||
aborting_connection_ = true;
|
||||
if(completing_connection_) {
|
||||
aborting_connection_ = true;
|
||||
while(completing_connection_)
|
||||
continue;
|
||||
}
|
||||
Logger().information(fmt::format("{}: Client disconnecting.", Id_));
|
||||
RTTYS_server()->DeRegister(Id_, this);
|
||||
if (Connected_) {
|
||||
RTTYS_server()->ClientReactor().removeEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketReadable));
|
||||
RTTYS_server()->ClientReactor().removeEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketShutdown));
|
||||
}
|
||||
Logger().information(fmt::format("{}: Client disconnected.", Id_));
|
||||
delete WS_;
|
||||
} catch (...) {
|
||||
Logger().information(fmt::format("{}: Client disconnected (exception).", Id_));
|
||||
if(Valid_) {
|
||||
MyGuard G(Mutex_);
|
||||
EndConnection(false);
|
||||
}
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::Close() {
|
||||
{
|
||||
std::lock_guard G(Mutex_);
|
||||
CloseConnection_ = true;
|
||||
void RTTYS_ClientConnection::EndConnection(bool SendNotification) {
|
||||
if(Valid_) {
|
||||
Valid_=false;
|
||||
try {
|
||||
Reactor_.removeEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketReadable));
|
||||
Reactor_.removeEventHandler(
|
||||
*WS_, Poco::NObserver<RTTYS_ClientConnection, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTYS_ClientConnection::onSocketShutdown));
|
||||
// WS_->shutdown();
|
||||
if (SendNotification)
|
||||
RTTYS_server()->NotifyClientDisconnect(Id_, this);
|
||||
} catch(...) {
|
||||
|
||||
}
|
||||
Logger_.information("Disconnected.");
|
||||
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
MyGuard G(Mutex_);
|
||||
bool MustDisconnect = false;
|
||||
{
|
||||
std::lock_guard G(Mutex_);
|
||||
try {
|
||||
int flags;
|
||||
auto n = WS_->receiveFrame(Buffer_, sizeof(Buffer_), flags);
|
||||
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
switch (Op) {
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
if (n == 0) {
|
||||
Logger().information(fmt::format("{}: Socket readable shutdown.", Id_));
|
||||
MustDisconnect = true;
|
||||
} else {
|
||||
std::string s((char *)Buffer_, n);
|
||||
try {
|
||||
auto Doc = nlohmann::json::parse(s);
|
||||
if (Doc.contains("type")) {
|
||||
auto Type = Doc["type"];
|
||||
if (Type == "winsize") {
|
||||
auto cols = Doc["cols"];
|
||||
auto rows = Doc["rows"];
|
||||
if (!RTTYS_server()->WindowSize(Id_, cols, rows)) {
|
||||
Logger().information(
|
||||
fmt::format("{}: Winsize shutdown.", Id_));
|
||||
MustDisconnect = true;
|
||||
}
|
||||
try {
|
||||
int flags;
|
||||
auto n = WS_->receiveFrame(Buffer_, sizeof(Buffer_), flags);
|
||||
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
|
||||
switch (Op) {
|
||||
case Poco::Net::WebSocket::FRAME_OP_PING: {
|
||||
WS_->sendFrame("", 0,
|
||||
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
|
||||
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_PONG: {
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
|
||||
if (n == 0) {
|
||||
Logger_.information("Socket readable shutdown.");
|
||||
MustDisconnect = true;
|
||||
} else {
|
||||
std::string s((char *)Buffer_, n);
|
||||
try {
|
||||
auto Doc = nlohmann::json::parse(s);
|
||||
if (Doc.contains("type")) {
|
||||
auto Type = Doc["type"];
|
||||
if (Type == "winsize") {
|
||||
auto cols = Doc["cols"];
|
||||
auto rows = Doc["rows"];
|
||||
if (!RTTYS_server()->WindowSize(Id_, cols, rows)) {
|
||||
Logger_.information("Winsize shutdown.");
|
||||
MustDisconnect = true;
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
// just ignore parse errors
|
||||
Logger().information(
|
||||
fmt::format("{}: Frame text exception shutdown.", Id_));
|
||||
MustDisconnect = true;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_BINARY: {
|
||||
if (n == 0) {
|
||||
Logger().information(fmt::format("{}: Frame binary size shutdown.", Id_));
|
||||
} catch (...) {
|
||||
// just ignore parse errors
|
||||
Logger_.information("Frame text exception shutdown.");
|
||||
MustDisconnect = true;
|
||||
} else {
|
||||
poco_trace(Logger(), fmt::format("Sending {} key strokes to device.", n));
|
||||
if (!RTTYS_server()->SendKeyStrokes(Id_, Buffer_, n)) {
|
||||
Logger().information(fmt::format("{}: Sendkeystrokes shutdown.", Id_));
|
||||
MustDisconnect = true;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
|
||||
Logger().information(fmt::format("{}: Frame frame close shutdown.", Id_));
|
||||
}
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_BINARY: {
|
||||
if (n == 0) {
|
||||
Logger_.information("Frame binary size shutdown.");
|
||||
MustDisconnect = true;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
} else {
|
||||
poco_trace(Logger_, fmt::format("Sending {} key strokes to device.", n));
|
||||
if (!RTTYS_server()->SendKeyStrokes(Id_, Buffer_, n)) {
|
||||
Logger_.information("Sendkeystrokes shutdown.");
|
||||
MustDisconnect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
Logger().information(fmt::format("{}: Frame readable shutdown.", Id_));
|
||||
} break;
|
||||
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
|
||||
Logger_.information("Frame frame close shutdown.");
|
||||
MustDisconnect = true;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
Logger_.information("Frame readable shutdown.");
|
||||
MustDisconnect = true;
|
||||
}
|
||||
|
||||
if(MustDisconnect)
|
||||
delete this;
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::SendData( const u_char *Buf, size_t len ) {
|
||||
bool done = false;
|
||||
{
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
try {
|
||||
WS_->sendFrame(Buf, len,
|
||||
Poco::Net::WebSocket::FRAME_FLAG_FIN |
|
||||
Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
} catch (...) {
|
||||
done = true;
|
||||
Logger().information(fmt::format("{}: SendData shutdown.", Id_));
|
||||
}
|
||||
if(!Valid_)
|
||||
return;
|
||||
// MyGuard G(Mutex_);
|
||||
try {
|
||||
WS_->sendFrame(Buf, len,
|
||||
Poco::Net::WebSocket::FRAME_FLAG_FIN |
|
||||
Poco::Net::WebSocket::FRAME_OP_BINARY);
|
||||
return;
|
||||
} catch (...) {
|
||||
Logger_.information("SendData shutdown.");
|
||||
}
|
||||
if(done)
|
||||
return delete this;
|
||||
MyGuard G(Mutex_);
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::SendData( const std::string &s , bool login) {
|
||||
bool done = false;
|
||||
{
|
||||
try {
|
||||
std::lock_guard G(Mutex_);
|
||||
if (login) {
|
||||
RTTYS_server()->LoginDone(Id_);
|
||||
}
|
||||
WS_->sendFrame(s.c_str(), s.length());
|
||||
} catch (...) {
|
||||
done = true;
|
||||
Logger().information(fmt::format("{}: Senddata shutdown.", Id_));
|
||||
return delete this;
|
||||
}
|
||||
void RTTYS_ClientConnection::SendData( const std::string &s) {
|
||||
if(!Valid_)
|
||||
return;
|
||||
// MyGuard G(Mutex_);
|
||||
try {
|
||||
WS_->sendFrame(s.c_str(), s.length());
|
||||
return;
|
||||
} catch (...) {
|
||||
Logger_.information("SendData shutdown.");
|
||||
}
|
||||
if(done)
|
||||
return delete this;
|
||||
MyGuard G(Mutex_);
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
void RTTYS_ClientConnection::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) {
|
||||
Logger().information(fmt::format("{}: Socket shutdown.", Id_));
|
||||
delete this;
|
||||
MyGuard G(Mutex_);
|
||||
Logger_.information("Socket shutdown.");
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,36 +12,41 @@
|
||||
#include "Poco/FIFOBuffer.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
enum class connection_state {
|
||||
initialized, waiting_for_login, connected, aborting, shutting_down, done
|
||||
};
|
||||
|
||||
class RTTYS_ClientConnection {
|
||||
public:
|
||||
// RTTYS_ClientConnection(std::unique_ptr<Poco::Net::WebSocket> WS, std::string &Id,
|
||||
RTTYS_ClientConnection(Poco::Net::WebSocket *WS,
|
||||
Poco::Logger &L,
|
||||
std::string &Id);
|
||||
RTTYS_ClientConnection(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response,
|
||||
Poco::Net::SocketReactor & reactor,
|
||||
const std::string &Id);
|
||||
~RTTYS_ClientConnection();
|
||||
void onSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf);
|
||||
void onSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf);
|
||||
|
||||
void SendData( const u_char *Buf, size_t len );
|
||||
void SendData( const std::string & S, bool login=false);
|
||||
void SendData( const std::string & S );
|
||||
|
||||
void Close();
|
||||
|
||||
void CompleteLogin();
|
||||
[[nodiscard]] inline std::string ID() { return Id_; }
|
||||
[[nodiscard]] inline bool Valid() { return Valid_; }
|
||||
using MyMutexType = std::recursive_mutex;
|
||||
using MyGuard = std::lock_guard<MyMutexType>;
|
||||
|
||||
private:
|
||||
Poco::Net::WebSocket *WS_= nullptr;
|
||||
Poco::Logger & Logger_;
|
||||
std::string Id_;
|
||||
std::string Sid_;
|
||||
mutable std::atomic_bool Connected_=false;
|
||||
u_char Buffer_[16000]{0};
|
||||
mutable bool CloseConnection_=false;
|
||||
std::mutex Mutex_;
|
||||
mutable std::atomic_bool aborting_connection_ = false;
|
||||
mutable std::atomic_bool completing_connection_ = false;
|
||||
Poco::Net::SocketReactor &Reactor_;
|
||||
std::string Id_;
|
||||
std::unique_ptr<Poco::Net::WebSocket> WS_;
|
||||
Poco::Logger &Logger_;
|
||||
std::string Sid_;
|
||||
std::atomic_bool Valid_=false;
|
||||
u_char Buffer_[64000]{0};
|
||||
MyMutexType Mutex_;
|
||||
// volatile connection_state state_ = connection_state::initialized;
|
||||
|
||||
void EndConnection(bool SendNotification=true);
|
||||
|
||||
inline Poco::Logger & Logger() { return Logger_; }
|
||||
};
|
||||
}
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
RTTY_Client_WebSocketRequestHandler::RTTY_Client_WebSocketRequestHandler(Poco::Logger & L)
|
||||
RTTYS_Client_WebSocketRequestHandler::RTTYS_Client_WebSocketRequestHandler(Poco::Logger & L)
|
||||
:Logger_(L) {
|
||||
}
|
||||
|
||||
void RTTY_Client_WebSocketRequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request,
|
||||
void RTTYS_Client_WebSocketRequestHandler::handleRequest(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response) {
|
||||
Poco::URI uri(request.getURI());
|
||||
const auto & P = uri.getPath();
|
||||
@@ -30,11 +30,7 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
try {
|
||||
Poco::Thread::current()->setName(fmt::format("WebRTTYRequest_WSHandler_{}", T[2]));
|
||||
std::cout << "Creating websocket end point for a RTTY client" << std::endl;
|
||||
auto WS = new Poco::Net::WebSocket(request, response);
|
||||
new RTTYS_ClientConnection(WS, Logger_, T[2]);
|
||||
std::cout << "Ending web server websocket creation end point for RTTY" << std::endl;
|
||||
RTTYS_server()->CreateNewClient(request,response,T[2]);
|
||||
} catch (...) {
|
||||
Logger_.warning("Exception during WS creation");
|
||||
}
|
||||
@@ -108,9 +104,9 @@ namespace OpenWifi {
|
||||
Poco::Net::HTTPServerResponse &response) {
|
||||
|
||||
Utils::SetThreadName("rt:webserver");
|
||||
uint64_t id = rtty_ws_id++;
|
||||
[[maybe_unused]] uint64_t id = rtty_ws_id++;
|
||||
|
||||
Logger_.information(fmt::format("{}: Starting request.",id));
|
||||
poco_debug(Logger(),fmt::format("{}: Starting request.",id));
|
||||
Poco::URI uri(request.getURI());
|
||||
auto Path = uri.getPath();
|
||||
|
||||
@@ -132,7 +128,7 @@ namespace OpenWifi {
|
||||
if (ParsedPath.count() > 1) {
|
||||
if (ParsedPath[1] == "connect") {
|
||||
response.redirect(Poco::replace(Path,"/connect/","/rtty/"));
|
||||
RTTYS_server()->Logger().information(fmt::format("redirect: {}",Path));
|
||||
poco_debug(Logger(),fmt::format("{}: Redirect: {}",id,Path));
|
||||
return;
|
||||
} else if (ParsedPath[1] == "authorized") {
|
||||
SetCommonHeaders(request,response, false);
|
||||
@@ -141,7 +137,7 @@ namespace OpenWifi {
|
||||
response.setContentType("application/json");
|
||||
std::ostream &answer = response.send();
|
||||
answer << to_string(doc);
|
||||
Logger_.information(fmt::format("{}: Finishing authorization request.",id));
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing authorization request.",id));
|
||||
return;
|
||||
} else if (ParsedPath[1] == "fontsize") {
|
||||
SetCommonHeaders(request,response, false);
|
||||
@@ -150,7 +146,7 @@ namespace OpenWifi {
|
||||
response.setContentType("application/json");
|
||||
std::ostream &answer = response.send();
|
||||
answer << to_string(doc);
|
||||
Logger_.information(fmt::format("{}: Finishing font size request.",id));
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing font size request.",id));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -158,12 +154,12 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
if(Path.find("../")!=std::string::npos) {
|
||||
Logger_.information(fmt::format("{}: Finishing request.",id));
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
return;
|
||||
}
|
||||
|
||||
if(Path.find("~/")!=std::string::npos) {
|
||||
Logger_.information(fmt::format("{}: Finishing request.",id));
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -173,7 +169,7 @@ namespace OpenWifi {
|
||||
// std::cout << id << ": Path " << Path << " does not exist" << std::endl;
|
||||
Path = RTTYS_server()->UIAssets() + "/index.html";
|
||||
response.sendFile(Path,"text/html");
|
||||
Logger_.information(fmt::format("{}: Finishing request.",id));
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
return;
|
||||
}
|
||||
Poco::Path P(Path);
|
||||
@@ -190,7 +186,7 @@ namespace OpenWifi {
|
||||
} else if (Ext == "css") {
|
||||
Type = "text/css; charset=utf-8";
|
||||
if(IsFileGZipped(Path)) {
|
||||
Logger_.information(fmt::format("{}: Downloading UI Assets.",id));
|
||||
poco_debug(Logger(),fmt::format("{}: Downloading UI Assets.",id));
|
||||
response.set("Content-Encoding", "gzip");
|
||||
}
|
||||
} else if (Ext == "ico")
|
||||
@@ -204,19 +200,19 @@ namespace OpenWifi {
|
||||
|
||||
response.setContentLength(F.getSize());
|
||||
response.sendFile(Path, Type);
|
||||
Logger_.information(fmt::format("{}: Finishing request.",id));
|
||||
poco_debug(Logger(),fmt::format("{}: Finishing request.",id));
|
||||
}
|
||||
|
||||
RTTY_Client_RequestHandlerFactory::RTTY_Client_RequestHandlerFactory(Poco::Logger & L)
|
||||
RTTYS_Client_RequestHandlerFactory::RTTYS_Client_RequestHandlerFactory(Poco::Logger & L)
|
||||
: Logger_(L) {}
|
||||
|
||||
Poco::Net::HTTPRequestHandler *
|
||||
RTTY_Client_RequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest &request) {
|
||||
RTTYS_Client_RequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest &request) {
|
||||
try {
|
||||
if (request.find("Upgrade") != request.end() &&
|
||||
Poco::icompare(request["Upgrade"], "websocket") == 0) {
|
||||
Poco::Thread::current()->setName("WebRTTYRequest_WSHandler");
|
||||
return new RTTY_Client_WebSocketRequestHandler(Logger_);
|
||||
return new RTTYS_Client_WebSocketRequestHandler(Logger_);
|
||||
} else {
|
||||
Poco::Thread::current()->setName("WebRTTYRequest_PageHandler");
|
||||
return new PageRequestHandler(Logger_);
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
#include "Poco/Net/WebSocket.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class RTTY_Client_WebSocketRequestHandler : public Poco::Net::HTTPRequestHandler {
|
||||
class RTTYS_Client_WebSocketRequestHandler : public Poco::Net::HTTPRequestHandler {
|
||||
public:
|
||||
explicit RTTY_Client_WebSocketRequestHandler(Poco::Logger &L);
|
||||
explicit RTTYS_Client_WebSocketRequestHandler(Poco::Logger &L);
|
||||
|
||||
void handleRequest(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response) override;
|
||||
@@ -32,11 +32,12 @@ namespace OpenWifi {
|
||||
|
||||
private:
|
||||
Poco::Logger & Logger_;
|
||||
inline Poco::Logger &Logger() { return Logger_; }
|
||||
};
|
||||
|
||||
class RTTY_Client_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
|
||||
class RTTYS_Client_RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
|
||||
public:
|
||||
explicit RTTY_Client_RequestHandlerFactory(Poco::Logger &L);
|
||||
explicit RTTYS_Client_RequestHandlerFactory(Poco::Logger &L);
|
||||
|
||||
Poco::Net::HTTPRequestHandler *
|
||||
createRequestHandler(const Poco::Net::HTTPServerRequest &request) override;
|
||||
|
||||
@@ -4,93 +4,120 @@
|
||||
|
||||
#include "RTTYS_device.h"
|
||||
#include "rttys/RTTYS_server.h"
|
||||
#include "rttys/RTTYS_ClientConnection.h"
|
||||
#include "Poco/Net/SecureStreamSocketImpl.h"
|
||||
#include "Poco/Net/StreamSocket.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
inline Poco::Logger & RTTY_Device_ConnectionHandler::Logger() { return RTTYS_server()->Logger(); }
|
||||
|
||||
RTTY_Device_ConnectionHandler::RTTY_Device_ConnectionHandler(Poco::Net::StreamSocket& socket, Poco::Net::SocketReactor & reactor):
|
||||
RTTYS_Device_ConnectionHandler::RTTYS_Device_ConnectionHandler(Poco::Net::StreamSocket& socket, Poco::Net::SocketReactor & reactor):
|
||||
socket_(socket),
|
||||
reactor_(reactor),
|
||||
inBuf_(RTTY_DEVICE_BUFSIZE){
|
||||
std::thread T([=]() { CompleteConnection(); });
|
||||
T.detach();
|
||||
Logger_(Poco::Logger::get(fmt::format("RTTY-device({})",socket_.peerAddress().toString())))
|
||||
{
|
||||
// std::thread T([=]() { CompleteConnection(); });
|
||||
// T.detach();
|
||||
CompleteConnection();
|
||||
}
|
||||
|
||||
void RTTY_Device_ConnectionHandler::CompleteConnection() {
|
||||
void RTTYS_Device_ConnectionHandler::CompleteConnection() {
|
||||
try {
|
||||
valid_=true;
|
||||
device_address_ = socket_.peerAddress();
|
||||
if (MicroService::instance().NoAPISecurity()) {
|
||||
Logger().information(
|
||||
fmt::format("{}: Unsecured connection.", device_address_.toString()));
|
||||
} else {
|
||||
auto SS = dynamic_cast<Poco::Net::SecureStreamSocketImpl *>(socket_.impl());
|
||||
while (true) {
|
||||
auto V = SS->completeHandshake();
|
||||
if (V == 1)
|
||||
break;
|
||||
}
|
||||
if ((SS->secure()))
|
||||
Logger().information(
|
||||
fmt::format("{}: Secure connection.", device_address_.toString()));
|
||||
|
||||
auto SS = dynamic_cast<Poco::Net::SecureStreamSocketImpl *>(socket_.impl());
|
||||
while (true) {
|
||||
auto V = SS->completeHandshake();
|
||||
if (V == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((SS->secure())) {
|
||||
poco_information(Logger(), "Secure connection.");
|
||||
}
|
||||
|
||||
reactor_.addEventHandler(
|
||||
socket_,
|
||||
Poco::NObserver<RTTY_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTY_Device_ConnectionHandler::onSocketReadable));
|
||||
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTYS_Device_ConnectionHandler::onSocketReadable));
|
||||
reactor_.addEventHandler(
|
||||
socket_,
|
||||
Poco::NObserver<RTTY_Device_ConnectionHandler, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTY_Device_ConnectionHandler::onSocketShutdown));
|
||||
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTYS_Device_ConnectionHandler::onSocketShutdown));
|
||||
} catch (...) {
|
||||
Logger().information(
|
||||
fmt::format("{}: Device cause exception while completing connection.", device_address_.toString()));
|
||||
delete this;
|
||||
poco_warning(Logger(), "Device caused exception while completing connection.");
|
||||
Guard G(M_);
|
||||
EndConnection();
|
||||
}
|
||||
}
|
||||
|
||||
RTTYS_Device_ConnectionHandler::~RTTYS_Device_ConnectionHandler() {
|
||||
if(valid_) {
|
||||
Guard G(M_);
|
||||
poco_warning(Logger(), "Device connection being deleted.");
|
||||
EndConnection(false);
|
||||
}
|
||||
}
|
||||
|
||||
RTTY_Device_ConnectionHandler::~RTTY_Device_ConnectionHandler() {
|
||||
void RTTYS_Device_ConnectionHandler::EndConnection(bool SendNotification) {
|
||||
try {
|
||||
reactor_.removeEventHandler(
|
||||
socket_,
|
||||
Poco::NObserver<RTTY_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTY_Device_ConnectionHandler::onSocketReadable));
|
||||
reactor_.removeEventHandler(
|
||||
socket_,
|
||||
Poco::NObserver<RTTY_Device_ConnectionHandler, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTY_Device_ConnectionHandler::onSocketShutdown));
|
||||
|
||||
if (registered_) {
|
||||
Logger().information(fmt::format("{}: Deregistering.", device_address_.toString()));
|
||||
RTTYS_server()->DeRegisterDevice(id_, this, web_socket_active_);
|
||||
Logger().information(fmt::format("{}: Deregistered.", device_address_.toString()));
|
||||
if(valid_) {
|
||||
valid_ = false;
|
||||
reactor_.removeEventHandler(
|
||||
socket_,
|
||||
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ReadableNotification>(
|
||||
*this, &RTTYS_Device_ConnectionHandler::onSocketReadable));
|
||||
reactor_.removeEventHandler(
|
||||
socket_,
|
||||
Poco::NObserver<RTTYS_Device_ConnectionHandler, Poco::Net::ShutdownNotification>(
|
||||
*this, &RTTYS_Device_ConnectionHandler::onSocketShutdown));
|
||||
if(SendNotification)
|
||||
RTTYS_server()->NotifyDeviceDisconnect(Id_,this);
|
||||
poco_information(Logger(), "Connection done.");
|
||||
socket_.close();
|
||||
}
|
||||
Logger().information(fmt::format("{}: Done.", device_address_.toString()));
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void RTTY_Device_ConnectionHandler::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
[[maybe_unused]] static void dump(unsigned char *p,uint l) {
|
||||
for(uint i=0;i<l;i++) {
|
||||
std::cout << std::hex << (uint) p[i] << " ";
|
||||
if(i % 16 == 0)
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::dec << std::endl ;
|
||||
}
|
||||
|
||||
void RTTYS_Device_ConnectionHandler::onSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) {
|
||||
bool good = true;
|
||||
|
||||
Guard G(M_);
|
||||
|
||||
try {
|
||||
auto received_bytes = socket_.receiveBytes(inBuf_);
|
||||
if(received_bytes==0) {
|
||||
// std::cout << "No data received" << std::endl;
|
||||
return delete this;
|
||||
if (received_bytes == 0) {
|
||||
poco_information(Logger(), fmt::format("{}: Device Closing connection - 0 bytes received.",Id_));
|
||||
return EndConnection();
|
||||
}
|
||||
|
||||
// std::cout << "Received: " << received_bytes << std::endl;
|
||||
while (inBuf_.isReadable() && good) {
|
||||
std::size_t msg_len;
|
||||
u_char header[3]{0};
|
||||
inBuf_.read((char *)&header[0], 3);
|
||||
last_command_ = header[0];
|
||||
msg_len = header[1] * 256 + header[2];
|
||||
uint32_t msg_len = 0;
|
||||
if (waiting_for_bytes_ != 0) {
|
||||
|
||||
} else {
|
||||
if (inBuf_.used() >= 3) {
|
||||
auto *head = (unsigned char *)inBuf_.begin();
|
||||
last_command_ = head[0];
|
||||
msg_len = head[1] * 256 + head[2];
|
||||
inBuf_.drain(3);
|
||||
} else {
|
||||
good = false;
|
||||
if (!good)
|
||||
std::cout << "do_msgTypeTermData:5 " << inBuf_.used() << std::endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (last_command_) {
|
||||
case msgTypeRegister: {
|
||||
@@ -126,57 +153,93 @@ namespace OpenWifi {
|
||||
case msgTypeMax: {
|
||||
good = do_msgTypeMax(msg_len);
|
||||
} break;
|
||||
default:
|
||||
Logger().warning(fmt::format("{}: ID:{} Unknown command {}", conn_id_, id_,
|
||||
(int)last_command_));
|
||||
default: {
|
||||
poco_warning(Logger(),
|
||||
fmt::format("{}: Unknown command {} from device. GW closing connection.", Id_,
|
||||
(int)last_command_));
|
||||
good = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
} catch (const Poco::Exception &E) {
|
||||
good = false;
|
||||
Logger().log(E,__FILE__,__LINE__);
|
||||
poco_warning(Logger(),fmt::format("{}: Exception. GW closing connection.", Id_));
|
||||
} catch (const std::exception &E) {
|
||||
poco_warning(Logger(),fmt::format("{}: Exception. GW closing connection.", Id_));
|
||||
good = false;
|
||||
}
|
||||
|
||||
if(!good)
|
||||
return delete this;
|
||||
}
|
||||
|
||||
void RTTY_Device_ConnectionHandler::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
|
||||
delete this;
|
||||
}
|
||||
|
||||
void RTTY_Device_ConnectionHandler::Stop() {
|
||||
running_ = false;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::SendToClient(const u_char *Buf, int Len) {
|
||||
return RTTYS_server()->SendToClient(id_, Buf, Len);
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::SendToClient(const std::string &S) {
|
||||
return RTTYS_server()->SendToClient(id_, S);
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::KeyStrokes(const u_char *buf, size_t len) {
|
||||
std::lock_guard G(M_);
|
||||
|
||||
if(len>(RTTY_DEVICE_BUFSIZE-5))
|
||||
return false;
|
||||
|
||||
auto total_len = 3 + 1 + len-1;
|
||||
scratch_[0] = msgTypeTermData;
|
||||
scratch_[1] = (len & 0xff00) >> 8 ;
|
||||
scratch_[2] = (len & 0x00ff) ;
|
||||
scratch_[3] = sid_;
|
||||
memcpy( &scratch_[4], &buf[1], len-1);
|
||||
try {
|
||||
socket_.sendBytes((const void *)&scratch_[0], total_len);
|
||||
return true;
|
||||
} catch (...) {
|
||||
return false;
|
||||
if(!good) {
|
||||
return EndConnection();
|
||||
}
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::WindowSize(int cols, int rows) {
|
||||
std::lock_guard G(M_);
|
||||
void RTTYS_Device_ConnectionHandler::onSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf) {
|
||||
Guard G(M_);
|
||||
poco_information(Logger(),fmt::format("{}: Connection being closed - socket shutdown.",Id_));
|
||||
EndConnection();
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::SendToClient(const u_char *Buf, int Len) {
|
||||
return RTTYS_server()->SendToClient(Id_, Buf, Len);
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::SendToClient(const std::string &S) {
|
||||
return RTTYS_server()->SendToClient(Id_, S);
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::KeyStrokes(const u_char *buf, size_t len) {
|
||||
if(!valid_)
|
||||
return false;
|
||||
|
||||
if(len<=(sizeof(small_buf_)-3)) {
|
||||
small_buf_[0] = msgTypeTermData;
|
||||
small_buf_[1] = (len & 0xff00) >> 8;
|
||||
small_buf_[2] = (len & 0x00ff);
|
||||
memcpy(&small_buf_[3],buf,len);
|
||||
try {
|
||||
socket_.sendBytes(small_buf_,len+3);
|
||||
return true;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
auto Msg = std::make_unique<unsigned char []>(len + 3);
|
||||
Msg.get()[0] = msgTypeTermData;
|
||||
Msg.get()[1] = (len & 0xff00) >> 8;
|
||||
Msg.get()[2] = (len & 0x00ff);
|
||||
memcpy((void *)(Msg.get() + 3), buf, len);
|
||||
try {
|
||||
socket_.sendBytes(Msg.get(), len + 3);
|
||||
return true;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
unsigned char Msg[64];
|
||||
Msg[0] = msgTypeTermData;
|
||||
Msg[1] = (len & 0xff00) >> 8;
|
||||
Msg[2] = (len & 0x00ff);
|
||||
|
||||
Poco::Net::SocketBufVec MsgParts{ Poco::Net::SocketBuf{ .iov_base=Msg, .iov_len=3},
|
||||
Poco::Net::SocketBuf{ .iov_base=(unsigned char *)buf, .iov_len=len}};
|
||||
try {
|
||||
socket_.sendBytes(MsgParts);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
|
||||
bool RTTYS_Device_ConnectionHandler::WindowSize(int cols, int rows) {
|
||||
if(!valid_)
|
||||
return false;
|
||||
|
||||
// Guard G(M_);
|
||||
|
||||
u_char outBuf[8]{0};
|
||||
outBuf[0] = msgTypeWinsize;
|
||||
@@ -196,8 +259,11 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::Login() {
|
||||
std::lock_guard G(M_);
|
||||
bool RTTYS_Device_ConnectionHandler::Login() {
|
||||
if(!valid_)
|
||||
return false;
|
||||
|
||||
// Guard G(M_);
|
||||
u_char outBuf[3]{0};
|
||||
outBuf[0] = msgTypeLogin;
|
||||
outBuf[1] = 0;
|
||||
@@ -205,25 +271,26 @@ namespace OpenWifi {
|
||||
try {
|
||||
socket_.sendBytes(outBuf, 3);
|
||||
} catch (const Poco::IOException &E) {
|
||||
// std::cout << "1 " << E.what() << " " << E.name() << " "<< E.className() << " "<< E.message() << std::endl;
|
||||
return false;
|
||||
} catch (const Poco::Exception &E) {
|
||||
// std::cout << "2 " << E.what() << " " << E.name() << std::endl;
|
||||
return false;
|
||||
}
|
||||
received_login_from_websocket_ = true;
|
||||
Logger().debug(fmt::format("{}: Device {} login", conn_id_, id_));
|
||||
poco_information(Logger(),fmt::format("{}: Device login", Id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::Logout() {
|
||||
std::lock_guard G(M_);
|
||||
bool RTTYS_Device_ConnectionHandler::Logout() {
|
||||
if(!valid_)
|
||||
return false;
|
||||
|
||||
Guard G(M_);
|
||||
|
||||
u_char outBuf[4]{0};
|
||||
outBuf[0] = msgTypeLogout;
|
||||
outBuf[1] = 0;
|
||||
outBuf[2] = 1;
|
||||
outBuf[3] = sid_;
|
||||
Logger().debug(fmt::format("{}: ID:{} Logout", conn_id_, id_));
|
||||
poco_information(Logger(),fmt::format("{}: Logout", Id_));
|
||||
try {
|
||||
socket_.sendBytes(outBuf, 4);
|
||||
return true;
|
||||
@@ -233,7 +300,7 @@ namespace OpenWifi {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string RTTY_Device_ConnectionHandler::ReadString() {
|
||||
std::string RTTYS_Device_ConnectionHandler::ReadString() {
|
||||
std::string Res;
|
||||
|
||||
while(inBuf_.used()) {
|
||||
@@ -248,37 +315,29 @@ namespace OpenWifi {
|
||||
return Res;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeRegister([[maybe_unused]] std::size_t msg_len) {
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeRegister([[maybe_unused]] std::size_t msg_len) {
|
||||
bool good = true;
|
||||
try {
|
||||
id_ = ReadString();
|
||||
Id_ = ReadString();
|
||||
desc_ = ReadString();
|
||||
token_ = ReadString();
|
||||
serial_ = RTTYS_server()->SerialNumber(id_);
|
||||
|
||||
Logger().debug(fmt::format("{}: ID:{} Serial:{} Description:{} Device registration",
|
||||
conn_id_, id_, serial_, desc_));
|
||||
if (RTTYS_server()->Register(id_, token_, this)) {
|
||||
u_char OutBuf[8];
|
||||
OutBuf[0] = msgTypeRegister;
|
||||
OutBuf[1] = 0;
|
||||
OutBuf[2] = 4;
|
||||
OutBuf[3] = 0;
|
||||
OutBuf[4] = 'O';
|
||||
OutBuf[5] = 'K';
|
||||
OutBuf[6] = 0;
|
||||
if (socket_.sendBytes(OutBuf, 7) != 7) {
|
||||
poco_information(Logger(),
|
||||
fmt::format("{}: Description:{} Device registration", Id_, desc_));
|
||||
RTTYS_server()->NotifyDeviceRegistration(Id_,token_,this);
|
||||
u_char OutBuf[8];
|
||||
OutBuf[0] = msgTypeRegister;
|
||||
OutBuf[1] = 0;
|
||||
OutBuf[2] = 4;
|
||||
OutBuf[3] = 0;
|
||||
OutBuf[4] = 'O';
|
||||
OutBuf[5] = 'K';
|
||||
OutBuf[6] = 0;
|
||||
if (socket_.sendBytes(OutBuf, 7) != 7) {
|
||||
poco_information(Logger(),
|
||||
fmt::format("{}: Description:{} Could not send data to complete registration",
|
||||
Id_, desc_));
|
||||
good = false;
|
||||
Logger().debug(fmt::format(
|
||||
"{}: ID:{} Serial:{} Description:{} Could not complete registration",
|
||||
conn_id_, id_, serial_, desc_));
|
||||
} else {
|
||||
registered_ = true;
|
||||
}
|
||||
} else {
|
||||
Logger().debug(fmt::format(
|
||||
"{}: ID:{} Serial:{} Description:{} Could not complete registration", conn_id_,
|
||||
id_, serial_, desc_));
|
||||
}
|
||||
} catch (...) {
|
||||
good = false;
|
||||
@@ -286,8 +345,8 @@ namespace OpenWifi {
|
||||
return good;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeLogin([[maybe_unused]] std::size_t msg_len) {
|
||||
Logger().debug(fmt::format("{}: ID:{} Serial:{} Asking for login", conn_id_, id_, serial_));
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeLogin([[maybe_unused]] std::size_t msg_len) {
|
||||
poco_information(Logger(),fmt::format("{}: Asking for login", Id_));
|
||||
nlohmann::json doc;
|
||||
char Error;
|
||||
inBuf_.read(&Error, 1);
|
||||
@@ -295,72 +354,79 @@ namespace OpenWifi {
|
||||
doc["type"] = "login";
|
||||
doc["err"] = Error;
|
||||
const auto login_msg = to_string(doc);
|
||||
web_socket_active_ = true ;
|
||||
return SendToClient(login_msg);
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeLogout([[maybe_unused]] std::size_t msg_len) {
|
||||
Logger().debug(fmt::format("{}: ID:{} Serial:{} Asking for logout", conn_id_, id_, serial_));
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeLogout([[maybe_unused]] std::size_t msg_len) {
|
||||
poco_information(Logger(),fmt::format("{}: Asking for logout", Id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeTermData(std::size_t msg_len) {
|
||||
bool good = false;
|
||||
if(waiting_for_bytes_!=0) {
|
||||
auto to_read = std::min(inBuf_.used(),waiting_for_bytes_);
|
||||
inBuf_.read(&scratch_[0], to_read);
|
||||
good = SendToClient((u_char *)&scratch_[0], (int) to_read);
|
||||
if(to_read<waiting_for_bytes_)
|
||||
waiting_for_bytes_ -= to_read;
|
||||
else
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeTermData(std::size_t msg_len) {
|
||||
bool good;
|
||||
if(waiting_for_bytes_>0) {
|
||||
if(inBuf_.used()<waiting_for_bytes_) {
|
||||
waiting_for_bytes_ = waiting_for_bytes_ - inBuf_.used();
|
||||
good = SendToClient((unsigned char *)inBuf_.begin(), (int) inBuf_.used());
|
||||
if(!good) std::cout << "do_msgTypeTermData:1" << std::endl;
|
||||
inBuf_.drain();
|
||||
} else {
|
||||
good = SendToClient((unsigned char *)inBuf_.begin(), waiting_for_bytes_);
|
||||
if(!good) std::cout << "do_msgTypeTermData:2" << std::endl;
|
||||
inBuf_.drain(waiting_for_bytes_);
|
||||
waiting_for_bytes_ = 0 ;
|
||||
}
|
||||
} else {
|
||||
if(inBuf_.used()<msg_len) {
|
||||
auto read_count = inBuf_.read(&scratch_[0], inBuf_.used());
|
||||
good = SendToClient((u_char *)&scratch_[0], read_count);
|
||||
waiting_for_bytes_ = msg_len - read_count;
|
||||
good = SendToClient((unsigned char *)inBuf_.begin(), inBuf_.used());
|
||||
if(!good) std::cout << "do_msgTypeTermData:3" << std::endl;
|
||||
waiting_for_bytes_ = msg_len - inBuf_.used();
|
||||
inBuf_.drain();
|
||||
} else {
|
||||
inBuf_.read(&scratch_[0], msg_len);
|
||||
good = SendToClient((u_char *)&scratch_[0], (int)msg_len);
|
||||
waiting_for_bytes_=0;
|
||||
waiting_for_bytes_ = 0 ;
|
||||
good = SendToClient((unsigned char *)inBuf_.begin(), msg_len);
|
||||
if(!good) std::cout << "do_msgTypeTermData:4" << std::endl;
|
||||
inBuf_.drain(msg_len);
|
||||
}
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeWinsize([[maybe_unused]] std::size_t msg_len) {
|
||||
Logger().debug(fmt::format("{}: ID:{} Serial:{} Asking for msgTypeWinsize", conn_id_, id_, serial_));
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeWinsize([[maybe_unused]] std::size_t msg_len) {
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeWinsize", Id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeCmd([[maybe_unused]] std::size_t msg_len) {
|
||||
Logger().debug(fmt::format("{}: ID:{} Serial:{} Asking for msgTypeCmd", conn_id_, id_, serial_));
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeCmd([[maybe_unused]] std::size_t msg_len) {
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeCmd", Id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeHeartbeat([[maybe_unused]] std::size_t msg_len) {
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeHeartbeat([[maybe_unused]] std::size_t msg_len) {
|
||||
// if(!RTTYS_server()->ValidClient(Id_))
|
||||
// return false;
|
||||
u_char MsgBuf[3]{0};
|
||||
MsgBuf[0] = msgTypeHeartbeat;
|
||||
return socket_.sendBytes(MsgBuf, 3)==3;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeFile([[maybe_unused]] std::size_t msg_len) {
|
||||
Logger().debug(fmt::format("{}: ID:{} Serial:{} Asking for msgTypeFile", conn_id_, id_, serial_));
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeFile([[maybe_unused]] std::size_t msg_len) {
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeFile", Id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeHttp([[maybe_unused]] std::size_t msg_len) {
|
||||
Logger().debug(fmt::format("{}: ID:{} Serial:{} Asking for msgTypeHttp", conn_id_, id_, serial_));
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeHttp([[maybe_unused]] std::size_t msg_len) {
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeHttp", Id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeAck([[maybe_unused]] std::size_t msg_len) {
|
||||
Logger().debug(fmt::format("{}: ID:{} Serial:{} Asking for msgTypeAck", conn_id_, id_, serial_));
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeAck([[maybe_unused]] std::size_t msg_len) {
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeAck", Id_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTY_Device_ConnectionHandler::do_msgTypeMax([[maybe_unused]] std::size_t msg_len) {
|
||||
Logger().debug(fmt::format("{}: ID:{} Serial:{} Asking for msgTypeMax", conn_id_, id_, serial_));
|
||||
bool RTTYS_Device_ConnectionHandler::do_msgTypeMax([[maybe_unused]] std::size_t msg_len) {
|
||||
poco_information(Logger(),fmt::format("{}: Asking for msgTypeMax", Id_));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,9 @@
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
inline static const std::size_t RTTY_DEVICE_BUFSIZE=64000;
|
||||
constexpr std::size_t RTTY_DEVICE_BUFSIZE=64000;
|
||||
|
||||
inline static std::atomic_uint64_t global_device_connection_id = 1;
|
||||
|
||||
class RTTY_Device_ConnectionHandler{
|
||||
class RTTYS_Device_ConnectionHandler{
|
||||
public:
|
||||
enum RTTY_MSG_TYPE {
|
||||
msgTypeRegister = 0,
|
||||
@@ -30,52 +28,48 @@ namespace OpenWifi {
|
||||
msgTypeAck,
|
||||
msgTypeMax };
|
||||
|
||||
explicit RTTY_Device_ConnectionHandler(Poco::Net::StreamSocket& socket, Poco::Net::SocketReactor& reactor);
|
||||
|
||||
~RTTY_Device_ConnectionHandler();
|
||||
explicit RTTYS_Device_ConnectionHandler(Poco::Net::StreamSocket& socket, Poco::Net::SocketReactor& reactor);
|
||||
~RTTYS_Device_ConnectionHandler();
|
||||
|
||||
bool Login();
|
||||
bool Logout();
|
||||
void Stop();
|
||||
|
||||
[[nodiscard]] bool SendToClient(const u_char *buf, int len);
|
||||
[[nodiscard]] bool SendToClient(const std::string &S);
|
||||
[[nodiscard]] bool WindowSize(int cols, int rows);
|
||||
[[nodiscard]] bool KeyStrokes(const u_char *buf, size_t len);
|
||||
std::string ReadString();
|
||||
inline auto SessionID() const { return conn_id_; }
|
||||
// inline auto SessionID() const { return conn_id_; }
|
||||
|
||||
void onSocketReadable(const Poco::AutoPtr<Poco::Net::ReadableNotification>& pNf);
|
||||
void onSocketShutdown(const Poco::AutoPtr<Poco::Net::ShutdownNotification>& pNf);
|
||||
|
||||
bool Connected() const { return received_login_from_websocket_; }
|
||||
using My_mutex_type = std::recursive_mutex;
|
||||
using Guard = std::lock_guard<My_mutex_type>;
|
||||
|
||||
inline Poco::Logger &Logger() { return Logger_; }
|
||||
inline bool Valid() { return valid_; }
|
||||
|
||||
private:
|
||||
Poco::Net::StreamSocket socket_;
|
||||
Poco::Net::SocketReactor &reactor_;
|
||||
Poco::FIFOBuffer inBuf_{RTTY_DEVICE_BUFSIZE};
|
||||
Poco::Logger &Logger_;
|
||||
|
||||
mutable std::atomic_bool running_=false;
|
||||
std::atomic_bool valid_=false;
|
||||
Poco::Net::SocketAddress device_address_;
|
||||
std::recursive_mutex M_;
|
||||
std::string id_;
|
||||
My_mutex_type M_;
|
||||
std::string Id_;
|
||||
std::string token_;
|
||||
std::string desc_;
|
||||
std::string serial_;
|
||||
char sid_=0;
|
||||
mutable std::atomic_bool registered_=false;
|
||||
mutable std::atomic_bool web_socket_active_=false;
|
||||
|
||||
Poco::FIFOBuffer inBuf_;
|
||||
std::array<char,RTTY_DEVICE_BUFSIZE> scratch_{0};
|
||||
std::size_t waiting_for_bytes_{0};
|
||||
u_char last_command_=0;
|
||||
uint64_t conn_id_=0;
|
||||
mutable std::atomic_bool received_login_from_websocket_=false;
|
||||
unsigned char small_buf_[64];
|
||||
|
||||
void EndConnection(bool SendNotification=true) ;
|
||||
void CompleteConnection();
|
||||
|
||||
Poco::Logger & Logger();
|
||||
|
||||
[[nodiscard]] bool do_msgTypeRegister(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeLogin(std::size_t msg_len);
|
||||
[[nodiscard]] bool do_msgTypeLogout(std::size_t msg_len);
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenWifi {
|
||||
|
||||
if(MicroService::instance().NoAPISecurity()) {
|
||||
Poco::Net::ServerSocket DeviceSocket(DSport, 64);
|
||||
DeviceAcceptor_ = std::make_unique<Poco::Net::SocketAcceptor<RTTY_Device_ConnectionHandler>>(DeviceSocket,DeviceReactor_);
|
||||
DeviceAcceptor_ = std::make_unique<Poco::Net::SocketAcceptor<RTTYS_Device_ConnectionHandler>>(DeviceSocket,DeviceReactor_);
|
||||
} else {
|
||||
auto DeviceSecureContext = new Poco::Net::Context(Poco::Net::Context::SERVER_USE,
|
||||
KeyFileName, CertFileName, "",
|
||||
@@ -44,7 +44,7 @@ namespace OpenWifi {
|
||||
SSL_CTX_dane_enable(SSLCtxDevice);
|
||||
|
||||
Poco::Net::SecureServerSocket DeviceSocket(DSport, 64, DeviceSecureContext);
|
||||
DeviceAcceptor_ = std::make_unique<Poco::Net::SocketAcceptor<RTTY_Device_ConnectionHandler>>(DeviceSocket,DeviceReactor_);
|
||||
DeviceAcceptor_ = std::make_unique<Poco::Net::SocketAcceptor<RTTYS_Device_ConnectionHandler>>(DeviceSocket,DeviceReactor_);
|
||||
}
|
||||
DeviceReactorThread_.start(DeviceReactor_);
|
||||
Utils::SetThreadName(DeviceReactorThread_,"rt:devreactor");
|
||||
@@ -57,7 +57,7 @@ namespace OpenWifi {
|
||||
if(MicroService::instance().NoAPISecurity()) {
|
||||
Poco::Net::ServerSocket ClientSocket(CSport, 64);
|
||||
ClientSocket.setNoDelay(true);
|
||||
WebServer_ = std::make_unique<Poco::Net::HTTPServer>(new RTTY_Client_RequestHandlerFactory(Logger()), ClientSocket, WebServerHttpParams);
|
||||
WebServer_ = std::make_unique<Poco::Net::HTTPServer>(new RTTYS_Client_RequestHandlerFactory(Logger()), ClientSocket, WebServerHttpParams);
|
||||
} else {
|
||||
auto WebClientSecureContext = new Poco::Net::Context(Poco::Net::Context::SERVER_USE, KeyFileName, CertFileName,
|
||||
"", Poco::Net::Context::VERIFY_RELAXED);
|
||||
@@ -73,7 +73,7 @@ namespace OpenWifi {
|
||||
|
||||
Poco::Net::SecureServerSocket ClientSocket(CSport, 64, WebClientSecureContext);
|
||||
ClientSocket.setNoDelay(true);
|
||||
WebServer_ = std::make_unique<Poco::Net::HTTPServer>(new RTTY_Client_RequestHandlerFactory(Logger()), ClientSocket, WebServerHttpParams);
|
||||
WebServer_ = std::make_unique<Poco::Net::HTTPServer>(new RTTYS_Client_RequestHandlerFactory(Logger()), ClientSocket, WebServerHttpParams);
|
||||
};
|
||||
WebServer_->start();
|
||||
ClientReactorThread_.start(ClientReactor_);
|
||||
@@ -81,17 +81,24 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
GCCallBack_ = std::make_unique<Poco::TimerCallback<RTTYS_server>>(*this, &RTTYS_server::onTimer);
|
||||
Timer_.setStartInterval(10 * 1000); // first run in 30 seconds
|
||||
Timer_.setPeriodicInterval(1 * 60 * 1000);
|
||||
Timer_.setStartInterval(30 * 1000); // first run in 30 seconds
|
||||
Timer_.setPeriodicInterval(20 * 1000);
|
||||
Timer_.start(*GCCallBack_);
|
||||
|
||||
NotificationManager_.start(*this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RTTYS_server::Stop() {
|
||||
if(Internal_) {
|
||||
NotificationManagerRunning_=false;
|
||||
ResponseQueue_.wakeUpAll();
|
||||
NotificationManager_.wakeUp();
|
||||
NotificationManager_.join();
|
||||
Timer_.stop();
|
||||
WebServer_->stopAll();
|
||||
WebServer_->stop();
|
||||
DeviceAcceptor_->unregisterAcceptor();
|
||||
DeviceReactor_.stop();
|
||||
DeviceReactorThread_.join();
|
||||
@@ -101,294 +108,197 @@ namespace OpenWifi {
|
||||
}
|
||||
|
||||
void RTTYS_server::onTimer([[maybe_unused]] Poco::Timer & timer) {
|
||||
Logger().debug("Removing stale connections.");
|
||||
std::lock_guard G(Mutex_);
|
||||
poco_debug(Logger(),"Removing stale connections.");
|
||||
Utils::SetThreadName("rt:janitor");
|
||||
// Logger().debug(fmt::format("Current: connections:{} threads:{}.", DeviceAcceptor_->currentConnections(), DeviceAcceptor_->currentThreads()));
|
||||
auto now = OpenWifi::Now();
|
||||
dump("GC ", std::cout);
|
||||
for(auto element=EndPoints_.begin();element!=EndPoints_.end();) {
|
||||
if( element->second.ShutdownComplete ||
|
||||
(element->second.ShuttingDown && (now-element->second.TimeStamp>600))) {
|
||||
static int count = 0;
|
||||
// MutexLockerDbg L(__func__ ,M_);
|
||||
|
||||
std::unique_lock G(M_);
|
||||
for(auto element=EndPoints_.begin();element!=EndPoints_.end();) {
|
||||
if(element->second->TooOld()) {
|
||||
auto c = fmt::format("Removing {}. Serial: {} Device connection time: {}s. Client connection time: {}s",
|
||||
element->first,
|
||||
element->second->SerialNumber(),
|
||||
element->second->TimeDeviceConnected(),
|
||||
element->second->TimeClientConnected());
|
||||
Logger().information(c);
|
||||
TotalConnectedClientTime_ += element->second->TimeClientConnected();
|
||||
TotalConnectedDeviceTime_ += element->second->TimeDeviceConnected();
|
||||
element = EndPoints_.erase(element);
|
||||
} else {
|
||||
++element;
|
||||
}
|
||||
}
|
||||
dump("GC ", std::cout);
|
||||
FailedDevices.clear();
|
||||
FailedClients.clear();
|
||||
count++;
|
||||
if(count==10) {
|
||||
count=0;
|
||||
Logger().information(fmt::format("Total connections:{} Total Device Connection Time: {}s Total Client Connection Time: {}s Device failures: {} Client failures: {}",
|
||||
TotalEndPoints_,
|
||||
TotalConnectedDeviceTime_,
|
||||
TotalConnectedClientTime_,
|
||||
FaildedNumDevices_,
|
||||
FailedNumClients_));
|
||||
}
|
||||
}
|
||||
|
||||
void RTTYS_server::Register(const std::string &Id, RTTYS_ClientConnection *Client) {
|
||||
std::lock_guard G(Mutex_);
|
||||
dump("C REG--> ", std::cout);
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It!=EndPoints_.end()) {
|
||||
It->second.Client = Client;
|
||||
It->second.ClientConnected = OpenWifi::Now();
|
||||
dump("C REG--> ", std::cout);
|
||||
}
|
||||
dump("C Already REG--> ", std::cout);
|
||||
void RTTYS_server::CreateNewClient(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response, const std::string &id) {
|
||||
|
||||
auto NewClient = new RTTYS_ClientConnection(request, response, ClientReactor_, id);
|
||||
NotifyClientRegistration(id,NewClient);
|
||||
}
|
||||
|
||||
bool RTTYS_server::Register(const std::string &Id, const std::string &Token, RTTY_Device_ConnectionHandler *Device) {
|
||||
std::lock_guard G(Mutex_);
|
||||
dump("D REG--> ", std::cout);
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It!=EndPoints_.end()) {
|
||||
It->second.Device = Device;
|
||||
It->second.Token = Token;
|
||||
It->second.DeviceConnected = OpenWifi::Now();
|
||||
Logger().information(fmt::format("Creating session: {}, device:'{}'",Id,It->second.SerialNumber));
|
||||
dump("D REG--> ", std::cout);
|
||||
return true;
|
||||
void RTTYS_server::run() {
|
||||
Utils::SetThreadName("rtty-mgr");
|
||||
NotificationManagerRunning_ = true;
|
||||
Poco::AutoPtr<Poco::Notification> NextNotification(ResponseQueue_.waitDequeueNotification());
|
||||
while (NextNotification && NotificationManagerRunning_) {
|
||||
auto Notification = dynamic_cast<RTTYS_Notification *>(NextNotification.get());
|
||||
if (Notification != nullptr) {
|
||||
std::unique_lock G(M_);
|
||||
auto It = EndPoints_.find(Notification->id_);
|
||||
if (It != EndPoints_.end()) {
|
||||
switch (Notification->type_) {
|
||||
case RTTYS_Notification_type::device_disconnection: {
|
||||
It->second->DisconnectDevice();
|
||||
} break;
|
||||
case RTTYS_Notification_type::client_disconnection: {
|
||||
It->second->DisconnectClient();
|
||||
} break;
|
||||
case RTTYS_Notification_type::device_registration: {
|
||||
auto ptr = std::unique_ptr<RTTYS_Device_ConnectionHandler>{Notification->device_};
|
||||
It->second->SetDevice(std::move(ptr));
|
||||
if(!It->second->Joined() && It->second->ValidClient()) {
|
||||
It->second->Join();
|
||||
It->second->Login();
|
||||
}
|
||||
} break;
|
||||
case RTTYS_Notification_type::client_registration: {
|
||||
auto ptr = std::unique_ptr<RTTYS_ClientConnection>{Notification->client_};
|
||||
It->second->SetClient(std::move(ptr));
|
||||
if(!It->second->Joined() && It->second->ValidDevice()) {
|
||||
It->second->Join();
|
||||
It->second->Login();
|
||||
}
|
||||
} break;
|
||||
case RTTYS_Notification_type::unknown: {
|
||||
} break;
|
||||
};
|
||||
} else {
|
||||
if(Notification->type_==RTTYS_Notification_type::device_registration) {
|
||||
FaildedNumDevices_++;
|
||||
auto ptr = std::unique_ptr<RTTYS_Device_ConnectionHandler>{Notification->device_};
|
||||
FailedDevices.push_back(std::move(ptr));
|
||||
} else if(Notification->type_==RTTYS_Notification_type::client_registration) {
|
||||
FailedNumClients_++;
|
||||
auto ptr = std::unique_ptr<RTTYS_ClientConnection>{Notification->client_};
|
||||
FailedClients.push_back(std::move(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
NextNotification = ResponseQueue_.waitDequeueNotification();
|
||||
}
|
||||
dump("D Already REG--> ", std::cout);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTTYS_server::SendToClient(const std::string &Id, const u_char *Buf, std::size_t Len) {
|
||||
std::lock_guard G(Mutex_);
|
||||
std::shared_lock Guard(M_);
|
||||
try {
|
||||
auto It = EndPoints_.find(Id);
|
||||
if (It != EndPoints_.end() && It->second.Client != nullptr) {
|
||||
It->second.Client->SendData(Buf, Len);
|
||||
return true;
|
||||
if (It != EndPoints_.end()) {
|
||||
return It->second->SendToClient(Buf,Len);
|
||||
}
|
||||
} catch(...) {
|
||||
|
||||
} catch(const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
} catch (...) {
|
||||
std::cout << "Exception in SendToClient 1" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTTYS_server::SendToClient(const std::string &Id, const std::string &s) {
|
||||
std::lock_guard G(Mutex_);
|
||||
std::shared_lock Guard(M_);
|
||||
try {
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It!=EndPoints_.end() && It->second.Client!= nullptr) {
|
||||
It->second.Client->SendData(s);
|
||||
return true;
|
||||
}
|
||||
} catch(...) {
|
||||
|
||||
auto It = EndPoints_.find(Id);
|
||||
if (It != EndPoints_.end()) {
|
||||
return It->second->SendToClient(s);
|
||||
}
|
||||
} catch(const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
} catch (...) {
|
||||
std::cout << "Exception in SendToClient 2" << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RTTYS_server::DeRegister(const std::string &Id, RTTYS_ClientConnection *Client) {
|
||||
std::lock_guard G(Mutex_);
|
||||
Logger().information("{}: Deregistering.", Client->ID());
|
||||
bool RTTYS_server::ValidClient(const std::string &Id) {
|
||||
std::shared_lock Guard(M_);
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It!=EndPoints_.end() && It->second.Client==Client) {
|
||||
if(It->second.Device!= nullptr) {
|
||||
if(!It->second.ShuttingDown) {
|
||||
It->second.ShuttingDown = true;
|
||||
if(It->second.Device!= nullptr)
|
||||
It->second.Device->Stop();
|
||||
} else {
|
||||
It->second.ShutdownComplete = true;
|
||||
}
|
||||
} else {
|
||||
if(!It->second.ShuttingDown) {
|
||||
It->second.ShuttingDown = true;
|
||||
} else {
|
||||
It->second.ShutdownComplete = true;
|
||||
}
|
||||
}
|
||||
It->second.ClientConnected=0;
|
||||
It->second.Client= nullptr;
|
||||
}
|
||||
Logger().information("{}: Deregistered.", Client->ID());
|
||||
return It!=EndPoints_.end() && It->second->ValidClient();
|
||||
}
|
||||
|
||||
void RTTYS_server::DeRegisterDevice(const std::string &Id, RTTY_Device_ConnectionHandler *Device, bool remove_websocket) {
|
||||
std::lock_guard G(Mutex_);
|
||||
dump("D DEREG--> ", std::cout);
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It!=EndPoints_.end() && It->second.Device==Device) {
|
||||
It->second.Device = nullptr;
|
||||
It->second.DeviceConnected = 0 ;
|
||||
if(It->second.Client!=nullptr) {
|
||||
if(remove_websocket) {
|
||||
It->second.ShuttingDown = true;
|
||||
if(It->second.Client!= nullptr)
|
||||
It->second.Client->Close();
|
||||
}
|
||||
/* if(!It->second.ShuttingDown) {
|
||||
It->second.ShuttingDown = true;
|
||||
It->second.Client->Close();
|
||||
} else {
|
||||
It->second.ShutdownComplete = true;
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
if(!It->second.ShuttingDown) {
|
||||
It->second.ShuttingDown = true;
|
||||
} else {
|
||||
It->second.ShutdownComplete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool RTTYS_server::SendKeyStrokes(const std::string &Id, const u_char *buffer, std::size_t len) {
|
||||
std::shared_lock Guard(M_);
|
||||
|
||||
Logger().information(fmt::format("{}: Deregistering device.", Device->SessionID()));
|
||||
if(Device!= nullptr) {
|
||||
for (auto i = EndPoints_.begin(); i != EndPoints_.end(); i++) {
|
||||
if (i->second.Device == Device) {
|
||||
EndPoints_.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
dump("D DEREG--> ", std::cout);
|
||||
}
|
||||
Logger().information(fmt::format("{}: Deregistered device.", Device->SessionID()));
|
||||
}
|
||||
|
||||
bool RTTYS_server::SendKeyStrokes(const std::string &Id, const u_char *buffer, std::size_t s) {
|
||||
std::lock_guard G(Mutex_);
|
||||
auto It=EndPoints_.find(Id);
|
||||
if(It==EndPoints_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (It->second.Device != nullptr)
|
||||
return It->second.Device->KeyStrokes(buffer, s);
|
||||
return It->second->KeyStrokes(buffer, len);
|
||||
} catch(const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
} catch (...) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTTYS_server::WindowSize(const std::string &Id, int cols, int rows) {
|
||||
std::lock_guard G(Mutex_);
|
||||
std::shared_lock Guard(M_);
|
||||
auto It=EndPoints_.find(Id);
|
||||
if(It==EndPoints_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(It->second.Device!= nullptr)
|
||||
return It->second.Device->WindowSize(cols,rows);
|
||||
try {
|
||||
return It->second->WindowSize(cols,rows);
|
||||
} catch(const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
} catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool RTTYS_server::CreateEndPoint(const std::string &Id, const std::string & Token, const std::string & UserName, const std::string & SerialNumber ) {
|
||||
std::lock_guard G(Mutex_);
|
||||
std::unique_lock Guard(M_);
|
||||
|
||||
EndPoint E;
|
||||
E.ShuttingDown = false;
|
||||
E.Token = Token;
|
||||
E.TimeStamp = OpenWifi::Now();
|
||||
E.SerialNumber = SerialNumber;
|
||||
E.UserName = UserName;
|
||||
EndPoints_[Id] = E;
|
||||
auto NewEP = std::make_unique<RTTYS_EndPoint>(Token, SerialNumber, UserName );
|
||||
EndPoints_[Id] = std::move(NewEP);
|
||||
++TotalEndPoints_;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string RTTYS_server::SerialNumber(const std::string & Id) {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It==EndPoints_.end())
|
||||
return "";
|
||||
return It->second.SerialNumber;
|
||||
}
|
||||
|
||||
bool RTTYS_server::ValidId(const std::string &Token) {
|
||||
std::lock_guard G(Mutex_);
|
||||
std::shared_lock Guard(M_);
|
||||
return EndPoints_.find(Token) != EndPoints_.end();
|
||||
}
|
||||
|
||||
void RTTYS_server::LoginDone(const std::string & Id) {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It==EndPoints_.end())
|
||||
return;
|
||||
Logger().information(fmt::format("User: {}, Serial: {} logged in.",It->second.UserName, It->second.SerialNumber ));
|
||||
}
|
||||
|
||||
bool RTTYS_server::ValidEndPoint(const std::string &Id, const std::string &Token) {
|
||||
std::lock_guard G(Mutex_);
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It==EndPoints_.end()) {
|
||||
return false;
|
||||
}
|
||||
uint64_t Now = OpenWifi::Now();
|
||||
return ((It->second.Token == Token) && ((Now-It->second.TimeStamp)<30));
|
||||
}
|
||||
|
||||
bool RTTYS_server::CanConnect( const std::string &Id, RTTYS_ClientConnection *Conn) {
|
||||
std::lock_guard G(Mutex_);
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It!=EndPoints_.end() && It->second.Client==Conn) {
|
||||
It->second.ClientConnected = OpenWifi::Now();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTTYS_server::IsDeviceRegistered( const std::string &Id, const std::string &Token, [[maybe_unused]] RTTY_Device_ConnectionHandler *Conn) {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It == EndPoints_.end() || It->second.Token != Token )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t RTTYS_server::DeviceSessionID(const std::string & Id) {
|
||||
auto it = EndPoints_.find(Id);
|
||||
if(it==EndPoints_.end()) {
|
||||
return 0;
|
||||
} else {
|
||||
if(it->second.Device== nullptr) {
|
||||
return 0;
|
||||
} else {
|
||||
return it->second.Device->SessionID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RTTYS_server::Login(const std::string & Id) {
|
||||
std::lock_guard G(Mutex_);
|
||||
std::shared_lock Guard(M_);
|
||||
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It == EndPoints_.end()) {
|
||||
auto ep = EndPoints_.find(Id);
|
||||
if(ep == EndPoints_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(It->second.Device!= nullptr) {
|
||||
// std::cout << "login " << Id << " session " << It->second.Device->SessionID() << std::endl;
|
||||
// It->second.Device->AddCommand(RTTY_Device_ConnectionHandler::msgTypeLogin);
|
||||
// std::cout << "login done" << Id << std::endl;
|
||||
return It->second.Device->Login();
|
||||
try {
|
||||
return ep->second->Login();
|
||||
} catch(const Poco::Exception &E) {
|
||||
Logger().log(E);
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RTTYS_server::Logout(const std::string & Id) {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It == EndPoints_.end()) {
|
||||
return false;
|
||||
}
|
||||
if(It->second.Device!= nullptr)
|
||||
It->second.Device->Logout();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RTTYS_server::Close(const std::string & Id) {
|
||||
std::lock_guard G(Mutex_);
|
||||
|
||||
auto It = EndPoints_.find(Id);
|
||||
if(It == EndPoints_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(It->second.Device!= nullptr)
|
||||
It->second.Device->Stop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -9,13 +9,203 @@
|
||||
#include "Poco/Net/SocketAcceptor.h"
|
||||
#include "Poco/Timer.h"
|
||||
#include "rttys/RTTYS_device.h"
|
||||
#include "rttys/RTTYS_ClientConnection.h"
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class RTTY_Device_ConnectionHandler;
|
||||
class RTTYS_Device_ConnectionHandler;
|
||||
class RTTYS_ClientConnection;
|
||||
|
||||
class RTTYS_server : public SubSystemServer
|
||||
template <typename T> class MutexLockerDbg {
|
||||
public:
|
||||
MutexLockerDbg(const std::string &name, T &L) :
|
||||
name_(name),
|
||||
L_(L)
|
||||
{
|
||||
std::cout << name_ << ":L:0:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
|
||||
L_.lock();
|
||||
std::cout << name_ << ":L:1:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
|
||||
}
|
||||
|
||||
~MutexLockerDbg() {
|
||||
std::cout << name_ << ":U:0:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
|
||||
L_.unlock();
|
||||
std::cout << name_ << ":U:1:" << Poco::Thread::current()->name() << ":" << Poco::Thread::currentTid() << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
T & L_;
|
||||
};
|
||||
|
||||
enum class RTTYS_Notification_type {
|
||||
unknown,
|
||||
device_disconnection,
|
||||
client_disconnection,
|
||||
client_registration,
|
||||
device_registration
|
||||
};
|
||||
|
||||
class RTTYS_Notification: public Poco::Notification {
|
||||
public:
|
||||
RTTYS_Notification(const RTTYS_Notification_type &type, const std::string &id,
|
||||
RTTYS_Device_ConnectionHandler * device) :
|
||||
type_(type),
|
||||
id_(id),
|
||||
device_(device) {
|
||||
}
|
||||
|
||||
RTTYS_Notification(const RTTYS_Notification_type &type, const std::string &id,
|
||||
RTTYS_ClientConnection * client) :
|
||||
type_(type),
|
||||
id_(id),
|
||||
client_(client) {
|
||||
}
|
||||
|
||||
RTTYS_Notification(const RTTYS_Notification_type &type,
|
||||
const std::string &id,
|
||||
const std::string &token,
|
||||
RTTYS_Device_ConnectionHandler * device) :
|
||||
type_(type),
|
||||
id_(id),
|
||||
token_(token),
|
||||
device_(device) {
|
||||
}
|
||||
|
||||
RTTYS_Notification_type type_=RTTYS_Notification_type::unknown;
|
||||
std::string id_;
|
||||
std::string token_;
|
||||
RTTYS_Device_ConnectionHandler *device_= nullptr;
|
||||
RTTYS_ClientConnection *client_ = nullptr;
|
||||
};
|
||||
|
||||
class RTTYS_EndPoint {
|
||||
public:
|
||||
RTTYS_EndPoint(const std::string &Token, const std::string &SerialNumber, const std::string &UserName ):
|
||||
Token_(Token),
|
||||
SerialNumber_(SerialNumber),
|
||||
UserName_(UserName)
|
||||
{
|
||||
Created_ = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
inline void SetClient(std::unique_ptr<RTTYS_ClientConnection> Client) {
|
||||
ClientConnected_ = std::chrono::high_resolution_clock::now();
|
||||
Client_ = std::move(Client);
|
||||
}
|
||||
|
||||
inline void SetDevice(std::unique_ptr<RTTYS_Device_ConnectionHandler> Device) {
|
||||
DeviceConnected_ = std::chrono::high_resolution_clock::now();
|
||||
Device_ = std::move(Device);
|
||||
}
|
||||
|
||||
inline bool Login() {
|
||||
if(Device_!= nullptr) {
|
||||
return Device_->Login();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RTTYS_EndPoint & operator=(RTTYS_EndPoint Other) {
|
||||
Other.Client_ = std::move(Client_);
|
||||
Other.Device_ = std::move(Device_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void DisconnectClient() {
|
||||
ClientDisconnected_ = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
inline void DisconnectDevice() {
|
||||
DeviceDisconnected_ = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool TooOld() {
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> now = std::chrono::high_resolution_clock::now();
|
||||
if(ClientDisconnected_!=std::chrono::time_point<std::chrono::high_resolution_clock>{0s} && (now-ClientDisconnected_)>15s) {
|
||||
if(DeviceDisconnected_==std::chrono::time_point<std::chrono::high_resolution_clock>{0s}) {
|
||||
DeviceDisconnected_ = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if(DeviceDisconnected_!=std::chrono::time_point<std::chrono::high_resolution_clock>{0s} && (now-DeviceDisconnected_)>15s) {
|
||||
if(ClientDisconnected_==std::chrono::time_point<std::chrono::high_resolution_clock>{0s}) {
|
||||
ClientDisconnected_ = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!Joined_ && (now-Created_)>30s) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// std::cout << ClientDisconnected_ << " " << ClientConnected_ << " " << DeviceDisconnected_ << " " << DeviceConnected_ << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SendToClient(const u_char *Buf, std::size_t Len) {
|
||||
if(Client_!= nullptr && Client_->Valid()) {
|
||||
Client_->SendData(Buf,Len);
|
||||
return true;
|
||||
}
|
||||
std::cout << "SendToClientFailure: " << (Client_!= nullptr) << " " << Client_->Valid() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool KeyStrokes(const u_char *buffer, std::size_t len) {
|
||||
if( Device_!= nullptr && Device_->Valid() )
|
||||
return Device_->KeyStrokes(buffer,len);
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool WindowSize( int cols, int rows) {
|
||||
if(Device_!= nullptr && Device_->Valid())
|
||||
return Device_->WindowSize(cols,rows);
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool ValidClient() const {
|
||||
return Client_!= nullptr && Client_->Valid();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool ValidDevice() const {
|
||||
return Device_!= nullptr && Device_->Valid();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool Joined() volatile const { return Joined_; }
|
||||
void Join() {
|
||||
Joined_=true;
|
||||
}
|
||||
|
||||
inline bool SendToClient(const std::string &S) {
|
||||
if(Client_!= nullptr && Client_->Valid()) {
|
||||
Client_->SendData(S);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const std::string & UserName() const { return UserName_; }
|
||||
[[nodiscard]] inline const std::string & SerialNumber() const { return SerialNumber_; }
|
||||
|
||||
[[nodiscard]] inline auto TimeDeviceConnected() const { return std::chrono::duration<double>{DeviceDisconnected_ - DeviceConnected_}.count(); }
|
||||
[[nodiscard]] inline auto TimeClientConnected() const { return std::chrono::duration<double>{ClientDisconnected_ - ClientConnected_}.count(); }
|
||||
|
||||
private:
|
||||
std::string Token_;
|
||||
std::string SerialNumber_;
|
||||
std::string UserName_;
|
||||
std::unique_ptr<RTTYS_ClientConnection> Client_;
|
||||
std::unique_ptr<RTTYS_Device_ConnectionHandler> Device_;
|
||||
std::string Id_;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock>
|
||||
Created_{0s},DeviceDisconnected_{0s},
|
||||
ClientDisconnected_{0s},DeviceConnected_{0s} ,ClientConnected_{0s};
|
||||
volatile bool Joined_=false;
|
||||
};
|
||||
|
||||
class RTTYS_server : public SubSystemServer, Poco::Runnable
|
||||
{
|
||||
public:
|
||||
static auto instance() {
|
||||
@@ -28,38 +218,35 @@ namespace OpenWifi {
|
||||
|
||||
inline auto UIAssets() { return RTTY_UIAssets_; }
|
||||
|
||||
void Register(const std::string &Id, RTTYS_ClientConnection *Client);
|
||||
void DeRegister(const std::string &Id, RTTYS_ClientConnection *Client);
|
||||
bool Register(const std::string &Id, const std::string &Token, RTTY_Device_ConnectionHandler *Device);
|
||||
void DeRegisterDevice(const std::string &Id, RTTY_Device_ConnectionHandler *Device, bool remove_websocket);
|
||||
bool CreateEndPoint(const std::string &Id, const std::string & Token, const std::string & UserName, const std::string & SerialNumber );
|
||||
std::string SerialNumber(const std::string & Id);
|
||||
void LoginDone(const std::string & Id);
|
||||
bool ValidEndPoint(const std::string &Id, const std::string &Token);
|
||||
bool CanConnect( const std::string &Id, RTTYS_ClientConnection *Conn);
|
||||
bool IsDeviceRegistered( const std::string &Id, const std::string &Token, [[maybe_unused]] RTTY_Device_ConnectionHandler *Conn);
|
||||
bool Login(const std::string & Id_);
|
||||
bool Logout(const std::string & Id_);
|
||||
bool Close(const std::string & Id_);
|
||||
uint64_t DeviceSessionID(const std::string & Id);
|
||||
bool SendKeyStrokes(const std::string &Id, const u_char *buffer, std::size_t s);
|
||||
bool WindowSize(const std::string &Id, int cols, int rows);
|
||||
bool SendToClient(const std::string &id, const u_char *Buf, std::size_t Len);
|
||||
bool SendToClient(const std::string &id, const std::string &s);
|
||||
bool ValidClient(const std::string &id);
|
||||
bool ValidId(const std::string &Id);
|
||||
|
||||
struct EndPoint {
|
||||
std::string Token;
|
||||
mutable RTTYS_ClientConnection * Client = nullptr;
|
||||
mutable RTTY_Device_ConnectionHandler * Device = nullptr;
|
||||
uint64_t TimeStamp = OpenWifi::Now();
|
||||
mutable uint64_t DeviceConnected = 0;
|
||||
mutable uint64_t ClientConnected = 0;
|
||||
std::string UserName;
|
||||
std::string SerialNumber;
|
||||
mutable bool ShuttingDown = false;
|
||||
mutable bool ShutdownComplete = false;
|
||||
};
|
||||
void run() final;
|
||||
|
||||
inline void NotifyDeviceDisconnect(const std::string &id, RTTYS_Device_ConnectionHandler *device) {
|
||||
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::device_disconnection,id,device));
|
||||
}
|
||||
|
||||
inline void NotifyClientDisconnect(const std::string &id, RTTYS_ClientConnection *client) {
|
||||
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::client_disconnection,id,client));
|
||||
}
|
||||
|
||||
inline void NotifyDeviceRegistration(const std::string &id, const std::string &token, RTTYS_Device_ConnectionHandler *device) {
|
||||
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::device_registration,id,token,device));
|
||||
}
|
||||
|
||||
inline void NotifyClientRegistration(const std::string &id, RTTYS_ClientConnection *client) {
|
||||
ResponseQueue_.enqueueNotification(new RTTYS_Notification(RTTYS_Notification_type::client_registration,id,client));
|
||||
}
|
||||
|
||||
void CreateNewClient(Poco::Net::HTTPServerRequest &request,
|
||||
Poco::Net::HTTPServerResponse &response, const std::string &id);
|
||||
|
||||
void onTimer(Poco::Timer & timer);
|
||||
|
||||
@@ -67,32 +254,35 @@ namespace OpenWifi {
|
||||
return Internal_;
|
||||
}
|
||||
|
||||
inline void dump([[maybe_unused]] const char *ID, [[maybe_unused]] std::ostream &s) {
|
||||
/* for(const auto &[id,point]:EndPoints_) {
|
||||
s << ID << " ID: " << id << " C:" << (point.Client == nullptr) << " D:" << (point.Device== nullptr)
|
||||
<< " Shutting down: " << point.ShuttingDown
|
||||
<< " Shutdown: " << point.ShutdownComplete << std::endl;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
inline Poco::Net::SocketReactor & ClientReactor() { return ClientReactor_; }
|
||||
|
||||
private:
|
||||
// std::recursive_mutex M_;
|
||||
Poco::Net::SocketReactor ClientReactor_;
|
||||
Poco::Net::SocketReactor DeviceReactor_;
|
||||
Poco::Thread ClientReactorThread_;
|
||||
std::string RTTY_UIAssets_;
|
||||
std::atomic_bool Internal_ = false;
|
||||
Poco::Net::SocketReactor ClientReactor_;
|
||||
Poco::Net::SocketReactor DeviceReactor_;
|
||||
Poco::Thread ClientReactorThread_;
|
||||
std::string RTTY_UIAssets_;
|
||||
bool Internal_ = false;
|
||||
|
||||
std::map<std::string, EndPoint> EndPoints_; // id, endpoint
|
||||
std::map<std::string,std::unique_ptr<RTTYS_EndPoint>> EndPoints_; // id, endpoint
|
||||
std::unique_ptr<Poco::Net::HTTPServer> WebServer_;
|
||||
std::unique_ptr<Poco::Net::SocketAcceptor<RTTY_Device_ConnectionHandler>> DeviceAcceptor_;
|
||||
Poco::Thread DeviceReactorThread_;
|
||||
std::unique_ptr<Poco::Net::SocketAcceptor<RTTYS_Device_ConnectionHandler>> DeviceAcceptor_;
|
||||
Poco::Thread DeviceReactorThread_;
|
||||
Poco::NotificationQueue ResponseQueue_;
|
||||
mutable bool NotificationManagerRunning_=false;
|
||||
Poco::Thread NotificationManager_;
|
||||
|
||||
Poco::Timer Timer_;
|
||||
std::unique_ptr<Poco::TimerCallback<RTTYS_server>> GCCallBack_;
|
||||
std::list<std::unique_ptr<RTTYS_Device_ConnectionHandler>> FailedDevices;
|
||||
std::list<std::unique_ptr<RTTYS_ClientConnection>> FailedClients;
|
||||
mutable std::shared_mutex M_;
|
||||
|
||||
uint64_t TotalEndPoints_=0;
|
||||
uint64_t FaildedNumDevices_=0;
|
||||
uint64_t FailedNumClients_=0;
|
||||
double TotalConnectedDeviceTime_=0.0;
|
||||
double TotalConnectedClientTime_=0.0;
|
||||
|
||||
|
||||
explicit RTTYS_server() noexcept:
|
||||
SubSystemServer("RTTY_Server", "RTTY-SVR", "rtty.server")
|
||||
|
||||
52
src/sdks/sdk_prov.h
Normal file
52
src/sdks/sdk_prov.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-07-16.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/MicroService.h"
|
||||
#include "RESTObjects/RESTAPI_ProvObjects.h"
|
||||
|
||||
namespace OpenWifi::SDK::Prov {
|
||||
|
||||
inline bool GetSerialNumbersForVenueOfSerialNumber( const std::string & SerialNumber, Types::UUID_t &Venue, Types::StringVec & AdjacentSerialNumbers , Poco::Logger &Logger ) {
|
||||
OpenAPIRequestGet GetInventoryForSerialNumber( uSERVICE_PROVISIONING, "/api/v1/inventory/" + SerialNumber , {} , 30000);
|
||||
|
||||
auto CallResponse1 = Poco::makeShared<Poco::JSON::Object>();
|
||||
if(!GetInventoryForSerialNumber.Do(CallResponse1,"")) {
|
||||
Logger.error(fmt::format("{}: Cannot find serial number in inventory.", SerialNumber));
|
||||
return false;
|
||||
}
|
||||
|
||||
ProvObjects::InventoryTag Device;
|
||||
if(!Device.from_json(CallResponse1)) {
|
||||
Logger.error(fmt::format("{}: Invalid Inventory response.", SerialNumber));
|
||||
return false;
|
||||
}
|
||||
|
||||
Venue = Device.venue;
|
||||
|
||||
OpenAPIRequestGet GetInventoryForVenue( uSERVICE_PROVISIONING, "/api/v1/inventory" ,
|
||||
{
|
||||
{"serialOnly","true"},
|
||||
{"venue", Venue}
|
||||
}, 30000);
|
||||
|
||||
auto CallResponse2 = Poco::makeShared<Poco::JSON::Object>();
|
||||
if(!GetInventoryForVenue.Do(CallResponse2,"")) {
|
||||
Logger.error(fmt::format("{}: Cannot get inventory for venue.", SerialNumber));
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
OpenWifi::RESTAPI_utils::field_from_json(CallResponse2, "serialNumbers",
|
||||
AdjacentSerialNumbers);
|
||||
} catch(...) {
|
||||
Logger.error(fmt::format("{}: Cannot parse inventory list", SerialNumber));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user