clientWriter
()
| 208 | |
| 209 | // clientWriter |
| 210 | func (c *Client) clientWriter() { |
| 211 | // Set up expiration timer. |
| 212 | // NOTE: if a token is created without an expiration date |
| 213 | // this will be set to nil, which will close the loop bellow |
| 214 | // and terminate the connection immediately. |
| 215 | // We can't have a token without an expiration date. |
| 216 | var authExpires time.Time |
| 217 | expires := auth.Expires(c.ctx) |
| 218 | if expires != nil { |
| 219 | authExpires = *expires |
| 220 | } |
| 221 | authTimer := time.NewTimer(time.Until(authExpires)) |
| 222 | ticker := time.NewTicker(pingPeriod) |
| 223 | defer func() { |
| 224 | c.Stop() |
| 225 | ticker.Stop() |
| 226 | authTimer.Stop() |
| 227 | }() |
| 228 | for { |
| 229 | select { |
| 230 | case message, ok := <-c.send: |
| 231 | if !ok { |
| 232 | // The hub closed the channel. |
| 233 | if err := c.writeMessage(websocket.CloseMessage, []byte{}); err != nil { |
| 234 | if IsErrorOfInterest(err) { |
| 235 | slog.With(slog.Any("error", err)).Error("failed to write message") |
| 236 | } |
| 237 | } |
| 238 | return |
| 239 | } |
| 240 | |
| 241 | if err := c.writeMessage(websocket.TextMessage, message); err != nil { |
| 242 | if IsErrorOfInterest(err) { |
| 243 | slog.With(slog.Any("error", err)).Error("error sending message") |
| 244 | } |
| 245 | return |
| 246 | } |
| 247 | case <-ticker.C: |
| 248 | if err := c.writeMessage(websocket.PingMessage, nil); err != nil { |
| 249 | if IsErrorOfInterest(err) { |
| 250 | slog.With(slog.Any("error", err)).Error("failed to write ping message") |
| 251 | } |
| 252 | return |
| 253 | } |
| 254 | case <-c.ctx.Done(): |
| 255 | return |
| 256 | case <-authTimer.C: |
| 257 | // Auth has expired |
| 258 | slog.DebugContext(c.ctx, "auth expired, closing connection") |
| 259 | return |
| 260 | } |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | func (c *Client) runWatcher() { |
| 265 | defer func() { |
no test coverage detected