or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

content-serialization.mdindex.mdplugin-configuration.mdraw-websocket-operations.mdsession-operations.mdwebsocket-connections.md

session-operations.mddocs/

0

# Session Operations

1

2

WebSocket session operations provide access to client-specific session interfaces, HTTP call context, and core frame communication functionality.

3

4

## Client WebSocket Session Interface

5

6

The main interface for client WebSocket sessions that provides access to the associated HTTP call:

7

8

```kotlin { .api }

9

interface ClientWebSocketSession : WebSocketSession {

10

val call: HttpClientCall

11

}

12

```

13

14

- **call**: Access to the original HttpClientCall that initiated the WebSocket connection

15

- **Inherits**: All functionality from WebSocketSession (masking, frame size, channels, extensions)

16

17

**Usage:**

18

```kotlin

19

client.webSocketSession("ws://example.com/") { session ->

20

// Access HTTP call context

21

println("Request URL: ${session.call.request.url}")

22

println("Response status: ${session.call.response.status}")

23

24

// Use WebSocket functionality

25

session.send("Hello!")

26

}

27

```

28

29

## Default Client WebSocket Session

30

31

The default implementation used by all WebSocket connection functions:

32

33

```kotlin { .api }

34

class DefaultClientWebSocketSession(

35

override val call: HttpClientCall,

36

delegate: DefaultWebSocketSession

37

) : ClientWebSocketSession, DefaultWebSocketSession by delegate

38

```

39

40

- **Delegation**: Delegates WebSocket functionality to DefaultWebSocketSession

41

- **HTTP Context**: Maintains reference to the originating HTTP call

42

- **Ping-Pong**: Supports automatic ping-pong heartbeat mechanism

43

44

**Properties inherited from WebSocketSession:**

45

```kotlin

46

var masking: Boolean // Frame masking (client-side typically true)

47

var maxFrameSize: Long // Maximum frame size limit

48

val incoming: ReceiveChannel<Frame> // Channel for incoming frames

49

val outgoing: SendChannel<Frame> // Channel for outgoing frames

50

val extensions: List<WebSocketExtension<*>> // Active WebSocket extensions

51

```

52

53

**Properties inherited from DefaultWebSocketSession:**

54

```kotlin

55

var pingIntervalMillis: Long // Ping interval in milliseconds

56

var timeoutMillis: Long // Session timeout in milliseconds

57

val closeReason: Deferred<CloseReason?> // Deferred close reason

58

```

59

60

## Frame Communication

61

62

### Sending Frames

63

64

Send different types of WebSocket frames:

65

66

```kotlin

67

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

68

// Send text frame (convenience method)

69

send("Hello WebSocket!")

70

71

// Send explicit text frame

72

send(Frame.Text("Explicit text frame"))

73

74

// Send binary frame

75

val data = "Binary data".toByteArray()

76

send(Frame.Binary(true, data))

77

78

// Send ping frame

79

send(Frame.Ping("ping-data".toByteArray()))

80

81

// Send pong frame (usually automatic)

82

send(Frame.Pong("pong-data".toByteArray()))

83

84

// Send close frame

85

send(Frame.Close(CloseReason(CloseReason.Codes.NORMAL, "Goodbye")))

86

}

87

```

88

89

### Receiving Frames

90

91

Process incoming WebSocket frames:

92

93

```kotlin

94

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

95

// Receive single frame

96

val frame = incoming.receive()

97

when (frame) {

98

is Frame.Text -> {

99

val text = frame.readText()

100

println("Text: $text")

101

}

102

is Frame.Binary -> {

103

val data = frame.data

104

println("Binary: ${data.size} bytes")

105

}

106

is Frame.Close -> {

107

val reason = frame.readReason()

108

println("Close: ${reason?.code} - ${reason?.message}")

109

}

110

is Frame.Ping -> {

111

println("Ping received")

112

// Pong response usually automatic

113

}

114

is Frame.Pong -> {

115

println("Pong received")

116

}

117

}

118

119

// Process all incoming frames

120

for (frame in incoming) {

121

when (frame) {

122

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

123

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

124

is Frame.Close -> {

125

println("Connection closed: ${frame.readReason()}")

126

break

127

}

128

else -> println("Other frame: $frame")

129

}

130

}

131

}

132

```

