github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/client/internal/network/response.go (about)

     1  package network
     2  
     3  import (
     4  	"strconv"
     5  
     6  	"github.com/pkg/errors"
     7  
     8  	"github.com/Mrs4s/MiraiGo/binary"
     9  )
    10  
    11  type Response struct {
    12  	Type        RequestType
    13  	EncryptType EncryptType
    14  	SequenceID  int32
    15  	Uin         int64
    16  	CommandName string
    17  	Body        []byte
    18  
    19  	Message string
    20  
    21  	// Request is the original request that obtained this response.
    22  	// Request *Request
    23  }
    24  
    25  var (
    26  	ErrSessionExpired    = errors.New("session expired")
    27  	ErrPacketDropped     = errors.New("packet dropped")
    28  	ErrInvalidPacketType = errors.New("invalid packet type")
    29  )
    30  
    31  func (t *Transport) ReadResponse(head []byte) (*Response, error) {
    32  	resp := new(Response)
    33  	r := binary.NewReader(head)
    34  	resp.Type = RequestType(r.ReadInt32())
    35  	if resp.Type != RequestTypeLogin && resp.Type != RequestTypeSimple {
    36  		return resp, ErrInvalidPacketType
    37  	}
    38  	resp.EncryptType = EncryptType(r.ReadByte())
    39  	_ = r.ReadByte() // 0x00?
    40  
    41  	resp.Uin, _ = strconv.ParseInt(r.ReadString(), 10, 64)
    42  	body := r.ReadAvailable()
    43  	switch resp.EncryptType {
    44  	case EncryptTypeNoEncrypt:
    45  		// nothing to do
    46  	case EncryptTypeD2Key:
    47  		body = binary.NewTeaCipher(t.Sig.D2Key).Decrypt(body)
    48  	case EncryptTypeEmptyKey:
    49  		emptyKey := make([]byte, 16)
    50  		body = binary.NewTeaCipher(emptyKey).Decrypt(body)
    51  	}
    52  	err := t.readSSOFrame(resp, body)
    53  	return resp, err
    54  }
    55  
    56  func (t *Transport) readSSOFrame(resp *Response, payload []byte) error {
    57  	reader := binary.NewReader(payload)
    58  	headLen := reader.ReadInt32()
    59  	if headLen < 4 || headLen-4 > int32(reader.Len()) {
    60  		return errors.WithStack(ErrPacketDropped)
    61  	}
    62  
    63  	head := binary.NewReader(reader.ReadBytes(int(headLen) - 4))
    64  	resp.SequenceID = head.ReadInt32()
    65  	switch retCode := head.ReadInt32(); retCode {
    66  	case 0:
    67  		// ok
    68  	case -10008:
    69  		return errors.WithStack(ErrSessionExpired)
    70  	default:
    71  		return errors.Errorf("return code unsuccessful: %d", retCode)
    72  	}
    73  	resp.Message = head.ReadString()
    74  	resp.CommandName = head.ReadString()
    75  	if resp.CommandName == "Heartbeat.Alive" {
    76  		return nil
    77  	}
    78  	_ = head.ReadInt32Bytes() // session id
    79  	compressedFlag := head.ReadInt32()
    80  
    81  	bodyLen := reader.ReadInt32() - 4
    82  	body := reader.ReadAvailable()
    83  	if bodyLen > 0 && bodyLen < int32(len(body)) {
    84  		body = body[:bodyLen]
    85  	}
    86  	switch compressedFlag {
    87  	case 0, 8:
    88  	case 1:
    89  		body = binary.ZlibUncompress(body)
    90  	}
    91  	resp.Body = body
    92  	return nil
    93  }