Compare commits

...

562 commits

Author SHA1 Message Date
Denis Knauf 1f53447813
Merge pull request #2 from iot-lab/pr/er-coap-dtls/tinydtls_and_er_coap_integration
Pr/er coap dtls/tinydtls and er coap integration
2018-03-10 22:34:41 +01:00
Denis Knauf 76ccd1ea13
Merge pull request #1 from osdomotics/master
level up
2018-03-10 22:29:08 +01:00
Harald Pichler 3f47cb300b change BUSY to PIN D14 2018-03-08 11:48:17 +01:00
Harald Pichler 0007835a5a bugfix timing 2018-03-08 11:24:20 +01:00
Harald Pichler c8bd1acde2 bugfix timing epaper 2018-03-07 09:25:14 +01:00
harald42 9d2f1715df bugfix init e-paper 2018-03-06 22:58:25 +01:00
harald42 02177f65e1 initial upload 2018-03-06 21:42:44 +01:00
harald42 46430fc77a initial upload 2018-03-05 21:28:35 +01:00
Harald 9da22fbec4
Merge pull request #12 from DenisKnauf/master
leds_off only provided, if PLATFORM_HAS_LEDS is 1, not if defined.
2018-03-02 08:24:53 +01:00
Denis Knauf ca431d2e46 leds_off only provided, if PLATFORM_HAS_LEDS is 1, not if defined. 2018-03-01 20:21:09 +01:00
Harald Pichler 3d255ed6f8 initial upload viewconfig 2018-02-28 16:28:46 +01:00
Christian Ratzenhofer 1c8b438bca Fixup osd examples, contiki prints panid and channel on boot 2018-02-14 18:49:37 +01:00
Christian Ratzenhofer 3de5c47802 pan ID and channel are defined on platform level, not example 2018-02-14 18:07:44 +01:00
Harald Pichler ea04534281 remove panid definition 2018-01-04 15:24:18 +01:00
Harald Pichler e62f254e7e bugfix now work with 8 sensors 2017-12-21 15:02:08 +01:00
Harald Pichler 9377759d3b initial upload 2017-12-20 12:02:58 +01:00
Harald Pichler 59b7f37e26 initial upload 2017-12-20 12:01:50 +01:00
Harald Pichler 7fd5b7a6a7 disable rpl quality 2017-12-20 11:40:37 +01:00
Harald Pichler 94f4b19460 update clock 2017-12-15 14:06:32 +01:00
Ralf Schlatterbeck eb68b98cf5 Also output smooth led on pin 3 2017-12-08 20:35:39 +01:00
harald42 196b169fbe remove unused code 2017-12-02 10:16:02 +01:00
Ralf Schlatterbeck d6618ade1a Add soft-blink LED example 2017-12-01 15:51:15 +01:00
Harald Pichler 9b901dd28e initial upload 2017-11-28 11:04:42 +01:00
Harald Pichler 713ffc33f2 add servo resource 2017-11-17 13:43:35 +01:00
Harald Pichler 2247c673fc add compile cpp files for resources 2017-11-17 13:04:38 +01:00
Harald Pichler a44c16a426 initial upload 2017-11-17 12:57:59 +01:00
Harald Pichler fb5fdca66a update readme 2017-11-16 16:20:05 +01:00
Harald Pichler 89d650d87b remove ifdef, merkur plattform have always battery cputemp and led possibility 2017-11-16 16:17:01 +01:00
Harald Pichler e0482d6d1b add arduino-settingsmanager to regression test 2017-11-16 14:29:35 +01:00
Ralf Schlatterbeck 81598323c6 Add Servo example 2017-11-09 11:07:36 +01:00
Harald Pichler 6695835808 bugfix compile error 2017-11-09 10:59:07 +01:00
Harald Pichler b929b419af initial upload 2017-11-09 08:39:35 +01:00
Marcus Priesch 80388188f7 fixed analog pin & compiling issues 2017-11-05 14:22:13 +01:00
Harald Pichler 502842a30b enable reciever always on 2017-10-20 11:19:46 +02:00
Harald Pichler aa9fc5d817 initial upload 2017-10-20 10:47:48 +02:00
Harald Pichler 1ee36e7429 make it possible to switch reviever always on at compile time 2017-10-19 16:00:03 +02:00
Harald Pichler 15039f6b5d cleanup code 2017-10-19 15:44:11 +02:00
Harald Pichler e93083073c expand to tree htu sensors 2017-10-19 14:28:10 +02:00
Harald Pichler 9355f678e3 rename htu to dhta ... c 2017-10-19 14:10:37 +02:00
Harald Pichler 4d90cd2e3f add dht sensor code 2017-10-19 11:35:46 +02:00
Harald Pichler da8cd47dea add arduino macro microsecondsToClockCycles 2017-10-19 11:34:06 +02:00
Harald Pichler e492974415 add ota resources 2017-10-16 16:01:43 +02:00
Harald Pichler 96c5d12e2a initial upload 2017-10-10 11:31:12 +02:00
Marcus Priesch 965ac84918 added 2017-10-10 00:39:53 +02:00
Harald Pichler 325e41ae6a print partition 2017-10-06 13:40:20 +02:00
Harald Pichler a9cb7ab7be Merge branch 'master' of https://github.com/osdomotics/osd-contiki 2017-10-06 13:34:48 +02:00
Harald Pichler 7fffc50d7c show acrive partition 2017-10-06 13:25:53 +02:00
Marcus Priesch 233cb02993 enabled rpl mesh routing 2017-10-05 17:01:09 +02:00
Marcus Priesch 54b72dcf64 update 2017-10-05 16:57:01 +02:00
Marcus Priesch 8c82ce0722 fixed some issues, added ota-update 2017-10-05 16:56:10 +02:00
Marcus Priesch 86596ac92f moved to apps folder 2017-10-05 16:53:26 +02:00
Marcus Priesch 259827b031 added coap:// links for firefox copper plugin 2017-10-05 16:45:30 +02:00
Harald Pichler 3479303454 enable rpl etx messurement 2017-10-02 16:15:16 +02:00
Harald Pichler 3fb61f7695 initial upload 2017-09-26 16:44:02 +02:00
Harald Pichler dd84558cd6 set default mcu sleep 2017-09-26 14:59:55 +02:00
Harald Pichler 297bd14f7b add enable aes hardwre 2017-09-26 14:15:53 +02:00
Harald Pichler 30de144aea save energy 2017-09-20 14:17:26 +02:00
Harald Pichler 13c22c0c71 cleanup code 2017-09-20 13:53:32 +02:00
Harald Pichler d4790c8ede bugfix set mcusleep value 2017-09-20 13:48:01 +02:00
Harald Pichler 5003aca5c7 add settings manager 2017-09-20 11:17:46 +02:00
Harald Pichler cfeb8036e0 bugfix thisplattform 2017-09-20 10:26:23 +02:00
Harald Pichler 2036cda4d9 add example and todos 2017-09-20 09:25:22 +02:00
Harald Pichler 29190681cc disable debug prints, remove rfchannel coap entry 2017-09-20 08:45:01 +02:00
Harald Pichler ba62fd2dd2 cleanup code and save memory 2017-09-20 06:22:07 +02:00
Harald Pichler ecdd101586 add rfsetings function 2017-09-19 16:40:22 +02:00
Harald Pichler 25d38eba2c remove s command from shell, add if typing disable mcusleep 2017-09-19 11:35:45 +02:00
Harald Pichler 927c0b8eac add start stop mcusleep 2017-09-18 15:05:39 +02:00
Harald Pichler 87f433d657 bugfix startup dont sleep 5sec. 2017-09-14 17:19:53 +02:00
Harald Pichler 0b24e047c5 add s command to disable mcusleep 2017-09-14 16:15:43 +02:00
Harald Pichler 31ec8687e4 add resources-common res-rfchannel 2017-09-13 16:50:53 +02:00
Harald Pichler 8b2ee08d55 add shell macconfig 2017-09-13 13:38:46 +02:00
Harald Pichler aaf1e8b2b1 initial upload 2017-09-12 16:28:05 +02:00
Harald Pichler 6694583291 cleanup code, move shell-merkur to apps/shell; move needed function from extended-rf-api to params 2017-09-12 14:39:38 +02:00
Harald Pichler fedd9cb0d7 bugfix set tx power from shell 2017-09-12 11:12:53 +02:00
Harald Pichler df2b297d91 bugix read tx power 2017-09-10 22:13:07 +02:00
Harald 4127d0993b Update README.md 2017-09-08 13:30:28 +02:00
Harald 11525b74ae Update README.md 2017-09-08 13:25:34 +02:00
Harald 8e23d07de4 Update README.md 2017-09-08 13:21:51 +02:00
Harald Pichler 5f8be3e6ea add Plattform documentation 2017-09-08 11:27:17 +02:00
Harald Pichler 07c21e6e7d add radio functions for settings radio parameter 2017-09-08 10:39:40 +02:00
Harald Pichler df282f348c cleanup code 2017-09-08 08:26:36 +02:00
Harald Pichler 3a560c79f9 change name saveparams to saverfparams 2017-09-07 21:07:24 +02:00
Harald Pichler 64b2750de3 set filter to standard 2017-09-07 16:01:42 +02:00
Harald Pichler a2f8424b74 add shell save parameter txpower, channel, panid 2017-09-07 11:44:54 +02:00
Harald Pichler f368875ea2 add params_save_channel 2017-09-06 16:54:56 +02:00
Harald Pichler 17e0b6f2cc add change cca thresholds 2017-09-05 22:48:57 +02:00
Harald Pichler 2ef7438131 add shell-merkur 2017-09-05 22:24:56 +02:00
Harald Pichler 8c5b66d715 work in progress -> rf settings shell 2017-09-05 16:38:55 +02:00
Harald Pichler 3f6cb4e795 Merge branch 'contiki' 2017-09-05 11:14:11 +02:00
Harald Pichler 7a6bab7b10 add shell comands 2017-09-01 11:18:20 +02:00
Harald Pichler 13c4934a37 bugfix settings mananger read EUI64 from bootloader 2017-08-31 16:06:15 +02:00
Harald Pichler 75e8c162ed initial upload settingsmanager example 2017-08-31 11:23:55 +02:00
Ralf Schlatterbeck 0c3a9c6b5a Fix OTA update
Image 0 did not work. We now get rid of bootloader_backup_irq_table and
do this manually: We may not write to address 0 while an image is
running. So for image 0 we write the lower 8 pages to the backup
address. For all other images (ony image 1 currently) we write to
*both*, the original address *and* the backup address. This is done
because some addresses in the lower 8 pages *are* used at the original
address and the bootloader doesn't (want to) know which addresses are
which.
There are more safeguards now: We refuse to write to the active or
boot_next image (if boot_next is not boot_default). We mark the uploaded
partition as not ok.
Needs latest bootloader with commit ID a5771ae033b57.
2017-08-27 15:00:04 +02:00
Harald Pichler 32afc08622 default programmer usb0 2017-08-24 13:56:24 +02:00
Harald Pichler d62fe15a26 bugfix upload to partition 0 2017-08-24 13:55:21 +02:00
Harald Pichler 3b56d718c6 bugfix make ota *.bin file 2017-08-23 13:19:42 +02:00
Harald Pichler 32bbd0cc71 add compile doku and fix compile warnings 2017-08-23 08:59:04 +02:00
Ralf Schlatterbeck 7ea0e3b933 Fix Makefiles, remove/fix flash targets
The target "flash" and related stuff is now in the platform makefiles.
2017-08-22 22:29:03 +02:00
Ralf Schlatterbeck 12ee7b7e39 Update README
Document resources and fix some outdated information.
2017-08-22 21:09:46 +02:00
Ralf Schlatterbeck cc48b88713 New method for determining active partition 2017-08-22 20:20:07 +02:00
Ralf Schlatterbeck 406fb7ea44 Add linker script
Also get rid of genbackupisr hack: We can achieve the same thing with
avr-objcopy which doesn't need additional software.
We use the new bootloader setting for irq-save area of 0x800.
2017-08-22 10:13:36 +02:00
Ralf Schlatterbeck edc7a59091 New make environment for new bootloader
Compatible with old bootloader. Adds an additional section with a copy
of the interrupt vector table to the end of the image. This is needed by
the new bootloader and should be ok for the old bootloader.

Note that for this to work, everybody needs python installed with
the IntelHex python package. On Linux this can be achieved with

pip install IntelHex
2017-08-20 20:57:17 +02:00
Ralf Schlatterbeck d890a492bb Set arduino LOOP_INTERVAL in project-conf.h 2017-08-20 19:42:42 +02:00
Ralf Schlatterbeck 3defa16553 Output min and max address on stderr 2017-08-20 19:41:34 +02:00
Ralf Schlatterbeck 6141e26999 Allow a second upload, reset state 2017-08-20 16:43:11 +02:00
Ralf Schlatterbeck dd9ba9e0ef Add missing resources.h 2017-08-20 15:09:22 +02:00
Ralf Schlatterbeck e3784fa9c7 Add query parameter to generic resouce macros
Modify all callback functions to use new signature.
ota-update now uses this to pass the partition to some get/put methods.
2017-08-20 15:01:30 +02:00
Ralf Schlatterbeck 954da749eb Factor irq methods
Now methods that need interrupts turned off are wrapped.
Make genbackupisr.py executable.
New resources for bootloader-related information.
2017-08-20 11:47:13 +02:00
Marcus Priesch 6eced34422 fixed size_t, irq 2017-08-20 00:12:57 +02:00
Marcus Priesch 140f43f4c1 work in progress 2017-08-19 22:11:13 +02:00
Ralf Schlatterbeck ed638a5f5a Add genbackupisr 2017-08-19 21:05:39 +02:00
Ralf Schlatterbeck b774d61713 First sketch of image uploader 2017-08-19 19:26:27 +02:00
Harald Pichler bfdae2a7a7 bugfix compile example settings-example 2017-08-16 16:13:34 +02:00
Marcus Priesch 0859e3442c added 2017-08-08 14:36:44 +02:00
Harald Pichler 5e20a17131 initial upload 2017-08-07 15:46:53 +02:00
Harald Pichler f576ef27ce update redme 2017-08-02 10:26:54 +02:00
Ralf Schlatterbeck c35be7c066 First stab at OTA-update
Introduce new testing-app example.
Add a new coap error code for blockwise transfer.
Add include-file for bootloader callbacks (jumptable).
Note that only the bootloader for osd-merkur-256 will support
OTA-update, the -128 simply has not enough flash memory, so only
in the -256 we have the bootloader functions in the jump-table
of the bootloader and in the bootloader-if.h include-file.
2017-07-31 13:26:29 +02:00
Marcus Priesch 1a57b55d8f added bootloader_write_page_to_flash symbol 2017-07-30 13:05:09 +02:00
Marcus Priesch 1384aad51a fixed leds 2017-07-30 13:04:56 +02:00
Ralf Schlatterbeck 181e2c436e Add description of new H-brigde breakout-board 2017-07-29 14:42:13 +02:00
Harald Pichler fd442fb9da set direction 2017-07-25 20:16:55 +02:00
George Oikonomou 719f712307 Merge pull request #2259 from arurke/cc26xxcc13xx_uart_optional_txrx_support
CC26xx/CC13xx: Support uni-directional UART
2017-07-23 14:06:50 +01:00
Harald Pichler 4b1580cc70 init arduino pwm driver 2017-07-21 13:31:44 +02:00
Harald Pichler a6670d99a8 set speed 2017-07-20 17:00:16 +02:00
Harald Pichler 38430ac259 set speed 2017-07-20 16:26:38 +02:00
Harald Pichler 60c6495fa3 initial upload 2017-07-20 15:16:01 +02:00
Harald Pichler 578dbaa431 add joystick, add BB-L Bridge 2017-07-20 15:14:45 +02:00
Harald Pichler 223ea26eb4 add led bar 2017-07-20 14:03:42 +02:00
Harald Pichler c39e10b2e7 initial upload 2017-07-20 10:33:19 +02:00
Andreas Urke 770bbfc6f6 Allow UART TX or RX to not be configured 2017-06-30 02:50:24 +02:00
Nicolas Tsiftes a08fc6a381 Merge pull request #2251 from arurke/RPL_debug_cleanup
Minor cleanup to RPL debug output
2017-06-22 16:41:55 +02:00
Andreas Urke a986ecf7c3 Remove minor duplicates in RPL printouts 2017-06-22 15:52:43 +02:00
Nicolas Tsiftes f0bddb277c Merge pull request #2203 from herjulf/AES128HW
Atmel radio AES128 crypto engine support.
2017-06-22 14:14:17 +02:00
Andreas Urke 5c0094cbd6 Minor cleanup to RPL debug output 2017-06-17 23:32:04 +02:00
Robert Olsson e97f3bca26 Fix misspelled copyright for AES128HW_test pointed out by Nicolas Tsiftes 2017-06-16 10:48:52 +02:00
Nicolas Tsiftes d53b6ad23e Merge pull request #2249 from nfi/coap-boundary-checks
Added boundary checks when parsing CoAP packets.
2017-06-15 14:56:58 +02:00
Niclas Finne 576ca6457f Added boundary checks when parsing CoAP packets.
Thanks to Stephan Zeisberg for reporting this issue.
2017-06-14 17:00:53 +02:00
George Oikonomou ea4e080bae Merge pull request #2245 from alexstanoev/mqtt-html-sanitize
Validate MQTT broker IP and escape quotes when displaying
2017-06-03 13:28:23 +01:00
alexstanoev 3a53d96526 Validate MQTT broker IP and escape quotes when displaying
This commit implements address validation for the broker address in the MQTT configuration page of the CC26XX web demo example. Additionally, the Type ID, Org ID, Auth Token, Command Type and Event Type ID fields have quotes escaped (" -> ") to prevent XSS/broken page issues when displaying user-sourced input in HTML input fields.
2017-06-03 00:04:01 +01:00
George Oikonomou 6e3387c830 Merge pull request #2244 from contiki-os/revert-2213-mqtt-html-sanitize
Revert "Validate MQTT broker IP and escape quotes when displaying"
2017-06-03 00:00:22 +01:00
George Oikonomou c558e1a559 Revert "Validate MQTT broker IP and escape quotes when displaying" 2017-06-02 23:02:54 +01:00
George Oikonomou 3800cb18a9 Merge pull request #2216 from herjulf/CCA
Atmel radio; Support for RADIO_PARAM_CCA_THRESHOLD plus rf_environment example
2017-06-02 22:40:27 +01:00
George Oikonomou 007f9c9798 Merge pull request #2213 from alexstanoev/mqtt-html-sanitize
Validate MQTT broker IP and escape quotes when displaying
2017-06-02 22:37:53 +01:00
alexstanoev 6b78ee9a4e MQTT: Validate broker IP and escape quotes when displaying
This commit implements address validation for the broker address in the
MQTT configuration page. Additionally, the Type ID, Org ID, Auth Token,
Command Type and Event Type ID fields have quotes escaped (" -> ")
to prevent XSS issues when displaying user-sourced input.
2017-06-02 15:13:58 +01:00
Robert Olsson bb5d5546ce Atmel radio bug fix when setting tx-power. Spotted by Voravit Tanyingyong 2017-06-02 08:42:43 +02:00
Robert Olsson bb90d50ba1 RADIO_PARAM_POWER_MODE for Atmel radio
modified:   cpu/avr/radio/rf230bb/rf230bb.c
	modified:   cpu/avr/radio/rf230bb/rf230bb.h
2017-06-01 17:30:30 +02:00
Simon Duquennoy ed47d47155 Merge pull request #2217 from g-oikonomou/doxy
Fix Doxygen PPA location
2017-06-01 14:22:08 +02:00
Robert Olsson b4ef18b2fa Keep cca scan function separated
modified:   examples/rf_environment/rf_environment.c
2017-05-23 21:07:59 +02:00
Robert Olsson 18cfaf7fa2 Reformat of table text for README
modified:   examples/rf_environment/README.md
2017-05-19 09:28:46 +02:00
Robert Olsson ef9b00103e Optimizing channel table size for CCA in rf_environment example
modified:   examples/rf_environment/rf_environment.c
2017-05-11 14:20:12 +02:00
Robert Olsson 71167f0ba6 Retrigger PR after Doxigen fix 2017-05-09 15:26:14 +02:00
George Oikonomou 9ed56b1485 Fix Doxygen PPA location 2017-05-09 09:11:20 +01:00
Robert Olsson 4040005056 Retrigger regression test
modified:   examples/rf_environment/README.md
2017-05-08 14:25:59 +02:00
Robert Olsson 91928592d0 Updated README for rf_environment example 2017-05-08 13:11:22 +02:00
Robert Olsson 22975df423 examples/rf_environment for rf CCA (non-intrusive) monitoring added 2017-05-05 12:57:18 +02:00
Robert Olsson c2560498b6 Atmel radio; Support for RADIO_PARAM_CCA_THRESHOLD added 2017-05-05 12:55:03 +02:00
Harald Pichler 5e15ec6488 bugfix store value to d_temp_s and enable debug prints as degfault 2017-05-04 16:29:55 +02:00
George Oikonomou 3c150a5e99 Merge pull request #2150 from posjodin/PR2
Several changes to fix and harden mqtt code.
2017-04-24 16:04:56 +01:00
George Oikonomou 3cc5505b69 Merge pull request #1787 from g-oikonomou/contrib/cc26xx/improve-cca-monitoring
Use `ccaInfo.ccaState` to decide whether CCA is complete
2017-04-24 16:02:47 +01:00
George Oikonomou 7b193ee014 Merge pull request #1932 from g-oikonomou/contrib/cc1350/lp-and-st
Add support for the CC1350 LP and Sensortag
2017-04-24 15:34:22 +01:00
George Oikonomou 6a36a398bd Merge pull request #1931 from g-oikonomou/contrib/cc26xx-cc13xx/update-rf-api
Use TI-Provided CC13xx/CC26xx RF API
2017-04-24 15:33:14 +01:00
Robert Olsson e9aed001bc Example project for Atmel radio AES128 cryto engine 2017-04-24 14:40:33 +02:00
Robert Olsson 58517dfcbd AES128 HW crypto engine support for Atmel radios
modified:   cpu/avr/radio/rf230bb/atmega128rfa1_registermap.h
modified:   cpu/avr/radio/rf230bb/atmega256rfr2_registermap.h
modified:   cpu/avr/radio/rf230bb/rf230bb.c
modified:   cpu/avr/radio/rf230bb/rf230bb.h
2017-04-24 14:34:01 +02:00
Nicolas Tsiftes ddf723f88d Merge pull request #2180 from atiselsts/bugfix/coap-observe-option
Keep CoAP 'observe' option length <= 3 bytes
2017-04-21 17:59:40 +02:00
Nicolas Tsiftes 66fe7abf79 Merge pull request #2188 from tonnenpinguin/pr/uninitialized_variables
Fix several uninitialized variables
2017-04-21 17:59:12 +02:00
Bernhard Hackl 848f801460 Fix several uninitialized variables 2017-04-19 01:55:27 -07:00
Nicolas Tsiftes 38b82aeeeb Merge pull request #2189 from tonnenpinguin/pr/unterminated_strings
Fix potentially unterminated strings
2017-04-18 16:39:34 +02:00
Nicolas Tsiftes 52c709bdb7 Merge pull request #2101 from yatch/pr/bugfix-rpl-icmp6
RPL: fix a bug accessing an uninitialized pointer
2017-04-18 16:09:06 +02:00
Nicolas Tsiftes 391a84726f Merge pull request #2148 from niziak/master
native-border-router: fix for disappearing timer 'uip_ds6_timer_perio…
2017-04-18 15:19:57 +02:00
Bernhard Hackl ae91d6b4b1 Fix potentially unterminated strings 2017-04-14 08:33:40 -07:00
Peter Sjödin a08adccfd5 Untabify mqtt.c 2017-04-11 17:19:43 +02:00
Peter 1fa9dde049 Merge remote-tracking branch 'contiki/master' into PR2 2017-04-11 17:00:38 +02:00
Oliver Schmidt 078359127b Merge pull request #2182 from oliverschmidt/master
Adjusted cc65 compiler options to recent cc65 option handling change.
2017-04-10 11:46:08 +02:00
Oliver Schmidt fa618ad86c Adjusted cc65 compiler options to recent cc65 option handling change. 2017-04-10 11:09:28 +02:00
Atis Elsts f83f035855 Keep CoAP 'observe' option length <= 3 bytes 2017-04-08 15:02:52 +01:00
George Oikonomou d0ddb7221e Merge pull request #2176 from atiselsts/bugfix/hdc_sensor
Fix HDC sensor reading conversion
2017-04-08 00:11:05 +01:00
Nicolas Tsiftes 0b85b76778 Merge pull request #2173 from simonduq/pr/tsch-readme
Updating TSCH readme file
2017-04-06 16:06:29 +02:00
Atis Elsts f6a2c4ea3f Fix HDC sensor reading conversion 2017-04-05 12:23:26 +01:00
Simon Duquennoy a330f59b8e TSCH readme: update with 802.15.4-2015 and 6TiSCH 2017-04-04 14:15:48 +02:00
Simon Duquennoy 51205eb809 TSCH readme: link to reference paper on implem and eval 2017-04-04 14:12:35 +02:00
George Oikonomou fbffcc2dfc Merge pull request #2109 from chenek/cc26xx-web-demo-adc-demo
add ADC example to cc26xx-web-demo
2017-04-03 12:21:03 +01:00
Yasuyuki Tanaka faeb71de00 RPL: fix a bug accessing an uninitialized pointer
This bug is uncovered when RPL_WITH_MULTICAST is enabled.
2017-04-03 17:54:25 +09:00
Yasuyuki Tanaka 3559402781 RPL: add regression test for multicast
This test aims to reproduce the issue #2031:

  https://github.com/contiki-os/contiki/issues/2031

Test nodes are built from the code under example/ipv6/multicast with
WITH_SMRF=1 and WITH_DAO_ACK=1.

If the simulation runs through for one hour, the test is regarded as
success. Otherwise, when it crashes, the test fails.
2017-04-03 17:54:18 +09:00
Yasuyuki Tanaka b7b23b712f RPL: fix indentation (rpl-icmp6.c) 2017-04-03 17:52:58 +09:00
George Oikonomou e9ee15efde Merge pull request #2166 from posjodin/TSCH-N1
Updates for Atmel radio part II
2017-04-02 21:31:59 +01:00
George Oikonomou e823ead4b0 Tidy up web demo ADC code style 2017-04-02 13:44:02 +01:00
George Oikonomou 474dc33e12 Wrap web demo ADC functionality inside #if blocks 2017-04-02 13:43:21 +01:00
chenek 22b262ce73 Add ADC example to cc26xx-web-demo 2017-04-02 13:43:12 +01:00
George Oikonomou 55f3a92211 Merge pull request #2168 from tarakanov/sensortag-spi
Correct SPI pins
2017-04-02 13:26:30 +01:00
Robert Olsson aed5457332 Correct names for Atmel previous radio fixes plus static declarations. 2017-04-02 11:32:52 +02:00
tarakanov f564e6bb5f Correct SPI pins 2017-04-02 13:14:09 +05:00
George Oikonomou e4da7c66e0 Merge pull request #2165 from alexandruioanp/check-ipv6addrconv-mqtt
Check broker IP conversion. Adjust state machine accordingly
2017-04-02 00:33:43 +01:00
George Oikonomou 6eac73103d Merge pull request #2164 from alexstanoev/web-demo-crash-fix
Zero out httpd_state before deallocating
2017-04-02 00:32:53 +01:00
George Oikonomou 12f17211e6 Merge pull request #2167 from posjodin/sensniff-new
Adding sensniff support for Atmel via avr-rss2 platform
2017-04-02 00:29:09 +01:00
Robert Olsson 417f32c65d Adding sensniff support for Atmel via avr-rss2 platform 2017-03-31 20:00:20 +02:00
Robert Olsson 093550ecbf Update for Atmel radio part II
modified:   cpu/avr/radio/rf230bb/halbb.c
	modified:   cpu/avr/radio/rf230bb/rf230bb.c
2017-03-31 18:38:27 +02:00
Alexandru-Ioan Pop f15b86158b Check broker IP conversion. Adjust state machine accordingly
The result of converting the IP address of the broker wasn't checked. As a result, the pointer was left uninitialised and the IPv6 address used for connecting was some random data. The function now returns an error. Before connect_to_broker is called, mqtt_register is executed, which memsets conn to 0, making its state 0 (MQTT_CONN_STATE_ERROR). In order to recover from this error state, the extra check was added in the MQTT_CLIENT_STATE_NEWCONFIG state.

This was discovered using [CodeSonar](https://www.grammatech.com/products/codesonar)
2017-03-31 17:33:29 +01:00
alexstanoev a30364189a Zero out httpd_state before deallocating
When a connection is aborted by the HTTP server while it's still being processed it is possible to hit a null pointer dereference issue by jumping back to a protothread (outputpt) after its httpd_state has been freed. This can be triggered by sending a POST to any form in the CC26xx web demo server using Firefox.
This patch prevents that by zeroing out httpd_state structs before freeing them, thus also clearing the httpd_state->outputpt field.
Tested using Firefox 55.0a1 on a CC2650 LaunchPad.
2017-03-31 16:44:11 +01:00
George Oikonomou 4425a67433 Merge pull request #2162 from posjodin/PR4
Updates for  Atmel radio
2017-03-31 12:24:55 +01:00
Nicolas Tsiftes 69c2e7e2b6 Merge pull request #2159 from posjodin/PR3
avr-rss2 platform fixes
2017-03-30 16:30:46 +02:00
Robert Olsson 399150b142 Minor spell fix in ANNOUNCE_BOOT
modified:   platform/avr-rss2/contiki-main.c
2017-03-30 15:24:19 +02:00
Nicolas Tsiftes 9d003fe52f Merge pull request #2155 from iot-lab/pr/er-coap/stylecleanup
er-coap: Fix style and add missing `addr` argument
2017-03-30 14:14:03 +02:00
Robert Olsson d6128852b2 Added missing register definitions in at86rf230_registermap.h
modified:   cpu/avr/radio/rf230bb/at86rf230_registermap.h
2017-03-29 11:32:39 +02:00
Robert Olsson 55daec98dc Added missing registers in
modified:   cpu/avr/radio/rf230bb/atmega128rfa1_registermap.h
2017-03-28 22:16:50 +02:00
Robert Olsson 94defe6ba2 Updates for Atmel RF233 radio in AtMega256rfr2 including register
update for MAC symbol counter. Basic functions for get/set-value
parameter setting added. SPI radios needs to be tested.

	modified:   cpu/avr/radio/rf230bb/atmega256rfr2_registermap.h
	modified:   cpu/avr/radio/rf230bb/rf230bb.c
2017-03-28 18:53:56 +02:00
Ralf Schlatterbeck dca85a7b6b Add valve example
Used for gardena valves with 9V power supply.
2017-03-24 20:10:37 +01:00
Robert Olsson 3829dd2f20 Leds toggle added
modified:   platform/avr-rss2/dev/leds.c
2017-03-24 17:37:37 +01:00
Robert Olsson e77dba152d Removing avr-rss2 private sniffer app. Better use examples/sensniff. 2017-03-24 17:29:50 +01:00
Robert Olsson bf8e77ea4e Added missing prototype
modified:   cpu/avr/radio/rf230bb/rf230bb.h
2017-03-24 17:07:35 +01:00
Robert Olsson c0239b41c9 Cleand-up _CONF for ROUTES, NEIGHBOR and BUFFER_SIZE
modified:   platform/avr-rss2/contiki-conf.h
2017-03-24 16:57:53 +01:00
Robert Olsson e09bdc0c07 Increasing route table from 4 to 20
modified:   platform/avr-rss2/examples/ipv6/mqtt-demo/project-conf.h
2017-03-24 16:57:27 +01:00
Robert Olsson 29914b5a1f Fixing input serial line initialization pointed by Peter Sjödin/KTH
For avr-rss2 platform
2017-03-24 16:57:03 +01:00
Peter Sjödin fa6c52633f Use RS232_BAUDRATE to define baudrate from projekt config file.
Removed serial initialization from contiki-main.c. It seems to be
too soon.
2017-03-24 16:56:42 +01:00
Robert Olsson 9e5aed5df6 Support for changing PANID and channel from project-conf.h
modified:   cpu/avr/radio/rf230bb/rf230bb.c
	modified:   platform/avr-rss2/contiki-conf.h
	modified:   platform/avr-rss2/contiki-main.c
2017-03-24 16:56:22 +01:00
Harald Pichler c56142ccec add save energie 2017-03-24 16:11:28 +01:00
Harald Pichler afde635051 initial upload 2017-03-24 11:08:45 +01:00
Gaëtan Harter c7de205029 er-coap/dtls: allow overwriting the default tinydtls specific functions 2017-03-23 17:23:22 +01:00
Gaëtan Harter 1addd8da3a apps/tinydtls: disable doxygen generation 2017-03-23 16:33:25 +01:00
Gaëtan Harter e24f500e57 er-rest-dtls: add rest dtls examples 2017-03-23 16:33:25 +01:00
Gaëtan Harter fcc4f6d39f er-coap-dtls: use tinydtls app if "WITH_DTLS_COAP" is set 2017-03-23 16:33:25 +01:00
Gaëtan Harter 59dc4413bb er-coap-dtls: rename wrongly name IDENTITY_"HINT"
It's not IDENTITY_HINT but only IDENTITY here.
IDENTITY_HINT is not handled in any ways.
2017-03-23 16:33:25 +01:00
Gaëtan Harter 612cb23759 er-coap: COPIED FROM CETIC 6LBR add cetic tinydtls 'er-coap' communication layer
I would rather have a different way of configuring the communication layer.
A way which would not require modifiying the er-coap application.

Maybe more like a "disable udp" communication layer thing.
And overwrite with something else.
2017-03-23 16:32:44 +01:00
Gaëtan Harter d94efe528a tinydtls: add tinydtls as an app submodule
Currently, I'm providing my version for the submodule, but patches have been
proposed upstream to make tinydtls work out of the box.
2017-03-23 16:30:27 +01:00
Gaëtan Harter 5640293e8f er-coap: separate the communication layer
This code was copied and adapted from: https://github.com/cetic/6lbr
Licensed under the same license as Contiki.
2017-03-23 15:33:50 +01:00
Gaëtan Harter f70adde9a9 er-coap-observe-client: missing 'addr' parameter 2017-03-23 15:12:42 +01:00
Gaëtan Harter c932ff45a3 er-coap: run uncrustify-fix-style.sh
Clean style before modifying.
2017-03-23 15:12:39 +01:00
Nicolas Tsiftes 7342a3f8a7 Merge pull request #2103 from stringr9/bugfix/non-storing-drop-fix
Don't drop packets bound for outside the RPL mesh in non-storing mode
2017-03-23 14:27:06 +01:00
Nicolas Tsiftes 90ea58e206 Merge pull request #2145 from g-oikonomou/bugfix/multicast-config
Don't force RPL MOP configuration in contiki-default-conf.h
2017-03-23 13:43:08 +01:00
Robert Olsson 34fa389054 Whitespace change to force new travis-check.
modified:   apps/mqtt/mqtt.h
2017-03-22 13:15:58 +01:00
Peter 432f12e156 Several changes to fix bugs and harden mqtt code.
1. The PT_MQTT_WAIT_SEND() macro has several issues:

- It does not check the return value from process_post(), which
  sometimes returns an error code. See next issue.

- Each time the macro is called, is posts an event to itself. The idea
seems to be that the event should be absorbed by the macro itself, so
when the macro terminates there is NOT a net growth of the event
queue. This does not work.  The reason is that the
PROCESS_WAIT_EVENT() sometimes absorbs a broadcast event instead of
its own event, and then the number of events in the event queue
increases. This leads to event explosions and overflow in the event
queue.

- The macro cannot call PT_EXIT(). This will expand to a return
statement, causing a return from the function calling the macro
(mqtt_process), rather then exiting the protothread (which was
probably the intention). Protothreads have lexical scope...

Fixes: 1) Check return value from process_post() 2) Loop until the
event posted to itself is absorbed (rather than just absorbing the
next event) 3) Replace PT_EXIT() with PT_INIT() (doesn't really make a
difference, could probably just be removed).

2. Change order of the checks in the protothread-calling loops in
mqtt_process().  Reason: When a protothread has been cleared by
PT_MQTT_WAIT_SEND(), it will not return a value, so checking against
PT_EXITED does not make sense.

3. PT_MQTT_WRITE_BYTES() should initialize conn->out_write_pos to 0.
When PT_MQTT_WRITE_BYTES() does not finish (due to TCP disconnect for
instance), it may leave conn->out_write_pos with a non-zero
value. Next time PT_MQTT_WRITE_BYTES() is called, it will take data
from the wrong place.

4. Put MQTT_CONN_STATE_ABORT_IMMEDIATE before
MQTT_CONN_STATE_NOT_CONNECTED in the enum list, so that the check
if(conn->state > MQTT_CONN_STATE_NOT_CONNECTED) in mqtt_connect()
fails when in state MQTT_CONN_STATE_ABORT_IMMEDIATE. Otherwise, it
will deadlock and not reattempt connections while in this state.
2017-03-21 16:43:15 +01:00
Wojciech Nizinski 5a0d085451 native-border-router: fix for disappearing timer 'uip_ds6_timer_periodic'
When UIP_ND6_SEND_NS is enabled, I've noticed that unreachable
neighbours still remains in REACHABLE state even if lifetime
(nbr->reachable) expired.

During network init 'tcpip_process' is scheduling
'uip_ds6_timer_periodic' is to tick every 100ms and make necessary
expirations.

When MAC addres is received from slip-radio (from 'etimer_process'
context), network is "reinitialized" and timer 'uip_ds6_timer_periodic'
is set again with wrong process.
2017-03-21 13:13:10 +01:00
Harald Pichler 0e861e76a3 Merge branch 'master' of https://github.com/osdomotics/osd-contiki 2017-03-18 20:43:10 +01:00
Harald Pichler 918b20f3cf set loop to 30 2017-03-18 20:42:47 +01:00
George Oikonomou 99402348eb Merge pull request #2147 from g-oikonomou/bugfix/1972
Add missing variable declaration
2017-03-18 17:23:41 +00:00
Oliver Schmidt 356814fe9c Merge pull request #2146 from oliverschmidt/slip
Add SLIP support to retro platforms.
2017-03-18 15:56:06 +01:00
George Oikonomou 739b901e0d Add missing variable declaration
#1972 removed the declaration of `i` from various locations. In one of those locations it is still needed. This commit puts it back
2017-03-18 14:01:10 +00:00
George Oikonomou 758d9aa168 Merge pull request #1972 from MohamedSeliem/patch-11
update httpd_cgi to enable the compilation of webserver-ipv6 example
2017-03-18 13:50:52 +00:00
Oliver Schmidt 7f3fcbd8e7 Made it somewhat more obvious that this is SLIP-only. 2017-03-18 14:19:36 +01:00
George Oikonomou dc782732e0 Merge pull request #2132 from JoaoS/energest_avr_rss2
add CPU energest measurements that were lacking in this platform
2017-03-18 13:17:51 +00:00
Oliver Schmidt a0134ff35e Beautified SLIP macros. 2017-03-18 14:06:11 +01:00
Oliver Schmidt 79855ff02d Beautified SLIP macros. 2017-03-18 14:05:36 +01:00
George Oikonomou 6d51c1a9f9 Merge pull request #2138 from atiselsts/bugfix/cc26xx/limited_busywait
CC26xx IEEE mode driver fixes and robustness improvements
2017-03-17 23:09:11 +00:00
George Oikonomou 905356da13 Merge pull request #2093 from thomas-blank/fix-mqtt-connection-refused
Fix Bug in MQTT App: Refused Connections should not be pursued.
2017-03-17 23:08:45 +00:00
George Oikonomou 21d6abe30b Merge pull request #2139 from atiselsts/sensortag-i2c/limited_busywait
CC26xx SensorTag I2C: add and use LIMITED_BUSYWAIT macro
2017-03-17 23:04:19 +00:00
George Oikonomou b91448dfa4 Merge pull request #1348 from g-oikonomou/bugfix/cc26xx/wait-for-rssi-valid
Wait for a valid RSSI reading in CC13xx/CC26xx RF drivers
2017-03-17 22:52:51 +00:00
George Oikonomou 7e6d5c2971 Don't force RPL MOP configuration in contiki-default-conf.h
rpl-private.h handles the default MOP correctly, whereas the block in `contiki-default-conf.h` is not only redundant but also fails to handle situations where RPL multicast is required.
2017-03-17 22:33:17 +00:00
George Oikonomou fbb682ae15 Merge pull request #2144 from MohamedSeliem/patch-12
fix a macro related to multicast, which are not user configuration
2017-03-17 22:19:49 +00:00
Ralf Schlatterbeck 3545f1fab5 Update README and LICENSE
Add comments about new Github Terms of Service (new since 2017-03-01)
and clarify the purpose of this project, point to LICENSE file in
README.md
2017-03-17 19:32:51 +01:00
Mohamed Seliem 08b12f2346 fix a macro related to multicast, which are not user configuration
fix a macro related to multicast, which are not user configuration
- RPL_CONF_MULTICAST      -> RPL_WITH_MULTICAST
2017-03-17 20:21:56 +02:00
Atis Elsts a0a2881ab0 CC26xx SensorTag I2C: add and use LIMITED_BUSYWAIT macro 2017-03-14 18:52:10 +00:00
Atis Elsts c850bae186 CC26xx IEEE mode: introduce and use LIMITED_BUSYWAIT macro; avoids watchdog reboots in cases when the radio fails to turn off 2017-03-14 18:42:09 +00:00
Atis Elsts 3b090d97c7 CC26xx IEEE mode: more robust radio timer handling: do not crash the system in case the radio timer failed to start; allow the overflow checker to be called when the radio is off 2017-03-14 18:41:05 +00:00
Atis Elsts dbd9d32daf CC26xx RF core: don't bail out from restarting the radio timer if just stopping it failed 2017-03-14 18:36:23 +00:00
root cc4aa440a0 moved energest init to after the rtimer init 2017-03-13 13:54:40 +00:00
Nicolas Tsiftes b756841522 Merge pull request #2102 from yatch/pr/rpl-leaf-only-debug-msg
RPL: move a debug message for RPL_LEAF_ONLY to a correct place
2017-03-10 15:11:31 +01:00
Thomas Blank ed1b27e40b Fix Bug in MQTT App: Refused Connections should not be pursued.
No means no.
2017-03-09 19:35:20 +01:00
Simon Duquennoy a24ac862de Merge pull request #2046 from yatch/pr/ringbufindex-bugfix
Bugfix in ringbufindex
2017-03-09 13:06:33 +01:00
Simon Duquennoy c5c1979d37 Merge pull request #2012 from cetic/jn516-hw-mac
JN516x: Add support for hardware MAC
2017-03-09 08:53:47 +01:00
Yasuyuki Tanaka 9acf177036 Enable TSCH regression testing 2017-03-09 16:47:54 +09:00
Yasuyuki Tanaka 2d42b91c7b ringbufindex: fix bugs of ringbufindex_peek_{put,get} 2017-03-09 16:47:24 +09:00
Yasuyuki Tanaka fbf9bb9e64 ringbufindex: explain return values by the APIs 2017-03-09 16:47:24 +09:00
Yasuyuki Tanaka baaa3da23e ringbufindex: fix a typo in a comment 2017-03-09 16:47:24 +09:00
Yasuyuki Tanaka 8df0f7dd01 Add a regression test for ringbufindex APIs 2017-03-09 16:47:24 +09:00
George Oikonomou b70677cce6 Merge pull request #2131 from t-than/master
Adjust CC26xx/CC13xx ADC reading for gain and offset
2017-03-08 22:18:57 +00:00
root 42cbe85a49 add CPU energest measurements that were lacking in this platform 2017-03-08 16:13:27 +00:00
Thanos Tsakiris dbcac67aab Normalize code style with uncrustify 2017-03-08 17:09:53 +02:00
andrewbrannan 0a85ccdc56 prevent the rpl root from dropping packets bound for outside the dodag while in NS mode 2017-03-08 14:34:25 +00:00
Laurent Deru da45afdf27 Add basic contikimac parameters for jn516x 2017-03-08 15:25:55 +01:00
Laurent Deru 79b06879fe Add to jn516x micromac driver full MAC layer support 2017-03-08 15:25:55 +01:00
Laurent Deru 9b6ba3c009 Make frame fcf creation and parsing standalone functions 2017-03-08 15:25:55 +01:00
Simon Duquennoy 0ceb45ee78 Merge pull request #2129 from simonduq/pr/update-jn516x-sdk
jn516x: update SDK
2017-03-08 15:20:31 +01:00
Thanos Tsakiris d80f362a2b Adjust CC26xx/CC13xx ADC reading for gain and offset 2017-03-08 15:55:28 +02:00
Simon Duquennoy 04bce213e6 jn516x: remove redundant declaration 2017-03-08 12:13:37 +01:00
Simon Duquennoy ae554aa256 jn516x: update SDK 2017-03-08 11:24:35 +01:00
Simon Duquennoy c37e7cfb0e Merge pull request #2108 from yatch/pr/poc-tsch-queue-flush-nbr-queue
TSCH: POC of a bug in tsch_queue_flush_nbr_queue()
2017-03-08 10:18:41 +01:00
Harald Pichler 2942868799 bugfix format 2017-03-03 11:45:46 +01:00
Harald Pichler 362eadd821 bugfix format 2017-03-03 11:40:13 +01:00
Harald Pichler 14baf5df6c bugfix format 2017-03-03 11:37:09 +01:00
Harald Pichler c954d22d81 bugfix format 2017-03-03 11:29:32 +01:00
Harald Pichler f36183f2b5 Merge branch 'master' of https://github.com/osdomotics/osd-contiki 2017-03-03 11:26:28 +01:00
Harald Pichler 314c46b91a bugfix format 2017-03-03 11:24:32 +01:00
Harald Pichler 6af70ee511 bugfix warning -Wwrite-strings 2017-03-03 11:21:43 +01:00
Harald Pichler 7000323c74 bugfix format 2017-03-03 11:17:33 +01:00
Oliver Schmidt a38cfc889e Merge pull request #2118 from oliverschmidt/master
Made rest of Microsoft-specific chat optional.
2017-02-24 20:53:55 +01:00
Harald Pichler ae6375d900 add humidity resource, bugfix pressure string variable 2017-02-24 10:28:35 +01:00
Harald Pichler 2137a12971 Merge branch 'master' of https://github.com/osdomotics/osd-contiki 2017-02-24 10:07:20 +01:00
Harald Pichler 4151c09e2c cleanup code 2017-02-23 22:36:32 +01:00
Harald Pichler 6677fac2ab bugfix use bmp280 and not bme280 2017-02-23 22:22:40 +01:00
Oliver Schmidt be9711d92e Made rest of Microsoft-specific chat optional.
Made code rest of the code in the SLIP driver optional that takes care of the Microsoft-specific CLIENT / SERVER / CLIENTSERVER chat.
2017-02-23 21:43:51 +01:00
Harald Pichler 8e07bab71f initial upload 2017-02-23 16:48:37 +01:00
Harald Pichler 85f3814f67 add i2c address 2017-02-23 08:59:49 +01:00
Harald Pichler 42dee52e65 initial upload 2017-02-23 08:49:02 +01:00
Harald Pichler 352f078be7 initial upload 2017-02-22 14:53:05 +01:00
Antonio Lignan f5f13c968c Merge pull request #2061 from cetic/pr-nat64-small-updates
Various updates for NAT64
2017-02-21 21:52:18 +01:00
Harald Pichler 5ea65cab08 temperature convert time is to short set from 50ms to 60ms 2017-02-21 20:06:15 +01:00
George Oikonomou 809ca640a1 Merge pull request #2090 from atiselsts/bugfix/cc26xx_lqi
CC26xx IEEE mode radio: fix LQI reading
2017-02-18 22:25:01 +00:00
Oliver Schmidt 91beb8670f Added SLIP support to retro platforms.
The cc65 tool chain comes with V.24 drivers so it seems reasonable to use the existing Contiki SLIP driver to implement network access via SLIP as alternative to Ethernet.

Some notes:
- The Ethernet configuration was simplified in order to allow share it with SLIP.
- The Contiki SLIP driver presumes an interrupt driven serial receiver to write into the SLIP buffer. However the cc65 V.24 drivers aren't up to that. Therefore the main loops were extended to pull received data from the V.24 buffers and push it into the SLIP buffer.
- As far as I understand the serial sender is supposed to block until the data is sent. Therefore a loop calls the non-blocking V.24 driver until the data is sent.

On all platforms there's only one V.24 driver available. Therefore V.24 drivers are always loaded statically.

On the Apple][ the mouse driver is now loaded statically - independently from SLIP vs. Ethernet. After all there's only one mouse driver available. However there's a major benefit with SLIP: Here all drivers are loaded statically. Therefore the dynamic module loader isn't necessary at all. And without the loader the heap manager isn't necessary at all. This allows for a reduction in code size roughly compensating for the size of the SLIP buffer.
2017-02-15 23:43:28 +01:00
Oliver Schmidt a26ee64dc0 Merge pull request #2097 from oliverschmidt/master
Removed artifacts of former uip_appdata handling.
2017-02-13 20:05:57 +01:00
Yasuyuki Tanaka 8b77c5ef4c TSCH: add a regression test for tsch_queue_flush_nbr_queue() 2017-02-10 17:37:33 +01:00
Yasuyuki Tanaka effdc6e212 TSCH: add debug messages to track queued packet addresses 2017-02-10 16:56:14 +01:00
Yasuyuki Tanaka 25ac43dae9 RPL: move a debug message for RPL_LEAF_ONLY to a correct place 2017-02-08 00:02:26 +01:00
Oliver Schmidt 6463c91a4f Removed artifacts of former uip_appdata handling.
Adam Dunkels writes on 2/5/2017 on the Contiki mailing list:
[...] the original idea was that the application could just point the uip_appdata pointer to wherever the data was, but we then changed it so that the data actually had to be copied into the uip_aligned_buf buffer. So, yes, the network device driver should only need to read from this buffer. [...]

This change removes comments on the possibility of uip_appdata pointing somewhere outside the uip_aligned_buf. And it removes code in the SLIP drivers not necessary anymore.

Additionally it makes code in a SLIP driver optional that takes care of the Microsoft-specific CLIENT / SERVER / CLIENTSERVER chat.
2017-02-05 23:20:39 +01:00
Simon Duquennoy 263af6f642 Merge pull request #2023 from OpenMote/master
Adding support for OpenMote-CC2538 Rev.A1 and OpenUSB
2017-02-02 08:47:07 +01:00
Harald Pichler 201a8174c6 print buffer text and hex format 2017-02-01 16:17:48 +01:00
Harald Pichler 6a9b6ae77b initial upload 2017-02-01 11:26:50 +01:00
Harald Pichler 9fb2352b08 bugfix buffer overflow 2017-02-01 10:28:02 +01:00
Harald Pichler 2f8549aaae Merge branch 'contiki'
Conflicts:
	cpu/cc26xx-cc13xx/lib/cc13xxware
	cpu/cc26xx-cc13xx/lib/cc26xxware
2017-01-31 15:00:59 +01:00
Oliver Schmidt 8248f524f5 Merge pull request #2091 from oliverschmidt/master
Revert to static Ethernet driver for the ATARI.
2017-01-27 11:34:44 +01:00
Oliver Schmidt a6472c8dd9 Revert to static Ethernet driver for the ATARI.
After all there's no momentum for a W5100-based Ethernet solution on the ATARI. So I revert to static linkage of the CS8900A driver as this improves program load times.
2017-01-27 00:18:25 +01:00
Atis Elsts cd1bcb101d CC26xx IEEE mode radio: fix reading lqi 2017-01-26 13:31:15 +00:00
George Oikonomou 7b7781360f Merge pull request #2071 from g-oikonomou/bugfix/cc13xx/no-acks
Make the number of Prop Mode RX Buffers easy to configure
2017-01-21 00:17:49 +00:00
Nicolas Tsiftes 5eb2ac15ff Merge pull request #2073 from cetic/pr-fix-send-na
Fix semantic of UIP_ND6_SEND_NA and add UIP_ND6_SEND_NS
2017-01-20 13:18:43 +01:00
Nicolas Tsiftes 0cfda4c026 Merge pull request #2053 from cetic/pr-fix-dag-lifetime
Use RPL_DAG_LIFETIME when computing dag lifetime
2017-01-20 11:08:43 +01:00
Simon Duquennoy d59bbcf86c Merge pull request #2080 from yatch/pr/tsch-reenable-regression-test
TSCH: re-enable TSCH regression tests
2017-01-19 16:53:21 +01:00
Yasuyuki Tanaka 2d44b47050 Print an entry for the root node as well as other entries 2017-01-19 14:36:59 +01:00
Yasuyuki Tanaka 651147df57 TSCH: Fix incorrect test criteria for regression-tests
The tests are recognized as success when a return value by
rpl_ns_num_nodes(), the number of entries in the nodelist, tells all the
routes for the nodes in the network are installed.

There are eight nodes in addition to one root node. Therefore, the value
for test success should not be eight but nine since we have to take into
account an nodelist entry for the root.
2017-01-19 14:35:37 +01:00
Yasuyuki Tanaka ac937eda24 TSCH: re-enable TSCH regression tests with Cooja mote 2017-01-19 14:25:06 +01:00
Yasuyuki Tanaka 83f2382791 Orchestra: avoid a link error for nbr_routes 2017-01-19 13:55:08 +01:00
Nicolas Tsiftes 2e754c7832 Merge pull request #2063 from cetic/pr-ndp-config
Make all NDP configuration parameters user configurable
2017-01-17 08:22:52 +01:00
Nicolas Tsiftes f80f673e21 Merge pull request #2062 from cetic/pr-add-defrt_list_head
Adding uip_ds6_defrt_list_head()
2017-01-17 08:21:50 +01:00
Laurent Deru 0fb597f2fa Use RPL_DAG_LIFETIME when computing dag lifetime 2017-01-16 16:56:22 +01:00
Laurent Deru 12c930893c Fix semantic of UIP_ND6_SEND_NA and add UIP_ND6_SEND_NS 2017-01-16 15:48:14 +01:00
Laurent Deru e5a604552e Allow modification of IP64 prefix 2017-01-16 14:38:35 +01:00
Laurent Deru 10be59cc15 Update nameserver using DHCP info 2017-01-16 14:38:35 +01:00
Laurent Deru 37fe6a2fa6 Use uip-debug in ip64-ipv4-dhcp.c 2017-01-16 14:37:52 +01:00
Laurent Deru 63ac4d2a3d Adding uip_ds6_defrt_head() 2017-01-16 13:54:36 +01:00
Laurent Deru 88d0003b75 Make all NDP configuration parameters user configurable 2017-01-16 13:50:56 +01:00
Antonio Lignan a7b5050382 Merge pull request #2047 from contiki-os/orion-update-motelist-string
Orion: update motelist string
2017-01-15 16:06:23 +01:00
George Oikonomou 5fb226f4c9 Make the count of prop mode RX buffers configurable 2017-01-15 12:31:09 +00:00
George Oikonomou 07de8b238b Easy manipulation of CC13xx Prop Mode RX buffers 2017-01-15 12:25:10 +00:00
George Oikonomou ba12ed2cce Re-initialise RX buffers each time we turn the RF on 2017-01-15 12:24:30 +00:00
George Oikonomou 82fd325b7a Merge pull request #2069 from alignan/pull/light-example-verbatim
Explicitly specify light sensor model in example
2017-01-15 11:52:09 +00:00
Antonio Lignan 999b246fd2 Explicitly specify light sensor model in example 2017-01-14 22:57:08 +01:00
Antonio Lignan 3d40056f4f Merge pull request #2054 from cetic/pr-check-incoming-rank
Reject parents with invalid rank
2017-01-13 16:08:00 +01:00
Antonio Lignan 0fb4a68332 Merge pull request #2052 from cetic/pr-rpl-route-infinite-lifetime
Make RPL route lifetime RFC compliant
2017-01-13 16:07:09 +01:00
Laurent Deru 0da6e128eb Remove servername from DHCP request 2017-01-13 13:35:25 +01:00
Laurent Deru f9ffa252f6 Reject parents with invalid rank 2017-01-13 12:32:33 +01:00
Laurent Deru d866e6bd34 Make RPL route lifetime RFC compliant 2017-01-13 10:54:06 +01:00
Antonio Lignan 10d54f228b Orion: update motelist string
Updates the expected motelist string
2017-01-12 11:23:20 +01:00
Nicolas Tsiftes c1f11cfaa9 Merge pull request #2034 from Vinggui/patch-1
Fixing Avr-Zigbit Makefile not compiling.
2017-01-12 07:49:30 +01:00
Vinicius Guimaraes 5e05a951f2 Fixing Avr-Zigbit Makefile not compiling
Fixed two errors in Zigbit's makefile:
-Compiling "frame.c" here is not necessary (already done in radio's makefile) and brings up an error. Removing it.
-Fixed undefined reference to "link_stats_input_callback" in "../../core/net/ipv6/sicslowpan.c:1521". Module "core/net" was missing.
Compiling working now.
2017-01-11 15:56:20 -02:00
Simon Duquennoy bb4f2e5678 Merge pull request #2043 from e120guru/master
Fixed rime-tsch sync problem in Cooja
2017-01-11 18:15:43 +01:00
Michael Karlsson 22d10ba03a Added Cooja target config to rime-tsch example 2017-01-11 16:35:16 +01:00
Simon Duquennoy fe210b05f0 Merge pull request #2002 from yatch/pr/tsch-misc-update
TSCH Miscelleneous updates
2017-01-10 14:05:36 +01:00
Yasuyuki Tanaka 1d5fc88ae9 TSCH: fix indentation in tsch-packet.c 2017-01-10 11:45:59 +01:00
Yasuyuki Tanaka 3dc74dc632 TSCH: fix a wrong return value
tsch_security_secure_frame() returns the length of MIC in case of
success. Otherwise, it is supposed to return 0. There was one case where
it returns 1 in an error handling block.
2017-01-10 11:45:59 +01:00
Yasuyuki Tanaka 4069ac5262 TSCH: add a regression test for tsch-packet.c 2017-01-10 11:45:59 +01:00
Yasuyuki Tanaka 35a1701236 TSCH: handle error cases returning -1 properly
- tsch_send_eb_process() in tsch-slot-operation.c
- tsch_rx_slot()         in tsch.c
2017-01-10 11:45:59 +01:00
Yasuyuki Tanaka 0b81c0de18 TSCH: make *dest_addr const (tsch_packet_create_eack) 2017-01-10 11:45:59 +01:00
Yasuyuki Tanaka 667dd6a210 TSCH: put tsch_ prefix to definitions in the global scope
struct asn_t         -> struct tsch_asn_t
  struct asn_divisor_t -> tsch_asn_divisor_t
  ASN_ macros          -> TSCH_ASN_ macros
  current_asn          -> tsch_current_asn
2017-01-10 11:45:59 +01:00
Antonio Lignan 7d9134757f Merge pull request #2004 from yatch/pr/tsch-security-update
Trivial Updates on tsch-security.[ch]
2017-01-10 11:23:55 +01:00
Pere Tuset 361cb612a7 Reduce bootloader baudrate to be on the safe side. 2017-01-10 10:59:06 +01:00
Antonio Lignan 82f3ce392e Merge pull request #2028 from joakimeriksson/minimal-net-ND-fix
added support for 6-bytes link-layer address
2017-01-10 09:07:50 +01:00
Antonio Lignan 247d79ea7c Merge pull request #2011 from jdede/z1-llsec
Enable llsec on Z1 nodes
2017-01-10 09:07:27 +01:00
Antonio Lignan bfef0b5d6a Merge pull request #2032 from simonduq/pr/tsch-ka-fix
TSCH bugfix: reset keep-alive timeout when switching time source
2017-01-10 08:47:30 +01:00
George Oikonomou 960b81d484 Merge pull request #2024 from alignan/pull/eth-gw
Zolertia Orion ethernet router with active POE support
2017-01-09 21:03:45 +00:00
George Oikonomou 14757201a5 Merge pull request #2027 from alignan/pull/fix-adc-channels
zoul: fix a bitmask bug in channels used
2017-01-09 21:02:20 +00:00
Nicolas Tsiftes 1537488e74 Merge pull request #2035 from simonduq/pr/csma-fix
CSMA bugfix: do not use field on a struct that may have been deallocated
2017-01-09 08:45:49 +01:00
Simon Duquennoy 0de3563ddb CSMA bugfix: do not use field on a struct that may have been deallocated 2017-01-05 10:47:11 +01:00
Vinicius Guimaraes 42557bf484 Fixing Avr-Zigbit Makefile not compiling.
I just tried to compile this platform for my Zigbit mote (AT86RF230) here in a hello-world example, but it didn't work.
I reviewed this makefile and found that the request to compile "frame.c" was not necessary and bring up a missing error:
"make: *** No rule to make target `obj_avr-zigbit/frame.o', needed by `contiki-avr-zigbit.a'.  Stop."
Frame.c is already inserted in radio's makefile.

Another problem was the undefined reference created by the missing module "core/net":
"contiki-avr-zigbit.a(sicslowpan.o): In function `input':"
"contiki/examples/hello-world/../../core/net/ipv6/sicslowpan.c:1521: undefined reference to `link_stats_input_callback'"

Both solved now. Hope it helps anyone else.
2017-01-04 16:58:53 -02:00
Antonio Lignan 53efcec1fa Merge pull request #1994 from yatch/pr/bugfix-framer802154-sender-addr
Bugfix on source address setting in framer_802154.create()
2017-01-04 14:10:57 +01:00
Simon Duquennoy fe99f1144a TSCH bugfix: reset keep-alive timeout when switching time source 2017-01-04 11:01:46 +01:00
Antonio Lignan 6e07fd7019 Merge pull request #2001 from joakimeriksson/cooja-quick-ui-fix
fixed so that Cooja can run in quick mode when having UI
2017-01-03 10:26:52 +01:00
Antonio Lignan 6aaf1c356c Merge pull request #2029 from t-than/master
Minor typo change
2017-01-02 09:18:54 +01:00
Thanos Tsakiris 92ad29ab33 Minor typo change 2016-12-30 13:13:53 +02:00
Joakim Eriksson cbf4a843e2 fixed comment. 2016-12-29 22:49:01 +01:00
Antonio Lignan 9d12801f01 Merge pull request #2026 from alignan/pull/fix-firefly-doc
Minor documentation fixes
2016-12-29 18:00:49 +01:00
Antonio Lignan a7e617657a zoul: fix a bitmask bug in channels used 2016-12-29 14:19:32 +01:00
Antonio Lignan fb9c6009a2 Fixed Firefly revision A image links 2016-12-29 13:40:50 +01:00
Antonio Lignan a98792a79f Updated ARM toolchain information 2016-12-29 13:38:09 +01:00
Antonio Lignan 6bda852052 Updated maintainer info 2016-12-29 13:32:35 +01:00
Antonio Lignan 579620ce0e Added Zolertia Orion ethernet router with active POE support 2016-12-29 13:07:53 +01:00
Pere Tuset 93828d867e Updated OpenMote-CC2538 README.md file with new features. 2016-12-29 12:30:58 +01:00
Pere Tuset b72110fe8a Add support for the OpenMote-CC2538 Rev.A1 board that uses the CC2538SF23 (256 KB) chip instead of the CC2538SF53 (512 KB) chip. 2016-12-29 12:10:21 +01:00
Pere Tuset 1a993da8fc Add support for automatic bootloading with the cc2538-bsl.py script on the OpenUSB carrier board. 2016-12-29 12:09:07 +01:00
Antonio Lignan 9befc02331 Merge pull request #1997 from yatch/pr/packetbuf-remaininglen
Introduce packetbuf_remaininglen()
2016-12-27 22:38:14 +01:00
Antonio Lignan 2464cdadc9 Merge pull request #1973 from g-oikonomou/contrib/sensniff-submodule
Add sensniff as a submodule
2016-12-25 19:42:18 +01:00
Antonio Lignan cf2b24971b Merge pull request #1978 from makrog/pr/cc1200-fixes
Added NullRDC and ContikiMAC timings for Zolertia RE-Mote.
2016-12-23 18:31:47 +01:00
Jens Dede 7b2c687789 Use hardware-AES on z1 as default 2016-12-22 20:08:19 +01:00
Jens Dede 0b68334e95 Enable llsec on Z1 nodes 2016-12-21 14:54:15 +01:00
George Oikonomou edec34f684 Merge pull request #2008 from alignan/pull/change-baudrate-zoul
zoul: default cc2538-bsl baudrate to 460800
2016-12-21 02:30:19 +00:00
Antonio Lignan 3594cf5167 zoul: default cc2538-bsl baudrate to 460800 2016-12-20 18:18:28 +01:00
Antonio Lignan 7927af021e Minor cosmetic change 2016-12-16 15:47:13 +01:00
Yasuyuki Tanaka 4faf139523 TSCH: change the return type of the APIs (tsch-security.h)
The return type is changed to "int" to "unsigned int" because APIs
provided by tsch-security are supposed to return an integer larger than
or equal to zero. This change clarifies that.
2016-12-15 19:32:22 +01:00
Yasuyuki Tanaka da853386a6 TSCH: fix indentation in tsch-packet.c 2016-12-15 19:32:04 +01:00
Yasuyuki Tanaka 38ff8e5283 TSCH: add brief API explanations (tsch-security.h) 2016-12-15 19:16:28 +01:00
Yasuyuki Tanaka 5186fa2ef1 TSCH: set PACKETBUF_ADDR_SENDER before NETSTACK_framer.create() 2016-12-15 15:10:15 +01:00
Yasuyuki Tanaka da29a5f8e3 ContikiMAC: set PACKET_ADDR_SENDER in qsend_list() 2016-12-15 15:10:15 +01:00
Yasuyuki Tanaka 586fb9a7fe framer-802154: bugfix on source address setting 2016-12-15 15:10:15 +01:00
Joakim Eriksson f069cef73a fixed so that Cooja can run in quick mode when having UI 2016-12-15 13:52:05 +01:00
Nicolas Tsiftes 9ef28c7eae Merge pull request #1993 from yatch/pr/bugfix-rime-sky-collect
Bugfix on regression-tests/04-rime/07-sky-collect.csc
2016-12-15 10:46:04 +01:00
Simon Duquennoy bba5a973ba Merge pull request #1987 from joakimeriksson/cooja-fix
Fixed COOJA to avoid using UI based message list when not using UI.
2016-12-15 08:40:03 +01:00
Yasuyuki Tanaka aa1f408825 packetbuf: add packetbuf_remaininglen()
packetbuf_freelen() returns the length of free space in packetbuf.
2016-12-14 14:19:46 +01:00
Yasuyuki Tanaka c48cfb6b9d Fix indentation in packetbuf.h 2016-12-14 14:16:55 +01:00
Yasuyuki Tanaka a3417b82b0 Fix indentation in packetbuf.c 2016-12-14 14:16:55 +01:00
Yasuyuki Tanaka 8b3f29325d Update example-collect.c
- bugfix: more frequent transmissions than expected (every 30 seconds)
- indentation: replace tabs with spaces
2016-12-14 12:38:55 +01:00
Yasuyuki Tanaka 5d19196e54 Update 04-rime/07-sky-collect.csc
- decrease timeout value to 450,000 msec, which is enough to send 10
  messages at 30 seconds interval after 2 minutes start-up wait
- handle the case of receiving seqno out of range
2016-12-14 12:38:55 +01:00
Joakim Eriksson fb0607f0f8 Merge pull request #3 from nfi/cooja-messagelist-ui
Fixed more MessageListUI to respect visualized in Cooja
2016-12-14 10:24:37 +01:00
Niclas Finne a02481bc99 Fixed more MessageListUI to respect visualized in Cooja 2016-12-14 10:10:25 +01:00
Nicolas Tsiftes 8fca9ced8e Merge pull request #1976 from yatch/pr/missing-single-quote
Resolve  "unmatched single quote" error in Travis CI failed tests
2016-12-12 17:06:16 +01:00
George Oikonomou a6b14a0731 Add documentation for the new boards 2016-12-11 20:44:26 +00:00
George Oikonomou 08439a878d Add travis tests for CC1350 boards 2016-12-11 20:44:26 +00:00
George Oikonomou fd3d733e4b Add support for the CC1350 Launchpad 2016-12-11 20:44:25 +00:00
George Oikonomou a864ebbce4 Re-organise sensortag documentation modules
Many of those doxygen blocks are now applicable to both sensortags, with only a couple of them being different between the CC1350 and CC2650 tags
2016-12-11 20:44:25 +00:00
George Oikonomou d291ec53e6 Add support for the CC1350 sensortag 2016-12-11 20:44:25 +00:00
George Oikonomou 7603e104c4 Allow band-specific RSSI offset override 2016-12-11 20:44:25 +00:00
George Oikonomou 47bda9b6be Provide additional overrides for the 470MHz frequency band 2016-12-11 20:44:25 +00:00
George Oikonomou c745199d53 Allow frequency band-specific overrides 2016-12-11 20:44:25 +00:00
George Oikonomou 5756248949 Factor-out CC13xx PROP mode TX power table
The CC13xx PROP mode TX power table can differ between boards as well as across frequency bands. This commit provides defaults for all bands and allows the board to override.
2016-12-11 20:41:00 +00:00
George Oikonomou 7ca3bea701 Make LNA bias trim offset configurable 2016-12-11 20:40:24 +00:00
Joakim Eriksson 2a3edc9136 Fixed so that COOJA sends in isVisible instead of quick as visibility parameter to plugins to get compile info back into COOJA - and fixed CoreComm to use MessageList text if no UI 2016-12-11 20:52:03 +01:00
George Oikonomou 6694e69788 Make Launchpad unused pins configurable 2016-12-11 16:54:11 +00:00
George Oikonomou 6b7681c516 Extend the RF core to support RF switches 2016-12-11 16:54:11 +00:00
George Oikonomou e0e6f82c46 Allow boards to explicitly provide an RSSI offset 2016-12-11 16:54:10 +00:00
George Oikonomou 00944ec677 Allow boards to append to overrides 2016-12-11 16:54:10 +00:00
George Oikonomou d9ea888323 Delegate RF Front End and Bias settings to board.h 2016-12-11 16:54:10 +00:00
George Oikonomou d6e8e7dab4 Adjust ContikiMAC timings to compensate for new patches/overrides 2016-12-11 16:51:48 +00:00
Jonas Olsson a56b520215 Make sure correct clocks is running in the RF Core (RFE). 2016-12-11 16:51:48 +00:00
Jonas Olsson 43b9679bcc Move setting of RF mode to correct place, needs to be called on every boot. 2016-12-11 16:51:48 +00:00
George Oikonomou e73ac7d26f Update to latest overrides and patches 2016-12-11 16:51:48 +00:00
Jonas Olsson db54175d8d Add missing structure from radio setup command. 2016-12-11 16:51:48 +00:00
George Oikonomou f07ed3fc01 Allow CC13xxware to automatically configure RTRIM for us 2016-12-11 16:51:48 +00:00
George Oikonomou 2934c6bbe7 Define RFC-related ccxxware macros 2016-12-11 16:51:48 +00:00
George Oikonomou 3a070bd332 Fix typo in TX power settings for prop mode (12.5 dBm) 2016-12-11 16:51:48 +00:00
George Oikonomou f9e6a78882 Update CMD_FS' fields to the current API 2016-12-11 16:51:47 +00:00
George Oikonomou a3c80cedb9 Adjust TX power settings to use current API fields 2016-12-11 16:51:47 +00:00
George Oikonomou 4d0051ad4d Switch to xxware-provided RF API headers 2016-12-11 16:51:47 +00:00
George Oikonomou b67d3cc6ea Remove RF API header files
xxwares ship these headers now, so we will switch to using those versions. The exceptions are IEEE API headers, which are for not part of xxwares, so we have to keep them locally for now.
2016-12-11 16:51:47 +00:00
Antonio Lignan ac2a31455e Merge pull request #1957 from alignan/pull/bme280-sensor
sensors: bme280 weather sensor
2016-12-10 18:37:21 +01:00
Antonio Lignan bd3f8fa3c5 Merge pull request #1939 from bthebaudeau/re-mote-sd-fat
Add global SD/MMC and FAT support, with RE-Mote as an example
2016-12-10 18:32:39 +01:00
Nicolas Tsiftes 9bb6286bb2 Merge pull request #1982 from nvt/coffee-io-semantics
Always enable the I/O semantics function in Coffee.
2016-12-09 16:09:32 +01:00
Nicolas Tsiftes 3030422830 Merge pull request #1854 from mdlemay/fix-efi-align
x86: Fix section alignment for EFI binaries
2016-12-08 20:18:50 +01:00
Nicolas Tsiftes ece7cfee38 Merge pull request #1835 from mdlemay/gp-exc-handler
galileo: Add general protection exception handler
2016-12-08 20:12:45 +01:00
Nicolas Tsiftes 1249d9cf8d Merge pull request #1855 from MohamedSeliem/patch-5
DAD: Remove useless "if" that tests if the source address is unspecified
2016-12-08 20:08:58 +01:00
Nicolas Tsiftes d133ed898f Merge pull request #1914 from yatch/pr/802154-panid-handling
frame802154: comply with IEEE 802.15.4-2015 on PAN ID Field Handling
2016-12-08 18:37:58 +01:00
Antonis Makrogiannakis ba241db968 Added NullRDC and ContikiMAC timings for Zolertia RE-Mote.
CC1200 SubGHz 50 Kbps mode.
2016-12-06 13:34:26 +02:00
Yasuyuki Tanaka 5fdd731166 frame802154: fix a typo in a comment 2016-12-05 22:45:07 +01:00
Yasuyuki Tanaka 3872965362 frame802154: comply with IEEE 802.15.4-2015 on PAN ID Field Handling
This patch changes the behaviors of frame802154_has_panid() for frames
of frame version 0b10 so that it complies with the PAN ID Field Handling
specification in IEEE 802.15.4-2015. For the other frame versions, 0b00
and 0b01, no change is made in frame802154_has_panid().

For more information, please refer to:
https://github.com/contiki-os/contiki/pull/1914/
2016-12-05 22:45:07 +01:00
Nicolas Tsiftes f09e84976a Merge pull request #1950 from yatch/pr/update-for-tsch-cooja-mote
Miscellaneous updates for tsch-cooja-mote
2016-12-05 18:40:28 +01:00
Yasuyuki Tanaka f5d6b7ed0f ContikiMoteType: add a missing single quote in a log message
This resolves the error of "unmatched single quote" by xargs seen in a
failed log of Travis CI.
2016-12-05 18:07:39 +01:00
Simon Duquennoy f6439121b4 Merge pull request #1963 from yatch/pr/code-style
Update doc/code-style.c
2016-12-05 13:40:36 +01:00
Antonio Lignan 95f69d92a8 Merge pull request #1918 from adamdunkels/pr-websocket-2
Contiki websocket client
2016-12-05 06:46:43 +01:00
Antonio Lignan 027f1c3e64 Merge pull request #1924 from g-oikonomou/contrib/cc26xx-cc13xx/update-ccxxwares
Update to latest CC13xxware/CC26xxware
2016-12-04 23:55:31 +01:00
George Oikonomou bad3384365 Update sensniff example documentation 2016-12-04 19:07:40 +00:00
George Oikonomou aaf0d1eb86 Automatically specify a correct baudrate for jn516x 2016-12-04 19:07:40 +00:00
George Oikonomou 7ef5902c3d Add the sniff make target
We can now run make sniff and this will provide correct command line arguments for all supported devices.
2016-12-04 18:51:57 +00:00
George Oikonomou 44edc187bc Specify default baudrate for CC2538DK 2016-12-04 18:43:41 +00:00
George Oikonomou 11877b4b6b Add sensniff as a submodule 2016-12-04 18:43:17 +00:00
Mohamed Seliem 88fdc46e03 update httpd_cgi to enable the compilation of webserver-ipv6 example
this simple change fixes the bug reported in @#1541.
../../apps/webserver/httpd.h:63:9: note: expected ‘uip_ip6addr_t’ but argument is of type ‘union uip_ipaddr_t *’
2016-12-04 19:03:15 +02:00
George Oikonomou 367104166e Update to latest CC13xxware/CC26xxware 2016-12-04 13:33:40 +00:00
Antonio Lignan af4f1e1c30 Merge pull request #1866 from yschroeder/pull-req/serialdump
Improved serialdump.c
2016-12-04 13:17:39 +01:00
Antonio Lignan 2be999c707 Merge pull request #1967 from MohamedSeliem/patch-9
Fix the leftover mentions of aaaa as a prefix to be UIP_DS6_DEFAULT_PREFIX (now fd00)
2016-12-04 12:46:07 +01:00
Antonio Lignan 36519a9742 Merge pull request #1969 from g-oikonomou/contrib/fix-typo
Fix minor typo
2016-12-04 12:45:04 +01:00
Mohamed seliem 4a93babb58 fix msg.dst.sin6_addr.__u6_addr.__u6_addr16 2016-12-04 03:29:50 +02:00
Mohamed seliem 452666b43e add missing include 2016-12-04 03:29:49 +02:00
Mohamed Seliem 82b5fb5073 Fix the leftover mentions of aaaa as a prefix to be UIP_DS6_DEFAULT_PREFIX (now fd00) 2016-12-04 03:29:49 +02:00
George Oikonomou d6656ccde1 Fix minor typo 2016-12-03 23:26:25 +00:00
Yasuyuki Tanaka 49808b8f1c Update code-style.c
- mention Uncrustify instead of GNU Indent
- add a missing argument of code_style_example_function()
- make the function return 0 or 1 as per doxygen comment
- replace tab with spaces
- correct case() to switch() in a comment
- add an indentation example for switch statement
2016-12-03 12:21:04 +01:00
Antonio Lignan 9ccc1697cf Merge pull request #1966 from yatch/pr/travis-jdk
travis: workaround for the Java issue on Travis CI
2016-12-03 12:13:40 +01:00
Yasuyuki Tanaka 120632b4a8 travis: workaround for the Java issue on Travis CI
References:
https://docs.travis-ci.com/user/build-environment-updates/2016-12-01/
https://github.com/travis-ci/travis-ci/issues/6928#issuecomment-264227708
2016-12-02 16:48:57 +01:00
Antonio Lignan 94854177e2 Merge pull request #1961 from jdede/uart-init
Do not initialize and use the wrong UART (z1)
2016-12-02 15:41:32 +01:00
Antonio Lignan 6565652e43 Merge pull request #1962 from MohamedSeliem/patch-8
update contiki-conf to avoid redfintion of UIP_CONF_RECEIVE_WINDOW
2016-12-02 09:52:48 +01:00
Mohamed seliem 0ef0a21d9e update for all platforms 2016-12-01 21:26:32 +02:00
Mohamed Seliem 0c65a4db9c update contiki-conf to avoid redfintion of UIP_CONF_RECEIVE_WINDOW
in case of compiling any example that contains the definition of UIP_CONF_RECEIVE_WINDOW over Z1 mote.
i receive this warning: 
 In file included from ../../../core/./contiki.h:38:0,
                   from ../../../core/./contiki-net.h:37,
                   from httpd-simple.c:43:
  ../../../platform/z1/./contiki-conf.h:225:0: warning: "UIP_CONF_RECEIVE_WINDOW" redefined
 ./project-conf.h:60:0: note: this is the location of the previous definition
2016-12-01 20:35:29 +02:00
Antonio Lignan 63322fdfb2 Merge pull request #1960 from pablocorbalan/rm-rpl-conf-of
Remove definitions of outdated RPL_CONF_OF
2016-12-01 16:30:46 +01:00
Nicolas Tsiftes 238e8b4dcf Merge pull request #1949 from simonduq/pr/non-storing-fix-dtsn
RPL non-storing: more conservative DTSN update
2016-12-01 16:27:38 +01:00
Simon Duquennoy 7bb50da178 Merge pull request #1271 from drugo72/pr-rpl
RPL: fix clock_time_t calculations
2016-12-01 16:22:43 +01:00
Jens Dede 0d3ff7b785 Rm unnecessary uart commands 2016-12-01 15:12:23 +01:00
Pablo Corbalán 983d858570 Remove definitions of outdated RPL_CONF_OF 2016-12-01 13:13:41 +01:00
Antonio Lignan 5e7acd4dc2 Merge pull request #1643 from akshaypm/zoul-uart-example
Zoul UART example
2016-12-01 11:42:44 +01:00
akshaypm cd75e50c28 cc2538 uart example 2016-12-01 12:45:10 +05:30
George Oikonomou 7c54b7cd50 Merge pull request #1867 from MohamedSeliem/patch-6
update uart1.c to include Special function registers bits definitions
2016-11-30 16:37:49 +01:00
Antonio Lignan a8acaf08d5 Merge pull request #1938 from makrog/pr/cc1200-fixes
Fixed checking of the cc1200 GPIO0 pin status.
2016-11-30 14:24:48 +01:00
Robert Olsson 4ef4bdd0a5 bme280 delay fixes plus Makefile for avr-rss2 2016-11-30 12:04:57 +01:00
Antonio Lignan f9b32f8139 bme280: reworked to allow platform-specific I2C implementations 2016-11-30 12:04:57 +01:00
Antonio Lignan bd1a6bf94e zoul: Added bme280 example 2016-11-30 12:04:57 +01:00
Robert Olsson 23a481600a BME280 fixes, codestyle, return code for bme280_init added, Unneeded header files removed 2016-11-30 12:04:57 +01:00
Robert Olsson 1c0e33be79 Update README.bme280 2016-11-30 12:04:57 +01:00
Robert Olsson cfed856720 I2C fixes
modified:   examples/avr-rss2/hello-sensors/hello-sensors.c
2016-11-30 12:04:57 +01:00
Robert Olsson dcbb5f6271 BME280 I2C integration fixes 2016-11-30 12:04:57 +01:00
Robert Olsson 5c25ec4d11 Example modified to use BME280 2016-11-30 12:04:57 +01:00
Robert Olsson cfabf0e6a2 Support for BME280 added.
new file:   dev/bme280/README.bme280
	new file:   dev/bme280/bme280-sensor.c
	new file:   dev/bme280/bme280-sensor.h
	new file:   dev/bme280/bme280.c
	new file:   dev/bme280/bme280.h
2016-11-30 12:04:57 +01:00
MakA 91a6ce6576 Fixed checking of the cc1200 GPIO0 pin status. 2016-11-29 12:16:03 +02:00
Antonio Lignan 1abc95a08e Merge pull request #1952 from arurke/fix_rf_channel_cc13xx
Move RF_CHANNEL check in cc13xx/cc26xx such that it applies for cc13xx prop mode
2016-11-28 09:37:00 +01:00
Benoît Thébaudeau a6d348917d Add FAT example
Zoul RE-Mote revision B is supported.

Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
2016-11-27 22:50:45 +01:00
Benoît Thébaudeau 3cd7b7efd1 zoul: remote: Add support for FAT
Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
2016-11-27 22:50:45 +01:00
Benoît Thébaudeau 12ea1bd492 zoul: remote: Factor out duplicate RTC init
Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
2016-11-27 22:50:44 +01:00
Benoît Thébaudeau 2866ae0555 Add support for the FAT file system
The FatFs generic FAT file system module is used.

Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
2016-11-27 22:50:44 +01:00
Benoît Thébaudeau 062a8535ec zoul: remote: Add support for SD/MMC
This change adds SD/MMC support at block level, by porting the SD/MMC
driver.

Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
2016-11-27 22:50:43 +01:00
Benoît Thébaudeau 8b57670121 cc2538: spi: Add support for dynamic clock frequency
This changes makes it possible to change the SPI clock frequency at
runtime.

Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
2016-11-27 22:50:43 +01:00
Benoît Thébaudeau c76b8235f4 cc2538: spi: Add support for dynamic instances
Previously, only constants could be used to pass SPI instances to the
SPI driver. This change makes it possible to use SPI instances from
variables.

Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
2016-11-27 22:50:43 +01:00
Benoît Thébaudeau 0e5b18635b cc2538: gpio: Add macro to get pin direction
Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
2016-11-27 22:50:42 +01:00
Benoît Thébaudeau faf22609f4 disk: Add SD/MMC driver
Only SPI is supported.

Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
2016-11-27 22:50:42 +01:00
Benoît Thébaudeau 92ecbf7064 Add disk API
Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
2016-11-27 22:15:34 +01:00
Andreas Urke 835a6aa6e6 Move RF_CHANNEL such that it is applied for prop mode as well 2016-11-27 16:13:58 +01:00
Simon Duquennoy 728e417e04 Merge pull request #1502 from yatch/pr-radiologger
Fix timestamps of packets recorded in pcap files
2016-11-27 11:58:03 +01:00
Yasuyuki Tanaka a4adc257e8 Add RTIMERTICKS_TO_US_64() macro (platform/cooja) 2016-11-26 11:47:59 +01:00
Yasuyuki Tanaka 106731cec1 TSCH: update README.md
- add cooja / Cooja mote as supported platform
- correct Rx mode requirements
2016-11-26 11:47:59 +01:00
Yasuyuki Tanaka 87337e12fc Revert coordinator selection based on node-id for Cooja mote
(example/ipv6/rpl-tsch/node.c)
2016-11-26 11:47:59 +01:00
Antonio Lignan 58243bc14a Merge pull request #1827 from alignan/pull/rf-channel
Harmonize RF_CHANNEL definition
2016-11-25 21:11:20 +01:00
George Oikonomou 610eefc2ff Merge pull request #1741 from simonduq/pr/tsch-adaptive-control-traffic
TSCH adaptive control traffic
2016-11-25 15:53:32 +00:00
Simon Duquennoy 3e00adacc0 RPL non-storing: more conservative DTSN update, as per RFC 6550, section 9.6. 2016-11-25 16:30:08 +01:00
Nicolas Tsiftes edf3a27920 Merge pull request #1879 from pernin/master
Change on DIO trickle timer condition for DIO sending
2016-11-25 16:15:08 +01:00
Nicolas Tsiftes a69d78ac73 Merge pull request #1948 from zhitaoh/zoul-example-readme
correct shell arguments
2016-11-25 16:13:02 +01:00
Nicolas Tsiftes 5281908018 Always enable the I/O semantics function in Coffee. 2016-11-25 16:02:44 +01:00
Zhitao He 7ba88a6800 correct shell arguments 2016-11-25 14:59:30 +01:00
Antonio Lignan fc582606f2 Harmonize RF_CHANNEL definition 2016-11-25 10:37:14 +01:00
Benoît Thébaudeau 52a8dcc65b Merge pull request #1816 from bthebaudeau/cm-cc2538-mt
Cortex-M and CC2538 multi-threading
2016-11-24 23:28:05 +01:00
Benoît Thébaudeau 9c47f874c4 CC2538: Enable Cortex-M mtarch implementation
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-11-24 22:30:26 +01:00
Benoît Thébaudeau 3f676a5a16 ARM: Add common Cortex-M mtarch implementation
This includes support for preemption ready to be integrated into
exception handlers.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-11-24 22:30:26 +01:00
Benoît Thébaudeau 81805129f8 mt: Fix preemption
Preemption was supposed to be supported, but it had no means of safely
updating the state of a thread, so mt_exec() could fail to resume a
preempted thread.

mt_exec() is allowed to be called only from the main Contiki thread, so
the mt threads passed to it may be only ready or exited, not running.
Consequently, there is no need for a distinction between the ready and
running states, so merge them as a started state, which avoids having to
update the state of a thread upon preemption.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-11-24 22:30:26 +01:00
Benoît Thébaudeau 927e9b8150 mt: Fix missing call to mtarch_pstop()
If mt_yield() needs it, then mt_exit() too. A thread could indeed be
preempted while calling mt_exit().

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-11-24 22:30:26 +01:00
Benoît Thébaudeau 82afa72c13 mt: Remove unused code
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-11-24 22:30:26 +01:00
Benoît Thébaudeau ab1491be69 CC2538: Use CMSIS-CORE
Switch to CMSIS-CORE and remove the duplicate code.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-11-24 22:30:26 +01:00
Benoît Thébaudeau 9195b49c18 ARM: CMSIS-CORE: Introduce NVIC_IsIRQEnabled()
This function returns the enable state of an interrupt.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-11-24 22:30:26 +01:00
Benoît Thébaudeau d3158897c2 ARM: CMSIS-CORE: Fix doxygen warnings
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-11-24 22:30:26 +01:00
Benoît Thébaudeau 280dc091d2 ARM: CMSIS-CORE: Bump version to 4.30
Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-11-24 22:30:26 +01:00
Benoît Thébaudeau ca86d5febf ARM: Fix doxygen style
The rule in Contiki is to use backslashes, not at signs.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
2016-11-24 22:30:26 +01:00
Luca Pernini 5803971adc Changing DIO timer condition - merge 2016-11-24 10:52:10 +01:00
Simon Duquennoy 86dbd590db Merge pull request #1400 from pablocorbalan/nud-with-acks
Refresh nbr reachable state after received IPv6 unicast message
2016-11-23 12:00:13 +01:00
Simon Duquennoy ecd1d57eec Merge pull request #1661 from yatch/pr-tsch-cooja-mote
TSCH on Cooja mote
2016-11-23 11:59:29 +01:00
Cristiano De Alti 1bdec853e1 Prevent interger overflow on the AVR
Compiling examples/er-rest-example for the avr-raven gives:

  integer overflow in expression [-Woverflow]

On the AVR int is 16 bit and some calculations may overflow.
This happens for example with multiplications involving
CLOCK_SECOND where all the operands are of type int.
Casting one of the operands to clock_time_t forces
the arithmetic to clock_time_t without increasing the size
of the program (the calculation is performed at compile time).
2016-11-05 22:46:42 +01:00
Adam Dunkels 36afb693b0 Removed left-over debug printout 2016-11-02 21:54:15 +01:00
Adam Dunkels 869df3bc36 Updated copyright statements 2016-11-02 21:54:02 +01:00
Adam Dunkels 937fddbedf Removed blanks 2016-11-02 21:53:43 +01:00
Adam Dunkels c484ee4998 Added comments 2016-11-02 21:53:31 +01:00
Adam Dunkels ae4801bba6 Bugfix: make sure the TCP connection is polled immediately after tcp_socket_send() is called so that the TCP segment goes out directly 2016-11-02 15:16:00 +01:00
Adam Dunkels f11d344d4d Add a tcp_socket_queuelen() function that returns the length of the current TCP output queue 2016-11-02 15:16:00 +01:00
Adam Dunkels 6ab9822fc2 Make debug printouts be PRINTF() statements to avoid including them in non-debug builds 2016-11-02 15:16:00 +01:00
Adam Dunkels bb071a7fba Contiki websocket HTTP client code 2016-11-02 15:16:00 +01:00
Adam Dunkels a7cbbe496f Contiki websocket client code 2016-11-02 15:16:00 +01:00
Adam Dunkels 5625a01baf Example node.js websocket server, to be used with the Contiki websocket client 2016-11-02 15:16:00 +01:00
Adam Dunkels 4f13d637e6 Example code for the Contiki websocket client 2016-11-02 15:16:00 +01:00
Mohamed Seliem 682abac7b7 update uart1.c to include Special function registers bits
including "sfr-bits.h" to define PERCFG_U1CFG, and UCSR_MODE
2016-09-21 14:32:09 +02:00
Yannic Schröder d524211c2a Clean exit of serialdump when hitting Ctrl-C
Ctrl-C is the best way to close serialdump after using make login.
With a clean exit it will signal to make that the make run was successful.
2016-09-20 14:18:21 +02:00
Yannic Schröder 9e080e8aa5 Terminate serialdump when serial device disconnects
The running serialdump does not recover from a disconnected device but
runs indefinitely with outputting anything. This makes it quit with a
proper error message.
2016-09-20 14:16:40 +02:00
Yannic Schröder 2974b796d1 Initialize serialdump termios properly
termios i_flags were not initialized and could be set to arbitrary values
this resulted in unpredicted behaviour of the output like additional
newlines
2016-09-20 14:14:14 +02:00
Mohamed Seliem f6795b4972 Neighbor Solicitation Processing (ns_input)
In the newest version of contiki, the function uip_nd6_ns_input() is obsolete.
ns_input function is defined static to be restrictively used in uip-nd6.c file, so removing the obsolete function requires moving the function description to the new function
2016-09-13 09:24:46 +02:00
Mohamed Seliem 675d9325b9 DAD: Remove useless "if" that tests if the source address is unspecified
No need to do the unspecified address twice.

#if UIP_ND6_DEF_MAXDADNS > 0
    if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
      /* DAD CASE */
       ..........
#else /* UIP_ND6_DEF_MAXDADNS > 0 */
    if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
      /* DAD CASE */
      goto discard; 
#endif /* UIP_ND6_DEF_MAXDADNS > 0 */

this logic will bring confusion, especially if you analyze the other ND functions (NUD, address resolution)  .
2016-09-10 10:56:19 +02:00
Michael LeMay 24f23588dd x86: Fix section alignment for EFI binaries
This patch fixes the section alignment specification in the linker script for
the Intel Quark X1000 SoC so that the UEFI GenFw program generates correct EFI
binaries.  See the added comment in quarkX1000.ld for details.
2016-09-08 12:13:28 -07:00
Yasuyuki Tanaka 30ddd97124 TSCH: add a sample .csc file and configuration for Cooja mote 2016-09-06 15:14:10 +02:00
Yasuyuki Tanaka 0ff474e393 Fix indentation in nullrdc.c 2016-09-06 15:14:10 +02:00
Yasuyuki Tanaka 6869dc7004 Yield inside busywaiting loops under cooja-ip64 (nullrdc.c)
The while loops waiting ACK_WAIT_TIME and AFTER_ACK_DETECTED_WAIT_TIME
cause infinite loop under the cooja-ip64 platform. This is because
RTIMER_NOW(), rtimer_arch_now(), has been changed not to call
cooja_mt_yield() in it since rtimer was reimplemented as a higher
resolution timer.

In order to avoid the infinite loop, cooja_mt_yield() needs to be
called inside the while loops under the platform as well as the cooja
platform.
2016-09-06 15:14:10 +02:00
Yasuyuki Tanaka 6d51c5f58e Reimplement Rtimer of Cooja mote as a microsecond resolution timer 2016-09-06 15:14:10 +02:00
Yasuyuki Tanaka 0201208664 TSCH: manage busy waiting on Cooja motes 2016-09-06 15:14:10 +02:00
Yasuyuki Tanaka 958ff6e4f6 Fix indentation in cooja-radio.c 2016-09-06 15:14:10 +02:00
Yasuyuki Tanaka 38c5382054 Add timing macros required for TSCH 2016-09-06 15:14:10 +02:00
Yasuyuki Tanaka 671b1cd9b8 Support the radio features required for TSCH 2016-09-06 15:14:10 +02:00
Yasuyuki Tanaka 830753f360 cooja-radio: enable to turn off the turnaround and CCA features 2016-09-06 15:14:10 +02:00
Yasuyuki Tanaka 33e86042e5 Support RADIO_PARAM_LAST_PACKET_TIMESTAMP with get_object() 2016-09-06 15:14:10 +02:00
Yasuyuki Tanaka ca715fdd6b Use appropriate types for "value" of setInt{16,32,64}ValueOf() 2016-09-06 15:14:10 +02:00
Joakim Eriksson 616b65c962 added support for 6-bytes link-layer address 2016-08-27 22:30:32 +02:00
Michael LeMay 6a3ce86e10 galileo: Add general protection exception handler
This patch adds a general protection exception handler that prints a
message indicating the faulting instruction and the error code. This is
useful when debugging general protection exceptions.
2016-08-23 11:34:32 -07:00
George Oikonomou 2039b3a552 Use ccaInfo.ccaState to decide whether CCA is complete
This commit changes the logic of `get_cca_info()` in the CC26xx IEEE mode driver. We now use the command's return status bits to determine whether the radio's CCA monitoring function has concluded, instead of drawing conclusions based on RSSI readings.
2016-07-17 20:19:13 +01:00
George Oikonomou 16f56abfad Wait for a valid RSSI reading in CC13xx/CC26xx RF drivers
As discussed in #1341, the current CC13xx/CC26xx IEEE mode driver sends `CMD_GET_RSSI` once and returns the RSSI reading uncondtionally. This happens within the `get_rssi()` function.

This logic is broken if `get_rssi()` is called with the radio off. The function will make sure to turn on the radio first, but it does not make sure the RSSI reading is valid, which only happens a number of symbol periods after the radio enters RX. The outcome is that `NETSTACK_RADIO.get_value(RADIO_PARAM_RSSI, ...)` will always return -128 (meaning that RSSI is unavailable) if the radio was off at the time of calling the function.

The same condition affects the prop mode driver.

This commit changes the logic of `get_rssi()`:
* For PROP mode, if `CMD_GET_RSSI` returns an invalid RSSI, we send it again. For unknown reasons, `CMD_GET_RSSI` on occasion returns 0, so we ignore that value too.
* For IEEE mode, we use `CMD_IEEE_CCA_REQ` and we inspect the value of `ccaInfo.ccaEnergy` of the return structure. If the value is 0x02 (Invalid), we send the command again.

Fixes #1341
2016-07-17 18:20:22 +01:00
Simon Duquennoy 27b20b09a3 TSCH: enable adaptive time synchronization by default 2016-06-23 22:39:54 +02:00
Simon Duquennoy 15dc86aeb1 TSCH: reduce keep-alive traffic as we get more accurate drift estimates 2016-06-23 22:39:44 +02:00
Simon Duquennoy ab706a6f33 TSCH: map RPL trickle interval to TSCH EB period 2016-06-23 18:48:01 +02:00
Pablo Corbalán 910f828975 Remove unneeded state refresh and set reachable timer upon adding a nbr 2016-06-12 18:40:13 +01:00
Pablo Corbalán 373e5653e6 uIPv6: Make sure dest address is not multicast before refreshing the state of a neighbor 2016-06-12 18:40:12 +01:00
Pablo Corbalán 0fb47d0a2d Refresh nbr reachable state after received IPv6 unicast message 2016-06-12 18:40:04 +01:00
Yasuyuki Tanaka 15d30b1125 Make PcapExporter record timestamps with preserving packet intervals 2016-03-30 18:26:20 +02:00
1093 changed files with 140322 additions and 12290 deletions

10
.gitmodules vendored
View file

@ -4,13 +4,15 @@
[submodule "tools/cc2538-bsl"] [submodule "tools/cc2538-bsl"]
path = tools/cc2538-bsl path = tools/cc2538-bsl
url = https://github.com/JelmerT/cc2538-bsl.git url = https://github.com/JelmerT/cc2538-bsl.git
[submodule "cpu/cc26xx-cc13xx/lib/cc26xxware"]
path = cpu/cc26xx-cc13xx/lib/cc26xxware
url = https://github.com/contiki-os/cc26xxware.git
[submodule "cpu/cc26xx-cc13xx/lib/cc13xxware"] [submodule "cpu/cc26xx-cc13xx/lib/cc13xxware"]
path = cpu/cc26xx-cc13xx/lib/cc13xxware path = cpu/cc26xx-cc13xx/lib/cc13xxware
url = https://github.com/contiki-os/cc13xxware.git url = https://github.com/contiki-os/cc13xxware.git
[submodule "platform/stm32nucleo-spirit1/stm32cube-lib"] [submodule "platform/stm32nucleo-spirit1/stm32cube-lib"]
path = platform/stm32nucleo-spirit1/stm32cube-lib path = platform/stm32nucleo-spirit1/stm32cube-lib
url = https://github.com/STclab/stm32nucleo-spirit1-lib url = https://github.com/STclab/stm32nucleo-spirit1-lib
[submodule "tools/sensniff"]
path = tools/sensniff
url = https://github.com/g-oikonomou/sensniff.git
[submodule "apps/tinydtls"]
path = apps/tinydtls
url = https://github.com/iot-lab/armour-tinydtls.git

View file

@ -1,3 +1,7 @@
# Workaround for the issue found in the stable image promoted on Dec 1, 2016.
# See https://github.com/travis-ci/travis-ci/issues/6928#issuecomment-264227708
group: deprecated
notifications: notifications:
email: false email: false
language: c #NOTE: this will set CC=gcc which might cause trouble language: c #NOTE: this will set CC=gcc which might cause trouble
@ -10,7 +14,7 @@ before_script:
## Install doxygen ## Install doxygen
- if [ ${BUILD_CATEGORY:-0} = doxygen ] ; then - if [ ${BUILD_CATEGORY:-0} = doxygen ] ; then
sudo add-apt-repository ppa:libreoffice/libreoffice-4-4 -y && sudo apt-get -qq update && sudo add-apt-repository ppa:libreoffice/ppa -y && sudo apt-get -qq update &&
sudo apt-get --no-install-suggests --no-install-recommends -qq install doxygen && sudo apt-get --no-install-suggests --no-install-recommends -qq install doxygen &&
doxygen --version ; doxygen --version ;
fi fi
@ -81,7 +85,7 @@ before_script:
- if [ ${BUILD_ARCH:-0} = jn516x ] ; then - if [ ${BUILD_ARCH:-0} = jn516x ] ; then
$WGET http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part1.tar.bz2 && $WGET http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part1.tar.bz2 &&
$WGET http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part2.tar.bz2 && $WGET http://simonduq.github.io/resources/ba-elf-gcc-4.7.4-part2.tar.bz2 &&
$WGET http://simonduq.github.io/resources/jn516x-sdk-4163.tar.bz2 && $WGET http://simonduq.github.io/resources/jn516x-sdk-4163-1416.tar.bz2 &&
mkdir /tmp/jn516x-sdk /tmp/ba-elf-gcc && mkdir /tmp/jn516x-sdk /tmp/ba-elf-gcc &&
tar xjf jn516x-sdk-*.tar.bz2 -C /tmp/jn516x-sdk && tar xjf jn516x-sdk-*.tar.bz2 -C /tmp/jn516x-sdk &&
tar xjf ba-elf-gcc-*part1.tar.bz2 -C /tmp/ba-elf-gcc && tar xjf ba-elf-gcc-*part1.tar.bz2 -C /tmp/ba-elf-gcc &&
@ -158,3 +162,5 @@ env:
- BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja' - BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja'
- BUILD_TYPE='llsec' MAKE_TARGETS='cooja' - BUILD_TYPE='llsec' MAKE_TARGETS='cooja'
- BUILD_TYPE='compile-avr' BUILD_CATEGORY='compile' BUILD_ARCH='avr-rss2' - BUILD_TYPE='compile-avr' BUILD_CATEGORY='compile' BUILD_ARCH='avr-rss2'
- BUILD_TYPE='ieee802154'
- BUILD_TYPE='tsch'

494
LICENSE
View file

@ -1,3 +1,37 @@
A note on Licensing (2017-03-17):
Github has recently (2017-03-01) changed their license terms:
https://help.github.com/articles/github-terms-of-service/
There were comments that this may violate some GPL and creative commons
licenses:
http://joeyh.name/blog/entry/removing_everything_from_github/
https://www.mirbsd.org/permalinks/wlog-10_e20170301-tg.htm
But also voices that don't see a problem:
https://www.earth.li/~noodles/blog/2017/03/github-tos-change.html
If your're german-speaking you may also want to read the two Heise
articles:
https://www.heise.de/developer/meldung/GitHub-eckt-mit-neuen-Nutzungsbedingungen-an-3647980.html
https://www.heise.de/developer/meldung/FSF-aeussert-sich-zu-den-GitHub-Nutzungsbedingungen-3657040.html
We trust that the problematic part in section D.5:
"If you set your pages and repositories to be viewed publicly, you grant
each User of GitHub a nonexclusive, worldwide license to access your
Content through the GitHub Service, and to use, display and perform your
Content, and to reproduce your Content solely on GitHub as permitted
through GitHub's functionality." that the part "solely on GitHub as
permitted through GitHub's functionality" also applies to "display and
perform your Content". If the latter part of the sentence would stand
alone it could be interpreted that we would grant *everybody*
essentially an unlimited license (which we cannot because the authors
from whom we forked applied other licenses). This interpretation is
further supported by the fact that Github writes "You may grant further
rights if you adopt a license." that in fact the statements above only
apply to the rendering on Github.
Note that in the following we have two licenses, the 3-clause BSD and
the LGPL license in short:
- Contiki OS (and our modification to it) are 3-clause BSD
- Our Arduino compatibility Layer on top of Contiki OS is LGPL
Contiki is licensed under the 3-clause BSD license. This license gives Contiki is licensed under the 3-clause BSD license. This license gives
everyone the right to use and distribute the code, either in binary or everyone the right to use and distribute the code, either in binary or
source code format, as long as the copyright license is retained in source code format, as long as the copyright license is retained in
@ -36,3 +70,463 @@ of license. The license text is:
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
Arduino-compatibility layer if not otherwise noted is under the
following license:
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

View file

@ -304,6 +304,25 @@ endif
%.flashprof: %.$(TARGET) %.flashprof: %.$(TARGET)
$(NM) -S -td --size-sort $< | grep -i " [t] " | cut -d' ' -f2,4 $(NM) -S -td --size-sort $< | grep -i " [t] " | cut -d' ' -f2,4
viewconf:
@echo "----------------- Make variables: --------------"
@echo "##### \"TARGET\": ________________________________ $(TARGET)"
@echo "##### \"BOARD\": _________________________________ $(BOARD)"
@echo "##### \"MAKE_MAC\": ______________________________ $(MAKE_MAC)"
@echo "##### \"MAKE_NET\": ______________________________ $(MAKE_NET)"
@echo "##### \"MAKE_ROUTING\": __________________________ $(MAKE_ROUTING)"
ifdef MAKE_COAP_DTLS_KEYSTORE
@echo "##### \"MAKE_COAP_DTLS_KEYSTORE\": _______________ $(MAKE_COAP_DTLS_KEYSTORE)"
endif
@echo "----------------- C variables: -----------------"
$(Q)$(CC) $(CFLAGS) -E $(CONTIKI)/tools/viewconf.c | grep \#\#\#\#\#
@echo "------------------------------------------------"
@echo "'==' Means the flag is set to a given a value"
@echo "'->' Means the flag is unset, but will default to a given value"
@echo "'><' Means the flag is unset and has no default value"
@echo "To view more Make variables, edit $(CONTIKI)/Makefile.include, rule 'viewconf'"
@echo "To view more C variables, edit $(CONTIKI)/tools/viewconf.c"
# Don't treat %.$(TARGET) as an intermediate file because it is # Don't treat %.$(TARGET) as an intermediate file because it is
# in fact the primary target. # in fact the primary target.
.PRECIOUS: %.$(TARGET) .PRECIOUS: %.$(TARGET)

View file

@ -1,8 +1,6 @@
The Contiki Operating System The Contiki Operating System
============================ ============================
[![Build Status](https://travis-ci.org/contiki-os/contiki.svg?branch=master)](https://travis-ci.org/contiki-os/contiki/branches)
Contiki is an open source operating system that runs on tiny low-power Contiki is an open source operating system that runs on tiny low-power
microcontrollers and makes it possible to develop applications that microcontrollers and makes it possible to develop applications that
make efficient use of the hardware while providing standardized make efficient use of the hardware while providing standardized
@ -17,3 +15,12 @@ and so on.
For more information, see the Contiki website: For more information, see the Contiki website:
[http://contiki-os.org](http://contiki-os.org) [http://contiki-os.org](http://contiki-os.org)
This fork of the Contiki Operating System adds support for our Merkur
Board, adds a lot of examples (with different hardware) and puts an
Arduino compatibility layer on top of Contiki-OS that allows Arduino
Sketches -- and a lot of drivers for Arduino compatible hardware -- to
run under Contiki-OS.
For the licensing terms (also in the light of recent debates of Github
changed Terms of Service on 2017-03-01) see the file LICENSE.

View file

@ -56,6 +56,8 @@
#include "adc.h" #include "adc.h"
#include "hw-arduino.h" #include "hw-arduino.h"
#include "contiki.h" #include "contiki.h"
#include "project-conf.h"
#define DEBUG 0 #define DEBUG 0
#if DEBUG #if DEBUG
@ -78,18 +80,34 @@ extern resource_t res_event, res_separate;
#endif /* PLATFORM_HAS_BUTTON */ #endif /* PLATFORM_HAS_BUTTON */
volatile uint8_t mcusleepcycleval; volatile uint8_t mcusleepcycleval;
/* 0 dont sleep; 1 sleep */
uint8_t mcusleep;
/*-------------- enabled sleep mode ----------------------------------------*/ /*-------------- enabled sleep mode ----------------------------------------*/
void void
mcu_sleep_init(void) mcu_sleep_init(void)
{ {
mcusleepcycleval=mcusleepcycle; mcusleepcycleval=mcusleepcycle;
mcu_sleep_disable(); // if a shell is active we can type
}
void
mcu_sleep_disable(void)
{
mcusleep=2;
mcu_sleep_off();
}
void
mcu_sleep_enable(void)
{
mcusleep=0;
} }
void void
mcu_sleep_on(void) mcu_sleep_on(void)
{ {
if(mcusleep == 0){
mcusleepcycle= mcusleepcycleval; mcusleepcycle= mcusleepcycleval;
} }
}
/*--------------- disable sleep mode ---------------------------------------*/ /*--------------- disable sleep mode ---------------------------------------*/
void void
mcu_sleep_off(void) mcu_sleep_off(void)
@ -101,7 +119,7 @@ void
mcu_sleep_set(uint8_t value) mcu_sleep_set(uint8_t value)
{ {
mcusleepcycleval= value; mcusleepcycleval= value;
mcusleepcycle = mcusleepcycleval; // mcusleepcycle = mcusleepcycleval;
} }
PROCESS(arduino_sketch, "Arduino Sketch Wrapper"); PROCESS(arduino_sketch, "Arduino Sketch Wrapper");
@ -109,10 +127,12 @@ PROCESS(arduino_sketch, "Arduino Sketch Wrapper");
#ifndef LOOP_INTERVAL #ifndef LOOP_INTERVAL
#define LOOP_INTERVAL (1 * CLOCK_SECOND) #define LOOP_INTERVAL (1 * CLOCK_SECOND)
#endif #endif
#define START_MCUSLEEP (10 * CLOCK_SECOND)
PROCESS_THREAD(arduino_sketch, ev, data) PROCESS_THREAD(arduino_sketch, ev, data)
{ {
static struct etimer loop_periodic_timer; static struct etimer loop_periodic_timer;
static struct etimer start_mcusleep_timer;
PROCESS_BEGIN(); PROCESS_BEGIN();
adc_init (); adc_init ();
@ -120,6 +140,7 @@ PROCESS_THREAD(arduino_sketch, ev, data)
setup (); setup ();
/* Define application-specific events here. */ /* Define application-specific events here. */
etimer_set(&loop_periodic_timer, LOOP_INTERVAL); etimer_set(&loop_periodic_timer, LOOP_INTERVAL);
etimer_set(&start_mcusleep_timer, START_MCUSLEEP);
while (1) { while (1) {
PROCESS_WAIT_EVENT(); PROCESS_WAIT_EVENT();
@ -131,6 +152,18 @@ PROCESS_THREAD(arduino_sketch, ev, data)
mcu_sleep_on(); mcu_sleep_on();
} }
#endif /* PLATFORM_HAS_BUTTON */ #endif /* PLATFORM_HAS_BUTTON */
if(etimer_expired(&start_mcusleep_timer)) {
PRINTF("mcusleep_timer %d\n",mcusleep);
if(mcusleep == 1){
PRINTF("mcu sleep on\n");
mcu_sleep_enable();
mcu_sleep_on();
}
if (mcusleep > 0) {
mcusleep--;
}
etimer_reset(&start_mcusleep_timer);
}
if(etimer_expired(&loop_periodic_timer)) { if(etimer_expired(&loop_periodic_timer)) {
mcu_sleep_off(); mcu_sleep_off();

View file

@ -52,8 +52,12 @@
#include "contiki.h" #include "contiki.h"
/*--------------- enable sleep mode ---------------------------------------*/ /*--------------- enable sleep mode ---------------------------------------*/
void mcu_sleep_on(void); void mcu_sleep_enable(void);
/*--------------- disable sleep mode ---------------------------------------*/ /*--------------- disable sleep mode ---------------------------------------*/
void mcu_sleep_disable(void);
/*--------------- sleep mode on---------------------------------------*/
void mcu_sleep_on(void);
/*--------------- sleep mode off---------------------------------------*/
void mcu_sleep_off(void); void mcu_sleep_off(void);
/*---------------- set sleep value ------------------------------------*/ /*---------------- set sleep value ------------------------------------*/
void mcu_sleep_set(uint8_t value); void mcu_sleep_set(uint8_t value);

View file

@ -4,3 +4,18 @@ er-coap_src = er-coap.c er-coap-engine.c er-coap-transactions.c \
# Erbium will implement the REST Engine # Erbium will implement the REST Engine
CFLAGS += -DREST=coap_rest_implementation CFLAGS += -DREST=coap_rest_implementation
ifeq ($(WITH_DTLS_COAP),1)
er-coap_src += er-coap-dtls.c
# Load tinydtls
APPS += tinydtls
$(CONTIKI)/apps/tinydtls/Makefile.tinydtls:
@echo " You should run 'git submodule update --init' to clone 'app/tinydtls'"
@exit 1
include $(CONTIKI)/apps/tinydtls/Makefile.tinydtls
PROJECTDIRS+=$(CONTIKI)/apps/tinydtls/aes $(CONTIKI)/apps/tinydtls/sha2 $(CONTIKI)/apps/tinydtls/ecc
else
er-coap_src += er-coap-udp.c
endif

View file

@ -0,0 +1,15 @@
#ifndef _ER_COAP_COMMUNICATION_H_
#define _ER_COAP_COMMUNICATION_H_
#include "contiki.h"
void
coap_init_communication_layer(uint16_t port);
void
coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, uint16_t length);
void
coap_handle_receive(void);
#endif

View file

@ -94,6 +94,7 @@ typedef enum {
NOT_FOUND_4_04 = 132, /* NOT_FOUND */ NOT_FOUND_4_04 = 132, /* NOT_FOUND */
METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */ METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */
NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */ NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */
REQUEST_ENTITY_INCOMPLETE_4_08 = 136, /* REQUEST_ENTITY_INCOMPLETE */
PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */ PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */
REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */ REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */
UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */ UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */

161
apps/er-coap/er-coap-dtls.c Normal file
View file

@ -0,0 +1,161 @@
#include "contiki.h"
#include "contiki-net.h"
#include "er-coap.h"
#include "er-coap-engine.h"
#include "dtls.h"
#include <string.h>
#define DEBUG DEBUG_NONE
#include "dtls_debug.h"
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static struct dtls_context_t *dtls_ctx = NULL;
static dtls_handler_t coap_dtls_callback = {
.write = coap_dtls_send_to_peer,
.read = coap_dtls_read_from_peer,
.event = NULL,
#ifdef DTLS_PSK
.get_psk_info = coap_dtls_get_psk_info,
#endif
#ifdef DTLS_ECC
.get_ecdsa_key = NULL,
.verify_ecdsa_key = NULL,
#endif
};
/*-----------------------------------------------------------------------------------*/
void
coap_init_communication_layer(uint16_t port)
{
struct uip_udp_conn *udp_conn = NULL;
dtls_init();
dtls_set_log_level(DTLS_LOG_DEBUG);
udp_conn = udp_new(NULL, 0, NULL);
udp_bind(udp_conn, port);
dtls_ctx = dtls_new_context(udp_conn);
if(dtls_ctx) {
dtls_set_handler(dtls_ctx, &COAP_DTLS_CALLBACK);
}
/* new connection with remote host */
printf("COAP-DTLS listening on port %u\n", uip_ntohs(udp_conn->lport));
}
/*-----------------------------------------------------------------------------------*/
void
coap_send_message(uip_ipaddr_t *addr, uint16_t port,
uint8_t *data, uint16_t length)
{
session_t session;
dtls_session_init(&session);
uip_ipaddr_copy(&session.addr, addr);
session.port = port;
dtls_write(dtls_ctx, &session, data, length);
}
/*-----------------------------------------------------------------------------------*/
void
coap_handle_receive()
{
session_t session;
if(uip_newdata()) {
dtls_session_init(&session);
uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr);
session.port = UIP_UDP_BUF->srcport;
dtls_handle_message(dtls_ctx, &session, uip_appdata, uip_datalen());
}
}
/* DTLS Specific functions */
/*-----------------------------------------------------------------------------------*/
#ifdef DTLS_PSK
/* This function is the "key store" for tinyDTLS. It is called to
* retrieve a key for the given identiy within this particular
* session. */
int
coap_dtls_get_psk_info(struct dtls_context_t *ctx, const session_t *session,
dtls_credentials_type_t type,
const unsigned char *id, size_t id_len,
unsigned char *result, size_t result_length)
{
struct keymap_t {
unsigned char *id;
size_t id_length;
unsigned char *key;
size_t key_length;
} psk[1] = {
{ (unsigned char *)DTLS_IDENTITY, DTLS_IDENTITY_LENGTH, (unsigned char *)DTLS_PSK_KEY_VALUE, DTLS_PSK_KEY_VALUE_LENGTH },
};
if(type == DTLS_PSK_IDENTITY) {
if(id_len) {
dtls_debug("got psk_identity_hint: '%.*s'\n", id_len, id);
}
if(result_length < psk[0].id_length) {
dtls_warn("cannot set psk_identity -- buffer too small\n");
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
}
memcpy(result, psk[0].id, psk[0].id_length);
return psk[0].id_length;
} else if(type == DTLS_PSK_KEY) {
if(id) {
int i;
for(i = 0; i < sizeof(psk) / sizeof(struct keymap_t); i++) {
if(id_len == psk[i].id_length && memcmp(id, psk[i].id, id_len) == 0) {
if(result_length < psk[i].key_length) {
dtls_warn("buffer too small for PSK");
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
}
memcpy(result, psk[i].key, psk[i].key_length);
return psk[i].key_length;
}
}
}
} else {
return 0;
}
return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR);
}
#endif
/*-----------------------------------------------------------------------------------*/
int
coap_dtls_send_to_peer(struct dtls_context_t *ctx,
session_t *session, uint8 *data, size_t len)
{
struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx);
uip_ipaddr_copy(&conn->ripaddr, &session->addr);
conn->rport = session->port;
uip_udp_packet_send(conn, data, len);
/* Restore server connection to allow data from any node */
memset(&conn->ripaddr, 0, sizeof(conn->ripaddr));
memset(&conn->rport, 0, sizeof(conn->rport));
return len;
}
/*-----------------------------------------------------------------------------------*/
int
coap_dtls_read_from_peer(struct dtls_context_t *ctx,
session_t *session, uint8 *data, size_t len)
{
uip_len = len;
memmove(uip_appdata, data, len);
coap_receive(ctx);
return 0;
}

View file

@ -0,0 +1,47 @@
#ifndef COAP_DTLS_H_
#define COAP_DTLS_H_
/* Internal configuration of tinydtls for er-coap-dtls */
#if defined DTLS_CONF_IDENTITY && defined DTLS_CONF_IDENTITY_LENGTH
#define DTLS_IDENTITY DTLS_CONF_IDENTITY
#define DTLS_IDENTITY_LENGTH DTLS_CONF_IDENTITY_LENGTH
#else
#define DTLS_IDENTITY "Client_identity"
#define DTLS_IDENTITY_LENGTH 15
#endif
#if defined DTLS_CONF_PSK_KEY && defined DTLS_CONF_PSK_KEY_LENGTH
#define DTLS_PSK_KEY_VALUE DTLS_CONF_PSK_KEY
#define DTLS_PSK_KEY_VALUE_LENGTH DTLS_CONF_PSK_KEY_LENGTH
#else
#warning "DTLS: Using default secret key !"
#define DTLS_PSK_KEY_VALUE "secretPSK"
#define DTLS_PSK_KEY_VALUE_LENGTH 9
#endif
/* Structure that hold tinydtls callbacks, has type 'dtls_handler_t'. */
#ifndef COAP_DTLS_CALLBACK
#ifdef COAP_DTLS_CONF_CALLBACK
#define COAP_DTLS_CALLBACK COAP_DTLS_CONF_CALLBACK
#else /* COAP_DTLS_CONF_CALLBACK */
#define COAP_DTLS_CALLBACK coap_dtls_callback
#endif /* COAP_DTLS_CALLBACK */
/* Send 'data' to peer defined by session */
int coap_dtls_send_to_peer(struct dtls_context_t *ctx,
session_t *session, uint8 *data, size_t len);
/* Read 'data' from peer */
int coap_dtls_read_from_peer(struct dtls_context_t *ctx,
session_t *session, uint8 *data, size_t len);
#ifdef DTLS_PSK
/* Retrieve the key for given identity withing this session */
int coap_dtls_get_psk_info(struct dtls_context_t *ctx,
const session_t *session,
dtls_credentials_type_t type,
const unsigned char *id, size_t id_len,
unsigned char *result, size_t result_length);
#endif
#endif /* COAP_DTLS_H_ */

View file

@ -41,6 +41,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "er-coap-engine.h" #include "er-coap-engine.h"
#include "er-coap-communication.h"
#define DEBUG 0 #define DEBUG 0
#if DEBUG #if DEBUG
@ -64,8 +65,8 @@ static service_callback_t service_cbk = NULL;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*- Internal API ------------------------------------------------------------*/ /*- Internal API ------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int int
coap_receive(void) coap_receive()
{ {
erbium_status_code = NO_ERROR; erbium_status_code = NO_ERROR;
@ -346,7 +347,7 @@ PROCESS_THREAD(coap_engine, ev, data)
PROCESS_YIELD(); PROCESS_YIELD();
if(ev == tcpip_event) { if(ev == tcpip_event) {
coap_receive(); coap_handle_receive();
} else if(ev == PROCESS_EVENT_TIMER) { } else if(ev == PROCESS_EVENT_TIMER) {
/* retransmissions are handled here */ /* retransmissions are handled here */
coap_check_transactions(); coap_check_transactions();
@ -482,6 +483,7 @@ const struct rest_implementation coap_rest_implementation = {
NOT_FOUND_4_04, NOT_FOUND_4_04,
METHOD_NOT_ALLOWED_4_05, METHOD_NOT_ALLOWED_4_05,
NOT_ACCEPTABLE_4_06, NOT_ACCEPTABLE_4_06,
REQUEST_ENTITY_INCOMPLETE_4_08,
REQUEST_ENTITY_TOO_LARGE_4_13, REQUEST_ENTITY_TOO_LARGE_4_13,
UNSUPPORTED_MEDIA_TYPE_4_15, UNSUPPORTED_MEDIA_TYPE_4_15,
INTERNAL_SERVER_ERROR_5_00, INTERNAL_SERVER_ERROR_5_00,

View file

@ -52,6 +52,7 @@ typedef coap_packet_t rest_request_t;
typedef coap_packet_t rest_response_t; typedef coap_packet_t rest_response_t;
void coap_init_engine(void); void coap_init_engine(void);
int coap_receive();
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*- Client Part -------------------------------------------------------------*/ /*- Client Part -------------------------------------------------------------*/

View file

@ -107,7 +107,7 @@ int coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port,
int coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, int coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port,
const char *url); const char *url);
void coap_handle_notification(uip_ipaddr_t *, uint16_t port, void coap_handle_notification(uip_ipaddr_t *addr, uint16_t port,
coap_packet_t *notification); coap_packet_t *notification);
coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr, coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr,

View file

@ -249,6 +249,8 @@ coap_notify_observers_sub(resource_t *resource, const char *subpath)
if(notification->code < BAD_REQUEST_4_00) { if(notification->code < BAD_REQUEST_4_00) {
coap_set_header_observe(notification, (obs->obs_counter)++); coap_set_header_observe(notification, (obs->obs_counter)++);
/* mask out to keep the CoAP observe option length <= 3 bytes */
obs->obs_counter &= 0xffffff;
} }
coap_set_token(notification, obs->token, obs->token_len); coap_set_token(notification, obs->token, obs->token_len);
@ -276,6 +278,8 @@ coap_observe_handler(resource_t *resource, void *request, void *response)
coap_req->uri_path, coap_req->uri_path_len); coap_req->uri_path, coap_req->uri_path_len);
if(obs) { if(obs) {
coap_set_header_observe(coap_res, (obs->obs_counter)++); coap_set_header_observe(coap_res, (obs->obs_counter)++);
/* mask out to keep the CoAP observe option length <= 3 bytes */
obs->obs_counter &= 0xffffff;
/* /*
* Following payload is for demonstration purposes only. * Following payload is for demonstration purposes only.
* A subscription should return the same representation as a normal GET. * A subscription should return the same representation as a normal GET.

View file

@ -0,0 +1,42 @@
#include "contiki.h"
#include "contiki-net.h"
#include "er-coap-engine.h"
#include "er-coap-communication.h"
#include <string.h>
#define DEBUG DEBUG_NONE
#include "uip-debug.h"
static struct uip_udp_conn *udp_conn = NULL;
/*-----------------------------------------------------------------------------------*/
void
coap_init_communication_layer(uint16_t port)
{
/* new connection with remote host */
udp_conn = udp_new(NULL, 0, NULL);
udp_bind(udp_conn, port);
PRINTF("Listening on port %u\n", uip_ntohs(udp_conn->lport));
}
/*-----------------------------------------------------------------------------------*/
void
coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, uint16_t length)
{
/* Configure connection to reply to client */
uip_ipaddr_copy(&udp_conn->ripaddr, addr);
udp_conn->rport = port;
uip_udp_packet_send(udp_conn, data, length);
PRINTF("-sent UDP datagram (%u)-\n", length);
/* Restore server connection to allow data from any node */
memset(&udp_conn->ripaddr, 0, sizeof(udp_conn->ripaddr));
udp_conn->rport = 0;
}
/*-----------------------------------------------------------------------------------*/
void
coap_handle_receive()
{
coap_receive();
}

View file

@ -44,6 +44,7 @@
#include "er-coap.h" #include "er-coap.h"
#include "er-coap-transactions.h" #include "er-coap-transactions.h"
#include "er-coap-communication.h"
#define DEBUG 0 #define DEBUG 0
#if DEBUG #if DEBUG
@ -60,7 +61,6 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*- Variables ---------------------------------------------------------------*/ /*- Variables ---------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static struct uip_udp_conn *udp_conn = NULL;
static uint16_t current_mid = 0; static uint16_t current_mid = 0;
coap_status_t erbium_status_code = NO_ERROR; coap_status_t erbium_status_code = NO_ERROR;
@ -279,9 +279,7 @@ void
coap_init_connection(uint16_t port) coap_init_connection(uint16_t port)
{ {
/* new connection with remote host */ /* new connection with remote host */
udp_conn = udp_new(NULL, 0, NULL); coap_init_communication_layer(port);
udp_bind(udp_conn, port);
PRINTF("Listening on port %u\n", uip_ntohs(udp_conn->lport));
/* initialize transaction ID */ /* initialize transaction ID */
current_mid = random_rand(); current_mid = random_rand();
@ -422,23 +420,6 @@ coap_serialize_message(void *packet, uint8_t *buffer)
return (option - buffer) + coap_pkt->payload_len; /* packet length */ return (option - buffer) + coap_pkt->payload_len; /* packet length */
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void
coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data,
uint16_t length)
{
/* configure connection to reply to client */
uip_ipaddr_copy(&udp_conn->ripaddr, addr);
udp_conn->rport = port;
uip_udp_packet_send(udp_conn, data, length);
PRINTF("-sent UDP datagram (%u)-\n", length);
/* restore server socket to allow data from any node */
memset(&udp_conn->ripaddr, 0, sizeof(udp_conn->ripaddr));
udp_conn->rport = 0;
}
/*---------------------------------------------------------------------------*/
coap_status_t coap_status_t
coap_parse_message(void *packet, uint8_t *data, uint16_t data_len) coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
{ {
@ -529,8 +510,21 @@ coap_parse_message(void *packet, uint8_t *data, uint16_t data_len)
++current_option; ++current_option;
} }
if(current_option + option_length > data + data_len) {
/* Malformed CoAP - out of bounds */
PRINTF("BAD REQUEST: options outside data packet: %u > %u\n",
(unsigned)(current_option + option_length - data), data_len);
return BAD_REQUEST_4_00;
}
option_number += option_delta; option_number += option_delta;
if(option_number > COAP_OPTION_SIZE1) {
/* Malformed CoAP - out of bounds */
PRINTF("BAD REQUEST: option number too large: %u\n", option_number);
return BAD_REQUEST_4_00;
}
PRINTF("OPTION %u (delta %u, len %zu): ", option_number, option_delta, PRINTF("OPTION %u (delta %u, len %zu): ", option_number, option_delta,
option_length); option_length);

View file

@ -119,6 +119,20 @@ static const char *get_uri (void *request)
return buf; return buf;
} }
static const char *get_query (void *request)
{
static char buf [MAX_QUERY_STRING_LENGTH];
const char *query;
size_t len = coap_get_header_uri_query (request, &query);
if (len > sizeof (buf) - 1) {
*buf = '\0';
} else {
strncpy (buf, query, len);
buf [len] = '\0';
}
return buf;
}
void generic_get_handler void generic_get_handler
( void *request ( void *request
, void *response , void *response
@ -127,7 +141,12 @@ void generic_get_handler
, int32_t *offset , int32_t *offset
, char *name , char *name
, int is_str , int is_str
, size_t (*to_str)(const char *name, const char *uri, char *buf, size_t bsize) , size_t (*to_str)
( const char *name
, const char *uri
, const char *query
, char *buf, size_t bsize
)
) )
{ {
int success = 1; int success = 1;
@ -135,6 +154,7 @@ void generic_get_handler
size_t len = 0; size_t len = 0;
unsigned int accept = -1; unsigned int accept = -1;
const char *uri = get_uri (request); const char *uri = get_uri (request);
const char *query = get_query (request);
REST.get_header_accept (request, &accept); REST.get_header_accept (request, &accept);
if ( accept != -1 if ( accept != -1
@ -160,7 +180,7 @@ void generic_get_handler
success = 0; success = 0;
goto out; goto out;
} }
len += to_str (name, uri, temp + len, sizeof (temp) - len); len += to_str (name, uri, query, temp + len, sizeof (temp) - len);
if (len > sizeof (temp)) { if (len > sizeof (temp)) {
success = 0; success = 0;
goto out; goto out;
@ -176,7 +196,7 @@ void generic_get_handler
goto out; goto out;
} }
} else { // TEXT Format } else { // TEXT Format
len += to_str (name, uri, temp + len, sizeof (temp) - len); len += to_str (name, uri, query, temp + len, sizeof (temp) - len);
if (len > sizeof (temp)) { if (len > sizeof (temp)) {
success = 0; success = 0;
goto out; goto out;
@ -203,7 +223,8 @@ void generic_put_handler
, uint16_t preferred_size , uint16_t preferred_size
, int32_t *offset , int32_t *offset
, char *name , char *name
, int (*from_str)(const char *name, const char *uri, const char *s) , int (*from_str)
(const char *name, const char *uri, const char *query, const char *s)
) )
{ {
int success = 1; int success = 1;
@ -212,6 +233,7 @@ void generic_put_handler
const uint8_t *bytes = NULL; const uint8_t *bytes = NULL;
unsigned int c_ctype; unsigned int c_ctype;
const char *uri = get_uri (request); const char *uri = get_uri (request);
const char *query = get_query (request);
REST.get_header_content_type (request, &c_ctype); REST.get_header_content_type (request, &c_ctype);
if (from_str && (len = coap_get_payload (request, &bytes))) { if (from_str && (len = coap_get_payload (request, &bytes))) {
@ -226,7 +248,7 @@ void generic_put_handler
goto out; goto out;
} }
} }
if (from_str (name, uri, temp) < 0) { if (from_str (name, uri, query, temp) < 0) {
success = 0; success = 0;
} else { } else {
REST.set_response_status (response, REST.status.CHANGED); REST.set_response_status (response, REST.status.CHANGED);

View file

@ -52,6 +52,7 @@
#define MAX_GET_STRING_LENGTH 100 #define MAX_GET_STRING_LENGTH 100
#define MAX_URI_STRING_LENGTH 30 #define MAX_URI_STRING_LENGTH 30
#define MAX_QUERY_STRING_LENGTH 30
/* /*
* A macro that extends the resource definition and also sets up the * A macro that extends the resource definition and also sets up the
@ -124,11 +125,8 @@ extern int8_t json_parse_variable
* *
* The callback functions get the name of the parameter as a first * The callback functions get the name of the parameter as a first
* argument, this allows to re-use the same function for different * argument, this allows to re-use the same function for different
* parameters. * parameters. In addition it gets a buffer and the size of the buffer.
* For the to_str function the is_json flag allows to generate a * It needs to return the number of bytes output, similar to sprintf.
* different string depending on the content-type. In addition it gets a
* buffer and the size of the buffer. It needs to return the number of
* bytes output, similar to sprintf.
*/ */
extern void generic_get_handler extern void generic_get_handler
( void *request ( void *request
@ -138,7 +136,13 @@ extern void generic_get_handler
, int32_t *offset , int32_t *offset
, char *name , char *name
, int is_str , int is_str
, size_t (*to_str)(const char *name, const char *uri, char *buf, size_t bsize) , size_t (*to_str)
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
); );
/** /**
@ -161,7 +165,8 @@ extern void generic_put_handler
, uint16_t preferred_size , uint16_t preferred_size
, int32_t *offset , int32_t *offset
, char *name , char *name
, int (*from_str)(const char *name, const char *uri, const char *s) , int (*from_str)
(const char *name, const char *uri, const char *query, const char *s)
); );
/* /*

View file

@ -130,6 +130,7 @@ typedef enum {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Protothread send macros */ /* Protothread send macros */
#define PT_MQTT_WRITE_BYTES(conn, data, len) \ #define PT_MQTT_WRITE_BYTES(conn, data, len) \
conn->out_write_pos = 0; \
while(write_bytes(conn, data, len)) { \ while(write_bytes(conn, data, len)) { \
PT_WAIT_UNTIL(pt, (conn)->out_buffer_sent); \ PT_WAIT_UNTIL(pt, (conn)->out_buffer_sent); \
} }
@ -147,15 +148,19 @@ typedef enum {
*/ */
#define PT_MQTT_WAIT_SEND() \ #define PT_MQTT_WAIT_SEND() \
do { \ do { \
process_post(PROCESS_CURRENT(), mqtt_continue_send_event, NULL); \ if (PROCESS_ERR_OK == \
process_post(PROCESS_CURRENT(), mqtt_continue_send_event, NULL)) { \
do { \
PROCESS_WAIT_EVENT(); \ PROCESS_WAIT_EVENT(); \
if(ev == mqtt_abort_now_event) { \ if(ev == mqtt_abort_now_event) { \
conn->state = MQTT_CONN_STATE_ABORT_IMMEDIATE; \ conn->state = MQTT_CONN_STATE_ABORT_IMMEDIATE; \
PT_EXIT(&conn->out_proto_thread); \ PT_INIT(&conn->out_proto_thread); \
process_post(PROCESS_CURRENT(), ev, data); \ process_post(PROCESS_CURRENT(), ev, data); \
} else if(ev >= mqtt_event_min && ev <= mqtt_event_max) { \ } else if(ev >= mqtt_event_min && ev <= mqtt_event_max) { \
process_post(PROCESS_CURRENT(), ev, data); \ process_post(PROCESS_CURRENT(), ev, data); \
} \ } \
} while (ev != mqtt_continue_send_event); \
} \
} while(0) } while(0)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static process_event_t mqtt_do_connect_tcp_event; static process_event_t mqtt_do_connect_tcp_event;
@ -751,6 +756,8 @@ handle_connack(struct mqtt_connection *conn)
call_event(conn, call_event(conn,
MQTT_EVENT_CONNECTION_REFUSED_ERROR, MQTT_EVENT_CONNECTION_REFUSED_ERROR,
&conn->in_packet.payload[1]); &conn->in_packet.payload[1]);
abort_connection(conn);
return;
} }
conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK; conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK;
@ -1186,8 +1193,8 @@ PROCESS_THREAD(mqtt_process, ev, data)
if(conn->state == MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT) { if(conn->state == MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT) {
if(conn->out_buffer_sent == 1) { if(conn->out_buffer_sent == 1) {
PT_INIT(&conn->out_proto_thread); PT_INIT(&conn->out_proto_thread);
while(disconnect_pt(&conn->out_proto_thread, conn) < PT_EXITED && while(conn->state != MQTT_CONN_STATE_ABORT_IMMEDIATE &&
conn->state != MQTT_CONN_STATE_ABORT_IMMEDIATE) { disconnect_pt(&conn->out_proto_thread, conn) < PT_EXITED) {
PT_MQTT_WAIT_SEND(); PT_MQTT_WAIT_SEND();
} }
abort_connection(conn); abort_connection(conn);
@ -1204,8 +1211,8 @@ PROCESS_THREAD(mqtt_process, ev, data)
if(conn->out_buffer_sent == 1 && if(conn->out_buffer_sent == 1 &&
conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
PT_INIT(&conn->out_proto_thread); PT_INIT(&conn->out_proto_thread);
while(pingreq_pt(&conn->out_proto_thread, conn) < PT_EXITED && while(conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER &&
conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { pingreq_pt(&conn->out_proto_thread, conn) < PT_EXITED) {
PT_MQTT_WAIT_SEND(); PT_MQTT_WAIT_SEND();
} }
} }
@ -1217,8 +1224,8 @@ PROCESS_THREAD(mqtt_process, ev, data)
if(conn->out_buffer_sent == 1 && if(conn->out_buffer_sent == 1 &&
conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
PT_INIT(&conn->out_proto_thread); PT_INIT(&conn->out_proto_thread);
while(subscribe_pt(&conn->out_proto_thread, conn) < PT_EXITED && while(conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER &&
conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { subscribe_pt(&conn->out_proto_thread, conn) < PT_EXITED) {
PT_MQTT_WAIT_SEND(); PT_MQTT_WAIT_SEND();
} }
} }
@ -1230,8 +1237,8 @@ PROCESS_THREAD(mqtt_process, ev, data)
if(conn->out_buffer_sent == 1 && if(conn->out_buffer_sent == 1 &&
conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
PT_INIT(&conn->out_proto_thread); PT_INIT(&conn->out_proto_thread);
while(unsubscribe_pt(&conn->out_proto_thread, conn) < PT_EXITED && while(conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER &&
conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { unsubscribe_pt(&conn->out_proto_thread, conn) < PT_EXITED) {
PT_MQTT_WAIT_SEND(); PT_MQTT_WAIT_SEND();
} }
} }
@ -1243,8 +1250,8 @@ PROCESS_THREAD(mqtt_process, ev, data)
if(conn->out_buffer_sent == 1 && if(conn->out_buffer_sent == 1 &&
conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) {
PT_INIT(&conn->out_proto_thread); PT_INIT(&conn->out_proto_thread);
while(publish_pt(&conn->out_proto_thread, conn) < PT_EXITED && while(conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER &&
conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { publish_pt(&conn->out_proto_thread, conn) < PT_EXITED) {
PT_MQTT_WAIT_SEND(); PT_MQTT_WAIT_SEND();
} }
} }
@ -1331,7 +1338,9 @@ mqtt_connect(struct mqtt_connection *conn, char *host, uint16_t port,
conn->connect_vhdr_flags |= MQTT_VHDR_CLEAN_SESSION_FLAG; conn->connect_vhdr_flags |= MQTT_VHDR_CLEAN_SESSION_FLAG;
/* convert the string IPv6 address to a numeric IPv6 address */ /* convert the string IPv6 address to a numeric IPv6 address */
uiplib_ip6addrconv(host, &ip6addr); if(uiplib_ip6addrconv(host, &ip6addr) == 0) {
return MQTT_STATUS_ERROR;
}
uip_ipaddr_copy(&(conn->server_ip), ipaddr); uip_ipaddr_copy(&(conn->server_ip), ipaddr);

View file

@ -196,7 +196,7 @@ typedef enum {
MQTT_CONN_STATE_ERROR, MQTT_CONN_STATE_ERROR,
MQTT_CONN_STATE_DNS_ERROR, MQTT_CONN_STATE_DNS_ERROR,
MQTT_CONN_STATE_DISCONNECTING, MQTT_CONN_STATE_DISCONNECTING,
MQTT_CONN_STATE_ABORT_IMMEDIATE,
MQTT_CONN_STATE_NOT_CONNECTED, MQTT_CONN_STATE_NOT_CONNECTED,
MQTT_CONN_STATE_DNS_LOOKUP, MQTT_CONN_STATE_DNS_LOOKUP,
MQTT_CONN_STATE_TCP_CONNECTING, MQTT_CONN_STATE_TCP_CONNECTING,
@ -204,7 +204,6 @@ typedef enum {
MQTT_CONN_STATE_CONNECTING_TO_BROKER, MQTT_CONN_STATE_CONNECTING_TO_BROKER,
MQTT_CONN_STATE_CONNECTED_TO_BROKER, MQTT_CONN_STATE_CONNECTED_TO_BROKER,
MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT, MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT,
MQTT_CONN_STATE_ABORT_IMMEDIATE,
} mqtt_conn_state_t; } mqtt_conn_state_t;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
struct mqtt_string { struct mqtt_string {

View file

@ -45,6 +45,14 @@
#include "net/ipv6/uip-ds6-route.h" #include "net/ipv6/uip-ds6-route.h"
#include "net/packetbuf.h" #include "net/packetbuf.h"
#include "net/rpl/rpl-conf.h" #include "net/rpl/rpl-conf.h"
#include "net/rpl/rpl-private.h"
/*
* The body of this rule should be compiled only when "nbr_routes" is available,
* otherwise a link error causes build failure. "nbr_routes" is compiled if
* UIP_CONF_MAX_ROUTES != 0. See uip-ds6-route.c.
*/
#if UIP_CONF_MAX_ROUTES != 0
#if ORCHESTRA_UNICAST_SENDER_BASED && ORCHESTRA_COLLISION_FREE_HASH #if ORCHESTRA_UNICAST_SENDER_BASED && ORCHESTRA_COLLISION_FREE_HASH
#define UNICAST_SLOT_SHARED_FLAG ((ORCHESTRA_UNICAST_PERIOD < (ORCHESTRA_MAX_HASH + 1)) ? LINK_OPTION_SHARED : 0) #define UNICAST_SLOT_SHARED_FLAG ((ORCHESTRA_UNICAST_PERIOD < (ORCHESTRA_MAX_HASH + 1)) ? LINK_OPTION_SHARED : 0)
@ -211,3 +219,5 @@ struct orchestra_rule unicast_per_neighbor_rpl_storing = {
child_added, child_added,
child_removed, child_removed,
}; };
#endif /* UIP_MAX_ROUTES */

View file

@ -0,0 +1 @@
ota-update_src = res_bootloader.c res_reboot.c res_upload_image.c

View file

@ -0,0 +1,22 @@
extern resource_t res_upload_image;
extern resource_t res_part_count;
extern resource_t res_part_size;
extern resource_t res_boot_default;
extern resource_t res_boot_next;
extern resource_t res_active_part;
extern resource_t res_part_start;
extern resource_t res_part_ok;
extern resource_t res_reboot;
#define OTA_ACTIVATE_RESOURCES() \
static char resname[] = "ota/update";\
rest_activate_resource (&res_upload_image, resname);\
rest_activate_resource (&res_part_count, (char *)"ota/part_count");\
rest_activate_resource (&res_part_size, (char *)"ota/part_size");\
rest_activate_resource (&res_boot_default, (char *)"ota/boot_default");\
rest_activate_resource (&res_boot_next, (char *)"ota/boot_next");\
rest_activate_resource (&res_active_part, (char *)"ota/active_part");\
rest_activate_resource (&res_part_start, (char *)"ota/part_start");\
rest_activate_resource (&res_part_ok, (char *)"ota/part_ok");\
rest_activate_resource (&res_reboot, (char *)"ota/reboot");

View file

@ -0,0 +1,260 @@
/*
* Copyright (c) 2015, Ralf Schlatterbeck Open Source Consulting
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Bootloader ressources
* \author
* Ralf Schlatterbeck <rsc@runtux.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "contiki.h"
#include "contiki-net.h"
#include "rest-engine.h"
#include "er-coap-engine.h"
#include "uiplib.h"
#include "generic_resource.h"
#include "bootloader_if.h"
#include "Arduino.h"
/*
* Resources to be activated need to be imported through the extern keyword.
* The build system automatically compiles the resources in the
* corresponding sub-directory.
*/
static size_t
part_count
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{
return snprintf (buf, bsize, "%ld", bootloader_get_part_count ());
}
GENERIC_RESOURCE
( part_count
, Partition Count
, count
, 0
, NULL
, part_count
);
static size_t
part_size
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{
return snprintf (buf, bsize, "%ld", bootloader_get_part_size ());
}
GENERIC_RESOURCE
( part_size
, Partition Size
, count
, 0
, NULL
, part_size
);
static size_t
get_boot_default
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{
return snprintf (buf, bsize, "%ld", bootloader_get_boot_default ());
}
static int
set_boot_default
(const char *name, const char *uri, const char *query, const char *s)
{
uint32_t tmp = strtoul (s, NULL, 10);
bootloader_set_boot_default (tmp);
return 0;
}
GENERIC_RESOURCE
( boot_default
, Default boot partition
, count
, 0
, set_boot_default
, get_boot_default
);
static size_t
get_boot_next
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{
return snprintf (buf, bsize, "%ld", bootloader_get_boot_next ());
}
static int
set_boot_next
(const char *name, const char *uri, const char *query, const char *s)
{
uint32_t tmp = strtoul (s, NULL, 10);
bootloader_set_boot_next (tmp);
return 0;
}
GENERIC_RESOURCE
( boot_next
, Next boot partition
, count
, 0
, set_boot_next
, get_boot_next
);
static size_t
get_active_part
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{
return snprintf (buf, bsize, "%ld", bootloader_get_active_part ());
}
GENERIC_RESOURCE
( active_part
, Currently active partition
, count
, 0
, NULL
, get_active_part
);
/*
* Parse query info. We insist that the query starts with 'part='
* Then we parse the integer following the part= string and return the
* number. The number is always positive, if something goes wrong we
* return a negative number.
*/
static int get_query_partition (const char *query)
{
if (strncmp (query, "part=", 5)) {
return -1;
}
return strtoul (query + 5, NULL, 10);
}
static size_t
get_part_start
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{
int idx = get_query_partition (query);
if (idx < 0) {
return snprintf (buf, bsize, "Invalid: \"%s\" use part=N query", query);
}
return snprintf (buf, bsize, "%ld", bootloader_get_part_start (idx));
}
GENERIC_RESOURCE
( part_start
, Start of partition
, count
, 0
, NULL
, get_part_start
);
static int
set_part_ok
(const char *name, const char *uri, const char *query, const char *s)
{
uint32_t tmp = strtoul (s, NULL, 10);
int idx = get_query_partition (query);
if (idx < 0) {
return -1;
}
if (tmp) {
bootloader_set_part_ok (idx);
} else {
bootloader_clr_part_ok (idx);
}
return 0;
}
static size_t
get_part_ok
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{
int idx = get_query_partition (query);
if (idx < 0) {
return snprintf (buf, bsize, "Invalid: \"%s\" use part=N query", query);
}
return snprintf (buf, bsize, "%ld", bootloader_get_part_ok (idx));
}
GENERIC_RESOURCE
( part_ok
, Set/Clear Partition OK flag
, count
, 0
, set_part_ok
, get_part_ok
);

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2017, Marcus Priesch Open Source Consulting
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Reboot ressource
* \author
* Marcus Priesch <marcus@priesch.co.at>
*/
#include <stdio.h>
#include <string.h>
#include "contiki.h"
#include "er-coap-engine.h"
#include "generic_resource.h"
#include "dev/watchdog.h"
PROCESS(reboot_process, "reboot");
PROCESS_THREAD(reboot_process, ev, data)
{
static struct etimer etimer;
//PROCESS_EXITHANDLER(leds_off(LEDS_ALL);)
PROCESS_BEGIN();
//shell_output_str(&reboot_command,
// "Rebooting the node in four seconds...", "");
etimer_set(&etimer, CLOCK_SECOND * 4);
PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
//leds_on(LEDS_RED);
//etimer_reset(&etimer);
//PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
//leds_on(LEDS_GREEN);
//etimer_reset(&etimer);
//PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
//leds_on(LEDS_BLUE);
//etimer_reset(&etimer);
//PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
watchdog_reboot();
PROCESS_END();
}
static size_t
get_reboot
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{
return snprintf (buf, bsize, "put 'OK' to reboot.");
}
static int
do_reboot
(const char *name, const char *uri, const char *query, const char *s)
{
if (strncmp (s, "OK", 2) == 0) {
process_start (&reboot_process, NULL);
return 0;
}
return 0;
}
GENERIC_RESOURCE
( reboot
, Reboot node
, count
, 0
, do_reboot
, get_reboot
);

View file

@ -0,0 +1,243 @@
/*
* Copyright (C) 2017, Marcus Priesch, Ralf Schlatterbeck
* with code from the res-plugtest-large-update.c by
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Over-the-air update using blockwise transfer
* \author
* Marcus Priesch <marcus@priesch.co.at>
* Ralf Schlatterbeck <rsc@runtux.com>
*/
#include <string.h>
#include "sys/cc.h"
#include "rest-engine.h"
#include "er-coap.h"
#include "contiki.h"
#include "contiki-net.h"
#include "er-coap.h"
#include "Arduino.h"
#include <avr/interrupt.h>
#include "bootloader_if.h"
#if 1
#include <stdio.h>
#define PRINTF(x) printf x
#else
#define PRINTF(x)
#endif
// We allocate this statically, otherwise we cannot flash a new image
// when ram is exhausted!
static uint8_t current_page [256];
static uint32_t current_offset = 0;
#define PAGESIZE (sizeof (current_page))
/*
* Note that the current code relies on the fact that the bootloader
* used only supports two images. This may change in the future. We
* mainly need to relax some of the checks and use a different algorithm
* for computing imgidx, the index of the partition to be overwritten.
* If the bootloader supports more than two partitions at some point we
* may want the uploader to explicitly define the partition to be used.
*/
static void
res_put_handler
( void *request
, void *response
, uint8_t *buffer
, uint16_t preferred_size
, int32_t *offset
)
{
coap_packet_t *const packet = (coap_packet_t *)request;
uint8_t *in_data = NULL;
size_t len = 0;
uint32_t partition_start = 0;
const uint32_t partition_size = bootloader_get_part_size ();
uint32_t imgidx = 0;
unsigned int ct = -1;
/* If the currently-booted partition is not the default partition we
* do not allow overwriting a partition: Neither the currently-booted
* one (this would crash) nor the only partition that is marked
* bootable. We also insist that boot_next == boot_default.
*/
if (bootloader_get_boot_default () != bootloader_get_boot_next ()) {
REST.set_response_status (response, REST.status.BAD_REQUEST);
const char *error_msg = "Won't overwrite boot_next";
REST.set_response_payload (response, error_msg, strlen (error_msg));
return;
}
if (bootloader_get_boot_default () != bootloader_get_active_part ()) {
REST.set_response_status (response, REST.status.BAD_REQUEST);
const char *error_msg = "Won't overwrite current";
REST.set_response_payload (response, error_msg, strlen (error_msg));
return;
}
imgidx = !bootloader_get_active_part ();
partition_start = bootloader_get_part_start (imgidx);
REST.get_header_content_type (request, &ct);
/* Require content_type APPLICATION_OCTET_STREAM */
if (ct != REST.type.APPLICATION_OCTET_STREAM) {
REST.set_response_status (response, REST.status.BAD_REQUEST);
const char *error_msg = "ContentType";
REST.set_response_payload (response, error_msg, strlen (error_msg));
return;
}
len = REST.get_request_payload (request, (const uint8_t **)&in_data);
PRINTF (("cur: %lu len: %lu, offset: %lu\n",
(uint32_t)current_offset, (uint32_t)len, (uint32_t)*offset));
PRINTF (("b1-offs: %lu, b1-size: %u, b1-num: %lu b1-more: %d b1-size1: %lu\n",
packet->block1_offset, packet->block1_size, packet->block1_num,
packet->block1_more, packet->size1));
if (len == 0 || NULL == in_data) {
REST.set_response_status (response, REST.status.BAD_REQUEST);
const char *error_msg = "NoPayload";
REST.set_response_payload (response, error_msg, strlen (error_msg));
return;
}
/* if the block1_offset is 0 a new transmission has started */
if (!packet->block1_offset) {
current_offset = 0;
}
if (packet->block1_offset > current_offset) {
REST.set_response_status (response, REST.status.REQUEST_ENTITY_INCOMPLETE);
const char *error_msg = "OutOfSequence";
REST.set_response_payload (response, error_msg, strlen (error_msg));
return;
}
/* Old packet or retransmission, immediately confirm */
if (packet->block1_offset && packet->block1_offset + len <= current_offset) {
REST.set_response_status (response, REST.status.CHANGED);
coap_set_header_block1
(response, packet->block1_num, 0, packet->block1_size);
return;
}
// FIXME: blocksize may be larger than our flash page size
if (len > PAGESIZE) {
REST.set_response_status (response, REST.status.INTERNAL_SERVER_ERROR);
const char *error_msg = "GRMPF: PageSize";
REST.set_response_payload (response, error_msg, strlen (error_msg));
return;
}
// FIXME: blocksize may be larger than our flash page size
// So we should handle this case and repeatedly flash a block until the
// received data is written.
if (current_offset % PAGESIZE + len > PAGESIZE) {
REST.set_response_status (response, REST.status.INTERNAL_SERVER_ERROR);
const char *error_msg = "GRMPF: blocksize";
REST.set_response_payload (response, error_msg, strlen (error_msg));
return;
}
// Should never happen, we test for < and > earlier.
if (packet->block1_offset != current_offset) {
REST.set_response_status (response, REST.status.INTERNAL_SERVER_ERROR);
const char *error_msg = "GRMPF: Offset";
REST.set_response_payload (response, error_msg, strlen (error_msg));
return;
}
if (packet->block1_offset + len > partition_size) {
REST.set_response_status
(response, REST.status.REQUEST_ENTITY_TOO_LARGE);
REST.set_response_payload
(response, buffer, sprintf ((char *)buffer, "%luB max.", partition_size));
return;
}
memcpy (current_page + current_offset % PAGESIZE, in_data, len);
/* Whenever an upload is started for a partition mark it as not ok */
if (current_offset == 0) {
PRINTF (("Clear partition_ok: %ld\n", imgidx));
bootloader_clr_part_ok (imgidx);
}
current_offset += len;
if (current_offset % PAGESIZE == 0) {
uint32_t dst_address = partition_start + current_offset - PAGESIZE;
/* Special case: Flash irq vectors to backup position */
if (current_offset - PAGESIZE < PART_IRQVEC_SIZE) {
/* Only for images not at position 0 write first PART_IRQVEC_SIZE
* bytes also to original position. For partition 0 it will be
* copied there anyway *and* we would crash if we wrote to the
* active memory!
*/
if (partition_start != 0) {
PRINTF (("Flashing: %lx to %lx\n", (uint32_t)PAGESIZE, dst_address));
bootloader_write_page_to_flash (dst_address, PAGESIZE, current_page);
}
/* Note: The partition_size returned by the bootloader does *NOT*
* include the PART_IRQVEC_SIZE
*/
dst_address = partition_start + partition_size
+ current_offset - PAGESIZE;
}
PRINTF (("Flashing: %lx to %lx\n", (uint32_t)PAGESIZE, dst_address));
bootloader_write_page_to_flash (dst_address, PAGESIZE, current_page);
} else if (!packet->block1_more) {
uint32_t dst_address =
partition_start + (current_offset / PAGESIZE) * PAGESIZE;
PRINTF (("Flashing: last %lx to %lx\n", (uint32_t)PAGESIZE, dst_address));
bootloader_write_page_to_flash (dst_address, PAGESIZE, current_page);
}
if (!packet->block1_more) {
// we are finished
bootloader_set_boot_next (imgidx);
current_offset = 0;
}
REST.set_response_status (response, REST.status.CHANGED);
coap_set_header_block1 (response, packet->block1_num, 0, packet->block1_size);
}
RESOURCE(
res_upload_image
, "title=\"Flash memory upgrade\";rt=\"block\""
, NULL
, NULL
, res_put_handler
, NULL
);

View file

@ -56,6 +56,7 @@ struct rest_implementation_status {
const unsigned int NOT_FOUND; /* NOT_FOUND_4_04, NOT_FOUND_404 */ const unsigned int NOT_FOUND; /* NOT_FOUND_4_04, NOT_FOUND_404 */
const unsigned int METHOD_NOT_ALLOWED; /* METHOD_NOT_ALLOWED_4_05, METHOD_NOT_ALLOWED_405 */ const unsigned int METHOD_NOT_ALLOWED; /* METHOD_NOT_ALLOWED_4_05, METHOD_NOT_ALLOWED_405 */
const unsigned int NOT_ACCEPTABLE; /* NOT_ACCEPTABLE_4_06, NOT_ACCEPTABLE_406 */ const unsigned int NOT_ACCEPTABLE; /* NOT_ACCEPTABLE_4_06, NOT_ACCEPTABLE_406 */
const unsigned int REQUEST_ENTITY_INCOMPLETE; /* REQUEST_ENTITY_INCOMPLETE_4_08, REQUEST_ENTITY_INCOMPLETE_408 */
const unsigned int REQUEST_ENTITY_TOO_LARGE; /* REQUEST_ENTITY_TOO_LARGE_4_13, REQUEST_ENTITY_TOO_LARGE_413 */ const unsigned int REQUEST_ENTITY_TOO_LARGE; /* REQUEST_ENTITY_TOO_LARGE_4_13, REQUEST_ENTITY_TOO_LARGE_413 */
const unsigned int UNSUPPORTED_MEDIA_TYPE; /* UNSUPPORTED_MEDIA_TYPE_4_15, UNSUPPORTED_MEDIA_TYPE_415 */ const unsigned int UNSUPPORTED_MEDIA_TYPE; /* UNSUPPORTED_MEDIA_TYPE_4_15, UNSUPPORTED_MEDIA_TYPE_415 */

View file

@ -49,7 +49,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "arduino-process.h"
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
PROCESS(serial_shell_process, "Contiki serial shell"); PROCESS(serial_shell_process, "Contiki serial shell");
@ -58,6 +58,8 @@ void
shell_default_output(const char *text1, int len1, const char *text2, int len2) shell_default_output(const char *text1, int len1, const char *text2, int len2)
{ {
int i; int i;
mcu_sleep_disable();
if(text1 == NULL) { if(text1 == NULL) {
text1 = ""; text1 = "";
len1 = 0; len1 = 0;
@ -89,6 +91,7 @@ void
shell_exit(void) shell_exit(void)
{ {
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
PROCESS_THREAD(serial_shell_process, ev, data) PROCESS_THREAD(serial_shell_process, ev, data)
{ {
@ -98,6 +101,7 @@ PROCESS_THREAD(serial_shell_process, ev, data)
while(1) { while(1) {
PROCESS_WAIT_EVENT_UNTIL(ev == serial_line_event_message && data != NULL); PROCESS_WAIT_EVENT_UNTIL(ev == serial_line_event_message && data != NULL);
mcu_sleep_disable();
shell_input(data, strlen(data)); shell_input(data, strlen(data));
} }

View file

@ -66,3 +66,11 @@ endif
ifeq ($(TARGET),z1) ifeq ($(TARGET),z1)
shell_src += shell-sky.c shell-exec.c shell_src += shell-sky.c shell-exec.c
endif endif
ifeq ($(TARGET),osd-merkur-256)
shell_src += shell-merkur.c
endif
ifeq ($(TARGET),osd-merkur-128)
shell_src += shell-merkur.c
endif

237
apps/shell/shell-merkur.c Normal file
View file

@ -0,0 +1,237 @@
/*
* Copyright (c) 2008, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* Merkurboard-specific Contiki shell commands
* \author
* Harald Pichler <harald@the-develop.net>
*/
#include "contiki.h"
#include <stdio.h>
#include <stdlib.h> /* strtol */
#include "sys/cc.h"
#include "dev/radio.h"
#include "shell-merkur.h"
#include "params.h"
#include "arduino-process.h"
/*---------------------------------------------------------------------------*/
PROCESS(shell_txpower_process, "txpower");
SHELL_COMMAND(txpower_command,
"txpower",
"txpower <power>: change transmission power 0 (3dbm, default) to 15 (-17.2dbm)",
&shell_txpower_process);
PROCESS(shell_panid_process, "panid");
SHELL_COMMAND(panid_command,
"panid",
"panid <0xabcd>: change panid (default 0xabcd)",
&shell_panid_process);
PROCESS(shell_rfchannel_process, "rfchannel");
SHELL_COMMAND(rfchannel_command,
"rfchannel",
"rfchannel <channel>: change radio channel (11 - 26)",
&shell_rfchannel_process);
PROCESS(shell_ccathresholds_process, "ccathresholds");
SHELL_COMMAND(ccathresholds_command,
"ccathresholds",
"ccathresholds <threshold: change cca thresholds -91 to -61 dBm (default -77)",
&shell_ccathresholds_process);
PROCESS(shell_macconf_process, "macconf");
SHELL_COMMAND(macconf_command,
"macconf",
"macconf <conf>: change mac layer 0 -> do nothing; 1 -> Radio allways on",
&shell_macconf_process);
PROCESS(shell_saverfparam_process, "saverfparam");
SHELL_COMMAND(saverfparam_command,
"saverfparam",
"saverfparam <> save radio parameters txpower, channel, panid to eeprom settingsmanager",
&shell_saverfparam_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_txpower_process, ev, data)
{
radio_value_t value;
char buf[10];
const char *newptr;
PROCESS_BEGIN();
value = shell_strtolong(data, &newptr);
/* If no transmission power was given on the command line, we print
out the current txpower. */
if(newptr == data) {
if(get_param(RADIO_PARAM_TXPOWER, &value) == RADIO_RESULT_OK) {
}
} else {
set_param(RADIO_PARAM_TXPOWER, value);
}
snprintf(buf, sizeof(buf), "%3d", value);
shell_output_str(&txpower_command, "TX Power: ", buf);
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_rfchannel_process, ev, data)
{
radio_value_t value;
char buf[10];
const char *newptr;
PROCESS_BEGIN();
value = shell_strtolong(data, &newptr);
/* If no channel was given on the command line, we print out the
current channel. */
if(newptr == data) {
if(get_param(RADIO_PARAM_CHANNEL, &value) == RADIO_RESULT_OK) {
}
} else {
set_param(RADIO_PARAM_CHANNEL, value);
}
snprintf(buf, sizeof(buf), "%d", value);
shell_output_str(&rfchannel_command, "Channel: ", buf);
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_ccathresholds_process, ev, data)
{
radio_value_t value;
char buf[10];
const char *newptr;
PROCESS_BEGIN();
value = shell_strtolong(data, &newptr);
/* If no channel was given on the command line, we print out the
current channel. */
if(newptr == data) {
if(get_param(RADIO_PARAM_CCA_THRESHOLD, &value) == RADIO_RESULT_OK) {
}
} else {
set_param(RADIO_PARAM_CCA_THRESHOLD, value);
}
snprintf(buf, sizeof(buf), "%d dBm", value);
shell_output_str(&rfchannel_command, "CCA Threshold: ", buf);
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_macconf_process, ev, data)
{
radio_value_t value;
char buf[10];
const char *newptr;
PROCESS_BEGIN();
value = shell_strtolong(data, &newptr);
/* If no transmission power was given on the command line, we print
out the current macconf. */
if(newptr == data) {
value = params_get_macconf();
} else {
params_set_macconf(value);
}
snprintf(buf, sizeof(buf), "%3d", value);
shell_output_str(&txpower_command, "macconf: ", buf);
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_panid_process, ev, data)
{
radio_value_t value;
char buf[10];
char *newptr;
PROCESS_BEGIN();
value = strtol(data, &newptr, 0);
/* If no channel was given on the command line, we print out the
current channel. */
if(newptr == data) {
if(get_param(RADIO_PARAM_PAN_ID, &value) != RADIO_RESULT_OK) {
// printf("error: get_param RADIO_PARAM_PAN_ID\n");
}
} else {
set_param(RADIO_PARAM_PAN_ID, value);
}
snprintf(buf, sizeof(buf),"0x%02x%02x\n", (value >> 8) & 0xFF, value & 0xFF);
shell_output_str(&panid_command, "panid: ", buf);
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_saverfparam_process, ev, data)
{
PROCESS_BEGIN();
/* Save txpower */
params_save_txpower();
/* Save rfchannel */
params_save_channel();
/* Save ccathresholds */
// todo
/* Save panid */
params_save_panid();
/* Save macconf */
params_save_macconf();
shell_output_str(&rfchannel_command, "saverfparam done ", 0);
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
void
shell_merkur_init(void)
{
// shell_ps_init();
shell_reboot_init();
shell_register_command(&txpower_command);
shell_register_command(&rfchannel_command);
shell_register_command(&ccathresholds_command);
shell_register_command(&panid_command);
shell_register_command(&macconf_command);
shell_register_command(&saverfparam_command);
// shell_register_command(&s_command);
}
/*---------------------------------------------------------------------------*/

47
apps/shell/shell-merkur.h Normal file
View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2008, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* Header file for Tmote Sky-specific Contiki shell commands
* \author
* harald pichler <harald@the-develop.net>
*/
#ifndef SHELL_MERKUR_H_
#define SHELL_MERKUR_H_
#include "shell.h"
void shell_merkur_init(void);
#endif /* SHELL_MERKUR_H_ */

View file

@ -35,7 +35,8 @@ static size_t get_index_from_uri (const char *uri)
return idx; return idx;
} }
int crontab_from_string (const char *name, const char *uri, const char *s) int crontab_from_string
(const char *name, const char *uri, const char *query, const char *s)
{ {
const char *err; const char *err;
int res; int res;
@ -52,7 +53,13 @@ int crontab_from_string (const char *name, const char *uri, const char *s)
} }
size_t size_t
crontab_to_string (const char *name, const char *uri, char *buf, size_t bsize) crontab_to_string
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{ {
/* FIXME: For now we only return "valid" or "invalid" until someone /* FIXME: For now we only return "valid" or "invalid" until someone
* comes up with a clever algorithm to reconstruct a crontab string * comes up with a clever algorithm to reconstruct a crontab string

View file

@ -17,7 +17,8 @@
#include "er-coap.h" #include "er-coap.h"
#include "generic_resource.h" #include "generic_resource.h"
size_t time_to_string (const char *name, const char *uri, char *buf, size_t bs) size_t time_to_string
(const char *name, const char *uri, const char *query, char *buf, size_t bs)
{ {
struct xtimeval tv; struct xtimeval tv;
struct xtm tm; struct xtm tm;

View file

@ -21,7 +21,8 @@
#include "er-coap.h" #include "er-coap.h"
#include "generic_resource.h" #include "generic_resource.h"
int timestamp_from_string (const char *name, const char *uri, const char *s) int timestamp_from_string
(const char *name, const char *uri, const char *query, const char *s)
{ {
struct xtimeval tv; struct xtimeval tv;
// FIXME: Platform has no strtoll (long long)? // FIXME: Platform has no strtoll (long long)?
@ -31,7 +32,13 @@ int timestamp_from_string (const char *name, const char *uri, const char *s)
} }
size_t size_t
timestamp_to_string (const char *name, const char *uri, char *buf, size_t bsize) timestamp_to_string
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{ {
struct xtimeval tv; struct xtimeval tv;
xgettimeofday (&tv, NULL); xgettimeofday (&tv, NULL);

View file

@ -17,14 +17,21 @@
#include "er-coap.h" #include "er-coap.h"
#include "generic_resource.h" #include "generic_resource.h"
int timezone_from_string (const char *name, const char *uri, const char *s) int timezone_from_string
(const char *name, const char *uri, const char *query, const char *s)
{ {
set_tz (s); set_tz (s);
return 0; return 0;
} }
size_t size_t
timezone_to_string (const char *name, const char *uri, char *buf, size_t bsize) timezone_to_string
( const char *name
, const char *uri
, const char *query
, char *buf
, size_t bsize
)
{ {
if (get_tz (buf, bsize) == NULL) { if (get_tz (buf, bsize) == NULL) {
*buf = '\0'; *buf = '\0';

1
apps/tinydtls Submodule

@ -0,0 +1 @@
Subproject commit e95b02584a0041817da67c8c01f2a197d0c26915

View file

@ -254,6 +254,7 @@ make_addresses(void *p)
{ {
uint8_t i, j = 0; uint8_t i, j = 0;
uint16_t numprinted; uint16_t numprinted;
numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh); numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
for (i=0; i<UIP_DS6_ADDR_NB;i++) { for (i=0; i<UIP_DS6_ADDR_NB;i++) {
if (uip_ds6_if.addr_list[i].isused) { if (uip_ds6_if.addr_list[i].isused) {
@ -280,7 +281,7 @@ PT_THREAD(addresses(struct httpd_state *s, char *ptr))
static unsigned short static unsigned short
make_neighbors(void *p) make_neighbors(void *p)
{ {
uint8_t i,j=0; uint8_t j=0;
uint16_t numprinted; uint16_t numprinted;
numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh); numprinted = httpd_snprintf((char *)uip_appdata, uip_mss(),httpd_cgi_addrh);
uip_ds6_nbr_t *nbr; uip_ds6_nbr_t *nbr;
@ -312,7 +313,7 @@ make_routes(void *p)
static const char httpd_cgi_rtes1[] HTTPD_STRING_ATTR = "(%u (via "; static const char httpd_cgi_rtes1[] HTTPD_STRING_ATTR = "(%u (via ";
static const char httpd_cgi_rtes2[] HTTPD_STRING_ATTR = ") %lus<br>"; static const char httpd_cgi_rtes2[] HTTPD_STRING_ATTR = ") %lus<br>";
static const char httpd_cgi_rtes3[] HTTPD_STRING_ATTR = ")<br>"; static const char httpd_cgi_rtes3[] HTTPD_STRING_ATTR = ")<br>";
uint8_t i,j=0; uint8_t j=0;
uint16_t numprinted; uint16_t numprinted;
uip_ds6_route_t *r; uip_ds6_route_t *r;
@ -323,7 +324,7 @@ make_routes(void *p)
j++; j++;
numprinted += httpd_cgi_sprint_ip6(r->ipaddr, uip_appdata + numprinted); numprinted += httpd_cgi_sprint_ip6(r->ipaddr, uip_appdata + numprinted);
numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes1, r->length); numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes1, r->length);
numprinted += httpd_cgi_sprint_ip6(uip_ds6_route_nexthop(r), uip_appdata + numprinted); numprinted += httpd_cgi_sprint_ip6(*(uip_ds6_route_nexthop(r)), uip_appdata + numprinted);
if(r->state.lifetime < 3600) { if(r->state.lifetime < 3600) {
numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes2, r->state.lifetime); numprinted += httpd_snprintf((char *)uip_appdata+numprinted, uip_mss()-numprinted, httpd_cgi_rtes2, r->state.lifetime);
} else { } else {

View file

@ -1309,7 +1309,6 @@ cfs_coffee_configure_log(const char *filename, unsigned log_size,
return 0; return 0;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if COFFEE_IO_SEMANTICS
int int
cfs_coffee_set_io_semantics(int fd, unsigned flags) cfs_coffee_set_io_semantics(int fd, unsigned flags)
{ {
@ -1321,7 +1320,6 @@ cfs_coffee_set_io_semantics(int fd, unsigned flags)
return 0; return 0;
} }
#endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
cfs_coffee_format(void) cfs_coffee_format(void)

View file

@ -148,13 +148,6 @@
#endif /* NBR_TABLE_FIND_REMOVABLE */ #endif /* NBR_TABLE_FIND_REMOVABLE */
#endif /* UIP_CONF_IPV6_RPL */ #endif /* UIP_CONF_IPV6_RPL */
/* RPL_CONF_MOP specifies the RPL mode of operation that will be
* advertised by the RPL root. Possible values: RPL_MOP_NO_DOWNWARD_ROUTES,
* RPL_MOP_NON_STORING, RPL_MOP_STORING_NO_MULTICAST, RPL_MOP_STORING_MULTICAST */
#ifndef RPL_CONF_MOP
#define RPL_CONF_MOP RPL_MOP_STORING_NO_MULTICAST
#endif /* RPL_CONF_MOP */
/* UIP_CONF_MAX_ROUTES specifies the maximum number of routes that each /* UIP_CONF_MAX_ROUTES specifies the maximum number of routes that each
node will be able to handle. */ node will be able to handle. */
#ifndef UIP_CONF_MAX_ROUTES #ifndef UIP_CONF_MAX_ROUTES
@ -211,7 +204,7 @@
#define UIP_CONF_ND6_SEND_RA (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL) #define UIP_CONF_ND6_SEND_RA (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL)
#endif /* UIP_CONF_ND6_SEND_RA */ #endif /* UIP_CONF_ND6_SEND_RA */
/* UIP_CONF_ND6_SEND_NA enables standard IPv6 Neighbor Discovery Protocol. /* UIP_CONF_ND6_SEND_NS enables standard IPv6 Neighbor Discovery Protocol.
We enable it by default when IPv6 is used without RPL. We enable it by default when IPv6 is used without RPL.
With RPL, the neighbor cache (link-local IPv6 <-> MAC address mapping) With RPL, the neighbor cache (link-local IPv6 <-> MAC address mapping)
is fed whenever receiving DIO and DAO messages. This is always sufficient is fed whenever receiving DIO and DAO messages. This is always sufficient
@ -221,9 +214,15 @@
neighbor to us is weak, if DIO transmissions are suppressed (Trickle neighbor to us is weak, if DIO transmissions are suppressed (Trickle
timer) or if the neighbor chooses not to transmit DIOs because it is timer) or if the neighbor chooses not to transmit DIOs because it is
a leaf node or for any reason. */ a leaf node or for any reason. */
#ifndef UIP_CONF_ND6_SEND_NS
#define UIP_CONF_ND6_SEND_NS (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL)
#endif /* UIP_CONF_ND6_SEND_NS */
/* UIP_CONF_ND6_SEND_NA allows to still comply with NDP even if the host does
not perform NUD or DAD processes. By default it is activated so the host
can still communicate with a full NDP peer. */
#ifndef UIP_CONF_ND6_SEND_NA #ifndef UIP_CONF_ND6_SEND_NA
#define UIP_CONF_ND6_SEND_NA (NETSTACK_CONF_WITH_IPV6 && !UIP_CONF_IPV6_RPL) #define UIP_CONF_ND6_SEND_NA (NETSTACK_CONF_WITH_IPV6)
#endif /* UIP_CONF_ND6_SEND_NA */ #endif /* UIP_CONF_ND6_SEND_NS */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* 6lowpan configuration options. /* 6lowpan configuration options.

View file

@ -47,6 +47,8 @@
#define IGNORE_CHAR(c) (c == 0x0d) #define IGNORE_CHAR(c) (c == 0x0d)
#define END 0x0a #define END 0x0a
//#define IGNORE_CHAR(c) (c == 0x0a)
//#define END 0x0d
static struct ringbuf rxbuf; static struct ringbuf rxbuf;
static uint8_t rxbuf_data[BUFSIZE]; static uint8_t rxbuf_data[BUFSIZE];

View file

@ -107,9 +107,6 @@ slip_send(void)
ptr = &uip_buf[UIP_LLH_LEN]; ptr = &uip_buf[UIP_LLH_LEN];
for(i = 0; i < uip_len; ++i) { for(i = 0; i < uip_len; ++i) {
if(i == UIP_TCPIP_HLEN) {
ptr = (uint8_t *)uip_appdata;
}
c = *ptr++; c = *ptr++;
if(c == SLIP_END) { if(c == SLIP_END) {
slip_arch_writeb(SLIP_ESC); slip_arch_writeb(SLIP_ESC);
@ -161,6 +158,7 @@ rxbuf_init(void)
static uint16_t static uint16_t
slip_poll_handler(uint8_t *outbuf, uint16_t blen) slip_poll_handler(uint8_t *outbuf, uint16_t blen)
{ {
#ifdef SLIP_CONF_MICROSOFT_CHAT
/* This is a hack and won't work across buffer edge! */ /* This is a hack and won't work across buffer edge! */
if(rxbuf[begin] == 'C') { if(rxbuf[begin] == 'C') {
int i; int i;
@ -177,6 +175,8 @@ slip_poll_handler(uint8_t *outbuf, uint16_t blen)
return 0; return 0;
} }
} }
#endif /* SLIP_CONF_MICROSOFT_CHAT */
#ifdef SLIP_CONF_ANSWER_MAC_REQUEST #ifdef SLIP_CONF_ANSWER_MAC_REQUEST
else if(rxbuf[begin] == '?') { else if(rxbuf[begin] == '?') {
/* Used by tapslip6 to request mac for auto configure */ /* Used by tapslip6 to request mac for auto configure */
@ -425,11 +425,13 @@ slip_input_byte(unsigned char c)
} }
rxbuf[cur_end] = c; rxbuf[cur_end] = c;
#ifdef SLIP_CONF_MICROSOFT_CHAT
/* There could be a separate poll routine for this. */ /* There could be a separate poll routine for this. */
if(c == 'T' && rxbuf[begin] == 'C') { if(c == 'T' && rxbuf[begin] == 'C') {
process_poll(&slip_process); process_poll(&slip_process);
return 1; return 1;
} }
#endif /* SLIP_CONF_MICROSOFT_CHAT */
if(c == SLIP_END) { if(c == SLIP_END) {
/* /*

View file

@ -83,7 +83,7 @@ ringbufindex_peek_put(const struct ringbufindex *r)
if(((r->put_ptr - r->get_ptr) & r->mask) == r->mask) { if(((r->put_ptr - r->get_ptr) & r->mask) == r->mask) {
return -1; return -1;
} }
return (r->put_ptr + 1) & r->mask; return r->put_ptr;
} }
/* Remove the first element and return its index */ /* Remove the first element and return its index */
int int
@ -118,7 +118,7 @@ ringbufindex_peek_get(const struct ringbufindex *r)
first one. If there are no bytes left, we return -1. first one. If there are no bytes left, we return -1.
*/ */
if(((r->put_ptr - r->get_ptr) & r->mask) > 0) { if(((r->put_ptr - r->get_ptr) & r->mask) > 0) {
return (r->get_ptr + 1) & r->mask; return r->get_ptr;
} else { } else {
return -1; return -1;
} }

View file

@ -48,25 +48,72 @@ struct ringbufindex {
uint8_t put_ptr, get_ptr; uint8_t put_ptr, get_ptr;
}; };
/* Initialize a ring buffer. The size must be a power of two */ /**
* \brief Initialize a ring buffer. The size must be a power of two
* \param r Pointer to ringbufindex
* \param size Size of ring buffer
*/
void ringbufindex_init(struct ringbufindex *r, uint8_t size); void ringbufindex_init(struct ringbufindex *r, uint8_t size);
/* Put one element to the ring buffer */
/**
* \brief Put one element to the ring buffer
* \param r Pointer to ringbufindex
* \retval 0 Failure; the ring buffer is full
* \retval 1 Success; an element is added
*/
int ringbufindex_put(struct ringbufindex *r); int ringbufindex_put(struct ringbufindex *r);
/* Check if there is space to put an element.
* Return the index where the next element is to be added */ /**
* \brief Check if there is space to put an element.
* \param r Pinter to ringbufindex
* \retval >= 0 The index where the next element is to be added.
* \retval -1 Failure; the ring buffer is full
*/
int ringbufindex_peek_put(const struct ringbufindex *r); int ringbufindex_peek_put(const struct ringbufindex *r);
/* Remove the first element and return its index */
/**
* \brief Remove the first element and return its index
* \param r Pinter to ringbufindex
* \retval >= 0 The index of the first element
* \retval -1 No element in the ring buffer
*/
int ringbufindex_get(struct ringbufindex *r); int ringbufindex_get(struct ringbufindex *r);
/* Return the index of the first element
* (which will be removed if calling ringbufindex_peek) */ /**
* \brief Return the index of the first element which will be removed if calling
* ringbufindex_get.
* \param r Pinter to ringbufindex
* \retval >= 0 The index of the first element
* \retval -1 No element in the ring buffer
*/
int ringbufindex_peek_get(const struct ringbufindex *r); int ringbufindex_peek_get(const struct ringbufindex *r);
/* Return the ring buffer size */
/**
* \brief Return the ring buffer size
* \param r Pinter to ringbufindex
* \return The size of the ring buffer
*/
int ringbufindex_size(const struct ringbufindex *r); int ringbufindex_size(const struct ringbufindex *r);
/* Return the number of elements currently in the ring buffer */
/**
* \brief Return the number of elements currently in the ring buffer.
* \param r Pinter to ringbufindex
* \return The number of elements in the ring buffer
*/
int ringbufindex_elements(const struct ringbufindex *r); int ringbufindex_elements(const struct ringbufindex *r);
/* Is the ring buffer full? */
/**
* \brief Is the ring buffer full?
* \retval 0 Not full
* \retval 1 Full
*/
int ringbufindex_full(const struct ringbufindex *r); int ringbufindex_full(const struct ringbufindex *r);
/* Is the ring buffer empty? */
/**
* \brief Is the ring buffer empty?
* \retval 0 Not empty
* \retval 1 Empty
*/
int ringbufindex_empty(const struct ringbufindex *r); int ringbufindex_empty(const struct ringbufindex *r);
#endif /* __RINGBUFINDEX_H__ */ #endif /* __RINGBUFINDEX_H__ */

View file

@ -130,7 +130,7 @@ typedef uint16_t settings_length_t;
#define SETTINGS_KEY_RDC_INDEX TCC('R','D') /*!< RDC index, uint8_t */ #define SETTINGS_KEY_RDC_INDEX TCC('R','D') /*!< RDC index, uint8_t */
#define SETTINGS_KEY_CHANNEL_MASK TCC('C','M') /*!< Channel mask, uint16_t */ #define SETTINGS_KEY_CHANNEL_MASK TCC('C','M') /*!< Channel mask, uint16_t */
#define SETTINGS_KEY_MAC_CONF TCC('M','C') /*!< MAC Layer Config, uint8_t */
/*****************************************************************************/ /*****************************************************************************/
// MARK: - Constants // MARK: - Constants

View file

@ -35,6 +35,10 @@
#include <string.h> #include <string.h>
#define printf(...) #define printf(...)
static uip_ip6addr_t ip64_prefix = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0}};
static uint8_t ip64_prefix_len = 96;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
ip64_addr_copy4(uip_ip4addr_t *dest, const uip_ip4addr_t *src) ip64_addr_copy4(uip_ip4addr_t *dest, const uip_ip4addr_t *src)
@ -56,20 +60,7 @@ ip64_addr_4to6(const uip_ip4addr_t *ipv4addr,
addresses. It returns 0 if it failed to convert the address and addresses. It returns 0 if it failed to convert the address and
non-zero if it could successfully convert the address. */ non-zero if it could successfully convert the address. */
/* The IPv4 address is encoded as an IPv6-encoded IPv4 address in uip_ipaddr_copy(ipv6addr, &ip64_prefix);
the ::ffff:0000/24 prefix.*/
ipv6addr->u8[0] = 0;
ipv6addr->u8[1] = 0;
ipv6addr->u8[2] = 0;
ipv6addr->u8[3] = 0;
ipv6addr->u8[4] = 0;
ipv6addr->u8[5] = 0;
ipv6addr->u8[6] = 0;
ipv6addr->u8[7] = 0;
ipv6addr->u8[8] = 0;
ipv6addr->u8[9] = 0;
ipv6addr->u8[10] = 0xff;
ipv6addr->u8[11] = 0xff;
ipv6addr->u8[12] = ipv4addr->u8[0]; ipv6addr->u8[12] = ipv4addr->u8[0];
ipv6addr->u8[13] = ipv4addr->u8[1]; ipv6addr->u8[13] = ipv4addr->u8[1];
ipv6addr->u8[14] = ipv4addr->u8[2]; ipv6addr->u8[14] = ipv4addr->u8[2];
@ -90,21 +81,7 @@ ip64_addr_6to4(const uip_ip6addr_t *ipv6addr,
returns 0 if it failed to convert the address and non-zero if it returns 0 if it failed to convert the address and non-zero if it
could successfully convert the address. */ could successfully convert the address. */
/* If the IPv6 address is an IPv6-encoded if(ip64_addr_is_ip64(ipv6addr)) {
IPv4 address (i.e. in the ::ffff:0/8 prefix), we simply use the
IPv4 addresses directly. */
if(ipv6addr->u8[0] == 0 &&
ipv6addr->u8[1] == 0 &&
ipv6addr->u8[2] == 0 &&
ipv6addr->u8[3] == 0 &&
ipv6addr->u8[4] == 0 &&
ipv6addr->u8[5] == 0 &&
ipv6addr->u8[6] == 0 &&
ipv6addr->u8[7] == 0 &&
ipv6addr->u8[8] == 0 &&
ipv6addr->u8[9] == 0 &&
ipv6addr->u8[10] == 0xff &&
ipv6addr->u8[11] == 0xff) {
ipv4addr->u8[0] = ipv6addr->u8[12]; ipv4addr->u8[0] = ipv6addr->u8[12];
ipv4addr->u8[1] = ipv6addr->u8[13]; ipv4addr->u8[1] = ipv6addr->u8[13];
ipv4addr->u8[2] = ipv6addr->u8[14]; ipv4addr->u8[2] = ipv6addr->u8[14];
@ -121,3 +98,16 @@ ip64_addr_6to4(const uip_ip6addr_t *ipv6addr,
return 0; return 0;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int
ip64_addr_is_ip64(const uip_ip6addr_t *ipv6addr)
{
return uip_ipaddr_prefixcmp(ipv6addr, &ip64_prefix, ip64_prefix_len);
}
/*---------------------------------------------------------------------------*/
void
ip64_addr_set_prefix(const uip_ip6addr_t *prefix, uint8_t prefix_len)
{
uip_ipaddr_copy(&ip64_prefix, prefix);
ip64_prefix_len = prefix_len;
}
/*---------------------------------------------------------------------------*/

View file

@ -58,6 +58,9 @@ int ip64_addr_6to4(const uip_ip6addr_t *ipv6addr,
int ip64_addr_4to6(const uip_ip4addr_t *ipv4addr, int ip64_addr_4to6(const uip_ip4addr_t *ipv4addr,
uip_ip6addr_t *ipv6addr); uip_ip6addr_t *ipv6addr);
int ip64_addr_is_ip64(const uip_ip6addr_t *ipv6addr);
void ip64_addr_set_prefix(const uip_ip6addr_t *prefix, uint8_t prefix_len);
#endif /* IP64_ADDR_H */ #endif /* IP64_ADDR_H */

View file

@ -1094,7 +1094,7 @@ resolv_set_hostname(const char *hostname)
/* Add the .local suffix if it isn't already there */ /* Add the .local suffix if it isn't already there */
if(strlen(resolv_hostname) < 7 || if(strlen(resolv_hostname) < 7 ||
strcasecmp(resolv_hostname + strlen(resolv_hostname) - 6, ".local") != 0) { strcasecmp(resolv_hostname + strlen(resolv_hostname) - 6, ".local") != 0) {
strncat(resolv_hostname, ".local", RESOLV_CONF_MAX_DOMAIN_NAME_SIZE); strncat(resolv_hostname, ".local", RESOLV_CONF_MAX_DOMAIN_NAME_SIZE - strlen(resolv_hostname));
} }
PRINTF("resolver: hostname changed to \"%s\"\n", resolv_hostname); PRINTF("resolver: hostname changed to \"%s\"\n", resolv_hostname);
@ -1248,8 +1248,8 @@ remove_trailing_dots(const char *name) {
static char dns_name_without_dots[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1]; static char dns_name_without_dots[RESOLV_CONF_MAX_DOMAIN_NAME_SIZE + 1];
size_t len = strlen(name); size_t len = strlen(name);
if(name[len - 1] == '.') { if(len && name[len - 1] == '.') {
strncpy(dns_name_without_dots, name, sizeof(dns_name_without_dots)); strncpy(dns_name_without_dots, name, RESOLV_CONF_MAX_DOMAIN_NAME_SIZE);
while(len && (dns_name_without_dots[len - 1] == '.')) { while(len && (dns_name_without_dots[len - 1] == '.')) {
dns_name_without_dots[--len] = 0; dns_name_without_dots[--len] = 0;
} }
@ -1309,7 +1309,7 @@ resolv_query(const char *name)
memset(nameptr, 0, sizeof(*nameptr)); memset(nameptr, 0, sizeof(*nameptr));
strncpy(nameptr->name, name, sizeof(nameptr->name)); strncpy(nameptr->name, name, sizeof(nameptr->name) - 1);
nameptr->state = STATE_NEW; nameptr->state = STATE_NEW;
nameptr->seqno = seqno; nameptr->seqno = seqno;
++seqno; ++seqno;
@ -1479,7 +1479,7 @@ resolv_found(char *name, uip_ipaddr_t * ipaddr)
} }
/* Re-add the .local suffix */ /* Re-add the .local suffix */
strncat(resolv_hostname, ".local", RESOLV_CONF_MAX_DOMAIN_NAME_SIZE); strncat(resolv_hostname, ".local", RESOLV_CONF_MAX_DOMAIN_NAME_SIZE - strlen(resolv_hostname));
start_name_collision_check(CLOCK_SECOND * 5); start_name_collision_check(CLOCK_SECOND * 5);
} else if(mdns_state == MDNS_STATE_READY) { } else if(mdns_state == MDNS_STATE_READY) {

View file

@ -102,9 +102,6 @@ slipdev_send(void)
ptr = &uip_buf[UIP_LLH_LEN]; ptr = &uip_buf[UIP_LLH_LEN];
for(i = 0; i < uip_len; ++i) { for(i = 0; i < uip_len; ++i) {
if(i == UIP_TCPIP_HLEN) {
ptr = (uint8_t *)uip_appdata;
}
c = *ptr++; c = *ptr++;
switch(c) { switch(c) {
case SLIP_END: case SLIP_END:

View file

@ -29,6 +29,9 @@
* *
*/ */
#define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h"
#include "contiki.h" #include "contiki.h"
#include "sys/cc.h" #include "sys/cc.h"
#include "contiki-net.h" #include "contiki-net.h"
@ -37,10 +40,8 @@
#include "tcp-socket.h" #include "tcp-socket.h"
#include <stdio.h>
#include <string.h> #include <string.h>
static void relisten(struct tcp_socket *s); static void relisten(struct tcp_socket *s);
LIST(socketlist); LIST(socketlist);
@ -80,7 +81,7 @@ acked(struct tcp_socket *s)
s->output_data_maxlen - s->output_data_send_nxt); s->output_data_maxlen - s->output_data_send_nxt);
} }
if(s->output_data_len < s->output_data_send_nxt) { if(s->output_data_len < s->output_data_send_nxt) {
printf("tcp: acked assertion failed s->output_data_len (%d) < s->output_data_send_nxt (%d)\n", PRINTF("tcp: acked assertion failed s->output_data_len (%d) < s->output_data_send_nxt (%d)\n",
s->output_data_len, s->output_data_len,
s->output_data_send_nxt); s->output_data_send_nxt);
tcp_markconn(uip_conn, NULL); tcp_markconn(uip_conn, NULL);
@ -121,7 +122,7 @@ newdata(struct tcp_socket *s)
bytesleft = 0; bytesleft = 0;
} }
if(bytesleft > 0) { if(bytesleft > 0) {
printf("tcp: newdata, bytesleft > 0 (%d) not implemented\n", bytesleft); PRINTF("tcp: newdata, bytesleft > 0 (%d) not implemented\n", bytesleft);
} }
dataptr += copylen; dataptr += copylen;
len -= copylen; len -= copylen;
@ -356,6 +357,8 @@ tcp_socket_send(struct tcp_socket *s,
s->output_senddata_len = s->output_data_len; s->output_senddata_len = s->output_data_len;
} }
tcpip_poll_tcp(s->c);
return len; return len;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -398,3 +401,9 @@ tcp_socket_max_sendlen(struct tcp_socket *s)
return s->output_data_maxlen - s->output_data_len; return s->output_data_maxlen - s->output_data_len;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int
tcp_socket_queuelen(struct tcp_socket *s)
{
return s->output_data_len;
}
/*---------------------------------------------------------------------------*/

View file

@ -284,4 +284,16 @@ int tcp_socket_unregister(struct tcp_socket *s);
*/ */
int tcp_socket_max_sendlen(struct tcp_socket *s); int tcp_socket_max_sendlen(struct tcp_socket *s);
/**
* \brief The number of bytes waiting to be sent
* \param s A pointer to a TCP socket
* \return The number of bytes that have not yet been acknowledged by the receiver.
*
* This function queries the TCP socket and returns the
* number of bytes that are currently not yet known to
* have been successfully received by the receiver.
*
*/
int tcp_socket_queuelen(struct tcp_socket *s);
#endif /* TCP_SOCKET_H */ #endif /* TCP_SOCKET_H */

View file

@ -662,7 +662,7 @@ tcpip_ipv6_output(void)
nbr = uip_ds6_nbr_lookup(nexthop); nbr = uip_ds6_nbr_lookup(nexthop);
if(nbr == NULL) { if(nbr == NULL) {
#if UIP_ND6_SEND_NA #if UIP_ND6_SEND_NS
if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE, NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) { if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE, NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) {
uip_clear_buf(); uip_clear_buf();
PRINTF("tcpip_ipv6_output: failed to add neighbor to cache\n"); PRINTF("tcpip_ipv6_output: failed to add neighbor to cache\n");
@ -691,13 +691,13 @@ tcpip_ipv6_output(void)
nbr->nscount = 1; nbr->nscount = 1;
/* Send the first NS try from here (multicast destination IP address). */ /* Send the first NS try from here (multicast destination IP address). */
} }
#else /* UIP_ND6_SEND_NA */ #else /* UIP_ND6_SEND_NS */
PRINTF("tcpip_ipv6_output: neighbor not in cache\n"); PRINTF("tcpip_ipv6_output: neighbor not in cache\n");
uip_len = 0; uip_len = 0;
return; return;
#endif /* UIP_ND6_SEND_NA */ #endif /* UIP_ND6_SEND_NS */
} else { } else {
#if UIP_ND6_SEND_NA #if UIP_ND6_SEND_NS
if(nbr->state == NBR_INCOMPLETE) { if(nbr->state == NBR_INCOMPLETE) {
PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n"); PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
@ -719,7 +719,7 @@ tcpip_ipv6_output(void)
nbr->nscount = 0; nbr->nscount = 0;
PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n"); PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
} }
#endif /* UIP_ND6_SEND_NA */ #endif /* UIP_ND6_SEND_NS */
tcpip_output(uip_ds6_nbr_get_ll(nbr)); tcpip_output(uip_ds6_nbr_get_ll(nbr));

View file

@ -490,26 +490,8 @@ void uip_reass_over(void);
* *
* The uip_aligned_buf array is used to hold incoming and outgoing * The uip_aligned_buf array is used to hold incoming and outgoing
* packets. The device driver should place incoming data into this * packets. The device driver should place incoming data into this
* buffer. When sending data, the device driver should read the link * buffer. When sending data, the device driver should read the
* level headers and the TCP/IP headers from this buffer. The size of * outgoing data from this buffer.
* the link level headers is configured by the UIP_LLH_LEN define.
*
* \note The application data need not be placed in this buffer, so
* the device driver must read it from the place pointed to by the
* uip_appdata pointer as illustrated by the following example:
\code
void
devicedriver_send(void)
{
hwsend(&uip_buf[0], UIP_LLH_LEN);
if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN);
} else {
hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN);
hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN);
}
}
\endcode
*/ */
typedef union { typedef union {

View file

@ -120,10 +120,6 @@ uint16_t uip_ipchksum(void);
* The TCP checksum is the Internet checksum of data contents of the * The TCP checksum is the Internet checksum of data contents of the
* TCP segment, and a pseudo-header as defined in RFC793. * TCP segment, and a pseudo-header as defined in RFC793.
* *
* \note The uip_appdata pointer that points to the packet data may
* point anywhere in memory, so it is not possible to simply calculate
* the Internet checksum of the contents of the uip_buf buffer.
*
* \return The TCP checksum of the TCP segment in uip_buf and pointed * \return The TCP checksum of the TCP segment in uip_buf and pointed
* to by uip_appdata. * to by uip_appdata.
*/ */

View file

@ -163,7 +163,6 @@ create_msg(CC_REGISTER_ARG struct dhcp_msg *m)
memset(&m->chaddr[s.mac_len], 0, sizeof(m->chaddr) - s.mac_len); memset(&m->chaddr[s.mac_len], 0, sizeof(m->chaddr) - s.mac_len);
memset(m->sname, 0, sizeof(m->sname)); memset(m->sname, 0, sizeof(m->sname));
strcpy((char *)m->sname, "Thingsquare");
memset(m->file, 0, sizeof(m->file)); memset(m->file, 0, sizeof(m->file));

View file

@ -39,6 +39,9 @@
#include <stdio.h> #include <stdio.h>
#define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h"
PROCESS(ip64_ipv4_dhcp_process, "IPv4 DHCP"); PROCESS(ip64_ipv4_dhcp_process, "IPv4 DHCP");
uip_ipaddr_t uip_hostaddr; /* Needed because it is referenced by dhcpc.c */ uip_ipaddr_t uip_hostaddr; /* Needed because it is referenced by dhcpc.c */
@ -48,7 +51,7 @@ uip_ipaddr_t uip_hostaddr; /* Needed because it is referenced by dhcpc.c */
void void
ip64_ipv4_dhcp_init(void) ip64_ipv4_dhcp_init(void)
{ {
printf("Starting DHCPv4\n"); printf("IP64: Starting DHCPv4\n");
process_start(&ip64_ipv4_dhcp_process, NULL); process_start(&ip64_ipv4_dhcp_process, NULL);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -58,10 +61,10 @@ PROCESS_THREAD(ip64_ipv4_dhcp_process, ev, data)
ip64_dhcpc_init(&ip64_eth_addr, sizeof(ip64_eth_addr)); ip64_dhcpc_init(&ip64_eth_addr, sizeof(ip64_eth_addr));
printf("Inited\n"); PRINTF("IP64: Inited\n");
ip64_dhcpc_request(); ip64_dhcpc_request();
printf("Requested\n"); PRINTF("IP64: Requested\n");
while(1) { while(1) {
PROCESS_WAIT_EVENT(); PROCESS_WAIT_EVENT();
@ -78,15 +81,22 @@ void
ip64_dhcpc_configured(const struct ip64_dhcpc_state *s) ip64_dhcpc_configured(const struct ip64_dhcpc_state *s)
{ {
uip_ip6addr_t ip6dnsaddr; uip_ip6addr_t ip6dnsaddr;
printf("DHCP Configured with %d.%d.%d.%d\n", PRINTF("IP64: DHCP Configured with %d.%d.%d.%d\n",
s->ipaddr.u8[0], s->ipaddr.u8[1], s->ipaddr.u8[0], s->ipaddr.u8[1],
s->ipaddr.u8[2], s->ipaddr.u8[3]); s->ipaddr.u8[2], s->ipaddr.u8[3]);
ip64_set_hostaddr((uip_ip4addr_t *)&s->ipaddr); ip64_set_hostaddr((uip_ip4addr_t *)&s->ipaddr);
ip64_set_netmask((uip_ip4addr_t *)&s->netmask); ip64_set_netmask((uip_ip4addr_t *)&s->netmask);
ip64_set_draddr((uip_ip4addr_t *)&s->default_router); ip64_set_draddr((uip_ip4addr_t *)&s->default_router);
if(!uip_ip4addr_cmp((uip_ip4addr_t *)&s->dnsaddr, &uip_all_zeroes_addr)) {
/* Note: Currently we assume only one DNS server */
uip_ipaddr_t * dns = uip_nameserver_get(0);
/* Only update DNS entry if it is empty or already IPv4 */
if(uip_is_addr_unspecified(dns) || ip64_addr_is_ip64(dns)) {
ip64_addr_4to6((uip_ip4addr_t *)&s->dnsaddr, &ip6dnsaddr); ip64_addr_4to6((uip_ip4addr_t *)&s->dnsaddr, &ip6dnsaddr);
// mdns_conf(&ip6dnsaddr); uip_nameserver_update(&ip6dnsaddr, uip_ntohs(s->lease_time[0])*65536ul + uip_ntohs(s->lease_time[1]));
}
}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void

View file

@ -162,7 +162,7 @@ struct uip_mcast6_driver {
#define UIP_MCAST6 smrf_driver #define UIP_MCAST6 smrf_driver
#elif UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_ESMRF #elif UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_ESMRF
#define RPL_CONF_MULTICAST 1 #define RPL_WITH_MULTICAST 1
#define UIP_MCAST6 esmrf_driver #define UIP_MCAST6 esmrf_driver
#else #else

View file

@ -88,19 +88,23 @@ uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr,
, reason, data); , reason, data);
if(nbr) { if(nbr) {
uip_ipaddr_copy(&nbr->ipaddr, ipaddr); uip_ipaddr_copy(&nbr->ipaddr, ipaddr);
#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER #if UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
nbr->isrouter = isrouter; nbr->isrouter = isrouter;
#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */ #endif /* UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
nbr->state = state; nbr->state = state;
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
uip_packetqueue_new(&nbr->packethandle); uip_packetqueue_new(&nbr->packethandle);
#endif /* UIP_CONF_IPV6_QUEUE_PKT */ #endif /* UIP_CONF_IPV6_QUEUE_PKT */
#if UIP_ND6_SEND_NA #if UIP_ND6_SEND_NS
/* timers are set separately, for now we put them in expired state */ if(nbr->state == NBR_REACHABLE) {
stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
} else {
/* We set the timer in expired state */
stimer_set(&nbr->reachable, 0); stimer_set(&nbr->reachable, 0);
}
stimer_set(&nbr->sendns, 0); stimer_set(&nbr->sendns, 0);
nbr->nscount = 0; nbr->nscount = 0;
#endif /* UIP_ND6_SEND_NA */ #endif /* UIP_ND6_SEND_NS */
PRINTF("Adding neighbor with ip addr "); PRINTF("Adding neighbor with ip addr ");
PRINT6ADDR(ipaddr); PRINT6ADDR(ipaddr);
PRINTF(" link addr "); PRINTF(" link addr ");
@ -241,7 +245,7 @@ uip_ds6_link_neighbor_callback(int status, int numtx)
#endif /* UIP_DS6_LL_NUD */ #endif /* UIP_DS6_LL_NUD */
} }
#if UIP_ND6_SEND_NA #if UIP_ND6_SEND_NS
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** Periodic processing on neighbors */ /** Periodic processing on neighbors */
void void
@ -322,6 +326,18 @@ uip_ds6_neighbor_periodic(void)
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void
uip_ds6_nbr_refresh_reachable_state(const uip_ipaddr_t *ipaddr)
{
uip_ds6_nbr_t *nbr;
nbr = uip_ds6_nbr_lookup(ipaddr);
if(nbr != NULL) {
nbr->state = NBR_REACHABLE;
nbr->nscount = 0;
stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
}
}
/*---------------------------------------------------------------------------*/
uip_ds6_nbr_t * uip_ds6_nbr_t *
uip_ds6_get_least_lifetime_neighbor(void) uip_ds6_get_least_lifetime_neighbor(void)
{ {
@ -340,6 +356,6 @@ uip_ds6_get_least_lifetime_neighbor(void)
} }
return nbr_expiring; return nbr_expiring;
} }
#endif /* UIP_ND6_SEND_NA */ #endif /* UIP_ND6_SEND_NS */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** @} */ /** @} */

View file

@ -69,11 +69,11 @@ typedef struct uip_ds6_nbr {
uip_ipaddr_t ipaddr; uip_ipaddr_t ipaddr;
uint8_t isrouter; uint8_t isrouter;
uint8_t state; uint8_t state;
#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA #if UIP_ND6_SEND_NS || UIP_ND6_SEND_RA
struct stimer reachable; struct stimer reachable;
struct stimer sendns; struct stimer sendns;
uint8_t nscount; uint8_t nscount;
#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA */ #endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_RA */
#if UIP_CONF_IPV6_QUEUE_PKT #if UIP_CONF_IPV6_QUEUE_PKT
struct uip_packetqueue_handle packethandle; struct uip_packetqueue_handle packethandle;
#define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4 #define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4
@ -98,6 +98,17 @@ void uip_ds6_link_neighbor_callback(int status, int numtx);
void uip_ds6_neighbor_periodic(void); void uip_ds6_neighbor_periodic(void);
int uip_ds6_nbr_num(void); int uip_ds6_nbr_num(void);
#if UIP_ND6_SEND_NS
/**
* \brief Refresh the reachable state of a neighbor. This function
* may be called when a node receives an IPv6 message that confirms the
* reachability of a neighbor.
* \param ipaddr pointer to the IPv6 address whose neighbor reachability state
* should be refreshed.
*/
void uip_ds6_nbr_refresh_reachable_state(const uip_ipaddr_t *ipaddr);
#endif /* UIP_ND6_SEND_NS */
/** /**
* \brief * \brief
* This searches inside the neighbor table for the neighbor that is about to * This searches inside the neighbor table for the neighbor that is about to

View file

@ -573,6 +573,12 @@ uip_ds6_route_rm_by_nexthop(uip_ipaddr_t *nexthop)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_defrt_t * uip_ds6_defrt_t *
uip_ds6_defrt_head(void)
{
return list_head(defaultrouterlist);
}
/*---------------------------------------------------------------------------*/
uip_ds6_defrt_t *
uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval) uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval)
{ {
uip_ds6_defrt_t *d; uip_ds6_defrt_t *d;

View file

@ -177,6 +177,7 @@ typedef struct uip_ds6_defrt {
/** \name Default router list basic routines */ /** \name Default router list basic routines */
/** @{ */ /** @{ */
uip_ds6_defrt_t *uip_ds6_defrt_head(void);
uip_ds6_defrt_t *uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, uip_ds6_defrt_t *uip_ds6_defrt_add(uip_ipaddr_t *ipaddr,
unsigned long interval); unsigned long interval);
void uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt); void uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt);

View file

@ -187,9 +187,9 @@ uip_ds6_periodic(void)
} }
#endif /* !UIP_CONF_ROUTER */ #endif /* !UIP_CONF_ROUTER */
#if UIP_ND6_SEND_NA #if UIP_ND6_SEND_NS
uip_ds6_neighbor_periodic(); uip_ds6_neighbor_periodic();
#endif /* UIP_ND6_SEND_RA */ #endif /* UIP_ND6_SEND_NS */
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
/* Periodic RA sending */ /* Periodic RA sending */

View file

@ -116,13 +116,16 @@ void uip_log(char *msg);
#define UIP_ND6_OPT_RDNSS_BUF ((uip_nd6_opt_dns *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) #define UIP_ND6_OPT_RDNSS_BUF ((uip_nd6_opt_dns *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
/** @} */ /** @} */
#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER #if UIP_ND6_SEND_NS || UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
static uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/ static uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/
static uint8_t *nd6_opt_llao; /** Pointer to llao option in uip_buf */ static uint8_t *nd6_opt_llao; /** Pointer to llao option in uip_buf */
static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/ static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/
static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */
static uip_ds6_addr_t *addr; /** Pointer to an interface address */ static uip_ds6_addr_t *addr; /** Pointer to an interface address */
#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */ #endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
#if UIP_ND6_SEND_NS || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */
#endif /* UIP_ND6_SEND_NS || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */
#if !UIP_CONF_ROUTER // TBD see if we move it to ra_input #if !UIP_CONF_ROUTER // TBD see if we move it to ra_input
static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /** Pointer to prefix information option in uip_buf */ static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /** Pointer to prefix information option in uip_buf */
@ -157,7 +160,27 @@ create_llao(uint8_t *llao, uint8_t type) {
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/**
* Neighbor Solicitation Processing
*
* The NS can be received in 3 cases (procedures):
* - sender is performing DAD (ip src = unspecified, no SLLAO option)
* - sender is performing NUD (ip dst = unicast)
* - sender is performing address resolution (ip dest = solicited node mcast
* address)
*
* We do:
* - if the tgt belongs to me, reply, otherwise ignore
* - if i was performing DAD for the same address, two cases:
* -- I already sent a NS, hence I win
* -- I did not send a NS yet, hence I lose
*
* If we need to send a NA in response (i.e. the NS was done for NUD, or
* address resolution, or DAD and there is a conflict), we do it in this
* function: set src, dst, tgt address in the three cases, then for all cases
* set the rest, including SLLAO
*
*/
#if UIP_ND6_SEND_NA #if UIP_ND6_SEND_NA
static void static void
ns_input(void) ns_input(void)
@ -238,9 +261,9 @@ ns_input(void)
addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr); addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr);
if(addr != NULL) { if(addr != NULL) {
#if UIP_ND6_DEF_MAXDADNS > 0
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
/* DAD CASE */ /* DAD CASE */
#if UIP_ND6_DEF_MAXDADNS > 0
#if UIP_CONF_IPV6_CHECKS #if UIP_CONF_IPV6_CHECKS
if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) { if(!uip_is_addr_solicited_node(&UIP_IP_BUF->destipaddr)) {
PRINTF("NS received is bad\n"); PRINTF("NS received is bad\n");
@ -258,9 +281,7 @@ ns_input(void)
goto discard; goto discard;
} }
#else /* UIP_ND6_DEF_MAXDADNS > 0 */ #else /* UIP_ND6_DEF_MAXDADNS > 0 */
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) { goto discard; /* DAD CASE */
/* DAD CASE */
goto discard;
#endif /* UIP_ND6_DEF_MAXDADNS > 0 */ #endif /* UIP_ND6_DEF_MAXDADNS > 0 */
} }
#if UIP_CONF_IPV6_CHECKS #if UIP_CONF_IPV6_CHECKS
@ -348,6 +369,7 @@ discard:
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
#if UIP_ND6_SEND_NS
void void
uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt) uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
{ {
@ -410,7 +432,9 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
PRINTF("\n"); PRINTF("\n");
return; return;
} }
#if UIP_ND6_SEND_NA #endif /* UIP_ND6_SEND_NS */
#if UIP_ND6_SEND_NS
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/** /**
* Neighbor Advertisement Processing * Neighbor Advertisement Processing
@ -522,14 +546,11 @@ na_input(void)
goto discard; goto discard;
} }
if(is_solicited) { /* Note: No need to refresh the state of the nbr here.
nbr->state = NBR_REACHABLE; * It has already been refreshed upon receiving the unicast IPv6 ND packet.
nbr->nscount = 0; * See: uip_ds6_nbr_refresh_reachable_state()
*/
/* reachable time is stored in ms */ if(!is_solicited) {
stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
} else {
nbr->state = NBR_STALE; nbr->state = NBR_STALE;
} }
nbr->isrouter = is_router; nbr->isrouter = is_router;
@ -552,11 +573,10 @@ na_input(void)
goto discard; goto discard;
} }
} }
if(is_solicited) { /* Note: No need to refresh the state of the nbr here.
nbr->state = NBR_REACHABLE; * It has already been refreshed upon receiving the unicast IPv6 ND packet.
/* reachable time is stored in ms */ * See: uip_ds6_nbr_refresh_reachable_state()
stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000); */
}
} }
} }
if(nbr->isrouter && !is_router) { if(nbr->isrouter && !is_router) {
@ -589,7 +609,7 @@ discard:
uip_clear_buf(); uip_clear_buf();
return; return;
} }
#endif /* UIP_ND6_SEND_NA */ #endif /* UIP_ND6_SEND_NS */
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
#if UIP_ND6_SEND_RA #if UIP_ND6_SEND_RA
@ -1083,6 +1103,8 @@ discard:
#if UIP_ND6_SEND_NA #if UIP_ND6_SEND_NA
UIP_ICMP6_HANDLER(ns_input_handler, ICMP6_NS, UIP_ICMP6_HANDLER_CODE_ANY, UIP_ICMP6_HANDLER(ns_input_handler, ICMP6_NS, UIP_ICMP6_HANDLER_CODE_ANY,
ns_input); ns_input);
#endif
#if UIP_ND6_SEND_NS
UIP_ICMP6_HANDLER(na_input_handler, ICMP6_NA, UIP_ICMP6_HANDLER_CODE_ANY, UIP_ICMP6_HANDLER(na_input_handler, ICMP6_NA, UIP_ICMP6_HANDLER_CODE_ANY,
na_input); na_input);
#endif #endif
@ -1100,19 +1122,16 @@ UIP_ICMP6_HANDLER(ra_input_handler, ICMP6_RA, UIP_ICMP6_HANDLER_CODE_ANY,
void void
uip_nd6_init() uip_nd6_init()
{ {
#if UIP_ND6_SEND_NA #if UIP_ND6_SEND_NA
/* Only handle NSs if we are prepared to send out NAs */ /* Only handle NSs if we are prepared to send out NAs */
uip_icmp6_register_input_handler(&ns_input_handler); uip_icmp6_register_input_handler(&ns_input_handler);
/*
* Only handle NAs if we are prepared to send out NAs.
* This is perhaps logically incorrect, but this condition was present in
* uip_process and we keep it until proven wrong
*/
uip_icmp6_register_input_handler(&na_input_handler);
#endif #endif
#if UIP_ND6_SEND_NS
/*
* Only handle NAs if we are prepared to send out NSs. */
uip_icmp6_register_input_handler(&na_input_handler);
#endif
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
/* Only accept RS if we are a router and happy to send out RAs */ /* Only accept RS if we are a router and happy to send out RAs */

View file

@ -60,11 +60,23 @@
/** \name RFC 4861 Host constant */ /** \name RFC 4861 Host constant */
/** @{ */ /** @{ */
/** \brief Maximum router solicitation delay */ /** \brief Maximum router solicitation delay */
#ifndef UIP_CONF_ND6_MAX_RTR_SOLICITATION_DELAY
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1 #define UIP_ND6_MAX_RTR_SOLICITATION_DELAY 1
#else
#define UIP_ND6_MAX_RTR_SOLICITATION_DELAY UIP_CONF_ND6_MAX_RTR_SOLICITATION_DELAY
#endif
/** \brief Router solicitation interval */ /** \brief Router solicitation interval */
#ifndef UIP_CONF_ND6_RTR_SOLICITATION_INTERVAL
#define UIP_ND6_RTR_SOLICITATION_INTERVAL 4 #define UIP_ND6_RTR_SOLICITATION_INTERVAL 4
#else
#define UIP_ND6_RTR_SOLICITATION_INTERVAL UIP_CONF_ND6_RTR_SOLICITATION_INTERVAL
#endif
/** \brief Maximum router solicitations */ /** \brief Maximum router solicitations */
#ifndef UIP_CONF_ND6_MAX_RTR_SOLICITATIONS
#define UIP_ND6_MAX_RTR_SOLICITATIONS 3 #define UIP_ND6_MAX_RTR_SOLICITATIONS 3
#else
#define UIP_ND6_MAX_RTR_SOLICITATIONS UIP_CONF_ND6_MAX_RTR_SOLICITATIONS
#endif
/** @} */ /** @} */
/** \name RFC 4861 Router constants */ /** \name RFC 4861 Router constants */
@ -74,6 +86,11 @@
#else #else
#define UIP_ND6_SEND_RA UIP_CONF_ND6_SEND_RA #define UIP_ND6_SEND_RA UIP_CONF_ND6_SEND_RA
#endif #endif
#ifndef UIP_CONF_ND6_SEND_NS
#define UIP_ND6_SEND_NS 1 /* enable/disable NS sending */
#else
#define UIP_ND6_SEND_NS UIP_CONF_ND6_SEND_NS
#endif
#ifndef UIP_CONF_ND6_SEND_NA #ifndef UIP_CONF_ND6_SEND_NA
#define UIP_ND6_SEND_NA 1 /* enable/disable NA sending */ #define UIP_ND6_SEND_NA 1 /* enable/disable NA sending */
#else #else
@ -91,7 +108,11 @@
#endif #endif
#define UIP_ND6_M_FLAG 0 #define UIP_ND6_M_FLAG 0
#define UIP_ND6_O_FLAG (UIP_ND6_RA_RDNSS || UIP_ND6_RA_DNSSL) #define UIP_ND6_O_FLAG (UIP_ND6_RA_RDNSS || UIP_ND6_RA_DNSSL)
#ifndef UIP_CONF_ROUTER_LIFETIME
#define UIP_ND6_ROUTER_LIFETIME 3 * UIP_ND6_MAX_RA_INTERVAL #define UIP_ND6_ROUTER_LIFETIME 3 * UIP_ND6_MAX_RA_INTERVAL
#else
#define UIP_ND6_ROUTER_LIFETIME UIP_CONF_ROUTER_LIFETIME
#endif
#define UIP_ND6_MAX_INITIAL_RA_INTERVAL 16 /*seconds*/ #define UIP_ND6_MAX_INITIAL_RA_INTERVAL 16 /*seconds*/
#define UIP_ND6_MAX_INITIAL_RAS 3 /*transmissions*/ #define UIP_ND6_MAX_INITIAL_RAS 3 /*transmissions*/
@ -109,7 +130,7 @@
#if UIP_CONF_LL_802154 #if UIP_CONF_LL_802154
#define UIP_ND6_DEF_MAXDADNS 0 #define UIP_ND6_DEF_MAXDADNS 0
#else /* UIP_CONF_LL_802154 */ #else /* UIP_CONF_LL_802154 */
#define UIP_ND6_DEF_MAXDADNS UIP_ND6_SEND_NA #define UIP_ND6_DEF_MAXDADNS UIP_ND6_SEND_NS
#endif /* UIP_CONF_LL_802154 */ #endif /* UIP_CONF_LL_802154 */
#else /* UIP_CONF_ND6_DEF_MAXDADNS */ #else /* UIP_CONF_ND6_DEF_MAXDADNS */
#define UIP_ND6_DEF_MAXDADNS UIP_CONF_ND6_DEF_MAXDADNS #define UIP_ND6_DEF_MAXDADNS UIP_CONF_ND6_DEF_MAXDADNS
@ -335,30 +356,6 @@ typedef struct uip_nd6_opt_redirected_hdr {
* \name ND Messages Processing and Generation * \name ND Messages Processing and Generation
* @{ * @{
*/ */
/**
* \brief Process a neighbor solicitation
*
* The NS can be received in 3 cases (procedures):
* - sender is performing DAD (ip src = unspecified, no SLLAO option)
* - sender is performing NUD (ip dst = unicast)
* - sender is performing address resolution (ip dest = solicited node mcast
* address)
*
* We do:
* - if the tgt belongs to me, reply, otherwise ignore
* - if i was performing DAD for the same address, two cases:
* -- I already sent a NS, hence I win
* -- I did not send a NS yet, hence I lose
*
* If we need to send a NA in response (i.e. the NS was done for NUD, or
* address resolution, or DAD and there is a conflict), we do it in this
* function: set src, dst, tgt address in the three cases, then for all cases
* set the rest, including SLLAO
*
*/
void
uip_nd6_ns_input(void);
/** /**
* \brief Send a neighbor solicitation, send a Neighbor Advertisement * \brief Send a neighbor solicitation, send a Neighbor Advertisement
* \param src pointer to the src of the NS if known * \param src pointer to the src of the NS if known

View file

@ -85,6 +85,10 @@
#include "rpl/rpl-private.h" #include "rpl/rpl-private.h"
#endif #endif
#if UIP_ND6_SEND_NS
#include "net/ipv6/uip-ds6-nbr.h"
#endif /* UIP_ND6_SEND_NS */
#include <string.h> #include <string.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -1151,6 +1155,13 @@ uip_process(uint8_t flag)
goto drop; goto drop;
} }
/* Refresh neighbor state after receiving a unicast message */
#if UIP_ND6_SEND_NS
if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
uip_ds6_nbr_refresh_reachable_state(&UIP_IP_BUF->srcipaddr);
}
#endif /* UIP_ND6_SEND_NS */
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
/* /*
* Next header field processing. In IPv6, we can have extension headers, * Next header field processing. In IPv6, we can have extension headers,

View file

@ -0,0 +1,347 @@
/*
* Copyright (c) 2014, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "websocket-http-client.h"
#include "net/ip/uiplib.h"
#include "net/ip/resolv.h"
#include "ip64-addr.h"
#include <stdio.h>
#include <string.h>
#define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h"
enum {
STATE_WAITING_FOR_HEADER,
STATE_WAITING_FOR_CONNECTED,
STATE_STEADY_STATE,
};
/*---------------------------------------------------------------------------*/
static void
send_get(struct websocket_http_client_state *s)
{
struct tcp_socket *tcps;
tcps = &s->s;
tcp_socket_send_str(tcps, "GET ");
tcp_socket_send_str(tcps, s->file);
tcp_socket_send_str(tcps, " HTTP/1.1\r\n");
tcp_socket_send_str(tcps, "Host: ");
tcp_socket_send_str(tcps, s->host);
tcp_socket_send_str(tcps, "\r\n");
if(strlen(s->header) > 0) {
tcp_socket_send_str(tcps, s->header);
}
/* The Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== header is
supposed to be a random value, encoded as base64, that is SHA1
hashed by the server and returned in a HTTP header. This is used
to make sure that we are not seeing some cached version of this
conversation. But we have no SHA1 code by default in Contiki, so
we can't check the return value. Therefore we just use a
hardcoded value here. */
tcp_socket_send_str(tcps,
"Connection: Upgrade\r\n"
"Upgrade: websocket\r\n"
"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n"
"Sec-WebSocket-Version: 13\r\n"
"Sec-WebSocket-Protocol:");
tcp_socket_send_str(tcps, s->subprotocol);
tcp_socket_send_str(tcps, "\r\n");
tcp_socket_send_str(tcps, "\r\n");
PRINTF("websocket-http-client: send_get(): output buffer left %d\n", tcp_socket_max_sendlen(tcps));
}
/*---------------------------------------------------------------------------*/
static void
send_connect(struct websocket_http_client_state *s)
{
struct tcp_socket *tcps;
char buf[20];
tcps = &s->s;
tcp_socket_send_str(tcps, "CONNECT ");
tcp_socket_send_str(tcps, s->host);
tcp_socket_send_str(tcps, ":");
sprintf(buf, "%d", s->port);
tcp_socket_send_str(tcps, buf);
tcp_socket_send_str(tcps, " HTTP/1.1\r\n");
tcp_socket_send_str(tcps, "Host: ");
tcp_socket_send_str(tcps, s->host);
tcp_socket_send_str(tcps, "\r\n");
tcp_socket_send_str(tcps, "Proxy-Connection: Keep-Alive\r\n\r\n");
}
/*---------------------------------------------------------------------------*/
static void
event(struct tcp_socket *tcps, void *ptr,
tcp_socket_event_t e)
{
struct websocket_http_client_state *s = ptr;
if(e == TCP_SOCKET_CONNECTED) {
if(s->proxy_port != 0) {
send_connect(s);
} else {
send_get(s);
}
} else if(e == TCP_SOCKET_CLOSED) {
websocket_http_client_closed(s);
} else if(e == TCP_SOCKET_TIMEDOUT) {
websocket_http_client_timedout(s);
} else if(e == TCP_SOCKET_ABORTED) {
websocket_http_client_aborted(s);
} else if(e == TCP_SOCKET_DATA_SENT) {
/* We could feed this information up to the websocket.c layer, but
we currently do not do that. */
}
}
/*---------------------------------------------------------------------------*/
static int
parse_header_byte(struct websocket_http_client_state *s,
uint8_t b)
{
static const char *endmarker = "\r\n\r\n";
PT_BEGIN(&s->parse_header_pt);
/* Skip the first part of the HTTP response */
while(b != ' ') {
PT_YIELD(&s->parse_header_pt);
}
/* Skip the space that follow the first part */
PT_YIELD(&s->parse_header_pt);
/* Read the first three bytes that constistute the HTTP status
code. We store the HTTP status code as an integer in the
s->http_status field. */
s->http_status = (b - '0');
PT_YIELD(&s->parse_header_pt);
s->http_status = s->http_status * 10 + (b - '0');
PT_YIELD(&s->parse_header_pt);
s->http_status = s->http_status * 10 + (b - '0');
if((s->proxy_port != 0 && !(s->http_status == 200 || s->http_status == 101)) ||
(s->proxy_port == 0 && s->http_status != 101)) {
/* This is a websocket request, so the server should have answered
with a 101 Switching protocols response. */
PRINTF("Websocket HTTP client didn't get the 101 status code (got %d), closing connection\n",
s->http_status);
websocket_http_client_close(s);
while(1) {
PT_YIELD(&s->parse_header_pt);
}
}
/* Keep eating header bytes until we reach the end of it. The end is
indicated by the string "\r\n\r\n". We don't actually look at any
of the headers.
The s->i variable contains the number of consecutive bytes
matched. If we match the total length of the string, we stop.
*/
s->i = 0;
do {
PT_YIELD(&s->parse_header_pt);
if(b == (uint8_t)endmarker[s->i]) {
s->i++;
} else {
s->i = 0;
}
} while(s->i < strlen(endmarker));
if(s->proxy_port != 0 && s->state == STATE_WAITING_FOR_HEADER) {
send_get(s);
s->state = STATE_WAITING_FOR_CONNECTED;
} else {
s->state = STATE_STEADY_STATE;
websocket_http_client_connected(s);
}
PT_END(&s->parse_header_pt);
}
/*---------------------------------------------------------------------------*/
static int
input(struct tcp_socket *tcps, void *ptr,
const uint8_t *inputptr, int inputdatalen)
{
struct websocket_http_client_state *s = ptr;
if(s->state == STATE_WAITING_FOR_HEADER ||
s->state == STATE_WAITING_FOR_CONNECTED) {
int i;
for(i = 0; i < inputdatalen; i++) {
parse_header_byte(s, inputptr[i]);
if(s->state == STATE_STEADY_STATE) {
i++;
break;
}
}
if(i < inputdatalen && s->state == STATE_STEADY_STATE) {
websocket_http_client_datahandler(s, &inputptr[i], inputdatalen - i);
}
} else {
websocket_http_client_datahandler(s, inputptr, inputdatalen);
}
return 0; /* all data consumed */
}
/*---------------------------------------------------------------------------*/
int
websocket_http_client_register(struct websocket_http_client_state *s,
const char *host,
uint16_t port,
const char *file,
const char *subprotocol,
const char *header)
{
if(host == NULL) {
return -1;
}
strncpy(s->host, host, sizeof(s->host));
if(file == NULL) {
return -1;
}
strncpy(s->file, file, sizeof(s->file));
if(subprotocol == NULL) {
return -1;
}
strncpy(s->subprotocol, subprotocol, sizeof(s->subprotocol));
if(header == NULL) {
strncpy(s->header, "", sizeof(s->header));
} else {
strncpy(s->header, header, sizeof(s->header));
}
if(port == 0) {
s->port = 80;
} else {
s->port = port;
}
return 1;
}
/*---------------------------------------------------------------------------*/
int
websocket_http_client_get(struct websocket_http_client_state *s)
{
uip_ip4addr_t ip4addr;
uip_ip6addr_t ip6addr;
uip_ip6addr_t *addr;
uint16_t port;
PRINTF("websocket_http_client_get: connecting to %s with file %s subprotocol %s header %s\n",
s->host, s->file, s->subprotocol, s->header);
s->state = STATE_WAITING_FOR_HEADER;
if(tcp_socket_register(&s->s, s,
s->inputbuf, sizeof(s->inputbuf),
s->outputbuf, sizeof(s->outputbuf),
input, event) < 0) {
return -1;
}
port = s->port;
if(s->proxy_port != 0) {
/* The proxy address should be an IPv6 address. */
uip_ipaddr_copy(&ip6addr, &s->proxy_addr);
port = s->proxy_port;
} else if(uiplib_ip6addrconv(s->host, &ip6addr) == 0) {
/* First check if the host is an IP address. */
if(uiplib_ip4addrconv(s->host, &ip4addr) != 0) {
ip64_addr_4to6(&ip4addr, &ip6addr);
} else {
/* Try to lookup the hostname. If it fails, we initiate a hostname
lookup. */
if(resolv_lookup(s->host, &addr) != RESOLV_STATUS_CACHED) {
return -1;
}
return tcp_socket_connect(&s->s, addr, s->port);
}
}
return tcp_socket_connect(&s->s, &ip6addr, port);
}
/*---------------------------------------------------------------------------*/
int
websocket_http_client_send(struct websocket_http_client_state *s,
const uint8_t *data,
uint16_t datalen)
{
if(s->state == STATE_STEADY_STATE) {
return tcp_socket_send(&s->s, data, datalen);
}
return -1;
}
/*---------------------------------------------------------------------------*/
int
websocket_http_client_sendbuflen(struct websocket_http_client_state *s)
{
return tcp_socket_max_sendlen(&s->s);
}
/*---------------------------------------------------------------------------*/
void
websocket_http_client_close(struct websocket_http_client_state *s)
{
tcp_socket_close(&s->s);
}
/*---------------------------------------------------------------------------*/
const char *
websocket_http_client_hostname(struct websocket_http_client_state *s)
{
return s->host;
}
/*---------------------------------------------------------------------------*/
void
websocket_http_client_init(struct websocket_http_client_state *s)
{
uip_create_unspecified(&s->proxy_addr);
s->proxy_port = 0;
}
/*---------------------------------------------------------------------------*/
void
websocket_http_client_set_proxy(struct websocket_http_client_state *s,
const uip_ipaddr_t *addr, uint16_t port)
{
uip_ipaddr_copy(&s->proxy_addr, addr);
s->proxy_port = port;
}
/*---------------------------------------------------------------------------*/
int
websocket_http_client_queuelen(struct websocket_http_client_state *s)
{
return tcp_socket_queuelen(&s->s);
}
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,123 @@
/*
* Copyright (c) 2014, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKET_HTTP_CLIENT_H_
#define WEBSOCKET_HTTP_CLIENT_H_
#include "contiki.h"
#include "tcp-socket.h"
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_INPUTBUFSIZE
#define WEBSOCKET_HTTP_CLIENT_INPUTBUFSIZE WEBSOCKET_HTTP_CLIENT_CONF_INPUTBUFSIZE
#else /* WEBSOCKET_HTTP_CLIENT_CONF_INPUTBUFSIZE */
#define WEBSOCKET_HTTP_CLIENT_INPUTBUFSIZE 100
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_INPUTBUFSIZE */
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_OUTPUTBUFSIZE
#define WEBSOCKET_HTTP_CLIENT_OUTPUTBUFSIZE WEBSOCKET_HTTP_CLIENT_CONF_OUTPUTBUFSIZE
#else /* WEBSOCKET_HTTP_CLIENT_CONF_OUTPUTBUFSIZE */
#define WEBSOCKET_HTTP_CLIENT_OUTPUTBUFSIZE 300
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_OUTPUTBUFSIZE */
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_MAX_HOSTLEN
#define WEBSOCKET_HTTP_CLIENT_MAX_HOSTLEN WEBSOCKET_HTTP_CLIENT_CONF_MAX_HOSTLEN
#else /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_HOSTLEN */
#define WEBSOCKET_HTTP_CLIENT_MAX_HOSTLEN 32
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_HOSTLEN */
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_MAX_FILELEN
#define WEBSOCKET_HTTP_CLIENT_MAX_FILELEN WEBSOCKET_HTTP_CLIENT_CONF_MAX_FILELEN
#else /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_FILELEN */
#define WEBSOCKET_HTTP_CLIENT_MAX_FILELEN 32
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_FILELEN */
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_MAX_SUBPROTOCOLLEN
#define WEBSOCKET_HTTP_CLIENT_MAX_SUBPROTOCOLLEN WEBSOCKET_HTTP_CLIENT_CONF_MAX_SUBPROTOCOLLEN
#else /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_SUBPROTOCOLLEN */
#define WEBSOCKET_HTTP_CLIENT_MAX_SUBPROTOCOLLEN 24
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_SUBPROTOCOLLEN */
#ifdef WEBSOCKET_HTTP_CLIENT_CONF_MAX_HEADERLEN
#define WEBSOCKET_HTTP_CLIENT_MAX_HEADERLEN WEBSOCKET_HTTP_CLIENT_CONF_MAX_HEADERLEN
#else /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_HEADERLEN */
#define WEBSOCKET_HTTP_CLIENT_MAX_HEADERLEN 128
#endif /* WEBSOCKET_HTTP_CLIENT_CONF_MAX_HEADERLEN */
struct websocket_http_client_state {
struct tcp_socket s;
uint8_t inputbuf[WEBSOCKET_HTTP_CLIENT_INPUTBUFSIZE];
uint8_t outputbuf[WEBSOCKET_HTTP_CLIENT_OUTPUTBUFSIZE];
char host[WEBSOCKET_HTTP_CLIENT_MAX_HOSTLEN];
char file[WEBSOCKET_HTTP_CLIENT_MAX_FILELEN];
char subprotocol[WEBSOCKET_HTTP_CLIENT_MAX_SUBPROTOCOLLEN];
char header[WEBSOCKET_HTTP_CLIENT_MAX_HEADERLEN];
uint16_t port;
int state;
struct pt parse_header_pt;
int http_status;
int i;
uip_ipaddr_t proxy_addr;
uint16_t proxy_port;
};
void websocket_http_client_init(struct websocket_http_client_state *s);
void websocket_http_client_set_proxy(struct websocket_http_client_state *s,
const uip_ipaddr_t *addr, uint16_t port);
int websocket_http_client_register(struct websocket_http_client_state *s,
const char *host,
uint16_t port,
const char *file,
const char *subprotocol,
const char *hdr);
int websocket_http_client_get(struct websocket_http_client_state *s);
int websocket_http_client_send(struct websocket_http_client_state *s,
const uint8_t *data,
uint16_t datalen);
int websocket_http_client_sendbuflen(struct websocket_http_client_state *s);
void websocket_http_client_close(struct websocket_http_client_state *s);
const char *websocket_http_client_hostname(struct websocket_http_client_state *s);
int websocket_http_client_queuelen(struct websocket_http_client_state *s);
/* Callback functions that have to be implemented by the application
program. */
void websocket_http_client_datahandler(struct websocket_http_client_state *s,
const uint8_t *data, uint16_t len);
void websocket_http_client_connected(struct websocket_http_client_state *s);
void websocket_http_client_timedout(struct websocket_http_client_state *s);
void websocket_http_client_aborted(struct websocket_http_client_state *s);
void websocket_http_client_closed(struct websocket_http_client_state *s);
#endif /* WEBSOCKET_HTTP_CLIENT_H_ */

724
core/net/ipv6/websocket.c Normal file
View file

@ -0,0 +1,724 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include "contiki-net.h"
#include "lib/petsciiconv.h"
#include "websocket.h"
PROCESS(websocket_process, "Websockets process");
#define MAX_HOSTLEN 64
#define MAX_PATHLEN 100
LIST(websocketlist);
#define WEBSOCKET_FIN_BIT 0x80
#define WEBSOCKET_OPCODE_MASK 0x0f
#define WEBSOCKET_OPCODE_CONT 0x00
#define WEBSOCKET_OPCODE_TEXT 0x01
#define WEBSOCKET_OPCODE_BIN 0x02
#define WEBSOCKET_OPCODE_CLOSE 0x08
#define WEBSOCKET_OPCODE_PING 0x09
#define WEBSOCKET_OPCODE_PONG 0x0a
#define WEBSOCKET_MASK_BIT 0x80
#define WEBSOCKET_LEN_MASK 0x7f
struct websocket_frame_hdr {
uint8_t opcode;
uint8_t len;
uint8_t extlen[4];
};
struct websocket_frame_mask {
uint8_t mask[4];
};
#define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h"
/*---------------------------------------------------------------------------*/
static int
parse_url(const char *url, char *host, uint16_t *portptr, char *path)
{
const char *urlptr;
int i;
const char *file;
uint16_t port;
if(url == NULL) {
return 0;
}
/* Don't even try to go further if the URL is empty. */
if(strlen(url) == 0) {
return 0;
}
/* See if the URL starts with http:// or ws:// and remove it. */
if(strncmp(url, "http://", strlen("http://")) == 0) {
urlptr = url + strlen("http://");
} else if(strncmp(url, "ws://", strlen("ws://")) == 0) {
urlptr = url + strlen("ws://");
} else {
urlptr = url;
}
/* Find host part of the URL. */
for(i = 0; i < MAX_HOSTLEN; ++i) {
if(*urlptr == 0 ||
*urlptr == '/' ||
*urlptr == ' ' ||
*urlptr == ':') {
if(host != NULL) {
host[i] = 0;
}
break;
}
if(host != NULL) {
host[i] = *urlptr;
}
++urlptr;
}
/* Find the port. Default is 0, which lets the underlying transport
select its default port. */
port = 0;
if(*urlptr == ':') {
port = 0;
do {
++urlptr;
if(*urlptr >= '0' && *urlptr <= '9') {
port = (10 * port) + (*urlptr - '0');
}
} while(*urlptr >= '0' &&
*urlptr <= '9');
}
if(portptr != NULL) {
*portptr = port;
}
/* Find file part of the URL. */
while(*urlptr != '/' && *urlptr != 0) {
++urlptr;
}
if(*urlptr == '/') {
file = urlptr;
} else {
file = "/";
}
if(path != NULL) {
strncpy(path, file, MAX_PATHLEN);
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int
start_get(struct websocket *s)
{
if(websocket_http_client_get(&(s->s)) == 0) {
PRINTF("Out of memory error\n");
s->state = WEBSOCKET_STATE_CLOSED;
return WEBSOCKET_ERR;
} else {
PRINTF("Connecting...\n");
s->state = WEBSOCKET_STATE_HTTP_REQUEST_SENT;
return WEBSOCKET_OK;
}
return WEBSOCKET_ERR;
}
/*---------------------------------------------------------------------------*/
void
call(struct websocket *s, websocket_result_t r,
const uint8_t *data, uint16_t datalen)
{
if(s != NULL && s->callback != NULL) {
s->callback(s, r, data, datalen);
}
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(websocket_process, ev, data)
{
PROCESS_BEGIN();
while(1) {
PROCESS_WAIT_EVENT();
if(ev == resolv_event_found && data != NULL) {
int ret;
struct websocket *s;
const char *name = data;
/* Either found a hostname, or not. We need to go through the
list of websocketsand figure out to which connection this
reply corresponds, then either restart the HTTP get, or kill
it (if no hostname was found). */
for(s = list_head(websocketlist);
s != NULL;
s = list_item_next(s)) {
if(strcmp(name, websocket_http_client_hostname(&s->s)) == 0) {
ret = resolv_lookup(name, NULL);
if(ret == RESOLV_STATUS_CACHED) {
/* Hostname found, restart get. */
if(s->state == WEBSOCKET_STATE_DNS_REQUEST_SENT) {
PRINTF("Restarting get\n");
start_get(s);
}
} else {
if(s->state == WEBSOCKET_STATE_DNS_REQUEST_SENT) {
/* Hostname not found, kill connection. */
/* PRINTF("XXX killing connection\n");*/
call(s, WEBSOCKET_HOSTNAME_NOT_FOUND, NULL, 0);
}
}
}
}
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
/* Callback function. Called from the webclient when the HTTP
* connection was abruptly aborted.
*/
void
websocket_http_client_aborted(struct websocket_http_client_state *client_state)
{
if(client_state != NULL) {
struct websocket *s = (struct websocket *)
((char *)client_state - offsetof(struct websocket, s));
PRINTF("Websocket reset\n");
s->state = WEBSOCKET_STATE_CLOSED;
call(s, WEBSOCKET_RESET, NULL, 0);
}
}
/*---------------------------------------------------------------------------*/
/* Callback function. Called from the webclient when the HTTP
* connection timed out.
*/
void
websocket_http_client_timedout(struct websocket_http_client_state *client_state)
{
if(client_state != NULL) {
struct websocket *s = (struct websocket *)
((char *)client_state - offsetof(struct websocket, s));
PRINTF("Websocket timed out\n");
s->state = WEBSOCKET_STATE_CLOSED;
call(s, WEBSOCKET_TIMEDOUT, NULL, 0);
}
}
/*---------------------------------------------------------------------------*/
/* Callback function. Called from the webclient when the HTTP
* connection was closed after a request from the "websocket_http_client_close()"
* function. .
*/
void
websocket_http_client_closed(struct websocket_http_client_state *client_state)
{
if(client_state != NULL) {
struct websocket *s = (struct websocket *)
((char *)client_state - offsetof(struct websocket, s));
PRINTF("Websocket closed.\n");
s->state = WEBSOCKET_STATE_CLOSED;
call(s, WEBSOCKET_CLOSED, NULL, 0);
}
}
/*---------------------------------------------------------------------------*/
/* Callback function. Called from the webclient when the HTTP
* connection is connected.
*/
void
websocket_http_client_connected(struct websocket_http_client_state *client_state)
{
struct websocket *s = (struct websocket *)
((char *)client_state - offsetof(struct websocket, s));
PRINTF("Websocket connected\n");
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
call(s, WEBSOCKET_CONNECTED, NULL, 0);
}
/*---------------------------------------------------------------------------*/
/* The websocket header may potentially be split into multiple TCP
segments. This function eats one byte each, puts it into
s->headercache, and checks whether or not the full header has been
received. */
static int
receive_header_byte(struct websocket *s, uint8_t byte)
{
int len;
int expected_len;
struct websocket_frame_hdr *hdr;
/* Take the next byte of data and place it in the header cache. */
if(s->state == WEBSOCKET_STATE_RECEIVING_HEADER) {
s->headercache[s->headercacheptr] = byte;
s->headercacheptr++;
if(s->headercacheptr >= sizeof(s->headercache)) {
/* Something bad happened: we ad read 10 bytes and had not yet
found a reasonable header, so we close the socket. */
websocket_close(s);
}
}
len = s->headercacheptr;
hdr = (struct websocket_frame_hdr *)s->headercache;
/* Check the header that we have received to see if it is long
enough. */
/* We start with expecting a length of at least two bytes (opcode +
1 length byte). */
expected_len = 2;
if(len >= expected_len) {
/* We check how many more bytes we should expect to see. The
length byte determines how many length bytes are included in
the header. */
if((hdr->len & WEBSOCKET_LEN_MASK) == 126) {
expected_len += 2;
} else if((hdr->len & WEBSOCKET_LEN_MASK) == 127) {
expected_len += 4;
}
/* If the option has the mask bit set, we should expect to see 4
mask bytes at the end of the header. */
if((hdr->len & WEBSOCKET_MASK_BIT ) != 0) {
expected_len += 4;
}
/* Now we know how long our header if expected to be. If it is
this long, we are done and we set the state to reflect this. */
if(len == expected_len) {
s->state = WEBSOCKET_STATE_HEADER_RECEIVED;
return 1;
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
/* Callback function. Called from the webclient module when HTTP data
* has arrived.
*/
void
websocket_http_client_datahandler(struct websocket_http_client_state *client_state,
const uint8_t *data, uint16_t datalen)
{
struct websocket *s = (struct websocket *)
((char *)client_state - offsetof(struct websocket, s));
struct websocket_frame_hdr *hdr;
struct websocket_frame_mask *maskptr;
if(data == NULL) {
call(s, WEBSOCKET_CLOSED, NULL, 0);
} else {
/* This function is a state machine that does different things
depending on the state. If we are waiting for header (the
default state), we change to the RECEIVING_HEADER state when we
get the first byte. If we are receiving header, we put all
bytes we have into a header buffer until the full header has
been received. If we have received the header, we parse it. If
we have received and parsed the header, we are ready to receive
data. Finally, if there is data left in the incoming packet, we
repeat the process. */
if(s->state == WEBSOCKET_STATE_WAITING_FOR_HEADER) {
s->state = WEBSOCKET_STATE_RECEIVING_HEADER;
s->headercacheptr = 0;
}
if(s->state == WEBSOCKET_STATE_RECEIVING_HEADER) {
while(datalen > 0 && s->state == WEBSOCKET_STATE_RECEIVING_HEADER) {
receive_header_byte(s, data[0]);
data++;
datalen--;
}
}
if(s->state == WEBSOCKET_STATE_HEADER_RECEIVED) {
/* If this is the start of an incoming websocket data frame, we
decode the header and check if we should act on in. If not, we
pipe the data to the application through a callback handler. If
data arrives in multiple packets, it is up to the application to
put it back together again. */
/* The websocket header is at the start of the incoming data. */
hdr = (struct websocket_frame_hdr *)s->headercache;
/* The s->left field holds the length of the application data
* chunk that we are about to receive. */
s->len = s->left = 0;
/* The s->mask field holds the bitmask of the data chunk, if
* any. */
memset(s->mask, 0, sizeof(s->mask));
/* We first read out the length of the application data
chunk. The length may be encoded over multiple bytes. If the
length is >= 126 bytes, it is encoded as two or more
bytes. The first length field determines if it is in 2 or 4
bytes. We also keep track of where the bitmask is held - its
place also differs depending on how the length is encoded. */
maskptr = (struct websocket_frame_mask *)hdr->extlen;
if((hdr->len & WEBSOCKET_LEN_MASK) < 126) {
s->len = s->left = hdr->len & WEBSOCKET_LEN_MASK;
} else if(hdr->len == 126) {
s->len = s->left = (hdr->extlen[0] << 8) + hdr->extlen[1];
maskptr = (struct websocket_frame_mask *)&hdr->extlen[2];
} else if(hdr->len == 127) {
s->len = s->left = ((uint32_t)hdr->extlen[0] << 24) +
((uint32_t)hdr->extlen[1] << 16) +
((uint32_t)hdr->extlen[2] << 8) +
hdr->extlen[3];
maskptr = (struct websocket_frame_mask *)&hdr->extlen[4];
}
/* Set user_data to point to the first byte of application data.
See if the application data chunk is masked or not. If it is,
we copy the bitmask into the s->mask field. */
if((hdr->len & WEBSOCKET_MASK_BIT) == 0) {
/* PRINTF("No mask\n");*/
} else {
memcpy(s->mask, &maskptr->mask, sizeof(s->mask));
/* PRINTF("There was a mask, %02x %02x %02x %02x\n",
s->mask[0], s->mask[1], s->mask[2], s->mask[3]);*/
}
/* Remember the opcode of the application chunk, put it in the
* s->opcode field. */
s->opcode = hdr->opcode & WEBSOCKET_OPCODE_MASK;
if(s->opcode == WEBSOCKET_OPCODE_PING) {
/* If the opcode is ping, we change the opcode to a pong, and
* send the data back. */
hdr->opcode = (hdr->opcode & (~WEBSOCKET_OPCODE_MASK)) |
WEBSOCKET_OPCODE_PONG;
websocket_http_client_send(&s->s, (const uint8_t*)hdr, 2);
if(s->left > 0) {
websocket_http_client_send(&s->s, (const uint8_t*)data, s->left);
}
PRINTF("Got ping\n");
call(s, WEBSOCKET_PINGED, NULL, 0);
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
} else if(s->opcode == WEBSOCKET_OPCODE_PONG) {
/* If the opcode is pong, we call the application to let it
know we got a pong. */
PRINTF("Got pong\n");
call(s, WEBSOCKET_PONG_RECEIVED, NULL, 0);
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
} else if(s->opcode == WEBSOCKET_OPCODE_CLOSE) {
/* If the opcode is a close, we send a close frame back. */
hdr->opcode = (hdr->opcode & (~WEBSOCKET_OPCODE_MASK)) |
WEBSOCKET_OPCODE_CLOSE;
websocket_http_client_send(&s->s, (const uint8_t*)hdr, 2);
if(s->left > 0) {
websocket_http_client_send(&s->s, (const uint8_t*)data, s->left);
}
PRINTF("websocket: got close, sending close\n");
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
websocket_http_client_close(&s->s);
} else if(s->opcode == WEBSOCKET_OPCODE_BIN ||
s->opcode == WEBSOCKET_OPCODE_TEXT) {
/* If the opcode is bin or text, and there is application
* layer data in the packet, we call the application to
* process it. */
if(s->left > 0) {
s->state = WEBSOCKET_STATE_RECEIVING_DATA;
if(datalen > 0) {
int len;
len = MIN(s->left, datalen);
/* XXX todo: mask if needed. */
call(s, WEBSOCKET_DATA, data, len);
data += len;
s->left -= len;
datalen -= len;
}
}
}
if(s->left == 0) {
call(s, WEBSOCKET_DATA_RECEIVED, NULL, s->len);
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
/* Need to keep parsing the incoming data to check for more
frames, if the incoming datalen is > than s->left. */
if(datalen > 0) {
PRINTF("XXX 1 again\n");
websocket_http_client_datahandler(client_state,
data, datalen);
}
}
} else if(s->state == WEBSOCKET_STATE_RECEIVING_DATA) {
/* XXX todo: mask if needed. */
/* PRINTF("Calling with s->left %d datalen %d\n",
s->left, datalen);*/
if(datalen > 0) {
if(datalen < s->left) {
call(s, WEBSOCKET_DATA, data, datalen);
s->left -= datalen;
data += datalen;
datalen = 0;
} else {
call(s, WEBSOCKET_DATA, data, s->left);
data += s->left;
datalen -= s->left;
s->left = 0;
}
}
if(s->left == 0) {
call(s, WEBSOCKET_DATA_RECEIVED, NULL, s->len);
s->state = WEBSOCKET_STATE_WAITING_FOR_HEADER;
/* Need to keep parsing the incoming data to check for more
frames, if the incoming datalen is > than len. */
if(datalen > 0) {
PRINTF("XXX 2 again (datalen %d s->left %d)\n", datalen, (int)s->left);
websocket_http_client_datahandler(client_state,
data, datalen);
}
}
}
}
}
/*---------------------------------------------------------------------------*/
static void
init(void)
{
static uint8_t inited = 0;
if(!inited) {
process_start(&websocket_process, NULL);
list_init(websocketlist);
inited = 1;
}
}
/*---------------------------------------------------------------------------*/
void
websocket_init(struct websocket *s)
{
init();
websocket_http_client_init(&s->s);
}
/*---------------------------------------------------------------------------*/
void
websocket_set_proxy(struct websocket *s,
const uip_ipaddr_t *addr, uint16_t port)
{
websocket_http_client_set_proxy(&s->s, addr, port);
}
/*---------------------------------------------------------------------------*/
websocket_result_t
websocket_open(struct websocket *s, const char *url,
const char *subprotocol, const char *hdr,
websocket_callback c)
{
int ret;
char host[MAX_HOSTLEN + 1] = {0};
char path[MAX_PATHLEN + 1] = {0};
uint16_t port;
uip_ipaddr_t addr;
init();
if(s == NULL) {
return WEBSOCKET_ERR;
}
if(s->state != WEBSOCKET_STATE_CLOSED) {
PRINTF("websocket_open: closing websocket before opening it again.\n");
websocket_close(s);
}
s->callback = c;
if(parse_url(url, host, &port, path)) {
list_add(websocketlist, s);
websocket_http_client_register(&s->s, host, port, path, subprotocol, hdr);
/* First check if the host is an IP address. */
if(uiplib_ip4addrconv(host, (uip_ip4addr_t *)&addr) == 0 &&
uiplib_ip6addrconv(host, (uip_ip6addr_t *)&addr) == 0) {
/* Try to lookup the hostname. If it fails, we initiate a hostname
lookup and print out an informative message on the
statusbar. */
ret = resolv_lookup(host, NULL);
if(ret != RESOLV_STATUS_CACHED) {
resolv_query(host);
s->state = WEBSOCKET_STATE_DNS_REQUEST_SENT;
PRINTF("Resolving host...\n");
return WEBSOCKET_OK;
}
}
PROCESS_CONTEXT_BEGIN(&websocket_process);
ret = start_get(s);
PROCESS_CONTEXT_END();
return ret;
}
return -1;
}
/*---------------------------------------------------------------------------*/
void
websocket_close(struct websocket *s)
{
websocket_http_client_close(&s->s);
s->state = WEBSOCKET_STATE_CLOSED;
}
/*---------------------------------------------------------------------------*/
static int
send_data(struct websocket *s, const void *data,
uint16_t datalen, uint8_t data_type_opcode)
{
uint8_t buf[WEBSOCKET_MAX_MSGLEN + 4 + 4]; /* The extra + 4 + 4 here
comes from the size of
the websocket framing
header. */
struct websocket_frame_hdr *hdr;
struct websocket_frame_mask *mask;
PRINTF("websocket send data len %d %.*s\n", datalen, datalen, (char *)data);
if(s->state == WEBSOCKET_STATE_CLOSED ||
s->state == WEBSOCKET_STATE_DNS_REQUEST_SENT ||
s->state == WEBSOCKET_STATE_HTTP_REQUEST_SENT) {
/* Trying to send data on a non-connected websocket. */
PRINTF("websocket send fail: not connected\n");
return -1;
}
/* We need to have 4 + 4 additional bytes for the websocket framing
header. */
if(4 + 4 + datalen > websocket_http_client_sendbuflen(&s->s)) {
PRINTF("websocket: too few bytes left (%d left, %d needed)\n",
websocket_http_client_sendbuflen(&s->s),
4 + 4 + datalen);
return -1;
}
if(datalen > sizeof(buf) - 4 - 4) {
PRINTF("websocket: trying to send too large data chunk %d > %d\n",
datalen, sizeof(buf) - 4 - 4);
return -1;
}
hdr = (struct websocket_frame_hdr *)&buf[0];
hdr->opcode = WEBSOCKET_FIN_BIT | data_type_opcode;
/* If the datalen is larger than 125 bytes, we need to send the data
length as two bytes. If the data length would be larger than 64k,
we should send the length as 4 bytes, but since we specify the
datalen as an unsigned 16-bit int, we do not handle the 64k case
here. */
if(datalen > 125) {
/* Data from client must always have the mask bit set, and a data
mask sent right after the header. */
hdr->len = 126 | WEBSOCKET_MASK_BIT;
hdr->extlen[0] = datalen >> 8;
hdr->extlen[1] = datalen & 0xff;
mask = (struct websocket_frame_mask *)&buf[4];
mask->mask[0] =
mask->mask[1] =
mask->mask[2] =
mask->mask[3] = 0;
memcpy(&buf[8], data, datalen);
return websocket_http_client_send(&s->s, buf, 8 + datalen);
} else {
/* Data from client must always have the mask bit set, and a data
mask sent right after the header. */
hdr->len = datalen | WEBSOCKET_MASK_BIT;
mask = (struct websocket_frame_mask *)&buf[2];
mask->mask[0] =
mask->mask[1] =
mask->mask[2] =
mask->mask[3] = 0;
memcpy(&buf[6], data, datalen);
return websocket_http_client_send(&s->s, buf, 6 + datalen);
}
return -1;
}
/*---------------------------------------------------------------------------*/
int
websocket_send_str(struct websocket *s, const char *str)
{
return send_data(s, str, strlen(str), WEBSOCKET_OPCODE_TEXT);
}
/*---------------------------------------------------------------------------*/
int
websocket_send(struct websocket *s, const uint8_t *data,
uint16_t datalen)
{
return send_data(s, data, datalen, WEBSOCKET_OPCODE_BIN);
}
/*---------------------------------------------------------------------------*/
int
websocket_ping(struct websocket *s)
{
uint8_t buf[sizeof(struct websocket_frame_hdr) +
sizeof(struct websocket_frame_mask)];
struct websocket_frame_hdr *hdr;
struct websocket_frame_mask *mask;
/* We need 2 + 4 additional bytes for the websocket framing
header. */
if(2 + 4 > websocket_http_client_sendbuflen(&s->s)) {
return -1;
}
hdr = (struct websocket_frame_hdr *)&buf[0];
mask = (struct websocket_frame_mask *)&buf[2];
hdr->opcode = WEBSOCKET_FIN_BIT | WEBSOCKET_OPCODE_PING;
/* Data from client must always have the mask bit set, and a data
mask sent right after the header. */
hdr->len = 0 | WEBSOCKET_MASK_BIT;
/* XXX: We just set a dummy mask of 0 for now and hope that this
works. */
mask->mask[0] =
mask->mask[1] =
mask->mask[2] =
mask->mask[3] = 0;
websocket_http_client_send(&s->s, buf, 2 + 4);
return 1;
}
/*---------------------------------------------------------------------------*/
int
websocket_queuelen(struct websocket *s)
{
return websocket_http_client_queuelen(&s->s);
}
/*---------------------------------------------------------------------------*/

113
core/net/ipv6/websocket.h Normal file
View file

@ -0,0 +1,113 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WEBSOCKET_H
#define WEBSOCKET_H
#include "websocket-http-client.h"
typedef enum {
WEBSOCKET_ERR = 0,
WEBSOCKET_OK = 1,
WEBSOCKET_IN_PROGRESS = 2,
WEBSOCKET_HOSTNAME_NOT_FOUND = 3,
WEBSOCKET_CONNECTED = 4,
WEBSOCKET_DATA = 5,
WEBSOCKET_RESET = 6,
WEBSOCKET_TIMEDOUT = 7,
WEBSOCKET_CLOSED = 8,
WEBSOCKET_PINGED = 9,
WEBSOCKET_DATA_RECEIVED = 10,
WEBSOCKET_PONG_RECEIVED = 11,
} websocket_result_t;
struct websocket;
typedef void (* websocket_callback)(struct websocket *s,
websocket_result_t result,
const uint8_t *data,
uint16_t datalen);
#ifdef WEBSOCKET_CONF_MAX_MSGLEN
#define WEBSOCKET_MAX_MSGLEN WEBSOCKET_CONF_MAX_MSGLEN
#else /* WEBSOCKET_CONF_MAX_MSGLEN */
#define WEBSOCKET_MAX_MSGLEN 200
#endif /* WEBSOCKET_CONF_MAX_MSGLEN */
struct websocket {
struct websocket *next; /* Must be first. */
struct websocket_http_client_state s;
websocket_callback callback;
uint8_t mask[4];
uint32_t left, len;
uint8_t opcode;
uint8_t state;
uint8_t headercacheptr;
uint8_t headercache[10]; /* The maximum websocket header + mask is 6
+ 4 bytes long */
};
enum {
WEBSOCKET_STATE_CLOSED = 0,
WEBSOCKET_STATE_DNS_REQUEST_SENT = 1,
WEBSOCKET_STATE_HTTP_REQUEST_SENT = 2,
WEBSOCKET_STATE_WAITING_FOR_HEADER = 3,
WEBSOCKET_STATE_RECEIVING_HEADER = 4,
WEBSOCKET_STATE_HEADER_RECEIVED = 5,
WEBSOCKET_STATE_RECEIVING_DATA = 6,
};
void websocket_init(struct websocket *s);
void websocket_set_proxy(struct websocket *s,
const uip_ipaddr_t *addr, uint16_t port);
websocket_result_t websocket_open(struct websocket *s,
const char *url,
const char *subprotocol,
const char *hdr,
websocket_callback c);
int websocket_send(struct websocket *s,
const uint8_t *data, uint16_t datalen);
int websocket_send_str(struct websocket *s,
const char *strptr);
void websocket_close(struct websocket *s);
int websocket_ping(struct websocket *s);
int websocket_queuelen(struct websocket *s);
#endif /* WEBSOCKET_H */

View file

@ -51,7 +51,7 @@
/* Maximum value for the freshness counter */ /* Maximum value for the freshness counter */
#define FRESHNESS_MAX 16 #define FRESHNESS_MAX 16
/* Statistics with no update in FRESHNESS_EXPIRATION_TIMEOUT is not fresh */ /* Statistics with no update in FRESHNESS_EXPIRATION_TIMEOUT is not fresh */
#define FRESHNESS_EXPIRATION_TIME (10 * 60 * CLOCK_SECOND) #define FRESHNESS_EXPIRATION_TIME (10 * 60 * (clock_time_t)CLOCK_SECOND)
/* EWMA (exponential moving average) used to maintain statistics over time */ /* EWMA (exponential moving average) used to maintain statistics over time */
#define EWMA_SCALE 100 #define EWMA_SCALE 100
@ -206,6 +206,6 @@ void
link_stats_init(void) link_stats_init(void)
{ {
nbr_table_register(link_stats, NULL); nbr_table_register(link_stats, NULL);
ctimer_set(&periodic_timer, 60 * CLOCK_SECOND * FRESHNESS_HALF_LIFE, ctimer_set(&periodic_timer, 60 * (clock_time_t)CLOCK_SECOND * FRESHNESS_HALF_LIFE,
periodic, NULL); periodic, NULL);
} }

View file

@ -52,6 +52,9 @@ const linkaddr_t linkaddr_null = { { 0, 0 } };
#if LINKADDR_SIZE == 8 #if LINKADDR_SIZE == 8
const linkaddr_t linkaddr_null = { { 0, 0, 0, 0, 0, 0, 0, 0 } }; const linkaddr_t linkaddr_null = { { 0, 0, 0, 0, 0, 0, 0, 0 } };
#endif /*LINKADDR_SIZE == 8*/ #endif /*LINKADDR_SIZE == 8*/
#if LINKADDR_SIZE == 6
const linkaddr_t linkaddr_null = { { 0, 0, 0, 0, 0, 0 } };
#endif /*LINKADDR_SIZE == 6*/
#endif /*LINKADDR_SIZE == 2*/ #endif /*LINKADDR_SIZE == 2*/

View file

@ -207,13 +207,13 @@ static int we_are_receiving_burst = 0;
#define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 2500 #define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 2500
#endif #endif
/* AFTER_ACK_DETECTECT_WAIT_TIME is the time to wait after a potential /* AFTER_ACK_DETECTED_WAIT_TIME is the time to wait after a potential
ACK packet has been detected until we can read it out from the ACK packet has been detected until we can read it out from the
radio. */ radio. */
#ifdef CONTIKIMAC_CONF_AFTER_ACK_DETECTECT_WAIT_TIME #ifdef CONTIKIMAC_CONF_AFTER_ACK_DETECTED_WAIT_TIME
#define AFTER_ACK_DETECTECT_WAIT_TIME CONTIKIMAC_CONF_AFTER_ACK_DETECTECT_WAIT_TIME #define AFTER_ACK_DETECTED_WAIT_TIME CONTIKIMAC_CONF_AFTER_ACK_DETECTED_WAIT_TIME
#else #else
#define AFTER_ACK_DETECTECT_WAIT_TIME RTIMER_ARCH_SECOND / 1500 #define AFTER_ACK_DETECTED_WAIT_TIME RTIMER_ARCH_SECOND / 1500
#endif #endif
/* MAX_PHASE_STROBE_TIME is the time that we transmit repeated packets /* MAX_PHASE_STROBE_TIME is the time that we transmit repeated packets
@ -766,7 +766,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
NETSTACK_RADIO.channel_clear() == 0)) { NETSTACK_RADIO.channel_clear() == 0)) {
uint8_t ackbuf[ACK_LEN]; uint8_t ackbuf[ACK_LEN];
wt = RTIMER_NOW(); wt = RTIMER_NOW();
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { } while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTED_WAIT_TIME)) { }
len = NETSTACK_RADIO.read(ackbuf, ACK_LEN); len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
if(len == ACK_LEN && seqno == ackbuf[ACK_LEN - 1]) { if(len == ACK_LEN && seqno == ackbuf[ACK_LEN - 1]) {
@ -878,6 +878,10 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
if(next != NULL) { if(next != NULL) {
packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1); packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
} }
#if !NETSTACK_CONF_BRIDGE_MODE
/* If NETSTACK_CONF_BRIDGE_MODE is set, assume PACKETBUF_ADDR_SENDER is already set. */
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#endif
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
if(NETSTACK_FRAMER.create() < 0) { if(NETSTACK_FRAMER.create() < 0) {
PRINTF("contikimac: framer failed\n"); PRINTF("contikimac: framer failed\n");

View file

@ -231,10 +231,12 @@ tx_done(int status, struct rdc_buf_list *q, struct neighbor_queue *n)
mac_callback_t sent; mac_callback_t sent;
struct qbuf_metadata *metadata; struct qbuf_metadata *metadata;
void *cptr; void *cptr;
uint8_t ntx;
metadata = (struct qbuf_metadata *)q->ptr; metadata = (struct qbuf_metadata *)q->ptr;
sent = metadata->sent; sent = metadata->sent;
cptr = metadata->cptr; cptr = metadata->cptr;
ntx = n->transmissions;
switch(status) { switch(status) {
case MAC_TX_OK: case MAC_TX_OK:
@ -251,7 +253,7 @@ tx_done(int status, struct rdc_buf_list *q, struct neighbor_queue *n)
} }
free_packet(n, q, status); free_packet(n, q, status);
mac_call_sent_callback(sent, cptr, status, n->transmissions); mac_call_sent_callback(sent, cptr, status, ntx);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void

View file

@ -146,24 +146,45 @@ frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest
} }
if(fcf->frame_version == FRAME802154_IEEE802154E_2012) { if(fcf->frame_version == FRAME802154_IEEE802154E_2012) {
/* IEEE 802.15.4e-2012, Table 2a, PAN ID Compression */ /*
if(!fcf->panid_compression) { * IEEE 802.15.4-2015
if(fcf->dest_addr_mode) { * Table 7-2, PAN ID Compression value for frame version 0b10
/* Use destination PAN ID if destination address is present */ */
if((fcf->dest_addr_mode == FRAME802154_NOADDR &&
fcf->src_addr_mode == FRAME802154_NOADDR &&
fcf->panid_compression == 1) ||
(fcf->dest_addr_mode != FRAME802154_NOADDR &&
fcf->src_addr_mode == FRAME802154_NOADDR &&
fcf->panid_compression == 0) ||
(fcf->dest_addr_mode == FRAME802154_LONGADDRMODE &&
fcf->src_addr_mode == FRAME802154_LONGADDRMODE &&
fcf->panid_compression == 0) ||
((fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
fcf->src_addr_mode != FRAME802154_NOADDR) ||
(fcf->dest_addr_mode != FRAME802154_NOADDR &&
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE)) ){
dest_pan_id = 1; dest_pan_id = 1;
} else if(fcf->src_addr_mode) { }
/* Only src address, include src PAN ID */
if(fcf->panid_compression == 0 &&
((fcf->dest_addr_mode == FRAME802154_NOADDR &&
fcf->src_addr_mode == FRAME802154_LONGADDRMODE) ||
(fcf->dest_addr_mode == FRAME802154_NOADDR &&
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE) ||
(fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE) ||
(fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
fcf->src_addr_mode == FRAME802154_LONGADDRMODE) ||
(fcf->dest_addr_mode == FRAME802154_LONGADDRMODE &&
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE))) {
src_pan_id = 1; src_pan_id = 1;
} }
} else if((fcf->dest_addr_mode == 0) && (fcf->src_addr_mode == 0)) {
/* No address included: PAN ID compression flag changes meaning */
dest_pan_id = 1;
}
} else { } else {
/* No PAN ID in ACK */ /* No PAN ID in ACK */
if(fcf->frame_type != FRAME802154_ACKFRAME) { if(fcf->frame_type != FRAME802154_ACKFRAME) {
if(!fcf->panid_compression && fcf->src_addr_mode & 3) { if(!fcf->panid_compression && (fcf->src_addr_mode & 3)) {
/* If compressed, don't inclue source PAN ID */ /* If compressed, don't include source PAN ID */
src_pan_id = 1; src_pan_id = 1;
} }
if(fcf->dest_addr_mode & 3) { if(fcf->dest_addr_mode & 3) {
@ -184,7 +205,7 @@ frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest
int int
frame802154_check_dest_panid(frame802154_t *frame) frame802154_check_dest_panid(frame802154_t *frame)
{ {
int has_dest_panid; int has_dest_panid = 0;
if(frame == NULL) { if(frame == NULL) {
return 0; return 0;
@ -283,7 +304,7 @@ field_len(frame802154_t *p, field_length_t *flen)
* up to the caller. */ * up to the caller. */
if(p->fcf.frame_version < FRAME802154_IEEE802154E_2012) { if(p->fcf.frame_version < FRAME802154_IEEE802154E_2012) {
/* Set PAN ID compression bit if src pan id matches dest pan id. */ /* Set PAN ID compression bit if src pan id matches dest pan id. */
if(p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 && if((p->fcf.dest_addr_mode & 3) && (p->fcf.src_addr_mode & 3) &&
p->src_pid == p->dest_pid) { p->src_pid == p->dest_pid) {
p->fcf.panid_compression = 1; p->fcf.panid_compression = 1;
} else { } else {
@ -341,6 +362,20 @@ frame802154_hdrlen(frame802154_t *p)
return 2 + flen.seqno_len + flen.dest_pid_len + flen.dest_addr_len + return 2 + flen.seqno_len + flen.dest_pid_len + flen.dest_addr_len +
flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len; flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
} }
void
frame802154_create_fcf(frame802154_fcf_t *fcf, uint8_t *buf)
{
buf[0] = (fcf->frame_type & 7) |
((fcf->security_enabled & 1) << 3) |
((fcf->frame_pending & 1) << 4) |
((fcf->ack_required & 1) << 5) |
((fcf->panid_compression & 1) << 6);
buf[1] = ((fcf->sequence_number_suppression & 1)) |
((fcf->ie_list_present & 1)) << 1 |
((fcf->dest_addr_mode & 3) << 2) |
((fcf->frame_version & 3) << 4) |
((fcf->src_addr_mode & 3) << 6);
}
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/** /**
* \brief Creates a frame for transmission over the air. This function is * \brief Creates a frame for transmission over the air. This function is
@ -367,17 +402,7 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
/* OK, now we have field lengths. Time to actually construct */ /* OK, now we have field lengths. Time to actually construct */
/* the outgoing frame, and store it in buf */ /* the outgoing frame, and store it in buf */
buf[0] = (p->fcf.frame_type & 7) | frame802154_create_fcf(&p->fcf, buf);
((p->fcf.security_enabled & 1) << 3) |
((p->fcf.frame_pending & 1) << 4) |
((p->fcf.ack_required & 1) << 5) |
((p->fcf.panid_compression & 1) << 6);
buf[1] = ((p->fcf.sequence_number_suppression & 1)) |
((p->fcf.ie_list_present & 1)) << 1 |
((p->fcf.dest_addr_mode & 3) << 2) |
((p->fcf.frame_version & 3) << 4) |
((p->fcf.src_addr_mode & 3) << 6);
pos = 2; pos = 2;
/* Sequence number */ /* Sequence number */
@ -439,6 +464,28 @@ frame802154_create(frame802154_t *p, uint8_t *buf)
return (int)pos; return (int)pos;
} }
void
frame802154_parse_fcf(uint8_t *data, frame802154_fcf_t *pfcf)
{
frame802154_fcf_t fcf;
/* decode the FCF */
fcf.frame_type = data[0] & 7;
fcf.security_enabled = (data[0] >> 3) & 1;
fcf.frame_pending = (data[0] >> 4) & 1;
fcf.ack_required = (data[0] >> 5) & 1;
fcf.panid_compression = (data[0] >> 6) & 1;
fcf.sequence_number_suppression = data[1] & 1;
fcf.ie_list_present = (data[1] >> 1) & 1;
fcf.dest_addr_mode = (data[1] >> 2) & 3;
fcf.frame_version = (data[1] >> 4) & 3;
fcf.src_addr_mode = (data[1] >> 6) & 3;
/* copy fcf */
memcpy(pfcf, &fcf, sizeof(frame802154_fcf_t));
}
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/** /**
* \brief Parses an input frame. Scans the input frame to find each * \brief Parses an input frame. Scans the input frame to find each
@ -468,19 +515,7 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
p = data; p = data;
/* decode the FCF */ /* decode the FCF */
fcf.frame_type = p[0] & 7; frame802154_parse_fcf(p, &fcf);
fcf.security_enabled = (p[0] >> 3) & 1;
fcf.frame_pending = (p[0] >> 4) & 1;
fcf.ack_required = (p[0] >> 5) & 1;
fcf.panid_compression = (p[0] >> 6) & 1;
fcf.sequence_number_suppression = p[1] & 1;
fcf.ie_list_present = (p[1] >> 1) & 1;
fcf.dest_addr_mode = (p[1] >> 2) & 3;
fcf.frame_version = (p[1] >> 4) & 3;
fcf.src_addr_mode = (p[1] >> 6) & 3;
/* copy fcf and seqNum */
memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t)); memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t));
p += 2; /* Skip first two bytes */ p += 2; /* Skip first two bytes */

View file

@ -207,8 +207,10 @@ typedef struct {
/* Prototypes */ /* Prototypes */
int frame802154_hdrlen(frame802154_t *p); int frame802154_hdrlen(frame802154_t *p);
void frame802154_create_fcf(frame802154_fcf_t *fcf, uint8_t *buf);
int frame802154_create(frame802154_t *p, uint8_t *buf); int frame802154_create(frame802154_t *p, uint8_t *buf);
int frame802154_parse(uint8_t *data, int length, frame802154_t *pf); int frame802154_parse(uint8_t *data, int length, frame802154_t *pf);
void frame802154_parse_fcf(uint8_t *data, frame802154_fcf_t *pfcf);
/* Get current PAN ID */ /* Get current PAN ID */
uint16_t frame802154_get_pan_id(void); uint16_t frame802154_get_pan_id(void);

View file

@ -70,7 +70,7 @@ struct ieee802154_ies {
uint16_t ie_mlme_len; uint16_t ie_mlme_len;
/* Payload Short MLME IEs */ /* Payload Short MLME IEs */
uint8_t ie_tsch_synchronization_offset; uint8_t ie_tsch_synchronization_offset;
struct asn_t ie_asn; struct tsch_asn_t ie_asn;
uint8_t ie_join_priority; uint8_t ie_join_priority;
uint8_t ie_tsch_timeslot_id; uint8_t ie_tsch_timeslot_id;
uint16_t ie_tsch_timeslot[tsch_ts_elements_count]; uint16_t ie_tsch_timeslot[tsch_ts_elements_count];

View file

@ -173,7 +173,8 @@ create_frame(int type, int do_create)
* Set up the source address using only the long address mode for * Set up the source address using only the long address mode for
* phase 1. * phase 1.
*/ */
linkaddr_copy((linkaddr_t *)&params.src_addr, &linkaddr_node_addr); linkaddr_copy((linkaddr_t *)&params.src_addr,
packetbuf_addr(PACKETBUF_ADDR_SENDER));
params.payload = packetbuf_dataptr(); params.payload = packetbuf_dataptr();
params.payload_len = packetbuf_datalen(); params.payload_len = packetbuf_datalen();

View file

@ -46,10 +46,10 @@
#include "net/rime/rimestats.h" #include "net/rime/rimestats.h"
#include <string.h> #include <string.h>
#if CONTIKI_TARGET_COOJA #if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
#include "lib/simEnvChange.h" #include "lib/simEnvChange.h"
#include "sys/cooja_mt.h" #include "sys/cooja_mt.h"
#endif /* CONTIKI_TARGET_COOJA */ #endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
#define DEBUG 0 #define DEBUG 0
#if DEBUG #if DEBUG
@ -158,10 +158,10 @@ send_one_packet(mac_callback_t sent, void *ptr)
wt = RTIMER_NOW(); wt = RTIMER_NOW();
watchdog_periodic(); watchdog_periodic();
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME)) { while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA #if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
simProcessRunValue = 1; simProcessRunValue = 1;
cooja_mt_yield(); cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */ #endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
} }
ret = MAC_TX_NOACK; ret = MAC_TX_NOACK;
@ -176,10 +176,10 @@ send_one_packet(mac_callback_t sent, void *ptr)
watchdog_periodic(); watchdog_periodic();
while(RTIMER_CLOCK_LT(RTIMER_NOW(), while(RTIMER_CLOCK_LT(RTIMER_NOW(),
wt + AFTER_ACK_DETECTED_WAIT_TIME)) { wt + AFTER_ACK_DETECTED_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA #if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
simProcessRunValue = 1; simProcessRunValue = 1;
cooja_mt_yield(); cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */ #endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
} }
} }

View file

@ -1,8 +1,8 @@
# IEEE 802.15.4e TSCH (TimeSlotted Channel Hopping) # IEEE 802.15.4-2015 TSCH and IETF 6TiSCH
## Overview ## Overview
TSCH is a MAC layer of the [IEEE 802.15.4e-2012 amendment][ieee802.15.4e-2012], Time Slotted Channel Hopping (TSCH) is a MAC layer of the [IEEE 802.15.4e-2012 amendment][ieee802.15.4e-2012],
currently being integrated as part of the new IEEE 802.15.4-2015. currently being integrated as part of the new IEEE 802.15.4-2015.
[6TiSCH][ietf-6tisch-wg] is an IETF Working Group focused on IPv6 over TSCH. [6TiSCH][ietf-6tisch-wg] is an IETF Working Group focused on IPv6 over TSCH.
This is a Contiki implementation of TSCH and the 6TiSCH so-called "minimal configuration", This is a Contiki implementation of TSCH and the 6TiSCH so-called "minimal configuration",
@ -13,7 +13,9 @@ It was developped by:
* Beshr Al Nahas, SICS (now Chalmers University), beshr@chalmers.se, github user: [beshrns](https://github.com/beshrns) * Beshr Al Nahas, SICS (now Chalmers University), beshr@chalmers.se, github user: [beshrns](https://github.com/beshrns)
* Atis Elsts, Univ. Bristol, atis.elsts@bristol.ac.uk, github user: [atiselsts](https://github.com/atiselsts) * Atis Elsts, Univ. Bristol, atis.elsts@bristol.ac.uk, github user: [atiselsts](https://github.com/atiselsts)
You can find an extensive evaluation of this implementation in our paper [*Orchestra: Robust Mesh Networks Through Autonomously Scheduled TSCH*](http://www.simonduquennoy.net/papers/duquennoy15orchestra.pdf), ACM SenSys'15.
This implementation is presented in depth and evaluated in our paper: [*TSCH and 6TiSCH for Contiki: Challenges, Design and Evaluation*](http://www.simonduquennoy.net/papers/duquennoy17tsch.pdf), IEEE DCOSS'17.
The scheduler Orchestra is detailled in [*Orchestra: Robust Mesh Networks Through Autonomously Scheduled TSCH*](http://www.simonduquennoy.net/papers/duquennoy15orchestra.pdf), ACM SenSys'15.
## Features ## Features
@ -27,7 +29,7 @@ This implementation includes:
* Standard TSCH link selection and slot operation (10ms slots by default) * Standard TSCH link selection and slot operation (10ms slots by default)
* Standard TSCH synchronization, including with ACK/NACK time correction Information Element * Standard TSCH synchronization, including with ACK/NACK time correction Information Element
* Standard TSCH queues and CSMA-CA mechanism * Standard TSCH queues and CSMA-CA mechanism
* Standard TSCH security * Standard TSCH and 6TiSCH security
* Standard 6TiSCH TSCH-RPL interaction (6TiSCH Minimal Configuration and Minimal Schedule) * Standard 6TiSCH TSCH-RPL interaction (6TiSCH Minimal Configuration and Minimal Schedule)
* A scheduling API to add/remove slotframes and links * A scheduling API to add/remove slotframes and links
* A system for logging from TSCH timeslot operation interrupt, with postponed printout * A system for logging from TSCH timeslot operation interrupt, with postponed printout
@ -42,6 +44,7 @@ It has been tested on the following platforms:
* Zolertia Zoul (`zoul`, tested on hardware) * Zolertia Zoul (`zoul`, tested on hardware)
* OpenMote-CC2538 (`openmote-cc2538`, tested on hardware) * OpenMote-CC2538 (`openmote-cc2538`, tested on hardware)
* CC2650 (`srf06-cc26xx`, tested on hardware) * CC2650 (`srf06-cc26xx`, tested on hardware)
* Cooja mote (`cooja`, tested with cooja)
This implementation was present at the ETSI Plugtest This implementation was present at the ETSI Plugtest
event in Prague in July 2015, and did successfully inter-operate with all event in Prague in July 2015, and did successfully inter-operate with all
@ -83,7 +86,7 @@ Orchestra is implemented in:
A simple TSCH+RPL example is included under `examples/ipv6/rpl-tsch`. A simple TSCH+RPL example is included under `examples/ipv6/rpl-tsch`.
To use TSCH, first make sure your platform supports it. To use TSCH, first make sure your platform supports it.
Currently, `jn516x`, `sky`, `z1`, `cc2538dk`, `zoul`, `openmote-cc2538`, and `srf06-cc26xx` are the supported platforms. Currently, `jn516x`, `sky`, `z1`, `cc2538dk`, `zoul`, `openmote-cc2538`, `srf06-cc26xx`, and `cooja` are the supported platforms.
To add your own, we refer the reader to the next section. To add your own, we refer the reader to the next section.
To add TSCH to your application, first include the TSCH module from your makefile with: To add TSCH to your application, first include the TSCH module from your makefile with:
@ -179,7 +182,7 @@ Instead, TSCH will poll the driver for incoming packets, from interrupt, exactly
TSCH will check when initializing (in `tsch_init`) that the radio driver supports all required features, namely: TSCH will check when initializing (in `tsch_init`) that the radio driver supports all required features, namely:
* get and set Rx mode (`RADIO_PARAM_RX_MODE`) as follows: * get and set Rx mode (`RADIO_PARAM_RX_MODE`) as follows:
* enable address filtering with `RADIO_RX_MODE_ADDRESS_FILTER` * disable address filtering with `RADIO_RX_MODE_ADDRESS_FILTER`
* disable auto-ack with `RADIO_RX_MODE_AUTOACK` * disable auto-ack with `RADIO_RX_MODE_AUTOACK`
* enable poll mode with `RADIO_RX_MODE_POLL_MODE` * enable poll mode with `RADIO_RX_MODE_POLL_MODE`
* get and set Tx mode (`RADIO_PARAM_TX_MODE`) as follows: * get and set Tx mode (`RADIO_PARAM_TX_MODE`) as follows:

View file

@ -38,8 +38,10 @@
* *
*/ */
#include "tsch-adaptive-timesync.h" #include "net/mac/tsch/tsch.h"
#include "tsch-log.h" #include "net/mac/tsch/tsch-conf.h"
#include "net/mac/tsch/tsch-adaptive-timesync.h"
#include "net/mac/tsch/tsch-log.h"
#include <stdio.h> #include <stdio.h>
#if TSCH_ADAPTIVE_TIMESYNC #if TSCH_ADAPTIVE_TIMESYNC
@ -72,6 +74,10 @@ timesync_entry_add(int32_t val, uint32_t time_delta)
buffer[pos] = val; buffer[pos] = val;
if(timesync_entry_count < NUM_TIMESYNC_ENTRIES) { if(timesync_entry_count < NUM_TIMESYNC_ENTRIES) {
timesync_entry_count++; timesync_entry_count++;
} else {
/* We now have accurate drift compensation.
* Increase keep-alive timeout. */
tsch_set_ka_timeout(TSCH_MAX_KEEPALIVE_TIMEOUT);
} }
pos = (pos + 1) % NUM_TIMESYNC_ENTRIES; pos = (pos + 1) % NUM_TIMESYNC_ENTRIES;

View file

@ -44,13 +44,13 @@
/************ Types ***********/ /************ Types ***********/
/* The ASN is an absolute slot number over 5 bytes. */ /* The ASN is an absolute slot number over 5 bytes. */
struct asn_t { struct tsch_asn_t {
uint32_t ls4b; /* least significant 4 bytes */ uint32_t ls4b; /* least significant 4 bytes */
uint8_t ms1b; /* most significant 1 byte */ uint8_t ms1b; /* most significant 1 byte */
}; };
/* For quick modulo operation on ASN */ /* For quick modulo operation on ASN */
struct asn_divisor_t { struct tsch_asn_divisor_t {
uint16_t val; /* Divisor value */ uint16_t val; /* Divisor value */
uint16_t asn_ms1b_remainder; /* Remainder of the operation 0x100000000 / val */ uint16_t asn_ms1b_remainder; /* Remainder of the operation 0x100000000 / val */
}; };
@ -58,38 +58,38 @@ struct asn_divisor_t {
/************ Macros **********/ /************ Macros **********/
/* Initialize ASN */ /* Initialize ASN */
#define ASN_INIT(asn, ms1b_, ls4b_) do { \ #define TSCH_ASN_INIT(asn, ms1b_, ls4b_) do { \
(asn).ms1b = (ms1b_); \ (asn).ms1b = (ms1b_); \
(asn).ls4b = (ls4b_); \ (asn).ls4b = (ls4b_); \
} while(0); } while(0);
/* Increment an ASN by inc (32 bits) */ /* Increment an ASN by inc (32 bits) */
#define ASN_INC(asn, inc) do { \ #define TSCH_ASN_INC(asn, inc) do { \
uint32_t new_ls4b = (asn).ls4b + (inc); \ uint32_t new_ls4b = (asn).ls4b + (inc); \
if(new_ls4b < (asn).ls4b) { (asn).ms1b++; } \ if(new_ls4b < (asn).ls4b) { (asn).ms1b++; } \
(asn).ls4b = new_ls4b; \ (asn).ls4b = new_ls4b; \
} while(0); } while(0);
/* Decrement an ASN by inc (32 bits) */ /* Decrement an ASN by inc (32 bits) */
#define ASN_DEC(asn, dec) do { \ #define TSCH_ASN_DEC(asn, dec) do { \
uint32_t new_ls4b = (asn).ls4b - (dec); \ uint32_t new_ls4b = (asn).ls4b - (dec); \
if(new_ls4b > (asn).ls4b) { (asn).ms1b--; } \ if(new_ls4b > (asn).ls4b) { (asn).ms1b--; } \
(asn).ls4b = new_ls4b; \ (asn).ls4b = new_ls4b; \
} while(0); } while(0);
/* Returns the 32-bit diff between asn1 and asn2 */ /* Returns the 32-bit diff between asn1 and asn2 */
#define ASN_DIFF(asn1, asn2) \ #define TSCH_ASN_DIFF(asn1, asn2) \
((asn1).ls4b - (asn2).ls4b) ((asn1).ls4b - (asn2).ls4b)
/* Initialize a struct asn_divisor_t */ /* Initialize a struct asn_divisor_t */
#define ASN_DIVISOR_INIT(div, val_) do { \ #define TSCH_ASN_DIVISOR_INIT(div, val_) do { \
(div).val = (val_); \ (div).val = (val_); \
(div).asn_ms1b_remainder = ((0xffffffff % (val_)) + 1) % (val_); \ (div).asn_ms1b_remainder = ((0xffffffff % (val_)) + 1) % (val_); \
} while(0); } while(0);
/* Returns the result (16 bits) of a modulo operation on ASN, /* Returns the result (16 bits) of a modulo operation on ASN,
* with divisor being a struct asn_divisor_t */ * with divisor being a struct asn_divisor_t */
#define ASN_MOD(asn, div) \ #define TSCH_ASN_MOD(asn, div) \
((uint16_t)((asn).ls4b % (div).val) \ ((uint16_t)((asn).ls4b % (div).val) \
+ (uint16_t)((asn).ms1b * (div).asn_ms1b_remainder % (div).val)) \ + (uint16_t)((asn).ms1b * (div).asn_ms1b_remainder % (div).val)) \
% (div).val % (div).val

View file

@ -174,7 +174,7 @@
#ifdef TSCH_CONF_ADAPTIVE_TIMESYNC #ifdef TSCH_CONF_ADAPTIVE_TIMESYNC
#define TSCH_ADAPTIVE_TIMESYNC TSCH_CONF_ADAPTIVE_TIMESYNC #define TSCH_ADAPTIVE_TIMESYNC TSCH_CONF_ADAPTIVE_TIMESYNC
#else #else
#define TSCH_ADAPTIVE_TIMESYNC 0 #define TSCH_ADAPTIVE_TIMESYNC 1
#endif #endif
/* HW frame filtering enabled */ /* HW frame filtering enabled */

View file

@ -132,7 +132,7 @@ tsch_log_prepare_add(void)
int log_index = ringbufindex_peek_put(&log_ringbuf); int log_index = ringbufindex_peek_put(&log_ringbuf);
if(log_index != -1) { if(log_index != -1) {
struct tsch_log_t *log = &log_array[log_index]; struct tsch_log_t *log = &log_array[log_index];
log->asn = current_asn; log->asn = tsch_current_asn;
log->link = current_link; log->link = current_link;
return log; return log;
} else { } else {

View file

@ -81,7 +81,7 @@ struct tsch_log_t {
tsch_log_rx, tsch_log_rx,
tsch_log_message tsch_log_message
} type; } type;
struct asn_t asn; struct tsch_asn_t asn;
struct tsch_link *link; struct tsch_link *link;
union { union {
char message[48]; char message[48];

View file

@ -66,7 +66,7 @@
/* Construct enhanced ACK packet and return ACK length */ /* Construct enhanced ACK packet and return ACK length */
int int
tsch_packet_create_eack(uint8_t *buf, int buf_size, tsch_packet_create_eack(uint8_t *buf, int buf_size,
linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack) const linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack)
{ {
int ret; int ret;
uint8_t curr_len = 0; uint8_t curr_len = 0;
@ -338,7 +338,7 @@ int
tsch_packet_update_eb(uint8_t *buf, int buf_size, uint8_t tsch_sync_ie_offset) tsch_packet_update_eb(uint8_t *buf, int buf_size, uint8_t tsch_sync_ie_offset)
{ {
struct ieee802154_ies ies; struct ieee802154_ies ies;
ies.ie_asn = current_asn; ies.ie_asn = tsch_current_asn;
ies.ie_join_priority = tsch_join_priority; ies.ie_join_priority = tsch_join_priority;
frame80215e_create_ie_tsch_synchronization(buf+tsch_sync_ie_offset, buf_size-tsch_sync_ie_offset, &ies); frame80215e_create_ie_tsch_synchronization(buf+tsch_sync_ie_offset, buf_size-tsch_sync_ie_offset, &ies);
return 1; return 1;

View file

@ -88,7 +88,7 @@ by default, useful in case of duplicate seqno */
/* Construct enhanced ACK packet and return ACK length */ /* Construct enhanced ACK packet and return ACK length */
int tsch_packet_create_eack(uint8_t *buf, int buf_size, int tsch_packet_create_eack(uint8_t *buf, int buf_size,
linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack); const linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack);
/* Parse enhanced ACK packet, extract drift and nack */ /* Parse enhanced ACK packet, extract drift and nack */
int tsch_packet_parse_eack(const uint8_t *buf, int buf_size, int tsch_packet_parse_eack(const uint8_t *buf, int buf_size,
uint8_t seqno, frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdr_len); uint8_t seqno, frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdr_len);

View file

@ -48,6 +48,10 @@
#include "net/linkaddr.h" #include "net/linkaddr.h"
#include "net/mac/tsch/tsch-asn.h" #include "net/mac/tsch/tsch-asn.h"
#include "net/mac/tsch/tsch-conf.h" #include "net/mac/tsch/tsch-conf.h"
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
/************ Types ***********/ /************ Types ***********/
@ -76,12 +80,12 @@ extern const linkaddr_t tsch_broadcast_address;
/* The address we use to identify EB queue */ /* The address we use to identify EB queue */
extern const linkaddr_t tsch_eb_address; extern const linkaddr_t tsch_eb_address;
/* The current Absolute Slot Number (ASN) */ /* The current Absolute Slot Number (ASN) */
extern struct asn_t current_asn; extern struct tsch_asn_t tsch_current_asn;
extern uint8_t tsch_join_priority; extern uint8_t tsch_join_priority;
extern struct tsch_link *current_link; extern struct tsch_link *current_link;
/* TSCH channel hopping sequence */ /* TSCH channel hopping sequence */
extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN]; extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
extern struct asn_divisor_t tsch_hopping_sequence_length; extern struct tsch_asn_divisor_t tsch_hopping_sequence_length;
/* TSCH timeslot timing (in rtimer ticks) */ /* TSCH timeslot timing (in rtimer ticks) */
extern rtimer_clock_t tsch_timing[tsch_ts_elements_count]; extern rtimer_clock_t tsch_timing[tsch_ts_elements_count];
@ -109,7 +113,14 @@ void tsch_disassociate(void);
#define TSCH_CLOCK_TO_SLOTS(c, timeslot_length) (TSCH_CLOCK_TO_TICKS(c) / timeslot_length) #define TSCH_CLOCK_TO_SLOTS(c, timeslot_length) (TSCH_CLOCK_TO_TICKS(c) / timeslot_length)
/* Wait for a condition with timeout t0+offset. */ /* Wait for a condition with timeout t0+offset. */
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) { \
simProcessRunValue = 1; \
cooja_mt_yield(); \
};
#else
#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \ #define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) ; while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) ;
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
#endif /* __TSCH_PRIVATE_H__ */ #endif /* __TSCH_PRIVATE_H__ */

View file

@ -163,6 +163,13 @@ tsch_queue_update_time_source(const linkaddr_t *new_addr)
/* Update time source */ /* Update time source */
if(new_time_src != NULL) { if(new_time_src != NULL) {
new_time_src->is_time_source = 1; new_time_src->is_time_source = 1;
/* (Re)set keep-alive timeout */
tsch_set_ka_timeout(TSCH_KEEPALIVE_TIMEOUT);
/* Start sending keepalives */
tsch_schedule_keepalive();
} else {
/* Stop sending keepalives */
tsch_set_ka_timeout(0);
} }
if(old_time_src != NULL) { if(old_time_src != NULL) {
@ -195,6 +202,7 @@ tsch_queue_flush_nbr_queue(struct tsch_neighbor *n)
/* Free packet queuebuf */ /* Free packet queuebuf */
tsch_queue_free_packet(p); tsch_queue_free_packet(p);
} }
PRINTF("TSCH-queue: packet is deleted packet=%p\n", p);
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -246,6 +254,8 @@ tsch_queue_add_packet(const linkaddr_t *addr, mac_callback_t sent, void *ptr)
/* Add to ringbuf (actual add committed through atomic operation) */ /* Add to ringbuf (actual add committed through atomic operation) */
n->tx_array[put_index] = p; n->tx_array[put_index] = p;
ringbufindex_put(&n->tx_ringbuf); ringbufindex_put(&n->tx_ringbuf);
PRINTF("TSCH-queue: packet is added put_index=%u, packet=%p\n",
put_index, p);
return p; return p;
} else { } else {
memb_free(&packet_memb, p); memb_free(&packet_memb, p);
@ -281,6 +291,7 @@ tsch_queue_remove_packet_from_queue(struct tsch_neighbor *n)
/* Get and remove packet from ringbuf (remove committed through an atomic operation */ /* Get and remove packet from ringbuf (remove committed through an atomic operation */
int16_t get_index = ringbufindex_get(&n->tx_ringbuf); int16_t get_index = ringbufindex_get(&n->tx_ringbuf);
if(get_index != -1) { if(get_index != -1) {
PRINTF("TSCH-queue: packet is removed, get_index=%u\n", get_index);
return n->tx_array[get_index]; return n->tx_array[get_index];
} else { } else {
return NULL; return NULL;

View file

@ -85,7 +85,7 @@ tsch_rpl_callback_new_dio_interval(uint8_t dio_interval)
tsch_set_coordinator(1); tsch_set_coordinator(1);
} }
/* Set EB period */ /* Set EB period */
tsch_set_eb_period(TSCH_EB_PERIOD); tsch_set_eb_period((CLOCK_SECOND * 1UL << dag->instance->dio_intcurrent) / 1000);
/* Set join priority based on RPL rank */ /* Set join priority based on RPL rank */
tsch_set_join_priority(DAG_RANK(dag->rank, dag->instance) - 1); tsch_set_join_priority(DAG_RANK(dag->rank, dag->instance) - 1);
} else { } else {

View file

@ -87,7 +87,7 @@ tsch_schedule_add_slotframe(uint16_t handle, uint16_t size)
if(sf != NULL) { if(sf != NULL) {
/* Initialize the slotframe */ /* Initialize the slotframe */
sf->handle = handle; sf->handle = handle;
ASN_DIVISOR_INIT(sf->size, size); TSCH_ASN_DIVISOR_INIT(sf->size, size);
LIST_STRUCT_INIT(sf, links_list); LIST_STRUCT_INIT(sf, links_list);
/* Add the slotframe to the global list */ /* Add the slotframe to the global list */
list_add(slotframe_list, sf); list_add(slotframe_list, sf);
@ -310,7 +310,7 @@ tsch_schedule_get_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t ti
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) */ /* Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) */
struct tsch_link * struct tsch_link *
tsch_schedule_get_next_active_link(struct asn_t *asn, uint16_t *time_offset, tsch_schedule_get_next_active_link(struct tsch_asn_t *asn, uint16_t *time_offset,
struct tsch_link **backup_link) struct tsch_link **backup_link)
{ {
uint16_t time_to_curr_best = 0; uint16_t time_to_curr_best = 0;
@ -324,7 +324,7 @@ tsch_schedule_get_next_active_link(struct asn_t *asn, uint16_t *time_offset,
/* For each slotframe, look for the earliest occurring link */ /* For each slotframe, look for the earliest occurring link */
while(sf != NULL) { while(sf != NULL) {
/* Get timeslot from ASN, given the slotframe length */ /* Get timeslot from ASN, given the slotframe length */
uint16_t timeslot = ASN_MOD(*asn, sf->size); uint16_t timeslot = TSCH_ASN_MOD(*asn, sf->size);
struct tsch_link *l = list_head(sf->links_list); struct tsch_link *l = list_head(sf->links_list);
while(l != NULL) { while(l != NULL) {
uint16_t time_to_timeslot = uint16_t time_to_timeslot =

View file

@ -119,7 +119,7 @@ struct tsch_slotframe {
uint16_t handle; uint16_t handle;
/* Number of timeslots in the slotframe. /* Number of timeslots in the slotframe.
* Stored as struct asn_divisor_t because we often need ASN%size */ * Stored as struct asn_divisor_t because we often need ASN%size */
struct asn_divisor_t size; struct tsch_asn_divisor_t size;
/* List of links belonging to this slotframe */ /* List of links belonging to this slotframe */
LIST_STRUCT(links_list); LIST_STRUCT(links_list);
}; };
@ -158,7 +158,7 @@ int tsch_schedule_remove_link(struct tsch_slotframe *slotframe, struct tsch_link
int tsch_schedule_remove_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t timeslot); int tsch_schedule_remove_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t timeslot);
/* Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) */ /* Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) */
struct tsch_link * tsch_schedule_get_next_active_link(struct asn_t *asn, uint16_t *time_offset, struct tsch_link * tsch_schedule_get_next_active_link(struct tsch_asn_t *asn, uint16_t *time_offset,
struct tsch_link **backup_link); struct tsch_link **backup_link);
#endif /* __TSCH_SCHEDULE_H__ */ #endif /* __TSCH_SCHEDULE_H__ */

View file

@ -73,7 +73,7 @@ static aes_key keys[] = {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
tsch_security_init_nonce(uint8_t *nonce, tsch_security_init_nonce(uint8_t *nonce,
const linkaddr_t *sender, struct asn_t *asn) const linkaddr_t *sender, struct tsch_asn_t *asn)
{ {
memcpy(nonce, sender, 8); memcpy(nonce, sender, 8);
nonce[8] = asn->ms1b; nonce[8] = asn->ms1b;
@ -120,11 +120,12 @@ tsch_security_check_level(const frame802154_t *frame)
required_key_index = TSCH_SECURITY_KEY_INDEX_OTHER; required_key_index = TSCH_SECURITY_KEY_INDEX_OTHER;
break; break;
} }
return frame->aux_hdr.security_control.security_level == required_security_level return ((frame->aux_hdr.security_control.security_level ==
&& frame->aux_hdr.key_index == required_key_index; required_security_level) &&
frame->aux_hdr.key_index == required_key_index);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int unsigned int
tsch_security_mic_len(const frame802154_t *frame) tsch_security_mic_len(const frame802154_t *frame)
{ {
if(frame != NULL && frame->fcf.security_enabled) { if(frame != NULL && frame->fcf.security_enabled) {
@ -134,9 +135,9 @@ tsch_security_mic_len(const frame802154_t *frame)
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int unsigned int
tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf, tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
int hdrlen, int datalen, struct asn_t *asn) int hdrlen, int datalen, struct tsch_asn_t *asn)
{ {
frame802154_t frame; frame802154_t frame;
uint8_t key_index = 0; uint8_t key_index = 0;
@ -159,7 +160,7 @@ tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
if(!frame.fcf.security_enabled) { if(!frame.fcf.security_enabled) {
/* Security is not enabled for this frame, we're done */ /* Security is not enabled for this frame, we're done */
return 1; return 0;
} }
/* Read security key index */ /* Read security key index */
@ -192,15 +193,15 @@ tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
CCM_STAR.aead(nonce, CCM_STAR.aead(nonce,
outbuf + a_len, m_len, outbuf + a_len, m_len,
outbuf, a_len, outbuf, a_len,
outbuf + hdrlen + datalen, mic_len, 1 outbuf + hdrlen + datalen, mic_len, 1);
);
return mic_len; return mic_len;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int unsigned int
tsch_security_parse_frame(const uint8_t *hdr, int hdrlen, int datalen, tsch_security_parse_frame(const uint8_t *hdr, int hdrlen, int datalen,
const frame802154_t *frame, const linkaddr_t *sender, struct asn_t *asn) const frame802154_t *frame, const linkaddr_t *sender,
struct tsch_asn_t *asn)
{ {
uint8_t generated_mic[16]; uint8_t generated_mic[16];
uint8_t key_index = 0; uint8_t key_index = 0;
@ -250,8 +251,7 @@ tsch_security_parse_frame(const uint8_t *hdr, int hdrlen, int datalen,
CCM_STAR.aead(nonce, CCM_STAR.aead(nonce,
(uint8_t *)hdr + a_len, m_len, (uint8_t *)hdr + a_len, m_len,
(uint8_t *)hdr, a_len, (uint8_t *)hdr, a_len,
generated_mic, mic_len, 0 generated_mic, mic_len, 0);
);
if(mic_len > 0 && memcmp(generated_mic, hdr + hdrlen + datalen, mic_len) != 0) { if(mic_len > 0 && memcmp(generated_mic, hdr + hdrlen + datalen, mic_len) != 0) {
return 0; return 0;

View file

@ -118,11 +118,28 @@
typedef uint8_t aes_key[16]; typedef uint8_t aes_key[16];
/********** Functions *********/ /********** Functions *********/
/**
* \brief Return MIC length
* \return The length of MIC (>= 0)
*/
unsigned int tsch_security_mic_len(const frame802154_t *frame);
int tsch_security_mic_len(const frame802154_t *frame); /**
int tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf, * \brief Protect a frame with encryption and/or MIC
int hdrlen, int datalen, struct asn_t *asn); * \return The length of a generated MIC (>= 0)
int tsch_security_parse_frame(const uint8_t *hdr, int hdrlen, int datalen, */
const frame802154_t *frame, const linkaddr_t *sender, struct asn_t *asn); unsigned int tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
int hdrlen, int datalen,
struct tsch_asn_t *asn);
/**
* \brief Parse and check a frame protected with encryption and/or MIC
* \retval 0 On error or security check failure (insecure frame)
* \retval 1 On success or no need for security check (good frame)
*/
unsigned int tsch_security_parse_frame(const uint8_t *hdr, int hdrlen,
int datalen, const frame802154_t *frame,
const linkaddr_t *sender,
struct tsch_asn_t *asn);
#endif /* __TSCH_SECURITY_H__ */ #endif /* __TSCH_SECURITY_H__ */

View file

@ -54,6 +54,10 @@
#include "net/mac/tsch/tsch-packet.h" #include "net/mac/tsch/tsch-packet.h"
#include "net/mac/tsch/tsch-security.h" #include "net/mac/tsch/tsch-security.h"
#include "net/mac/tsch/tsch-adaptive-timesync.h" #include "net/mac/tsch/tsch-adaptive-timesync.h"
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
#if TSCH_LOG_LEVEL >= 1 #if TSCH_LOG_LEVEL >= 1
#define DEBUG DEBUG_PRINT #define DEBUG DEBUG_PRINT
@ -104,7 +108,10 @@
#if RTIMER_SECOND < (32 * 1024) #if RTIMER_SECOND < (32 * 1024)
#error "TSCH: RTIMER_SECOND < (32 * 1024)" #error "TSCH: RTIMER_SECOND < (32 * 1024)"
#endif #endif
#if RTIMER_SECOND >= 200000 #if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
/* Use 0 usec guard time for Cooja Mote with a 1 MHz Rtimer*/
#define RTIMER_GUARD 0u
#elif RTIMER_SECOND >= 200000
#define RTIMER_GUARD (RTIMER_SECOND / 100000) #define RTIMER_GUARD (RTIMER_SECOND / 100000)
#else #else
#define RTIMER_GUARD 2u #define RTIMER_GUARD 2u
@ -132,7 +139,7 @@ struct ringbufindex input_ringbuf;
struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS]; struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
/* Last time we received Sync-IE (ACK or data packet from a time source) */ /* Last time we received Sync-IE (ACK or data packet from a time source) */
static struct asn_t last_sync_asn; static struct tsch_asn_t last_sync_asn;
/* A global lock for manipulating data structures safely from outside of interrupt */ /* A global lock for manipulating data structures safely from outside of interrupt */
static volatile int tsch_locked = 0; static volatile int tsch_locked = 0;
@ -200,7 +207,12 @@ tsch_get_lock(void)
if(tsch_in_slot_operation) { if(tsch_in_slot_operation) {
busy_wait = 1; busy_wait = 1;
busy_wait_time = RTIMER_NOW(); busy_wait_time = RTIMER_NOW();
while(tsch_in_slot_operation); while(tsch_in_slot_operation) {
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
simProcessRunValue = 1;
cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
}
busy_wait_time = RTIMER_NOW() - busy_wait_time; busy_wait_time = RTIMER_NOW() - busy_wait_time;
} }
if(!tsch_locked) { if(!tsch_locked) {
@ -236,9 +248,9 @@ tsch_release_lock(void)
/* Return channel from ASN and channel offset */ /* Return channel from ASN and channel offset */
uint8_t uint8_t
tsch_calculate_channel(struct asn_t *asn, uint8_t channel_offset) tsch_calculate_channel(struct tsch_asn_t *asn, uint8_t channel_offset)
{ {
uint16_t index_of_0 = ASN_MOD(*asn, tsch_hopping_sequence_length); uint16_t index_of_0 = TSCH_ASN_MOD(*asn, tsch_hopping_sequence_length);
uint16_t index_of_offset = (index_of_0 + channel_offset) % tsch_hopping_sequence_length.val; uint16_t index_of_offset = (index_of_0 + channel_offset) % tsch_hopping_sequence_length.val;
return tsch_hopping_sequence[index_of_offset]; return tsch_hopping_sequence[index_of_offset];
} }
@ -518,7 +530,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
* the original untouched. This is to allow for future retransmissions. */ * the original untouched. This is to allow for future retransmissions. */
int with_encryption = queuebuf_attr(current_packet->qb, PACKETBUF_ATTR_SECURITY_LEVEL) & 0x4; int with_encryption = queuebuf_attr(current_packet->qb, PACKETBUF_ATTR_SECURITY_LEVEL) & 0x4;
packet_len += tsch_security_secure_frame(packet, with_encryption ? encrypted_packet : packet, current_packet->header_len, packet_len += tsch_security_secure_frame(packet, with_encryption ? encrypted_packet : packet, current_packet->header_len,
packet_len - current_packet->header_len, &current_asn); packet_len - current_packet->header_len, &tsch_current_asn);
if(with_encryption) { if(with_encryption) {
packet = encrypted_packet; packet = encrypted_packet;
} }
@ -615,7 +627,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
#if LLSEC802154_ENABLED #if LLSEC802154_ENABLED
if(ack_len != 0) { if(ack_len != 0) {
if(!tsch_security_parse_frame(ackbuf, ack_hdrlen, ack_len - ack_hdrlen - tsch_security_mic_len(&frame), if(!tsch_security_parse_frame(ackbuf, ack_hdrlen, ack_len - ack_hdrlen - tsch_security_mic_len(&frame),
&frame, &current_neighbor->addr, &current_asn)) { &frame, &current_neighbor->addr, &tsch_current_asn)) {
TSCH_LOG_ADD(tsch_log_message, TSCH_LOG_ADD(tsch_log_message,
snprintf(log->message, sizeof(log->message), snprintf(log->message, sizeof(log->message),
"!failed to authenticate ACK")); "!failed to authenticate ACK"));
@ -632,7 +644,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
if(ack_len != 0) { if(ack_len != 0) {
if(is_time_source) { if(is_time_source) {
int32_t eack_time_correction = US_TO_RTIMERTICKS(ack_ies.ie_time_correction); int32_t eack_time_correction = US_TO_RTIMERTICKS(ack_ies.ie_time_correction);
int32_t since_last_timesync = ASN_DIFF(current_asn, last_sync_asn); int32_t since_last_timesync = TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn);
if(eack_time_correction > SYNC_IE_BOUND) { if(eack_time_correction > SYNC_IE_BOUND) {
drift_correction = SYNC_IE_BOUND; drift_correction = SYNC_IE_BOUND;
} else if(eack_time_correction < -SYNC_IE_BOUND) { } else if(eack_time_correction < -SYNC_IE_BOUND) {
@ -649,7 +661,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
is_drift_correction_used = 1; is_drift_correction_used = 1;
tsch_timesync_update(current_neighbor, since_last_timesync, drift_correction); tsch_timesync_update(current_neighbor, since_last_timesync, drift_correction);
/* Keep track of sync time */ /* Keep track of sync time */
last_sync_asn = current_asn; last_sync_asn = tsch_current_asn;
tsch_schedule_keepalive(); tsch_schedule_keepalive();
} }
mac_tx_status = MAC_TX_OK; mac_tx_status = MAC_TX_OK;
@ -781,7 +793,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
/* Read packet */ /* Read packet */
current_input->len = NETSTACK_RADIO.read((void *)current_input->payload, TSCH_PACKET_MAX_LEN); current_input->len = NETSTACK_RADIO.read((void *)current_input->payload, TSCH_PACKET_MAX_LEN);
NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi); NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi);
current_input->rx_asn = current_asn; current_input->rx_asn = tsch_current_asn;
current_input->rssi = (signed)radio_last_rssi; current_input->rssi = (signed)radio_last_rssi;
current_input->channel = current_channel; current_input->channel = current_channel;
header_len = frame802154_parse((uint8_t *)current_input->payload, current_input->len, &frame); header_len = frame802154_parse((uint8_t *)current_input->payload, current_input->len, &frame);
@ -801,7 +813,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
if(frame_valid) { if(frame_valid) {
if(tsch_security_parse_frame( if(tsch_security_parse_frame(
current_input->payload, header_len, current_input->len - header_len - tsch_security_mic_len(&frame), current_input->payload, header_len, current_input->len - header_len - tsch_security_mic_len(&frame),
&frame, &source_address, &current_asn)) { &frame, &source_address, &tsch_current_asn)) {
current_input->len -= tsch_security_mic_len(&frame); current_input->len -= tsch_security_mic_len(&frame);
} else { } else {
TSCH_LOG_ADD(tsch_log_message, TSCH_LOG_ADD(tsch_log_message,
@ -849,10 +861,11 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
ack_len = tsch_packet_create_eack(ack_buf, sizeof(ack_buf), ack_len = tsch_packet_create_eack(ack_buf, sizeof(ack_buf),
&source_address, frame.seq, (int16_t)RTIMERTICKS_TO_US(estimated_drift), do_nack); &source_address, frame.seq, (int16_t)RTIMERTICKS_TO_US(estimated_drift), do_nack);
if(ack_len > 0) {
#if LLSEC802154_ENABLED #if LLSEC802154_ENABLED
if(tsch_is_pan_secured) { if(tsch_is_pan_secured) {
/* Secure ACK frame. There is only header and header IEs, therefore data len == 0. */ /* Secure ACK frame. There is only header and header IEs, therefore data len == 0. */
ack_len += tsch_security_secure_frame(ack_buf, ack_buf, ack_len, 0, &current_asn); ack_len += tsch_security_secure_frame(ack_buf, ack_buf, ack_len, 0, &tsch_current_asn);
} }
#endif /* LLSEC802154_ENABLED */ #endif /* LLSEC802154_ENABLED */
@ -866,13 +879,14 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
NETSTACK_RADIO.transmit(ack_len); NETSTACK_RADIO.transmit(ack_len);
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT); tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
} }
}
/* If the sender is a time source, proceed to clock drift compensation */ /* If the sender is a time source, proceed to clock drift compensation */
n = tsch_queue_get_nbr(&source_address); n = tsch_queue_get_nbr(&source_address);
if(n != NULL && n->is_time_source) { if(n != NULL && n->is_time_source) {
int32_t since_last_timesync = ASN_DIFF(current_asn, last_sync_asn); int32_t since_last_timesync = TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn);
/* Keep track of last sync time */ /* Keep track of last sync time */
last_sync_asn = current_asn; last_sync_asn = tsch_current_asn;
/* Save estimated drift */ /* Save estimated drift */
drift_correction = -estimated_drift; drift_correction = -estimated_drift;
is_drift_correction_used = 1; is_drift_correction_used = 1;
@ -958,7 +972,7 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
is_active_slot = current_packet != NULL || (current_link->link_options & LINK_OPTION_RX); is_active_slot = current_packet != NULL || (current_link->link_options & LINK_OPTION_RX);
if(is_active_slot) { if(is_active_slot) {
/* Hop channel */ /* Hop channel */
current_channel = tsch_calculate_channel(&current_asn, current_link->channel_offset); current_channel = tsch_calculate_channel(&tsch_current_asn, current_link->channel_offset);
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel); NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel);
/* Turn the radio on already here if configured so; necessary for radios with slow startup */ /* Turn the radio on already here if configured so; necessary for radios with slow startup */
tsch_radio_on(TSCH_RADIO_CMD_ON_START_OF_TIMESLOT); tsch_radio_on(TSCH_RADIO_CMD_ON_START_OF_TIMESLOT);
@ -984,12 +998,12 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
/* End of slot operation, schedule next slot or resynchronize */ /* End of slot operation, schedule next slot or resynchronize */
/* Do we need to resynchronize? i.e., wait for EB again */ /* Do we need to resynchronize? i.e., wait for EB again */
if(!tsch_is_coordinator && (ASN_DIFF(current_asn, last_sync_asn) > if(!tsch_is_coordinator && (TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn) >
(100 * TSCH_CLOCK_TO_SLOTS(TSCH_DESYNC_THRESHOLD / 100, tsch_timing[tsch_ts_timeslot_length])))) { (100 * TSCH_CLOCK_TO_SLOTS(TSCH_DESYNC_THRESHOLD / 100, tsch_timing[tsch_ts_timeslot_length])))) {
TSCH_LOG_ADD(tsch_log_message, TSCH_LOG_ADD(tsch_log_message,
snprintf(log->message, sizeof(log->message), snprintf(log->message, sizeof(log->message),
"! leaving the network, last sync %u", "! leaving the network, last sync %u",
(unsigned)ASN_DIFF(current_asn, last_sync_asn)); (unsigned)TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn));
); );
last_timesource_neighbor = NULL; last_timesource_neighbor = NULL;
tsch_disassociate(); tsch_disassociate();
@ -1011,14 +1025,14 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
} }
/* Get next active link */ /* Get next active link */
current_link = tsch_schedule_get_next_active_link(&current_asn, &timeslot_diff, &backup_link); current_link = tsch_schedule_get_next_active_link(&tsch_current_asn, &timeslot_diff, &backup_link);
if(current_link == NULL) { if(current_link == NULL) {
/* There is no next link. Fall back to default /* There is no next link. Fall back to default
* behavior: wake up at the next slot. */ * behavior: wake up at the next slot. */
timeslot_diff = 1; timeslot_diff = 1;
} }
/* Update ASN */ /* Update ASN */
ASN_INC(current_asn, timeslot_diff); TSCH_ASN_INC(tsch_current_asn, timeslot_diff);
/* Time to next wake up */ /* Time to next wake up */
time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length] + drift_correction; time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length] + drift_correction;
drift_correction = 0; drift_correction = 0;
@ -1049,14 +1063,14 @@ tsch_slot_operation_start(void)
do { do {
uint16_t timeslot_diff; uint16_t timeslot_diff;
/* Get next active link */ /* Get next active link */
current_link = tsch_schedule_get_next_active_link(&current_asn, &timeslot_diff, &backup_link); current_link = tsch_schedule_get_next_active_link(&tsch_current_asn, &timeslot_diff, &backup_link);
if(current_link == NULL) { if(current_link == NULL) {
/* There is no next link. Fall back to default /* There is no next link. Fall back to default
* behavior: wake up at the next slot. */ * behavior: wake up at the next slot. */
timeslot_diff = 1; timeslot_diff = 1;
} }
/* Update ASN */ /* Update ASN */
ASN_INC(current_asn, timeslot_diff); TSCH_ASN_INC(tsch_current_asn, timeslot_diff);
/* Time to next wake up */ /* Time to next wake up */
time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length]; time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length];
/* Update current slot start */ /* Update current slot start */
@ -1068,11 +1082,11 @@ tsch_slot_operation_start(void)
/* Start actual slot operation */ /* Start actual slot operation */
void void
tsch_slot_operation_sync(rtimer_clock_t next_slot_start, tsch_slot_operation_sync(rtimer_clock_t next_slot_start,
struct asn_t *next_slot_asn) struct tsch_asn_t *next_slot_asn)
{ {
current_slot_start = next_slot_start; current_slot_start = next_slot_start;
current_asn = *next_slot_asn; tsch_current_asn = *next_slot_asn;
last_sync_asn = current_asn; last_sync_asn = tsch_current_asn;
current_link = NULL; current_link = NULL;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -87,7 +87,7 @@ int TSCH_CALLBACK_DO_NACK(struct tsch_link *link, linkaddr_t *src, linkaddr_t *d
/* Stores data about an incoming packet */ /* Stores data about an incoming packet */
struct input_packet { struct input_packet {
uint8_t payload[TSCH_PACKET_MAX_LEN]; /* Packet payload */ uint8_t payload[TSCH_PACKET_MAX_LEN]; /* Packet payload */
struct asn_t rx_asn; /* ASN when the packet was received */ struct tsch_asn_t rx_asn; /* ASN when the packet was received */
int len; /* Packet len */ int len; /* Packet len */
int16_t rssi; /* RSSI for this packet */ int16_t rssi; /* RSSI for this packet */
uint8_t channel; /* Channel we received the packet on */ uint8_t channel; /* Channel we received the packet on */
@ -107,7 +107,7 @@ extern struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
/********** Functions *********/ /********** Functions *********/
/* Returns a 802.15.4 channel from an ASN and channel offset */ /* Returns a 802.15.4 channel from an ASN and channel offset */
uint8_t tsch_calculate_channel(struct asn_t *asn, uint8_t channel_offset); uint8_t tsch_calculate_channel(struct tsch_asn_t *asn, uint8_t channel_offset);
/* Is TSCH locked? */ /* Is TSCH locked? */
int tsch_is_locked(void); int tsch_is_locked(void);
/* Lock TSCH (no link operation) */ /* Lock TSCH (no link operation) */
@ -117,7 +117,7 @@ void tsch_release_lock(void);
/* Set global time before starting slot operation, /* Set global time before starting slot operation,
* with a rtimer time and an ASN */ * with a rtimer time and an ASN */
void tsch_slot_operation_sync(rtimer_clock_t next_slot_start, void tsch_slot_operation_sync(rtimer_clock_t next_slot_start,
struct asn_t *next_slot_asn); struct tsch_asn_t *next_slot_asn);
/* Start actual slot operation */ /* Start actual slot operation */
void tsch_slot_operation_start(void); void tsch_slot_operation_start(void);

View file

@ -90,7 +90,7 @@ NBR_TABLE(struct eb_stat, eb_stats);
/* TSCH channel hopping sequence */ /* TSCH channel hopping sequence */
uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN]; uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
struct asn_divisor_t tsch_hopping_sequence_length; struct tsch_asn_divisor_t tsch_hopping_sequence_length;
/* Default TSCH timeslot timing (in micro-second) */ /* Default TSCH timeslot timing (in micro-second) */
static const uint16_t tsch_default_timing_us[tsch_ts_elements_count] = { static const uint16_t tsch_default_timing_us[tsch_ts_elements_count] = {
@ -131,7 +131,7 @@ int tsch_is_associated = 0;
/* Is the PAN running link-layer security? */ /* Is the PAN running link-layer security? */
int tsch_is_pan_secured = LLSEC802154_ENABLED; int tsch_is_pan_secured = LLSEC802154_ENABLED;
/* The current Absolute Slot Number (ASN) */ /* The current Absolute Slot Number (ASN) */
struct asn_t current_asn; struct tsch_asn_t tsch_current_asn;
/* Device rank or join priority: /* Device rank or join priority:
* For PAN coordinator: 0 -- lower is better */ * For PAN coordinator: 0 -- lower is better */
uint8_t tsch_join_priority; uint8_t tsch_join_priority;
@ -139,6 +139,8 @@ uint8_t tsch_join_priority;
static uint8_t tsch_packet_seqno = 0; static uint8_t tsch_packet_seqno = 0;
/* Current period for EB output */ /* Current period for EB output */
static clock_time_t tsch_current_eb_period; static clock_time_t tsch_current_eb_period;
/* Current period for keepalive output */
static clock_time_t tsch_current_ka_timeout;
/* timer for sending keepalive messages */ /* timer for sending keepalive messages */
static struct ctimer keepalive_timer; static struct ctimer keepalive_timer;
@ -175,9 +177,15 @@ tsch_set_join_priority(uint8_t jp)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
tsch_set_ka_timeout(uint32_t timeout)
{
tsch_current_ka_timeout = timeout;
}
/*---------------------------------------------------------------------------*/
void
tsch_set_eb_period(uint32_t period) tsch_set_eb_period(uint32_t period)
{ {
tsch_current_eb_period = period; tsch_current_eb_period = MIN(period, TSCH_MAX_EB_PERIOD);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
@ -194,7 +202,7 @@ tsch_reset(void)
tsch_queue_update_time_source(NULL); tsch_queue_update_time_source(NULL);
/* Initialize global variables */ /* Initialize global variables */
tsch_join_priority = 0xff; tsch_join_priority = 0xff;
ASN_INIT(current_asn, 0, 0); TSCH_ASN_INIT(tsch_current_asn, 0, 0);
current_link = NULL; current_link = NULL;
/* Reset timeslot timing to defaults */ /* Reset timeslot timing to defaults */
for(i = 0; i < tsch_ts_elements_count; i++) { for(i = 0; i < tsch_ts_elements_count; i++) {
@ -244,10 +252,10 @@ keepalive_send()
void void
tsch_schedule_keepalive() tsch_schedule_keepalive()
{ {
/* Pick a delay in the range [TSCH_KEEPALIVE_TIMEOUT*0.9, TSCH_KEEPALIVE_TIMEOUT[ */ /* Pick a delay in the range [tsch_current_ka_timeout*0.9, tsch_current_ka_timeout[ */
if(!tsch_is_coordinator && tsch_is_associated) { if(!tsch_is_coordinator && tsch_is_associated && tsch_current_ka_timeout > 0) {
unsigned long delay = (TSCH_KEEPALIVE_TIMEOUT - TSCH_KEEPALIVE_TIMEOUT / 10) unsigned long delay = (tsch_current_ka_timeout - tsch_current_ka_timeout / 10)
+ random_rand() % (TSCH_KEEPALIVE_TIMEOUT / 10); + random_rand() % (tsch_current_ka_timeout / 10);
ctimer_set(&keepalive_timer, delay, keepalive_send, NULL); ctimer_set(&keepalive_timer, delay, keepalive_send, NULL);
} }
} }
@ -302,7 +310,7 @@ eb_input(struct input_packet *current_input)
/* Did the EB come from our time source? */ /* Did the EB come from our time source? */
if(n != NULL && linkaddr_cmp((linkaddr_t *)&frame.src_addr, &n->addr)) { if(n != NULL && linkaddr_cmp((linkaddr_t *)&frame.src_addr, &n->addr)) {
/* Check for ASN drift */ /* Check for ASN drift */
int32_t asn_diff = ASN_DIFF(current_input->rx_asn, eb_ies.ie_asn); int32_t asn_diff = TSCH_ASN_DIFF(current_input->rx_asn, eb_ies.ie_asn);
if(asn_diff != 0) { if(asn_diff != 0) {
/* We disagree with our time source's ASN -- leave the network */ /* We disagree with our time source's ASN -- leave the network */
PRINTF("TSCH:! ASN drifted by %ld, leaving the network\n", asn_diff); PRINTF("TSCH:! ASN drifted by %ld, leaving the network\n", asn_diff);
@ -393,7 +401,7 @@ tsch_start_coordinator(void)
frame802154_set_pan_id(IEEE802154_PANID); frame802154_set_pan_id(IEEE802154_PANID);
/* Initialize hopping sequence as default */ /* Initialize hopping sequence as default */
memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)); memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)); TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
#if TSCH_SCHEDULE_WITH_6TISCH_MINIMAL #if TSCH_SCHEDULE_WITH_6TISCH_MINIMAL
tsch_schedule_create_minimal(); tsch_schedule_create_minimal();
#endif #endif
@ -402,10 +410,10 @@ tsch_start_coordinator(void)
tsch_join_priority = 0; tsch_join_priority = 0;
PRINTF("TSCH: starting as coordinator, PAN ID %x, asn-%x.%lx\n", PRINTF("TSCH: starting as coordinator, PAN ID %x, asn-%x.%lx\n",
frame802154_get_pan_id(), current_asn.ms1b, current_asn.ls4b); frame802154_get_pan_id(), tsch_current_asn.ms1b, tsch_current_asn.ls4b);
/* Start slot operation */ /* Start slot operation */
tsch_slot_operation_sync(RTIMER_NOW(), &current_asn); tsch_slot_operation_sync(RTIMER_NOW(), &tsch_current_asn);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Leave the TSCH network */ /* Leave the TSCH network */
@ -434,7 +442,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
return 0; return 0;
} }
current_asn = ies.ie_asn; tsch_current_asn = ies.ie_asn;
tsch_join_priority = ies.ie_join_priority + 1; tsch_join_priority = ies.ie_join_priority + 1;
#if TSCH_JOIN_SECURED_ONLY #if TSCH_JOIN_SECURED_ONLY
@ -447,7 +455,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
#if LLSEC802154_ENABLED #if LLSEC802154_ENABLED
if(!tsch_security_parse_frame(input_eb->payload, hdrlen, if(!tsch_security_parse_frame(input_eb->payload, hdrlen,
input_eb->len - hdrlen - tsch_security_mic_len(&frame), input_eb->len - hdrlen - tsch_security_mic_len(&frame),
&frame, (linkaddr_t*)&frame.src_addr, &current_asn)) { &frame, (linkaddr_t*)&frame.src_addr, &tsch_current_asn)) {
PRINTF("TSCH:! parse_eb: failed to authenticate\n"); PRINTF("TSCH:! parse_eb: failed to authenticate\n");
return 0; return 0;
} }
@ -486,11 +494,11 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
/* TSCH hopping sequence */ /* TSCH hopping sequence */
if(ies.ie_channel_hopping_sequence_id == 0) { if(ies.ie_channel_hopping_sequence_id == 0) {
memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)); memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)); TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
} else { } else {
if(ies.ie_hopping_sequence_len <= sizeof(tsch_hopping_sequence)) { if(ies.ie_hopping_sequence_len <= sizeof(tsch_hopping_sequence)) {
memcpy(tsch_hopping_sequence, ies.ie_hopping_sequence_list, ies.ie_hopping_sequence_len); memcpy(tsch_hopping_sequence, ies.ie_hopping_sequence_list, ies.ie_hopping_sequence_len);
ASN_DIVISOR_INIT(tsch_hopping_sequence_length, ies.ie_hopping_sequence_len); TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, ies.ie_hopping_sequence_len);
} else { } else {
PRINTF("TSCH:! parse_eb: hopping sequence too long (%u)\n", ies.ie_hopping_sequence_len); PRINTF("TSCH:! parse_eb: hopping sequence too long (%u)\n", ies.ie_hopping_sequence_len);
return 0; return 0;
@ -501,10 +509,10 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
/* Divide by 4k and multiply again to avoid integer overflow */ /* Divide by 4k and multiply again to avoid integer overflow */
uint32_t expected_asn = 4096 * TSCH_CLOCK_TO_SLOTS(clock_time() / 4096, tsch_timing_timeslot_length); /* Expected ASN based on our current time*/ uint32_t expected_asn = 4096 * TSCH_CLOCK_TO_SLOTS(clock_time() / 4096, tsch_timing_timeslot_length); /* Expected ASN based on our current time*/
int32_t asn_threshold = TSCH_CHECK_TIME_AT_ASSOCIATION * 60ul * TSCH_CLOCK_TO_SLOTS(CLOCK_SECOND, tsch_timing_timeslot_length); int32_t asn_threshold = TSCH_CHECK_TIME_AT_ASSOCIATION * 60ul * TSCH_CLOCK_TO_SLOTS(CLOCK_SECOND, tsch_timing_timeslot_length);
int32_t asn_diff = (int32_t)current_asn.ls4b - expected_asn; int32_t asn_diff = (int32_t)tsch_current_asn.ls4b - expected_asn;
if(asn_diff > asn_threshold) { if(asn_diff > asn_threshold) {
PRINTF("TSCH:! EB ASN rejected %lx %lx %ld\n", PRINTF("TSCH:! EB ASN rejected %lx %lx %ld\n",
current_asn.ls4b, expected_asn, asn_diff); tsch_current_asn.ls4b, expected_asn, asn_diff);
return 0; return 0;
} }
#endif #endif
@ -554,7 +562,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
frame802154_set_pan_id(frame.src_pid); frame802154_set_pan_id(frame.src_pid);
/* Synchronize on EB */ /* Synchronize on EB */
tsch_slot_operation_sync(timestamp - tsch_timing[tsch_ts_tx_offset], &current_asn); tsch_slot_operation_sync(timestamp - tsch_timing[tsch_ts_tx_offset], &tsch_current_asn);
/* Update global flags */ /* Update global flags */
tsch_is_associated = 1; tsch_is_associated = 1;
@ -570,7 +578,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
PRINTF("TSCH: association done, sec %u, PAN ID %x, asn-%x.%lx, jp %u, timeslot id %u, hopping id %u, slotframe len %u with %u links, from ", PRINTF("TSCH: association done, sec %u, PAN ID %x, asn-%x.%lx, jp %u, timeslot id %u, hopping id %u, slotframe len %u with %u links, from ",
tsch_is_pan_secured, tsch_is_pan_secured,
frame.src_pid, frame.src_pid,
current_asn.ms1b, current_asn.ls4b, tsch_join_priority, tsch_current_asn.ms1b, tsch_current_asn.ls4b, tsch_join_priority,
ies.ie_tsch_timeslot_id, ies.ie_tsch_timeslot_id,
ies.ie_channel_hopping_sequence_id, ies.ie_channel_hopping_sequence_id,
ies.ie_tsch_slotframe_and_link.slotframe_size, ies.ie_tsch_slotframe_and_link.slotframe_size,
@ -601,7 +609,7 @@ PT_THREAD(tsch_scan(struct pt *pt))
/* Time when we started scanning on current_channel */ /* Time when we started scanning on current_channel */
static clock_time_t current_channel_since; static clock_time_t current_channel_since;
ASN_INIT(current_asn, 0, 0); TSCH_ASN_INIT(tsch_current_asn, 0, 0);
etimer_set(&scan_timer, CLOCK_SECOND / TSCH_ASSOCIATION_POLL_FREQUENCY); etimer_set(&scan_timer, CLOCK_SECOND / TSCH_ASSOCIATION_POLL_FREQUENCY);
current_channel_since = clock_time(); current_channel_since = clock_time();
@ -741,7 +749,7 @@ PROCESS_THREAD(tsch_send_eb_process, ev, data)
#endif /* LLSEC802154_ENABLED */ #endif /* LLSEC802154_ENABLED */
eb_len = tsch_packet_create_eb(packetbuf_dataptr(), PACKETBUF_SIZE, eb_len = tsch_packet_create_eb(packetbuf_dataptr(), PACKETBUF_SIZE,
&hdr_len, &tsch_sync_ie_offset); &hdr_len, &tsch_sync_ie_offset);
if(eb_len != 0) { if(eb_len > 0) {
struct tsch_packet *p; struct tsch_packet *p;
packetbuf_set_datalen(eb_len); packetbuf_set_datalen(eb_len);
/* Enqueue EB packet */ /* Enqueue EB packet */
@ -902,6 +910,15 @@ send_packet(mac_callback_t sent, void *ptr)
packet_count_before = tsch_queue_packet_count(addr); packet_count_before = tsch_queue_packet_count(addr);
#if !NETSTACK_CONF_BRIDGE_MODE
/*
* In the Contiki stack, the source address of a frame is set at the RDC
* layer. Since TSCH doesn't use any RDC protocol and bypasses the layer to
* transmit a frame, it should set the source address by itself.
*/
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#endif
if((hdr_len = NETSTACK_FRAMER.create()) < 0) { if((hdr_len = NETSTACK_FRAMER.create()) < 0) {
PRINTF("TSCH:! can't send packet due to framer error\n"); PRINTF("TSCH:! can't send packet due to framer error\n");
ret = MAC_TX_ERR; ret = MAC_TX_ERR;

View file

@ -49,18 +49,33 @@
#define TSCH_KEEPALIVE_TIMEOUT (12 * CLOCK_SECOND) #define TSCH_KEEPALIVE_TIMEOUT (12 * CLOCK_SECOND)
#endif #endif
/* With TSCH_ADAPTIVE_TIMESYNC enabled: keep-alive timeout used after reaching
* accurate drift compensation. */
#ifdef TSCH_CONF_MAX_KEEPALIVE_TIMEOUT
#define TSCH_MAX_KEEPALIVE_TIMEOUT TSCH_CONF_MAX_KEEPALIVE_TIMEOUT
#else
#define TSCH_MAX_KEEPALIVE_TIMEOUT (60 * CLOCK_SECOND)
#endif
/* Max time without synchronization before leaving the PAN */ /* Max time without synchronization before leaving the PAN */
#ifdef TSCH_CONF_DESYNC_THRESHOLD #ifdef TSCH_CONF_DESYNC_THRESHOLD
#define TSCH_DESYNC_THRESHOLD TSCH_CONF_DESYNC_THRESHOLD #define TSCH_DESYNC_THRESHOLD TSCH_CONF_DESYNC_THRESHOLD
#else #else
#define TSCH_DESYNC_THRESHOLD (4 * TSCH_KEEPALIVE_TIMEOUT) #define TSCH_DESYNC_THRESHOLD (2 * TSCH_MAX_KEEPALIVE_TIMEOUT)
#endif #endif
/* Period between two consecutive EBs */ /* Period between two consecutive EBs */
#ifdef TSCH_CONF_EB_PERIOD #ifdef TSCH_CONF_EB_PERIOD
#define TSCH_EB_PERIOD TSCH_CONF_EB_PERIOD #define TSCH_EB_PERIOD TSCH_CONF_EB_PERIOD
#else #else
#define TSCH_EB_PERIOD (4 * CLOCK_SECOND) #define TSCH_EB_PERIOD (16 * CLOCK_SECOND)
#endif
/* Max Period between two consecutive EBs */
#ifdef TSCH_CONF_MAX_EB_PERIOD
#define TSCH_MAX_EB_PERIOD TSCH_CONF_MAX_EB_PERIOD
#else
#define TSCH_MAX_EB_PERIOD (50 * CLOCK_SECOND)
#endif #endif
/* Max acceptable join priority */ /* Max acceptable join priority */
@ -157,8 +172,10 @@ extern const struct mac_driver tschmac_driver;
/* The the TSCH join priority */ /* The the TSCH join priority */
void tsch_set_join_priority(uint8_t jp); void tsch_set_join_priority(uint8_t jp);
/* The the period at which EBs are sent */ /* The period at which EBs are sent */
void tsch_set_eb_period(uint32_t period); void tsch_set_eb_period(uint32_t period);
/* The keep-alive timeout */
void tsch_set_ka_timeout(uint32_t timeout);
/* Set the node as PAN coordinator */ /* Set the node as PAN coordinator */
void tsch_set_coordinator(int enable); void tsch_set_coordinator(int enable);
/* Set the pan as secured or not */ /* Set the pan as secured or not */

View file

@ -184,6 +184,12 @@ packetbuf_totlen(void)
return packetbuf_hdrlen() + packetbuf_datalen(); return packetbuf_hdrlen() + packetbuf_datalen();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uint16_t
packetbuf_remaininglen(void)
{
return PACKETBUF_SIZE - packetbuf_totlen();
}
/*---------------------------------------------------------------------------*/
void void
packetbuf_attr_clear(void) packetbuf_attr_clear(void)
{ {

View file

@ -123,6 +123,13 @@ uint16_t packetbuf_datalen(void);
*/ */
uint16_t packetbuf_totlen(void); uint16_t packetbuf_totlen(void);
/**
* \brief Get the total length of the remaining space in the packetbuf
* \return Length of the remaining space in the packetbuf
*
*/
uint16_t packetbuf_remaininglen(void);
/** /**
* \brief Set the length of the data in the packetbuf * \brief Set the length of the data in the packetbuf
* \param len The length of the data * \param len The length of the data

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