Json Rpc Transport Session
The raw transport contract that backs a JsonRpc session.
Implement this interface to adapt any underlying connection technology (WebSocket, TCP, stdio, SSE, …) to the JSON-RPC layer. Pass the implementation to JsonRpc.of and the protocol handling is taken care of automatically.
Implementing this interface
A minimal implementation has three responsibilities:
1. Feed messageInbox — run a read loop on your transport and send each incoming raw JSON string into the channel. Using kotlinx.coroutines.channels.produce is a convenient way to do this, as the channel is closed automatically when the coroutine completes:
override val messageInbox: ReceiveChannel<String> = coroutineScope.produce {
for (frame in websocketSession.incoming) {
send(frame.readText())
}
// channel closes here → JsonRpc detects the disconnection
}Closing messageInbox is critical. When the channel closes, JsonRpc stops its message loop and closes JsonRpc.callsInbox. If the channel never closes, the session will hang indefinitely after the connection drops.
2. Implement send — write the given JSON string to the underlying transport. JsonRpc serializes all calls to send internally, so this function is never called concurrently. No additional locking is needed on your end.
3. Implement close — tear down the underlying connection. This triggers the remote peer to close as well, which in turn causes your read loop to finish and messageInbox to close. Any exception thrown here is caught and logged by JsonRpc; it will not propagate to the caller. Implement it as idempotent when possible.