231 Commits

Author SHA1 Message Date
Ian Craggs
07a95121fc Add required Eclipse meta docs 2024-01-18 15:17:28 +00:00
Tomoaki Yamaguchi
59797127e7 Merge pull request #251 from agalliazzo/udp6_multicast_hop_bugfix
Fix issue #250
2021-12-26 16:20:44 +09:00
Tomoaki Yamaguchi
27b5c7623e Merge pull request #252 from fgrandel/bugfix/secure-flag
fix: secure client networks no longer work with pre-allocated client list
2021-12-26 16:20:21 +09:00
Tomoaki Yamaguchi
4508461fc1 Merge pull request #254 from fgrandel/bugfix/build-script-clean
fix: typo in build script clean command
2021-12-26 16:19:38 +09:00
Tomoaki Yamaguchi
b5f2fd655d Merge pull request #253 from fgrandel/bugfix/typo-in-config
fix: the sample configuration contains a non-existent configuration key
2021-12-26 16:18:19 +09:00
Florian Grandel
c4e2ac4026 fix: typo in build script clean command 2021-12-22 03:54:13 +01:00
Florian Grandel
273c71774b fix: the sample configuration contains a non-existent configuration key 2021-12-22 03:26:59 +01:00
Florian Grandel
135e79e4da fix: single point of truth for secure client network 2021-12-22 02:53:35 +01:00
Alessio Galliazzo
debc21760b Fix issue #250 2021-12-13 16:59:11 +00:00
Tomoaki Yamaguchi
59fd3ec598 Merge pull request #247 from eclipse/develop
Bugfix of  #246
2021-10-06 10:37:24 +09:00
tomoaki
9c67c75939 Bugfix of #246
Revert a line deleted by commit 15c527e


Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-10-02 11:21:21 +09:00
Tomoaki Yamaguchi
a37803ac04 Merge pull request #245 from eclipse/develop
Update Gateway
2021-09-16 15:32:13 +09:00
tomoaki
52500a0c79 Update README
delete unused include statement
2021-09-16 11:13:13 +09:00
tomoaki
0398566e82 Bugfix of #241
DTLS Enhancement #90 complete.
OpenSSL version 1.1.1k 25 Mar. 2021 is required.
This fix does not work with version 1.1.1 11 sep. 2018

Merge branch 'dtls' into develop
2021-08-11 18:49:31 +09:00
tomoaki
4dcfa98303 Bugfix of DTLS6 #241
This fix doesn't work on OpenSSL version 1.1.1 11.sep 2018
Upgrade to version 1.1.1k 25 Mar. 2021

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-08-11 18:30:51 +09:00
tomoaki
a136f50c75 Bugfix of #241, #90
Two clients works fine.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-08-03 14:24:35 +09:00
tomoaki
b6a152a912 Bugfix of #241
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-08-02 17:05:17 +09:00
tomoaki
4fc0e2f52b Bugfix 0f #234
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-08-02 07:25:28 +09:00
tomoaki
5fb4312aad This branch for debugging DTLS #90, #150, #195, #227
The purpose of this branch is to share work in process.
Change sellect() of UDP to poll()
Rewrite UDP6 for DTLS6

Known bug: can't reconnect DTLS

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-08-01 19:45:58 +09:00
tomoaki
fa0925d24e settings was changed
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-08-01 19:27:17 +09:00
tomoaki
f2dcda358f Bugfix of #234
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-07-14 11:28:20 +09:00
tomoaki
776099ebb3 Bugfix Set a secure flag to a Client instance.
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-07-09 07:45:39 +09:00
tomoaki
83c30d662f Bugfix check network status after initialization.
future branch is merged into develop. #69
Change Tab to 4 spaces

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-06-11 09:46:00 +09:00
tomoaki
85ae4e3596 Update README
Fix typo #240

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-06-07 18:09:12 +09:00
tomoaki
d3626bb68d Add a new sensor network Bluetooth RFCOMM
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-06-07 18:00:02 +09:00
tomoaki
de355e28b6 Add apt install bluez and libbluetooth-dev
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-06-02 20:42:07 +09:00
tomoaki
55128f0f0e Add Bluetooth classic as a sensor network #69, #195, #90
I think the architecture of the ble sensor network, which does not use
threads per socket, can be applied to DTLS.

Known bug:
Occasionally a timeout error occurs when connecting to RFCOMM.
BLE is not supported yet. I need help to do it.


Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-06-02 20:40:02 +09:00
tomoaki
982e6d4884 Add ClientPool
Clients are created and kept in the pool at first.
ClientList gets a free client from the pool.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-25 11:50:58 +09:00
tomoaki
740faeb09f update test
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-18 21:07:24 +09:00
tomoaki
74fa104c64 add LoRaLink config
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-18 20:58:06 +09:00
tomoaki
26e4e0d91a Add function for a test
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-18 20:58:06 +09:00
tomoaki
15c527e073 Bugfix of #221
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-18 20:58:06 +09:00
tomoaki
5fbd32151e Update Test for debug
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-18 20:58:06 +09:00
tomoaki
aa98498e57 Update README
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-18 20:58:05 +09:00
tomoaki
9cb991b774 Copy config files to bin directory
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-18 20:58:05 +09:00
tomoaki
57f8effb7d Bugfix of #238
This reverts commit 69fd222d6070a5e9ec02c90b03a7bb0671ca0db0.
2021-05-18 20:58:05 +09:00
tomoaki
a7133dd751 Bugfix of #230 c65d66e reverted
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-17 15:26:01 +09:00
tomoaki
cd6b1151a3 Add Test fucntions
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-17 09:50:30 +09:00
tomoaki
ae0cc2ec61 waste removal
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>e
2021-05-16 15:45:38 +09:00
tomoaki
dc3142f2f0 Bugfix of #196, #214, #222
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-15 20:03:00 +09:00
tomoaki
f079211ea7 upgrade and bugfix for a test
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-15 18:32:05 +09:00
tomoaki
9c9de103df Fix of Mac copile error
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-14 14:31:00 +09:00
tomoaki
c65d66e3d3 Bugfix of #230
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-13 20:45:54 +09:00
tomoaki
d567b0ba7f Bugfix of test
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-13 20:28:46 +09:00
tomoaki
fa7daac109 Bugfix of #225
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-13 15:09:04 +09:00
tomoaki
dcde0bf4ff Bug Fix of wildcard character
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-13 13:37:55 +09:00
tomoaki
bb72c590c6 Fix of #221
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-13 13:09:28 +09:00
tomoaki
ceaa3ab592 Add Exception Handling scheme explanation. #173
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-13 12:57:54 +09:00
tomoaki
390f940b4a Update BrokerName
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-13 10:37:56 +09:00
tomoaki
e1b000b6f4 Fix of Test error
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-11 15:11:12 +09:00
tomoaki
5876ab8f3c BugFix of #220
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-11 14:41:25 +09:00
tomoaki
fb4958c271 Bugfix of CMakeFile
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-11 14:40:57 +09:00
tomoaki
4777252df0 Refacter UDP SensorNetwork
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-11 13:58:21 +09:00
tomoaki
dd13618845 Add Exception message to Mutex
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-11 13:57:22 +09:00
tomoaki
9a22c1bd7e Change a brokers host name
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-11 12:28:04 +09:00
tomoaki
2cf6df41f4 Add Include path of OpenSSL
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-10 10:43:17 +09:00
tomoaki
63b546e254 Flush message immediately
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-08 20:53:02 +09:00
tomoaki
4d77386026 Bugfix of #229
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-08 17:19:19 +09:00
tomoaki
f933946043 Add mutex keys to a gitignore
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-08 16:45:54 +09:00
tomoaki
17cbed6590 Disabled build log
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-07 18:43:12 +09:00
tomoaki
f631f27c25 Add errno to a Exception property
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-05 15:47:19 +09:00
tomoaki
29486503d1 Set Gateway version by CMakeFile.txt
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-05 11:00:32 +09:00
tomoaki
2adc167207 Refactor Exception handle scheme
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-04 17:34:46 +09:00
tomoaki
4478eafc8d Bugfix of Exception Handling
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-03 19:20:52 +09:00
tomoaki
8a2d28a5e4 Add Gateway build script.
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-05-01 16:36:01 +09:00
tomoaki
c4efb6d31c Add MQTT-SN Gateway Overview
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-30 23:29:49 +09:00
tomoaki
12fc05b196 Bugfix of #231
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-30 23:11:37 +09:00
tomoaki
0ad10f9759 Update UDP6 Address comment
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-30 20:38:23 +09:00
tomoaki
53433c2b64 Bugfix of README
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-30 20:36:55 +09:00
tomoaki
18af949c7a Change Execption messages
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-30 19:21:49 +09:00
tomoaki
5c7cefdf48 Update README
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-30 19:20:39 +09:00
tomoaki
e4ccfe9487 Bugfix of Travis CI build
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-30 16:38:53 +09:00
tomoaki
c15d3ac252 Bugfix of Travis CI Build failed
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-30 16:30:19 +09:00
tomoaki
9a84cc9a6a Bugfix #276 failed
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-30 16:18:14 +09:00
tomoaki
2bf7985e2b Bugfix cmake related files
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-30 14:55:22 +09:00
tomoaki
c12e93122f Add CMakelists.txt for MQTTSNGateway #235
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-29 21:32:25 +09:00
tomoaki
48772fce3b Stop compiler warning message #206
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-29 11:00:58 +09:00
tomoaki
aaad3a0122 Bugfix of Handling Exception #236
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-29 11:00:58 +09:00
tomoaki
60fcab2504 Change Client Type
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-04-27 21:34:54 +09:00
tomoaki
69b229daae Change TAB to 4spaces
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2021-02-16 15:51:54 +09:00
Tomoaki Yamaguchi
ca467548b4 Merge pull request #217 from eclipse/develop
Merge latest develop branch to master
2020-10-13 15:41:02 +09:00
Tomoaki Yamaguchi
d05bf8eaf4 Merge branch 'master' into develop 2020-10-13 15:11:07 +09:00
tomoaki
63036f1c8f change project's properties
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-13 14:52:52 +09:00
tomoaki
b387c4c341 Change Include pathes to Relative path
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-13 14:38:14 +09:00
tomoaki
b4a598e895 Update 9c214a and 438a9a1
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-13 11:19:12 +09:00
tomoaki
5041caf7a2 Avoid compile error of Mac
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-12 21:07:09 +09:00
tomoaki
ce8c9cabad Fix of compile error
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-12 20:15:39 +09:00
tomoaki
910dd07f3a Comment out debug messages and bugfix of Makefile
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-12 19:33:52 +09:00
tomoaki
8ceb7ee67e Bugfix of compile error and update README
update Makefile for Mac

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-12 18:33:01 +09:00
tomoaki
45ea265344 Add LoRaLink sensor network
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-12 17:58:32 +09:00
tomoaki
21f2f84219 Typo fixed #212
Add Gateway terminate status

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-12 17:48:20 +09:00
tomoaki
1f9241b260 Bugfix of DISCONNECT and ClientSend error message
Close the Connection after sending DISCONNECT.
Separate multicast error message.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-12 17:30:11 +09:00
tomoaki
aa199cdf9b Bugfix of short topic
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-12 17:24:20 +09:00
tomoaki
d91de457f3 BugFix of #209
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-10-12 17:00:09 +09:00
Ian Craggs
ab94a094b5 Update copyright statement 2020-07-09 12:06:20 +01:00
Ian Craggs
9cd214a8bb Improve handling of no config file 2020-07-09 12:05:54 +01:00
Ian Craggs
438a9a131f Bug fixes from #209 2020-07-09 12:01:17 +01:00
tomoaki
48169d48fa Fix typo #207 2020-06-06 12:23:33 +09:00
tomoaki
b73d743d00 BugFix of #205
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-05-28 11:57:30 +09:00
tomoaki
f8a60d811a BugFix of #205
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-05-23 10:41:17 +09:00
tomoaki
9adc2fed13 Bugfix of #192
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-04-14 10:06:03 +09:00
tomoaki
52ddaf2686 Bugfix of #191
WILLTOPICUPD is not handled.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-04-07 15:25:55 +09:00
tomoaki
480d084e69 refacter
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-04-07 14:21:53 +09:00
tomoaki
687a78ee2c update for #188
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-04-06 19:02:02 +09:00
tomoaki
61d9a283f5 Change prompt of the gateway
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-03-24 14:57:56 +09:00
tomoaki
c6d7daba11 BugFix of PR #189
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-03-24 14:35:42 +09:00
tomoaki
1ef0add867 a 2020-03-20 12:40:41 +09:00
tomoaki
258d534009 Update Aggregatting gateway can now receive PUBLISH from a broker
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-03-05 18:05:46 +09:00
tomoaki
53be14f76e Bugfix of #177
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-25 15:50:56 +09:00
tomoaki
6a8cdba186 Bugfix can't read PredefinedTopicList file
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-23 17:35:06 +09:00
tomoaki
f57d391b16 Change outage logs to be nicely.
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-21 18:49:58 +09:00
tomoaki
1b6e6faab5 Update README #180
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-21 14:11:43 +09:00
tomoaki
ae462989ec BugFix ClientList file name is not shown
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-21 11:29:37 +09:00
tomoaki
c37d9334d4 update README 2020-02-18 12:56:00 +09:00
tomoaki
1b08591fad BugFix of #181 2020-02-15 18:24:51 +09:00
tomoaki
731a392559 Add info to README #179
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-12 10:57:47 +09:00
tomoaki
9d6b9d46ef Add a new function to set TTL/Hops of SensorNetwork(UDP and UDP6) #175
Add Parameters to the gateway.conf to set those values.
MulticastTTL=1 for UDP
GatewayUDP6Hops=1 for UDP6

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-11 19:13:17 +09:00
tomoaki
b8129d6781 Add a new function to set TTL/Hops of SensorNetwork(UDP and UDP6) #175
Parameters to set them in the gateway.conf,
MulticastTTL=1 for UDP
GatewayUDP6Hops=1 for UDP6

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-11 18:30:33 +09:00
tomoaki
768123b76f Bugfix of #171
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-11 16:22:01 +09:00
tomoaki
ac909accc7 Merge branch 'BugFixofAdapter' into develop 2020-02-11 16:08:35 +09:00
tomoaki
f1fefd47ce BugFix Adapters
PINGREQ and PINGRESP
Add Error message when the Aggregate GW receives PUBLISH from the
broker.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-11 16:06:09 +09:00
tomoaki
7246ea2c8a a 2020-02-10 17:23:41 +09:00
tomoaki
1715d5d47c BugFix Adapters
PINGREQ and PINGRESP
Add Error message when the Aggregate GW receives PUBLISH from the
broker.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2020-02-10 16:02:06 +09:00
Tomoaki Yamaguchi
6e3c53ec83 Merge pull request #176 from Jochen0x90h/macos
Support for MacOS
I have confirmed it works on linux. but I haven't confirmed if it works on Mac,
2020-02-03 13:50:37 +09:00
Jochen Wilhelmy
d6effc8074 Support for MacOS
Split semaphore classes into Semaphore and NamedSemaphore
Semaphore is implemented with Grand Central Dispatch
NamedSemaphore uses the spin lock approach like in boost for sem_timedwait
sem_getvalue is not supported on MacOS and therefore was removed
Fixed bug (*gatewayaddress_len > 0) in MQTTSNSearchClient.c

Signed-off-by: Jochen Wilhelmy <jochen.wilhelmy@gmail.com>
2020-01-18 11:43:54 +01:00
Tomoaki Yamaguchi
e64e817f80 Merge pull request #164 from martinkirsche/feature/decode-documentation-fix
Fix documentation of MQTTSNPacket_decode
2019-10-28 11:01:23 +09:00
tomoaki
65583a6887 Add Invalid TopicId check.
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-10-04 21:12:00 +09:00
tomoaki
7aa44d94d1 Bugfix of #165
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-10-03 15:13:29 +09:00
tomoaki
271b635d3f Fix Typo
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-10-03 10:39:44 +09:00
Martin Kirsche
84b90f9a0c Fix documentation of MQTTSNPacket_decode
Added a documentation for the missing parameters buf and buflen and
removed the non-existing parameter getcharfn.

Signed-off-by: Martin Kirsche <martin.kirsche@gmail.com>
2019-09-14 23:07:46 +02:00
tomoaki
2067e6fe92 Validate MsgId of PUBLISH
MsgId of QoS0 or QoS-1 should be 0.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-08-24 17:33:42 +09:00
Tomoaki Yamaguchi
ad86a276b5 Merge pull request #162 from eclipse/develop
BugFix of #149 and #151
2019-07-27 12:32:20 +09:00
tomoaki
22e7f0d272 Bugfix of test
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-07-27 12:20:57 +09:00
tomoaki
2b7f040b57 Update a errata of README
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-07-27 12:04:23 +09:00
tomoaki
04bc61dbca Update README
Add Tips for Debug
Delete unused define

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-07-19 12:09:53 +09:00
tomoaki
93e297c6d3 BugFix of #149
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-07-13 16:38:12 +09:00
tomoaki
18885668cf Update README
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-05-30 10:09:14 +09:00
tomoaki
6cb7935027 BugFix of #151
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-05-28 16:45:32 +09:00
tomoaki
3fae393efc Errata Sensernet Address of UDP is IPAdress:PortNo
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-05-17 16:55:46 +09:00
tomoaki
d8bced8a62 update README
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-02-26 21:57:34 +09:00
tomoaki
3d5b8f75d1 update README
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-02-26 21:51:37 +09:00
tomoaki
528934962f Improve documentation #145
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-02-23 11:36:00 +09:00
Tomoaki Yamaguchi
c9e807da31 Merge pull request #143 from eclipse/develop
Add functions of Aggregating Gateway, QoS-1 and forwarder encapsulation.
2019-01-17 07:13:40 +09:00
tomoaki
284b5d5b46 Update READ.me
MQTT-SN transparent Gateway to transparent/aggrigating gateway.


Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-01-15 17:18:16 +09:00
tomoaki
c7b8ef1e54 Refacter the MQTT-SN Packet printf()
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-01-15 16:38:55 +09:00
Tomoaki Yamaguchi
502ba1f117 Update README.md 2019-01-15 10:51:38 +09:00
Tomoaki Yamaguchi
004b90a298 Update README.md 2019-01-15 10:50:37 +09:00
tomoaki
7e13268466 Update: Add MQTT-SN message length to the Gateway log.
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2019-01-15 09:37:54 +09:00
tomoaki
fd782f8e50 Do not discard PUBLISH message while the client is sleeping.
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-10-21 11:00:47 +09:00
tomoaki
fa4725b85d BugFix Subscribe pre\defined\topic #132
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-25 10:28:22 +09:00
tomoaki
6ef24f3bb8 Change Commom ClientID of predifinedTopic.conf to '*' #132
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-25 09:56:15 +09:00
tomoaki
42125d173b Update for Issue #132
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-25 08:38:21 +09:00
Tomoaki Yamaguchi
9a06b8a697 Merge pull request #130 from eclipse/develop
Install the gateway into any directories. #124
2018-08-18 12:23:19 +09:00
tomoaki
7fae038296 Install the gateway into any directory. #124
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-18 12:18:23 +09:00
tomoaki
ee15a21ff3 #129
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-15 07:11:43 +09:00
tomoaki
42886b70f0 Compile Errors #68
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-15 06:58:57 +09:00
tomoaki
6e865d62f0 Bugfix of #68
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-14 09:04:58 +09:00
Tomoaki Yamaguchi
a23242d267 Merge pull request #128 from eclipse/develop
You can select Aggregate or Transparent gateway in the config file setting.
2018-08-14 08:22:27 +09:00
tomoaki
9de1dc3705 Generate the QoSm1Proxy Name from the Gateway Id.
Bugfix of AggregatePublish
Memory leak of ClientList

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-14 08:11:11 +09:00
tomoaki
97cffe4573 Forwerders are declared by the ClientList file.
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-13 21:28:51 +09:00
tomoaki
f216abd97e BugFix: resource leak
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-13 06:05:18 +09:00
tomoaki
e308c3da83 Correction to eliminate compiler warning message
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-12 14:59:51 +09:00
tomoaki
f7fc5c49f5 Update: Add Aggregate Gateway functions. #127
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-08-12 14:04:41 +09:00
tomoaki
862e501512 BugFix add retry PINGREQ and re CONNECT #126
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-31 20:56:03 +09:00
tomoaki
df080f2851 Set whether to run ClientProxy at startup.
If it does not start, do not create an instance of ClientProxy.
Change the name of ClientProxy to QoSm1Proxy

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-31 15:49:25 +09:00
tomoaki
e942ee451d BugFix of #126
and the content of the conf file matched with the sample program


Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-31 10:06:22 +09:00
tomoaki
79f6aef8e4 BugFix: PINGREQ timeout of ClientProxy
reset PINGREQ timer of ClientProxy when QoS-1 PUBLISH is sent.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-31 06:35:20 +09:00
tomoaki
4932d2d0ee QoS-1 PUBLISH is available #34
BugFix of #69

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-30 21:00:01 +09:00
Tomoaki Yamaguchi
344c0e4e57 Merge pull request #125 from eclipse/develop
Forwarder Encapsulation are supported.
2018-07-29 06:29:42 +08:00
tomoaki
9940aadd4b Add The forwarder Encapsulation mesage #27 #69
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-28 23:05:16 +09:00
tomoaki
4d75351a06 BugFix of #123
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-24 07:19:39 +09:00
tomoaki
797ddf43f8 update test program
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-18 21:40:20 +09:00
tomoaki
521715e011 Bugfix of #122
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-18 21:32:46 +09:00
tomoaki
74a9ebaa55 BugFix of #121
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-18 21:03:03 +09:00
Tomoaki Yamaguchi
70b2c8cea8 Merge pull request #120 from eclipse/develop
Add Pre-defined-topic
2018-07-17 07:00:50 +09:00
tomoaki
a658bd5714 BugFix of Issue #119
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
add

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-17 05:48:45 +09:00
tomoaki
bb993aed5b Update: Add Pre-defined-Topic
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-07-14 19:20:48 +09:00
Tomoaki Yamaguchi
e2abc8783c Merge pull request #116 from eclipse/develop
Add two test programs.
2018-06-30 04:39:58 +09:00
tomoaki
9ae5c72125 Add: Two Gateway Test programs
BugFix: invalid pointer

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-06-29 15:27:24 +09:00
Tomoaki Yamaguchi
e734fccb38 Refactor: DISCONNECT prcedure
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-06-16 16:33:44 +09:00
Tomoaki Yamaguchi
29bebd14cb Merge pull request #114 from eclipse/develop
Update:  It's safer to use s6_addr32 macro than implementation specific union details.
2018-03-21 09:27:05 +09:00
Tomoaki Yamaguchi
9a0b4ca938 Merge pull request #113 from tieto/develop
Improve UDPv6 code portability
2018-03-20 22:57:50 +09:00
Mariusz Suchora
df13c052a8 Improve UDPv6 code portability
Signed-off-by: Mariusz Suchora <mariusz.suchora@tieto.com>
2018-03-19 14:04:45 +01:00
Tomoaki Yamaguchi
f2f4ed4630 Merge pull request #111 from eclipse/develop
BugFix of #105
2018-03-08 12:07:19 +09:00
Tomoaki Yamaguchi
dec00d0ee2 Merge pull request #110 from tieto/develop
BugFix of #105
2018-03-08 11:50:11 +09:00
Mariusz
e6a9fdca01 Subscribe to all topics with '#'
Signed-off-by: Mariusz <mariusz.suchora@tieto.com>
2018-03-06 10:55:40 +01:00
Ian Craggs
9414410cce Update contributing guidelines for ECA 2018-03-05 13:37:34 +00:00
Tomoaki Yamaguchi
c51b12e32b Merge pull request #109 from eclipse/develop
BugFix  of #107
2018-03-05 18:18:32 +09:00
tomoaki
a63125255d Update: Change Arrow shape of Log for packets from/to the Broker
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-03-05 17:18:13 +09:00
tomoaki
301814cc26 BugFix of #107
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2018-02-27 11:50:13 +09:00
Tomoaki Yamaguchi
b711472f91 Merge pull request #108 from eclipse/develop
Develop
2018-02-25 17:11:25 +09:00
Tomoaki Yamaguchi
e17c29978d Merge pull request #103 from tieto/develop
Gateway improvements
2018-02-24 09:25:50 +09:00
Mariusz Suchora
ef715ebfa7 Set pointer to client to 0 when client was erased
Signed-off-by: Mariusz Suchora <mariusz.suchora@tieto.com>
2018-02-23 10:40:06 +01:00
Mariusz Suchora
b6192d863b Fix handling PUBREC message received from client
Signed-off-by: Mariusz Suchora <mariusz.suchora@tieto.com>
2018-02-23 10:32:07 +01:00
Mariusz Suchora
bba3f1dede Fix topic name registration procedure started by GW when handling PUBLISH message
Signed-off-by: Mariusz Suchora <mariusz.suchora@tieto.com>
2018-02-23 10:30:45 +01:00
Mariusz Suchora
c49a040569 Preventing memory leaks
Signed-off-by: Mariusz Suchora <mariusz.suchora@tieto.com>
2018-02-23 10:29:36 +01:00
Mariusz Suchora
fbab6ee91f Fix unsubscribing from short topics (two octets length)
Signed-off-by: Mariusz Suchora <mariusz.suchora@tieto.com>
2018-02-23 10:24:52 +01:00
Mariusz Suchora
6dffa66bb0 Fix gateway crash when subscribing to short topics (two octets length)
Signed-off-by: Mariusz Suchora <mariusz.suchora@tieto.com>
2018-02-23 10:23:36 +01:00
Mariusz Suchora
1ef38fb7a0 Fix adding elements to WaitREGACKPacketList
Signed-off-by: Mariusz Suchora <mariusz.suchora@tieto.com>
2018-02-23 10:20:32 +01:00
Mariusz Suchora
594db623ee Lock critical section when adding new Client to list
Signed-off-by: Mariusz Suchora <mariusz.suchora@tieto.com>
2018-02-23 10:18:46 +01:00
Tomoaki Yamaguchi
9d221d7ad7 Merge pull request #97 from eclipse/develop
BugFix of #93
2017-12-21 23:16:22 +09:00
Tomoaki Yamaguchi
7945fa810a Merge pull request #95 from ty4tw/develop
BugFix of #93
2017-12-21 22:49:30 +09:00
tomoaki
23b358ad08 BugFix of #93
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-12-21 22:43:20 +09:00
Tomoaki Yamaguchi
946dc70826 Merge pull request #94 from ty4tw/develop
Bugfix of #91, #93
2017-12-20 16:36:42 +09:00
tomoaki
9540c748f5 Bugfix of #91, #93
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-12-20 16:13:09 +09:00
Tomoaki Yamaguchi
3d7a349998 Merge pull request #89 from ty4tw/develop
Update make codes simple #86
2017-09-28 22:41:25 +09:00
tomoaki
9d258cf53a Update: change codes simple #86
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-09-28 22:26:18 +09:00
tomoaki
8a2ac67b4f Update Makefile to add command line parameters
Parameters are additional include and lib directories for future useage.

e.g. make INCLUDE="-I/foo" LIB="-L/bar"

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-09-28 16:01:50 +09:00
Tomoaki Yamaguchi
1143a6a8ad Merge pull request #88 from ty4tw/develop
Bug Fix of Empty Client Id of CONNECT #86
2017-09-28 08:25:42 +09:00
tomoaki
6905e7aa1c Fix of warning: may be used uninitialized in this function
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-09-28 07:59:46 +09:00
tomoaki
4935d2aa86 BugFix of #86
Fix of warning: comparison between signed and unsigned integer
expressions 


Set a null string to the client ID when it of CONNECT is empty.

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-09-28 07:19:22 +09:00
Tomoaki Yamaguchi
bb1af2251b Merge pull request #85 from eclipse/develop
BugFix of #72 - #83
2017-09-13 06:27:08 +09:00
Tomoaki Yamaguchi
3ffe492c21 Merge pull request #84 from ty4tw/develop
Update Explanation of Multicast Address #83
2017-09-12 23:30:51 +09:00
tomoaki
98c1ebae50 Update Explanation of Multicast Address #83
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-09-12 23:26:53 +09:00
Tomoaki Yamaguchi
93a26b28c4 Merge pull request #82 from ty4tw/develop
Add OSX build check
2017-09-10 10:44:33 +09:00
tomoaki
6818202582 Add OSX build check
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-09-10 10:14:12 +09:00
tomoaki
b3b4a909b9 Add OSX compile setup
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-09-10 10:06:05 +09:00
tomoaki
1ca82ed97d Fix OSX compile error
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-09-10 08:34:56 +09:00
tomoaki
ca063cec9d Add comment to the GatewayTester
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-09-08 14:25:52 +09:00
Tomoaki Yamaguchi
c63583af83 Merge pull request #81 from ty4tw/develop
Bugfix of #80
2017-09-08 12:09:22 +09:00
tomoaki
e22d00046e Bugfix of #80
1. sleepy node problem
2. sender of PINGREQ in the log

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-09-08 11:24:39 +09:00
Tomoaki Yamaguchi
f92f11f87a Merge pull request #79 from ty4tw/develop
Update: forget to delete #define DEBUG
2017-08-27 17:03:20 +09:00
tomoaki
99ae7644e5 Update: forget to delete #define DEBUG
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-08-27 16:56:05 +09:00
Tomoaki Yamaguchi
88ecb2e11d Merge pull request #78 from ty4tw/develop
BugFix of #76 and #77
2017-08-27 16:45:56 +09:00
tomoaki
bc731210ae BugFix of #76 and #77
1.Return CONNACK instead of the broker when the gateway receives CONNECT
while the client is Sleep or Awake mode.

2.Define the max size of a que for PUBLISH while the client state is
Asleep mode.  Despose packets when the que is full of packets.

3.Return PUBACK or PUBREL to the broker when the client is Asleep or
Awake.


Signed-off-by: tomoaki <tomoaki@tomy-tech.com>



Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-08-27 16:39:29 +09:00
Tomoaki Yamaguchi
cc9029807b Merge pull request #75 from jciupis/pr/fix-ipv6-addr-scope-bug
Fix IPv6 address scope bug
2017-08-12 09:52:23 +09:00
Tomoaki Yamaguchi
3a8a616969 Merge pull request #74 from seko24/fix_min_message_len
Fixing issue #72: Setting minimum message length to 2.
2017-08-12 05:26:34 +09:00
Ciupis, Jedrzej
9c20f2f18d Fix IPv6 address scope bug
Signed-off-by: Ciupis, Jedrzej <jedrzej.ciupis@nordicsemi.no>
2017-08-10 14:32:00 +02:00
seko24
e12682056c Fixing issue #72: Setting minimum message length to 2.
Signed-off-by: seko24 <seb12@mailbox.org>
2017-08-09 09:35:38 +02:00
Tomoaki Yamaguchi
d5b70b19ce Merge pull request #71 from eclipse/develop
Bugfix of Gateway can't receive MQTT packets with no payload.
2017-07-30 09:10:29 +09:00
tomoaki
7099531e0e BugFix: MQTT packets wiith no payload can't be received collectly.
Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
2017-07-28 14:33:41 +09:00
162 changed files with 20340 additions and 7763 deletions

View File

@@ -14,30 +14,42 @@
</extensions> </extensions>
</storageModule> </storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0"> <storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.1685199227" name="Debug" parent="cdt.managedbuild.config.gnu.exe.debug"> <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.1685199227" name="Debug" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="cdt.managedbuild.config.gnu.exe.debug">
<folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1685199227." name="/" resourcePath=""> <folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1685199227." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.102264757" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug"> <toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.102264757" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.2137160061" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/> <targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.2137160061" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/>
<builder buildPath="${workspace_loc:/MQTTSN-embedded-C}/Debug" id="cdt.managedbuild.target.gnu.builder.exe.debug.767762182" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/> <builder buildPath="${workspace_loc:/MQTTSN-embedded-C}/Debug" id="cdt.managedbuild.target.gnu.builder.exe.debug.767762182" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.602829827" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> <tool id="cdt.managedbuild.tool.gnu.archiver.base.602829827" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.109068141" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug"> <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.109068141" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug">
<option id="gnu.cpp.compiler.exe.debug.option.optimization.level.1710260957" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/> <option id="gnu.cpp.compiler.exe.debug.option.optimization.level.1710260957" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
<option id="gnu.cpp.compiler.exe.debug.option.debugging.level.1258567310" name="Debug Level" superClass="gnu.cpp.compiler.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/> <option id="gnu.cpp.compiler.exe.debug.option.debugging.level.1258567310" name="Debug Level" superClass="gnu.cpp.compiler.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.default" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.dialect.std.1678347248" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.dialect.std.1678347248" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.c++11" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.dialect.flags.1711182709" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=c++11" valueType="string"/> <option id="gnu.cpp.compiler.option.dialect.flags.1711182709" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="" valueType="string"/>
<option id="gnu.cpp.compiler.option.include.paths.1361987608" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.1361987608" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNGateway/src"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src}&quot;"/>
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester/src"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/GatewayTester/src}&quot;"/>
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNGateway/src/linux"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux/dtls}&quot;"/>
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNPacket/src"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux}&quot;"/>
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNClient/src"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNPacket/src}&quot;"/>
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNGateway/src/linux/udp"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNClient/src}&quot;"/>
</option>
<option id="gnu.cpp.compiler.option.debugging.sanitleak.778932189" name="Sanitize memory leak (-fsanitize=leak)" superClass="gnu.cpp.compiler.option.debugging.sanitleak" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="gnu.cpp.compiler.option.debugging.sanitpointers.435146187" name="Sanitize pointer operations (-fsanitize=pointer-compare -fsanitize=pointer-subtract)" superClass="gnu.cpp.compiler.option.debugging.sanitpointers" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option id="gnu.cpp.compiler.option.debugging.sanitaddress.501742254" name="Sanitize address (-fsanitize=address)" superClass="gnu.cpp.compiler.option.debugging.sanitaddress" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.preprocessor.def.1354093543" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="DTLS"/>
</option> </option>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1626802967" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1626802967" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool> </tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2017162618" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug"> <tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2017162618" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug">
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.exe.debug.option.optimization.level.1941536725" name="Optimization Level" superClass="gnu.c.compiler.exe.debug.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/> <option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.exe.debug.option.optimization.level.1941536725" name="Optimization Level" superClass="gnu.c.compiler.exe.debug.option.optimization.level" useByScannerDiscovery="false" valueType="enumerated"/>
<option id="gnu.c.compiler.exe.debug.option.debugging.level.1668726974" name="Debug Level" superClass="gnu.c.compiler.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/> <option id="gnu.c.compiler.exe.debug.option.debugging.level.1668726974" name="Debug Level" superClass="gnu.c.compiler.exe.debug.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.max" valueType="enumerated"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.preprocessor.def.symbols.798283837" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="OPENSSL_API_COMPAT=30000"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.c.compiler.option.include.paths.1870583388" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux/dtls}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.814497727" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.814497727" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool> </tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1881440001" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug"> <tool id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1881440001" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug">
@@ -47,14 +59,16 @@
</inputType> </inputType>
</tool> </tool>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.581660133" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug"> <tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.581660133" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug">
<option id="gnu.cpp.link.option.libs.1848275182" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.1848275182" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="pthread"/> <listOptionValue builtIn="false" value="ssl"/>
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="ssl"/> <listOptionValue builtIn="false" value="crypto"/>
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="crypto"/> <listOptionValue builtIn="false" value="pthread"/>
<listOptionValue builtIn="false" value="bluetooth"/>
</option> </option>
<option id="gnu.cpp.link.option.paths.170974409" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.paths.170974409" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths">
<listOptionValue builtIn="false" value="/usr/local/lib"/> <listOptionValue builtIn="false" value="/usr/local/lib"/>
</option> </option>
<option id="gnu.cpp.link.option.shared.1648098307" name="Shared (-shared)" superClass="gnu.cpp.link.option.shared" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.98211496" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.98211496" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/> <additionalInput kind="additionalinput" paths="$(LIBS)"/>
@@ -66,7 +80,9 @@
</toolChain> </toolChain>
</folderInfo> </folderInfo>
<sourceEntries> <sourceEntries>
<entry excluding="MQTTSNGateway/src/linux/udp|MQTTSNGateway/src/tests|MQTTSNGateway/GatewayTester|MQTTSNGateway/GatewayTester/samples/mainTest.cpp|MQTTSNGateway/GatewayTester/samples/mainTemplate.cpp|MQTTSNGateway/src/tests/mainTestProcessFramework.cpp|MQTTSNGateway/GatewayTester/samples/mainOTA.cpp|MQTTSNGateway/src/mainLogmonitor.cpp|MQTTSNPacket/test|MQTTSNPacket/samples" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> <entry excluding="GatewayTester|src/linux/udp6|src/linux/udp|src/linux/dtls/SensorNetSubTask.cpp|GatewayTester/samples/ClientSub|GatewayTester/samples/ClientPubQoS-1|GatewayTester/samples/ClientPub|src/linux/rfcomm|src/tests|src/linux/xbee|src/mainLogmonitor.cpp|src/linux/loralink" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNGateway"/>
<entry excluding="mainTest.cpp|ClientSub|ClientPubQoS-1|ClientPub" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTSNGateway/GatewayTester/samples"/>
<entry excluding="samples|test" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNPacket"/>
</sourceEntries> </sourceEntries>
</configuration> </configuration>
</storageModule> </storageModule>
@@ -85,7 +101,7 @@
</extensions> </extensions>
</storageModule> </storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0"> <storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.561557339" name="Release" parent="cdt.managedbuild.config.gnu.exe.release"> <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.561557339" name="Release" optionalBuildProperties="" parent="cdt.managedbuild.config.gnu.exe.release">
<folderInfo id="cdt.managedbuild.config.gnu.exe.release.561557339." name="/" resourcePath=""> <folderInfo id="cdt.managedbuild.config.gnu.exe.release.561557339." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.474335535" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release"> <toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.474335535" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release">
<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.338327831" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/> <targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.338327831" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/>
@@ -95,12 +111,12 @@
<option id="gnu.cpp.compiler.exe.release.option.optimization.level.15425920" name="Optimization Level" superClass="gnu.cpp.compiler.exe.release.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/> <option id="gnu.cpp.compiler.exe.release.option.optimization.level.15425920" name="Optimization Level" superClass="gnu.cpp.compiler.exe.release.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
<option id="gnu.cpp.compiler.exe.release.option.debugging.level.857802503" name="Debug Level" superClass="gnu.cpp.compiler.exe.release.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> <option id="gnu.cpp.compiler.exe.release.option.debugging.level.857802503" name="Debug Level" superClass="gnu.cpp.compiler.exe.release.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
<option id="gnu.cpp.compiler.option.dialect.flags.1078302249" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=c++11" valueType="string"/> <option id="gnu.cpp.compiler.option.dialect.flags.1078302249" name="Other dialect flags" superClass="gnu.cpp.compiler.option.dialect.flags" useByScannerDiscovery="true" value="-std=c++11" valueType="string"/>
<option id="gnu.cpp.compiler.option.include.paths.2114194326" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.include.paths.2114194326" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNGateway/src/linux/udp"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux/udp}&quot;"/>
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester/src"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNPacket/src}&quot;"/>
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNGateway/src"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src/linux}&quot;"/>
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNGateway/src/linux"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/src}&quot;"/>
<listOptionValue builtIn="false" value="/home/tomoaki/git/paho.mqtt-sn.embedded-c/MQTTSNPacket/src"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/MQTTSNGateway/GatewayTester/src}&quot;"/>
</option> </option>
<option id="gnu.cpp.compiler.option.dialect.std.216116103" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.dialect.std.216116103" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1606625536" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1606625536" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
@@ -117,12 +133,12 @@
</inputType> </inputType>
</tool> </tool>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1623573602" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release"> <tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1623573602" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release">
<option id="gnu.cpp.link.option.libs.68366124" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.68366124" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="pthread"/> <listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="pthread"/>
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="ssl"/> <listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="ssl"/>
<listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="crypto"/> <listOptionValue builtIn="false" srcPrefixMapping="" srcRootPath="" value="crypto"/>
</option> </option>
<option id="gnu.cpp.link.option.paths.1879517971" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths"> <option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.paths.1879517971" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths">
<listOptionValue builtIn="false" value="/usr/local/lib"/> <listOptionValue builtIn="false" value="/usr/local/lib"/>
</option> </option>
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.2044523925" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input"> <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.2044523925" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
@@ -136,9 +152,9 @@
</toolChain> </toolChain>
</folderInfo> </folderInfo>
<sourceEntries> <sourceEntries>
<entry excluding="MQTTSNGateway/GatewayTester|MQTTSNGateway/GatewayTester/samples/mainTest.cpp|MQTTSNGateway/GatewayTester/samples/mainTemplate.cpp|MQTTSNGateway/GatewayTester/samples/mainOTA.cpp|MQTTSNPacket/src|MQTTSNGateway/src|MQTTSNGateway/src/linux|MQTTSNGateway/src/linux/udp|MQTTSNGateway/src/mainLogmonitor.cpp|MQTTSNGateway/src/linux/xbee|MQTTSNPacket/test|MQTTSNPacket/samples" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/> <entry excluding="MQTTSNPacket/test|MQTTSNPacket/samples|MQTTSNGateway/GatewayTester/samples/ClientPub|MQTTSNGateway/src/tests/mainTestProcess.cpp|MQTTSNGateway/src/linux|MQTTSNGateway|MQTTSNGateway/GatewayTester/samples/mainOTA.cpp|MQTTSNGateway/GatewayTester/samples/ClientSub|MQTTSNClient|MQTTSNGateway/src/mainLogmonitor.cpp|MQTTSNGateway/GatewayTester/samples/ClientPubQoS-1|MQTTSNGateway/GatewayTester/samples/mainTemplate.cpp|MQTTSNGateway/src|MQTTSNPacket/src|MQTTSNGateway/GatewayTester|ClientPubQoS-1" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/>
<entry excluding="tests|tests/mainTestProcessFramework.cpp|mainLogmonitor.cpp|linux|linux/udp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNGateway/src"/> <entry excluding="mainTest.cpp|ClientSub|ClientPubQoS-1|ClientPub" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTSNGateway/GatewayTester/samples"/>
<entry excluding="udp" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNGateway/src/linux"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="MQTTSNGateway/src"/>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNPacket/src"/> <entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="MQTTSNPacket/src"/>
</sourceEntries> </sourceEntries>
</configuration> </configuration>
@@ -151,28 +167,26 @@
</storageModule> </storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/> <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2"> <storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Debug"/>
<configuration configurationName="Release"> <configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/MQTTSN-embedded-C"/> <resource resourceType="PROJECT" workspacePath="/MQTTSN-embedded-C"/>
</configuration> </configuration>
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/MQTTSN-embedded-C"/>
</configuration>
</storageModule> </storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/> <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="scannerConfiguration"> <storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.561557339;cdt.managedbuild.config.gnu.exe.release.561557339.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1903732701;cdt.managedbuild.tool.gnu.cpp.compiler.input.1606625536">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1685199227;cdt.managedbuild.config.gnu.exe.debug.1685199227.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2017162618;cdt.managedbuild.tool.gnu.c.compiler.input.814497727">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1685199227;cdt.managedbuild.config.gnu.exe.debug.1685199227.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.109068141;cdt.managedbuild.tool.gnu.cpp.compiler.input.1626802967"> <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1685199227;cdt.managedbuild.config.gnu.exe.debug.1685199227.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.109068141;cdt.managedbuild.tool.gnu.cpp.compiler.input.1626802967">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo> </scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.561557339;cdt.managedbuild.config.gnu.exe.release.561557339.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.246546722;cdt.managedbuild.tool.gnu.c.compiler.input.456127079"> <scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.561557339;cdt.managedbuild.config.gnu.exe.release.561557339.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.246546722;cdt.managedbuild.tool.gnu.c.compiler.input.456127079">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo> </scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1685199227;cdt.managedbuild.config.gnu.exe.debug.1685199227.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.2017162618;cdt.managedbuild.tool.gnu.c.compiler.input.814497727">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.561557339;cdt.managedbuild.config.gnu.exe.release.561557339.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.1903732701;cdt.managedbuild.tool.gnu.cpp.compiler.input.1606625536">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule> </storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/> </cproject>
</cproject>

12
.gitignore vendored
View File

@@ -5,3 +5,15 @@
*.pyc *.pyc
/doc/MQTTSNClient/ /doc/MQTTSNClient/
/doc/MQTTSNPacket/ /doc/MQTTSNPacket/
rbmutex.key
ringbuffer.key
/Release/
/Debug/
/core
Build/
*.a
CMakeFiles/
*.cmake
CMakeCache.txt
bin/
/build.gateway/

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="cdt.managedbuild.config.gnu.exe.debug.1685199227" name="Debug">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-176156747064280842" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
<configuration id="cdt.managedbuild.config.gnu.exe.release.561557339" name="Release">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-176157551606184930" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
</extension>
</configuration>
</project>

View File

@@ -0,0 +1,77 @@
eclipse.preferences.version=1
fr.ac6.mcu.ide.source.checker.libnano.problem=Error
fr.ac6.mcu.ide.source.checker.libnano.problem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Float formatting support\\")"}
org.eclipse.cdt.codan.checkers.errnoreturn=Warning
org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false}
org.eclipse.cdt.codan.checkers.errreturnvalue=Error
org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"}
org.eclipse.cdt.codan.checkers.nocommentinside=-Error
org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"}
org.eclipse.cdt.codan.checkers.nolinecomment=-Error
org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"}
org.eclipse.cdt.codan.checkers.noreturn=Error
org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false}
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"}
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"}
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"}
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"}
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false}
org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"}
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true}
org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error
org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"}
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"}
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"}
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"}
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"}
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"}
org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"}
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"}
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"}
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"}
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"}
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false}
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false}
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true}
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true}
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")}
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"}
org.eclipse.cdt.qt.core.qtproblem=Warning
org.eclipse.cdt.qt.core.qtproblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_ON_FILE_OPEN\=>true,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>null}

View File

@@ -0,0 +1,2 @@
eclipse.preferences.version=1
formatter_settings_version=1

View File

@@ -1,30 +1,23 @@
language: cpp language: cpp
compiler: g++ compiler:
- g++
install: install:
- if ["$CXX" = "g++" ]; then export CXX="g++-4.8"; fi
addons: addons:
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- george-edison55-precise-backports # cmake 3.2.3 / doxygen 1.8.3
packages: packages:
- g++-4.8 - g++-4.8
- cmake - cmake
- cmake-data - cmake-data
- bluez
- libbluetooth-dev
script: script:
- ./travis-build.sh - ./travis-build.sh
- cd MQTTSNGateway
- make CXX="g++-4.8" SENSORNET="xbee"
- make CXX="g++-4.8" SENSORNET="udp"
- make CXX="g++-4.8" SENSORNET="udp6"
- make test
- cd GatewayTester
- make CXX="g++-4.8"
notifications: notifications:
emails: emails:

View File

@@ -14,7 +14,7 @@
# Ian Craggs - initial version # Ian Craggs - initial version
#*******************************************************************************/ #*******************************************************************************/
CMAKE_MINIMUM_REQUIRED(VERSION 2.8) CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
PROJECT("paho-mqttsn" CXX) PROJECT("paho-mqttsn" CXX)
MESSAGE(STATUS "CMake version: " ${CMAKE_VERSION}) MESSAGE(STATUS "CMake version: " ${CMAKE_VERSION})
MESSAGE(STATUS "CMake system name: " ${CMAKE_SYSTEM_NAME}) MESSAGE(STATUS "CMake system name: " ${CMAKE_SYSTEM_NAME})
@@ -39,3 +39,4 @@ INCLUDE(CPack)
ENABLE_TESTING() ENABLE_TESTING()
ADD_SUBDIRECTORY(MQTTSNPacket) ADD_SUBDIRECTORY(MQTTSNPacket)
ADD_SUBDIRECTORY(MQTTSNGateway)

94
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,94 @@
# Community Code of Conduct
**Version 2.0
January 1, 2023**
## Our Pledge
In the interest of fostering an open and welcoming environment, we as community members, contributors, Committers[^1], and Project Leads (collectively "Contributors") pledge to make participation in our projects and our community a harassment-free and inclusive experience for everyone.
This Community Code of Conduct ("Code") outlines our behavior expectations as members of our community in all Eclipse Foundation activities, both offline and online. It is not intended to govern scenarios or behaviors outside of the scope of Eclipse Foundation activities. Nor is it intended to replace or supersede the protections offered to all our community members under the law. Please follow both the spirit and letter of this Code and encourage other Contributors to follow these principles into our work. Failure to read or acknowledge this Code does not excuse a Contributor from compliance with the Code.
## Our Standards
Examples of behavior that contribute to creating a positive and professional environment include:
- Using welcoming and inclusive language;
- Actively encouraging all voices;
- Helping others bring their perspectives and listening actively. If you find yourself dominating a discussion, it is especially important to encourage other voices to join in;
- Being respectful of differing viewpoints and experiences;
- Gracefully accepting constructive criticism;
- Focusing on what is best for the community;
- Showing empathy towards other community members;
- Being direct but professional; and
- Leading by example by holding yourself and others accountable
Examples of unacceptable behavior by Contributors include:
- The use of sexualized language or imagery;
- Unwelcome sexual attention or advances;
- Trolling, insulting/derogatory comments, and personal or political attacks;
- Public or private harassment, repeated harassment;
- Publishing others' private information, such as a physical or electronic address, without explicit permission;
- Violent threats or language directed against another person;
- Sexist, racist, or otherwise discriminatory jokes and language;
- Posting sexually explicit or violent material;
- Sharing private content, such as emails sent privately or non-publicly, or unlogged forums such as IRC channel history;
- Personal insults, especially those using racist or sexist terms;
- Excessive or unnecessary profanity;
- Advocating for, or encouraging, any of the above behavior; and
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
With the support of the Eclipse Foundation employees, consultants, officers, and directors (collectively, the "Staff"), Committers, and Project Leads, the Eclipse Foundation Conduct Committee (the "Conduct Committee") is responsible for clarifying the standards of acceptable behavior. The Conduct Committee takes appropriate and fair corrective action in response to any instances of unacceptable behavior.
## Scope
This Code applies within all Project, Working Group, and Interest Group spaces and communication channels of the Eclipse Foundation (collectively, "Eclipse spaces"), within any Eclipse-organized event or meeting, and in public spaces when an individual is representing an Eclipse Foundation Project, Working Group, Interest Group, or their communities. Examples of representing a Project or community include posting via an official social media account, personal accounts, or acting as an appointed representative at an online or offline event. Representation of Projects, Working Groups, and Interest Groups may be further defined and clarified by Committers, Project Leads, or the Staff.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the Conduct Committee via conduct@eclipse-foundation.org. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Without the explicit consent of the reporter, the Conduct Committee is obligated to maintain confidentiality with regard to the reporter of an incident. The Conduct Committee is further obligated to ensure that the respondent is provided with sufficient information about the complaint to reply. If such details cannot be provided while maintaining confidentiality, the Conduct Committee will take the respondents inability to provide a defense into account in its deliberations and decisions. Further details of enforcement guidelines may be posted separately.
Staff, Committers and Project Leads have the right to report, remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code, or to block temporarily or permanently any Contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. Any such actions will be reported to the Conduct Committee for transparency and record keeping.
Any Staff (including officers and directors of the Eclipse Foundation), Committers, Project Leads, or Conduct Committee members who are the subject of a complaint to the Conduct Committee will be recused from the process of resolving any such complaint.
## Responsibility
The responsibility for administering this Code rests with the Conduct Committee, with oversight by the Executive Director and the Board of Directors. For additional information on the Conduct Committee and its process, please write to <conduct@eclipse-foundation.org>.
## Investigation of Potential Code Violations
All conflict is not bad as a healthy debate may sometimes be necessary to push us to do our best. It is, however, unacceptable to be disrespectful or offensive, or violate this Code. If you see someone engaging in objectionable behavior violating this Code, we encourage you to address the behavior directly with those involved. If for some reason, you are unable to resolve the matter or feel uncomfortable doing so, or if the behavior is threatening or harassing, please report it following the procedure laid out below.
Reports should be directed to <conduct@eclipse-foundation.org>. It is the Conduct Committees role to receive and address reported violations of this Code and to ensure a fair and speedy resolution.
The Eclipse Foundation takes all reports of potential Code violations seriously and is committed to confidentiality and a full investigation of all allegations. The identity of the reporter will be omitted from the details of the report supplied to the accused. Contributors who are being investigated for a potential Code violation will have an opportunity to be heard prior to any final determination. Those found to have violated the Code can seek reconsideration of the violation and disciplinary action decisions. Every effort will be made to have all matters disposed of within 60 days of the receipt of the complaint.
## Actions
Contributors who do not follow this Code in good faith may face temporary or permanent repercussions as determined by the Conduct Committee.
This Code does not address all conduct. It works in conjunction with our [Communication Channel Guidelines](https://www.eclipse.org/org/documents/communication-channel-guidelines/), [Social Media Guidelines](https://www.eclipse.org/org/documents/social_media_guidelines.php), [Bylaws](https://www.eclipse.org/org/documents/eclipse-foundation-be-bylaws-en.pdf), and [Internal Rules](https://www.eclipse.org/org/documents/ef-be-internal-rules.pdf) which set out additional protections for, and obligations of, all contributors. The Foundation has additional policies that provide further guidance on other matters.
Its impossible to spell out every possible scenario that might be deemed a violation of this Code. Instead, we rely on one anothers good judgment to uphold a high standard of integrity within all Eclipse Spaces. Sometimes, identifying the right thing to do isnt an easy call. In such a scenario, raise the issue as early as possible.
## No Retaliation
The Eclipse community relies upon and values the help of Contributors who identify potential problems that may need to be addressed within an Eclipse Space. Any retaliation against a Contributor who raises an issue honestly is a violation of this Code. That a Contributor has raised a concern honestly or participated in an investigation, cannot be the basis for any adverse action, including threats, harassment, or discrimination. If you work with someone who has raised a concern or provided information in an investigation, you should continue to treat the person with courtesy and respect. If you believe someone has retaliated against you, report the matter as described by this Code. Honest reporting does not mean that you have to be right when you raise a concern; you just have to believe that the information you are providing is accurate.
False reporting, especially when intended to retaliate or exclude, is itself a violation of this Code and will not be accepted or tolerated.
Everyone is encouraged to ask questions about this Code. Your feedback is welcome, and you will get a response within three business days. Write to <conduct@eclipse-foundation.org>.
## Amendments
The Eclipse Foundation Board of Directors may amend this Code from time to time and may vary the procedures it sets out where appropriate in a particular case.
### Attribution
This Code was inspired by the [Contributor Covenant](https://www.contributor-covenant.org/), version 1.4, available [here](https://www.contributor-covenant.org/version/1/4/code-of-conduct/).
[^1]: Capitalized terms used herein without definition shall have the meanings assigned to them in the Bylaws.

View File

@@ -10,12 +10,12 @@ In order for your contribution to be accepted, it must comply with the Eclipse F
Please read the [Eclipse Foundation policy on accepting contributions via Git](http://wiki.eclipse.org/Development_Resources/Contributing_via_Git). Please read the [Eclipse Foundation policy on accepting contributions via Git](http://wiki.eclipse.org/Development_Resources/Contributing_via_Git).
1. Sign the [Eclipse CLA](http://www.eclipse.org/legal/CLA.php) 1. Sign the [Eclipse ECA](http://www.eclipse.org/legal/ECA.php)
1. Register for an Eclipse Foundation User ID. You can register [here](https://dev.eclipse.org/site_login/createaccount.php). 1. Register for an Eclipse Foundation User ID. You can register [here](https://dev.eclipse.org/site_login/createaccount.php).
2. Log into the [Projects Portal](https://projects.eclipse.org/), and click on the '[Eclipse CLA](https://projects.eclipse.org/user/sign/cla)' link. 2. Log into the [Eclipse projects forge](https://www.eclipse.org/contribute/cla), and click on 'Eclipse Contributor Agreement'.
2. Go to your [account settings](https://dev.eclipse.org/site_login/myaccount.php#open_tab_accountsettings) and add your GitHub username to your account. 2. Go to your [account settings](https://dev.eclipse.org/site_login/myaccount.php#open_tab_accountsettings) and add your GitHub username to your account.
3. Make sure that you _sign-off_ your Git commits in the following format: 3. Make sure that you _sign-off_ your Git commits in the following format:
``` Signed-off-by: John Smith <johnsmith@nowhere.com> ``` This is usually at the bottom of the commit message. You can automate this by adding the '-s' flag when you make the commits. e.g. ```git commit -s -m "Adding a cool feature"``` ``` Signed-off-by: Alex Smith <alexsmith@nowhere.com> ``` This is usually at the bottom of the commit message. You can automate this by adding the '-s' flag when you make the commits. e.g. ```git commit -s -m "Adding a cool feature"```
4. Ensure that the email address that you make your commits with is the same one you used to sign up to the Eclipse Foundation website with. 4. Ensure that the email address that you make your commits with is the same one you used to sign up to the Eclipse Foundation website with.
## Contributing a change ## Contributing a change

13
LICENSE Normal file
View File

@@ -0,0 +1,13 @@
Eclipse Public License - v 2.0
This program and the accompanying materials
are made available under the terms of the Eclipse Public License v2.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
https://www.eclipse.org/legal/epl-2.0/
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
For an explanation of what dual-licensing means to you, see:
https://www.eclipse.org/legal/eplfaq.php#DUALLIC

View File

@@ -390,7 +390,7 @@ int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::readPacket(Timer& timer)
int lenlen = 0; int lenlen = 0;
int datalen = 0; int datalen = 0;
#define MQTTSN_MIN_PACKET_LENGTH 3 #define MQTTSN_MIN_PACKET_LENGTH 2
// 1. read the packet, datagram style // 1. read the packet, datagram style
if ((len = ipstack.read(readbuf, MAX_PACKET_SIZE, timer.left_ms())) < MQTTSN_MIN_PACKET_LENGTH) if ((len = ipstack.read(readbuf, MAX_PACKET_SIZE, timer.left_ms())) < MQTTSN_MIN_PACKET_LENGTH)
goto exit; goto exit;

View File

@@ -0,0 +1,16 @@
#*******************************************************************************
# Copyright (c) 2022 a1lu
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# and Eclipse Distribution License v1.0 which accompany this distribution.
#
# The Eclipse Public License is available at
# http://www.eclipse.org/legal/epl-v10.html
# and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# Contributors:
# a1lu - initial version
#*******************************************************************************/
ADD_SUBDIRECTORY(src)

Binary file not shown.

View File

@@ -1,15 +1,29 @@
PROGNAME := MQTT-SNGatewayTester PROGTEST := MQTT-SNGatewayTester
APPL := mainTest TESTAPPL := mainTest
PRGPUB := MQTT-SNPub
PUBAPPL := mainPub
PRGSUB := MQTT-SNSub
SUBAPPL := mainSub
PRGQOS := MQTT-SNPubQoS-1
QOSAPPL := mainPubQoS-1
SRCDIR := samples SRCDIR := samples
SRCPUB := ClientPub
SRCSUB := ClientSub
SRCQOS := ClientPubQoS-1
SUBDIR := src SUBDIR := src
CPPSRCS := \ CPPSRCS := \
$(SRCDIR)/$(APPL).cpp \
$(SUBDIR)/LGwProxy.cpp \ $(SUBDIR)/LGwProxy.cpp \
$(SUBDIR)/LMqttsnClient.cpp \ $(SUBDIR)/LMqttsnClient.cpp \
$(SUBDIR)/LNetworkUdp.cpp \ $(SUBDIR)/LNetworkUdp.cpp \
$(SUBDIR)/LNetworkUdp6.cpp \
$(SUBDIR)/LNetworkRfcomm.cpp \
$(SUBDIR)/LNetworkDtls.cpp \
$(SUBDIR)/LNetworkDtls6.cpp \
$(SUBDIR)/LPublishManager.cpp \ $(SUBDIR)/LPublishManager.cpp \
$(SUBDIR)/LRegisterManager.cpp \ $(SUBDIR)/LRegisterManager.cpp \
$(SUBDIR)/LSubscribeManager.cpp \ $(SUBDIR)/LSubscribeManager.cpp \
@@ -19,51 +33,78 @@ $(SUBDIR)/LTopicTable.cpp \
$(SUBDIR)/LScreen.cpp \ $(SUBDIR)/LScreen.cpp \
$(SUBDIR)/Payload.cpp \ $(SUBDIR)/Payload.cpp \
$(SUBDIR)/Util.cpp \ $(SUBDIR)/Util.cpp \
#$(SRCDIR)/$(TESTAPPL).cpp \
#$(SRCDIR)/$(SRCPUB)/$(PUBAPPL).cpp \
#$(SRCDIR)/$(SRCSUB)/$(SUBAPPL).cpp \
CXX := g++ CXX := g++
CPPFLAGS += CPPFLAGS +=
INCLUDES += -I$(SUBDIR) INCLUDES += -I$(SUBDIR) -I/usr/local/opt/openssl/include
DEFS := DEF1 :=
LIBS += DEF2 :=
DEFS := -D$(SN) $(DEF1) $(DEF2)
LIBS += -L/usr/local/lib -L/usr/local/opt/openssl/lib
LDFLAGS := LDFLAGS :=
CXXFLAGS := -Wall -O3 -std=c++11 CXXFLAGS := -Wall -O3 -std=c++11
LDADD := LDADD := -lssl -lcrypto $(LDADDBLT)
OUTDIR := Build OUTDIR := Build
PROG := $(OUTDIR)/$(PROGNAME) PROG := $(OUTDIR)/$(PROGTEST)
OBJS := $(CPPSRCS:%.cpp=$(OUTDIR)/%.o) OBJS := $(CPPSRCS:%.cpp=$(OUTDIR)/%.o)
DEPS := $(CPPSRCS:%.cpp=$(OUTDIR)/%.d) DEPS := $(CPPSRCS:%.cpp=$(OUTDIR)/%.d)
PROGPUB := $(OUTDIR)/$(PRGPUB)
PROGSUB := $(OUTDIR)/$(PRGSUB)
PROGQOS := $(OUTDIR)/$(PRGQOS)
.PHONY: install clean .PHONY: install clean
all: $(PROG) all: $(PROG) $(PROGPUB) $(PROGSUB) $(PROGQOS)
-include $(DEPS) -include $(DEPS)
$(PROG): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(APPL).o $(PROG): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(TESTAPPL).o
$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) $(LDADD) $(CXX) $(LDFLAGS) -o $(PROG) $(OUTDIR)/$(SRCDIR)/$(TESTAPPL).o $(OBJS) $(LIBS) $(LDADD)
$(PROGPUB): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(SRCPUB)/$(PUBAPPL).o
$(CXX) $(LDFLAGS) -o $(PROGPUB) $(OUTDIR)/$(SRCDIR)/$(SRCPUB)/$(PUBAPPL).o $(OBJS) $(LIBS) $(LDADD)
$(PROGSUB): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(SRCSUB)/$(SUBAPPL).o
$(CXX) $(LDFLAGS) -o $(PROGSUB) $(OUTDIR)/$(SRCDIR)/$(SRCSUB)/$(SUBAPPL).o $(OBJS) $(LIBS) $(LDADD)
$(PROGQOS): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(SRCQOS)/$(QOSAPPL).o
$(CXX) $(LDFLAGS) -o $(PROGQOS) $(OUTDIR)/$(SRCDIR)/$(SRCQOS)/$(QOSAPPL).o $(OBJS) $(LIBS) $(LDADD)
$(OUTDIR)/$(SUBDIR)/%.o:$(SUBDIR)/%.cpp $(OUTDIR)/$(SUBDIR)/%.o:$(SUBDIR)/%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< $(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/%.o:$(SRCDIR)/%.cpp $(OUTDIR)/$(SRCDIR)/%.o:$(SRCDIR)/%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi @if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $< $(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(SRCPUB)/%.o:$(SRCDIR)/$(SRCPUB)%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(SRCSUB)/%.o:$(SRCDIR)/$(SRCSUB)%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(SRCQOS)/%.o:$(SRCDIR)/$(SRCQOS)%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(DEFS) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
clean: clean:
rm -rf $(OUTDIR) rm -rf $(OUTDIR)
install: install:
cp -pf $(PROG) ../../../ cp -pf $(PROG) ../../../
cp -pf $(PROGPUB) ../../../
cp -pf $(PROGSUB) ../../../
cp -pf $(PROGQOS) ../../../

View File

@@ -1,119 +1,117 @@
###Gateway Test Program. # Gateway Test Program.
**sample/mainTest.cpp** is a Test sample coading. **sample/mainTest.cpp** is a Test sample coading.
Each test is described as one function. test1(), test2()... Each test is described as one function. test1(), test2()...
```` ```
/*------------------------------------------------------
* Test functions
*
* you can use 4 commands in Test functions
*
* 1) PUBLISH(const char* topicName,
* uint8_t* payload,
* uint16_t len,
* uint8_t qos,
* bool retain = false);
*
* 2) SUBSCRIBE(const char* topicName,
* TopicCallback onPublish,
* uint8_t qos);
*
* 3) UNSUBSCRIBE(const char* topicName);
*
* 4) DISCONNECT(uint16_t sleepInSecs);
*
*------------------------------------------------------*/
void test1(void) void test1(void)
{ {
char payload[300]; char payload[300];
sprintf(payload, "ESP8266-08b133 "); sprintf(payload, "ESP8266-08b133 ");
uint8_t qos = 0; uint8_t qos = 0;
PUBLISH(topic1,(uint8_t*)payload, strlen(payload), qos); PUBLISH(topic1,(uint8_t*)payload, strlen(payload), qos);
} }
void test2(void) void test2(void)
{ {
uint8_t qos = 1; uint8_t qos = 1;
SUBSCRIBE(topic2, on_publish02, qos); SUBSCRIBE(topic2, on_publish02, qos);
} }
````
**TEST_LIST** is a test senario. Test functions are executed one by one. *---------------------------------------------------------------------------
```` *
* MQTT-SN GATEWAY TEST CLIENT
*
* Supported functions.
*
* void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos );
*
* void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
*
* void UNSUBSCRIBE ( const char* topicName );
*
* void UNSUBSCRIBE ( uint16_t topicId );
*
* void DISCONNECT ( uint16_t sleepInSecs );
*
* void CONNECT ( void );
*
* void DISPLAY( format, .....); <== instead of printf()
*--------------------------------------------------------------------------
```
**TEST_LIST** is a test senario. Test functions are executed interactively.
```
/*------------------------------------------------------ /*------------------------------------------------------
* A List of Test Tasks * A List of Test Tasks
*------------------------------------------------------*/ *------------------------------------------------------*/
TEST_LIST = {// e.g. TEST( Label, Test), TEST_LIST = {// e.g. TEST( Label, Test),
TEST("Publish topic1", test1), TEST("Publish topic1", test1),
TEST("Subscribe topic2", test2), TEST("Subscribe topic2", test2),
TEST("Publish topic2", test3), TEST("Publish topic2", test3),
TEST("Unsubscribe topic2", test4), TEST("Unsubscribe topic2", test4),
TEST("Publish topic2", test3), TEST("Publish topic2", test3),
TEST("Disconnect", test5), TEST("Disconnect", test5),
END_OF_TEST_LIST END_OF_TEST_LIST
}; };
````
```
### **step1. Build ** **UDP**, **DTLS**, **UDP6**, **DTLS6** or **Bluetooth** is available as a sensor network.
```` ```
$ git clone https://github.com/eclipse/paho.mqtt-sn.embedded-c /*------------------------------------------------------
* UDP, DTLS Configuration (theNetcon)
*------------------------------------------------------*/
UDPCONF = { "GatewayTestClient", // ClientId
{ 225, 1, 1, 1 }, // Multicast group IP
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* UDP6, DTLS6 Configuration (theNetcon)
*------------------------------------------------------*/
UDP6CONF = { "GatewayTestClient", // ClientId
"ff12::feed:caca:dead", // Multicast group IP
"wlp4s0",
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/
RFCOMMCONF = { "GatewayTestClient", // ClientId
"60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel
};
```
## How to Build
```
copy codes from the github.
$ cd paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester $ cd paho.mqtt-sn.embedded-c/MQTTSNGateway/GatewayTester
$ make $ ./build.sh [udp | udp6 | dtls | dtls6 | rfcomm]
$ make install
$ make clean
``` ```
MQTT-SNGatewayTester program is copied into ../../../ directory.
### **step2. Execute Gateway Tester.** ## Execute Gateway Tester
```
```` $ ./Build/MQTT-SNGatewayTester
$ cd ../../..
$ ./MQTT-SNGatewayTester
*************************************************************************** ***************************************************************************
* MQTT-SN Gateway Tester * MQTT-SN Gateway Tester DTLS
* Part of Project Paho in Eclipse * Part of Project Paho in Eclipse
* (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/) * (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/)
* *
* Author : Tomoaki YAMAGUCHI * Author : Tomoaki YAMAGUCHI
* Version: 0.0.0 * Version: 2.0.0
*************************************************************************** ***************************************************************************
Attempting to Connect the Broker..... Attempting to Connect the Broker.....
Execute "Step0:Connect" ? ( y/n ) :
sendto 225.1.1.1 :1883 03 01 00 ```
recved 192.168.11.5 :1883 03 01 00
sendto 225.1.1.1 :1883 03 01 00
recved 192.168.11.5 :1883 03 01 00
recved 192.168.11.17 :10000 03 02 01
sendto 192.168.11.17 :10000 13 04 0c 01 03 84 47 61 74 65 77 61 79 54 65 73 74 65 72
recved 192.168.11.17 :10000 02 06
sendto 192.168.11.17 :10000 0c 07 00 77 69 6c 6c 54 6f 70 69 63
recved 192.168.11.17 :10000 02 08
sendto 192.168.11.17 :10000 0d 09 77 69 6c 6c 4d 65 73 73 61 67 65
recved 192.168.11.17 :10000 03 05 00
Connected to the Broker
Attempting OnConnect.....
sendto 192.168.11.17 :10000 13 12 20 00 01 74 79 34 74 77 2f 63 6c 69 65 6e 74 49 64
recved 192.168.11.17 :10000 08 13 20 00 01 00 01 00
SUBSCRIBE complete. ty4tw/clientId
OnConnect complete
Test Ready.
Execute Publish topic1 Test ? ( Y/N ) :
````

View File

@@ -0,0 +1,23 @@
#!/bin/bash
DEF1="DEF1=${2}"
DEF2="DEF2=${3}"
if [ $1 == "udp" ] ; then
make SN=UDP $DEF1 $DEF2
elif [ $1 == "udp6" ] ; then
make SN=UDP6 $DEF1 $DEF2
elif [ $1 == "rfcomm" ] ; then
export LDADDBLT=-lbluetooth
make SN=RFCOMM $DEF1 $DEF2
elif [ $1 == "dtls" ] ; then
make SN=DTLS $DEF1 $DEF2
elif [ $1 == "dtls6" ] ; then
make SN=DTLS6 $DEF1 $DEF2
elif [ $1 == "clean" ] ; then
make clean
else
echo "Usage: build.sh [ udp | udp6 | rfcomm | dtls | dtls6 | clean]"
fi

View File

@@ -0,0 +1,183 @@
/****************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
*---------------------------------------------------------------------------
*
* MQTT-SN GATEWAY TEST CLIENT
*
* Supported functions.
*
* void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos );
*
* void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
*
* void UNSUBSCRIBE ( const char* topicName );
*
* void UNSUBSCRIBE ( uint16_t topicId );
*
* void DISCONNECT ( uint16_t sleepInSecs );
*
* void CONNECT ( void );
*
* void DISPLAY( format, .....); <== instead of printf()
*
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation
***************************************************************************/
#include "LMqttsnClientApp.h"
#include "LMqttsnClient.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern LMqttsnClient* theClient;
extern LScreen* theScreen;
/*------------------------------------------------------
* UDP Configuration (theNetcon)
*------------------------------------------------------*/
UDPCONF = { "ClientPUB", // ClientId
{ 225, 1, 1, 1 }, // Multicast group IP
1883, // Multicast group Port
20010, // Local PortNo
};
/*------------------------------------------------------
* UDP6 Configuration (theNetcon)
*------------------------------------------------------*/
UDP6CONF = { "ClientPUB", // ClientId
"ff1e:feed:caca:dead::1", // Multicast group IP
"wlp4s0", // Network Interface
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/
RFCOMMCONF = { "ClientPUB", // ClientId
"60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel
};
/*------------------------------------------------------
* Client Configuration (theMqcon)
*------------------------------------------------------*/
MQTTSNCONF = {
300, //KeepAlive [seconds]
true, //Clean session
300, //Sleep duration [seconds]
"", //WillTopic
"", //WillMessage
0, //WillQos
false //WillRetain
};
/*------------------------------------------------------
* Define Topics
*------------------------------------------------------*/
const char* topic1 = "ty4tw/topic1";
const char* topic2 = "ty4tw/topic2";
const char* topic3 = "ty4tw/topic3";
const char* topic57 = "ty4tw/topic5/7";
/*------------------------------------------------------
* Callback routines for Subscribed Topics
*------------------------------------------------------*/
/*------------------------------------------------------
* A Link list of Callback routines and Topics
*------------------------------------------------------*/
SUBSCRIBE_LIST = {// e.g. SUB(topic, callback, QoS),
END_OF_SUBSCRIBE_LIST
};
/*------------------------------------------------------
* Test functions
*------------------------------------------------------*/
void publishTopic1(void)
{
char payload[300];
sprintf(payload, "publish \"ty4tw/Topic1\" \n");
uint8_t qos = 0;
PUBLISH(topic1,(uint8_t*)payload, strlen(payload), qos);
}
void publishTopic2(void)
{
char payload[300];
sprintf(payload, "publish \"ty4tw/topic2\" \n");
uint8_t qos = 0;
PUBLISH(topic2,(uint8_t*)payload, strlen(payload), qos);
}
void publishTopic57(void)
{
char payload[300];
sprintf(payload, "publish \"ty4tw/topic57\" \n");
uint8_t qos = 0;
PUBLISH(topic57, (uint8_t* )payload, strlen(payload), qos);
}
void disconnect(void)
{
DISCONNECT(0);
}
/*------------------------------------------------------
* A List of Test functions is valid in case of
* line 23 of LMqttsnClientApp.h is commented out.
* //#define CLIENT_MODE
*------------------------------------------------------*/
TEST_LIST = {// e.g. TEST( Label, Test),
TEST("Step1:Publish topic1", publishTopic1),
TEST("Step2:Publish topic57", publishTopic57),
TEST("Step3:Publish topic2", publishTopic2),
TEST("Step4:Disconnect", disconnect),
END_OF_TEST_LIST
};
/*------------------------------------------------------
* List of tasks is valid in case of line23 of
* LMqttsnClientApp.h is uncommented.
* #define CLIENT_MODE
*------------------------------------------------------*/
TASK_LIST = {// e.g. TASK( task, executing duration in second),
TASK(publishTopic1, 4), // publishTopic1() is executed every 4 seconds
TASK(publishTopic2, 7), // publishTopic2() is executed every 7 seconds
END_OF_TASK_LIST
};
/*------------------------------------------------------
* Initialize function
*------------------------------------------------------*/
void setup(void)
{
SetForwarderMode(false);
}
/***************** END OF PROGRAM ********************/

View File

@@ -0,0 +1,178 @@
/****************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
*---------------------------------------------------------------------------
*
* MQTT-SN GATEWAY TEST CLIENT
*
* Supported functions.
*
* void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos );
*
* void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
*
* void UNSUBSCRIBE ( const char* topicName );
*
* void UNSUBSCRIBE ( uint16_t topicId );
*
* void DISCONNECT ( uint16_t sleepInSecs );
*
* void CONNECT ( void );
*
* void DISPLAY( format, .....); <== instead of printf()
*
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation
***************************************************************************/
#include "LMqttsnClientApp.h"
#include "LMqttsnClient.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern LMqttsnClient* theClient;
extern LScreen* theScreen;
/*------------------------------------------------------
* UDP Configuration (theNetcon)
*------------------------------------------------------*/
UDPCONF = { "QoS-1_Client01", // ClientId
{ 225, 1, 1, 1 }, // Multicast group IP
1883, // Multicast group Port
20001, // Local PortNo
};
/*------------------------------------------------------
* UDP6 Configuration (theNetcon)
*------------------------------------------------------*/
UDP6CONF = { "QoS-1_Client01", // ClientId
"ff1e:feed:caca:dead::1", // Multicast group IP
"wlp4s0", // Network Interface
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/
RFCOMMCONF = { "QoS-1_Client01", // ClientId
"60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel
};
/*------------------------------------------------------
* Client Configuration (theMqcon)
*------------------------------------------------------*/
MQTTSNCONF = {
300, //KeepAlive [seconds]
true, //Clean session
300, //Sleep duration [seconds]
"", //WillTopic
"", //WillMessage
0, //WillQos
false //WillRetain
};
/*------------------------------------------------------
* Define Topics
*------------------------------------------------------*/
/*------------------------------------------------------
* Callback routines for Subscribed Topics
*------------------------------------------------------*/
/*------------------------------------------------------
* A Link list of Callback routines and Topics
*------------------------------------------------------*/
SUBSCRIBE_LIST = {// e.g. SUB(TopicType, topicName, TopicId, callback, QoSx),
END_OF_SUBSCRIBE_LIST
};
/*------------------------------------------------------
* Test functions
*------------------------------------------------------*/
void publishTopic1(void)
{
char payload[300];
sprintf(payload, "publish \"ty4tw/Topic1\" \n");
uint8_t qos = 3;
PUBLISH(1,(uint8_t*)payload, strlen(payload), qos);
}
void publishTopic2(void)
{
char payload[300];
sprintf(payload, "publish \"ty4tw/topic2\" \n");
uint8_t qos = 3;
PUBLISH(2,(uint8_t*)payload, strlen(payload), qos);
}
void publishTopic57(void)
{
char payload[300];
sprintf(payload, "publish \"ty4tw/topic57\" \n");
uint8_t qos = 3;
PUBLISH(5,(uint8_t*)payload, strlen(payload), qos);
}
void disconnect(void)
{
DISCONNECT(0);
}
/*------------------------------------------------------
* A List of Test functions is valid in case of
* line 23 of LMqttsnClientApp.h is commented out.
* //#define CLIENT_MODE
*------------------------------------------------------*/
TEST_LIST = {// e.g. TEST( Label, Test),
TEST("Step1:Publish topic1", publishTopic1),
TEST("Step2:Publish topic57", publishTopic57),
TEST("Step3:Publish topic2", publishTopic2),
END_OF_TEST_LIST
};
/*------------------------------------------------------
* List of tasks is invalid in case of line23 of
* LMqttsnClientApp.h is commented out.
* #define CLIENT_MODE
*------------------------------------------------------*/
TASK_LIST = {// e.g. TASK( task, executing duration in second),
TASK(publishTopic1, 4), // publishTopic1() is executed every 4 seconds
TASK(publishTopic2, 7), // publishTopic2() is executed every 7 seconds
END_OF_TASK_LIST
};
/*------------------------------------------------------
* Initialize function
*------------------------------------------------------*/
void setup(void)
{
SetQoSMinus1Mode(true);
}
/***************** END OF PROGRAM ********************/

View File

@@ -0,0 +1,224 @@
/****************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
*---------------------------------------------------------------------------
*
* MQTT-SN GATEWAY TEST CLIENT
*
* Supported functions.
*
* void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos );
*
* void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
*
* void UNSUBSCRIBE ( const char* topicName );
*
* void UNSUBSCRIBE ( uint16_t topicId );
*
* void DISCONNECT ( uint16_t sleepInSecs );
*
* void CONNECT ( void );
*
* void DISPLAY( format, .....); <== instead of printf()
*
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation
***************************************************************************/
#include "LMqttsnClientApp.h"
#include "LMqttsnClient.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern LMqttsnClient* theClient;
extern LScreen* theScreen;
/*------------------------------------------------------
* UDP Configuration (theNetcon)
*------------------------------------------------------*/
UDPCONF = { "ClientSUB", // ClientId
{ 225, 1, 1, 1 }, // Multicast group IP
1883, // Multicast group Port
20011, // Local PortNo
};
/*------------------------------------------------------
* UDP6 Configuration (theNetcon)
*------------------------------------------------------*/
UDP6CONF = { "ClientSUB", // ClientId
"ff1e:feed:caca:dead::1", // Multicast group IP
"wlp4s0", // Network Interface
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/
RFCOMMCONF = { "ClientSUB", // ClientId
"60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel
};
/*------------------------------------------------------
* Client Configuration (theMqcon)
*------------------------------------------------------*/
MQTTSNCONF = {
60, //KeepAlive [seconds]
true, //Clean session
300, //Sleep duration [seconds]
"", //WillTopic
"", //WillMessage
0, //WillQos
false //WillRetain
};
/*------------------------------------------------------
* Define Topics
*------------------------------------------------------*/
const char* topic1 = "ty4tw/topic1";
const char* topic2 = "ty4tw/topic2";
const char* topic3 = "ty4tw/topic3";
const char* topic4 = "a";
const char* topic5 = "ty4tw/#";
/*------------------------------------------------------
* Callback routines for Subscribed Topics
*------------------------------------------------------*/
int on_Topic01(uint8_t* pload, uint16_t ploadlen)
{
DISPLAY("\n\nTopic1 recv.\n");
char c = pload[ploadlen-1];
pload[ploadlen-1]= 0; // set null terminator
DISPLAY("Payload -->%s%c<--\n\n",pload, c);
return 0;
}
int on_Topic02(uint8_t* pload, uint16_t ploadlen)
{
DISPLAY("\n\nTopic2 recv.\n");
pload[ploadlen-1]= 0; // set null terminator
DISPLAY("Payload -->%s <--\n\n",pload);
return 0;
}
int on_Topic03(uint8_t* pload, uint16_t ploadlen)
{
DISPLAY("\n\nNew callback recv TopicA\n");
pload[ploadlen-1]= 0; // set null terminator
DISPLAY("Payload -->%s <--\n\n",pload);
return 0;
}
int on_Topic05(uint8_t* pload, uint16_t ploadlen)
{
DISPLAY("\n\nNew callback recv TopicA\n");
pload[ploadlen-1]= 0; // set null terminator
DISPLAY("Payload -->%s <--\n\n",pload);
return 0;
}
/*------------------------------------------------------
* A Link list of Callback routines and Topics
*------------------------------------------------------*/
SUBSCRIBE_LIST = {// e.g. SUB(TopicType, topicName, TopicId, callback, QoSx),
// SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic5, 0, on_Topic05, QoS1),
//SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic2, 0, on_Topic02, QoS1),
END_OF_SUBSCRIBE_LIST
};
/*------------------------------------------------------
* Test functions
*------------------------------------------------------*/
void subscribeTopic1(void)
{
uint8_t qos = 1;
SUBSCRIBE(topic1, on_Topic01, qos);
}
void subscribeTopic2(void)
{
uint8_t qos = 1;
SUBSCRIBE(topic2, on_Topic02, qos);
}
void subscribeTopic5(void)
{
uint8_t qos = 1;
SUBSCRIBE(topic5, on_Topic05, qos);
}
void disconnect(void)
{
DISCONNECT(0);
}
void connect(void)
{
CONNECT();
}
void asleep(void)
{
DISCONNECT(theMqcon.sleepDuration);
}
/*------------------------------------------------------
* A List of Test functions is valid in case of
* line 23 of LMqttsnClientApp.h is commented out.
* //#define CLIENT_MODE
*------------------------------------------------------*/
TEST_LIST = {// e.g. TEST( Label, Test),
TEST("Step1:Subscribe topic5", subscribeTopic5),
//TEST("Step2:Subscribe topic2", subscribeTopic2),
TEST("Step2:Disconnect", asleep),
TEST("Step3:Cconnect", connect),
TEST("Step4:Disconnect", asleep),
END_OF_TEST_LIST
};
/*------------------------------------------------------
* List of tasks is valid in case of line23 of
* LMqttsnClientApp.h is uncommented.
* #define CLIENT_MODE
*------------------------------------------------------*/
TASK_LIST = {// e.g. TASK( task, executing duration in second),
END_OF_TASK_LIST
};
/*------------------------------------------------------
* Initialize function
*------------------------------------------------------*/
void setup(void)
{
SetForwarderMode(false);
}
/***************** END OF PROGRAM ********************/

View File

@@ -1,162 +0,0 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation
**************************************************************************************/
#include "LMqttsnClientApp.h"
#include "LMqttsnClient.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern LMqttsnClient* theClient;
extern LScreen* theScreen;
extern int run(void);
/*
* MQTT-SN Functions supported :
*
* void PUBLISH ( const char* topicName, uint8_t* payload,
* uint16_t len, uint8_t qos, bool retain = false );
*
* void PUBLISH ( uint16_t topicId, uint8_t* payload,
* uint16_t len, uint8_t qos, bool retain = false );
*
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish,
* uint8_t qos );
*
* void UNSUBSCRIBE( const char* topicName );
*
* void DISCONNECT ( uint16_t sleepInSecs );
*
* void DISPLAY( format, valiables, .....); <== instead of printf()
*
*/
/*------------------------------------------------------
* UDP Configuration
*------------------------------------------------------*/
UDPCONF = {
"GatewayTester", // ClientId
{225,1,1,1}, // Multicast group IP
1883, // Multicast group Port
20000, // Local PortNo
};
/*------------------------------------------------------
* Client Configuration
*------------------------------------------------------*/
MQTTSNCONF = {
60, //KeepAlive (seconds)
true, //Clean session
0, //Sleep duration in msecs
"willTopic", //WillTopic
"willMessage", //WillMessage
0, //WillQos
false //WillRetain
};
/*------------------------------------------------------
* Define Topics
*------------------------------------------------------*/
const char* topic1 = "ty4tw/clientId";
/*------------------------------------------------------
* Callback routines for Subscribed Topics
*------------------------------------------------------*/
int on_publish01(uint8_t* pload, uint16_t ploadlen)
{
return 0;
}
/*------------------------------------------------------
* A Link list of Callback routines and Topics
*------------------------------------------------------*/
SUBSCRIBE_LIST = {// e.g. SUB(topic, callback, QoS),
//SUB(topic1, on_publish01, 1),
END_OF_SUBSCRIBE_LIST
};
/*------------------------------------------------------
* Test functions
*------------------------------------------------------*/
void test1(void)
{
char payload[300];
sprintf(payload, "Client-01 ");
uint8_t qos = 0;
PUBLISH(topic1,(uint8_t*)payload, strlen(payload), qos);
}
void test2(void)
{
}
void test3(void)
{
}
void test4(void)
{
}
void test5(void)
{
}
/*------------------------------------------------------
* A List of Test functions
*------------------------------------------------------*/
TEST_LIST = {// e.g. TEST( Label, Test),
TEST("Publish topic1", test1),
END_OF_TEST_LIST
};
/*------------------------------------------------------
* unused for Test
*------------------------------------------------------*/
TASK_LIST = {// e.g. TASK( task, executing duration in second),
TASK(test1, 4),
END_OF_TASK_LIST
};
/*------------------------------------------------------
* Initialize function
*------------------------------------------------------*/
void setup(void)
{
}
/*======================================================
* main
*======================================================*/
/* uncomment this
int main(int argc, char** argv)
{
return run();
}
*/

View File

@@ -1,4 +1,4 @@
/************************************************************************************** /****************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi * Copyright (c) 2016, Tomoaki Yamaguchi
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
@@ -10,9 +10,34 @@
* and the Eclipse Distribution License is available at * and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php. * http://www.eclipse.org/org/documents/edl-v10.php.
* *
*---------------------------------------------------------------------------
*
* MQTT-SN GATEWAY TEST CLIENT
*
* Supported functions.
*
* void PUBLISH ( const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void PUBLISH ( uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false );
*
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish, uint8_t qos );
*
* void SUBSCRIBE ( uint16_t topicId, TopicCallback onPublish, uint8_t qos );
*
* void UNSUBSCRIBE ( const char* topicName );
*
* void UNSUBSCRIBE ( uint16_t topicId );
*
* void DISCONNECT ( uint16_t sleepInSecs );
*
* void CONNECT ( void );
*
* void DISPLAY( format, .....); <== instead of printf()
*
*
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation * Tomoaki Yamaguchi - initial API and implementation
**************************************************************************************/ ***************************************************************************/
#include "LMqttsnClientApp.h" #include "LMqttsnClientApp.h"
#include "LMqttsnClient.h" #include "LMqttsnClient.h"
@@ -22,49 +47,45 @@ using namespace std;
using namespace linuxAsyncClient; using namespace linuxAsyncClient;
extern LMqttsnClient* theClient; extern LMqttsnClient* theClient;
extern LScreen* theScreen; extern LScreen* theScreen;
extern int run(void);
/*
* Functions supported.
*
* void PUBLISH ( const char* topicName, uint8_t* payload,
* uint16_t len, uint8_t qos, bool retain = false );
*
* void PUBLISH ( uint16_t topicId, uint8_t* payload,
* uint16_t len, uint8_t qos, bool retain = false );
*
* void SUBSCRIBE ( const char* topicName, TopicCallback onPublish,
* uint8_t qos );
*
* void UNSUBSCRIBE( const char* topicName );
*
* void DISCONNECT ( uint16_t sleepInSecs );
*
* void DISPLAY( format, .....); <== instead of printf()
*
*/
/*------------------------------------------------------
* UDP Configuration
*------------------------------------------------------*/
UDPCONF = {
"GatewayTester", // ClientId
{225,1,1,1}, // Multicast group IP
1883, // Multicast group Port
20001, // Local PortNo
};
/*------------------------------------------------------ /*------------------------------------------------------
* Client Configuration * UDP,DTLS Configuration (theNetcon)
*------------------------------------------------------*/ *------------------------------------------------------*/
MQTTSNCONF = { UDPCONF = { "GatewayTestClient", // ClientId
300, //KeepAlive (seconds) { 225, 1, 1, 1 }, // Multicast group IP
true, //Clean session 1883, // Multicast group Port
0, //Sleep duration in msecs 20020, // Local PortNo
"willTopic", //WillTopic };
"willMessage", //WillMessage
0, //WillQos /*------------------------------------------------------
false //WillRetain * UDP6, DTLS6 Configuration (theNetcon)
}; *------------------------------------------------------*/
UDP6CONF = { "GatewayTestClient", // ClientId
"ff1e:feed:caca:dead::1", // Multicast group IP
"wlp4s0", // Network Interface
1883, // Multicast group Port
20020, // Local PortNo
};
/*------------------------------------------------------
* RFCOMM Configuration (theNetcon)
*------------------------------------------------------*/
RFCOMMCONF = { "GatewayTestClient", // ClientId
"60:57:18:06:8B:72", // GW Address
1, // Rfcomm channel
};
/*------------------------------------------------------
* Client Configuration (theMqcon)
*------------------------------------------------------*/
MQTTSNCONF = { 60, //KeepAlive [seconds]
true, //Clean session
300, //Sleep duration [seconds]
"", //WillTopic
"", //WillMessage
0, //WillQos
false //WillRetain
};
/*------------------------------------------------------ /*------------------------------------------------------
* Define Topics * Define Topics
@@ -72,7 +93,12 @@ MQTTSNCONF = {
const char* topic1 = "ty4tw/topic1"; const char* topic1 = "ty4tw/topic1";
const char* topic2 = "ty4tw/topic2"; const char* topic2 = "ty4tw/topic2";
const char* topic3 = "ty4tw/topic3"; const char* topic3 = "ty4tw/topic3";
const char* topic4 = "ty4tw/topic4";
const char* topic40 = "ty4tw/#";
const char* topic51 = "ty4tw/topic5/1";
const char* topic52 = "ty4tw/topic5/2";
const char* topic53 = "ty4tw/topic5/3";
const char* topic50 = "ty4tw/topic5/+";
/*------------------------------------------------------ /*------------------------------------------------------
* Callback routines for Subscribed Topics * Callback routines for Subscribed Topics
@@ -80,25 +106,33 @@ const char* topic3 = "ty4tw/topic3";
int on_Topic01(uint8_t* pload, uint16_t ploadlen) int on_Topic01(uint8_t* pload, uint16_t ploadlen)
{ {
DISPLAY("\n\nTopic1 recv.\n"); DISPLAY("\n\nTopic1 recv.\n");
char c = pload[ploadlen-1]; char c = pload[ploadlen - 1];
pload[ploadlen-1]= 0; // set null terminator pload[ploadlen - 1] = 0; // set null terminator
DISPLAY("Payload -->%s%c<--\n\n",pload, c); DISPLAY("Payload -->%s%c<--\n\n", pload, c);
return 0; return 0;
} }
int on_Topic02(uint8_t* pload, uint16_t ploadlen) int on_Topic02(uint8_t* pload, uint16_t ploadlen)
{ {
DISPLAY("\n\nTopic2 recv.\n"); DISPLAY("\n\nTopic2 recv.\n");
pload[ploadlen-1]= 0; // set null terminator pload[ploadlen - 1] = 0; // set null terminator
DISPLAY("Payload -->%s <--\n\n",pload); DISPLAY("Payload -->%s <--\n\n", pload);
return 0; return 0;
} }
int on_Topic03(uint8_t* pload, uint16_t ploadlen) int on_Topic03(uint8_t* pload, uint16_t ploadlen)
{ {
DISPLAY("\n\nNew callback recv Topic2\n"); DISPLAY("\n\nNew callback recv Topic3\n");
pload[ploadlen-1]= 0; // set null terminator pload[ploadlen - 1] = 0; // set null terminator
DISPLAY("Payload -->%s <--\n\n",pload); DISPLAY("Payload -->%s <--\n\n", pload);
return 0;
}
int on_TopicWildcard(uint8_t* pload, uint16_t ploadlen)
{
DISPLAY("\n\nNew callback recv TopicWildcard\n");
pload[ploadlen - 1] = 0; // set null terminator
DISPLAY("Payload -->%s <--\n\n", pload);
return 0; return 0;
} }
@@ -106,38 +140,53 @@ int on_Topic03(uint8_t* pload, uint16_t ploadlen)
* A Link list of Callback routines and Topics * A Link list of Callback routines and Topics
*------------------------------------------------------*/ *------------------------------------------------------*/
SUBSCRIBE_LIST = {// e.g. SUB(topic, callback, QoS), SUBSCRIBE_LIST =
SUB(topic1, on_Topic01, 1), { // e.g. SUB(TopicType, topicName, TopicId, callback, QoSx),
END_OF_SUBSCRIBE_LIST SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic1, 0, on_Topic01, QoS1),
}; SUB(MQTTSN_TOPIC_TYPE_NORMAL, topic2, 0, on_Topic02, QoS1),
END_OF_SUBSCRIBE_LIST
};
/*------------------------------------------------------ /*------------------------------------------------------
* Test functions * Test functions
*------------------------------------------------------*/ *------------------------------------------------------*/
void subscribePredefTopic1(void)
{
SUBSCRIBE_PREDEF(1, on_Topic03, QoS1);
}
void publishTopic1(void) void publishTopic1(void)
{ {
char payload[300]; char payload[300];
sprintf(payload, "publish \"ty4tw/Topic1\" \n"); sprintf(payload, "publish \"ty4tw/topic1\" \n");
uint8_t qos = 0; PUBLISH(topic1, (uint8_t* )payload, strlen(payload), QoS0);
PUBLISH(topic1,(uint8_t*)payload, strlen(payload), qos);
}
void subscribeTopic2(void)
{
uint8_t qos = 1;
SUBSCRIBE(topic2, on_Topic02, qos);
} }
void publishTopic2(void) void publishTopic2(void)
{ {
char payload[300]; char payload[300];
sprintf(payload, "publish \"ty4tw/topic2\" \n"); sprintf(payload, "publish \"ty4tw/topic2\" \n");
uint8_t qos = 0; PUBLISH(topic2, (uint8_t* )payload, strlen(payload), QoS1);
PUBLISH(topic2,(uint8_t*)payload, strlen(payload), qos);
} }
void publishTopic4(void)
{
char payload[300];
sprintf(payload, "publish \"ty4tw/topic40\" \n");
PUBLISH(topic4, (uint8_t* )payload, strlen(payload), QoS1);
}
void subscribeTopic10(void)
{
SUBSCRIBE_PREDEF(10, on_Topic02, QoS1);
}
void subscribeWildcardTopic(void)
{
SUBSCRIBE(topic50, on_TopicWildcard, QoS1);
}
void unsubscribe(void) void unsubscribe(void)
{ {
UNSUBSCRIBE(topic2); UNSUBSCRIBE(topic2);
@@ -145,8 +194,7 @@ void unsubscribe(void)
void subscribechangeCallback(void) void subscribechangeCallback(void)
{ {
uint8_t qos = 1; SUBSCRIBE(topic2, on_Topic02, QoS1);
SUBSCRIBE(topic2, on_Topic03, qos);
} }
void test3(void) void test3(void)
@@ -154,7 +202,7 @@ void test3(void)
char payload[300]; char payload[300];
sprintf(payload, "TEST3 "); sprintf(payload, "TEST3 ");
uint8_t qos = 0; uint8_t qos = 0;
PUBLISH(topic2,(uint8_t*)payload, strlen(payload), qos); PUBLISH(topic2, (uint8_t* )payload, strlen(payload), qos);
} }
void disconnect(void) void disconnect(void)
@@ -162,45 +210,81 @@ void disconnect(void)
DISCONNECT(0); DISCONNECT(0);
} }
/*------------------------------------------------------ void asleep(void)
* A List of Test functions {
*------------------------------------------------------*/ DISCONNECT(theMqcon.sleepDuration);
}
TEST_LIST = {// e.g. TEST( Label, Test), void onconnect(void)
TEST("Step1:Publish topic1", publishTopic1), {
TEST("Step2:Publish topic2", publishTopic2), ONCONNECT();
TEST("Step3:Subscribe topic2", subscribeTopic2), }
TEST("Step4:Publish topic2", publishTopic2),
TEST("Step5:Unsubscribe topic2", unsubscribe),
TEST("Step6:Publish topic2", publishTopic2),
TEST("Step7:subscribe again", subscribechangeCallback),
TEST("Step8:Publish topic2", publishTopic2),
TEST("Step9:Disconnect", disconnect),
END_OF_TEST_LIST
};
void connect(void)
{
CONNECT();
}
void DisableAutoPingreq(void)
{
SetAutoPingReqMode(false);
}
void CleanSessionOff(void)
{
SetCleanSession(false);
}
/*------------------------------------------------------ /*------------------------------------------------------
* unused for Test * A List of Test functions is valid in case of
* line 23 of LMqttsnClientApp.h is commented out.
* //#define CLIENT_MODE
*------------------------------------------------------*/ *------------------------------------------------------*/
TASK_LIST = {// e.g. TASK( task, executing duration in second),
//TASK(test1, 4); TEST_LIST =
END_OF_TASK_LIST { // e.g. TEST( Label, Test),
}; TEST("Step0:Connect", connect),
TEST("Step1:Subscribe list", onconnect),
TEST("Step2:Subscribe predef topic1", subscribePredefTopic1),
TEST("Step3:Publish topic1", publishTopic1),
TEST("Step4:Publish topic2", publishTopic2),
TEST("Step5:Subscribe PreDefined topic10. ID is not defined.", subscribeTopic10),
TEST("Step6:Publish topic2", publishTopic2),
TEST("Step7:Unsubscribe topic2", unsubscribe),
TEST("Step8:Publish topic2", publishTopic2),
TEST("Step9:subscribe again", subscribechangeCallback),
TEST("Step10:Publish topic2", publishTopic2),
TEST("Step11:Sleep ", asleep),
TEST("Step12:Publish topic1", publishTopic1),
TEST("Step13:Disconnect", disconnect),
TEST("Step14:Publish topic2", publishTopic1),
TEST("Step15:Connect", connect),
TEST("Step16:Publish topic2", publishTopic2),
TEST("Step17:Auto Pingreq mode off", DisableAutoPingreq),
TEST("Step18:Publish topic2", publishTopic1),
TEST("Step19:Disconnect", disconnect),
END_OF_TEST_LIST
};
/*------------------------------------------------------
* List of tasks is valid in case of line23 of
* LMqttsnClientApp.h is uncommented.
* #define CLIENT_MODE
*------------------------------------------------------*/
TASK_LIST =
{ // e.g. TASK( task, executing duration in second),
TASK(publishTopic1, 4),// publishTopic1() is executed every 4 seconds
TASK(publishTopic2, 7),// publishTopic2() is executed every 7 seconds
END_OF_TASK_LIST
};
/*------------------------------------------------------ /*------------------------------------------------------
* Initialize function * Initialize function
*------------------------------------------------------*/ *------------------------------------------------------*/
void setup(void) void setup(void)
{ {
SetForwarderMode(false);
} }
/*------------------------------------------------------ /***************** END OF PROGRAM ********************/
* main
*------------------------------------------------------*/
int main(int argc, char** argv)
{
return run();
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,9 +19,14 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <time.h>
#include "LMqttsnClientApp.h" #include "LMqttsnClientApp.h"
#include "LNetworkUdp.h" #include "LNetworkUdp.h"
#include "LNetworkUdp6.h"
#include "LNetworkRfcomm.h"
#include "LNetworkDtls.h"
#include "LNetworkDtls6.h"
#include "LRegisterManager.h" #include "LRegisterManager.h"
#include "LTimer.h" #include "LTimer.h"
#include "LTopicTable.h" #include "LTopicTable.h"
@@ -41,6 +46,7 @@ using namespace std;
#define GW_SLEEPING 10 #define GW_SLEEPING 10
#define GW_DISCONNECTED 11 #define GW_DISCONNECTED 11
#define GW_SLEPT 12 #define GW_SLEPT 12
#define SSL_CONNECTING 13
#define GW_WAIT_PINGRESP 1 #define GW_WAIT_PINGRESP 1
@@ -50,60 +56,73 @@ namespace linuxAsyncClient {
=======================================*/ =======================================*/
class LGwProxy{ class LGwProxy{
public: public:
LGwProxy(); LGwProxy();
~LGwProxy(); ~LGwProxy();
void initialize(LUdpConfig netconf, LMqttsnConfig mqconf); void initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf);
void connect(void); void connect(void);
void disconnect(uint16_t sec = 0); void disconnect(uint16_t sec = 0);
int getMessage(void); int getMessage(void);
uint16_t registerTopic(char* topic, uint16_t toipcId); uint16_t registerTopic(char* topic, uint16_t toipcId);
void setWillTopic(const char* willTopic, uint8_t qos, bool retain = false); void setWillTopic(const char* willTopic, uint8_t qos, bool retain = false);
void setWillMsg(const char* willMsg); void setWillMsg(const char* willMsg);
void setCleanSession(bool); void setCleanSession(bool);
void setKeepAliveDuration(uint16_t duration); void setKeepAliveDuration(uint16_t duration);
void setAdvertiseDuration(uint16_t duration); void setAdvertiseDuration(uint16_t duration);
void reconnect(void); void setForwarderMode(bool valid);
int writeMsg(const uint8_t* msg); void setQoSMinus1Mode(bool valid);
void resetPingReqTimer(void); void setPingReqMode(bool valid);
uint16_t getNextMsgId(); void setAutoConnectMode(bool valid);
LTopicTable* getTopicTable(void); void setSessionMode(bool valid);
LRegisterManager* getRegisterManager(void); void reconnect(void);
const char* getClientId(void); int writeMsg(const uint8_t* msg);
void setPingReqTimer(void);
uint16_t getNextMsgId();
LTopicTable* getTopicTable(void);
LRegisterManager* getRegisterManager(void);
const char* getClientId(void);
uint8_t getStatus(void);
private: private:
int readMsg(void); int readMsg(void);
void writeGwMsg(void); void writeGwMsg(void);
void checkPingReq(void); void checkPingReq(void);
void checkAdvertise(void); void checkAdvertise(void);
int getConnectResponce(void); int getConnectResponce(void);
int getDisconnectResponce(void); int getDisconnectResponce(void);
bool isPingReqRequired(void);
LNetwork _network; LNetwork _network;
uint8_t* _mqttsnMsg; uint8_t* _mqttsnMsg;
uint16_t _nextMsgId; uint16_t _nextMsgId;
const char* _clientId; const char* _clientId;
const char* _willTopic; const char* _willTopic;
const char* _willMsg; const char* _willMsg;
uint8_t _cleanSession; uint8_t _cleanSession;
uint8_t _retainWill; uint8_t _initialized;
uint8_t _qosWill; uint8_t _retainWill;
uint8_t _gwId; uint8_t _qosWill;
uint16_t _tkeepAlive; uint8_t _gwId;
uint32_t _tAdv; uint16_t _tkeepAlive;
uint32_t _sendUTC; uint32_t _tAdv;
int _retryCount; time_t _sendUTC;
int _connectRetry; int _retryCount;
uint8_t _status; int _connectRetry;
uint32_t _pingSendUTC; uint8_t _status;
uint8_t _pingRetryCount; time_t _pingSendUTC;
uint8_t _pingStatus; uint8_t _pingRetryCount;
LRegisterManager _regMgr; uint8_t _pingStatus;
LTopicTable _topicTbl; LRegisterManager _regMgr;
LTimer _gwAliveTimer; LTopicTable _topicTbl;
LTimer _keepAliveTimer; LTimer _gwAliveTimer;
uint16_t _tSleep; LTimer _keepAliveTimer;
char _msg[MQTTSN_MAX_MSG_LENGTH + 1]; uint16_t _tSleep;
uint16_t _tWake;
bool _isForwarderMode;
bool _isQoSMinus1Mode;
bool _isPingReqMode;
bool _isAutoConnectMode;
char _msg[MQTTSN_MAX_MSG_LENGTH + 1];
}; };
} /* end of namespace */ } /* end of namespace */

View File

@@ -29,8 +29,9 @@ extern TaskList theTaskList[];
extern TestList theTestList[]; extern TestList theTestList[];
extern OnPublishList theOnPublishList[]; extern OnPublishList theOnPublishList[];
extern MQTTSNCONF; extern MQTTSNCONF;
extern UDPCONF; extern SENSORNET_CONFIG_t theNetcon;
extern void setup(void); extern void setup(void);
/*===================================== /*=====================================
LMqttsnClient LMqttsnClient
======================================*/ ======================================*/
@@ -39,45 +40,63 @@ LScreen* theScreen = new LScreen();
bool theOTAflag = false; bool theOTAflag = false;
bool theClientMode = true; bool theClientMode = true;
int run(void)
/*-------------------------------------
* main
*------------------------------------*/
int main(int argc, char** argv)
{ {
#ifndef CLIENT_MODE
char c = 0; char c = 0;
setup();
printf("\n%s", PAHO_COPYRIGHT4); printf("\n%s", PAHO_COPYRIGHT4);
printf("\n%s\n", PAHO_COPYRIGHT0); printf("\n%s", PAHO_COPYRIGHT0);
#if defined(UDP)
printf("UDP ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo);
#elif defined(UDP6)
printf("UDP6 ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo);
#elif defined(DTLS)
printf("DTLS ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo);
#elif defined(DTLS6)
printf("DTLS6 ClientId:%s PortNo:%d\n", theNetcon.clientId, theNetcon.uPortNo);
#elif defined(RFCOMM)
printf("RFCOMM ClientId:%s channel:%d\n", theNetcon.clientId, theNetcon.channel);
#else
printf("\n");
#endif
printf("%s\n", PAHO_COPYRIGHT1); printf("%s\n", PAHO_COPYRIGHT1);
printf("%s\n", PAHO_COPYRIGHT2); printf("%s\n", PAHO_COPYRIGHT2);
printf(" *\n%s\n", PAHO_COPYRIGHT3); printf(" *\n%s\n", PAHO_COPYRIGHT3);
printf("%s\n", TESTER_VERSION); printf("%s\n", TESTER_VERSION);
printf("%s\n", PAHO_COPYRIGHT4); printf("%s\n", PAHO_COPYRIGHT4);
#ifndef CLIENT_MODE theClientMode = false;
PROMPT(" Do you like Tomoaki ? ( y/n ) : ");
while (true)
{ {
theClientMode = false; if (CHECKKEYIN(&c))
PROMPT(" Do you like Tomoaki ? ( y/n ) : ");
while (true)
{ {
if (CHECKKEYIN(&c)) if ( toupper(c) == 'N' )
{ {
if ( toupper(c) == 'N' ) DISPLAY("\033[0;31m\n**** Sorry ****\033[0;37m\n\n");
{
DISPLAY("\033[0;31m\n**** Sorry ****\033[0;37m\n\n");
PROMPT("");
return 0;
}
}
else if ( toupper(c) == 'Y' )
{
DISPLAY("\033[0m\033[0;32mAttempting to Connect the Broker.....\033[0m\033[0;37m\n");
PROMPT(""); PROMPT("");
break; return 0;
} }
} }
else if ( toupper(c) == 'Y' )
{
DISPLAY("\033[0m\033[0;32mAttempting to Connect the Broker.....\033[0m\033[0;37m\n");
PROMPT("");
break;
}
} }
theClient->setAutoConnectMode(false);
theClient->getPublishManager()->setAutoConnectMode(false);
#endif #endif
setup();
theClient->addTask(theClientMode); theClient->addTask(theClientMode);
theClient->initialize( theNetcon, theMqcon); theClient->initialize( &theNetcon, &theMqcon);
do do
{ {
theClient->run(); theClient->run();
@@ -94,7 +113,7 @@ int run(void)
======================================*/ ======================================*/
LMqttsnClient::LMqttsnClient() LMqttsnClient::LMqttsnClient()
{ {
_isAutoConnect = true;
} }
LMqttsnClient::~LMqttsnClient() LMqttsnClient::~LMqttsnClient()
@@ -102,10 +121,10 @@ LMqttsnClient::~LMqttsnClient()
} }
void LMqttsnClient::initialize(LUdpConfig netconf, LMqttsnConfig mqconf) void LMqttsnClient::initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf)
{ {
_gwProxy.initialize(netconf, mqconf); _gwProxy.initialize(netconf, mqconf);
setSleepDuration(mqconf.sleepDuration); setSleepDuration(mqconf->sleepDuration);
} }
void LMqttsnClient::addTask(bool clientMode) void LMqttsnClient::addTask(bool clientMode)
@@ -179,9 +198,10 @@ void LMqttsnClient::subscribe(const char* topicName, TopicCallback onPublish, ui
_subMgr.subscribe(topicName, onPublish, qos); _subMgr.subscribe(topicName, onPublish, qos);
} }
void LMqttsnClient::subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos, uint8_t topicType) void LMqttsnClient::subscribePredefinedId(uint16_t topicId, TopicCallback onPublish,
uint8_t qos)
{ {
_subMgr.subscribe(topicId, onPublish, qos, topicType); _subMgr.subscribePredefinedId(topicId, onPublish, qos);
} }
void LMqttsnClient::unsubscribe(const char* topicName) void LMqttsnClient::unsubscribe(const char* topicName)
@@ -189,6 +209,11 @@ void LMqttsnClient::unsubscribe(const char* topicName)
_subMgr.unsubscribe(topicName); _subMgr.unsubscribe(topicName);
} }
void LMqttsnClient::unsubscribe(const uint16_t topicId)
{
_subMgr.unsubscribe(topicId);
}
void LMqttsnClient::disconnect(uint16_t sleepInSecs) void LMqttsnClient::disconnect(uint16_t sleepInSecs)
{ {
_gwProxy.disconnect(sleepInSecs); _gwProxy.disconnect(sleepInSecs);
@@ -196,14 +221,29 @@ void LMqttsnClient::disconnect(uint16_t sleepInSecs)
void LMqttsnClient::run() void LMqttsnClient::run()
{ {
_gwProxy.connect(); if (_isAutoConnect)
{
_gwProxy.connect();
}
_taskMgr.run(); _taskMgr.run();
sleep(); }
void LMqttsnClient::setAutoConnectMode(uint8_t flg)
{
_isAutoConnect = flg;
_pubMgr.setAutoConnectMode(flg);
_gwProxy.setAutoConnectMode(flg);
}
void LMqttsnClient::setSleepMode(uint32_t duration)
{
// ToDo: set WDT and sleep mode
DISPLAY("\033[0m\033[0;32m\n\n Get into SLEEP mode %u [msec].\033[0m\033[0;37m\n\n", duration);
} }
void LMqttsnClient::sleep(void) void LMqttsnClient::sleep(void)
{ {
disconnect(_sleepDuration);
} }
void LMqttsnClient::setSleepDuration(uint32_t duration) void LMqttsnClient::setSleepDuration(uint32_t duration)
@@ -213,7 +253,10 @@ void LMqttsnClient::setSleepDuration(uint32_t duration)
void LMqttsnClient::onConnect(void) void LMqttsnClient::onConnect(void)
{ {
_subMgr.onConnect(); if (_isAutoConnect)
{
_subMgr.onConnect();
}
} }
const char* LMqttsnClient::getClientId(void) const char* LMqttsnClient::getClientId(void)
@@ -221,6 +264,8 @@ const char* LMqttsnClient::getClientId(void)
return _gwProxy.getClientId(); return _gwProxy.getClientId();
} }
uint16_t LMqttsnClient::getTopicId(const char* topicName)
{
return _gwProxy.getTopicTable()->getTopicId(topicName);
}

View File

@@ -34,7 +34,9 @@ namespace linuxAsyncClient {
struct OnPublishList struct OnPublishList
{ {
MQTTSN_topicTypes type;
const char* topic; const char* topic;
uint16_t id;
int (*pubCallback)(uint8_t* payload, uint16_t payloadlen); int (*pubCallback)(uint8_t* payload, uint16_t payloadlen);
uint8_t qos; uint8_t qos;
}; };
@@ -52,15 +54,19 @@ public:
void publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain = false); void publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain = false);
void publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false); void publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false);
void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos); void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos);
void subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos, uint8_t topicType); void subscribePredefinedId(uint16_t topicId, TopicCallback onPublish, uint8_t qos);
void unsubscribe(const char* topicName); void unsubscribe(const char* topicName);
void unsubscribe(const uint16_t topicId);
void disconnect(uint16_t sleepInSecs); void disconnect(uint16_t sleepInSecs);
void initialize(LUdpConfig netconf, LMqttsnConfig mqconf); void initialize(SENSORNET_CONFIG_t* netconf, LMqttsnConfig* mqconf);
void run(void); void run(void);
void addTask(bool test); void addTask(bool test);
void setSleepDuration(uint32_t duration); void setSleepDuration(uint32_t duration);
void setSleepMode(uint32_t duration);
void setAutoConnectMode(uint8_t flg);
void sleep(void); void sleep(void);
const char* getClientId(void); const char* getClientId(void);
uint16_t getTopicId(const char* topicName);
LGwProxy* getGwProxy(void); LGwProxy* getGwProxy(void);
LPublishManager* getPublishManager(void); LPublishManager* getPublishManager(void);
LSubscribeManager* getSubscribeManager(void); LSubscribeManager* getSubscribeManager(void);
@@ -73,6 +79,7 @@ private:
LSubscribeManager _subMgr; LSubscribeManager _subMgr;
LGwProxy _gwProxy; LGwProxy _gwProxy;
uint32_t _sleepDuration; uint32_t _sleepDuration;
uint8_t _isAutoConnect;
}; };

View File

@@ -1,5 +1,5 @@
/************************************************************************************** /**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi * Copyright (c) 2016-2018, Tomoaki Yamaguchi
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
@@ -17,17 +17,16 @@
#ifndef MQTTSNCLIENTAPP_H_ #ifndef MQTTSNCLIENTAPP_H_
#define MQTTSNCLIENTAPP_H_ #define MQTTSNCLIENTAPP_H_
/*======================================
* Program mode Flag
======================================*/
//#define CLIENT_MODE
/*====================================== /*======================================
* Debug Flag * Debug Flag
======================================*/ ======================================*/
//#define DEBUG_NW //#define DEBUG_NW
//#define DEBUG_MQTTSN //#define DEBUG_MQTTSN
//#define DEBUG_OTA
/*======================================
* Program mode Flag
======================================*/
//#define CLIENT_MODE
/**************************************** /****************************************
MQTT-SN Parameters MQTT-SN Parameters
@@ -56,7 +55,8 @@ typedef signed int int32_t;
Application config structures Application config structures
*****************************************/ *****************************************/
struct LMqttsnConfig{ struct LMqttsnConfig
{
uint16_t keepAlive; uint16_t keepAlive;
bool cleanSession; bool cleanSession;
uint32_t sleepDuration; uint32_t sleepDuration;
@@ -66,23 +66,87 @@ struct LMqttsnConfig{
bool willRetain; bool willRetain;
}; };
struct LUdpConfig{ struct LUdpConfig
{
const char* clientId; const char* clientId;
uint8_t ipAddress[4]; uint8_t ipAddress[4];
uint16_t gPortNo; uint16_t gPortNo;
uint16_t uPortNo; uint16_t uPortNo;
}; };
struct LUdp6Config
{
const char* clientId;
const char* ipAddress;
const char *interface;
uint16_t gPortNo;
uint16_t uPortNo;
};
struct LRfcommConfig
{
const char* clientId;
const char* gwAddress;
uint8_t channel;
};
typedef enum
{
MQTTSN_TOPIC_TYPE_NORMAL,
MQTTSN_TOPIC_TYPE_PREDEFINED,
MQTTSN_TOPIC_TYPE_SHORT
} MQTTSN_topicTypes;
/*====================================== /*======================================
MACROs for Application MACROs for Application
=======================================*/ =======================================*/
#define MQTTSN_CONFIG MqttsnConfig theMqttsnConfig #define MQTTSN_CONFIG MqttsnConfig theMqttsnConfig
#define NETWORK_CONFIG UdpConfig theNetworkConfig #define MQTTSNCONF LMqttsnConfig theMqcon
#if defined(UDP)
#define UDPCONF LUdpConfig theNetcon
#define UDP6CONF LUdp6Config theU6Conf
#define RFCOMMCONF LRfcommConfig theRfConf
#define SENSORNET_CONFIG_t LUdpConfig
#elif defined(UDP6)
#define UDP6CONF LUdp6Config theNetcon
#define UDPCONF LUdpConfig theUConf
#define RFCOMMCONF LRfcommConfig theRfConf
#define SENSORNET_CONFIG_t LUdp6Config
#elif defined(RFCOMM)
#define RFCOMMCONF LRfcommConfig theNetcon
#define UDPCONF LUdpConfig theUConf
#define UDP6CONF LUdp6Config theU6Conf
#define SENSORNET_CONFIG_t LRfcommConfig
#elif defined(DTLS)
#define UDPCONF LUdpConfig theNetcon
#define UDP6CONF LUdp6Config theU6Conf
#define RFCOMMCONF LRfcommConfig theRfConf
#define SENSORNET_CONFIG_t LUdpConfig
#elif defined(DTLS6)
#define UDPCONF LUdpConfig theUConf
#define UDP6CONF LUdp6Config theNetcon
#define RFCOMMCONF LRfcommConfig theRfConf
#define SENSORNET_CONFIG_t LUdp6Config
#else
#error "UDP, UDP6, DTLS, DTLS6 or RFCOMM is not defined in LMqttsnClientApp.h"
#endif
#define CONNECT(...) theClient->getGwProxy()->connect(__VA_ARGS__)
#define PUBLISH(...) theClient->publish(__VA_ARGS__) #define PUBLISH(...) theClient->publish(__VA_ARGS__)
#define SUBSCRIBE(...) theClient->subscribe(__VA_ARGS__) #define SUBSCRIBE(...) theClient->subscribe(__VA_ARGS__)
#define SUBSCRIBE_PREDEF(...) theClient->subscribePredefinedId(__VA_ARGS__)
#define UNSUBSCRIBE(...) theClient->unsubscribe(__VA_ARGS__) #define UNSUBSCRIBE(...) theClient->unsubscribe(__VA_ARGS__)
#define DISCONNECT(...) theClient->disconnect(__VA_ARGS__) #define DISCONNECT(...) theClient->disconnect(__VA_ARGS__)
#define ONCONNECT() theClient->getSubscribeManager()->onConnect()
#define TASK_LIST TaskList theTaskList[] #define TASK_LIST TaskList theTaskList[]
#define TASK(...) {__VA_ARGS__, 0, 0} #define TASK(...) {__VA_ARGS__, 0, 0}
@@ -92,9 +156,14 @@ struct LUdpConfig{
#define END_OF_TEST_LIST {0, 0, 0} #define END_OF_TEST_LIST {0, 0, 0}
#define SUBSCRIBE_LIST OnPublishList theOnPublishList[] #define SUBSCRIBE_LIST OnPublishList theOnPublishList[]
#define SUB(...) {__VA_ARGS__} #define SUB(...) {__VA_ARGS__}
#define END_OF_SUBSCRIBE_LIST {0,0,0} #define END_OF_SUBSCRIBE_LIST {MQTTSN_TOPIC_TYPE_NORMAL,0,0,0, 0}
#define UDPCONF LUdpConfig theNetcon
#define MQTTSNCONF LMqttsnConfig theMqcon
#define SetForwarderMode(...) theClient->getGwProxy()->setForwarderMode(__VA_ARGS__)
#define SetQoSMinus1Mode(...) theClient->getGwProxy()->setQoSMinus1Mode(__VA_ARGS__)
#define SetAutoConnectMode(...) theClient->setAutoConnectMode(__VA_ARGS__)
#define SetAutoPingReqMode(...) theClient->getGwProxy()->setPingReqMode(__VA_ARGS__)
#define SetCleanSession(...) theClient->getGwProxy()->setSessionMode(__VA_ARGS__)
#ifdef CLIENT_MODE #ifdef CLIENT_MODE
#define DISPLAY(...) #define DISPLAY(...)
#define PROMPT(...) #define PROMPT(...)
@@ -128,6 +197,10 @@ struct LUdpConfig{
/*====================================== /*======================================
MQTT-SN Defines MQTT-SN Defines
========================================*/ ========================================*/
#define QoS0 0
#define QoS1 1
#define QoS2 2
#define Q0Sm1 3
#define MQTTSN_TYPE_ADVERTISE 0x00 #define MQTTSN_TYPE_ADVERTISE 0x00
#define MQTTSN_TYPE_SEARCHGW 0x01 #define MQTTSN_TYPE_SEARCHGW 0x01
#define MQTTSN_TYPE_GWINFO 0x02 #define MQTTSN_TYPE_GWINFO 0x02
@@ -155,17 +228,15 @@ struct LUdpConfig{
#define MQTTSN_TYPE_WILLTOPICRESP 0x1B #define MQTTSN_TYPE_WILLTOPICRESP 0x1B
#define MQTTSN_TYPE_WILLMSGUPD 0x1C #define MQTTSN_TYPE_WILLMSGUPD 0x1C
#define MQTTSN_TYPE_WILLMSGRESP 0x1D #define MQTTSN_TYPE_WILLMSGRESP 0x1D
#define MQTTSN_TYPE_ENCAPSULATED 0xFE
#define MQTTSN_TOPIC_TYPE_NORMAL 0x00 #define MQTTSN_TOPIC_TYPE 0x03
#define MQTTSN_TOPIC_TYPE_PREDEFINED 0x01
#define MQTTSN_TOPIC_TYPE_SHORT 0x02
#define MQTTSN_TOPIC_TYPE 0x03
#define MQTTSN_FLAG_DUP 0x80 #define MQTTSN_FLAG_DUP 0x80
#define MQTTSN_FLAG_QOS_0 0x0 #define MQTTSN_FLAG_QOS_0 0x0
#define MQTTSN_FLAG_QOS_1 0x20 #define MQTTSN_FLAG_QOS_1 0x20
#define MQTTSN_FLAG_QOS_2 0x40 #define MQTTSN_FLAG_QOS_2 0x40
#define MQTTSN_FLAG_QOS_N1 0xc0 #define MQTTSN_FLAG_QOS_M1 0x60
#define MQTTSN_FLAG_RETAIN 0x10 #define MQTTSN_FLAG_RETAIN 0x10
#define MQTTSN_FLAG_WILL 0x08 #define MQTTSN_FLAG_WILL 0x08
#define MQTTSN_FLAG_CLEAN 0x04 #define MQTTSN_FLAG_CLEAN 0x04
@@ -178,18 +249,14 @@ struct LUdpConfig{
#define MQTTSN_RC_REJECTED_INVALID_TOPIC_ID 0x02 #define MQTTSN_RC_REJECTED_INVALID_TOPIC_ID 0x02
#define MQTTSN_RC_REJECTED_NOT_SUPPORTED 0x03 #define MQTTSN_RC_REJECTED_NOT_SUPPORTED 0x03
#define PREDEFINEDID_OTA_REQ (0x0ff0)
#define PREDEFINEDID_OTA_READY (0x0ff1)
#define PREDEFINEDID_OTA_NO_CLIENT (0x0ff2)
/*================================= /*=================================
* Starting prompt * Starting prompt
==================================*/ ==================================*/
#define TESTER_VERSION " * Version: 1.0.0" #define TESTER_VERSION " * Version: 2.1.0"
#define PAHO_COPYRIGHT0 " * MQTT-SN Gateway Tester" #define PAHO_COPYRIGHT0 " * "
#define PAHO_COPYRIGHT1 " * Part of Project Paho in Eclipse" #define PAHO_COPYRIGHT1 " * Part of Project Paho in Eclipse"
#define PAHO_COPYRIGHT2 " * (http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt-sn.embedded-c.git/)" #define PAHO_COPYRIGHT2 " * (https://github.com/eclipse/paho.mqtt-sn.embedded-c.git)"
#define PAHO_COPYRIGHT3 " * Author : Tomoaki YAMAGUCHI" #define PAHO_COPYRIGHT3 " * Author : Tomoaki YAMAGUCHI"
#define PAHO_COPYRIGHT4 " ***************************************************************************" #define PAHO_COPYRIGHT4 " ***************************************************************************"

View File

@@ -0,0 +1,544 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifdef DTLS
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include "LMqttsnClientApp.h"
#include "LNetworkDtls.h"
#include "LTimer.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern uint16_t getUint16(const uint8_t* pos);
extern uint32_t getUint32(const uint8_t* pos);
extern LScreen* theScreen;
extern bool theClientMode;
/* Certificate verification. Returns 1 if trusted, else 0 */
int verify_cert(int ok, X509_STORE_CTX *ctx);
/*=========================================
Class LNetwork
=========================================*/
LNetwork::LNetwork()
{
_sleepflg = false;
resetGwAddress();
}
LNetwork::~LNetwork()
{
}
int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
{
return LDtlsPort::multicast(xmitData, (uint32_t) dataLen);
}
int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
{
return LDtlsPort::unicast(xmitData, dataLen);
}
uint8_t* LNetwork::getMessage(int *len)
{
*len = 0;
uint16_t recvLen = 0;
if (checkRecvBuf())
{
recvLen = LDtlsPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
if (_gwIpAddress && isUnicast() && (_ipAddress != _gwIpAddress) && (_portNo != _gwPortNo))
{
return 0;
}
if (recvLen < 0)
{
*len = recvLen;
return 0;
}
else
{
if (_rxDataBuf[0] == 0x01)
{
*len = getUint16(_rxDataBuf + 1);
}
else
{
*len = _rxDataBuf[0];
}
return _rxDataBuf;
}
}
return 0;
}
void LNetwork::setGwAddress(void)
{
_gwPortNo = _portNo;
_gwIpAddress = _ipAddress;
}
void LNetwork::resetGwAddress(void)
{
_gwIpAddress = 0;
_gwPortNo = 0;
}
bool LNetwork::initialize(LUdpConfig *config)
{
return LDtlsPort::open(config);
}
void LNetwork::setSleep()
{
_sleepflg = true;
}
bool LNetwork::isBroadcastable()
{
return true;
}
int LNetwork::sslConnect(void)
{
return LDtlsPort::sslConnect(_gwIpAddress, _gwPortNo);
}
/*=========================================
Class DtlsPort
=========================================*/
LDtlsPort::LDtlsPort()
{
_disconReq = false;
_sockfdMcast = 0;
_sockfdSsl = 0;
_castStat = 0;
}
LDtlsPort::~LDtlsPort()
{
close();
}
void LDtlsPort::close()
{
if (_sockfdMcast > 0)
{
::close(_sockfdMcast);
_sockfdMcast = 0;
if (_sockfdSsl > 0)
{
::close(_sockfdSsl);
_sockfdSsl = 0;
}
}
}
bool LDtlsPort::open(LUdpConfig *config)
{
char errmsg[256];
int optval = 0;
uint8_t sav = config->ipAddress[3];
config->ipAddress[3] = config->ipAddress[0];
config->ipAddress[0] = sav;
sav = config->ipAddress[2];
config->ipAddress[2] = config->ipAddress[1];
config->ipAddress[1] = sav;
_gIpAddr = getUint32((const uint8_t*) config->ipAddress);
_gPortNo = htons(config->gPortNo);
_uPortNo = htons(config->uPortNo);
if (_gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0)
{
return false;
}
SSL_load_error_strings();
SSL_library_init();
_ctx = SSL_CTX_new(DTLS_client_method());
if (_ctx == 0)
{
ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg));
DISPLAY("SSL_CTX_new() %s\n", errmsg);
return false;
}
/* Client certification and cookie are not required */
SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, verify_cert);
/* setup Multicast socket */
_sockfdMcast = socket(AF_INET, SOCK_DGRAM, 0);
if (_sockfdMcast < 0)
{
return false;
}
struct sockaddr_in addrm;
addrm.sin_family = AF_INET;
addrm.sin_port = _gPortNo;
addrm.sin_addr.s_addr = INADDR_ANY;
optval = 1;
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if (::bind(_sockfdMcast, (struct sockaddr*) &addrm, sizeof(addrm)) < 0)
{
return false;
}
optval = 1;
if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror IP_MULTICAST_LOOP in LDtlsPort::open\033[0m\033[0;37m\n");
close();
return false;
}
ip_mreq mreq;
mreq.imr_interface.s_addr = INADDR_ANY;
mreq.imr_multiaddr.s_addr = _gIpAddr;
if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror IP_ADD_MEMBERSHIP in LDtlsPort::open\033[0m\033[0;37m\n");
close();
return false;
}
return true;
}
bool LDtlsPort::isUnicast()
{
return (_castStat == STAT_UNICAST);
}
int LDtlsPort::unicast(const uint8_t *buf, uint32_t length)
{
int status = SSL_write(_ssl, buf, length);
if (status <= 0)
{
int rc = 0;
SSL_get_error(_ssl, rc);
DISPLAY("errno == %d in LDtlsPort::unicast\n", rc);
}
else
{
D_NWLOG("sendto gateway via DTLS ");
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34msendto the gateway via SSL ");
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
}
return status;
}
int LDtlsPort::multicast(const uint8_t *buf, uint32_t length)
{
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = _gPortNo;
dest.sin_addr.s_addr = _gIpAddr;
int status = ::sendto(_sockfdMcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
if (status < 0)
{
D_NWLOG("\033[0m\033[0;31merrno == %d in LDtlsPort::multicast\033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merrno == %d in LDtlsPort::multicast\033[0m\033[0;37m\n", errno);
return errno;
}
else
{
D_NWLOG("sendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(_gPortNo));
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
DISPLAY(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34msendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(_gPortNo));
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
}
bool LDtlsPort::checkRecvBuf()
{
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 50000; // 50 msec
uint8_t buf[2];
fd_set recvfds;
int maxSock = 0;
FD_ZERO(&recvfds);
if (_sockfdMcast)
{
FD_SET(_sockfdMcast, &recvfds);
}
if (_sockfdSsl)
{
FD_SET(_sockfdSsl, &recvfds);
}
if (_sockfdMcast > _sockfdSsl)
{
maxSock = _sockfdMcast;
}
else
{
maxSock = _sockfdSsl;
}
select(maxSock + 1, &recvfds, 0, 0, &timeout);
if (FD_ISSET(_sockfdMcast, &recvfds))
{
if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_MULTICAST;
return true;
}
}
else if (FD_ISSET(_sockfdSsl, &recvfds))
{
if (::recv(_sockfdSsl, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_SSL;
return true;
}
}
_castStat = STAT_NONE;
return false;
}
int LDtlsPort::recv(uint8_t *buf, uint16_t len, bool flg, uint32_t *ipAddressPtr, in_port_t *portPtr)
{
int flags = flg ? MSG_DONTWAIT : 0;
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
}
int LDtlsPort::recvfrom(uint8_t *buf, uint16_t length, int flags, uint32_t *ipAddressPtr, in_port_t *portPtr)
{
struct sockaddr_in sender;
int status = 0;
socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen);
if (_castStat == STAT_SSL)
{
D_NWLOG("Ucast ");
if (SSL_read(_ssl, buf, length) == 0)
{
return 0;
}
}
else if (_castStat == STAT_MULTICAST)
{
D_NWLOG("Mcast ");
status = ::recvfrom(_sockfdMcast, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
}
else
{
return 0;
}
if (status < 0 && errno != EAGAIN)
{
D_NWLOG("\033[0m\033[0;31merrno == %d in LDtlsPort::recvfrom \033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merrno == %d in LDtlsPort::recvfrom \033[0m\033[0;37m\n", errno);
}
else if (status > 0)
{
*ipAddressPtr = sender.sin_addr.s_addr;
*portPtr = sender.sin_port;
D_NWLOG("recved %-15s:%-6u", inet_ntoa(sender.sin_addr), ntohs(*portPtr));
for (uint16_t i = 0; i < status; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", inet_ntoa(sender.sin_addr), ntohs(*portPtr));
pos = strlen(sbuf);
for (uint16_t i = 0; i < status; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
else
{
return 0;
}
return status;
}
int LDtlsPort::sslConnect(uint32_t ipAddress, in_port_t portNo)
{
int reuse = 1;
if (_ssl != 0)
{
D_NWLOG("LDtlsPort::sslConnect SSL exists.\n");
SSL_shutdown(_ssl);
SSL_free(_ssl);
_sockfdSsl = 0;
_ssl = 0;
}
if (_sockfdSsl > 0)
{
D_NWLOG("LDtlsPort::sslConnect socket exists.\n");
::close(_sockfdSsl);
}
_sockfdSsl = socket(AF_INET, SOCK_DGRAM, 0);
if (_sockfdSsl < 0)
{
D_NWLOG("LDtlsPort::sslConnect Can't create a socket\n");
return -1;
}
setsockopt(_sockfdSsl, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = _uPortNo;
addr.sin_addr.s_addr = INADDR_ANY;
if (::bind(_sockfdSsl, (struct sockaddr*) &addr, sizeof(addr)) < 0)
{
::close(_sockfdSsl);
_sockfdSsl = 0;
D_NWLOG("LDtlsPort::sslConnect Can't bind a socket\n");
return -1;
}
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = portNo;
dest.sin_addr.s_addr = ipAddress;
int rc = 0;
errno = 0;
BIO *cbio = BIO_new_dgram(_sockfdSsl, BIO_NOCLOSE);
connect(_sockfdSsl, (sockaddr*) &dest, sizeof(sockaddr_in));
BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dest);
_ssl = SSL_new(_ctx);
SSL_set_bio(_ssl, cbio, cbio);
D_NWLOG("LDtlsPort::sslConnect connect to %-15s:%-6u\n", inet_ntoa(dest.sin_addr), htons(dest.sin_port));
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
int stat = SSL_connect(_ssl);
if (stat != 1)
{
rc = -1;
D_NWLOG("SSL fail to connect\n");
}
else
{
rc = 1;
D_NWLOG("SSL connected\n");
}
return rc;
}
int verify_cert(int ok, X509_STORE_CTX *ctx)
{
return 1;
}
#endif

View File

@@ -0,0 +1,118 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef NETWORKDTLS_H_
#define NETWORKDTLS_H_
#ifdef DTLS
#include <sys/time.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
using namespace std;
namespace linuxAsyncClient {
#define STAT_NONE 0
#define STAT_UNICAST 1
#define STAT_MULTICAST 2
#define STAT_SSL 3
/*========================================
Class LDtlsPort
=======================================*/
class LDtlsPort
{
friend class LNetwork;
public:
LDtlsPort();
virtual ~LDtlsPort();
bool open(LUdpConfig* config);
int unicast(const uint8_t *buf, uint32_t length);
int multicast( const uint8_t* buf, uint32_t length );
int recv(uint8_t* buf, uint16_t len, bool nonblock, uint32_t* ipaddress, in_port_t* port );
int recv(uint8_t* buf, int flags);
bool checkRecvBuf();
bool isUnicast();
SSL* getSSL(void);
int sslConnect(uint32_t ipAddress, in_port_t port);
private:
void close();
int recvfrom ( uint8_t* buf, uint16_t len, int flags, uint32_t* ipaddress, in_port_t* port );
int _sockfdMcast;
int _sockfdSsl;
SSL_CTX *_ctx;
SSL *_ssl;
in_port_t _gPortNo;
in_port_t _uPortNo;
uint32_t _gIpAddr;
uint8_t _castStat;
bool _disconReq;
};
#define NO_ERROR 0
#define PACKET_EXCEEDS_LENGTH 1
/*===========================================
Class Network
============================================*/
class LNetwork: public LDtlsPort
{
public:
LNetwork();
~LNetwork();
int broadcast(const uint8_t* payload, uint16_t payloadLen);
int unicast(const uint8_t* payload, uint16_t payloadLen);
void setGwAddress(void);
void resetGwAddress(void);
bool initialize(LUdpConfig* config);
uint8_t* getMessage(int* len);
bool isBroadcastable();
int sslConnect(void);
private:
void setSleep();
int readApiFrame(void);
uint32_t _gwIpAddress;
uint32_t _ipAddress;
in_port_t _gwPortNo;
in_port_t _portNo;
int _returnCode;
bool _sleepflg;
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
};
} /* end of namespace */
#endif /* DTLS */
#endif /* NETWORKDTLS_H_ */

View File

@@ -0,0 +1,586 @@
/**************************************************************************************
* Copyright (c) 2021, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifdef DTLS6
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <net/if.h>
#include <termios.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <poll.h>
#include "LMqttsnClientApp.h"
#include "LNetworkDtls6.h"
#include "LTimer.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern uint16_t getUint16(const uint8_t *pos);
extern uint32_t getUint32(const uint8_t *pos);
extern LScreen *theScreen;
extern bool theClientMode;
/* Certificate verification. Returns 1 if trusted, else 0 */
int verify_cert(int ok, X509_STORE_CTX *ctx);
/*=========================================
Class LNetwork
=========================================*/
LNetwork::LNetwork()
{
_sleepflg = false;
resetGwAddress();
}
LNetwork::~LNetwork()
{
}
int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
{
return LDtls6Port::multicast(xmitData, (uint32_t) dataLen);
}
int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
{
return LDtls6Port::unicast(xmitData, dataLen);
}
uint8_t* LNetwork::getMessage(int *len)
{
*len = 0;
if (checkRecvBuf())
{
uint16_t recvLen = LDtls6Port::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
int addrFlg = memcmp(_ipAddress.s6_addr, _gwIpAddress.s6_addr, sizeof(_gwIpAddress.s6_addr));
if (isUnicast() && addrFlg && (_portNo != _gwPortNo))
{
return 0;
}
if (recvLen < 0)
{
*len = recvLen;
return 0;
}
else
{
if (_rxDataBuf[0] == 0x01)
{
*len = getUint16(_rxDataBuf + 1);
}
else
{
*len = _rxDataBuf[0];
}
return _rxDataBuf;
}
}
return 0;
}
void LNetwork::setGwAddress(void)
{
_gwPortNo = _portNo;
memcpy(&_gwIpAddress.s6_addr, &_ipAddress.s6_addr, sizeof(_ipAddress.s6_addr));
}
void LNetwork::resetGwAddress(void)
{
memset(&_gwIpAddress, 0, sizeof(_gwIpAddress));
_gwPortNo = 0;
}
bool LNetwork::initialize(LUdp6Config *config)
{
return LDtls6Port::open(config);
}
void LNetwork::setSleep()
{
_sleepflg = true;
}
bool LNetwork::isBroadcastable()
{
return true;
}
int LNetwork::sslConnect(void)
{
return LDtls6Port::sslConnect(_gwIpAddress, _gwPortNo);
}
/*=========================================
Class Dtls6Port
=========================================*/
LDtls6Port::LDtls6Port()
{
_disconReq = false;
_castStat = STAT_NONE;
_ifIndex = 0;
_gIpAddrStr = nullptr;
_sockfdMcast = 0;
_sockfdSsl = 0;
_ctx = nullptr;
_ssl = nullptr;
_gPortNo = _uPortNo = 0;
}
LDtls6Port::~LDtls6Port()
{
close();
if (_gIpAddrStr)
{
free(_gIpAddrStr);
}
}
void LDtls6Port::close()
{
if (_sockfdMcast > 0)
{
::close(_sockfdMcast);
_sockfdMcast = 0;
if (_sockfdSsl > 0)
{
::close(_sockfdSsl);
_sockfdSsl = 0;
}
}
}
bool LDtls6Port::open(LUdp6Config *config)
{
int optval = 1;
sockaddr_in6 addr6;
char errmsg[256];
_gPortNo = htons(config->gPortNo);
_uPortNo = htons(config->uPortNo);
if (_gPortNo == 0 || _uPortNo == 0)
{
return false;
}
SSL_load_error_strings();
SSL_library_init();
_ctx = SSL_CTX_new(DTLS_client_method());
if (_ctx == 0)
{
ERR_error_string_n(ERR_get_error(), errmsg, sizeof(errmsg));
DISPLAY("SSL_CTX_new() %s\n", errmsg);
return false;
}
/* Client certification and cookie are not required */
SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, verify_cert);
if (strlen(config->interface) > 0)
{
_ifIndex = if_nametoindex(config->interface);
_interfaceName = config->interface;
}
/* create a multicast socket */
_sockfdMcast = socket(AF_INET6, SOCK_DGRAM, 0);
if (_sockfdMcast < 0)
{
return false;
}
optval = 1;
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(_sockfdMcast, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = _gPortNo;
addr6.sin6_addr = in6addr_any;
if (::bind(_sockfdMcast, (sockaddr*) &addr6, sizeof(addr6)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s ::bind() in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
return false;
}
ipv6_mreq addrm;
addrm.ipv6mr_interface = _ifIndex;
inet_pton(AF_INET6, config->ipAddress, &addrm.ipv6mr_multiaddr);
if (setsockopt(_sockfdMcast, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &addrm, sizeof(addrm)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s IPV6_ADD_MEMBERSHIP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
close();
return false;
}
optval = 1;
if (setsockopt(_sockfdMcast, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s IPV6_MULTICAST_LOOP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
close();
return false;
}
_gIpAddr.sin6_family = AF_INET6;
_gIpAddr.sin6_port = _gPortNo;
memcpy(&_gIpAddr.sin6_addr, (const void*) &addrm.ipv6mr_multiaddr, sizeof(addrm.ipv6mr_multiaddr));
_gIpAddrStr = strdup(config->ipAddress);
return true;
}
bool LDtls6Port::isUnicast()
{
return (_castStat == STAT_UNICAST);
}
int LDtls6Port::unicast(const uint8_t *buf, uint32_t length)
{
int status = SSL_write(_ssl, buf, length);
if (status <= 0)
{
int rc = 0;
SSL_get_error(_ssl, rc);
DISPLAY("errno == %d in LDtls6Port::unicast\n", rc);
}
else
{
D_NWLOG("sendto gateway via DTLS6 ");
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34msendto the gateway via SSL ");
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
}
return status;
}
int LDtls6Port::multicast(const uint8_t *buf, uint32_t length)
{
char sbuf[SCREEN_BUFF_SIZE];
char portStr[8];
sprintf(portStr, "%d", ntohs(_gIpAddr.sin6_port));
int status = ::sendto(_sockfdMcast, buf, length, 0, (sockaddr*) &_gIpAddr, sizeof(_gIpAddr));
if (status < 0)
{
DISPLAY("\033[0m\033[0;31merrno == %d in LDtls6Port::multicast\033[0m\033[0;37m\n", errno);
return errno;
}
else
{
D_NWLOG("multicast to [%s]:%-6s", _gIpAddrStr, portStr);
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
memset(sbuf, 0, SCREEN_BUFF_SIZE);
int pos = 0;
sprintf(sbuf, "\033[0;34mmulticast to [%s]:%-6s", _gIpAddrStr, portStr);
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
}
bool LDtls6Port::checkRecvBuf()
{
timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 50000; // 50 msec
uint8_t buf[2];
fd_set recvfds;
int maxSock = 0;
FD_ZERO(&recvfds);
if (_sockfdMcast)
{
FD_SET(_sockfdMcast, &recvfds);
}
if (_sockfdSsl)
{
FD_SET(_sockfdSsl, &recvfds);
}
if (_sockfdMcast > _sockfdSsl)
{
maxSock = _sockfdMcast;
}
else
{
maxSock = _sockfdSsl;
}
select(maxSock + 1, &recvfds, 0, 0, &timeout);
if (FD_ISSET(_sockfdMcast, &recvfds))
{
if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_MULTICAST;
return true;
}
}
else if (FD_ISSET(_sockfdSsl, &recvfds))
{
if (::recv(_sockfdSsl, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_castStat = STAT_SSL;
return true;
}
}
_castStat = STAT_NONE;
return false;
}
int LDtls6Port::recv(uint8_t *buf, uint16_t len, bool flg, in6_addr *ipAddressPtr, in_port_t *portPtr)
{
int flags = flg ? MSG_DONTWAIT : 0;
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
}
int LDtls6Port::recvfrom(uint8_t *buf, uint16_t length, int flags, in6_addr *ipAddressPtr, in_port_t *portPtr)
{
sockaddr_in6 sender;
int status = 0;
socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen);
char addrBuf[INET6_ADDRSTRLEN];
if (_castStat == STAT_SSL)
{
D_NWLOG("Ucast ");
if (SSL_read(_ssl, buf, length) == 0)
{
return 0;
}
}
else if (_castStat == STAT_MULTICAST)
{
D_NWLOG("Mcast ");
status = ::recvfrom(_sockfdMcast, buf, length, flags, (sockaddr*) &sender, &addrlen);
}
else
{
return 0;
}
if (status < 0 && errno != EAGAIN)
{
D_NWLOG("\033[0m\033[0;31merrno == %d in LDtls6Port::recvfrom \033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merrno == %d in LDtls6Port::recvfrom \033[0m\033[0;37m\n", errno);
}
else if (status > 0)
{
inet_ntop(AF_INET6, &sender.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
memcpy(ipAddressPtr->s6_addr, (const void*) sender.sin6_addr.s6_addr, sizeof(sender.sin6_addr.s6_addr));
*portPtr = sender.sin6_port;
D_NWLOG("recved %-15s:%-6u", addrBuf, htons(*portPtr));
for (uint16_t i = 0; i < status; i++)
{
D_NWLOG(" %02x", *(buf + i));
}D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", addrBuf, htons(*portPtr));
pos = strlen(sbuf);
for (uint16_t i = 0; i < status; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
else
{
return 0;
}
return status;
}
int LDtls6Port::sslConnect(in6_addr ipAddress, in_port_t portNo)
{
int optval = 1;
if (_ssl != 0)
{
D_NWLOG("LDtls6Port::sslConnect SSL exists.\n");
SSL_shutdown(_ssl);
SSL_free(_ssl);
_sockfdSsl = 0;
_ssl = 0;
}
if (_sockfdSsl > 0)
{
D_NWLOG("LDtls6Port::sslConnect socket exists.\n");
::close(_sockfdSsl);
}
_sockfdSsl = socket(AF_INET6, SOCK_DGRAM, 0);
if (_sockfdSsl <= 0)
{
D_NWLOG("LDtls6Port::sslConnect Can't create a socket\n");
return -1;
}
optval = 1;
setsockopt(_sockfdSsl, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
setsockopt(_sockfdSsl, SOL_SOCKET, SO_REUSEADDR || SO_REUSEPORT, &optval, sizeof(optval));
if (_ifIndex > 0)
{
#ifdef __APPLE__
setsockopt(_sockfdSsl, IPPROTO_IP, IP_BOUND_IF, &_ifIndex, sizeof(_ifIndex));
#else
setsockopt(_sockfdSsl, SOL_SOCKET, SO_BINDTODEVICE, _interfaceName.c_str(), _interfaceName.size());
#endif
}
sockaddr_in6 addr;
addr.sin6_family = AF_INET6;
addr.sin6_port = _uPortNo;
addr.sin6_addr = in6addr_any;
if (::bind(_sockfdSsl, (struct sockaddr*) &addr, sizeof(addr)) < 0)
{
::close(_sockfdSsl);
D_NWLOG("LDtlsPort::sslConnect Can't bind a socket\n");
return -1;
}
// Destination is a gateway address and portNo
int rc = 0;
sockaddr_in6 dest;
dest.sin6_family = AF_INET6;
dest.sin6_port = portNo;
memcpy(dest.sin6_addr.s6_addr, (const void*) ipAddress.s6_addr, sizeof(ipAddress.s6_addr));
BIO *cbio = BIO_new_dgram(_sockfdSsl, BIO_NOCLOSE);
if (connect(_sockfdSsl, (sockaddr*) &dest, sizeof(sockaddr_in6)) < 0)
{
D_NWLOG("socket can't connect %s\n",strerror(errno));
return -1;
}
if (BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dest) <0)
{
D_NWLOG("BIO_ctrl %s\n",strerror(errno));
return -1;
}
_ssl = SSL_new(_ctx);
if (_ssl == nullptr)
{
D_NWLOG("SSL_new %s\n",strerror(errno));
return -1;
}
SSL_set_bio(_ssl, cbio, cbio);
#ifdef DEBUG_NW
char addrBuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &dest.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
D_NWLOG("connect to %-15s:%-6u\n", addrBuf, ntohs(dest.sin6_port));
#endif
timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
BIO_ctrl(cbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
errno = 0;
int stat = SSL_connect(_ssl);
if (stat != 1)
{
rc = -1;
D_NWLOG("SSL fail to connect %s\n",strerror(errno));
}
else
{
rc = 1;
D_NWLOG("SSL connected\n");
}
return rc;
}
int verify_cert(int ok, X509_STORE_CTX *ctx)
{
return 1;
}
#endif

View File

@@ -0,0 +1,122 @@
/**************************************************************************************
* Copyright (c) 2021, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef NETWORKDTLS6_H_
#define NETWORKDTLS6_H_
#ifdef DTLS6
#include <sys/time.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <poll.h>
#define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
#define STAT_NONE 0
#define STAT_UNICAST 1
#define STAT_MULTICAST 2
#define STAT_SSL 3
using namespace std;
namespace linuxAsyncClient {
/*========================================
Class LDtls6Port
=======================================*/
class LDtls6Port
{
friend class LNetwork;
public:
LDtls6Port();
virtual ~LDtls6Port();
bool open(LUdp6Config* config);
int unicast(const uint8_t *buf, uint32_t length);
int multicast( const uint8_t* buf, uint32_t length );
int recv(uint8_t* buf, uint16_t len, bool nonblock, in6_addr* ipaddress, in_port_t* port );
int recv(uint8_t* buf, int flags);
bool checkRecvBuf();
bool isUnicast();
SSL* getSSL(void);
int sslConnect(in6_addr ipAddress, uint16_t port);
private:
void close();
int recvfrom ( uint8_t* buf, uint16_t len, int flags, in6_addr* ipaddress, in_port_t* port );
int _sockfdMcast;
int _sockfdSsl;
SSL_CTX *_ctx;
SSL *_ssl;
in_port_t _gPortNo;
in_port_t _uPortNo;
sockaddr_in6 _gIpAddr;
char *_gIpAddrStr;
uint32_t _ifIndex;
string _interfaceName;
uint8_t _castStat;
bool _disconReq;
};
#define NO_ERROR 0
#define PACKET_EXCEEDS_LENGTH 1
/*===========================================
Class Network
============================================*/
class LNetwork: public LDtls6Port
{
public:
LNetwork();
~LNetwork();
int broadcast(const uint8_t* payload, uint16_t payloadLen);
int unicast(const uint8_t* payload, uint16_t payloadLen);
void setGwAddress(void);
void resetGwAddress(void);
bool initialize(LUdp6Config* config);
uint8_t* getMessage(int* len);
bool isBroadcastable();
int sslConnect(void);
private:
void setSleep();
int readApiFrame(void);
in6_addr _gwIpAddress;
in6_addr _ipAddress;
in_port_t _gwPortNo;
in_port_t _portNo;
int _returnCode;
bool _sleepflg;
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
};
} /* end of namespace */
#endif /* DTLS6 */
#endif /* NETWORKDTLS6_H_ */

View File

@@ -0,0 +1,286 @@
/**************************************************************************************
* Copyright (c) 2021, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifdef RFCOMM
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include "LMqttsnClientApp.h"
#include "LNetworkRfcomm.h"
#include "LTimer.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern uint16_t getUint16(const uint8_t* pos);
extern uint32_t getUint32(const uint8_t* pos);
extern LScreen* theScreen;
extern bool theClientMode;
extern LRfcommConfig theNetcon;
/*=========================================
Class LNetwork
=========================================*/
LNetwork::LNetwork()
{
_sleepflg = false;
_returnCode = 0;
}
LNetwork::~LNetwork()
{
}
int LNetwork::broadcast(const uint8_t* xmitData, uint16_t dataLen)
{
return LRfcommPort::unicast(xmitData, dataLen);
}
int LNetwork::unicast(const uint8_t* xmitData, uint16_t dataLen)
{
return LRfcommPort::unicast(xmitData, dataLen);
}
uint8_t* LNetwork::getMessage(int* len)
{
*len = 0;
if (checkRecvBuf())
{
uint16_t recvLen = LRfcommPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false);
if (recvLen < 0)
{
*len = recvLen;
return 0;
}
else
{
if (_rxDataBuf[0] == 0x01)
{
*len = getUint16(_rxDataBuf + 1);
}
else
{
*len = _rxDataBuf[0];
}
return _rxDataBuf;
}
}
return 0;
}
void LNetwork::setGwAddress(void)
{
}
void LNetwork::setFixedGwAddress(void)
{
_channel = LRfcommPort::_channel;
str2ba( theNetcon.gwAddress, (bdaddr_t*)_gwAddress);
}
bool LNetwork::initialize(LRfcommConfig* config)
{
return LRfcommPort::open(config);
}
void LNetwork::setSleep()
{
_sleepflg = true;
}
bool LNetwork::isBroadcastable()
{
return false;
}
/*=========================================
Class RFCOMM Stack
=========================================*/
LRfcommPort::LRfcommPort()
{
_disconReq = false;
_sockRfcomm = 0;
_channel = 0;
}
LRfcommPort::~LRfcommPort()
{
close();
}
void LRfcommPort::close()
{
if (_sockRfcomm > 0)
{
::close(_sockRfcomm);
_sockRfcomm = 0;
}
}
bool LRfcommPort::open(LRfcommConfig* config)
{
const int reuse = 1;
str2ba(config->gwAddress, (bdaddr_t*)_gwAddress);
_channel = config->channel;
if (_channel == 0 || _gwAddress == 0 )
{
D_NWLOG("\033[0m\033[0;31merror Bluetooth Address in LRfcommPort::open\033[0m\033[0;37m\n");
DISPLAY("\033[0m\033[0;31m\nerror Bluetooth Address in LRfcommPort::open\033[0m\033[0;37m\n");
return false;
}
_sockRfcomm = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
if (_sockRfcomm < 0)
{
D_NWLOG("\033[0m\033[0;31merror Can't create socket in LRfcommPort::open\033[0m\033[0;37m\n");
DISPLAY("\033[0m\033[0;31m\nerror Can't create socket in LRfcommPort::open\033[0m\033[0;37m\n");
return false;
}
setsockopt(_sockRfcomm, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
struct sockaddr_rc addru = { 0 };
addru.rc_family = AF_BLUETOOTH;
addru.rc_channel = _channel;
memcpy(&addru.rc_bdaddr, _gwAddress, 6);
char bufgw[30];
ba2str(&addru.rc_bdaddr, bufgw);
DISPLAY("GW MAC = %s RFCOMM CH = %d\n", bufgw, addru.rc_channel);
// connect to server
errno = 0;
int status = connect(_sockRfcomm, (struct sockaddr *) &addru, sizeof(addru));
if (status < 0)
{
D_NWLOG("\033[0m\033[0;31merror = %d Can't connect to GW in LRfcommPort::open\033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merror = %d Can't connect to GW Ble socket in LRfcommPort::open\033[0m\033[0;37m\n",errno);
close();
return false;
}
return true;
}
int LRfcommPort::unicast(const uint8_t* buf, uint32_t length)
{
int status = ::write(_sockRfcomm, buf, length);
if (status < 0)
{
D_NWLOG("errno == %d in LRfcommPort::unicast\n", errno);
DISPLAY("errno == %d in LRfcommPort::unicast\n", errno);
}
else
{
D_NWLOG("sendto %-2d", _channel);
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34msendto %-2dch", _channel);
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
}
return status;
}
bool LRfcommPort::checkRecvBuf()
{
uint8_t buf[2];
if (::recv(_sockRfcomm, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
return true;
}
return false;
}
int LRfcommPort::recv(uint8_t* buf, uint16_t length, bool flg)
{
int flags = flg ? MSG_DONTWAIT : 0;
int status = ::recv(_sockRfcomm, buf, length, flags);
if (status < 0 && errno != EAGAIN)
{
D_NWLOG("\033[0m\033[0;31merrno = %d in LRfcommPort::recv \033[0m\033[0;37m\n", errno);
DISPLAY("\033[0m\033[0;31merrno = %d in LRfcommPort::recv \033[0m\033[0;37m\n", errno);
}
else if (status > 0)
{
D_NWLOG("\nrecved ");
for (uint16_t i = 0; i < status; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34mrecved ");
pos = strlen(sbuf);
for (uint16_t i = 0; i < status; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
else
{
return 0;
}
return status;
}
#endif

View File

@@ -0,0 +1,102 @@
/**************************************************************************************
* Copyright (c) 2021, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef NETWORKRFCOMM_H_
#define NETWORKRFCOMM_H_
#ifdef RFCOMM
#include <sys/time.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <bluetooth/bluetooth.h>
#define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
#define STAT_UNICAST 1
#define STAT_MULTICAST 2
using namespace std;
namespace linuxAsyncClient
{
/*========================================
Class LRfcommPort
=======================================*/
class LRfcommPort
{
friend class LNetwork;
public:
LRfcommPort();
virtual ~LRfcommPort();
bool open(LRfcommConfig* config);
int unicast(const uint8_t* buf, uint32_t length);
int recv(uint8_t* buf, uint16_t len, bool nonblock);
bool checkRecvBuf();
bool isUnicast();
private:
void close();
int _sockRfcomm;
uint8_t _gwAddress[6];
uint8_t _channel;
bool _disconReq;
};
#define NO_ERROR 0
#define PACKET_EXCEEDS_LENGTH 1
/*===========================================
Class Network
============================================*/
class LNetwork: public LRfcommPort
{
public:
LNetwork();
~LNetwork();
int broadcast(const uint8_t* payload, uint16_t payloadLen);
int unicast(const uint8_t* payload, uint16_t payloadLen);
void setGwAddress(void);
void resetGwAddress(void);
void setFixedGwAddress(void);
bool initialize(LRfcommConfig* config);
uint8_t* getMessage(int* len);
bool isBroadcastable();
private:
void setSleep();
int readApiFrame(void);
int _returnCode;
bool _sleepflg;
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
};
} /* end of namespace */
#endif /* RFCOMM */
#endif /* NETWORKRFCOM_H_ */

View File

@@ -13,6 +13,7 @@
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/ **************************************************************************************/
#ifdef UDP
#include <stdio.h> #include <stdio.h>
#include <sys/time.h> #include <sys/time.h>
@@ -23,368 +24,428 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h>
#include <termios.h> #include <termios.h>
#include "LMqttsnClientApp.h"
#include "LNetworkUdp.h" #include "LNetworkUdp.h"
#include "LTimer.h" #include "LTimer.h"
#include "LScreen.h" #include "LScreen.h"
#include "LMqttsnClientApp.h"
using namespace std; using namespace std;
using namespace linuxAsyncClient; using namespace linuxAsyncClient;
extern uint16_t getUint16(const uint8_t* pos); extern uint16_t getUint16(const uint8_t *pos);
extern uint32_t getUint32(const uint8_t* pos); extern uint32_t getUint32(const uint8_t *pos);
extern LScreen* theScreen; extern LScreen *theScreen;
extern bool theClientMode; extern bool theClientMode;
/*========================================= /*=========================================
Class LNetwork Class LNetwork
=========================================*/ =========================================*/
LNetwork::LNetwork(){ LNetwork::LNetwork()
_sleepflg = false; {
resetGwAddress(); _sleepflg = false;
resetGwAddress();
} }
LNetwork::~LNetwork(){ LNetwork::~LNetwork()
{
} }
int LNetwork::broadcast(const uint8_t* xmitData, uint16_t dataLen){ int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
return LUdpPort::multicast(xmitData, (uint32_t)dataLen); {
return LUdpPort::multicast(xmitData, (uint32_t) dataLen);
} }
int LNetwork::unicast(const uint8_t* xmitData, uint16_t dataLen){ int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
return LUdpPort::unicast(xmitData, dataLen, _gwIpAddress, _gwPortNo); {
return LUdpPort::unicast(xmitData, dataLen, _gwIpAddress, _gwPortNo);
} }
uint8_t* LNetwork::getMessage(int *len)
{
*len = 0;
if (checkRecvBuf())
{
uint16_t recvLen = LUdpPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
if (_gwIpAddress && isUnicast() && (_ipAddress != _gwIpAddress) && (_portNo != _gwPortNo))
{
return 0;
}
uint8_t* LNetwork::getMessage(int* len){ if (recvLen < 0)
*len = 0; {
if (checkRecvBuf()){ *len = recvLen;
uint16_t recvLen = LUdpPort::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo); return 0;
if(_gwIpAddress && isUnicast() && (_ipAddress != _gwIpAddress) && (_portNo != _gwPortNo)){ }
return 0; else
} {
if (_rxDataBuf[0] == 0x01)
if(recvLen < 0){ {
*len = recvLen; *len = getUint16(_rxDataBuf + 1);
return 0; }
}else{ else
if(_rxDataBuf[0] == 0x01){ {
*len = getUint16(_rxDataBuf + 1 ); *len = _rxDataBuf[0];
}else{ }
*len = _rxDataBuf[0]; //if(recvLen != *len){
} // *len = 0;
if(recvLen != *len){ // return 0;
*len = 0; //}else{
return 0; return _rxDataBuf;
}else{ //}
return _rxDataBuf; }
} }
} return 0;
}
return 0;
} }
void LNetwork::setGwAddress(void){ void LNetwork::setGwAddress(void)
_gwPortNo = _portNo; {
_gwIpAddress = _ipAddress; _gwPortNo = _portNo;
_gwIpAddress = _ipAddress;
} }
void LNetwork::setFixedGwAddress(void){ void LNetwork::setFixedGwAddress(void)
{
_gwPortNo = LUdpPort::_gPortNo; _gwPortNo = LUdpPort::_gPortNo;
_gwIpAddress = LUdpPort::_gIpAddr; _gwIpAddress = LUdpPort::_gIpAddr;
} }
void LNetwork::resetGwAddress(void){ void LNetwork::resetGwAddress(void)
_gwIpAddress = 0; {
_gwPortNo = 0; _gwIpAddress = 0;
_gwPortNo = 0;
} }
bool LNetwork::initialize(LUdpConfig *config)
bool LNetwork::initialize(LUdpConfig config){ {
return LUdpPort::open(config); return LUdpPort::open(config);
} }
void LNetwork::setSleep(){ void LNetwork::setSleep()
_sleepflg = true; {
_sleepflg = true;
} }
bool LNetwork::isBroadcastable()
{
return true;
}
/*========================================= /*=========================================
Class udpStack Class udpStack
=========================================*/ =========================================*/
LUdpPort::LUdpPort(){ LUdpPort::LUdpPort()
{
_disconReq = false; _disconReq = false;
_sockfdUcast = -1; _sockfdUcast = -1;
_sockfdMcast = -1; _sockfdMcast = -1;
_castStat = 0; _castStat = 0;
} }
LUdpPort::~LUdpPort(){ LUdpPort::~LUdpPort()
{
close(); close();
} }
void LUdpPort::close()
void LUdpPort::close(){ {
if(_sockfdMcast > 0){ if (_sockfdMcast > 0)
::close( _sockfdMcast); {
_sockfdMcast = -1; ::close(_sockfdMcast);
if(_sockfdUcast > 0){ _sockfdMcast = -1;
::close( _sockfdUcast); if (_sockfdUcast > 0)
_sockfdUcast = -1; {
} ::close(_sockfdUcast);
} _sockfdUcast = -1;
}
}
} }
bool LUdpPort::open(LUdpConfig config){ bool LUdpPort::open(LUdpConfig *config)
const int reuse = 1; {
char loopch = 1; int optval = 0;
uint8_t sav = config.ipAddress[3]; uint8_t sav = config->ipAddress[3];
config.ipAddress[3] = config.ipAddress[0]; config->ipAddress[3] = config->ipAddress[0];
config.ipAddress[0] = sav; config->ipAddress[0] = sav;
sav = config.ipAddress[2]; sav = config->ipAddress[2];
config.ipAddress[2] = config.ipAddress[1]; config->ipAddress[2] = config->ipAddress[1];
config.ipAddress[1] = sav; config->ipAddress[1] = sav;
_gPortNo = htons(config.gPortNo); _gPortNo = htons(config->gPortNo);
_gIpAddr = getUint32((const uint8_t*)config.ipAddress); _gIpAddr = getUint32((const uint8_t*) config->ipAddress);
_uPortNo = htons(config.uPortNo); _uPortNo = htons(config->uPortNo);
if( _gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0){ if (_gPortNo == 0 || _gIpAddr == 0 || _uPortNo == 0)
return false; {
} return false;
}
_sockfdUcast = socket(AF_INET, SOCK_DGRAM, 0); _sockfdUcast = socket(AF_INET, SOCK_DGRAM, 0);
if (_sockfdUcast < 0){ if (_sockfdUcast < 0)
return false; {
} return false;
}
setsockopt(_sockfdUcast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); optval = 1;
setsockopt(_sockfdUcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
struct sockaddr_in addr; sockaddr_in addr;
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = _uPortNo; addr.sin_port = _uPortNo;
addr.sin_addr.s_addr = INADDR_ANY; addr.sin_addr.s_addr = INADDR_ANY;
if( ::bind ( _sockfdUcast, (struct sockaddr*)&addr, sizeof(addr)) <0){ if (::bind(_sockfdUcast, (struct sockaddr*) &addr, sizeof(addr)) < 0)
return false; {
} D_NWLOG("\033[0m\033[0;31merror %s ::bind() to unicast address\033[0m\033[0;37m\n", strerror(errno));
return false;
}
_sockfdMcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); _sockfdMcast = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (_sockfdMcast < 0){ if (_sockfdMcast < 0)
return false; {
} return false;
}
struct sockaddr_in addrm; sockaddr_in addrm;
addrm.sin_family = AF_INET; addrm.sin_family = AF_INET;
addrm.sin_port = _gPortNo; addrm.sin_port = _gPortNo;
addrm.sin_addr.s_addr = htonl(INADDR_ANY); addrm.sin_addr.s_addr = INADDR_ANY;
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); optval = 1;
setsockopt(_sockfdMcast, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if( ::bind ( _sockfdMcast, (struct sockaddr*)&addrm, sizeof(addrm)) <0){ if (::bind(_sockfdMcast, (struct sockaddr*) &addrm, sizeof(addrm)) < 0)
return false; {
} D_NWLOG("\033[0m\033[0;31merror %s ::bind() in UdpPort::open\033[0m\033[0;37m\n", strerror(errno));
return false;
}
if(setsockopt(_sockfdMcast, IPPROTO_IP, IP_MULTICAST_LOOP,(char*)&loopch, sizeof(loopch)) <0 ){ ip_mreq mreq;
D_NWLOG("\033[0m\033[0;31merror IP_MULTICAST_LOOP in UdpPPort::open\033[0m\033[0;37m\n"); mreq.imr_interface.s_addr = INADDR_ANY;
DISPLAY("\033[0m\033[0;31m\nerror IP_MULTICAST_LOOP in UdpPPort::open\033[0m\033[0;37m\n"); mreq.imr_multiaddr.s_addr = _gIpAddr;
close();
return false;
}
ip_mreq mreq; if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
mreq.imr_interface.s_addr = INADDR_ANY; {
mreq.imr_multiaddr.s_addr = _gIpAddr; D_NWLOG("\033[0m\033[0;31merror IP_ADD_MEMBERSHIP in UdpPort::open\033[0m\033[0;37m\n");
close();
return false;
}
if( setsockopt(_sockfdMcast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq) )< 0){ optval= 1;
D_NWLOG("\033[0m\033[0;31merror IP_ADD_MEMBERSHIP in UdpPort::open\033[0m\033[0;37m\n"); if (setsockopt(_sockfdMcast, IPPROTO_IP, IP_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
DISPLAY("\033[0m\033[0;31m\nerror IP_ADD_MEMBERSHIP in UdpPort::open\033[0m\033[0;37m\n"); {
close(); D_NWLOG("\033[0m\033[0;31merror IP_MULTICAST_LOOP in UdpPPort::open\033[0m\033[0;37m\n");
return false; close();
} return false;
return true; }
return true;
} }
bool LUdpPort::isUnicast(){ bool LUdpPort::isUnicast()
return ( _castStat == STAT_UNICAST); {
return (_castStat == STAT_UNICAST);
} }
int LUdpPort::unicast(const uint8_t *buf, uint32_t length, uint32_t ipAddress, uint16_t port)
{
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = port;
dest.sin_addr.s_addr = ipAddress;
int LUdpPort::unicast(const uint8_t* buf, uint32_t length, uint32_t ipAddress, uint16_t port ){ int status = ::sendto(_sockfdUcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
struct sockaddr_in dest; if (status < 0)
dest.sin_family = AF_INET; {
dest.sin_port = port; D_NWLOG("errno == %d in UdpPort::unicast\n", errno);
dest.sin_addr.s_addr = ipAddress; }
else
{
D_NWLOG("sendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(port));
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
} D_NWLOG("\n");
int status = ::sendto( _sockfdUcast, buf, length, 0, (const sockaddr*)&dest, sizeof(dest) ); if (!theClientMode)
if( status < 0){ {
D_NWLOG("errno == %d in UdpPort::unicast\n", errno); char sbuf[SCREEN_BUFF_SIZE];
DISPLAY("errno == %d in UdpPort::unicast\n", errno); int pos = 0;
}else{ sprintf(sbuf, "\033[0;34msendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(port));
D_NWLOG("sendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(port)); pos = strlen(sbuf);
for(uint16_t i = 0; i < length ; i++){ for (uint16_t i = 0; i < length; i++)
D_NWLOG(" %02x", *(buf + i)); {
} sprintf(sbuf + pos, " %02x", *(buf + i));
D_NWLOG("\n"); if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
{
if ( !theClientMode ) break;
{ }
char sbuf[SCREEN_BUFF_SIZE]; pos += 3;
int pos = 0; }
sprintf(sbuf,"\033[0;34msendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(port)); sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
pos = strlen(sbuf); }
for(uint16_t i = 0; i < length ; i++){ }
sprintf(sbuf + pos, " %02x", *(buf + i)); return status;
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20 ) // -20 for Escape sequence
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
}
return status;
} }
int LUdpPort::multicast(const uint8_t *buf, uint32_t length)
{
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = _gPortNo;
dest.sin_addr.s_addr = _gIpAddr;
int LUdpPort::multicast( const uint8_t* buf, uint32_t length ){ int status = ::sendto(_sockfdMcast, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
struct sockaddr_in dest; if (status < 0)
dest.sin_family = AF_INET; {
dest.sin_port = _gPortNo; D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno);
dest.sin_addr.s_addr = _gIpAddr; return errno;
}
else
{
D_NWLOG("sendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(_gPortNo));
int status = ::sendto( _sockfdMcast, buf, length, 0, (const sockaddr*)&dest, sizeof(dest) ); for (uint16_t i = 0; i < length; i++)
if( status < 0){ {
D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno); D_NWLOG(" %02x", *(buf + i));
DISPLAY("\033[0m\033[0;31merrno == %d in UdpPort::multicast\033[0m\033[0;37m\n", errno); } D_NWLOG("\n");
return errno;
}else{
D_NWLOG("sendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(_gPortNo));
for(uint16_t i = 0; i < length ; i++){ if (!theClientMode)
D_NWLOG(" %02x", *(buf + i)); {
DISPLAY(" %02x", *(buf + i)); char sbuf[SCREEN_BUFF_SIZE];
} int pos = 0;
D_NWLOG("\n"); sprintf(sbuf, "\033[0;34msendto %-15s:%-6u", inet_ntoa(dest.sin_addr), htons(_gPortNo));
pos = strlen(sbuf);
if ( !theClientMode ) for (uint16_t i = 0; i < length; i++)
{ {
char sbuf[SCREEN_BUFF_SIZE]; sprintf(sbuf + pos, " %02x", *(buf + i));
int pos = 0; if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
sprintf(sbuf,"\033[0;34msendto %-15s:%-6u",inet_ntoa(dest.sin_addr),htons(_gPortNo)); {
pos = strlen(sbuf); break;
for(uint16_t i = 0; i < length ; i++){ }
sprintf(sbuf + pos, " %02x", *(buf + i)); pos += 3;
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20 ) }
{ sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
break; theScreen->display(sbuf);
} }
pos += 3; return status;
} }
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
} }
bool LUdpPort::checkRecvBuf(){ bool LUdpPort::checkRecvBuf()
struct timeval timeout; {
timeout.tv_sec = 0; struct timeval timeout;
timeout.tv_usec = 50000; // 50 msec timeout.tv_sec = 0;
timeout.tv_usec = 50000; // 50 msec
uint8_t buf[2]; uint8_t buf[2];
fd_set recvfds; fd_set recvfds;
int maxSock = 0; int maxSock = 0;
FD_ZERO(&recvfds); FD_ZERO(&recvfds);
FD_SET(_sockfdUcast, &recvfds); FD_SET(_sockfdUcast, &recvfds);
FD_SET(_sockfdMcast, &recvfds); FD_SET(_sockfdMcast, &recvfds);
if(_sockfdMcast > _sockfdUcast){ if (_sockfdMcast > _sockfdUcast)
maxSock = _sockfdMcast; {
}else{ maxSock = _sockfdMcast;
maxSock = _sockfdUcast; }
} else
{
maxSock = _sockfdUcast;
}
select(maxSock + 1, &recvfds, 0, 0, &timeout); select(maxSock + 1, &recvfds, 0, 0, &timeout);
if(FD_ISSET(_sockfdUcast, &recvfds)){ if (FD_ISSET(_sockfdUcast, &recvfds))
if( ::recv(_sockfdUcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0){ {
_castStat = STAT_UNICAST; if (::recv(_sockfdUcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
return true; {
} _castStat = STAT_UNICAST;
}else if(FD_ISSET(_sockfdMcast, &recvfds)){ return true;
if( ::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0){ }
_castStat = STAT_MULTICAST; }
return true; else if (FD_ISSET(_sockfdMcast, &recvfds))
} {
} if (::recv(_sockfdMcast, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
_castStat = 0; {
return false; _castStat = STAT_MULTICAST;
return true;
}
}
_castStat = 0;
return false;
} }
int LUdpPort::recv(uint8_t* buf, uint16_t len, bool flg, uint32_t* ipAddressPtr, uint16_t* portPtr){ int LUdpPort::recv(uint8_t *buf, uint16_t len, bool flg, uint32_t *ipAddressPtr, uint16_t *portPtr)
int flags = flg ? MSG_DONTWAIT : 0; {
return recvfrom (buf, len, flags, ipAddressPtr, portPtr ); int flags = flg ? MSG_DONTWAIT : 0;
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
} }
int LUdpPort::recvfrom (uint8_t* buf, uint16_t length, int flags, uint32_t* ipAddressPtr, uint16_t* portPtr ){ int LUdpPort::recvfrom(uint8_t *buf, uint16_t length, int flags, uint32_t *ipAddressPtr, uint16_t *portPtr)
struct sockaddr_in sender; {
int status; struct sockaddr_in sender;
socklen_t addrlen = sizeof(sender); int status;
memset(&sender, 0, addrlen); socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen);
if(isUnicast()){ if (isUnicast())
status = ::recvfrom( _sockfdUcast, buf, length, flags, (struct sockaddr*)&sender, &addrlen ); {
}else if(_castStat == STAT_MULTICAST){ D_NWLOG("Ucast ");
status = ::recvfrom( _sockfdMcast, buf, length, flags, (struct sockaddr*)&sender, &addrlen ); status = ::recvfrom(_sockfdUcast, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
}else{ }
return 0; else if (_castStat == STAT_MULTICAST)
} {
D_NWLOG("Mcast ");
status = ::recvfrom(_sockfdMcast, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
}
else
{
return 0;
}
if (status < 0 && errno != EAGAIN) { if (status < 0 && errno != EAGAIN)
D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::recvfrom \033[0m\033[0;37m\n", errno); {
DISPLAY("\033[0m\033[0;31merrno == %d in UdpPort::recvfrom \033[0m\033[0;37m\n", errno); D_NWLOG("\033[0m\033[0;31merrno == %d in UdpPort::recvfrom \033[0m\033[0;37m\n", errno);
}else if(status > 0){ }
*ipAddressPtr = sender.sin_addr.s_addr; else if (status > 0)
*portPtr = sender.sin_port; {
D_NWLOG("\nrecved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr)); *ipAddressPtr = sender.sin_addr.s_addr;
for(uint16_t i = 0; i < status ; i++){ *portPtr = sender.sin_port;
D_NWLOG(" %02x", *(buf + i)); D_NWLOG("recved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr));
} for (uint16_t i = 0; i < status; i++)
D_NWLOG("\n"); {
D_NWLOG(" %02x", *(buf + i));
} D_NWLOG("\n");
if ( !theClientMode ) if (!theClientMode)
{ {
char sbuf[SCREEN_BUFF_SIZE]; char sbuf[SCREEN_BUFF_SIZE];
int pos = 0; int pos = 0;
sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u",inet_ntoa(sender.sin_addr), htons(*portPtr)); sprintf(sbuf, "\033[0;34mrecved %-15s:%-6u", inet_ntoa(sender.sin_addr), htons(*portPtr));
pos = strlen(sbuf); pos = strlen(sbuf);
for(uint16_t i = 0; i < status ; i++){ for (uint16_t i = 0; i < status; i++)
sprintf(sbuf + pos, " %02x", *(buf + i)); {
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20 ) sprintf(sbuf + pos, " %02x", *(buf + i));
{ if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
break; {
} break;
pos += 3; }
} pos += 3;
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n"); }
theScreen->display(sbuf); sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
} theScreen->display(sbuf);
return status; }
}else{ return status;
return 0; }
} else
return status; {
return 0;
}
return status;
} }
#endif

View File

@@ -17,6 +17,8 @@
#ifndef NETWORKUDP_H_ #ifndef NETWORKUDP_H_
#define NETWORKUDP_H_ #define NETWORKUDP_H_
#ifdef UDP
#include <sys/time.h> #include <sys/time.h>
#include <iostream> #include <iostream>
#include <sys/types.h> #include <sys/types.h>
@@ -27,8 +29,6 @@
#include <string> #include <string>
#include <arpa/inet.h> #include <arpa/inet.h>
#include "LMqttsnClientApp.h"
#define SOCKET_MAXHOSTNAME 200 #define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5 #define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500 #define SOCKET_MAXRECV 500
@@ -49,7 +49,7 @@ public:
LUdpPort(); LUdpPort();
virtual ~LUdpPort(); virtual ~LUdpPort();
bool open(LUdpConfig config); bool open(LUdpConfig* config);
int unicast(const uint8_t* buf, uint32_t length, uint32_t ipaddress, uint16_t port ); int unicast(const uint8_t* buf, uint32_t length, uint32_t ipaddress, uint16_t port );
int multicast( const uint8_t* buf, uint32_t length ); int multicast( const uint8_t* buf, uint32_t length );
@@ -87,8 +87,9 @@ public:
void setGwAddress(void); void setGwAddress(void);
void resetGwAddress(void); void resetGwAddress(void);
void setFixedGwAddress(void); void setFixedGwAddress(void);
bool initialize(LUdpConfig config); bool initialize(LUdpConfig* config);
uint8_t* getMessage(int* len); uint8_t* getMessage(int* len);
bool isBroadcastable();
private: private:
void setSleep(); void setSleep();
int readApiFrame(void); int readApiFrame(void);
@@ -103,6 +104,6 @@ private:
}; };
} /* end of namespace */ } /* end of namespace */
#endif /* UDP */
#endif /* NETWORKUDP_H_ */ #endif /* NETWORKUDP_H_ */

View File

@@ -0,0 +1,433 @@
/**************************************************************************************
* Copyright (c) 2021, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifdef UDP6
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <netinet/in.h>
#include <net/if.h>
#include "LMqttsnClientApp.h"
#include "LNetworkUdp6.h"
#include "LTimer.h"
#include "LScreen.h"
using namespace std;
using namespace linuxAsyncClient;
extern uint16_t getUint16(const uint8_t *pos);
extern uint32_t getUint32(const uint8_t *pos);
extern LScreen *theScreen;
extern bool theClientMode;
/*=========================================
Class LNetwork
=========================================*/
LNetwork::LNetwork()
{
_sleepflg = false;
resetGwAddress();
}
LNetwork::~LNetwork()
{
}
int LNetwork::broadcast(const uint8_t *xmitData, uint16_t dataLen)
{
return LUdp6Port::multicast(xmitData, (uint32_t) dataLen);
}
int LNetwork::unicast(const uint8_t *xmitData, uint16_t dataLen)
{
return LUdp6Port::unicast(xmitData, dataLen, _gwIpAddress, _gwPortNo);
}
uint8_t* LNetwork::getMessage(int *len)
{
*len = 0;
if (checkRecvBuf())
{
uint16_t recvLen = LUdp6Port::recv(_rxDataBuf, MQTTSN_MAX_PACKET_SIZE, false, &_ipAddress, &_portNo);
int diffAddr = memcmp(_ipAddress.s6_addr, _gwIpAddress.s6_addr, sizeof(_gwIpAddress.s6_addr));
if (isUnicast() && diffAddr && (_portNo != _gwPortNo))
{
return 0;
}
if (recvLen < 0)
{
*len = recvLen;
return 0;
}
else
{
if (_rxDataBuf[0] == 0x01)
{
*len = getUint16(_rxDataBuf + 1);
}
else
{
*len = _rxDataBuf[0];
}
return _rxDataBuf;
}
}
return 0;
}
void LNetwork::setGwAddress(void)
{
memcpy(_gwIpAddress.s6_addr, _ipAddress.s6_addr, sizeof(_gwIpAddress.s6_addr));
_gwPortNo = _portNo;
}
void LNetwork::resetGwAddress(void)
{
memset(_gwIpAddress.s6_addr, 0, sizeof(_gwIpAddress.s6_addr));
_gwPortNo = 0;
}
bool LNetwork::initialize(LUdp6Config *config)
{
return LUdp6Port::open(config);
}
void LNetwork::setSleep()
{
_sleepflg = true;
}
bool LNetwork::isBroadcastable()
{
return true;
}
/*=========================================
Class udp6Stack
=========================================*/
LUdp6Port::LUdp6Port()
{
_disconReq = false;
memset(_pollfds, 0, sizeof(_pollfds));
_sock = 0;
_interface = NULL;
_gIpAddrStr = NULL;
}
LUdp6Port::~LUdp6Port()
{
close();
if (_gIpAddrStr)
{
free(_gIpAddrStr);
}
if (_interface)
{
free(_interface);
}
}
void LUdp6Port::close()
{
for (int i = 0; i < 2; i++)
{
if (_pollfds[i].fd > 0)
{
::close(_pollfds[i].fd);
_pollfds[i].fd = 0;
}
}
}
bool LUdp6Port::open(LUdp6Config *config)
{
int optval = 1;
int sock = 0;
uint32_t ifindex = 0;
sockaddr_in6 addr6;
_gPortNo = htons(config->gPortNo);
_uPortNo = htons(config->uPortNo);
if (_gPortNo == 0 || _uPortNo == 0)
{
return false;
}
/* create a unicast socket */
sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock < 0)
{
return false;
}
optval = 1;
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if (strlen(config->interface) > 0)
{
ifindex = if_nametoindex(config->interface);
#ifdef __APPLE__
setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex));
#else
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, config->interface, strlen(config->interface));
#endif
}
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = _uPortNo;
addr6.sin6_addr = in6addr_any;
if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s ::bind() to unicast address\033[0m\033[0;37m\n", strerror(errno));
return false;
}
_pollfds[0].fd = sock;
_pollfds[0].events = POLLIN;
/* create a multicast socket */
sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock < 0)
{
return false;
}
optval = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval));
memset(&addr6, 0, sizeof(addr6));
addr6.sin6_family = AF_INET6;
addr6.sin6_port = _gPortNo;
addr6.sin6_addr = in6addr_any;
if (::bind(sock, (sockaddr*) &addr6, sizeof(addr6)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s ::bind() in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
return false;
}
ipv6_mreq addrm;
addrm.ipv6mr_interface = ifindex;
inet_pton(AF_INET6, config->ipAddress, &addrm.ipv6mr_multiaddr);
if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &addrm, sizeof(addrm)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s IPV6_ADD_MEMBERSHIP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
close();
return false;
}
optval = 1;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) < 0)
{
D_NWLOG("\033[0m\033[0;31merror %s IPV6_MULTICAST_LOOP in Udp6Port::open\033[0m\033[0;37m\n", strerror(errno));
close();
return false;
}
_pollfds[1].fd = sock;
_pollfds[1].events = POLLIN;
_gIpAddr.sin6_family = AF_INET6;
_gIpAddr.sin6_port = _gPortNo;
memcpy(&_gIpAddr.sin6_addr, (const void*) &addrm.ipv6mr_multiaddr, sizeof(addrm.ipv6mr_multiaddr));
_gIpAddrStr = strdup(config->ipAddress);
return true;
}
int LUdp6Port::unicast(const uint8_t *buf, uint32_t length, in6_addr ipAddress, uint16_t port)
{
struct sockaddr_in6 dest;
dest.sin6_family = AF_INET6;
dest.sin6_port = port;
memcpy(dest.sin6_addr.s6_addr, (const void*) ipAddress.s6_addr, sizeof(ipAddress.s6_addr));
char addrBuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &dest.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
D_NWLOG("unicast to [%s]:%-6u", addrBuf, htons(port));
int status = ::sendto(_pollfds[0].fd, buf, length, 0, (const sockaddr*) &dest, sizeof(dest));
if (status < 0)
{
D_NWLOG(" errno = %d %s in Udp6Port::unicast\n", errno, strerror(errno));
}
else
{
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34municast to [%s[:%-6u", addrBuf, htons(port));
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20) // -20 for Escape sequence
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
}
return status;
}
int LUdp6Port::multicast(const uint8_t *buf, uint32_t length)
{
char sbuf[SCREEN_BUFF_SIZE];
char portStr[8];
sprintf(portStr, "%d", ntohs(_gPortNo));
int status = ::sendto(_pollfds[1].fd, buf, length, 0, (sockaddr*) &_gIpAddr, sizeof(_gIpAddr));
if (status < 0)
{
D_NWLOG("multicast to [%s]:%-6s ", _gIpAddrStr, portStr);
D_NWLOG("\033[0m\033[0;31merrno = %d %s in Udp6Port::multicast\033[0m\033[0;37m\n", errno, strerror(errno));
return errno;
}
else
{
D_NWLOG("multicast to [%s]:%-6s", _gIpAddrStr, portStr);
for (uint16_t i = 0; i < length; i++)
{
D_NWLOG(" %02x", *(buf + i));
}
D_NWLOG("\n");
if (!theClientMode)
{
memset(sbuf, 0, SCREEN_BUFF_SIZE);
int pos = 0;
sprintf(sbuf, "\033[0;34mmulticast to [%s]:%-6s", _gIpAddrStr, portStr);
pos = strlen(sbuf);
for (uint16_t i = 0; i < length; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
}
bool LUdp6Port::checkRecvBuf()
{
uint8_t buf[2];
int cnt = poll(_pollfds, 2, 50); // Timeout 50m secs
if (cnt == 0)
{
return false;
}
for (int i = 0; i < 2; i++)
{
if (_pollfds[i].revents & POLLIN)
{
if (::recv(_pollfds[i].fd, buf, 1, MSG_DONTWAIT | MSG_PEEK) > 0)
{
_sock = _pollfds[i].fd;
return true;
}
}
}
return false;
}
int LUdp6Port::recv(uint8_t *buf, uint16_t len, bool flg, in6_addr *ipAddressPtr, uint16_t *portPtr)
{
int flags = flg ? MSG_DONTWAIT : 0;
return recvfrom(buf, len, flags, ipAddressPtr, portPtr);
}
int LUdp6Port::recvfrom(uint8_t *buf, uint16_t length, int flags, in6_addr *ipAddressPtr, uint16_t *portPtr)
{
struct sockaddr_in6 sender;
int status;
socklen_t addrlen = sizeof(sender);
memset(&sender, 0, addrlen);
char addrBuf[INET6_ADDRSTRLEN];
status = ::recvfrom(_sock, buf, length, flags, (struct sockaddr*) &sender, &addrlen);
if (status < 0 && errno != EAGAIN)
{
D_NWLOG("\033[0m\033[0;31merrno == %d in Udp6Port::recvfrom \033[0m\033[0;37m\n", errno);
}
if (status > 0)
{
inet_ntop(AF_INET6, &sender.sin6_addr, addrBuf, INET6_ADDRSTRLEN);
memcpy(ipAddressPtr->s6_addr, (const void*) sender.sin6_addr.s6_addr, sizeof(sender.sin6_addr.s6_addr));
*portPtr = sender.sin6_port;
if (!theClientMode)
{
char sbuf[SCREEN_BUFF_SIZE];
int pos = 0;
sprintf(sbuf, "\033[0;34mrecv from [%s]:%-6u", addrBuf, htons(*portPtr));
pos = strlen(sbuf);
for (uint16_t i = 0; i < status; i++)
{
sprintf(sbuf + pos, " %02x", *(buf + i));
if (strlen(sbuf) > SCREEN_BUFF_SIZE - 20)
{
break;
}
pos += 3;
}
sprintf(sbuf + strlen(sbuf), "\033[0;37m\n");
theScreen->display(sbuf);
}
return status;
}
else
{
return 0;
}
return status;
}
bool LUdp6Port::isUnicast(void)
{
return (_sock == _pollfds[0].fd && _sock > 0);
}
#endif /* UDP6 */

View File

@@ -0,0 +1,113 @@
/**************************************************************************************
* Copyright (c) 2021, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef NETWORKUDP6_H_
#define NETWORKUDP6_H_
#ifdef UDP6
#include <sys/time.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>
#include <poll.h>
#define SOCKET_MAXHOSTNAME 200
#define SOCKET_MAXCONNECTIONS 5
#define SOCKET_MAXRECV 500
#define SOCKET_MAXBUFFER_LENGTH 500 // buffer size
#define STAT_UNICAST 1
#define STAT_MULTICAST 2
using namespace std;
namespace linuxAsyncClient {
/*========================================
Class LUpd6Port
=======================================*/
class LUdp6Port
{
friend class LNetwork;
public:
LUdp6Port();
virtual ~LUdp6Port();
bool open(LUdp6Config *config);
int unicast(const uint8_t *buf, uint32_t length, in6_addr ipaddress, uint16_t port);
int multicast( const uint8_t* buf, uint32_t length );
int recv(uint8_t *buf, uint16_t len, bool nonblock, in6_addr *ipaddress, uint16_t *port);
int recv(uint8_t* buf, int flags);
bool checkRecvBuf();
bool isUnicast();
private:
void close();
int recvfrom(uint8_t *buf, uint16_t len, int flags, in6_addr *ipaddress, uint16_t *port);
pollfd _pollfds[2];
uint16_t _gPortNo;
uint16_t _uPortNo;
sockaddr_in6 _gIpAddr;
char *_gIpAddrStr;
char* _interface;
int _sock;
bool _disconReq;
};
#define NO_ERROR 0
#define PACKET_EXCEEDS_LENGTH 1
/*===========================================
Class Network
============================================*/
class LNetwork: public LUdp6Port
{
public:
LNetwork();
~LNetwork();
int broadcast(const uint8_t* payload, uint16_t payloadLen);
int unicast(const uint8_t* payload, uint16_t payloadLen);
void setGwAddress(void);
void resetGwAddress(void);
bool initialize(LUdp6Config *config);
uint8_t* getMessage(int* len);
bool isBroadcastable();
private:
void setSleep();
int readApiFrame(void);
in6_addr _gwIpAddress;
in6_addr _ipAddress;
uint16_t _gwPortNo;
uint16_t _portNo;
int _returnCode;
bool _sleepflg;
uint8_t _rxDataBuf[MQTTSN_MAX_PACKET_SIZE + 1]; // defined in MqttsnClientApp.h
};
} /* end of namespace */
#endif /* UDP6 */
#endif /* NETWORKUDP_H_ */

View File

@@ -40,354 +40,360 @@ const char* NULLCHAR = "";
LPublishManager::LPublishManager() LPublishManager::LPublishManager()
{ {
_first = 0; _first = 0;
_last = 0; _last = 0;
_elmCnt = 0; _elmCnt = 0;
_publishedFlg = SAVE_TASK_INDEX; _publishedFlg = SAVE_TASK_INDEX;
_autoConnectFlg = false;
} }
LPublishManager::~LPublishManager() LPublishManager::~LPublishManager()
{ {
PubElement* elm = _first; PubElement* elm = _first;
PubElement* sav = 0; PubElement* sav = 0;
while (elm) while (elm)
{ {
sav = elm->next; sav = elm->next;
if (elm != 0) if (elm != 0)
{ {
delElement(elm); delElement(elm);
} }
elm = sav; elm = sav;
} }
} }
void LPublishManager::publish(const char* topicName, Payload* payload, uint8_t qos, bool retain) void LPublishManager::publish(const char* topicName, Payload* payload, uint8_t qos, bool retain)
{ {
publish(topicName, payload->getRowData(), payload->getLen(), qos, retain); publish(topicName, payload->getRowData(), payload->getLen(), qos, retain);
} }
void LPublishManager::publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain) void LPublishManager::publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain)
{ {
uint8_t topicType = MQTTSN_TOPIC_TYPE_NORMAL; uint16_t msgId = 0;
if ( strlen(topicName) < 2 ) uint8_t topicType = MQTTSN_TOPIC_TYPE_SHORT;
{ if ( strlen(topicName) > 2 )
topicType = MQTTSN_TOPIC_TYPE_SHORT; {
} topicType = MQTTSN_TOPIC_TYPE_NORMAL;
publish(topicName, payload, len, qos, topicType, retain); }
}
void LPublishManager::publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, uint8_t topicType, bool retain) if ( qos > 0 && qos < 3 )
{ {
uint16_t msgId = 0; msgId = theClient->getGwProxy()->getNextMsgId();
if ( qos > 0 ) }
{
msgId = theClient->getGwProxy()->getNextMsgId(); PubElement* elm = add(topicName, 0, payload, len, qos, retain, msgId, topicType);
}
PubElement* elm = add(topicName, 0, payload, len, qos, retain, msgId, topicType); if (elm->status == TOPICID_IS_READY)
if (elm->status == TOPICID_IS_READY) {
{ sendPublish(elm);
sendPublish(elm); }
} else
else {
{ theClient->getGwProxy()->registerTopic((char*) topicName, 0);
theClient->getGwProxy()->registerTopic((char*) topicName, 0); }
}
} }
void LPublishManager::publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain) void LPublishManager::publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain)
{ {
publish(topicId, payload->getRowData(), payload->getLen(), qos, retain); publish(topicId, payload->getRowData(), payload->getLen(), qos, retain);
} }
void LPublishManager::publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain) void LPublishManager::publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain)
{ {
uint16_t msgId = 0; uint16_t msgId = 0;
if ( qos > 0 ) if ( qos > 0 && qos < 3 )
{ {
msgId = theClient->getGwProxy()->getNextMsgId(); msgId = theClient->getGwProxy()->getNextMsgId();
} }
PubElement* elm = add(NULLCHAR, topicId, payload, len, qos, retain, msgId, MQTTSN_TOPIC_TYPE_PREDEFINED); PubElement* elm = add(NULLCHAR, topicId, payload, len, qos, retain, msgId, MQTTSN_TOPIC_TYPE_PREDEFINED);
sendPublish(elm); sendPublish(elm);
} }
void LPublishManager::sendPublish(PubElement* elm) void LPublishManager::sendPublish(PubElement* elm)
{ {
if (elm == 0) if (elm == 0)
{
return;
}
if (_autoConnectFlg)
{ {
return; theClient->getGwProxy()->connect();
} }
theClient->getGwProxy()->connect(); uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1];
uint8_t org = 0;
if (elm->payloadlen > 248)
{
msg[0] = 0x01;
setUint16(msg + 1, elm->payloadlen + 9);
org = 2;
}
else
{
msg[0] = (uint8_t) elm->payloadlen + 7;
}
msg[org + 1] = MQTTSN_TYPE_PUBLISH;
msg[org + 2] = elm->flag;
if ((elm->retryCount < MQTTSN_RETRY_COUNT))
{
msg[org + 2] = msg[org + 2] | MQTTSN_FLAG_DUP;
}
if ((elm->flag & 0x03) == MQTTSN_TOPIC_TYPE_SHORT )
{
memcpy(msg + org + 3, elm->topicName, 2);
}
else
{
setUint16(msg + org + 3, elm->topicId);
}
setUint16(msg + org + 5, elm->msgId);
memcpy(msg + org + 7, elm->payload, elm->payloadlen);
uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1]; theClient->getGwProxy()->writeMsg(msg);
uint8_t org = 0; theClient->getGwProxy()->setPingReqTimer();
if (elm->payloadlen > 128) if ( ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_0 ) || ( (elm->flag & 0x60) == MQTTSN_FLAG_QOS_M1) )
{ {
msg[0] = 0x01; DISPLAY("\033[0m\033[0;32m Topic \"%s\" was Published. \033[0m\033[0;37m\n\n", elm->topicName);
setUint16(msg + 1, elm->payloadlen + 9); remove(elm); // PUBLISH Done
org = 2; return;
} }
else else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_1)
{ {
msg[0] = (uint8_t) elm->payloadlen + 7; elm->status = WAIT_PUBACK;
} }
msg[org + 1] = MQTTSN_TYPE_PUBLISH; else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_2)
msg[org + 2] = elm->flag; {
if ((elm->retryCount < MQTTSN_RETRY_COUNT)) elm->status = WAIT_PUBREC;
{ }
msg[org + 2] = msg[org + 2] | MQTTSN_FLAG_DUP;
}
if ((elm->flag & 0x03) == MQTTSN_TOPIC_TYPE_SHORT )
{
memcpy(msg + org + 3, elm->topicName, 2);
}
else
{
setUint16(msg + org + 3, elm->topicId);
}
setUint16(msg + org + 5, elm->msgId);
memcpy(msg + org + 7, elm->payload, elm->payloadlen);
theClient->getGwProxy()->writeMsg(msg); elm->sendUTC = time(NULL);
theClient->getGwProxy()->resetPingReqTimer(); elm->retryCount--;
if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_0)
{
DISPLAY("\033[0m\033[0;32m Topic \"%s\" was Published. \033[0m\033[0;37m\n\n", elm->topicName);
remove(elm); // PUBLISH Done
return;
}
else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_1)
{
elm->status = WAIT_PUBACK;
}
else if ((elm->flag & 0x60) == MQTTSN_FLAG_QOS_2)
{
elm->status = WAIT_PUBREC;
}
elm->sendUTC = time(NULL);
elm->retryCount--;
} }
void LPublishManager::sendSuspend(const char* topicName, uint16_t topicId, uint8_t topicType) void LPublishManager::sendSuspend(const char* topicName, uint16_t topicId, uint8_t topicType)
{ {
PubElement* elm = _first; PubElement* elm = _first;
while (elm) while (elm)
{ {
if (strcmp(elm->topicName, topicName) == 0 && elm->status == TOPICID_IS_SUSPEND) if (strcmp(elm->topicName, topicName) == 0 && elm->status == TOPICID_IS_SUSPEND)
{ {
elm->topicId = topicId; elm->topicId = topicId;
elm->flag |= topicType; elm->flag |= topicType;
elm->status = TOPICID_IS_READY; elm->status = TOPICID_IS_READY;
sendPublish(elm); sendPublish(elm);
elm = 0; elm = 0;
} }
else else
{ {
elm = elm->next; elm = elm->next;
} }
} }
} }
void LPublishManager::sendPubAck(uint16_t topicId, uint16_t msgId, uint8_t rc) void LPublishManager::sendPubAck(uint16_t topicId, uint16_t msgId, uint8_t rc)
{ {
uint8_t msg[7]; uint8_t msg[7];
msg[0] = 7; msg[0] = 7;
msg[1] = MQTTSN_TYPE_PUBACK; msg[1] = MQTTSN_TYPE_PUBACK;
setUint16(msg + 2, topicId); setUint16(msg + 2, topicId);
setUint16(msg + 4, msgId); setUint16(msg + 4, msgId);
msg[6] = rc; msg[6] = rc;
theClient->getGwProxy()->writeMsg(msg); theClient->getGwProxy()->writeMsg(msg);
} }
void LPublishManager::sendPubRel(PubElement* elm) void LPublishManager::sendPubRel(PubElement* elm)
{ {
uint8_t msg[4]; uint8_t msg[4];
msg[0] = 4; msg[0] = 4;
msg[1] = MQTTSN_TYPE_PUBREL; msg[1] = MQTTSN_TYPE_PUBREL;
setUint16(msg + 2, elm->msgId); setUint16(msg + 2, elm->msgId);
theClient->getGwProxy()->writeMsg(msg); theClient->getGwProxy()->writeMsg(msg);
} }
bool LPublishManager::isDone(void) bool LPublishManager::isDone(void)
{ {
return (_first == 0); return (_first == 0);
} }
bool LPublishManager::isMaxFlight(void) bool LPublishManager::isMaxFlight(void)
{ {
return (_elmCnt > MAX_INFLIGHT_MSG / 2); return (_elmCnt > MAX_INFLIGHT_MSG / 2);
} }
void LPublishManager::responce(const uint8_t* msg, uint16_t msglen) void LPublishManager::responce(const uint8_t* msg, uint16_t msglen)
{ {
if (msg[0] == MQTTSN_TYPE_PUBACK) if (msg[0] == MQTTSN_TYPE_PUBACK)
{ {
uint16_t msgId = getUint16(msg + 3); uint16_t msgId = getUint16(msg + 3);
PubElement* elm = getElement(msgId); PubElement* elm = getElement(msgId);
if (elm == 0) if (elm == 0)
{ {
return; return;
} }
if (msg[5] == MQTTSN_RC_ACCEPTED) if (msg[5] == MQTTSN_RC_ACCEPTED)
{ {
if (elm->status == WAIT_PUBACK) if (elm->status == WAIT_PUBACK)
{ {
DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Published. \033[0m\033[0;37m\n\n", elm->topicName, elm->topicId); DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Published. \033[0m\033[0;37m\n\n", elm->topicName, elm->topicId);
remove(elm); // PUBLISH Done remove(elm); // PUBLISH Done
} }
} }
else if (msg[5] == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID) else if (msg[5] == MQTTSN_RC_REJECTED_INVALID_TOPIC_ID)
{ {
elm->status = TOPICID_IS_SUSPEND; elm->status = TOPICID_IS_SUSPEND;
elm->topicId = 0; elm->topicId = 0;
elm->retryCount = MQTTSN_RETRY_COUNT; elm->retryCount = MQTTSN_RETRY_COUNT;
elm->sendUTC = 0; elm->sendUTC = 0;
theClient->getGwProxy()->registerTopic((char*) elm->topicName, 0); theClient->getGwProxy()->registerTopic((char*) elm->topicName, 0);
} }
} }
else if (msg[0] == MQTTSN_TYPE_PUBREC) else if (msg[0] == MQTTSN_TYPE_PUBREC)
{ {
PubElement* elm = getElement(getUint16(msg + 1)); PubElement* elm = getElement(getUint16(msg + 1));
if (elm == 0) if (elm == 0)
{ {
return; return;
} }
if (elm->status == WAIT_PUBREC || elm->status == WAIT_PUBCOMP) if (elm->status == WAIT_PUBREC || elm->status == WAIT_PUBCOMP)
{ {
sendPubRel(elm); sendPubRel(elm);
elm->status = WAIT_PUBCOMP; elm->status = WAIT_PUBCOMP;
elm->sendUTC = time(NULL); elm->sendUTC = time(NULL);
} }
} }
else if (msg[0] == MQTTSN_TYPE_PUBCOMP) else if (msg[0] == MQTTSN_TYPE_PUBCOMP)
{ {
PubElement* elm = getElement(getUint16(msg + 1)); PubElement* elm = getElement(getUint16(msg + 1));
if (elm == 0) if (elm == 0)
{ {
return; return;
} }
if (elm->status == WAIT_PUBCOMP) if (elm->status == WAIT_PUBCOMP)
{ {
DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Published. \033[0m\033[0;37m\n\n", elm->topicName, elm->topicId); DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Published. \033[0m\033[0;37m\n\n", elm->topicName, elm->topicId);
remove(elm); // PUBLISH Done remove(elm); // PUBLISH Done
} }
} }
} }
void LPublishManager::published(uint8_t* msg, uint16_t msglen) void LPublishManager::published(uint8_t* msg, uint16_t msglen)
{ {
uint16_t topicId = getUint16(msg + 2); uint16_t topicId = getUint16(msg + 2);
if (msg[1] & MQTTSN_FLAG_QOS_1) if (msg[1] & MQTTSN_FLAG_QOS_1)
{ {
sendPubAck(topicId, getUint16(msg + 4), MQTTSN_RC_ACCEPTED); sendPubAck(topicId, getUint16(msg + 4), MQTTSN_RC_ACCEPTED);
} }
_publishedFlg = NEG_TASK_INDEX; _publishedFlg = NEG_TASK_INDEX;
theClient->getTopicTable()->execCallback(topicId, msg + 6, msglen - 6, msg[1] & 0x03); theClient->getTopicTable()->execCallback(topicId, msg + 6, msglen - 6, (MQTTSN_topicTypes)(msg[1] & MQTTSN_TOPIC_TYPE));
_publishedFlg = SAVE_TASK_INDEX; _publishedFlg = SAVE_TASK_INDEX;
} }
void LPublishManager::checkTimeout(void) void LPublishManager::checkTimeout(void)
{ {
PubElement* elm = _first; PubElement* elm = _first;
while (elm) while (elm)
{ {
if (elm->sendUTC > 0 && elm->sendUTC + MQTTSN_TIME_RETRY < time(NULL)) if (elm->sendUTC > 0 && elm->sendUTC + MQTTSN_TIME_RETRY < time(NULL))
{ {
if (elm->retryCount >= 0) if (elm->retryCount >= 0)
{ {
sendPublish(elm); sendPublish(elm);
D_MQTTLOG("...Timeout retry\r\n"); D_MQTTLOG("...Timeout retry\r\n");
} }
else else
{ {
theClient->getGwProxy()->reconnect(); theClient->getGwProxy()->reconnect();
elm->retryCount = MQTTSN_RETRY_COUNT; elm->retryCount = MQTTSN_RETRY_COUNT;
break; break;
} }
} }
elm = elm->next; elm = elm->next;
} }
}
void LPublishManager::setAutoConnectMode(bool flg)
{
_autoConnectFlg = flg;
} }
PubElement* LPublishManager::getElement(uint16_t msgId) PubElement* LPublishManager::getElement(uint16_t msgId)
{ {
PubElement* elm = _first; PubElement* elm = _first;
while (elm) while (elm)
{ {
if (elm->msgId == msgId) if (elm->msgId == msgId)
{ {
break; break;
} }
else else
{ {
elm = elm->next; elm = elm->next;
} }
} }
return elm; return elm;
} }
PubElement* LPublishManager::getElement(const char* topicName) PubElement* LPublishManager::getElement(const char* topicName)
{ {
PubElement* elm = _first; PubElement* elm = _first;
while (elm) while (elm)
{ {
if (strcmp(elm->topicName, topicName) == 0) if (strcmp(elm->topicName, topicName) == 0)
{ {
break; break;
} }
else else
{ {
elm = elm->next; elm = elm->next;
} }
} }
return elm; return elm;
} }
void LPublishManager::remove(PubElement* elm) void LPublishManager::remove(PubElement* elm)
{ {
if (elm) if (elm)
{ {
if (elm->prev == 0) if (elm->prev == 0)
{ {
_first = elm->next; _first = elm->next;
if (elm->next == 0) if (elm->next == 0)
{ {
_last = 0; _last = 0;
} }
else else
{ {
elm->next->prev = 0; elm->next->prev = 0;
_last = elm->next; _last = elm->next;
} }
} }
else else
{ {
if ( elm->next == 0 ) if ( elm->next == 0 )
{ {
_last = elm->prev; _last = elm->prev;
} }
elm->prev->next = elm->next; elm->prev->next = elm->next;
} }
delElement(elm); delElement(elm);
} }
} }
void LPublishManager::delElement(PubElement* elm) void LPublishManager::delElement(PubElement* elm)
{ {
if (elm->taskIndex >= 0) if (elm->taskIndex >= 0)
{ {
theClient->getTaskManager()->done(elm->taskIndex); theClient->getTaskManager()->done(elm->taskIndex);
} }
_elmCnt--; _elmCnt--;
if ( elm->payload ) if ( elm->payload )
{ {
free(elm->payload); free(elm->payload);
} }
free(elm); free(elm);
} }
/* /*
@@ -396,75 +402,88 @@ void LPublishManager::delElement(PubElement* elm)
}*/ }*/
PubElement* LPublishManager::add(const char* topicName, uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, PubElement* LPublishManager::add(const char* topicName, uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos,
uint8_t retain, uint16_t msgId, uint8_t topicType) uint8_t retain, uint16_t msgId, uint8_t topicType)
{ {
PubElement* elm = (PubElement*) calloc(1, sizeof(PubElement)); PubElement* elm = (PubElement*) calloc(1, sizeof(PubElement));
if (elm == 0) if (elm == 0)
{ {
return elm; return elm;
} }
if (_last == 0) if (_last == 0)
{ {
_first = elm; _first = elm;
_last = elm; _last = elm;
} }
else else
{ {
elm->prev = _last; elm->prev = _last;
_last->next = elm; _last->next = elm;
_last = elm; _last = elm;
} }
elm->topicName = topicName; elm->topicName = topicName;
elm->flag |= topicType; elm->flag |= topicType;
if (qos == 0) if (qos == 0)
{ {
elm->flag |= MQTTSN_FLAG_QOS_0; elm->flag |= MQTTSN_FLAG_QOS_0;
} }
else if (qos == 1) else if (qos == 1)
{ {
elm->flag |= MQTTSN_FLAG_QOS_1; elm->flag |= MQTTSN_FLAG_QOS_1;
} }
else if (qos == 2) else if (qos == 2)
{ {
elm->flag |= MQTTSN_FLAG_QOS_2; elm->flag |= MQTTSN_FLAG_QOS_2;
} }
if (retain) else if (qos == 3)
{ {
elm->flag |= MQTTSN_FLAG_RETAIN; elm->flag |= MQTTSN_FLAG_QOS_M1;
} }
if (retain)
{
elm->flag |= MQTTSN_FLAG_RETAIN;
}
if (topicId) if (topicId)
{ {
elm->status = TOPICID_IS_READY; elm->status = TOPICID_IS_READY;
elm->topicId = topicId; elm->topicId = topicId;
} }
else
{
uint16_t id = theClient->getTopicId(topicName);
if ( id )
{
elm->status = TOPICID_IS_READY;
elm->topicId = id;
}
}
elm->payloadlen = len; elm->payloadlen = len;
elm->msgId = msgId; elm->msgId = msgId;
elm->retryCount = MQTTSN_RETRY_COUNT; elm->retryCount = MQTTSN_RETRY_COUNT;
elm->sendUTC = 0; elm->sendUTC = 0;
if (_publishedFlg == NEG_TASK_INDEX) if (_publishedFlg == NEG_TASK_INDEX)
{ {
elm->taskIndex = -1; elm->taskIndex = -1;
} }
else else
{ {
elm->taskIndex = theClient->getTaskManager()->getIndex(); elm->taskIndex = theClient->getTaskManager()->getIndex();
theClient->getTaskManager()->suspend(elm->taskIndex); theClient->getTaskManager()->suspend(elm->taskIndex);
} }
elm->payload = (uint8_t*) malloc(len); elm->payload = (uint8_t*) malloc(len);
if (elm->payload == 0) if (elm->payload == 0)
{ {
delElement(elm); delElement(elm);
return 0; return 0;
} }
memcpy(elm->payload, payload, len); memcpy(elm->payload, payload, len);
++_elmCnt; ++_elmCnt;
return elm; return elm;
} }

View File

@@ -16,6 +16,7 @@
#ifndef PUBLISHMANAGER_H_ #ifndef PUBLISHMANAGER_H_
#define PUBLISHMANAGER_H_ #define PUBLISHMANAGER_H_
#include <time.h>
#include "LMqttsnClientApp.h" #include "LMqttsnClientApp.h"
#include "LTimer.h" #include "LTimer.h"
#include "LTopicTable.h" #include "LTopicTable.h"
@@ -42,7 +43,7 @@ typedef struct PubElement{
const char* topicName; const char* topicName;
uint8_t* payload; uint8_t* payload;
uint16_t payloadlen; uint16_t payloadlen;
uint32_t sendUTC; time_t sendUTC;
int (*callback)(void); int (*callback)(void);
int retryCount; int retryCount;
int taskIndex; int taskIndex;
@@ -61,7 +62,6 @@ public:
~LPublishManager(); ~LPublishManager();
void publish(const char* topicName, Payload* payload, uint8_t qos, bool retain = false); void publish(const char* topicName, Payload* payload, uint8_t qos, bool retain = false);
void publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false); void publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false);
void publish(const char* topicName, uint8_t* payload, uint16_t len, uint8_t qos, uint8_t topicType, bool retain = false);
void publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain = false); void publish(uint16_t topicId, Payload* payload, uint8_t qos, bool retain = false);
void publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false); void publish(uint16_t topicId, uint8_t* payload, uint16_t len, uint8_t qos, bool retain = false);
void responce(const uint8_t* msg, uint16_t msglen); void responce(const uint8_t* msg, uint16_t msglen);
@@ -70,6 +70,7 @@ public:
void sendSuspend(const char* topicName, uint16_t topicId, uint8_t topicType); void sendSuspend(const char* topicName, uint16_t topicId, uint8_t topicType);
bool isDone(void); bool isDone(void);
bool isMaxFlight(void); bool isMaxFlight(void);
void setAutoConnectMode(bool);
private: private:
PubElement* getElement(uint16_t msgId); PubElement* getElement(uint16_t msgId);
PubElement* getElement(const char* topicName); PubElement* getElement(const char* topicName);
@@ -84,7 +85,8 @@ private:
PubElement* _last; PubElement* _last;
uint8_t _elmCnt; uint8_t _elmCnt;
uint8_t _publishedFlg; uint8_t _publishedFlg;
uint8_t _autoConnectFlg;
}; };
} /* tomyAsyncClient */ } /* tomyAsyncClient */
#endif /* PUBLISHMANAGER_H_ */ #endif /* PUBLISHMANAGER_H_ */

View File

@@ -190,13 +190,13 @@ void LRegisterManager::registerTopic(char* topicName)
void LRegisterManager::responceRegAck(uint16_t msgId, uint16_t topicId) void LRegisterManager::responceRegAck(uint16_t msgId, uint16_t topicId)
{ {
const char* topicName = getTopic(msgId); const char* topicName = getTopic(msgId);
MQTTSN_topicTypes type = MQTTSN_TOPIC_TYPE_NORMAL;
if (topicName) if (topicName)
{ {
uint8_t topicType = strlen((char*) topicName) > 2 ? MQTTSN_TOPIC_TYPE_NORMAL : MQTTSN_TOPIC_TYPE_SHORT; theClient->getGwProxy()->getTopicTable()->setTopicId((char*) topicName, topicId, type); // Add Topic to TopicTable
theClient->getGwProxy()->getTopicTable()->setTopicId((char*) topicName, topicId, topicType); // Add Topic to TopicTable
RegQueElement* elm = getElement(msgId); RegQueElement* elm = getElement(msgId);
remove(elm); remove(elm);
theClient->getPublishManager()->sendSuspend((char*) topicName, topicId, topicType); theClient->getPublishManager()->sendSuspend((char*) topicName, topicId, type);
} }
} }
@@ -206,14 +206,14 @@ void LRegisterManager::responceRegister(uint8_t* msg, uint16_t msglen)
uint8_t regack[7]; uint8_t regack[7];
regack[0] = 7; regack[0] = 7;
regack[1] = MQTTSN_TYPE_REGACK; regack[1] = MQTTSN_TYPE_REGACK;
memcpy(regack + 2, msg + 2, 4); memcpy(regack + 2, msg + 1, 4);
LTopic* tp = theClient->getGwProxy()->getTopicTable()->match((char*) msg + 5); LTopic* tp = theClient->getGwProxy()->getTopicTable()->match((char*) msg + 5);
if (tp) if (tp)
{ {
TopicCallback callback = tp->getCallback(); TopicCallback callback = tp->getCallback();
void* topicName = calloc(strlen((char*) msg + 5) + 1, sizeof(char)); void* topicName = calloc(strlen((char*) msg + 5) + 1, sizeof(char));
theClient->getGwProxy()->getTopicTable()->add((char*) topicName, 0, MQTTSN_TOPIC_TYPE_NORMAL, callback, 1); theClient->getGwProxy()->getTopicTable()->add((char*) topicName, MQTTSN_TOPIC_TYPE_NORMAL, 0, callback, 1);
regack[6] = MQTTSN_RC_ACCEPTED; regack[6] = MQTTSN_RC_ACCEPTED;
} }
else else

View File

@@ -17,6 +17,7 @@
#ifndef REGISTERQUE_H_ #ifndef REGISTERQUE_H_
#define REGISTERQUE_H_ #define REGISTERQUE_H_
#include <time.h>
#include "LMqttsnClientApp.h" #include "LMqttsnClientApp.h"
namespace linuxAsyncClient { namespace linuxAsyncClient {
@@ -27,7 +28,7 @@ typedef struct RegQueElement{
const char* topicName; const char* topicName;
uint16_t msgId; uint16_t msgId;
int retryCount; int retryCount;
uint32_t sendUTC; time_t sendUTC;
RegQueElement* prev; RegQueElement* prev;
RegQueElement* next; RegQueElement* next;
}RegQueElement; }RegQueElement;

View File

@@ -23,7 +23,6 @@
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include "LScreen.h" #include "LScreen.h"

View File

@@ -39,350 +39,373 @@ extern LScreen* theScreen;
=======================================*/ =======================================*/
LSubscribeManager::LSubscribeManager() LSubscribeManager::LSubscribeManager()
{ {
_first = 0; _first = 0;
_last = 0; _last = 0;
} }
LSubscribeManager::~LSubscribeManager() LSubscribeManager::~LSubscribeManager()
{ {
SubElement* elm = _first; SubElement* elm = _first;
SubElement* sav = 0; SubElement* sav = 0;
while (elm) while (elm)
{ {
sav = elm->next; sav = elm->next;
if (elm != 0) if (elm != 0)
{ {
free(elm); free(elm);
} }
elm = sav; elm = sav;
} }
} }
void LSubscribeManager::onConnect(void) void LSubscribeManager::onConnect(void)
{ {
DISPLAY("\033[0m\033[0;32m Attempting OnConnect.....\033[0m\033[0;37m\n"); DISPLAY("\033[0m\033[0;32m Attempting OnConnect.....\033[0m\033[0;37m\n");
if (_first == 0) if (_first == 0)
{ {
for (uint8_t i = 0; theOnPublishList[i].topic != 0; i++) for (uint8_t i = 0; theOnPublishList[i].topic != 0; i++)
{ {
subscribe(theOnPublishList[i].topic, theOnPublishList[i].pubCallback, theOnPublishList[i].qos); if ( theOnPublishList[i].type == MQTTSN_TOPIC_TYPE_PREDEFINED)
} {
} subscribePredefinedId(theOnPublishList[i].id,
else theOnPublishList[i].pubCallback,
{ theOnPublishList[i].qos);
SubElement* elm = _first; }
SubElement* pelm; else
do {
{ subscribe(theOnPublishList[i].topic, theOnPublishList[i].pubCallback, theOnPublishList[i].qos);
pelm = elm; }
if (elm->msgType == MQTTSN_TYPE_SUBSCRIBE) }
{ }
elm->done = SUB_READY; else
elm->retryCount = MQTTSN_RETRY_COUNT; {
subscribe(elm->topicName, elm->callback, elm->qos); SubElement* elm = _first;
} SubElement* pelm;
elm = pelm->next; do
} while (pelm->next); {
} pelm = elm;
if (elm->msgType == MQTTSN_TYPE_SUBSCRIBE)
{
elm->done = SUB_READY;
elm->retryCount = MQTTSN_RETRY_COUNT;
subscribe(elm->topicName, elm->callback, elm->qos);
}
elm = pelm->next;
} while (pelm->next);
}
while (!theClient->getSubscribeManager()->isDone()) while (!theClient->getSubscribeManager()->isDone())
{ {
theClient->getGwProxy()->getMessage(); theClient->getGwProxy()->getMessage();
} }
DISPLAY("\033[0m\033[0;32m OnConnect complete\033[0m\033[0;37m\n"); DISPLAY("\033[0m\033[0;32m OnConnect complete\033[0m\033[0;37m\n");
DISPLAY("\033[0m\033[0;32m Test is Ready.\033[0m\033[0;37m\n"); DISPLAY("\033[0m\033[0;32m Test is Ready.\033[0m\033[0;37m\n");
} }
bool LSubscribeManager::isDone(void) bool LSubscribeManager::isDone(void)
{ {
SubElement* elm = _first; SubElement* elm = _first;
SubElement* prevelm; SubElement* prevelm;
while (elm) while (elm)
{ {
prevelm = elm; prevelm = elm;
if (elm->done == SUB_READY) if (elm->done == SUB_READY)
{ {
return false; return false;
} }
elm = prevelm->next; elm = prevelm->next;
} }
return true; return true;
} }
void LSubscribeManager::send(SubElement* elm) void LSubscribeManager::send(SubElement* elm)
{ {
if (elm->done == SUB_DONE) if (elm->done == SUB_DONE)
{ {
return; return;
} }
uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1];
if (elm->topicType == MQTTSN_TOPIC_TYPE_NORMAL)
{
msg[0] = 5 + strlen(elm->topicName);
strcpy((char*) msg + 5, elm->topicName);
}
else
{
msg[0] = 7;
setUint16(msg + 5, elm->topicId);
}
msg[1] = elm->msgType;
msg[2] = elm->qos | elm->topicType;
if (elm->retryCount == MQTTSN_RETRY_COUNT)
{
elm->msgId = theClient->getGwProxy()->getNextMsgId();
}
if ((elm->retryCount < MQTTSN_RETRY_COUNT) && elm->msgType == MQTTSN_TYPE_SUBSCRIBE) uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1];
{ if (elm->topicType == MQTTSN_TOPIC_TYPE_PREDEFINED)
msg[2] = msg[2] | MQTTSN_FLAG_DUP; {
} msg[0] = 7;
setUint16(msg + 5, elm->topicId);
}
else
{
msg[0] = 5 + strlen(elm->topicName);
strcpy((char*) msg + 5, elm->topicName);
}
msg[1] = elm->msgType;
msg[2] = elm->qos | elm->topicType;
if (elm->retryCount == MQTTSN_RETRY_COUNT)
{
elm->msgId = theClient->getGwProxy()->getNextMsgId();
}
setUint16(msg + 3, elm->msgId); if ((elm->retryCount < MQTTSN_RETRY_COUNT) && elm->msgType == MQTTSN_TYPE_SUBSCRIBE)
{
msg[2] = msg[2] | MQTTSN_FLAG_DUP;
}
theClient->getGwProxy()->connect(); setUint16(msg + 3, elm->msgId);
theClient->getGwProxy()->writeMsg(msg);
theClient->getGwProxy()->resetPingReqTimer(); theClient->getGwProxy()->connect();
elm->sendUTC = time(NULL); theClient->getGwProxy()->writeMsg(msg);
elm->retryCount--; theClient->getGwProxy()->setPingReqTimer();
elm->sendUTC = time(NULL);
elm->retryCount--;
} }
void LSubscribeManager::subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos) void LSubscribeManager::subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos)
{ {
uint8_t topicType = MQTTSN_TOPIC_TYPE_NORMAL; MQTTSN_topicTypes topicType;
if ( strlen(topicName) <= 2) if ( strlen(topicName) > 2 )
{ {
topicType = MQTTSN_TOPIC_TYPE_SHORT; topicType = MQTTSN_TOPIC_TYPE_NORMAL;
} }
SubElement* elm = add(MQTTSN_TYPE_SUBSCRIBE, topicName, 0, topicType, qos, onPublish); else
send(elm); {
topicType = MQTTSN_TOPIC_TYPE_SHORT;
}
SubElement* elm = add(MQTTSN_TYPE_SUBSCRIBE, topicName, topicType, 0, qos, onPublish);
send(elm);
} }
void LSubscribeManager::subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos, uint8_t topicType) void LSubscribeManager::subscribePredefinedId(uint16_t topicId, TopicCallback onPublish, uint8_t qos)
{ {
SubElement* elm = add(MQTTSN_TYPE_SUBSCRIBE, 0, topicId, topicType, qos, onPublish); SubElement* elm = add(MQTTSN_TYPE_SUBSCRIBE, 0, MQTTSN_TOPIC_TYPE_PREDEFINED, topicId, qos, onPublish);
send(elm); send(elm);
} }
void LSubscribeManager::unsubscribe(const char* topicName) void LSubscribeManager::unsubscribe(const char* topicName)
{ {
SubElement* elm = add(MQTTSN_TYPE_UNSUBSCRIBE, topicName, 0, MQTTSN_TOPIC_TYPE_NORMAL, 0, 0); MQTTSN_topicTypes topicType;
send(elm); if ( strlen(topicName) > 2 )
{
topicType = MQTTSN_TOPIC_TYPE_NORMAL;
}
else
{
topicType = MQTTSN_TOPIC_TYPE_SHORT;
}
SubElement* elm = add(MQTTSN_TYPE_UNSUBSCRIBE, topicName, topicType, 0, 0, 0);
send(elm);
} }
void LSubscribeManager::unsubscribe(uint16_t topicId, uint8_t topicType) void LSubscribeManager::unsubscribe( uint16_t topicId)
{ {
SubElement* elm = add(MQTTSN_TYPE_UNSUBSCRIBE, 0, topicId, topicType, 0, 0); SubElement* elm = add(MQTTSN_TYPE_UNSUBSCRIBE, 0, MQTTSN_TOPIC_TYPE_PREDEFINED, topicId, 0, 0);
send(elm); send(elm);
} }
void LSubscribeManager::checkTimeout(void) void LSubscribeManager::checkTimeout(void)
{ {
SubElement* elm = _first; SubElement* elm = _first;
while (elm) while (elm)
{ {
if (elm->sendUTC + MQTTSN_TIME_RETRY < time(NULL)) if (elm->sendUTC + MQTTSN_TIME_RETRY < time(NULL))
{ {
if (elm->retryCount >= 0) if (elm->retryCount >= 0)
{ {
send(elm); send(elm);
} }
else else
{ {
if ( elm->done == SUB_READY ) if ( elm->done == SUB_READY )
{ {
if (elm->msgType == MQTTSN_TYPE_SUBSCRIBE) if (elm->msgType == MQTTSN_TYPE_SUBSCRIBE)
{ {
DISPLAY("\033[0m\033[0;31m\n!!!!!! SUBSCRIBE Error !!!!! Topic : %s\033[0m\033[0;37m\n\n", (char*)elm->topicName); DISPLAY("\033[0m\033[0;31m\n!!!!!! SUBSCRIBE Error !!!!! Topic : %s\033[0m\033[0;37m\n\n", (char*)elm->topicName);
}else{ }else{
DISPLAY("\033[0m\033[0;31m\n!!!!!! UNSUBSCRIBE Error !!!!! Topic : %s\033[0m\033[0;37m\n\n", (char*)elm->topicName); DISPLAY("\033[0m\033[0;31m\n!!!!!! UNSUBSCRIBE Error !!!!! Topic : %s\033[0m\033[0;37m\n\n", (char*)elm->topicName);
} }
elm->done = SUB_DONE; elm->done = SUB_DONE;
} }
} }
} }
elm = elm->next; elm = elm->next;
} }
} }
void LSubscribeManager::responce(const uint8_t* msg) void LSubscribeManager::responce(const uint8_t* msg)
{ {
if (msg[0] == MQTTSN_TYPE_SUBACK) if (msg[0] == MQTTSN_TYPE_SUBACK)
{ {
uint16_t topicId = getUint16(msg + 2); uint16_t topicId = getUint16(msg + 2);
uint16_t msgId = getUint16(msg + 4); uint16_t msgId = getUint16(msg + 4);
uint8_t rc = msg[6]; uint8_t rc = msg[6];
LTopicTable* tt = theClient->getGwProxy()->getTopicTable(); SubElement* elm = getElement(msgId);
SubElement* elm = getElement(msgId); if (elm)
if (elm) {
{ if ( rc == MQTTSN_RC_ACCEPTED )
if ( rc == MQTTSN_RC_ACCEPTED ) {
{ theClient->getGwProxy()->getTopicTable()->add((char*) elm->topicName, elm->topicType, topicId, elm->callback);
tt->add((char*) elm->topicName, topicId, elm->topicType, elm->callback); getElement(msgId)->done = SUB_DONE;
getElement(msgId)->done = SUB_DONE; DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Subscribed. \033[0m\033[0;37m\n\n", getElement(msgId)->topicName, topicId);
DISPLAY("\033[0m\033[0;32m Topic \"%s\" Id : %d was Subscribed. \033[0m\033[0;37m\n\n", getElement(msgId)->topicName, topicId); }
} else
else {
{ DISPLAY("\033[0m\033[0;31m SUBACK Invalid messageId. %s\033[0m\033[0;37m\n\n", getElement(msgId)->topicName);
remove(elm); remove(elm);
DISPLAY("\033[0m\033[0;31m SUBACK Invalid messageId. %s\033[0m\033[0;37m\n\n", getElement(msgId)->topicName); }
} }
} }
} else if (msg[0] == MQTTSN_TYPE_UNSUBACK)
else if (msg[0] == MQTTSN_TYPE_UNSUBACK) {
{ uint16_t msgId = getUint16(msg + 1);
uint16_t msgId = getUint16(msg + 1); SubElement* elm = getElement(msgId);
SubElement* elm = getElement(msgId); if (elm)
if (elm) {
{ //theClient->getGwProxy()->getTopicTable()->setCallback(elm->topicName, 0);
LTopicTable* tt = theClient->getGwProxy()->getTopicTable(); DISPLAY("\033[0m\033[0;32m Topic \"%s\" was Unsubscribed. \033[0m\033[0;37m\n\n", getElement(msgId)->topicName);
tt->setCallback(elm->topicName, 0); remove(elm);
DISPLAY("\033[0m\033[0;32m Topic \"%s\" was Unsubscribed. \033[0m\033[0;37m\n\n", getElement(msgId)->topicName); }
remove(getElement(msgId)); else
} {
else DISPLAY(
{ "\033[0m\033[0;31m UNSUBACK Invalid messageId=%04x. \033[0m\033[0;37m\n\n",
DISPLAY("\033[0m\033[0;31m UNSUBACK Invalid messageId. %s\033[0m\033[0;37m\n\n", getElement(msgId)->topicName); msgId);
remove(getElement(msgId)); }
} }
}
} }
/* SubElement operations */ /* SubElement operations */
SubElement* LSubscribeManager::add(uint8_t msgType, const char* topicName, uint16_t topicId, uint8_t topicType, SubElement* LSubscribeManager::add(uint8_t msgType, const char* topicName, MQTTSN_topicTypes topicType, uint16_t topicId,
uint8_t qos, TopicCallback callback) uint8_t qos, TopicCallback callback)
{ {
SubElement* elm = 0; SubElement* elm = 0;
if (topicName ) if (topicName )
{ {
elm = getElement(topicName, msgType); elm = getElement(topicName, msgType);
} }
else else
{ {
elm = getElement(topicId, topicType); elm = getElement(topicId, topicType);
} }
if ( elm == 0 )
{
elm = (SubElement*) calloc(1, sizeof(SubElement));
if (elm == 0)
{
return 0;
}
if (_last == 0)
{
_first = elm;
_last = elm;
}
else
{
elm->prev = _last;
_last->next = elm;
_last = elm;
}
}
elm->msgType = msgType; if ( elm == 0 )
elm->callback = callback; {
elm->topicName = topicName; elm = (SubElement*) calloc(1, sizeof(SubElement));
elm->topicId = topicId; if (elm == 0)
elm->topicType = topicType; {
return 0;
}
if (_last == 0)
{
_first = elm;
_last = elm;
}
else
{
elm->prev = _last;
_last->next = elm;
_last = elm;
}
}
if (qos == 1) elm->msgType = msgType;
{ elm->callback = callback;
elm->qos = MQTTSN_FLAG_QOS_1; elm->topicName = topicName;
} elm->topicId = topicId;
else if (qos == 2) elm->topicType = topicType;
{
elm->qos = MQTTSN_FLAG_QOS_2;
}
else
{
elm->qos = MQTTSN_FLAG_QOS_0;
}
elm->msgId = 0;
elm->retryCount = MQTTSN_RETRY_COUNT;
elm->done = SUB_READY;
elm->sendUTC = 0;
return elm; if (qos == 1)
{
elm->qos = MQTTSN_FLAG_QOS_1;
}
else if (qos == 2)
{
elm->qos = MQTTSN_FLAG_QOS_2;
}
else
{
elm->qos = MQTTSN_FLAG_QOS_0;
}
elm->msgId = 0;
elm->retryCount = MQTTSN_RETRY_COUNT;
elm->done = SUB_READY;
elm->sendUTC = 0;
return elm;
} }
void LSubscribeManager::remove(SubElement* elm) void LSubscribeManager::remove(SubElement* elm)
{ {
if (elm) if (elm)
{ {
if (elm->prev == 0) if (elm->prev == 0)
{ {
_first = elm->next; _first = elm->next;
if (elm->next != 0) if (elm->next != 0)
{ {
elm->next->prev = 0; elm->next->prev = 0;
_last = elm->next; _last = elm->next;
} }
free(elm); free(elm);
} }
else else
{ {
if ( elm->next == 0 ) if ( elm->next == 0 )
{ {
_last = elm->prev; _last = elm->prev;
} }
elm->prev->next = elm->next; elm->prev->next = elm->next;
free(elm); free(elm);
} }
} }
} }
SubElement* LSubscribeManager::getElement(uint16_t msgId) SubElement* LSubscribeManager::getElement(uint16_t msgId)
{ {
SubElement* elm = _first; SubElement* elm = _first;
while (elm) while (elm)
{ {
if (elm->msgId == msgId) if (elm->msgId == msgId)
{ {
return elm; return elm;
} }
else else
{ {
elm = elm->next; elm = elm->next;
} }
} }
return 0; return 0;
} }
SubElement* LSubscribeManager::getElement(const char* topicName, uint8_t msgType) SubElement* LSubscribeManager::getElement(const char* topicName, uint8_t msgType)
{ {
SubElement* elm = _first; SubElement* elm = _first;
while (elm) while (elm)
{ {
if (strcmp(elm->topicName, topicName) == 0 && elm->msgType == msgType) if ( elm->msgType == msgType && strncmp(elm->topicName, topicName, strlen(topicName)) == 0 )
{ {
return elm; return elm;
} }
else else
{ {
elm = elm->next; elm = elm->next;
} }
} }
return 0; return 0;
} }
SubElement* LSubscribeManager::getElement(uint16_t topicId, uint8_t topicType) SubElement* LSubscribeManager::getElement(uint16_t topicId, MQTTSN_topicTypes topicType)
{ {
SubElement* elm = _first; SubElement* elm = _first;
while (elm) while (elm)
{ {
if (elm->topicId == topicId && elm->topicType == topicType) if (elm->topicId == topicId && elm->topicType == topicType)
{ {
return elm; return elm;
} }
else else
{ {
elm = elm->next; elm = elm->next;
} }
} }
return 0; return 0;
} }

View File

@@ -19,6 +19,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <time.h>
#include "LMqttsnClientApp.h" #include "LMqttsnClientApp.h"
#include "LRegisterManager.h" #include "LRegisterManager.h"
@@ -33,10 +34,10 @@ typedef struct SubElement{
TopicCallback callback; TopicCallback callback;
const char* topicName; const char* topicName;
uint16_t msgId; uint16_t msgId;
uint32_t sendUTC; time_t sendUTC;
uint16_t topicId; uint16_t topicId;
uint8_t msgType; uint8_t msgType;
uint8_t topicType; MQTTSN_topicTypes topicType;
uint8_t qos; uint8_t qos;
int retryCount; int retryCount;
@@ -55,9 +56,9 @@ public:
~LSubscribeManager(); ~LSubscribeManager();
void onConnect(void); void onConnect(void);
void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos); void subscribe(const char* topicName, TopicCallback onPublish, uint8_t qos);
void subscribe(uint16_t topicId, TopicCallback onPublish, uint8_t qos, uint8_t topicType); void subscribePredefinedId(uint16_t topicId, TopicCallback onPublish, uint8_t qos);
void unsubscribe(const char* topicName); void unsubscribe(const char* topicName);
void unsubscribe(uint16_t topicId, uint8_t topicType); void unsubscribe(uint16_t topicId);
void responce(const uint8_t* msg); void responce(const uint8_t* msg);
void checkTimeout(void); void checkTimeout(void);
bool isDone(void); bool isDone(void);
@@ -65,9 +66,9 @@ private:
void send(SubElement* elm); void send(SubElement* elm);
SubElement* getFirstElement(void); SubElement* getFirstElement(void);
SubElement* getElement(uint16_t msgId); SubElement* getElement(uint16_t msgId);
SubElement* getElement(uint16_t topicId, uint8_t topicType); SubElement* getElement(uint16_t topicId, MQTTSN_topicTypes topicType);
SubElement* getElement(const char* topicName, uint8_t msgType); SubElement* getElement(const char* topicName, uint8_t msgType);
SubElement* add(uint8_t msgType, const char* topicName, uint16_t topicId, uint8_t topicType, uint8_t qos, TopicCallback callback); SubElement* add(uint8_t msgType, const char* topicName, MQTTSN_topicTypes topicType, uint16_t topicId, uint8_t qos, TopicCallback callback);
void remove(SubElement* elm); void remove(SubElement* elm);
SubElement* _first; SubElement* _first;
SubElement* _last; SubElement* _last;

View File

@@ -14,7 +14,6 @@
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/ **************************************************************************************/
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -32,146 +31,153 @@ extern LMqttsnClient* theClient;
extern LScreen* theScreen; extern LScreen* theScreen;
extern bool theClientMode; extern bool theClientMode;
/*===================================== /*=====================================
TaskManager TaskManager
======================================*/ ======================================*/
LTaskManager::LTaskManager(void){ LTaskManager::LTaskManager(void)
_tasks = 0; {
_tests = 0; _tasks = 0;
_index = 0; _tests = 0;
_index = 0;
} }
LTaskManager::~LTaskManager(void){ LTaskManager::~LTaskManager(void)
{
} }
void LTaskManager::add(TaskList* task){ void LTaskManager::add(TaskList* task)
{
_tasks = task; _tasks = task;
} }
void LTaskManager::add(TestList* test){ void LTaskManager::add(TestList* test)
{
_tests = test; _tests = test;
} }
void LTaskManager::run(void){ void LTaskManager::run(void)
int i = 0; {
char c = 0; int i = 0;
bool cancelFlg = false; char c = 0;
bool cancelFlg = false;
TestList test = { 0 };
TaskList task = { 0 };
if ( !theClientMode ) if (!theClientMode)
{ {
theClient->getGwProxy()->getMessage(); theClient->getGwProxy()->getMessage();
for (i = 0; _tests[i].testTask > 0; i++) for (i = 0; _tests[i].testTask > test.testTask; i++)
{ {
PROMPT("Execute \"%s\" ? ( y/n ) : ", _tests[i].testLabel); PROMPT("Execute \"%s\" ? ( y/n ) : ", _tests[i].testLabel);
while (true) while (true)
{ {
if (CHECKKEYIN(&c)) if (CHECKKEYIN(&c))
{ {
if ( toupper(c) == 'N' ) if (toupper(c) == 'N')
{ {
DISPLAY("\033[0m\033[0;32m\n**** %s is canceled ****\033[0m\033[0;37m\n\n", _tests[i].testLabel); DISPLAY("\033[0m\033[0;32m\n**** %s is canceled ****\033[0m\033[0;37m\n\n", _tests[i].testLabel);
theScreen->prompt(""); theScreen->prompt("");
cancelFlg = true; cancelFlg = true;
break; break;
} }
else if ( toupper(c) == 'Y' ) else if (toupper(c) == 'Y')
{ {
DISPLAY("\033[0m\033[0;32m\n\n**** %s start ****\033[0m\033[0;37m\n", _tests[i].testLabel); DISPLAY("\033[0m\033[0;32m\n\n**** %s start ****\033[0m\033[0;37m\n", _tests[i].testLabel);
theScreen->prompt(""); theScreen->prompt("");
(_tests[i].testTask)(); (_tests[i].testTask)();
cancelFlg = false; cancelFlg = false;
break; break;
} }
} }
else else
{ {
theClient->getGwProxy()->getMessage(); theClient->getGwProxy()->getMessage();
} }
} }
while ( true ) while (true)
{ {
do do
{ {
theClient->getGwProxy()->getMessage(); theClient->getGwProxy()->getMessage();
} }
while(theClient->getPublishManager()->isMaxFlight() || while (theClient->getPublishManager()->isMaxFlight() || !theClient->getSubscribeManager()->isDone()
!theClient->getSubscribeManager()->isDone() || || !theClient->getRegisterManager()->isDone());
!theClient->getRegisterManager()->isDone());
if (theClient->getPublishManager()->isDone()) if (theClient->getPublishManager()->isDone())
{ {
break; break;
} }
} }
if ( !cancelFlg ) if (!cancelFlg)
{ {
DISPLAY("\033[0m\033[0;32m\n**** %s complete ****\033[0m\033[0;37m\n\n", _tests[i].testLabel); DISPLAY("\033[0m\033[0;32m\n**** %s complete ****\033[0m\033[0;37m\n\n", _tests[i].testLabel);
} }
} }
DISPLAY("\033[0m\033[0;32m\n\n######### All tests complete! ###########\033[0m\033[0;37m\n\n"); DISPLAY("\033[0m\033[0;32m\n\n######### All tests complete! ###########\033[0m\033[0;37m\n\n");
} }
else else
{ {
while (true) while (true)
{ {
theClient->getGwProxy()->getMessage(); theClient->getGwProxy()->getMessage();
for (_index = 0; _tasks[_index].callback > 0; _index++) for (_index = 0; _tasks[_index].callback > task.callback; _index++)
{ {
if ((_tasks[_index].prevTime + _tasks[_index].interval <= time(NULL)) && if ((_tasks[_index].prevTime + _tasks[_index].interval <= time(NULL)) && _tasks[_index].count == 0)
_tasks[_index].count == 0) {
{ _tasks[_index].prevTime = time(NULL);
_tasks[_index].prevTime = time(NULL); (_tasks[_index].callback)();
(_tasks[_index].callback)(); }
} }
}
do do
{ {
theClient->getGwProxy()->getMessage(); theClient->getGwProxy()->getMessage();
} }
while(theClient->getPublishManager()->isMaxFlight() || while (theClient->getPublishManager()->isMaxFlight() || !theClient->getSubscribeManager()->isDone()
!theClient->getSubscribeManager()->isDone() || || !theClient->getRegisterManager()->isDone());
!theClient->getRegisterManager()->isDone());
if (theClient->getPublishManager()->isDone()) if (theClient->getPublishManager()->isDone())
{ {
break; break;
} }
} }
} }
} }
uint8_t LTaskManager::getIndex(void){ uint8_t LTaskManager::getIndex(void)
return _index; {
return _index;
} }
void LTaskManager::done(uint8_t index){ void LTaskManager::done(uint8_t index)
if (_tasks ) {
{ if (_tasks)
if (_tasks[index].count > 0) {
{ if (_tasks[index].count > 0)
_tasks[index].count--; {
} _tasks[index].count--;
} }
if (_tests ) }
{ if (_tests)
if (_tests[index].count > 0) {
{ if (_tests[index].count > 0)
_tests[index].count--; {
} _tests[index].count--;
} }
}
} }
void LTaskManager::suspend(uint8_t index){ void LTaskManager::suspend(uint8_t index)
if ( _tasks ) {
{ if (_tasks)
_tasks[index].count++; {
} _tasks[index].count++;
if ( _tests ) }
{ if (_tests)
_tests[index].count++; {
} _tests[index].count++;
}
} }

View File

@@ -19,6 +19,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <time.h>
#include "LMqttsnClientApp.h" #include "LMqttsnClientApp.h"
#include "LTimer.h" #include "LTimer.h"
@@ -29,8 +30,8 @@ namespace linuxAsyncClient {
struct TaskList{ struct TaskList{
void (*callback)(void); void (*callback)(void);
uint32_t interval; time_t interval;
uint32_t prevTime; time_t prevTime;
uint8_t count; uint8_t count;
}; };

View File

@@ -16,11 +16,12 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/time.h>
#include "LMqttsnClientApp.h" #include "LMqttsnClientApp.h"
#include "LTimer.h" #include "LTimer.h"
using namespace std; //using namespace std;
using namespace linuxAsyncClient; using namespace linuxAsyncClient;
/*===================================== /*=====================================
@@ -63,3 +64,17 @@ void LTimer::stop(){
_millis = 0; _millis = 0;
} }
uint32_t LTimer::getRemain(void)
{
struct timeval curTime;
uint32_t secs, usecs;
if (_millis <= 0){
return 0;
}else{
gettimeofday(&curTime, 0);
secs = (curTime.tv_sec - _startTime.tv_sec) * 1000;
usecs = (curTime.tv_usec - _startTime.tv_usec) / 1000.0;
secs = _millis - (secs + usecs);
return secs;
}
}

View File

@@ -35,6 +35,7 @@ public:
bool isTimeUp(void); bool isTimeUp(void);
void stop(void); void stop(void);
void changeUTC(void){}; void changeUTC(void){};
uint32_t getRemain(void);
static void setUnixTime(uint32_t utc){}; static void setUnixTime(uint32_t utc){};
private: private:
struct timeval _startTime; struct timeval _startTime;

View File

@@ -131,7 +131,7 @@ LTopic* LTopicTable::getTopic(const char* topic){
return 0; return 0;
} }
LTopic* LTopicTable::getTopic(uint16_t topicId, uint8_t topicType){ LTopic* LTopicTable::getTopic(uint16_t topicId, MQTTSN_topicTypes topicType){
LTopic* p = _first; LTopic* p = _first;
while(p){ while(p){
if (p->_topicId == topicId && p->_topicType == topicType){ if (p->_topicId == topicId && p->_topicType == topicType){
@@ -156,12 +156,12 @@ char* LTopicTable::getTopicName(LTopic* topic){
} }
void LTopicTable::setTopicId(const char* topic, uint16_t id, uint8_t type){ void LTopicTable::setTopicId(const char* topic, uint16_t id, MQTTSN_topicTypes type){
LTopic* tp = getTopic(topic); LTopic* tp = getTopic(topic);
if (tp){ if (tp){
tp->_topicId = id; tp->_topicId = id;
}else{ }else{
add(topic, id, type, 0); add(topic, type, id, 0);
} }
} }
@@ -176,7 +176,7 @@ bool LTopicTable::setCallback(const char* topic, TopicCallback callback){
} }
bool LTopicTable::setCallback(uint16_t topicId, uint8_t topicType, TopicCallback callback){ bool LTopicTable::setCallback(uint16_t topicId, MQTTSN_topicTypes topicType, TopicCallback callback){
LTopic* p = getTopic(topicId, topicType); LTopic* p = getTopic(topicId, topicType);
if (p){ if (p){
p->_callback = callback; p->_callback = callback;
@@ -186,7 +186,7 @@ bool LTopicTable::setCallback(uint16_t topicId, uint8_t topicType, TopicCallback
} }
int LTopicTable::execCallback(uint16_t topicId, uint8_t* payload, uint16_t payloadlen, uint8_t topicType){ int LTopicTable::execCallback(uint16_t topicId, uint8_t* payload, uint16_t payloadlen, MQTTSN_topicTypes topicType){
LTopic* p = getTopic(topicId, topicType); LTopic* p = getTopic(topicId, topicType);
if (p){; if (p){;
return p->execCallback(payload, payloadlen); return p->execCallback(payload, payloadlen);
@@ -195,7 +195,7 @@ int LTopicTable::execCallback(uint16_t topicId, uint8_t* payload, uint16_t payl
} }
LTopic* LTopicTable::add(const char* topicName, uint16_t id, uint8_t type, TopicCallback callback, uint8_t alocFlg) LTopic* LTopicTable::add(const char* topicName, MQTTSN_topicTypes type, uint16_t id, TopicCallback callback, uint8_t alocFlg)
{ {
LTopic* elm; LTopic* elm;
@@ -234,9 +234,9 @@ exit:
return elm; return elm;
} }
void LTopicTable::remove(uint16_t topicId) void LTopicTable::remove(uint16_t topicId, MQTTSN_topicTypes type)
{ {
LTopic* elm = getTopic(topicId); LTopic* elm = getTopic(topicId, type);
if (elm){ if (elm){
if (elm->_prev == 0) if (elm->_prev == 0)

View File

@@ -42,7 +42,7 @@ public:
TopicCallback getCallback(void); TopicCallback getCallback(void);
private: private:
uint16_t _topicId; uint16_t _topicId;
uint8_t _topicType; MQTTSN_topicTypes _topicType;
char* _topicStr; char* _topicStr;
TopicCallback _callback; TopicCallback _callback;
uint8_t _malocFlg; uint8_t _malocFlg;
@@ -60,16 +60,16 @@ public:
uint16_t getTopicId(const char* topic); uint16_t getTopicId(const char* topic);
char* getTopicName(LTopic* topic); char* getTopicName(LTopic* topic);
LTopic* getTopic(const char* topic); LTopic* getTopic(const char* topic);
LTopic* getTopic(uint16_t topicId, uint8_t topicType = MQTTSN_TOPIC_TYPE_NORMAL); LTopic* getTopic(uint16_t topicId, MQTTSN_topicTypes topicType);
void setTopicId(const char* topic, uint16_t id, uint8_t topicType); void setTopicId(const char* topic, uint16_t id, MQTTSN_topicTypes topicType);
bool setCallback(const char* topic, TopicCallback callback); bool setCallback(const char* topic, TopicCallback callback);
bool setCallback(uint16_t topicId, uint8_t type, TopicCallback callback); bool setCallback(uint16_t topicId, MQTTSN_topicTypes type, TopicCallback callback);
int execCallback(uint16_t topicId, uint8_t* payload, uint16_t payloadlen, uint8_t topicType = MQTTSN_TOPIC_TYPE_NORMAL); int execCallback(uint16_t topicId, uint8_t* payload, uint16_t payloadlen, MQTTSN_topicTypes topicType);
LTopic* add(const char* topic, uint16_t id = 0, uint8_t type = MQTTSN_TOPIC_TYPE_NORMAL, TopicCallback callback = 0, uint8_t alocFlg = 0); LTopic* add(const char* topic, MQTTSN_topicTypes type, uint16_t id = 0, TopicCallback callback = 0, uint8_t alocFlg = 0);
LTopic* add(uint16_t topicId, uint16_t id, uint8_t type, TopicCallback callback, uint8_t alocFlg); //LTopic* add(uint16_t topicId, uint16_t id, MQTTSN_topicTypes type, TopicCallback callback, uint8_t alocFlg);
LTopic* match(const char* topic); LTopic* match(const char* topic);
void clearTopic(void); void clearTopic(void);
void remove(uint16_t topicId); void remove(uint16_t topicId, MQTTSN_topicTypes type);
private: private:
LTopic* _first; LTopic* _first;

View File

@@ -1,140 +0,0 @@
PROGNAME := MQTT-SNGateway
APPL := mainGateway
LPROGNAME := MQTT-SNLogmonitor
LAPPL := mainLogmonitor
TESTPROGNAME := testPFW
TESTAPPL := mainTestProcess
CONFIG := gateway.conf
CLIENTS := clients.conf
SRCDIR := src
SUBDIR := ../MQTTSNPacket/src
OS := linux
SENSORNET := udp
TEST := tests
CPPSRCS := \
$(SRCDIR)/MQTTGWConnectionHandler.cpp \
$(SRCDIR)/MQTTGWPacket.cpp \
$(SRCDIR)/MQTTGWPublishHandler.cpp \
$(SRCDIR)/MQTTGWSubscribeHandler.cpp \
$(SRCDIR)/MQTTSNGateway.cpp \
$(SRCDIR)/MQTTSNGWBrokerRecvTask.cpp \
$(SRCDIR)/MQTTSNGWBrokerSendTask.cpp \
$(SRCDIR)/MQTTSNGWClient.cpp \
$(SRCDIR)/MQTTSNGWClientRecvTask.cpp \
$(SRCDIR)/MQTTSNGWClientSendTask.cpp \
$(SRCDIR)/MQTTSNGWConnectionHandler.cpp \
$(SRCDIR)/MQTTSNGWLogmonitor.cpp \
$(SRCDIR)/MQTTSNGWPacket.cpp \
$(SRCDIR)/MQTTSNGWPacketHandleTask.cpp \
$(SRCDIR)/MQTTSNGWProcess.cpp \
$(SRCDIR)/MQTTSNGWPublishHandler.cpp \
$(SRCDIR)/MQTTSNGWSubscribeHandler.cpp \
$(SRCDIR)/$(OS)/$(SENSORNET)/SensorNetwork.cpp \
$(SRCDIR)/$(OS)/Timer.cpp \
$(SRCDIR)/$(OS)/Network.cpp \
$(SRCDIR)/$(OS)/Threading.cpp \
$(SRCDIR)/$(TEST)/TestProcess.cpp \
$(SRCDIR)/$(TEST)/TestQue.cpp \
$(SRCDIR)/$(TEST)/TestTree23.cpp \
$(SRCDIR)/$(TEST)/TestTopics.cpp \
$(SRCDIR)/$(TEST)/TestTopicIdMap.cpp \
$(SRCDIR)/$(TEST)/TestTask.cpp
CSRCS := $(SUBDIR)/MQTTSNConnectClient.c \
$(SUBDIR)/MQTTSNConnectServer.c \
$(SUBDIR)/MQTTSNDeserializePublish.c \
$(SUBDIR)/MQTTSNPacket.c \
$(SUBDIR)/MQTTSNSearchClient.c \
$(SUBDIR)/MQTTSNSearchServer.c \
$(SUBDIR)/MQTTSNSerializePublish.c \
$(SUBDIR)/MQTTSNSubscribeClient.c \
$(SUBDIR)/MQTTSNSubscribeServer.c \
$(SUBDIR)/MQTTSNUnsubscribeClient.c \
$(SUBDIR)/MQTTSNUnsubscribeServer.c
CXX := g++
CPPFLAGS +=
INCLUDES += -I$(SRCDIR) \
-I$(SRCDIR)/$(OS) \
-I$(SRCDIR)/$(OS)/$(SENSORNET) \
-I$(SUBDIR) \
-I$(SRCDIR)/$(TEST)
DEFS :=
LIBS += -L/usr/local/lib
LDFLAGS :=
CXXFLAGS := -Wall -O3 -std=c++11
LDADD := -lpthread -lssl -lcrypto -lrt
OUTDIR := Build
PROG := $(OUTDIR)/$(PROGNAME)
LPROG := $(OUTDIR)/$(LPROGNAME)
TPROG := $(OUTDIR)/$(TESTPROGNAME)
OBJS := $(CPPSRCS:%.cpp=$(OUTDIR)/%.o)
OBJS += $(CSRCS:%.c=$(OUTDIR)/%.o)
DEPS := $(CPPSRCS:%.cpp=$(OUTDIR)/%.d)
DEPS += $(CSRCS:%.c=$(OUTDIR)/%.d)
.PHONY: install clean exectest
all: $(PROG) $(LPROG) $(TPROG)
monitor: $(LPROG)
test: $(TPROG) $(LPROG) exectest
-include $(DEPS)
$(PROG): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(APPL).o
$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) $(LDADD)
$(LPROG): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(LAPPL).o
$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) $(LDADD)
$(TPROG): $(OBJS) $(OUTDIR)/$(SRCDIR)/$(TEST)/$(TESTAPPL).o
$(CXX) $(LDFLAGS) -o $@ $^ $(LIBS) $(LDADD)
$(OUTDIR)/$(SRCDIR)/%.o:$(SRCDIR)/%.cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(APPL).o:$(SRCDIR)/$(APPL).cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(TEST)/$(TESTAPPL).o:$(SRCDIR)/$(TEST)/$(TESTAPPL).cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SRCDIR)/$(LAPPL).o:$(SRCDIR)/$(LAPPL).cpp
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
$(OUTDIR)/$(SUBDIR)/%.o:$(SUBDIR)/%.c
@if [ ! -e `dirname $@` ]; then mkdir -p `dirname $@`; fi
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $(DEFS) -o $@ -c -MMD -MP -MF $(@:%.o=%.d) $<
clean:
rm -rf $(OUTDIR)
install:
cp -pf $(PROG) ../../
cp -pf $(LPROG) ../../
cp -pf $(CONFIG) ../../
cp -pf $(CLIENTS) ../../
exectest:
./$(OUTDIR)/$(TESTPROGNAME) -f ./gateway.conf

View File

@@ -1,84 +1,211 @@
**MQTT-SN** requires a MQTT-SN Gateway which acts as a protocol converter to convert **MQTT-SN messages to MQTT messages**. MQTT-SN client (UDP) can not communicate directly with MQTT broker(TCP/IP). # MQTT-SN Transparent / Aggregating Gateway
MQTT-SN requires a MQTT-SN Gateway which acts as a protocol converter to convert MQTT-SN messages to MQTT messages.
MQTT-SN client over SensorNetwork can not communicate directly with MQTT broker(TCP/IP).
This Gateway can run as a transparent or aggregating Gateway by specifying the gateway.conf.
### step1. Build the gateway
copy and expand source code then,
```
$ cd paho.mqtt-sn.embedded-c/MQTTSNGateway
```
In order to build a gateway, one sensor network argument is required.
```
$ ./build.sh [udp|udp6|xbee|loralink|rfcomm|dtls|dtls6]
```
### **step1. Build the gateway** MQTT-SNGateway and MQTT-SNLogmonitor (executable programs) are built in ./bin directory.
````
$ git clone https://github.com/eclipse/paho.mqtt-sn.embedded-c
$ cd paho.mqtt-sn.embedded-c/MQTTSNGateway
$ make
$ make install
$ make clean
````
MQTT-SNGateway, MQTT-SNLogmonitor and param.conf are copied into ../ directory.
### step2. Execute the Gateway.
### **step2. Execute the Gateway.**
```` ```
$ cd ../ $ cd bin
$ ./MQTT-SNGateway [-f Config file name] $ ./MQTT-SNGateway
```` ```
If you get the error message as follows:
### **How to Change the configuration of the gateway** RingBuffer can't create a shared memory. ABORT Gateway!!!
**../gateway.conf** Contents are follows: You have to start using sudo command only once for the first time.
```
```` $ sudo ./MQTT-SNGateway
```
## Contents of the gateway configuration file
**gateway.conf** is in bin directory. It's contents are follows:
```
#**************************************************************************
# Copyright (c) 2016-2021, Tomoaki Yamaguchi
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# and Eclipse Distribution License v1.0 which accompany this distribution.
#
# The Eclipse Public License is available at
# http://www.eclipse.org/legal/epl-v10.html
# and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#***************************************************************************
#
# config file of MQTT-SN Gateway # config file of MQTT-SN Gateway
#
BrokerName=iot.eclipse.org GatewayID=1
GatewayName=PahoGateway-01
MaxNumberOfClients=30
KeepAlive=60
#LoginID=your_ID
#Password=your_Password
BrokerName=mqtt.eclipseprojects.io
BrokerPortNo=1883 BrokerPortNo=1883
BrokerSecurePortNo=8883 BrokerSecurePortNo=8883
```
**GatewayID** is a gateway ID which used by GWINFO message.
**GatewayName** is a name of the gateway.
**MaxNumberOfClients** is a maxmum number of clients. Clients are dynamically allocated.
**KeepAlive** is KeepAlive time in seconds.
**LoginID** is used by CONNECT message.
**Password** is used by CONNECT message.
**BrokerName**is a domain name or IP address of a broker.
**BrokerPortNo** is a broker's port no.
**BrokerSecurePortNo** is a broker's port no of TLS connection.
```
#
# CertKey for TLS connections to a broker
#
#RootCAfile=/etc/ssl/certs/ca-certificates.crt
#RootCApath=/etc/ssl/certs/
#CertKey=/path/to/certKey.pem
#PrivateKey=/path/to/privateKey.pem
```
**RootCAfile** is a CA file name.
**RootCApath** is a CA path. **SSL_CTX_load_verify_locations(ctx, CAfile, CApath)** function requires these parameters.
**CertKey** is a certificate pem file.
**PrivateKey** is a private key pem file.
Clients can connect to the broker via TLS by setting '**Secure Connection**' for each client in the client conf file.
```
#
# When AggregatingGateway=YES or ClientAuthentication=YES,
# All clients must be specified by the ClientList File
#
AggregatingGateway=NO
QoS-1=NO
Forwarder=NO
PredefinedTopic=NO
ClientAuthentication=NO ClientAuthentication=NO
#ClientsList=/path/to/your_clients.conf
#RootCAfile=/path/to/your_Root_CA.crt
#RootCApath=/path/to/your_certs_directory/
#CertKey=/path/to/your_cert.pem
#PrivateKey=/path/to/your_private-key.pem
GatewayID=1
GatewayName=PahoGateway-01
KeepAlive=900
#LoginID=your_ID
#Password=your_Password
# UDP ClientsList=/path/to/your_clients.conf
GatewayPortNo=10000 PredefinedTopicList=/path/to/your_predefinedTopic.conf
MulticastIP=225.1.1.1 ```
MulticastPortNo=1883 The gateway runs as a aggregating gateway when **AggregatingGateway** is 'YES'.
If **QoS-1** is 'YES, the gateway prepares a proxy for the QoS-1 client. QoS-1 client has a 'QoS-1' parameter in a clients.conf file. For QoS-1 clients, set the QoS-1 parameters in the clients.conf file.
If **Forwarder** is 'YES', the gateway prepare a forwarder agent.
If **ClientAuthentication** is 'YES', the client cannot connect unless it is registered in the clients.conf file.
**ClientsList** defines clients and those address so on.
**PredefinedTopicList** file defines Predefined Topic.
```
#==============================
# SensorNetworks parameters
#==============================
#
# UDP | DTLS
#
GatewayPortNo=10000
MulticastPortNo=1883
MulticastIP=225.1.1.1
MulticastTTL=1
```
**GatewayPortNo** is a unicast port no of the gateway.
**MulticastIP** and **MulticastPortNo** are for GWSEARCH messages. Clients can get the gateway address (Gateway IP address and GatewayPortNo) from GWINFO message by means of std::recvfrom().
Client needs to know the MulticastIP and MulticastPortNo to send a SEARCHGW message.
**MulticastTTL** is a multicast TTL.
```
#
# UDP6 | DTLS6
#
GatewayIPv6PortNo=10000
MulticastIPv6PortNo=1883
MulticastIPv6=ff1e:feed:caca:dead::feed:caca:dead
MulticastIPv6If=wlp4s0
MulticastHops=1
```
**GatewayIPv6PortNo** is a unicast port no of the gateway.
**MulticastIPv6PortNo** and **MulticastIPv6** are for GWSEARCH messages. Set the Global scope Multicast address so that the Global address is used for sending GWINFO.
Clients can get the gateway address (Gateway IPv6 address and GatewayPortNo) from GWINFO message by means of std::recvfrom().
**MulticastIPv6If** is a multicast interface name.
**MulticastHops** is a multicast hops.
```
#
# DTLS | DTLS6 DTLS CertsKey
#
DtlsCertsKey=/etc/ssl/certs/gateway.pem
DtlsPrivKey=/etc/ssl/private/privkey.pem
```
**DtlsCertsKey** is a certs Key pem file for DTLS connection.
**DtlsPrivKey** is a private key pem file for DTLS connection.
```
#
# XBee # XBee
Baudrate=38400 #
SerialDevice=/dev/ttyUSB0
ApiMode=2
````
**BrokerName** to specify a domain name of the Broker, and **BrokerPortNo** is a port No of the Broker. **BrokerSecurePortNo** is for TLS connection. Baudrate=38400
**MulticastIP** and **MulticastPortNo** is a multicast address for ADVERTISE, GWSEARCH and GWINFO messages. Gateway is waiting GWSEARCH multicast message and when receiving it send GWINFO message via Broadcast address. Clients can get the gateway address (Gateway IP address and **GatewayPortNo**) from GWINFO message by means of std::recvfrom(), SerialDevice=/dev/ttyUSB0
Client should know the BroadcastIP and PortNo to send a SEARCHGW message. ApiMode=2
**GatewayId** is defined by GWSEARCH message. ```
**KeepAlive** is a duration of ADVERTISE message in seconds. **Baudrate** is a baudrate of xbee.
when **ClientAuthentication** is YES, see MQTTSNGWClient.cpp line53, clients file specified by ClientsList is required. This file defines connect allowed clients by ClientId and SensorNetwork Address. e.g. IP address and Port No. ```
#
# LoRaLink
#
BaudrateLoRaLink=115200
DeviceRxLoRaLink=/dev/loralinkRx
DeviceTxLoRaLink=/dev/loralinkTx
```
https://github.com/ty4tw/MQTT-SN-LoRa
```
#
# Bluetooth RFCOMM
#
### ** How to monitor the gateway from remote. ** RFCOMMAddress=60:57:18:06:8B:72.*
```
**RFCOMMAddress** is a bluetooth mac address and channel. channel should be * for the gateway.
```
#
# LOG
#
Uncomment line32 in MQTTSNGWDefined.h. ShearedMemory=NO
```
`//#define RINGBUFFER // print out Packets log into shared memory./"` ### How to monitor the gateway from a remote terminal.
```` Change gateway.conf as follows:
$ make ```
$ make install # LOG
$ make clean ShearedMemory=YES;
```` ```
restart the gateway. Restart the gateway with sudo only once to create shared memories.
open ssh terminal and execute LogMonitor. open ssh terminal and execute LogMonitor.
```
`$ ./MQTT-SNLogmonitor` $ cd bin
$ ./MQTT-SNLogmonitor
```
Now you can get the Log on your terminal. Now you can get the Log on your terminal.
##### Tips
Use compiler definitions then you can get more precise logs.
**-DDEBUG_NW** is a flag for debug logs of Sensor network.
**-DDEBUG_MQTTSN** is a flag for debug logs of MQTT-SN message haandling.
One or both flags can be specified.
```
./build.sh udp -DDEBUG -DDEBUG_NW
```

46
MQTTSNGateway/build.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/bin/bash
WORK_DIR=$(realpath $(dirname "$0")/..)
BDIR=build.gateway
ODIR=bin/
build () {
echo "Start building MQTT-SN Gateway $1"
pushd "$WORK_DIR"
if [ ! -d ./$BDIR ]; then
mkdir $BDIR
fi
cd $BDIR
cmake .. -DSENSORNET=$1 -DDEFS="${2} ${3}"
make MQTTSNPacket
make MQTT-SNGateway
make MQTT-SNLogmonitor
popd
cp *.conf ./$ODIR
}
if [ $1 == "udp" ] ; then
build $1 $2 $3
elif [ $1 == "udp6" ] ; then
build $1 $2 $3
elif [ $1 == "xbee" ] ; then
build $1 $2 $3
elif [ $1 == "loralink" ]; then
build $1 $2 $3
elif [ $1 == "rfcomm" ] ; then
build $1 $2 $3
elif [ $1 == "dtls" ] ; then
build $1 $2 $3
elif [ $1 == "dtls6" ] ; then
build dtls "${2} ${3} -DDTLS6"
elif [ $1 == "clean" ] ; then
pushd "$WORK_DIR"
rm -rf ./$BDIR
popd
rm -rf ./$ODIR
else
echo "Usage: build.sh [ udp | udp6 | xbee | loralink | rfcomm | dtls | dtls6 | clean]"
fi

View File

@@ -11,8 +11,48 @@
# http://www.eclipse.org/org/documents/edl-v10.php. # http://www.eclipse.org/org/documents/edl-v10.php.
#*********************************************************************** #***********************************************************************
# #
# File format is:
# Lines bigning with # are comment line.
# ClientId, SensorNetAddress, "unstableLine", "secureConnection"
# in case of UDP, SensorNetAddress format is IPAddress: port no.
# if the SensorNetwork is not stable, specify "unstableLine".
# if Broker's Connection is TLS, specify "secureConnection".
# if the client is a forwarder,specify "forwarder".
# if the client send PUBLISH QoS-1, specify "QoS-1".
#
# Ex:
# #Client List
# ClientId1,192.168.10.10:11200
# ClientID2,192.168.50.200:35000,unstableLine
# ClientID3,192.168.200.50:40000,secureConnection
# ClientID4,192.168.200.52:41000,unstableLine,secureConnection
# ClientID5,192.168.200.53:41000,unstableLine,secureConnection,QoS-1
# ClientID6,192.168.200.54:41000,unstableLine,secureConnection,forwarder
#
# SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function. # SensorNetwork address format is defined by SensorNetAddress::setAddress(string* data) function.
# #
Client02,172.16.1.7:12002 # UDP6 (IPv6 UDP) [IPv6 address]:PortNo
Client03,172.16.1.8:13003 # RFCOMM Device_address.channel (1-30)
Client01,172.16.1.6:12001 # XBee FFFFFFFFFFFFFFFF 8bytes Hex
# LoRaLink 1-254
#
#
# This is a sample of UDP.
#
# REWRITE ALL ACCORDING TO YOUR CLIENTS.
#
GatewayTester, 172.16.1.11:20020
ClientPUB,172.16.1.11:2010
Client01,172.16.1.11:12001
Client02,172.16.1.11:12002
Client03,172.16.1.11:13003
QoS-1_Client01,172.16.1.11:20001,QoS-1
QoS-1_Client02,172.16.1.11:20002,QoS-1
QoS-1_Client03,172.16.1.11:20003,QoS-1
Forwarder01,172.16.1.11:22002,forwarder
Forwarder02,172.16.1.11:22003,forwarder
Forwarder03,172.16.1.11:22004,forwarder

View File

@@ -1,5 +1,5 @@
#************************************************************************** #**************************************************************************
# Copyright (c) 2016, Tomoaki Yamaguchi # Copyright (c) 2016-2021, Tomoaki Yamaguchi
# #
# All rights reserved. This program and the accompanying materials # All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0 # are made available under the terms of the Eclipse Public License v1.0
@@ -10,37 +10,99 @@
# and the Eclipse Distribution License is available at # and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php. # http://www.eclipse.org/org/documents/edl-v10.php.
#*************************************************************************** #***************************************************************************
#
# config file of MQTT-SN Gateway # config file of MQTT-SN Gateway
#
BrokerName=iot.eclipse.org
BrokerPortNo=1883
BrokerSecurePortNo=8883
ClientAuthentication=NO
#ClientsList=/path/to/your_clients.conf
#RootCAfile=/etc/ssl/certs/ca-certificates.crt
#RootCApath=/etc/ssl/certs/
#CertsFile=/path/to/certKey.pem
#PrivateKey=/path/to/privateKey.pem
GatewayID=1 GatewayID=1
GatewayName=PahoGateway-01 GatewayName=PahoGateway-01
KeepAlive=900 MaxNumberOfClients=30
KeepAlive=60
#LoginID=your_ID #LoginID=your_ID
#Password=your_Password #Password=your_Password
# UDP BrokerName=mqtt.eclipseprojects.io
GatewayPortNo=10000 BrokerPortNo=1883
MulticastIP=225.1.1.1 BrokerSecurePortNo=8883
MulticastPortNo=1883
#
# CertsKey for TLS connections to a broker
#
#RootCAfile=/etc/ssl/certs/ca-certificates.crt
#RootCApath=/etc/ssl/certs/
#CertKey=/path/to/certKey.pem
#PrivateKey=/path/to/privateKey.pem
#
# When AggregatingGateway=YES or ClientAuthentication=YES,
# All clients must be specified by the ClientList File
#
AggregatingGateway=NO
QoS-1=NO
Forwarder=NO
PredefinedTopic=NO
ClientAuthentication=NO
ClientsList=/path/to/your_clients.conf
PredefinedTopicList=/path/to/your_predefinedTopic.conf
#==============================
# SensorNetworks parameters
#==============================
#
# UDP | DTLS
#
GatewayPortNo=10000
MulticastPortNo=1883
MulticastIP=225.1.1.1
MulticastTTL=1
#
# UDP6 | DTLS6
#
GatewayIPv6PortNo=10000
MulticastIPv6PortNo=1883
MulticastIPv6=ff1e:feed:caca:dead::1
MulticastIPv6If=wlp4s0
MulticastHops=1
#
# DTLS | DTLS6
#
DtlsCertsKey=/etc/ssl/certs/gateway.pem
DtlsPrivKey=/etc/ssl/private/privkey.pem
#
# XBee # XBee
#
Baudrate=38400 Baudrate=38400
SerialDevice=/dev/ttyUSB0 SerialDevice=/dev/ttyUSB0
ApiMode=2 ApiMode=2
# LOG #
ShearedMemory=NO; # LoRaLink
#
BaudrateLoRaLink=115200
DeviceRxLoRaLink=/dev/loralinkRx
DeviceTxLoRaLink=/dev/loralinkTx
#
# Bluetooth RFCOMM
#
RFCOMMAddress=60:57:18:06:8B:72.*
#
# LOG
#
ShearedMemory=NO

View File

@@ -0,0 +1,36 @@
#***********************************************************************
# Copyright (c) 2017, Tomoaki Yamaguchi
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# and Eclipse Distribution License v1.0 which accompany this distribution.
#
# The Eclipse Public License is available at
# http://www.eclipse.org/legal/epl-v10.html
# and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#***********************************************************************
#
# pre-defined-topics are defined by this file.
# A format of this file is in CSV as follows:
#
# ClientID, TopicName, TopicID
#
# Topics is common to all clients, ClientID should be *.
#
# pre-defined-topics for Clients
#
*,ty4tw/predefinedTopic1, 1
GatewayTestClient,ty4tw/predefinedTopic2, 2
GatewayTestClient,ty4tw/predefinedTopic3, 3
#
# pre-defined-topics for QoS-1 clients.
#
QoS-1_Client03,ty4tw/proxy/predefTopic4, 1
QoS-1_Client03,ty4tw/proxy/predefTopic5, 2
QoS-1_Client03,ty4tw/proxy/predefTopic6, 3

View File

@@ -0,0 +1,151 @@
#*******************************************************************************
# Copyright (c) 2022 a1lu
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# and Eclipse Distribution License v1.0 which accompany this distribution.
#
# The Eclipse Public License is available at
# http://www.eclipse.org/legal/epl-v10.html
# and the Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# Contributors:
# a1lu - initial version
# ty4tw - modify
#*******************************************************************************/
PROJECT(mqtt-sn-gateway CXX)
SET(GW_VERSION_MAJOR 1)
SET(GW_VERSION_MINOR 5)
SET(GW_VERSION_PATCH 1)
SET(GATEWAY_VERSION ${GW_VERSION_MAJOR}.${GW_VERSION_MINOR}.${GW_VERSION_PATCH})
MESSAGE(STATUS "VERSION : ${GATEWAY_VERSION}")
configure_file( MQTTSNGWVersion.h.in ${CMAKE_CURRENT_SOURCE_DIR}/MQTTSNGWVersion.h )
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../bin)
SET(CMAKE_CXX_STANDARD 11)
SET(OS linux)
IF(NOT DEFINED SENSORNET)
SET(SENSORNET udp)
ENDIF()
MESSAGE(STATUS "SENSORNET: " ${SENSORNET})
ADD_DEFINITIONS(${DEFS})
MESSAGE(STATUS "Definitions: " ${DEFS})
ADD_LIBRARY(mqtt-sngateway_common
MQTTGWConnectionHandler.cpp
MQTTGWPacket.cpp
MQTTGWPublishHandler.cpp
MQTTGWSubscribeHandler.cpp
MQTTSNGateway.cpp
MQTTSNGWBrokerRecvTask.cpp
MQTTSNGWBrokerSendTask.cpp
MQTTSNGWClient.cpp
MQTTSNGWClientRecvTask.cpp
MQTTSNGWClientSendTask.cpp
MQTTSNGWConnectionHandler.cpp
MQTTSNGWLogmonitor.cpp
MQTTSNGWPacket.cpp
MQTTSNGWPacketHandleTask.cpp
MQTTSNGWProcess.cpp
MQTTSNGWPublishHandler.cpp
MQTTSNGWSubscribeHandler.cpp
MQTTSNGWEncapsulatedPacket.cpp
MQTTSNGWForwarder.cpp
MQTTSNGWQoSm1Proxy.cpp
MQTTSNGWAdapter.cpp
MQTTSNGWAggregater.cpp
MQTTSNGWClientList.cpp
MQTTSNGWTopic.cpp
MQTTSNGWAdapterManager.cpp
MQTTSNAggregateConnectionHandler.cpp
MQTTSNGWMessageIdTable.cpp
MQTTSNGWAggregateTopicTable.cpp
${OS}/${SENSORNET}/SensorNetwork.cpp
${OS}/${SENSORNET}/SensorNetwork.h
${OS}/Timer.cpp
${OS}/Timer.h
${OS}/Network.cpp
${OS}/Network.h
${OS}/Threading.cpp
${OS}/Threading.h
)
# linux
link_directories("/usr/local/lib")
# Mac
link_directories("/usr/local/opt/openssl/lib")
TARGET_INCLUDE_DIRECTORIES(mqtt-sngateway_common
PUBLIC
.
${OS}
${OS}/${SENSORNET}
../../MQTTSNPacket/src
/usr/local/include
/usr/local/opt/openssl/include
)
IF(SENSORNET MATCHES "rfcomm")
TARGET_LINK_LIBRARIES(mqtt-sngateway_common
PRIVATE
MQTTSNPacket
pthread
ssl
crypto
bluetooth
)
ELSE()
TARGET_LINK_LIBRARIES(mqtt-sngateway_common
PRIVATE
MQTTSNPacket
pthread
ssl
crypto
)
ENDIF()
ADD_EXECUTABLE(MQTT-SNGateway
mainGateway.cpp
)
TARGET_LINK_LIBRARIES(MQTT-SNGateway
mqtt-sngateway_common
)
ADD_EXECUTABLE(MQTT-SNLogmonitor
mainLogmonitor.cpp
)
TARGET_LINK_LIBRARIES(MQTT-SNLogmonitor
mqtt-sngateway_common
)
ADD_EXECUTABLE(testPFW
tests/mainTestProcess.cpp
tests/TestProcess.cpp
tests/TestQue.cpp
tests/TestTree23.cpp
tests/TestTopics.cpp
tests/TestTopicIdMap.cpp
tests/TestTask.cpp
)
TARGET_LINK_LIBRARIES(testPFW
mqtt-sngateway_common
)
ADD_TEST(NAME testPFW
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/..
COMMAND testPFW -f ./gateway.conf)

View File

@@ -1,5 +1,5 @@
/************************************************************************************** /**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi * Copyright (c) 2016, 2020 Tomoaki Yamaguchi and others
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
@@ -22,7 +22,7 @@ using namespace MQTTSNGW;
MQTTGWConnectionHandler::MQTTGWConnectionHandler(Gateway* gateway) MQTTGWConnectionHandler::MQTTGWConnectionHandler(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
} }
MQTTGWConnectionHandler::~MQTTGWConnectionHandler() MQTTGWConnectionHandler::~MQTTGWConnectionHandler()
@@ -32,75 +32,67 @@ MQTTGWConnectionHandler::~MQTTGWConnectionHandler()
void MQTTGWConnectionHandler::handleConnack(Client* client, MQTTGWPacket* packet) void MQTTGWConnectionHandler::handleConnack(Client* client, MQTTGWPacket* packet)
{ {
uint8_t rc = MQTT_SERVER_UNAVAILABLE; uint8_t rc = MQTT_SERVER_UNAVAILABLE;
Connack resp; Connack resp;
packet->getCONNACK(&resp); packet->getCONNACK(&resp);
/* convert MQTT ReturnCode to MQTT-SN one */ /* convert MQTT ReturnCode to MQTT-SN one */
if (resp.rc == MQTT_CONNECTION_ACCEPTED) if (resp.rc == MQTT_CONNECTION_ACCEPTED)
{ {
rc = MQTTSN_RC_ACCEPTED; rc = MQTTSN_RC_ACCEPTED;
} }
else if (resp.rc == MQTT_UNACCEPTABLE_PROTOCOL_VERSION) else if (resp.rc == MQTT_UNACCEPTABLE_PROTOCOL_VERSION)
{ {
rc = MQTTSN_RC_NOT_SUPPORTED; rc = MQTTSN_RC_NOT_SUPPORTED;
WRITELOG(" ClientID : %s Requested Protocol version is not supported.\n", client->getClientId()); WRITELOG(" ClientID : %s Requested Protocol version is not supported.\n", client->getClientId());
} }
else if (resp.rc == MQTT_IDENTIFIER_REJECTED) else if (resp.rc == MQTT_IDENTIFIER_REJECTED)
{ {
rc = MQTTSN_RC_NOT_SUPPORTED; rc = MQTTSN_RC_NOT_SUPPORTED;
WRITELOG(" ClientID : %s ClientID is collect UTF-8 but not allowed by the Server.\n", WRITELOG(" ClientID : %s ClientID is collect UTF-8 but not allowed by the Server.\n", client->getClientId());
client->getClientId()); }
} else if (resp.rc == MQTT_SERVER_UNAVAILABLE)
else if (resp.rc == MQTT_SERVER_UNAVAILABLE) {
{ rc = MQTTSN_RC_REJECTED_CONGESTED;
rc = MQTTSN_RC_REJECTED_CONGESTED; WRITELOG(" ClientID : %s The Network Connection has been made but the MQTT service is unavailable.\n",
WRITELOG(" ClientID : %s The Network Connection has been made but the MQTT service is unavailable.\n", client->getClientId());
client->getClientId()); }
} else if (resp.rc == MQTT_BAD_USERNAME_OR_PASSWORD)
else if (resp.rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
{ rc = MQTTSN_RC_NOT_SUPPORTED;
rc = MQTTSN_RC_NOT_SUPPORTED; WRITELOG(" Gateway Configuration Error: The data in the user name or password is malformed.\n");
WRITELOG(" Gateway Configuration Error: The data in the user name or password is malformed.\n"); }
} else if (resp.rc == MQTT_NOT_AUTHORIZED)
else if (resp.rc == MQTT_NOT_AUTHORIZED) {
{ rc = MQTTSN_RC_NOT_SUPPORTED;
rc = MQTTSN_RC_NOT_SUPPORTED; WRITELOG(" Gateway Configuration Error: The Client is not authorized to connect.\n");
WRITELOG(" Gateway Configuration Error: The Client is not authorized to connect.\n"); }
}
MQTTSNPacket* snPacket = new MQTTSNPacket(); MQTTSNPacket* snPacket = new MQTTSNPacket();
snPacket->setCONNACK(rc); snPacket->setCONNACK(rc);
Event* ev1 = new Event(); Event* ev1 = new Event();
ev1->setClientSendEvent(client, snPacket); ev1->setClientSendEvent(client, snPacket);
client->connackSended(rc); // update the client's status client->connackSended(rc); // update the client's status
_gateway->getClientSendQue()->post(ev1); _gateway->getClientSendQue()->post(ev1);
MQTTSNPacket* sleepPacket = 0;
while ( (sleepPacket = client->getClientSleepPacket()) )
{
Event* ev1 = new Event();
ev1->setClientSendEvent(client, sleepPacket);
_gateway->getClientSendQue()->post(ev1);
}
} }
void MQTTGWConnectionHandler::handlePingresp(Client* client, MQTTGWPacket* packet) void MQTTGWConnectionHandler::handlePingresp(Client* client, MQTTGWPacket* packet)
{ {
MQTTSNPacket* snPacket = new MQTTSNPacket(); MQTTSNPacket* snPacket = new MQTTSNPacket();
snPacket->setPINGRESP(); snPacket->setPINGRESP();
Event* ev1 = new Event(); Event* ev1 = new Event();
ev1->setClientSendEvent(client, snPacket); ev1->setClientSendEvent(client, snPacket);
_gateway->getClientSendQue()->post(ev1); client->updateStatus(snPacket);
_gateway->getClientSendQue()->post(ev1);
} }
void MQTTGWConnectionHandler::handleDisconnect(Client* client, MQTTGWPacket* packet) void MQTTGWConnectionHandler::handleDisconnect(Client* client, MQTTGWPacket* packet)
{ {
MQTTSNPacket* snPacket = new MQTTSNPacket(); MQTTSNPacket* snPacket = new MQTTSNPacket();
snPacket->setDISCONNECT(0); snPacket->setDISCONNECT(0);
client->disconnected(); client->disconnected();
client->getNetwork()->close(); client->getNetwork()->close();
Event* ev1 = new Event(); Event* ev1 = new Event();
ev1->setClientSendEvent(client, snPacket); ev1->setClientSendEvent(client, snPacket);
} }

View File

@@ -26,13 +26,13 @@ namespace MQTTSNGW
class MQTTGWConnectionHandler class MQTTGWConnectionHandler
{ {
public: public:
MQTTGWConnectionHandler(Gateway* gateway); MQTTGWConnectionHandler(Gateway* gateway);
~MQTTGWConnectionHandler(); ~MQTTGWConnectionHandler();
void handleConnack(Client* client, MQTTGWPacket* packet); void handleConnack(Client* client, MQTTGWPacket* packet);
void handlePingresp(Client* client, MQTTGWPacket* packet); void handlePingresp(Client* client, MQTTGWPacket* packet);
void handleDisconnect(Client* client, MQTTGWPacket* packet); void handleDisconnect(Client* client, MQTTGWPacket* packet);
private: private:
Gateway* _gateway; Gateway* _gateway;
}; };
} }

View File

@@ -21,13 +21,15 @@
using namespace MQTTSNGW; using namespace MQTTSNGW;
int readInt(char** ptr);
void writeInt(unsigned char** pptr, int msgId);
#define MAX_NO_OF_REMAINING_LENGTH_BYTES 3 #define MAX_NO_OF_REMAINING_LENGTH_BYTES 3
/** /**
* List of the predefined MQTT v3 packet names. * List of the predefined MQTT v3 packet names.
*/ */
static const char* mqtt_packet_names[] = static const char* mqtt_packet_names[] = { "RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL", "PUBCOMP",
{ "RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL", "PUBCOMP", "SUBSCRIBE", "SUBACK", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", "DISCONNECT" };
"UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", "DISCONNECT" };
/** /**
* Encodes the message length according to the MQTT algorithm * Encodes the message length according to the MQTT algorithm
@@ -37,17 +39,18 @@ static const char* mqtt_packet_names[] =
*/ */
int MQTTPacket_encode(char* buf, int length) int MQTTPacket_encode(char* buf, int length)
{ {
int rc = 0; int rc = 0;
do do
{ {
char d = length % 128; char d = length % 128;
length /= 128; length /= 128;
/* if there are more digits to encode, set the top bit of this digit */ /* if there are more digits to encode, set the top bit of this digit */
if (length > 0) if (length > 0)
d |= 0x80; d |= 0x80;
buf[rc++] = d; buf[rc++] = d;
} while (length > 0); }
return rc; while (length > 0);
return rc;
} }
/** /**
@@ -57,10 +60,10 @@ int MQTTPacket_encode(char* buf, int length)
*/ */
int readInt(char** pptr) int readInt(char** pptr)
{ {
char* ptr = *pptr; char* ptr = *pptr;
int len = 256 * ((unsigned char) (*ptr)) + (unsigned char) (*(ptr + 1)); int len = 256 * ((unsigned char) (*ptr)) + (unsigned char) (*(ptr + 1));
*pptr += 2; *pptr += 2;
return len; return len;
} }
/** /**
@@ -77,20 +80,20 @@ int readInt(char** pptr)
*/ */
char* readUTFlen(char** pptr, char* enddata, int* len) char* readUTFlen(char** pptr, char* enddata, int* len)
{ {
char* string = NULL; char* string = NULL;
if (enddata - (*pptr) > 1) /* enough length to read the integer? */ if (enddata - (*pptr) > 1) /* enough length to read the integer? */
{ {
*len = readInt(pptr); *len = readInt(pptr);
if (&(*pptr)[*len] <= enddata) if (&(*pptr)[*len] <= enddata)
{ {
string = (char*)calloc(*len + 1, 1); string = (char*) calloc(*len + 1, 1);
memcpy(string, *pptr, (size_t)*len); memcpy(string, *pptr, (size_t) *len);
string[*len] = '\0'; string[*len] = '\0';
*pptr += *len; *pptr += *len;
} }
} }
return string; return string;
} }
/** /**
@@ -105,8 +108,8 @@ char* readUTFlen(char** pptr, char* enddata, int* len)
*/ */
char* readUTF(char** pptr, char* enddata) char* readUTF(char** pptr, char* enddata)
{ {
int len; int len;
return readUTFlen(pptr, enddata, &len); return readUTFlen(pptr, enddata, &len);
} }
/** /**
@@ -116,9 +119,9 @@ char* readUTF(char** pptr, char* enddata)
*/ */
unsigned char readChar(char** pptr) unsigned char readChar(char** pptr)
{ {
unsigned char c = **pptr; unsigned char c = **pptr;
(*pptr)++; (*pptr)++;
return c; return c;
} }
/** /**
@@ -128,8 +131,8 @@ unsigned char readChar(char** pptr)
*/ */
void writeChar(unsigned char** pptr, char c) void writeChar(unsigned char** pptr, char c)
{ {
**pptr = c; **pptr = c;
(*pptr)++; (*pptr)++;
} }
/** /**
@@ -139,10 +142,10 @@ void writeChar(unsigned char** pptr, char c)
*/ */
void writeInt(unsigned char** pptr, int anInt) void writeInt(unsigned char** pptr, int anInt)
{ {
**pptr = (unsigned char)(anInt / 256); **pptr = (unsigned char) (anInt / 256);
(*pptr)++; (*pptr)++;
**pptr = (unsigned char)(anInt % 256); **pptr = (unsigned char) (anInt % 256);
(*pptr)++; (*pptr)++;
} }
/** /**
@@ -152,10 +155,10 @@ void writeInt(unsigned char** pptr, int anInt)
*/ */
void writeUTF(unsigned char** pptr, const char* string) void writeUTF(unsigned char** pptr, const char* string)
{ {
int len = (int)strlen(string); int len = (int) strlen(string);
writeInt(pptr, len); writeInt(pptr, len);
memcpy(*pptr, string, (size_t)len); memcpy(*pptr, string, (size_t) len);
*pptr += len; *pptr += len;
} }
/** /**
@@ -164,379 +167,480 @@ void writeUTF(unsigned char** pptr, const char* string)
*/ */
MQTTGWPacket::MQTTGWPacket() MQTTGWPacket::MQTTGWPacket()
{ {
_data = 0; _data = 0;
_header.byte = 0; _header.byte = 0;
_remainingLength = 0; _remainingLength = 0;
} }
MQTTGWPacket::~MQTTGWPacket() MQTTGWPacket::~MQTTGWPacket()
{ {
if (_data) if (_data)
{ {
free(_data); free(_data);
} }
} }
int MQTTGWPacket::recv(Network* network) int MQTTGWPacket::recv(Network* network)
{ {
int len = 0; int len = 0;
int multiplier = 1; int multiplier = 1;
unsigned char c; unsigned char c;
/* read First Byte of Packet */ /* read First Byte of Packet */
int rc = network->recv((unsigned char*)&_header.byte, 1); int rc = network->recv((unsigned char*) &_header.byte, 1);
if ( rc <= 0) if (rc <= 0)
{ {
return rc; return rc;
} }
/* read RemainingLength */ /* read RemainingLength */
do do
{ {
if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
{ {
return -2; return -2;
} }
if (network->recv(&c, 1) == -1) if (network->recv(&c, 1) == -1)
{ {
return -1; return -1;
} }
_remainingLength += (c & 127) * multiplier; _remainingLength += (c & 127) * multiplier;
multiplier *= 128; multiplier *= 128;
} while ((c & 128) != 0); }
while ((c & 128) != 0);
/* allocate buffer */ if (_remainingLength > 0)
_data = (unsigned char*)calloc(_remainingLength, 1); {
if ( !_data ) /* allocate buffer */
{ _data = (unsigned char*) calloc(_remainingLength, 1);
return -3; if (!_data)
} {
return -3;
}
/* read Payload */ /* read Payload */
int remlen = network->recv(_data, _remainingLength); int remlen = network->recv(_data, _remainingLength);
if (remlen == -1 ) if (remlen == -1)
{ {
return -1; return -1;
} }
else if ( remlen != _remainingLength ) else if (remlen != _remainingLength)
{ {
return -2; return -2;
} }
return 1 + len + _remainingLength; }
return 1 + len + _remainingLength;
} }
int MQTTGWPacket::send(Network* network) int MQTTGWPacket::send(Network* network)
{ {
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE];
memset(buf, 0, MQTTSNGW_MAX_PACKET_SIZE); memset(buf, 0, MQTTSNGW_MAX_PACKET_SIZE);
int len = getPacketData(buf); int len = getPacketData(buf);
return network->send(buf, len); return network->send(buf, len);
} }
int MQTTGWPacket::getAck(Ack* ack) int MQTTGWPacket::getAck(Ack* ack)
{ {
if (PUBACK != _header.bits.type && PUBREC != _header.bits.type && PUBREL != _header.bits.type if (PUBACK != _header.bits.type && PUBREC != _header.bits.type && PUBREL != _header.bits.type
&& PUBCOMP != _header.bits.type && UNSUBACK != _header.bits.type) && PUBCOMP != _header.bits.type && UNSUBACK != _header.bits.type)
{ {
return 0; return 0;
} }
char* ptr = (char*) _data; char* ptr = (char*) _data;
ack->header.byte = _header.byte; ack->header.byte = _header.byte;
ack->msgId = readInt((char**) &ptr); ack->msgId = readInt((char**) &ptr);
return 1; return 1;
} }
int MQTTGWPacket::getCONNACK(Connack* resp) int MQTTGWPacket::getCONNACK(Connack* resp)
{ {
if (_header.bits.type != CONNACK) if (_header.bits.type != CONNACK)
{ {
return 0; return 0;
} }
char* ptr = (char*) _data; char* ptr = (char*) _data;
resp->header.byte = _header.byte; resp->header.byte = _header.byte;
resp->flags.all = *ptr++; resp->flags.all = *ptr++;
resp->rc = readChar(&ptr); resp->rc = readChar(&ptr);
return 1; return 1;
} }
int MQTTGWPacket::getSUBACK(unsigned short* msgId, unsigned char* rc) int MQTTGWPacket::getSUBACK(unsigned short* msgId, unsigned char* rc)
{ {
if (_header.bits.type != SUBACK) if (_header.bits.type != SUBACK)
{ {
return 0; return 0;
} }
char *ptr = (char*) _data; char *ptr = (char*) _data;
*msgId = readInt((char**) &ptr); *msgId = readInt((char**) &ptr);
*rc = readChar(&ptr); *rc = readChar(&ptr);
return 1; return 1;
} }
int MQTTGWPacket::getPUBLISH(Publish* pub) int MQTTGWPacket::getPUBLISH(Publish* pub)
{ {
if (_header.bits.type != PUBLISH) if (_header.bits.type != PUBLISH)
{ {
return 0; return 0;
} }
char* ptr = (char*) _data; char* ptr = (char*) _data;
pub->header = _header; pub->header = _header;
pub->topiclen = readInt((char**) &ptr); pub->topiclen = readInt((char**) &ptr);
pub->topic = (char*) _data + 2; pub->topic = (char*) _data + 2;
ptr += pub->topiclen; ptr += pub->topiclen;
if (_header.bits.qos > 0) if (_header.bits.qos > 0)
{ {
pub->msgId = readInt(&ptr); pub->msgId = readInt(&ptr);
pub->payloadlen = _remainingLength - pub->topiclen - 4; pub->payloadlen = _remainingLength - pub->topiclen - 4;
} }
else else
{ {
pub->msgId = 0; pub->msgId = 0;
pub->payloadlen = _remainingLength - pub->topiclen - 2; pub->payloadlen = _remainingLength - pub->topiclen - 2;
} }
pub->payload = ptr; pub->payload = ptr;
return 1; return 1;
} }
int MQTTGWPacket::setCONNECT(Connect* connect, unsigned char* username, unsigned char* password) int MQTTGWPacket::setCONNECT(Connect* connect, unsigned char* username, unsigned char* password)
{ {
clearData(); clearData();
_header = connect->header; _header = connect->header;
_remainingLength = ((connect->version == 3) ? 12 : 10) + (int)strlen(connect->clientID) + 2; _remainingLength = ((connect->version == 3) ? 12 : 10) + (int) strlen(connect->clientID) + 2;
if (connect->flags.bits.will) if (connect->flags.bits.will)
{ {
_remainingLength += (int)strlen(connect->willTopic) + 2 + (int)strlen(connect->willMsg) + 2; _remainingLength += (int) strlen(connect->willTopic) + 2 + (int) strlen(connect->willMsg) + 2;
} }
if ( connect->flags.bits.username ) if (connect->flags.bits.username)
{ {
_remainingLength += (int)strlen((char*) username) + 2; _remainingLength += (int) strlen((char*) username) + 2;
} }
if (connect->flags.bits.password) if (connect->flags.bits.password)
{ {
_remainingLength += (int)strlen((char*) password) + 2; _remainingLength += (int) strlen((char*) password) + 2;
} }
_data = (unsigned char*)calloc(_remainingLength, 1); _data = (unsigned char*) calloc(_remainingLength, 1);
unsigned char* ptr = _data; unsigned char* ptr = _data;
if (connect->version == 3) if (connect->version == 3)
{ {
writeUTF(&ptr, "MQIsdp"); writeUTF(&ptr, "MQIsdp");
writeChar(&ptr, (char) 3); writeChar(&ptr, (char) 3);
} }
else if (connect->version == 4) else if (connect->version == 4)
{ {
writeUTF(&ptr, "MQTT"); writeUTF(&ptr, "MQTT");
writeChar(&ptr, (char) 4); writeChar(&ptr, (char) 4);
} }
else else
{ {
return 0; return 0;
} }
writeChar(&ptr, connect->flags.all); writeChar(&ptr, connect->flags.all);
writeInt(&ptr, connect->keepAliveTimer); writeInt(&ptr, connect->keepAliveTimer);
writeUTF(&ptr, connect->clientID); writeUTF(&ptr, connect->clientID);
if (connect->flags.bits.will) if (connect->flags.bits.will)
{ {
writeUTF(&ptr, connect->willTopic); writeUTF(&ptr, connect->willTopic);
writeUTF(&ptr, connect->willMsg); writeUTF(&ptr, connect->willMsg);
} }
if (connect->flags.bits.username) if (connect->flags.bits.username)
{ {
writeUTF(&ptr, (const char*) username); writeUTF(&ptr, (const char*) username);
} }
if (connect->flags.bits.password) if (connect->flags.bits.password)
{ {
writeUTF(&ptr, (const char*) password); writeUTF(&ptr, (const char*) password);
} }
return 1; return 1;
} }
int MQTTGWPacket::setSUBSCRIBE(const char* topic, unsigned char qos, unsigned short msgId) int MQTTGWPacket::setSUBSCRIBE(const char* topic, unsigned char qos, unsigned short msgId)
{ {
clearData(); clearData();
_header.byte = 0; _header.byte = 0;
_header.bits.type = SUBSCRIBE; _header.bits.type = SUBSCRIBE;
_header.bits.qos = 1; // Reserved _header.bits.qos = 1; // Reserved
_remainingLength = (int)strlen(topic) + 5; _remainingLength = (int) strlen(topic) + 5;
_data = (unsigned char*)calloc(_remainingLength, 1); _data = (unsigned char*) calloc(_remainingLength, 1);
if (_data) if (_data)
{ {
unsigned char* ptr = _data; unsigned char* ptr = _data;
writeInt(&ptr, msgId); writeInt(&ptr, msgId);
writeUTF(&ptr, topic); writeUTF(&ptr, topic);
writeChar(&ptr, (char) qos); writeChar(&ptr, (char) qos);
return 1; return 1;
} }
clearData(); clearData();
return 0; return 0;
} }
int MQTTGWPacket::setUNSUBSCRIBE(const char* topic, unsigned short msgid) int MQTTGWPacket::setUNSUBSCRIBE(const char* topic, unsigned short msgid)
{ {
clearData(); clearData();
_header.byte = 0; _header.byte = 0;
_header.bits.type = UNSUBSCRIBE; _header.bits.type = UNSUBSCRIBE;
_header.bits.qos = 1; _header.bits.qos = 1;
_remainingLength = (int)strlen(topic) + 4; _remainingLength = (int) strlen(topic) + 4;
_data = (unsigned char*)calloc(_remainingLength, 1); _data = (unsigned char*) calloc(_remainingLength, 1);
if (_data) if (_data)
{ {
unsigned char* ptr = _data; unsigned char* ptr = _data;
writeInt(&ptr, msgid); writeInt(&ptr, msgid);
writeUTF(&ptr, topic); writeUTF(&ptr, topic);
return 1; return 1;
} }
clearData(); clearData();
return 0; return 0;
} }
int MQTTGWPacket::setPUBLISH(Publish* pub) int MQTTGWPacket::setPUBLISH(Publish* pub)
{ {
clearData(); clearData();
_header.byte = pub->header.byte; _header.byte = pub->header.byte;
_header.bits.type = PUBLISH; _header.bits.type = PUBLISH;
_remainingLength = 4 + pub->topiclen + pub->payloadlen; _remainingLength = 4 + pub->topiclen + pub->payloadlen;
_data = (unsigned char*)calloc(_remainingLength, 1); _data = (unsigned char*) calloc(_remainingLength, 1);
if (_data) if (_data)
{ {
unsigned char* ptr = _data; unsigned char* ptr = _data;
writeInt(&ptr, pub->topiclen); writeInt(&ptr, pub->topiclen);
memcpy(ptr, pub->topic, pub->topiclen); memcpy(ptr, pub->topic, pub->topiclen);
ptr += pub->topiclen; ptr += pub->topiclen;
if ( _header.bits.qos > 0 ) if (_header.bits.qos > 0)
{ {
writeInt(&ptr, pub->msgId); writeInt(&ptr, pub->msgId);
} }
else else
{ {
_remainingLength -= 2; _remainingLength -= 2;
} }
memcpy(ptr, pub->payload, pub->payloadlen); memcpy(ptr, pub->payload, pub->payloadlen);
return 1; return 1;
} }
else else
{ {
clearData(); clearData();
return 0; return 0;
} }
} }
int MQTTGWPacket::setAck(unsigned char msgType, unsigned short msgid) int MQTTGWPacket::setAck(unsigned char msgType, unsigned short msgid)
{ {
clearData(); clearData();
_remainingLength = 2; _remainingLength = 2;
_header.bits.type = msgType; _header.bits.type = msgType;
_header.bits.qos = (msgType == PUBREL) ? 1 : 0; _header.bits.qos = (msgType == PUBREL) ? 1 : 0;
_data = (unsigned char*)calloc(_remainingLength, 1); _data = (unsigned char*) calloc(_remainingLength, 1);
if (_data) if (_data)
{ {
unsigned char* data = _data; unsigned char* data = _data;
writeInt(&data, msgid); writeInt(&data, msgid);
return 1; return 1;
} }
return 0; return 0;
} }
int MQTTGWPacket::setHeader(unsigned char msgType) int MQTTGWPacket::setHeader(unsigned char msgType)
{ {
clearData(); clearData();
if (msgType < CONNECT || msgType > DISCONNECT) if (msgType < CONNECT || msgType > DISCONNECT)
{ {
return 0; return 0;
} }
_header.bits.type = msgType; _header.bits.type = msgType;
return 0; return 0;
} }
int MQTTGWPacket::getType(void) int MQTTGWPacket::getType(void)
{ {
return _header.bits.type; return _header.bits.type;
} }
const char* MQTTGWPacket::getName(void) const char* MQTTGWPacket::getName(void)
{ {
return getType() > DISCONNECT ? "UNKNOWN" : mqtt_packet_names[getType()]; return getType() > DISCONNECT ? "UNKNOWN" : mqtt_packet_names[getType()];
} }
int MQTTGWPacket::getPacketData(unsigned char* buf) int MQTTGWPacket::getPacketData(unsigned char* buf)
{ {
unsigned char* ptr = buf; unsigned char* ptr = buf;
*ptr++ = _header.byte; *ptr++ = _header.byte;
int len = MQTTPacket_encode((char*)ptr, _remainingLength); int len = MQTTPacket_encode((char*) ptr, _remainingLength);
ptr += len; ptr += len;
memcpy(ptr, _data, _remainingLength); memcpy(ptr, _data, _remainingLength);
return 1 + len + _remainingLength; return 1 + len + _remainingLength;
} }
int MQTTGWPacket::getPacketLength(void) int MQTTGWPacket::getPacketLength(void)
{ {
char buf[4]; char buf[4];
return 1 + MQTTPacket_encode(buf, _remainingLength) + _remainingLength; return 1 + MQTTPacket_encode(buf, _remainingLength) + _remainingLength;
} }
void MQTTGWPacket::clearData(void) void MQTTGWPacket::clearData(void)
{ {
if (_data) if (_data)
{ {
free(_data); free(_data);
} }
_header.byte = 0; _header.byte = 0;
_remainingLength = 0; _remainingLength = 0;
} }
char* MQTTGWPacket::getMsgId(char* pbuf) char* MQTTGWPacket::getMsgId(char* pbuf)
{ {
int type = getType(); int type = getType();
switch ( type ) switch (type)
{ {
case PUBLISH: case PUBLISH:
Publish pub; Publish pub;
getPUBLISH(&pub); pub.msgId = 0;
if ( _header.bits.dup ) getPUBLISH(&pub);
{ if (_header.bits.dup)
sprintf(pbuf, "+%04X", pub.msgId); {
} sprintf(pbuf, "+%04X", pub.msgId);
else }
{ else
sprintf(pbuf, " %04X", pub.msgId); {
} sprintf(pbuf, " %04X", pub.msgId);
break; }
case PUBACK: break;
case PUBREC: case SUBSCRIBE:
case PUBREL: case UNSUBSCRIBE:
case PUBCOMP: case PUBACK:
case SUBSCRIBE: case PUBREC:
case UNSUBSCRIBE: case PUBREL:
case SUBACK: case PUBCOMP:
case UNSUBACK: case SUBACK:
sprintf(pbuf, " %02X%02X", _data[0], _data[1]); case UNSUBACK:
break; sprintf(pbuf, " %02X%02X", _data[0], _data[1]);
default: break;
sprintf(pbuf, " "); default:
break; sprintf(pbuf, " ");
} break;
return pbuf; }
if (strcmp(pbuf, " 0000") == 0)
{
sprintf(pbuf, " ");
}
return pbuf;
}
int MQTTGWPacket::getMsgId(void)
{
int type = getType();
int msgId = 0;
switch (type)
{
case PUBLISH:
Publish pub;
pub.msgId = 0;
getPUBLISH(&pub);
msgId = pub.msgId;
break;
case PUBACK:
case PUBREC:
case PUBREL:
case PUBCOMP:
case SUBSCRIBE:
case UNSUBSCRIBE:
case SUBACK:
case UNSUBACK:
msgId = 256 * (unsigned char) _data[0] + (unsigned char) _data[1];
break;
default:
break;
}
return msgId;
}
void MQTTGWPacket::setMsgId(int msgId)
{
int type = getType();
unsigned char* ptr = 0;
switch (type)
{
case PUBLISH:
Publish pub;
pub.topiclen = 0;
pub.msgId = 0;
getPUBLISH(&pub);
pub.msgId = msgId;
ptr = _data + pub.topiclen;
writeInt(&ptr, pub.msgId);
*ptr++ = (unsigned char) (msgId / 256);
*ptr = (unsigned char) (msgId % 256);
break;
case SUBSCRIBE:
case UNSUBSCRIBE:
case PUBACK:
case PUBREC:
case PUBREL:
case PUBCOMP:
case SUBACK:
case UNSUBACK:
ptr = _data;
*ptr++ = (unsigned char) (msgId / 256);
*ptr = (unsigned char) (msgId % 256);
break;
default:
break;
}
} }
char* MQTTGWPacket::print(char* pbuf) char* MQTTGWPacket::print(char* pbuf)
{ {
uint8_t packetData[MQTTSNGW_MAX_PACKET_SIZE]; uint8_t packetData[MQTTSNGW_MAX_PACKET_SIZE];
char* ptr = pbuf; char* ptr = pbuf;
char** pptr = &pbuf; char** pptr = &pbuf;
int len = getPacketData(packetData); int len = getPacketData(packetData);
int size = len > SIZE_OF_LOG_PACKET ? SIZE_OF_LOG_PACKET : len;
for (int i = 0; i < len; i++) for (int i = 0; i < size; i++)
{ {
sprintf(*pptr, " %02X", packetData[i]); sprintf(*pptr, " %02X", packetData[i]);
*pptr += 3; *pptr += 3;
} }
**pptr = 0; **pptr = 0;
return ptr; return ptr;
} }
MQTTGWPacket& MQTTGWPacket::operator =(MQTTGWPacket& packet)
{
clearData();
this->_header.byte = packet._header.byte;
this->_remainingLength = packet._remainingLength;
_data = (unsigned char*) calloc(_remainingLength, 1);
if (_data)
{
memcpy(this->_data, packet._data, _remainingLength);
}
else
{
clearData();
}
return *this;
}
UTF8String MQTTGWPacket::getTopic(void)
{
UTF8String str = { 0, nullptr };
if (_header.bits.type == SUBSCRIBE || _header.bits.type == UNSUBSCRIBE)
{
char* ptr = (char*) (_data + 2);
str.len = readInt(&ptr);
str.data = (char*) (_data + 4);
}
return str;
}

View File

@@ -31,186 +31,218 @@ typedef void* (*pf)(unsigned char, char*, size_t);
enum msgTypes enum msgTypes
{ {
CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, CONNECT = 1,
PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, CONNACK,
PINGREQ, PINGRESP, DISCONNECT PUBLISH,
PUBACK,
PUBREC,
PUBREL,
PUBCOMP,
SUBSCRIBE,
SUBACK,
UNSUBSCRIBE,
UNSUBACK,
PINGREQ,
PINGRESP,
DISCONNECT
}; };
/** /**
* Bitfields for the MQTT header byte. * Bitfields for the MQTT header byte.
*/ */
typedef union typedef union
{ {
/*unsigned*/ char byte; /**< the whole byte */ /*unsigned*/
char byte; /**< the whole byte */
#if defined(REVERSED) #if defined(REVERSED)
struct struct
{ {
unsigned int type : 4; /**< message type nibble */ unsigned int type : 4; /**< message type nibble */
bool dup : 1; /**< DUP flag bit */ bool dup : 1; /**< DUP flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */
bool retain : 1; /**< retained flag bit */ bool retain : 1; /**< retained flag bit */
} bits; }bits;
#else #else
struct struct
{ {
bool retain : 1; /**< retained flag bit */ bool retain :1; /**< retained flag bit */
unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ unsigned int qos :2; /**< QoS value, 0, 1 or 2 */
bool dup : 1; /**< DUP flag bit */ bool dup :1; /**< DUP flag bit */
unsigned int type : 4; /**< message type nibble */ unsigned int type :4; /**< message type nibble */
} bits; } bits;
#endif #endif
} Header; } Header;
/** /**
* Data for a connect packet. * Data for a connect packet.
*/ */
enum MQTT_connackCodes{ enum MQTT_connackCodes
MQTT_CONNECTION_ACCEPTED , {
MQTT_UNACCEPTABLE_PROTOCOL_VERSION, MQTT_CONNECTION_ACCEPTED,
MQTT_IDENTIFIER_REJECTED, MQTT_UNACCEPTABLE_PROTOCOL_VERSION,
MQTT_SERVER_UNAVAILABLE, MQTT_IDENTIFIER_REJECTED,
MQTT_BAD_USERNAME_OR_PASSWORD, MQTT_SERVER_UNAVAILABLE,
MQTT_NOT_AUTHORIZED MQTT_BAD_USERNAME_OR_PASSWORD,
MQTT_NOT_AUTHORIZED
}; };
typedef struct typedef struct
{ {
Header header; /**< MQTT header byte */ Header header; /**< MQTT header byte */
union union
{ {
unsigned char all; /**< all connect flags */ unsigned char all; /**< all connect flags */
#if defined(REVERSED) #if defined(REVERSED)
struct struct
{ {
bool username : 1; /**< 3.1 user name */ bool username : 1; /**< 3.1 user name */
bool password : 1; /**< 3.1 password */ bool password : 1; /**< 3.1 password */
bool willRetain : 1; /**< will retain setting */ bool willRetain : 1; /**< will retain setting */
unsigned int willQoS : 2; /**< will QoS value */ unsigned int willQoS : 2; /**< will QoS value */
bool will : 1; /**< will flag */ bool will : 1; /**< will flag */
bool cleanstart : 1; /**< cleansession flag */ bool cleanstart : 1; /**< cleansession flag */
int : 1; /**< unused */ int : 1; /**< unused */
} bits; }bits;
#else #else
struct struct
{ {
int : 1; /**< unused */ int :1; /**< unused */
bool cleanstart : 1; /**< cleansession flag */ bool cleanstart :1; /**< cleansession flag */
bool will : 1; /**< will flag */ bool will :1; /**< will flag */
unsigned int willQoS : 2; /**< will QoS value */ unsigned int willQoS :2; /**< will QoS value */
bool willRetain : 1; /**< will retain setting */ bool willRetain :1; /**< will retain setting */
bool password : 1; /**< 3.1 password */ bool password :1; /**< 3.1 password */
bool username : 1; /**< 3.1 user name */ bool username :1; /**< 3.1 user name */
} bits; } bits;
#endif #endif
} flags; /**< connect flags byte */ } flags; /**< connect flags byte */
char *Protocol, /**< MQTT protocol name */ char *Protocol, /**< MQTT protocol name */
*clientID, /**< string client id */ *clientID, /**< string client id */
*willTopic, /**< will topic */ *willTopic, /**< will topic */
*willMsg; /**< will payload */ *willMsg; /**< will payload */
int keepAliveTimer; /**< keepalive timeout value in seconds */ int keepAliveTimer; /**< keepalive timeout value in seconds */
unsigned char version; /**< MQTT version number */ unsigned char version; /**< MQTT version number */
} Connect; } Connect;
#define MQTTPacket_Connect_Initializer {{0}, {0}, nullptr, nullptr, nullptr, nullptr, 0, 0}
#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 }
#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \
MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} }
/** /**
* Data for a willMessage. * Data for a willMessage.
*/ */
typedef struct typedef struct
{ {
char* topic; char* topic;
char* msg; char* msg;
int retained; int retained;
int qos; int qos;
}willMessages; } willMessages;
/** /**
* Data for a connack packet. * Data for a connack packet.
*/ */
typedef struct typedef struct
{ {
Header header; /**< MQTT header byte */ Header header; /**< MQTT header byte */
union union
{ {
unsigned char all; /**< all connack flags */ unsigned char all; /**< all connack flags */
#if defined(REVERSED) #if defined(REVERSED)
struct struct
{ {
unsigned int reserved : 7; /**< message type nibble */ unsigned int reserved : 7; /**< message type nibble */
bool sessionPresent : 1; /**< was a session found on the server? */ bool sessionPresent : 1; /**< was a session found on the server? */
} bits; }bits;
#else #else
struct struct
{ {
bool sessionPresent : 1; /**< was a session found on the server? */ bool sessionPresent :1; /**< was a session found on the server? */
unsigned int reserved : 7; /**< message type nibble */ unsigned int reserved :7; /**< message type nibble */
} bits; } bits;
#endif #endif
} flags; /**< connack flags byte */ } flags; /**< connack flags byte */
char rc; /**< connack return code */ char rc; /**< connack return code */
} Connack; } Connack;
/** /**
* Data for a publish packet. * Data for a publish packet.
*/ */
typedef struct typedef struct
{ {
Header header; /**< MQTT header byte */ Header header; /**< MQTT header byte */
char* topic; /**< topic string */ char* topic; /**< topic string */
int topiclen; int topiclen;
int msgId; /**< MQTT message id */ int msgId; /**< MQTT message id */
char* payload; /**< binary payload, length delimited */ char* payload; /**< binary payload, length delimited */
int payloadlen; /**< payload length */ int payloadlen; /**< payload length */
} Publish; } Publish;
#define MQTTPacket_Publish_Initializer {{0}, nullptr, 0, 0, nullptr, 0}
/** /**
* Data for one of the ack packets. * Data for one of the ack packets.
*/ */
typedef struct typedef struct
{ {
Header header; /**< MQTT header byte */ Header header; /**< MQTT header byte */
int msgId; /**< MQTT message id */ int msgId; /**< MQTT message id */
} Ack; } Ack;
/**
* UTF8String.
*/
typedef struct
{
unsigned char len;
char* data;
} UTF8String;
/** /**
* Class MQTT Packet * Class MQTT Packet
*/ */
class MQTTGWPacket class MQTTGWPacket
{ {
public: public:
MQTTGWPacket(); MQTTGWPacket();
~MQTTGWPacket(); ~MQTTGWPacket();
int recv(Network* network); int recv(Network* network);
int send(Network* network); int send(Network* network);
int getType(void); int getType(void);
int getPacketData(unsigned char* buf); int getPacketData(unsigned char* buf);
int getPacketLength(void); int getPacketLength(void);
const char* getName(void); const char* getName(void);
int getAck(Ack* ack); int getAck(Ack* ack);
int getCONNACK(Connack* resp); int getCONNACK(Connack* resp);
int getSUBACK(unsigned short* msgId, unsigned char* rc); int getSUBACK(unsigned short* msgId, unsigned char* rc);
int getPUBLISH(Publish* pub); int getPUBLISH(Publish* pub);
int setCONNECT(Connect* conect, unsigned char* username, unsigned char* password); int setCONNECT(Connect* conect, unsigned char* username,
int setPUBLISH(Publish* pub); unsigned char* password);
int setAck(unsigned char msgType, unsigned short msgid); int setPUBLISH(Publish* pub);
int setHeader(unsigned char msgType); int setAck(unsigned char msgType, unsigned short msgid);
int setSUBSCRIBE(const char* topic, unsigned char qos, unsigned short msgId); int setHeader(unsigned char msgType);
int setUNSUBSCRIBE(const char* topics, unsigned short msgid); int setSUBSCRIBE(const char* topic, unsigned char qos,
char* getMsgId(char* buf); unsigned short msgId);
char* print(char* buf); int setUNSUBSCRIBE(const char* topics, unsigned short msgid);
UTF8String getTopic(void);
char* getMsgId(char* buf);
int getMsgId(void);
void setMsgId(int msgId);
char* print(char* buf);
MQTTGWPacket& operator =(MQTTGWPacket& packet);
private: private:
void clearData(void); void clearData(void);
Header _header; Header _header;
int _remainingLength; int _remainingLength;
unsigned char* _data; unsigned char* _data;
}; };
} }

View File

@@ -12,6 +12,7 @@
* *
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
* Tieto Poland Sp. z o.o. - Gateway improvements
**************************************************************************************/ **************************************************************************************/
#include "MQTTGWPublishHandler.h" #include "MQTTGWPublishHandler.h"
@@ -26,7 +27,7 @@ char* currentDateTime(void);
MQTTGWPublishHandler::MQTTGWPublishHandler(Gateway* gateway) MQTTGWPublishHandler::MQTTGWPublishHandler(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
} }
MQTTGWPublishHandler::~MQTTGWPublishHandler() MQTTGWPublishHandler::~MQTTGWPublishHandler()
@@ -36,187 +37,284 @@ MQTTGWPublishHandler::~MQTTGWPublishHandler()
void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet) void MQTTGWPublishHandler::handlePublish(Client* client, MQTTGWPacket* packet)
{ {
if ( !client->isActive() && !client->isSleep() ) if (!client->isActive() && !client->isSleep() && !client->isAwake())
{ {
WRITELOG(" The client is neither active nor sleep %s\n", client->getStatus()); WRITELOG("%s The client is neither active nor sleep %s%s\n",
return; ERRMSG_HEADER, client->getStatus(), ERRMSG_FOOTER);
} return;
}
Publish pub; /* client is sleeping. save PUBLISH */
packet->getPUBLISH(&pub); if (client->isSleep())
{
Publish pub;
packet->getPUBLISH(&pub);
MQTTSNPacket* snPacket = new MQTTSNPacket(); WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(),
RIGHTARROW, client->getClientId(), "is sleeping. a message was saved.");
/* create MQTTSN_topicid */ if (pub.header.bits.qos == 1)
MQTTSN_topicid topicId; {
uint16_t id = 0; replyACK(client, &pub, PUBACK);
}
else if (pub.header.bits.qos == 2)
{
replyACK(client, &pub, PUBREC);
}
if (pub.topiclen == 2) MQTTGWPacket* msg = new MQTTGWPacket();
{ *msg = *packet;
topicId.type = MQTTSN_TOPIC_TYPE_SHORT; if (msg->getType() == 0)
*(topicId.data.short_name) = *pub.topic; {
*(topicId.data.short_name + 1) = *(pub.topic + 1); WRITELOG("%s MQTTGWPublishHandler::handlePublish can't allocate memories for Packet.%s\n",
} ERRMSG_HEADER, ERRMSG_FOOTER);
else delete msg;
{ return;
topicId.type = MQTTSN_TOPIC_TYPE_NORMAL; }
topicId.data.long_.len = pub.topiclen; client->setClientSleepPacket(msg);
topicId.data.long_.name = pub.topic; return;
id = client->getTopics()->getTopicId(&topicId); }
if ( id > 0 ) Publish pub;
{ packet->getPUBLISH(&pub);
topicId.data.id = id;
}
else
{
/* This message might be subscribed with wild card. */
Topic* topic = client->getTopics()->match(&topicId);
if (topic == 0)
{
WRITELOG(" Invalid Topic. PUBLISH message is canceled.\n");
if (pub.header.bits.qos == 1)
{
replyACK(client, &pub, PUBACK);
}
else if ( pub.header.bits.qos == 2 )
{
replyACK(client, &pub, PUBREC);
}
return;
}
/* add the Topic and get a TopicId */ MQTTSNPacket* snPacket = new MQTTSNPacket();
topic = client->getTopics()->add(&topicId);
id = topic->getTopicId();
if (id > 0) /* create MQTTSN_topicid */
{ MQTTSN_topicid topicId;
/* create REGACK */ uint16_t id = 0;
MQTTSNPacket* regPacket = new MQTTSNPacket();
MQTTSNString topicName; if (pub.topiclen <= 2)
topicName.lenstring.len = topicId.data.long_.len; {
topicName.lenstring.data = topicId.data.long_.name; topicId.type = MQTTSN_TOPIC_TYPE_SHORT;
*(topicId.data.short_name) = *pub.topic;
*(topicId.data.short_name + 1) = *(pub.topic + 1);
}
else
{
topicId.data.long_.len = pub.topiclen;
topicId.data.long_.name = pub.topic;
Topic* tp = client->getTopics()->getTopicByName(&topicId);
uint16_t regackMsgId = client->getNextSnMsgId(); if (tp)
regPacket->setREGISTER(id, regackMsgId, &topicName); {
topicId.type = tp->getType();
topicId.data.long_.len = pub.topiclen;
topicId.data.long_.name = pub.topic;
topicId.data.id = tp->getTopicId();
}
else
{
/* This message might be subscribed with wild card or not cleanSession*/
topicId.type = MQTTSN_TOPIC_TYPE_NORMAL;
Topic* topic = client->getTopics()->match(&topicId);
if (client->isSleep()) if (topic == nullptr && client->isCleanSession())
{ {
client->setClientSleepPacket(regPacket); WRITELOG("%sMQTTGWPublishHandler Invalid Topic. PUBLISH message is discarded.%s\n",
WRITELOG(FORMAT_BL_NL, currentDateTime(), regPacket->getName(), ERRMSG_HEADER, ERRMSG_FOOTER);
RIGHTARROW, client->getClientId(), "is sleeping. REGISTER was saved."); if (pub.header.bits.qos == 1)
} {
else if (client->isActive()) replyACK(client, &pub, PUBACK);
{ }
/* send REGISTER */ else if (pub.header.bits.qos == 2)
Event* evrg = new Event(); {
evrg->setClientSendEvent(client, regPacket); replyACK(client, &pub, PUBREC);
_gateway->getClientSendQue()->post(evrg); }
}
/* send PUBLISH */ delete snPacket;
topicId.data.id = id; return;
snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos, }
(uint8_t) pub.header.bits.retain, (uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload,
pub.payloadlen);
client->getWaitREGACKPacketList()->setPacket(snPacket, regackMsgId);
}
else
{
WRITELOG("\x1b[0m\x1b[31mMQTTGWPublishHandler Can't create a Topic.\n");
delete snPacket;
return;
}
}
}
/* TopicId was acquired. */ if (topic == nullptr)
if (client->isSleep()) {
{ topicId.type = MQTTSN_TOPIC_TYPE_NORMAL;
/* client is sleeping. save PUBLISH */ topicId.data.long_.len = pub.topiclen;
client->setClientSleepPacket(snPacket); topicId.data.long_.name = pub.topic;
WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), topicId.data.id = 0;
RIGHTARROW, client->getClientId(), "is sleeping. a message was saved."); }
int type = 0;
if (pub.header.bits.qos == 1) /* add the Topic and get a TopicId */
{ topic = client->getTopics()->add(&topicId);
type = PUBACK; if (topic == nullptr)
} {
else if ( pub.header.bits.qos == 2) WRITELOG(
{ "%sMQTTGWPublishHandler Can't Add a Topic. MAX_TOPIC_PAR_CLIENT is exceeded. PUBLISH message is discarded.%s\n",
WRITELOG(" While Client is sleeping, QoS2 is not supported.\n"); ERRMSG_HEADER, ERRMSG_FOOTER);
type = PUBREC; delete snPacket;
} return;
replyACK(client, &pub, type); }
pub.header.bits.qos = 0; id = topic->getTopicId();
replyACK(client, &pub, PUBACK); if (id > 0)
pub.msgId = 0; {
snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos, /* create REGISTER */
(uint8_t) pub.header.bits.retain, (uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload, MQTTSNPacket* regPacket = new MQTTSNPacket();
pub.payloadlen);
client->setClientSleepPacket(snPacket); MQTTSNString topicName = MQTTSNString_initializer;
} topicName.lenstring.len = topicId.data.long_.len;
else if (client->isActive()) topicName.lenstring.data = topicId.data.long_.name;
{
snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos, (uint8_t) pub.header.bits.retain, uint16_t regackMsgId = client->getNextSnMsgId();
(uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload, pub.payloadlen); regPacket->setREGISTER(id, regackMsgId, &topicName);
Event* ev1 = new Event();
ev1->setClientSendEvent(client, snPacket); /* send REGISTER */
_gateway->getClientSendQue()->post(ev1); Event* evrg = new Event();
} evrg->setClientSendEvent(client, regPacket);
_gateway->getClientSendQue()->post(evrg);
/* send PUBLISH */
topicId.data.id = id;
snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos, (uint8_t) pub.header.bits.retain,
(uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload, pub.payloadlen);
client->getWaitREGACKPacketList()->setPacket(snPacket, regackMsgId);
return;
}
else
{
WRITELOG("%sMQTTGWPublishHandler Can't create a Topic. PUBLISH message is discarded.%s\n",
ERRMSG_HEADER, ERRMSG_FOOTER);
delete snPacket;
return;
}
}
}
snPacket->setPUBLISH((uint8_t) pub.header.bits.dup, (int) pub.header.bits.qos, (uint8_t) pub.header.bits.retain,
(uint16_t) pub.msgId, topicId, (uint8_t*) pub.payload, pub.payloadlen);
Event* ev1 = new Event();
ev1->setClientSendEvent(client, snPacket);
_gateway->getClientSendQue()->post(ev1);
} }
void MQTTGWPublishHandler::replyACK(Client* client, Publish* pub, int type) void MQTTGWPublishHandler::replyACK(Client* client, Publish* pub, int type)
{ {
MQTTGWPacket* pubAck = new MQTTGWPacket(); MQTTGWPacket* pubAck = new MQTTGWPacket();
pubAck->setAck(type, (uint16_t)pub->msgId); pubAck->setAck(type, (uint16_t) pub->msgId);
Event* ev1 = new Event(); Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, pubAck); ev1->setBrokerSendEvent(client, pubAck);
_gateway->getBrokerSendQue()->post(ev1); _gateway->getBrokerSendQue()->post(ev1);
} }
void MQTTGWPublishHandler::handlePuback(Client* client, MQTTGWPacket* packet) void MQTTGWPublishHandler::handlePuback(Client* client, MQTTGWPacket* packet)
{ {
Ack ack; Ack ack;
packet->getAck(&ack); packet->getAck(&ack);
uint16_t topicId = client->getWaitedPubTopicId((uint16_t)ack.msgId); TopicIdMapElement* topicId = client->getWaitedPubTopicId((uint16_t) ack.msgId);
if (topicId) if (topicId)
{ {
MQTTSNPacket* mqttsnPacket = new MQTTSNPacket(); MQTTSNPacket* mqttsnPacket = new MQTTSNPacket();
mqttsnPacket->setPUBACK(topicId, (uint16_t)ack.msgId, 0); mqttsnPacket->setPUBACK(topicId->getTopicId(), (uint16_t) ack.msgId, 0);
client->eraseWaitedPubTopicId((uint16_t)ack.msgId); client->eraseWaitedPubTopicId((uint16_t) ack.msgId);
Event* ev1 = new Event(); Event* ev1 = new Event();
ev1->setClientSendEvent(client, mqttsnPacket); ev1->setClientSendEvent(client, mqttsnPacket);
_gateway->getClientSendQue()->post(ev1); _gateway->getClientSendQue()->post(ev1);
return; return;
} }
WRITELOG(" PUBACK from the Broker is invalid. PacketID : %04X ClientID : %s \n", (uint16_t)ack.msgId, client->getClientId()); WRITELOG(" PUBACK from the Broker is invalid. PacketID : %04X ClientID : %s \n", (uint16_t) ack.msgId,
client->getClientId());
} }
void MQTTGWPublishHandler::handleAck(Client* client, MQTTGWPacket* packet, int type) void MQTTGWPublishHandler::handleAck(Client* client, MQTTGWPacket* packet, int type)
{ {
Ack ack; Ack ack;
packet->getAck(&ack); packet->getAck(&ack);
MQTTSNPacket* mqttsnPacket = new MQTTSNPacket();
if (type == PUBREC)
{
mqttsnPacket->setPUBREC((uint16_t) ack.msgId);
}
else if (type == PUBREL)
{
mqttsnPacket->setPUBREL((uint16_t) ack.msgId);
}
else if (type == PUBCOMP)
{
mqttsnPacket->setPUBCOMP((uint16_t) ack.msgId);
}
Event* ev1 = new Event(); if (client->isActive() || client->isAwake())
ev1->setClientSendEvent(client, mqttsnPacket); {
_gateway->getClientSendQue()->post(ev1); MQTTSNPacket* mqttsnPacket = new MQTTSNPacket();
if (type == PUBREC)
{
mqttsnPacket->setPUBREC((uint16_t) ack.msgId);
}
else if (type == PUBREL)
{
mqttsnPacket->setPUBREL((uint16_t) ack.msgId);
}
else if (type == PUBCOMP)
{
mqttsnPacket->setPUBCOMP((uint16_t) ack.msgId);
}
Event* ev1 = new Event();
ev1->setClientSendEvent(client, mqttsnPacket);
_gateway->getClientSendQue()->post(ev1);
}
else if (client->isSleep())
{
if (type == PUBREL)
{
MQTTGWPacket* pubComp = new MQTTGWPacket();
pubComp->setAck(PUBCOMP, (uint16_t) ack.msgId);
Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, pubComp);
_gateway->getBrokerSendQue()->post(ev1);
}
}
}
void MQTTGWPublishHandler::handleAggregatePuback(Client* client, MQTTGWPacket* packet)
{
uint16_t msgId = packet->getMsgId();
uint16_t clientMsgId = 0;
Client* newClient = _gateway->getAdapterManager()->convertClient(msgId, &clientMsgId);
if (newClient != nullptr)
{
packet->setMsgId((int) clientMsgId);
handlePuback(newClient, packet);
}
}
void MQTTGWPublishHandler::handleAggregateAck(Client* client, MQTTGWPacket* packet, int type)
{
uint16_t msgId = packet->getMsgId();
uint16_t clientMsgId = 0;
Client* newClient = _gateway->getAdapterManager()->convertClient(msgId, &clientMsgId);
if (newClient != nullptr)
{
packet->setMsgId((int) clientMsgId);
handleAck(newClient, packet, type);
}
}
void MQTTGWPublishHandler::handleAggregatePubrel(Client* client, MQTTGWPacket* packet)
{
Publish pub;
packet->getPUBLISH(&pub);
replyACK(client, &pub, PUBCOMP);
}
void MQTTGWPublishHandler::handleAggregatePublish(Client* client, MQTTGWPacket* packet)
{
Publish pub;
packet->getPUBLISH(&pub);
string* topicName = new string(pub.topic, pub.topiclen); // topic deletes topicName when the topic is deleted
Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL);
// ToDo: need to refactor
ClientTopicElement* elm = _gateway->getAdapterManager()->getAggregater()->getClientElement(&topic);
while (elm != nullptr)
{
Client* devClient = elm->getClient();
MQTTGWPacket* msg = new MQTTGWPacket();
*msg = *packet;
if (msg->getType() == 0)
{
WRITELOG("%s MQTTGWPublishHandler::handleAggregatePublish can't allocate memories for Packet.%s\n",
ERRMSG_HEADER, ERRMSG_FOOTER);
delete msg;
break;
}
Event* ev = new Event();
ev->setBrokerRecvEvent(devClient, msg);
_gateway->getPacketEventQue()->post(ev);
elm = elm->getNextClientElement();
}
} }

View File

@@ -26,20 +26,23 @@ namespace MQTTSNGW
class MQTTGWPublishHandler class MQTTGWPublishHandler
{ {
public: public:
MQTTGWPublishHandler(Gateway* gateway); MQTTGWPublishHandler(Gateway* gateway);
~MQTTGWPublishHandler(); ~MQTTGWPublishHandler();
void handlePublish(Client* client, MQTTGWPacket* packet); void handlePublish(Client* client, MQTTGWPacket* packet);
void handlePuback(Client* client, MQTTGWPacket* packet); void handlePuback(Client* client, MQTTGWPacket* packet);
void handleAck(Client* client, MQTTGWPacket* packet, int type); void handleAck(Client* client, MQTTGWPacket* packet, int type);
void handleAggregatePublish(Client* client, MQTTGWPacket* packet);
void handleAggregatePuback(Client* client, MQTTGWPacket* packet);
void handleAggregateAck(Client* client, MQTTGWPacket* packet, int type);
void handleAggregatePubrel(Client* client, MQTTGWPacket* packet);
private: private:
void replyACK(Client* client, Publish* pub, int type); void replyACK(Client* client, Publish* pub, int type);
Gateway* _gateway; Gateway* _gateway;
}; };
} }
#endif /* MQTTGWPUBLISHHANDLER_H_ */ #endif /* MQTTGWPUBLISHHANDLER_H_ */

View File

@@ -22,7 +22,7 @@ using namespace MQTTSNGW;
MQTTGWSubscribeHandler::MQTTGWSubscribeHandler(Gateway* gateway) MQTTGWSubscribeHandler::MQTTGWSubscribeHandler(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
} }
MQTTGWSubscribeHandler::~MQTTGWSubscribeHandler() MQTTGWSubscribeHandler::~MQTTGWSubscribeHandler()
@@ -32,43 +32,67 @@ MQTTGWSubscribeHandler::~MQTTGWSubscribeHandler()
void MQTTGWSubscribeHandler::handleSuback(Client* client, MQTTGWPacket* packet) void MQTTGWSubscribeHandler::handleSuback(Client* client, MQTTGWPacket* packet)
{ {
uint16_t msgId; uint16_t msgId;
uint8_t rc; uint8_t rc;
uint8_t returnCode; uint8_t returnCode;
int qos = 0; int qos = 0;
packet->getSUBACK(&msgId, &rc); packet->getSUBACK(&msgId, &rc);
uint16_t topicId = client->getWaitedSubTopicId(msgId); TopicIdMapElement* topicId = client->getWaitedSubTopicId(msgId);
if (topicId) if (topicId)
{ {
MQTTSNPacket* snPacket = new MQTTSNPacket(); MQTTSNPacket* snPacket = new MQTTSNPacket();
client->eraseWaitedSubTopicId(msgId);
if (rc == 0x80) if (rc == 0x80)
{ {
returnCode = MQTTSN_RC_REJECTED_INVALID_TOPIC_ID; returnCode = MQTTSN_RC_REJECTED_INVALID_TOPIC_ID;
} }
else else
{ {
returnCode = MQTTSN_RC_ACCEPTED; returnCode = MQTTSN_RC_ACCEPTED;
qos = rc; qos = rc;
} }
snPacket->setSUBACK(qos, topicId, msgId, returnCode); snPacket->setSUBACK(qos, topicId->getTopicId(), msgId, returnCode);
Event* evt = new Event(); Event* evt = new Event();
evt->setClientSendEvent(client, snPacket); evt->setClientSendEvent(client, snPacket);
_gateway->getClientSendQue()->post(evt); _gateway->getClientSendQue()->post(evt);
} client->eraseWaitedSubTopicId(msgId);
}
} }
void MQTTGWSubscribeHandler::handleUnsuback(Client* client, MQTTGWPacket* packet) void MQTTGWSubscribeHandler::handleUnsuback(Client* client, MQTTGWPacket* packet)
{ {
Ack ack; Ack ack;
packet->getAck(&ack); packet->getAck(&ack);
MQTTSNPacket* snPacket = new MQTTSNPacket(); MQTTSNPacket* snPacket = new MQTTSNPacket();
snPacket->setUNSUBACK(ack.msgId); snPacket->setUNSUBACK(ack.msgId);
Event* evt = new Event(); Event* evt = new Event();
evt->setClientSendEvent(client, snPacket); evt->setClientSendEvent(client, snPacket);
_gateway->getClientSendQue()->post(evt); _gateway->getClientSendQue()->post(evt);
}
void MQTTGWSubscribeHandler::handleAggregateSuback(Client* client, MQTTGWPacket* packet)
{
uint16_t msgId = packet->getMsgId();
uint16_t clientMsgId = 0;
Client* newClient = _gateway->getAdapterManager()->getAggregater()->convertClient(msgId, &clientMsgId);
if (newClient != nullptr)
{
packet->setMsgId((int) clientMsgId);
handleSuback(newClient, packet);
}
}
void MQTTGWSubscribeHandler::handleAggregateUnsuback(Client* client, MQTTGWPacket* packet)
{
uint16_t msgId = packet->getMsgId();
uint16_t clientMsgId = 0;
Client* newClient = _gateway->getAdapterManager()->getAggregater()->convertClient(msgId, &clientMsgId);
if (newClient != nullptr)
{
packet->setMsgId((int) clientMsgId);
handleUnsuback(newClient, packet);
}
} }

View File

@@ -27,13 +27,15 @@ namespace MQTTSNGW
class MQTTGWSubscribeHandler class MQTTGWSubscribeHandler
{ {
public: public:
MQTTGWSubscribeHandler(Gateway* gateway); MQTTGWSubscribeHandler(Gateway* gateway);
~MQTTGWSubscribeHandler(); ~MQTTGWSubscribeHandler();
void handleSuback(Client* clnode, MQTTGWPacket* packet); void handleSuback(Client* clnode, MQTTGWPacket* packet);
void handleUnsuback(Client* clnode, MQTTGWPacket* packet); void handleUnsuback(Client* clnode, MQTTGWPacket* packet);
void handleAggregateSuback(Client* client, MQTTGWPacket* packet);
void handleAggregateUnsuback(Client* client, MQTTGWPacket* packet);
private: private:
Gateway* _gateway; Gateway* _gateway;
}; };
} }

View File

@@ -0,0 +1,204 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNAggregateConnectionHandler.h"
#include "MQTTSNGateway.h"
#include "MQTTSNGWPacket.h"
#include "MQTTGWPacket.h"
#include <string.h>
using namespace std;
using namespace MQTTSNGW;
/*=====================================
Class MQTTSNAggregateConnectionHandler
=====================================*/
MQTTSNAggregateConnectionHandler::MQTTSNAggregateConnectionHandler(Gateway* gateway)
{
_gateway = gateway;
}
MQTTSNAggregateConnectionHandler::~MQTTSNAggregateConnectionHandler()
{
}
/*
* CONNECT
*/
void MQTTSNAggregateConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet)
{
MQTTSNPacket_connectData data;
if (packet->getCONNECT(&data) == 0)
{
return;
}
/* return CONNACK when the client is sleeping */
if (client->isSleep() || client->isAwake())
{
MQTTSNPacket* packet = new MQTTSNPacket();
packet->setCONNACK(MQTTSN_RC_ACCEPTED);
Event* ev = new Event();
ev->setClientSendEvent(client, packet);
_gateway->getClientSendQue()->post(ev);
sendStoredPublish(client);
return;
}
//* clear ConnectData of Client */
Connect* connectData = client->getConnectData();
memset(connectData, 0, sizeof(Connect));
client->disconnected();
Topics* topics = client->getTopics();
/* CONNECT was not sent yet. prepare Connect data */
client->setSessionStatus(false);
if (data.cleansession)
{
/* reset the table of msgNo and TopicId pare */
client->clearWaitedPubTopicId();
client->clearWaitedSubTopicId();
/* renew the TopicList */
if (topics)
{
Topic* tp = topics->getFirstTopic();
while (tp != nullptr)
{
if (tp->getType() == MQTTSN_TOPIC_TYPE_NORMAL)
{
_gateway->getAdapterManager()->getAggregater()->removeAggregateTopic(tp, client);
}
tp = topics->getNextTopic(tp);
}
topics->eraseNormal();
}
client->setSessionStatus(true);
}
if (data.willFlag)
{
/* create & send WILLTOPICREQ message to the client */
MQTTSNPacket* reqTopic = new MQTTSNPacket();
reqTopic->setWILLTOPICREQ();
Event* evwr = new Event();
evwr->setClientSendEvent(client, reqTopic);
/* Send WILLTOPICREQ to the client */
_gateway->getClientSendQue()->post(evwr);
}
else
{
/* create CONNACK & send it to the client */
MQTTSNPacket* packet = new MQTTSNPacket();
packet->setCONNACK(MQTTSN_RC_ACCEPTED);
Event* ev = new Event();
ev->setClientSendEvent(client, packet);
_gateway->getClientSendQue()->post(ev);
client->connackSended(MQTTSN_RC_ACCEPTED);
sendStoredPublish(client);
return;
}
}
/*
* WILLMSG
*/
void MQTTSNAggregateConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet)
{
if (!client->isWaitWillMsg())
{
DEBUGLOG(" MQTTSNConnectionHandler::handleWillmsg WaitWillMsgFlg is off.\n");
return;
}
MQTTSNString willmsg = MQTTSNString_initializer;
//Connect* connectData = client->getConnectData();
if (client->isConnectSendable())
{
/* save WillMsg in the client */
if (packet->getWILLMSG(&willmsg) == 0)
{
return;
}
client->setWillMsg(willmsg);
/* Send CONNACK to the client */
MQTTSNPacket* packet = new MQTTSNPacket();
packet->setCONNACK(MQTTSN_RC_ACCEPTED);
Event* ev = new Event();
ev->setClientSendEvent(client, packet);
_gateway->getClientSendQue()->post(ev);
sendStoredPublish(client);
return;
}
}
/*
* DISCONNECT
*/
void MQTTSNAggregateConnectionHandler::handleDisconnect(Client* client, MQTTSNPacket* packet)
{
MQTTSNPacket* snMsg = new MQTTSNPacket();
snMsg->setDISCONNECT(0);
Event* evt = new Event();
evt->setClientSendEvent(client, snMsg);
_gateway->getClientSendQue()->post(evt);
}
/*
* PINGREQ
*/
void MQTTSNAggregateConnectionHandler::handlePingreq(Client* client, MQTTSNPacket* packet)
{
if ((client->isSleep() || client->isAwake()) && client->getClientSleepPacket())
{
sendStoredPublish(client);
client->holdPingRequest();
}
/* create and send PINGRESP to the PacketHandler */
client->resetPingRequest();
MQTTGWPacket* pingresp = new MQTTGWPacket();
pingresp->setHeader(PINGRESP);
Event* evt = new Event();
evt->setBrokerRecvEvent(client, pingresp);
_gateway->getPacketEventQue()->post(evt);
}
void MQTTSNAggregateConnectionHandler::sendStoredPublish(Client* client)
{
MQTTGWPacket* msg = nullptr;
while ((msg = client->getClientSleepPacket()) != nullptr)
{
client->deleteFirstClientSleepPacket(); // pop the que to delete element.
Event* ev = new Event();
ev->setBrokerRecvEvent(client, msg);
_gateway->getPacketEventQue()->post(ev);
}
}

View File

@@ -0,0 +1,47 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNAGGREGATECONNECTIONHANDLER_H_
#define MQTTSNGATEWAY_SRC_MQTTSNAGGREGATECONNECTIONHANDLER_H_
#include "MQTTSNGWDefines.h"
namespace MQTTSNGW
{
class Gateway;
class Client;
class MQTTSNPacket;
class MQTTSNAggregateConnectionHandler
{
public:
MQTTSNAggregateConnectionHandler(Gateway* gateway);
~MQTTSNAggregateConnectionHandler(void);
void handleConnect(Client* client, MQTTSNPacket* packet);
void handleWillmsg(Client* client, MQTTSNPacket* packet);
void handleDisconnect(Client* client, MQTTSNPacket* packet);
void handlePingreq(Client* client, MQTTSNPacket* packet);
private:
void sendStoredPublish(Client* client);
Gateway* _gateway;
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNAGGREGATECONNECTIONHANDLER_H_ */

View File

@@ -0,0 +1,323 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "Timer.h"
#include "MQTTSNGWDefines.h"
#include "MQTTSNGateway.h"
#include "MQTTSNGWAdapter.h"
#include "SensorNetwork.h"
#include "MQTTSNGWProcess.h"
#include "MQTTSNGWClient.h"
#include <string.h>
using namespace MQTTSNGW;
/*=====================================
Class Adapter
=====================================*/
Adapter::Adapter(Gateway* gw)
{
_gateway = gw;
_proxy = new Proxy(gw);
_proxySecure = new Proxy(gw);
}
Adapter::~Adapter(void)
{
if (_proxy)
{
delete _proxy;
}
if (_proxySecure)
{
delete _proxySecure;
}
}
void Adapter::setup(const char* adpterName, AdapterType adapterType)
{
_isSecure = false;
if (_gateway->hasSecureConnection())
{
_isSecure = true;
}
MQTTSNString id = MQTTSNString_initializer;
MQTTSNString idSecure = MQTTSNString_initializer;
string name = string(adpterName);
id.cstring = const_cast<char*>(name.c_str());
string nameSecure = string(adpterName) + "-S";
idSecure.cstring = const_cast<char*>(nameSecure.c_str());
Client* client = _gateway->getClientList()->createClient(0, &id, true, false, TRANSPEARENT_TYPE);
setClient(client, false);
client->setAdapterType(adapterType);
client = _gateway->getClientList()->createClient(0, &idSecure, true, true,
TRANSPEARENT_TYPE);
setClient(client, true);
client->setAdapterType(adapterType);
}
Client* Adapter::getClient(SensorNetAddress* addr)
{
Client* client = _gateway->getClientList()->getClient(addr);
if (!client)
{
return nullptr;
}
else if (client->isQoSm1())
{
return client;
}
else
{
return nullptr;
}
}
const char* Adapter::getClientId(SensorNetAddress* addr)
{
Client* client = getClient(addr);
if (!client)
{
return nullptr;
}
else if (client->isQoSm1())
{
return client->getClientId();
}
else
{
return nullptr;
}
}
bool Adapter::isSecure(SensorNetAddress* addr)
{
Client* client = getClient(addr);
if (!client)
{
return false;
}
else if (client->isSecureNetwork())
{
return true;
}
else
{
return false;
}
}
bool Adapter::isSecure(void)
{
return _isSecure;
}
void Adapter::setClient(Client* client, bool secure)
{
if (secure)
{
_clientSecure = client;
}
else
{
_client = client;
}
}
Client* Adapter::getClient(void)
{
return _client;
}
Client* Adapter::getSecureClient(void)
{
return _clientSecure;
}
void Adapter::checkConnection(void)
{
_proxy->checkConnection(_client);
if (_isSecure)
{
_proxySecure->checkConnection(_clientSecure);
}
}
void Adapter::send(MQTTSNPacket* packet, Client* client)
{
Proxy* proxy = _proxy;
if (client->isSecureNetwork() && !_isSecure)
{
if (_isSecure)
{
proxy = _proxySecure;
}
else
{
WRITELOG("%s %s No Secure connections %s 's packet is discarded.%s\n",
ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
return;
}
}
proxy->recv(packet, client);
}
void Adapter::resetPingTimer(bool secure)
{
if (secure)
{
_proxySecure->resetPingTimer();
}
else
{
_proxy->resetPingTimer();
}
}
bool Adapter::isActive(void)
{
return _isActive;
}
void Adapter::savePacket(Client* client, MQTTSNPacket* packet)
{
if (client->isSecureNetwork())
{
_proxySecure->savePacket(client, packet);
}
else
{
_proxy->savePacket(client, packet);
}
}
Client* Adapter::getAdapterClient(Client* client)
{
if (client->isSecureNetwork())
{
return _clientSecure;
}
else
{
return _client;
}
}
/*=====================================
Class Proxy
=====================================*/
Proxy::Proxy(Gateway* gw)
{
_gateway = gw;
_suspendedPacketEventQue = new EventQue();
}
Proxy::~Proxy(void)
{
if (_suspendedPacketEventQue)
{
delete _suspendedPacketEventQue;
}
}
void Proxy::checkConnection(Client* client)
{
if (client->isDisconnect() || (client->isConnecting() && _responseTimer.isTimeup()))
{
client->connectSended();
_responseTimer.start(PROXY_RESPONSE_DURATION * 1000UL);
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
options.clientID.cstring = client->getClientId();
options.duration = PROXY_KEEPALIVE_DURATION;
MQTTSNPacket* packet = new MQTTSNPacket();
packet->setCONNECT(&options);
Event* ev = new Event();
ev->setClientRecvEvent(client, packet);
_gateway->getPacketEventQue()->post(ev);
}
else if ((client->isActive() && _keepAliveTimer.isTimeup()) || (_isWaitingResp && _responseTimer.isTimeup()))
{
MQTTSNPacket* packet = new MQTTSNPacket();
MQTTSNString clientId = MQTTSNString_initializer;
packet->setPINGREQ(&clientId);
Event* ev = new Event();
ev->setClientRecvEvent(client, packet);
_gateway->getPacketEventQue()->post(ev);
_responseTimer.start(PROXY_RESPONSE_DURATION * 1000UL);
_isWaitingResp = true;
if (++_retryCnt > PROXY_MAX_RETRY_CNT)
{
client->disconnected();
}
resetPingTimer();
}
}
void Proxy::resetPingTimer(void)
{
_keepAliveTimer.start(PROXY_KEEPALIVE_DURATION * 1000UL);
}
void Proxy::recv(MQTTSNPacket* packet, Client* client)
{
if (packet->getType() == MQTTSN_CONNACK)
{
if (packet->isAccepted())
{
_responseTimer.stop();
_retryCnt = 0;
resetPingTimer();
sendSuspendedPacket();
}
}
else if (packet->getType() == MQTTSN_PINGRESP)
{
_isWaitingResp = false;
_responseTimer.stop();
_retryCnt = 0;
resetPingTimer();
}
else if (packet->getType() == MQTTSN_DISCONNECT)
{
// blank
}
}
void Proxy::savePacket(Client* client, MQTTSNPacket* packet)
{
MQTTSNPacket* pk = new MQTTSNPacket(*packet);
Event* ev = new Event();
ev->setClientRecvEvent(client, pk);
_suspendedPacketEventQue->post(ev);
}
void Proxy::sendSuspendedPacket(void)
{
while (_suspendedPacketEventQue->size())
{
Event* ev = _suspendedPacketEventQue->wait();
_gateway->getPacketEventQue()->post(ev);
}
}

View File

@@ -0,0 +1,101 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWADAPTER_H_
#define MQTTSNGATEWAY_SRC_MQTTSNGWADAPTER_H_
#include <stdint.h>
#include "Timer.h"
namespace MQTTSNGW
{
class Gateway;
class Client;
class Proxy;
class SensorNetAddress;
class MQTTSNPacket;
class MQTTSNGWPacket;
class EventQue;
class Timer;
/* When you add a new type, Client::setAdapterType() and Client::isAdapter() functions must be modified. */
typedef enum
{
Atype_QoSm1Proxy, Atype_Aggregater
} AdapterType;
/*=====================================
Class Adapter
=====================================*/
class Adapter
{
public:
Adapter(Gateway* gw);
~Adapter(void);
void setup(const char* adpterName, AdapterType adapterType);
const char* getClientId(SensorNetAddress* addr);
void setClient(Client* client, bool secure);
Client* getClient(SensorNetAddress* addr);
Client* getClient(void);
Client* getSecureClient(void);
Client* getAdapterClient(Client* client);
void resetPingTimer(bool secure);
void checkConnection(void);
void send(MQTTSNPacket* packet, Client* client);
bool isActive(void);
bool isSecure(SensorNetAddress* addr);
bool isSecure(void);
void savePacket(Client* client, MQTTSNPacket* packet);
private:
Gateway* _gateway { nullptr };
Proxy* _proxy { nullptr };
Proxy* _proxySecure { nullptr };
Client* _client { nullptr };
Client* _clientSecure { nullptr };
bool _isActive { false };
bool _isSecure { false };
};
/*=====================================
Class Proxy
=====================================*/
class Proxy
{
public:
Proxy(Gateway* gw);
~Proxy(void);
void setKeepAlive(uint16_t secs);
void checkConnection(Client* client);
void resetPingTimer(void);
void recv(MQTTSNPacket* packet, Client* client);
void savePacket(Client* client, MQTTSNPacket* packet);
private:
void sendSuspendedPacket(void);
Gateway* _gateway;
EventQue* _suspendedPacketEventQue
{ nullptr };
Timer _keepAliveTimer;
Timer _responseTimer;
bool _isWaitingResp { false };
int _retryCnt { 0 };
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWADAPTER_H_ */

View File

@@ -0,0 +1,208 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWDefines.h"
#include "MQTTSNGateway.h"
#include "SensorNetwork.h"
#include "MQTTSNGWProcess.h"
#include "MQTTSNGWVersion.h"
#include "MQTTSNGWClientRecvTask.h"
#include "MQTTSNGWClientSendTask.h"
#include "MQTTSNGWClient.h"
#include "MQTTSNGWAggregater.h"
#include "MQTTSNGWQoSm1Proxy.h"
#include <string.h>
using namespace MQTTSNGW;
char* currentDateTime(void);
/*=====================================
Class AdapterManager
=====================================*/
AdapterManager::AdapterManager(Gateway* gw)
{
_gateway = gw;
_forwarders = new ForwarderList();
_qosm1Proxy = new QoSm1Proxy(gw);
_aggregater = new Aggregater(gw);
}
void AdapterManager::initialize(char* gwName, bool aggregate, bool forwarder, bool qosM1)
{
if (aggregate)
{
_aggregater->initialize(gwName);
}
if (qosM1)
{
_qosm1Proxy->initialize(gwName);
}
if (forwarder)
{
_forwarders->initialize(_gateway);
}
}
AdapterManager::~AdapterManager(void)
{
if (_forwarders)
{
delete _forwarders;
}
if (_qosm1Proxy)
{
delete _qosm1Proxy;
}
if (_aggregater)
{
delete _aggregater;
}
}
ForwarderList* AdapterManager::getForwarderList(void)
{
return _forwarders;
}
QoSm1Proxy* AdapterManager::getQoSm1Proxy(void)
{
return _qosm1Proxy;
}
Aggregater* AdapterManager::getAggregater(void)
{
return _aggregater;
}
bool AdapterManager::isAggregatedClient(Client* client)
{
if (!_aggregater->isActive() || client->isQoSm1() || client->isAggregater() || client->isQoSm1Proxy())
{
return false;
}
else
{
return true;
}
}
Client* AdapterManager::getClient(Client* client)
{
bool secure = client->isSecureNetwork();
Client* newClient = client;
if (client->isQoSm1())
{
newClient = _qosm1Proxy->getAdapterClient(client);
_qosm1Proxy->resetPingTimer(secure);
}
else if (client->isAggregated())
{
newClient = _aggregater->getAdapterClient(client);
_aggregater->resetPingTimer(secure);
}
else if (client->isQoSm1Proxy())
{
_qosm1Proxy->resetPingTimer(secure);
}
else if (client->isAggregater())
{
_aggregater->resetPingTimer(secure);
}
return newClient;
}
int AdapterManager::unicastToClient(Client* client, MQTTSNPacket* packet, ClientSendTask* task)
{
char pbuf[SIZE_OF_LOG_PACKET * 3];
Forwarder* fwd = client->getForwarder();
int rc = 0;
if (fwd)
{
MQTTSNGWEncapsulatedPacket encap(packet);
WirelessNodeId* wnId = fwd->getWirelessNodeId(client);
encap.setWirelessNodeId(wnId);
task->log(client, packet);
WRITELOG(FORMAT_Y_W_G, currentDateTime(), encap.getName(), RIGHTARROW, fwd->getId(), encap.print(pbuf));
rc = encap.unicast(_gateway->getSensorNetwork(), fwd->getSensorNetAddr());
}
else
{
task->log(client, packet);
if (client->isQoSm1Proxy())
{
_qosm1Proxy->send(packet, client);
}
else if (client->isAggregater())
{
_aggregater->send(packet, client);
}
else
{
rc = packet->unicast(_gateway->getSensorNetwork(), client->getSensorNetAddress());
}
}
return rc;
}
void AdapterManager::checkConnection(void)
{
if (_aggregater->isActive())
{
_aggregater->checkConnection();
}
if (_qosm1Proxy->isActive())
{
_qosm1Proxy->checkConnection();
}
}
Client* AdapterManager::convertClient(uint16_t msgId, uint16_t* clientMsgId)
{
return _aggregater->convertClient(msgId, clientMsgId);
}
bool AdapterManager::isAggregaterActive(void)
{
return _aggregater->isActive();
}
/*
AggregateTopicElement* AdapterManager::findTopic(Topic* topic)
{
return _aggregater->findTopic(topic);
}
AggregateTopicElement* AdapterManager::addAggregateTopic(Topic* topic, Client* client)
{
return _aggregater->addAggregateTopic(topic, client);
}
void AdapterManager::removeAggregateTopic(Topic* topic, Client* client)
{
//_aggregater->removeAggregateTopic(topic, client);
}
void AdapterManager::removeAggregateTopicList(Topics* topics, Client* client)
{
}
*/

View File

@@ -0,0 +1,64 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWADAPTERMANAGER_H_
#define MQTTSNGATEWAY_SRC_MQTTSNGWADAPTERMANAGER_H_
#include "MQTTSNGWAggregater.h"
#include "MQTTSNGWQoSm1Proxy.h"
namespace MQTTSNGW
{
class Gateway;
class Client;
class QoSm1Proxy;
class Aggregater;
class ForwarderList;
class Forwarder;
class MQTTSNPacket;
class MQTTSNGWPacket;
class ClientRecvTask;
class ClientSendTask;
/*=====================================
Class AdapterManager
=====================================*/
class AdapterManager
{
public:
AdapterManager(Gateway* gw);
~AdapterManager(void);
void initialize(char* gwName, bool aggregater, bool fowarder, bool qosM1);
ForwarderList* getForwarderList(void);
QoSm1Proxy* getQoSm1Proxy(void);
Aggregater* getAggregater(void);
void checkConnection(void);
bool isAggregatedClient(Client* client);
Client* getClient(Client* client);
Client* convertClient(uint16_t msgId, uint16_t* clientMsgId);
int unicastToClient(Client* client, MQTTSNPacket* packet,
ClientSendTask* task);
bool isAggregaterActive(void);
private:
Gateway* _gateway { nullptr };
ForwarderList* _forwarders { nullptr };
QoSm1Proxy* _qosm1Proxy { nullptr };
Aggregater* _aggregater { nullptr };
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWADAPTERMANAGER_H_ */

View File

@@ -0,0 +1,320 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWAggregateTopicTable.h"
#include "MQTTSNGWClient.h"
/*=====================================
Class ClientTopicElement
=====================================*/
ClientTopicElement::ClientTopicElement(Client* client)
{
_client = client;
}
ClientTopicElement::~ClientTopicElement()
{
}
Client* ClientTopicElement::getClient(void)
{
return _client;
}
ClientTopicElement* ClientTopicElement::getNextClientElement(void)
{
return _next;
}
/*=====================================
Class AggregateTopicElement
=====================================*/
AggregateTopicElement::AggregateTopicElement(void)
{
}
AggregateTopicElement::AggregateTopicElement(Topic* topic, Client* client)
{
_topic = topic;
ClientTopicElement* elm = new ClientTopicElement(client);
if (elm != nullptr)
{
_head = elm;
_tail = elm;
}
}
AggregateTopicElement::~AggregateTopicElement(void)
{
_mutex.lock();
if (_head != nullptr)
{
ClientTopicElement* p = _tail;
while (p)
{
ClientTopicElement* pPrev = p;
delete p;
p = pPrev->_prev;
}
_head = _tail = nullptr;
}
_mutex.unlock();
}
ClientTopicElement* AggregateTopicElement::add(Client* client)
{
ClientTopicElement* elm = new ClientTopicElement(client);
if (elm == nullptr)
{
return nullptr;
}
_mutex.lock();
if (_head == nullptr)
{
_head = elm;
_tail = elm;
}
else
{
ClientTopicElement* p = find(client);
if (p == nullptr)
{
p = _tail;
_tail = elm;
elm->_prev = p;
p->_next = elm;
}
else
{
delete elm;
elm = p;
}
}
_mutex.unlock();
return elm;
}
ClientTopicElement* AggregateTopicElement::find(Client* client)
{
ClientTopicElement* p = _head;
while (p != nullptr)
{
if (p->_client == client)
{
break;
}
p = p->_next;
}
return p;
}
ClientTopicElement* AggregateTopicElement::getFirstClientTopicElement(void)
{
return _head;
}
ClientTopicElement* AggregateTopicElement::getNextClientTopicElement(ClientTopicElement* elmClient)
{
return elmClient->_next;
}
void AggregateTopicElement::eraseClient(Client* client)
{
_mutex.lock();
ClientTopicElement* p = find(client);
if (p != nullptr)
{
if (p->_prev == nullptr) // head element
{
_head = p->_next;
if (p->_next == nullptr) // head & only one
{
_tail = nullptr;
}
else
{
p->_next->_prev = nullptr; // head & midle
}
}
else if (p->_next != nullptr) // middle
{
p->_prev->_next = p->_next;
}
else // tail
{
p->_prev->_next = nullptr;
_tail = p->_prev;
}
delete p;
}
_mutex.unlock();
}
/*=====================================
Class AggregateTopicTable
======================================*/
AggregateTopicTable::AggregateTopicTable()
{
}
AggregateTopicTable::~AggregateTopicTable()
{
}
AggregateTopicElement* AggregateTopicTable::add(Topic* topic, Client* client)
{
AggregateTopicElement* elm = nullptr;
_mutex.lock();
elm = getAggregateTopicElement(topic);
if (elm != nullptr)
{
if (elm->find(client) == nullptr)
{
elm->add(client);
}
}
else
{
Topic* newTopic = topic->duplicate();
elm = new AggregateTopicElement(newTopic, client);
if (_head == nullptr)
{
_head = elm;
_tail = elm;
}
else
{
elm->_prev = _tail;
_tail->_next = elm;
_tail = elm;
}
}
_mutex.unlock();
return elm;
}
void AggregateTopicTable::erase(Topic* topic, Client* client)
{
AggregateTopicElement* elm = nullptr;
_mutex.lock();
elm = getAggregateTopicElement(topic);
if (elm != nullptr)
{
elm->eraseClient(client);
}
if (elm->_head == nullptr)
{
erase(elm);
}
_mutex.unlock();
return;
}
void AggregateTopicTable::erase(AggregateTopicElement* elmTopic)
{
if (elmTopic != nullptr)
{
if (elmTopic->_prev == nullptr) // head element
{
_head = elmTopic->_next;
if (elmTopic->_next == nullptr) // head & only one
{
_tail = nullptr;
}
else
{
elmTopic->_next->_prev = nullptr; // head & midle
}
}
else if (elmTopic->_next != nullptr) // middle
{
elmTopic->_prev->_next = elmTopic->_next;
}
else // tail
{
elmTopic->_prev->_next = nullptr;
_tail = elmTopic->_prev;
}
delete elmTopic;
}
}
AggregateTopicElement* AggregateTopicTable::getAggregateTopicElement(Topic* topic)
{
AggregateTopicElement* elm = _head;
while (elm != nullptr)
{
if (elm->_topic->isMatch(topic->_topicName))
{
break;
}
elm = elm->_next;
}
return elm;
}
ClientTopicElement* AggregateTopicTable::getClientElement(Topic* topic)
{
AggregateTopicElement* elm = getAggregateTopicElement(topic);
if (elm != nullptr)
{
return elm->_head;
}
else
{
return nullptr;
}
}
void AggregateTopicTable::print(void)
{
AggregateTopicElement* elm = _head;
printf("Beginning of AggregateTopicTable\n");
while (elm != nullptr)
{
printf("%s\n", elm->_topic->getTopicName()->c_str());
ClientTopicElement* clElm = elm->getFirstClientTopicElement();
Client* client = clElm->getClient();
while (client != nullptr)
{
printf(" %s\n", client->getClientId());
clElm = clElm->getNextClientElement();
if (clElm != nullptr)
{
client = clElm->getClient();
}
else
{
client = nullptr;
}
}
elm = elm->_next;
}
printf("End of AggregateTopicTable\n");
}

View File

@@ -0,0 +1,107 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATETOPICTABLE_H_
#define MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATETOPICTABLE_H_
#include "MQTTSNGWDefines.h"
#include "MQTTSNGWProcess.h"
#include <stdint.h>
namespace MQTTSNGW
{
class Client;
class Topic;
class AggregateTopicElement;
class ClientTopicElement;
class Mutex;
/*=====================================
Class AggregateTopicTable
======================================*/
class AggregateTopicTable
{
public:
AggregateTopicTable();
~AggregateTopicTable();
AggregateTopicElement* add(Topic* topic, Client* client);
AggregateTopicElement* getAggregateTopicElement(Topic* topic);
ClientTopicElement* getClientElement(Topic* topic);
void erase(Topic* topic, Client* client);
void clear(void);
void print(void);
private:
void erase(AggregateTopicElement* elmTopic);
Mutex _mutex;
AggregateTopicElement* _head { nullptr };
AggregateTopicElement* _tail { nullptr };
int _cnt { 0 };
int _maxSize { MAX_MESSAGEID_TABLE_SIZE };
};
/*=====================================
Class AggregateTopicElement
=====================================*/
class AggregateTopicElement
{
friend class AggregateTopicTable;
public:
AggregateTopicElement(void);
AggregateTopicElement(Topic* topic, Client* client);
~AggregateTopicElement(void);
ClientTopicElement* add(Client* client);
ClientTopicElement* getFirstClientTopicElement(void);
ClientTopicElement* getNextClientTopicElement(
ClientTopicElement* elmClient);
void eraseClient(Client* client);
ClientTopicElement* find(Client* client);
private:
Mutex _mutex;
Topic* _topic { nullptr };
AggregateTopicElement* _next { nullptr };
AggregateTopicElement* _prev { nullptr };
ClientTopicElement* _head { nullptr };
ClientTopicElement* _tail { nullptr };
};
/*=====================================
Class ClientTopicElement
=====================================*/
class ClientTopicElement
{
friend class AggregateTopicTable;
friend class AggregateTopicElement;
public:
ClientTopicElement(Client* client);
~ClientTopicElement(void);
ClientTopicElement* getNextClientElement(void);
Client* getClient(void);
private:
Client* _client { nullptr };
ClientTopicElement* _next { nullptr };
ClientTopicElement* _prev { nullptr };
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATETOPICTABLE_H_ */

View File

@@ -0,0 +1,147 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWAggregater.h"
#include "MQTTSNGateway.h"
#include "MQTTSNGWClient.h"
#include "MQTTSNGWAdapter.h"
#include "MQTTSNGWAdapterManager.h"
#include "MQTTSNGWMessageIdTable.h"
#include "MQTTSNGWTopic.h"
#include <stdio.h>
#include <string.h>
#include <string>
using namespace MQTTSNGW;
Aggregater::Aggregater(Gateway* gw) :
Adapter(gw)
{
_gateway = gw;
}
Aggregater::~Aggregater(void)
{
}
void Aggregater::initialize(char* gwName)
{
/* Create Aggregater Client */
string name = string(gwName) + string("_Aggregater");
setup(name.c_str(), Atype_Aggregater);
_isActive = true;
//testMessageIdTable();
}
bool Aggregater::isActive(void)
{
return _isActive;
}
uint16_t Aggregater::msgId(void)
{
// Only SecureClient generates msgId to avoid duplication of msgId. Client does not generate it.
return Adapter::getSecureClient()->getNextPacketId();
}
Client* Aggregater::convertClient(uint16_t msgId, uint16_t* clientMsgId)
{
return _msgIdTable.getClientMsgId(msgId, clientMsgId);
}
uint16_t Aggregater::addMessageIdTable(Client* client, uint16_t msgId)
{
/* set Non secure client`s nextMsgId. otherwise Id is duplicated.*/
MessageIdElement* elm = _msgIdTable.add(this, client, msgId);
if (elm == nullptr)
{
return 0;
}
else
{
return elm->_msgId;
}
}
uint16_t Aggregater::getMsgId(Client* client, uint16_t clientMsgId)
{
return _msgIdTable.getMsgId(client, clientMsgId);
}
AggregateTopicElement* Aggregater::addAggregateTopic(Topic* topic, Client* client)
{
return _topicTable.add(topic, client);
}
void Aggregater::removeAggregateTopic(Topic* topic, Client* client)
{
_topicTable.erase(topic, client);
}
AggregateTopicElement* Aggregater::findTopic(Topic* topic)
{
return _topicTable.getAggregateTopicElement(topic);
}
ClientTopicElement* Aggregater::getClientElement(Topic* topic)
{
AggregateTopicElement* elm = findTopic(topic);
if (elm != nullptr)
{
return elm->getFirstClientTopicElement();
}
else
{
return nullptr;
}
}
void Aggregater::printAggregateTopicTable(void)
{
_topicTable.print();
}
bool Aggregater::testMessageIdTable(void)
{
Client* client = new Client();
uint16_t msgId = 0;
printf("msgId=%d\n", addMessageIdTable(client, 1));
printf("msgId=%d\n", addMessageIdTable(client, 2));
printf("msgId=%d\n", addMessageIdTable(client, 3));
printf("msgId=%d\n", addMessageIdTable(client, 1));
printf("msgId=%d\n", addMessageIdTable(client, 2));
printf("msgId=%d\n", addMessageIdTable(client, 3));
printf("msgId=%d\n", addMessageIdTable(client, 4));
printf("msgId=%d\n", addMessageIdTable(client, 4));
printf("msgId=%d\n", addMessageIdTable(client, 4));
convertClient(1, &msgId);
printf("msgId=%d\n", msgId);
convertClient(2, &msgId);
printf("msgId=%d\n", msgId);
convertClient(5, &msgId);
printf("msgId=%d\n", msgId);
convertClient(4, &msgId);
printf("msgId=%d\n", msgId);
convertClient(3, &msgId);
printf("msgId=%d\n", msgId);
return true;
}

View File

@@ -0,0 +1,78 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATER_H_
#define MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATER_H_
#include "MQTTSNGWAdapter.h"
#include "MQTTSNGWMessageIdTable.h"
#include "MQTTSNGWAggregateTopicTable.h"
namespace MQTTSNGW
{
class Gateway;
class Adapter;
class Client;
class SensorNetAddress;
class MessageIdTable;
class AggregateTopicTable;
class Topics;
/*=====================================
Class Aggregater
=====================================*/
class Aggregater: public Adapter
{
friend class MessageIdTable;
public:
Aggregater(Gateway* gw);
~Aggregater(void);
void initialize(char* gwName);
const char* getClientId(SensorNetAddress* addr);
Client* getClient(SensorNetAddress* addr);
Client* convertClient(uint16_t msgId, uint16_t* clientMsgId);
uint16_t addMessageIdTable(Client* client, uint16_t msgId);
uint16_t getMsgId(Client* client, uint16_t clientMsgId);
ClientTopicElement* getClientElement(Topic* topic);
ClientTopicElement* getNextClientElement(ClientTopicElement* clientElement);
Client* getClient(ClientTopicElement* clientElement);
AggregateTopicElement* findTopic(Topic* topic);
AggregateTopicElement* addAggregateTopic(Topic* topic, Client* client);
void removeAggregateTopic(Topic* topic, Client* client);
void removeAggregateAllTopic(Client* client);
bool isActive(void);
void printAggregateTopicTable(void);
bool testMessageIdTable(void);
private:
uint16_t msgId(void);
Gateway* _gateway { nullptr };
MessageIdTable _msgIdTable;
AggregateTopicTable _topicTable;
bool _isActive { false };
bool _isSecure { false };
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWAGGREGATER_H_ */

View File

@@ -16,6 +16,8 @@
#include "MQTTSNGWBrokerRecvTask.h" #include "MQTTSNGWBrokerRecvTask.h"
#include "MQTTSNGWClient.h" #include "MQTTSNGWClient.h"
#include "MQTTSNGWClientList.h"
#include "MQTTSNGateway.h"
#include <unistd.h> #include <unistd.h>
using namespace std; using namespace std;
@@ -28,14 +30,14 @@ char* currentDateTime(void);
=====================================*/ =====================================*/
BrokerRecvTask::BrokerRecvTask(Gateway* gateway) BrokerRecvTask::BrokerRecvTask(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
_gateway->attach((Thread*)this); _gateway->attach((Thread*) this);
_light = 0; _light = nullptr;
setTaskName("BrokerRecvTask");
} }
BrokerRecvTask::~BrokerRecvTask() BrokerRecvTask::~BrokerRecvTask()
{ {
} }
/** /**
@@ -43,7 +45,7 @@ BrokerRecvTask::~BrokerRecvTask()
*/ */
void BrokerRecvTask::initialize(int argc, char** argv) void BrokerRecvTask::initialize(int argc, char** argv)
{ {
_light = _gateway->getLightIndicator(); _light = _gateway->getLightIndicator();
} }
/** /**
@@ -51,133 +53,130 @@ void BrokerRecvTask::initialize(int argc, char** argv)
*/ */
void BrokerRecvTask::run(void) void BrokerRecvTask::run(void)
{ {
struct timeval timeout; struct timeval timeout;
MQTTGWPacket* packet = 0; MQTTGWPacket* packet = nullptr;
int rc; int rc;
Event* ev = 0; Event* ev = nullptr;
fd_set rset; fd_set rset;
fd_set wset; fd_set wset;
while (true) while (true)
{ {
_light->blueLight(false); _light->blueLight(false);
if (CHK_SIGINT) if (CHK_SIGINT)
{ {
WRITELOG("%s BrokerRecvTask stopped.\n", currentDateTime()); WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName());
return; return;
} }
timeout.tv_sec = 0; timeout.tv_sec = 0;
timeout.tv_usec = 500000; // 500 msec timeout.tv_usec = 500000; // 500 msec
FD_ZERO(&rset); FD_ZERO(&rset);
FD_ZERO(&wset); FD_ZERO(&wset);
int maxSock = 0; int maxSock = 0;
int sockfd = 0; int sockfd = 0;
/* Prepare sockets list to read */ /* Prepare sockets list to read */
Client* client = _gateway->getClientList()->getClient(); Client* client = _gateway->getClientList()->getClient(0);
while (client > 0) while (client)
{ {
if (client->getNetwork()->isValid()) if (client->getNetwork()->isValid())
{ {
sockfd = client->getNetwork()->getSock(); sockfd = client->getNetwork()->getSock();
FD_SET(sockfd, &rset); FD_SET(sockfd, &rset);
FD_SET(sockfd, &wset); FD_SET(sockfd, &wset);
if (sockfd > maxSock) if (sockfd > maxSock)
{ {
maxSock = sockfd; maxSock = sockfd;
} }
} }
client = client->getNextClient(); client = client->getNextClient();
} }
if (maxSock == 0) if (maxSock == 0)
{ {
usleep(500 * 1000); usleep(500 * 1000);
} }
else else
{ {
/* Check sockets is ready to read */ /* Check sockets is ready to read */
int activity = select(maxSock + 1, &rset, 0, 0, &timeout); int activity = select(maxSock + 1, &rset, 0, 0, &timeout);
if (activity > 0)
{
client = _gateway->getClientList()->getClient();
while (client > 0) if (activity > 0)
{ {
_light->blueLight(false); client = _gateway->getClientList()->getClient(0);
if (client->getNetwork()->isValid())
{
int sockfd = client->getNetwork()->getSock();
if (FD_ISSET(sockfd, &rset))
{
packet = new MQTTGWPacket();
rc = 0;
/* read sockets */
_light->blueLight(true);
rc = packet->recv(client->getNetwork());
if ( rc > 0 )
{
if ( log(client, packet) == -1 )
{
delete packet;
goto nextClient;
}
/* post a BrokerRecvEvent */ while (client)
ev = new Event(); {
ev->setBrokerRecvEvent(client, packet); _light->blueLight(false);
_gateway->getPacketEventQue()->post(ev); if (client->getNetwork()->isValid())
} {
else int sockfd = client->getNetwork()->getSock();
{ if (FD_ISSET(sockfd, &rset))
if ( rc == 0 ) // Disconnected {
{ packet = new MQTTGWPacket();
client->getNetwork()->close(); rc = 0;
delete packet; /* read sockets */
_light->blueLight(true);
rc = packet->recv(client->getNetwork());
if (rc > 0)
{
if (log(client, packet) == -1)
{
delete packet;
goto nextClient;
}
/* delete client when the client is not authorized & session is clean */ /* post a BrokerRecvEvent */
_gateway->getClientList()->erase(client); ev = new Event();
ev->setBrokerRecvEvent(client, packet);
_gateway->getPacketEventQue()->post(ev);
}
else
{
if (rc == 0) // Disconnected
{
WRITELOG("%s BrokerRecvTask %s is disconnected by the broker.%s\n",
ERRMSG_HEADER, client->getClientId(),
ERRMSG_FOOTER);
client->getNetwork()->close();
client->disconnected();
}
else if (rc == -1)
{
WRITELOG("%s BrokerRecvTask can't receive a packet from the broker errno=%d %s%s\n",
ERRMSG_HEADER, errno, client->getClientId(),
ERRMSG_FOOTER);
}
else if (rc == -2)
{
WRITELOG(
"%s BrokerRecvTask receive invalid length of packet from the broker. DISCONNECT %s %s\n",
ERRMSG_HEADER, client->getClientId(),
ERRMSG_FOOTER);
}
else if (rc == -3)
{
WRITELOG("%s BrokerRecvTask can't allocate memories for the packet %s%s\n",
ERRMSG_HEADER, client->getClientId(),
ERRMSG_FOOTER);
}
if ( client ) delete packet;
{
client = client->getNextClient();
}
continue;
}
else if (rc == -1)
{
WRITELOG("%s BrokerRecvTask can't receive a packet from the broker errno=%d %s%s\n", ERRMSG_HEADER, errno, client->getClientId(), ERRMSG_FOOTER);
}
else if ( rc == -2 )
{
WRITELOG("%s BrokerRecvTask receive invalid length of packet from the broker. DISCONNECT %s %s\n", ERRMSG_HEADER, client->getClientId(),ERRMSG_FOOTER);
}
else if ( rc == -3 )
{
WRITELOG("%s BrokerRecvTask can't get memories for the packet %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
}
delete packet; if ((rc == -1 || rc == -2) && (client->isActive() || client->isSleep() || client->isAwake()))
{
if ( (rc == -1 || rc == -2) && client->isActive() ) client->getNetwork()->close();
{ client->disconnected();
/* disconnect the client */ }
packet = new MQTTGWPacket(); }
packet->setHeader(DISCONNECT); }
ev = new Event(); }
ev->setBrokerRecvEvent(client, packet); nextClient: client = client->getNextClient();
_gateway->getPacketEventQue()->post(ev); }
} }
} }
} }
}
nextClient:
client = client->getNextClient();
}
}
}
}
} }
/** /**
@@ -185,35 +184,38 @@ void BrokerRecvTask::run(void)
*/ */
int BrokerRecvTask::log(Client* client, MQTTGWPacket* packet) int BrokerRecvTask::log(Client* client, MQTTGWPacket* packet)
{ {
char pbuf[(SIZE_OF_LOG_PACKET + 5 )* 3]; char pbuf[(SIZE_OF_LOG_PACKET + 5) * 3];
char msgId[6]; char msgId[6];
int rc = 0; int rc = 0;
switch (packet->getType()) switch (packet->getType())
{ {
case CONNACK: case CONNACK:
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), LEFTARROW, client->getClientId(), packet->print(pbuf)); WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), LEFTARROWB, client->getClientId(), packet->print(pbuf));
break; break;
case PUBLISH: case PUBLISH:
WRITELOG(FORMAT_W_MSGID_Y_W_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, client->getClientId(), packet->print(pbuf)); WRITELOG(FORMAT_W_MSGID_Y_W_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB,
break; client->getClientId(), packet->print(pbuf));
case PUBACK: break;
case PUBREC: case PUBACK:
case PUBREL: case PUBREC:
case PUBCOMP: case PUBREL:
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, client->getClientId(), packet->print(pbuf)); case PUBCOMP:
break; WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB,
case SUBACK: client->getClientId(), packet->print(pbuf));
case UNSUBACK: break;
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, client->getClientId(), packet->print(pbuf)); case SUBACK:
break; case UNSUBACK:
case PINGRESP: WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROWB,
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), LEFTARROW, client->getClientId(), packet->print(pbuf)); client->getClientId(), packet->print(pbuf));
break; break;
default: case PINGRESP:
WRITELOG("Type=%x\n", packet->getType()); WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), LEFTARROWB, client->getClientId(), packet->print(pbuf));
rc = -1; break;
break; default:
} WRITELOG("Type=%x\n", packet->getType());
return rc; rc = -1;
break;
}
return rc;
} }

View File

@@ -28,21 +28,20 @@ namespace MQTTSNGW
class BrokerRecvTask: public Thread class BrokerRecvTask: public Thread
{ {
MAGIC_WORD_FOR_THREAD; MAGIC_WORD_FOR_THREAD;
;
public: public:
BrokerRecvTask(Gateway* gateway); BrokerRecvTask(Gateway* gateway);
~BrokerRecvTask(); ~BrokerRecvTask();
void initialize(int argc, char** argv); void initialize(int argc, char** argv);
void run(void); void run(void);
private: private:
int log(Client*, MQTTGWPacket*); int log(Client*, MQTTGWPacket*);
Gateway* _gateway; Gateway* _gateway;
LightIndicator* _light; LightIndicator* _light;
}; };
} }
#endif /* MQTTSNGWBROKERRECVTASK_H_ */ #endif /* MQTTSNGWBROKERRECVTASK_H_ */

View File

@@ -14,6 +14,7 @@
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/ **************************************************************************************/
#include <MQTTSNGWAdapterManager.h>
#include "MQTTSNGWBrokerSendTask.h" #include "MQTTSNGWBrokerSendTask.h"
#include "MQTTSNGWDefines.h" #include "MQTTSNGWDefines.h"
#include "MQTTSNGateway.h" #include "MQTTSNGateway.h"
@@ -32,15 +33,15 @@ char* currentDateTime();
=====================================*/ =====================================*/
BrokerSendTask::BrokerSendTask(Gateway* gateway) BrokerSendTask::BrokerSendTask(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
_gateway->attach((Thread*)this); _gateway->attach((Thread*) this);
_gwparams = 0; _gwparams = nullptr;
_light = 0; _light = nullptr;
setTaskName("BrokerSendTask");
} }
BrokerSendTask::~BrokerSendTask() BrokerSendTask::~BrokerSendTask()
{ {
} }
/** /**
@@ -48,8 +49,8 @@ BrokerSendTask::~BrokerSendTask()
*/ */
void BrokerSendTask::initialize(int argc, char** argv) void BrokerSendTask::initialize(int argc, char** argv)
{ {
_gwparams = _gateway->getGWParams(); _gwparams = _gateway->getGWParams();
_light = _gateway->getLightIndicator(); _light = _gateway->getLightIndicator();
} }
/** /**
@@ -57,120 +58,137 @@ void BrokerSendTask::initialize(int argc, char** argv)
*/ */
void BrokerSendTask::run() void BrokerSendTask::run()
{ {
Event* ev = 0; Event* ev = nullptr;
MQTTGWPacket* packet = 0; MQTTGWPacket* packet = nullptr;
Client* client = 0; Client* client = nullptr;
int rc = 0; AdapterManager* adpMgr = _gateway->getAdapterManager();
int rc = 0;
while (true) while (true)
{ {
ev = _gateway->getBrokerSendQue()->wait(); ev = _gateway->getBrokerSendQue()->wait();
if ( ev->getEventType() == EtStop ) if (ev->getEventType() == EtStop)
{ {
WRITELOG("%s BrokerSendTask stopped.\n", currentDateTime()); WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName());
delete ev; delete ev;
return; return;
} }
if ( ev->getEventType() == EtBrokerSend) if (ev->getEventType() == EtBrokerSend)
{ {
client = ev->getClient(); client = ev->getClient();
packet = ev->getMQTTGWPacket(); packet = ev->getMQTTGWPacket();
if ( packet->getType() == CONNECT && client->getNetwork()->isValid() ) /* Check Client is managed by Adapters */
{ client = adpMgr->getClient(client);
client->getNetwork()->close();
}
if ( !client->getNetwork()->isValid() ) if (packet->getType() == CONNECT && client->getNetwork()->isValid())
{ {
/* connect to the broker and send a packet */ client->getNetwork()->close();
}
if (client->isSecureNetwork()) if (!client->getNetwork()->isValid())
{ {
rc = client->getNetwork()->connect(_gwparams->brokerName, _gwparams->portSecure, _gwparams->rootCApath, /* connect to the broker and send a packet */
_gwparams->rootCAfile, _gwparams->certKey, _gwparams->privateKey);
}
else
{
rc = client->getNetwork()->connect(_gwparams->brokerName, _gwparams->port);
}
if ( !rc ) if (client->isSecureNetwork())
{ {
/* disconnect the broker and the client */ rc = client->getNetwork()->connect((const char*) _gwparams->brokerName, (const char*) _gwparams->portSecure,
WRITELOG("%s BrokerSendTask can't connect to the broker. %s%s\n", (const char*) _gwparams->rootCApath, (const char*) _gwparams->rootCAfile,
ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); (const char*) _gwparams->certKey, (const char*) _gwparams->privateKey);
delete ev; }
client->getNetwork()->close(); else
continue; {
} rc = client->getNetwork()->connect((const char*) _gwparams->brokerName, (const char*) _gwparams->port);
} }
/* send a packet */ if (!rc)
_light->blueLight(true); {
if ( (rc = packet->send(client->getNetwork())) > 0 ) /* disconnect the broker and the client */
{ WRITELOG("%s BrokerSendTask: %s can't connect to the broker. errno=%d %s %s\n",
if ( packet->getType() == CONNECT ) ERRMSG_HEADER, client->getClientId(), errno, strerror(errno), ERRMSG_FOOTER);
{ delete ev;
client->connectSended(); client->getNetwork()->close();
} continue;
log(client, packet); }
} }
else
{
WRITELOG("%s BrokerSendTask can't send a packet to the broker errno=%d %s%s\n",
ERRMSG_HEADER, rc == -1 ? errno : 0, client->getClientId(), ERRMSG_FOOTER);
client->getNetwork()->close();
/* Disconnect the client */ /* send a packet */
packet = new MQTTGWPacket(); _light->blueLight(true);
packet->setHeader(DISCONNECT); if ((rc = packet->send(client->getNetwork())) > 0)
Event* ev1 = new Event(); {
ev1->setBrokerRecvEvent(client, packet); if (packet->getType() == CONNECT)
_gateway->getPacketEventQue()->post(ev1); {
} client->connectSended();
}
else if (packet->getType() == DISCONNECT)
{
client->getNetwork()->close();
client->disconnected();
}
log(client, packet);
}
else
{
WRITELOG("%s BrokerSendTask: %s can't send a packet to the broker. errno=%d %s %s\n",
ERRMSG_HEADER, client->getClientId(), rc == -1 ? errno : 0, strerror(errno), ERRMSG_FOOTER);
if ( errno != EBADF)
{
client->getNetwork()->close();
}
_light->blueLight(false); /* Disconnect the client */
} packet = new MQTTGWPacket();
delete ev; packet->setHeader(DISCONNECT);
} Event* ev1 = new Event();
ev1->setBrokerRecvEvent(client, packet);
_gateway->getPacketEventQue()->post(ev1);
}
_light->blueLight(false);
}
delete ev;
}
} }
/** /**
* write message content into stdout or Ringbuffer * write message content into stdout or Ringbuffer
*/ */
void BrokerSendTask::log(Client* client, MQTTGWPacket* packet) void BrokerSendTask::log(Client* client, MQTTGWPacket* packet)
{ {
char pbuf[(SIZE_OF_LOG_PACKET + 5 )* 3]; char pbuf[(SIZE_OF_LOG_PACKET + 5) * 3];
char msgId[6]; char msgId[6];
switch (packet->getType()) switch (packet->getType())
{ {
case CONNECT: case CONNECT:
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), RIGHTARROW, client->getClientId(), packet->print(pbuf)); WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(),
break; RIGHTARROWB, client->getClientId(), packet->print(pbuf));
case PUBLISH: break;
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, client->getClientId(), packet->print(pbuf)); case PUBLISH:
break; WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROWB,
case SUBSCRIBE: client->getClientId(), packet->print(pbuf));
case UNSUBSCRIBE: break;
case PUBACK: case SUBSCRIBE:
case PUBREC: case UNSUBSCRIBE:
case PUBREL: case PUBACK:
case PUBCOMP: case PUBREC:
WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, client->getClientId(), packet->print(pbuf)); case PUBREL:
break; case PUBCOMP:
case PINGREQ: WRITELOG(FORMAT_W_MSGID_Y_W, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROWB,
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), RIGHTARROW, client->getClientId(), packet->print(pbuf)); client->getClientId(), packet->print(pbuf));
break; break;
case DISCONNECT: case PINGREQ:
WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(), RIGHTARROW, client->getClientId(), packet->print(pbuf)); WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(),
break; RIGHTARROWB, client->getClientId(), packet->print(pbuf));
default: break;
break; case DISCONNECT:
} WRITELOG(FORMAT_Y_Y_W, currentDateTime(), packet->getName(),
RIGHTARROWB, client->getClientId(), packet->print(pbuf));
break;
default:
break;
}
} }

View File

@@ -22,22 +22,25 @@
namespace MQTTSNGW namespace MQTTSNGW
{ {
class Adapter;
/*===================================== /*=====================================
Class BrokerSendTask Class BrokerSendTask
=====================================*/ =====================================*/
class BrokerSendTask : public Thread class BrokerSendTask: public Thread
{ {
MAGIC_WORD_FOR_THREAD; MAGIC_WORD_FOR_THREAD;
friend AdapterManager;
public: public:
BrokerSendTask(Gateway* gateway); BrokerSendTask(Gateway* gateway);
~BrokerSendTask(); ~BrokerSendTask();
void initialize(int argc, char** argv); void initialize(int argc, char** argv);
void run(); void run();
private: private:
void log(Client*, MQTTGWPacket*); void log(Client*, MQTTGWPacket*);
Gateway* _gateway; Gateway* _gateway;
GatewayParams* _gwparams; GatewayParams* _gwparams;
LightIndicator* _light; LightIndicator* _light;
}; };
} }

File diff suppressed because it is too large Load Diff

View File

@@ -12,6 +12,7 @@
* *
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
* Tieto Poland Sp. z o.o. - Gateway improvements
**************************************************************************************/ **************************************************************************************/
#ifndef MQTTSNGWCLIENT_H_ #ifndef MQTTSNGWCLIENT_H_
@@ -25,6 +26,11 @@
#include "Network.h" #include "Network.h"
#include "SensorNetwork.h" #include "SensorNetwork.h"
#include "MQTTSNPacket.h" #include "MQTTSNPacket.h"
#include "MQTTSNGWEncapsulatedPacket.h"
#include "MQTTSNGWForwarder.h"
#include "MQTTSNGWTopic.h"
#include "MQTTSNGWClientList.h"
#include "MQTTSNGWAdapter.h"
namespace MQTTSNGW namespace MQTTSNGW
{ {
@@ -38,142 +44,71 @@ namespace MQTTSNGW
template<class T> class PacketQue template<class T> class PacketQue
{ {
public: public:
PacketQue() PacketQue()
{ {
_que = new Que<T>; _que = new Que<T>;
} }
~PacketQue() ~PacketQue()
{ {
clear(); clear();
delete _que; delete _que;
} }
T* getPacket() T* getPacket()
{ {
T* packet; T* packet;
if (_que->size() > 0) if (_que->size() > 0)
{ {
_mutex.lock(); _mutex.lock();
packet = _que->front(); packet = _que->front();
_mutex.unlock(); _mutex.unlock();
return packet; return packet;
} }
else else
{ {
return 0; return 0;
} }
} }
void post(T* packet) int post(T* packet)
{ {
_mutex.lock(); int rc;
_que->post(packet); _mutex.lock();
_mutex.unlock(); rc = _que->post(packet);
} _mutex.unlock();
return rc;
}
void pop() void pop()
{ {
if (_que->size() > 0) if (_que->size() > 0)
{ {
_mutex.lock(); _mutex.lock();
_que->pop(); _que->pop();
_mutex.unlock(); _mutex.unlock();
} }
} }
void clear() void clear()
{ {
_mutex.lock(); _mutex.lock();
while (_que->size() > 0) while (_que->size() > 0)
{ {
delete _que->front(); delete _que->front();
_que->pop(); _que->pop();
} }
_mutex.unlock(); _mutex.unlock();
} }
void setMaxSize(int size)
{
_que->setMaxSize(size);
}
private: private:
Que<T>* _que; Que<T>* _que;
Mutex _mutex; Mutex _mutex;
};
/*=====================================
Class Topic
======================================*/
class Topic
{
friend class Topics;
public:
Topic();
Topic(string* topic);
~Topic();
string* getTopicName(void);
uint16_t getTopicId(void);
bool isMatch(string* topicName);
private:
uint16_t _topicId;
string* _topicName;
Topic* _next;
};
/*=====================================
Class Topics
======================================*/
class Topics
{
public:
Topics();
~Topics();
Topic* add(const MQTTSN_topicid* topicid);
Topic* add(const string* topic);
uint16_t getTopicId(const MQTTSN_topicid* topic);
uint16_t getNextTopicId();
Topic* getTopic(uint16_t topicId);
Topic* getTopic(const MQTTSN_topicid* topicid);
Topic* match(const MQTTSN_topicid* topicid);
private:
uint16_t _nextTopicId;
Topic* _first;
};
/*=====================================
Class TopicIdMap
=====================================*/
class TopicIdMapelement
{
friend class TopicIdMap;
public:
TopicIdMapelement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type);
~TopicIdMapelement();
private:
uint16_t _msgId;
uint16_t _topicId;
MQTTSN_topicTypes _type;
TopicIdMapelement* _next;
TopicIdMapelement* _prev;
};
class TopicIdMap
{
public:
TopicIdMap();
~TopicIdMap();
uint16_t getTopicId(uint16_t msgId, MQTTSN_topicTypes* type);
int add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type);
void erase(uint16_t msgId);
void clear(void);
private:
uint16_t* _msgIds;
TopicIdMapelement* _first;
TopicIdMapelement* _end;
int _cnt;
int _maxInflight;
}; };
/*===================================== /*=====================================
@@ -181,16 +116,16 @@ private:
=====================================*/ =====================================*/
class waitREGACKPacket class waitREGACKPacket
{ {
friend class WaitREGACKPacketList; friend class WaitREGACKPacketList;
public: public:
waitREGACKPacket(MQTTSNPacket* packet, uint16_t REGACKMsgId); waitREGACKPacket(MQTTSNPacket* packet, uint16_t REGACKMsgId);
~waitREGACKPacket(); ~waitREGACKPacket();
private: private:
uint16_t _msgId; uint16_t _msgId;
MQTTSNPacket* _packet; MQTTSNPacket* _packet;
waitREGACKPacket* _next; waitREGACKPacket* _next;
waitREGACKPacket* _prev; waitREGACKPacket* _prev;
}; };
/*===================================== /*=====================================
@@ -199,151 +134,176 @@ private:
class WaitREGACKPacketList class WaitREGACKPacketList
{ {
public: public:
WaitREGACKPacketList(); WaitREGACKPacketList();
~WaitREGACKPacketList(); ~WaitREGACKPacketList();
int setPacket(MQTTSNPacket* packet, uint16_t REGACKMsgId); int setPacket(MQTTSNPacket* packet, uint16_t REGACKMsgId);
MQTTSNPacket* getPacket(uint16_t REGACKMsgId); MQTTSNPacket* getPacket(uint16_t REGACKMsgId);
void erase(uint16_t REGACKMsgId); void erase(uint16_t REGACKMsgId);
uint8_t getCount(void);
private: private:
waitREGACKPacket* _first; uint8_t _cnt;
waitREGACKPacket* _end; waitREGACKPacket* _first;
waitREGACKPacket* _end;
}; };
/*===================================== /*=====================================
Class Client Class Client
=====================================*/ =====================================*/
#define MQTTSN_CLIENTID_LENGTH 23 typedef enum
{
Cstat_Free = 0,
Cstat_Disconnected,
Cstat_TryConnecting,
Cstat_Connecting,
Cstat_Active,
Cstat_Asleep,
Cstat_Awake,
Cstat_Lost
} ClientStatus;
typedef enum typedef enum
{ {
Cstat_Disconnected = 0, Cstat_TryConnecting, Cstat_Connecting, Cstat_Active, Cstat_Asleep, Cstat_Awake, Cstat_Lost Ctype_Normal = 0,
} ClientStatus; Ctype_Forwarded,
Ctype_QoS_1,
Ctype_Aggregated,
Ctype_Proxy,
Ctype_Aggregater
} ClientType;
class Forwarder;
class Client class Client
{ {
friend class ClientList; friend class ClientList;
friend class ClientsPool;
public: public:
Client(bool secure = false); Client();
Client(uint8_t maxInflightMessages, bool secure); ~Client();
~Client();
Connect* getConnectData(void); Connect* getConnectData(void);
uint16_t getWaitedPubTopicId(uint16_t msgId); TopicIdMapElement* getWaitedPubTopicId(uint16_t msgId);
uint16_t getWaitedSubTopicId(uint16_t msgId); TopicIdMapElement* getWaitedSubTopicId(uint16_t msgId);
MQTTSNPacket* getClientSleepPacket(); MQTTGWPacket* getClientSleepPacket(void);
WaitREGACKPacketList* getWaitREGACKPacketList(void); void deleteFirstClientSleepPacket(void);
void eraseWaitedPubTopicId(uint16_t msgId); MQTTSNPacket* getProxyPacket(void);
void eraseWaitedSubTopicId(uint16_t msgId); void deleteFirstProxyPacket(void);
void clearWaitedPubTopicId(void); WaitREGACKPacketList* getWaitREGACKPacketList(void);
void clearWaitedSubTopicId(void);
void setClientSleepPacket(MQTTSNPacket*); void eraseWaitedPubTopicId(uint16_t msgId);
void setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); void eraseWaitedSubTopicId(uint16_t msgId);
void setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type); void clearWaitedPubTopicId(void);
void clearWaitedSubTopicId(void);
bool checkTimeover(void); int setClientSleepPacket(MQTTGWPacket*);
void updateStatus(MQTTSNPacket*); int setProxyPacket(MQTTSNPacket* packet);
void updateStatus(ClientStatus); void setWaitedPubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic);
void connectSended(void); void setWaitedSubTopicId(uint16_t msgId, uint16_t topicId, MQTTSN_topicid* topic);
void connackSended(int rc);
void disconnected(void);
bool isConnectSendable(void);
uint16_t getNextPacketId(void); bool checkTimeover(void);
uint8_t getNextSnMsgId(void); void updateStatus(MQTTSNPacket*);
Topics* getTopics(void); void updateStatus(ClientStatus);
void setTopics(Topics* topics); void connectSended(void);
void setKeepAlive(MQTTSNPacket* packet); void connackSended(int rc);
void disconnected(void);
bool isConnectSendable(void);
void tryConnect(void);
ClientStatus getClientStatus(void);
SensorNetAddress* getSensorNetAddress(void); uint16_t getNextPacketId(void);
Network* getNetwork(void); uint8_t getNextSnMsgId(void);
void setClientAddress(SensorNetAddress* sensorNetAddr); Topics* getTopics(void);
void setSensorNetType(bool stable); void setTopics(Topics* topics);
void setKeepAlive(MQTTSNPacket* packet);
void setClientId(MQTTSNString id); SensorNetAddress* getSensorNetAddress(void);
void setWillTopic(MQTTSNString willTopic); Network* getNetwork(void);
void setWillMsg(MQTTSNString willmsg); void setClientAddress(SensorNetAddress* sensorNetAddr);
char* getClientId(void); void setSensorNetType(bool stable);
char* getWillTopic(void);
char* getWillMsg(void);
const char* getStatus(void);
void setWaitWillMsgFlg(bool);
void setSessionStatus(bool); // true: clean session
bool erasable(void);
bool isDisconnect(void); Forwarder* getForwarder(void);
bool isActive(void); void setForwarder(Forwarder* forwader);
bool isSleep(void);
bool isSecureNetwork(void);
bool isSensorNetStable(void);
bool isWaitWillMsg(void);
Client* getNextClient(void); void setAdapterType(AdapterType type);
Client* getOTAClient(void); void setQoSm1(void);
void setOTAClient(Client* cl); void setAggregated(void);
bool isQoSm1Proxy(void);
bool isForwarded(void);
bool isAggregated(void);
bool isAggregater(void);
bool isQoSm1(void);
bool isAdapter(void);
void setClientId(MQTTSNString id);
void setWillTopic(MQTTSNString willTopic);
void setWillMsg(MQTTSNString willmsg);
char* getClientId(void);
char* getWillTopic(void);
char* getWillMsg(void);
const char* getStatus(void);
void setWaitWillMsgFlg(bool);
void setSessionStatus(bool); // true: clean session
bool erasable(void);
bool isDisconnect(void);
bool isConnecting(void);
bool isActive(void);
bool isSleep(void);
bool isAwake(void);
bool isSecureNetwork(void);
bool isSensorNetStable(void);
bool isWaitWillMsg(void);
bool isCleanSession(void);
void holdPingRequest(void);
void resetPingRequest(void);
bool isHoldPingReqest(void);
Client* getNextClient(void);
private: private:
PacketQue<MQTTSNPacket> _clientSleepPacketQue; PacketQue<MQTTGWPacket> _clientSleepPacketQue;
WaitREGACKPacketList _waitREGACKList; PacketQue<MQTTSNPacket> _proxyPacketQue;
Topics* _topics; WaitREGACKPacketList _waitREGACKList;
TopicIdMap _waitedPubTopicIdMap;
TopicIdMap _waitedSubTopicIdMap;
Connect _connectData; Topics* _topics;
MQTTSNPacket* _connAck; TopicIdMap _waitedPubTopicIdMap;
TopicIdMap _waitedSubTopicIdMap;
char* _clientId; Connect _connectData;
char* _willTopic; MQTTSNPacket* _connAck;
char* _willMsg;
Timer _keepAliveTimer; char* _clientId;
uint32_t _keepAliveMsec; char* _willTopic;
char* _willMsg;
ClientStatus _status; bool _holdPingRequest;
bool _waitWillMsgFlg;
uint16_t _packetId; Timer _keepAliveTimer;
uint8_t _snMsgId; uint32_t _keepAliveMsec;
Network* _network; // Broker ClientStatus _status;
bool _secureNetwork; // SSL bool _waitWillMsgFlg;
bool _sensorNetype; // false: unstable network like a G3
SensorNetAddress _sensorNetAddr;
bool _sessionStatus; uint16_t _packetId;
uint8_t _snMsgId;
Client* _nextClient; Network* _network; // Broker
Client* _prevClient; bool _secureNetwork; // SSL
Client* _otaClient; bool _sensorNetype; // false: unstable network like a G3
}; SensorNetAddress _sensorNetAddr;
/*===================================== Forwarder* _forwarder;
Class ClientList ClientType _clientType;
=====================================*/
class ClientList bool _sessionStatus;
{ bool _hasPredefTopic;
public:
ClientList(); Client* _nextClient;
~ClientList(); Client* _prevClient;
bool authorize(const char* fileName);
void erase(Client*);
Client* getClient(SensorNetAddress* addr);
Client* getClient(uint8_t* clientId);
Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine,
bool secure);
uint16_t getClientCount(void);
Client* getClient(void);
bool isAuthorized();
private:
Client* _firstClient;
Client* _endClient;
Mutex _mutex;
uint16_t _clientCnt;
bool _authorize;
}; };
} }

View File

@@ -0,0 +1,517 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
* Tieto Poland Sp. z o.o. - Gateway improvements
**************************************************************************************/
#include "MQTTSNGWClientList.h"
#include "MQTTSNGateway.h"
#include <string.h>
#include <string>
using namespace MQTTSNGW;
char* currentDateTime(void);
/*=====================================
Class ClientList
=====================================*/
const char* common_topic = "*";
ClientList::ClientList(Gateway* gw)
{
_clientCnt = 0;
_authorize = false;
_firstClient = nullptr;
_endClient = nullptr;
_clientsPool = new ClientsPool();
_gateway = gw;
}
ClientList::~ClientList()
{
_mutex.lock();
Client* cl = _firstClient;
Client* ncl;
while (cl != nullptr)
{
ncl = cl->_nextClient;
delete cl;
cl = ncl;
};
if (_clientsPool)
{
delete _clientsPool;
}
_mutex.unlock();
}
void ClientList::initialize(bool aggregate)
{
_maxClients = _gateway->getGWParams()->maxClients;
_clientsPool->allocate(_gateway->getGWParams()->maxClients);
if (_gateway->getGWParams()->clientAuthentication)
{
int type = TRANSPEARENT_TYPE;
if (aggregate)
{
type = AGGREGATER_TYPE;
}
setClientList(type);
_authorize = true;
}
if (_gateway->getGWParams()->predefinedTopic)
{
setPredefinedTopics(aggregate);
}
}
void ClientList::setClientList(int type)
{
if (!createList(_gateway->getGWParams()->clientListName, type))
{
throw EXCEPTION("ClientList::setClientList Client list not found!", 0);
}
}
void ClientList::setPredefinedTopics(bool aggrecate)
{
if (!readPredefinedList(_gateway->getGWParams()->predefinedTopicFileName, aggrecate))
{
throw EXCEPTION("ClientList::setPredefinedTopics PredefindTopic list not found!", 0);
}
}
/**
* Create ClientList from a client list file.
* @param File name of the client list
* @return true: Reject client connection that is not registered in the client list
*
* File format is:
* Lines bigning with # are comment line.
* ClientId, SensorNetAddress, "unstableLine", "secureConnection"
* in case of UDP, SensorNetAddress format is IPAddress:portNo.
* if the SensorNetwork is not stable, write unstableLine.
* if BrokerConnection is SSL, write secureConnection.
* if the client send PUBLISH QoS-1, QoS-1 is required.
*
* Ex:
* #Client List
* ClientId1,192.168.10.10:11200
* ClientID2,192.168.50.200:35000,unstableLine
* ClientID3,192.168.200.50:40000,secureConnection
* ClientID4,192.168.200.51:41000,unstableLine,secureConnection
* ClientID5,192.168.200.51:41000,unstableLine,secureConnection,QoS-1
*/
bool ClientList::createList(const char* fileName, int type)
{
FILE* fp;
char buf[MAX_CLIENTID_LENGTH + 256];
size_t pos;
bool secure;
bool stable;
bool qos_1;
bool forwarder;
bool rc = false;
SensorNetAddress netAddr;
MQTTSNString clientId = MQTTSNString_initializer;
if ((fp = fopen(fileName, "r")) != 0)
{
while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0)
{
if (*buf == '#')
{
continue;
}
string data = string(buf);
while ((pos = data.find_first_of("  \t\n")) != string::npos)
{
data.erase(pos, 1);
}
if (data.empty())
{
continue;
}
pos = data.find_first_of(",");
string id = data.substr(0, pos);
clientId.cstring = strdup(id.c_str());
string addr = data.substr(pos + 1);
if (netAddr.setAddress(&addr) == 0)
{
qos_1 = (data.find("QoS-1") != string::npos);
forwarder = (data.find("forwarder") != string::npos);
secure = (data.find("secureConnection") != string::npos);
stable = !(data.find("unstableLine") != string::npos);
if ((qos_1 && type == QOSM1PROXY_TYPE) || (!qos_1 && type == AGGREGATER_TYPE))
{
createClient(&netAddr, &clientId, stable, secure, type);
}
else if (forwarder && type == FORWARDER_TYPE)
{
_gateway->getAdapterManager()->getForwarderList()->addForwarder(&netAddr, &clientId);
}
else if (type == TRANSPEARENT_TYPE)
{
createClient(&netAddr, &clientId, stable, secure, type);
}
}
else
{
WRITELOG("Invalid address %s\n", data.c_str());
rc = false;
}
free(clientId.cstring);
}
fclose(fp);
rc = true;
}
return rc;
}
bool ClientList::readPredefinedList(const char* fileName, bool aggregate)
{
FILE* fp;
char buf[MAX_CLIENTID_LENGTH + 256];
size_t pos0, pos1;
MQTTSNString clientId = MQTTSNString_initializer;
;
bool rc = false;
if ((fp = fopen(fileName, "r")) != 0)
{
while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0)
{
if (*buf == '#')
{
continue;
}
string data = string(buf);
while ((pos0 = data.find_first_of("  \t\n")) != string::npos)
{
data.erase(pos0, 1);
}
if (data.empty())
{
continue;
}
pos0 = data.find_first_of(",");
pos1 = data.find(",", pos0 + 1);
string id = data.substr(0, pos0);
clientId.cstring = strdup(id.c_str());
string topicName = data.substr(pos0 + 1, pos1 - pos0 - 1);
uint16_t topicID = stoul(data.substr(pos1 + 1));
createPredefinedTopic(&clientId, topicName, topicID, aggregate);
free(clientId.cstring);
}
fclose(fp);
rc = true;
}
else
{
WRITELOG("ClientList can not open the Predefined Topic List. %s\n", fileName);
return false;
}
return rc;
}
void ClientList::erase(Client*& client)
{
if (!_authorize && client->erasable())
{
_mutex.lock();
Client* prev = client->_prevClient;
Client* next = client->_nextClient;
if (prev)
{
prev->_nextClient = next;
}
else
{
_firstClient = next;
}
if (next)
{
next->_prevClient = prev;
}
else
{
_endClient = prev;
}
_clientCnt--;
Forwarder* fwd = client->getForwarder();
if (fwd)
{
fwd->eraseClient(client);
}
delete client;
client = nullptr;
_mutex.unlock();
}
}
Client* ClientList::getClient(SensorNetAddress* addr)
{
if (addr)
{
_mutex.lock();
Client* client = _firstClient;
while (client != nullptr)
{
if (client->getSensorNetAddress()->isMatch(addr))
{
_mutex.unlock();
return client;
}
client = client->_nextClient;
}
_mutex.unlock();
}
return 0;
}
Client* ClientList::getClient(int index)
{
Client* client = _firstClient;
int p = 0;
while (client != nullptr)
{
if (p == index)
{
return client;
}
else
{
client = client->_nextClient;
p++;
}
}
return nullptr;
}
Client* ClientList::getClient(MQTTSNString* clientId)
{
_mutex.lock();
Client* client = _firstClient;
const char* clID = clientId->cstring;
if (clID == nullptr)
{
clID = clientId->lenstring.data;
}
while (client != nullptr)
{
if (strncmp((const char*) client->getClientId(), clID, MQTTSNstrlen(*clientId)) == 0)
{
_mutex.unlock();
return client;
}
client = client->_nextClient;
}
_mutex.unlock();
return 0;
}
Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, int type)
{
return createClient(addr, clientId, false, false, type);
}
Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type)
{
Client* client = getClient(addr);
if (client)
{
return client;
}
/* acquire a free client */
client = _clientsPool->getClient();
if (!client)
{
WRITELOG("%s%sMax number of Clients%s\n", currentDateTime(),
ERRMSG_HEADER, ERRMSG_FOOTER);
return nullptr;
}
client->disconnected();
if (addr)
{
client->setClientAddress(addr);
}
client->setSensorNetType(unstableLine);
if (MQTTSNstrlen(*clientId))
{
client->setClientId(*clientId);
}
else
{
MQTTSNString dummyId MQTTSNString_initializer;
dummyId.cstring = strdup("");
client->setClientId(dummyId);
free(dummyId.cstring);
}
if (type == AGGREGATER_TYPE)
{
client->setAggregated();
}
else if (type == QOSM1PROXY_TYPE)
{
client->setQoSm1();
}
client->getNetwork()->setSecure(secure);
_mutex.lock();
/* add the list */
if (_firstClient == nullptr)
{
_firstClient = client;
_endClient = client;
}
else
{
_endClient->_nextClient = client;
client->_prevClient = _endClient;
_endClient = client;
}
_clientCnt++;
_mutex.unlock();
return client;
}
Client* ClientList::createPredefinedTopic(MQTTSNString* clientId, string topicName, uint16_t topicId, bool aggregate)
{
if (topicId == 0)
{
WRITELOG("Invalid TopicId. Predefined Topic %s, TopicId is 0. \n", topicName.c_str());
return nullptr;
}
if (strcmp(clientId->cstring, common_topic) == 0)
{
_gateway->getTopics()->add((const char*) topicName.c_str(), topicId);
return nullptr;
}
else
{
Client *client = getClient(clientId);
if (_authorize && client == nullptr)
{
return nullptr;
}
client = createClient(NULL, clientId, aggregate);
if (client == nullptr)
{
return nullptr;
}
// create Topic & Add it
client->getTopics()->add((const char*) topicName.c_str(), topicId);
client->_hasPredefTopic = true;
return client;
}
}
uint16_t ClientList::getClientCount()
{
return _clientCnt;
}
bool ClientList::isAuthorized()
{
return _authorize;
}
/******************************
* Class ClientsPool
******************************/
ClientsPool::ClientsPool()
{
_clientCnt = 0;
_firstClient = nullptr;
_endClient = nullptr;
}
ClientsPool::~ClientsPool()
{
Client* cl = _firstClient;
Client* ncl;
while (cl != nullptr)
{
ncl = cl->_nextClient;
delete cl;
cl = ncl;
};
}
void ClientsPool::allocate(int maxClients)
{
Client* cl = nullptr;
_firstClient = new Client();
for (int i = 0; i < maxClients; i++)
{
if ((cl = new Client()) == nullptr)
{
throw Exception("ClientsPool::Can't allocate max number of clients\n", 0);
}
cl->_nextClient = _firstClient;
_firstClient = cl;
_clientCnt++;
}
}
Client* ClientsPool::getClient(void)
{
Client *cl = nullptr;
while (_firstClient != nullptr)
{
cl = _firstClient;
_firstClient = cl->_nextClient;
cl->_nextClient = nullptr;
_clientCnt--;
break;
}
return cl;
}
void ClientsPool::setClient(Client* client)
{
if (client)
{
client->_nextClient = _firstClient;
_firstClient = client;
_clientCnt++;
}
}

View File

@@ -0,0 +1,92 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
* Tieto Poland Sp. z o.o. - Gateway improvements
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_
#define MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_
#include "MQTTSNGWClient.h"
#include "MQTTSNGateway.h"
namespace MQTTSNGW
{
#define TRANSPEARENT_TYPE 0
#define QOSM1PROXY_TYPE 1
#define AGGREGATER_TYPE 2
#define FORWARDER_TYPE 3
class Client;
/*=====================================
Class ClientsPool
=====================================*/
class ClientsPool
{
public:
ClientsPool();
~ClientsPool();
void allocate(int maxClients);
Client* getClient(void);
void setClient(Client* client);
private:
Client* _firstClient;
Client* _endClient;
int _clientCnt;
};
/*=====================================
Class ClientList
=====================================*/
class ClientList
{
public:
ClientList(Gateway* gw);
~ClientList();
void initialize(bool aggregate);
void setClientList(int type);
void setPredefinedTopics(bool aggregate);
void erase(Client*&);
Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId,
int type);
Client* createClient(SensorNetAddress* addr, MQTTSNString* clientId,
bool unstableLine, bool secure, int type);
bool createList(const char* fileName, int type);
Client* getClient(SensorNetAddress* addr);
Client* getClient(MQTTSNString* clientId);
Client* getClient(int index);
uint16_t getClientCount(void);
Client* getClient(void);
bool isAuthorized();
private:
bool readPredefinedList(const char* fileName, bool _aggregate);
ClientsPool* _clientsPool;
Gateway* _gateway;
Client* createPredefinedTopic(MQTTSNString* clientId, string topicName,
uint16_t toipcId, bool _aggregate);
Client* _firstClient;
Client* _endClient;
Mutex _mutex;
uint16_t _clientCnt;
uint16_t _maxClients;
bool _authorize { false };
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWCLIENTLIST_H_ */

View File

@@ -15,193 +15,319 @@
**************************************************************************************/ **************************************************************************************/
#include "MQTTSNGWClientRecvTask.h" #include "MQTTSNGWClientRecvTask.h"
#include "MQTTSNGateway.h" #include "MQTTSNPacket.h"
#include <string.h> #include "MQTTSNGWQoSm1Proxy.h"
#include "MQTTSNGWEncapsulatedPacket.h"
#include <cstring>
using namespace MQTTSNGW;
char* currentDateTime(void); char* currentDateTime(void);
/*===================================== /*=====================================
Class ClientRecvTask Class ClientRecvTask
=====================================*/ =====================================*/
ClientRecvTask::ClientRecvTask(Gateway* gateway) ClientRecvTask::ClientRecvTask(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
_gateway->attach((Thread*)this); _gateway->attach((Thread*) this);
_sensorNetwork = _gateway->getSensorNetwork(); _sensorNetwork = _gateway->getSensorNetwork();
setTaskName("ClientRecvTask");
} }
ClientRecvTask::~ClientRecvTask() ClientRecvTask::~ClientRecvTask()
{ {
} }
/**
* Initialize SensorNetwork
*/
void ClientRecvTask::initialize(int argc, char** argv) void ClientRecvTask::initialize(int argc, char** argv)
{ {
if ( _sensorNetwork->initialize() < 0 )
{
throw Exception(" Can't open the sensor network.\n");
}
} }
/* /*
* Receive a packet from clients via sensor netwwork * Receive a packet from clients via sensor netwwork
* and generate a event to execute the packet handling procedure * and creats a event to execute the packet handling procedure
* of MQTTSNPacketHandlingTask. * of MQTTSNPacketHandlingTask.
*/ */
void ClientRecvTask::run() void ClientRecvTask::run()
{ {
Event* ev = 0; Event* ev = nullptr;
Client* client = 0; AdapterManager* adpMgr = _gateway->getAdapterManager();
char buf[128]; QoSm1Proxy* qosm1Proxy = adpMgr->getQoSm1Proxy();
int clientType = adpMgr->isAggregaterActive() ? AGGREGATER_TYPE : TRANSPEARENT_TYPE;
ClientList* clientList = _gateway->getClientList();
EventQue* packetEventQue = _gateway->getPacketEventQue();
EventQue* clientsendQue = _gateway->getClientSendQue();
while (true) char buf[128];
{
MQTTSNPacket* packet = new MQTTSNPacket();
int packetLen = packet->recv(_sensorNetwork);
if (CHK_SIGINT) while (true)
{ {
WRITELOG("%s ClientRecvTask stopped.\n", currentDateTime()); Client* client = nullptr;
delete packet; Forwarder* fwd = nullptr;
return; WirelessNodeId nodeId;
}
if (packetLen < 2 ) MQTTSNPacket* packet = new MQTTSNPacket();
{ int packetLen = packet->recv(_sensorNetwork);
delete packet;
continue;
}
if ( packet->getType() <= MQTTSN_ADVERTISE || packet->getType() == MQTTSN_GWINFO ) if (CHK_SIGINT)
{ {
delete packet; WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName());
continue; delete packet;
} return;
}
if ( packet->getType() == MQTTSN_SEARCHGW ) if (packetLen < 2)
{ {
/* write log and post Event */ delete packet;
log(0, packet); continue;
ev = new Event(); }
ev->setBrodcastEvent(packet);
_gateway->getPacketEventQue()->post(ev);
continue;
}
/* get client from the ClientList of Gateway by sensorNetAddress. */ if (packet->getType() <= MQTTSN_ADVERTISE || packet->getType() == MQTTSN_GWINFO)
client = _gateway->getClientList()->getClient(_sensorNetwork->getSenderAddress()); {
delete packet;
continue;
}
if ( client ) if (packet->getType() == MQTTSN_SEARCHGW)
{ {
/* write log and post Event */ /* write log and post Event */
log(client, packet); log(0, packet, 0);
ev = new Event(); ev = new Event();
ev->setClientRecvEvent(client,packet); ev->setBrodcastEvent(packet);
_gateway->getPacketEventQue()->post(ev); packetEventQue->post(ev);
} continue;
else }
{
/* new client */
if (packet->getType() == MQTTSN_CONNECT)
{
MQTTSNPacket_connectData data;
memset(&data, 0, sizeof(MQTTSNPacket_connectData));
if ( !packet->getCONNECT(&data) )
{
log(0, packet, &data.clientID);
WRITELOG("%s CONNECT message form %s is incorrect.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER);
delete packet;
continue;
}
/* create a client */ SensorNetAddress senderAddr = *_gateway->getSensorNetwork()->getSenderAddress();
client = _gateway->getClientList()->createClient(_sensorNetwork->getSenderAddress(), &data.clientID, false, false);
log(client, packet, &data.clientID);
if (!client)
{
WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER);
delete packet;
continue;
}
/* set sensorNetAddress & post Event */ if (packet->getType() == MQTTSN_ENCAPSULATED)
client->setClientAddress(_sensorNetwork->getSenderAddress()); {
ev = new Event(); fwd = _gateway->getAdapterManager()->getForwarderList()->getForwarder(&senderAddr);
ev->setClientRecvEvent(client, packet);
_gateway->getPacketEventQue()->post(ev); if (fwd != nullptr)
} {
else MQTTSNString fwdName = MQTTSNString_initializer;
{ fwdName.cstring = const_cast<char *>(fwd->getName());
log(client, packet); log(0, packet, &fwdName);
delete packet;
/* Send DISCONNECT */ /* get the packet from the encapsulation message */
SensorNetAddress* addr = new SensorNetAddress(); MQTTSNGWEncapsulatedPacket encap;
*addr = (*_sensorNetwork->getSenderAddress()); encap.desirialize(packet->getPacketData(), packet->getPacketLength());
packet = new MQTTSNPacket(); nodeId.setId(encap.getWirelessNodeId());
packet->setDISCONNECT(0); client = fwd->getClient(&nodeId);
ev = new Event(); packet = encap.getMQTTSNPacket();
ev->setClientSendEvent(addr, packet); }
_gateway->getClientSendQue()->post(ev); }
continue; else
} {
} /* Check the client belonging to QoS-1Proxy ? */
}
if (qosm1Proxy->isActive())
{
const char *clientName = qosm1Proxy->getClientId(&senderAddr);
if (clientName != nullptr)
{
client = qosm1Proxy->getClient();
if (!packet->isQoSMinusPUBLISH())
{
log(clientName, packet);
WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n",
ERRMSG_HEADER, clientName, senderAddr.sprint(buf), ERRMSG_FOOTER);
delete packet;
continue;
}
}
}
if (client == nullptr)
{
client = _gateway->getClientList()->getClient(&senderAddr);
}
}
if (client != nullptr)
{
log(client, packet, 0);
if (client->isDisconnect() && packet->getType() != MQTTSN_CONNECT)
{
WRITELOG("%s MQTTSNGWClientRecvTask %s is not connecting.%s\n",
ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER);
/* send DISCONNECT to the client, if it is not connected */
MQTTSNPacket* snPacket = new MQTTSNPacket();
snPacket->setDISCONNECT(0);
ev = new Event();
ev->setClientSendEvent(client, snPacket);
clientsendQue->post(ev);
delete packet;
continue;
}
else
{
ev = new Event();
ev->setClientRecvEvent(client, packet);
packetEventQue->post(ev);
}
}
else
{
/* new client */
if (packet->getType() == MQTTSN_CONNECT)
{
MQTTSNPacket_connectData data;
memset(&data, 0, sizeof(MQTTSNPacket_connectData));
if (!packet->getCONNECT(&data))
{
log(0, packet, &data.clientID);
WRITELOG("%s CONNECT message form %s is incorrect.%s\n",
ERRMSG_HEADER, senderAddr.sprint(buf),
ERRMSG_FOOTER);
delete packet;
continue;
}
client = clientList->getClient(&data.clientID);
if (fwd != nullptr)
{
if (client == nullptr)
{
/* create a new client */
client = clientList->createClient(0, &data.clientID, clientType);
}
/* Add to a forwarded client list of forwarder. */
fwd->addClient(client, &nodeId);
}
else
{
if (client)
{
/* Authentication is not required */
if (_gateway->getGWParams()->clientAuthentication == false)
{
client->setClientAddress(&senderAddr);
}
}
else
{
/* create a new client */
client = clientList->createClient(&senderAddr, &data.clientID, clientType);
}
}
log(client, packet, &data.clientID);
if (client == nullptr)
{
WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n",
ERRMSG_HEADER, senderAddr.sprint(buf),
ERRMSG_FOOTER);
delete packet;
continue;
}
/* post Client RecvEvent */
ev = new Event();
ev->setClientRecvEvent(client, packet);
packetEventQue->post(ev);
}
else
{
log(client, packet, 0);
if (packet->getType() == MQTTSN_ENCAPSULATED)
{
WRITELOG(
"%s MQTTSNGWClientRecvTask Forwarder(%s) is not declared by ClientList file. message has been discarded.%s\n",
ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf),
ERRMSG_FOOTER);
}
else
{
WRITELOG("%s MQTTSNGWClientRecvTask Client(%s) is not connecting. message has been discarded.%s\n",
ERRMSG_HEADER, senderAddr.sprint(buf),
ERRMSG_FOOTER);
}
delete packet;
}
}
}
} }
void ClientRecvTask::log(Client* client, MQTTSNPacket* packet, MQTTSNString* id) void ClientRecvTask::log(Client* client, MQTTSNPacket* packet, MQTTSNString* id)
{ {
char pbuf[SIZE_OF_LOG_PACKET * 3]; const char* clientId;
const char* clientId; char cstr[MAX_CLIENTID_LENGTH + 1];
char cstr[MAX_CLIENTID_LENGTH + 1];
char msgId[6];
if ( id ) if (id)
{ {
memset((void*)cstr, 0, id->lenstring.len + 1); if (id->cstring)
strncpy(cstr, id->lenstring.data, id->lenstring.len) ; {
clientId = cstr; strncpy(cstr, id->cstring, strlen(id->cstring));
} clientId = cstr;
else if ( client ) }
{ else
clientId = client->getClientId(); {
} memset((void*) cstr, 0, id->lenstring.len + 1);
else strncpy(cstr, id->lenstring.data, id->lenstring.len);
{ clientId = cstr;
clientId = UNKNOWNCL; }
} }
else if (client)
{
clientId = client->getClientId();
}
else
{
clientId = UNKNOWNCL;
}
switch (packet->getType()) log(clientId, packet);
{ }
case MQTTSN_SEARCHGW:
case MQTTSN_PINGREQ: void ClientRecvTask::log(const char* clientId, MQTTSNPacket* packet)
WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, CLIENT, packet->print(pbuf)); {
break; char pbuf[ SIZE_OF_LOG_PACKET * 3 + 1];
case MQTTSN_CONNECT: char msgId[6];
WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf));
break; switch (packet->getType())
case MQTTSN_DISCONNECT: {
case MQTTSN_WILLTOPICUPD: case MQTTSN_SEARCHGW:
case MQTTSN_WILLMSGUPD: WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(),
case MQTTSN_WILLTOPIC: LEFTARROW, CLIENT, packet->print(pbuf));
case MQTTSN_WILLMSG: break;
WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); case MQTTSN_CONNECT:
break; case MQTTSN_PINGREQ:
case MQTTSN_PUBLISH: WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(),
case MQTTSN_REGISTER: LEFTARROW, clientId, packet->print(pbuf));
case MQTTSN_SUBSCRIBE: break;
case MQTTSN_UNSUBSCRIBE: case MQTTSN_DISCONNECT:
WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); case MQTTSN_WILLTOPICUPD:
break; case MQTTSN_WILLMSGUPD:
case MQTTSN_REGACK: case MQTTSN_WILLTOPIC:
case MQTTSN_PUBACK: case MQTTSN_WILLMSG:
case MQTTSN_PUBREC: WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf));
case MQTTSN_PUBREL: break;
case MQTTSN_PUBCOMP: case MQTTSN_PUBLISH:
WRITELOG(FORMAT_G_MSGID_G_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); case MQTTSN_REGISTER:
break; case MQTTSN_SUBSCRIBE:
default: case MQTTSN_UNSUBSCRIBE:
WRITELOG(FORMAT_W_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId,
break; packet->print(pbuf));
} break;
case MQTTSN_REGACK:
case MQTTSN_PUBACK:
case MQTTSN_PUBREC:
case MQTTSN_PUBREL:
case MQTTSN_PUBCOMP:
WRITELOG(FORMAT_G_MSGID_G_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId,
packet->print(pbuf));
break;
case MQTTSN_ENCAPSULATED:
WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf));
break;
default:
WRITELOG(FORMAT_W_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf));
break;
}
} }

View File

@@ -21,24 +21,27 @@
namespace MQTTSNGW namespace MQTTSNGW
{ {
class AdapterManager;
/*===================================== /*=====================================
Class ClientRecvTask Class ClientRecvTask
=====================================*/ =====================================*/
class ClientRecvTask:public Thread class ClientRecvTask: public Thread
{ {
MAGIC_WORD_FOR_THREAD; MAGIC_WORD_FOR_THREAD;
friend AdapterManager;
public: public:
ClientRecvTask(Gateway*); ClientRecvTask(Gateway*);
~ClientRecvTask(); ~ClientRecvTask(void);
virtual void initialize(int argc, char** argv); virtual void initialize(int argc, char** argv);
void run(); void run(void);
private: private:
void log(Client*, MQTTSNPacket*, MQTTSNString* id = 0); void log(Client*, MQTTSNPacket*, MQTTSNString* id);
void log(const char* clientId, MQTTSNPacket* packet);
Gateway* _gateway; Gateway* _gateway;
SensorNetwork* _sensorNetwork; SensorNetwork* _sensorNetwork;
}; };
} }

View File

@@ -15,8 +15,10 @@
**************************************************************************************/ **************************************************************************************/
#include "MQTTSNGWClientSendTask.h" #include "MQTTSNGWClientSendTask.h"
#include "MQTTSNGWPacket.h" #include "MQTTSNGWPacket.h"
#include "MQTTSNGWPacket.h"
#include "MQTTSNGateway.h" #include "MQTTSNGateway.h"
#include "MQTTSNGWEncapsulatedPacket.h"
#include "MQTTSNGWQoSm1Proxy.h"
#include <errno.h>
using namespace MQTTSNGW; using namespace MQTTSNGW;
using namespace std; using namespace std;
@@ -26,96 +28,110 @@ char* currentDateTime(void);
=====================================*/ =====================================*/
ClientSendTask::ClientSendTask(Gateway* gateway) ClientSendTask::ClientSendTask(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
_gateway->attach((Thread*)this); _gateway->attach((Thread*) this);
_sensorNetwork = _gateway->getSensorNetwork(); _sensorNetwork = _gateway->getSensorNetwork();
setTaskName("ClientSendTask");
} }
ClientSendTask::~ClientSendTask() ClientSendTask::~ClientSendTask()
{ {
} }
void ClientSendTask::run() void ClientSendTask::run()
{ {
Client* client = 0; Client* client = nullptr;
MQTTSNPacket* packet = 0; MQTTSNPacket* packet = nullptr;
int rc = 0; AdapterManager* adpMgr = _gateway->getAdapterManager();
int rc = 0;
while (true) while (true)
{ {
Event* ev = _gateway->getClientSendQue()->wait(); Event* ev = _gateway->getClientSendQue()->wait();
if (ev->getEventType() == EtStop) if (ev->getEventType() == EtStop || _gateway->IsStopping())
{ {
WRITELOG("%s ClientSendTask stopped.\n", currentDateTime()); WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName());
delete ev; delete ev;
break; break;
} }
if (ev->getEventType() == EtClientSend)
{
client = ev->getClient();
packet = ev->getMQTTSNPacket();
log(client, packet);
rc = packet->unicast(_sensorNetwork, client->getSensorNetAddress());
}
else if (ev->getEventType() == EtBroadcast)
{
packet = ev->getMQTTSNPacket();
log(client, packet);
rc = packet->broadcast(_sensorNetwork);
}
else if (ev->getEventType() == EtSensornetSend)
{
packet = ev->getMQTTSNPacket();
log(client, packet);
rc = packet->unicast(_sensorNetwork, ev->getSensorNetAddress());
}
if ( rc < 0 ) if (ev->getEventType() == EtBroadcast)
{ {
WRITELOG("%s ClientSendTask can't send a packet to the client.\n", packet = ev->getMQTTSNPacket();
ERRMSG_HEADER, (client ? (const char*)client->getClientId() : UNKNOWNCL ), ERRMSG_FOOTER); log(client, packet);
}
delete ev; if (packet->broadcast(_sensorNetwork) < 0)
} {
WRITELOG("%s ClientSendTask can't multicast a packet Error=%d%s\n",
ERRMSG_HEADER, errno, ERRMSG_FOOTER);
}
}
else
{
if (ev->getEventType() == EtClientSend)
{
client = ev->getClient();
packet = ev->getMQTTSNPacket();
rc = adpMgr->unicastToClient(client, packet, this);
}
else if (ev->getEventType() == EtSensornetSend)
{
packet = ev->getMQTTSNPacket();
log(client, packet);
rc = packet->unicast(_sensorNetwork, ev->getSensorNetAddress());
}
if (rc < 0)
{
WRITELOG("%s ClientSendTask can't send a packet to the client %s. Error=%d%s\n",
ERRMSG_HEADER, (client ? (const char*) client->getClientId() : UNKNOWNCL),
errno, ERRMSG_FOOTER);
}
}
delete ev;
}
} }
void ClientSendTask::log(Client* client, MQTTSNPacket* packet) void ClientSendTask::log(Client* client, MQTTSNPacket* packet)
{ {
char pbuf[SIZE_OF_LOG_PACKET * 3]; char pbuf[SIZE_OF_LOG_PACKET * 3 + 1];
char msgId[6]; char msgId[6];
const char* clientId = client ? (const char*)client->getClientId() : UNKNOWNCL ; const char* clientId = client ? (const char*) client->getClientId() : UNKNOWNCL;
switch (packet->getType()) switch (packet->getType())
{ {
case MQTTSN_ADVERTISE: case MQTTSN_ADVERTISE:
case MQTTSN_GWINFO: case MQTTSN_GWINFO:
case MQTTSN_PINGRESP: WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW,
WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW, CLIENTS, packet->print(pbuf)); CLIENTS, packet->print(pbuf));
break; break;
case MQTTSN_CONNACK: case MQTTSN_CONNACK:
case MQTTSN_DISCONNECT: case MQTTSN_DISCONNECT:
case MQTTSN_WILLTOPICREQ: case MQTTSN_WILLTOPICREQ:
case MQTTSN_WILLMSGREQ: case MQTTSN_WILLMSGREQ:
case MQTTSN_WILLTOPICRESP: case MQTTSN_WILLTOPICRESP:
case MQTTSN_WILLMSGRESP: case MQTTSN_WILLMSGRESP:
WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW, clientId, packet->print(pbuf)); case MQTTSN_PINGRESP:
break; WRITELOG(FORMAT_Y_W_G, currentDateTime(), packet->getName(), RIGHTARROW, clientId, packet->print(pbuf));
case MQTTSN_REGISTER: break;
case MQTTSN_PUBLISH: case MQTTSN_REGISTER:
WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId, packet->print(pbuf)); case MQTTSN_PUBLISH:
break; WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId,
case MQTTSN_REGACK: packet->print(pbuf));
case MQTTSN_PUBACK: break;
case MQTTSN_PUBREC: case MQTTSN_REGACK:
case MQTTSN_PUBREL: case MQTTSN_PUBACK:
case MQTTSN_PUBCOMP: case MQTTSN_PUBREC:
case MQTTSN_SUBACK: case MQTTSN_PUBREL:
case MQTTSN_UNSUBACK: case MQTTSN_PUBCOMP:
WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId, packet->print(pbuf)); case MQTTSN_SUBACK:
break; case MQTTSN_UNSUBACK:
default: WRITELOG(FORMAT_W_MSGID_W_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), RIGHTARROW, clientId,
break; packet->print(pbuf));
} break;
default:
break;
}
} }

View File

@@ -21,23 +21,25 @@
namespace MQTTSNGW namespace MQTTSNGW
{ {
class AdapterManager;
/*===================================== /*=====================================
Class ClientSendTask Class ClientSendTask
=====================================*/ =====================================*/
class ClientSendTask: public Thread class ClientSendTask: public Thread
{ {
MAGIC_WORD_FOR_THREAD; MAGIC_WORD_FOR_THREAD;
friend AdapterManager;
public: public:
ClientSendTask(Gateway* gateway); ClientSendTask(Gateway* gateway);
~ClientSendTask(); ~ClientSendTask(void);
void run(); void run(void);
private: private:
void log(Client*, MQTTSNPacket*); void log(Client* client, MQTTSNPacket* packet);
Gateway* _gateway; Gateway* _gateway;
SensorNetwork* _sensorNetwork; SensorNetwork* _sensorNetwork;
}; };
} }

View File

@@ -1,5 +1,5 @@
/************************************************************************************** /**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi * Copyright (c) 2016, 2020 Tomoaki Yamaguchi and others
* *
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
@@ -28,7 +28,7 @@ using namespace MQTTSNGW;
=====================================*/ =====================================*/
MQTTSNConnectionHandler::MQTTSNConnectionHandler(Gateway* gateway) MQTTSNConnectionHandler::MQTTSNConnectionHandler(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
} }
MQTTSNConnectionHandler::~MQTTSNConnectionHandler() MQTTSNConnectionHandler::~MQTTSNConnectionHandler()
@@ -41,11 +41,11 @@ MQTTSNConnectionHandler::~MQTTSNConnectionHandler()
*/ */
void MQTTSNConnectionHandler::sendADVERTISE() void MQTTSNConnectionHandler::sendADVERTISE()
{ {
MQTTSNPacket* adv = new MQTTSNPacket(); MQTTSNPacket* adv = new MQTTSNPacket();
adv->setADVERTISE(_gateway->getGWParams()->gatewayId, _gateway->getGWParams()->keepAlive); adv->setADVERTISE(_gateway->getGWParams()->gatewayId, _gateway->getGWParams()->keepAlive);
Event* ev1 = new Event(); Event* ev1 = new Event();
ev1->setBrodcastEvent(adv); //broadcast ev1->setBrodcastEvent(adv); //broadcast
_gateway->getClientSendQue()->post(ev1); _gateway->getClientSendQue()->post(ev1);
} }
/* /*
@@ -53,14 +53,14 @@ void MQTTSNConnectionHandler::sendADVERTISE()
*/ */
void MQTTSNConnectionHandler::handleSearchgw(MQTTSNPacket* packet) void MQTTSNConnectionHandler::handleSearchgw(MQTTSNPacket* packet)
{ {
if (packet->getType() == MQTTSN_SEARCHGW) if (packet->getType() == MQTTSN_SEARCHGW)
{ {
MQTTSNPacket* gwinfo = new MQTTSNPacket(); MQTTSNPacket* gwinfo = new MQTTSNPacket();
gwinfo->setGWINFO(_gateway->getGWParams()->gatewayId); gwinfo->setGWINFO(_gateway->getGWParams()->gatewayId);
Event* ev1 = new Event(); Event* ev1 = new Event();
ev1->setBrodcastEvent(gwinfo); ev1->setBrodcastEvent(gwinfo);
_gateway->getClientSendQue()->post(ev1); _gateway->getClientSendQue()->post(ev1);
} }
} }
/* /*
@@ -68,72 +68,91 @@ void MQTTSNConnectionHandler::handleSearchgw(MQTTSNPacket* packet)
*/ */
void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet) void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet)
{ {
MQTTSNPacket_connectData data; MQTTSNPacket_connectData data;
if ( packet->getCONNECT(&data) == 0 ) if (packet->getCONNECT(&data) == 0)
{ {
return; return;
} }
/* clear ConnectData of Client */ /* return CONNACK when the client is sleeping */
Connect* connectData = client->getConnectData(); if (client->isSleep() || client->isAwake())
memset(connectData, 0, sizeof(Connect)); {
client->disconnected(); MQTTSNPacket* packet = new MQTTSNPacket();
packet->setCONNACK(MQTTSN_RC_ACCEPTED);
Event* ev = new Event();
ev->setClientSendEvent(client, packet);
_gateway->getClientSendQue()->post(ev);
Topics* topics = client->getTopics(); sendStoredPublish(client);
return;
}
/* CONNECT was not sent yet. prepare Connect data */ //* clear ConnectData of Client */
connectData->header.bits.type = CONNECT; Connect* connectData = client->getConnectData();
connectData->clientID = client->getClientId(); memset(connectData, 0, sizeof(Connect));
connectData->version = _gateway->getGWParams()->mqttVersion; if (!client->isAdapter())
connectData->keepAliveTimer = data.duration; {
connectData->flags.bits.will = data.willFlag; client->disconnected();
}
if ((const char*) _gateway->getGWParams()->loginId != 0 && (const char*) _gateway->getGWParams()->password != 0) Topics* topics = client->getTopics();
{
connectData->flags.bits.password = 1;
connectData->flags.bits.username = 1;
}
client->setSessionStatus(false); /* CONNECT was not sent yet. prepare Connect data */
if (data.cleansession) connectData->header.bits.type = CONNECT;
{ connectData->clientID = client->getClientId();
connectData->flags.bits.cleanstart = 1; connectData->version = _gateway->getGWParams()->mqttVersion;
/* reset the table of msgNo and TopicId pare */ connectData->keepAliveTimer = data.duration;
client->clearWaitedPubTopicId(); connectData->flags.bits.will = data.willFlag;
client->clearWaitedSubTopicId();
/* renew the TopicList */ if ((const char*) _gateway->getGWParams()->loginId != nullptr)
if (topics) {
{ connectData->flags.bits.username = 1;
delete topics; }
}
topics = new Topics();
client->setTopics(topics);
client->setSessionStatus(true);
}
if (data.willFlag) if ((const char*) _gateway->getGWParams()->password != 0)
{ {
/* create & send WILLTOPICREQ message to the client */ connectData->flags.bits.password = 1;
MQTTSNPacket* reqTopic = new MQTTSNPacket(); }
reqTopic->setWILLTOPICREQ();
Event* evwr = new Event();
evwr->setClientSendEvent(client, reqTopic);
/* Send WILLTOPICREQ to the client */ client->setSessionStatus(false);
_gateway->getClientSendQue()->post(evwr); if (data.cleansession)
} {
else connectData->flags.bits.cleanstart = 1;
{ /* reset the table of msgNo and TopicId pare */
client->clearWaitedPubTopicId();
client->clearWaitedSubTopicId();
/* CONNECT message was not qued in. /* renew the TopicList */
* create CONNECT message & send it to the broker */ if (topics)
MQTTGWPacket* mqMsg = new MQTTGWPacket(); {
mqMsg->setCONNECT(client->getConnectData(), (unsigned char*)_gateway->getGWParams()->loginId, (unsigned char*)_gateway->getGWParams()->password); topics->eraseNormal();
Event* ev1 = new Event(); ;
ev1->setBrokerSendEvent(client, mqMsg); }
_gateway->getBrokerSendQue()->post(ev1); client->setSessionStatus(true);
} }
if (data.willFlag)
{
/* create & send WILLTOPICREQ message to the client */
MQTTSNPacket* reqTopic = new MQTTSNPacket();
reqTopic->setWILLTOPICREQ();
Event* evwr = new Event();
evwr->setClientSendEvent(client, reqTopic);
/* Send WILLTOPICREQ to the client */
_gateway->getClientSendQue()->post(evwr);
}
else
{
/* CONNECT message was not qued in.
* create CONNECT message & send it to the broker */
MQTTGWPacket* mqMsg = new MQTTGWPacket();
mqMsg->setCONNECT(client->getConnectData(), (unsigned char*) _gateway->getGWParams()->loginId,
(unsigned char*) _gateway->getGWParams()->password);
Event* ev1 = new Event();
ev1->setBrokerSendEvent(client, mqMsg);
_gateway->getBrokerSendQue()->post(ev1);
}
} }
/* /*
@@ -141,29 +160,29 @@ void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet
*/ */
void MQTTSNConnectionHandler::handleWilltopic(Client* client, MQTTSNPacket* packet) void MQTTSNConnectionHandler::handleWilltopic(Client* client, MQTTSNPacket* packet)
{ {
int willQos; int willQos;
uint8_t willRetain; uint8_t willRetain;
MQTTSNString willTopic; MQTTSNString willTopic = MQTTSNString_initializer;
if ( packet->getWILLTOPIC(&willQos, &willRetain, &willTopic) == 0 ) if (packet->getWILLTOPIC(&willQos, &willRetain, &willTopic) == 0)
{ {
return; return;
} }
client->setWillTopic(willTopic); client->setWillTopic(willTopic);
Connect* connectData = client->getConnectData(); Connect* connectData = client->getConnectData();
/* add the connectData for MQTT CONNECT message */ /* add the connectData for MQTT CONNECT message */
connectData->willTopic = client->getWillTopic(); connectData->willTopic = client->getWillTopic();
connectData->flags.bits.willQoS = willQos; connectData->flags.bits.willQoS = willQos;
connectData->flags.bits.willRetain = willRetain; connectData->flags.bits.willRetain = willRetain;
/* Send WILLMSGREQ to the client */ /* Send WILLMSGREQ to the client */
client->setWaitWillMsgFlg(true); client->setWaitWillMsgFlg(true);
MQTTSNPacket* reqMsg = new MQTTSNPacket(); MQTTSNPacket* reqMsg = new MQTTSNPacket();
reqMsg->setWILLMSGREQ(); reqMsg->setWILLMSGREQ();
Event* evt = new Event(); Event* evt = new Event();
evt->setClientSendEvent(client, reqMsg); evt->setClientSendEvent(client, reqMsg);
_gateway->getClientSendQue()->post(evt); _gateway->getClientSendQue()->post(evt);
} }
/* /*
@@ -171,35 +190,36 @@ void MQTTSNConnectionHandler::handleWilltopic(Client* client, MQTTSNPacket* pack
*/ */
void MQTTSNConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet) void MQTTSNConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet)
{ {
if ( !client->isWaitWillMsg() ) if (!client->isWaitWillMsg())
{ {
DEBUGLOG(" MQTTSNConnectionHandler::handleWillmsg WaitWillMsgFlg is off.\n"); DEBUGLOG(" MQTTSNConnectionHandler::handleWillmsg WaitWillMsgFlg is off.\n");
return; return;
} }
MQTTSNString willmsg; MQTTSNString willmsg = MQTTSNString_initializer;
Connect* connectData = client->getConnectData(); Connect* connectData = client->getConnectData();
if( client->isConnectSendable() ) if (client->isConnectSendable())
{ {
/* save WillMsg in the client */ /* save WillMsg in the client */
if ( packet->getWILLMSG(&willmsg) == 0 ) if (packet->getWILLMSG(&willmsg) == 0)
{ {
return; return;
} }
client->setWillMsg(willmsg); client->setWillMsg(willmsg);
/* create CONNECT message */ /* create CONNECT message */
MQTTGWPacket* mqttPacket = new MQTTGWPacket(); MQTTGWPacket* mqttPacket = new MQTTGWPacket();
connectData->willMsg = client->getWillMsg(); connectData->willMsg = client->getWillMsg();
mqttPacket->setCONNECT(connectData, (unsigned char*)_gateway->getGWParams()->loginId, (unsigned char*)_gateway->getGWParams()->password); mqttPacket->setCONNECT(connectData, (unsigned char*) _gateway->getGWParams()->loginId,
(unsigned char*) _gateway->getGWParams()->password);
/* Send CONNECT to the broker */ /* Send CONNECT to the broker */
Event* evt = new Event(); Event* evt = new Event();
evt->setBrokerSendEvent(client, mqttPacket); evt->setBrokerSendEvent(client, mqttPacket);
client->setWaitWillMsgFlg(false); client->setWaitWillMsgFlg(false);
_gateway->getBrokerSendQue()->post(evt); _gateway->getBrokerSendQue()->post(evt);
} }
} }
/* /*
@@ -207,25 +227,25 @@ void MQTTSNConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet
*/ */
void MQTTSNConnectionHandler::handleDisconnect(Client* client, MQTTSNPacket* packet) void MQTTSNConnectionHandler::handleDisconnect(Client* client, MQTTSNPacket* packet)
{ {
Event* ev = new Event(); uint16_t duration = 0;
MQTTSNPacket* snMsg = new MQTTSNPacket();
snMsg->setDISCONNECT(0);
ev->setClientSendEvent(client, snMsg);
_gateway->getClientSendQue()->post(ev);
uint16_t duration = 0; if (packet->getDISCONNECT(&duration) != 0)
if ( packet->getDISCONNECT(&duration) == 0 ) {
{ if (duration == 0)
return; {
} MQTTGWPacket* mqMsg = new MQTTGWPacket();
if ( duration == 0 ) mqMsg->setHeader(DISCONNECT);
{ Event* ev = new Event();
MQTTGWPacket* mqMsg = new MQTTGWPacket(); ev->setBrokerSendEvent(client, mqMsg);
mqMsg->setHeader(DISCONNECT); _gateway->getBrokerSendQue()->post(ev);
ev = new Event(); }
ev->setBrokerSendEvent(client, mqMsg); }
_gateway->getBrokerSendQue()->post(ev);
} MQTTSNPacket* snMsg = new MQTTSNPacket();
snMsg->setDISCONNECT(0);
Event* evt = new Event();
evt->setClientSendEvent(client, snMsg);
_gateway->getClientSendQue()->post(evt);
} }
/* /*
@@ -233,12 +253,12 @@ void MQTTSNConnectionHandler::handleDisconnect(Client* client, MQTTSNPacket* pac
*/ */
void MQTTSNConnectionHandler::handleWilltopicupd(Client* client, MQTTSNPacket* packet) void MQTTSNConnectionHandler::handleWilltopicupd(Client* client, MQTTSNPacket* packet)
{ {
/* send NOT_SUPPORTED responce to the client */ /* send NOT_SUPPORTED responce to the client */
MQTTSNPacket* respMsg = new MQTTSNPacket(); MQTTSNPacket* respMsg = new MQTTSNPacket();
respMsg->setWILLTOPICRESP(MQTTSN_RC_NOT_SUPPORTED); respMsg->setWILLTOPICRESP(MQTTSN_RC_NOT_SUPPORTED);
Event* evt = new Event(); Event* evt = new Event();
evt->setClientSendEvent(client, respMsg); evt->setClientSendEvent(client, respMsg);
_gateway->getClientSendQue()->post(evt); _gateway->getClientSendQue()->post(evt);
} }
/* /*
@@ -246,12 +266,12 @@ void MQTTSNConnectionHandler::handleWilltopicupd(Client* client, MQTTSNPacket* p
*/ */
void MQTTSNConnectionHandler::handleWillmsgupd(Client* client, MQTTSNPacket* packet) void MQTTSNConnectionHandler::handleWillmsgupd(Client* client, MQTTSNPacket* packet)
{ {
/* send NOT_SUPPORTED responce to the client */ /* send NOT_SUPPORTED responce to the client */
MQTTSNPacket* respMsg = new MQTTSNPacket(); MQTTSNPacket* respMsg = new MQTTSNPacket();
respMsg->setWILLMSGRESP(MQTTSN_RC_NOT_SUPPORTED); respMsg->setWILLMSGRESP(MQTTSN_RC_NOT_SUPPORTED);
Event* evt = new Event(); Event* evt = new Event();
evt->setClientSendEvent(client, respMsg); evt->setClientSendEvent(client, respMsg);
_gateway->getClientSendQue()->post(evt); _gateway->getClientSendQue()->post(evt);
} }
/* /*
@@ -259,10 +279,34 @@ void MQTTSNConnectionHandler::handleWillmsgupd(Client* client, MQTTSNPacket* pac
*/ */
void MQTTSNConnectionHandler::handlePingreq(Client* client, MQTTSNPacket* packet) void MQTTSNConnectionHandler::handlePingreq(Client* client, MQTTSNPacket* packet)
{ {
/* send PINGREQ to the broker */ if ((client->isSleep() || client->isAwake()) && client->getClientSleepPacket())
MQTTGWPacket* pingreq = new MQTTGWPacket(); {
pingreq->setHeader(PINGREQ); sendStoredPublish(client);
Event* evt = new Event(); client->holdPingRequest();
evt->setBrokerSendEvent(client, pingreq); }
_gateway->getBrokerSendQue()->post(evt); else
{
/* send PINGREQ to the broker */
client->resetPingRequest();
MQTTGWPacket* pingreq = new MQTTGWPacket();
pingreq->setHeader(PINGREQ);
Event* evt = new Event();
evt->setBrokerSendEvent(client, pingreq);
_gateway->getBrokerSendQue()->post(evt);
}
}
void MQTTSNConnectionHandler::sendStoredPublish(Client* client)
{
MQTTGWPacket* msg = nullptr;
while ((msg = client->getClientSleepPacket()) != nullptr)
{
// ToDo: This version can't re-send PUBLISH when PUBACK is not returned.
client->deleteFirstClientSleepPacket(); // pop the que to delete element.
Event* ev = new Event();
ev->setBrokerRecvEvent(client, msg);
_gateway->getPacketEventQue()->post(ev);
}
} }

View File

@@ -25,20 +25,21 @@ namespace MQTTSNGW
class MQTTSNConnectionHandler class MQTTSNConnectionHandler
{ {
public: public:
MQTTSNConnectionHandler(Gateway* gateway); MQTTSNConnectionHandler(Gateway* gateway);
~MQTTSNConnectionHandler(); ~MQTTSNConnectionHandler();
void sendADVERTISE(void); void sendADVERTISE(void);
void handleSearchgw(MQTTSNPacket* packet); void handleSearchgw(MQTTSNPacket* packet);
void handleConnect(Client* client, MQTTSNPacket* packet); void handleConnect(Client* client, MQTTSNPacket* packet);
void handleWilltopic(Client* client, MQTTSNPacket* packet); void handleWilltopic(Client* client, MQTTSNPacket* packet);
void handleWillmsg(Client* client, MQTTSNPacket* packet); void handleWillmsg(Client* client, MQTTSNPacket* packet);
void handleDisconnect(Client* client, MQTTSNPacket* packet); void handleDisconnect(Client* client, MQTTSNPacket* packet);
void handleWilltopicupd(Client* client, MQTTSNPacket* packet); void handleWilltopicupd(Client* client, MQTTSNPacket* packet);
void handleWillmsgupd(Client* client, MQTTSNPacket* packet); void handleWillmsgupd(Client* client, MQTTSNPacket* packet);
void handlePingreq(Client* client, MQTTSNPacket* packet); void handlePingreq(Client* client, MQTTSNPacket* packet);
private: private:
char _pbuf[MQTTSNGW_MAX_PACKET_SIZE * 3]; void sendStoredPublish(Client* client);
Gateway* _gateway;
Gateway* _gateway;
}; };
} }

View File

@@ -25,6 +25,8 @@ namespace MQTTSNGW
#define CONFIG_DIRECTORY "./" #define CONFIG_DIRECTORY "./"
#define CONFIG_FILE "gateway.conf" #define CONFIG_FILE "gateway.conf"
#define CLIENT_LIST "clients.conf" #define CLIENT_LIST "clients.conf"
#define PREDEFINEDTOPIC_FILE "predefinedTopic.conf"
#define FORWARDER_LIST "forwarders.conf"
/*========================================================== /*==========================================================
* Gateway default parameters * Gateway default parameters
@@ -35,30 +37,42 @@ namespace MQTTSNGW
/*================================= /*=================================
* MQTT-SN Parametrs * MQTT-SN Parametrs
==================================*/ ==================================*/
#define MAX_CLIENTS (100) // Number of Clients can be handled. #define MAX_CLIENTS (100) // Default number of Clients can be handled.
#define MAX_CLIENTID_LENGTH (64) // Max length of clientID #define MAX_CLIENTID_LENGTH (64) // Max length of clientID
#define MAX_INFLIGHTMESSAGES (10) // Number of inflight messages #define MAX_INFLIGHTMESSAGES (10) // Number of inflight messages
#define MQTTSNGW_MAX_PACKET_SIZE (1024) // Max Packet size (5+2+TopicLen+PayloadLen) #define MAX_MESSAGEID_TABLE_SIZE (500) // Number of MessageIdTable size
#define MAX_SAVED_PUBLISH (20) // Max number of PUBLISH message for Asleep state
#define MAX_TOPIC_PAR_CLIENT (50) // Max Topic count for a client. it should be less than 256
#define MQTTSNGW_MAX_PACKET_SIZE (1024) // Max Packet size (5+2+TopicLen+PayloadLen + Foward Encapsulation)
#define SIZE_OF_LOG_PACKET (500) // Length of the packet log in bytes #define SIZE_OF_LOG_PACKET (500) // Length of the packet log in bytes
#define PROXY_KEEPALIVE_DURATION (900) // Seconds
#define PROXY_RESPONSE_DURATION (10) // Seconds
#define PROXY_MAX_RETRY_CNT (3)
/*================================= /*=================================
* Data Type * Data Type
==================================*/ ==================================*/
typedef unsigned char uint8_t; typedef unsigned char uint8_t;
typedef unsigned short uint16_t; typedef unsigned short uint16_t;
typedef unsigned int uint32_t; typedef unsigned int uint32_t;
/*================================= /*=================================
* Log controls * Log controls
==================================*/ ==================================*/
//#define DEBUG // print out log for debug //#define DEBUG_MQTTSN // print out log for debug
//#define DEBUG_NWSTACK // print out SensorNetwork log //#define DEBUG_NW // print out SensorNetwork log
#ifdef DEBUG_MQTTSN
#ifdef DEBUG
#define DEBUGLOG(...) printf(__VA_ARGS__) #define DEBUGLOG(...) printf(__VA_ARGS__)
#else #else
#define DEBUGLOG(...) #define DEBUGLOG(...)
#endif #endif
#ifdef DEBUG_NW
#define D_NWSTACK(...) printf(__VA_ARGS__)
#else
#define D_NWSTACK(...)
#endif
} }
#endif /* MQTTSNGWDEFINES_H_ */ #endif /* MQTTSNGWDEFINES_H_ */

View File

@@ -0,0 +1,175 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWPacket.h"
#include "MQTTSNGWEncapsulatedPacket.h"
#include "MQTTSNPacket.h"
#include <string.h>
using namespace MQTTSNGW;
using namespace std;
WirelessNodeId::WirelessNodeId() :
_len { 0 }, _nodeId { 0 }
{
}
WirelessNodeId::~WirelessNodeId()
{
if (_nodeId)
{
free(_nodeId);
}
}
void WirelessNodeId::setId(uint8_t* id, uint8_t len)
{
if (_nodeId)
{
free(_nodeId);
}
uint8_t* buf = (uint8_t*) malloc(len);
if (buf)
{
memcpy(buf, id, len);
_len = len;
_nodeId = buf;
}
else
{
_nodeId = nullptr;
_len = 0;
}
}
void WirelessNodeId::setId(WirelessNodeId* id)
{
setId(id->_nodeId, id->_len);
}
bool WirelessNodeId::operator ==(WirelessNodeId& id)
{
if (_len == id._len)
{
return memcmp(_nodeId, id._nodeId, _len) == 0;
}
else
{
return false;
}
}
/*
* Class MQTTSNGWEncapsulatedPacket
*/
MQTTSNGWEncapsulatedPacket::MQTTSNGWEncapsulatedPacket() :
_mqttsn { 0 }, _ctrl { 0 }
{
}
MQTTSNGWEncapsulatedPacket::MQTTSNGWEncapsulatedPacket(MQTTSNPacket* packet) :
_mqttsn { packet }, _ctrl { 0 }
{
}
MQTTSNGWEncapsulatedPacket::~MQTTSNGWEncapsulatedPacket()
{
/* Do not delete the MQTTSNPacket. MQTTSNPacket is deleted by delete Event */
}
int MQTTSNGWEncapsulatedPacket::unicast(SensorNetwork* network, SensorNetAddress* sendTo)
{
uint8_t buf[MQTTSNGW_MAX_PACKET_SIZE];
int len = serialize(buf);
return network->unicast(buf, len, sendTo);
}
int MQTTSNGWEncapsulatedPacket::serialize(uint8_t* buf)
{
int len = 0;
buf[0] = _id._len + 3;
buf[1] = MQTTSN_ENCAPSULATED;
buf[2] = _ctrl;
memcpy(buf + 3, _id._nodeId, _id._len);
if (_mqttsn)
{
len = _mqttsn->getPacketLength();
memcpy(buf + buf[0], _mqttsn->getPacketData(), len);
}
return buf[0] + len;
}
int MQTTSNGWEncapsulatedPacket::desirialize(unsigned char* buf, unsigned short len)
{
if (_mqttsn)
{
delete _mqttsn;
_mqttsn = nullptr;
}
_ctrl = buf[2];
_id.setId(buf + 3, buf[0] - 3);
_mqttsn = new MQTTSNPacket;
_mqttsn->desirialize(buf + buf[0], len - buf[0]);
return buf[0];
}
int MQTTSNGWEncapsulatedPacket::getType(void)
{
return MQTTSN_ENCAPSULATED;
}
const char* MQTTSNGWEncapsulatedPacket::getName()
{
return MQTTSNPacket_name(MQTTSN_ENCAPSULATED);
}
MQTTSNPacket* MQTTSNGWEncapsulatedPacket::getMQTTSNPacket(void)
{
return _mqttsn;
}
WirelessNodeId* MQTTSNGWEncapsulatedPacket::getWirelessNodeId(void)
{
return &_id;
}
void MQTTSNGWEncapsulatedPacket::setWirelessNodeId(WirelessNodeId* id)
{
_id.setId(id);
}
char* MQTTSNGWEncapsulatedPacket::print(char* pbuf)
{
char* ptr = pbuf;
char** pptr = &pbuf;
uint8_t buf[MQTTSNGW_MAX_PACKET_SIZE];
int len = serialize(buf);
int size = len > SIZE_OF_LOG_PACKET ? SIZE_OF_LOG_PACKET : len;
for (int i = 1; i < size; i++)
{
sprintf(*pptr, " %02X", *(buf + i));
*pptr += 3;
}
**pptr = 0;
return ptr;
}

View File

@@ -0,0 +1,63 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWENCAPSULATEDPACKET_H_
#define MQTTSNGATEWAY_SRC_MQTTSNGWENCAPSULATEDPACKET_H_
namespace MQTTSNGW
{
class WirelessNodeId
{
friend class MQTTSNGWEncapsulatedPacket;
public:
WirelessNodeId();
~WirelessNodeId();
void setId(uint8_t* id, uint8_t len);
void setId(WirelessNodeId* id);
bool operator ==(WirelessNodeId& id);
private:
uint8_t _len;
uint8_t* _nodeId;
};
class MQTTSNGWEncapsulatedPacket
{
public:
MQTTSNGWEncapsulatedPacket();
MQTTSNGWEncapsulatedPacket(MQTTSNPacket* packet);
~MQTTSNGWEncapsulatedPacket();
int unicast(SensorNetwork* network, SensorNetAddress* sendTo);
int serialize(uint8_t* buf);
int desirialize(unsigned char* buf, unsigned short len);
int getType(void);
unsigned char* getPacketData(void);
int getPacketLength(void);
const char* getName();
MQTTSNPacket* getMQTTSNPacket(void);
void setWirelessNodeId(WirelessNodeId* id);
WirelessNodeId* getWirelessNodeId(void);
char* print(char* buf);
private:
MQTTSNPacket* _mqttsn;
WirelessNodeId _id;
uint8_t _ctrl;
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWENCAPSULATEDPACKET_H_ */

View File

@@ -0,0 +1,277 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWForwarder.h"
#include "SensorNetwork.h"
#include <string.h>
using namespace MQTTSNGW;
using namespace std;
/*=====================================
Class ForwarderList
=====================================*/
ForwarderList::ForwarderList()
{
_head = nullptr;
}
ForwarderList::~ForwarderList()
{
if (_head)
{
Forwarder* p = _head;
while (p)
{
Forwarder* next = p->_next;
delete p;
p = next;
}
}
}
void ForwarderList::initialize(Gateway* gw)
{
/* Create Fowarders from clients.conf */
gw->getClientList()->setClientList(FORWARDER_TYPE);
}
Forwarder* ForwarderList::getForwarder(SensorNetAddress* addr)
{
Forwarder* p = _head;
while (p)
{
if (p->_sensorNetAddr.isMatch(addr))
{
break;
}
p = p->_next;
}
return p;
}
Forwarder* ForwarderList::addForwarder(SensorNetAddress* addr, MQTTSNString* forwarderId)
{
Forwarder* fdr = new Forwarder(addr, forwarderId);
if (_head == nullptr)
{
_head = fdr;
}
else
{
Forwarder* p = _head;
while (p)
{
if (p->_next == nullptr)
{
p->_next = fdr;
break;
}
else
{
p = p->_next;
}
}
}
return fdr;
}
Forwarder::Forwarder()
{
_headClient = nullptr;
_next = nullptr;
}
/*=====================================
Class ForwarderList
=====================================*/
Forwarder::Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId)
{
_forwarderName = string(forwarderId->cstring);
_sensorNetAddr = *addr;
_headClient = nullptr;
_next = nullptr;
}
Forwarder::~Forwarder(void)
{
if (_headClient)
{
ForwarderElement* p = _headClient;
while (p)
{
ForwarderElement* next = p->_next;
delete p;
p = next;
}
}
}
const char* Forwarder::getId(void)
{
return _forwarderName.c_str();
}
void Forwarder::addClient(Client* client, WirelessNodeId* id)
{
ForwarderElement* p = _headClient;
ForwarderElement* prev = nullptr;
client->setForwarder(this);
if (p != nullptr)
{
while (p)
{
if (p->_client == client)
{
client->setForwarder(this);
p->setWirelessNodeId(id);
return;
}
prev = p;
p = p->_next;
}
}
ForwarderElement* fclient = new ForwarderElement();
fclient->setClient(client);
fclient->setWirelessNodeId(id);
if (prev)
{
prev->_next = fclient;
}
else
{
_headClient = fclient;
}
}
Client* Forwarder::getClient(WirelessNodeId* id)
{
Client* cl = nullptr;
_mutex.lock();
ForwarderElement* p = _headClient;
while (p)
{
if (*(p->_wirelessNodeId) == *id)
{
cl = p->_client;
break;
}
else
{
p = p->_next;
}
}
_mutex.unlock();
return cl;
}
const char* Forwarder::getName(void)
{
return _forwarderName.c_str();
}
WirelessNodeId* Forwarder::getWirelessNodeId(Client* client)
{
WirelessNodeId* nodeId = nullptr;
_mutex.lock();
ForwarderElement* p = _headClient;
while (p)
{
if (p->_client == client)
{
nodeId = p->_wirelessNodeId;
break;
}
else
{
p = p->_next;
}
}
_mutex.unlock();
return nodeId;
}
void Forwarder::eraseClient(Client* client)
{
ForwarderElement* prev = nullptr;
_mutex.lock();
ForwarderElement* p = _headClient;
while (p)
{
if (p->_client == client)
{
if (prev)
{
prev->_next = p->_next;
}
else
{
_headClient = p->_next;
}
delete p;
break;
}
else
{
p = p->_next;
}
}
_mutex.unlock();
}
SensorNetAddress* Forwarder::getSensorNetAddr(void)
{
return &_sensorNetAddr;
}
/*
* Class ForwardedClient
*/
ForwarderElement::ForwarderElement() :
_client { 0 }, _wirelessNodeId { 0 }, _next { 0 }
{
}
ForwarderElement::~ForwarderElement()
{
if (_wirelessNodeId)
{
delete _wirelessNodeId;
}
}
void ForwarderElement::setClient(Client* client)
{
_client = client;
}
void ForwarderElement::setWirelessNodeId(WirelessNodeId* id)
{
if (_wirelessNodeId == nullptr)
{
_wirelessNodeId = new WirelessNodeId();
}
_wirelessNodeId->setId(id);
}

View File

@@ -0,0 +1,96 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWFORWARDER_H_
#define MQTTSNGATEWAY_SRC_MQTTSNGWFORWARDER_H_
#include "MQTTSNGWClient.h"
#include "MQTTSNGateway.h"
#include "MQTTSNGWEncapsulatedPacket.h"
#include "SensorNetwork.h"
namespace MQTTSNGW
{
class Gateway;
class Client;
class WirelessNodeId;
/*=====================================
Class ForwarderElement
=====================================*/
class ForwarderElement
{
friend class Forwarder;
public:
ForwarderElement();
~ForwarderElement();
void setClient(Client* client);
void setWirelessNodeId(WirelessNodeId* id);
private:
Client* _client;
WirelessNodeId* _wirelessNodeId;
ForwarderElement* _next;
};
/*=====================================
Class Forwarder
=====================================*/
class Forwarder
{
friend class ForwarderList;
public:
Forwarder(void);
Forwarder(SensorNetAddress* addr, MQTTSNString* forwarderId);
~Forwarder();
void initialize(void);
const char* getId(void);
void addClient(Client* client, WirelessNodeId* id);
Client* getClient(WirelessNodeId* id);
WirelessNodeId* getWirelessNodeId(Client* client);
void eraseClient(Client* client);
SensorNetAddress* getSensorNetAddr(void);
const char* getName(void);
private:
string _forwarderName;
SensorNetAddress _sensorNetAddr;
ForwarderElement* _headClient { nullptr };
Forwarder* _next { nullptr };
Mutex _mutex;
};
/*=====================================
Class ForwarderList
=====================================*/
class ForwarderList
{
public:
ForwarderList();
~ForwarderList();
void initialize(Gateway* gw);
Forwarder* getForwarder(SensorNetAddress* addr);
Forwarder* addForwarder(SensorNetAddress* addr, MQTTSNString* forwarderId);
private:
Forwarder* _head;
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWFORWARDER_H_ */

View File

@@ -13,8 +13,6 @@
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/ **************************************************************************************/
#define RINGBUFFER
#include "MQTTSNGWProcess.h" #include "MQTTSNGWProcess.h"
#include "MQTTSNGWLogmonitor.h" #include "MQTTSNGWLogmonitor.h"
#include <stdio.h> #include <stdio.h>
@@ -24,7 +22,7 @@ using namespace MQTTSNGW;
Logmonitor::Logmonitor() Logmonitor::Logmonitor()
{ {
theProcess = this; theProcess = this;
} }
Logmonitor::~Logmonitor() Logmonitor::~Logmonitor()
@@ -34,17 +32,17 @@ Logmonitor::~Logmonitor()
void Logmonitor::run() void Logmonitor::run()
{ {
while (true) while (true)
{ {
const char* data = getLog(); const char* data = getLog();
if ( *data == 0 ) if (*data == 0)
{ {
break; break;
} }
else else
{ {
printf("%s", data); printf("%s", data);
} }
} }
} }

View File

@@ -23,9 +23,9 @@ namespace MQTTSNGW
class Logmonitor: public Process class Logmonitor: public Process
{ {
public: public:
Logmonitor(); Logmonitor();
~Logmonitor(); ~Logmonitor();
void run(); void run();
}; };
} }

View File

@@ -0,0 +1,212 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#include "MQTTSNGWMessageIdTable.h"
#include "MQTTSNGWClient.h"
using namespace MQTTSNGW;
/*===============================
* Class MessageIdTable
===============================*/
MessageIdTable::MessageIdTable()
{
}
MessageIdTable::~MessageIdTable()
{
_mutex.lock();
if (_head != nullptr)
{
MessageIdElement* p = _tail;
while (p)
{
MessageIdElement* pPrev = p;
delete p;
_cnt--;
p = pPrev->_prev;
}
_head = _tail = nullptr;
}
_mutex.unlock();
}
MessageIdElement* MessageIdTable::add(Aggregater* aggregater, Client* client, uint16_t clientMsgId)
{
if (_cnt > _maxSize)
{
return nullptr;
}
MessageIdElement* elm = new MessageIdElement(0, client, clientMsgId);
if (elm == nullptr)
{
return nullptr;
}
_mutex.lock();
if (_head == nullptr)
{
elm->_msgId = aggregater->msgId();
_head = elm;
_tail = elm;
_cnt++;
}
else
{
MessageIdElement* p = find(client, clientMsgId);
if (p == nullptr)
{
elm->_msgId = aggregater->msgId();
p = _tail;
_tail = elm;
elm->_prev = p;
p->_next = elm;
_cnt++;
}
else
{
delete elm;
elm = nullptr;
}
}
_mutex.unlock();
return elm;
}
MessageIdElement* MessageIdTable::find(uint16_t msgId)
{
MessageIdElement* p = _head;
while (p)
{
if (p->_msgId == msgId)
{
break;
}
p = p->_next;
}
return p;
}
MessageIdElement* MessageIdTable::find(Client* client, uint16_t clientMsgId)
{
MessageIdElement* p = _head;
while (p)
{
if (p->_clientMsgId == clientMsgId && p->_client == client)
{
break;
}
p = p->_next;
}
return p;
}
Client* MessageIdTable::getClientMsgId(uint16_t msgId, uint16_t* clientMsgId)
{
Client* clt = nullptr;
*clientMsgId = 0;
_mutex.lock();
MessageIdElement* p = find(msgId);
if (p != nullptr)
{
clt = p->_client;
*clientMsgId = p->_clientMsgId;
clear(p);
}
_mutex.unlock();
return clt;
}
void MessageIdTable::erase(uint16_t msgId)
{
_mutex.lock();
MessageIdElement* p = find(msgId);
clear(p);
_mutex.unlock();
}
void MessageIdTable::clear(MessageIdElement* elm)
{
if (elm == nullptr)
{
return;
}
if (elm->_prev == nullptr)
{
_head = elm->_next;
if (_head == nullptr)
{
_tail = nullptr;
}
else
{
_head->_prev = nullptr;
}
delete elm;
_cnt--;
return;
}
else
{
elm->_prev->_next = elm->_next;
if (elm->_next == nullptr)
{
_tail = elm->_prev;
}
else
{
elm->_next->_prev = elm->_prev;
}
delete elm;
_cnt--;
return;
}
}
uint16_t MessageIdTable::getMsgId(Client* client, uint16_t clientMsgId)
{
uint16_t msgId = 0;
MessageIdElement* p = find(client, clientMsgId);
if (p != nullptr)
{
msgId = p->_msgId;
}
return msgId;
}
/*===============================
* Class MessageIdElement
===============================*/
MessageIdElement::MessageIdElement(void) :
_msgId { 0 }, _clientMsgId { 0 }, _client { nullptr }, _next { nullptr }, _prev { nullptr }
{
}
MessageIdElement::MessageIdElement(uint16_t msgId, Client* client, uint16_t clientMsgId) :
MessageIdElement()
{
_msgId = msgId;
_client = client;
_clientMsgId = clientMsgId;
}
MessageIdElement::~MessageIdElement(void)
{
}

View File

@@ -0,0 +1,78 @@
/**************************************************************************************
* Copyright (c) 2018, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
**************************************************************************************/
#ifndef MQTTSNGATEWAY_SRC_MQTTSNGWMESSAGEIDTABLE_H_
#define MQTTSNGATEWAY_SRC_MQTTSNGWMESSAGEIDTABLE_H_
#include "MQTTSNGWDefines.h"
#include "MQTTSNGWProcess.h"
#include <stdint.h>
namespace MQTTSNGW
{
class Client;
class MessageIdElement;
class Meutex;
class Aggregater;
/*=====================================
Class MessageIdTable
======================================*/
class MessageIdTable
{
public:
MessageIdTable();
~MessageIdTable();
MessageIdElement* add(Aggregater* aggregater, Client* client,
uint16_t clientMsgId);
Client* getClientMsgId(uint16_t msgId, uint16_t* clientMsgId);
uint16_t getMsgId(Client* client, uint16_t clientMsgId);
void erase(uint16_t msgId);
void clear(MessageIdElement* elm);
private:
MessageIdElement* find(uint16_t msgId);
MessageIdElement* find(Client* client, uint16_t clientMsgId);
MessageIdElement* _head { nullptr };
MessageIdElement* _tail{ nullptr };
int _cnt { 0 };
int _maxSize { MAX_MESSAGEID_TABLE_SIZE };
Mutex _mutex;
};
/*=====================================
Class MessageIdElement
=====================================*/
class MessageIdElement
{
friend class MessageIdTable;
friend class Aggregater;
public:
MessageIdElement(void);
MessageIdElement(uint16_t msgId, Client* client, uint16_t clientMsgId);
~MessageIdElement(void);
private:
uint16_t _msgId;
uint16_t _clientMsgId;
Client* _client;
MessageIdElement* _next;
MessageIdElement* _prev;
};
}
#endif /* MQTTSNGATEWAY_SRC_MQTTSNGWMESSAGEIDTABLE_H_ */

View File

@@ -24,390 +24,553 @@
using namespace std; using namespace std;
using namespace MQTTSNGW; using namespace MQTTSNGW;
int readInt(char** pptr);
void writeInt(unsigned char** pptr, int msgId);
MQTTSNPacket::MQTTSNPacket() MQTTSNPacket::MQTTSNPacket(void)
{ {
_buf = 0; _buf = nullptr;
_bufLen = 0; _bufLen = 0;
} }
MQTTSNPacket::MQTTSNPacket(MQTTSNPacket& packet)
{
_buf = (unsigned char*) malloc(packet._bufLen);
if (_buf)
{
_bufLen = packet._bufLen;
memcpy(_buf, packet._buf, _bufLen);
}
else
{
_buf = nullptr;
_bufLen = 0;
}
}
MQTTSNPacket::~MQTTSNPacket() MQTTSNPacket::~MQTTSNPacket()
{ {
if (_buf) if (_buf)
{ {
free(_buf); free(_buf);
} }
} }
int MQTTSNPacket::unicast(SensorNetwork* network, SensorNetAddress* sendTo) int MQTTSNPacket::unicast(SensorNetwork* network, SensorNetAddress* sendTo)
{ {
return network->unicast(_buf, _bufLen, sendTo); return network->unicast(_buf, _bufLen, sendTo);
} }
int MQTTSNPacket::broadcast(SensorNetwork* network) int MQTTSNPacket::broadcast(SensorNetwork* network)
{ {
return network->broadcast(_buf, _bufLen); return network->broadcast(_buf, _bufLen);
} }
int MQTTSNPacket::serialize(uint8_t* buf) int MQTTSNPacket::serialize(uint8_t* buf)
{ {
buf = _buf; buf = _buf;
return _bufLen; return _bufLen;
} }
int MQTTSNPacket::desirialize(unsigned char* buf, unsigned short len) int MQTTSNPacket::desirialize(unsigned char* buf, unsigned short len)
{ {
if ( _buf ) if (_buf)
{ {
free(_buf); free(_buf);
} }
_buf = (unsigned char*)calloc(len, sizeof(unsigned char)); _buf = (unsigned char*) calloc(len, sizeof(unsigned char));
if ( _buf ) if (_buf)
{ {
memcpy(_buf, buf, len); memcpy(_buf, buf, len);
_bufLen = len; _bufLen = len;
} }
else else
{ {
_bufLen = 0; _bufLen = 0;
} }
return _bufLen; return _bufLen;
} }
int MQTTSNPacket::recv(SensorNetwork* network) int MQTTSNPacket::recv(SensorNetwork* network)
{ {
uint8_t buf[MQTTSNGW_MAX_PACKET_SIZE]; uint8_t buf[MQTTSNGW_MAX_PACKET_SIZE];
int len = network->read((uint8_t*) buf, MQTTSNGW_MAX_PACKET_SIZE); int len = network->read((uint8_t*) buf, MQTTSNGW_MAX_PACKET_SIZE);
if (len > 1) if (len > 1)
{ {
len = desirialize(buf, len); len = desirialize(buf, len);
} }
else return len;
{
len = 0;
}
return len;
} }
int MQTTSNPacket::getType(void) int MQTTSNPacket::getType(void)
{ {
if ( _bufLen == 0 ) if (_bufLen == 0)
{ {
return 0; return 0;
} }
int value = 0; int value = 0;
int p = MQTTSNPacket_decode(_buf, _bufLen, &value); int p = MQTTSNPacket_decode(_buf, _bufLen, &value);
return _buf[p]; return _buf[p];
}
bool MQTTSNPacket::isQoSMinusPUBLISH(void)
{
if (_bufLen == 0)
{
return false;;
}
int value = 0;
int p = MQTTSNPacket_decode(_buf, _bufLen, &value);
return ((_buf[p] == MQTTSN_PUBLISH) && ((_buf[p + 1] & 0x60) == 0x60));
} }
unsigned char* MQTTSNPacket::getPacketData(void) unsigned char* MQTTSNPacket::getPacketData(void)
{ {
return _buf; return _buf;
} }
int MQTTSNPacket::getPacketLength(void) int MQTTSNPacket::getPacketLength(void)
{ {
return _bufLen; return _bufLen;
} }
const char* MQTTSNPacket::getName() const char* MQTTSNPacket::getName()
{ {
return MQTTSNPacket_name(getType()); return MQTTSNPacket_name(getType());
} }
int MQTTSNPacket::setADVERTISE(uint8_t gatewayid, uint16_t duration) int MQTTSNPacket::setADVERTISE(uint8_t gatewayid, uint16_t duration)
{ {
unsigned char buf[5]; unsigned char buf[5];
int len = MQTTSNSerialize_advertise(buf, 5, (unsigned char) gatewayid, int buflen = sizeof(buf);
(unsigned short) duration); int len = MQTTSNSerialize_advertise(buf, buflen, (unsigned char) gatewayid, (unsigned short) duration);
return desirialize(buf, len); return desirialize(buf, len);
} }
int MQTTSNPacket::setGWINFO(uint8_t gatewayId) int MQTTSNPacket::setGWINFO(uint8_t gatewayId)
{ {
unsigned char buf[3]; unsigned char buf[3];
int len = MQTTSNSerialize_gwinfo(buf, 3, (unsigned char) gatewayId, 0, 0); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_gwinfo(buf, buflen, (unsigned char) gatewayId, 0, 0);
return desirialize(buf, len);
} }
int MQTTSNPacket::setConnect(void) int MQTTSNPacket::setConnect(void)
{ {
unsigned char buf[40]; unsigned char buf[40];
MQTTSNPacket_connectData data; int buflen = sizeof(buf);
data.clientID.cstring = (char*)"client01"; MQTTSNPacket_connectData data;
int len = MQTTSNSerialize_connect(buf, 40, &data); data.clientID.cstring = (char*) "client01";
return desirialize(buf, len); int len = MQTTSNSerialize_connect(buf, buflen, &data);
return desirialize(buf, len);
}
bool MQTTSNPacket::isAccepted(void)
{
return (getType() == MQTTSN_CONNACK) && (_buf[2] == MQTTSN_RC_ACCEPTED);
} }
int MQTTSNPacket::setCONNACK(uint8_t returnCode) int MQTTSNPacket::setCONNACK(uint8_t returnCode)
{ {
unsigned char buf[3]; unsigned char buf[3];
int len = MQTTSNSerialize_connack(buf, 3, (int) returnCode); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_connack(buf, buflen, (int) returnCode);
return desirialize(buf, len);
} }
int MQTTSNPacket::setWILLTOPICREQ(void) int MQTTSNPacket::setWILLTOPICREQ(void)
{ {
unsigned char buf[2]; unsigned char buf[2];
int len = MQTTSNSerialize_willtopicreq(buf, 2); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_willtopicreq(buf, buflen);
return desirialize(buf, len);
} }
int MQTTSNPacket::setWILLMSGREQ(void) int MQTTSNPacket::setWILLMSGREQ(void)
{ {
unsigned char buf[2]; unsigned char buf[2];
int len = MQTTSNSerialize_willmsgreq(buf, 2); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_willmsgreq(buf, buflen);
return desirialize(buf, len);
} }
int MQTTSNPacket::setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* topicName) int MQTTSNPacket::setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* topicName)
{ {
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE];
int len = MQTTSNSerialize_register(buf, MQTTSNGW_MAX_PACKET_SIZE, (unsigned short) topicId, (unsigned short) msgId, int buflen = sizeof(buf);
topicName); int len = MQTTSNSerialize_register(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, topicName);
return desirialize(buf, len); return desirialize(buf, len);
} }
int MQTTSNPacket::setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode) int MQTTSNPacket::setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode)
{ {
unsigned char buf[7]; unsigned char buf[7];
int len = MQTTSNSerialize_regack(buf, 7, (unsigned short) topicId, (unsigned short) msgId, int buflen = sizeof(buf);
(unsigned char) returnCode); int len = MQTTSNSerialize_regack(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode);
return desirialize(buf, len); return desirialize(buf, len);
} }
int MQTTSNPacket::setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId, MQTTSN_topicid topic, int MQTTSNPacket::setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId, MQTTSN_topicid topic, uint8_t* payload,
uint8_t* payload, uint16_t payloadlen) uint16_t payloadlen)
{ {
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE];
int len = MQTTSNSerialize_publish(buf, MQTTSNGW_MAX_PACKET_SIZE, (unsigned char) dup, qos, (unsigned char) retained, int buflen = sizeof(buf);
(unsigned short) msgId, topic, (unsigned char*) payload, (int) payloadlen); int len = MQTTSNSerialize_publish(buf, buflen, (unsigned char) dup, qos, (unsigned char) retained, (unsigned short) msgId,
return desirialize(buf, len); topic, (unsigned char*) payload, (int) payloadlen);
return desirialize(buf, len);
} }
int MQTTSNPacket::setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode) int MQTTSNPacket::setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode)
{ {
unsigned char buf[7]; unsigned char buf[7];
int len = MQTTSNSerialize_puback(buf, 7, (unsigned short) topicId, (unsigned short) msgId, int buflen = sizeof(buf);
(unsigned char) returnCode); int len = MQTTSNSerialize_puback(buf, buflen, (unsigned short) topicId, (unsigned short) msgId, (unsigned char) returnCode);
return desirialize(buf, len); return desirialize(buf, len);
} }
int MQTTSNPacket::setPUBREC(uint16_t msgId) int MQTTSNPacket::setPUBREC(uint16_t msgId)
{ {
unsigned char buf[4]; unsigned char buf[4];
int len = MQTTSNSerialize_pubrec(buf, 4, (unsigned short) msgId); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_pubrec(buf, buflen, (unsigned short) msgId);
return desirialize(buf, len);
} }
int MQTTSNPacket::setPUBREL(uint16_t msgId) int MQTTSNPacket::setPUBREL(uint16_t msgId)
{ {
unsigned char buf[4]; unsigned char buf[4];
int len = MQTTSNSerialize_pubrel(buf, 4, (unsigned short) msgId); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_pubrel(buf, buflen, (unsigned short) msgId);
return desirialize(buf, len);
} }
int MQTTSNPacket::setPUBCOMP(uint16_t msgId) int MQTTSNPacket::setPUBCOMP(uint16_t msgId)
{ {
unsigned char buf[4]; unsigned char buf[4];
int len = MQTTSNSerialize_pubcomp(buf, 4, (unsigned short) msgId); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_pubcomp(buf, buflen, (unsigned short) msgId);
return desirialize(buf, len);
} }
int MQTTSNPacket::setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t returnCode) int MQTTSNPacket::setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t returnCode)
{ {
unsigned char buf[8]; unsigned char buf[8];
int len = MQTTSNSerialize_suback(buf, 8, qos, (unsigned short) topicId, int buflen = sizeof(buf);
(unsigned short) msgId, (unsigned char) returnCode); int len = MQTTSNSerialize_suback(buf, buflen, qos, (unsigned short) topicId, (unsigned short) msgId,
return desirialize(buf, len); (unsigned char) returnCode);
return desirialize(buf, len);
} }
int MQTTSNPacket::setUNSUBACK(uint16_t msgId) int MQTTSNPacket::setUNSUBACK(uint16_t msgId)
{ {
unsigned char buf[4]; unsigned char buf[4];
int len = MQTTSNSerialize_unsuback(buf, 4, (unsigned short) msgId); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_unsuback(buf, buflen, (unsigned short) msgId);
return desirialize(buf, len);
} }
int MQTTSNPacket::setPINGRESP(void) int MQTTSNPacket::setPINGRESP(void)
{ {
unsigned char buf[32]; unsigned char buf[32];
int len = MQTTSNSerialize_pingresp(buf, 32); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_pingresp(buf, buflen);
return desirialize(buf, len);
} }
int MQTTSNPacket::setDISCONNECT(uint16_t duration) int MQTTSNPacket::setDISCONNECT(uint16_t duration)
{ {
unsigned char buf[4]; unsigned char buf[4];
int len = MQTTSNSerialize_disconnect(buf, 4, (int) duration); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_disconnect(buf, buflen, (int) duration);
return desirialize(buf, len);
} }
int MQTTSNPacket::setWILLTOPICRESP(uint8_t returnCode) int MQTTSNPacket::setWILLTOPICRESP(uint8_t returnCode)
{ {
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE];
int len = MQTTSNSerialize_willtopicresp(buf, MQTTSNGW_MAX_PACKET_SIZE, (int) returnCode); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_willtopicresp(buf, buflen, (int) returnCode);
return desirialize(buf, len);
} }
int MQTTSNPacket::setWILLMSGRESP(uint8_t returnCode) int MQTTSNPacket::setWILLMSGRESP(uint8_t returnCode)
{ {
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE]; unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE];
int len = MQTTSNSerialize_willmsgresp(buf, MQTTSNGW_MAX_PACKET_SIZE, (int) returnCode); int buflen = sizeof(buf);
return desirialize(buf, len); int len = MQTTSNSerialize_willmsgresp(buf, buflen, (int) returnCode);
return desirialize(buf, len);
}
int MQTTSNPacket::setCONNECT(MQTTSNPacket_connectData* options)
{
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE];
int buflen = sizeof(buf);
int len = MQTTSNSerialize_connect(buf, buflen, options);
return desirialize(buf, len);
}
int MQTTSNPacket::setPINGREQ(MQTTSNString* clientId)
{
unsigned char buf[MQTTSNGW_MAX_PACKET_SIZE];
int buflen = sizeof(buf);
int len = MQTTSNSerialize_pingreq(buf, buflen, *clientId);
return desirialize(buf, len);
} }
int MQTTSNPacket::getSERCHGW(uint8_t* radius) int MQTTSNPacket::getSERCHGW(uint8_t* radius)
{ {
return MQTTSNDeserialize_searchgw((unsigned char*) radius, (unsigned char*) _buf, _bufLen); return MQTTSNDeserialize_searchgw((unsigned char*) radius, (unsigned char*) _buf, _bufLen);
} }
int MQTTSNPacket::getCONNECT(MQTTSNPacket_connectData* data) int MQTTSNPacket::getCONNECT(MQTTSNPacket_connectData* data)
{ {
return MQTTSNDeserialize_connect(data, _buf, _bufLen); return MQTTSNDeserialize_connect(data, _buf, _bufLen);
} }
int MQTTSNPacket::getCONNACK(uint8_t* returnCode) int MQTTSNPacket::getCONNACK(uint8_t* returnCode)
{ {
return MQTTSNSerialize_connack(_buf, _bufLen, (int) *returnCode); return MQTTSNSerialize_connack(_buf, _bufLen, (int) *returnCode);
} }
int MQTTSNPacket::getWILLTOPIC(int* willQoS, uint8_t* willRetain, MQTTSNString* willTopic) int MQTTSNPacket::getWILLTOPIC(int* willQoS, uint8_t* willRetain, MQTTSNString* willTopic)
{ {
return MQTTSNDeserialize_willtopic((int*) willQoS, (unsigned char*) willRetain, willTopic, _buf, _bufLen); return MQTTSNDeserialize_willtopic((int*) willQoS, (unsigned char*) willRetain, willTopic, _buf, _bufLen);
} }
int MQTTSNPacket::getWILLMSG(MQTTSNString* willmsg) int MQTTSNPacket::getWILLMSG(MQTTSNString* willmsg)
{ {
return MQTTSNDeserialize_willmsg(willmsg, _buf, _bufLen); return MQTTSNDeserialize_willmsg(willmsg, _buf, _bufLen);
} }
int MQTTSNPacket::getREGISTER(uint16_t* topicId, uint16_t* msgId, MQTTSNString* topicName) int MQTTSNPacket::getREGISTER(uint16_t* topicId, uint16_t* msgId, MQTTSNString* topicName)
{ {
return MQTTSNDeserialize_register((unsigned short*) topicId, (unsigned short*) msgId, topicName, return MQTTSNDeserialize_register((unsigned short*) topicId, (unsigned short*) msgId, topicName, _buf, _bufLen);
_buf, _bufLen);
} }
int MQTTSNPacket::getREGACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode) int MQTTSNPacket::getREGACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode)
{ {
return MQTTSNDeserialize_regack((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf, _bufLen); return MQTTSNDeserialize_regack((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf,
_bufLen);
} }
int MQTTSNPacket::getPUBLISH(uint8_t* dup, int* qos, uint8_t* retained, uint16_t* msgId, MQTTSN_topicid* topic, int MQTTSNPacket::getPUBLISH(uint8_t* dup, int* qos, uint8_t* retained, uint16_t* msgId, MQTTSN_topicid* topic,
uint8_t** payload, int* payloadlen) uint8_t** payload, int* payloadlen)
{ {
return MQTTSNDeserialize_publish((unsigned char*) dup, qos, (unsigned char*) retained, (unsigned short*) msgId, return MQTTSNDeserialize_publish((unsigned char*) dup, qos, (unsigned char*) retained, (unsigned short*) msgId, topic,
topic, (unsigned char**) payload, (int*) payloadlen, _buf, _bufLen); (unsigned char**) payload, (int*) payloadlen, _buf, _bufLen);
} }
int MQTTSNPacket::getPUBACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode) int MQTTSNPacket::getPUBACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode)
{ {
return MQTTSNDeserialize_puback((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, return MQTTSNDeserialize_puback((unsigned short*) topicId, (unsigned short*) msgId, (unsigned char*) returnCode, _buf,
_buf, _bufLen); _bufLen);
} }
int MQTTSNPacket::getACK(uint16_t* msgId) int MQTTSNPacket::getACK(uint16_t* msgId)
{ {
unsigned char type; unsigned char type;
return MQTTSNDeserialize_ack(&type, (unsigned short*) msgId, _buf, _bufLen); return MQTTSNDeserialize_ack(&type, (unsigned short*) msgId, _buf, _bufLen);
} }
int MQTTSNPacket::getSUBSCRIBE(uint8_t* dup, int* qos, uint16_t* msgId, MQTTSN_topicid* topicFilter) int MQTTSNPacket::getSUBSCRIBE(uint8_t* dup, int* qos, uint16_t* msgId, MQTTSN_topicid* topicFilter)
{ {
return MQTTSNDeserialize_subscribe((unsigned char*) dup, qos, (unsigned short*) msgId, topicFilter, _buf, _bufLen); return MQTTSNDeserialize_subscribe((unsigned char*) dup, qos, (unsigned short*) msgId, topicFilter, _buf, _bufLen);
} }
int MQTTSNPacket::getUNSUBSCRIBE(uint16_t* msgId, MQTTSN_topicid* topicFilter) int MQTTSNPacket::getUNSUBSCRIBE(uint16_t* msgId, MQTTSN_topicid* topicFilter)
{ {
return MQTTSNDeserialize_unsubscribe((unsigned short*) msgId, topicFilter, _buf, _bufLen); return MQTTSNDeserialize_unsubscribe((unsigned short*) msgId, topicFilter, _buf, _bufLen);
} }
int MQTTSNPacket::getPINGREQ(void) int MQTTSNPacket::getPINGREQ(void)
{ {
if (getType() == MQTTSN_PINGRESP && _bufLen > 2 ) if (getType() == MQTTSN_PINGRESP && _bufLen > 2)
{ {
return _bufLen - 2; return _bufLen - 2;
} }
return 0; return 0;
} }
int MQTTSNPacket::getDISCONNECT(uint16_t* duration) int MQTTSNPacket::getDISCONNECT(uint16_t* duration)
{ {
int dur = 0; int dur = 0;
int rc = MQTTSNDeserialize_disconnect(&dur, _buf, _bufLen); int rc = MQTTSNDeserialize_disconnect(&dur, _buf, _bufLen);
*duration = (uint16_t)dur; *duration = (uint16_t) dur;
return rc; return rc;
} }
int MQTTSNPacket::getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic) int MQTTSNPacket::getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic)
{ {
return MQTTSNDeserialize_willtopicupd((int*) willQoS, (unsigned char*) willRetain, willTopic, _buf, _bufLen); return MQTTSNDeserialize_willtopicupd((int*) willQoS, (unsigned char*) willRetain, willTopic, _buf, _bufLen);
} }
int MQTTSNPacket::getWILLMSGUPD(MQTTSNString* willMsg) int MQTTSNPacket::getWILLMSGUPD(MQTTSNString* willMsg)
{ {
return MQTTSNDeserialize_willmsgupd(willMsg, _buf, _bufLen); return MQTTSNDeserialize_willmsgupd(willMsg, _buf, _bufLen);
} }
char* MQTTSNPacket::print(char* pbuf) char* MQTTSNPacket::print(char* pbuf)
{ {
char* ptr = pbuf; char* ptr = pbuf;
char** pptr = &pbuf; char** pptr = &pbuf;
int value = 0; int size = _bufLen > SIZE_OF_LOG_PACKET ? SIZE_OF_LOG_PACKET : _bufLen;
int i = MQTTSNPacket_decode(_buf, _bufLen, &value); for (int i = 0; i < size; i++)
int size = _bufLen > SIZE_OF_LOG_PACKET ? SIZE_OF_LOG_PACKET : _bufLen; {
sprintf(*pptr, " %02X", *(_buf + i));
for (; i < size; i++) *pptr += 3;
{ }
sprintf(*pptr, " %02X", *(_buf + i)); **pptr = 0;
*pptr += 3; return ptr;
}
**pptr = 0;
return ptr;
} }
char* MQTTSNPacket::getMsgId(char* pbuf) char* MQTTSNPacket::getMsgId(char* pbuf)
{ {
int value = 0; int value = 0;
int p = 0; int p = 0;
switch ( getType() ) switch (getType())
{ {
case MQTTSN_PUBLISH: case MQTTSN_PUBLISH:
p = MQTTSNPacket_decode(_buf, _bufLen, &value); p = MQTTSNPacket_decode(_buf, _bufLen, &value);
if ( _buf[p + 1] & 0x80 ) if (_buf[p + 1] & 0x80)
{ {
sprintf(pbuf, "+%02X%02X", _buf[p + 4], _buf[p + 5]); sprintf(pbuf, "+%02X%02X", _buf[p + 4], _buf[p + 5]);
} }
else else
{ {
sprintf(pbuf, " %02X%02X", _buf[p + 4], _buf[p + 5]); sprintf(pbuf, " %02X%02X", _buf[p + 4], _buf[p + 5]);
} }
break; break;
case MQTTSN_PUBACK: case MQTTSN_PUBACK:
case MQTTSN_REGISTER: case MQTTSN_REGISTER:
case MQTTSN_REGACK: case MQTTSN_REGACK:
sprintf(pbuf, " %02X%02X", _buf[4], _buf[5]); sprintf(pbuf, " %02X%02X", _buf[4], _buf[5]);
break; break;
case MQTTSN_PUBREC: case MQTTSN_PUBREC:
case MQTTSN_PUBREL: case MQTTSN_PUBREL:
case MQTTSN_PUBCOMP: case MQTTSN_PUBCOMP:
case MQTTSN_UNSUBACK: case MQTTSN_UNSUBACK:
sprintf(pbuf, " %02X%02X", _buf[2], _buf[3]); sprintf(pbuf, " %02X%02X", _buf[2], _buf[3]);
break; break;
case MQTTSN_SUBSCRIBE: case MQTTSN_SUBSCRIBE:
case MQTTSN_UNSUBSCRIBE: case MQTTSN_UNSUBSCRIBE:
p = MQTTSNPacket_decode(_buf, _bufLen, &value); p = MQTTSNPacket_decode(_buf, _bufLen, &value);
sprintf(pbuf, " %02X%02X", _buf[p + 2], _buf[p + 3]); sprintf(pbuf, " %02X%02X", _buf[p + 2], _buf[p + 3]);
break; break;
case MQTTSN_SUBACK: case MQTTSN_SUBACK:
sprintf(pbuf, " %02X%02X", _buf[5], _buf[6]); sprintf(pbuf, " %02X%02X", _buf[5], _buf[6]);
break; break;
default: default:
sprintf(pbuf, " "); sprintf(pbuf, " ");
break; break;
} }
return pbuf; if (strcmp(pbuf, " 0000") == 0)
{
sprintf(pbuf, " ");
}
return pbuf;
}
int MQTTSNPacket::getMsgId(void)
{
int value = 0;
int p = 0;
int msgId = 0;
char* ptr = 0;
switch (getType())
{
case MQTTSN_PUBLISH:
p = MQTTSNPacket_decode(_buf, _bufLen, &value);
ptr = (char*) _buf + p + 4;
msgId = readInt((char**) &ptr);
break;
case MQTTSN_PUBACK:
case MQTTSN_REGISTER:
case MQTTSN_REGACK:
ptr = (char*) _buf + 4;
msgId = readInt((char**) &ptr);
break;
case MQTTSN_PUBREC:
case MQTTSN_PUBREL:
case MQTTSN_PUBCOMP:
case MQTTSN_UNSUBACK:
ptr = (char*) _buf + 2;
msgId = readInt((char**) &ptr);
break;
case MQTTSN_SUBSCRIBE:
case MQTTSN_UNSUBSCRIBE:
p = MQTTSNPacket_decode(_buf, _bufLen, &value);
ptr = (char*) _buf + p + 2;
msgId = readInt((char**) &ptr);
break;
case MQTTSN_SUBACK:
ptr = (char*) _buf + 5;
msgId = readInt((char**) &ptr);
break;
default:
break;
}
return msgId;
}
void MQTTSNPacket::setMsgId(uint16_t msgId)
{
int value = 0;
int p = 0;
//unsigned char* ptr = 0;
switch (getType())
{
case MQTTSN_PUBLISH:
p = MQTTSNPacket_decode(_buf, _bufLen, &value);
_buf[p + 4] = (unsigned char) (msgId / 256);
_buf[p + 5] = (unsigned char) (msgId % 256);
//ptr = _buf + p + 4;
//writeInt(&ptr, msgId);
break;
case MQTTSN_PUBACK:
case MQTTSN_REGISTER:
case MQTTSN_REGACK:
_buf[4] = (unsigned char) (msgId / 256);
_buf[5] = (unsigned char) (msgId % 256);
//ptr = _buf + 4;
//writeInt(&ptr, msgId);
break;
case MQTTSN_PUBREC:
case MQTTSN_PUBREL:
case MQTTSN_PUBCOMP:
case MQTTSN_UNSUBACK:
_buf[2] = (unsigned char) (msgId / 256);
_buf[3] = (unsigned char) (msgId % 256);
//ptr = _buf + 2;
//writeInt(&ptr, msgId);
break;
case MQTTSN_SUBSCRIBE:
case MQTTSN_UNSUBSCRIBE:
p = MQTTSNPacket_decode(_buf, _bufLen, &value);
_buf[p + 2] = (unsigned char) (msgId / 256);
_buf[p + 3] = (unsigned char) (msgId % 256);
//ptr = _buf + p + 2;
//writeInt(&ptr, msgId);
break;
case MQTTSN_SUBACK:
_buf[5] = (unsigned char) (msgId / 256);
_buf[6] = (unsigned char) (msgId % 256);
//ptr = _buf + 5;
//writeInt(&ptr, msgId);
break;
default:
break;
}
}
bool MQTTSNPacket::isDuplicate(void)
{
int value = 0;
int p = MQTTSNPacket_decode(_buf, _bufLen, &value);
return (_buf[p + 1] & 0x80);
} }

View File

@@ -22,66 +22,82 @@
namespace MQTTSNGW namespace MQTTSNGW
{ {
class SensorNetwork;
class MQTTSNPacket class MQTTSNPacket
{ {
public: public:
MQTTSNPacket(); MQTTSNPacket(void);
~MQTTSNPacket(); MQTTSNPacket(MQTTSNPacket &packet);
int unicast(SensorNetwork* network, SensorNetAddress* sendTo); ~MQTTSNPacket(void);
int broadcast(SensorNetwork* network); int unicast(SensorNetwork* network, SensorNetAddress* sendTo);
int recv(SensorNetwork* network); int broadcast(SensorNetwork* network);
int serialize(uint8_t* buf); int recv(SensorNetwork* network);
int desirialize(unsigned char* buf, unsigned short len); int serialize(uint8_t* buf);
int getType(void); int desirialize(unsigned char* buf, unsigned short len);
unsigned char* getPacketData(void); int getType(void);
int getPacketLength(void); unsigned char* getPacketData(void);
const char* getName(); int getPacketLength(void);
const char* getName();
int setConnect(void); // Debug int setConnect(void); // Debug
int setADVERTISE(uint8_t gatewayid, uint16_t duration); int setADVERTISE(uint8_t gatewayid, uint16_t duration);
int setGWINFO(uint8_t gatewayId); int setGWINFO(uint8_t gatewayId);
int setCONNACK(uint8_t returnCode); int setCONNACK(uint8_t returnCode);
int setWILLTOPICREQ(void); int setWILLTOPICREQ(void);
int setWILLMSGREQ(void); int setWILLMSGREQ(void);
int setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* TopicName); int setREGISTER(uint16_t topicId, uint16_t msgId, MQTTSNString* TopicName);
int setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode); int setREGACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode);
int setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId, int setPUBLISH(uint8_t dup, int qos, uint8_t retained, uint16_t msgId,
MQTTSN_topicid topic, uint8_t* payload, uint16_t payloadlen); MQTTSN_topicid topic, uint8_t* payload, uint16_t payloadlen);
int setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode); int setPUBACK(uint16_t topicId, uint16_t msgId, uint8_t returnCode);
int setPUBREC(uint16_t msgId); int setPUBREC(uint16_t msgId);
int setPUBREL(uint16_t msgId); int setPUBREL(uint16_t msgId);
int setPUBCOMP(uint16_t msgId); int setPUBCOMP(uint16_t msgId);
int setSUBACK(int qos, uint16_t topicId, uint16_t msgId, uint8_t returnCode); int setSUBACK(int qos, uint16_t topicId, uint16_t msgId,
int setUNSUBACK(uint16_t msgId); uint8_t returnCode);
int setPINGRESP(void); int setUNSUBACK(uint16_t msgId);
int setDISCONNECT(uint16_t duration); int setPINGRESP(void);
int setWILLTOPICRESP(uint8_t returnCode); int setDISCONNECT(uint16_t duration);
int setWILLMSGRESP(uint8_t returnCode); int setWILLTOPICRESP(uint8_t returnCode);
int setWILLMSGRESP(uint8_t returnCode);
int getSERCHGW(uint8_t* radius); int setCONNECT(MQTTSNPacket_connectData* options);
int getCONNECT(MQTTSNPacket_connectData* option); int setPINGREQ(MQTTSNString* clientId);
int getCONNACK(uint8_t* returnCode);
int getWILLTOPIC(int* willQoS, uint8_t* willRetain, MQTTSNString* willTopic); int getSERCHGW(uint8_t* radius);
int getWILLMSG(MQTTSNString* willmsg); int getCONNECT(MQTTSNPacket_connectData* option);
int getREGISTER(uint16_t* topicId, uint16_t* msgId, MQTTSNString* topicName); int getCONNACK(uint8_t* returnCode);
int getREGACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode); int getWILLTOPIC(int* willQoS, uint8_t* willRetain,
int getPUBLISH(uint8_t* dup, int* qos, uint8_t* retained, uint16_t* msgId, MQTTSNString* willTopic);
MQTTSN_topicid* topic, unsigned char** payload, int* payloadlen); int getWILLMSG(MQTTSNString* willmsg);
int getPUBACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode); int getREGISTER(uint16_t* topicId, uint16_t* msgId,
int getACK(uint16_t* msgId); MQTTSNString* topicName);
int getSUBSCRIBE(uint8_t* dup, int* qos, uint16_t* msgId, MQTTSN_topicid* topicFilter); int getREGACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode);
int getUNSUBSCRIBE(uint16_t* msgId, MQTTSN_topicid* topicFilter); int getPUBLISH(uint8_t* dup, int* qos, uint8_t* retained, uint16_t* msgId,
int getPINGREQ(void); MQTTSN_topicid* topic, unsigned char** payload, int* payloadlen);
int getDISCONNECT(uint16_t* duration); int getPUBACK(uint16_t* topicId, uint16_t* msgId, uint8_t* returnCode);
int getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain, MQTTSNString* willTopic); int getACK(uint16_t* msgId);
int getWILLMSGUPD(MQTTSNString* willMsg); int getSUBSCRIBE(uint8_t* dup, int* qos, uint16_t* msgId,
char* getMsgId(char* buf); MQTTSN_topicid* topicFilter);
char* print(char* buf); int getUNSUBSCRIBE(uint16_t* msgId, MQTTSN_topicid* topicFilter);
int getPINGREQ(void);
int getDISCONNECT(uint16_t* duration);
int getWILLTOPICUPD(uint8_t* willQoS, uint8_t* willRetain,
MQTTSNString* willTopic);
int getWILLMSGUPD(MQTTSNString* willMsg);
bool isAccepted(void);
bool isDuplicate(void);
bool isQoSMinusPUBLISH(void);
char* getMsgId(char* buf);
int getMsgId(void);
void setMsgId(uint16_t msgId);
char* print(char* buf);
private: private:
unsigned char* _buf; // Ptr to a packet data unsigned char* _buf; // Ptr to a packet data
int _bufLen; // length of the packet data int _bufLen; // length of the packet data
}; };
} }

View File

@@ -12,6 +12,7 @@
* *
* Contributors: * Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
* Tieto Poland Sp. z o.o. - Gateway improvements
**************************************************************************************/ **************************************************************************************/
#include "MQTTSNGWDefines.h" #include "MQTTSNGWDefines.h"
@@ -20,12 +21,16 @@
#include "MQTTGWPacket.h" #include "MQTTGWPacket.h"
#include "MQTTSNGWClient.h" #include "MQTTSNGWClient.h"
#include "MQTTSNGWProcess.h" #include "MQTTSNGWProcess.h"
#include "MQTTSNGWAdapterManager.h"
#include "MQTTGWConnectionHandler.h" #include "MQTTGWConnectionHandler.h"
#include "MQTTGWPublishHandler.h" #include "MQTTGWPublishHandler.h"
#include "MQTTGWSubscribeHandler.h" #include "MQTTGWSubscribeHandler.h"
#include "MQTTSNGWConnectionHandler.h" #include "MQTTSNGWConnectionHandler.h"
#include "MQTTSNGWPublishHandler.h" #include "MQTTSNGWPublishHandler.h"
#include "MQTTSNGWSubscribeHandler.h" #include "MQTTSNGWSubscribeHandler.h"
#include "Timer.h"
#include "MQTTSNAggregateConnectionHandler.h"
#include <string.h> #include <string.h>
using namespace std; using namespace std;
@@ -33,20 +38,24 @@ using namespace MQTTSNGW;
#define EVENT_QUE_TIME_OUT 2000 // 2000 msecs #define EVENT_QUE_TIME_OUT 2000 // 2000 msecs
char* currentDateTime(void); char* currentDateTime(void);
/*===================================== /*=====================================
Class PacketHandleTask Class PacketHandleTask
=====================================*/ =====================================*/
PacketHandleTask::PacketHandleTask(Gateway* gateway) PacketHandleTask::PacketHandleTask(Gateway* gateway)
{ {
_gateway = gateway; _gateway = gateway;
_gateway->attach((Thread*)this); _gateway->attach((Thread*) this);
_mqttConnection = new MQTTGWConnectionHandler(_gateway); _mqttConnection = new MQTTGWConnectionHandler(_gateway);
_mqttPublish = new MQTTGWPublishHandler(_gateway); _mqttPublish = new MQTTGWPublishHandler(_gateway);
_mqttSubscribe = new MQTTGWSubscribeHandler(_gateway); _mqttSubscribe = new MQTTGWSubscribeHandler(_gateway);
_mqttsnConnection = new MQTTSNConnectionHandler(_gateway); _mqttsnConnection = new MQTTSNConnectionHandler(_gateway);
_mqttsnPublish = new MQTTSNPublishHandler(_gateway); _mqttsnPublish = new MQTTSNPublishHandler(_gateway);
_mqttsnSubscribe = new MQTTSNSubscribeHandler(_gateway); _mqttsnSubscribe = new MQTTSNSubscribeHandler(_gateway);
_mqttsnAggrConnection = new MQTTSNAggregateConnectionHandler(_gateway);
setTaskName("PacketHandleTask");
} }
/** /**
@@ -54,175 +63,309 @@ PacketHandleTask::PacketHandleTask(Gateway* gateway)
*/ */
PacketHandleTask::~PacketHandleTask() PacketHandleTask::~PacketHandleTask()
{ {
if ( _mqttConnection ) if (_mqttConnection)
{ {
delete _mqttConnection; delete _mqttConnection;
} }
if ( _mqttPublish ) if (_mqttPublish)
{ {
delete _mqttPublish; delete _mqttPublish;
} }
if ( _mqttSubscribe ) if (_mqttSubscribe)
{ {
delete _mqttSubscribe; delete _mqttSubscribe;
} }
if ( _mqttsnConnection ) if (_mqttsnConnection)
{ {
delete _mqttsnConnection; delete _mqttsnConnection;
} }
if ( _mqttsnPublish ) if (_mqttsnPublish)
{ {
delete _mqttsnPublish; delete _mqttsnPublish;
} }
if ( _mqttsnSubscribe ) if (_mqttsnSubscribe)
{ {
delete _mqttsnSubscribe; delete _mqttsnSubscribe;
} }
if (_mqttsnAggrConnection)
{
delete _mqttsnAggrConnection;
}
} }
void PacketHandleTask::run() void PacketHandleTask::run()
{ {
Event* ev = 0; Event* ev = nullptr;
EventQue* eventQue = _gateway->getPacketEventQue(); EventQue* eventQue = _gateway->getPacketEventQue();
Client* client = 0; AdapterManager* adpMgr = _gateway->getAdapterManager();
MQTTSNPacket* snPacket = 0;
MQTTGWPacket* brPacket = 0;
char msgId[6];
memset(msgId, 0, 6);
_advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL); Client* client = nullptr;
MQTTSNPacket* snPacket = nullptr;
MQTTGWPacket* brPacket = nullptr;
char msgId[6];
memset(msgId, 0, 6);
while (true) _advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL);
{
/* wait Event */
ev = eventQue->timedwait(EVENT_QUE_TIME_OUT);
if (ev->getEventType() == EtStop) while (true)
{ {
WRITELOG("%s PacketHandleTask stopped.\n", currentDateTime()); /* wait Event */
delete ev; ev = eventQue->timedwait(EVENT_QUE_TIME_OUT);
return;
}
if (ev->getEventType() == EtTimeout) if (ev->getEventType() == EtStop)
{ {
/*------ Check Keep Alive Timer & send Advertise ------*/ WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName());
if (_advertiseTimer.isTimeup()) delete ev;
{ return;
_mqttsnConnection->sendADVERTISE(); }
_advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL);
}
}
/*------ Handle SEARCHGW Message ---------*/ if (ev->getEventType() == EtTimeout)
else if (ev->getEventType() == EtBroadcast) {
{ /*------ Check Keep Alive Timer & send Advertise ------*/
snPacket = ev->getMQTTSNPacket(); if (_advertiseTimer.isTimeup())
_mqttsnConnection->handleSearchgw(snPacket); {
} _mqttsnConnection->sendADVERTISE();
_advertiseTimer.start(_gateway->getGWParams()->keepAlive * 1000UL);
}
/*------ Handle Messages form Clients ---------*/ /*------ Check Adapters Connect or PINGREQ ------*/
else if (ev->getEventType() == EtClientRecv) adpMgr->checkConnection();
{ }
client = ev->getClient();
snPacket = ev->getMQTTSNPacket();
DEBUGLOG(" PacketHandleTask gets %s %s from the client.\n", snPacket->getName(), snPacket->getMsgId(msgId)); /*------ Handle SEARCHGW Message ---------*/
else if (ev->getEventType() == EtBroadcast)
{
snPacket = ev->getMQTTSNPacket();
_mqttsnConnection->handleSearchgw(snPacket);
}
switch (snPacket->getType()) /*------ Handle Messages form Clients ---------*/
{ else if (ev->getEventType() == EtClientRecv)
case MQTTSN_CONNECT: {
_mqttsnConnection->handleConnect(client, snPacket); client = ev->getClient();
break; snPacket = ev->getMQTTSNPacket();
case MQTTSN_WILLTOPIC:
_mqttsnConnection->handleWilltopic(client, snPacket);
break;
case MQTTSN_WILLMSG:
_mqttsnConnection->handleWillmsg(client, snPacket);
break;
case MQTTSN_DISCONNECT:
_mqttsnConnection->handleDisconnect(client, snPacket);
break;
case MQTTSN_WILLMSGUPD:
_mqttsnConnection->handleWillmsgupd(client, snPacket);
break;
case MQTTSN_PINGREQ:
_mqttsnConnection->handlePingreq(client, snPacket);
break;
case MQTTSN_PUBLISH:
_mqttsnPublish->handlePublish(client, snPacket);
break;
case MQTTSN_PUBACK:
_mqttsnPublish->handlePuback(client, snPacket);
break;
_mqttsnPublish->handleAck(client, snPacket, PUBREC);
break;
case MQTTSN_PUBREL:
_mqttsnPublish->handleAck(client, snPacket, PUBREL);
break;
case MQTTSN_PUBCOMP:
_mqttsnPublish->handleAck(client, snPacket, PUBCOMP);
break;
case MQTTSN_REGISTER:
_mqttsnPublish->handleRegister(client, snPacket);
break;
case MQTTSN_REGACK:
// NOP
break;
case MQTTSN_SUBSCRIBE:
_mqttsnSubscribe->handleSubscribe(client, snPacket);
break;
case MQTTSN_UNSUBSCRIBE:
_mqttsnSubscribe->handleUnsubscribe(client, snPacket);
break;
default:
break;
}
/* Reset the Timer for PINGREQ. */ DEBUGLOG(" PacketHandleTask gets %s %s from the client.\n", snPacket->getName(), snPacket->getMsgId(msgId));
client->updateStatus(snPacket);
}
/*------ Handle Messages form Broker ---------*/ if (adpMgr->isAggregatedClient(client))
else if (ev->getEventType() == EtBrokerRecv) {
{ aggregatePacketHandler(client, snPacket); // client is converted to Aggregater by BrokerSendTask
client = ev->getClient(); }
brPacket = ev->getMQTTGWPacket(); else
DEBUGLOG(" PacketHandleTask gets %s %s from the broker.\n", brPacket->getName(), brPacket->getMsgId(msgId)); {
switch (brPacket->getType()) transparentPacketHandler(client, snPacket);
{ }
case CONNACK:
_mqttConnection->handleConnack(client, brPacket); /* Reset the Timer for PINGREQ. */
break; client->updateStatus(snPacket);
case PINGRESP: }
_mqttConnection->handlePingresp(client, brPacket); /*------ Handle Messages form Broker ---------*/
break; else if (ev->getEventType() == EtBrokerRecv)
case PUBLISH: {
_mqttPublish->handlePublish(client, brPacket); client = ev->getClient();
break; brPacket = ev->getMQTTGWPacket();
case PUBACK: DEBUGLOG(" PacketHandleTask gets %s %s from the broker.\n", brPacket->getName(), brPacket->getMsgId(msgId));
_mqttPublish->handlePuback(client, brPacket);
break; if (client->isAggregater())
case PUBREC: {
_mqttPublish->handleAck(client, brPacket, PUBREC); aggregatePacketHandler(client, brPacket);
break; }
case PUBREL: else
_mqttPublish->handleAck(client, brPacket, PUBREL); {
break; transparentPacketHandler(client, brPacket);
case PUBCOMP: }
_mqttPublish->handleAck(client, brPacket, PUBCOMP); }
break; delete ev;
case SUBACK: }
_mqttSubscribe->handleSuback(client, brPacket); }
break;
case UNSUBACK: void PacketHandleTask::aggregatePacketHandler(Client*client, MQTTSNPacket* packet)
_mqttSubscribe->handleUnsuback(client, brPacket); {
break; switch (packet->getType())
default: {
break; case MQTTSN_CONNECT:
} _mqttsnAggrConnection->handleConnect(client, packet);
} break;
delete ev; case MQTTSN_WILLTOPIC:
} _mqttsnConnection->handleWilltopic(client, packet);
break;
case MQTTSN_WILLMSG:
_mqttsnAggrConnection->handleWillmsg(client, packet);
break;
case MQTTSN_DISCONNECT:
_mqttsnAggrConnection->handleDisconnect(client, packet);
break;
case MQTTSN_WILLTOPICUPD:
_mqttsnConnection->handleWilltopicupd(client, packet);
break;
case MQTTSN_WILLMSGUPD:
_mqttsnConnection->handleWillmsgupd(client, packet);
break;
case MQTTSN_PINGREQ:
_mqttsnAggrConnection->handlePingreq(client, packet);
break;
case MQTTSN_PUBLISH:
_mqttsnPublish->handleAggregatePublish(client, packet);
break;
case MQTTSN_PUBACK:
_mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBACK);
break;
case MQTTSN_PUBREC:
_mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBREC);
break;
case MQTTSN_PUBREL:
_mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBREL);
break;
case MQTTSN_PUBCOMP:
_mqttsnPublish->handleAggregateAck(client, packet, MQTTSN_PUBCOMP);
break;
case MQTTSN_REGISTER:
_mqttsnPublish->handleRegister(client, packet);
break;
case MQTTSN_REGACK:
_mqttsnPublish->handleRegAck(client, packet);
break;
case MQTTSN_SUBSCRIBE:
_mqttsnSubscribe->handleAggregateSubscribe(client, packet);
break;
case MQTTSN_UNSUBSCRIBE:
_mqttsnSubscribe->handleAggregateUnsubscribe(client, packet);
break;
default:
break;
}
}
void PacketHandleTask::aggregatePacketHandler(Client*client, MQTTGWPacket* packet)
{
switch (packet->getType())
{
case CONNACK:
_mqttConnection->handleConnack(client, packet);
break;
case PINGRESP:
_mqttConnection->handlePingresp(client, packet);
break;
case PUBLISH:
_mqttPublish->handleAggregatePublish(client, packet);
break;
case PUBACK:
_mqttPublish->handleAggregatePuback(client, packet);
break;
case PUBREC:
_mqttPublish->handleAggregateAck(client, packet, PUBREC);
break;
case PUBREL:
_mqttPublish->handleAggregatePubrel(client, packet);
break;
case PUBCOMP:
_mqttPublish->handleAggregateAck(client, packet, PUBCOMP);
break;
case SUBACK:
_mqttSubscribe->handleAggregateSuback(client, packet);
break;
case UNSUBACK:
_mqttSubscribe->handleAggregateUnsuback(client, packet);
break;
default:
break;
}
}
void PacketHandleTask::transparentPacketHandler(Client*client, MQTTSNPacket* packet)
{
switch (packet->getType())
{
case MQTTSN_CONNECT:
_mqttsnConnection->handleConnect(client, packet);
break;
case MQTTSN_WILLTOPIC:
_mqttsnConnection->handleWilltopic(client, packet);
break;
case MQTTSN_WILLMSG:
_mqttsnConnection->handleWillmsg(client, packet);
break;
case MQTTSN_DISCONNECT:
_mqttsnConnection->handleDisconnect(client, packet);
break;
case MQTTSN_WILLTOPICUPD:
_mqttsnConnection->handleWilltopicupd(client, packet);
break;
case MQTTSN_WILLMSGUPD:
_mqttsnConnection->handleWillmsgupd(client, packet);
break;
case MQTTSN_PINGREQ:
_mqttsnConnection->handlePingreq(client, packet);
break;
case MQTTSN_PUBLISH:
_mqttsnPublish->handlePublish(client, packet);
break;
case MQTTSN_PUBACK:
_mqttsnPublish->handlePuback(client, packet);
break;
case MQTTSN_PUBREC:
_mqttsnPublish->handleAck(client, packet, PUBREC);
break;
case MQTTSN_PUBREL:
_mqttsnPublish->handleAck(client, packet, PUBREL);
break;
case MQTTSN_PUBCOMP:
_mqttsnPublish->handleAck(client, packet, PUBCOMP);
break;
case MQTTSN_REGISTER:
_mqttsnPublish->handleRegister(client, packet);
break;
case MQTTSN_REGACK:
_mqttsnPublish->handleRegAck(client, packet);
break;
case MQTTSN_SUBSCRIBE:
_mqttsnSubscribe->handleSubscribe(client, packet);
break;
case MQTTSN_UNSUBSCRIBE:
_mqttsnSubscribe->handleUnsubscribe(client, packet);
break;
default:
break;
}
}
void PacketHandleTask::transparentPacketHandler(Client*client, MQTTGWPacket* packet)
{
switch (packet->getType())
{
case CONNACK:
_mqttConnection->handleConnack(client, packet);
break;
case PINGRESP:
_mqttConnection->handlePingresp(client, packet);
break;
case PUBLISH:
_mqttPublish->handlePublish(client, packet);
break;
case PUBACK:
_mqttPublish->handlePuback(client, packet);
break;
case PUBREC:
_mqttPublish->handleAck(client, packet, PUBREC);
break;
case PUBREL:
_mqttPublish->handleAck(client, packet, PUBREL);
break;
case PUBCOMP:
_mqttPublish->handleAck(client, packet, PUBCOMP);
break;
case SUBACK:
_mqttSubscribe->handleSuback(client, packet);
break;
case UNSUBACK:
_mqttSubscribe->handleUnsuback(client, packet);
break;
case DISCONNECT:
client->disconnected(); // Just change Client's status to "Disconnected"
break;
default:
break;
}
} }

Some files were not shown because too many files have changed in this diff Show More