mirror of
https://github.com/yusing/godoxy.git
synced 2026-03-18 23:33:51 +01:00
- Adjusted headerSize calculation to reflect the correct size based on field definitions. - Changed HostLength and PortLength types from uint8 to byte. - Updated PROTOCOL.md to reflect the new header size and structure.
98 lines
2.3 KiB
Go
98 lines
2.3 KiB
Go
package stream
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"fmt"
|
|
"hash/crc32"
|
|
"reflect"
|
|
"unsafe"
|
|
)
|
|
|
|
const (
|
|
versionSize = 8
|
|
hostSize = 255
|
|
portSize = 5
|
|
checksumSize = 4 // crc32 checksum
|
|
|
|
headerSize = versionSize + 1 + hostSize + 1 + portSize + checksumSize
|
|
)
|
|
|
|
var version = [versionSize]byte{'0', '.', '1', '.', '0', 0, 0, 0}
|
|
|
|
var ErrInvalidHeader = errors.New("invalid header")
|
|
|
|
type StreamRequestHeader struct {
|
|
Version [versionSize]byte
|
|
|
|
HostLength byte
|
|
Host [hostSize]byte
|
|
|
|
PortLength byte
|
|
Port [portSize]byte
|
|
|
|
Checksum [checksumSize]byte
|
|
}
|
|
|
|
func init() {
|
|
if headerSize != reflect.TypeFor[StreamRequestHeader]().Size() {
|
|
panic("headerSize does not match the size of StreamRequestHeader")
|
|
}
|
|
}
|
|
|
|
func NewStreamRequestHeader(host, port string) (*StreamRequestHeader, error) {
|
|
if len(host) > hostSize {
|
|
return nil, fmt.Errorf("host is too long: max %d characters, got %d", hostSize, len(host))
|
|
}
|
|
if len(port) > portSize {
|
|
return nil, fmt.Errorf("port is too long: max %d characters, got %d", portSize, len(port))
|
|
}
|
|
header := &StreamRequestHeader{}
|
|
copy(header.Version[:], version[:])
|
|
header.HostLength = byte(len(host))
|
|
copy(header.Host[:], host)
|
|
header.PortLength = byte(len(port))
|
|
copy(header.Port[:], port)
|
|
header.updateChecksum()
|
|
return header, nil
|
|
}
|
|
|
|
func ToHeader(buf [headerSize]byte) *StreamRequestHeader {
|
|
return (*StreamRequestHeader)(unsafe.Pointer(&buf[0]))
|
|
}
|
|
|
|
func (h *StreamRequestHeader) GetHostPort() (string, string) {
|
|
return string(h.Host[:h.HostLength]), string(h.Port[:h.PortLength])
|
|
}
|
|
|
|
func (h *StreamRequestHeader) Validate() bool {
|
|
if h.Version != version {
|
|
return false
|
|
}
|
|
if h.HostLength > hostSize {
|
|
return false
|
|
}
|
|
if h.PortLength > portSize {
|
|
return false
|
|
}
|
|
return h.validateChecksum()
|
|
}
|
|
|
|
func (h *StreamRequestHeader) updateChecksum() {
|
|
checksum := crc32.ChecksumIEEE(h.BytesWithoutChecksum())
|
|
binary.BigEndian.PutUint32(h.Checksum[:], checksum)
|
|
}
|
|
|
|
func (h *StreamRequestHeader) validateChecksum() bool {
|
|
checksum := crc32.ChecksumIEEE(h.BytesWithoutChecksum())
|
|
return checksum == binary.BigEndian.Uint32(h.Checksum[:])
|
|
}
|
|
|
|
func (h *StreamRequestHeader) BytesWithoutChecksum() []byte {
|
|
return (*[headerSize - checksumSize]byte)(unsafe.Pointer(h))[:]
|
|
}
|
|
|
|
func (h *StreamRequestHeader) Bytes() []byte {
|
|
return (*[headerSize]byte)(unsafe.Pointer(h))[:]
|
|
}
|