Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoder for the polling transport. #505

Merged
merged 1 commit into from May 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/unittest.yaml
Expand Up @@ -11,7 +11,7 @@ jobs:
- '1.14.x'
- '1.15.x'
- '1.16.x'
- 'tip'
- '1.17.x'
steps:
- name: Install Go
if: matrix.go != 'tip'
Expand Down
45 changes: 21 additions & 24 deletions engineio/transport/polling/decoder.go
Expand Up @@ -21,64 +21,61 @@ func newDecoder(buf []byte, r io.Reader) *decoder {
}

// NextFrame returns a reader to read the next frame.
func (d *decoder) NextFrame() (frame.Frame, error) {
func (d *decoder) NextFrame() (frame.Type, io.Reader, error) {
if d.lastFrame != nil {
if err := d.lastFrame.Discard(); err != nil {
return frame.Frame{}, err
return 0, nil, err
}
}

if err := d.reader.Fill(); err != nil {
return frame.Frame{}, err
return 0, nil, err
}

next, err := d.reader.ReadByte()
if err != nil && err != io.EOF {
return frame.Frame{}, err
return 0, nil, err
}

if d.lastFrame != nil {
// Start from the 2nd frame, need to ignore the separator.
next, err = d.reader.ReadByte()
if err != nil && err != io.EOF {
return frame.Frame{}, err
return 0, nil, err
}
}

d.lastFrame = &frameReader{
reader: d.reader,
reader: d.reader,
finished: false,
}

if err == nil && next == binaryPrefix {
return frame.Frame{
Type: frame.Binary,
Data: base64.NewDecoder(base64.StdEncoding, d.lastFrame),
}, nil
return frame.Binary, base64.NewDecoder(base64.StdEncoding, d.lastFrame), nil
}

// The next byte is not binary prefix byte. Push it back to the reader
if err == nil {
if err := d.lastFrame.reader.PushBack(1); err != nil {
return frame.Frame{}, err
return 0, nil, err
}
}

return frame.Frame{
Type: frame.Text,
Data: d.lastFrame,
}, nil
return frame.Text, d.lastFrame, nil
}

// frameReader is a reader to read one frame.
type frameReader struct {
reader *bufReader
reader *bufReader
finished bool
}

// Read reads data of the frame to buffer b.
func (r *frameReader) Read(b []byte) (int, error) {
n, err := r.reader.Read(b)
for i := 0; i < n; i++ {
if b[i] == separator {
r.finished = true
if err := r.reader.PushBack(n - i); err != nil {
return n, fmt.Errorf("decode package error:(it should not happen) %w", err)
}
Expand Down Expand Up @@ -117,14 +114,14 @@ func (r *frameReader) ReadByte() (byte, error) {
// Discard discards all data in the frame.
func (r *frameReader) Discard() error {
var buf [1024]byte
var err error

for err == nil {
_, err = r.Read(buf[:])
}

if err != nil && err != io.EOF {
return err
for {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

_, err := r.Read(buf[:])
if err != nil {
if err == io.EOF {
break
}
return err
}
}

return nil
Expand Down
30 changes: 15 additions & 15 deletions engineio/transport/polling/decoder_test.go
Expand Up @@ -34,21 +34,21 @@ func TestDecoder(t *testing.T) {
var gotType []frame.Type

for {
frame, err := decoder.NextFrame()
ft, rdFrame, err := decoder.NextFrame()
if err != nil {
if err == io.EOF {
break
}
t.Fatalf("reading(%q) NextFrame() error: %s", test.input, err)
}

b, err := ioutil.ReadAll(frame.Data)
b, err := ioutil.ReadAll(rdFrame)
if err != nil {
t.Fatalf("reading(%q) frame error: %s", test.input, err)
}

got = append(got, string(b))
gotType = append(gotType, frame.Type)
gotType = append(gotType, ft)
}

if diff := cmp.Diff(test.want, got); diff != "" {
Expand All @@ -65,19 +65,19 @@ func TestDecoderIgnoreReading(t *testing.T) {
var buf [50]byte
decoder := newDecoder(buf[:], strings.NewReader(data))

if _, err := decoder.NextFrame(); err != nil {
if _, _, err := decoder.NextFrame(); err != nil {
t.Fatalf("get next frame error: %s", err)
}
f, err := decoder.NextFrame()
ft, rd, err := decoder.NextFrame()
if err != nil {
t.Fatalf("get next frame again error: %s", err)
}

b, err := ioutil.ReadAll(f.Data)
b, err := ioutil.ReadAll(rd)
if err != nil {
t.Fatalf("read frame error: %s", err)
}
if want, got := frame.Text, f.Type; want != got {
if want, got := frame.Text, ft; want != got {
t.Fatalf("frame type, want: %v, got: %v", want, got)
}
if want, got := "5678", string(b); want != got {
Expand All @@ -94,16 +94,16 @@ func TestDecoderTextWithReadByte(t *testing.T) {
var buf [50]byte
decoder := newDecoder(buf[:], strings.NewReader(data))

f, err := decoder.NextFrame()
ft, rd, err := decoder.NextFrame()
if err != nil {
t.Fatalf("get next frame error: %s", err)
}
if want, got := frame.Text, f.Type; want != got {
if want, got := frame.Text, ft; want != got {
t.Fatalf("frame type, want: %v, got: %v", want, got)
}
brd, ok := f.Data.(byteReader)
brd, ok := rd.(byteReader)
if !ok {
t.Fatalf("text frame reader should have ReadByte(), but not: %v", f.Data)
t.Fatalf("text frame reader should have ReadByte(), but not: %v", rd)
}
for _, want := range []byte("1234") {
got, err := brd.ReadByte()
Expand All @@ -119,14 +119,14 @@ func TestDecoderTextWithReadByte(t *testing.T) {
t.Fatalf("read text should return io.EOF, but got: byte(%x), error(%s)", bt, err)
}

f, err = decoder.NextFrame()
ft, rd, err = decoder.NextFrame()
if err != nil {
t.Fatalf("get next frame error: %s", err)
}
if want, got := frame.Binary, f.Type; want != got {
if want, got := frame.Binary, ft; want != got {
t.Fatalf("frame type, want: %v, got: %v", want, got)
}
if _, ok := f.Data.(byteReader); ok {
t.Fatalf("binary frame reader should not have ReadByte(), but it have: %v", f.Data)
if _, ok := rd.(byteReader); ok {
t.Fatalf("binary frame reader should not have ReadByte(), but it have: %v", rd)
}
}