mysql.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package l7
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "strconv"
  6. )
  7. const (
  8. MysqlComQuery = 3
  9. MysqlComStmtPrepare = 0x16
  10. MysqlComStmtExecute = 0x17
  11. MysqlComStmtClose = 0x19
  12. mysqlMsgHeaderSize = 4
  13. )
  14. type MysqlParser struct {
  15. preparedStatements map[string]string
  16. }
  17. func NewMysqlParser() *MysqlParser {
  18. return &MysqlParser{preparedStatements: map[string]string{}}
  19. }
  20. func (p *MysqlParser) Parse(payload []byte, statementId uint32) string {
  21. payloadSize := len(payload)
  22. if payloadSize < mysqlMsgHeaderSize+5 {
  23. return ""
  24. }
  25. msgSize := int(payload[0]) | int(payload[1])<<8 | int(payload[2])<<16
  26. cmd := payload[4]
  27. readQuery := func() (query string) {
  28. to := mysqlMsgHeaderSize + msgSize
  29. partial := false
  30. if to > payloadSize {
  31. to = payloadSize
  32. partial = true
  33. }
  34. query = string(payload[mysqlMsgHeaderSize+1 : to])
  35. if partial {
  36. query += "..."
  37. }
  38. return query
  39. }
  40. readStatementId := func() string {
  41. return strconv.FormatUint(uint64(binary.LittleEndian.Uint32(payload[mysqlMsgHeaderSize+1:])), 10)
  42. }
  43. switch cmd {
  44. case MysqlComQuery:
  45. return readQuery()
  46. case MysqlComStmtExecute:
  47. statementIdStr := readStatementId()
  48. statement, ok := p.preparedStatements[statementIdStr]
  49. if !ok {
  50. statement = fmt.Sprintf(`EXECUTE %s /* unknown */`, statementIdStr)
  51. }
  52. return statement
  53. case MysqlComStmtPrepare:
  54. query := readQuery()
  55. statementIdStr := strconv.FormatUint(uint64(statementId), 10)
  56. p.preparedStatements[statementIdStr] = query
  57. return fmt.Sprintf("PREPARE %s FROM %s", statementIdStr, query)
  58. case MysqlComStmtClose:
  59. statementIdStr := readStatementId()
  60. delete(p.preparedStatements, statementIdStr)
  61. }
  62. return ""
  63. }