From dfa9938cad6af2df6a989abe33ccc94533eec3e7 Mon Sep 17 00:00:00 2001 From: Gyeonghwan Hong Date: Wed, 4 Sep 2019 19:03:52 +0900 Subject: [PATCH] Separate Selective Connection subproject into another repository --- .gitmodules | 3 + subprojects/sc/.gitignore | 26 - subprojects/sc/README.md | 128 -- subprojects/sc/android/.project | 17 - .../org.eclipse.buildship.core.prefs | 2 - subprojects/sc/android/Readme.md | 1 - subprojects/sc/android/app/.classpath | 6 - subprojects/sc/android/app/.gitignore | 1 - subprojects/sc/android/app/.project | 23 - .../org.eclipse.buildship.core.prefs | 2 - subprojects/sc/android/app/build.gradle | 29 - subprojects/sc/android/app/proguard-rules.pro | 17 - .../testapp/ExampleInstrumentedTest.java | 26 - .../android/app/src/main/AndroidManifest.xml | 29 - .../android/app/src/main/ic_launcher-web.png | Bin 30254 -> 0 bytes .../main/java/com/redcarrottt/sc/api/API.java | 44 - .../redcarrottt/sc/api/OnStartSCResult.java | 21 - .../redcarrottt/sc/api/OnStopSCResult.java | 21 - .../sc/internal/ClientAdapter.java | 901 ------------ .../internal/ClientAdapterStateListener.java | 21 - .../redcarrottt/sc/internal/ClientSocket.java | 120 -- .../sc/internal/ControlMessageListener.java | 23 - .../sc/internal/ControlMessageProtocol.java | 35 - .../sc/internal/ControlMessageReceiver.java | 195 --- .../sc/internal/ControlMessageSender.java | 69 - .../com/redcarrottt/sc/internal/Core.java | 357 ----- .../com/redcarrottt/sc/internal/Device.java | 117 -- .../redcarrottt/sc/internal/ExpConfig.java | 25 - .../sc/internal/NetworkSwitcher.java | 306 ---- .../sc/internal/OnConnectResult.java | 5 - .../sc/internal/OnDisconnectResult.java | 5 - .../sc/internal/OnDiscoverResult.java | 5 - .../redcarrottt/sc/internal/P2PClient.java | 196 --- .../sc/internal/ProtocolManager.java | 126 -- .../sc/internal/SegmentManager.java | 488 ------- .../sc/internal/bt/BtClientAdapter.java | 32 - .../redcarrottt/sc/internal/bt/BtDevice.java | 110 -- .../sc/internal/bt/BtP2PClient.java | 32 - .../sc/internal/bt/RfcommClientSocket.java | 141 -- .../sc/internal/wfd/TcpClientSocket.java | 162 --- .../sc/internal/wfd/WfdClientAdapter.java | 61 - .../sc/internal/wfd/WfdDevice.java | 101 -- .../sc/internal/wfd/WfdP2PClient.java | 390 ----- .../redcarrottt/testapp/CommInitializer.java | 197 --- .../java/com/redcarrottt/testapp/Logger.java | 126 -- .../com/redcarrottt/testapp/MainActivity.java | 461 ------ .../app/src/main/res/layout/activity_main.xml | 52 - .../android/app/src/main/res/layout/item.xml | 10 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 2891 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 1772 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4115 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 6635 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 9706 -> 0 bytes .../app/src/main/res/values-w820dp/dimens.xml | 6 - .../app/src/main/res/values/colors.xml | 6 - .../app/src/main/res/values/dimens.xml | 5 - .../app/src/main/res/values/strings.xml | 3 - .../app/src/main/res/values/styles.xml | 11 - .../redcarrottt/testapp/ExampleUnitTest.java | 17 - subprojects/sc/android/build.gradle | 24 - subprojects/sc/android/gradle.properties | 17 - .../android/gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - subprojects/sc/android/gradlew | 160 --- subprojects/sc/android/gradlew.bat | 90 -- subprojects/sc/android/settings.gradle | 1 - subprojects/sc/linux/LICENSE | 126 -- subprojects/sc/linux/bin/.git_empty_file | 0 .../sc/linux/common/inc/ArrivalTimeCounter.h | 64 - .../sc/linux/common/inc/ChildProcess.h | 37 - subprojects/sc/linux/common/inc/Counter.h | 181 --- subprojects/sc/linux/common/inc/DebugLog.h | 132 -- subprojects/sc/linux/common/inc/RefCount.h | 52 - .../sc/linux/common/src/ChildProcess.cpp | 154 -- subprojects/sc/linux/common/src/DebugLog.cpp | 64 - subprojects/sc/linux/configs/ExpConfig.h | 42 - .../sc/linux/configs/NetworkSwitcherConfig.h | 44 - subprojects/sc/linux/configs/PathConfig.h | 30 - subprojects/sc/linux/configs/WfdConfig.h | 38 - subprojects/sc/linux/core/inc/API.h | 46 - subprojects/sc/linux/core/inc/APIInternal.h | 28 - .../linux/core/inc/ControlMessageProtocol.h | 60 - .../linux/core/inc/ControlMessageReceiver.h | 64 - .../sc/linux/core/inc/ControlMessageSender.h | 48 - subprojects/sc/linux/core/inc/Core.h | 237 ---- subprojects/sc/linux/core/inc/Device.h | 73 - .../sc/linux/core/inc/NetworkMonitor.h | 131 -- .../sc/linux/core/inc/NetworkSwitcher.h | 182 --- subprojects/sc/linux/core/inc/P2PServer.h | 70 - .../sc/linux/core/inc/ProtocolManager.h | 65 - .../sc/linux/core/inc/ReceiverThread.h | 132 -- subprojects/sc/linux/core/inc/Segment.h | 45 - .../sc/linux/core/inc/SegmentManager.h | 215 --- subprojects/sc/linux/core/inc/SegmentQueue.h | 125 -- subprojects/sc/linux/core/inc/SenderThread.h | 186 --- subprojects/sc/linux/core/inc/ServerAdapter.h | 245 ---- .../sc/linux/core/inc/ServerAdapterState.h | 38 - .../core/inc/ServerAdapterStateListener.h | 36 - subprojects/sc/linux/core/inc/ServerSocket.h | 68 - subprojects/sc/linux/core/src/API.cpp | 88 -- .../linux/core/src/ControlMessageReceiver.cpp | 187 --- .../linux/core/src/ControlMessageSender.cpp | 124 -- subprojects/sc/linux/core/src/Core.cpp | 315 ----- subprojects/sc/linux/core/src/Device.cpp | 76 - .../sc/linux/core/src/NetworkMonitor.cpp | 336 ----- .../sc/linux/core/src/NetworkSwitcher.cpp | 431 ------ subprojects/sc/linux/core/src/P2PServer.cpp | 68 - .../sc/linux/core/src/ProtocolManager.cpp | 138 -- .../sc/linux/core/src/ReceiverThread.cpp | 139 -- .../sc/linux/core/src/SegmentManager.cpp | 398 ------ .../sc/linux/core/src/SenderThread.cpp | 214 --- .../sc/linux/core/src/ServerAdapter.cpp | 531 ------- .../sc/linux/core/src/ServerSocket.cpp | 90 -- subprojects/sc/linux/device/inc/BtDevice.h | 43 - subprojects/sc/linux/device/inc/BtP2PServer.h | 43 - .../sc/linux/device/inc/BtServerAdapter.h | 66 - .../sc/linux/device/inc/CommInitializer.h | 36 - .../sc/linux/device/inc/EthServerAdapter.h | 80 -- .../sc/linux/device/inc/RfcommServerSocket.h | 77 - .../sc/linux/device/inc/TcpServerSocket.h | 71 - subprojects/sc/linux/device/inc/WfdDevice.h | 44 - .../linux/device/inc/WfdIpAddressListener.h | 30 - .../sc/linux/device/inc/WfdP2PServer.h | 90 -- .../sc/linux/device/inc/WfdServerAdapter.h | 65 - subprojects/sc/linux/device/src/BtDevice.cpp | 50 - .../sc/linux/device/src/BtP2PServer.cpp | 33 - .../sc/linux/device/src/BtServerAdapter.cpp | 24 - .../sc/linux/device/src/CommInitializer.cpp | 118 -- .../sc/linux/device/src/EthServerAdapter.cpp | 24 - .../linux/device/src/RfcommServerSocket.cpp | 294 ---- .../sc/linux/device/src/TcpServerSocket.cpp | 180 --- subprojects/sc/linux/device/src/WfdDevice.cpp | 47 - .../sc/linux/device/src/WfdP2PServer.cpp | 453 ------ .../sc/linux/device/src/WfdServerAdapter.cpp | 24 - subprojects/sc/linux/exp/csv.h | 1252 ----------------- subprojects/sc/linux/exp/trace_runner.cpp | 262 ---- subprojects/sc/linux/script/bt_off.sh | 2 - subprojects/sc/linux/script/bt_on.sh | 2 - subprojects/sc/linux/script/monitor-wpa.sh | 14 - subprojects/sc/linux/script/status.sh | 10 - subprojects/sc/linux/script/wfd_off.sh | 7 - subprojects/sc/linux/script/wfd_on.sh | 3 - subprojects/sc/linux/tests/comm_init.cpp | 120 -- subprojects/sc/linux/tests/udhcpd.cpp | 101 -- subprojects/sc/linux/tests/wpa_cli.cpp | 45 - subprojects/sc/workload/video_client.sh | 2 - subprojects/sc/workload/video_server.sh | 2 - subprojects/selective-connection | 1 + 148 files changed, 4 insertions(+), 15515 deletions(-) delete mode 100644 subprojects/sc/.gitignore delete mode 100644 subprojects/sc/README.md delete mode 100644 subprojects/sc/android/.project delete mode 100644 subprojects/sc/android/.settings/org.eclipse.buildship.core.prefs delete mode 100644 subprojects/sc/android/Readme.md delete mode 100644 subprojects/sc/android/app/.classpath delete mode 100755 subprojects/sc/android/app/.gitignore delete mode 100644 subprojects/sc/android/app/.project delete mode 100644 subprojects/sc/android/app/.settings/org.eclipse.buildship.core.prefs delete mode 100755 subprojects/sc/android/app/build.gradle delete mode 100755 subprojects/sc/android/app/proguard-rules.pro delete mode 100755 subprojects/sc/android/app/src/androidTest/java/com/redcarrottt/testapp/ExampleInstrumentedTest.java delete mode 100755 subprojects/sc/android/app/src/main/AndroidManifest.xml delete mode 100644 subprojects/sc/android/app/src/main/ic_launcher-web.png delete mode 100755 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/API.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStartSCResult.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStopSCResult.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapter.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapterStateListener.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientSocket.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageListener.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageProtocol.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageReceiver.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageSender.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Core.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Device.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ExpConfig.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/NetworkSwitcher.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnConnectResult.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDisconnectResult.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDiscoverResult.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/P2PClient.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ProtocolManager.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/SegmentManager.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtClientAdapter.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtDevice.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtP2PClient.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/RfcommClientSocket.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/TcpClientSocket.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdClientAdapter.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdDevice.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdP2PClient.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/CommInitializer.java delete mode 100644 subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/Logger.java delete mode 100755 subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/MainActivity.java delete mode 100755 subprojects/sc/android/app/src/main/res/layout/activity_main.xml delete mode 100644 subprojects/sc/android/app/src/main/res/layout/item.xml delete mode 100755 subprojects/sc/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100755 subprojects/sc/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100755 subprojects/sc/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100755 subprojects/sc/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100755 subprojects/sc/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100755 subprojects/sc/android/app/src/main/res/values-w820dp/dimens.xml delete mode 100755 subprojects/sc/android/app/src/main/res/values/colors.xml delete mode 100755 subprojects/sc/android/app/src/main/res/values/dimens.xml delete mode 100755 subprojects/sc/android/app/src/main/res/values/strings.xml delete mode 100755 subprojects/sc/android/app/src/main/res/values/styles.xml delete mode 100755 subprojects/sc/android/app/src/test/java/com/redcarrottt/testapp/ExampleUnitTest.java delete mode 100755 subprojects/sc/android/build.gradle delete mode 100755 subprojects/sc/android/gradle.properties delete mode 100755 subprojects/sc/android/gradle/wrapper/gradle-wrapper.jar delete mode 100755 subprojects/sc/android/gradle/wrapper/gradle-wrapper.properties delete mode 100755 subprojects/sc/android/gradlew delete mode 100755 subprojects/sc/android/gradlew.bat delete mode 100755 subprojects/sc/android/settings.gradle delete mode 100644 subprojects/sc/linux/LICENSE delete mode 100644 subprojects/sc/linux/bin/.git_empty_file delete mode 100644 subprojects/sc/linux/common/inc/ArrivalTimeCounter.h delete mode 100644 subprojects/sc/linux/common/inc/ChildProcess.h delete mode 100644 subprojects/sc/linux/common/inc/Counter.h delete mode 100644 subprojects/sc/linux/common/inc/DebugLog.h delete mode 100644 subprojects/sc/linux/common/inc/RefCount.h delete mode 100644 subprojects/sc/linux/common/src/ChildProcess.cpp delete mode 100644 subprojects/sc/linux/common/src/DebugLog.cpp delete mode 100644 subprojects/sc/linux/configs/ExpConfig.h delete mode 100644 subprojects/sc/linux/configs/NetworkSwitcherConfig.h delete mode 100644 subprojects/sc/linux/configs/PathConfig.h delete mode 100644 subprojects/sc/linux/configs/WfdConfig.h delete mode 100644 subprojects/sc/linux/core/inc/API.h delete mode 100644 subprojects/sc/linux/core/inc/APIInternal.h delete mode 100644 subprojects/sc/linux/core/inc/ControlMessageProtocol.h delete mode 100644 subprojects/sc/linux/core/inc/ControlMessageReceiver.h delete mode 100644 subprojects/sc/linux/core/inc/ControlMessageSender.h delete mode 100644 subprojects/sc/linux/core/inc/Core.h delete mode 100644 subprojects/sc/linux/core/inc/Device.h delete mode 100644 subprojects/sc/linux/core/inc/NetworkMonitor.h delete mode 100644 subprojects/sc/linux/core/inc/NetworkSwitcher.h delete mode 100644 subprojects/sc/linux/core/inc/P2PServer.h delete mode 100644 subprojects/sc/linux/core/inc/ProtocolManager.h delete mode 100644 subprojects/sc/linux/core/inc/ReceiverThread.h delete mode 100644 subprojects/sc/linux/core/inc/Segment.h delete mode 100644 subprojects/sc/linux/core/inc/SegmentManager.h delete mode 100644 subprojects/sc/linux/core/inc/SegmentQueue.h delete mode 100644 subprojects/sc/linux/core/inc/SenderThread.h delete mode 100644 subprojects/sc/linux/core/inc/ServerAdapter.h delete mode 100644 subprojects/sc/linux/core/inc/ServerAdapterState.h delete mode 100644 subprojects/sc/linux/core/inc/ServerAdapterStateListener.h delete mode 100644 subprojects/sc/linux/core/inc/ServerSocket.h delete mode 100644 subprojects/sc/linux/core/src/API.cpp delete mode 100644 subprojects/sc/linux/core/src/ControlMessageReceiver.cpp delete mode 100644 subprojects/sc/linux/core/src/ControlMessageSender.cpp delete mode 100644 subprojects/sc/linux/core/src/Core.cpp delete mode 100644 subprojects/sc/linux/core/src/Device.cpp delete mode 100644 subprojects/sc/linux/core/src/NetworkMonitor.cpp delete mode 100644 subprojects/sc/linux/core/src/NetworkSwitcher.cpp delete mode 100644 subprojects/sc/linux/core/src/P2PServer.cpp delete mode 100644 subprojects/sc/linux/core/src/ProtocolManager.cpp delete mode 100644 subprojects/sc/linux/core/src/ReceiverThread.cpp delete mode 100644 subprojects/sc/linux/core/src/SegmentManager.cpp delete mode 100644 subprojects/sc/linux/core/src/SenderThread.cpp delete mode 100644 subprojects/sc/linux/core/src/ServerAdapter.cpp delete mode 100644 subprojects/sc/linux/core/src/ServerSocket.cpp delete mode 100644 subprojects/sc/linux/device/inc/BtDevice.h delete mode 100644 subprojects/sc/linux/device/inc/BtP2PServer.h delete mode 100644 subprojects/sc/linux/device/inc/BtServerAdapter.h delete mode 100644 subprojects/sc/linux/device/inc/CommInitializer.h delete mode 100644 subprojects/sc/linux/device/inc/EthServerAdapter.h delete mode 100644 subprojects/sc/linux/device/inc/RfcommServerSocket.h delete mode 100644 subprojects/sc/linux/device/inc/TcpServerSocket.h delete mode 100644 subprojects/sc/linux/device/inc/WfdDevice.h delete mode 100644 subprojects/sc/linux/device/inc/WfdIpAddressListener.h delete mode 100644 subprojects/sc/linux/device/inc/WfdP2PServer.h delete mode 100644 subprojects/sc/linux/device/inc/WfdServerAdapter.h delete mode 100644 subprojects/sc/linux/device/src/BtDevice.cpp delete mode 100644 subprojects/sc/linux/device/src/BtP2PServer.cpp delete mode 100644 subprojects/sc/linux/device/src/BtServerAdapter.cpp delete mode 100644 subprojects/sc/linux/device/src/CommInitializer.cpp delete mode 100644 subprojects/sc/linux/device/src/EthServerAdapter.cpp delete mode 100644 subprojects/sc/linux/device/src/RfcommServerSocket.cpp delete mode 100644 subprojects/sc/linux/device/src/TcpServerSocket.cpp delete mode 100644 subprojects/sc/linux/device/src/WfdDevice.cpp delete mode 100644 subprojects/sc/linux/device/src/WfdP2PServer.cpp delete mode 100644 subprojects/sc/linux/device/src/WfdServerAdapter.cpp delete mode 100644 subprojects/sc/linux/exp/csv.h delete mode 100644 subprojects/sc/linux/exp/trace_runner.cpp delete mode 100755 subprojects/sc/linux/script/bt_off.sh delete mode 100755 subprojects/sc/linux/script/bt_on.sh delete mode 100755 subprojects/sc/linux/script/monitor-wpa.sh delete mode 100755 subprojects/sc/linux/script/status.sh delete mode 100755 subprojects/sc/linux/script/wfd_off.sh delete mode 100755 subprojects/sc/linux/script/wfd_on.sh delete mode 100644 subprojects/sc/linux/tests/comm_init.cpp delete mode 100644 subprojects/sc/linux/tests/udhcpd.cpp delete mode 100644 subprojects/sc/linux/tests/wpa_cli.cpp delete mode 100755 subprojects/sc/workload/video_client.sh delete mode 100755 subprojects/sc/workload/video_server.sh create mode 160000 subprojects/selective-connection diff --git a/.gitmodules b/.gitmodules index f9ecabc0..6aa63c6d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "android/libs/armeabi"] path = android/libs/armeabi url = https://github.com/SKKU-ESLAB/ant-android-libs-armeabi.git +[submodule "subprojects/selective-connection"] + path = subprojects/selective-connection + url = https://github.com/SKKU-ESLAB/selective-connection diff --git a/subprojects/sc/.gitignore b/subprojects/sc/.gitignore deleted file mode 100644 index cafe80e5..00000000 --- a/subprojects/sc/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -tags -cscope -cscope.out -.vscode -*.o -bin/* -dhcpd.conf -!bin/.git_empty_file -SelectiveConnection.IAB -SelectiveConnection.IAD -SelectiveConnection.IMB -SelectiveConnection.IMD -SelectiveConnection.PFI -SelectiveConnection.PO -SelectiveConnection.PR -SelectiveConnection.PRI -SelectiveConnection.PS -*.iml -.gradle -android/local.properties -android/.idea -.DS_Store -android/build -android/captures -.externalNativeBuild -*.swp diff --git a/subprojects/sc/README.md b/subprojects/sc/README.md deleted file mode 100644 index 6807cfa2..00000000 --- a/subprojects/sc/README.md +++ /dev/null @@ -1,128 +0,0 @@ -# P2PForYourThings -C++ APIs for you to easily setup and communicate via smart P2P (using available p2p modules among Wi-Fi Direct / Bluetooth / Bluetooth LE) - -## Supported Devices -* Raspberry-pi 3 -* NVIDIA Jetson-TX1 - -# Android -[P2PForYourThings-android](https://github.com/sinban04/P2PForYourThings-android) - - -# Quick Start -## How to Get the Source Code -``` -$ git clone https://github.com/sinban04/P2PForYourThings.git -$ cd P2PForYourThings -``` - -## Pre-requisite -- Install Bluetooth library -``` -$ sudo apt-get install libbluetooth-dev -``` - -Check your bluetooth version and if it is equal to or higher than 5.0, then -``` -$ sudo vi /etc/systemd/system/dbus-org.bluez.service - -ExecStart=/usr/lib/bluetooth/bluetoothd --compat - -$ sudo systemctl daemon-reload -$ sudo systemctl restart bluetooth -$ sudo chmod 777 /var/run/sdp -``` - -- Check the wifi module support p2p -``` -$ iw list -``` - -- Modify the wpa_supplicant.conf (```/etc/wpa_supplicant/wpa_supplicant.conf```) -Add two parameters - -> update_config=1 -> -> driver_param=p2p_device=1 - -- Install UDHCPD for wifi-direct -``` -$ sudo apt-get install udhcpd -$ sudo touch /var/lib/misc/udhcpd.leases -``` - -- Set ```wpa_supplicant``` configuration -``` -sudo wpa_supplicant -iwlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf -``` - - -## How to Build the Source Code -``` -// No need to make the new directories now (Already exists) -$ mkdir bin obj ./device/obj -$ make -``` -Then you can find the binary file of the communicator test example, -which is in the ```tests/``` directory. - -## How to Run -``` -$ sudo ./bin/test -``` - -# Notes -## Bluetooth Issues -### Bluetooth Version Compatibility -Check your bluetooth version using -``` -$ sudo vi /etc/systemd/system/dbus-org.bluez.service - -ExecStart=/usr/lib/bluetooth/bluetoothd --compat - -$ sudo systemctl daemon-reload -$ sudo systemctl restart bluetooth -$ sudo chmod 777 /var/run/sdp -``` - -### Check the bluetooth HCI interface -``` -$ hciconfig -a -``` - -### Change hci0 interface to Scan Mode -Set page scan and inquiry can (Discoverable) -``` -$ sudo hciconfig hci0 piscan -``` - -### Change the hci0 interface name -e.g., change the name of the bluetooth interface to ```pi``` -``` -$ sudo hciconfig hci0 name pi -``` - -### Turn on the interface -``` -$ sudo hciconfig hci0 up -``` - -### Turn on the bluetoothd (For the case, it's off) -``` -sudo service bluetooth start -``` -When the bluetooth.target is masked, unmask it -``` -$ sudo systemctl unmask bluetooth -``` -Check the bluetoothd exists -``` -$ ps -ef | grep bluetooth -``` - -## Wifi-Direct Issues -### Remove the P2P group (Wifi-direct) on the wifi interface -remove group ```p2p-wlan0-0``` on the wifi interface ```wlan0``` -``` -sudo wpa_cli -i wlan0 p2p_group_remove p2p-wlan0-0 -``` diff --git a/subprojects/sc/android/.project b/subprojects/sc/android/.project deleted file mode 100644 index 3964dd3f..00000000 --- a/subprojects/sc/android/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - android - Project android created by Buildship. - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/subprojects/sc/android/.settings/org.eclipse.buildship.core.prefs b/subprojects/sc/android/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index e8895216..00000000 --- a/subprojects/sc/android/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -connection.project.dir= -eclipse.preferences.version=1 diff --git a/subprojects/sc/android/Readme.md b/subprojects/sc/android/Readme.md deleted file mode 100644 index 98b9bfe0..00000000 --- a/subprojects/sc/android/Readme.md +++ /dev/null @@ -1 +0,0 @@ -[P2PForYourThings](https://github.com/esevan/P2PForYourThings) diff --git a/subprojects/sc/android/app/.classpath b/subprojects/sc/android/app/.classpath deleted file mode 100644 index eb19361b..00000000 --- a/subprojects/sc/android/app/.classpath +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/subprojects/sc/android/app/.gitignore b/subprojects/sc/android/app/.gitignore deleted file mode 100755 index 3543521e..00000000 --- a/subprojects/sc/android/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/subprojects/sc/android/app/.project b/subprojects/sc/android/app/.project deleted file mode 100644 index ac485d7c..00000000 --- a/subprojects/sc/android/app/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - app - Project app created by Buildship. - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/subprojects/sc/android/app/.settings/org.eclipse.buildship.core.prefs b/subprojects/sc/android/app/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index b1886adb..00000000 --- a/subprojects/sc/android/app/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -connection.project.dir=.. -eclipse.preferences.version=1 diff --git a/subprojects/sc/android/app/build.gradle b/subprojects/sc/android/app/build.gradle deleted file mode 100755 index ec825f69..00000000 --- a/subprojects/sc/android/app/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 25 - buildToolsVersion '27.0.3' - defaultConfig { - applicationId "com.redcarrottt.sc" - minSdkVersion 19 - targetSdkVersion 25 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { - exclude group: 'com.android.support', module: 'support-annotations' - }) - compile 'com.android.support:appcompat-v7:25.0.0' - testCompile 'junit:junit:4.12' -} diff --git a/subprojects/sc/android/app/proguard-rules.pro b/subprojects/sc/android/app/proguard-rules.pro deleted file mode 100755 index fa3c8f5e..00000000 --- a/subprojects/sc/android/app/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in C:\Users\eslab\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/subprojects/sc/android/app/src/androidTest/java/com/redcarrottt/testapp/ExampleInstrumentedTest.java b/subprojects/sc/android/app/src/androidTest/java/com/redcarrottt/testapp/ExampleInstrumentedTest.java deleted file mode 100755 index 832a7b5d..00000000 --- a/subprojects/sc/android/app/src/androidTest/java/com/redcarrottt/testapp/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package kr.ac.skku.nyx.selectiveconnection; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumentation test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("kr.ac.skku.nyx.selectiveconnection", appContext.getPackageName()); - } -} diff --git a/subprojects/sc/android/app/src/main/AndroidManifest.xml b/subprojects/sc/android/app/src/main/AndroidManifest.xml deleted file mode 100755 index 992dd9fb..00000000 --- a/subprojects/sc/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/ic_launcher-web.png b/subprojects/sc/android/app/src/main/ic_launcher-web.png deleted file mode 100644 index 2321e583c073fa8757c2f88bd1b324e4fa5fe61a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30254 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 diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/API.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/API.java deleted file mode 100755 index a8dcdc22..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/API.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.redcarrottt.sc.api; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * Eunsoo Park (esevan.park@gmail.com) - * Injung Hwang (sinban04@gmail.com) - * - * 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. - */ - -import com.redcarrottt.sc.internal.ClientAdapter; -import com.redcarrottt.sc.internal.Core; - -public class API { - public static void startSC(OnStartSCResult resultListener) { - Core.singleton().start(resultListener); - } - - public static void stopSC(OnStopSCResult resultListener) { - Core.singleton().stop(resultListener); - } - - public static void registerAdapter(ClientAdapter adapter) { - Core.singleton().registerAdapter(adapter); - } - - public static int send(byte[] dataBuffer, int dataLength) { - return Core.singleton().send(dataBuffer, dataLength, false); - } - - public static int receive(byte[] dataBuffer) { - return Core.singleton().receive(dataBuffer, false); - } -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStartSCResult.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStartSCResult.java deleted file mode 100644 index 5646c9e5..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStartSCResult.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.redcarrottt.sc.api; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public interface OnStartSCResult { - public void onDoneStartSC(boolean isSuccess); -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStopSCResult.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStopSCResult.java deleted file mode 100644 index c5a6a1ef..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStopSCResult.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.redcarrottt.sc.api; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public interface OnStopSCResult { - public void onDoneStopSC(boolean isSuccess); -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapter.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapter.java deleted file mode 100644 index ebd8110f..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapter.java +++ /dev/null @@ -1,901 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import android.util.Log; - -import com.redcarrottt.testapp.Logger; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Date; - -import static com.redcarrottt.sc.internal.ExpConfig.VERBOSE_CLIENT_ADAPTER; -import static com.redcarrottt.sc.internal.ExpConfig.VERBOSE_RECEIVER_TIME; -import static com.redcarrottt.sc.internal.ExpConfig.VERBOSE_SEGMENT_DEQUEUE_CTRL; -import static com.redcarrottt.sc.internal.ExpConfig.VERBOSE_SEGMENT_DEQUEUE_DATA; -import static com.redcarrottt.sc.internal.SegmentManager.kDeqSendControlData; -import static com.redcarrottt.sc.internal.SegmentManager.kSQRecvControl; -import static com.redcarrottt.sc.internal.SegmentManager.kSQRecvData; -import static com.redcarrottt.sc.internal.SegmentManager.kSegFlagControl; -import static com.redcarrottt.sc.internal.SegmentManager.kSegHeaderSize; -import static com.redcarrottt.sc.internal.SegmentManager.kSegSize; - -public class ClientAdapter { - private final String kTag = "ClientAdapter"; - private final ClientAdapter self = this; - - // Main Functions: connect, disconnect, send, receive - public void connect(ConnectResultListener listener, boolean isSendRequest) { - int state = this.getState(); - if (state != State.kDisconnected) { - Logger.ERR(kTag, "Connect Failed: Already connected or connect/disconnection is in " - + "progress: " + this.getName() + " / " + this.getState()); - listener.onConnectResult(false); - return; - } - - if (isSendRequest) { - Core.singleton().getControlMessageSender().sendRequestConnect(this.getId()); - } - - ConnectThread thread = new ConnectThread(listener); - thread.start(); - } - - public void disconnectOnCommand(DisconnectResultListener listener) { - // Check if the adapter is not sleeping - int state = this.getState(); - if (state == State.kGoingSleep) { - Logger.VERB(kTag, this.getName() + ": Disconnect - waiting for sleeping..."); - while (state != State.kSleeping) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - state = this.getState(); - } - } else if (state != State.kSleeping) { - Logger.ERR(kTag, this.getName() + ": Disconnect fail - not sleeping - " + state); - listener.onDisconnectResult(false); - return; - } - - // Set this disconnection is on purpose - this.startDisconnectingOnPurpose(); - - // Get my final seq_no - SegmentManager sm = SegmentManager.singleton(); - int my_final_seq_no_control = sm.getLastSeqNoControl(); - int my_final_seq_no_data = sm.getLastSeqNoData(); - - // Send disconnect request - Core.singleton().getControlMessageSender().sendRequestDisconnect(this.getId(), - my_final_seq_no_control, my_final_seq_no_data); - - disconnectInternal(listener); - } - - public void disconnectOnPeerCommand(DisconnectResultListener listener, int - peerFinalSeqNoControl, int peerFinalSeqNoData) { - // Check if the adapter is not sleeping - int state = this.getState(); - - // TODO: wait for sleeping should be implemented - - // Set this disconnection is on purpose - this.startDisconnectingOnPurpose(); - this.peerKnowsDisconnectingOnPurpose(); - - // Start wait receiving - SegmentManager sm = SegmentManager.singleton(); - sm.waitReceiving(peerFinalSeqNoControl, peerFinalSeqNoData); - - // Send disconnect ack - Core.singleton().getControlMessageSender().sendRequestDisconnectAck(this.getId()); - - disconnectInternal(listener); - } - - public void disconnectOnFailure(DisconnectResultListener listener) { - // Check if the adapter is not sleeping - int state = this.getState(); - if (state == State.kDisconnected || state == State.kDisconnecting) { - Logger.VERB(kTag, this.getName() + ": Disconnect - already disconnecting or " + - "disconnected - " + state); - listener.onDisconnectResult(false); - return; - } - - disconnectInternal(listener); - } - - private void disconnectInternal(DisconnectResultListener listener) { - // Spawn disconnect thread - DisconnectThread thread = new DisconnectThread(listener); - thread.start(); - } - - int send(byte[] dataBuffer, int dataLength) { - int state = this.getState(); - if (state == State.kSleeping || state == State.kGoingSleep || state == State.kWakingUp) { - if (!this.isDisconnectingOnPurpose()) { - Logger.ERR(kTag, "Send Failed: Already sleeping: " + this.getName() + " / " + - this.getState()); - } - return -1; - } else if (state != State.kActive) { - Logger.ERR(kTag, "Send Failed: Already disconnected or connect/disconnection is in " - + "progress: " + this.getName() + " / " + this.getState()); - return -1; - } - - if (this.mClientSocket == null) { - return -2; - } - - Logger.VERB(this.getName(), "Send data: length=" + dataLength); - - // Omit Implementing Statistics: SendDataSize - return this.mClientSocket.send(dataBuffer, dataLength); - } - - int receive(byte[] dataBuffer, int dataLength) { - int state = this.getState(); - if (state != State.kActive && state != State.kGoingSleep && state != State.kSleeping && - state != State.kWakingUp) { - if (!this.isDisconnectingOnPurpose()) { - Logger.ERR(kTag, "Receive Failed: Already disconnected or connect/disconnection " - + "is " + "in" + " progress: " + this.getName() + " / " + this.getState()); - } - return -1; - } - - if (this.mClientSocket == null) { - return -2; - } - - // Omit Implementing Statistics: ReceiveDataSize - return this.mClientSocket.receive(dataBuffer, dataLength); - } - - // Connect/Disconnect Threads & Callbacks - class ConnectThread extends Thread implements TurnOnResultListener, - DiscoverAndConnectResultListener { - @Override - public void run() { - this.setName(self.getName() + "/Connect"); - Logger.VERB(kTag, self.getName() + "'s Connect Thread Spawned! (id:" + this.getId() + - ")"); - setState(ClientAdapter.State.kConnecting); - - if (self.mDevice == null || self.mP2PClient == null || self.mClientSocket == null) { - this.onFail(); - return; - } - - // Turn on device - self.mDevice.turnOn(this); - } - - @Override - public void onTurnOnResult(boolean isSuccess) { - int deviceState = self.mDevice.getState(); - if (!isSuccess || deviceState != Device.State.kOn) { - Logger.ERR(kTag, "Cannot connect the server adapter - turn-on fail: " + self - .getName()); - this.onFail(); - return; - } - - Logger.VERB(kTag, "Turn on success: " + self.getName()); - - // Discover and connect to server - self.mP2PClient.discoverAndConnect(this); - } - - @Override - public void onDiscoverAndConnectResult(boolean isSuccess) { - // Check the result of "Discover and connect" - int p2pClientState = self.mP2PClient.getState(); - if (!isSuccess || p2pClientState != P2PClient.State.kConnected) { - Logger.ERR(kTag, "Cannot connect the server adapter - discover fail:" + self - .getName()); - self.mDevice.turnOff(null); - this.onFail(); - return; - } - - Logger.VERB(kTag, "P2P connect success: " + self.getName()); - - this.mSocketOpenThread = new SocketOpenThread(); - this.mSocketOpenThread.start(); - } - - private SocketOpenThread mSocketOpenThread; - - class SocketOpenThread extends Thread { - @Override - public void run() { - // Open client socket - this.setName(self.getName() + "/SocketOpen"); - int socketState = self.mClientSocket.getState(); - if (socketState != ClientSocket.State.kOpened) { - boolean res = self.mClientSocket.open(); - - socketState = self.mClientSocket.getState(); - if (!res || socketState != ClientSocket.State.kOpened) { - Logger.ERR(kTag, "Cannot connect the server adapter - socket open fail: " - + self.getName()); - self.mP2PClient.disconnect(null); - self.mDevice.turnOff(null); - onFail(); - return; - } - } - - Logger.VERB(kTag, "Socket connect success: " + self.getName()); - - // Run sender & receiver threads - if (self.mSenderThread != null && !self.mSenderThread.isOn()) { - self.mSenderThread.start(); - } - - if (self.mReceiverThread != null && !self.mReceiverThread.isOn()) { - self.mReceiverThread.start(); - } - - // Report result success - self.setState(ClientAdapter.State.kActive); - if (mResultListener != null) { - mResultListener.onConnectResult(true); - mResultListener = null; - } - } - } - - private void onFail() { - self.setState(ClientAdapter.State.kDisconnected); - - // Report result fail - if (this.mResultListener != null) { - this.mResultListener.onConnectResult(false); - this.mResultListener = null; - } - } - - private ConnectResultListener mResultListener; - - ConnectThread(ConnectResultListener resultListener) { - this.mResultListener = resultListener; - } - } - - class DisconnectThread extends Thread implements com.redcarrottt.sc.internal - .DisconnectResultListener, TurnOffResultListener { - @Override - public void run() { - this.setName(self.getName() + "/Disconnect"); - Logger.VERB(kTag, self.getName() + "'s Disconnect Thread Spawned! (id:" + this.getId - () + ")"); - int oldState = self.getState(); - setState(ClientAdapter.State.kDisconnecting); - - if (isDisconnectingOnPurpose() && !isDisconnectingOnPurposePeer()) { - waitForDisconnectingOnPurposePeer(); - } - - boolean res = this.__disconnect_thread(oldState); - - finishDisconnectingOnPurpose(); - - if (!res) { - this.onFail(); - } - - Logger.VERB(kTag, self.getName() + "'s Disconnect Thread Finished. (id:" + this.getId - () + ")"); - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private boolean __disconnect_thread(int oldState) { - // Finish sender & receiver threads - if (self.mSenderThread != null) { - self.mSenderThread.finish(); - if (oldState == ClientAdapter.State.kSleeping) { - self.wakeUpInternal(); - } - } - if (self.mReceiverThread != null) { - self.mReceiverThread.finish(); - } - - // Wake up sender thread waiting segment queue - SegmentManager sm = SegmentManager.singleton(); - sm.wakeUpDequeueWaiting(kDeqSendControlData); - - // Close client socket - if (self.mClientSocket == null) { - return false; - } - int socketState = self.mClientSocket.getState(); - if (socketState != ClientSocket.State.kClosed) { - boolean res = self.mClientSocket.close(); - - socketState = self.mClientSocket.getState(); - if (!res || socketState != ClientSocket.State.kClosed) { - Logger.ERR(kTag, "Cannot disconnect the server adapter - socket " + "close " - + "fail: " + "" + "" + self.getName()); - return false; - } - } - - // P2P Disconnect - self.mP2PClient.disconnect(this); - - // Wait for sender/receiver thread - try { - synchronized (self.mWaitSenderThread) { - if (self.mSenderThread.isOn()) { - Logger.DEBUG(kTag, "Waiting for sender thread... " + mName); - synchronized (self.mIsWaitSenderThread) { - self.mIsWaitSenderThread = true; - } - self.mWaitSenderThread.wait(); - } - Logger.DEBUG(kTag, "Sender thread's end is detected... " + mName); - } - synchronized (self.mWaitReceiverThread) { - if (self.mReceiverThread.isOn()) { - Logger.DEBUG(kTag, "Waiting for receiver thread..." + mName); - synchronized (self.mIsWaitReceiverThread) { - self.mIsWaitReceiverThread = true; - } - self.mWaitReceiverThread.wait(); - } - Logger.DEBUG(kTag, "Receiver thread's end is detected... " + mName); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - return true; - } - - @Override - public void onDisconnectResult(boolean isSuccess) { - // Check the result of "P2P Disconnect" - int p2pClientState = self.mP2PClient.getState(); - if (!isSuccess) { - Logger.ERR(kTag, "Cannot disconnect the server adapter - " + "disconnect P2P " + - "client fail: " + self.getName()); - this.onFail(); - return; - } - - // Turn off device - self.mDevice.turnOff(this); - } - - @Override - public void onTurnOffResult(boolean isSuccess) { - int deviceState = self.mDevice.getState(); - if (!isSuccess) { - Logger.ERR(kTag, "Cannot disconnect the server adapter - turn-off " + "fail:" + - "" + " " + self.getName()); - this.onFail(); - return; - } - - // Report result success - self.setState(ClientAdapter.State.kDisconnected); - if (this.mResultListener != null) { - this.mResultListener.onDisconnectResult(true); - this.mResultListener = null; - } - } - - private void onFail() { - self.setState(ClientAdapter.State.kActive); - - // Report result fail - if (this.mResultListener != null) { - this.mResultListener.onDisconnectResult(false); - this.mResultListener = null; - } - } - - private DisconnectResultListener mResultListener; - - DisconnectThread(DisconnectResultListener resultListener) { - this.mResultListener = resultListener; - } - } - - interface ConnectResultListener { - void onConnectResult(boolean isSuccess); - } - - interface DisconnectResultListener { - void onDisconnectResult(boolean isSuccess); - } - - // Sender/Receiver Threads - @SuppressWarnings("SynchronizeOnNonFinalField") - class SenderThread extends Thread { - @Override - public void run() { - this.setName(self.getName() + "/Sender"); - synchronized (this.mIsOn) { - this.mIsOn = true; - } - synchronized (this.mIsSuspended) { - this.mIsSuspended = false; - } - - synchronized (self.mIsWaitSenderThread) { - self.mIsWaitSenderThread = false; - } - - this.senderThreadLoop(); - -// NetworkSwitcher.singleton().reconnectAdapter(ClientAdapter.this); - Logger.VERB(kTag, ClientAdapter.this.getName() + "'s Sender thread ends"); - - synchronized (self.mIsWaitSenderThread) { - if (self.mIsWaitSenderThread) { - self.mWaitSenderThread.notifyAll(); - } - } - } - - private void senderThreadLoop() { - Logger.VERB(kTag, ClientAdapter.this.getName() + "'s Sender thread starts"); - while (this.mIsOn) { - SegmentManager sm = SegmentManager.singleton(); - Segment segmentToSend; - - // If this sender is set to be suspended, wait until it wakes up - { - boolean sender_suspended; - do { - synchronized (mSenderSuspended) { - sender_suspended = mSenderSuspended; - } - if (!sender_suspended) { - break; - } - Logger.VERB(kTag, "Sender thread suspended: " + this.getName()); - setState(ClientAdapter.State.kSleeping); - synchronized (mSenderSuspended) { - try { - mSenderSuspended.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - setState(ClientAdapter.State.kActive); - } while (true); - } - - // Dequeue from a queue (one of the three queues) - // Priority 1. Failed sending queue - segmentToSend = sm.get_failed_sending(); - // Priority 2. Send control queue - // Priority 3. Send data queue - if (segmentToSend == null) { - segmentToSend = sm.dequeue(kDeqSendControlData); - } - - if (segmentToSend == null) { - // Nothing to send. - // SegmentManager::wake_up_dequeue_waiting() function may make this case - continue; - } - - int state = self.getState(); - if (state == ClientAdapter.State.kDisconnecting || state == ClientAdapter.State - .kDisconnected || isDisconnectingOnPurpose()) { - sm.failed_sending(segmentToSend); - continue; - } - - // If it is suspended, push the segment to the send-fail queue - { - boolean sender_suspended; - synchronized (mSenderSuspended) { - sender_suspended = mSenderSuspended; - } - if (sender_suspended) { - Logger.VERB(kTag, "Sending segment is pushed to failed queue at " + this - .getName() + " (suspended)"); - sm.failed_sending(segmentToSend); - continue; - } - } - - Logger.DEBUG(ClientAdapter.this.getName(), "SEND Segment " + segmentToSend.seq_no - + " / " + segmentToSend.len + "" + " / " + segmentToSend.flag); - - int res = send(segmentToSend.data, kSegHeaderSize + kSegSize); - if (res < 0) { - Logger.WARN(kTag, "Sending failed at " + ClientAdapter.this.getName()); - sm.failed_sending(segmentToSend); - break; - } - sm.free_segment(segmentToSend); - } - } - - public void finish() { - synchronized (this.mIsOn) { - this.mIsOn = false; - } - synchronized (this.mIsSuspended) { - this.mIsSuspended = false; - } - } - - SenderThread() { - this.mIsOn = false; - this.mIsSuspended = false; - } - - public boolean isOn() { - return this.mIsOn; - } - - private Boolean mIsOn; - private Boolean mIsSuspended; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - class ReceiverThread extends Thread { - @Override - public void run() { - this.setName(self.getName() + "/Receiver"); - synchronized (this.mIsOn) { - this.mIsOn = true; - } - synchronized (self.mIsWaitReceiverThread) { - self.mIsWaitReceiverThread = false; - } - - this.receiverThreadLoop(self); - - synchronized (self.mIsWaitReceiverThread) { - if (self.mIsWaitReceiverThread) { - self.mWaitReceiverThread.notifyAll(); - } - } - } - - private int mReceiveCount = 0; - private Date mDates[] = new Date[5]; - private long mIntervals[] = new long[4]; - - public void receiverThreadLoop(ClientAdapter adapter) { - Logger.VERB(kTag, ClientAdapter.this.getName() + "'s Receiver thread starts"); - byte prevData[] = new byte[SegmentManager.kSegSize + SegmentManager.kSegHeaderSize]; - - while (this.isOn()) { - if (VERBOSE_RECEIVER_TIME) this.mDates[0] = new Date(); - - SegmentManager sm = SegmentManager.singleton(); - Segment segmentToReceive = sm.get_free_segment(); - int len = kSegSize + kSegHeaderSize; - - if (VERBOSE_RECEIVER_TIME) this.mDates[1] = new Date(); - - if (VERBOSE_CLIENT_ADAPTER) { - Logger.DEBUG(kTag, adapter.getName() + ": Receiving..."); - } - int res = adapter.receive(segmentToReceive.data, len); - if (res < len) { - Logger.WARN(kTag, "Receiving failed at " + adapter.getName()); - break; - } - - if (VERBOSE_RECEIVER_TIME) this.mDates[2] = new Date(); - - // Read segment metadata - ByteBuffer buffer = ByteBuffer.allocate(4); - buffer.put(segmentToReceive.data, 0, 4); - segmentToReceive.seq_no = buffer.getInt(0); - - buffer = ByteBuffer.allocate(4); - buffer.put(segmentToReceive.data, 4, 4); - segmentToReceive.len = buffer.getInt(0); - - buffer = ByteBuffer.allocate(4); - buffer.put(segmentToReceive.data, 8, 4); - segmentToReceive.flag = buffer.getInt(0); - - //Logger.DEBUG(kTag, "RECEIVE " + segmentToReceive.seq_no + " / " + - // segmentToReceive.len + " / " + segmentToReceive.flag); - - if (VERBOSE_RECEIVER_TIME) this.mDates[3] = new Date(); - - boolean is_control = ((segmentToReceive.flag & kSegFlagControl) != 0); - - if (VERBOSE_SEGMENT_DEQUEUE_CTRL && is_control) { - Logger.DEBUG(getName(), "Receive Segment: seqno=" + segmentToReceive.seq_no + - " / type=ctrl"); - } - if (VERBOSE_SEGMENT_DEQUEUE_DATA && !is_control) { - Logger.DEBUG(getName(), "Receive Segment: seqno=" + segmentToReceive.seq_no + - " / type=data"); - } - - if (is_control) { - sm.enqueue(kSQRecvControl, segmentToReceive); - } else { - sm.enqueue(kSQRecvData, segmentToReceive); - } - - if (VERBOSE_RECEIVER_TIME) this.mDates[4] = new Date(); - - if (VERBOSE_RECEIVER_TIME) { - this.mReceiveCount++; - for (int i = 0; i < 4; i++) { - this.mIntervals[i] += this.mDates[i + 1].getTime() - this.mDates[i] - .getTime(); - } - if (this.mReceiveCount % 500 == 0) { - Log.d(kTag, "Receive Time " + this.mIntervals[0] + " / " + this - .mIntervals[1] + " / " + this.mIntervals[2] + " / " + this - .mIntervals[3]); - for (int i = 0; i < 4; i++) { - this.mIntervals[i] = 0; - } - } - } - } - -// NetworkSwitcher.singleton().reconnectAdapter(ClientAdapter.this); - Logger.VERB(kTag, ClientAdapter.this.getName() + "'s Receiver thread ends"); - } - - public void finish() { - synchronized (this.mIsOn) { - this.mIsOn = false; - } - } - - ReceiverThread() { - this.mIsOn = false; - } - - public boolean isOn() { - return this.mIsOn; - } - - private Boolean mIsOn; - } - - private SenderThread mSenderThread; - private ReceiverThread mReceiverThread; - private Boolean mSenderSuspended; - - private Boolean mIsWaitSenderThread; - private Boolean mIsWaitReceiverThread; - private Object mWaitSenderThread = new Object(); - private Object mWaitReceiverThread = new Object(); - - @SuppressWarnings("SynchronizeOnNonFinalField") - public boolean sleep(boolean isSendRequest) { - int state = this.getState(); - if (state != State.kActive) { - Logger.ERR(kTag, "Failed to sleep: " + this.getName() + "(state: " + state + ")"); - return false; - } - - synchronized (this.mSenderSuspended) { - if (this.mSenderSuspended) { - Logger.ERR(kTag, "Sender has already been suspended!: " + this.getName()); - return false; - } else { - if (isSendRequest) { - // Send Request - Core.singleton().getControlMessageSender().sendRequestSleep(this.getId()); - } - - // Sleep - this.setState(State.kGoingSleep); - this.mSenderSuspended = true; - - // Wake up sender thread waiting segment queue - SegmentManager sm = SegmentManager.singleton(); - sm.wakeUpDequeueWaiting(kDeqSendControlData); - return true; - } - } - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - public boolean wakeUp(boolean isSendRequest) { - int state = this.getState(); - if (state != State.kSleeping) { - Logger.ERR(kTag, "Failed to wake up: " + this.getName() + "(state: " + state + ")"); - return false; - } - boolean sender_suspended; - synchronized (this.mSenderSuspended) { - sender_suspended = this.mSenderSuspended; - } - if (sender_suspended) { - // Send Request - Core.singleton().getControlMessageSender().sendRequestWakeup(this.getId()); - - // Wake up - this.setState(State.kWakingUp); - this.wakeUpInternal(); - - return true; - } else { - Logger.ERR(kTag, "Sender has not been suspended!: " + this.getName()); - return false; - } - } - - private void wakeUpInternal() { - synchronized (this.mSenderSuspended) { - this.mSenderSuspended = false; - this.mSenderSuspended.notifyAll(); - } - } - - // Initialize - public ClientAdapter(int id, String name) { - this.mId = id; - this.mName = name; - this.mState = State.kDisconnected; - this.mListeners = new ArrayList<>(); - this.mSenderSuspended = false; - this.mIsDisconnectingOnPurpose = false; - this.mIsDisconnectingOnPurposePeer = false; - this.mIsWaitReceiverThread = false; - this.mIsWaitSenderThread = false; - - this.mSenderThread = new SenderThread(); - this.mReceiverThread = new ReceiverThread(); - } - - protected void initialize(Device device, P2PClient p2pClient, ClientSocket clientSocket) { - this.mDevice = device; - this.mP2PClient = p2pClient; - this.mClientSocket = clientSocket; - } - - // Attribute getters - public int getId() { - return this.mId; - } - - public String getName() { - return this.mName; - } - - public boolean isDisconnectingOnPurpose() { - return this.mIsDisconnectingOnPurpose; - } - - public boolean isDisconnectingOnPurposePeer() { - return this.mIsDisconnectingOnPurposePeer; - } - - // Attribute setters - public void startDisconnectingOnPurpose() { - this.mIsDisconnectingOnPurpose = true; - } - - public void waitForDisconnectingOnPurposePeer() { - synchronized (mWaitForDisconnectAck) { - try { - mWaitForDisconnectAck.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public void peerKnowsDisconnectingOnPurpose() { - this.mIsDisconnectingOnPurposePeer = true; - synchronized (this.mWaitForDisconnectAck) { - this.mWaitForDisconnectAck.notifyAll(); - } - } - - private void finishDisconnectingOnPurpose() { - this.mIsDisconnectingOnPurpose = false; - this.mIsDisconnectingOnPurposePeer = false; - } - - // Attributes - private int mId; - private String mName; - - // Disconnecting on purpose by a device - private boolean mIsDisconnectingOnPurpose; - private boolean mIsDisconnectingOnPurposePeer; - private Object mWaitForDisconnectAck = new Object(); - - // State - class State { - public static final int kDisconnected = 0; - public static final int kConnecting = 1; - public static final int kActive = 2; - public static final int kDisconnecting = 3; - public static final int kGoingSleep = 4; - public static final int kSleeping = 5; - public static final int kWakingUp = 6; - public static final int kASNum = 7; - } - - public static String stateToString(int state) { - final String[] stateStr = {"Disconnected", "Connecting", "Active", "Disconnecting", - "GoingSleep", "Sleeping", "WakingUp"}; - if (state >= State.kASNum || state < 0) { - return ""; - } else { - return stateStr[state]; - } - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - public int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - int oldState; - synchronized (this.mState) { - oldState = this.mState; - this.mState = newState; - } - - Logger.DEBUG(this.getName(), "State(" + stateToString(oldState) + "->" + stateToString - (newState) + ")"); - - for (ClientAdapterStateListener listener : this.mListeners) { - listener.onUpdateClientAdapterState(this, oldState, newState); - } - } - - public void listenState(ClientAdapterStateListener listener) { - synchronized (this.mListeners) { - this.mListeners.add(listener); - } - } - - // State - private Integer mState; - - // State Listener - private final ArrayList mListeners; - - // Main Components : Device, P2PClient, ClientSocket - private Device mDevice; - private P2PClient mP2PClient; - - private ClientSocket mClientSocket; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapterStateListener.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapterStateListener.java deleted file mode 100644 index c12efee6..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapterStateListener.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public interface ClientAdapterStateListener { - void onUpdateClientAdapterState(ClientAdapter adapter, int oldState, int newState); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientSocket.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientSocket.java deleted file mode 100644 index 8fe485c9..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientSocket.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import com.redcarrottt.testapp.Logger; - -public abstract class ClientSocket { - private final String kTag = "ClientSocket"; - - // Main Functions - public boolean open() { - if (this.getState() != State.kClosed) { - Logger.ERR(kTag, "It's already opened or opening/closing is in progress"); - return false; - } - - this.setState(State.kOpening); - boolean res = this.openImpl(); - if (!res) { - this.setState(State.kClosed); - } else { - this.setState(State.kOpened); - } - return res; - } - - public boolean close() { - if (this.getState() != State.kOpened) { - Logger.ERR(kTag, "It's already closed or opening/closing is in progress"); - return false; - } - - this.setState(State.kClosing); - boolean res = this.closeImpl(); - this.setState(State.kClosed); - - return res; - } - - public int send(byte[] dataBuffer, int dataLength) { - if (this.getState() != State.kOpened) { - Logger.ERR(kTag, "Socket is not opened"); - return -1; - } - - int res = this.sendImpl(dataBuffer, dataLength); - if (res < 0) { - this.setState(State.kClosed); - } - return res; - } - - public int receive(byte[] dataBuffer, int dataLength) { - if (this.getState() != State.kOpened) { - Logger.ERR(kTag, "Socket is not opened"); - return -1; - } - - int res = this.receiveImpl(dataBuffer, dataLength); - if (res < 0) { - this.setState(State.kClosed); - } - return res; - } - - // Implemented by child classes - protected abstract boolean openImpl(); - - protected abstract boolean closeImpl(); - - protected abstract int sendImpl(byte[] dataBuffer, int dataLength); - - protected abstract int receiveImpl(byte[] dataBuffer, int dataLength); - - // State - class State { - public static final int kClosed = 0; - public static final int kOpening = 1; - public static final int kOpened = 2; - public static final int kClosing = 3; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - protected int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - synchronized (this.mState) { - this.mState = newState; - } - } - - protected ClientSocket() { - } - - // Attributes - - // State - private Integer mState = State.kClosed; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageListener.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageListener.java deleted file mode 100644 index a5ab60cd..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ - -// Control Message Listener -public interface ControlMessageListener { - void onReceiveControlMessage(int privateType, String privateMessage); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageProtocol.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageProtocol.java deleted file mode 100644 index 7b4c16c6..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageProtocol.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public class ControlMessageProtocol { - // Control Request Code - class CMCode { - public static final char kConnect = 1; - public static final char kSleep = 2; - public static final char kWakeup = 3; - public static final char kDisconnect = 4; - public static final char kPriv = 10; - public static final char kDisconnectAck = 24; - } - - // Priv Type Code - public class PrivType { - public static final char kWFDInfo = 1; - public static final char kWFDUnknown = 999; - } -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageReceiver.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageReceiver.java deleted file mode 100644 index 6be22426..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageReceiver.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.redcarrottt.sc.internal; - -import android.util.Log; - -import com.redcarrottt.testapp.Logger; - -import java.util.ArrayList; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public class ControlMessageReceiver { - private static final String kTag = "ControlMessageReceiver"; - private static final String kThreadName = "Control Message Receiving"; - - public void startReceivingThread() { - this.mReceivingThread = new ReceivingThread(); - this.mReceivingThread.start(); - } - - public void stopReceivingThread() { - this.mReceivingThread.finish(); - } - - // Thread - private class ReceivingThread extends Thread { - @Override - public void run() { - this.setName("ControlMsgReceiver"); - this.mIsOn = true; - Logger.THREAD_LAUNCH(kThreadName); - - while (this.mIsOn) { - this.loopInternal(); - } - - Logger.THREAD_FINISH(kThreadName); - this.mIsOn = false; - } - - public boolean loopInternal() { - byte[] messageBuffer = new byte[10 * 1024]; - int res = Core.singleton().receive(messageBuffer, true); - if (res <= 0) { - return false; - } - - String message = new String(messageBuffer).trim(); - - // Find separator location (between first line and other lines) - Log.d(kTag, "Control message incoming: " + message); - int separatorPos = message.indexOf('\n'); - - // Divide the message into first line & other lines - String firstLine = message.substring(0, separatorPos); - String otherLines = message.substring(separatorPos + 1); - - int controlMessageCode = Integer.parseInt(firstLine); - - switch (controlMessageCode) { - case ControlMessageProtocol.CMCode.kConnect: - case ControlMessageProtocol.CMCode.kSleep: - case ControlMessageProtocol.CMCode.kWakeup: - case ControlMessageProtocol.CMCode.kDisconnectAck: { - // Normal type - int adapterId = Integer.parseInt(otherLines); - onReceiveNormalMessage(controlMessageCode, adapterId); - break; - } - case ControlMessageProtocol.CMCode.kDisconnect: { - // Disconnect type - // Divide the message into second line, third line, fourth line - separatorPos = otherLines.indexOf('\n'); - String secondLine = otherLines.substring(0, separatorPos); - String thirdFourthLine = otherLines.substring(separatorPos + 1); - separatorPos = thirdFourthLine.indexOf('\n'); - String thirdLine = thirdFourthLine.substring(0, separatorPos); - String fourthLine = thirdFourthLine.substring(separatorPos + 1); - - int adapterId = Integer.parseInt(secondLine); - int finalSeqNoControl = Integer.parseInt(thirdLine); - int finalSeqNoData = Integer.parseInt(fourthLine); - - onReceiveDisconnectMessage(adapterId, finalSeqNoControl, finalSeqNoData); - break; - } - case ControlMessageProtocol.CMCode.kPriv: { - // Priv type - onReceivePrivateMessage(otherLines); - break; - } - default: { - Logger.ERR(kTag, "Unknown control message code (" + controlMessageCode + ")" - + "!\n" + message); - break; - } - } - - return true; - } - - public void finish() { - this.mIsOn = false; - } - - // Constructor - public ReceivingThread() { - this.mIsOn = false; - } - - // Attributes - private boolean mIsOn; - } - - private void onReceiveNormalMessage(int controlMessageCode, int adapterId) { - switch (controlMessageCode) { - case ControlMessageProtocol.CMCode.kConnect: { - Logger.VERB(kTag, "Receive(Control Msg): Request(Connect " + adapterId + ")"); - NetworkSwitcher.singleton().connectAdapterByPeer(adapterId); - break; - } - case ControlMessageProtocol.CMCode.kSleep: { - Logger.VERB(kTag, "Receive(Control Msg): Request(Sleep " + adapterId + ")"); - NetworkSwitcher.singleton().sleepAdapterByPeer(adapterId); - break; - } - case ControlMessageProtocol.CMCode.kWakeup: { - Logger.VERB(kTag, "Receive(Control Msg): Request(WakeUp " + adapterId + ")"); - NetworkSwitcher.singleton().wakeUpAdapterByPeer(adapterId); - break; - } - case ControlMessageProtocol.CMCode.kDisconnectAck: { - Logger.VERB(kTag, "Receive(Control Msg): Request(DisconenctAck " + adapterId + ")"); - ClientAdapter disconnectAdapter = Core.singleton().findAdapterById(adapterId); - if (disconnectAdapter == null) { - Logger.WARN(kTag, "Cannot find adapter " + adapterId); - } else { - disconnectAdapter.peerKnowsDisconnectingOnPurpose(); - } - break; - } - } - } - - private void onReceiveDisconnectMessage(int adapterId, int finalSeqNoControl, int - finalSeqNoData) { - Logger.VERB(kTag, "Receive(Control Msg): Request(Disconnect " + adapterId + " / " + - "final_seq_no_control=" + finalSeqNoControl + " / final_seq_no_data=" + - finalSeqNoData + ")"); - NetworkSwitcher.singleton().disconnectAdapterByPeer(adapterId, finalSeqNoControl, - finalSeqNoData); - } - - private void onReceivePrivateMessage(String contents) { - // Find separator location - int separatorPos = contents.indexOf('\n'); - - // Divide the message into second line & other lines - String secondLine = contents.substring(0, separatorPos); - String privateMessage = contents.substring(separatorPos + 1); - - int privateType = Integer.parseInt(secondLine); - - // Notify the private message - for (ControlMessageListener listener : mControlMessageListeners) { - listener.onReceiveControlMessage(privateType, privateMessage); - } - } - - public void addControlMessageListener(ControlMessageListener listener) { - this.mControlMessageListeners.add(listener); - } - - public ControlMessageReceiver() { - this.mReceivingThread = null; - this.mControlMessageListeners = new ArrayList<>(); - } - - // Attributes - private ReceivingThread mReceivingThread; - private ArrayList mControlMessageListeners; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageSender.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageSender.java deleted file mode 100644 index 82786e39..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageSender.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.redcarrottt.sc.internal; - -import com.redcarrottt.testapp.Logger; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public class ControlMessageSender { - private static final String kTag = "ControlMessageSender"; - - public void sendRequestConnect(int adapterId) { - this.sendRequest(ControlMessageProtocol.CMCode.kConnect, adapterId); - Logger.VERB(kTag, "Send(Control Msg): Request(Connect " + adapterId + ")"); - } - - public void sendRequestDisconnect(int adapterId, int final_seq_no_control, int - final_seq_no_data) { - String message = "" + ControlMessageProtocol.CMCode.kDisconnect + "\n" + adapterId + "\n" - + final_seq_no_control + "\n" + final_seq_no_data; - this.sendControlMessage(message); - Logger.VERB(kTag, "Send(Control Msg): Request(Disconnect " + adapterId + "; " + - "final_seq_no_control=" + final_seq_no_control + "; final_seq_no_data=" + - final_seq_no_data + ")"); - } - - public void sendRequestDisconnectAck(int adapterId) { - this.sendRequest(ControlMessageProtocol.CMCode.kDisconnectAck, adapterId); - Logger.VERB(kTag, "Send(Control Msg): Request(DisconnectAck " + adapterId + ")"); - } - - public void sendRequestSleep(int adapterId) { - this.sendRequest(ControlMessageProtocol.CMCode.kSleep, adapterId); - Logger.VERB(kTag, "Send(Control Msg): Request(Sleep " + adapterId + ")"); - } - - public void sendRequestWakeup(int adapterId) { - this.sendRequest(ControlMessageProtocol.CMCode.kWakeup, adapterId); - Logger.VERB(kTag, "Send(Control Msg): Request(WakeUp " + adapterId + ")"); - } - - public void sendNotiPrivateData(int privateType, String privateMessage) { - String message = "" + ControlMessageProtocol.CMCode.kPriv + "\n" + privateType + "\n" + - privateMessage; - this.sendControlMessage(message); - } - - private void sendRequest(int requestCode, int adapterId) { - String message = "" + requestCode + "\n" + adapterId; - this.sendControlMessage(message); - } - - private void sendControlMessage(String controlMessage) { - byte[] messageBuffer = controlMessage.getBytes(); - Core.singleton().send(messageBuffer, messageBuffer.length, true); - } -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Core.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Core.java deleted file mode 100644 index 56e43997..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Core.java +++ /dev/null @@ -1,357 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import com.redcarrottt.sc.api.OnStartSCResult; -import com.redcarrottt.sc.api.OnStopSCResult; -import com.redcarrottt.testapp.Logger; - -import java.util.ArrayList; - -public class Core { - private static final String kTag = "Core"; - - // APIs: These functions are mapped to ones in API. - public void start(OnStartSCResult resultListener) { - if (this.getState() != State.kIdle) { - Logger.ERR(kTag, "Core has already started"); - doneStart(false, resultListener); - return; - } else if (this.mAdapters.isEmpty()) { - Logger.ERR(kTag, "No adapter is registered!"); - doneStart(false, resultListener); - return; - } - this.setState(State.kStarting); - runStartCoreTx(this, resultListener); - } - - private void doneStart(boolean isSuccess, OnStartSCResult resultListener) { - if (isSuccess) { - Logger.VERB(kTag, "Succeed to start core!"); - this.setState(State.kReady); - - // Launch control message receiving thread - this.mControlMessageReceiver.startReceivingThread(); - } else { - Logger.ERR(kTag, "Failed to start core!"); - this.setState(State.kIdle); - } - if (resultListener != null) resultListener.onDoneStartSC(isSuccess); - } - - public void stop(OnStopSCResult resultListener) { - int state = this.getState(); - if (state == State.kStarting || state == State.kStopping) { - Logger.ERR(kTag, "Cannot stop core during starting/stopping!"); - doneStop(false, resultListener); - return; - } else if (state == State.kIdle) { - Logger.ERR(kTag, "Core is already idle state!"); - doneStop(false, resultListener); - return; - } else if (this.mAdapters.isEmpty()) { - Logger.ERR(kTag, "No adapter is registered!"); - doneStop(false, resultListener); - return; - } - - this.setState(State.kStopping); - runStopCoreTx(this, resultListener); - } - - private void doneStop(boolean isSuccess, OnStopSCResult resultListener) { - if (isSuccess) { - Logger.VERB(kTag, "Succeed to stop core!"); - this.setState(State.kIdle); - - // Finish control message receiving thread - this.mControlMessageReceiver.stopReceivingThread(); - } else { - Logger.ERR(kTag, "Failed to stop core!"); - this.setState(State.kReady); - } - if (resultListener != null) resultListener.onDoneStopSC(isSuccess); - } - - public void registerAdapter(ClientAdapter adapter) { - if (this.getState() != State.kIdle) { - Logger.ERR(kTag, "You can register adapter on only idle state!"); - return; - } - - synchronized (this.mAdapters) { - this.mAdapters.add(adapter); - } - } - - public int send(byte[] dataBuffer, int dataLength, boolean isControl) { - int state = this.getState(); - if (state != State.kReady) { - Logger.ERR(kTag, "Core is not started yet, so you cannot send the data"); - return -1; - } - - int currOffset = 0; - - // Attach the protocol header to the payload - ProtocolData protocolData = ProtocolManager.data_to_protocol_data(dataBuffer, dataLength); - if (protocolData == null) throw new AssertionError(); - - int packetSize = ProtocolManager.serialize(protocolData, dataBuffer, currOffset, - dataLength); - if (!(packetSize > 0)) { - Logger.ERR(kTag, "Failed to make protocol data to send(" + currOffset + "/" + - dataLength + ")"); - throw new AssertionError(); - } - - int sentBytes = ProtocolManager.send_packet(packetSize, isControl); - if (sentBytes < 0) { - Logger.ERR(kTag, "Sending stopped (" + currOffset + "/" + dataLength + ") by " + - sentBytes); - throw new AssertionError(); - } - - return sentBytes; - } - - public int receive(byte[] dataBuffer, boolean isControl) { - int state = this.getState(); - if (state != State.kReady) { - Logger.ERR(kTag, "Core is not started yet, so you cannot receive data"); - return -1; - } - - return ProtocolManager.recv_packet(dataBuffer, isControl); - } - - // State - class State { - public static final int kIdle = 0; - public static final int kStarting = 1; - public static final int kReady = 2; - public static final int kStopping = 3; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - synchronized (this.mState) { - this.mState = newState; - } - } - - - // Adapters Getter - public ClientAdapter findAdapterById(int adapterId) { - for (ClientAdapter adapter : this.mAdapters) { - if (adapter.getId() == adapterId) { - return adapter; - } - } - return null; - } - - public ControlMessageReceiver getControlMessageReceiver() { - return this.mControlMessageReceiver; - } - - public ControlMessageSender getControlMessageSender() { - return this.mControlMessageSender; - } - - // Components - private final ArrayList mAdapters; - private ControlMessageReceiver mControlMessageReceiver; - private ControlMessageSender mControlMessageSender; - - // State - private Integer mState; - - // Singleton - private static Core sSingleton; - - public static Core singleton() { - if (sSingleton == null) { - sSingleton = new Core(); - } - return sSingleton; - } - - // Constructor - private Core() { - this.mState = State.kIdle; - this.mAdapters = new ArrayList<>(); - this.mControlMessageReceiver = new ControlMessageReceiver(); - this.mControlMessageSender = new ControlMessageSender(); - } - - // Transactions - // ---------------------------------------------------------------- - // Singleton runner - private static void runStartCoreTx(Core caller, OnStartSCResult resultListener) { - if (sOngoingStartCore == null) { - sOngoingStartCore = new StartCoreTransaction(caller, resultListener); - sOngoingStartCore.start(); - } else { - Logger.WARN(kTag, "Already starting core"); - doneStartCoreTx(caller, false, resultListener); - } - } - - private static void doneStartCoreTx(Core caller, boolean isSuccess, OnStartSCResult - resultListener) { - sOngoingStartCore = null; - caller.doneStart(isSuccess, resultListener); - } - - private static void runStopCoreTx(Core caller, OnStopSCResult resultListener) { - if (sOngoingStopCore == null) { - sOngoingStopCore = new StopCoreTransaction(caller, resultListener); - sOngoingStopCore.start(); - } else { - Logger.WARN(kTag, "Already stopping core"); - doneStopCoreTx(caller, false, resultListener); - } - } - - private static void doneStopCoreTx(Core caller, boolean isSuccess, OnStopSCResult - resultListener) { - sOngoingStopCore = null; - caller.doneStop(isSuccess, resultListener); - } - - private static StartCoreTransaction sOngoingStartCore = null; - private static StopCoreTransaction sOngoingStopCore = null; - - // Start Core - private static class StartCoreTransaction { - // Private Constructor - private StartCoreTransaction(Core caller, OnStartSCResult resultListener) { - this.mCaller = caller; - this.mResultListener = resultListener; - this.onConnectFirstAdapter = new OnConnectFirstAdapter(); - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void start() { - // Connect first adapter - ClientAdapter firstAdapter = this.mCaller.mAdapters.get(0); - if (firstAdapter == null) { - Logger.ERR(kTag, "Cannot find first adapter"); - doneStartCoreTx(mCaller, false, mResultListener); - return; - } - firstAdapter.connect(this.onConnectFirstAdapter, false); - } - - private OnConnectFirstAdapter onConnectFirstAdapter; - - class OnConnectFirstAdapter implements ClientAdapter.ConnectResultListener { - @SuppressWarnings("SimplifiableIfStatement") - @Override - public void onConnectResult(boolean isSuccess) { - if (isSuccess) { - // Done transaction - doneStartCoreTx(mCaller, true, mResultListener); - } else { - Logger.ERR(kTag, "Connecting first adapter is failed"); - doneStartCoreTx(mCaller, false, mResultListener); - } - } - } - - // Attributes - private Core mCaller; - private OnStartSCResult mResultListener; - } - - // Stop Core - private static class StopCoreTransaction { - private StopCoreTransaction(Core caller, OnStopSCResult resultListener) { - this.mCaller = caller; - this.mResultListener = resultListener; - this.onDisconnectAdapter = new OnDisconnectAdapter(); - this.mAdaptersCount = 0; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - void start() { - // Get active adapter count - synchronized (this.mCaller.mAdapters) { - for (ClientAdapter adapter : this.mCaller.mAdapters) { - int adapterState = adapter.getState(); - if (adapterState != ClientAdapter.State.kDisconnected && adapterState != - ClientAdapter.State.kDisconnecting) { - this.mAdaptersCount++; - } - } - } - - // Disconnect only active adapters - synchronized (this.mCaller.mAdapters) { - for (ClientAdapter adapter : this.mCaller.mAdapters) { - int adapterState = adapter.getState(); - if (adapterState != ClientAdapter.State.kDisconnected && adapterState != - ClientAdapter.State.kDisconnecting) { - adapter.disconnectOnCommand(onDisconnectAdapter); - } - } - } - } - - private OnDisconnectAdapter onDisconnectAdapter; - - class OnDisconnectAdapter implements ClientAdapter.DisconnectResultListener { - @Override - public void onDisconnectResult(boolean isSuccess) { - if (!isSuccess) { - Logger.ERR(kTag, "Disconnecting adapter is failed"); - doneStopCoreTx(mCaller, false, mResultListener); - return; - } - - // Check if all the active adapters are disconnected - boolean doneDisconnectAll = false; - synchronized (mAdaptersCount) { - mAdaptersCount--; - if (mAdaptersCount == 0) { - doneDisconnectAll = true; - } - } - - if (doneDisconnectAll) { - doneStopCoreTx(mCaller, true, mResultListener); - } - } - } - - // Attributes - private Core mCaller; - private Integer mAdaptersCount; - private OnStopSCResult mResultListener; - } -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Device.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Device.java deleted file mode 100644 index f6c41ccd..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Device.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -interface TurnOnResultListener { - void onTurnOnResult(boolean isSuccess); -} - -interface TurnOffResultListener { - void onTurnOffResult(boolean isSuccess); -} - -public abstract class Device { - private final String kTag = "Device"; - - // Main Functions - @SuppressWarnings("SynchronizeOnNonFinalField") - void turnOn(TurnOnResultListener resultListener) { - this.mTurnOnResultListener = resultListener; - - this.setState(State.kTurningOn); - this.turnOnImpl(); - } - - private TurnOnResultListener mTurnOnResultListener; - - protected void doneTurnOn(boolean isSuccess) { - if (isSuccess) { - // Proceed state - this.setState(State.kOn); - } else { - this.setState(State.kOff); - } - - if (this.mTurnOnResultListener != null) { - this.mTurnOnResultListener.onTurnOnResult(isSuccess); - } - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - void turnOff(TurnOffResultListener resultListener) { - this.mTurnOffResultListener = resultListener; - - this.setState(State.kTurningOff); - this.turnOffImpl(); - } - - private TurnOffResultListener mTurnOffResultListener; - - protected void doneTurnOff(boolean isSuccess) { - if (isSuccess) { - // Proceed state - this.setState(State.kOff); - } else { - // Recover original state - this.setState(State.kOn); - } - - if (this.mTurnOffResultListener != null) { - this.mTurnOffResultListener.onTurnOffResult(isSuccess); - } - } - - // Implemented by child classes - protected abstract void turnOnImpl(); - - protected abstract void turnOffImpl(); - - // State - class State { - public static final int kOff = 0; - public static final int kTurningOn = 1; - public static final int kOn = 2; - public static final int kTurningOff = 3; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - protected int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - synchronized (this.mState) { - this.mState = newState; - } - } - - public Device(String name) { - this.mState = State.kOff; - this.mName = name; - } - - // Attributes - private String mName; - - // State - private Integer mState; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ExpConfig.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ExpConfig.java deleted file mode 100644 index 90137bbd..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ExpConfig.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public class ExpConfig { - public static final boolean VERBOSE_SEGMENT_DEQUEUE_CTRL = true; - public static final boolean VERBOSE_SEGMENT_DEQUEUE_DATA = false; - public static final boolean VERBOSE_RECEIVER_TIME = false; - public static final boolean VERBOSE_CLIENT_ADAPTER = false; - public static final boolean VERBOSE_BANDWIDTH_UPDATE = false; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/NetworkSwitcher.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/NetworkSwitcher.java deleted file mode 100644 index 5e44e560..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/NetworkSwitcher.java +++ /dev/null @@ -1,306 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import com.redcarrottt.testapp.Logger; - -public class NetworkSwitcher { - private static final String kTag = "NetworkSwitcher"; - - // Connect adapter command. - // It is called by peer through Core. - void connectAdapterByPeer(int adapterId) { - int state = this.getState(); - if (state == State.kSwitching) { - Logger.VERB(kTag, "It's now switching. Cannot connect to adapter " + adapterId); - return; - } - this.setState(State.kSwitching); - runConnectRequestTx(adapterId); - } - - // Disconnect adapter command. - // It is called by peer through Core. - void disconnectAdapterByPeer(int adapterId, int finalSeqNoControl, int finalSeqNoData) { - int state = this.getState(); - if (state == State.kSwitching) { - Logger.VERB(kTag, "It's now switching. Cannot disconnect to adapter " + adapterId); - return; - } - - Core core = Core.singleton(); - ClientAdapter adapter = core.findAdapterById(adapterId); - if (adapter == null) { - Logger.WARN(kTag, "Cannot find adapter " + adapterId); - return; - } - - this.setState(State.kSwitching); - - adapter.disconnectOnPeerCommand(onResultDisconnectAdapterByPeer, finalSeqNoControl, finalSeqNoData); - } - - ClientAdapter.DisconnectResultListener onResultDisconnectAdapterByPeer = new ClientAdapter - .DisconnectResultListener() { - @Override - public void onDisconnectResult(boolean isSuccess) { - NetworkSwitcher switcher = NetworkSwitcher.singleton(); - switcher.doneSwitch(); - } - }; - - // Sleep adapter command. - // It is called by peer through Core. - void sleepAdapterByPeer(int adapterId) { - int state = this.getState(); - if (state == State.kSwitching) { - Logger.VERB(kTag, "It's now switching. Cannot sleep to adapter " + adapterId); - return; - } - this.setState(State.kSwitching); - ClientAdapter adapter = Core.singleton().findAdapterById(adapterId); - adapter.sleep(false); - this.setState(State.kReady); - } - - // Wake up adapter command. - // It is called by peer through Core. - void wakeUpAdapterByPeer(int adapterId) { - int state = this.getState(); - if (state == State.kSwitching) { - Logger.VERB(kTag, "It's now switching. Cannot sleep to adapter " + adapterId); - return; - } - this.setState(State.kSwitching); - ClientAdapter adapter = Core.singleton().findAdapterById(adapterId); - adapter.wakeUp(false); - this.setState(State.kReady); - } - - // Reconnect adapter command. - // It is called by Core. - void reconnectAdapter(ClientAdapter adapter) { - // If it is disconnecting on purpose, do not reconnect it. - if (adapter.isDisconnectingOnPurpose()) { - return; - } - - int state = this.getState(); - if (state == State.kSwitching) { - Logger.VERB(kTag, adapter.getName() + ": It's now switching. Cannot reconnect " + - "adapter" + "."); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - this.reconnectAdapter(adapter); - return; - } - this.setState(State.kSwitching); - runReconnectAdapterTx(adapter); - } - - // Notification of switch done event - private void doneSwitch() { - int state = this.getState(); - switch (state) { - case State.kSwitching: - this.setState(State.kReady); - break; - case State.kReady: - break; - } - } - - // State Getter/Setter - @SuppressWarnings("SynchronizeOnNonFinalField") - private int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - synchronized (this.mState) { - this.mState = newState; - } - } - - class State { - public static final int kReady = 0; - public static final int kSwitching = 1; - } - - // State - private Integer mState; - - // Singleton - private static NetworkSwitcher sSingleton; - - public static NetworkSwitcher singleton() { - if (sSingleton == null) { - sSingleton = new NetworkSwitcher(); - } - return sSingleton; - } - - // Constructor - private NetworkSwitcher() { - // Since there is no NetworkSwitcher for Android implementation, - // NetworkSwitcher's initial state goes to Running at beginning. - this.mState = State.kReady; - } - - // Transactions - // ---------------------------------------------------------------- - // Singleton runner - private static boolean runConnectRequestTx(int adapterId) { - if (sOngoingConnectRequest == null) { - sOngoingConnectRequest = new ConnectRequestTransaction(adapterId); - sOngoingConnectRequest.start(); - return true; - } else { - Logger.WARN(kTag, "Already connecting"); - return false; - } - } - - private static void doneConnectRequestTx(boolean isSuccess) { - sOngoingConnectRequest = null; - if (!isSuccess) { - Logger.WARN(kTag, "Connection request failed"); - } - NetworkSwitcher.singleton().doneSwitch(); - sOngoingConnectRequest = null; - } - - private static void runReconnectAdapterTx(ClientAdapter adapter) { - if (sOngoingReconnectAdapter == null) { - sOngoingReconnectAdapter = new ReconnectAdapterTransaction(adapter); - sOngoingReconnectAdapter.start(); - } else { - Logger.WARN(kTag, "Already stopping core"); - } - } - - private static void restartReconnectAdapterTx(ClientAdapter adapter) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - sOngoingReconnectAdapter = null; - runReconnectAdapterTx(adapter); - } - - private static ConnectRequestTransaction sOngoingConnectRequest = null; - private static ReconnectAdapterTransaction sOngoingReconnectAdapter = null; - - private static class ConnectRequestTransaction { - private ConnectRequestTransaction(int adapterId) { - this.mAdapterId = adapterId; - this.onConnectAdapter = new OnConnectAdapter(); - } - - void start() { - ClientAdapter adapter = Core.singleton().findAdapterById(this.mAdapterId); - if (adapter == null) { - Logger.ERR(kTag, "Connecting requested adapter is failed"); - doneConnectRequestTx(false); - return; - } - adapter.connect(onConnectAdapter, false); - } - - private OnConnectAdapter onConnectAdapter; - - class OnConnectAdapter implements ClientAdapter.ConnectResultListener { - @Override - public void onConnectResult(boolean isSuccess) { - if (!isSuccess) { - Logger.ERR(kTag, "Connecting requested adapter is failed"); - doneConnectRequestTx(false); - return; - } - Logger.VERB(kTag, "Connecting requested adapter is done"); - doneConnectRequestTx(true); - } - } - - private int mAdapterId; - } - - private static class ReconnectAdapterTransaction { - private ReconnectAdapterTransaction(ClientAdapter targetAdapter) { - this.onConnectAdapter = new OnConnectAdapter(); - this.onDisconnectAdapter = new OnDisconnectAdapter(); - this.mTargetAdapter = targetAdapter; - } - - private ClientAdapter mTargetAdapter; - - void start() { - if (this.mTargetAdapter == null) { - Logger.ERR(kTag, "Reconnecting adapter is failed: retry"); - restartReconnectAdapterTx(mTargetAdapter); - return; - } - this.mTargetAdapter.disconnectOnFailure(onDisconnectAdapter); - } - - private OnDisconnectAdapter onDisconnectAdapter; - - class OnDisconnectAdapter implements ClientAdapter.DisconnectResultListener { - @Override - public void onDisconnectResult(boolean isSuccess) { - if (!isSuccess) { - Logger.ERR(kTag, "Reconnecting adapter is failed: retry"); - restartReconnectAdapterTx(mTargetAdapter); - return; - } - if (mTargetAdapter == null) { - Logger.ERR(kTag, "Reconnecting adapter is failed: retry"); - restartReconnectAdapterTx(mTargetAdapter); - return; - } - - mTargetAdapter.connect(onConnectAdapter, false); - } - } - - private OnConnectAdapter onConnectAdapter; - - class OnConnectAdapter implements ClientAdapter.ConnectResultListener { - @Override - public void onConnectResult(boolean isSuccess) { - if (!isSuccess) { - Logger.ERR(kTag, "Reconnecting adapter is failed: retry"); - restartReconnectAdapterTx(mTargetAdapter); - return; - } - - Logger.VERB(kTag, "Reconnecting adapter is done"); - NetworkSwitcher.singleton().doneSwitch(); - } - } - } -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnConnectResult.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnConnectResult.java deleted file mode 100644 index 460aa60f..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnConnectResult.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.redcarrottt.sc.internal; - -public interface OnConnectResult { - public void onDoneConnect(boolean isSuccess); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDisconnectResult.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDisconnectResult.java deleted file mode 100644 index a6848747..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDisconnectResult.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.redcarrottt.sc.internal; - -public interface OnDisconnectResult { - public void onDoneDisconnect(boolean isSuccess); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDiscoverResult.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDiscoverResult.java deleted file mode 100644 index 767da676..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDiscoverResult.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.redcarrottt.sc.internal; - -public interface OnDiscoverResult { - public void onDoneDiscover(boolean isSuccess); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/P2PClient.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/P2PClient.java deleted file mode 100644 index 3a8b2af9..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/P2PClient.java +++ /dev/null @@ -1,196 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import com.redcarrottt.testapp.Logger; - -interface DiscoverAndConnectResultListener { - void onDiscoverAndConnectResult(boolean isSuccess); -} - -interface DisconnectResultListener { - void onDisconnectResult(boolean isSuccess); -} - -public abstract class P2PClient { - private final String kTag = "P2PClient"; - - // Main function 1: Discover and connect - public void discoverAndConnect(DiscoverAndConnectResultListener resultListener) { - if (this.getState() != State.kDisconnected) { - Logger.ERR(kTag, "It's already connected or discovering is in progress"); - doneDiscoverAndConnectTx(resultListener, false); - return; - } - runDiscoverAndConnectTx(resultListener); - } - - private void runDiscoverAndConnectTx(DiscoverAndConnectResultListener resultListener) { - if (sOngoingDiscoverConnectTx == null) { - sOngoingDiscoverConnectTx = new DiscoverAndConnectTransaction(); - sOngoingDiscoverConnectTx.start(resultListener); - } else { - Logger.ERR(kTag, "Discover/Connect has already been in progress."); - doneDiscoverAndConnectTx(resultListener, false); - } - } - - private void doneDiscoverAndConnectTx(DiscoverAndConnectResultListener resultListener, - boolean isSuccess) { - sOngoingDiscoverConnectTx = null; - if (isSuccess) { - this.setState(State.kConnected); - } else { - this.setState(State.kDisconnected); - } - - if (resultListener != null) { - resultListener.onDiscoverAndConnectResult(isSuccess); - } - } - - private static DiscoverAndConnectTransaction sOngoingDiscoverConnectTx = null; - - class DiscoverAndConnectTransaction { - private DiscoverAndConnectResultListener mResultListener; - - DiscoverAndConnectTransaction() { - } - - void start(DiscoverAndConnectResultListener resultListener) { - this.mResultListener = resultListener; - - setState(State.kDiscovering); - discoverImpl(onDiscoverResult); - } - - private OnDiscoverResult onDiscoverResult = new OnDiscoverResult() { - @Override - public void onDoneDiscover(boolean isSuccess) { - if (isSuccess) { - setState(State.kConnecting); - connectImpl(onConnectResult); - } else { - doneDiscoverAndConnectTx(mResultListener, false); - } - } - }; - - private OnConnectResult onConnectResult = new OnConnectResult() { - @Override - public void onDoneConnect(boolean isSuccess) { - doneDiscoverAndConnectTx(mResultListener, isSuccess); - } - }; - } - - // Main function 2: Disconnect - public void disconnect(DisconnectResultListener resultListener) { - int state = this.getState(); - if (state == State.kDisconnected || state == State.kDisconnecting) { - Logger.ERR(kTag, "It's already disconnected or disconnecting is in progress"); - doneDisconnectTx(resultListener, false); - return; - } - runDisconnectTx(resultListener); - } - - private void runDisconnectTx(DisconnectResultListener resultListener) { - if (sOngoingDisconnectTx == null) { - sOngoingDisconnectTx = new DisconnectTransaction(); - sOngoingDisconnectTx.start(resultListener); - } else { - Logger.ERR(kTag, "Disconnection has already been in progress."); - doneDisconnectTx(resultListener, false); - } - } - - private void doneDisconnectTx(DisconnectResultListener resultListener, boolean isSuccess) { - sOngoingDisconnectTx = null; - if (isSuccess) { - this.setState(State.kDisconnected); - } else { - this.setState(State.kConnected); - } - if (resultListener != null) { - resultListener.onDisconnectResult(isSuccess); - } - } - - private static DisconnectTransaction sOngoingDisconnectTx = null; - - class DisconnectTransaction { - private DisconnectResultListener mResultListener; - - DisconnectTransaction() { - } - - void start(DisconnectResultListener resultListener) { - this.mResultListener = resultListener; - - setState(State.kDisconnecting); - disconnectImpl(onDisconnectResult); - } - - private OnDisconnectResult onDisconnectResult = new OnDisconnectResult() { - @Override - public void onDoneDisconnect(boolean isSuccess) { - doneDisconnectTx(mResultListener, isSuccess); - } - }; - - } - - // Implemented by child classes - protected abstract void discoverImpl(OnDiscoverResult onDiscoverResult); - - protected abstract void connectImpl(OnConnectResult onConnectResult); - - protected abstract void disconnectImpl(OnDisconnectResult onDisconnectResult); - - // State - class State { - public static final int kDisconnected = 0; - public static final int kDiscovering = 1; - public static final int kConnecting = 2; - public static final int kConnected = 3; - public static final int kDisconnecting = 4; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - protected int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - synchronized (this.mState) { - this.mState = newState; - } - } - - protected P2PClient() { - this.mState = State.kDisconnected; - } - - // State - private Integer mState; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ProtocolManager.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ProtocolManager.java deleted file mode 100644 index df47ef4a..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ProtocolManager.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * Eunsoo Park (esevan.park@gmail.com) - * Injung Hwang (sinban04@gmail.com) - * - * 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. - */ - -import java.nio.ByteBuffer; - -class ProtocolData { - short id; - int len; - byte[] data; - - ProtocolData() { - id = 0; - len = 0; - data = null; - } -} - -class ProtocolManager { - static public final int kProtocolHeaderSize = 6; - - static private short sPacketId; - static private byte[] sSerializedVector = null; - - static private void serialize_header(ProtocolData pd, byte[] vec_ptr) { - if (vec_ptr == null) throw new AssertionError(); - - int vec_offset = 0; - - ByteBuffer buffer = ByteBuffer.allocate(2); - - buffer.putShort(pd.id); - byte[] net_id = buffer.array(); - - buffer = ByteBuffer.allocate(4); - buffer.putInt(pd.len); - byte[] net_len = buffer.array(); - - System.arraycopy(net_id, 0, vec_ptr, vec_offset, 2); - vec_offset += 2; - - System.arraycopy(net_len, 0, vec_ptr, vec_offset, 4); - } - - static public ProtocolData data_to_protocol_data(byte[] buf, int len) { - ProtocolData pd = new ProtocolData(); - - pd.id = sPacketId++; - pd.len = len; - pd.data = buf; - - return pd; - } - - static public int serialize(ProtocolData protocolData, byte[] buf, int offset, int - payload_size) { - int vec_size; - int data_offset; - - data_offset = kProtocolHeaderSize; - vec_size = data_offset + payload_size; - - sSerializedVector = new byte[vec_size]; - - serialize_header(protocolData, sSerializedVector); - System.arraycopy(buf, offset, sSerializedVector, data_offset, payload_size); - - if (sSerializedVector == null) throw new AssertionError(); - - return vec_size; - } - - static void parse_header(byte[] serialized, ProtocolData protocolData) { - if (serialized == null || protocolData == null) throw new AssertionError(); - - int vec_offset = 0; - ByteBuffer buffer = ByteBuffer.allocate(2); - - buffer.put(serialized, vec_offset, 2); - protocolData.id = buffer.getShort(0); - vec_offset += 2; - - buffer = ByteBuffer.allocate(4); - buffer.put(serialized, vec_offset, 4); - protocolData.len = buffer.getInt(0); - } - - static public int send_packet(int packetSize, boolean isControl) { - SegmentManager sm = SegmentManager.singleton(); - - return sm.send_to_segment_manager(sSerializedVector, packetSize, isControl); - } - - static public int recv_packet(byte[] buf, boolean isControl) { - if (buf == null) throw new AssertionError(); - - ProtocolData protocolData = new ProtocolData(); - SegmentManager sm = SegmentManager.singleton(); - - byte[] data = sm.recv_from_segment_manager(protocolData, isControl); - - System.arraycopy(data, 0, buf, 0, (protocolData.len < buf.length) ? protocolData.len : - buf.length); - - - return protocolData.len; - } - -// private static String kTag = "protocol manager"; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/SegmentManager.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/SegmentManager.java deleted file mode 100644 index 87e8a2bd..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/SegmentManager.java +++ /dev/null @@ -1,488 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * Eunsoo Park (esevan.park@gmail.com) - * Injung Hwang (sinban04@gmail.com) - * - * 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. - */ - -import com.redcarrottt.testapp.Logger; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.ListIterator; - -/* - Segment is the minimum unit of the sending data through the network. - Segment header (sequence # + len + flag) is 16bytes (4bytes + 4bytes + 4bytes) - */ -class Segment { - int seq_no; - int len; - int flag; - byte[] data; - - Segment() { - seq_no = -1; - len = 0; - flag = 0; - data = new byte[SegmentManager.kSegSize + SegmentManager.kSegHeaderSize]; - } -} - -class SegmentManager { - static private SegmentManager instance = null; - static public final int kSegSize = 512; - private static final int kSegFreeThreshold = 256; - - static public final int kSegHeaderSize = 12; - - static final int kSQSendData = 0; - static final int kSQRecvData = 1; - static final int kSQSendControl = 2; - static final int kSQRecvControl = 3; - private static final int kNumSQ = 4; - static final int kSQUnknown = 999; - - static final int kDeqSendControlData = 0; - static final int kDeqRecvData = 1; - static final int kDeqRecvControl = 2; - private static final int kNumDeq = 3; - - static final int kSNData = 0; - static final int kSNControl = 1; - private static final int kNumSN = 2; - - static final short kSegFlagMF = 1; - static final short kSegFlagControl = 2; - - private int[] mNextSeqNo; - private int[] mExpectedSeqNo; - - private LinkedList[] mQueues; - private Object[] mDequeueCond; - private final LinkedList mFailedSendingQueue; - private LinkedList[] mPendingQueue; - private int[] mQueueLengths; - - private static String kTag = "SegmentManager"; - - private final LinkedList mFreeSegments; - private int mFreeSegmentsSize; - - private SegmentManager() { - this.mQueues = new LinkedList[kNumSQ]; - for (int i = 0; i < kNumSQ; i++) { - this.mQueues[i] = new LinkedList(); - } - - this.mDequeueCond = new Object[kNumDeq]; - for (int i = 0; i < kNumDeq; i++) { - this.mDequeueCond[i] = new Object(); - } - - this.mFailedSendingQueue = new LinkedList(); - this.mPendingQueue = new LinkedList[kNumSQ]; - for (int i = 0; i < kNumSQ; i++) { - this.mPendingQueue[i] = new LinkedList(); - } - - this.mQueueLengths = new int[kNumSQ]; - for (int i = 0; i < kNumSQ; i++) { - this.mQueueLengths[i] = 0; - } - - this.mExpectedSeqNo = new int[kNumSQ]; - for (int i = 0; i < kNumSQ; i++) { - this.mExpectedSeqNo[i] = 0; - } - - this.mNextSeqNo = new int[kNumSN]; - for (int i = 0; i < kNumSN; i++) { - this.mNextSeqNo[i] = 0; - } - - this.mFreeSegments = new LinkedList(); - } - - - static public SegmentManager singleton() { - if (instance == null) instance = new SegmentManager(); - - return instance; - } - - private int getNextSeqNo(int seq_num_type, int length) { - int ret = mNextSeqNo[seq_num_type]; - mNextSeqNo[seq_num_type] += length; - return ret; - } - - // Wait data before disconnection - public void waitReceiving(int wait_seq_no_control, int wait_seq_no_data) { - synchronized (this.mWaitReceiving) { - this.mIsWaitReceiving = true; - this.mWaitSeqNoControl = wait_seq_no_control; - this.mWaitSeqNoData = wait_seq_no_data; - try { - this.mWaitReceiving.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public int getLastSeqNoControl() { - return this.mNextSeqNo[kSNControl] - 1; - } - - public int getLastSeqNoData() { - return this.mNextSeqNo[kSNData] - 1; - } - - private void checkReceivingDone() { - boolean is_wakeup = false; - synchronized (this.mWaitReceiving) { - if (this.mIsWaitReceiving && this.mExpectedSeqNo[kSQRecvControl] >= this - .mWaitSeqNoControl && this.mExpectedSeqNo[kSQRecvData] >= this.mWaitSeqNoData) { - is_wakeup = true; - } - - if (is_wakeup) { - this.mWaitReceiving.notifyAll(); - this.mIsWaitReceiving = false; - } - } - } - - public void wakeUpDequeueWaiting(int dequeueType) { - synchronized (mDequeueCond[dequeueType]) { - this.mDequeueCond[dequeueType].notifyAll(); - } - } - - boolean mIsWaitReceiving = false; - int mWaitSeqNoControl = 0; - int mWaitSeqNoData = 0; - Object mWaitReceiving = new Object(); - - public int send_to_segment_manager(byte[] data, int length, boolean isControl) { - if (data == null || length <= 0) throw new AssertionError(); - - int offset = 0; - int num_of_segments = (length + kSegSize - 1) / kSegSize; - int seq_num_type = (isControl) ? kSNControl : kSNData; - int allocated_seq_no = getNextSeqNo(seq_num_type, num_of_segments); - int seg_idx; - for (seg_idx = 0; seg_idx < num_of_segments; seg_idx++) { - int seg_len = (length - offset < kSegSize) ? (length - offset) : kSegSize; - Segment seg = get_free_segment(); - - // 0~3: seq_no - seg.seq_no = allocated_seq_no++; - - // 4~7: len - seg.len = seg_len; - - // 8~11: flag - int flag = 0; - if (offset + seg_len < length) flag = flag | kSegFlagMF; - if (isControl) flag = flag | kSegFlagControl; - seg.flag = flag; - - // 12~: data - System.arraycopy(data, offset, seg.data, kSegHeaderSize, seg_len); - offset += seg_len; - - serialize_segment_header(seg); - - if (isControl) { - enqueue(kSQSendControl, seg); - } else { - enqueue(kSQSendData, seg); - } - } - - return 0; - } - - private void serialize_segment_header(Segment segment) { - ByteBuffer buffer = ByteBuffer.allocate(4); - buffer.putInt(segment.seq_no); - byte[] net_seq_no = buffer.array(); - - buffer = ByteBuffer.allocate(4); - buffer.putInt(segment.len); - byte[] net_len = buffer.array(); - - buffer = ByteBuffer.allocate(4); - buffer.putInt(segment.flag); - byte[] net_flag = buffer.array(); - - System.arraycopy(net_seq_no, 0, segment.data, 0, 4); - System.arraycopy(net_len, 0, segment.data, 4, 4); - System.arraycopy(net_flag, 0, segment.data, 8, 4); - } - - public byte[] recv_from_segment_manager(ProtocolData protocolData, boolean isControl) { - if (protocolData == null) throw new AssertionError(); - - byte[] serialized; - int offset = 0; - int data_size; - boolean cont; - - Segment seg; - do { - if (isControl) { - seg = dequeue(kDeqRecvControl); - } else { - seg = dequeue(kDeqRecvData); - } - } while (seg == null); - ProtocolManager.parse_header(Arrays.copyOfRange(seg.data, kSegHeaderSize, seg.data - .length), protocolData); - if (protocolData.len == 0) return null; - - //Logger.DEBUG(kTag, "pd.len is " + pd.len); - serialized = new byte[protocolData.len]; - - // Handle the first segment of the data bulk, because it contains protocol data - data_size = seg.len - ProtocolManager.kProtocolHeaderSize; - System.arraycopy(seg.data, kSegHeaderSize + ProtocolManager.kProtocolHeaderSize, - serialized, offset, data_size); - offset += data_size; - - cont = ((seg.flag & kSegFlagMF) != 0); - free_segment(seg); - - while (cont) { - do { - if (isControl) { - seg = dequeue(kDeqRecvControl); - } else { - seg = dequeue(kDeqRecvData); - } - } while (seg == null); - data_size = seg.len; - System.arraycopy(seg.data, kSegHeaderSize, serialized, offset, data_size); - cont = ((seg.flag & kSegFlagMF) != 0); - offset += data_size; - free_segment(seg); - } - - return serialized; - } - - @SuppressWarnings("unchecked") - public void enqueue(int queueType, Segment segment) { - if (queueType >= kNumSQ) throw new AssertionError(); - - int dequeueType; - switch (queueType) { - case kSQRecvControl: - dequeueType = kDeqRecvControl; - break; - case kSQRecvData: - dequeueType = kDeqRecvData; - break; - case kSQSendControl: - case kSQSendData: - dequeueType = kDeqSendControlData; - break; - default: - Logger.ERR(kTag, "Enqueue: Unknown queue type: " + queueType); - return; - } - - - boolean segmentEnqueued = false; - - synchronized (this.mQueues[queueType]) { - if (segment.seq_no == this.mExpectedSeqNo[queueType]) { - // Case 1. this seq no. = expected seq no. - // In-order segments -> enqueue to the target queue - this.mExpectedSeqNo[queueType]++; - - this.mQueues[queueType].offerLast(segment); - this.mQueueLengths[queueType]++; - segmentEnqueued = true; - } else if (segment.seq_no < this.mExpectedSeqNo[queueType]) { - // Case 2. this seq no. < expected seq no. - // Duplicated segments -> ignore - return; - } else { - // Case 3. this seq no. > expected seq no. - // Out-of-order segments -> insert at the proper position of pending queue - ListIterator it = this.mPendingQueue[queueType].listIterator(); - while (it.hasNext()) { - Segment walker = (Segment) it.next(); - if (walker.seq_no > segment.seq_no) break; - } - it.add(segment); - Logger.WARN(kTag, "Pending Queue: (" + queueType + ") incoming=" + segment - .seq_no + " / expected_next=" + this.mExpectedSeqNo[queueType]); - } - - // TODO: why do that? - ListIterator it = this.mPendingQueue[queueType].listIterator(); - while (it.hasNext()) { - Segment walker = (Segment) it.next(); - - if (walker.seq_no != this.mExpectedSeqNo[queueType]) break; - - this.mQueues[queueType].offerLast(walker); - this.mQueueLengths[queueType]++; - this.mExpectedSeqNo[queueType]++; - segmentEnqueued = true; - - it.remove(); - } - } - - if (segmentEnqueued) { - this.wakeUpDequeueWaiting(dequeueType); - } - - this.checkReceivingDone(); - } - - public Segment dequeue(int dequeueType) { - assert (dequeueType < kNumDeq); - synchronized (this.mDequeueCond[dequeueType]) { - // If queue is empty, wait until some segment is enqueued - boolean isWaitRequired = false; - switch (dequeueType) { - case kDeqSendControlData: - isWaitRequired = ((this.mQueueLengths[kSQSendControl] == 0) && (this - .mQueueLengths[kSQSendData] == 0)); - break; - case kDeqRecvControl: - isWaitRequired = (this.mQueueLengths[kSQRecvControl] == 0); - break; - case kDeqRecvData: - isWaitRequired = (this.mQueueLengths[kSQRecvData] == 0); - break; - } - if (isWaitRequired) { - try { - this.mDequeueCond[dequeueType].wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - // Set target queue type - int targetQueueType = kSQUnknown; - switch (dequeueType) { - case kDeqSendControlData: - if (this.mQueueLengths[kSQSendControl] != 0) { - // Priority 1. Dequeue send control queue - targetQueueType = kSQSendControl; - } else if (this.mQueueLengths[kSQSendData] != 0) { - // Priority 2. Dequeue send data queue - targetQueueType = kSQSendData; - } else { - return null; - } - break; - case kDeqRecvControl: - targetQueueType = kSQRecvControl; - break; - case kDeqRecvData: - targetQueueType = kSQRecvData; - break; - default: - Logger.ERR(kTag, "Dequeue failed: invalid dequeue type (Dequeue=" + - dequeueType + ")"); - return null; - } - - // Check queue type - if (targetQueueType >= kNumSQ) { - Logger.ERR(kTag, "Dequeue failed: invalid queue type (Dequeue=" + dequeueType + - ")"); - return null; - } - - // Dequeue from queue - synchronized (this.mQueues[targetQueueType]) { - // Check the dequeued segment - Segment segmentDequeued = (Segment) this.mQueues[targetQueueType].pollFirst(); - if (segmentDequeued == null) { -// Logger.DEBUG(kTag, "Dequeue interrupted: empty queue (queue=" + -// targetQueueType + ", dequeue=" + dequeueType + ")"); - return null; - } - mQueueLengths[targetQueueType]--; - return segmentDequeued; - } - } - } - - public Segment get_free_segment() { - Segment ret; - synchronized (mFreeSegments) { - if (mFreeSegmentsSize == 0) { - ret = new Segment(); - } else { - ret = mFreeSegments.pop(); - mFreeSegmentsSize--; - } - - if (ret == null) throw new AssertionError(); - - ret.seq_no = -1; - ret.flag = 0; - ret.len = 0; - } - return ret; - } - - public void free_segment(Segment seg) { - synchronized (mFreeSegments) { - mFreeSegments.push(seg); - mFreeSegmentsSize++; - - if (mFreeSegmentsSize > kSegFreeThreshold) { - release_segment_from_free_list(kSegFreeThreshold / 2); - } - } - } - - private void release_segment_from_free_list(int threshold) { - while (mFreeSegmentsSize > threshold) { - mFreeSegments.pop(); - mFreeSegmentsSize--; - } - } - - public void failed_sending(Segment seg) { - synchronized (mFailedSendingQueue) { - mFailedSendingQueue.offerLast(seg); - this.wakeUpDequeueWaiting(kDeqSendControlData); - } - } - - public Segment get_failed_sending() { - Segment ret; - synchronized (mFailedSendingQueue) { - ret = mFailedSendingQueue.pollFirst(); - } - - return ret; - } -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtClientAdapter.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtClientAdapter.java deleted file mode 100644 index 89c2ed19..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtClientAdapter.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.redcarrottt.sc.internal.bt; - -import android.app.Activity; - -import com.redcarrottt.sc.internal.ClientAdapter; - -public class BtClientAdapter extends ClientAdapter { - // Singleton - static public BtClientAdapter singleton(int id, String name, String targetMacAddr, String - serviceUuid, Activity ownerActivity) { - if (sSingleton == null) { - sSingleton = new BtClientAdapter(id, name, targetMacAddr, serviceUuid, ownerActivity); - } - return sSingleton; - } - - static private BtClientAdapter sSingleton = null; - - // Constructor - private BtClientAdapter(int id, String name, String targetMacAddr, String serviceUuid, - Activity ownerActivity) { - super(id, name); - - // Components - BtDevice device = new BtDevice(ownerActivity); - BtP2PClient p2pClient = new BtP2PClient(); - RfcommClientSocket clientSocket = new RfcommClientSocket(targetMacAddr, serviceUuid); - - // Initialize - this.initialize(device, p2pClient, clientSocket); - } -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtDevice.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtDevice.java deleted file mode 100644 index bb9e7221..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtDevice.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.redcarrottt.sc.internal.bt; - -import android.app.Activity; -import android.bluetooth.BluetoothAdapter; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; - -import com.redcarrottt.sc.internal.Device; -import com.redcarrottt.testapp.Logger; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -class BtDevice extends Device { - private static final String kTag = "BtDevice"; - - // TODO: there is no timeout on turn on/off of BtDevice - @Override - protected void turnOnImpl() { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter.isEnabled()) { - Logger.DEBUG(kTag, "Bluetooth is already turned on"); - this.doneTurnOn(true); - } else { - // Register bluetooth device on event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - Context context = this.mOwnerActivity.getApplicationContext(); - context.registerReceiver(this.mBtDeviceOnEventReceiver, intentFilter); - - // turn on adapter command - adapter.enable(); - } - } - - @Override - protected void turnOffImpl() { - // Register bluetooth device off event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - Context context = this.mOwnerActivity.getApplicationContext(); - context.registerReceiver(this.mBtDeviceOffEventReceiver, intentFilter); - - // turn off adapter command - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if(!adapter.isEnabled()) { - Logger.DEBUG(kTag, "Bluetooth is already turned off"); - this.doneTurnOff(true); - } else { - adapter.disable(); - } - } - - private BroadcastReceiver mBtDeviceOnEventReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, - BluetoothAdapter.ERROR); - Logger.DEBUG(kTag, "Bluetooth Adapter state changed: " + state); - if (state == BluetoothAdapter.STATE_ON) { - Logger.DEBUG(kTag, "Bluetooth is turned on successfully"); - doneTurnOn(true); - context.unregisterReceiver(mBtDeviceOnEventReceiver); - } - } - } - }; - - private BroadcastReceiver mBtDeviceOffEventReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, - BluetoothAdapter.ERROR); - Logger.DEBUG(kTag, "Bluetooth Adapter state changed: " + state); - if (state == BluetoothAdapter.STATE_OFF) { - Logger.DEBUG(kTag, "Bluetooth is turned off successfully"); - doneTurnOff(true); - context.unregisterReceiver(mBtDeviceOffEventReceiver); - } - } - } - }; - - private Activity mOwnerActivity; - - // Constructor - public BtDevice(Activity ownerActivity) { - super("Bluetooth"); - this.mOwnerActivity = ownerActivity; - } -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtP2PClient.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtP2PClient.java deleted file mode 100644 index 2c6c3795..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtP2PClient.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.redcarrottt.sc.internal.bt; - -import com.redcarrottt.sc.internal.OnConnectResult; -import com.redcarrottt.sc.internal.OnDisconnectResult; -import com.redcarrottt.sc.internal.OnDiscoverResult; -import com.redcarrottt.sc.internal.P2PClient; - -class BtP2PClient extends P2PClient { - @Override - protected void discoverImpl(OnDiscoverResult onDiscoverResult) { - // Assume that target device has already been bonded. - onDiscoverResult.onDoneDiscover(true); - } - - @Override - protected void connectImpl(OnConnectResult onConnectResult) { - // Assume that target device has already been bonded. - onConnectResult.onDoneConnect(true); - } - - @Override - protected void disconnectImpl(OnDisconnectResult onDisconnectResult) { - // Assume that target device has already been bonded. - onDisconnectResult.onDoneDisconnect(true); - } - - // Constructor - public BtP2PClient() { - } - - // Attributes -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/RfcommClientSocket.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/RfcommClientSocket.java deleted file mode 100644 index d7d69e8b..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/RfcommClientSocket.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.redcarrottt.sc.internal.bt; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothSocket; - -import com.redcarrottt.sc.internal.ClientSocket; -import com.redcarrottt.testapp.Logger; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.util.Set; -import java.util.UUID; - -class RfcommClientSocket extends ClientSocket { - private static String kTag = "RfcommClientSocket"; - - @Override - protected boolean openImpl() { - // Initialize socket - this.mSocket = null; - Set pairedBtDevices = BluetoothAdapter.getDefaultAdapter() - .getBondedDevices(); - for (BluetoothDevice btDevice : pairedBtDevices) { - Logger.DEBUG(kTag, "Found Device: " + btDevice.getAddress() + " / " + btDevice - .getName()); - if (btDevice.getAddress().equals(this.mTargetMacAddr)) { - try { - this.mSocket = btDevice.createRfcommSocketToServiceRecord(this.mServiceUuid); - } catch (IOException e) { - Logger.ERR(kTag, "Socket initialization failed"); - return false; - } - } - } - if (this.mSocket == null) { - Logger.ERR(kTag, "Cannot create bluetooth socket"); - return false; - } - - // Try to open socket - final int kMaxTries = 10; - for (int tries = 0; tries < kMaxTries; tries++) { - try { - this.mSocket.connect(); - this.mInputStream = new BufferedInputStream(this.mSocket.getInputStream()); - this.mOutputStream = new BufferedOutputStream(this.mSocket.getOutputStream()); - break; - } catch (IOException e) { - this.mInputStream = null; - this.mOutputStream = null; - Logger.WARN(kTag, "Try socket open " + tries); - } - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - if (this.mSocket.isConnected()) { - Logger.VERB(kTag, "Socket open success"); - return true; - } else { - Logger.ERR(kTag, "Socket open failed!"); - this.mSocket = null; - return false; - } - } - - @Override - protected boolean closeImpl() { - if (this.mSocket != null && this.mSocket.isConnected()) { - try { - this.mInputStream.close(); - this.mOutputStream.close(); - this.mSocket.close(); - Logger.VERB(kTag, "Socket closed"); - return true; - } catch (IOException e) { - return false; - } - } - return true; - } - - @Override - protected int sendImpl(byte[] dataBuffer, int dataLength) { - if (this.mSocket == null || !this.mSocket.isConnected() || this.mOutputStream == null) { - Logger.ERR(kTag, "Socket closed! Send failed!"); - return -1; - } - try { - this.mOutputStream.write(dataBuffer, 0, dataLength); - this.mOutputStream.flush(); - return dataLength; - } catch (IOException e) { - Logger.ERR(kTag, "Send failed! / " + e.getMessage()); - return -2; - } - } - - @Override - protected int receiveImpl(byte[] dataBuffer, int dataLength) { - if (this.mSocket == null || !this.mSocket.isConnected() || this.mInputStream == null) { - Logger.ERR(kTag, "Socket closed! Receive failed!"); - return -1; - } - try { - int receivedBytes = 0; - while (receivedBytes < dataLength) { - int onceReceivedBytes = this.mInputStream.read(dataBuffer, receivedBytes, - dataLength - receivedBytes); - if (onceReceivedBytes < 0) { - Logger.ERR(kTag, "Receive failed! 1"); - return -2; - } - receivedBytes += onceReceivedBytes; - } - return dataLength; - } catch (IOException e) { - Logger.ERR(kTag, "Receive failed! 2 / " + e.getMessage()); - return -3; - } - } - - // Constructor - RfcommClientSocket(String targetMacAddr, String serviceUuid) { - this.mTargetMacAddr = targetMacAddr; - this.mServiceUuid = UUID.fromString(serviceUuid); - } - - private BluetoothSocket mSocket; - private BufferedInputStream mInputStream; - private BufferedOutputStream mOutputStream; - - // Attributes - private String mTargetMacAddr; - private UUID mServiceUuid; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/TcpClientSocket.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/TcpClientSocket.java deleted file mode 100644 index 5e839c7c..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/TcpClientSocket.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.redcarrottt.sc.internal.wfd; - -import com.redcarrottt.sc.internal.ClientSocket; -import com.redcarrottt.testapp.Logger; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; - -class TcpClientSocket extends ClientSocket { - private final String kTag = "TcpClientSocket"; - - @Override - protected boolean openImpl() { - Logger.DEBUG(kTag, "Connect to server " + this.getTargetIpAddress() + ":" + this - .mTargetPort); - - // Try to open socket - final int kMaxTries = 10; - for (int tries = 0; tries < kMaxTries; tries++) { - try { - this.mSocket = new Socket(); - this.mSocket.setReuseAddress(true); - this.mSocket.bind(null); - this.mSocket.connect(new InetSocketAddress(this.getTargetIpAddress(), this - .mTargetPort)); - this.mInputStream = new BufferedInputStream(this.mSocket.getInputStream()); - this.mOutputStream = new BufferedOutputStream(this.mSocket.getOutputStream()); - break; - } catch (IOException e) { - this.mSocket = null; - this.mInputStream = null; - this.mOutputStream = null; - Logger.WARN(kTag, "Try socket open " + tries); - } - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - if (this.mSocket != null && this.mSocket.isConnected()) { - Logger.VERB(kTag, "Socket open success"); - return true; - } else { - Logger.ERR(kTag, "Socket open failed!"); - this.mSocket = null; - return false; - } - } - - @Override - protected boolean closeImpl() { - if (this.mSocket != null && this.mSocket.isConnected()) { - try { - this.mInputStream.close(); - this.mOutputStream.close(); - this.mSocket.close(); - Logger.VERB(kTag, "Socket closed"); - return true; - } catch (IOException e) { - return false; - } - } - return true; - } - - @Override - protected int sendImpl(byte[] dataBuffer, int dataLength) { - if (this.mSocket == null || !this.mSocket.isConnected() || this.mOutputStream == null) { - Logger.ERR(kTag, "Socket closed! Send failed!"); - return -1; - } - try { - this.mOutputStream.write(dataBuffer, 0, dataLength); - this.mOutputStream.flush(); - return dataLength; - } catch (IOException e) { - Logger.ERR(kTag, "Send failed! / " + e.getMessage()); - return -2; - } - } - - @Override - protected int receiveImpl(byte[] dataBuffer, int dataLength) { - if (this.mSocket == null || !this.mSocket.isConnected() || this.mInputStream == null) { - Logger.ERR(kTag, "Socket closed! Receive failed!"); - return -1; - } - try { - int receivedBytes = 0; - while (receivedBytes < dataLength) { - int onceReceivedBytes = this.mInputStream.read(dataBuffer, receivedBytes, - dataLength - receivedBytes); - if (onceReceivedBytes < 0) { - Logger.ERR(kTag, "Receive failed! 1"); - return -2; - } - receivedBytes += onceReceivedBytes; - } - -// Logger.DEBUG(kTag, "TCP received " + receivedBytes); - return dataLength; - } catch (IOException e) { - Logger.ERR(kTag, "Receive failed! 2 / " + e.getMessage()); - return -3; - } - } - - // Constructor - TcpClientSocket(int targetPort) { - this.mTargetPort = targetPort; - this.mIsInfoSet = false; - this.mInfoSetTrigger = new Object(); - } - - public void setTcpClientInfo(String targetIpAddress) { - this.mTargetIpAddress = targetIpAddress; - - Logger.DEBUG(kTag, "Notify: WfdP2PInfo"); - this.mIsInfoSet = true; - synchronized (this.mInfoSetTrigger) { - this.mInfoSetTrigger.notifyAll(); - } - } - - private String getTargetIpAddress() { - // Wait until wps pin is set, then get the information. - if (this.mIsInfoSet) { - return this.mTargetIpAddress; - } else { - Logger.DEBUG(kTag, "Waiting: mTargetIpAddress"); - while (!this.mIsInfoSet) { - synchronized (this.mInfoSetTrigger) { - try { - this.mInfoSetTrigger.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - return this.mTargetIpAddress; - } - } - - // Components - private Socket mSocket; - private BufferedInputStream mInputStream; - private BufferedOutputStream mOutputStream; - - // TODO: adding port to WFD info would be good. - // Attributes - private int mTargetPort; - - // TCP Socket Info Attributes - private boolean mIsInfoSet; - private final Object mInfoSetTrigger; - private String mTargetIpAddress; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdClientAdapter.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdClientAdapter.java deleted file mode 100644 index 91eb22a8..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdClientAdapter.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.redcarrottt.sc.internal.wfd; - -import android.app.Activity; - -import com.redcarrottt.sc.internal.ClientAdapter; -import com.redcarrottt.sc.internal.ControlMessageListener; -import com.redcarrottt.sc.internal.ControlMessageProtocol; -import com.redcarrottt.sc.internal.Core; -import com.redcarrottt.testapp.Logger; - -public class WfdClientAdapter extends ClientAdapter implements ControlMessageListener { - private static final String kTag = "WfdClientAdapter"; - - // Singleton - static public WfdClientAdapter singleton(int id, String name, int targetPort, Activity - ownerActivity) { - if (sSingleton == null) { - sSingleton = new WfdClientAdapter(id, name, targetPort, ownerActivity); - } - return sSingleton; - } - - static private WfdClientAdapter sSingleton; - - // Constructor - private WfdClientAdapter(int id, String name, int targetPort, Activity ownerActivity) { - super(id, name); - - // Components - WfdDevice device = new WfdDevice(ownerActivity); - this.mP2pClient = new WfdP2PClient(ownerActivity); - this.mClientSocket = new TcpClientSocket(targetPort); - - // Initialize - this.initialize(device, this.mP2pClient, this.mClientSocket); - - // Add WfdP2PClient as a control message listener - Core.singleton().getControlMessageReceiver().addControlMessageListener(this); - } - - @Override - public void onReceiveControlMessage(int privateType, String privateMessage) { - if (privateType == ControlMessageProtocol.PrivType.kWFDInfo) { - Logger.DEBUG(kTag, "Received WFD info message: " + privateMessage); - String wfdInfoLines[] = privateMessage.split("\\r?\\n"); - if (wfdInfoLines.length < 3) { - Logger.ERR(kTag, "WFD info is insufficient: " + wfdInfoLines.length + " < 3"); - } - String targetMacAddress = wfdInfoLines[0]; - String wpsPin = wfdInfoLines[1]; - String targetIpAddress = wfdInfoLines[2]; - - mP2pClient.setWfdP2PInfo(targetMacAddress, wpsPin); - mClientSocket.setTcpClientInfo(targetIpAddress); - } - } - - // Components - private WfdP2PClient mP2pClient; - private TcpClientSocket mClientSocket; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdDevice.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdDevice.java deleted file mode 100644 index dfafe28a..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdDevice.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.redcarrottt.sc.internal.wfd; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.wifi.WifiManager; - -import com.redcarrottt.sc.internal.Device; -import com.redcarrottt.testapp.Logger; - -class WfdDevice extends Device { - private static final String kTag = "WFdDevice"; - - // TODO: there is no timeout on turn on/off of WfdDevice - @Override - protected void turnOnImpl() { - WifiManager wifiManager = (WifiManager) this.mOwnerActivity.getApplicationContext() - .getSystemService(Context.WIFI_SERVICE); - if (wifiManager == null) { - doneTurnOn(false); - } else if (wifiManager.isWifiEnabled()) { - Logger.DEBUG(kTag, "Wi-fi Direct is already turned on"); - doneTurnOn(true); - } else { - // Register wi-fi device on event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - Context context = this.mOwnerActivity.getApplicationContext(); - context.registerReceiver(this.mWfdDeviceOnEventReceiver, intentFilter); - - // turn on wi-fi command - wifiManager.setWifiEnabled(true); - } - } - - @Override - protected void turnOffImpl() { - // Register wi-fi device off event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - Context context = this.mOwnerActivity.getApplicationContext(); - context.registerReceiver(this.mWfdDeviceOffEventReceiver, intentFilter); - - // turn off wi-fi command - WifiManager wifiManager = (WifiManager) this.mOwnerActivity.getApplicationContext() - .getSystemService(Context.WIFI_SERVICE); - if(wifiManager == null) { - doneTurnOff(true); - } else if(!wifiManager.isWifiEnabled()) { - Logger.DEBUG(kTag, "Wi-fi Direct is already turned off"); - doneTurnOff(true); - } else { - wifiManager.setWifiEnabled(false); - } - } - - private BroadcastReceiver mWfdDeviceOnEventReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - final int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN); - Logger.DEBUG(kTag, "Wi-fi Adapter state changed: " + state); - if (state == WifiManager.WIFI_STATE_ENABLED) { - Logger.DEBUG(kTag, "Wi-fi is turned on successfully"); - doneTurnOn(true); - context.unregisterReceiver(mWfdDeviceOnEventReceiver); - } - } - } - }; - - private BroadcastReceiver mWfdDeviceOffEventReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - final int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN); - Logger.DEBUG(kTag, "Wi-fi Adapter state changed: " + state); - if (state == WifiManager.WIFI_STATE_DISABLED) { - Logger.DEBUG(kTag, "Wi-fi is turned off successfully"); - doneTurnOff(true); - context.unregisterReceiver(mWfdDeviceOffEventReceiver); - } - } - } - }; - - // Constructor - public WfdDevice(Activity ownerActivity) { - super("Wi-fi Direct"); - this.mOwnerActivity = ownerActivity; - } - - // Attributes - private Activity mOwnerActivity; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdP2PClient.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdP2PClient.java deleted file mode 100644 index f9b909de..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdP2PClient.java +++ /dev/null @@ -1,390 +0,0 @@ -package com.redcarrottt.sc.internal.wfd; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.NetworkInfo; -import android.net.wifi.WpsInfo; -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pDevice; -import android.net.wifi.p2p.WifiP2pDeviceList; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pManager; -import android.os.Looper; - -import com.redcarrottt.sc.internal.OnConnectResult; -import com.redcarrottt.sc.internal.OnDisconnectResult; -import com.redcarrottt.sc.internal.OnDiscoverResult; -import com.redcarrottt.sc.internal.P2PClient; -import com.redcarrottt.testapp.Logger; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -class WfdP2PClient extends P2PClient { - private static final String kTag = "WfdP2PClient"; - - @Override - protected void discoverImpl(OnDiscoverResult onDiscoverResult) { - // Run Discover Transaction - runDiscoverTx(onDiscoverResult); - } - - private void runDiscoverTx(OnDiscoverResult onDiscoverResult) { - if (sOngoingDiscover == null) { - sOngoingDiscover = new DiscoverTransaction(); - sOngoingDiscover.run(onDiscoverResult); - } else { - Logger.WARN(kTag, "Already stopping core"); - onDiscoverResult.onDoneDiscover(false); - } - } - - private static void doneDiscoverTx(OnDiscoverResult onDiscoverResult, boolean isSuccess) { - onDiscoverResult.onDoneDiscover(isSuccess); - sOngoingDiscover = null; - } - - private static DiscoverTransaction sOngoingDiscover = null; - - private class DiscoverTransaction { - // TODO: Adding timeout on this transaction would be good. - private OnDiscoverResult mOnDiscoverResult; - private int mTries = 0; - private final int kMaxTries = 100; - - void run(OnDiscoverResult onDiscoverResult) { - this.mTries = 0; - this.mOnDiscoverResult = onDiscoverResult; - stopP2PDiscovery(); - } - - void retry() { - stopP2PDiscovery(); - } - - // Step 1 - private void stopP2PDiscovery() { - Logger.DEBUG(kTag, "Stop discovery"); - mWFDManager.stopPeerDiscovery(mWFDChannel, new WifiP2pManager.ActionListener() { - @Override - public void onSuccess() { - startP2PDiscovery(); - } - - @Override - public void onFailure(int i) { - Logger.ERR(kTag, "Stopping discovery failed / reason=" + i); - mTries++; - if (mTries < kMaxTries) { - retry(); - } else { - doneDiscoverTx(mOnDiscoverResult, false); - } - } - }); - } - - // Step 2 - private void startP2PDiscovery() { - Logger.DEBUG(kTag, "Start discovery"); - - // Start to listen peer change - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); - Context context = mOwnerActivity.getApplicationContext(); - this.mPeersChangedReceiver = new PeersChangedReceiver(); - context.registerReceiver(mPeersChangedReceiver, intentFilter); - this.mPeerListListener = new PeerListListener(); - - // Discover peers - mWFDManager.discoverPeers(mWFDChannel, null); - } - - // Step 4 - private PeersChangedReceiver mPeersChangedReceiver; - - private class PeersChangedReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - assert action != null; - if (action.equals(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)) { - Logger.DEBUG(kTag, "Peers changed event"); - - // Request peer list - Logger.DEBUG(kTag, "Request WFD peers"); - mWFDManager.requestPeers(mWFDChannel, mPeerListListener); - } - } - } - - ; - - // Step 5 - private PeerListListener mPeerListListener; - - class PeerListListener implements WifiP2pManager.PeerListListener { - private Lock mCallbackLock; - private Boolean mIsPeerFound; - - PeerListListener() { - this.mCallbackLock = new ReentrantLock(); - this.mIsPeerFound = false; - } - - @Override - public void onPeersAvailable(WifiP2pDeviceList peers) { - final WifiP2pDeviceList kPeers = peers; - // Since getting peer device address requires locks, it should run on child thread. - Thread childThread = new Thread() { - @Override - public void run() { - if (mCallbackLock.tryLock()) { - try { - synchronized (mIsPeerFound) { - if (!mIsPeerFound) { - Logger.DEBUG(kTag, "Got peer list (Target=" + - getTargetMacAddress() + ")"); - for (WifiP2pDevice p2pDevice : kPeers.getDeviceList()) { - Logger.DEBUG(kTag, "Peer: " + p2pDevice.deviceAddress - + " / " + p2pDevice.deviceName + " / " + - p2pDevice.status); - - if (p2pDevice.deviceAddress.equals - (getTargetMacAddress()) && p2pDevice.status - == WifiP2pDevice.AVAILABLE) { - mFoundWFDDevice = p2pDevice; - Logger.DEBUG(kTag, "Peer found"); - mIsPeerFound = true; - break; - } - } - } - } - - // Unregister PeersChangedReceiver - if (mPeerListListener != null) { - mOwnerActivity.getApplicationContext().unregisterReceiver - (mPeersChangedReceiver); - mPeerListListener = null; - } - - synchronized (mIsPeerFound) { - if (mIsPeerFound) { - doneDiscoverTx(mOnDiscoverResult, true); - } else { - mTries++; - if (mTries < kMaxTries) { - retry(); - } else { - doneDiscoverTx(mOnDiscoverResult, false); - } - } - } - } finally { - mCallbackLock.unlock(); - } - } - } - }; - childThread.start(); - } - } - } - - private WifiP2pDevice mFoundWFDDevice = null; - - // TODO: Adding timeout on this transaction would be good. - @Override - protected void connectImpl(OnConnectResult onConnectResult) { - if (this.mFoundWFDDevice == null) { - Logger.ERR(kTag, "Not found target WFD device"); - onConnectResult.onDoneConnect(false); - return; - } - - // Start to listen P2P connection event - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); - Context context = mOwnerActivity.getApplicationContext(); - mWFDConnectionReceiver.setOnConnectResult(onConnectResult); - context.registerReceiver(mWFDConnectionReceiver, intentFilter); - - // Setting P2P config - Logger.DEBUG(kTag, "Connect WFD Peer"); - WifiP2pDevice p2pDevice = this.mFoundWFDDevice; - WifiP2pConfig p2pConfig = new WifiP2pConfig(); - p2pConfig.deviceAddress = p2pDevice.deviceAddress; - if (p2pDevice.wpsKeypadSupported()) { - Logger.DEBUG(kTag, "WPS Method: Keypad"); - p2pConfig.wps.setup = WpsInfo.KEYPAD; - p2pConfig.wps.pin = this.getWpsPin(); - } else if (p2pDevice.wpsPbcSupported()) { - Logger.DEBUG(kTag, "WPS Method: PBC - Unsupported"); - p2pConfig.wps.setup = WpsInfo.PBC; - onConnectResult.onDoneConnect(false); - return; - } else if (p2pDevice.wpsDisplaySupported()) { - Logger.DEBUG(kTag, "WPS Method: Display - Unsupported"); - onConnectResult.onDoneConnect(false); - return; - } - p2pConfig.groupOwnerIntent = 0; - - // P2P connection request - final OnConnectResult fOnConnectResult = onConnectResult; - Logger.DEBUG(kTag, "Request to connect: " + p2pDevice.deviceName + " " + p2pDevice - .deviceAddress + " (" + p2pConfig.wps.pin + ")"); - mWFDManager.connect(mWFDChannel, p2pConfig, new WifiP2pManager.ActionListener() { - @Override - public void onSuccess() { - Logger.DEBUG(kTag, "WFD Connection Success"); - } - - @Override - public void onFailure(int i) { - Logger.WARN(kTag, "WFD Connection Failure / reason=" + i + " - retry to connect..."); - connectImpl(fOnConnectResult); - } - }); - } - - private WFDConnectionReceiver mWFDConnectionReceiver = new WFDConnectionReceiver(); - - private class WFDConnectionReceiver extends BroadcastReceiver { - private OnConnectResult mOnConnectResult = null; - - public void setOnConnectResult(OnConnectResult onConnectResult) { - this.mOnConnectResult = onConnectResult; - } - - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - assert (action != null); - - if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { - NetworkInfo netInfo = (NetworkInfo) intent.getParcelableExtra(WifiP2pManager - .EXTRA_NETWORK_INFO); - Logger.DEBUG(kTag, "Wi-fi direct connection change detected! " + netInfo.toString - ()); - if (netInfo.isConnected()) { - Logger.DEBUG(kTag, "Wi-fi direct Connected!"); - WifiP2pGroup p2pGroup = intent.getParcelableExtra(WifiP2pManager - .EXTRA_WIFI_P2P_GROUP); - String goMacAddress = p2pGroup.getOwner().deviceAddress; - Logger.DEBUG(kTag, "Group owner address: " + goMacAddress); - if (goMacAddress != null && goMacAddress.equals(getTargetMacAddress())) { - context.unregisterReceiver(mWFDConnectionReceiver); - mOnConnectResult.onDoneConnect(true); - } - } - } - } - } - - @Override - protected void disconnectImpl(OnDisconnectResult onDisconnectResult) { - final OnDisconnectResult kOnDisconnectResult = onDisconnectResult; - mWFDManager.removeGroup(mWFDChannel, new WifiP2pManager.ActionListener() { - @Override - public void onSuccess() { - kOnDisconnectResult.onDoneDisconnect(true); - } - - @Override - public void onFailure(int i) { - kOnDisconnectResult.onDoneDisconnect(false); - } - }); - } - - public void setWfdP2PInfo(String targetMacAddress, String wpsPin) { - this.mTargetMacAddress = targetMacAddress; - this.mWpsPin = wpsPin; - - Logger.DEBUG(kTag, "Notify: WfdP2PInfo"); - this.mIsInfoSet = true; - synchronized (this.mInfoSetTrigger) { - this.mInfoSetTrigger.notifyAll(); - } - } - - private String getTargetMacAddress() { - // Wait until target mac address is set, then get the information. - if (this.mIsInfoSet) { - return this.mTargetMacAddress; - } else { - Logger.DEBUG(kTag, "Waiting: mTargetMacAddress"); - while (!this.mIsInfoSet) { - synchronized (this.mInfoSetTrigger) { - try { - this.mInfoSetTrigger.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - Logger.DEBUG(kTag, "Got: mTargetMacAddress"); - return this.mTargetMacAddress; - } - } - - private String getWpsPin() { - // Wait until wps pin is set, then get the information. - if (this.mIsInfoSet) { - return this.mWpsPin; - } else { - Logger.DEBUG(kTag, "Waiting: mWpsPin"); - while (!this.mIsInfoSet) { - synchronized (this.mInfoSetTrigger) { - try { - this.mInfoSetTrigger.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - Logger.DEBUG(kTag, "Got: mWpsPin"); - return this.mWpsPin; - } - } - - // Constructor - public WfdP2PClient(Activity ownerActivity) { - this.mOwnerActivity = ownerActivity; - this.mIsInfoSet = false; - this.mInfoSetTrigger = new Object(); - - // Initialize Android WFD Manager Channel - this.mWFDManager = (WifiP2pManager) this.mOwnerActivity.getApplicationContext() - .getSystemService(Context.WIFI_P2P_SERVICE); - if (this.mWFDManager == null) { - Logger.ERR(kTag, "Failed to initialize Wi-fi Direct Manager"); - return; - } - - - this.mWFDChannel = this.mWFDManager.initialize(this.mOwnerActivity, Looper.getMainLooper - (), null); - if (this.mWFDChannel == null) { - Logger.ERR(kTag, "Failed to initialize Wi-fi Direct Manager"); - } - } - - // Attributes - private Activity mOwnerActivity; - - // P2P Info Attributes - private boolean mIsInfoSet; - private final Object mInfoSetTrigger; - private String mTargetMacAddress; - private String mWpsPin; - - // Components - private WifiP2pManager mWFDManager; - private WifiP2pManager.Channel mWFDChannel; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/CommInitializer.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/CommInitializer.java deleted file mode 100644 index 87aa7cf1..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/CommInitializer.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.redcarrottt.testapp; - -import android.bluetooth.BluetoothAdapter; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.wifi.WifiManager; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public class CommInitializer { - private static final String kTag = "CommInit"; - - public void start() { - new Thread() { - @Override - public void run() { - turnOffBt(); - } - }.start(); - } - - private void turnOffBt() { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter.isEnabled()) { - // Register bluetooth device on event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - Context context = this.mMainActivity.getApplicationContext(); - context.registerReceiver(this.TurnOffBtResult, intentFilter); - - // turn on adapter command - Logger.DEBUG(kTag, "Turn off BT Start"); - adapter.disable(); - } else { - Logger.DEBUG(kTag, "BT already turned off"); - this.turnOnBt(); - } - } - - private BroadcastReceiver TurnOffBtResult = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, - BluetoothAdapter.ERROR); - if (state == BluetoothAdapter.STATE_OFF) { - Logger.DEBUG(kTag, "Turn off BT Success"); - context.unregisterReceiver(TurnOffBtResult); - turnOnBt(); - } - } - } - }; - - private void turnOnBt() { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (!adapter.isEnabled()) { - // Register bluetooth device on event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - Context context = this.mMainActivity.getApplicationContext(); - context.registerReceiver(this.TurnOnBtResult, intentFilter); - - // turn on adapter command - Logger.DEBUG(kTag, "Turn on BT Start"); - adapter.enable(); - } else { - Logger.WARN(kTag, "BT not turned on"); - this.mOnResult.onCommInitializerResult(false); - } - } - - private BroadcastReceiver TurnOnBtResult = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, - BluetoothAdapter.ERROR); - if (state == BluetoothAdapter.STATE_ON) { - Logger.DEBUG(kTag, "Turn on BT Success"); - context.unregisterReceiver(TurnOnBtResult); - turnOffWifi(); - } - } - } - }; - - private void turnOffWifi() { - // Register wi-fi device off event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - Context context = this.mMainActivity.getApplicationContext(); - context.registerReceiver(this.TurnOffWifiResult, intentFilter); - - // turn off wi-fi command - WifiManager wifiManager = (WifiManager) this.mMainActivity.getApplicationContext() - .getSystemService(Context.WIFI_SERVICE); - if (wifiManager == null) { - Logger.ERR(kTag, "Failed to get Wi-fi Manager"); - return; - } - - if (wifiManager.isWifiEnabled()) { - Logger.DEBUG(kTag, "Turn off WIFI Start"); - wifiManager.setWifiEnabled(false); - } else { - Logger.DEBUG(kTag, "WIFI already turned off"); - this.turnOnWifi(); - } - } - - private BroadcastReceiver TurnOffWifiResult = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - final int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager - .WIFI_STATE_UNKNOWN); - if (state == WifiManager.WIFI_STATE_DISABLED) { - Logger.DEBUG(kTag, "Turn off WFD success"); - context.unregisterReceiver(TurnOffWifiResult); - turnOnWifi(); - } - } - } - }; - - private void turnOnWifi() { - // Register wi-fi device off event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - Context context = this.mMainActivity.getApplicationContext(); - context.registerReceiver(this.TurnOnWifiResult, intentFilter); - - // turn off wi-fi command - WifiManager wifiManager = (WifiManager) this.mMainActivity.getApplicationContext() - .getSystemService(Context.WIFI_SERVICE); - if (wifiManager == null) { - Logger.ERR(kTag, "Failed to get Wi-fi Manager"); - return; - } - - if (!wifiManager.isWifiEnabled()) { - Logger.DEBUG(kTag, "Turn on WIFI Start"); - wifiManager.setWifiEnabled(true); - } else { - Logger.DEBUG(kTag, "WIFI already turned on"); - this.mOnResult.onCommInitializerResult(true); - } - } - - private BroadcastReceiver TurnOnWifiResult = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - final int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager - .WIFI_STATE_UNKNOWN); - if (state == WifiManager.WIFI_STATE_ENABLED) { - Logger.DEBUG(kTag, "Turn on WFD success"); - context.unregisterReceiver(TurnOnWifiResult); - mOnResult.onCommInitializerResult(true); - } - } - } - }; - - public CommInitializer(MainActivity mainActivity, CommInitializerResult onResult) { - this.mMainActivity = mainActivity; - this.mOnResult = onResult; - } - - private MainActivity mMainActivity; - private CommInitializerResult mOnResult; -} - -interface CommInitializerResult { - public void onCommInitializerResult(boolean isSuccess); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/Logger.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/Logger.java deleted file mode 100644 index e1e79755..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/Logger.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.redcarrottt.testapp; - -/* Copyright (c) 2018, contributors. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import android.annotation.SuppressLint; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -class LogLevel { - public static final int ERR = 1; - public static final int WARN = 2; - public static final int VERB = 3; - public static final int DEBUG = 4; -} - -class LogReceiver extends BroadcastReceiver { - public static final String kAction = "LogBroadcast"; - public static final String kKeyLogLevel = "LogLevel"; - public static final String kKeyLogTag = "LogTag"; - public static final String kKeyLogMessage = "LogMessage"; - - private Callback mCallback; - - public LogReceiver(Callback callback) { - this.mCallback = callback; - } - - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - assert action != null; - if (action.equals(kAction)) { - String logTag = intent.getStringExtra(kKeyLogTag); - String logMessage = intent.getStringExtra(kKeyLogMessage); - int logLevel = intent.getIntExtra(kKeyLogLevel, LogLevel.DEBUG); - this.mCallback.onLogMessage(logLevel, logTag, logMessage); - } - } - - interface Callback { - void onLogMessage(final int logLevel, String logTag, String logMessage); - } -} - -public class Logger { - private static void print(Context context, int logLevel, String logTag, String logMessage) { - Intent broadcastIntent = new Intent(); - broadcastIntent.setAction(LogReceiver.kAction); - broadcastIntent.putExtra(LogReceiver.kKeyLogLevel, logLevel); - broadcastIntent.putExtra(LogReceiver.kKeyLogTag, logTag); - broadcastIntent.putExtra(LogReceiver.kKeyLogMessage, logMessage); - context.sendBroadcast(broadcastIntent); - } - - private static void print(String tag, int logLevel, String logMessage) { - print(defaultContext, logLevel, tag, logMessage); - } - - public static void ERR(String tag, String logMessage) { - print(tag, LogLevel.ERR, logMessage); - } - - public static void WARN(String tag, String logMessage) { - print(tag, LogLevel.WARN, logMessage); - } - - public static void VERB(String tag, String logMessage) { - print(tag, LogLevel.VERB, logMessage); - } - - public static void DEBUG(String tag, String logMessage) { - print(tag, LogLevel.DEBUG, logMessage); - } - - public static void THREAD_LAUNCH(String threadName) { - VERB(threadName, "Thread(" + threadName + "/" + Thread.currentThread().getId() + ") " + - "Launch"); - } - - public static void THREAD_ADAPTER_LAUNCH(String adapterName, String threadName) { - VERB(threadName, "Thread(" + adapterName + "-" + threadName + "/" + Thread.currentThread - ().getId() + ") Launch"); - } - - public static void THREAD_FINISH(String threadName) { - VERB(threadName, "Thread(" + threadName + "/" + Thread.currentThread().getId() + ") " + - "Finish"); - } - - public static void THREAD_ADAPTER_FINISH(String adapterName, String threadName) { - VERB(threadName, "Thread(" + adapterName + "-" + threadName + "/" + Thread.currentThread - ().getId() + ") Finish"); - } - - public static void THREAD_FAIL(String threadName) { - ERR(threadName, "Thread(" + threadName + "/" + Thread.currentThread().getId() + ") " + - "Fail"); - } - - public static void THREAD_ADAPTER_FAIL(String adapterName, String threadName) { - ERR(threadName, "Thread(" + adapterName + "-" + threadName + "/" + Thread.currentThread - ().getId() + ") Fail"); - } - - public static void setDefaultContext(Context context) { - Logger.defaultContext = context; - } - - @SuppressLint("StaticFieldLeak") - private static Context defaultContext; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/MainActivity.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/MainActivity.java deleted file mode 100755 index 1814068e..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/MainActivity.java +++ /dev/null @@ -1,461 +0,0 @@ -package com.redcarrottt.testapp; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * Eunsoo Park (esevan.park@gmail.com) - * Injung Hwang (sinban04@gmail.com) - * - * 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. - */ - -import android.Manifest; -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.graphics.Color; -import android.os.Bundle; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AppCompatActivity; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.Button; -import android.widget.ListView; -import android.widget.TextView; - -import com.redcarrottt.sc.api.API; -import com.redcarrottt.sc.api.OnStartSCResult; -import com.redcarrottt.sc.api.OnStopSCResult; -import com.redcarrottt.sc.internal.ClientAdapter; -import com.redcarrottt.sc.internal.ClientAdapterStateListener; -import com.redcarrottt.sc.internal.bt.BtClientAdapter; -import com.redcarrottt.sc.internal.wfd.WfdClientAdapter; - -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Date; - -import static com.redcarrottt.sc.internal.ExpConfig.VERBOSE_BANDWIDTH_UPDATE; - -public class MainActivity extends AppCompatActivity implements LogReceiver.Callback, - CommInitializerResult { - private static final String kTag = "MainActivity"; - - // Components - private ArrayList mLogListViewData = new ArrayList<>(); - private LogListViewAdapter mLogListViewAdapter; - private SpeedWatcherThread mSpeedWatcherThread; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - // Initialize SwitchProfileButton - Button switchProfileButton = (Button) findViewById(R.id.switchProfileButton); - switchProfileButton.setOnClickListener(onClickSwitchProfileButton); - this.updateSwitchProfileButton(); - - // Initialize StartButton - Button startButton = (Button) findViewById(R.id.startButton); - startButton.setOnClickListener(onClickStartButton); - - // Initialize SpeedWatcherThread for BandwidthTextView - this.mSpeedWatcherThread = new SpeedWatcherThread(); - this.mSpeedWatcherThread.start(); - - // Initialize LogListView - this.mLogListViewAdapter = new LogListViewAdapter(this, this.mLogListViewData); - ListView logListView = (ListView) findViewById(R.id.logListView); - logListView.setAdapter(this.mLogListViewAdapter); - - // Initialize Log Receiver - Logger.setDefaultContext(this); - LogReceiver logReceiver = new LogReceiver(this); - IntentFilter broadcastIntentFilter = new IntentFilter(); - broadcastIntentFilter.addAction(LogReceiver.kAction); - this.registerReceiver(logReceiver, broadcastIntentFilter); - - // Require permissions for SC - this.requestPermissions(); - - // Initialize Communication Interfaces - Logger.VERB(kTag, "Initializing network interfaces..."); - mCommInitializer = new CommInitializer(this, this); - mCommInitializer.start(); - } - - - private CommInitializer mCommInitializer; - - @Override - public void onCommInitializerResult(boolean isSuccess) { - if (isSuccess) { - Logger.VERB(kTag, "All network Interfaces ready"); - Button startButton = (Button) findViewById(R.id.startButton); - startButton.setEnabled(true); - } else { - Logger.ERR(kTag, "Initialization failed"); - } - } - - private View.OnClickListener onClickStartButton = new View.OnClickListener() { - @Override - public void onClick(View view) { - // Initialize SC - initializeCommunication(); - } - }; - - private String[] mProfiles = {"Lab", "Home"}; - private int mPresentProfile = 0; - private View.OnClickListener onClickSwitchProfileButton = new View.OnClickListener() { - @Override - public void onClick(View view) { - final int kMaxProfiles = mProfiles.length; - mPresentProfile = (mPresentProfile + 1) % kMaxProfiles; - updateSwitchProfileButton(); - } - }; - - private void updateSwitchProfileButton() { - Button switchProfileButton = (Button) findViewById(R.id.switchProfileButton); - switchProfileButton.setText(this.mProfiles[this.mPresentProfile] + " Profile"); - } - - private void requestPermissions() { - if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.INTERNET) != - PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission - .INTERNET, Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission - .ACCESS_WIFI_STATE, Manifest.permission.CHANGE_WIFI_STATE, Manifest - .permission.CHANGE_NETWORK_STATE, Manifest.permission - .ACCESS_COARSE_LOCATION}, 0); - } - } - - private void initializeCommunication() { - String btAddress = ""; - switch (this.mPresentProfile) { - case 0: - btAddress = "B8:27:EB:D9:FA:85"; - break; - case 1: - btAddress = "B8:27:EB:77:C3:4A"; - break; - } - - if (btAddress == "") { - Logger.ERR(kTag, "No bluetooth address is defined!"); - return; - } else { - Logger.VERB(kTag, "BT Address: " + btAddress); - } - - - // Setting adapters - this.mBtClientAdapter = BtClientAdapter.singleton(1, "BT", btAddress, - "150e8400-1234-41d4-a716-446655440000", this); - this.mBtClientAdapter.listenState(this.mClientAdapterStateListener); - API.registerAdapter(this.mBtClientAdapter); - - this.mWfdClientAdapter = WfdClientAdapter.singleton(2, "WFD", 3455, this); - this.mWfdClientAdapter.listenState(this.mClientAdapterStateListener); - API.registerAdapter(this.mWfdClientAdapter); - - // Start the selective connection - API.startSC(onStartSCResult); - } - - @Override - protected void onResume() { - super.onResume(); - } - - @Override - protected void onPause() { - super.onPause(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - API.stopSC(onStopSCResult); - } - - // ClientAdapters - private BtClientAdapter mBtClientAdapter; - private WfdClientAdapter mWfdClientAdapter; - - private int mBtClientAdapterState; - private int mWfdClientAdapterState; - - private ClientAdapterStateListener mClientAdapterStateListener = new - ClientAdapterStateListener() { - - @Override - public void onUpdateClientAdapterState(ClientAdapter adapter, int oldState, int newState) { - // Update local state variable - if (adapter == mBtClientAdapter) { - mBtClientAdapterState = newState; - } else if (adapter == mWfdClientAdapter) { - mWfdClientAdapterState = newState; - } - - // Update state text - final String btClientAdapterState = ClientAdapter.stateToString(mBtClientAdapterState); - final String wfdClientAdapterState = ClientAdapter.stateToString - (mWfdClientAdapterState); - final String stateString = "BT: " + btClientAdapterState + " / WFD: " + - wfdClientAdapterState; - - runOnUiThread(new Runnable() { - @Override - public void run() { - // Update UI - TextView adapterStateTextView = (TextView) findViewById(R.id - .adapterStateTextView); - adapterStateTextView.setText(stateString); - - // Add Log - Logger.VERB("Adapters", stateString); - } - }); - } - }; - - private OnStartSCResult onStartSCResult = new OnStartSCResult() { - private int mRetries = 0; - private static final int kMaxRetries = 5; - - @Override - public void onDoneStartSC(boolean isSuccess) { - if (isSuccess) { - // Starting Selective Connection is done - ReceivingThread receivingThread = new ReceivingThread(); - receivingThread.start(); - } else { - // Retry to start SC - if (mRetries++ < kMaxRetries) { - Logger.VERB(kTag, "Failed to start SC... Retry to start."); - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - API.startSC(onStartSCResult); - } - } - } - }; - - private OnStopSCResult onStopSCResult = new OnStopSCResult() { - @Override - public void onDoneStopSC(boolean isSuccess) { - if (!isSuccess) { - Log.e(kTag, "Stopping Selective Connection failed"); - } - } - }; - - private class SpeedWatcherThread extends Thread { - private Date mLastAccessedTS; - private int mPrevValue; - private int mTotalDataSize; // Bytes - private final int kSleepMS = 1000; - - public void arrive(int dataSize) { - this.mTotalDataSize += dataSize; - } - - private int getSpeed() { - int speed; - - Date startTS = this.mLastAccessedTS; - Date endTS = new Date(); - int prevValue = this.mPrevValue; - int presentValue = this.mTotalDataSize; - - speed = (int) ((float) (presentValue - prevValue) / ((float) (endTS.getTime() - - startTS.getTime()) / 1000)); - - this.mLastAccessedTS = endTS; - this.mPrevValue = presentValue; - - return speed; - } - - @SuppressLint("SetTextI18n") - @SuppressWarnings("InfiniteLoopStatement") - @Override - public void run() { - this.setName("SpeedWatcher"); - this.mPrevValue = 0; - this.mTotalDataSize = 0; - this.mLastAccessedTS = new Date(); - while (true) { - final int speed = this.getSpeed(); - runOnUiThread(new Runnable() { - @Override - public void run() { - TextView bandwidthTextView = (TextView) findViewById(R.id - .bandwidthTextView); - NumberFormat format = NumberFormat.getNumberInstance(); - if (VERBOSE_BANDWIDTH_UPDATE) { - Log.d(kTag, "Bandwidth update: " + format.format(speed) + "B/s"); - } - bandwidthTextView.setText("Bandwidth: " + format.format(speed) + "B/s"); - } - }); - try { - Thread.sleep(kSleepMS); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - - private class ReceivingThread extends Thread { - private static final String kTag = "Recv"; - private boolean mIsAlive; - private final boolean kVerboseReceivingThread = false; - - ReceivingThread() { - this.mIsAlive = false; - } - - @Override - public void run() { - this.setName("AppReceiving"); - this.mIsAlive = true; - byte[] buf = new byte[100 * 1024 * 1024]; - String sending_buf = "ACK"; /* Ack Message */ - - while (this.mIsAlive) { - int receivedLength = API.receive(buf); - mSpeedWatcherThread.arrive(receivedLength); - if (kVerboseReceivingThread) { - Logger.DEBUG(kTag, "Received: Size=" + receivedLength); - } - } - } - - public void terminate() { - this.mIsAlive = false; - } - } - - @Override - public void onLogMessage(final int logLevel, final String logTag, final String logMessage) { - final int kPrintThreshold = LogLevel.VERB; - final String kTag = "LOG"; - this.runOnUiThread(new Runnable() { - @SuppressLint("SetTextI18n") - @Override - public void run() { - String printLevel = ""; - int color = Color.BLACK; - switch (logLevel) { - case LogLevel.ERR: - Log.e(logTag, logMessage); - printLevel = "E"; - color = Color.RED; - break; - case LogLevel.WARN: - Log.w(logTag, logMessage); - printLevel = "W"; - color = Color.parseColor("#FF8000"); - break; - case LogLevel.VERB: - Log.i(logTag, logMessage); - printLevel = "V"; - color = Color.parseColor("#0072C1"); - break; - case LogLevel.DEBUG: - Log.d(logTag, logMessage); - printLevel = "D"; - color = Color.parseColor("#5C676F"); - break; - } - String printMessage = "[" + printLevel + "/" + logTag + "] " + logMessage; - - if (logLevel <= kPrintThreshold) { - mLogListViewData.add(0, new LogListViewItem(printMessage, color)); - mLogListViewAdapter.notifyDataSetChanged(); - } - } - }); - } -} - -class LogListViewItem { - private String mText; - private int mColor; - - public String getText() { - return this.mText; - } - - public int getColor() { - return this.mColor; - } - - LogListViewItem(String text, int color) { - this.mText = text; - this.mColor = color; - } -} - -class LogListViewAdapter extends BaseAdapter { - private LayoutInflater mInflater; - private int mLayout; - private ArrayList mData; - - LogListViewAdapter(Context context, ArrayList data) { - this.mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - this.mLayout = R.layout.item; - this.mData = data; - } - - @Override - public int getCount() { - return this.mData.size(); - } - - @Override - public String getItem(int position) { - return this.mData.get(position).getText(); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mInflater.inflate(this.mLayout, parent, false); - } - - LogListViewItem item = this.mData.get(position); - TextView contentsTextView = (TextView) convertView.findViewById(R.id.contentsTextView); - contentsTextView.setText(item.getText()); - contentsTextView.setTextColor(item.getColor()); - return contentsTextView; - } -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/res/layout/activity_main.xml b/subprojects/sc/android/app/src/main/res/layout/activity_main.xml deleted file mode 100755 index 5aaada2f..00000000 --- a/subprojects/sc/android/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - -