or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

frame-operations.mdindex.mdplugin-configuration.mdserialization-support.mdsession-management.mdwebsocket-connections.md

session-management.mddocs/

0

# Session Management

1

2

WebSocket session interfaces providing frame-level control, connection lifecycle management, and extension support for real-time bidirectional communication.

3

4

## Capabilities

5

6

### Client WebSocket Session Interface

7

8

Base interface for client-specific WebSocket sessions with access to the underlying HTTP call.

9

10

```kotlin { .api }

11

/**

12

* Client specific WebSocket session interface

13

* Extends WebSocketSession with client-specific functionality

14

*/

15

interface ClientWebSocketSession : WebSocketSession {

16

/** HttpClientCall associated with this WebSocket session */

17

val call: HttpClientCall

18

}

19

```

20

21

### Default Client WebSocket Session

22

23

Default implementation of client WebSocket session with full feature support.

24

25

```kotlin { .api }

26

/**

27

* Default implementation of ClientWebSocketSession

28

* Provides complete WebSocket functionality with ping/pong support

29

* @param call HttpClientCall associated with session

30

* @param delegate Underlying DefaultWebSocketSession implementation

31

*/

32

class DefaultClientWebSocketSession(

33

override val call: HttpClientCall,

34

delegate: DefaultWebSocketSession

35

) : ClientWebSocketSession, DefaultWebSocketSession by delegate

36

```

37

38

### Base WebSocket Session Interface

39

40

Core WebSocket session interface providing frame communication and lifecycle management.

41

42

```kotlin { .api }

43

/**

44

* Base WebSocket session interface for bidirectional communication

45

* Extends CoroutineScope for structured concurrency support

46

*/

47

interface WebSocketSession : CoroutineScope {

48

/** Enable/disable masking of outgoing messages with random XOR mask */

49

var masking: Boolean

50

51

/** Frame size limit - connection closed if exceeded */

52

var maxFrameSize: Long

53

54

/** Channel for receiving incoming WebSocket frames */

55

val incoming: ReceiveChannel<Frame>

56

57

/** Channel for sending outgoing WebSocket frames */

58

val outgoing: SendChannel<Frame>

59

60

/** List of installed WebSocket extensions */

61

val extensions: List<WebSocketExtension<*>>

62

}

63

```

64

65

**Usage Examples:**

66

67

```kotlin

68

client.webSocket("ws://echo.websocket.org") {

69

// Configure session properties

70

maxFrameSize = 1024 * 1024 // 1MB limit

71

masking = true

72

73

// Send frames through outgoing channel

74

outgoing.send(Frame.Text("Hello WebSocket!"))

75

76

// Receive frames from incoming channel

77

for (frame in incoming) {

78

when (frame) {

79

is Frame.Text -> println("Text: ${frame.readText()}")

80

is Frame.Binary -> println("Binary: ${frame.data.size} bytes")

81

is Frame.Close -> break

82

}

83

}

84

}

85

```

86

87

### Default WebSocket Session Interface

88

89

Extended WebSocket session with ping/pong functionality and timeout handling.

90

91

```kotlin { .api }

92

/**

93

* Default WebSocket session with ping/pong support

94

* Provides automatic keep-alive functionality

95

*/

96

interface DefaultWebSocketSession : WebSocketSession {

97

/** Interval between ping messages in milliseconds */

98

val pingIntervalMillis: Long

99

100

/** Timeout for ping/pong roundtrip in milliseconds */

101

val timeoutMillis: Long

102

}

103

104

/**

105

* Create DefaultWebSocketSession with ping/pong configuration

106

* @param session Underlying WebSocket session

107

* @param pingIntervalMillis Ping interval in milliseconds

108

* @param timeoutMillis Ping timeout in milliseconds

109

* @return Configured DefaultWebSocketSession

110

*/

111

fun DefaultWebSocketSession(

112

session: WebSocketSession,

113

pingIntervalMillis: Long,

114

timeoutMillis: Long = pingIntervalMillis * 2

115

): DefaultWebSocketSession

116

```

117

118

### Session Extension Functions

119

120

Utility functions for working with WebSocket extensions.

121

122

```kotlin { .api }

123

/**

124

* Get WebSocket extension instance by factory

125

* @param extension Extension factory to look up

126

* @return Extension instance

127

* @throws NoSuchElementException if extension not found

128

*/

129

fun <T : WebSocketExtension<*>> WebSocketSession.extension(

130

extension: WebSocketExtensionFactory<*, T>

131

): T

132

133

/**

134

* Get WebSocket extension instance by factory, or null if not found

135

* @param extension Extension factory to look up

136

* @return Extension instance or null

137

*/

138

fun <T : WebSocketExtension<*>> WebSocketSession.extensionOrNull(

139

extension: WebSocketExtensionFactory<*, T>

140

): T?

141

142

/**

143

* Send text message as Text frame

144

* @param content Text content to send

145

*/

146

suspend fun WebSocketSession.send(content: String)

147

148

/**

149

* Send binary data as Binary frame

150

* @param content Binary data to send

151

*/

152

suspend fun WebSocketSession.send(content: ByteArray)

153

154

/**

155

* Send WebSocket frame

156

* @param frame Frame to send

157

*/

158

suspend fun WebSocketSession.send(frame: Frame)

159

```

