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

fix(client):Malformed packet #639

Closed
wants to merge 5 commits into from
Closed

Conversation

pretty66
Copy link
Contributor

@pretty66 pretty66 commented Nov 1, 2021

Fixes #638
Fixes #618

When go-mysql acts as a proxy to forward OK packets, Resultset needs to be equal to nil, otherwise it will cause:

ERROR 2027 (HY000): Malformed packet

image

The problem can be reproduced by the following code

package main

import (
	"context"
	"errors"
	"github.com/go-mysql-org/go-mysql/client"
	"github.com/go-mysql-org/go-mysql/mysql"
	"github.com/go-mysql-org/go-mysql/server"
	"io"
	"log"
	"net"
)

type proxy struct {
	pool   *client.Pool
}

func main() {
	p := proxy{}
	p.pool = client.NewPool(func(format string, args ...interface{}) {
		log.Printf(format, args...)
	}, 0, 50, 180, "127.0.0.1:3306", "root", "root", "test")

	l, err := net.Listen("tcp", ":23306")
	if err != nil {
		panic(err)
	}
	for {
		conn, err := l.Accept()
		if err != nil {
			if errors.Is(err, io.EOF) {
				return
			}
			panic(err)
		}
		go p.onConn(conn)
	}
}


func (p *proxy) onConn(conn net.Conn) {
	// The account password provided by the client connection
	clientConn, err := server.NewConn(conn, "root", "root", p)
	if err != nil {
		conn.Close()
		return
	}
	defer func() {
		if !clientConn.Closed() {
			clientConn.Close()
		}
	}()

	for {
		err = clientConn.HandleCommand()
		if err != nil {
			log.Println(err)
			return
		}
	}
}

func (h *proxy) CloseConn() error {
	return nil
}

func (h *proxy) UseDB(dbName string) error {
	conn, err := h.pool.GetConn(context.TODO())
	if err != nil {
		return err
	}
	defer h.pool.PutConn(conn)
	return conn.UseDB(dbName)
}

func (h *proxy) HandleQuery(query string) (res *mysql.Result, err error) {
	conn, err := h.pool.GetConn(context.TODO())
	if err != nil {
		return nil, err
	}
	defer h.pool.PutConn(conn)
	return conn.Execute(query)
}

func (h *proxy) HandleFieldList(table string, fieldWildcard string) ([]*mysql.Field, error) {
	conn, err := h.pool.GetConn(context.TODO())
	if err != nil {
		return nil, err
	}
	defer h.pool.PutConn(conn)
	return conn.FieldList(table, fieldWildcard)
}

func (h *proxy) HandleStmtPrepare(query string) (int, int, interface{}, error) {
	conn, err := h.pool.GetConn(context.TODO())
	if err != nil {
		return 0, 0, nil, err
	}
	defer h.pool.PutConn(conn)
	stmt, err := conn.Prepare(query)
	if err != nil {
		return 0, 0, nil, err
	}
	return stmt.ParamNum(), stmt.ColumnNum(), stmt, err
}

func (h *proxy) HandleStmtExecute(context interface{}, query string, args []interface{}) (*mysql.Result, error) {
	stmt, ok := context.(*client.Stmt)
	if !ok {
		return nil, errors.New("stmt point empty")
	}
	return stmt.Execute(args...)
}

func (h *proxy) HandleStmtClose(context interface{}) error {
	stmt, ok := context.(*client.Stmt)
	if !ok {
		return errors.New("stmt point empty")
	}
	return stmt.Close()
}

func (h *proxy) HandleOtherCommand(cmd byte, data []byte) error {
	return errors.New("command %d is not supported now" + string(cmd))
}

@lance6716
Copy link
Collaborator

seems this line has been changed back and forth for a long time #578 #637 . We should now find a better way to satisfy all above scenarios 😂

@pretty66 can you help us for a better behaviour?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Client code ok response packet protocol parsing error ERROR 2027 (HY000): Malformed packet
2 participants