Skip to content

Commit 844c58a

Browse files
committed
add iperf using kotlin wrapper
1 parent 334d7b1 commit 844c58a

File tree

8 files changed

+217
-0
lines changed

8 files changed

+217
-0
lines changed

app/src/main/cpp/include/iperf3_jni_api.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ JNIEXPORT jint JNICALL Java_com_lcl_lclmeasurementtool_Functionality_Iperf3Clien
1212
JNIEXPORT void JNICALL Java_com_lcl_lclmeasurementtool_Functionality_Iperf3Client_stopIperfTest
1313
(JNIEnv *, jobject);
1414

15+
JNIEXPORT jint JNICALL Java_com_lcl_lclmeasurementtool_features_iperf_IperfClient_runIperfTest
16+
(JNIEnv *, jobject, jobject , jobject, jstring);
17+
18+
JNIEXPORT void JNICALL Java_com_lcl_lclmeasurementtool_features_iperf_IperfClient_stopIperfTest
19+
(JNIEnv *, jobject);
20+
1521
}
1622

1723
#endif // _INCLUDED_CMII_IPERF3

app/src/main/cpp/src/iperf3_jni_api.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,27 @@ extern "C" JNIEXPORT void JNICALL Java_com_lcl_lclmeasurementtool_Functionality_
2929

3030
__android_log_print(ANDROID_LOG_VERBOSE, __FILE_NAME__, "Exiting stopIperfTest JNI function");
3131
}
32+
33+
34+
extern "C" JNIEXPORT jint JNICALL Java_com_lcl_lclmeasurementtool_features_iperf_IperfClient_runIperfTest(
35+
JNIEnv *env, jobject iperfClient, jobject iperfConfig, jobject callback, jstring cacheDirTemplate) {
36+
__android_log_print(ANDROID_LOG_VERBOSE, __FILE_NAME__, "Entering runIperfTest JNI function");
37+
auto wrapper = std::make_unique<IperfStateWrapper>();
38+
39+
wrapper->register_callbacks(env, iperfConfig, callback, cacheDirTemplate);
40+
if (wrapper->run_test() < 0) {
41+
// TODO(matt9j) Propagate actual error string.
42+
return -1;
43+
}
44+
45+
__android_log_print(ANDROID_LOG_VERBOSE, __FILE_NAME__, "Exiting runIperfTest JNI function");
46+
return 0;
47+
}
48+
49+
extern "C" JNIEXPORT void JNICALL Java_com_lcl_lclmeasurementtool_features_iperf_IperfClient_stopIperfTest (JNIEnv * env, jobject iperfClient) {
50+
__android_log_print(ANDROID_LOG_VERBOSE, __FILE_NAME__, "Entering stopIperfTest JNI function");
51+
52+
stop_wrapper();
53+
54+
__android_log_print(ANDROID_LOG_VERBOSE, __FILE_NAME__, "Exiting stopIperfTest JNI function");
55+
}

