Skip to content

Commit

Permalink
2.3.1 mitigate new websocket behavior found in iOS 16.4 [MTSDK-183] (#…
Browse files Browse the repository at this point in the history
…174)

* Mitigating new socket behavior seen in iOS 16.4

[MTSDK-183]
In iOS 16.4, when the network becomes unavailable, such as when the device is put into airplane mode, the NSURLSessionWebSocketTask now immediately completes with an error. This happens without the socket closing first. Furthermore, the completion handler for sendPingWithPongReceiveHandler happens on something other than the main thread. To mitigate, we can listen for the socket task completion as well as ensure that our external facing listeners from the SDK are dispatched on Main.

* fix: check websocket task state before send ping

revert: revert wrapping of listeners and attempting to dispatch back to main thread
revert: revert adding listener to websocket task to check for unexpected task completion. allow keepAlive engine to handle it.

* MTSDK-183 Hotfix

- Update transport version to `2.3.1`

---------

Co-authored-by: aafanasi <Anton.Afanasiev@genesys.com>
  • Loading branch information
crumpf and AfanasievAnton authored May 11, 2023
1 parent 675cf66 commit e6d50b4
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 25 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ plugins {
}

// CocoaPods requires the podspec to have a `version`.
val buildVersion = "2.3.0"
val buildVersion = "2.3.1"
val snapshot = System.getenv("SNAPSHOT_BUILD") ?: ""
version = "${buildVersion}${snapshot}"
group = "cloud.genesys"
Expand Down
4 changes: 2 additions & 2 deletions iosApp/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PODS:
- transport (2.3.0)
- transport (2.3.1)

DEPENDENCIES:
- transport (from `../transport`)
Expand All @@ -9,7 +9,7 @@ EXTERNAL SOURCES:
:path: "../transport"

SPEC CHECKSUMS:
transport: 0931cd2a8fa1f5eb05d7154f43606cec5fceb8d7
transport: f86d3bfdd48460d950f81ecb4db2e375df9d1ba0

PODFILE CHECKSUM: c3105f0698090ba6d9702820eb0f13f123776417

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ internal class MessageStore(
val updateAttachmentStateWith = { attachment: Attachment -> update(attachment) }
var messageListener: ((MessageEvent) -> Unit)? = null

private fun publish(event: MessageEvent) {
messageListener?.invoke(event)
}

fun prepareMessage(
text: String,
customAttributes: Map<String, String> = emptyMap(),
): OnMessageRequest {
val messageToSend = pendingMessage.copy(text = text, state = Message.State.Sending).also {
log.i { "Message prepared to send: $it" }
activeConversation.add(it)
messageListener?.invoke(MessageEvent.MessageInserted(it))
publish(MessageEvent.MessageInserted(it))
pendingMessage = Message()
}
val channel =
Expand All @@ -52,15 +56,15 @@ internal class MessageStore(
Direction.Inbound -> {
activeConversation.find { it.id == message.id }?.let {
activeConversation[it.getIndex()] = message
messageListener?.invoke(MessageEvent.MessageUpdated(message))
publish(MessageEvent.MessageUpdated(message))
} ?: run {
activeConversation.add(message)
messageListener?.invoke(MessageEvent.MessageInserted(message))
publish(MessageEvent.MessageInserted(message))
}
}
Direction.Outbound -> {
activeConversation.add(message)
messageListener?.invoke(MessageEvent.MessageInserted(message))
publish(MessageEvent.MessageInserted(message))
}
}
nextPage = activeConversation.getNextPage()
Expand All @@ -72,7 +76,7 @@ internal class MessageStore(
it[attachment.id] = attachment
}
pendingMessage = pendingMessage.copy(attachments = attachments)
messageListener?.invoke(MessageEvent.AttachmentUpdated(attachment))
publish(MessageEvent.AttachmentUpdated(attachment))
}

fun updateMessageHistory(historyPage: List<Message>, total: Int) {
Expand All @@ -81,7 +85,7 @@ internal class MessageStore(
log.i { "Message history updated with: $this." }
activeConversation.addAll(0, this)
nextPage = activeConversation.getNextPage()
messageListener?.invoke(MessageEvent.HistoryFetched(this, startOfConversation))
publish(MessageEvent.HistoryFetched(this, startOfConversation))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ import platform.Foundation.NSURLErrorBadServerResponse
import platform.Foundation.NSURLErrorNotConnectedToInternet
import platform.Foundation.NSURLSession
import platform.Foundation.NSURLSessionConfiguration
import platform.Foundation.NSURLSessionTaskStateRunning
import platform.Foundation.NSURLSessionWebSocketCloseCode
import platform.Foundation.NSURLSessionWebSocketDelegateProtocol
import platform.Foundation.NSURLSessionWebSocketMessage
import platform.Foundation.NSURLSessionWebSocketTask
import platform.Foundation.setValue
import platform.darwin.NSObject
import platform.posix.ENOTCONN
import platform.posix.ETIMEDOUT

internal actual class PlatformSocket actual constructor(
Expand Down Expand Up @@ -133,26 +135,33 @@ internal actual class PlatformSocket actual constructor(
handleError(nsError, "Pong not received within interval [$pingInterval]")
return@scheduledTimerWithTimeInterval
}
sendPing()

waitingOnPong = true
log.i { "Sending ping" }
sendPing { nsError ->
if (nsError != null) {
handleError(nsError, "Pong handler failure")
return@sendPing
}
waitingOnPong = false
log.i { "Received pong" }
}
}
}
}

private fun sendPing() {
log.i { "Sending ping" }
if (waitingOnPong) {
log.w { "Trying to send ping while still waiting for pong." }
private fun sendPing(pongHandler: (NSError?) -> Unit) {
if (webSocket?.state != NSURLSessionTaskStateRunning) {
pongHandler(
NSError(
domain = NSPOSIXErrorDomain,
code = ENOTCONN.convert(),
userInfo = null
)
)
return
}
waitingOnPong = true
webSocket?.sendPingWithPongReceiveHandler { nsError ->
waitingOnPong = false
if (nsError != null) {
handleError(nsError, "Received pong error")
} else {
log.i { "Received pong" }
}
}
webSocket?.sendPingWithPongReceiveHandler(pongHandler)
}

private fun cancelPings() {
Expand Down Expand Up @@ -206,6 +215,6 @@ private fun NSError.toTransportErrorCode(): ErrorCode =
else -> ErrorCode.WebsocketError
}

internal fun NSTimer?.isScheduled(): Boolean {
private fun NSTimer?.isScheduled(): Boolean {
return this?.valid ?: false
}
2 changes: 1 addition & 1 deletion transport/transport.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = 'transport'
spec.version = '2.3.0'
spec.version = '2.3.1'
spec.homepage = 'https://github.com/MyPureCloud/genesys-messenger-transport-mobile-sdk'
spec.source = { :http=> ''}
spec.authors = 'Genesys Cloud Services, Inc.'
Expand Down

0 comments on commit e6d50b4

Please sign in to comment.