gosocketio/vendor/github.com/googollee/go-socket.io/engineio/payload/encoder.go

128 lines
2.5 KiB
Go

package payload
import (
"bytes"
"encoding/base64"
"io"
"github.com/googollee/go-socket.io/engineio/frame"
"github.com/googollee/go-socket.io/engineio/packet"
)
type writerFeeder interface {
getWriter() (io.Writer, error)
putWriter(error) error
}
type encoder struct {
supportBinary bool
feeder writerFeeder
ft frame.Type
pt packet.Type
header bytes.Buffer
frameCache bytes.Buffer
b64Writer io.WriteCloser
rawWriter io.Writer
}
func (e *encoder) NOOP() []byte {
if e.supportBinary {
return []byte{0x00, 0x01, 0xff, '6'}
}
return []byte("1:6")
}
func (e *encoder) NextWriter(ft frame.Type, pt packet.Type) (io.WriteCloser, error) {
w, err := e.feeder.getWriter()
if err != nil {
return nil, err
}
e.rawWriter = w
e.ft = ft
e.pt = pt
e.frameCache.Reset()
if !e.supportBinary && ft == frame.Binary {
e.b64Writer = base64.NewEncoder(base64.StdEncoding, &e.frameCache)
} else {
e.b64Writer = nil
}
return e, nil
}
func (e *encoder) Write(p []byte) (int, error) {
if e.b64Writer != nil {
return e.b64Writer.Write(p)
}
return e.frameCache.Write(p)
}
func (e *encoder) Close() error {
if e.b64Writer != nil {
e.b64Writer.Close()
}
var writeHeader func() error
if e.supportBinary {
writeHeader = e.writeBinaryHeader
} else {
if e.ft == frame.Binary {
writeHeader = e.writeB64Header
} else {
writeHeader = e.writeTextHeader
}
}
e.header.Reset()
err := writeHeader()
if err == nil {
_, err = e.header.WriteTo(e.rawWriter)
}
if err == nil {
_, err = e.frameCache.WriteTo(e.rawWriter)
}
if werr := e.feeder.putWriter(err); werr != nil {
return werr
}
return err
}
func (e *encoder) writeTextHeader() error {
l := int64(e.frameCache.Len() + 1) // length for packet type
err := writeTextLen(l, &e.header)
if err == nil {
err = e.header.WriteByte(e.pt.StringByte())
}
return err
}
func (e *encoder) writeB64Header() error {
l := int64(e.frameCache.Len() + 2) // length for 'b' and packet type
err := writeTextLen(l, &e.header)
if err == nil {
err = e.header.WriteByte('b')
}
if err == nil {
err = e.header.WriteByte(e.pt.StringByte())
}
return err
}
func (e *encoder) writeBinaryHeader() error {
l := int64(e.frameCache.Len() + 1) // length for packet type
b := e.pt.StringByte()
if e.ft == frame.Binary {
b = e.pt.BinaryByte()
}
err := e.header.WriteByte(e.ft.Byte())
if err == nil {
err = writeBinaryLen(l, &e.header)
}
if err == nil {
err = e.header.WriteByte(b)
}
return err
}