iotjs update 2018.05.03 accepted/tizen/4.0/unified/20180508.071454 accepted/tizen/unified/20180508.071441 submit/tizen/20180503.130743 submit/tizen_4.0/20180503.130810
authorHaesik Jun <haesik.jun@samsung.com>
Thu, 3 May 2018 12:54:46 +0000 (21:54 +0900)
committerHaesik Jun <haesik.jun@samsung.com>
Thu, 3 May 2018 12:54:46 +0000 (21:54 +0900)
github commitid: 94115221b0cdfa40060b660fd34cbe3a3607e634

Change-Id: I60f89c60ad68e9939d6c49baef0d499ba171ef59
Signed-off-by: Haesik Jun <haesik.jun@samsung.com>
42 files changed:
.travis.yml
CMakeLists.txt
README.md
cmake/iotjs.cmake
config/tizen/packaging/iotjs.spec
config/tizen/patch4tizenorg.sh [new file with mode: 0755]
config/tizen/template/IoTjsApp/project/src/main.c
docs/api/IoT.js-API-GPIO.md
docs/api/IoT.js-API-I2C.md
docs/api/IoT.js-API-MQTT.md [new file with mode: 0644]
docs/api/IoT.js-API-Module.md
docs/api/IoT.js-API-Process.md
docs/api/IoT.js-API-SPI.md
docs/api/IoT.js-API-UART.md
docs/targets/tizen/SystemIO-Pin-Information-Tizen.md [new file with mode: 0644]
packaging/iotjs.spec
samples/bridge_sample/src/iotjs_bridge_sample.c
samples/tizen-bridge-native/tizen_bridge_native.c [new file with mode: 0644]
samples/tizen-bridge-native/tizen_bridge_native.js [new file with mode: 0644]
sonar-project.properties [new file with mode: 0644]
src/iotjs_magic_strings.h
src/iotjs_util.c
src/iotjs_util.h
src/js/iotjs.js
src/js/module.js
src/js/mqtt.js [new file with mode: 0644]
src/js/tizen.js
src/modules.json
src/modules/iotjs_module_bridge.c
src/modules/iotjs_module_i2c.c
src/modules/iotjs_module_mqtt.c [new file with mode: 0644]
src/modules/iotjs_module_mqtt.h [new file with mode: 0644]
src/modules/iotjs_module_process.c
src/modules/tizen/iotjs_module_tizen-tizen.c
src/platform/tizen/iotjs_tizen_service_app.c
src/platform/tizen/iotjs_tizen_service_app.h
test/run_pass/issue/issue-1351.js [deleted file]
test/run_pass/test_process_readsource.js [deleted file]
test/testsets.json
test/tools/systemio_common.js
tools/build.py
tools/check_sonarqube.sh [new file with mode: 0755]

index 8353bff99d9ad0422284724cddcaf636c8c4ec50..2916ac0117008531b97e6c1832f25051f26f15c6 100644 (file)
@@ -70,4 +70,15 @@ matrix:
           build_command: "tools/travis_script.py"
           branch_pattern: master
       env: OPTS="coverity"
+    - os: linux
+      addons:
+        sonarcloud:
+          organization: "samsung-iotjs"
+          token:
+            secure: "u9HWNQNhAqQQdgl3yldKcQVH8plMQRwIdpzjsM4j3GBC4Wrh9u8guLJB3o003i0UsyaGg2knYFdLgOmEsgcvXAo2aIUyzf9CfK9RLRw5RtIuPMpmR7UjHdlf+QfCF+nY+BB2j0nAiWnxHve95du7sZflNxi+eNJJzquyBh1Wm8eqwoiRpCgiDzjRDEAUoz0FWMNny/x5545E970jpQ2bjHGx98tCMUO8ikINeL8sC99sumffaFONG8GVpwLjc8McfQfYpWbk0e0OPxZtGDyqKcyMxcbAGctklsigtsBZKlpj69uba3w4OSA3zJPCdQ4dKwCyBOcAAP8qeF5Jf0eLI8WLEgnKir2Pfc/rKkY0owuz7S+tUmizm3+T06wDFgwpLu0/PcA5oOcp4WpGXbAX7WujaAHB7YKAEsk324XC7Bdf+39OuZ0dbKWMiwU7rYV4NOYNPjN2BCb1XqyE0Ung41Ls6P4t/zwzYRZtiovhr6ibNBcwLVclfQZ/tbyBDuh++8dh7Ixe+x5RFiiCB0w/fiKqqXYM8/we4JU3f71y4DK6fP+nSN/vIYttvkN28HCCvBVSdyuuvPRM6Ro1yLNw9U9PHCJ1CIgcx8+I8Mep3PzBhDILXWjzlVu4sa/+aIoEq7MvWBDMhrFEP6RX+M6CiPmgj5+Lu/GZNivbu51RASI="
+      script: ./tools/check_sonarqube.sh
+      cache:
+        directories:
+          - '$HOME/.sonar/cache'
+      env: OPTS="sonarqube"
   fast_finish: true
index acf9c19bfdd4403ce05a37c576db357a6a234f36..bc9c4cf03667e5c32b80df8e0c339ddbf8b42a02 100644 (file)
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 cmake_minimum_required(VERSION 2.8)
+include(CheckCCompilerFlag)
 
 project(IOTJS C)
 
@@ -67,9 +68,18 @@ macro(iotjs_add_link_flags)
   iotjs_add_flags(IOTJS_LINKER_FLAGS ${ARGV})
 endmacro()
 
+CHECK_C_COMPILER_FLAG(-no-pie HAS_NO_PIE)
+
 # Add buildtype-related flags
 if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
   iotjs_add_compile_flags(-DDEBUG -DENABLE_DEBUG_LOG)
+  if(HAS_NO_PIE)
+    iotjs_add_link_flags(-no-pie)
+  endif()
+endif()
+
+if (CREATE_SHARED_LIB)
+  iotjs_add_compile_flags(-fPIC)
 endif()
 
 if(EXPERIMENTAL)
