diff options
Diffstat (limited to 'src/ssl/test/runner/packet_adapter.go')
-rw-r--r-- | src/ssl/test/runner/packet_adapter.go | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/ssl/test/runner/packet_adapter.go b/src/ssl/test/runner/packet_adapter.go new file mode 100644 index 0000000..671b413 --- /dev/null +++ b/src/ssl/test/runner/packet_adapter.go @@ -0,0 +1,101 @@ +// 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) +} |