wire: Export var length string serialization funcs.

This commit exports the ReadVarString and WriteVarString functions so
they are available for callers to use.

A variable length string is encoded as a variable length integer
containing the length of the string followed by the bytes that represent
the string itself.
This commit is contained in:
Dave Collins 2015-10-16 10:52:39 -05:00
parent 4c3ad4987b
commit 80fa803875
7 changed files with 42 additions and 54 deletions

View file

@ -187,7 +187,7 @@ func BenchmarkReadVarInt9(b *testing.B) {
func BenchmarkReadVarStr4(b *testing.B) { func BenchmarkReadVarStr4(b *testing.B) {
buf := []byte{0x04, 't', 'e', 's', 't'} buf := []byte{0x04, 't', 'e', 's', 't'}
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
readVarString(bytes.NewReader(buf), 0) ReadVarString(bytes.NewReader(buf), 0)
} }
} }
@ -196,7 +196,7 @@ func BenchmarkReadVarStr4(b *testing.B) {
func BenchmarkReadVarStr10(b *testing.B) { func BenchmarkReadVarStr10(b *testing.B) {
buf := []byte{0x0a, 't', 'e', 's', 't', '0', '1', '2', '3', '4', '5'} buf := []byte{0x0a, 't', 'e', 's', 't', '0', '1', '2', '3', '4', '5'}
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
readVarString(bytes.NewReader(buf), 0) ReadVarString(bytes.NewReader(buf), 0)
} }
} }
@ -204,7 +204,7 @@ func BenchmarkReadVarStr10(b *testing.B) {
// four byte variable length string. // four byte variable length string.
func BenchmarkWriteVarStr4(b *testing.B) { func BenchmarkWriteVarStr4(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
writeVarString(ioutil.Discard, 0, "test") WriteVarString(ioutil.Discard, 0, "test")
} }
} }
@ -212,7 +212,7 @@ func BenchmarkWriteVarStr4(b *testing.B) {
// ten byte variable length string. // ten byte variable length string.
func BenchmarkWriteVarStr10(b *testing.B) { func BenchmarkWriteVarStr10(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
writeVarString(ioutil.Discard, 0, "test012345") WriteVarString(ioutil.Discard, 0, "test012345")
} }
} }

View file

