(ctx context.Context, h header)
| 288 | } |
| 289 | |
| 290 | func (c *Conn) handleControl(ctx context.Context, h header) (err error) { |
| 291 | if h.payloadLength < 0 || h.payloadLength > maxControlPayload { |
| 292 | err := fmt.Errorf("received control frame payload with invalid length: %d", h.payloadLength) |
| 293 | c.writeError(StatusProtocolError, err) |
| 294 | return err |
| 295 | } |
| 296 | |
| 297 | if !h.fin { |
| 298 | err := errors.New("received fragmented control frame") |
| 299 | c.writeError(StatusProtocolError, err) |
| 300 | return err |
| 301 | } |
| 302 | |
| 303 | ctx, cancel := context.WithTimeout(ctx, time.Second*5) |
| 304 | defer cancel() |
| 305 | |
| 306 | b := c.readControlBuf[:h.payloadLength] |
| 307 | _, err = c.readFramePayload(ctx, b) |
| 308 | if err != nil { |
| 309 | return err |
| 310 | } |
| 311 | |
| 312 | if h.masked { |
| 313 | mask(b, h.maskKey) |
| 314 | } |
| 315 | |
| 316 | switch h.opcode { |
| 317 | case opPing: |
| 318 | if c.onPingReceived != nil { |
| 319 | if !c.onPingReceived(ctx, b) { |
| 320 | return nil |
| 321 | } |
| 322 | } |
| 323 | return c.writeControl(ctx, opPong, b) |
| 324 | case opPong: |
| 325 | if c.onPongReceived != nil { |
| 326 | c.onPongReceived(ctx, b) |
| 327 | } |
| 328 | c.activePingsMu.Lock() |
| 329 | pong, ok := c.activePings[string(b)] |
| 330 | c.activePingsMu.Unlock() |
| 331 | if ok { |
| 332 | select { |
| 333 | case pong <- struct{}{}: |
| 334 | default: |
| 335 | } |
| 336 | } |
| 337 | return nil |
| 338 | } |
| 339 | |
| 340 | // opClose |
| 341 | |
| 342 | ce, err := parseClosePayload(b) |
| 343 | if err != nil { |
| 344 | err = fmt.Errorf("received invalid close payload: %w", err) |
| 345 | c.writeError(StatusProtocolError, err) |
| 346 | return err |
| 347 | } |
no test coverage detected