in packetbeat/protos/mysql/mysql.go [1001:1148]
func (mysql *mysqlPlugin) parseMysqlResponse(data []byte) ([]string, [][]string) {
length, err := readLength(data, 0)
if err != nil {
logp.Warn("Invalid response: %v", err)
return []string{}, [][]string{}
}
if length < 1 {
logp.Warn("Warning: Skipping empty Response")
return []string{}, [][]string{}
}
if len(data) < 5 {
logp.Warn("Invalid response: data less than 5 bytes")
return []string{}, [][]string{}
}
fields := []string{}
rows := [][]string{}
switch data[4] {
case 0x00:
// OK response
case 0xff:
// Error response
default:
offset := 5
logp.Debug("mysql", "Data len: %d", len(data))
// Read fields
for {
length, err = readLength(data, offset)
if err != nil {
logp.Warn("Invalid response: %v", err)
return []string{}, [][]string{}
}
if len(data[offset:]) < 5 {
logp.Warn("Invalid response.")
return []string{}, [][]string{}
}
if data[offset+4] == 0xfe {
// EOF
offset += length + 4
break
}
_ /* catalog */, off, complete, err := readLstring(data, offset+4)
if err != nil || !complete {
logp.Debug("mysql", "Reading field: %v %v", err, complete)
return fields, rows
}
_ /*database*/, off, complete, err = readLstring(data, off)
if err != nil || !complete {
logp.Debug("mysql", "Reading field: %v %v", err, complete)
return fields, rows
}
_ /*table*/, off, complete, err = readLstring(data, off)
if err != nil || !complete {
logp.Debug("mysql", "Reading field: %v %v", err, complete)
return fields, rows
}
_ /*org table*/, off, complete, err = readLstring(data, off)
if err != nil || !complete {
logp.Debug("mysql", "Reading field: %v %v", err, complete)
return fields, rows
}
name, off, complete, err := readLstring(data, off)
if err != nil || !complete {
logp.Debug("mysql", "Reading field: %v %v", err, complete)
return fields, rows
}
_ /* org name */, _ /*off*/, complete, err = readLstring(data, off)
if err != nil || !complete {
logp.Debug("mysql", "Reading field: %v %v", err, complete)
return fields, rows
}
fields = append(fields, string(name))
offset += length + 4
if len(data) < offset {
logp.Warn("Invalid response.")
return []string{}, [][]string{}
}
}
// Read rows
for offset < len(data) {
var row []string
var rowLen int
if len(data[offset:]) < 5 {
logp.Warn("Invalid response.")
break
}
if data[offset+4] == 0xfe {
// EOF
offset += length + 4 // ineffassign
break
}
length, err = readLength(data, offset)
if err != nil {
logp.Warn("Invalid response: %v", err)
break
}
off := offset + 4 // skip length + packet number
start := off
for off < start+length {
var text []byte
if data[off] == 0xfb {
text = []byte("NULL")
off++
} else {
var err error
var complete bool
text, off, complete, err = readLstring(data, off)
if err != nil || !complete {
logp.Debug("mysql", "Error parsing rows: %+v %t", err, complete)
// nevertheless, return what we have so far
return fields, rows
}
}
if rowLen < mysql.maxRowLength {
if rowLen+len(text) > mysql.maxRowLength {
text = text[:mysql.maxRowLength-rowLen]
}
row = append(row, string(text))
rowLen += len(text)
}
}
logp.Debug("mysqldetailed", "Append row: %v", row)
rows = append(rows, row)
if len(rows) >= mysql.maxStoreRows {
break
}
offset += length + 4
}
}
return fields, rows
}