index 7b4f7bd9aed47300826ff9955293fd5587c3059c..fcde96fcdb577e3191e776cf1efdf03c4a78c8c5 100644 (file)
--- a/README.md
+++ b/README.md
@@ -13,6 +13,7 @@ The following table shows the latest results on the devices:
 
 |      Artik053         | [![Remote Testrunner](https://firebasestorage.googleapis.com/v0/b/remote-testrunner.appspot.com/o/status%2Fiotjs%2Fartik053.svg?alt=media&token=1)](https://samsung.github.io/iotjs-test-results/?view=artik053)  |
 |        :---:          |                                             :---:                                                                                                |
+| **Artik530**    | [![Remote Testrunner](https://firebasestorage.googleapis.com/v0/b/remote-testrunner.appspot.com/o/status%2Fiotjs%2Fartik530.svg?alt=media&token=1)](https://samsung.github.io/iotjs-test-results/?view=artik530)          |
 | **Raspberry Pi 2**    | [![Remote Testrunner](https://firebasestorage.googleapis.com/v0/b/remote-testrunner.appspot.com/o/status%2Fiotjs%2Frpi2.svg?alt=media&token=1)](https://samsung.github.io/iotjs-test-results/?view=rpi2)          |
 | **STM32F4-Discovery** | [![Remote Testrunner](https://firebasestorage.googleapis.com/v0/b/remote-testrunner.appspot.com/o/status%2Fiotjs%2Fstm32f4dis.svg?alt=media&token=1)](https://samsung.github.io/iotjs-test-results/?view=stm32f4dis)   |
 
index 0dcaf0b1b2e128e1720d1277e30b2e9fefd00ac8..4a7b5b34beec19f3a1297acaf6867bad52fd5c99 100644 (file)
@@ -463,14 +463,14 @@ message(STATUS "TARGET_SYSTEMROOT        ${TARGET_SYSTEMROOT}")
 iotjs_add_compile_flags(${IOTJS_MODULE_DEFINES})
 
 # Configure the libiotjs.a
-set(TARGET_LIB_IOTJS libiotjs)
-add_library(${TARGET_LIB_IOTJS} STATIC ${LIB_IOTJS_SRC})
-set_target_properties(${TARGET_LIB_IOTJS} PROPERTIES
+set(TARGET_STATIC_IOTJS libiotjs)
+add_library(${TARGET_STATIC_IOTJS} STATIC ${LIB_IOTJS_SRC})
+set_target_properties(${TARGET_STATIC_IOTJS} PROPERTIES
   OUTPUT_NAME iotjs
   ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
 )
-target_include_directories(${TARGET_LIB_IOTJS} PRIVATE ${IOTJS_INCLUDE_DIRS})
-target_link_libraries(${TARGET_LIB_IOTJS}
+target_include_directories(${TARGET_STATIC_IOTJS} PRIVATE ${IOTJS_INCLUDE_DIRS})
+target_link_libraries(${TARGET_STATIC_IOTJS}
   ${JERRY_LIBS}
   ${TUV_LIBS}
   libhttp-parser
@@ -486,7 +486,27 @@ if("${BIN_INSTALL_DIR}" STREQUAL "")
   set(BIN_INSTALL_DIR "bin")
 endif()
 
-install(TARGETS ${TARGET_LIB_IOTJS} DESTINATION ${LIB_INSTALL_DIR})
+install(TARGETS ${TARGET_STATIC_IOTJS} DESTINATION ${LIB_INSTALL_DIR})
+
+# Configure the libiotjs.so
+if (NOT BUILD_LIB_ONLY AND CREATE_SHARED_LIB)
+  set(TARGET_SHARED_IOTJS shared_iotjs)
+  add_library(${TARGET_SHARED_IOTJS} SHARED)
+  set_target_properties(${TARGET_SHARED_IOTJS} PROPERTIES
+    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
+    LIBRARY_OUTPUT_NAME iotjs
+    LINKER_LANGUAGE C
+  )
+  target_link_libraries(${TARGET_SHARED_IOTJS}
+    -Wl,--whole-archive
+    ${TARGET_STATIC_IOTJS}
+    ${JERRY_LIBS}
+    ${TUV_LIBS}
+    libhttp-parser
+    ${MBEDTLS_LIBS}
+    -Wl,--no-whole-archive
+    ${EXTERNAL_LIBS})
+endif()
 
 # Configure the iotjs executable
 if(NOT BUILD_LIB_ONLY)
@@ -497,7 +517,7 @@ if(NOT BUILD_LIB_ONLY)
     RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
   )
   target_include_directories(${TARGET_IOTJS} PRIVATE ${IOTJS_INCLUDE_DIRS})
-  target_link_libraries(${TARGET_IOTJS} ${TARGET_LIB_IOTJS})
+  target_link_libraries(${TARGET_IOTJS} ${TARGET_STATIC_IOTJS})
   install(TARGETS ${TARGET_IOTJS} DESTINATION ${BIN_INSTALL_DIR})
 
   add_subdirectory(test)
index 9a4f66ce8193fde4ad900865e808d36695ce7513..37a7ccd7d6bced785fad96eae996fbc6ba901da7 100644 (file)
@@ -64,7 +64,7 @@ cat LICENSE
 cp %{SOURCE1001} .
 
 %build
-./tools/build.py \
+V=1 VERBOSE=1 ./tools/build.py \
   --clean \
   --buildtype=%{build_mode} \
   --profile=test/profiles/tizen.profile \
@@ -76,26 +76,23 @@ cp %{SOURCE1001} .
   --external-lib=dlog \
   --external-lib=bundle \
   --external-lib=capi-appfw-app-control \
+  --external-lib=appcore-agent \
+  --external-lib=pthread \
+  --external-lib=curl \
   --external-include-dir=/usr/include/dlog/ \
   --external-include-dir=/usr/include/appcore-agent/ \
   --external-include-dir=/usr/include/appfw/ \
   --external-include-dir=/usr/include/glib-2.0/ \
   --external-include-dir=/usr/lib/glib-2.0/include/ \
   --compile-flag=-D__TIZEN__ \
-  --compile-flag=-fPIC \
+  --compile-flag=-DENABLE_DEBUG_LOG \
   --jerry-cmake-param=-DENABLE_STATIC_LINK=OFF \
+  --create-shared-lib \
   --no-init-submodule \
   --no-parallel-build \
   %{external_build_options}
 # --external-lib=sdkapi \
 
-# Create shared library
-%define iotjs_target_lib libjerry-core.a libjerry-port-default.a libhttpparser.a libtuv.a \\\
-  libmbedx509.a libmbedtls.a libmbedcrypto.a libiotjs.a
-%define iotjs_lib_flag -lcapi-system-peripheral-io -lpthread -lcurl -ldlog -lappcore-agent -lcapi-appfw-app-common -lbundle -lcapi-appfw-app-control
-cd ./build/noarch-tizen/%{build_mode}/lib/
-gcc -shared -o libiotjs.so -Wl,--whole-archive %{iotjs_target_lib} -Wl,--no-whole-archive %{iotjs_lib_flag}
-
 %install
 mkdir -p %{buildroot}%{_bindir}
 mkdir -p %{buildroot}%{_includedir}/iotjs
diff --git a/config/tizen/patch4tizenorg.sh b/config/tizen/patch4tizenorg.sh
new file mode 100755 (executable)
index 0000000..871c87d
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+# Copyright 2018-present Samsung Electronics Co., Ltd. and other contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+echo "******************************************************************"
+echo "*                       Tizen patch for obs build                *"
+echo "******************************************************************"
+echo ""
+echo "This working folder will be copied to ../iotjs_tizen_org"
+
+cd ..
+echo copy from $OLDPWD to ../iotjs_tizen_org
+cp -ra $OLDPWD iotjs_tizen_org
+cd iotjs_tizen_org
+
+echo -e "\n(1) Now, cloning submodules. "
+git submodule init
+
+echo -e "\n(2) Update submodules... "
+git submodule update
+
+echo -e "\n(3) remove .git folders.. "
+find ./ -name '.git' | xargs rm -rf
+
+# Initialize Git repository
+if [ ! -d .git ]
+then
+  git init ./
+  git checkout -b tizen_gbs
+  git add ./
+  git commit -m "Initial commit"
+fi
+
+
+echo -e "\n(4) Patch for tizen.org... "
+patch -p1 < config/tizen/iotjs_tizen.patch
+cp -ra config/tizen/packaging .
+
index 8e38c724d9201155a888b9bccb658928d733f2e7..c7dcb84459a8c1f6710bb9cc4017d92249860e86 100644 (file)
@@ -19,6 +19,9 @@ void service_app_terminate(void *data)
 void service_app_control(app_control_h app_control, void *data)
 {
        // Todo: add your code here.
+
+       // Emit 'appControl' event to the JavaScript side.
+       iotjs_tizen_app_control_cb(app_control, data);
        return;
 }
 
index 37a02ab1a225d6b812fdf7fd8db8b2310758ec0b..06b38608db1644a18396ea1a53b29ee5dfd0e930 100644 (file)
@@ -24,8 +24,8 @@ The logical number might be different from the physical
 pin number of the board. The mapping is available
 in the documentation of a given board.
 
-On NuttX, the pin number is defined in target board
-module. For more information, please check the
+* On Tizen, the pin number is defined in [this documentation](../targets/tizen/SystemIO-Pin-Information-Tizen.md#gpio).
+* On NuttX, the pin number is defined in the documentation of the target board. For more information, please check the
 following list:
 [STM32F4-discovery](../targets/nuttx/stm32f4dis/IoT.js-API-Stm32f4dis.md#gpio-pin)
 
index 6aece5c5c7235dc0c7cbe4ce2831f8b7fb3e700e..fe0f0f9669c242b73c8f6bb8ef15c411a08342e4 100644 (file)
@@ -18,6 +18,8 @@ The following shows I2C module APIs available for each platform.
 
 The I2C module supports the I2C protocol. I2C bus has two signals - SDA and SCL.
 
+* On Tizen, the bus number is defined in [this documentation](../targets/tizen/SystemIO-Pin-Information-Tizen.md#i2c).
+
 ### i2c.open(configuration, callback)
 * `configuration` {Object} Configuration for open I2CBus.
   * `device` {string} Device path. (only on Linux)
diff --git a/docs/api/IoT.js-API-MQTT.md b/docs/api/IoT.js-API-MQTT.md
new file mode 100644 (file)
index 0000000..2227097
--- /dev/null
@@ -0,0 +1,198 @@
+### Platform Support
+
+The following chart shows the availability of each TLS module API function on each platform.
+
+|  | Linux<br/>(Ubuntu) | Tizen<br/>(Raspberry Pi) | Raspbian<br/>(Raspberry Pi) | Nuttx<br/>(STM32F4-Discovery) | TizenRT<br/>(Artik053) |
+| :---: | :---: | :---: | :---: | :---: | :---: |
+| mqtt.getClient  | O | X | X | X | X | X |
+| mqtt.publish  | O | X | X | X | X | X |
+| mqtt.subscribe | O | X | X | X | X | X |
+| mqtt.unsubscribe | X | X | X | X | X | X |
+| mqtt.ping | O | X | X | X | X | X |
+| mqtt.connect | O | X | X | X | X | X |
+
+# MQTT
+
+MQTT is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is required and/or network bandwidth is at a premium.
+
+### QoS
+The QoS level can be 0, 1 or 2.
+- Level 0 means the packet arrives at most once.
+- Level 1 means the packet arrives at least once (duplications might occur, it is the user's responsibility to take care of them).
+- Level 2 means that the package is delivered exactly once.
+
+### Topic seperating and wildcarding
+Topics can be wildcarded and they also can be structured into multiple levels. These levels are divided by the `/` sign (eg. `iotjs/jerryscript/jerry-core`). There are multiple wildcarding possibilities:
+ - `Multi-level wildcard` The `#` sign is a wildcard character that matches any number of levels within a topic. This character MUST be the last character in a topic name. Typing `iotjs/#` means the client subscribes to anything that is under the `iotjs` topic.
+ - `Single-level wildcard` The `+` sign is a wildcard character that matches only one topic level. It can be used more at than one level in the topic name. It MUST be used so it occupies an entire level of the name. Typing `iotjs/+/jerry-core` subscribes you to `jerry-core` topic.
+ - Topics that are beginning with `$` can not be matched with wildcard filters such as `#` or `+`. Subscriptions with wildcards to these topics means that they receive no data at all.
+
+## Class: MQTTClient
+The `MQTTClient` can subscribe or publish data to a broker. It sends data over a `net.socket`.
+
+### mqtt.getClient(options)
+- `options` {Object}
+    -  `clientId` {Buffer | string} Optional. The broker identifies each client by its `clientId`. If not specified, a randomly generated `clientId` is created.
+    -  `host` {Buffer | string} The address of the broker.
+    -  `port` {number} The port of the broker.
+    - `username` {Buffer | string} Optional. Use username when onnecting to a broker.
+    - `password` {Buffer | string} Optional. Use password authentication when connecting to a broker.
+    - `keepalive` {number} Keepalive time in seconds. If no data is sent on the connection in the given time window the broker disconnects the client.
+    - `will` {boolean} Optional. If this flag is set to `true`, a `message` and a `topic` must follow with a QoS value between 0 and 2.
+    - `qos` {number} If `will` is set to `true`, the message will be sent with the given QoS.
+    - `topic` {Buffer | string} Only processed when `will` is set to `true`. The topic the `message` should be sent to.
+    - `message` {Buffer | string} Only processed when `will` is set to `true`. The message to be sent to the broker when connecting.
+
+Returns an MQTTClient.
+
+### mqtt.connect(callback)
+- `callback` {function} The function will be executed when the client successfuly connected to the broker.
+
+Connects the client to a broker. Emits a `connect` event.
+
+**Example**
+```js
+var mqtt = require('mqtt');
+
+var opts = {
+    host: '127.0.0.1',
+    port: 443,
+    keepalive: 10,
+    clientId: 'IoT.js Client',
+}
+
+var client = mqtt.getClient(opts);
+client.connect(function () {
+    client.disconnect();
+});
+```
+
+### mqtt.disconnect()
+Disconnects the client from the broker.
+
+### mqtt.ping()
+Sends a ping request to the server. If the server doesn't respond within 3 seconds, the client closes the connection. Emits a `pingresp` event if the server responded.
+
+**Example**
+```js
+var mqtt = require('mqtt');
+
+var opts = {
+    host: '127.0.0.1',
+    port: 443,
+    keepalive: 10,
+    clientId: 'IoT.js Client',
+}
+
+var client = mqtt.getClient(opts);
+client.connect(function () {
+    client.ping();
+});
+
+client.on('pingresp', function() {
+  client.disconnect();
+});
+```
+
+### mqtt.subscribe(options)
+- `options` {Object}
+    - `topic` {Buffer | string} The topic the client subscribes to.
+    - `qos` {number} Optional. Defaults to 0.
+    - `retain` {boolean} Optional. If retain is `true` the client receives the messages that were sent to the desired `topic` before it connected. Defaults to `false`.
+
+The client subscribes to a given `topic`. If there are messages available on the `topic` the client emits a `data` event with the message received from the broker.
+
+**Example**
+```js
+var mqtt = require('mqtt');
+
+var opts = {
+    host: '127.0.0.1',
+    port: 443,
+    keepalive: 10,
+    clientId: 'IoT.js Client',
+}
+
+var subscribe_opts {
+  topic: 'hello/#/iotjs',
+  retain: false,
+  qos: 2
+}
+
+var client = mqtt.getClient(opts);
+client.connect(function () {
+    client.subscribe(subscribe_opts);
+});
+
+client.on('data', function(data) {
+  console.log('I received something: ' + data.toString());
+});
+```
+
+### mqtt.unsubscribe(topic)
+- `options` {Buffer | string} The topic to unsubscribe from.
+
+Unsubscribes the client from a given topic. If QoS was turned on on the subscription the remaining packets will be sent by the server.
+
+
+### mqtt.publish(options)
+- `options` {Object}
+    - `topic` {Buffer | string} The topic to send the `message` to.
+    - `message` {Buffer | string} The message to be sent.
+    - `qos` {number} Optional. Defaults to 0.
+    - `retain` {boolean} Optional. If retain is `true` the broker stores the message for clients subscribing with retain `true` flag, therefore they can receive it later.
+
+Publishes a `message` to the broker under the given `topic`.
+
+**Example**
+```js
+var mqtt = require('mqtt');
+
+var opts = {
+    host: '127.0.0.1',
+    port: 443,
+    keepalive: 10,
+    clientId: 'IoT.js Client',
+}
+
+var publish_opts {
+  topic: 'hello/#/iotjs',
+  message: 'MQTT now works!',
+  retain: false,
+  qos: 1
+}
+
+var client = mqtt.getClient(opts);
+client.connect(function () {
+    client.publish(publish_opts);
+});
+```
+
+## Events
+### `connect`
+Emitted when the client successfully connects to a broker.
+
+### `disconnect`
+A `disconnect` event is emitted when the broker disconnects the client gracefully.
+
+### `error`
+If an error occured an `error` event is emitted with the error data.
+
+### `message`
+When data is received from the server a `message` event is emitted with a `data` object. It has the following properties:
+   - `message`: The message the broker sent.
+   - `topic`: The topic the message was sent from.
+   - `qos`: The QoS level the message was sent with.
+   - `packet_id`: The id of the packet if QoS was enabled.
+
+### `pingresp`
+Emitted when we receive a ping response from the server.
+
+### `puback`
+`puback` is emitted if the server has successfully received the QoS 1 packet sent with `publish`.
+
+### `pubcomp`
+If a QoS level 2 package has successfully arrived a `pubcomp` is emitted.
+
+### `suback`
+If a subscription was accepted by the broker to a topic, a `suback` event is emitted.
index 20d73421678b9d96f20eac5d8f8716e9a221bc21..62b22bdf79f56ed392c4defc9621d2f4369f4038 100644 (file)
@@ -45,6 +45,10 @@ For each directory in search paths above:
 - Extra step for Linux/Tizen targets:
   - If a file with `id.iotjs` exists, try to load it as an IoT.js dynamic module and return.
 
+**Changing current working directory**
+
+You can explicitly change current working directory by setting `IOTJS_WORKING_DIR_PATH` environment variable. It is not recommended that you set this variable, if possible.
+
 **Adding extra paths for module loading**
 
 In order to add more directories to look for modules, you can set `IOTJS_EXTRA_MODULE_PATH` as an environment variable of your system. For instance, `./node_modules` and `./my_modules` will be referred if they're declared as follows.
index 41662499b648cf95aaeca686dcc31948d2104681..7d56526bea896af5883014af6271f762d40471d3 100644 (file)
@@ -47,6 +47,7 @@ The `env` property returns an object containing a few environment variables.
 The following environment elements can be accessed:
 * `HOME`
 * `IOTJS_PATH` which is set to `/mnt/sdcard` on NuttX by default.
+* `IOTJS_WORKING_DIR_PATH` is the specified current working directory path to change the root of the module load.
 * `IOTJS_EXTRA_MODULE_PATH` contains the paths to be additionally referenced to load any module.
 * `env` contains `'experimental'` if the IoT.js was build with experimental support.
 
index b2141888ebace80978df723188d660ae5bb6d88a..0fc3b9b078bba791e79436723ee26877d28df775 100644 (file)
@@ -16,7 +16,8 @@ The following shows spi module APIs available for each platform.
 
 SPI (Serial Peripheral Interface) is a communication protocol which defines a way to communicate between devices.
 
-On NuttX, you have to know the number of pins that is defined on the target board module. For more information, please see the list below.
+* On Tizen, the bus number is defined in [this documentation](../targets/tizen/SystemIO-Pin-Information-Tizen.md#spi).
+* On NuttX, you have to know the number of pins that is defined on the target board module. For more information, please see the list below.
   * [STM32F4-discovery](../targets/nuttx/stm32f4dis/IoT.js-API-Stm32f4dis.md)
 
 ### SPI.MODE
index c5d1e4822f08a2b3c5195d3379fb2ebce116893a..ab572105c00432eac2a270c0220e7b4337f44b8f 100644 (file)
@@ -15,6 +15,8 @@ The following shows uart module APIs available for each platform.
 
 The UART (Universal Asynchronous Receiver/Transmitter) class supports asynchronous serial communication.
 
+* On Tizen, the port number is defined in [this documentation](../targets/tizen/SystemIO-Pin-Information-Tizen.md#uart).
+
 ### uart.open(configuration, callback)
 * `configuration` {Object}
   * `device` {string} Mandatory configuration. The specified device path.(Linux, Nuttx and TizenRT only)
diff --git a/docs/targets/tizen/SystemIO-Pin-Information-Tizen.md b/docs/targets/tizen/SystemIO-Pin-Information-Tizen.md
new file mode 100644 (file)
index 0000000..55b6cb9
--- /dev/null
@@ -0,0 +1,71 @@
+When you use System I/O module that is `GPIO`, `PWM`, `SPI`, `I2C`, and `UART`, you should know specified pin, bus or port number. 
+
+### GPIO
+
+#### ARTIK530
+| GPIO Name | Pin Number | GPIO Name | Pin Number |
+| :---: | :---: | :---: | :---: |
+| GPIO0 | 128 | GPIO1 | 129 |
+| GPIO2 | 130 | GPIO3 | 46 |
+| GPIO4 | 14 | GPIO5 | 41 |
+| GPIO6 | 25 | GPIO7 | 0 |
+| GPIO8 | 26 | GPIO9 | 27 |
+
+#### Raspberry Pi3
+| GPIO Name | Pin Number | GPIO Name | Pin Number |
+| :---: | :---: | :---: | :---: |
+| GPIO4 | 4 | GPIO5 | 5 |
+| GPIO6 | 6 | GPIO12 | 12 |
+| GPIO13 | 13 | GPIO16 | 16 |
+| GPIO17 | 17 | GPIO18 | 18 |
+| GPIO19 | 19 | GPIO20 | 20 |
+| GPIO21 | 21 | GPIO20 | 20 |
+| GPIO23 | 23 | GPIO24 | 24 |
+| GPIO25 | 25 | GPIO26 | 26 |
+| GPIO27 | 27 | - | - |
+
+
+### PWM
+
+#### ARTIK530
+| PWM Name | Pin Number |
+| :---: | :---: |
+| PWM0 | 2 |
+
+
+### SPI
+
+#### ARTIK530
+| SPI Name | Bus Number | Chip Select |
+| :---: | :---: | :---: |
+| SPI | 2 | 0 |
+
+#### Raspberry Pi3
+| SPI Name | Bus Number | Chip Select |
+| :---: | :---: | :---: |
+| SPI0(CS0) | 0 | 0 |
+| SPI0(CS1) | 0 | 1 |
+
+### I2C
+
+#### ARTIK530
+| I2C Name | Bus Number |
+| :---: | :---: |
+| I2C | 1 |
+
+#### Raspberry Pi3
+| I2C Name | Bus Number |
+| :---: | :---: |
+| I2C | 1 |
+
+#### UART
+
+#### ARTIK530
+| UART Name | Port Number |
+| :---: | :---: |
+| UART0 | 4 |
+
+#### Raspberry Pi3
+| UART Name | Port Number |
+| :---: | :---: |
+| UART0 | 0 |
\ No newline at end of file
index 9a4f66ce8193fde4ad900865e808d36695ce7513..37a7ccd7d6bced785fad96eae996fbc6ba901da7 100644 (file)
@@ -64,7 +64,7 @@ cat LICENSE
 cp %{SOURCE1001} .
 
 %build
-./tools/build.py \
+V=1 VERBOSE=1 ./tools/build.py \
   --clean \
   --buildtype=%{build_mode} \
   --profile=test/profiles/tizen.profile \
@@ -76,26 +76,23 @@ cp %{SOURCE1001} .
   --external-lib=dlog \
   --external-lib=bundle \
   --external-lib=capi-appfw-app-control \
+  --external-lib=appcore-agent \
+  --external-lib=pthread \
+  --external-lib=curl \
   --external-include-dir=/usr/include/dlog/ \
   --external-include-dir=/usr/include/appcore-agent/ \
   --external-include-dir=/usr/include/appfw/ \
   --external-include-dir=/usr/include/glib-2.0/ \
   --external-include-dir=/usr/lib/glib-2.0/include/ \
   --compile-flag=-D__TIZEN__ \
-  --compile-flag=-fPIC \
+  --compile-flag=-DENABLE_DEBUG_LOG \
   --jerry-cmake-param=-DENABLE_STATIC_LINK=OFF \
+  --create-shared-lib \
   --no-init-submodule \
   --no-parallel-build \
   %{external_build_options}
 # --external-lib=sdkapi \
 
-# Create shared library
-%define iotjs_target_lib libjerry-core.a libjerry-port-default.a libhttpparser.a libtuv.a \\\
-  libmbedx509.a libmbedtls.a libmbedcrypto.a libiotjs.a
-%define iotjs_lib_flag -lcapi-system-peripheral-io -lpthread -lcurl -ldlog -lappcore-agent -lcapi-appfw-app-common -lbundle -lcapi-appfw-app-control
-cd ./build/noarch-tizen/%{build_mode}/lib/
-gcc -shared -o libiotjs.so -Wl,--whole-archive %{iotjs_target_lib} -Wl,--no-whole-archive %{iotjs_lib_flag}
-
 %install
 mkdir -p %{buildroot}%{_bindir}
 mkdir -p %{buildroot}%{_includedir}/iotjs
index 6249fd2de0b67010718b67408c75162020215abc..72708a56874567b415115c75509950aa1ba1cbb9 100644 (file)
@@ -39,7 +39,6 @@ void iotjs_bridge_sample_func(const char* command, const char* message,
   } else if (strncmp(command, "testThread", strlen("testThread")) == 0) {
     uv_thread_t thread1;
     uv_thread_create(&thread1, thread1_worker, return_handle);
-    uv_thread_join(&thread1);
   } else if (strncmp(command, "getResPath", strlen("getResPath")) == 0) {
     iotjs_bridge_set_msg(return_handle, "res/");
   } else {
diff --git a/samples/tizen-bridge-native/tizen_bridge_native.c b/samples/tizen-bridge-native/tizen_bridge_native.c
new file mode 100644 (file)
index 0000000..8ce585c
--- /dev/null
@@ -0,0 +1,52 @@
+/* Copyright 2018-present Samsung Electronics Co., Ltd. and other contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "iotjs.h"
+#include "iotjs_tizen_service_app.h"
+
+/* thread */
+#include <pthread.h>
+#include <unistd.h>
+/* printf */
+#include <stdio.h>
+
+
+static void user_cb(int err, const char* data) {
+  printf("err: %d, data: %s\n", err, data);
+}
+
+
+void* thread(void* data) {
+  sleep(1);
+
+  char* str = "1234567A1234567B1234567C";
+  IOTJS_TIZEN_CALL_JFUNC("hello", "world", user_cb);
+  IOTJS_TIZEN_CALL_JFUNC("hello", str, user_cb);
+  IOTJS_TIZEN_CALL_JFUNC("hello", "", user_cb);
+  IOTJS_TIZEN_CALL_JFUNC("", "", user_cb);
+  IOTJS_TIZEN_CALL_JFUNC("", "", NULL);
+  IOTJS_TIZEN_CALL_JFUNC("notReturnString", "", user_cb);
+  return 0;
+}
+
+
+int main(int argc, char** argv) {
+  pthread_t tid;
+  if (pthread_create(&(tid), NULL, &thread, NULL)) {
+    return 1;
+  }
+
+  return iotjs_entry(argc, argv);
+}
diff --git a/samples/tizen-bridge-native/tizen_bridge_native.js b/samples/tizen-bridge-native/tizen_bridge_native.js
new file mode 100644 (file)
index 0000000..0db23fa
--- /dev/null
@@ -0,0 +1,27 @@
+/* Copyright 2018-present Samsung Electronics Co., Ltd. and other contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var tizen = require('tizen');
+
+tizen.hello = function(data) {
+  return 'tizen.hello is called with data, ' + (data ? data : 'null');
+}
+
+tizen.notReturnString = function(data) {
+}
+
+setInterval(function() {
+  console.log('heartbeat');
+}, 10000);
diff --git a/sonar-project.properties b/sonar-project.properties
new file mode 100644 (file)
index 0000000..9a74a10
--- /dev/null
@@ -0,0 +1,5 @@
+sonar.projectKey=samsung.iot.js
+sonar.projectName=IoT.js
+sonar.projectVersion=1.0
+sonar.sources=src
+sonar.cfamily.build-wrapper-output=bw-output
index 52187a0715094a7954dffdc22cd53068853ff6dc..b4ba182a5c4a9fb25fe1d8e726e7104ae663e262 100644 (file)
@@ -23,6 +23,9 @@
 #define IOTJS_MAGIC_STRING_3 "3"
 #endif
 #define IOTJS_MAGIC_STRING_ABORT "abort"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_ACKTYPE "type"
+#endif
 #if ENABLE_MODULE_ADC
 #define IOTJS_MAGIC_STRING_ADC "Adc"
 #endif
@@ -74,6 +77,9 @@
 #define IOTJS_MAGIC_STRING_CHIPSELECT "chipSelect"
 #define IOTJS_MAGIC_STRING_CHIPSELECT_U "CHIPSELECT"
 #endif
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_CLIENTID "clientId"
+#endif
 #define IOTJS_MAGIC_STRING_CLOSE "close"
 #define IOTJS_MAGIC_STRING_CLOSESYNC "closeSync"
 #define IOTJS_MAGIC_STRING_CODE "code"
 #define IOTJS_MAGIC_STRING_DIRECTION "direction"
 #define IOTJS_MAGIC_STRING_DIRECTION_U "DIRECTION"
 #endif
+#ifdef ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_DISCONNECT "disconnect"
+#endif
 #define IOTJS_MAGIC_STRING_DOEXIT "doExit"
 #if ENABLE_MODULE_UDP
 #define IOTJS_MAGIC_STRING_DROPMEMBERSHIP "dropMembership"
 #define IOTJS_MAGIC_STRING_IOTJS_ENV_U "IOTJS_ENV"
 #define IOTJS_MAGIC_STRING_IOTJS_PATH_U "IOTJS_PATH"
 #define IOTJS_MAGIC_STRING_IOTJS_EXTRA_MODULE_PATH_U "IOTJS_EXTRA_MODULE_PATH"
+#define IOTJS_MAGIC_STRING_IOTJS_WORKING_DIR_PATH_U "IOTJS_WORKING_DIR_PATH"
 #define IOTJS_MAGIC_STRING_IOTJS "iotjs"
 #define IOTJS_MAGIC_STRING_IPV4 "IPv4"
 #define IOTJS_MAGIC_STRING_IPV6 "IPv6"
 #if ENABLE_MODULE_TLS
 #define IOTJS_MAGIC_STRING_ISSERVER "isServer"
 #endif
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_KEEPALIVE "keepalive"
+#endif
 #define IOTJS_MAGIC_STRING_KEY "key"
 #define IOTJS_MAGIC_STRING_LENGTH "length"
 #define IOTJS_MAGIC_STRING_LISTEN "listen"
 #define IOTJS_MAGIC_STRING_LSB "LSB"
 #define IOTJS_MAGIC_STRING_MAXSPEED "maxSpeed"
 #endif
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_MESSAGE "message"
+#endif
 #define IOTJS_MAGIC_STRING_METHOD "method"
 #define IOTJS_MAGIC_STRING_METHODS "methods"
 #define IOTJS_MAGIC_STRING_MKDIR "mkdir"
 #if ENABLE_MODULE_SPI || ENABLE_MODULE_GPIO
 #define IOTJS_MAGIC_STRING_MODE_U "MODE"
 #endif
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_MQTTINIT "MqttInit"
+#define IOTJS_MAGIC_STRING_MQTTMESSAGE "MqttMessage"
+#define IOTJS_MAGIC_STRING_MQTTHANDLE "MqttHandle"
+#endif
 #if ENABLE_MODULE_SPI
 #define IOTJS_MAGIC_STRING_MSB "MSB"
 #endif
 #define IOTJS_MAGIC_STRING_ONBODY "OnBody"
 #define IOTJS_MAGIC_STRING_ONCLOSE "onclose"
 #define IOTJS_MAGIC_STRING_ONCLOSED "onClosed"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING__ONCONNECT "_onconnect"
+#endif
 #define IOTJS_MAGIC_STRING_ONCONNECTION "onconnection"
 #define IOTJS_MAGIC_STRING_ONDATA "onData"
+#ifdef ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING__ONDISCONNECT "_ondisconnect"
+#endif
 #define IOTJS_MAGIC_STRING_ONEND "onEnd"
 #define IOTJS_MAGIC_STRING_ONERROR "onError"
 #if ENABLE_MODULE_TLS
 #define IOTJS_MAGIC_STRING_ONHEADERSCOMPLETE "OnHeadersComplete"
 #define IOTJS_MAGIC_STRING_ONHEADERS "OnHeaders"
 #define IOTJS_MAGIC_STRING_ONMESSAGECOMPLETE "OnMessageComplete"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING__ONMESSAGE "_onmessage"
+#endif
 #define IOTJS_MAGIC_STRING_ONMESSAGE "onmessage"
 #define IOTJS_MAGIC_STRING__ONNEXTTICK "_onNextTick"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING__ONPINGRESP "_onpingresp"
+#define IOTJS_MAGIC_STRING__ONPUBACK "_onpuback"
+#define IOTJS_MAGIC_STRING__ONPUBCOMP "_onpubcomp"
+#define IOTJS_MAGIC_STRING__ONPUBREC "_onpubrec"
+#define IOTJS_MAGIC_STRING__ONPUBREL "_onpubrel"
+#endif
 #define IOTJS_MAGIC_STRING_ONREAD "onread"
 #define IOTJS_MAGIC_STRING_ONSOCKET "onSocket"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING__ONSUBACK "_onsuback"
+#define IOTJS_MAGIC_STRING__ONUNSUBACK "_onunsuback"
+#endif
 #define IOTJS_MAGIC_STRING_ONTIMEOUT "onTimeout"
 #define IOTJS_MAGIC_STRING__ONUNCAUGHTEXCEPTION "_onUncaughtException"
 #if ENABLE_MODULE_TLS
 #define IOTJS_MAGIC_STRING_OUT_U "OUT"
 #endif
 #define IOTJS_MAGIC_STRING_OWNER "owner"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_PACKETID "packet_id"
+#define IOTJS_MAGIC_STRING_PASSWORD "password"
+#endif
 #define IOTJS_MAGIC_STRING_PAUSE "pause"
 #define IOTJS_MAGIC_STRING_PERIOD "period"
 #define IOTJS_MAGIC_STRING_PIN "pin"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_PING "ping"
+#endif
 #define IOTJS_MAGIC_STRING_PLATFORM "platform"
 #define IOTJS_MAGIC_STRING_PORT "port"
+#define IOTJS_MAGIC_STRING_PRIVATE "_private"
 #define IOTJS_MAGIC_STRING_PROTOTYPE "prototype"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_PUBLISH "publish"
+#endif
 #if ENABLE_MODULE_GPIO
 #define IOTJS_MAGIC_STRING_PULLDOWN_U "PULLDOWN"
 #define IOTJS_MAGIC_STRING_PULLUP_U "PULLUP"
 #define IOTJS_MAGIC_STRING_PUSHPULL_U "PUSHPULL"
 #endif
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_QOS "qos"
+#endif
 #define IOTJS_MAGIC_STRING_READDIR "readdir"
 #define IOTJS_MAGIC_STRING_READ "read"
 #define IOTJS_MAGIC_STRING_READSOURCE "readSource"
 #define IOTJS_MAGIC_STRING_REQUEST_U "REQUEST"
 #define IOTJS_MAGIC_STRING_RESPONSE_U "RESPONSE"
 #define IOTJS_MAGIC_STRING_RESUME "resume"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_RETAIN "retain"
+#endif
 #define IOTJS_MAGIC_STRING__REUSEADDR "_reuseAddr"
 #if ENABLE_MODULE_GPIO
 #define IOTJS_MAGIC_STRING_RISING_U "RISING"
 #endif
 #define IOTJS_MAGIC_STRING_RMDIR "rmdir"
 #define IOTJS_MAGIC_STRING_SEND "send"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_SENDACK "sendAck"
+#endif
 #define IOTJS_MAGIC_STRING_SENDREQUEST "sendRequest"
 #if ENABLE_MODULE_TLS
 #define IOTJS_MAGIC_STRING_SERVERNAME "servername"
 #define IOTJS_MAGIC_STRING_STDERR "stderr"
 #define IOTJS_MAGIC_STRING_STDOUT "stdout"
 #define IOTJS_MAGIC_STRING_STOP "stop"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_SUBSCRIBE "subscribe"
+#endif
 #if ENABLE_MODULE_TLS
 #define IOTJS_MAGIC_STRING_TLSSOCKET "TLSSocket"
 #define IOTJS_MAGIC_STRING_TLSCONTEXT "TlsContext"
 #define IOTJS_MAGIC_STRING_TLSINIT "TlsInit"
 #endif
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_TOPIC "topic"
+#endif
 #define IOTJS_MAGIC_STRING_TOSTRING "toString"
 #if ENABLE_MODULE_SPI
 #define IOTJS_MAGIC_STRING_TRANSFER "transfer"
 #endif
 #define IOTJS_MAGIC_STRING_UNLINK "unlink"
 #define IOTJS_MAGIC_STRING_UNREF "unref"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_UNSUBSCRIBE "unsubscribe"
+#endif
 #define IOTJS_MAGIC_STRING_UPGRADE "upgrade"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_USERNAME "username"
+#endif
 #define IOTJS_MAGIC_STRING_URL "url"
 #define IOTJS_MAGIC_STRING_VERSION "version"
+#if ENABLE_MODULE_MQTT
+#define IOTJS_MAGIC_STRING_WILL "will"
+#endif
 #define IOTJS_MAGIC_STRING_WRITEUINT8 "writeUInt8"
 #define IOTJS_MAGIC_STRING_WRITE "write"
 #define IOTJS_MAGIC_STRING_WRITEDECODE "writeDecode"
index 243ee6bb88f718607c16f27a5e7c6213261bcb61..abd7a8634e030b6fce3803e6d6d2c83cf70f565f 100644 (file)
@@ -25,6 +25,8 @@
 #include <execinfo.h>
 #endif
 
+void force_terminate();
+
 iotjs_string_t iotjs_file_read(const char* path) {
   FILE* file = fopen(path, "rb");
   if (file == NULL) {
@@ -40,6 +42,13 @@ iotjs_string_t iotjs_file_read(const char* path) {
   fseek_ret = fseek(file, 0, SEEK_SET);
   IOTJS_ASSERT(fseek_ret == 0);
 
+  if (ftell_ret < 0 || fseek_ret != 0) {
+    iotjs_string_t empty_content = iotjs_string_create();
+    fclose(file);
+    DLOG("iotjs_file_read error");
+    return empty_content;
+  }
+
   char* buffer = iotjs_buffer_allocate(len + 1);
 
 #if defined(__NUTTX__) || defined(__TIZENRT__)
@@ -68,7 +77,10 @@ iotjs_string_t iotjs_file_read(const char* path) {
 
 char* iotjs_buffer_allocate(size_t size) {
   char* buffer = (char*)(calloc(size, sizeof(char)));
-  IOTJS_ASSERT(buffer != NULL);
+  if (buffer == NULL) {
+    DLOG("Out of memory");
+    force_terminate();
+  }
   return buffer;
 }
 
@@ -87,7 +99,12 @@ char* iotjs_buffer_allocate_from_number_array(size_t size,
 
 char* iotjs_buffer_reallocate(char* buffer, size_t size) {
   IOTJS_ASSERT(buffer != NULL);
-  return (char*)(realloc(buffer, size));
+  char* newbuffer = (char*)(realloc(buffer, size));
+  if (newbuffer == NULL) {
+    DLOG("Out of memmory");
+    force_terminate();
+  }
+  return newbuffer;
 }
 
 
index 9574b69b70635532ece5fa45446796582f7af616..adccee216159bf97d593523450f1f82d89331700 100644 (file)
@@ -32,6 +32,9 @@ void iotjs_buffer_release(char* buff);
 #define IOTJS_ALLOC(type) /* Allocate (type)-sized, (type*)-typed memory */ \
   (type*)iotjs_buffer_allocate(sizeof(type))
 
+#define IOTJS_CALLOC(num, type) \
+  (type*)iotjs_buffer_allocate((num * sizeof(type)))
+
 #define IOTJS_RELEASE(ptr) /* Release memory allocated by IOTJS_ALLOC() */ \
   ({                                                                       \
     iotjs_buffer_release((char*)ptr);                                      \
index 01c029f39217d2315ef38925f659bb98887cd4c2..7d51be3bf0e970393fb28b36b59bccaebbc61bf1 100644 (file)
     this.exports = {};
   }
 
-
   Module.cache = {};
+  Module.builtin_modules = {};
 
+  mixin(Module.builtin_modules, process.builtin_modules);
+  mixin(Module, process._private);
+  process._private = undefined;
 
   Module.require = function(id) {
-    if (id == 'native') {
+    if (id === 'builtin') {
       return Module;
     }
 
@@ -44,7 +47,7 @@
 
 
   Module.prototype.compile = function() {
-    process.compileModule(this, Module.require);
+    Module.compileModule(this, Module.require);
   };
 
 
 
   EventEmitter.call(process);
 
-  var keys = Object.keys(EventEmitter.prototype);
-  var keysLength = keys.length;
-  for (var i = 0; i < keysLength; ++i) {
-    var key = keys[i];
-    if (!process[key]) {
-      process[key] = EventEmitter.prototype[key];
+  mixin(process, EventEmitter.prototype);
+
+  function mixin(target, source) {
+    for (var prop in source) {
+      if (source.hasOwnProperty(prop) && !target[prop]) {
+        target[prop] = source[prop];
+      }
     }
   }
 
index 3a1620c3efb44aca561c5bfb2118d94eb28a5ad9..5627804544f32e15ed901e98c3b692325c0663cc 100644 (file)
@@ -14,8 +14,9 @@
  */
 
 
-var Native = require('native');
-var fs = Native.require('fs');
+var Builtin = require('builtin');
+var fs = Builtin.require('fs');
+var dynamicloader = Builtin.require('dynamicloader');
 
 function Module(id, parent) {
   this.id = id;
@@ -31,13 +32,12 @@ Module.cache = {};
 // Cache to store not yet compiled remote modules
 Module.remoteCache = {};
 
+var moduledirs = [''];
 
 var cwd;
 try {
-  cwd = process.cwd();
+  cwd = process.env.IOTJS_WORKING_DIR_PATH || process.cwd();
 } catch (e) { }
-
-var moduledirs = [''];
 if (cwd) {
   moduledirs.push(cwd + '/');
   moduledirs.push(cwd + '/iotjs_modules/');
@@ -61,8 +61,6 @@ if (process.env.IOTJS_EXTRA_MODULE_PATH) {
   });
 }
 
-var dynamicloader = Native.require('dynamicloader');
-
 function tryPath(modulePath, ext) {
   return Module.tryPath(modulePath) ||
          Module.tryPath(modulePath + ext);
@@ -106,7 +104,7 @@ Module.resolveFilepath = function(id, directories) {
     var jsonpath = modulePath + '/package.json';
 
     if (Module.tryPath(jsonpath)) {
-      var pkgSrc = process.readSource(jsonpath);
+      var pkgSrc = Builtin.readSource(jsonpath);
       var pkgMainFile = JSON.parse(pkgSrc).main;
 
       // pkgmain[.ext]
@@ -190,8 +188,8 @@ Module.tryPath = function(path) {
 
 
 Module.load = function(id, parent) {
-  if (process.builtin_modules[id]) {
-    return Native.require(id);
+  if (Builtin.builtin_modules[id]) {
+    return Builtin.require(id);
   }
   if (Module.remoteCache[id]) {
     Module.compileRemoteSource(id, Module.remoteCache[id]);
@@ -219,10 +217,10 @@ Module.load = function(id, parent) {
   var source;
 
   if (ext === 'js') {
-    source = process.readSource(modPath);
+    source = Builtin.readSource(modPath);
     module.compile(modPath, source);
   } else if (ext === 'json') {
-    source = process.readSource(modPath);
+    source = Builtin.readSource(modPath);
     module.exports = JSON.parse(source);
   } else if (dynamicloader && ext === 'iotjs') {
     module.exports = dynamicloader(modPath);
@@ -250,14 +248,14 @@ Module.compileRemoteSource = function(filename, source) {
 
 
 Module.prototype.compile = function(filename, source) {
-    var fn = process.compile(filename, source);
+    var fn = Builtin.compile(filename, source);
     fn.call(this.exports, this.exports, this.require.bind(this), this);
 };
 
 
 Module.runMain = function() {
-  if (process.debuggerWaitSource) {
-    var sources = process.debuggerGetSource();
+  if (Builtin.debuggerWaitSource) {
+    var sources = Builtin.debuggerGetSource();
     sources.forEach(function(rModule) {
       Module.remoteCache[rModule[0]] = rModule[1];
     });
diff --git a/src/js/mqtt.js b/src/js/mqtt.js
new file mode 100644 (file)
index 0000000..77c8ef2
--- /dev/null
@@ -0,0 +1,337 @@
+/* Copyright 2018-present Samsung Electronics Co., Ltd. and other contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var net = require('net');
+var util = require('util');
+var EventEmitter = require('events').EventEmitter;
+
+util.inherits(MQTTClient, EventEmitter);
+
+var PacketTypeEnum = {
+  PUBACK: 4,
+  PUBREC: 5,
+  PUBREL: 6,
+  PUBCOMP: 7,
+};
+
+function MQTTClient(options) {
+  if (!(this instanceof MQTTClient)) {
+    return new MQTTClient(options);
+  }
+
+  EventEmitter.call(this);
+
+  this._clientOptions = Object.create(options, {
+    host: { value: options.host || '127.0.0.1'},
+    port: { value: options.port || 8883 },
+    qos: { value: options.qos || 0 },
+    keepalive: { value: options.keepalive || 60 },
+  });
+
+  this._socket = options.socket || new net.Socket();
+  this._socket.on('error', onerror);
+
+  this._isConnected = false;
+  this._reconnecting = false;
+  this._package_id = 0;
+
+  // Set the native callbacks
+  this._onconnect = onconnect;
+  this._ondisconnect = ondisconnect;
+  this._onmessage = onmessage;
+  this._onpingresp = onpingresp;
+  this._onpuback = onpuback;
+  this._onpubcomp = onpubcomp;
+  this._onpubrec = onpubrec;
+  this._onpubrel = onpubrel;
+  this._onsuback = onsuback;
+}
+
+/*
+ * Connect to an MQTT broker.
+ */
+function MqttConnect(socket, options) {
+  var buff = native.connect(options);
+  socket.write(buff);
+}
+
+MQTTClient.prototype.connect = function(callback) {
+  this._clientOptions.cb = callback;
+  var jsref = this;
+  if (this._socket instanceof net.Socket) {
+    this._socket = net.connect(this._clientOptions);
+    this._socket.on('connect', function() {
+      MqttConnect(this, jsref._clientOptions);
+    });
+  }
+
+  if (util.isFunction(callback)) {
+    this.on('connect', callback);
+  }
+
+  this._socket.on('data', function(data) {
+    ondata(jsref, data);
+  });
+  this._socket.on('error', function(e) {
+    jsref.emit('error', e);
+  });
+  this._socket.on('end', function() {
+    ondisconnect(jsref);
+  });
+};
+
+MQTTClient.prototype.disconnect = function(error) {
+  if (error) {
+    this.emit('error', error);
+  }
+
+  this._isConnected = false;
+  var buf = native.disconnect();
+  this._socket.write(buf);
+  this._socket.end();
+};
+
+MQTTClient.prototype.reconnect = function() {
+  if (this._reconnecting) {
+    return;
+  }
+
+  this.disconnect();
+  setTimeout(this.connect, this._options.reconnectPeriod);
+};
+
+MQTTClient.prototype.publish = function(options) {
+  if (!Buffer.isBuffer(options.message)) {
+    options.message = new Buffer(options.message);
+  }
+  if (!Buffer.isBuffer(options.topic)) {
+    options.topic = new Buffer(options.topic);
+  }
+
+  if (util.isNumber(options.qos) && options.qos > 0) {
+    options.packet_id = this._package_id;
+    this._package_id++;
+
+    var buffer = native.publish(options);
+    this._socket.write(buffer);
+
+    var self = this;
+
+    var interval = setInterval(function() {
+      self._socket.write(buffer);
+    }, 3000);
+
+    this.on('puback', function() {
+      clearInterval(interval);
+    });
+    this.on('pubrec', function() {
+      clearInterval(interval);
+    });
+
+    return;
+  }
+
+  this._socket.write(native.publish(options));
+};
+
+MQTTClient.prototype.subscribe = function(options) {
+  if (!Buffer.isBuffer(options.topic)) {
+    options.topic = new Buffer(options.topic);
+  }
+
+  var buff = native.subscribe(options);
+  this._socket.write(buff);
+};
+
+MQTTClient.prototype.ping = function() {
+  var buff = native.ping();
+  this._socket.write(buff);
+};
+
+MQTTClient.prototype.unsubscribe = function(topic) {
+  if (!Buffer.isBuffer(topic)) {
+    topic = new Buffer(topic);
+  }
+
+  var buf = native.unsubscribe(topic);
+  this._socket.write(buf);
+};
+
+MQTTClient.prototype.sendAcknowledge = function(options) {
+  var buff = native.sendAck(options);
+  this._socket.write(buff);
+};
+
+function onpubcomp(jsref, data) {
+  /*
+   * Qos level 2
+   * Handle PUBCOMP package. If this package is arrived, the sending process
+   * is done.
+   */
+  jsref.emit('pubcomp', data);
+}
+
+function onpubrel(jsref, data) {
+  /*
+   * Qos level 2
+   * Handle PUBREL package. If this package is arrived, we have to send back
+   * a PUBCOMP package to the server.
+   */
+  var options = {
+    type: PacketTypeEnum.PUBCOMP,
+    packet_id: data,
+  };
+
+  jsref.sendAcknowledge(options);
+}
+
+function ondata(jsref, data) {
+  var ret_val = native.MqttHandle(jsref, data);
+  if (ret_val instanceof Error) {
+    jsref.disconnect();
+    onerror(jsref, ret_val);
+  }
+}
+
+function onconnect(jsref) {
+  jsref.emit('connect');
+}
+
+function onpingresp(jsref) {
+  jsref.emit('pingresp');
+}
+
+function onmessage(jsref, message, topic, qos, packet_id) {
+  var data = {
+    message: message,
+    topic: topic,
+    qos: qos,
+    packet_id: packet_id,
+  };
+
+  if (qos == 1) {
+    var opts = {
+      type: PacketTypeEnum.PUBACK,
+      packet_id: packet_id,
+    };
+
+    jsref.sendAcknowledge(opts);
+  } else if (qos == 2) {
+    var options = {
+      type: PacketTypeEnum.PUBREC,
+      packet_id: packet_id,
+    };
+    jsref.sendAcknowledge(options);
+  }
+
+  jsref.emit('message', data);
+}
+
+function ondisconnect(jsref, message) {
+  jsref._isConnected = false;
+  jsref.emit('disconnect', message);
+}
+
+function onpuback(jsref, data) {
+  /*
+   * QoS level 1
+   * Handle PUBACK package. If this package isn't arrived (properly),
+   * we have to resend the last message.
+   *
+   * The 'data' contains the packet identifier.
+   */
+
+  jsref.emit('puback', data);
+}
+
+function onpubrec(jsref, data) {
+  /*
+   * Qos level 2
+   * Handle PUBREC package. If this package is arrived, we have to send back
+   * a PUBREL package to the server.
+   */
+  var options = {
+    type: PacketTypeEnum.PUBREL,
+    packet_id: data,
+  };
+
+  jsref.sendAcknowledge(options);
+
+  var interval = setInterval(function() {
+    jsref.sendAcknowledge(options);
+  }, 3000);
+
+  jsref.on('pubcomp', function() {
+    clearInterval(interval);
+  });
+
+  jsref.emit('pubrec', data);
+}
+
+function onsuback(jsref, data) {
+  /*
+   * Successful subscription, the client will get messages from the requested
+   * topic. The granted QoS is given in data.
+   */
+   jsref.emit('suback', data);
+}
+
+function onerror(jsref, error) {
+  jsref.emit('error', error);
+}
+
+/*
+ * Returns an unique client ID based on current time.
+ */
+function defaultClientId() {
+  return 'iotjs_mqtt_client_' + Date.now();
+}
+
+function getClient(connectOptions) {
+  if (util.isUndefined(connectOptions.clientId)) {
+    connectOptions.clientId = defaultClientId();
+  }
+  if (!Buffer.isBuffer(connectOptions.clientId)) {
+    connectOptions.clientId =
+        new Buffer(connectOptions.clientId.toString());
+  }
+  if (!util.isUndefined(connectOptions.username) &&
+      !Buffer.isBuffer(connectOptions.username)) {
+    connectOptions.username = new Buffer(connectOptions.username.toString());
+  }
+  if (!util.isUndefined(connectOptions.password) &&
+      !Buffer.isBuffer(connectOptions.password)) {
+    connectOptions.password = new Buffer(connectOptions.password.toString());
+  }
+  if (connectOptions.will) {
+    if (util.isUndefined(connectOptions.topic) ||
+        util.isUndefined(connectOptions.message) ||
+        connectOptions.qos < 0 || connectOptions.qos > 2) {
+      throw new Error('Wrong options given! Please refer to the documentation');
+    }
+
+    if (!util.isUndefined(connectOptions.topic) &&
+        !Buffer.isBuffer(connectOptions.topic)) {
+      connectOptions.topic = new Buffer(connectOptions.topic.toString());
+    }
+    if (!util.isUndefined(connectOptions.message) &&
+        !Buffer.isBuffer(connectOptions.message)) {
+      connectOptions.message = new Buffer(connectOptions.message.toString());
+    }
+  }
+  return new MQTTClient(connectOptions);
+}
+
+exports.getClient = getClient;
index 566011c083d961ff531cf0c75ecca30950413c63..ccce7849dcb9dfeb7544929805e93a2aa9b46489 100644 (file)
@@ -134,7 +134,7 @@ function launchAppControl(option) {
 
 
 var getResPath = function() {
-  return this.bridge.sendSync('getResPath', '');
+  return bridge.sendSync('getResPath', '');
 };
 
 
index f11a6672cb441a5ce3c02b76bea5c2ded22e0a38..9454159f1839ae0aaa022465570804689b31a85e 100644 (file)
       "js_file": "js/module.js",
       "require": ["fs"]
     },
+    "mqtt": {
+      "js_file": "js/mqtt.js",
+      "require": ["events", "util", "url"],
+      "native_files": ["modules/iotjs_module_mqtt.c"],
+      "init": "InitMQTT"
+    },
     "net": {
       "js_file": "js/net.js",
       "require": ["assert", "events", "stream", "tcp", "util"]
index 909e8d40434c70da36fb1c58200ad52bcfacdb07..f8dadb760d3552e7bc22cd580204dcb57be648cb 100644 (file)
@@ -323,6 +323,7 @@ void after_worker(uv_work_t* req, int status) {
   } else {
     uv_loop_t* loop = iotjs_environment_loop(iotjs_environment_get());
     uv_async_t* async = IOTJS_ALLOC(uv_async_t);
+    bridgecall->async = async;
     async->data = (void*)bridgecall;
     uv_async_init(loop, async, aysnc_callback);
     uv_mutex_unlock(&bridgecall->call_lock);
index a3933758b318952202ff11d1194016ef9b8d7b43..d0e264c9fca47e6a8784a1226510d87746af8b85 100644 (file)
@@ -159,11 +159,16 @@ JS_FUNCTION(ReadSync) {
 
   JS_GET_REQUIRED_ARG_VALUE(0, i2c->buf_len, IOTJS_MAGIC_STRING_LENGTH, number);
 
-  if (!iotjs_i2c_read(i2c)) {
-    return JS_CREATE_ERROR(COMMON, iotjs_periph_error_str(kI2cOpRead));
+  jerry_value_t result;
+  if (iotjs_i2c_read(i2c)) {
+    result = iotjs_jval_create_byte_array(i2c->buf_len, i2c->buf_data);
+  } else {
+    result = JS_CREATE_ERROR(COMMON, iotjs_periph_error_str(kI2cOpRead));
   }
 
-  return iotjs_jval_create_byte_array(i2c->buf_len, i2c->buf_data);
+  IOTJS_RELEASE(i2c->buf_data);
+
+  return result;
 }
 
 jerry_value_t InitI2c() {
diff --git a/src/modules/iotjs_module_mqtt.c b/src/modules/iotjs_module_mqtt.c
new file mode 100644 (file)
index 0000000..58d0ef9
--- /dev/null
@@ -0,0 +1,798 @@
+/* Copyright 2018-present Samsung Electronics Co., Ltd. and other contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "iotjs_def.h"
+#include "iotjs_module_buffer.h"
+#include "iotjs_module_mqtt.h"
+
+
+#include "iotjs_handlewrap.h"
+#include "iotjs_reqwrap.h"
+
+
+static jerry_value_t mqtt_client_connack_error(const unsigned char error_code) {
+  switch (error_code) {
+    case UNACCEPTABLE_PROTOCOL:
+      return JS_CREATE_ERROR(COMMON,
+                             "MQTT: Connection refused: unacceptable protocol");
+    case BAD_IDENTIFIER:
+      return JS_CREATE_ERROR(COMMON,
+                             "MQTT: Connection refused: bad client identifier");
+    case SERVER_UNAVIABLE:
+      return JS_CREATE_ERROR(COMMON,
+                             "MQTT: Connection refused: server unaviable");
+    case BAD_CREDENTIALS:
+      return JS_CREATE_ERROR(
+          COMMON, "MQTT: Connection refused: bad username or password");
+    case UNAUTHORISED:
+      return JS_CREATE_ERROR(COMMON, "MQTT: Connection refused: unauthorised");
+    default:
+      return JS_CREATE_ERROR(COMMON, "MQTT: Unknown error");
+  }
+}
+
+
+static uint8_t *iotjs_encode_remaining_length(unsigned char *buffer,
+                                              uint32_t len) {
+  size_t rc = 0;
+  do {
+    unsigned char d = len & 0x7F;
+    len >>= 7;
+    if (len > 0) {
+      d |= 0x80;
+    }
+    buffer[rc++] = d;
+  } while (len > 0);
+
+  return (buffer + rc);
+}
+
+
+static size_t get_remaining_length_size(uint32_t len) {
+  uint8_t n = 0;
+  while (len != 0) {
+    len >>= 7;
+    n++;
+  }
+
+  return n;
+}
+
+
+static uint32_t iotjs_decode_remaining_length(char *buffer, size_t *offset) {
+  unsigned char c;
+  uint32_t remaining_length = 0;
+  uint32_t length = 0;
+  uint32_t shift = 0;
+
+  do {
+    if (++length > IOTJS_MODULE_MQTT_MAX_REMAINING_LENGTH_BYTES) {
+      return UINT32_MAX;
+    }
+    c = (unsigned char)buffer[*offset];
+    remaining_length += (uint32_t)(c & 0x7F) << shift;
+    shift += 7;
+
+    (*offset)++;
+  } while ((c & 128) != 0);
+
+  return remaining_length;
+}
+
+
+static uint16_t iotjs_mqtt_calculate_length(uint8_t msb, uint8_t lsb) {
+  return (msb << 8) | lsb;
+}
+
+
+static uint8_t *iotjs_mqtt_string_serialize(uint8_t *dst_buffer,
+                                            iotjs_bufferwrap_t *src_buffer) {
+  uint16_t len = src_buffer->length;
+  dst_buffer[0] = (uint8_t)(len >> 8);
+  dst_buffer[1] = (uint8_t)(len & 0x00FF);
+  memcpy(dst_buffer + 2, src_buffer->buffer, src_buffer->length);
+  return (dst_buffer + 2 + src_buffer->length);
+}
+
+void iotjs_create_ack_callback(char *buffer, char *name, jerry_value_t jsref) {
+  uint8_t packet_identifier_MSB = (uint8_t)buffer[2];
+  uint8_t packet_identifier_LSB = (uint8_t)buffer[3];
+
+  uint16_t package_id =
+      iotjs_mqtt_calculate_length(packet_identifier_MSB, packet_identifier_LSB);
+
+  // The callback takes the packet identifier as parameter.
+  iotjs_jargs_t args = iotjs_jargs_create(2);
+  iotjs_jargs_append_jval(&args, jsref);
+  iotjs_jargs_append_number(&args, package_id);
+
+  jerry_value_t fn = iotjs_jval_get_property(jsref, name);
+  iotjs_make_callback(fn, jsref, &args);
+  jerry_release_value(fn);
+  iotjs_jargs_destroy(&args);
+}
+
+
+JS_FUNCTION(MqttConnect) {
+  DJS_CHECK_THIS();
+
+  DJS_CHECK_ARGS(1, object);
+
+  jerry_value_t joptions = JS_GET_ARG(0, object);
+
+  jerry_value_t jclient_id =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_CLIENTID);
+  jerry_value_t jusername =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_USERNAME);
+  jerry_value_t jpassword =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_PASSWORD);
+  jerry_value_t jkeepalive =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_KEEPALIVE);
+  jerry_value_t jwill =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_WILL);
+  jerry_value_t jqos =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_QOS);
+  jerry_value_t jmessage =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_MESSAGE);
+  jerry_value_t jtopic =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_TOPIC);
+  jerry_value_t jretain =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_TOPIC);
+
+  uint8_t connect_flags = 0;
+  uint8_t keep_alive_msb = 0;
+  uint8_t keep_alive_lsb = 10;
+  connect_flags |= MQTT_FLAG_CLEANSESSION;
+  iotjs_bufferwrap_t *username = NULL;
+  iotjs_bufferwrap_t *password = NULL;
+  iotjs_bufferwrap_t *message = NULL;
+  iotjs_bufferwrap_t *topic = NULL;
+
+  uint8_t header_byte = 0;
+  header_byte |= (CONNECT << 4);
+
+
+  if (!jerry_value_is_undefined(jwill) && jerry_get_boolean_value(jwill)) {
+    connect_flags |= MQTT_FLAG_WILL;
+    if (!jerry_value_is_undefined(jqos)) {
+      uint8_t qos = 0;
+      qos = jerry_get_number_value(qos);
+      if (qos) {
+        connect_flags |= (qos == 1) ? MQTT_FLAG_WILLQOS_1 : MQTT_FLAG_WILLQOS_2;
+      }
+    }
+
+    if (!jerry_value_is_undefined(jretain) &&
+        jerry_get_boolean_value(jretain)) {
+      connect_flags |= MQTT_FLAG_WILLRETAIN;
+    }
+    message = iotjs_bufferwrap_from_jbuffer(jmessage);
+    topic = iotjs_bufferwrap_from_jbuffer(jtopic);
+  }
+
+  if (!jerry_value_is_undefined(jusername)) {
+    connect_flags |= MQTT_FLAG_USERNAME;
+    username = iotjs_bufferwrap_from_jbuffer(jusername);
+  }
+  if (!jerry_value_is_undefined(jpassword)) {
+    connect_flags |= MQTT_FLAG_PASSWORD;
+    password = iotjs_bufferwrap_from_jbuffer(jpassword);
+  }
+  if (!jerry_value_is_undefined(jkeepalive)) {
+    uint16_t len = jerry_get_number_value(jkeepalive);
+    keep_alive_msb = (uint8_t)(len >> 8);
+    keep_alive_lsb = (uint8_t)(len & 0x00FF);
+  }
+
+
+  iotjs_bufferwrap_t *client_id = iotjs_bufferwrap_from_jbuffer(jclient_id);
+
+  unsigned char variable_header_protocol[7];
+  variable_header_protocol[0] = 0;
+  variable_header_protocol[1] = 4;
+  variable_header_protocol[2] = 'M';
+  variable_header_protocol[3] = 'Q';
+  variable_header_protocol[4] = 'T';
+  variable_header_protocol[5] = 'T';
+  variable_header_protocol[6] = 4;
+
+  size_t variable_header_len = sizeof(variable_header_protocol) +
+                               sizeof(connect_flags) + sizeof(keep_alive_lsb) +
+                               sizeof(keep_alive_msb);
+
+  size_t payload_len = client_id->length + IOTJS_MQTT_LSB_MSB_SIZE;
+  if (connect_flags & MQTT_FLAG_USERNAME) {
+    payload_len += IOTJS_MQTT_LSB_MSB_SIZE + username->length;
+  }
+  if (connect_flags & MQTT_FLAG_PASSWORD) {
+    payload_len += IOTJS_MQTT_LSB_MSB_SIZE + password->length;
+  }
+  if (connect_flags & MQTT_FLAG_WILL) {
+    payload_len += IOTJS_MQTT_LSB_MSB_SIZE + topic->length;
+    payload_len += IOTJS_MQTT_LSB_MSB_SIZE + message->length;
+  }
+  uint32_t remaining_length = payload_len + variable_header_len;
+  size_t full_len = sizeof(header_byte) +
+                    get_remaining_length_size(remaining_length) +
+                    variable_header_len + payload_len;
+
+  jerry_value_t jbuff = iotjs_bufferwrap_create_buffer(full_len);
+  iotjs_bufferwrap_t *buffer_wrap = iotjs_bufferwrap_from_jbuffer(jbuff);
+
+  uint8_t *buff_ptr = (uint8_t *)buffer_wrap->buffer;
+
+  *buff_ptr++ = header_byte;
+  buff_ptr = iotjs_encode_remaining_length(buff_ptr, remaining_length);
+
+  memcpy(buff_ptr, variable_header_protocol, sizeof(variable_header_protocol));
+  buff_ptr += sizeof(variable_header_protocol);
+  *buff_ptr++ = connect_flags;
+  *buff_ptr++ = keep_alive_msb;
+  *buff_ptr++ = keep_alive_lsb;
+
+  buff_ptr = iotjs_mqtt_string_serialize(buff_ptr, client_id);
+
+  if (connect_flags & MQTT_FLAG_WILL) {
+    buff_ptr = iotjs_mqtt_string_serialize(buff_ptr, topic);
+    buff_ptr = iotjs_mqtt_string_serialize(buff_ptr, message);
+  }
+
+  if (connect_flags & MQTT_FLAG_USERNAME) {
+    buff_ptr = iotjs_mqtt_string_serialize(buff_ptr, username);
+  }
+  if (connect_flags & MQTT_FLAG_PASSWORD) {
+    buff_ptr = iotjs_mqtt_string_serialize(buff_ptr, password);
+  }
+
+  jerry_release_value(jretain);
+  jerry_release_value(jtopic);
+  jerry_release_value(jmessage);
+  jerry_release_value(jqos);
+  jerry_release_value(jwill);
+  jerry_release_value(jkeepalive);
+  jerry_release_value(jclient_id);
+  jerry_release_value(jusername);
+  jerry_release_value(jpassword);
+
+  return jbuff;
+}
+
+
+JS_FUNCTION(MqttPublish) {
+  DJS_CHECK_THIS();
+
+  DJS_CHECK_ARGS(1, object);
+
+  jerry_value_t joptions = JS_GET_ARG(0, object);
+
+  jerry_value_t jmessage =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_MESSAGE);
+  jerry_value_t jtopic =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_TOPIC);
+  jerry_value_t jretain =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_RETAIN);
+  jerry_value_t jqos =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_QOS);
+  jerry_value_t jpacket_id =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_PACKETID);
+
+  uint8_t qos = 0;
+  if (jerry_value_is_number(jqos)) {
+    qos = jerry_get_number_value(jqos);
+  }
+
+  bool dup = false;
+
+  uint8_t header_byte = 0;
+  header_byte |= (PUBLISH << 4);
+  header_byte |= (dup << 3);
+  header_byte |= (qos << 1);
+  header_byte |= (jerry_get_boolean_value(jretain));
+
+  iotjs_bufferwrap_t *message_payload = iotjs_bufferwrap_from_jbuffer(jmessage);
+  iotjs_bufferwrap_t *topic_payload = iotjs_bufferwrap_from_jbuffer(jtopic);
+
+  uint8_t packet_identifier_lsb = 0;
+  uint8_t packet_identifier_msb = 0;
+
+  if (qos > 0 && jerry_value_is_number(jpacket_id)) {
+    uint16_t packet_identifier = jerry_get_number_value(jpacket_id);
+    packet_identifier_msb = (uint8_t)(packet_identifier >> 8);
+    packet_identifier_lsb = (uint8_t)(packet_identifier & 0x00FF);
+  }
+
+  size_t payload_len = message_payload->length + IOTJS_MQTT_LSB_MSB_SIZE;
+  size_t variable_header_len = topic_payload->length + IOTJS_MQTT_LSB_MSB_SIZE +
+                               sizeof(packet_identifier_msb) +
+                               sizeof(packet_identifier_lsb);
+  uint32_t remaining_length = payload_len + variable_header_len;
+  size_t full_len = sizeof(header_byte) +
+                    get_remaining_length_size(remaining_length) +
+                    variable_header_len + payload_len;
+
+  jerry_value_t jbuff = iotjs_bufferwrap_create_buffer(full_len);
+  iotjs_bufferwrap_t *buffer_wrap = iotjs_bufferwrap_from_jbuffer(jbuff);
+
+  uint8_t *buff_ptr = (uint8_t *)buffer_wrap->buffer;
+
+  *buff_ptr++ = header_byte;
+  buff_ptr = iotjs_encode_remaining_length(buff_ptr, remaining_length);
+  buff_ptr = iotjs_mqtt_string_serialize(buff_ptr, topic_payload);
+  *buff_ptr++ = packet_identifier_msb;
+  *buff_ptr++ = packet_identifier_lsb;
+
+  // Don't need to put length before the payload, so we can't use the
+  // iotjs_mqtt_string_serialize. The broker and the other clients calculate
+  // the payload length from remaining length and the topic length.
+  memcpy(buff_ptr, message_payload->buffer, message_payload->length);
+
+  jerry_release_value(jmessage);
+  jerry_release_value(jtopic);
+  jerry_release_value(jretain);
+
+  return jbuff;
+}
+
+
+JS_FUNCTION(MqttHandle) {
+  DJS_CHECK_THIS();
+  DJS_CHECK_ARGS(2, object, object);
+
+  jerry_value_t jsref = JS_GET_ARG(0, object);
+  jerry_value_t jparam = JS_GET_ARG(1, object);
+
+  iotjs_bufferwrap_t *buffer_wrap = iotjs_bufferwrap_from_jbuffer(jparam);
+  char *buffer = buffer_wrap->buffer;
+
+  char first_byte = buffer[0];
+  char packet_type = (first_byte >> 4) & 0x0F;
+
+  size_t offset = 1;
+  uint32_t remaining_length = iotjs_decode_remaining_length(buffer, &offset);
+
+  switch (packet_type) {
+    case CONNACK: {
+      if (remaining_length != 2) {
+        return JS_CREATE_ERROR(COMMON, "MQTT: CONNACK packet is corrupted");
+      }
+
+      uint8_t return_code = (uint8_t)buffer[++offset];
+
+      if (return_code != 0) {
+        return mqtt_client_connack_error(return_code);
+      }
+
+      jerry_value_t fn =
+          iotjs_jval_get_property(jsref, IOTJS_MAGIC_STRING__ONCONNECT);
+      iotjs_jargs_t jargs = iotjs_jargs_create(1);
+      iotjs_jargs_append_jval(&jargs, jsref);
+      iotjs_make_callback(fn, jsref, &jargs);
+
+      iotjs_jargs_destroy(&jargs);
+      jerry_release_value(fn);
+      break;
+    }
+    case PUBLISH: {
+      MQTTHeader header = { 0 };
+      header.bits.type = PUBLISH;
+      header.bits.dup = first_byte & 0x08;
+      header.bits.qos = (first_byte & 0x06) >> 1;
+      header.bits.retain = first_byte & 0x01;
+
+      uint8_t topic_length_MSB = (uint8_t)buffer[offset];
+      offset += sizeof(topic_length_MSB);
+
+      uint8_t topic_length_LSB = (uint8_t)buffer[offset];
+      offset += sizeof(topic_length_LSB);
+
+      uint16_t topic_length =
+          iotjs_mqtt_calculate_length(topic_length_MSB, topic_length_LSB);
+
+      jerry_value_t jtopic = iotjs_bufferwrap_create_buffer(topic_length);
+      iotjs_bufferwrap_t *topic_wrap = iotjs_bufferwrap_from_jbuffer(jtopic);
+
+      memcpy(topic_wrap->buffer, buffer + offset, topic_length);
+      offset += topic_length;
+
+      // The Packet Identifier field is only present in PUBLISH packets
+      // where the QoS level is 1 or 2.
+      uint16_t packet_identifier = 0;
+      if (header.bits.qos > 0) {
+        uint8_t packet_identifier_MSB = 0;
+        uint8_t packet_identifier_LSB = 0;
+
+
+        memcpy(&packet_identifier_MSB, buffer + offset, sizeof(uint8_t));
+        offset += sizeof(packet_identifier_MSB);
+
+        memcpy(&packet_identifier_LSB, buffer + offset, sizeof(uint8_t));
+        offset += sizeof(packet_identifier_LSB);
+
+        packet_identifier = iotjs_mqtt_calculate_length(packet_identifier_MSB,
+                                                        packet_identifier_LSB);
+      }
+
+      size_t payload_length =
+          (size_t)remaining_length - topic_length - sizeof(topic_length);
+
+      if (header.bits.qos > 0) {
+        payload_length -= sizeof(packet_identifier);
+      }
+
+      jerry_value_t jmessage = iotjs_bufferwrap_create_buffer(payload_length);
+      iotjs_bufferwrap_t *msg_wrap = iotjs_bufferwrap_from_jbuffer(jmessage);
+
+      IOTJS_ASSERT(jerry_is_valid_utf8_string((const uint8_t *)msg_wrap->buffer,
+                                              msg_wrap->length));
+
+      IOTJS_ASSERT(
+          jerry_is_valid_utf8_string((const uint8_t *)topic_wrap->buffer,
+                                     topic_wrap->length));
+
+      memcpy(msg_wrap->buffer, buffer + offset, payload_length);
+      offset += payload_length;
+
+      iotjs_jargs_t args = iotjs_jargs_create(5);
+      iotjs_jargs_append_jval(&args, jsref);
+      iotjs_jargs_append_string_raw(&args, msg_wrap->buffer);
+      iotjs_jargs_append_string_raw(&args, topic_wrap->buffer);
+      iotjs_jargs_append_number(&args, header.bits.qos);
+      iotjs_jargs_append_number(&args, packet_identifier);
+
+      jerry_value_t fn =
+          iotjs_jval_get_property(jsref, IOTJS_MAGIC_STRING__ONMESSAGE);
+      iotjs_make_callback(fn, jsref, &args);
+      jerry_release_value(fn);
+
+      iotjs_jargs_destroy(&args);
+      jerry_release_value(jmessage);
+      jerry_release_value(jtopic);
+
+      break;
+    }
+    case PUBACK: {
+      if (remaining_length != 2) {
+        return JS_CREATE_ERROR(COMMON, "MQTT: PUBACK packet is corrupted");
+      }
+
+      iotjs_create_ack_callback(buffer, IOTJS_MAGIC_STRING__ONPUBACK, jsref);
+      break;
+    }
+    case PUBREC: {
+      if (remaining_length != 2) {
+        return JS_CREATE_ERROR(COMMON, "MQTT: RUBREC packet is corrupted");
+      }
+
+      iotjs_create_ack_callback(buffer, IOTJS_MAGIC_STRING__ONPUBREC, jsref);
+      break;
+    }
+    case PUBREL: {
+      if (remaining_length != 2) {
+        return JS_CREATE_ERROR(COMMON, "MQTT: PUBREL packet is corrupted");
+      }
+
+      char control_packet_reserved = first_byte & 0x0F;
+      if (control_packet_reserved != 2) {
+        return JS_CREATE_ERROR(COMMON, "MQTT: PUBREL packet is corrupted");
+      }
+
+      iotjs_create_ack_callback(buffer, IOTJS_MAGIC_STRING__ONPUBREL, jsref);
+      break;
+    }
+    case PUBCOMP: {
+      if (remaining_length != 2) {
+        return JS_CREATE_ERROR(COMMON, "MQTT: PUBCOMP packet is corrupted");
+      }
+
+      iotjs_create_ack_callback(buffer, IOTJS_MAGIC_STRING__ONPUBCOMP, jsref);
+      break;
+    }
+    case SUBACK: {
+      // We assume that only one topic was in the SUBSCRIBE packet.
+      if (remaining_length != 3) {
+        return JS_CREATE_ERROR(COMMON, "MQTT: SUBACK packet is corrupted");
+      }
+
+      uint8_t return_code = (uint8_t)buffer[4];
+      if (return_code == 128) {
+        return JS_CREATE_ERROR(COMMON, "MQTT: Subscription was unsuccessful");
+      }
+
+      // The callback takes the granted QoS as parameter.
+      iotjs_jargs_t args = iotjs_jargs_create(2);
+      iotjs_jargs_append_jval(&args, jsref);
+      iotjs_jargs_append_number(&args, return_code);
+
+      jerry_value_t sub_fn =
+          iotjs_jval_get_property(jsref, IOTJS_MAGIC_STRING__ONSUBACK);
+      iotjs_make_callback(sub_fn, jsref, &args);
+      jerry_release_value(sub_fn);
+      iotjs_jargs_destroy(&args);
+      break;
+    }
+    case UNSUBACK: {
+      if (remaining_length != 2) {
+        return JS_CREATE_ERROR(COMMON, "MQTT: UNSUBACK packet is corrupted");
+      }
+
+      iotjs_create_ack_callback(buffer, IOTJS_MAGIC_STRING__ONUNSUBACK, jsref);
+      break;
+    }
+    case PINGRESP: {
+      if (remaining_length != 0) {
+        return JS_CREATE_ERROR(COMMON, "MQTT: PingRESP packet is corrupted");
+      }
+      jerry_value_t fn =
+          iotjs_jval_get_property(jsref, IOTJS_MAGIC_STRING__ONPINGRESP);
+      iotjs_jargs_t jargs = iotjs_jargs_create(1);
+      iotjs_jargs_append_jval(&jargs, jsref);
+      iotjs_make_callback(fn, jsref, &jargs);
+      jerry_release_value(fn);
+      iotjs_jargs_destroy(&jargs);
+      break;
+    }
+    case DISCONNECT: {
+      iotjs_jargs_t jargs = iotjs_jargs_create(2);
+      iotjs_jargs_append_jval(&jargs, jsref);
+      jerry_value_t str_arg = jerry_create_string(
+          (jerry_char_t *)"The broker disconnected the client");
+      iotjs_jargs_append_jval(&jargs, str_arg);
+      jerry_value_t fn =
+          iotjs_jval_get_property(jsref, IOTJS_MAGIC_STRING__ONDISCONNECT);
+      iotjs_make_callback(fn, jsref, &jargs);
+      jerry_release_value(str_arg);
+      jerry_release_value(fn);
+      iotjs_jargs_destroy(&jargs);
+      break;
+    }
+
+    case CONNECT:
+    case SUBSCRIBE:
+    case UNSUBSCRIBE:
+    case PINGREQ:
+      return JS_CREATE_ERROR(
+          COMMON, "MQTT: Unallowed packet has arrived to the client");
+  }
+
+  return jerry_create_undefined();
+}
+
+
+JS_FUNCTION(MqttSubscribe) {
+  DJS_CHECK_THIS();
+  DJS_CHECK_ARGS(1, object);
+
+  jerry_value_t joptions = JS_GET_ARG(0, object);
+
+  jerry_value_t jtopic =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_TOPIC);
+  jerry_value_t jqos =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_QOS);
+
+  uint8_t qos = 0;
+  if (jerry_value_is_number(jqos)) {
+    qos = (uint8_t)jerry_get_number_value(jqos);
+  }
+
+  bool dup = false;
+  bool retain = false;
+
+  uint8_t header_byte = 0;
+  header_byte |= (SUBSCRIBE << 4);
+  header_byte |= (dup << 3);
+  header_byte |= (1 << 1); // always 1
+  header_byte |= retain;
+
+  iotjs_bufferwrap_t *topic_payload = iotjs_bufferwrap_from_jbuffer(jtopic);
+
+  uint8_t packet_identifier_lsb = 0;
+  uint8_t packet_identifier_msb = 0;
+
+  size_t payload_len =
+      sizeof(qos) + topic_payload->length + IOTJS_MQTT_LSB_MSB_SIZE;
+  size_t variable_header_len =
+      sizeof(packet_identifier_msb) + sizeof(packet_identifier_lsb);
+  uint32_t remaining_length = payload_len + variable_header_len;
+  size_t full_len = sizeof(header_byte) +
+                    get_remaining_length_size(remaining_length) +
+                    variable_header_len + payload_len;
+
+  jerry_value_t jbuff = iotjs_bufferwrap_create_buffer(full_len);
+  iotjs_bufferwrap_t *buffer_wrap = iotjs_bufferwrap_from_jbuffer(jbuff);
+
+  uint8_t *buff_ptr = (uint8_t *)buffer_wrap->buffer;
+
+  *buff_ptr++ = header_byte;
+
+  buff_ptr = iotjs_encode_remaining_length(buff_ptr, remaining_length);
+
+  *buff_ptr++ = packet_identifier_msb;
+  *buff_ptr++ = packet_identifier_lsb;
+
+  buff_ptr = iotjs_mqtt_string_serialize(buff_ptr, topic_payload);
+
+  buff_ptr[0] = qos;
+
+  jerry_release_value(jtopic);
+  jerry_release_value(jqos);
+
+  return jbuff;
+}
+
+
+JS_FUNCTION(MqttPing) {
+  DJS_CHECK_THIS();
+
+  uint8_t header_byte = 0;
+  header_byte |= (PINGREQ << 4);
+
+  uint8_t remaining_length = 0;
+  size_t full_len = sizeof(header_byte) + sizeof(remaining_length);
+
+  jerry_value_t jbuff = iotjs_bufferwrap_create_buffer(full_len);
+  iotjs_bufferwrap_t *buffer_wrap = iotjs_bufferwrap_from_jbuffer(jbuff);
+
+  uint8_t *buff_ptr = (uint8_t *)buffer_wrap->buffer;
+
+  buff_ptr[0] = header_byte;
+  buff_ptr[1] = remaining_length;
+
+  return jbuff;
+}
+
+
+JS_FUNCTION(MqttUnsubscribe) {
+  DJS_CHECK_THIS();
+  DJS_CHECK_ARGS(1, object);
+
+  jerry_value_t jtopic = JS_GET_ARG(0, object);
+
+  iotjs_bufferwrap_t *topic_payload = iotjs_bufferwrap_from_jbuffer(jtopic);
+
+  uint8_t header_byte = 0;
+  header_byte |= (UNSUBSCRIBE << 4);
+  // Reserved
+  header_byte |= (1 << 1);
+
+  uint8_t packet_identifier_msb = 0;
+  uint8_t packet_identifier_lsb = 0;
+
+  size_t payload_len = topic_payload->length + IOTJS_MQTT_LSB_MSB_SIZE;
+  size_t variable_header_len =
+      sizeof(packet_identifier_msb) + sizeof(packet_identifier_lsb);
+  uint32_t remaining_length = payload_len + variable_header_len;
+  size_t full_len = sizeof(header_byte) +
+                    get_remaining_length_size(remaining_length) +
+                    variable_header_len + payload_len;
+
+  jerry_value_t jbuff = iotjs_bufferwrap_create_buffer(full_len);
+  iotjs_bufferwrap_t *buffer_wrap = iotjs_bufferwrap_from_jbuffer(jbuff);
+
+  uint8_t *buff_ptr = (uint8_t *)buffer_wrap->buffer;
+
+  *buff_ptr++ = header_byte;
+
+  buff_ptr = iotjs_encode_remaining_length(buff_ptr, remaining_length);
+
+  *buff_ptr++ = packet_identifier_msb;
+  *buff_ptr++ = packet_identifier_lsb;
+
+  buff_ptr = iotjs_mqtt_string_serialize(buff_ptr, topic_payload);
+
+  return jbuff;
+}
+
+
+JS_FUNCTION(MqttDisconnect) {
+  DJS_CHECK_THIS();
+
+  uint8_t header_byte = 0;
+  uint8_t remaining_length = 0;
+  header_byte |= (DISCONNECT << 4);
+
+  size_t full_len = sizeof(header_byte) + sizeof(remaining_length);
+
+  jerry_value_t jbuff = iotjs_bufferwrap_create_buffer(full_len);
+  iotjs_bufferwrap_t *buffer_wrap = iotjs_bufferwrap_from_jbuffer(jbuff);
+
+  uint8_t *buff_ptr = (uint8_t *)buffer_wrap->buffer;
+
+  buff_ptr[0] = header_byte;
+  buff_ptr[1] = remaining_length;
+
+  return jbuff;
+}
+
+JS_FUNCTION(MqttSendAck) {
+  DJS_CHECK_THIS();
+  DJS_CHECK_ARGS(1, object);
+
+  jerry_value_t joptions = JS_GET_ARG(0, object);
+  jerry_value_t jack_type =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_ACKTYPE);
+  jerry_value_t jpacket_id =
+      iotjs_jval_get_property(joptions, IOTJS_MAGIC_STRING_PACKETID);
+
+  uint16_t packet_id = 0;
+  if (!jerry_value_is_undefined(jpacket_id)) {
+    packet_id = (uint16_t)jerry_get_number_value(jpacket_id);
+  }
+
+  uint8_t ack_type = 0;
+  if (!jerry_value_is_undefined(jack_type)) {
+    ack_type = (uint8_t)jerry_get_number_value(jack_type);
+  }
+
+  uint8_t header_byte = 0;
+  uint8_t remaining_length = 2;
+
+  switch (ack_type) {
+    case PUBACK: {
+      header_byte |= (PUBACK << 4);
+      break;
+    }
+    case PUBREC: {
+      header_byte |= (PUBREC << 4);
+      break;
+    }
+    case PUBREL: {
+      header_byte |= (PUBREL << 4);
+      header_byte |= 2;
+      break;
+    }
+    case PUBCOMP: {
+      header_byte |= (PUBCOMP << 4);
+      break;
+    }
+  }
+
+  uint8_t packet_identifier_msb = (uint8_t)(packet_id >> 8);
+  uint8_t packet_identifier_lsb = (uint8_t)(packet_id & 0x00FF);
+
+  size_t full_len =
+      sizeof(header_byte) + sizeof(remaining_length) + sizeof(packet_id);
+
+  jerry_value_t jbuff = iotjs_bufferwrap_create_buffer(full_len);
+  iotjs_bufferwrap_t *buffer_wrap = iotjs_bufferwrap_from_jbuffer(jbuff);
+
+  uint8_t *buff_ptr = (uint8_t *)buffer_wrap->buffer;
+
+  buff_ptr[0] = header_byte;
+  buff_ptr[1] = remaining_length;
+  buff_ptr[2] = packet_identifier_msb;
+  buff_ptr[3] = packet_identifier_lsb;
+
+  jerry_release_value(jpacket_id);
+  jerry_release_value(jack_type);
+
+  return jbuff;
+}
+
+jerry_value_t InitMQTT() {
+  jerry_value_t jMQTT = jerry_create_object();
+  iotjs_jval_set_method(jMQTT, IOTJS_MAGIC_STRING_CONNECT, MqttConnect);
+  iotjs_jval_set_method(jMQTT, IOTJS_MAGIC_STRING_DISCONNECT, MqttDisconnect);
+  iotjs_jval_set_method(jMQTT, IOTJS_MAGIC_STRING_MQTTHANDLE, MqttHandle);
+  iotjs_jval_set_method(jMQTT, IOTJS_MAGIC_STRING_PING, MqttPing);
+  iotjs_jval_set_method(jMQTT, IOTJS_MAGIC_STRING_PUBLISH, MqttPublish);
+  iotjs_jval_set_method(jMQTT, IOTJS_MAGIC_STRING_SENDACK, MqttSendAck);
+  iotjs_jval_set_method(jMQTT, IOTJS_MAGIC_STRING_SUBSCRIBE, MqttSubscribe);
+  iotjs_jval_set_method(jMQTT, IOTJS_MAGIC_STRING_UNSUBSCRIBE, MqttUnsubscribe);
+
+  return jMQTT;
+}
diff --git a/src/modules/iotjs_module_mqtt.h b/src/modules/iotjs_module_mqtt.h
new file mode 100644 (file)
index 0000000..4a1f8e2
--- /dev/null
@@ -0,0 +1,130 @@
+/* Copyright 2018-present Samsung Electronics Co., Ltd. and other contributors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IOTJS_MODULE_MQTT_H
+#define IOTJS_MODULE_MQTT_H
+
+#include "iotjs_def.h"
+
+#define IOTJS_MODULE_MQTT_MAX_REMAINING_LENGTH_BYTES 4
+#define IOTJS_MQTT_LSB_MSB_SIZE 2
+
+/*
+ * The types of the control packet.
+ * These values determine the aim of the message.
+ */
+enum {
+  CONNECT = 0x1,
+  CONNACK = 0x2,
+  PUBLISH = 0x3,
+  PUBACK = 0x4,
+  PUBREC = 0x5,
+  PUBREL = 0x6,
+  PUBCOMP = 0x7,
+  SUBSCRIBE = 0x8,
+  SUBACK = 0x9,
+  UNSUBSCRIBE = 0xA,
+  UNSUBACK = 0xB,
+  PINGREQ = 0xC,
+  PINGRESP = 0xD,
+  DISCONNECT = 0xE
+} iotjs_mqtt_control_packet_type;
+
+/*
+ * The values of the Quality of Service.
+ */
+enum {
+  QoS0 = 0, // At most once delivery.
+  QoS1 = 1, // At least once delivery.
+  QoS2 = 2  // Exactly once delivery.
+} iotjs_mqtt_quality_of_service;
+
+enum {
+  UNACCEPTABLE_PROTOCOL = 1,
+  BAD_IDENTIFIER = 2,
+  SERVER_UNAVIABLE = 3,
+  BAD_CREDENTIALS = 4,
+  UNAUTHORISED = 5
+} iotjs_mqtt_connection_error;
+
+/*
+ * First byte of the message's fixed header.
+ * Contains:
+ * - MQTT Control Packet type,
+ * - Specific flags to each MQTT Control Packet.
+ */
+typedef struct {
+  uint8_t RETAIN : 1;    // PUBLISH Retain flag.
+  unsigned char QoS : 2; // PUBLISH Quality of Service.
+  uint8_t DUP : 1;       // Duplicate delivery of PUBLISH Control Packet.
+  unsigned char packet_type : 4;
+} iotjs_mqtt_control_packet_t;
+
+/*
+ * The fixed header of the MQTT message structure.
+ */
+typedef struct {
+  iotjs_mqtt_control_packet_t packet;
+  uint8_t remaining_length;
+} iotjs_mqtt_fixed_header_t;
+
+/*
+ * Type of the MQTT CONNECT message.
+ */
+
+typedef union {
+  unsigned char byte;
+
+  struct {
+    uint8_t retain : 1;
+    uint8_t qos : 2;
+    uint8_t dup : 1;
+    uint8_t type : 4;
+  } bits;
+} MQTTHeader;
+
+enum {
+  // Reserved bit, must be 0
+  MQTT_FLAG_RESERVED = 1 << 0,
+  // Clean session bit
+  MQTT_FLAG_CLEANSESSION = 1 << 1,
+  /**
+   * If the will flag is set to 1 Will QoS and Will Retain flags must be
+   * also set to 1, and be present in the payload. Otherwise, both must be set
+   * to 0.
+   */
+  MQTT_FLAG_WILL = 1 << 2,
+  /**
+   * QoS can only be set, if the Will flag is set to 1. Otherwise it's 0x00.
+   * QoS types are as follows:
+   * Type 0: Both QoS bits are set to 0 (0x00)
+   * Type 1: WILLQOS_1 is set to 1, WILLQOS_2 is set to 0 (0x01)
+   * Type 2: WILLQOS_2 is set to 1, WILLQOS_1 is set to 0 (0x02)
+   */
+  MQTT_FLAG_WILLQOS_1 = 1 << 3,
+  MQTT_FLAG_WILLQOS_2 = 1 << 4,
+  /**
+   * Will retain flag can only be set to 1 if Will flag is set to 1 as well.
+   * If retain is set to 1, the server must publish will message as a retained
+   * message.
+   */
+  MQTT_FLAG_WILLRETAIN = 1 << 5,
+  // Whether password is sent by the user
+  MQTT_FLAG_PASSWORD = 1 << 6,
+  // Whether username is sent
+  MQTT_FLAG_USERNAME = 1 << 7
+} iotjs_mqtt_connect_flag_t;
+
+#endif /* IOTJS_MODULE_MQTT_H */
index 66ab7396e1705392d93dd071e12e398affc1e6d0..157fc3923dee7b82793309cdd4d7aff9e1f70ce1 100644 (file)
@@ -242,7 +242,8 @@ void SetNativeSources(jerry_value_t native_sources) {
 
 
 static void SetProcessEnv(jerry_value_t process) {
-  const char *homedir, *iotjspath, *iotjsenv, *extra_module_path;
+  const char *homedir, *iotjspath, *iotjsenv, *extra_module_path,
+      *working_dir_path;
 
   homedir = getenv(IOTJS_MAGIC_STRING_HOME_U);
   if (homedir == NULL) {
@@ -265,6 +266,7 @@ static void SetProcessEnv(jerry_value_t process) {
 #endif
 
   extra_module_path = getenv(IOTJS_MAGIC_STRING_IOTJS_EXTRA_MODULE_PATH_U);
+  working_dir_path = getenv(IOTJS_MAGIC_STRING_IOTJS_WORKING_DIR_PATH_U);
 
   jerry_value_t env = jerry_create_object();
   iotjs_jval_set_property_string_raw(env, IOTJS_MAGIC_STRING_HOME_U, homedir);
@@ -275,6 +277,9 @@ static void SetProcessEnv(jerry_value_t process) {
   iotjs_jval_set_property_string_raw(
       env, IOTJS_MAGIC_STRING_IOTJS_EXTRA_MODULE_PATH_U,
       extra_module_path ? extra_module_path : "");
+  iotjs_jval_set_property_string_raw(
+      env, IOTJS_MAGIC_STRING_IOTJS_WORKING_DIR_PATH_U,
+      working_dir_path ? working_dir_path : "");
 
   iotjs_jval_set_property_jval(process, IOTJS_MAGIC_STRING_ENV, env);
 
@@ -322,18 +327,33 @@ static void SetBuiltinModules(jerry_value_t builtin_modules) {
   }
 }
 
+static void SetProcessPrivate(jerry_value_t process, bool wait_source) {
+  jerry_value_t private = jerry_create_object();
+  iotjs_jval_set_property_jval(process, IOTJS_MAGIC_STRING_PRIVATE, private);
+
+  iotjs_jval_set_method(private, IOTJS_MAGIC_STRING_COMPILE, Compile);
+  iotjs_jval_set_method(private, IOTJS_MAGIC_STRING_COMPILEMODULE,
+                        CompileModule);
+  iotjs_jval_set_method(private, IOTJS_MAGIC_STRING_READSOURCE, ReadSource);
+
+  // debugger
+  iotjs_jval_set_method(private, IOTJS_MAGIC_STRING_DEBUGGERGETSOURCE,
+                        DebuggerGetSource);
+
+  jerry_value_t wait_source_val = jerry_create_boolean(wait_source);
+  iotjs_jval_set_property_jval(private, IOTJS_MAGIC_STRING_DEBUGGERWAITSOURCE,
+                               wait_source_val);
+
+  jerry_release_value(wait_source_val);
+  jerry_release_value(private);
+}
+
 
 jerry_value_t InitProcess() {
   jerry_value_t process = jerry_create_object();
 
-  iotjs_jval_set_method(process, IOTJS_MAGIC_STRING_COMPILE, Compile);
-  iotjs_jval_set_method(process, IOTJS_MAGIC_STRING_COMPILEMODULE,
-                        CompileModule);
-  iotjs_jval_set_method(process, IOTJS_MAGIC_STRING_READSOURCE, ReadSource);
   iotjs_jval_set_method(process, IOTJS_MAGIC_STRING_CWD, Cwd);
   iotjs_jval_set_method(process, IOTJS_MAGIC_STRING_CHDIR, Chdir);
-  iotjs_jval_set_method(process, IOTJS_MAGIC_STRING_DEBUGGERGETSOURCE,
-                        DebuggerGetSource);
   iotjs_jval_set_method(process, IOTJS_MAGIC_STRING_DOEXIT, DoExit);
   SetProcessEnv(process);
 
@@ -358,22 +378,17 @@ jerry_value_t InitProcess() {
 
   // Set iotjs
   SetProcessIotjs(process);
-  bool wait_source;
+  bool wait_source = false;
   if (iotjs_environment_config(iotjs_environment_get())->debugger != NULL) {
     wait_source = iotjs_environment_config(iotjs_environment_get())
                       ->debugger->wait_source;
-  } else {
-    wait_source = false;
   }
 
   if (!wait_source) {
     SetProcessArgv(process);
   }
 
-  jerry_value_t wait_source_val = jerry_create_boolean(wait_source);
-  iotjs_jval_set_property_jval(process, IOTJS_MAGIC_STRING_DEBUGGERWAITSOURCE,
-                               wait_source_val);
-  jerry_release_value(wait_source_val);
+  SetProcessPrivate(process, wait_source);
 
   return process;
 }
index d58b871030b439fe99505d72563267b0bc33a946..9d00793fcd0d9004dec32f5b07dd822af6a57389 100644 (file)
 #include "modules/iotjs_module_bridge.h"
 
 #include <app_common.h>
-#include <app_control.h>
-#include <bundle.h>
+#include <stdlib.h>
 
 typedef enum {
-  IOTJS_ERROR_NONE = 0,
-  IOTJS_ERROR_RESULT_FAILED,
+  IOTJS_ERROR_RESULT_FAILED = INT_MIN,
   IOTJS_ERROR_INVALID_PARAMETER,
+  IOTJS_ERROR_OUT_OF_MEMORY,
+  IOTJS_ERROR_NONE = 0,
 } iotjs_error_t;
 
-// application control
+// # tizen app-control
+#include <app_control.h>
 #include <app_control_internal.h>
+#include <bundle.h>
 #include <bundle_internal.h>
 
-iotjs_error_t send_launch_request(const char* json, void* hbridge) {
+static iotjs_error_t tizen_send_launch_request(const char* json,
+                                               void* hbridge) {
   DDDLOG("%s", __func__);
 
   bundle* b;
@@ -87,7 +90,7 @@ iotjs_error_t send_launch_request(const char* json, void* hbridge) {
 }
 
 
-void iotjs_service_app_control_cb(app_control_h app_control, void* user_data) {
+void iotjs_tizen_app_control_cb(app_control_h app_control, void* user_data) {
   DDDLOG("%s", __func__);
 
   iotjs_environment_t* env = iotjs_environment_get();
@@ -123,7 +126,7 @@ void iotjs_service_app_control_cb(app_control_h app_control, void* user_data) {
 
   iotjs_make_callback(fn, tizen, &jargv);
 
-  IOTJS_RELEASE(json);
+  free(json);
   bundle_free(b);
 
   jerry_release_value(fn);
@@ -131,16 +134,20 @@ void iotjs_service_app_control_cb(app_control_h app_control, void* user_data) {
 }
 
 
+// # tizen bridge
 void iotjs_tizen_func(const char* command, const char* message, void* handle) {
   DDDLOG("%s, cmd: %s, msg: %s", __func__, command, message);
 
   if (strncmp(command, "getResPath", strlen("getResPath")) == 0) {
     char* app_res_path = app_get_resource_path();
     iotjs_bridge_set_msg(handle, app_res_path);
+    if (app_res_path != NULL) {
+      free(app_res_path);
+    }
 
   } else if (strncmp(command, "launchAppControl", strlen("launchAppControl")) ==
              0) {
-    iotjs_error_t err = send_launch_request(message, handle);
+    iotjs_error_t err = tizen_send_launch_request(message, handle);
     if (err == IOTJS_ERROR_NONE) {
       iotjs_bridge_set_msg(handle, "OK");
     }
@@ -149,3 +156,107 @@ void iotjs_tizen_func(const char* command, const char* message, void* handle) {
     iotjs_bridge_set_err(handle, "Can't find command");
   }
 }
+
+
+// # tizen bridge-native
+typedef void (*user_callback_t)(int error, const char* data);
+
+typedef struct {
+  uv_async_t async;
+  char* module;
+  char* fn_name;
+  char* message;
+  user_callback_t cb;
+} iotjs_call_jfunc_t;
+
+
+static char* create_string_buffer(const char* src, size_t size) {
+  char* dest = IOTJS_CALLOC(size + 1, char);
+  strncpy(dest, src, size);
+  dest[size] = '\0'; // just for being sure
+  return dest;
+}
+
+
+static bool bridge_native_call(const char* module_name, const char* func_name,
+                               const char* message,
+                               iotjs_string_t* output_str) {
+  bool result = false;
+
+  jerry_value_t jmodule = iotjs_module_get(module_name);
+  jerry_value_t jfunc = iotjs_jval_get_property(jmodule, func_name);
+
+  if (jerry_value_is_function(jfunc) == false) {
+    return result;
+  }
+
+  iotjs_jargs_t jargv = iotjs_jargs_create(1);
+  iotjs_jargs_append_string_raw(&jargv, message);
+  jerry_value_t jres = iotjs_make_callback_with_result(jfunc, jmodule, &jargv);
+
+  if (jerry_value_is_string(jres)) {
+    IOTJS_ASSERT(output_str != NULL);
+    *output_str = iotjs_jval_as_string(jres);
+    result = true;
+  }
+
+  jerry_release_value(jfunc);
+  jerry_release_value(jres);
+  iotjs_jargs_destroy(&jargv);
+  return result;
+}
+
+
+static void bridge_native_async_handler(uv_async_t* handle) {
+  DDDLOG("%s\n", __func__);
+  iotjs_call_jfunc_t* data = (iotjs_call_jfunc_t*)handle->data;
+
+  bool result;
+  iotjs_string_t output;
+
+  result = bridge_native_call(IOTJS_MAGIC_STRING_TIZEN, data->fn_name,
+                              data->message, &output);
+
+  if (data->cb) {
+    data->cb((int)!result, iotjs_string_data(&output));
+  }
+
+  iotjs_string_destroy(&output);
+
+  // release
+  uv_close((uv_handle_t*)&data->async, NULL);
+  IOTJS_RELEASE(data->module);
+  IOTJS_RELEASE(data->fn_name);
+  IOTJS_RELEASE(data->message);
+  IOTJS_RELEASE(data);
+}
+
+
+int iotjs_tizen_bridge_native(const char* fn_name, unsigned fn_name_size,
+                              const char* message, unsigned message_size,
+                              user_callback_t cb) {
+  iotjs_environment_t* env = iotjs_environment_get();
+
+  if (env->state != kRunningMain && env->state != kRunningLoop) {
+    return IOTJS_ERROR_RESULT_FAILED;
+  }
+
+  iotjs_call_jfunc_t* handle = IOTJS_ALLOC(iotjs_call_jfunc_t);
+
+  if (handle == NULL) {
+    return IOTJS_ERROR_OUT_OF_MEMORY;
+  }
+
+  handle->async.data = (void*)handle;
+  handle->fn_name = create_string_buffer(fn_name, fn_name_size);
+  handle->message = create_string_buffer(message, message_size);
+  handle->module = create_string_buffer(IOTJS_MAGIC_STRING_TIZEN,
+                                        sizeof(IOTJS_MAGIC_STRING_TIZEN));
+  handle->cb = cb;
+
+  uv_loop_t* loop = iotjs_environment_loop(env);
+  uv_async_init(loop, &handle->async, bridge_native_async_handler);
+  uv_async_send(&handle->async);
+
+  return IOTJS_ERROR_NONE;
+}
index 56d58472a3615f01f32cfd242291deb765412f50..7024e48b3bb661fc0cfd138c9e6a9c19be41552d 100644 (file)
@@ -180,8 +180,11 @@ int iotjs_service_app_start(int argc, char** argv, char* js_path,
     return 1;
   }
 
+  // The JavaScript entry file is located in application res directory.
   snprintf(js_absolute_path, sizeof(js_absolute_path), "%s%s", app_res_path,
            js_path);
+  setenv(IOTJS_MAGIC_STRING_IOTJS_WORKING_DIR_PATH_U, app_res_path, 1);
+
   IOTJS_RELEASE(app_res_path);
 
   service_app_loop_method_s loop_method = {.init = loop_method_init_cb,
index eb56a88a6ccdcd4349a46c425169a73fbc2602ea..7c6932286da7555d0d1be6ddcf80ff5fa04b97da 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef IOTJS_TIZEN_SERVICE_APP_H
 #define IOTJS_TIZEN_SERVICE_APP_H
 
+#include <app_control.h>
+#include <string.h>
 
 #ifdef __cplusplus
 #define IOTJS_EXTERN_C extern "C"
 #define IOTJS_EXTERN_C extern
 #endif /* !__cplusplus */
 
+typedef void (*user_callback_t)(int error, const char* data);
+
 
 IOTJS_EXTERN_C int iotjs_service_app_start(int argc, char** argv, char* js_path,
                                            void* event_callbacks,
                                            void* user_data);
 
+IOTJS_EXTERN_C
+void iotjs_tizen_app_control_cb(app_control_h app_control, void* user_data);
+
+IOTJS_EXTERN_C
+int iotjs_tizen_bridge_native(const char* fn_name, unsigned fn_name_size,
+                              const char* message, unsigned message_size,
+                              user_callback_t cb);
+
+#define IOTJS_TIZEN_CALL_JFUNC(name, msg, cb)                              \
+  ({                                                                       \
+    if (name != NULL && (msg) != NULL)                                     \
+      iotjs_tizen_bridge_native(name, strlen(name), msg, strlen(msg), cb); \
+  })
+
 
 #endif /* IOTJS_TIZEN_SERVICE_APP_H */
diff --git a/test/run_pass/issue/issue-1351.js b/test/run_pass/issue/issue-1351.js
deleted file mode 100644 (file)
index afa4c73..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright 2017-present Samsung Electronics Co., Ltd. and other contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var assert = require('assert');
-var fs = require('fs');
-
-var filePath = process.cwd() + '/resources';
-
-try {
-  process.readSource(filePath);
-} catch (e) {
-  assert.equal(fs.existsSync(filePath), true);
-  assert.equal(e.name, 'Error');
-  assert.equal(e.message, 'ReadSource error, not a regular file');
-}
diff --git a/test/run_pass/test_process_readsource.js b/test/run_pass/test_process_readsource.js
deleted file mode 100644 (file)
index a582d44..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright 2017-present Samsung Electronics Co., Ltd. and other contributors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-var assert = require('assert');
-
-var json_file = process.cwd() + "/resources/process/package.json";
-
-// Load a JSON file.
-var str = process.readSource(json_file);
-var json = JSON.parse(str);
-
-assert.equal(json.version, "2.9.1");
-assert.equal(json.name, "npm");
-assert.equal(json.main, "./lib/npm.js");
-assert.equal(json.repository.type, "git");
index 23e8f49a9237722f35d5c1bcac3e80fff126d5bc..dd0ee23c0b1b8453786db19cf97c3f57f2b05e0a 100644 (file)
@@ -86,7 +86,6 @@
     { "name": "test_process_experimental_off.js", "skip": ["experimental"], "reason": "needed if testing stablity is set with stable" },
     { "name": "test_process_experimental_on.js", "skip": ["stable"], "reason": "needed if testing stablity is set with experimental" },
     { "name": "test_process_next_tick.js" },
-    { "name": "test_process_readsource.js" },
     { "name": "test_process_uncaught_order.js" },
     { "name": "test_process_uncaught_simple.js" },
     { "name": "test_pwm_async.js", "skip": ["all"], "reason": "need to setup test environment" },
     { "name": "issue-1077.js" },
     { "name": "issue-1101.js", "skip": ["all"], "reason": "need to setup test environment" },
     { "name": "issue-1348.js" },
-    { "name": "issue-1351.js" },
     { "name": "issue-1485.js" },
     { "name": "issue-1507.js" },
     { "name": "issue-1557.js" }
index d5568bc61a894b9cb93af93a89b7247b14bfd528..aa8c87b89dbc5927eb271e047b31f03bc68b84b4 100644 (file)
@@ -25,12 +25,19 @@ if (process.platform === 'linux') {
   pin.spi1 = '/dev/spidev0.0';
   pin.uart1 = '/dev/ttyS0';
 } else if (process.platform === 'tizen') {
-  pin.led = 20;
-  pin.switch = 13;
-  pin.pwm1 = 2;
+  if (process.iotjs.board === 'rpi3') {
+    pin.led = 20;
+    pin.switch = 13;
+    pin.spi1 = 0;
+    pin.uart1 = 0;
+  } else if (process.iotjs.board === 'artik530') {
+    pin.led = 128;
+    pin.switch = 27;
+    pin.pwm1 = 2;
+    pin.spi1 = 2;
+    pin.uart1 = 4;
+  }
   pin.i2c1 = 1;
-  pin.spi1 = 0;
-  pin.uart1 = 0;
 } else if (process.platform === 'nuttx') {
   var stm32_pin = require('stm32f4dis').pin;
   pin.led = stm32_pin.PA10;
index 91250e3dec90588358385f0467db52215fdc876b..b30bf61197132cbb66e17800d38773df10469a32 100755 (executable)
@@ -71,130 +71,126 @@ def init_options():
     argv = argv + sys.argv[1:]
 
     # Prepare argument parser.
-    parser = argparse.ArgumentParser()
+    parser = argparse.ArgumentParser(description='Building tool for IoT.js '
+        'JavaScript framework for embedded systems.')
 
-    parser.add_argument('--buildtype',
+    iotjs_group = parser.add_argument_group('Arguments of IoT.js',
+        'The following arguments are related to the IoT.js framework.')
+    iotjs_group.add_argument('--buildtype',
         choices=['debug', 'release'], default='debug',
-        help='Specify the build type: %(choices)s (default: %(default)s)')
-
-    parser.add_argument('--builddir', default=path.BUILD_ROOT,
+        help='Specify the build type (default: %(default)s).')
+    iotjs_group.add_argument('--builddir', default=path.BUILD_ROOT,
         help='Specify the build directory (default: %(default)s)')
-    parser.add_argument('--buildlib', action='store_true', default=False,
-        help='Build IoT.js library only (default: %(default)s)')
-
-    parser.add_argument('--clean', action='store_true', default=False,
-        help='Clean build directory before build (default: %(default)s)')
-
-    parser.add_argument('--config', default=path.BUILD_CONFIG_PATH,
-        help='Specify the config file (default: %(default)s)',
-        dest='config_path')
-
-    parser.add_argument('--profile',
-        help='Specify the module profile file for IoT.js')
-
-    parser.add_argument('--target-arch',
-        choices=['arm', 'x86', 'i686', 'x86_64', 'x64', 'mips', 'noarch'],
-        default=platform.arch(),
-        help='Specify the target architecture: '
-             '%(choices)s (default: %(default)s)')
-    parser.add_argument('--target-os',
-        choices=['linux', 'darwin', 'osx', 'nuttx', 'tizen', 'tizenrt',
-                 'openwrt'],
-        default=platform.os(),
-        help='Specify the target os: %(choices)s (default: %(default)s)')
-
-    parser.add_argument('--target-board',
-        choices=[None, 'artik10', 'stm32f4dis', 'rpi2', 'rpi3', 'artik05x'],
-        default=None, help='Specify the target board (if needed): '
-             '%(choices)s (default: %(default)s)')
-    parser.add_argument('--nuttx-home', default=None, dest='sysroot',
-        help='Specify the NuttX base directory (required for NuttX build)')
-
-    parser.add_argument('--sysroot', action='store',
-        help='The location of the development tree root directory (sysroot).'
-        'Must be compatible with used toolchain.')
-
-    parser.add_argument('--cmake-param',
+    iotjs_group.add_argument('--buildlib', action='store_true', default=False,
+        help='Build IoT.js static library only (default: %(default)s)')
+    iotjs_group.add_argument('--create-shared-lib',
+        action='store_true', default=False,
+        help='Create shared library (default: %(default)s)')
+    iotjs_group.add_argument('--cmake-param',
         action='append', default=[],
         help='Specify additional cmake parameters '
              '(can be used multiple times)')
-    parser.add_argument('--compile-flag',
+    iotjs_group.add_argument('--compile-flag',
         action='append', default=[],
         help='Specify additional compile flags (can be used multiple times)')
-    parser.add_argument('--link-flag',
-        action='append', default=[],
-        help='Specify additional linker flags (can be used multiple times)')
-
-    parser.add_argument('--external-include-dir',
+    iotjs_group.add_argument('--clean', action='store_true', default=False,
+        help='Clean build directory before build (default: %(default)s)')
+    iotjs_group.add_argument('--config', default=path.BUILD_CONFIG_PATH,
+        help='Specify the config file (default: %(default)s)',
+        dest='config_path')
+    iotjs_group.add_argument('-e', '--experimental',
+        action='store_true', default=False,
+        help='Enable to build experimental features')
+    iotjs_group.add_argument('--external-include-dir',
         action='append', default=[],
         help='Specify additional external include directory '
              '(can be used multiple times)')
-    parser.add_argument('--external-lib',
+    iotjs_group.add_argument('--external-lib',
         action='append', default=[],
         help='Specify additional external library '
              '(can be used multiple times)')
-
-    parser.add_argument('--external-modules',
+    iotjs_group.add_argument('--external-modules',
         action='store', default=set(), type=lambda x: set(x.split(',')),
         help='Specify the path of modules.json files which should be processed '
              '(format: path1,path2,...)')
+    iotjs_group.add_argument('--link-flag',
+        action='append', default=[],
+        help='Specify additional linker flags (can be used multiple times)')
+    iotjs_group.add_argument('--no-check-valgrind',
+        action='store_true', default=False,
+        help='Disable test execution with valgrind after build')
+    iotjs_group.add_argument('--no-init-submodule',
+        action='store_true', default=False,
+        help='Disable initialization of git submodules')
+    iotjs_group.add_argument('--no-parallel-build',
+        action='store_true', default=False,
+        help='Disable parallel build')
+    iotjs_group.add_argument('--no-snapshot',
+        action='store_true', default=False,
+        help='Disable snapshot generation for IoT.js')
+    iotjs_group.add_argument('--nuttx-home', default=None, dest='sysroot',
+        help='Specify the NuttX base directory (required for NuttX build)')
+    iotjs_group.add_argument('--profile',
+        help='Specify the module profile file for IoT.js')
+    iotjs_group.add_argument('--run-test',
+        nargs='?', default=False, const="quiet", choices=["full", "quiet"],
+        help='Execute tests after build, optional argument specifies '
+             'the level of output for the testrunner')
+    iotjs_group.add_argument('--sysroot', action='store',
+        help='The location of the development tree root directory (sysroot). '
+             'Must be compatible with used toolchain.')
+    iotjs_group.add_argument('--target-arch',
+        choices=['arm', 'x86', 'i686', 'x86_64', 'x64', 'mips', 'noarch'],
+        default=platform.arch(),
+        help='Specify the target architecture (default: %(default)s).')
+    iotjs_group.add_argument('--target-board',
+        choices=[None, 'artik10', 'stm32f4dis', 'rpi2', 'rpi3', 'artik05x'],
+        default=None, help='Specify the target board (default: %(default)s).')
+    iotjs_group.add_argument('--target-os',
+        choices=['linux', 'darwin', 'osx', 'nuttx', 'tizen', 'tizenrt',
+                 'openwrt'],
+        default=platform.os(),
+        help='Specify the target OS (default: %(default)s).')
+    iotjs_group.add_argument('--testsets',
+        help='Specify the additional testsets file for IoT.js')
 
-    parser.add_argument('--jerry-cmake-param',
+
+    jerry_group = parser.add_argument_group('Arguments of JerryScript',
+        'The following arguments are related to the JavaScript engine under '
+        'the framework. For example they can change the enabled features of '
+        'the ECMA-262 standard.')
+    jerry_group.add_argument('--jerry-cmake-param',
         action='append', default=[],
         help='Specify additional cmake parameters for JerryScript '
-        '(can be used multiple times')
-    parser.add_argument('--jerry-compile-flag',
+        '(can be used multiple times)')
+    jerry_group.add_argument('--jerry-compile-flag',
         action='append', default=[],
         help='Specify additional compile flags for JerryScript '
-             '(can be used multiple times')
-    parser.add_argument('--jerry-lto',
+             '(can be used multiple times)')
+    jerry_group.add_argument('--jerry-debugger',
         action='store_true', default=False,
-        help='Build JerryScript with LTO enabled')
-
-    parser.add_argument('--jerry-heap-section',
-        action='store', default=None,
-        help='Specify the name of the JerryScript heap section')
-    parser.add_argument('--jerry-heaplimit',
+        help='Enable JerryScript-debugger')
+    jerry_group.add_argument('--jerry-heaplimit',
         type=int, default=build_config['jerry-heaplimit'],
         help='Specify the size of the JerryScript max heap size '
              '(default: %(default)s)')
-
-    parser.add_argument('--jerry-memstat',
+    jerry_group.add_argument('--jerry-heap-section',
+        action='store', default=None,
+        help='Specify the name of the JerryScript heap section')
+    jerry_group.add_argument('--jerry-lto',
+        action='store_true', default=False,
+        help='Build JerryScript with LTO enabled')
+    jerry_group.add_argument('--jerry-memstat',
         action='store_true', default=False,
         help='Enable JerryScript heap statistics')
-
-    parser.add_argument('--jerry-profile',
+    jerry_group.add_argument('--jerry-profile',
         choices=['es5.1', 'es2015-subset'], default='es5.1',
-        help='Specify the profile for JerryScript: %(choices)s'
-             ' (default: %(default)s)')
-    parser.add_argument('--jerry-debugger',
-        action='store_true', default=False,
-        help='Enable JerryScript-debugger')
-    parser.add_argument('--no-init-submodule',
-        action='store_true', default=False,
-        help='Disable initialization of git submodules')
-    parser.add_argument('--no-check-valgrind',
-        action='store_true', default=False,
-        help='Disable test execution with valgrind after build')
-    parser.add_argument('--run-test',
-        nargs='?', default=False, const="quiet", choices=["full", "quiet"],
-        help='Execute tests after build, optional argument specifies '
-             'the level of output for the testrunner')
-    parser.add_argument('--no-parallel-build',
-        action='store_true', default=False,
-        help='Disable parallel build')
-    parser.add_argument('--no-snapshot',
-        action='store_true', default=False,
-        help='Disable snapshot generation for IoT.js')
-    parser.add_argument('--js-backtrace',
+        help='Specify the profile for JerryScript (default: %(default)s).')
+    jerry_group.add_argument('--js-backtrace',
         choices=['ON', 'OFF'], type=str.upper,
         help='Enable/disable backtrace information of JavaScript code '
-        '(%(choices)s; default: ON in debug and OFF in release build)')
-    parser.add_argument('-e', '--experimental',
-        action='store_true', default=False,
-        help='Enable to build experimental features')
-    parser.add_argument('--testsets',
-        help='Specify the additional testsets file for IoT.js')
+             '(default: ON in debug and OFF in release build)')
+
 
     options = parser.parse_args(argv)
     options.config = build_config
@@ -318,6 +314,7 @@ def build_iotjs(options):
         '-DENABLE_LTO=%s' % get_on_off(options.jerry_lto), # --jerry-lto
         '-DENABLE_SNAPSHOT=%s' % get_on_off(not options.no_snapshot),
         '-DBUILD_LIB_ONLY=%s' % get_on_off(options.buildlib), # --buildlib
+        '-DCREATE_SHARED_LIB=%s' % get_on_off(options.create_shared_lib),
         # --jerry-memstat
         '-DFEATURE_MEM_STATS=%s' % get_on_off(options.jerry_memstat),
         # --external-modules
diff --git a/tools/check_sonarqube.sh b/tools/check_sonarqube.sh
new file mode 100755 (executable)
index 0000000..977dff8
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# Copyright 2018-present Samsung Electronics Co., Ltd. and other contributors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if [[ -n "${TRAVIS_PULL_REQUEST_SLUG}" &&
+         "${TRAVIS_PULL_REQUEST_SLUG}" != "${TRAVIS_REPO_SLUG}" ]]; then
+  echo "Skip: The pull request from ${TRAVIS_PULL_REQUEST_SLUG} is an \
+  external one. It's not supported yet in Travis-CI";
+else
+  git fetch --unshallow;
+  build-wrapper-linux-x86-64 --out-dir bw-output ./tools/build.py;
+  sonar-scanner;
+fi