develop
This commit is contained in:
parent
0506fa2f63
commit
c7833a9df7
|
@ -267,8 +267,6 @@ func readFromServerPackage(
|
||||||
sessionKey := spliceSessionKey(srcIP, srcPort)
|
sessionKey := spliceSessionKey(srcIP, srcPort)
|
||||||
session := sessionPool[*sessionKey]
|
session := sessionPool[*sessionKey]
|
||||||
if session != nil {
|
if session != nil {
|
||||||
// session.readFromServer(tcpPayload)
|
|
||||||
// qp = session.GenerateQueryPiece()
|
|
||||||
pkt := model.NewTCPPacket(tcpPayload, int64(tcpPkt.Ack), false)
|
pkt := model.NewTCPPacket(tcpPayload, int64(tcpPkt.Ack), false)
|
||||||
session.ReceiveTCPPacket(pkt)
|
session.ReceiveTCPPacket(pkt)
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ const (
|
||||||
// See https://dev.mysql.com/doc/refman/5.7/en/identifiers.html
|
// See https://dev.mysql.com/doc/refman/5.7/en/identifiers.html
|
||||||
const (
|
const (
|
||||||
// MaxMysqlPacketLen is the max packet payload length.
|
// MaxMysqlPacketLen is the max packet payload length.
|
||||||
MaxMysqlPacketLen = 1<<24 - 1
|
MaxMysqlPacketLen = 4 * 1024 * 1024
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -8,8 +8,15 @@ type handshakeResponse41 struct {
|
||||||
Auth []byte
|
Auth []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// receiveRange record mysql package begin and end seq id
|
// jigsaw record tcp package begin and end seq id
|
||||||
type receiveRange struct {
|
type jigsaw struct {
|
||||||
beginSeqID int64
|
begin int64
|
||||||
endSeqID int64
|
end int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func newJigsaw(begin, end int64) (js *jigsaw) {
|
||||||
|
return &jigsaw{
|
||||||
|
begin: begin,
|
||||||
|
end: end,
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,15 @@
|
||||||
package mysql
|
package mysql
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"container/list"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/zr-hebo/sniffer-agent/communicator"
|
|
||||||
|
|
||||||
// "strings"
|
// "strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"github.com/pingcap/tidb/util/hack"
|
"github.com/pingcap/tidb/util/hack"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/zr-hebo/sniffer-agent/communicator"
|
||||||
"github.com/zr-hebo/sniffer-agent/model"
|
"github.com/zr-hebo/sniffer-agent/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,13 +22,11 @@ type MysqlSession struct {
|
||||||
serverIP *string
|
serverIP *string
|
||||||
serverPort int
|
serverPort int
|
||||||
stmtBeginTime int64
|
stmtBeginTime int64
|
||||||
packageOffset int64
|
// packageOffset int64
|
||||||
expectReceiveSize int
|
|
||||||
// coverRanges []*receiveRange
|
|
||||||
// coverRange *receiveRange
|
|
||||||
beginSeqID int64
|
beginSeqID int64
|
||||||
expectSeqID int64
|
endSeqID int64
|
||||||
|
coverRanges *list.List
|
||||||
|
expectReceiveSize int
|
||||||
expectSendSize int
|
expectSendSize int
|
||||||
prepareInfo *prepareInfo
|
prepareInfo *prepareInfo
|
||||||
cachedPrepareStmt map[int][]byte
|
cachedPrepareStmt map[int][]byte
|
||||||
|
@ -63,7 +61,7 @@ func NewMysqlSession(
|
||||||
queryPieceReceiver: receiver,
|
queryPieceReceiver: receiver,
|
||||||
closeConn: make(chan bool, 1),
|
closeConn: make(chan bool, 1),
|
||||||
expectReceiveSize: -1,
|
expectReceiveSize: -1,
|
||||||
expectSeqID: -1,
|
coverRanges: list.New(),
|
||||||
ignoreAckID: -1,
|
ignoreAckID: -1,
|
||||||
sendSize: 0,
|
sendSize: 0,
|
||||||
pkgCacheLock: sync.Mutex{},
|
pkgCacheLock: sync.Mutex{},
|
||||||
|
@ -97,6 +95,7 @@ func (ms *MysqlSession) ReceiveTCPPacket(newPkt *model.TCPPacket) {
|
||||||
ms.queryPieceReceiver <- qp
|
ms.queryPieceReceiver <- qp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *MysqlSession) resetBeginTime() {
|
func (ms *MysqlSession) resetBeginTime() {
|
||||||
|
@ -113,16 +112,39 @@ func (ms *MysqlSession) readFromServer(bytes []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *MysqlSession) oneMysqlPackageFinish() bool {
|
func mergeRanges(currRange *jigsaw, pkgRanges []*jigsaw) (mergedRange *jigsaw, newPkgRanges []*jigsaw) {
|
||||||
if int64(len(ms.cachedStmtBytes))%MaxMysqlPacketLen == 0 {
|
var nextRange *jigsaw
|
||||||
return true
|
newPkgRanges = make([]*jigsaw, 0, 4)
|
||||||
|
|
||||||
|
if len(pkgRanges) < 1 {
|
||||||
|
return currRange, newPkgRanges
|
||||||
|
|
||||||
|
} else if len(pkgRanges) == 1 {
|
||||||
|
nextRange = pkgRanges[0]
|
||||||
|
|
||||||
|
} else {
|
||||||
|
nextRange, newPkgRanges = mergeRanges(pkgRanges[0], pkgRanges[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
if currRange.end >= nextRange.begin {
|
||||||
|
mergedRange = &jigsaw{begin: currRange.begin, end: nextRange.end}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
tmpRanges := make([]*jigsaw, len(newPkgRanges)+1)
|
||||||
|
tmpRanges[0] = nextRange
|
||||||
|
if len(newPkgRanges) > 0 {
|
||||||
|
copy(tmpRanges[1:], newPkgRanges)
|
||||||
|
}
|
||||||
|
newPkgRanges = tmpRanges
|
||||||
|
mergedRange = currRange
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *MysqlSession) checkFinish() bool {
|
func (ms *MysqlSession) checkFinish() bool {
|
||||||
if ms.beginSeqID != -1 && ms.expectReceiveSize == 0 {
|
ms.mergeRange()
|
||||||
|
if ms.endSeqID - ms.beginSeqID == int64(len(ms.cachedStmtBytes)) && ms.expectReceiveSize == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,19 +157,24 @@ func (ms *MysqlSession) clear() {
|
||||||
ms.expectSendSize = -1
|
ms.expectSendSize = -1
|
||||||
ms.prepareInfo = nil
|
ms.prepareInfo = nil
|
||||||
ms.beginSeqID = -1
|
ms.beginSeqID = -1
|
||||||
ms.expectSeqID = -1
|
ms.endSeqID = -1
|
||||||
ms.ignoreAckID = -1
|
ms.ignoreAckID = -1
|
||||||
ms.sendSize = 0
|
ms.sendSize = 0
|
||||||
|
ms.coverRanges = list.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *MysqlSession) readFromClient(seqID int64, bytes []byte) {
|
func (ms *MysqlSession) readFromClient(seqID int64, bytes []byte) {
|
||||||
contentSize := int64(len(bytes))
|
contentSize := int64(len(bytes))
|
||||||
|
|
||||||
if ms.expectReceiveSize == -1 || ms.oneMysqlPackageFinish() {
|
if ms.expectReceiveSize == -1 {
|
||||||
ms.expectReceiveSize = extractMysqlPayloadSize(bytes[:4])
|
ms.expectReceiveSize = extractMysqlPayloadSize(bytes[:4])
|
||||||
// ms.packageOffset = int64(len(ms.cachedStmtBytes))
|
// ignore too big mysql packet
|
||||||
|
if ms.expectReceiveSize >= MaxMysqlPacketLen {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
contents := bytes[4:]
|
contents := bytes[4:]
|
||||||
|
// add prepare info
|
||||||
if contents[0] == ComStmtPrepare {
|
if contents[0] == ComStmtPrepare {
|
||||||
ms.prepareInfo = &prepareInfo{}
|
ms.prepareInfo = &prepareInfo{}
|
||||||
}
|
}
|
||||||
|
@ -155,18 +182,26 @@ func (ms *MysqlSession) readFromClient(seqID int64, bytes []byte) {
|
||||||
contentSize = int64(len(contents))
|
contentSize = int64(len(contents))
|
||||||
seqID += 4
|
seqID += 4
|
||||||
ms.beginSeqID = seqID
|
ms.beginSeqID = seqID
|
||||||
|
ms.endSeqID = seqID
|
||||||
|
|
||||||
newCache := make([]byte, ms.expectReceiveSize+len(ms.cachedStmtBytes))
|
// if len(ms.cachedStmtBytes) > 0 {
|
||||||
if len(ms.cachedStmtBytes) > 0 {
|
// copy(newCache[:len(ms.cachedStmtBytes)], ms.cachedStmtBytes)
|
||||||
copy(newCache[:len(ms.cachedStmtBytes)], ms.cachedStmtBytes)
|
// }
|
||||||
|
if int64(ms.expectReceiveSize) < int64(len(contents)) {
|
||||||
|
log.Warnf("receive invalid mysql packet")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if int64(ms.expectReceiveSize+len(ms.cachedStmtBytes)) >= ms.packageOffset+int64(len(contents)) {
|
newCache := make([]byte, ms.expectReceiveSize)
|
||||||
copy(newCache[ms.packageOffset:ms.packageOffset+int64(len(contents))], contents)
|
copy(newCache[:len(contents)], contents)
|
||||||
ms.cachedStmtBytes = newCache
|
ms.cachedStmtBytes = newCache
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// ignore too big mysql packet
|
||||||
|
if ms.expectReceiveSize >= MaxMysqlPacketLen {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if ms.beginSeqID == -1 {
|
if ms.beginSeqID == -1 {
|
||||||
log.Warnf("cover range is empty")
|
log.Warnf("cover range is empty")
|
||||||
return
|
return
|
||||||
|
@ -181,29 +216,65 @@ func (ms *MysqlSession) readFromClient(seqID int64, bytes []byte) {
|
||||||
} else if seqID + int64(len(bytes)) <= ms.beginSeqID {
|
} else if seqID + int64(len(bytes)) <= ms.beginSeqID {
|
||||||
// repeat packet
|
// repeat packet
|
||||||
log.Debugf("receive repeat packet")
|
log.Debugf("receive repeat packet")
|
||||||
return
|
|
||||||
|
|
||||||
} else if seqID > ms.expectSeqID {
|
|
||||||
// discontinuous packet
|
|
||||||
log.Debugf("receive discontinuous packet")
|
|
||||||
ms.clear()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
seqOffset := seqID - ms.beginSeqID + ms.packageOffset
|
seqOffset := seqID - ms.beginSeqID
|
||||||
if seqOffset+int64(len(bytes)) > int64(len(ms.cachedStmtBytes)) {
|
if seqOffset+contentSize > int64(len(ms.cachedStmtBytes)) {
|
||||||
// is not a normal mysql packet
|
// not in a normal mysql packet
|
||||||
log.Debugf("receive an unexpect packet")
|
log.Debugf("receive an unexpect packet")
|
||||||
ms.clear()
|
// ms.clear()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// add byte to stmt cache
|
// add byte to stmt cache
|
||||||
copy(ms.cachedStmtBytes[ms.packageOffset+seqOffset:ms.packageOffset+seqOffset+contentSize], bytes)
|
copy(ms.cachedStmtBytes[seqOffset:seqOffset+contentSize], bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ms.addRange(newJigsaw(seqID, seqID+contentSize))
|
||||||
ms.expectReceiveSize = ms.expectReceiveSize - int(contentSize)
|
ms.expectReceiveSize = ms.expectReceiveSize - int(contentSize)
|
||||||
ms.expectSeqID = seqID + contentSize
|
}
|
||||||
|
|
||||||
|
func (ms *MysqlSession) addRange(js *jigsaw) {
|
||||||
|
head := ms.coverRanges.Front()
|
||||||
|
// empty list
|
||||||
|
if head == nil {
|
||||||
|
ms.coverRanges.PushBack(js)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// find insert position
|
||||||
|
var node = head
|
||||||
|
for ; node != nil; node = node.Next() {
|
||||||
|
nodeVal := node.Value.(*jigsaw)
|
||||||
|
if nodeVal.begin > js.begin {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert element
|
||||||
|
if node != nil {
|
||||||
|
ms.coverRanges.InsertBefore(js, node)
|
||||||
|
} else {
|
||||||
|
ms.coverRanges.PushBack(js)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *MysqlSession) mergeRange() {
|
||||||
|
head := ms.coverRanges.Front()
|
||||||
|
// empty list
|
||||||
|
if head == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// find insert position
|
||||||
|
var node = head
|
||||||
|
|
||||||
|
for ; node != nil; node = node.Next() {
|
||||||
|
nodeVal := node.Value.(*jigsaw)
|
||||||
|
if nodeVal.begin <= ms.endSeqID && nodeVal.end > ms.endSeqID {
|
||||||
|
ms.endSeqID = nodeVal.end
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *MysqlSession) GenerateQueryPiece() (qp model.QueryPiece) {
|
func (ms *MysqlSession) GenerateQueryPiece() (qp model.QueryPiece) {
|
||||||
|
|
Loading…
Reference in New Issue