mirror of
https://github.com/apernet/hysteria.git
synced 2025-04-03 20:47:38 +03:00
152 lines
3.3 KiB
Go
152 lines
3.3 KiB
Go
package speedtest
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"io"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
typeDownload = 0x1
|
|
typeUpload = 0x2
|
|
)
|
|
|
|
// DownloadRequest format:
|
|
// 0x1 (byte)
|
|
// Request data length (uint32 BE)
|
|
|
|
func readDownloadRequest(r io.Reader) (uint32, error) {
|
|
var l uint32
|
|
err := binary.Read(r, binary.BigEndian, &l)
|
|
return l, err
|
|
}
|
|
|
|
func writeDownloadRequest(w io.Writer, l uint32) error {
|
|
buf := make([]byte, 5)
|
|
buf[0] = typeDownload
|
|
binary.BigEndian.PutUint32(buf[1:], l)
|
|
_, err := w.Write(buf)
|
|
return err
|
|
}
|
|
|
|
// DownloadResponse format:
|
|
// Status (byte, 0=ok, 1=error)
|
|
// Message length (uint16 BE)
|
|
// Message (bytes)
|
|
|
|
func readDownloadResponse(r io.Reader) (bool, string, error) {
|
|
var status [1]byte
|
|
if _, err := io.ReadFull(r, status[:]); err != nil {
|
|
return false, "", err
|
|
}
|
|
var msgLen uint16
|
|
if err := binary.Read(r, binary.BigEndian, &msgLen); err != nil {
|
|
return false, "", err
|
|
}
|
|
// No message is fine
|
|
if msgLen == 0 {
|
|
return status[0] == 0, "", nil
|
|
}
|
|
msgBuf := make([]byte, msgLen)
|
|
_, err := io.ReadFull(r, msgBuf)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
return status[0] == 0, string(msgBuf), nil
|
|
}
|
|
|
|
func writeDownloadResponse(w io.Writer, ok bool, msg string) error {
|
|
sz := 1 + 2 + len(msg)
|
|
buf := make([]byte, sz)
|
|
if ok {
|
|
buf[0] = 0
|
|
} else {
|
|
buf[0] = 1
|
|
}
|
|
binary.BigEndian.PutUint16(buf[1:], uint16(len(msg)))
|
|
copy(buf[3:], msg)
|
|
_, err := w.Write(buf)
|
|
return err
|
|
}
|
|
|
|
// UploadRequest format:
|
|
// 0x2 (byte)
|
|
// Upload data length (uint32 BE)
|
|
|
|
func readUploadRequest(r io.Reader) (uint32, error) {
|
|
var l uint32
|
|
err := binary.Read(r, binary.BigEndian, &l)
|
|
return l, err
|
|
}
|
|
|
|
func writeUploadRequest(w io.Writer, l uint32) error {
|
|
buf := make([]byte, 5)
|
|
buf[0] = typeUpload
|
|
binary.BigEndian.PutUint32(buf[1:], l)
|
|
_, err := w.Write(buf)
|
|
return err
|
|
}
|
|
|
|
// UploadResponse format:
|
|
// Status (byte, 0=ok, 1=error)
|
|
// Message length (uint16 BE)
|
|
// Message (bytes)
|
|
|
|
func readUploadResponse(r io.Reader) (bool, string, error) {
|
|
var status [1]byte
|
|
if _, err := io.ReadFull(r, status[:]); err != nil {
|
|
return false, "", err
|
|
}
|
|
var msgLen uint16
|
|
if err := binary.Read(r, binary.BigEndian, &msgLen); err != nil {
|
|
return false, "", err
|
|
}
|
|
// No message is fine
|
|
if msgLen == 0 {
|
|
return status[0] == 0, "", nil
|
|
}
|
|
msgBuf := make([]byte, msgLen)
|
|
_, err := io.ReadFull(r, msgBuf)
|
|
if err != nil {
|
|
return false, "", err
|
|
}
|
|
return status[0] == 0, string(msgBuf), nil
|
|
}
|
|
|
|
func writeUploadResponse(w io.Writer, ok bool, msg string) error {
|
|
sz := 1 + 2 + len(msg)
|
|
buf := make([]byte, sz)
|
|
if ok {
|
|
buf[0] = 0
|
|
} else {
|
|
buf[0] = 1
|
|
}
|
|
binary.BigEndian.PutUint16(buf[1:], uint16(len(msg)))
|
|
copy(buf[3:], msg)
|
|
_, err := w.Write(buf)
|
|
return err
|
|
}
|
|
|
|
// UploadSummary format:
|
|
// Duration (in milliseconds, uint32 BE)
|
|
// Received data length (uint32 BE)
|
|
|
|
func readUploadSummary(r io.Reader) (time.Duration, uint32, error) {
|
|
var duration uint32
|
|
if err := binary.Read(r, binary.BigEndian, &duration); err != nil {
|
|
return 0, 0, err
|
|
}
|
|
var l uint32
|
|
if err := binary.Read(r, binary.BigEndian, &l); err != nil {
|
|
return 0, 0, err
|
|
}
|
|
return time.Duration(duration) * time.Millisecond, l, nil
|
|
}
|
|
|
|
func writeUploadSummary(w io.Writer, duration time.Duration, l uint32) error {
|
|
buf := make([]byte, 8)
|
|
binary.BigEndian.PutUint32(buf, uint32(duration/time.Millisecond))
|
|
binary.BigEndian.PutUint32(buf[4:], l)
|
|
_, err := w.Write(buf)
|
|
return err
|
|
}
|