133

134

### Frame Utilities

135

136

Convenience methods for working with frames:

137

138

```kotlin

139

// Text frame utilities

140

fun Frame.Text.readText(): String // Read frame content as text

141

142

// Binary frame utilities

143

val Frame.Binary.data: ByteArray // Access binary data

144

145

// Close frame utilities

146

fun Frame.Close.readReason(): CloseReason? // Read close reason

147

```

148

149

## Session Management

150

151

### Manual Session Management

152

153

Create and manage sessions manually:

154

155

```kotlin

156

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

157

158

try {

159

// Use session

160

session.send("Hello!")

161

val response = session.incoming.receive()

162

println("Response: $response")

163

} finally {

164

// Always close manually created sessions

165

session.close(CloseReason(CloseReason.Codes.NORMAL, "Done"))

166

}

167

```

168

169

### Automatic Session Management

170

171

Use session blocks for automatic management:

172

173

```kotlin

174

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

175

// Session automatically closed when block exits

176

send("Hello!")

177

val response = incoming.receive()

178

println("Response: $response")

179

180

// Explicit close optional

181

close(CloseReason(CloseReason.Codes.NORMAL, "Finished"))

182

}

183

```

184

185

## Session Properties and Methods

186

187

### Core WebSocket Methods

188

189

```kotlin { .api }

190

suspend fun WebSocketSession.send(frame: Frame)

191

suspend fun WebSocketSession.flush()

192

suspend fun WebSocketSession.close(reason: CloseReason? = null)

193

```

194

195

### Ping-Pong Control

196

197

```kotlin { .api }

198

var DefaultWebSocketSession.pingIntervalMillis: Long // Ping interval

199

var DefaultWebSocketSession.timeoutMillis: Long // Timeout for responses

200

val DefaultWebSocketSession.closeReason: Deferred<CloseReason?> // Final close reason

201

```

202

203

**Usage:**

204

```kotlin

205

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

206

// Configure ping behavior

207

pingIntervalMillis = 30_000 // 30 seconds

208

timeoutMillis = 60_000 // 60 seconds timeout

209

210

send("Configured connection!")

211

212

// Wait for close reason

213

val reason = closeReason.await()

214

println("Session closed: $reason")

215

}

216

```

217

218

## Error Handling in Sessions

219

220

Handle session-level errors and exceptions:

221

222

```kotlin

223

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

224

try {

225

send("Test message")

226

227

for (frame in incoming) {

228

when (frame) {

229

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

230

is Frame.Close -> {

231

val reason = frame.readReason()

232

if (reason?.code != CloseReason.Codes.NORMAL.code) {

233

println("Abnormal close: ${reason?.message}")

234

}

235

break

236

}

237

else -> { /* Handle other frames */ }

238

}

239

}

240

} catch (e: ClosedReceiveChannelException) {

241

println("Connection closed unexpectedly")

242

} catch (e: WebSocketException) {

243

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

244

} catch (e: Exception) {

245

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

246

// Close gracefully on error

247

close(CloseReason(CloseReason.Codes.INTERNAL_ERROR, "Client error"))

248

}

249

}

250

```

251

252

## Content Converter Access

253

254

Access the configured content converter for serialization:

255

256

```kotlin { .api }

257

val DefaultClientWebSocketSession.converter: WebsocketContentConverter?

258

```

259

260

**Usage:**

261

```kotlin

262

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

263

val converter = this.converter

264

if (converter != null) {

265

println("Content converter available: ${converter::class.simpleName}")

266

// Use sendSerialized/receiveDeserialized

267

} else {

268

println("No content converter configured")

269

// Use raw frame operations

270

}

271

}

272

```

273

274

## Session Lifecycle

275

276

1. **Creation**: Session created during WebSocket handshake

277

2. **Initialization**: ping-pong timers started (if configured)

278

3. **Active Communication**: Frame exchange through incoming/outgoing channels

279

4. **Heartbeat**: Automatic ping frames sent based on pingIntervalMillis

280

5. **Timeout Detection**: Session terminated if no pong received within timeoutMillis

281

6. **Graceful Close**: Close frame exchange with reason code

282

7. **Resource Cleanup**: Channels closed, timers cancelled, HTTP call completed