Skip to content

Commit

Permalink
Improved TLS handling and add support for ALPN (#43)
Browse files Browse the repository at this point in the history
* Improved tls handling and add support for alpn

* removed socket factory from connection config

* applied spotless

* added expeirmental config for new ssl flow

* dump public api

* corrected sample app

* fixed test failures

* removed redundant code and required checks

* fixed review comments

* converted paho to java module

* updated docs

* add back required checks

* fixed broker docs link

Co-authored-by: Anubhav Gupta <[email protected]>
  • Loading branch information
Anubhav Gupta and Anubhav Gupta authored Sep 28, 2022
1 parent 01ebb11 commit 13b166b
Show file tree
Hide file tree
Showing 60 changed files with 4,020 additions and 234 deletions.
1 change: 1 addition & 0 deletions adaptive-keep-alive/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ dependencies {
implementation(project(":mqtt-pingsender"))
implementation(project(":network-tracker"))

testImplementation(deps.android.test.mockitoCore)
testImplementation(deps.android.test.kotlinTestJunit)
}

Expand Down
23 changes: 11 additions & 12 deletions app/src/main/java/com/gojek/courier/app/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -92,31 +92,30 @@ class MainActivity : AppCompatActivity() {
}

private fun connectMqtt(clientId: String, username: String, password: String, ip: String, port: Int) {
val connectOptions = MqttConnectOptions(
serverUris = listOf(ServerUri(ip, port, if (port == 443) "ssl" else "tcp")),
clientId = clientId,
username = username,
keepAlive = KeepAlive(
timeSeconds = 30
),
isCleanSession = false,
password = password
)
val connectOptions = MqttConnectOptions.Builder()
.serverUris(listOf(ServerUri(ip, port, if (port == 443) "ssl" else "tcp")))
.clientId(clientId)
.userName(username)
.password(password)
.cleanSession(false)
.keepAlive(KeepAlive(timeSeconds = 30))
.build()

mqttClient.connect(connectOptions)
}

private fun initialiseCourier() {
val mqttConfig = MqttV3Configuration(
socketFactory = null,
logger = getLogger(),
eventHandler = eventHandler,
authenticator = object : Authenticator {
override fun authenticate(
connectOptions: MqttConnectOptions,
forceRefresh: Boolean
): MqttConnectOptions {
return connectOptions.copy(password = password.text.toString())
return connectOptions.newBuilder()
.password(password.text.toString())
.build()
}
},
mqttInterceptorList = listOf(MqttChuckInterceptor(this, MqttChuckConfig(retentionPeriod = Period.ONE_HOUR))),
Expand Down
6 changes: 3 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ allprojects {
subprojects {
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = "1.8"
jvmTarget = "11"
}
}
tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = JavaVersion.VERSION_1_8.toString()
targetCompatibility = JavaVersion.VERSION_1_8.toString()
sourceCompatibility = JavaVersion.VERSION_11.toString()
targetCompatibility = JavaVersion.VERSION_11.toString()
}
}

Expand Down
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/deps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ object deps {
const val runner = "androidx.test:runner:1.2.0"
const val roboelectric = "org.robolectric:robolectric:4.2"
const val mockito = "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
const val mockitoCore = "org.mockito:mockito-core:4.4.0"
const val junitExt = "androidx.test.ext:junit:1.1.1"
const val kotlinTestJunit = "org.jetbrains.kotlin:kotlin-test-junit:${versions.kotlin}"
}
Expand Down
1 change: 1 addition & 0 deletions courier-auth-http/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies {

implementation(deps.square.retrofit)

testImplementation(deps.android.test.mockitoCore)
testImplementation(deps.android.test.kotlinTestJunit)
}

Expand Down
28 changes: 18 additions & 10 deletions docs/docs/ConnectionSetup.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ val mqttClient = MqttClientFactory.create(
### Connect using MqttClient

~~~ kotlin
val connectOptions = MqttConnectOptions(
serverUris = listOf(ServerUri(SERVER_URI, SERVER_PORT)),
clientId = clientId,
username = username,
keepAlive = KeepAlive(
timeSeconds = keepAliveSeconds
),
isCleanSession = cleanSessionFlag,
password = password
)
val alpnProtocol = "mqtt"
val connectOptions = MqttConnectOptions.Builder()
.serverUris(listof(ServerUri(SERVER_URI, SERVER_PORT)))
.clientId(clientId)
.userName(username)
.password(password)
.keepAlive(KeepAlive(timeSeconds = keepAliveSeconds))
.cleanSession(cleanSessionFlag)
.alpnProtocols(listOf(Protocol(alpnProtocol)))
.build()

mqttClient.connect(connectOptions)
~~~
Expand Down Expand Up @@ -56,6 +56,14 @@ mqttClient.disconnect()

- **User properties** : Custom user properties appended to the CONNECT packet.

- **Socket Factory** : Sets the socket factory used to create connections. If unset, the **SocketFactory.getDefault** socket factory will be used. Set [shouldUseNewSSLFlow](ExperimentConfigs) to true to enable this.

- **SSL Socket Factory**: Sets the socket factory and trust manager used to secure MQTT connections. If unset, the system defaults will be used. Set [shouldUseNewSSLFlow](ExperimentConfigs) to true to enable this.

- **Connection Spec**: Specifies configuration for the socket connection that MQTT traffic travels through. This includes the TLS version and cipher suites to use when negotiating a secure connection. Set [shouldUseNewSSLFlow](ExperimentConfigs) to true to enable this.

- **ALPN Protocols**: Configure the alpn protocols used by this client to communicate with MQTT broker. Set [shouldUseNewSSLFlow](ExperimentConfigs) to true to enable this.

[1]: https://github.com/gojek/courier-android/blob/main/mqtt-client/src/main/java/com/gojek/mqtt/client/MqttClient.kt
[2]: https://github.com/gojek/courier-android/blob/main/mqtt-client/src/main/java/com/gojek/mqtt/model/MqttConnectOptions.kt
[3]: https://github.com/gojek/courier-android/blob/main/mqtt-client/src/main/java/com/gojek/mqtt/model/ServerUri.kt
4 changes: 3 additions & 1 deletion docs/docs/ExperimentConfigs.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ These are the experimentation configs used in Courier library. These are volatil

- **incomingMessagesTTLSecs** : When there is no listener attached for an incoming message, messages are persisted for this interval.

- **incomingMessagesCleanupIntervalSecs** : Interval at which cleanup for incoming messages persistence is performed.
- **incomingMessagesCleanupIntervalSecs** : Interval at which cleanup for incoming messages persistence is performed.

- **shouldUseNewSSLFlow** : Set this true for enabling alpn protocol, custom ssl socket factory.
2 changes: 0 additions & 2 deletions docs/docs/MqttConfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ As we have seen earlier, [MqttClient][1] requires an instance of [MqttV3Configur

- **Experimentation Configs** : These are the experiment configs used inside Courier library which are explained in detail [here](ExperimentConfigs).

- **Socket Factory** : An instance of SocketFactory can be passed to control the socket creation for the underlying MQTT connection.

- **WakeLock Timeout** : When positive value of this timeout is passed, a wakelock is acquired while creating the MQTT connection. By default, it is 0.

[1]: https://github.com/gojek/courier-android/blob/main/mqtt-client/src/main/java/com/gojek/mqtt/client/MqttClient.kt
Expand Down
20 changes: 11 additions & 9 deletions docs/docs/NonStandardOptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
This option allows you to send user-properties in CONNECT packet for MQTT v3.1.1.

~~~ kotlin
val connectOptions = MqttConnectOptions(
serverUris = listOf(ServerUri(SERVER_URI, SERVER_PORT)),
clientId = clientId,
...
userPropertiesMap = mapOf(
"key1" to "value1",
"key2" to "value2"
)
)
val connectOptions = MqttConnectOptions.Builder()
.serverUris(listOf(ServerUri(SERVER_URI, SERVER_PORT)))
.clientId(clientId)
...
.userProperties(
userProperties = mapOf(
"key1" to "value1",
"key2" to "value2"
)
)
.build()

mqttClient.connect(connectOptions)
~~~
Expand Down
Loading

0 comments on commit 13b166b

Please sign in to comment.