github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/debug-tools/binlog-event-blackhole/packet.go (about)

     1  // Copyright 2019 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package main
    15  
    16  import (
    17  	"encoding/binary"
    18  	"io"
    19  	"os"
    20  )
    21  
    22  // registerSlaveCommand generates a COM_REGISTER_SLAVE command (with uninitialized header).
    23  // ref https://dev.mysql.com/doc/internals/en/com-register-slave.html.
    24  func registerSlaveCommand(username, password string, serverID uint32) []byte {
    25  	hn, _ := os.Hostname()
    26  
    27  	packet := make([]byte, 4+1+4+1+len(hn)+1+len(username)+1+len(password)+2+4+4)
    28  	offset := 4 // 4 bytes header
    29  
    30  	packet[offset] = 0x15 // COM_REGISTER_SLAVE
    31  	offset++
    32  
    33  	binary.LittleEndian.PutUint32(packet[offset:], serverID)
    34  	offset += 4
    35  
    36  	packet[offset] = uint8(len(hn))
    37  	offset++
    38  	n := copy(packet[offset:], hn)
    39  	offset += n
    40  
    41  	packet[offset] = uint8(len(username))
    42  	offset++
    43  	n = copy(packet[offset:], username)
    44  	offset += n
    45  
    46  	packet[offset] = uint8(len(password))
    47  	offset++
    48  	n = copy(packet[offset:], password)
    49  	offset += n
    50  
    51  	binary.LittleEndian.PutUint16(packet[offset:], 0)
    52  	offset += 2
    53  
    54  	binary.LittleEndian.PutUint32(packet[offset:], 0)
    55  	offset += 4
    56  
    57  	binary.LittleEndian.PutUint32(packet[offset:], 0)
    58  
    59  	setCommandHeader(packet, 0)
    60  
    61  	return packet
    62  }
    63  
    64  // dumpCommand generates a COM_BINLOG_DUMP command.
    65  // ref https://dev.mysql.com/doc/internals/en/com-binlog-dump.html.
    66  func dumpCommand(serverID uint32, name string, pos uint32) []byte {
    67  	packet := make([]byte, 4+1+4+2+4+len(name))
    68  	offset := 4 // 4 bytes header
    69  
    70  	packet[offset] = 0x12 // COM_BINLOG_DUMP
    71  	offset++
    72  
    73  	binary.LittleEndian.PutUint32(packet[offset:], pos)
    74  	offset += 4
    75  
    76  	binary.LittleEndian.PutUint16(packet[offset:], 0x00) // BINLOG_DUMP_NEVER_STOP
    77  	offset += 2
    78  
    79  	binary.LittleEndian.PutUint32(packet[offset:], serverID)
    80  	offset += 4
    81  
    82  	copy(packet[offset:], name)
    83  
    84  	setCommandHeader(packet, 0)
    85  
    86  	return packet
    87  }
    88  
    89  // setCommandHeader set the header of the command inplace.
    90  // ref https://dev.mysql.com/doc/internals/en/mysql-packet.html.
    91  func setCommandHeader(packet []byte, seqID uint8) {
    92  	// do not handle a payload which is larger than or equal to 2^24−1 bytes (16 MB) now.
    93  	length := len(packet) - 4
    94  	packet[0] = byte(length)
    95  	packet[1] = byte(length >> 8)
    96  	packet[2] = byte(length >> 16)
    97  
    98  	packet[3] = seqID
    99  }
   100  
   101  // readPacket tries to read a MySQL packet (header & payload) from the Reader.
   102  func readPacket(r io.Reader) ([]byte, []byte, error) {
   103  	header := []byte{0, 0, 0, 0}
   104  	_, err := io.ReadFull(r, header)
   105  	if err != nil {
   106  		return nil, nil, err
   107  	}
   108  
   109  	length := int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16)
   110  	payload := make([]byte, length)
   111  	_, err = io.ReadFull(r, payload)
   112  	if err != nil {
   113  		return nil, nil, err
   114  	}
   115  
   116  	return header, payload, nil
   117  }