5fa3eba03d
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>
102 lines
2.3 KiB
Go
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)
|
|
}
|