boringssl/ssl/test/runner/packet_adapter.go
David Benjamin 5fa3eba03d Clear the error queue when dropping a bad DTLS packet.
This regressed in e95d20dcb8. EVP_AEAD will push
errors on the error queue (unlike the EVP_CIPHER codepath which checked
everything internally to ssl/ and didn't bother pushing anything). This meant
that a dropped packet would leave junk in the error queue.

Later, when SSL_read returns <= 0 (EOF or EWOULDBLOCK), the non-empty error
queue check in SSL_get_error kicks in and SSL_read looks to have failed.

BUG=https://code.google.com/p/webrtc/issues/detail?id=4214

Change-Id: I1e5e41c77a3e5b71e9eb0c72294abf0da677f840
Reviewed-on: https://boringssl-review.googlesource.com/2982
Reviewed-by: Adam Langley <agl@google.com>
2015-01-22 22:06:40 +00:00

102 lines
2.3 KiB
Go

// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"encoding/binary"
"errors"
"net"
)
type packetAdaptor struct {
net.Conn
}
// newPacketAdaptor wraps a reliable streaming net.Conn into a
// reliable packet-based net.Conn. Every packet is encoded with a
// 32-bit length prefix as a framing layer.
func newPacketAdaptor(conn net.Conn) net.Conn {
return &packetAdaptor{conn}
}
func (p *packetAdaptor) Read(b []byte) (int, error) {
var length uint32
if err := binary.Read(p.Conn, binary.BigEndian, &length); err != nil {
return 0, err
}
out := make([]byte, length)
n, err := p.Conn.Read(out)
if err != nil {
return 0, err
}
if n != int(length) {
return 0, errors.New("internal error: length mismatch!")
}
return copy(b, out), nil
}
func (p *packetAdaptor) Write(b []byte) (int, error) {
length := uint32(len(b))
if err := binary.Write(p.Conn, binary.BigEndian, length); err != nil {
return 0, err
}
n, err := p.Conn.Write(b)
if err != nil {
return 0, err
}
if n != len(b) {
return 0, errors.New("internal error: length mismatch!")
}
return len(b), nil
}
type replayAdaptor struct {
net.Conn
prevWrite []byte
}
// newReplayAdaptor wraps a packeted net.Conn. It transforms it into
// one which, after writing a packet, always replays the previous
// write.
func newReplayAdaptor(conn net.Conn) net.Conn {
return &replayAdaptor{Conn: conn}
}
func (r *replayAdaptor) Write(b []byte) (int, error) {
n, err := r.Conn.Write(b)
// Replay the previous packet and save the current one to
// replay next.
if r.prevWrite != nil {
r.Conn.Write(r.prevWrite)
}
r.prevWrite = append(r.prevWrite[:0], b...)
return n, err
}
type damageAdaptor struct {
net.Conn
damage bool
}
// newDamageAdaptor wraps a packeted net.Conn. It transforms it into one which
// optionally damages the final byte of every Write() call.
func newDamageAdaptor(conn net.Conn) *damageAdaptor {
return &damageAdaptor{Conn: conn}
}
func (d *damageAdaptor) setDamage(damage bool) {
d.damage = damage
}
func (d *damageAdaptor) Write(b []byte) (int, error) {
if d.damage && len(b) > 0 {
b = append([]byte{}, b...)
b[len(b)-1]++
}
return d.Conn.Write(b)
}