mirror of https://github.com/40t/go-sniffer.git
Merge 0313eb2dff
into a50ccb4caa
This commit is contained in:
commit
6d9b72393f
|
@ -2,13 +2,14 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/google/gopacket/pcap"
|
|
||||||
"log"
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/google/gopacket/pcap"
|
||||||
"github.com/google/gopacket/tcpassembly"
|
"github.com/google/gopacket/tcpassembly"
|
||||||
"github.com/google/gopacket/tcpassembly/tcpreader"
|
"github.com/google/gopacket/tcpassembly/tcpreader"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Dispatch struct {
|
type Dispatch struct {
|
||||||
|
@ -41,7 +42,7 @@ func (d *Dispatch) Capture() {
|
||||||
|
|
||||||
// Capture
|
// Capture
|
||||||
src := gopacket.NewPacketSource(handle, handle.LinkType())
|
src := gopacket.NewPacketSource(handle, handle.LinkType())
|
||||||
packets := src.Packets()
|
packets := src.Packets() // get packet chan
|
||||||
|
|
||||||
// Set up assembly
|
// Set up assembly
|
||||||
streamFactory := &ProtocolStreamFactory{
|
streamFactory := &ProtocolStreamFactory{
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -19,6 +19,27 @@ const (
|
||||||
CreateTopicsReqKind = 19
|
CreateTopicsReqKind = 19
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ()
|
||||||
|
|
||||||
|
var RquestNameMap = map[int16]string{
|
||||||
|
0: "ProduceRequest",
|
||||||
|
1: "FetchRequest",
|
||||||
|
2: "OffsetRequest",
|
||||||
|
3: "MetadataRequest",
|
||||||
|
//Non-user facing control APIs = 4-7
|
||||||
|
8: "OffsetCommitRequest",
|
||||||
|
9: "OffsetFetchRequest",
|
||||||
|
10: "GroupCoordinatorRequest",
|
||||||
|
11: "JoinGroupRequest",
|
||||||
|
12: "HeartbeatRequest",
|
||||||
|
13: "LeaveGroupRequest",
|
||||||
|
14: "SyncGroupRequest",
|
||||||
|
15: "DescribeGroupsRequest",
|
||||||
|
16: "ListGroupsRequest",
|
||||||
|
18: "APIVersionsReqKind",
|
||||||
|
19: "CreateTopicsReqKind",
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ApiV0 = 0
|
ApiV0 = 0
|
||||||
ApiV1 = 1
|
ApiV1 = 1
|
||||||
|
|
|
@ -2,11 +2,13 @@ package build
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/google/gopacket"
|
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/google/gopacket"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -23,10 +25,10 @@ type Kafka struct {
|
||||||
|
|
||||||
type stream struct {
|
type stream struct {
|
||||||
packets chan *packet
|
packets chan *packet
|
||||||
|
correlationMap map[int32]requestHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
type packet struct {
|
type packet struct {
|
||||||
|
|
||||||
isClientFlow bool //客户端->服务器端流
|
isClientFlow bool //客户端->服务器端流
|
||||||
messageSize int32
|
messageSize int32
|
||||||
|
|
||||||
|
@ -51,9 +53,10 @@ type messageSet struct {
|
||||||
offset int64
|
offset int64
|
||||||
messageSize int32
|
messageSize int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMessageSet(r io.Reader) messageSet {
|
func newMessageSet(r io.Reader) messageSet {
|
||||||
messageSet := messageSet{}
|
messageSet := messageSet{}
|
||||||
messageSet.offset = ReadInt64(r)
|
_, messageSet.offset = ReadInt64(r)
|
||||||
messageSet.messageSize = ReadInt32(r)
|
messageSet.messageSize = ReadInt32(r)
|
||||||
|
|
||||||
return messageSet
|
return messageSet
|
||||||
|
@ -69,6 +72,7 @@ type message struct {
|
||||||
|
|
||||||
var kafkaInstance *Kafka
|
var kafkaInstance *Kafka
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
|
|
||||||
func NewInstance() *Kafka {
|
func NewInstance() *Kafka {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
kafkaInstance = &Kafka{
|
kafkaInstance = &Kafka{
|
||||||
|
@ -94,7 +98,7 @@ func (m *Kafka) SetFlag(flg []string) {
|
||||||
|
|
||||||
switch key {
|
switch key {
|
||||||
case CmdPort:
|
case CmdPort:
|
||||||
p, err := strconv.Atoi(val);
|
p, err := strconv.Atoi(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("端口数不正确")
|
panic("端口数不正确")
|
||||||
}
|
}
|
||||||
|
@ -110,7 +114,7 @@ func (m *Kafka) SetFlag(flg []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Kafka) BPFFilter() string {
|
func (m *Kafka) BPFFilter() string {
|
||||||
return "tcp and port "+strconv.Itoa(m.port);
|
return "tcp and port " + strconv.Itoa(m.port)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Kafka) Version() string {
|
func (m *Kafka) Version() string {
|
||||||
|
@ -127,6 +131,7 @@ func (m *Kafka) ResolveStream(net, transport gopacket.Flow, buf io.Reader) {
|
||||||
|
|
||||||
var newStream = stream{
|
var newStream = stream{
|
||||||
packets: make(chan *packet, 100),
|
packets: make(chan *packet, 100),
|
||||||
|
correlationMap: make(map[int32]requestHeader),
|
||||||
}
|
}
|
||||||
|
|
||||||
m.source[uuid] = &newStream
|
m.source[uuid] = &newStream
|
||||||
|
@ -139,7 +144,7 @@ func (m *Kafka) ResolveStream(net, transport gopacket.Flow, buf io.Reader) {
|
||||||
|
|
||||||
newPacket := m.newPacket(net, transport, buf)
|
newPacket := m.newPacket(net, transport, buf)
|
||||||
if newPacket == nil {
|
if newPacket == nil {
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
m.source[uuid].packets <- newPacket
|
m.source[uuid].packets <- newPacket
|
||||||
|
@ -151,8 +156,22 @@ func (m *Kafka) newPacket(net, transport gopacket.Flow, r io.Reader) *packet {
|
||||||
//read packet
|
//read packet
|
||||||
pk := packet{}
|
pk := packet{}
|
||||||
|
|
||||||
|
/*
|
||||||
|
bs := make([]byte, 0)
|
||||||
|
count, err := r.Read(bs)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("read: %d, buffer: %b", count, bs)
|
||||||
|
return nil
|
||||||
|
*/
|
||||||
|
|
||||||
//read messageSize
|
//read messageSize
|
||||||
pk.messageSize = ReadInt32(r)
|
pk.messageSize = ReadInt32(r)
|
||||||
|
if pk.messageSize == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fmt.Printf("pk.messageSize: %d\n", pk.messageSize)
|
||||||
|
|
||||||
//set flow direction
|
//set flow direction
|
||||||
if transport.Src().String() == strconv.Itoa(m.port) {
|
if transport.Src().String() == strconv.Itoa(m.port) {
|
||||||
|
@ -160,6 +179,7 @@ func (m *Kafka) newPacket(net, transport gopacket.Flow, r io.Reader) *packet {
|
||||||
|
|
||||||
respHeader := responseHeader{}
|
respHeader := responseHeader{}
|
||||||
respHeader.correlationId = ReadInt32(r)
|
respHeader.correlationId = ReadInt32(r)
|
||||||
|
// TODO extract request
|
||||||
pk.responseHeader = respHeader
|
pk.responseHeader = respHeader
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
@ -204,29 +224,68 @@ func (stm *stream) resolve() {
|
||||||
select {
|
select {
|
||||||
case packet := <-stm.packets:
|
case packet := <-stm.packets:
|
||||||
if packet.isClientFlow {
|
if packet.isClientFlow {
|
||||||
|
stm.correlationMap[packet.requestHeader.correlationId] = packet.requestHeader
|
||||||
stm.resolveClientPacket(packet)
|
stm.resolveClientPacket(packet)
|
||||||
} else {
|
} else {
|
||||||
stm.resolveServerPacket(packet)
|
if _, ok := stm.correlationMap[packet.responseHeader.correlationId]; ok {
|
||||||
|
stm.resolveServerPacket(packet, stm.correlationMap[packet.responseHeader.correlationId])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stm *stream) resolveServerPacket(pk *packet) {
|
func (stm *stream) resolveServerPacket(pk *packet, rh requestHeader) {
|
||||||
return
|
var msg interface{}
|
||||||
|
payload := pk.payload
|
||||||
|
|
||||||
|
action := Action{
|
||||||
|
Request: GetRquestName(pk.apiKey),
|
||||||
|
Direction: "isServer",
|
||||||
|
ApiVersion: pk.apiVersion,
|
||||||
|
}
|
||||||
|
switch int(rh.apiKey) {
|
||||||
|
case ProduceRequest:
|
||||||
|
msg = ReadProduceResponse(payload, rh.apiVersion)
|
||||||
|
case MetadataRequest:
|
||||||
|
msg = ReadMetadataResponse(payload, rh.apiVersion)
|
||||||
|
default:
|
||||||
|
fmt.Printf("response ApiKey:%d TODO", rh.apiKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg != nil {
|
||||||
|
action.Message = msg
|
||||||
|
}
|
||||||
|
bs, err := json.Marshal(action)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("json marshal action failed, err: %+v\n", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", string(bs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stm *stream) resolveClientPacket(pk *packet) {
|
func (stm *stream) resolveClientPacket(pk *packet) {
|
||||||
var msg string
|
var msg interface{}
|
||||||
|
action := Action{
|
||||||
|
Request: GetRquestName(pk.apiKey),
|
||||||
|
Direction: "isClient",
|
||||||
|
ApiVersion: pk.apiVersion,
|
||||||
|
}
|
||||||
payload := pk.payload
|
payload := pk.payload
|
||||||
|
|
||||||
fmt.Println("apiKey:")
|
|
||||||
fmt.Println(pk.apiKey)
|
|
||||||
|
|
||||||
switch int(pk.apiKey) {
|
switch int(pk.apiKey) {
|
||||||
case ProduceRequest:
|
case ProduceRequest:
|
||||||
msg = ReadProduceRequest(payload, pk.apiVersion)
|
msg = ReadProduceRequest(payload, pk.apiVersion)
|
||||||
|
case MetadataRequest:
|
||||||
|
msg = ReadMetadataRequest(payload, pk.apiVersion)
|
||||||
|
default:
|
||||||
|
fmt.Printf("ApiKey:%d TODO", pk.apiKey)
|
||||||
}
|
}
|
||||||
_=msg
|
|
||||||
//fmt.Println(msg)
|
if msg != nil {
|
||||||
|
action.Message = msg
|
||||||
|
}
|
||||||
|
bs, err := json.Marshal(action)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("json marshal action failed, err: %+v\n", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", string(bs))
|
||||||
}
|
}
|
|
@ -6,12 +6,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
Key []byte
|
Key []byte
|
||||||
Value []byte
|
Value []byte
|
||||||
Offset int64
|
Offset int64
|
||||||
Crc uint32
|
Crc uint32
|
||||||
|
Magic byte
|
||||||
|
CompressCode byte
|
||||||
Topic string
|
Topic string
|
||||||
Partition int32
|
Partition int32
|
||||||
TipOffset int64
|
TipOffset int64
|
||||||
|
@ -44,9 +45,8 @@ type ProduceReqPartition struct {
|
||||||
Messages []*Message
|
Messages []*Message
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadProduceRequest(r io.Reader, version int16) string {
|
func ReadProduceRequest(r io.Reader, version int16) *ProduceReq {
|
||||||
|
// version == 1
|
||||||
var msg string
|
|
||||||
|
|
||||||
produceReq := ProduceReq{}
|
produceReq := ProduceReq{}
|
||||||
|
|
||||||
|
@ -59,21 +59,157 @@ func ReadProduceRequest(r io.Reader, version int16) string {
|
||||||
produceReq.Timeout = time.Duration(ReadInt32(r)) * time.Millisecond
|
produceReq.Timeout = time.Duration(ReadInt32(r)) * time.Millisecond
|
||||||
|
|
||||||
l := ReadInt32(r)
|
l := ReadInt32(r)
|
||||||
req := ProduceReq{}
|
produceReq.Topics = make([]ProduceReqTopic, l)
|
||||||
req.Topics = make([]ProduceReqTopic, l)
|
|
||||||
|
|
||||||
for ti := range req.Topics {
|
for ti := range produceReq.Topics {
|
||||||
var topic = &req.Topics[ti]
|
var topic = &produceReq.Topics[ti]
|
||||||
topic.Name, _ = ReadString(r)
|
topic.Name, _ = ReadString(r)
|
||||||
fmt.Println("msg")
|
|
||||||
fmt.Println(topic.Name)
|
|
||||||
|
|
||||||
l := ReadInt32(r)
|
l := ReadInt32(r)
|
||||||
topic.Partitions = make([]ProduceReqPartition, l)
|
topic.Partitions = make([]ProduceReqPartition, l)
|
||||||
|
|
||||||
|
for idx := 0; idx < int(l); idx++ {
|
||||||
|
topic.Partitions[idx].ID = ReadInt32(r)
|
||||||
|
_ = ReadInt32(r) // partitions size
|
||||||
|
topic.Partitions[idx].Messages = ReadMessages(r, version)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg
|
return &produceReq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProduceRspPartitions struct {
|
||||||
|
PartitionID int32
|
||||||
|
Error int16
|
||||||
|
Offset int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProduceRspTopic struct {
|
||||||
|
TopicName string
|
||||||
|
Partitions []ProduceRspPartitions
|
||||||
|
ThrottleTime int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProduceRsp struct {
|
||||||
|
Topics []ProduceRspTopic
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadProduceResponse(r io.Reader, version int16) *ProduceRsp {
|
||||||
|
// version == 1
|
||||||
|
produceRsp := ProduceRsp{}
|
||||||
|
l := ReadInt32(r)
|
||||||
|
produceRsp.Topics = make([]ProduceRspTopic, 0)
|
||||||
|
for i := 0; i < int(l); i++ {
|
||||||
|
topic := ProduceRspTopic{}
|
||||||
|
topic.TopicName, _ = ReadString(r)
|
||||||
|
pl := ReadInt32(r)
|
||||||
|
topic.Partitions = make([]ProduceRspPartitions, 0)
|
||||||
|
for j := 0; j < int(pl); j++ {
|
||||||
|
pt := ProduceRspPartitions{}
|
||||||
|
pt.PartitionID = ReadInt32(r)
|
||||||
|
pt.Error = ReadInt16(r)
|
||||||
|
_, pt.Offset = ReadInt64(r)
|
||||||
|
topic.Partitions = append(topic.Partitions, pt)
|
||||||
|
}
|
||||||
|
produceRsp.Topics = append(produceRsp.Topics, topic)
|
||||||
|
}
|
||||||
|
return &produceRsp
|
||||||
|
}
|
||||||
|
|
||||||
|
type MetadataReq struct {
|
||||||
|
TopicNames []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadMetadataRequest(r io.Reader, version int16) *MetadataReq {
|
||||||
|
// version == 0
|
||||||
|
metadataReq := MetadataReq{}
|
||||||
|
|
||||||
|
l := ReadInt32(r)
|
||||||
|
for i := 0; i < int(l); i++ {
|
||||||
|
topicName, _ := ReadString(r)
|
||||||
|
metadataReq.TopicNames = append(metadataReq.TopicNames, topicName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &metadataReq
|
||||||
|
}
|
||||||
|
|
||||||
|
type Broker struct {
|
||||||
|
NodeID int32
|
||||||
|
Host string
|
||||||
|
Port int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type PartitionMetada struct {
|
||||||
|
ErrorCode int16
|
||||||
|
PartitionIndex int32
|
||||||
|
LeaderID int32
|
||||||
|
ReplicaNodes []int32
|
||||||
|
IsrNodes []int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type TopicMetadata struct {
|
||||||
|
ErrorCode int16
|
||||||
|
Name string
|
||||||
|
Partitions []PartitionMetada
|
||||||
|
}
|
||||||
|
|
||||||
|
type MetadataRsp struct {
|
||||||
|
Brokers []Broker
|
||||||
|
Topics []TopicMetadata
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadMetadataResponse(r io.Reader, version int16) *MetadataRsp {
|
||||||
|
// version == 0
|
||||||
|
metadataRsp := MetadataRsp{}
|
||||||
|
|
||||||
|
// read brokers
|
||||||
|
metadataRsp.Brokers = make([]Broker, 0)
|
||||||
|
l := ReadInt32(r)
|
||||||
|
for i := 0; i < int(l); i++ {
|
||||||
|
broker := Broker{}
|
||||||
|
broker.NodeID = ReadInt32(r)
|
||||||
|
broker.Host, _ = ReadString(r)
|
||||||
|
broker.Port = ReadInt32(r)
|
||||||
|
metadataRsp.Brokers = append(metadataRsp.Brokers, broker)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read topics
|
||||||
|
metadataRsp.Topics = make([]TopicMetadata, 0)
|
||||||
|
l = ReadInt32(r)
|
||||||
|
for i := 0; i < int(l); i++ {
|
||||||
|
topicMetadata := TopicMetadata{}
|
||||||
|
topicMetadata.ErrorCode = ReadInt16(r)
|
||||||
|
topicMetadata.Name, _ = ReadString(r)
|
||||||
|
pl := ReadInt32(r)
|
||||||
|
topicMetadata.Partitions = make([]PartitionMetada, 0)
|
||||||
|
for j := 0; j < int(pl); j++ {
|
||||||
|
pm := PartitionMetada{}
|
||||||
|
pm.ErrorCode = ReadInt16(r)
|
||||||
|
pm.PartitionIndex = ReadInt32(r)
|
||||||
|
pm.LeaderID = ReadInt32(r)
|
||||||
|
|
||||||
|
pm.ReplicaNodes = make([]int32, 0)
|
||||||
|
replicaLen := ReadInt32(r)
|
||||||
|
for ri := 0; ri < int(replicaLen); ri++ {
|
||||||
|
pm.ReplicaNodes = append(pm.ReplicaNodes, ReadInt32(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
pm.IsrNodes = make([]int32, 0)
|
||||||
|
isrLen := ReadInt32(r)
|
||||||
|
for ri := 0; ri < int(isrLen); ri++ {
|
||||||
|
pm.IsrNodes = append(pm.IsrNodes, ReadInt32(r))
|
||||||
|
}
|
||||||
|
topicMetadata.Partitions = append(topicMetadata.Partitions, pm)
|
||||||
|
}
|
||||||
|
metadataRsp.Topics = append(metadataRsp.Topics, topicMetadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &metadataRsp
|
||||||
|
}
|
||||||
|
|
||||||
|
type Action struct {
|
||||||
|
Request string
|
||||||
|
Direction string
|
||||||
|
ApiVersion int16
|
||||||
|
Message interface{}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ package build
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,6 +33,11 @@ func ReadOnce() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReadByte(r io.Reader) (n byte) {
|
||||||
|
binary.Read(r, binary.BigEndian, &n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func ReadInt16(r io.Reader) (n int16) {
|
func ReadInt16(r io.Reader) (n int16) {
|
||||||
binary.Read(r, binary.BigEndian, &n)
|
binary.Read(r, binary.BigEndian, &n)
|
||||||
return
|
return
|
||||||
|
@ -41,11 +48,16 @@ func ReadInt32(r io.Reader) (n int32) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadInt64(r io.Reader) (n int64) {
|
func ReadUint32(r io.Reader) (n uint32) {
|
||||||
binary.Read(r, binary.BigEndian, &n)
|
binary.Read(r, binary.BigEndian, &n)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReadInt64(r io.Reader) (err error, n int64) {
|
||||||
|
err = binary.Read(r, binary.BigEndian, &n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func ReadString(r io.Reader) (string, int) {
|
func ReadString(r io.Reader) (string, int) {
|
||||||
|
|
||||||
l := int(ReadInt16(r))
|
l := int(ReadInt16(r))
|
||||||
|
@ -62,6 +74,7 @@ func ReadString(r io.Reader) (string, int) {
|
||||||
|
|
||||||
return string(str), l
|
return string(str), l
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//func TryReadInt16(r io.Reader) (n int16, err error) {
|
//func TryReadInt16(r io.Reader) (n int16, err error) {
|
||||||
//
|
//
|
||||||
|
@ -76,19 +89,70 @@ func ReadString(r io.Reader) (string, int) {
|
||||||
func ReadBytes(r io.Reader) []byte {
|
func ReadBytes(r io.Reader) []byte {
|
||||||
|
|
||||||
l := int(ReadInt32(r))
|
l := int(ReadInt32(r))
|
||||||
|
result := make([]byte, 0)
|
||||||
|
|
||||||
|
if l <= 0 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
var result []byte
|
|
||||||
var b = make([]byte, l)
|
var b = make([]byte, l)
|
||||||
for i := 0; i < l; i++ {
|
for i := 0; i < l; i++ {
|
||||||
|
|
||||||
_, err := r.Read(b)
|
_, err := r.Read(b)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result = append(result, b[0])
|
result = append(result, b...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReadMessages(r io.Reader, version int16) []*Message {
|
||||||
|
switch version {
|
||||||
|
case 0:
|
||||||
|
return ReadMessagesV1(r)
|
||||||
|
case 1:
|
||||||
|
return ReadMessagesV1(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return make([]*Message, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadMessagesV1(r io.Reader) []*Message {
|
||||||
|
var err error
|
||||||
|
messages := make([]*Message, 0)
|
||||||
|
for {
|
||||||
|
message := Message{}
|
||||||
|
err, message.Offset = ReadInt64(r)
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != io.ErrUnexpectedEOF {
|
||||||
|
fmt.Printf("read message offset , err: %+v\n", err)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ = ReadInt32(r) // message size
|
||||||
|
message.Crc = ReadUint32(r)
|
||||||
|
message.Magic = ReadByte(r)
|
||||||
|
message.CompressCode = ReadByte(r)
|
||||||
|
message.Key = ReadBytes(r)
|
||||||
|
message.Value = ReadBytes(r)
|
||||||
|
messages = append(messages, &message)
|
||||||
|
}
|
||||||
|
return messages
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRquestName(apiKey int16) string {
|
||||||
|
if name, ok := RquestNameMap[apiKey]; ok {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return strconv.Itoa(int(apiKey))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue