mirror of
https://github.com/yv1ing/rdp_channel.git
synced 2025-09-16 14:59:08 +08:00
完成TPKT、X224、FastPath协议基本封装和测试
This commit is contained in:
230
protocol/fastpath.go
Normal file
230
protocol/fastpath.go
Normal file
@@ -0,0 +1,230 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
/*
|
||||
定义协议相关的常量值
|
||||
*/
|
||||
|
||||
// FASTPATH_UPDATE_HEADER
|
||||
// UpdateHeader(1 byte)
|
||||
// updateCode(4 bits) | fragmentation(2 bits) | compression(2 bits)
|
||||
// 参考:https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/a1c4caa8-00ed-45bb-a06e-5177473766d3
|
||||
const FASTPATH_UPDATE_HEADER uint8 = 0b00010000
|
||||
|
||||
/*
|
||||
FastPath PDU定义
|
||||
参考:https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/0ae3c114-1439-4465-8d3f-6585227eff7d
|
||||
*/
|
||||
|
||||
type FastPathPDU struct {
|
||||
UpdateHeader uint8
|
||||
CompressionFlags uint8
|
||||
Size uint16
|
||||
Payload BitmapUpdateData
|
||||
}
|
||||
|
||||
/*
|
||||
Bitmap Data 定义
|
||||
参考:https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/d681bb11-f3b5-4add-b092-19fe7075f9e3
|
||||
https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/84a3d4d2-5523-4e49-9a48-33952c559485
|
||||
*/
|
||||
|
||||
type BitmapUpdateData struct {
|
||||
UpdateType uint16
|
||||
NumberRectangles uint16
|
||||
Payload BitmapData
|
||||
}
|
||||
|
||||
type BitmapData struct {
|
||||
DestLeft uint16
|
||||
DestTop uint16
|
||||
DestRight uint16
|
||||
DestBottom uint16
|
||||
Width uint16
|
||||
Height uint16
|
||||
BitsPerPixel uint16
|
||||
Flags uint16
|
||||
BitmapLength uint16
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
/*
|
||||
FastPath协议封装
|
||||
*/
|
||||
|
||||
type FastPath struct {
|
||||
transport *TPKT
|
||||
}
|
||||
|
||||
func NewFastPath(conn io.ReadWriter) *FastPath {
|
||||
return &FastPath{transport: NewTPKT(conn)}
|
||||
}
|
||||
|
||||
/*
|
||||
FastPath封包
|
||||
*/
|
||||
|
||||
func (f *FastPath) Write(payload []byte) error {
|
||||
payloadLen := len(payload)
|
||||
|
||||
// 构造BitmapData
|
||||
bitmapData := BitmapData{
|
||||
DestLeft: 0x0000,
|
||||
DestTop: 0x0000,
|
||||
DestRight: 0x000f, // 15 = 0 + 16 -1
|
||||
DestBottom: 0x000f, // 15
|
||||
Width: 0x0010, // 16
|
||||
Height: 0x0010, // 16
|
||||
BitsPerPixel: 0x0010, // 16位每像素
|
||||
Flags: 0x0000, // 无压缩
|
||||
BitmapLength: uint16(payloadLen),
|
||||
Payload: payload,
|
||||
}
|
||||
|
||||
// 序列化BitmapData
|
||||
var bitmapDataBuff bytes.Buffer
|
||||
binary.Write(&bitmapDataBuff, binary.LittleEndian, bitmapData.DestLeft)
|
||||
binary.Write(&bitmapDataBuff, binary.LittleEndian, bitmapData.DestTop)
|
||||
binary.Write(&bitmapDataBuff, binary.LittleEndian, bitmapData.DestRight)
|
||||
binary.Write(&bitmapDataBuff, binary.LittleEndian, bitmapData.DestBottom)
|
||||
binary.Write(&bitmapDataBuff, binary.LittleEndian, bitmapData.Width)
|
||||
binary.Write(&bitmapDataBuff, binary.LittleEndian, bitmapData.Height)
|
||||
binary.Write(&bitmapDataBuff, binary.LittleEndian, bitmapData.BitsPerPixel)
|
||||
binary.Write(&bitmapDataBuff, binary.LittleEndian, bitmapData.Flags)
|
||||
binary.Write(&bitmapDataBuff, binary.LittleEndian, bitmapData.BitmapLength)
|
||||
bitmapDataBuff.Write(bitmapData.Payload)
|
||||
|
||||
// 构造BitmapUpdateData
|
||||
bitmapUpdateData := BitmapUpdateData{
|
||||
UpdateType: 0x0001,
|
||||
NumberRectangles: 0x0001,
|
||||
Payload: bitmapData,
|
||||
}
|
||||
|
||||
// 序列化BitmapUpdateData
|
||||
var updateDataBuff bytes.Buffer
|
||||
binary.Write(&updateDataBuff, binary.LittleEndian, bitmapUpdateData.UpdateType)
|
||||
binary.Write(&updateDataBuff, binary.LittleEndian, bitmapUpdateData.NumberRectangles)
|
||||
updateDataBuff.Write(bitmapDataBuff.Bytes())
|
||||
|
||||
updateDataBytes := updateDataBuff.Bytes()
|
||||
updateDataLength := len(updateDataBytes)
|
||||
|
||||
// 构造FastPathPDU
|
||||
var fastPathPDUBuff bytes.Buffer
|
||||
fastPathPDUBuff.WriteByte(FASTPATH_UPDATE_HEADER)
|
||||
fastPathPDUBuff.WriteByte(0x00)
|
||||
|
||||
size := uint16(updateDataLength)
|
||||
if size <= 0x7F {
|
||||
fastPathPDUBuff.WriteByte(byte(size))
|
||||
} else {
|
||||
fastPathPDUBuff.WriteByte(byte((size >> 8) | 0x80))
|
||||
fastPathPDUBuff.WriteByte(byte(size & 0xFF))
|
||||
}
|
||||
|
||||
fastPathPDUBuff.Write(updateDataBytes)
|
||||
return f.transport.Write(fastPathPDUBuff.Bytes())
|
||||
}
|
||||
|
||||
/*
|
||||
FastParh解包
|
||||
*/
|
||||
|
||||
func (f *FastPath) Read() (payload []byte, err error) {
|
||||
packet, err := f.transport.Read()
|
||||
if err != nil {
|
||||
return nil, errors.New("[FASTPATH] read packet error: " + err.Error())
|
||||
}
|
||||
|
||||
reader := bytes.NewReader(packet)
|
||||
|
||||
// 解析FastPathPDU
|
||||
fastPathPDU := FastPathPDU{}
|
||||
|
||||
fastPathPDU.UpdateHeader, err = reader.ReadByte()
|
||||
if err != nil {
|
||||
return nil, errors.New("[FASTPATH] read fastpathpdu's update header error: " + err.Error())
|
||||
}
|
||||
|
||||
fastPathPDU.CompressionFlags, err = reader.ReadByte()
|
||||
if err != nil {
|
||||
return nil, errors.New("[FASTPATH] read fastpathpdu's compression flags error: " + err.Error())
|
||||
}
|
||||
|
||||
// 解析Size字段
|
||||
lengthByte, err := reader.ReadByte()
|
||||
if err != nil {
|
||||
return nil, errors.New("[FASTPATH] read fastpathpdu's size first byte error: " + err.Error())
|
||||
}
|
||||
|
||||
var size uint16
|
||||
if (lengthByte & 0x80) != 0 {
|
||||
lengthByte2, err := reader.ReadByte()
|
||||
if err != nil {
|
||||
return nil, errors.New("[FASTPATH] read fastpathpdu's size second byte error: " + err.Error())
|
||||
}
|
||||
size = (uint16(lengthByte&0x7F) << 8) | uint16(lengthByte2)
|
||||
} else {
|
||||
size = uint16(lengthByte)
|
||||
}
|
||||
|
||||
fastPathPDU.Size = size
|
||||
|
||||
// 提取FastPathPDU的Payload
|
||||
fastPathPDUPayload := make([]byte, fastPathPDU.Size)
|
||||
n, err := reader.Read(fastPathPDUPayload)
|
||||
if err != nil || n != int(size) {
|
||||
return nil, errors.New("[FASTPATH] read fastpathpdu's payload error: " + err.Error())
|
||||
}
|
||||
|
||||
// 解析BitmapUpdateData
|
||||
updateReader := bytes.NewReader(fastPathPDUPayload)
|
||||
var updateType uint16
|
||||
if err := binary.Read(updateReader, binary.LittleEndian, &updateType); err != nil {
|
||||
return nil, errors.New("[FASTPATH] read bitmapupdatedata's update type error: " + err.Error())
|
||||
}
|
||||
|
||||
var numRects uint16
|
||||
if err := binary.Read(updateReader, binary.LittleEndian, &numRects); err != nil {
|
||||
return nil, errors.New("[FASTPATH] read bitmapupdatedata's number rectangles error: " + err.Error())
|
||||
}
|
||||
|
||||
// 解析BitmapData
|
||||
var bitmapData BitmapData
|
||||
fields := []interface{}{
|
||||
&bitmapData.DestLeft,
|
||||
&bitmapData.DestTop,
|
||||
&bitmapData.DestRight,
|
||||
&bitmapData.DestBottom,
|
||||
&bitmapData.Width,
|
||||
&bitmapData.Height,
|
||||
&bitmapData.BitsPerPixel,
|
||||
&bitmapData.Flags,
|
||||
&bitmapData.BitmapLength,
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
if err := binary.Read(updateReader, binary.LittleEndian, field); err != nil {
|
||||
return nil, errors.New("[FASTPATH] read bitmapdata field error: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if bitmapData.BitmapLength > uint16(updateReader.Len()) {
|
||||
return nil, errors.New("[FASTPATH] invalid bitmaplength")
|
||||
}
|
||||
|
||||
// 提取真实的Payload
|
||||
bitmapPayload := make([]byte, bitmapData.BitmapLength)
|
||||
if _, err := updateReader.Read(bitmapPayload); err != nil {
|
||||
return nil, errors.New("[FASTPATH] read bitmappayload error: " + err.Error())
|
||||
}
|
||||
|
||||
return bitmapPayload, nil
|
||||
}
|
||||
Reference in New Issue
Block a user