app/src/main/java/com/lcl/lclmeasurementtool/MainActivityViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.kongzue.dialogx.dialogs.WaitDialog
1212
import com.lcl.lclmeasurementtool.Utils.ECDSA
1313
import com.lcl.lclmeasurementtool.Utils.Hex
1414
import com.lcl.lclmeasurementtool.Utils.SecurityUtils
15+
import com.lcl.lclmeasurementtool.features.iperf.runIperf
1516
import com.lcl.lclmeasurementtool.model.datamodel.QRCodeKeysModel
1617
import com.lcl.lclmeasurementtool.model.datamodel.RegistrationModel
1718
import com.lcl.lclmeasurementtool.model.datamodel.UserData
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.lcl.lclmeasurementtool.features.iperf
2+
3+
import kotlinx.coroutines.channels.awaitClose
4+
import kotlinx.coroutines.flow.callbackFlow
5+
import kotlinx.coroutines.flow.conflate
6+
import java.io.File
7+
8+
suspend fun runIperf(config: IperfConfig, cacheDir: File) {
9+
val client = IperfClient()
10+
val testResult = callbackFlow {
11+
val callback = object: IperfCallback {
12+
override fun onInterval(
13+
timeStart: Float,
14+
timeEnd: Float,
15+
sendBytes: String,
16+
bandWidth: String,
17+
isDown: Boolean
18+
) {
19+
channel.trySend(IperfResult(timeStart, timeEnd, sendBytes, bandWidth, isDown, null, IperfStatus.RUNNING))
20+
}
21+
22+
override fun onResult(
23+
timeStart: Float,
24+
timeEnd: Float,
25+
sendBytes: String,
26+
bandWidth: String,
27+
isDown: Boolean
28+
) {
29+
channel.trySend(IperfResult(timeStart, timeEnd, sendBytes, bandWidth, isDown, null, IperfStatus.FINISHED))
30+
}
31+
32+
override fun onError(errMsg: String) {
33+
channel.trySend(IperfResult(null, null, null, null, null, errMsg, IperfStatus.ERROR))
34+
}
35+
}
36+
37+
client.exec(config, callback, cacheDir)
38+
39+
awaitClose {
40+
41+
}
42+
}.conflate()
43+
44+
45+
46+
47+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.lcl.lclmeasurementtool.features.iperf
2+
3+
interface IperfCallback {
4+
/**
5+
* callback during the iperf test
6+
* @param timeStart the time when the iperf test interval starts
7+
* @param timeEnd the time when the iperf test interval ends
8+
* @param sendBytes the number of bytes sent
9+
* @param bandWidth the bandwidth
10+
* @param isDown is downstream enabled
11+
*/
12+
fun onInterval(
13+
timeStart: Float,
14+
timeEnd: Float,
15+
sendBytes: String,
16+
bandWidth: String,
17+
isDown: Boolean
18+
)
19+
20+
/**
21+
* callback when the iperf test ends
22+
* @param timeStart the time when the iperf test starts
23+
* @param timeEnd the time when the iperf test ends
24+
* @param sendBytes the number of bytes sent
25+
* @param bandWidth the bandwidth
26+
* @param isDown is downstream enabled
27+
*/
28+
fun onResult(
29+
timeStart: Float,
30+
timeEnd: Float,
31+
sendBytes: String,
32+
bandWidth: String,
33+
isDown: Boolean
34+
)
35+
36+
/**
37+
* callback when an error occurs during the test
38+
* @param errMsg the error message associated with the error
39+
*/
40+
fun onError(errMsg: String)
41+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.lcl.lclmeasurementtool.features.iperf;
2+
3+
import android.util.Log;
4+
5+
import com.lcl.lclmeasurementtool.Functionality.Iperf3Callback;
6+
import com.lcl.lclmeasurementtool.Functionality.Iperf3Config;
7+
8+
import java.io.File;
9+
10+
public class IperfClient {
11+
// debugging tag
12+
private static final String TAG = "IperfClient";
13+
14+
// load the iperf libc
15+
static {
16+
System.loadLibrary("lcl_measurement_tool_native");
17+
}
18+
19+
public IperfClient() {}
20+
21+
///////////////////// NATIVE FUNCTIONS //////////////////////////
22+
23+
// native function for running the test
24+
private native int runIperfTest(IperfConfig testConfig, IperfCallback callback, String cacheDir);
25+
26+
// native function for stopping the iperf test
27+
private native void stopIperfTest();
28+
29+
////////////////////// JAVA INVOCATION ////////////////////////
30+
31+
/**
32+
* Run the iperf test following the configuration and callback protocol
33+
* @param testConfig the test configuration
34+
* @param callback the callback functions
35+
* @param cacheDir the cache directory
36+
* @see Iperf3Config
37+
* @see Iperf3Callback
38+
*/
39+
public void exec(IperfConfig testConfig, IperfCallback callback, File cacheDir) {
40+
Log.i(TAG, "Running iperf client exec");
41+
Log.d(TAG, "testConfig: " + testConfig.toString());
42+
Log.d(TAG, "callback: " + callback.toString());
43+
44+
String cacheTemplate = cacheDir.toString() + "/iperf3.XXXXXX";
45+
46+
// Translate from the "c-style" error return codes to java-style exceptions so calling code
47+
// can operate cleanly.
48+
if (runIperfTest(testConfig, callback, cacheTemplate) != 0) {
49+
// TODO(matt9j) Propagate the error cause in the exception
50+
throw new RuntimeException("Iperf test failed to run");
51+
}
52+
}
53+
54+
/**
55+
* Cancel the running iperf test
56+
*/
57+
public void cancelTest() {
58+
Log.v(TAG, "Iperf cancel in thread" + Thread.currentThread().getName() + ":" + Thread.currentThread().getState());
59+
stopIperfTest();
60+
}
61+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.lcl.lclmeasurementtool.features.iperf
2+
3+
data class IperfConfig(
4+
var serverAdder: String,
5+
var serverPort: Int,
6+
var isDownMode: Boolean,
7+
var testInterval: Double,
8+
var bandwidth: Long = BANDWIDTH_1M,
9+
var unit: Char = 'm',
10+
var numParallels: Int = 1,
11+
var userName: String,
12+
var password: String,
13+
var rsaKey: String
14+
) {
15+
companion object {
16+
const val BANDWIDTH_1M: Long = 1000 * 1000
17+
const val BANDWIDTH_10M: Long = 10 * BANDWIDTH_1M
18+
const val BANDWIDTH_1000M: Long = 1000 * BANDWIDTH_1M
19+
}
20+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.lcl.lclmeasurementtool.features.iperf
2+
3+
data class IperfResult(
4+
val timeStart: Float?,
5+
val timeEnd: Float?,
6+
val sendBytes: String?,
7+
val bandWidth: String?,
8+
val isDownMode: Boolean?,
9+
val errorMSg: String?,
10+
val status: IperfStatus
11+
)
12+
13+
enum class IperfStatus {
14+
RUNNING,
15+
FINISHED,
16+
ERROR
17+
}

0 commit comments

Comments
 (0)