160

161

**Usage Examples:**

162

163

```kotlin

164

client.webSocket("ws://example.com") {

165

// Check if compression extension is available

166

val deflate = extensionOrNull(WebSocketDeflateExtension)

167

if (deflate != null) {

168

println("Using compression: ${deflate.compressionLevel}")

169

}

170

171

// Get required extension (throws if not found)

172

try {

173

val customExt = extension(CustomWebSocketExtension)

174

customExt.configure()

175

} catch (e: NoSuchElementException) {

176

println("Custom extension not available")

177

}

178

}

179

```

180

181

## Session Management Examples

182

183

### Basic Session Usage

184

185

```kotlin

186

client.webSocket("ws://echo.websocket.org") {

187

// Session is DefaultClientWebSocketSession

188

println("Connected to: ${call.request.url}")

189

println("Max frame size: $maxFrameSize")

190

191

// Send text message

192

send("Hello!")

193

194

// Process incoming messages

195

for (frame in incoming) {

196

when (frame) {

197

is Frame.Text -> {

198

val text = frame.readText()

199

println("Received: $text")

200

if (text == "bye") break

201

}

202

is Frame.Close -> {

203

println("Connection closed")

204

break

205

}

206

}

207

}

208

}

209

```

210

211

### Manual Session Management

212

213

```kotlin

214

val session = client.webSocketSession("ws://api.example.com/ws")

215

216

try {

217

// Configure session

218

session.maxFrameSize = 512 * 1024

219

220

// Send initial message

221

session.outgoing.send(Frame.Text("CONNECT"))

222

223

// Handle responses

224

while (!session.incoming.isClosedForReceive) {

225

val frame = session.incoming.receiveCatching().getOrNull() ?: break

226

227

when (frame) {

228

is Frame.Text -> processMessage(frame.readText())

229

is Frame.Binary -> processBinary(frame.data)

230

is Frame.Ping -> session.outgoing.send(Frame.Pong(frame.data))

231

is Frame.Close -> break

232

}

233

}

234

} finally {

235

session.close()

236

}

237

```

238

239

### Session with Ping/Pong Monitoring

240

241

```kotlin

242

client.webSocket("ws://api.example.com/realtime") {

243

println("Ping interval: ${pingIntervalMillis}ms")

244

println("Timeout: ${timeoutMillis}ms")

245

246

// Monitor connection health

247

launch {

248

while (isActive) {

249

delay(5000) // Check every 5 seconds

250

if (incoming.isClosedForReceive) {

251

println("Connection lost")

252

break

253

}

254

}

255

}

256

257

// Handle messages

258

for (frame in incoming) {

259

when (frame) {

260

is Frame.Text -> handleMessage(frame.readText())

261

is Frame.Ping -> {

262

println("Received ping")

263

// Pong is sent automatically

264

}

265

is Frame.Pong -> println("Received pong")

266

is Frame.Close -> {

267

val reason = frame.readReason()

268

println("Connection closed: ${reason?.message}")

269

break

270

}

271

}

272

}

273

}

274

```

275

276

### Concurrent Send and Receive

277

278

```kotlin

279

client.webSocket("ws://chat.example.com") {

280

// Separate coroutines for sending and receiving

281

val sendJob = launch {

282

while (isActive) {

283

val message = readLine() ?: break

284

outgoing.send(Frame.Text(message))

285

}

286

}

287

288

val receiveJob = launch {

289

for (frame in incoming) {

290

when (frame) {

291

is Frame.Text -> println(">> ${frame.readText()}")

292

is Frame.Close -> break

293

}

294

}

295

}

296

297

// Wait for either job to complete

298

select {

299

sendJob.onJoin { println("Send completed") }

300

receiveJob.onJoin { println("Receive completed") }

301

}

302

303

// Cancel remaining job

304

sendJob.cancel()

305

receiveJob.cancel()

306

}

307

```

308

309

### Extension Management

310

311

```kotlin

312

client.webSocket("ws://api.example.com") {

313

// List all active extensions

314

println("Active extensions:")

315

extensions.forEach { ext ->

316

println("- ${ext::class.simpleName}")

317

}

318

319

// Check for specific extension

320

extensionOrNull(WebSocketDeflateExtension)?.let { deflate ->

321

println("Compression enabled: level ${deflate.compressionLevel}")

322

}

323

324

// Session logic continues...

325

}

326

```

327

328

### Error Handling in Sessions

329

330

```kotlin

331

try {

332

client.webSocket("ws://unreliable.example.com") {

333

// Configure larger timeout for unreliable connection

334

maxFrameSize = 2 * 1024 * 1024 // 2MB

335

336

for (frame in incoming) {

337

try {

338

when (frame) {

339

is Frame.Text -> processText(frame.readText())

340

is Frame.Binary -> processBinary(frame.data)

341

}

342

} catch (e: Exception) {

343

println("Frame processing error: ${e.message}")

344

// Continue processing other frames

345

}

346

}

347

}

348

} catch (e: WebSocketException) {

349

println("WebSocket error: ${e.message}")

350

} catch (e: ProtocolViolationException) {

351

println("Protocol violation: ${e.message}")

352

}

353

```