@ -440,14 +440,13 @@ func VarIntSerializeSize(val uint64) int {
return 9 return 9
} }
// readVarString reads a variable length string from r and returns it as a Go // ReadVarString reads a variable length string from r and returns it as a Go
// string. A varString is encoded as a varInt containing the length of the // string. A variable length string is encoded as a variable length integer
// string, and the bytes that represent the string itself. An error is returned // containing the length of the string followed by the bytes that represent the
// if the length is greater than the maximum block payload size, since it would // string itself. An error is returned if the length is greater than the
// not be possible to put a varString of that size into a block anyways and it // maximum block payload size since it helps protect against memory exhaustion
// also helps protect against memory exhaustion attacks and forced panics // attacks and forced panics through malformed messages.
// through malformed messages. func ReadVarString(r io.Reader, pver uint32) (string, error) {
func readVarString(r io.Reader, pver uint32) (string, error) {
count, err := readVarInt(r, pver) count, err := readVarInt(r, pver)
if err != nil { if err != nil {
return "", err return "", err
@ -459,7 +458,7 @@ func readVarString(r io.Reader, pver uint32) (string, error) {
if count > MaxMessagePayload { if count > MaxMessagePayload {
str := fmt.Sprintf("variable length string is too long "+ str := fmt.Sprintf("variable length string is too long "+
"[count %d, max %d]", count, MaxMessagePayload) "[count %d, max %d]", count, MaxMessagePayload)
return "", messageError("readVarString", str) return "", messageError("ReadVarString", str)
} }
buf := make([]byte, count) buf := make([]byte, count)
@ -470,9 +469,10 @@ func readVarString(r io.Reader, pver uint32) (string, error) {
return string(buf), nil return string(buf), nil
} }
// writeVarString serializes str to w as a varInt containing the length of the // WriteVarString serializes str to w as a variable length integer containing
// string followed by the bytes that represent the string itself. // the length of the string followed by the bytes that represent the string
func writeVarString(w io.Writer, pver uint32, str string) error { // itself.
func WriteVarString(w io.Writer, pver uint32, str string) error {
err := writeVarInt(w, pver, uint64(len(str))) err := writeVarInt(w, pver, uint64(len(str)))
if err != nil { if err != nil {
return err return err

View file

@ -471,26 +471,26 @@ func TestVarStringWire(t *testing.T) {
for i, test := range tests { for i, test := range tests {
// Encode to wire format. // Encode to wire format.
var buf bytes.Buffer var buf bytes.Buffer
err := wire.TstWriteVarString(&buf, test.pver, test.in) err := wire.WriteVarString(&buf, test.pver, test.in)
if err != nil { if err != nil {
t.Errorf("writeVarString #%d error %v", i, err) t.Errorf("WriteVarString #%d error %v", i, err)
continue continue
} }
if !bytes.Equal(buf.Bytes(), test.buf) { if !bytes.Equal(buf.Bytes(), test.buf) {
t.Errorf("writeVarString #%d\n got: %s want: %s", i, t.Errorf("WriteVarString #%d\n got: %s want: %s", i,
spew.Sdump(buf.Bytes()), spew.Sdump(test.buf)) spew.Sdump(buf.Bytes()), spew.Sdump(test.buf))
continue continue
} }
// Decode from wire format. // Decode from wire format.
rbuf := bytes.NewReader(test.buf) rbuf := bytes.NewReader(test.buf)
val, err := wire.TstReadVarString(rbuf, test.pver) val, err := wire.ReadVarString(rbuf, test.pver)
if err != nil { if err != nil {
t.Errorf("readVarString #%d error %v", i, err) t.Errorf("ReadVarString #%d error %v", i, err)
continue continue
} }
if val != test.out { if val != test.out {
t.Errorf("readVarString #%d\n got: %s want: %s", i, t.Errorf("ReadVarString #%d\n got: %s want: %s", i,
val, test.out) val, test.out)
continue continue
} }
@ -526,18 +526,18 @@ func TestVarStringWireErrors(t *testing.T) {
for i, test := range tests { for i, test := range tests {
// Encode to wire format. // Encode to wire format.
w := newFixedWriter(test.max) w := newFixedWriter(test.max)
err := wire.TstWriteVarString(w, test.pver, test.in) err := wire.WriteVarString(w, test.pver, test.in)
if err != test.writeErr { if err != test.writeErr {
t.Errorf("writeVarString #%d wrong error got: %v, want: %v", t.Errorf("WriteVarString #%d wrong error got: %v, want: %v",
i, err, test.writeErr) i, err, test.writeErr)
continue continue
} }
// Decode from wire format. // Decode from wire format.
r := newFixedReader(test.max, test.buf) r := newFixedReader(test.max, test.buf)
_, err = wire.TstReadVarString(r, test.pver) _, err = wire.ReadVarString(r, test.pver)
if err != test.readErr { if err != test.readErr {
t.Errorf("readVarString #%d wrong error got: %v, want: %v", t.Errorf("ReadVarString #%d wrong error got: %v, want: %v",
i, err, test.readErr) i, err, test.readErr)
continue continue
} }
@ -566,9 +566,9 @@ func TestVarStringOverflowErrors(t *testing.T) {
for i, test := range tests { for i, test := range tests {
// Decode from wire format. // Decode from wire format.
rbuf := bytes.NewReader(test.buf) rbuf := bytes.NewReader(test.buf)
_, err := wire.TstReadVarString(rbuf, test.pver) _, err := wire.ReadVarString(rbuf, test.pver)
if reflect.TypeOf(err) != reflect.TypeOf(test.err) { if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
t.Errorf("readVarString #%d wrong error got: %v, "+ t.Errorf("ReadVarString #%d wrong error got: %v, "+
"want: %v", i, err, reflect.TypeOf(test.err)) "want: %v", i, err, reflect.TypeOf(test.err))
continue continue
} }

View file

@ -63,18 +63,6 @@ func TstWriteVarInt(w io.Writer, pver uint32, val uint64) error {
return writeVarInt(w, pver, val) return writeVarInt(w, pver, val)
} }
// TstReadVarString makes the internal readVarString function available to the
// test package.
func TstReadVarString(r io.Reader, pver uint32) (string, error) {
return readVarString(r, pver)
}
// TstWriteVarString makes the internal writeVarString function available to the
// test package.
func TstWriteVarString(w io.Writer, pver uint32, str string) error {
return writeVarString(w, pver, str)
}
// TstReadVarBytes makes the internal readVarBytes function available to the // TstReadVarBytes makes the internal readVarBytes function available to the
// test package. // test package.
func TstReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) { func TstReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) {

View file

@ -188,7 +188,7 @@ func (alert *Alert) Serialize(w io.Writer, pver uint32) error {
return err return err
} }
for i := 0; i < int(count); i++ { for i := 0; i < int(count); i++ {
err = writeVarString(w, pver, alert.SetSubVer[i]) err = WriteVarString(w, pver, alert.SetSubVer[i])
if err != nil { if err != nil {
return err return err
} }
@ -198,15 +198,15 @@ func (alert *Alert) Serialize(w io.Writer, pver uint32) error {
if err != nil { if err != nil {
return err return err
} }
err = writeVarString(w, pver, alert.Comment) err = WriteVarString(w, pver, alert.Comment)
if err != nil { if err != nil {
return err return err
} }
err = writeVarString(w, pver, alert.StatusBar) err = WriteVarString(w, pver, alert.StatusBar)
if err != nil { if err != nil {
return err return err
} }
err = writeVarString(w, pver, alert.Reserved) err = WriteVarString(w, pver, alert.Reserved)
if err != nil { if err != nil {
return err return err
} }
@ -260,7 +260,7 @@ func (alert *Alert) Deserialize(r io.Reader, pver uint32) error {
} }
alert.SetSubVer = make([]string, count) alert.SetSubVer = make([]string, count)
for i := 0; i < int(count); i++ { for i := 0; i < int(count); i++ {
alert.SetSubVer[i], err = readVarString(r, pver) alert.SetSubVer[i], err = ReadVarString(r, pver)
if err != nil { if err != nil {
return err return err
} }
@ -270,15 +270,15 @@ func (alert *Alert) Deserialize(r io.Reader, pver uint32) error {
if err != nil { if err != nil {
return err return err
} }
alert.Comment, err = readVarString(r, pver) alert.Comment, err = ReadVarString(r, pver)
if err != nil { if err != nil {
return err return err
} }
alert.StatusBar, err = readVarString(r, pver) alert.StatusBar, err = ReadVarString(r, pver)
if err != nil { if err != nil {
return err return err
} }
alert.Reserved, err = readVarString(r, pver) alert.Reserved, err = ReadVarString(r, pver)
if err != nil { if err != nil {
return err return err
} }

View file

@ -79,7 +79,7 @@ func (msg *MsgReject) BtcDecode(r io.Reader, pver uint32) error {
} }
// Command that was rejected. // Command that was rejected.
cmd, err := readVarString(r, pver) cmd, err := ReadVarString(r, pver)
if err != nil { if err != nil {
return err return err
} }
@ -93,7 +93,7 @@ func (msg *MsgReject) BtcDecode(r io.Reader, pver uint32) error {
// Human readable string with specific details (over and above the // Human readable string with specific details (over and above the
// reject code above) about why the command was rejected. // reject code above) about why the command was rejected.
reason, err := readVarString(r, pver) reason, err := ReadVarString(r, pver)
if err != nil { if err != nil {
return err return err
} }
@ -121,7 +121,7 @@ func (msg *MsgReject) BtcEncode(w io.Writer, pver uint32) error {
} }
// Command that was rejected. // Command that was rejected.
err := writeVarString(w, pver, msg.Cmd) err := WriteVarString(w, pver, msg.Cmd)
if err != nil { if err != nil {
return err return err
} }
@ -134,7 +134,7 @@ func (msg *MsgReject) BtcEncode(w io.Writer, pver uint32) error {
// Human readable string with specific details (over and above the // Human readable string with specific details (over and above the
// reject code above) about why the command was rejected. // reject code above) about why the command was rejected.
err = writeVarString(w, pver, msg.Reason) err = WriteVarString(w, pver, msg.Reason)
if err != nil { if err != nil {
return err return err
} }

View file

@ -115,7 +115,7 @@ func (msg *MsgVersion) BtcDecode(r io.Reader, pver uint32) error {
} }
} }
if buf.Len() > 0 { if buf.Len() > 0 {
userAgent, err := readVarString(buf, pver) userAgent, err := ReadVarString(buf, pver)
if err != nil { if err != nil {
return err return err
} }
@ -181,7 +181,7 @@ func (msg *MsgVersion) BtcEncode(w io.Writer, pver uint32) error {
return err return err
} }
err = writeVarString(w, pver, msg.UserAgent) err = WriteVarString(w, pver, msg.UserAgent)
if err != nil { if err != nil {
return err return err
} }