mirror of
https://github.com/fumiama/WireGold.git
synced 2026-06-05 07:50:24 +08:00
optimize(all): drop lstnq & impl. orbyte
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
const ShowDebugLog = true
|
const ShowDebugLog = false
|
||||||
|
|||||||
3
go.mod
3
go.mod
@@ -3,11 +3,12 @@ module github.com/fumiama/WireGold
|
|||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562
|
github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d
|
||||||
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7
|
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7
|
||||||
github.com/fumiama/blake2b-simd v0.0.0-20220412110131-4481822068bb
|
github.com/fumiama/blake2b-simd v0.0.0-20220412110131-4481822068bb
|
||||||
github.com/fumiama/go-base16384 v1.7.0
|
github.com/fumiama/go-base16384 v1.7.0
|
||||||
github.com/fumiama/go-x25519 v1.0.0
|
github.com/fumiama/go-x25519 v1.0.0
|
||||||
|
github.com/fumiama/orbyte v0.0.0-20250225103543-4a462a143731
|
||||||
github.com/fumiama/water v0.0.0-20211231134027-da391938d6ac
|
github.com/fumiama/water v0.0.0-20211231134027-da391938d6ac
|
||||||
github.com/klauspost/compress v1.17.9
|
github.com/klauspost/compress v1.17.9
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
|
|||||||
6
go.sum
6
go.sum
@@ -1,5 +1,5 @@
|
|||||||
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562 h1:snfw7FNFym1eNnLrQ/VCf80LiQo9C7jHgrunZDwiRcY=
|
github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d h1:mUQ/c3wXKsUGa4Sg9DBy01APXKB68PmobhxOyaJI7lY=
|
||||||
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
||||||
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 h1:S/ferNiehVjNaBMNNBxUjLtVmP/YWD6Yh79RfPv4ehU=
|
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 h1:S/ferNiehVjNaBMNNBxUjLtVmP/YWD6Yh79RfPv4ehU=
|
||||||
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
|
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -11,6 +11,8 @@ github.com/fumiama/go-base16384 v1.7.0 h1:6fep7XPQWxRlh4Hu+KsdH+6+YdUp+w6CwRXtMW
|
|||||||
github.com/fumiama/go-base16384 v1.7.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
github.com/fumiama/go-base16384 v1.7.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
||||||
github.com/fumiama/go-x25519 v1.0.0 h1:hiGg9EhseVmGCc8T1jECVkj8Keu/aJ1ZK05RM8Vuavo=
|
github.com/fumiama/go-x25519 v1.0.0 h1:hiGg9EhseVmGCc8T1jECVkj8Keu/aJ1ZK05RM8Vuavo=
|
||||||
github.com/fumiama/go-x25519 v1.0.0/go.mod h1:8VOhfyGZzw4IUs4nCjQFqW9cA3V/QpSCtP3fo2dLNg4=
|
github.com/fumiama/go-x25519 v1.0.0/go.mod h1:8VOhfyGZzw4IUs4nCjQFqW9cA3V/QpSCtP3fo2dLNg4=
|
||||||
|
github.com/fumiama/orbyte v0.0.0-20250225103543-4a462a143731 h1:FUL+OQCPz69Iizhrf2GxRvcGSbJgAQvV/pIAFF4g8OQ=
|
||||||
|
github.com/fumiama/orbyte v0.0.0-20250225103543-4a462a143731/go.mod h1:qkUllQ1+gTx5sGrmKvIsqUgsnOO21Hiq847YHJRifbk=
|
||||||
github.com/fumiama/water v0.0.0-20211231134027-da391938d6ac h1:A/5A0rODsg+EQHH61Ew5mMUtDpRXaSNqHhPvW+fN4C4=
|
github.com/fumiama/water v0.0.0-20211231134027-da391938d6ac h1:A/5A0rODsg+EQHH61Ew5mMUtDpRXaSNqHhPvW+fN4C4=
|
||||||
github.com/fumiama/water v0.0.0-20211231134027-da391938d6ac/go.mod h1:BBnNY9PwK+UUn4trAU+H0qsMEypm7+3Bj1bVFuJItlo=
|
github.com/fumiama/water v0.0.0-20211231134027-da391938d6ac/go.mod h1:BBnNY9PwK+UUn4trAU+H0qsMEypm7+3Bj1bVFuJItlo=
|
||||||
github.com/fumiama/wintun v0.0.0-20211229152851-8bc97c8034c0 h1:WfrSFlIlCAtg6Rt2IGna0HhJYSDE45YVHiYqO4wwsEw=
|
github.com/fumiama/wintun v0.0.0-20211229152851-8bc97c8034c0 h1:WfrSFlIlCAtg6Rt2IGna0HhJYSDE45YVHiYqO4wwsEw=
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
package head
|
package head
|
||||||
|
|
||||||
import "encoding/binary"
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
type PacketFlags uint16
|
type PacketFlags uint16
|
||||||
|
|
||||||
|
func (pf PacketFlags) String() string {
|
||||||
|
return fmt.Sprintf("%04x", uint16(pf))
|
||||||
|
}
|
||||||
|
|
||||||
func (pf PacketFlags) IsValid() bool {
|
func (pf PacketFlags) IsValid() bool {
|
||||||
return pf&0x8000 == 0
|
return pf&0x8000 == 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,11 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
blake2b "github.com/fumiama/blake2b-simd"
|
blake2b "github.com/fumiama/blake2b-simd"
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/fumiama/WireGold/config"
|
"github.com/fumiama/WireGold/config"
|
||||||
@@ -37,6 +40,8 @@ type Packet struct {
|
|||||||
DstPort uint16
|
DstPort uint16
|
||||||
// Flags 高3位为标志(xDM),低13位为分片偏移
|
// Flags 高3位为标志(xDM),低13位为分片偏移
|
||||||
Flags PacketFlags
|
Flags PacketFlags
|
||||||
|
// 记录还有多少字节未到达
|
||||||
|
rembytes int32
|
||||||
// Src 源 ip (ipv4)
|
// Src 源 ip (ipv4)
|
||||||
Src net.IP
|
Src net.IP
|
||||||
// Dst 目的 ip (ipv4)
|
// Dst 目的 ip (ipv4)
|
||||||
@@ -48,82 +53,113 @@ type Packet struct {
|
|||||||
// crc64 包头字段的 checksum 值,可以认为在一定时间内唯一 (现已更改算法为 md5 但名字未变)
|
// crc64 包头字段的 checksum 值,可以认为在一定时间内唯一 (现已更改算法为 md5 但名字未变)
|
||||||
crc64 uint64
|
crc64 uint64
|
||||||
// data 承载的数据
|
// data 承载的数据
|
||||||
data []byte
|
data pbuf.Bytes
|
||||||
// Data 当前的偏移
|
// Data 当前的偏移
|
||||||
a, b int
|
a, b int
|
||||||
// 记录还有多少字节未到达
|
|
||||||
rembytes int
|
|
||||||
// 是否经由 helper.MakeBytes 创建 Data
|
|
||||||
buffered bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPacket 生成一个新包
|
// NewPacketPartial 从一些预设参数生成一个新包
|
||||||
func NewPacket(proto uint8, srcPort uint16, dst net.IP, dstPort uint16, data []byte) (p *Packet) {
|
func NewPacketPartial(
|
||||||
p = SelectPacket()
|
proto uint8, srcPort uint16,
|
||||||
p.Proto = proto
|
dst net.IP, dstPort uint16,
|
||||||
p.TTL = 16
|
data pbuf.Bytes,
|
||||||
p.SrcPort = srcPort
|
) (p *orbyte.Item[Packet]) {
|
||||||
p.DstPort = dstPort
|
p = selectPacket()
|
||||||
p.Dst = dst
|
pp := p.Pointer()
|
||||||
p.data = data
|
pp.Proto = proto
|
||||||
p.b = len(data)
|
pp.TTL = 16
|
||||||
|
pp.SrcPort = srcPort
|
||||||
|
pp.DstPort = dstPort
|
||||||
|
pp.Dst = dst
|
||||||
|
pp.data = data
|
||||||
|
pp.b = data.Len()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal 将 data 的数据解码到自身
|
func ParsePacket(p Packet) *orbyte.Item[Packet] {
|
||||||
func (p *Packet) Unmarshal(data []byte) (complete bool, err error) {
|
return packetPool.Parse(nil, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePacketHeader(data []byte) (p *orbyte.Item[Packet], err error) {
|
||||||
if len(data) < 60 {
|
if len(data) < 60 {
|
||||||
err = ErrDataLenLT60
|
err = ErrDataLenLT60
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.crc64 = CRC64(data)
|
p = selectPacket()
|
||||||
if CalcCRC64(data) != p.crc64 {
|
pp := p.Pointer()
|
||||||
|
pp.crc64 = CRC64(data)
|
||||||
|
if CalcCRC64(data) != pp.crc64 {
|
||||||
err = ErrBadCRCChecksum
|
err = ErrBadCRCChecksum
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pp.idxdatsz = binary.LittleEndian.Uint32(data[:4])
|
||||||
|
sz := pp.Len()
|
||||||
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[packet] header data len", sz, "read data len", len(data))
|
||||||
|
}
|
||||||
|
pt := binary.LittleEndian.Uint16(data[4:6])
|
||||||
|
pp.Proto = uint8(pt)
|
||||||
|
pp.TTL = uint8(pt >> 8)
|
||||||
|
pp.SrcPort = binary.LittleEndian.Uint16(data[6:8])
|
||||||
|
pp.DstPort = binary.LittleEndian.Uint16(data[8:10])
|
||||||
|
|
||||||
|
flags := PacketFlags(binary.LittleEndian.Uint16(data[10:12]))
|
||||||
|
pp.Flags = flags
|
||||||
|
pp.Src = make(net.IP, 4)
|
||||||
|
copy(pp.Src, data[12:16])
|
||||||
|
pp.Dst = make(net.IP, 4)
|
||||||
|
copy(pp.Dst, data[16:20])
|
||||||
|
copy(pp.Hash[:], data[20:52])
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case sz+PacketHeadLen == len(data):
|
||||||
|
pp.b = sz
|
||||||
|
pp.rembytes = -1
|
||||||
|
case pp.rembytes == 0:
|
||||||
|
pp.data = pbuf.NewBytes(sz)
|
||||||
|
pp.b = sz
|
||||||
|
pp.rembytes = int32(sz)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseData 将 data 的数据解码到自身
|
||||||
|
//
|
||||||
|
// 必须先调用 ParsePacketHeader
|
||||||
|
func (p *Packet) ParseData(data []byte) (complete bool) {
|
||||||
sz := p.Len()
|
sz := p.Len()
|
||||||
if sz == 0 && len(p.data) == 0 {
|
if sz+PacketHeadLen == len(data) {
|
||||||
p.idxdatsz = binary.LittleEndian.Uint32(data[:4])
|
p.data = pbuf.ParseBytes(data[PacketHeadLen:]...)
|
||||||
sz = p.Len()
|
return true
|
||||||
if sz+52 == len(data) {
|
|
||||||
p.data = data[52:]
|
|
||||||
p.b = len(p.data)
|
|
||||||
p.rembytes = 0
|
|
||||||
} else {
|
|
||||||
p.data = helper.MakeBytes(sz)
|
|
||||||
p.buffered = true
|
|
||||||
p.b = sz
|
|
||||||
p.rembytes = sz
|
|
||||||
}
|
|
||||||
pt := binary.LittleEndian.Uint16(data[4:6])
|
|
||||||
p.Proto = uint8(pt)
|
|
||||||
p.TTL = uint8(pt >> 8)
|
|
||||||
p.SrcPort = binary.LittleEndian.Uint16(data[6:8])
|
|
||||||
p.DstPort = binary.LittleEndian.Uint16(data[8:10])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
flags := PacketFlags(binary.LittleEndian.Uint16(data[10:12]))
|
flags := PacketFlags(binary.LittleEndian.Uint16(data[10:12]))
|
||||||
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[packet] parse data flags", flags, "off", flags.Offset())
|
||||||
|
}
|
||||||
if flags.ZeroOffset() {
|
if flags.ZeroOffset() {
|
||||||
p.Flags = flags
|
p.Flags = flags
|
||||||
p.Src = make(net.IP, 4)
|
|
||||||
copy(p.Src, data[12:16])
|
|
||||||
p.Dst = make(net.IP, 4)
|
|
||||||
copy(p.Dst, data[16:20])
|
|
||||||
copy(p.Hash[:], data[20:52])
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.rembytes > 0 {
|
|
||||||
p.rembytes -= copy(p.data[flags.Offset():], data[PacketHeadLen:])
|
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[packet] copied frag", hex.EncodeToString(p.Hash[:]), "rembytes:", p.rembytes)
|
logrus.Debugln("[packet] parse data set zero offset flags", flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
complete = p.rembytes == 0
|
rembytes := atomic.LoadInt32(&p.rembytes)
|
||||||
|
if rembytes > 0 {
|
||||||
|
n := int32(copy(p.data.Bytes()[flags.Offset():], data[PacketHeadLen:]))
|
||||||
|
newrem := rembytes - n
|
||||||
|
for !atomic.CompareAndSwapInt32(&p.rembytes, rembytes, newrem) {
|
||||||
|
rembytes = atomic.LoadInt32(&p.rembytes)
|
||||||
|
newrem = rembytes - n
|
||||||
|
}
|
||||||
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[packet] copied frag", hex.EncodeToString(data[20:52]), "rembytes:", p.rembytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return p.rembytes <= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecreaseAndGetTTL TTL 自减后返回
|
// DecreaseAndGetTTL TTL 自减后返回
|
||||||
@@ -132,9 +168,13 @@ func (p *Packet) DecreaseAndGetTTL() uint8 {
|
|||||||
return p.TTL
|
return p.TTL
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal 将自身数据编码为 []byte
|
// MarshalWith 补全剩余参数, 将自身数据编码为 []byte
|
||||||
// offset 必须为 8 的倍数,表示偏移的 8 位
|
// offset 必须为 8 的倍数,表示偏移的 8 位
|
||||||
func (p *Packet) Marshal(src net.IP, teatype uint8, additional uint16, datasz uint32, offset uint16, dontfrag, hasmore bool) ([]byte, func()) {
|
func (p *Packet) MarshalWith(
|
||||||
|
src net.IP, teatype uint8, additional uint16,
|
||||||
|
datasz uint32, offset uint16,
|
||||||
|
dontfrag, hasmore bool,
|
||||||
|
) pbuf.Bytes {
|
||||||
if src != nil {
|
if src != nil {
|
||||||
p.Src = src
|
p.Src = src
|
||||||
p.idxdatsz = (uint32(teatype) << 27) | (uint32(additional&0x07ff) << 16) | datasz&0xffff
|
p.idxdatsz = (uint32(teatype) << 27) | (uint32(additional&0x07ff) << 16) | datasz&0xffff
|
||||||
@@ -148,8 +188,7 @@ func (p *Packet) Marshal(src net.IP, teatype uint8, additional uint16, datasz ui
|
|||||||
offset |= 0x2000
|
offset |= 0x2000
|
||||||
}
|
}
|
||||||
p.Flags = PacketFlags(offset)
|
p.Flags = PacketFlags(offset)
|
||||||
|
return helper.NewWriterF(func(w *helper.Writer) {
|
||||||
return helper.OpenWriterF(func(w *helper.Writer) {
|
|
||||||
w.WriteUInt32(p.idxdatsz)
|
w.WriteUInt32(p.idxdatsz)
|
||||||
w.WriteUInt16((uint16(p.TTL) << 8) | uint16(p.Proto))
|
w.WriteUInt16((uint16(p.TTL) << 8) | uint16(p.Proto))
|
||||||
w.WriteUInt16(p.SrcPort)
|
w.WriteUInt16(p.SrcPort)
|
||||||
@@ -158,7 +197,7 @@ func (p *Packet) Marshal(src net.IP, teatype uint8, additional uint16, datasz ui
|
|||||||
w.Write(p.Src.To4())
|
w.Write(p.Src.To4())
|
||||||
w.Write(p.Dst.To4())
|
w.Write(p.Dst.To4())
|
||||||
w.Write(p.Hash[:])
|
w.Write(p.Hash[:])
|
||||||
p.crc64 = CalcCRC64(w.Bytes())
|
p.crc64 = CalcCRC64(w.UnsafeBytes())
|
||||||
w.WriteUInt64(p.crc64)
|
w.WriteUInt64(p.crc64)
|
||||||
w.Write(p.Body())
|
w.Write(p.Body())
|
||||||
})
|
})
|
||||||
@@ -189,6 +228,7 @@ func (p *Packet) IsVaildHash() bool {
|
|||||||
var sum [32]byte
|
var sum [32]byte
|
||||||
_ = h.Sum(sum[:0])
|
_ = h.Sum(sum[:0])
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[packet] sum data len:", len(p.Body()))
|
||||||
logrus.Debugln("[packet] sum calulated:", hex.EncodeToString(sum[:]))
|
logrus.Debugln("[packet] sum calulated:", hex.EncodeToString(sum[:]))
|
||||||
logrus.Debugln("[packet] sum in packet:", hex.EncodeToString(p.Hash[:]))
|
logrus.Debugln("[packet] sum in packet:", hex.EncodeToString(p.Hash[:]))
|
||||||
}
|
}
|
||||||
@@ -210,45 +250,28 @@ func (p *Packet) Len() int {
|
|||||||
return int(p.idxdatsz & 0xffff)
|
return int(p.idxdatsz & 0xffff)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put 将自己放回池中
|
|
||||||
func (p *Packet) Put() {
|
|
||||||
PutPacket(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Packet) CRC64() uint64 {
|
func (p *Packet) CRC64() uint64 {
|
||||||
return p.crc64
|
return p.crc64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Body returns data
|
// Body returns data
|
||||||
func (p *Packet) Body() []byte {
|
func (p *Packet) Body() []byte {
|
||||||
return p.data[p.a:p.b]
|
return p.data.Bytes()[p.a:p.b]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Packet) BodyLen() int {
|
func (p *Packet) BodyLen() int {
|
||||||
return p.b - p.a
|
return p.b - p.a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Packet) SetBody(b []byte, buffered bool) {
|
func (p *Packet) SetBody(b []byte) {
|
||||||
p.a = 0
|
p.a = 0
|
||||||
p.b = len(b)
|
p.b = len(b)
|
||||||
if len(b) <= cap(p.data) {
|
p.data = pbuf.ParseBytes(b...)
|
||||||
p.data = p.data[:len(b)]
|
|
||||||
copy(p.data, b)
|
|
||||||
if buffered {
|
|
||||||
helper.PutBytes(b)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if p.buffered {
|
|
||||||
helper.PutBytes(p.data)
|
|
||||||
}
|
|
||||||
p.data = b
|
|
||||||
p.buffered = buffered
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Packet) CropBody(a, b int) {
|
func (p *Packet) CropBody(a, b int) {
|
||||||
if b > len(p.data) {
|
if b > p.data.Len() {
|
||||||
b = len(p.data)
|
b = p.data.Len()
|
||||||
}
|
}
|
||||||
if a < 0 || b < 0 || a > b {
|
if a < 0 || b < 0 || a > b {
|
||||||
return
|
return
|
||||||
@@ -256,16 +279,8 @@ func (p *Packet) CropBody(a, b int) {
|
|||||||
p.a, p.b = a, b
|
p.a, p.b = a, b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Packet) Copy() *Packet {
|
func (p *Packet) ShallowCopy() (newp Packet) {
|
||||||
newp := SelectPacket()
|
newp = *p
|
||||||
*newp = *p
|
newp.data = p.data.Ref()
|
||||||
newp.buffered = false
|
|
||||||
return newp
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Packet) CopyWithBody() *Packet {
|
|
||||||
newp := p.Copy()
|
|
||||||
newp.data = helper.MakeBytes(len(p.data))
|
|
||||||
copy(newp.data, p.data)
|
|
||||||
return newp
|
return newp
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,20 @@ package head
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
crand "crypto/rand"
|
crand "crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMarshalUnmarshal(t *testing.T) {
|
func TestMarshalUnmarshal(t *testing.T) {
|
||||||
data := make([]byte, 4096)
|
data := pbuf.NewBytes(4096)
|
||||||
_, err := crand.Read(data)
|
n, err := crand.Read(data.Bytes())
|
||||||
|
if n != 4096 {
|
||||||
|
t.Fatal("unexpected")
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -28,40 +34,40 @@ func TestMarshalUnmarshal(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
p := NewPacket(proto, srcPort, dst, dstPort, data)
|
p := NewPacketPartial(proto, srcPort, dst, dstPort, data.SliceTo(i))
|
||||||
p.FillHash()
|
p.Pointer().FillHash()
|
||||||
d, cl := p.Marshal(src, teatype, uint16(i), uint32(len(data)), 0, true, false)
|
d := p.Pointer().MarshalWith(src, teatype, uint16(i), uint32(i), 0, true, false)
|
||||||
p = SelectPacket()
|
t.Log("data:", hex.EncodeToString(d.Bytes()))
|
||||||
ok, err := p.Unmarshal(d)
|
p, err := ParsePacketHeader(d.Bytes())
|
||||||
cl()
|
if err != nil {
|
||||||
|
t.Fatal("index", i, err)
|
||||||
|
}
|
||||||
|
ok := p.Pointer().ParseData(d.Bytes())
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("index", i)
|
t.Fatal("index", i)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if !p.Pointer().IsVaildHash() {
|
||||||
t.Fatal(err)
|
t.Fatal("index", i, "expect body", hex.EncodeToString(data.SliceTo(i).Bytes()), "got", hex.EncodeToString(p.Pointer().Body()))
|
||||||
}
|
}
|
||||||
if !p.IsVaildHash() {
|
if p.Pointer().Proto != proto {
|
||||||
t.Fatal("index", i)
|
t.Fatal("index", i)
|
||||||
}
|
}
|
||||||
if p.Proto != proto {
|
if p.Pointer().CipherIndex() != teatype {
|
||||||
|
t.Fatal("index", i, "expect", teatype, "got", p.Pointer().CipherIndex())
|
||||||
|
}
|
||||||
|
if p.Pointer().SrcPort != srcPort {
|
||||||
t.Fatal("index", i)
|
t.Fatal("index", i)
|
||||||
}
|
}
|
||||||
if p.CipherIndex() != teatype {
|
if p.Pointer().DstPort != dstPort {
|
||||||
t.Fatal("index", i, "expect", teatype, "got", p.CipherIndex())
|
|
||||||
}
|
|
||||||
if p.SrcPort != srcPort {
|
|
||||||
t.Fatal("index", i)
|
t.Fatal("index", i)
|
||||||
}
|
}
|
||||||
if p.DstPort != dstPort {
|
if !p.Pointer().Src.Equal(src) {
|
||||||
t.Fatal("index", i)
|
t.Fatal("index", i)
|
||||||
}
|
}
|
||||||
if !p.Src.Equal(src) {
|
if !p.Pointer().Dst.Equal(dst) {
|
||||||
t.Fatal("index", i)
|
t.Fatal("index", i)
|
||||||
}
|
}
|
||||||
if !p.Dst.Equal(dst) {
|
if p.Pointer().AdditionalData() != uint16(i) {
|
||||||
t.Fatal("index", i)
|
|
||||||
}
|
|
||||||
if p.AdditionalData() != uint16(i) {
|
|
||||||
t.Fatal("index", i)
|
t.Fatal("index", i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,37 @@
|
|||||||
package head
|
package head
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"github.com/fumiama/orbyte"
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
"github.com/fumiama/WireGold/helper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var packetPool = sync.Pool{
|
type packetPooler struct {
|
||||||
New: func() interface{} {
|
orbyte.Pooler[Packet]
|
||||||
return new(Packet)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectPacket 从池中取出一个 Packet
|
func (packetPooler) New(_ any, pooled Packet) Packet {
|
||||||
func SelectPacket() *Packet {
|
return pooled
|
||||||
return packetPool.Get().(*Packet)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutPacket 将 Packet 放回池中
|
func (packetPooler) Parse(obj any, _ Packet) Packet {
|
||||||
func PutPacket(p *Packet) {
|
return obj.(Packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (packetPooler) Reset(p *Packet) {
|
||||||
p.idxdatsz = 0
|
p.idxdatsz = 0
|
||||||
if p.buffered {
|
p.data = pbuf.Bytes{}
|
||||||
helper.PutBytes(p.data)
|
|
||||||
p.buffered = false
|
|
||||||
}
|
|
||||||
p.a, p.b = 0, 0
|
p.a, p.b = 0, 0
|
||||||
p.data = nil
|
|
||||||
p.rembytes = 0
|
p.rembytes = 0
|
||||||
packetPool.Put(p)
|
}
|
||||||
|
|
||||||
|
func (packetPooler) Copy(dst, src *Packet) {
|
||||||
|
*dst = *src
|
||||||
|
dst.data = src.data.Copy()
|
||||||
|
}
|
||||||
|
|
||||||
|
var packetPool = orbyte.NewPool[Packet](packetPooler{})
|
||||||
|
|
||||||
|
// selectPacket 从池中取出一个 Packet
|
||||||
|
func selectPacket() *orbyte.Item[Packet] {
|
||||||
|
return packetPool.New(nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/fumiama/WireGold/helper"
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,14 +54,12 @@ func expandkeyunit(v1, v2 byte) (v uint16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Encode by aead and put b into pool
|
// Encode by aead and put b into pool
|
||||||
func (l *Link) Encode(teatype uint8, additional uint16, b []byte) (eb []byte) {
|
func (l *Link) Encode(teatype uint8, additional uint16, b []byte) (eb pbuf.Bytes) {
|
||||||
if len(b) == 0 || teatype >= 32 {
|
if len(b) == 0 || teatype >= 32 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if l.keys[0] == nil {
|
if l.keys[0] == nil {
|
||||||
eb = helper.MakeBytes(len(b))
|
return pbuf.ParseBytes(b...)
|
||||||
copy(eb, b)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
aead := l.keys[teatype]
|
aead := l.keys[teatype]
|
||||||
if aead == nil {
|
if aead == nil {
|
||||||
@@ -72,14 +71,12 @@ func (l *Link) Encode(teatype uint8, additional uint16, b []byte) (eb []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode by aead and put b into pool
|
// Decode by aead and put b into pool
|
||||||
func (l *Link) Decode(teatype uint8, additional uint16, b []byte) (db []byte, err error) {
|
func (l *Link) Decode(teatype uint8, additional uint16, b []byte) (db pbuf.Bytes, err error) {
|
||||||
if len(b) == 0 || teatype >= 32 {
|
if len(b) == 0 || teatype >= 32 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if l.keys[0] == nil {
|
if l.keys[0] == nil {
|
||||||
db = helper.MakeBytes(len(b))
|
return pbuf.ParseBytes(b...), nil
|
||||||
copy(db, b)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
aead := l.keys[teatype]
|
aead := l.keys[teatype]
|
||||||
if aead == nil {
|
if aead == nil {
|
||||||
@@ -88,59 +85,67 @@ func (l *Link) Decode(teatype uint8, additional uint16, b []byte) (db []byte, er
|
|||||||
return decode(aead, additional, b)
|
return decode(aead, additional, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(aead cipher.AEAD, additional uint16, b []byte) []byte {
|
func encode(aead cipher.AEAD, additional uint16, b []byte) pbuf.Bytes {
|
||||||
nsz := aead.NonceSize()
|
nsz := aead.NonceSize()
|
||||||
// Accocate capacity for all the stuffs.
|
// Accocate capacity for all the stuffs.
|
||||||
buf := helper.MakeBytes(2 + nsz + len(b) + aead.Overhead())
|
buf := pbuf.NewBytes(2 + nsz + len(b) + aead.Overhead())
|
||||||
binary.LittleEndian.PutUint16(buf[:2], additional)
|
binary.LittleEndian.PutUint16(buf.Bytes()[:2], additional)
|
||||||
nonce := buf[2 : 2+nsz]
|
nonce := buf.Bytes()[2 : 2+nsz]
|
||||||
// Select a random nonce
|
// Select a random nonce
|
||||||
_, err := rand.Read(nonce)
|
_, err := rand.Read(nonce)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
// Encrypt the message and append the ciphertext to the nonce.
|
// Encrypt the message and append the ciphertext to the nonce.
|
||||||
eb := aead.Seal(nonce[nsz:nsz], nonce, b, buf[:2])
|
eb := aead.Seal(nonce[nsz:nsz], nonce, b, buf.Bytes()[:2])
|
||||||
return nonce[:nsz+len(eb)]
|
return buf.Trans().Slice(2, 2+nsz+len(eb))
|
||||||
}
|
}
|
||||||
|
|
||||||
func decode(aead cipher.AEAD, additional uint16, b []byte) ([]byte, error) {
|
func decode(aead cipher.AEAD, additional uint16, b []byte) (pbuf.Bytes, error) {
|
||||||
nsz := aead.NonceSize()
|
nsz := aead.NonceSize()
|
||||||
if len(b) < nsz {
|
if len(b) < nsz {
|
||||||
return nil, ErrCipherTextTooShort
|
return pbuf.Bytes{}, ErrCipherTextTooShort
|
||||||
}
|
}
|
||||||
// Split nonce and ciphertext.
|
// Split nonce and ciphertext.
|
||||||
nonce, ciphertext := b[:nsz], b[nsz:]
|
nonce, ciphertext := b[:nsz], b[nsz:]
|
||||||
if len(ciphertext) == 0 {
|
if len(ciphertext) == 0 {
|
||||||
return nil, nil
|
return pbuf.Bytes{}, nil
|
||||||
}
|
}
|
||||||
// Decrypt the message and check it wasn't tampered with.
|
// Decrypt the message and check it wasn't tampered with.
|
||||||
var buf [2]byte
|
var buf [2]byte
|
||||||
binary.LittleEndian.PutUint16(buf[:], additional)
|
binary.LittleEndian.PutUint16(buf[:], additional)
|
||||||
return aead.Open(helper.SelectWriter().Bytes(), nonce, ciphertext, buf[:])
|
data, err := aead.Open(
|
||||||
|
pbuf.NewBytes(4096).Trans().Bytes()[:0],
|
||||||
|
nonce, ciphertext, buf[:],
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return pbuf.Bytes{}, nil
|
||||||
|
}
|
||||||
|
return pbuf.ParseBytes(data...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// xorenc 按 8 字节, 以初始 m.mask 循环异或编码 data
|
// xorenc 按 8 字节, 以初始 m.mask 循环异或编码 data
|
||||||
func (m *Me) xorenc(data []byte, seq uint32) []byte {
|
func (m *Me) xorenc(data []byte, seq uint32) pbuf.Bytes {
|
||||||
batchsz := len(data) / 8
|
batchsz := len(data) / 8
|
||||||
remain := len(data) % 8
|
remain := len(data) % 8
|
||||||
sum := m.mask
|
sum := m.mask
|
||||||
newdat := helper.MakeBytes(8 + batchsz*8 + 8) // seqrand dat tail
|
newdat := pbuf.NewBytes(8 + batchsz*8 + 8) // seqrand dat tail
|
||||||
binary.LittleEndian.PutUint32(newdat[:4], seq)
|
binary.LittleEndian.PutUint32(newdat.Bytes()[:4], seq)
|
||||||
_, _ = rand.Read(newdat[4:8]) // seqrand
|
_, _ = rand.Read(newdat.Bytes()[4:8]) // seqrand
|
||||||
sum ^= binary.LittleEndian.Uint64(newdat[:8]) // init from seqrand
|
sum ^= binary.LittleEndian.Uint64(newdat.Bytes()[:8]) // init from seqrand
|
||||||
binary.LittleEndian.PutUint64(newdat[:8], sum)
|
binary.LittleEndian.PutUint64(newdat.Bytes()[:8], sum)
|
||||||
for i := 0; i < batchsz; i++ { // range on batch data
|
for i := 0; i < batchsz; i++ { // range on batch data
|
||||||
a := i * 8
|
a := i * 8
|
||||||
b := (i + 1) * 8
|
b := (i + 1) * 8
|
||||||
sum ^= binary.LittleEndian.Uint64(data[a:b])
|
sum ^= binary.LittleEndian.Uint64(data[a:b])
|
||||||
binary.LittleEndian.PutUint64(newdat[a+8:b+8], sum)
|
binary.LittleEndian.PutUint64(newdat.Bytes()[a+8:b+8], sum)
|
||||||
}
|
}
|
||||||
p := batchsz * 8
|
p := batchsz * 8
|
||||||
copy(newdat[8+p:], data[p:])
|
copy(newdat.Bytes()[8+p:], data[p:])
|
||||||
newdat[len(newdat)-1] = byte(remain)
|
runtime.KeepAlive(data)
|
||||||
sum ^= binary.LittleEndian.Uint64(newdat[8+p:])
|
newdat.Bytes()[newdat.Len()-1] = byte(remain)
|
||||||
binary.LittleEndian.PutUint64(newdat[8+p:], sum)
|
sum ^= binary.LittleEndian.Uint64(newdat.Bytes()[8+p:])
|
||||||
|
binary.LittleEndian.PutUint64(newdat.Bytes()[8+p:], sum)
|
||||||
return newdat
|
return newdat
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,5 +168,6 @@ func (m *Me) xordec(data []byte) (uint32, []byte) {
|
|||||||
if remain >= 8 {
|
if remain >= 8 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
return binary.LittleEndian.Uint32(data[:4]), data[8 : len(data)-8+int(remain)]
|
return binary.LittleEndian.Uint32(data[:4]),
|
||||||
|
data[8 : len(data)-8+int(remain)]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"io"
|
"io"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
@@ -27,10 +28,11 @@ func TestXOR(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
seq, dec := m.xordec(m.xorenc(r1.Bytes(), uint32(i)))
|
seq, dec := m.xordec(m.xorenc(r1.Bytes(), uint32(i)).Trans().Bytes())
|
||||||
if !bytes.Equal(dec, r2.Bytes()) {
|
if !bytes.Equal(dec, r2.Bytes()) {
|
||||||
t.Fatal("unexpected xor at", i, "except", hex.EncodeToString(r2.Bytes()), "got", hex.EncodeToString(dec))
|
t.Fatal("unexpected xor at", i, "except", hex.EncodeToString(r2.Bytes()), "got", hex.EncodeToString(dec))
|
||||||
}
|
}
|
||||||
|
runtime.KeepAlive(dec)
|
||||||
if seq != uint32(i) {
|
if seq != uint32(i) {
|
||||||
t.Fatal("unexpected xor at", i, "seq", seq)
|
t.Fatal("unexpected xor at", i, "seq", seq)
|
||||||
}
|
}
|
||||||
@@ -53,11 +55,11 @@ func TestXChacha20(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
for i := 0; i < 4096; i++ {
|
for i := 0; i < 4096; i++ {
|
||||||
db, err := decode(aead, uint16(i), encode(aead, uint16(i), data[:i]))
|
db, err := decode(aead, uint16(i), encode(aead, uint16(i), data[:i]).Trans().Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if !bytes.Equal(db, data[:i]) {
|
if !bytes.Equal(db.Bytes(), data[:i]) {
|
||||||
t.Fatal("unexpected preshared at idx(len)", i, "addt", uint16(i))
|
t.Fatal("unexpected preshared at idx(len)", i, "addt", uint16(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/fumiama/WireGold/gold/p2p"
|
"github.com/fumiama/WireGold/gold/p2p"
|
||||||
"github.com/fumiama/WireGold/helper"
|
"github.com/fumiama/WireGold/helper"
|
||||||
base14 "github.com/fumiama/go-base16384"
|
base14 "github.com/fumiama/go-base16384"
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -26,7 +27,7 @@ type Link struct {
|
|||||||
// 收到的包的队列
|
// 收到的包的队列
|
||||||
// 没有下层 nic 时
|
// 没有下层 nic 时
|
||||||
// 包会分发到此
|
// 包会分发到此
|
||||||
pipe chan *head.Packet
|
pipe chan *orbyte.Item[head.Packet]
|
||||||
// peer 的虚拟 ip
|
// peer 的虚拟 ip
|
||||||
peerip net.IP
|
peerip net.IP
|
||||||
// peer 的公网 endpoint
|
// peer 的公网 endpoint
|
||||||
|
|||||||
@@ -19,56 +19,12 @@ import (
|
|||||||
"github.com/fumiama/WireGold/gold/head"
|
"github.com/fumiama/WireGold/gold/head"
|
||||||
"github.com/fumiama/WireGold/gold/p2p"
|
"github.com/fumiama/WireGold/gold/p2p"
|
||||||
"github.com/fumiama/WireGold/helper"
|
"github.com/fumiama/WireGold/helper"
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
const lstnbufgragsz = 65536
|
const lstnbufgragsz = 65536
|
||||||
|
|
||||||
type lstnq struct {
|
|
||||||
index int
|
|
||||||
addr p2p.EndPoint
|
|
||||||
buf []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type listenqueue chan lstnq
|
|
||||||
|
|
||||||
func (q listenqueue) listen(m *Me, hasntfinished []sync.Mutex) {
|
|
||||||
recvtotlcnt := uint64(0)
|
|
||||||
recvloopcnt := uint16(0)
|
|
||||||
recvlooptime := time.Now().UnixMilli()
|
|
||||||
for lstn := range q {
|
|
||||||
recvtotlcnt += uint64(len(lstn.buf))
|
|
||||||
recvloopcnt++
|
|
||||||
if recvloopcnt%m.speedloop == 0 {
|
|
||||||
now := time.Now().UnixMilli()
|
|
||||||
logrus.Infof("[listen] queue recv avg speed: %.2f KB/s", float64(recvtotlcnt)/float64(now-recvlooptime))
|
|
||||||
recvtotlcnt = 0
|
|
||||||
recvlooptime = now
|
|
||||||
}
|
|
||||||
packet := m.wait(lstn.buf[:len(lstn.buf):lstnbufgragsz])
|
|
||||||
if packet == nil {
|
|
||||||
if lstn.index < 0 {
|
|
||||||
if config.ShowDebugLog {
|
|
||||||
logrus.Debugln("[listen] queue waiting")
|
|
||||||
}
|
|
||||||
helper.PutBytes(lstn.buf)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if config.ShowDebugLog {
|
|
||||||
logrus.Debugln("[listen] queue waiting, unlock index", lstn.index)
|
|
||||||
}
|
|
||||||
hasntfinished[lstn.index].Unlock()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if lstn.index >= 0 {
|
|
||||||
go m.dispatch(packet, lstn.addr, lstn.index, hasntfinished[lstn.index].Unlock)
|
|
||||||
} else {
|
|
||||||
go m.dispatch(packet, lstn.addr, lstn.index, func() {
|
|
||||||
helper.PutBytes(lstn.buf)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听本机 endpoint
|
// 监听本机 endpoint
|
||||||
func (m *Me) listen() (conn p2p.Conn, err error) {
|
func (m *Me) listen() (conn p2p.Conn, err error) {
|
||||||
conn, err = m.ep.Listen()
|
conn, err = m.ep.Listen()
|
||||||
@@ -85,9 +41,6 @@ func (m *Me) listen() (conn p2p.Conn, err error) {
|
|||||||
logrus.Infoln("[listen] use cpu num:", n)
|
logrus.Infoln("[listen] use cpu num:", n)
|
||||||
listenbuf := make([]byte, lstnbufgragsz*n)
|
listenbuf := make([]byte, lstnbufgragsz*n)
|
||||||
hasntfinished := make([]sync.Mutex, n)
|
hasntfinished := make([]sync.Mutex, n)
|
||||||
q := make(listenqueue, n)
|
|
||||||
defer close(q)
|
|
||||||
go q.listen(m, hasntfinished)
|
|
||||||
for {
|
for {
|
||||||
usenewbuf := false
|
usenewbuf := false
|
||||||
i := uint(0)
|
i := uint(0)
|
||||||
@@ -105,13 +58,16 @@ func (m *Me) listen() (conn p2p.Conn, err error) {
|
|||||||
if config.ShowDebugLog && !usenewbuf {
|
if config.ShowDebugLog && !usenewbuf {
|
||||||
logrus.Debugln("[listen] lock index", i)
|
logrus.Debugln("[listen] lock index", i)
|
||||||
}
|
}
|
||||||
var lbf []byte
|
var lbf pbuf.Bytes
|
||||||
if usenewbuf {
|
if usenewbuf {
|
||||||
lbf = helper.MakeBytes(lstnbufgragsz)
|
lbf = pbuf.NewBytes(lstnbufgragsz)
|
||||||
} else {
|
} else {
|
||||||
lbf = listenbuf[i*lstnbufgragsz : (i+1)*lstnbufgragsz]
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[listen] take index", i, "slice", i*lstnbufgragsz, (i+1)*lstnbufgragsz, "cap", lstnbufgragsz)
|
||||||
|
}
|
||||||
|
lbf = pbuf.ParseBytes(listenbuf[i*lstnbufgragsz : (i+1)*lstnbufgragsz : (i+1)*lstnbufgragsz]...)
|
||||||
}
|
}
|
||||||
n, addr, err := conn.ReadFromPeer(lbf)
|
n, addr, err := conn.ReadFromPeer(lbf.Bytes())
|
||||||
if m.connections == nil || errors.Is(err, net.ErrClosed) {
|
if m.connections == nil || errors.Is(err, net.ErrClosed) {
|
||||||
logrus.Warnln("[listen] quit listening")
|
logrus.Warnln("[listen] quit listening")
|
||||||
return
|
return
|
||||||
@@ -138,39 +94,70 @@ func (m *Me) listen() (conn p2p.Conn, err error) {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
lq := lstnq{
|
index := -1
|
||||||
index: -1,
|
|
||||||
addr: addr,
|
|
||||||
buf: lbf[:n],
|
|
||||||
}
|
|
||||||
if !usenewbuf {
|
if !usenewbuf {
|
||||||
lq.index = int(i)
|
index = int(i)
|
||||||
}
|
}
|
||||||
q <- lq
|
go m.waitordispatch(index, addr, lbf.Trans().SliceTo(n), hasntfinished)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Me) dispatch(packet *head.Packet, addr p2p.EndPoint, index int, finish func()) {
|
func (m *Me) waitordispatch(index int, addr p2p.EndPoint, buf pbuf.Bytes, hasntfinished []sync.Mutex) {
|
||||||
defer finish()
|
recvtotlcnt := atomic.AddUint64(&m.recvtotlcnt, uint64(buf.Len()))
|
||||||
|
recvloopcnt := atomic.AddUintptr(&m.recvloopcnt, 1)
|
||||||
|
recvlooptime := atomic.LoadInt64(&m.recvlooptime)
|
||||||
|
if recvloopcnt%uintptr(m.speedloop) == 0 {
|
||||||
|
now := time.Now().UnixMilli()
|
||||||
|
logrus.Infof("[listen] queue recv avg speed: %.2f KB/s", float64(recvtotlcnt)/float64(now-recvlooptime))
|
||||||
|
atomic.StoreUint64(&m.recvtotlcnt, 0)
|
||||||
|
atomic.StoreInt64(&m.recvlooptime, now)
|
||||||
|
}
|
||||||
|
packet := m.wait(buf.Trans())
|
||||||
|
if packet == nil {
|
||||||
|
if index < 0 {
|
||||||
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[listen] queue waiting")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[listen] queue waiting, unlock index", index)
|
||||||
|
}
|
||||||
|
hasntfinished[index].Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[listen] index", index, "dispatch", len(packet.Pointer().Body()), "bytes packet")
|
||||||
|
}
|
||||||
|
if index >= 0 {
|
||||||
|
defer hasntfinished[index].Unlock()
|
||||||
|
m.dispatch(packet, addr, index)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.dispatch(packet, addr, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Me) dispatch(packet *orbyte.Item[head.Packet], addr p2p.EndPoint, index int) {
|
||||||
|
defer runtime.KeepAlive(packet)
|
||||||
|
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
defer logrus.Debugln("[listen] dispatched, unlock index", index)
|
defer logrus.Debugln("[listen] dispatched, unlock index", index)
|
||||||
logrus.Debugln("[listen] start dispatching index", index)
|
logrus.Debugln("[listen] start dispatching index", index)
|
||||||
}
|
}
|
||||||
r := packet.Len() - packet.BodyLen()
|
pp := packet.Pointer()
|
||||||
|
r := pp.Len() - pp.BodyLen()
|
||||||
if r > 0 {
|
if r > 0 {
|
||||||
logrus.Warnln("[listen] @", index, "packet from endpoint", addr, "len", packet.BodyLen(), "is smaller than it declared len", packet.Len(), ", drop it")
|
logrus.Warnln("[listen] @", index, "packet from endpoint", addr, "len", pp.BodyLen(), "is smaller than it declared len", pp.Len(), ", drop it")
|
||||||
packet.Put()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p, ok := m.IsInPeer(packet.Src.String())
|
p, ok := m.IsInPeer(pp.Src.String())
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[listen] @", index, "recv from endpoint", addr, "src", packet.Src, "dst", packet.Dst)
|
logrus.Debugln("[listen] @", index, "recv from endpoint", addr, "src", pp.Src, "dst", pp.Dst)
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
logrus.Warnln("[listen] @", index, "packet from", packet.Src, "to", packet.Dst, "is refused")
|
logrus.Warnln("[listen] @", index, "packet from", pp.Src, "to", pp.Dst, "is refused")
|
||||||
packet.Put()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if helper.IsNilInterface(p.endpoint) || !p.endpoint.Euqal(addr) {
|
if helper.IsNilInterface(p.endpoint) || !p.endpoint.Euqal(addr) {
|
||||||
@@ -185,25 +172,23 @@ func (m *Me) dispatch(packet *head.Packet, addr p2p.EndPoint, index int, finish
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.lastalive)), unsafe.Pointer(&now))
|
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.lastalive)), unsafe.Pointer(&now))
|
||||||
switch {
|
switch {
|
||||||
case p.IsToMe(packet.Dst):
|
case p.IsToMe(pp.Dst):
|
||||||
if !p.Accept(packet.Src) {
|
if !p.Accept(pp.Src) {
|
||||||
logrus.Warnln("[listen] @", index, "refused packet from", packet.Src.String()+":"+strconv.Itoa(int(packet.SrcPort)))
|
logrus.Warnln("[listen] @", index, "refused packet from", pp.Src.String()+":"+strconv.Itoa(int(pp.SrcPort)))
|
||||||
packet.Put()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
addt := packet.AdditionalData()
|
addt := pp.AdditionalData()
|
||||||
var err error
|
var err error
|
||||||
data, err := p.Decode(packet.CipherIndex(), addt, packet.Body())
|
data, err := p.Decode(pp.CipherIndex(), addt, pp.Body())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[listen] @", index, "drop invalid packet key idx:", packet.CipherIndex(), "addt:", addt, "err:", err)
|
logrus.Debugln("[listen] @", index, "drop invalid packet key idx:", pp.CipherIndex(), "addt:", addt, "err:", err)
|
||||||
}
|
}
|
||||||
packet.Put()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
packet.SetBody(data, true)
|
pp.SetBody(data.Trans().Bytes())
|
||||||
if p.usezstd {
|
if p.usezstd {
|
||||||
dec, _ := zstd.NewReader(bytes.NewReader(packet.Body()))
|
dec, _ := zstd.NewReader(bytes.NewReader(pp.Body()))
|
||||||
var err error
|
var err error
|
||||||
w := helper.SelectWriter()
|
w := helper.SelectWriter()
|
||||||
_, err = io.Copy(w, dec)
|
_, err = io.Copy(w, dec)
|
||||||
@@ -212,25 +197,27 @@ func (m *Me) dispatch(packet *head.Packet, addr p2p.EndPoint, index int, finish
|
|||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[listen] @", index, "drop invalid zstd packet:", err)
|
logrus.Debugln("[listen] @", index, "drop invalid zstd packet:", err)
|
||||||
}
|
}
|
||||||
packet.Put()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
packet.SetBody(w.Bytes(), true)
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[listen] @", index, "zstd decoded len:", w.Len())
|
||||||
|
}
|
||||||
|
pp.SetBody(w.TransBytes())
|
||||||
}
|
}
|
||||||
if !packet.IsVaildHash() {
|
if !pp.IsVaildHash() {
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[listen] @", index, "drop invalid hash packet")
|
logrus.Debugln("[listen] @", index, "drop invalid hash packet")
|
||||||
}
|
}
|
||||||
packet.Put()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch packet.Proto {
|
switch pp.Proto {
|
||||||
case head.ProtoHello:
|
case head.ProtoHello:
|
||||||
switch {
|
switch {
|
||||||
case len(packet.Body()) == 0:
|
case len(pp.Body()) == 0:
|
||||||
logrus.Warnln("[listen] @", index, "recv old hello packet, do nothing")
|
logrus.Warnln("[listen] @", index, "recv old hello packet, do nothing")
|
||||||
case packet.Body()[0] == byte(head.HelloPing):
|
case pp.Body()[0] == byte(head.HelloPing):
|
||||||
n, err := p.WriteAndPut(head.NewPacket(head.ProtoHello, m.SrcPort(), p.peerip, m.DstPort(), []byte{byte(head.HelloPong)}), false)
|
n, err := p.WritePacket(head.NewPacketPartial(
|
||||||
|
head.ProtoHello, m.SrcPort(), p.peerip, m.DstPort(), pbuf.ParseBytes(byte(head.HelloPong))), false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logrus.Infoln("[listen] @", index, "recv hello, send", n, "bytes hello ack packet")
|
logrus.Infoln("[listen] @", index, "recv hello, send", n, "bytes hello ack packet")
|
||||||
} else {
|
} else {
|
||||||
@@ -239,57 +226,49 @@ func (m *Me) dispatch(packet *head.Packet, addr p2p.EndPoint, index int, finish
|
|||||||
default:
|
default:
|
||||||
logrus.Infoln("[listen] @", index, "recv hello ack packet, do nothing")
|
logrus.Infoln("[listen] @", index, "recv hello ack packet, do nothing")
|
||||||
}
|
}
|
||||||
packet.Put()
|
|
||||||
case head.ProtoNotify:
|
case head.ProtoNotify:
|
||||||
logrus.Infoln("[listen] @", index, "recv notify from", packet.Src)
|
logrus.Infoln("[listen] @", index, "recv notify from", pp.Src)
|
||||||
go p.onNotify(packet.Body())
|
p.onNotify(pp.Body())
|
||||||
packet.Put()
|
|
||||||
case head.ProtoQuery:
|
case head.ProtoQuery:
|
||||||
logrus.Infoln("[listen] @", index, "recv query from", packet.Src)
|
logrus.Infoln("[listen] @", index, "recv query from", pp.Src)
|
||||||
go p.onQuery(packet.Body())
|
p.onQuery(pp.Body())
|
||||||
packet.Put()
|
|
||||||
case head.ProtoData:
|
case head.ProtoData:
|
||||||
if p.pipe != nil {
|
if p.pipe != nil {
|
||||||
p.pipe <- packet.CopyWithBody()
|
p.pipe <- packet.Copy()
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[listen] @", index, "deliver to pipe of", p.peerip)
|
logrus.Debugln("[listen] @", index, "deliver to pipe of", p.peerip)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, err := m.nic.Write(packet.Body())
|
_, err := m.nic.Write(pp.Body())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorln("[listen] @", index, "deliver", packet.BodyLen(), "bytes data to nic err:", err)
|
logrus.Errorln("[listen] @", index, "deliver", pp.BodyLen(), "bytes data to nic err:", err)
|
||||||
} else if config.ShowDebugLog {
|
} else if config.ShowDebugLog {
|
||||||
logrus.Debugln("[listen] @", index, "deliver", packet.BodyLen(), "bytes data to nic")
|
logrus.Debugln("[listen] @", index, "deliver", pp.BodyLen(), "bytes data to nic")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
packet.Put()
|
|
||||||
default:
|
default:
|
||||||
logrus.Warnln("[listen] @", index, "recv unknown proto:", packet.Proto)
|
logrus.Warnln("[listen] @", index, "recv unknown proto:", pp.Proto)
|
||||||
packet.Put()
|
|
||||||
}
|
}
|
||||||
case p.Accept(packet.Dst):
|
case p.Accept(pp.Dst):
|
||||||
if !p.allowtrans {
|
if !p.allowtrans {
|
||||||
logrus.Warnln("[listen] @", index, "refused to trans packet to", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)))
|
logrus.Warnln("[listen] @", index, "refused to trans packet to", pp.Dst.String()+":"+strconv.Itoa(int(pp.DstPort)))
|
||||||
packet.Put()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 转发
|
// 转发
|
||||||
lnk := m.router.NextHop(packet.Dst.String())
|
lnk := m.router.NextHop(pp.Dst.String())
|
||||||
if lnk == nil {
|
if lnk == nil {
|
||||||
logrus.Warnln("[listen] @", index, "transfer drop packet: nil nexthop")
|
logrus.Warnln("[listen] @", index, "transfer drop packet: nil nexthop")
|
||||||
packet.Put()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n, err := lnk.WriteAndPut(packet, true)
|
n, err := lnk.WritePacket(packet, true)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[listen] @", index, "trans", n, "bytes packet to", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)))
|
logrus.Debugln("[listen] @", index, "trans", n, "bytes packet to", pp.Dst.String()+":"+strconv.Itoa(int(pp.DstPort)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logrus.Errorln("[listen] @", index, "trans packet to", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)), "err:", err)
|
logrus.Errorln("[listen] @", index, "trans packet to", pp.Dst.String()+":"+strconv.Itoa(int(pp.DstPort)), "err:", err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
logrus.Warnln("[listen] @", index, "packet dst", packet.Dst.String()+":"+strconv.Itoa(int(packet.DstPort)), "is not in peers")
|
logrus.Warnln("[listen] @", index, "packet dst", pp.Dst.String()+":"+strconv.Itoa(int(pp.DstPort)), "is not in peers")
|
||||||
packet.Put()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/FloatTech/ttl"
|
"github.com/FloatTech/ttl"
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
"github.com/fumiama/water/waterutil"
|
"github.com/fumiama/water/waterutil"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@@ -46,13 +48,19 @@ type Me struct {
|
|||||||
// 本机路由表
|
// 本机路由表
|
||||||
router *Router
|
router *Router
|
||||||
// 本机未接收完全分片池
|
// 本机未接收完全分片池
|
||||||
recving *ttl.Cache[uint64, *head.Packet]
|
recving *ttl.Cache[uint64, *orbyte.Item[head.Packet]]
|
||||||
// 抗重放攻击记录池
|
// 抗重放攻击记录池
|
||||||
recved *ttl.Cache[uint64, bool]
|
recved *ttl.Cache[uint64, struct{}]
|
||||||
// 本机上层配置
|
// 本机上层配置
|
||||||
srcport, dstport, mtu, speedloop uint16
|
srcport, dstport, mtu, speedloop uint16
|
||||||
// 报头掩码
|
// 报头掩码
|
||||||
mask uint64
|
mask uint64
|
||||||
|
// 本机总接收字节数
|
||||||
|
recvtotlcnt uint64
|
||||||
|
// 上一次触发循环计数时间
|
||||||
|
recvlooptime int64
|
||||||
|
// 本机总接收数据包计数
|
||||||
|
recvloopcnt uintptr
|
||||||
// 是否进行 base16384 编码
|
// 是否进行 base16384 编码
|
||||||
base14 bool
|
base14 bool
|
||||||
// 本机网络端点初始化配置
|
// 本机网络端点初始化配置
|
||||||
@@ -122,12 +130,13 @@ func NewMe(cfg *MyConfig) (m Me) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
m.mask = cfg.Mask
|
m.mask = cfg.Mask
|
||||||
|
m.recvlooptime = time.Now().UnixMilli()
|
||||||
m.base14 = cfg.Base14
|
m.base14 = cfg.Base14
|
||||||
var buf [8]byte
|
var buf [8]byte
|
||||||
binary.BigEndian.PutUint64(buf[:], m.mask)
|
binary.BigEndian.PutUint64(buf[:], m.mask)
|
||||||
logrus.Infoln("[me] xor mask", hex.EncodeToString(buf[:]))
|
logrus.Infoln("[me] xor mask", hex.EncodeToString(buf[:]))
|
||||||
m.recving = ttl.NewCache[uint64, *head.Packet](time.Second * 30)
|
m.recving = ttl.NewCache[uint64, *orbyte.Item[head.Packet]](time.Second * 10)
|
||||||
m.recved = ttl.NewCache[uint64, bool](time.Second * 30)
|
m.recved = ttl.NewCache[uint64, struct{}](time.Minute)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +163,7 @@ func (m *Me) Restart() error {
|
|||||||
}
|
}
|
||||||
m.me = ip
|
m.me = ip
|
||||||
m.subnet = *cidr
|
m.subnet = *cidr
|
||||||
|
m.recvlooptime = time.Now().UnixMilli()
|
||||||
m.conn, err = m.listen()
|
m.conn, err = m.listen()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -280,11 +290,10 @@ func (m *Me) sendAllSameDst(packet []byte) (n int) {
|
|||||||
logrus.Warnln("[me] drop packet to", dst.String()+":"+strconv.Itoa(int(m.DstPort())), ": nil nexthop")
|
logrus.Warnln("[me] drop packet to", dst.String()+":"+strconv.Itoa(int(m.DstPort())), ": nil nexthop")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pcp := helper.MakeBytes(len(packet))
|
pcp := pbuf.NewBytes(len(packet))
|
||||||
copy(pcp, packet)
|
copy(pcp.Bytes(), packet)
|
||||||
go func(packet []byte) {
|
go func(packet pbuf.Bytes) {
|
||||||
defer helper.PutBytes(packet)
|
_, err := lnk.WritePacket(head.NewPacketPartial(head.ProtoData, m.SrcPort(), lnk.peerip, m.DstPort(), packet), false)
|
||||||
_, err := lnk.WriteAndPut(head.NewPacket(head.ProtoData, m.SrcPort(), lnk.peerip, m.DstPort(), packet), false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Warnln("[me] write to peer", lnk.peerip, "err:", err)
|
logrus.Warnln("[me] write to peer", lnk.peerip, "err:", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package link
|
package link
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -12,6 +13,8 @@ import (
|
|||||||
"github.com/fumiama/WireGold/gold/head"
|
"github.com/fumiama/WireGold/gold/head"
|
||||||
"github.com/fumiama/WireGold/gold/p2p"
|
"github.com/fumiama/WireGold/gold/p2p"
|
||||||
"github.com/fumiama/WireGold/helper"
|
"github.com/fumiama/WireGold/helper"
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 保持 NAT
|
// 保持 NAT
|
||||||
@@ -35,7 +38,7 @@ func (l *Link) keepAlive(dur int64) {
|
|||||||
logrus.Infoln("[nat] re-connect me succeeded")
|
logrus.Infoln("[nat] re-connect me succeeded")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
n, err := l.WriteAndPut(head.NewPacket(head.ProtoHello, l.me.srcport, l.peerip, l.me.dstport, []byte{byte(head.HelloPing)}), false)
|
n, err := l.WritePacket(head.NewPacketPartial(head.ProtoHello, l.me.srcport, l.peerip, l.me.dstport, pbuf.ParseBytes(byte(head.HelloPing))), false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logrus.Infoln("[nat] send", n, "bytes keep alive packet")
|
logrus.Infoln("[nat] send", n, "bytes keep alive packet")
|
||||||
} else {
|
} else {
|
||||||
@@ -131,12 +134,14 @@ func (l *Link) onQuery(packet []byte) {
|
|||||||
logrus.Infoln("[nat] query wrap", len(notify), "notify")
|
logrus.Infoln("[nat] query wrap", len(notify), "notify")
|
||||||
w := helper.SelectWriter()
|
w := helper.SelectWriter()
|
||||||
_ = json.NewEncoder(w).Encode(¬ify)
|
_ = json.NewEncoder(w).Encode(¬ify)
|
||||||
_, err = l.WriteAndPut(head.NewPacket(head.ProtoNotify, l.me.srcport, l.peerip, l.me.dstport, w.Bytes()), false)
|
_, err = l.WritePacket(head.NewPacketPartial(
|
||||||
|
head.ProtoNotify, l.me.srcport, l.peerip, l.me.dstport,
|
||||||
|
pbuf.BufferItemToBytes((*orbyte.Item[bytes.Buffer])(w).Trans()),
|
||||||
|
), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorln("[nat] notify peer", l, "err:", err)
|
logrus.Errorln("[nat] notify peer", l, "err:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
helper.PutWriter(w)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +157,10 @@ func (l *Link) sendquery(tick time.Duration, peers ...string) {
|
|||||||
t := time.NewTicker(tick)
|
t := time.NewTicker(tick)
|
||||||
for range t.C {
|
for range t.C {
|
||||||
logrus.Infoln("[nat] query send query to", l.peerip)
|
logrus.Infoln("[nat] query send query to", l.peerip)
|
||||||
_, err = l.WriteAndPut(head.NewPacket(head.ProtoQuery, l.me.srcport, l.peerip, l.me.dstport, data), false)
|
_, err = l.WritePacket(head.NewPacketPartial(
|
||||||
|
head.ProtoQuery, l.me.srcport, l.peerip, l.me.dstport,
|
||||||
|
pbuf.ParseBytes(data...),
|
||||||
|
), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorln("[nat] query write err:", err)
|
logrus.Errorln("[nat] query write err:", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/fumiama/WireGold/gold/head"
|
"github.com/fumiama/WireGold/gold/head"
|
||||||
"github.com/fumiama/WireGold/gold/p2p"
|
"github.com/fumiama/WireGold/gold/p2p"
|
||||||
curve "github.com/fumiama/go-x25519"
|
curve "github.com/fumiama/go-x25519"
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
)
|
)
|
||||||
@@ -49,7 +50,7 @@ func (m *Me) AddPeer(cfg *PeerConfig) (l *Link) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !cfg.NoPipe {
|
if !cfg.NoPipe {
|
||||||
l.pipe = make(chan *head.Packet, 32)
|
l.pipe = make(chan *orbyte.Item[head.Packet], 65536)
|
||||||
}
|
}
|
||||||
var k, p []byte
|
var k, p []byte
|
||||||
if cfg.PubicKey != nil {
|
if cfg.PubicKey != nil {
|
||||||
|
|||||||
@@ -9,129 +9,123 @@ import (
|
|||||||
"github.com/fumiama/WireGold/config"
|
"github.com/fumiama/WireGold/config"
|
||||||
"github.com/fumiama/WireGold/gold/head"
|
"github.com/fumiama/WireGold/gold/head"
|
||||||
base14 "github.com/fumiama/go-base16384"
|
base14 "github.com/fumiama/go-base16384"
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Read 从 peer 收包
|
// Read 从 peer 收包
|
||||||
func (l *Link) Read() *head.Packet {
|
func (l *Link) Read() *orbyte.Item[head.Packet] {
|
||||||
return <-l.pipe
|
return <-l.pipe
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Me) wait(data []byte) *head.Packet {
|
func (m *Me) wait(data pbuf.Bytes) *orbyte.Item[head.Packet] {
|
||||||
if len(data) < head.PacketHeadLen { // not a valid packet
|
if data.Len() < head.PacketHeadLen { // not a valid packet
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[recv] invalid data len", len(data))
|
logrus.Debugln("[recv] invalid data len", data.Len())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
bound := 64
|
bound := 64
|
||||||
endl := "..."
|
endl := "..."
|
||||||
if len(data) < bound {
|
if data.Len() < bound {
|
||||||
bound = len(data)
|
bound = data.Len()
|
||||||
endl = "."
|
endl = "."
|
||||||
}
|
}
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[recv] data bytes, len", len(data), "val", hex.EncodeToString(data[:bound]), endl)
|
logrus.Debugln("[recv] data bytes, len", data.Len(), "val", hex.EncodeToString(data.Bytes()[:bound]), endl)
|
||||||
}
|
}
|
||||||
if m.base14 {
|
if m.base14 {
|
||||||
data = base14.Decode(data)
|
data = pbuf.ParseBytes(base14.Decode(data.Bytes())...)
|
||||||
if len(data) < bound {
|
if data.Len() < bound {
|
||||||
bound = len(data)
|
bound = data.Len()
|
||||||
endl = "."
|
endl = "."
|
||||||
}
|
}
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[recv] data b14ed, len", len(data), "val", hex.EncodeToString(data[:bound]), endl)
|
logrus.Debugln("[recv] data b14ed, len", data.Len(), "val", hex.EncodeToString(data.Bytes()[:bound]), endl)
|
||||||
}
|
}
|
||||||
if len(data) < head.PacketHeadLen { // not a valid packet
|
if data.Len() < head.PacketHeadLen { // not a valid packet
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[recv] invalid data len", len(data))
|
logrus.Debugln("[recv] invalid data len", data.Len())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seq, data := m.xordec(data)
|
seq, dat := m.xordec(data.Trans().Bytes())
|
||||||
if len(data) < bound {
|
if len(dat) < bound {
|
||||||
bound = len(data)
|
bound = len(dat)
|
||||||
endl = "."
|
endl = "."
|
||||||
}
|
}
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[recv] data xored, len", len(data), "val", hex.EncodeToString(data[:bound]), endl)
|
logrus.Debugln("[recv] data xored, len", len(dat), "val", hex.EncodeToString(dat[:bound]), endl)
|
||||||
}
|
}
|
||||||
if len(data) < head.PacketHeadLen { // not a valid packet
|
header, err := head.ParsePacketHeader(dat)
|
||||||
|
if err != nil { // not a valid packet
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[recv] invalid data len", len(data))
|
logrus.Debugln("[recv] invalid packet header:", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
flags := head.Flags(data)
|
if !header.Pointer().Flags.IsValid() {
|
||||||
if !flags.IsValid() {
|
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[recv] drop invalid flags packet:", hex.EncodeToString(data[11:12]), hex.EncodeToString(data[10:11]))
|
logrus.Debugln("[recv] drop invalid flags packet:", header.Pointer().Flags)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
crc := head.CRC64(data)
|
crc := header.Pointer().CRC64()
|
||||||
crclog := crc
|
crclog := crc
|
||||||
crc ^= (uint64(seq) << 16)
|
crc ^= (uint64(seq) << 16)
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugf("[recv] packet crc %016x, seq %08x, xored crc %016x", crclog, seq, crc)
|
logrus.Debugf("[recv] packet crc %016x, seq %08x, xored crc %016x", crclog, seq, crc)
|
||||||
}
|
}
|
||||||
if m.recved.Get(crc) {
|
if _, got := m.recved.GetOrSet(crc, struct{}{}); got {
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[recv] ignore duplicated crc packet", strconv.FormatUint(crc, 16))
|
logrus.Debugln("[recv] ignore duplicated crc packet", strconv.FormatUint(crc, 16))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
m.recved.Set(crc, true)
|
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[recv]", strconv.FormatUint(crc, 16), len(data), "bytes data with flag", hex.EncodeToString(data[11:12]), hex.EncodeToString(data[10:11]))
|
logrus.Debugln(
|
||||||
|
"[recv]", strconv.FormatUint(crc, 16),
|
||||||
|
len(dat), "bytes data with flag", header.Pointer().Flags,
|
||||||
|
"offset", header.Pointer().Flags.Offset(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if flags.IsSingle() || flags.NoFrag() {
|
if header.Pointer().Flags.IsSingle() || header.Pointer().Flags.NoFrag() {
|
||||||
h := head.SelectPacket()
|
ok := header.Pointer().ParseData(dat)
|
||||||
_, err := h.Unmarshal(data)
|
if !ok {
|
||||||
if err != nil {
|
logrus.Errorln("[recv]", strconv.FormatUint(crc, 16), "unexpected !ok")
|
||||||
logrus.Errorln("[recv]", strconv.FormatUint(crc, 16), "unmarshal err:", err)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return h
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[recv]", strconv.FormatUint(crc, 16), len(dat), "bytes full data waited")
|
||||||
|
}
|
||||||
|
return header
|
||||||
}
|
}
|
||||||
|
|
||||||
crchash := crc64.New(crc64.MakeTable(crc64.ISO))
|
crchash := crc64.New(crc64.MakeTable(crc64.ISO))
|
||||||
_, _ = crchash.Write(head.Hash(data))
|
_, _ = crchash.Write(head.Hash(data.Bytes()))
|
||||||
var buf [4]byte
|
var buf [4]byte
|
||||||
binary.LittleEndian.PutUint32(buf[:], seq)
|
binary.LittleEndian.PutUint32(buf[:], seq)
|
||||||
_, _ = crchash.Write(buf[:])
|
_, _ = crchash.Write(buf[:])
|
||||||
hsh := crchash.Sum64()
|
hsh := crchash.Sum64()
|
||||||
h := m.recving.Get(hsh)
|
h, got := m.recving.GetOrSet(hsh, header)
|
||||||
if h != nil {
|
if got && h == header {
|
||||||
if config.ShowDebugLog {
|
panic("unexpected multi-put found")
|
||||||
logrus.Debugln("[recv]", strconv.FormatUint(crc, 16), "get another frag part of", strconv.FormatUint(hsh, 16))
|
|
||||||
}
|
|
||||||
ok, err := h.Unmarshal(data)
|
|
||||||
if err == nil {
|
|
||||||
if ok {
|
|
||||||
m.recving.Delete(hsh)
|
|
||||||
if config.ShowDebugLog {
|
|
||||||
logrus.Debugln("[recv]", strconv.FormatUint(crc, 16), "all parts of", strconv.FormatUint(hsh, 16), "has reached")
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
h.Put()
|
|
||||||
logrus.Errorln("[recv]", strconv.FormatUint(crc, 16), "unmarshal err:", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[recv]", strconv.FormatUint(crc, 16), "get new frag part of", strconv.FormatUint(hsh, 16))
|
logrus.Debugln("[recv]", strconv.FormatUint(crc, 16), "get frag part of", strconv.FormatUint(hsh, 16), "isnew:", !got)
|
||||||
}
|
}
|
||||||
h = head.SelectPacket()
|
ok := h.Pointer().ParseData(dat)
|
||||||
_, err := h.Unmarshal(data)
|
if !ok {
|
||||||
if err != nil {
|
if config.ShowDebugLog {
|
||||||
h.Put()
|
logrus.Debugln("[recv]", strconv.FormatUint(crc, 16), "wait other frag parts of", strconv.FormatUint(hsh, 16), "isnew:", !got)
|
||||||
logrus.Errorln("[recv]", strconv.FormatUint(crc, 16), "unmarshal err:", err)
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
m.recving.Set(hsh, h)
|
m.recving.Delete(hsh)
|
||||||
return nil
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[recv]", strconv.FormatUint(crc, 16), "all parts of", strconv.FormatUint(hsh, 16), "has reached")
|
||||||
|
}
|
||||||
|
return h
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/klauspost/compress/zstd"
|
"github.com/klauspost/compress/zstd"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@@ -17,6 +18,8 @@ import (
|
|||||||
"github.com/fumiama/WireGold/gold/head"
|
"github.com/fumiama/WireGold/gold/head"
|
||||||
"github.com/fumiama/WireGold/helper"
|
"github.com/fumiama/WireGold/helper"
|
||||||
base14 "github.com/fumiama/go-base16384"
|
base14 "github.com/fumiama/go-base16384"
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -24,15 +27,19 @@ var (
|
|||||||
ErrTTL = errors.New("ttl exceeded")
|
ErrTTL = errors.New("ttl exceeded")
|
||||||
)
|
)
|
||||||
|
|
||||||
// WriteAndPut 向 peer 发包并将包放回缓存池
|
func randseq(i uint16) uint32 {
|
||||||
func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) {
|
|
||||||
defer p.Put()
|
|
||||||
teatype := l.randkeyidx()
|
|
||||||
sndcnt := uint16(l.incgetsndcnt())
|
|
||||||
var buf [4]byte
|
var buf [4]byte
|
||||||
_, _ = crand.Read(buf[:2])
|
_, _ = crand.Read(buf[:2])
|
||||||
binary.BigEndian.PutUint16(buf[2:4], sndcnt)
|
binary.BigEndian.PutUint16(buf[2:4], i)
|
||||||
seq := binary.BigEndian.Uint32(buf[:])
|
return binary.BigEndian.Uint32(buf[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// WritePacket 向 peer 发包
|
||||||
|
func (l *Link) WritePacket(p *orbyte.Item[head.Packet], istransfer bool) (n int, err error) {
|
||||||
|
pp := p.Pointer()
|
||||||
|
teatype := l.randkeyidx()
|
||||||
|
sndcnt := uint16(l.incgetsndcnt())
|
||||||
|
seq := randseq(sndcnt)
|
||||||
mtu := l.mtu
|
mtu := l.mtu
|
||||||
if l.mturandomrange > 0 {
|
if l.mturandomrange > 0 {
|
||||||
mtu -= uint16(rand.Intn(int(l.mturandomrange)))
|
mtu -= uint16(rand.Intn(int(l.mturandomrange)))
|
||||||
@@ -41,48 +48,48 @@ func (l *Link) WriteAndPut(p *head.Packet, istransfer bool) (n int, err error) {
|
|||||||
logrus.Debugln("[send] mtu:", mtu, ", addt:", sndcnt&0x07ff, ", key index:", teatype)
|
logrus.Debugln("[send] mtu:", mtu, ", addt:", sndcnt&0x07ff, ", key index:", teatype)
|
||||||
}
|
}
|
||||||
if !istransfer {
|
if !istransfer {
|
||||||
l.encrypt(p, sndcnt, teatype)
|
l.encrypt(pp, sndcnt, teatype)
|
||||||
}
|
}
|
||||||
delta := (int(mtu) - head.PacketHeadLen) & 0x0000fff8
|
delta := (int(mtu) - head.PacketHeadLen) & 0x0000fff8
|
||||||
if delta <= 0 {
|
if delta <= 0 {
|
||||||
logrus.Warnln("[send] reset invalid data frag len", delta, "to 8")
|
logrus.Warnln("[send] reset invalid data frag len", delta, "to 8")
|
||||||
delta = 8
|
delta = 8
|
||||||
}
|
}
|
||||||
remlen := p.BodyLen()
|
remlen := pp.BodyLen()
|
||||||
if remlen <= delta {
|
if remlen <= delta {
|
||||||
return l.write(p, teatype, sndcnt, uint32(remlen), 0, istransfer, false, seq)
|
return l.write(p, teatype, sndcnt, uint32(remlen), 0, istransfer, false, seq)
|
||||||
}
|
}
|
||||||
if istransfer && p.Flags.DontFrag() && remlen > delta {
|
if istransfer && pp.Flags.DontFrag() && remlen > delta {
|
||||||
return 0, ErrDropBigDontFragPkt
|
return 0, ErrDropBigDontFragPkt
|
||||||
}
|
}
|
||||||
ttl := p.TTL
|
ttl := pp.TTL
|
||||||
totl := uint32(remlen)
|
totl := uint32(remlen)
|
||||||
pos := 0
|
pos := 0
|
||||||
packet := p.Copy()
|
packet := head.ParsePacket(pp.ShallowCopy())
|
||||||
for remlen > delta {
|
for remlen > delta {
|
||||||
remlen -= delta
|
remlen -= delta
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[send] split frag [", pos, "~", pos+delta, "], remain:", remlen)
|
logrus.Debugln("[send] split frag [", pos, "~", pos+delta, "], remain:", remlen)
|
||||||
}
|
}
|
||||||
packet.CropBody(pos, pos+delta)
|
packet.Pointer().CropBody(pos, pos+delta)
|
||||||
cnt, err := l.write(packet, teatype, sndcnt, totl, uint16(pos>>3), istransfer, true, seq)
|
cnt, err := l.write(packet, teatype, sndcnt, totl, uint16(pos>>3), istransfer, true, seq)
|
||||||
n += cnt
|
n += cnt
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
packet.TTL = ttl
|
packet.Pointer().TTL = ttl
|
||||||
pos += delta
|
pos += delta
|
||||||
}
|
}
|
||||||
packet.Put()
|
|
||||||
if remlen > 0 {
|
if remlen > 0 {
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[send] last frag [", pos, "~", pos+remlen, "]")
|
logrus.Debugln("[send] last frag [", pos, "~", pos+remlen, "]")
|
||||||
}
|
}
|
||||||
p.CropBody(pos, pos+remlen)
|
pp.CropBody(pos, pos+remlen)
|
||||||
cnt := 0
|
cnt := 0
|
||||||
cnt, err = l.write(p, teatype, sndcnt, totl, uint16(pos>>3), istransfer, false, seq)
|
cnt, err = l.write(p, teatype, sndcnt, totl, uint16(pos>>3), istransfer, false, seq)
|
||||||
n += cnt
|
n += cnt
|
||||||
}
|
}
|
||||||
|
runtime.KeepAlive(p)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,24 +101,27 @@ func (l *Link) encrypt(p *head.Packet, sndcnt uint16, teatype uint8) {
|
|||||||
data := p.Body()
|
data := p.Body()
|
||||||
if l.usezstd {
|
if l.usezstd {
|
||||||
w := helper.SelectWriter()
|
w := helper.SelectWriter()
|
||||||
defer helper.PutWriter(w)
|
|
||||||
enc, _ := zstd.NewWriter(w, zstd.WithEncoderLevel(zstd.SpeedFastest))
|
enc, _ := zstd.NewWriter(w, zstd.WithEncoderLevel(zstd.SpeedFastest))
|
||||||
_, _ = io.Copy(enc, bytes.NewReader(data))
|
_, _ = io.Copy(enc, bytes.NewReader(data))
|
||||||
enc.Close()
|
enc.Close()
|
||||||
data = w.Bytes()
|
data = w.TransBytes()
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[send] data len after zstd:", len(data))
|
logrus.Debugln("[send] data len after zstd:", len(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.SetBody(l.Encode(teatype, sndcnt&0x07ff, data), true)
|
p.SetBody(l.Encode(teatype, sndcnt&0x07ff, data).Trans().Bytes())
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[send] data len after xchacha20:", p.BodyLen(), "addt:", sndcnt)
|
logrus.Debugln("[send] data len after xchacha20:", p.BodyLen(), "addt:", sndcnt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// write 向 peer 发包
|
// write 向 peer 发包
|
||||||
func (l *Link) write(p *head.Packet, teatype uint8, additional uint16, datasz uint32, offset uint16, istransfer, hasmore bool, seq uint32) (int, error) {
|
func (l *Link) write(
|
||||||
if p.DecreaseAndGetTTL() <= 0 {
|
p *orbyte.Item[head.Packet], teatype uint8, additional uint16,
|
||||||
|
datasz uint32, offset uint16, istransfer,
|
||||||
|
hasmore bool, seq uint32,
|
||||||
|
) (int, error) {
|
||||||
|
if p.Pointer().DecreaseAndGetTTL() <= 0 {
|
||||||
return 0, ErrTTL
|
return 0, ErrTTL
|
||||||
}
|
}
|
||||||
if l.doublepacket {
|
if l.doublepacket {
|
||||||
@@ -121,26 +131,28 @@ func (l *Link) write(p *head.Packet, teatype uint8, additional uint16, datasz ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write 向 peer 发一个包
|
// write 向 peer 发一个包
|
||||||
func (l *Link) writeonce(p *head.Packet, teatype uint8, additional uint16, datasz uint32, offset uint16, istransfer, hasmore bool, seq uint32) (int, error) {
|
func (l *Link) writeonce(
|
||||||
|
p *orbyte.Item[head.Packet], teatype uint8, additional uint16,
|
||||||
|
datasz uint32, offset uint16,
|
||||||
|
istransfer, hasmore bool, seq uint32,
|
||||||
|
) (int, error) {
|
||||||
peerep := l.endpoint
|
peerep := l.endpoint
|
||||||
if helper.IsNilInterface(peerep) {
|
if helper.IsNilInterface(peerep) {
|
||||||
return 0, errors.New("nil endpoint of " + p.Dst.String())
|
return 0, errors.New("nil endpoint of " + p.Pointer().Dst.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
var d []byte
|
var d pbuf.Bytes
|
||||||
var cl func()
|
|
||||||
// TODO: now all packet allow frag, adapt to DF
|
// TODO: now all packet allow frag, adapt to DF
|
||||||
if istransfer {
|
if istransfer {
|
||||||
d, cl = p.Marshal(nil, 0, 0, 0, offset, false, hasmore)
|
d = p.Pointer().MarshalWith(nil, 0, 0, 0, offset, false, hasmore)
|
||||||
} else {
|
} else {
|
||||||
d, cl = p.Marshal(l.me.me, teatype, additional, datasz, offset, false, hasmore)
|
d = p.Pointer().MarshalWith(l.me.me, teatype, additional, datasz, offset, false, hasmore)
|
||||||
}
|
}
|
||||||
defer cl()
|
|
||||||
|
|
||||||
bound := 64
|
bound := 64
|
||||||
endl := "..."
|
endl := "..."
|
||||||
if len(d) < bound {
|
if d.Len() < bound {
|
||||||
bound = len(d)
|
bound = d.Len()
|
||||||
endl = "."
|
endl = "."
|
||||||
}
|
}
|
||||||
conn := l.me.conn
|
conn := l.me.conn
|
||||||
@@ -148,17 +160,15 @@ func (l *Link) writeonce(p *head.Packet, teatype uint8, additional uint16, datas
|
|||||||
return 0, io.ErrClosedPipe
|
return 0, io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
|
logrus.Debugln("[send] write", d.Len(), "bytes data from ep", conn.LocalAddr(), "to", peerep, "offset", fmt.Sprintf("%04x", offset), "crc", fmt.Sprintf("%016x", p.Pointer().CRC64()))
|
||||||
logrus.Debugln("[send] write", len(d), "bytes data from ep", conn.LocalAddr(), "to", peerep, "offset", fmt.Sprintf("%04x", offset), "crc", fmt.Sprintf("%016x", p.CRC64()))
|
logrus.Debugln("[send] data bytes", hex.EncodeToString(d.Bytes()[:bound]), endl)
|
||||||
logrus.Debugln("[send] data bytes", hex.EncodeToString(d[:bound]), endl)
|
|
||||||
}
|
}
|
||||||
d = l.me.xorenc(d, seq)
|
d = l.me.xorenc(d.Bytes(), seq)
|
||||||
if l.me.base14 {
|
if l.me.base14 {
|
||||||
d = base14.Encode(d)
|
d = pbuf.ParseBytes(base14.Encode(d.Bytes())...)
|
||||||
}
|
}
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[send] data xored", hex.EncodeToString(d[:bound]), endl)
|
logrus.Debugln("[send] data xored", hex.EncodeToString(d.Bytes()[:bound]), endl)
|
||||||
}
|
}
|
||||||
defer helper.PutBytes(d)
|
return conn.WriteToPeer(d.Trans().Bytes(), peerep)
|
||||||
return conn.WriteToPeer(d, peerep)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
package tcp
|
package tcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fumiama/WireGold/config"
|
"github.com/fumiama/WireGold/config"
|
||||||
"github.com/fumiama/WireGold/helper"
|
"github.com/fumiama/WireGold/helper"
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,17 +37,19 @@ var (
|
|||||||
type packet struct {
|
type packet struct {
|
||||||
typ packetType
|
typ packetType
|
||||||
len uint16
|
len uint16
|
||||||
dat []byte
|
dat pbuf.Bytes
|
||||||
io.ReaderFrom
|
io.ReaderFrom
|
||||||
io.WriterTo
|
io.WriterTo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *packet) pack() (net.Buffers, func()) {
|
func (p *packet) pack() (net.Buffers, func()) {
|
||||||
d, cl := helper.OpenWriterF(func(w *helper.Writer) {
|
d := helper.NewWriterF(func(w *helper.Writer) {
|
||||||
w.WriteByte(byte(p.typ))
|
w.WriteByte(byte(p.typ))
|
||||||
w.WriteUInt16(p.len)
|
w.WriteUInt16(p.len)
|
||||||
})
|
})
|
||||||
return net.Buffers{magicbuf, d, p.dat}, cl
|
return net.Buffers{magicbuf, d.Bytes(), p.dat.Bytes()}, func() {
|
||||||
|
runtime.KeepAlive(d)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *packet) Read(_ []byte) (int, error) {
|
func (p *packet) Read(_ []byte) (int, error) {
|
||||||
@@ -81,7 +87,7 @@ func (p *packet) ReadFrom(r io.Reader) (n int64, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.dat = w.Bytes()
|
p.dat = pbuf.BufferItemToBytes((*orbyte.Item[bytes.Buffer])(w).Trans())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
"github.com/fumiama/WireGold/config"
|
"github.com/fumiama/WireGold/config"
|
||||||
"github.com/fumiama/WireGold/gold/p2p"
|
"github.com/fumiama/WireGold/gold/p2p"
|
||||||
"github.com/fumiama/WireGold/helper"
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EndPoint struct {
|
type EndPoint struct {
|
||||||
@@ -377,9 +377,8 @@ func (conn *Conn) ReadFromPeer(b []byte) (int, p2p.EndPoint, error) {
|
|||||||
if p.pckt.typ == packetTypeNormal {
|
if p.pckt.typ == packetTypeNormal {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
defer helper.PutBytes(p.pckt.dat)
|
|
||||||
}
|
}
|
||||||
n := copy(b, p.pckt.dat)
|
n := copy(b, p.pckt.dat.Bytes())
|
||||||
return n, p.addr, nil
|
return n, p.addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,7 +452,7 @@ RECONNECT:
|
|||||||
cnt, err := io.Copy(tcpconn, &packet{
|
cnt, err := io.Copy(tcpconn, &packet{
|
||||||
typ: packetTypeNormal,
|
typ: packetTypeNormal,
|
||||||
len: uint16(len(b)),
|
len: uint16(len(b)),
|
||||||
dat: b,
|
dat: pbuf.ParseBytes(b...),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if subc == nil {
|
if subc == nil {
|
||||||
|
|||||||
@@ -1,45 +1,10 @@
|
|||||||
package helper
|
package helper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://github.com/Mrs4s/MiraiGo/blob/master/binary/pool.go
|
|
||||||
|
|
||||||
var bufferPool = sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
return new(Writer)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func MakeBytes(sz int) []byte {
|
|
||||||
w := SelectWriter()
|
|
||||||
b := w.Bytes()
|
|
||||||
if cap(b) >= sz {
|
|
||||||
return b[:sz]
|
|
||||||
}
|
|
||||||
return make([]byte, sz)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PutBytes(b []byte) {
|
|
||||||
PutWriter((*Writer)(bytes.NewBuffer(b)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectWriter 从池中取出一个 Writer
|
// SelectWriter 从池中取出一个 Writer
|
||||||
func SelectWriter() *Writer {
|
func SelectWriter() *Writer {
|
||||||
// 因为 bufferPool 定义有 New 函数
|
return (*Writer)(pbuf.NewBuffer(nil))
|
||||||
// 所以 bufferPool.Get() 永不为 nil
|
|
||||||
// 不用判空
|
|
||||||
return bufferPool.Get().(*Writer)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PutWriter 将 Writer 放回池中
|
|
||||||
func PutWriter(w *Writer) {
|
|
||||||
// See https://golang.org/issue/23199
|
|
||||||
const maxSize = 1 << 16
|
|
||||||
if (*bytes.Buffer)(w).Cap() < maxSize { // 对于大Buffer直接丢弃
|
|
||||||
w.Reset()
|
|
||||||
bufferPool.Put(w)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
136
helper/writer.go
136
helper/writer.go
@@ -6,52 +6,22 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"io"
|
|
||||||
"unsafe"
|
"github.com/fumiama/orbyte"
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Writer 写入
|
// Writer 写入
|
||||||
type Writer bytes.Buffer
|
type Writer orbyte.Item[bytes.Buffer]
|
||||||
|
|
||||||
func NewWriterF(f func(writer *Writer)) []byte {
|
func NewWriterF(f func(writer *Writer)) pbuf.Bytes {
|
||||||
w := SelectWriter()
|
w := SelectWriter()
|
||||||
f(w)
|
f(w)
|
||||||
b := append([]byte(nil), w.Bytes()...)
|
return pbuf.BufferItemToBytes((*orbyte.Item[bytes.Buffer])(w).Trans())
|
||||||
w.put()
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenWriterF must call func cl to close
|
|
||||||
func OpenWriterF(f func(*Writer)) (b []byte, cl func()) {
|
|
||||||
w := SelectWriter()
|
|
||||||
f(w)
|
|
||||||
return w.Bytes(), w.put
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Writer) FillUInt16() (pos int) {
|
|
||||||
pos = w.Len()
|
|
||||||
(*bytes.Buffer)(w).Write([]byte{0, 0})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Writer) WriteUInt16At(pos int, v uint16) {
|
|
||||||
newdata := (*bytes.Buffer)(w).Bytes()[pos:]
|
|
||||||
binary.LittleEndian.PutUint16(newdata, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Writer) FillUInt32() (pos int) {
|
|
||||||
pos = w.Len()
|
|
||||||
(*bytes.Buffer)(w).Write([]byte{0, 0, 0, 0})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Writer) WriteUInt32At(pos int, v uint32) {
|
|
||||||
newdata := (*bytes.Buffer)(w).Bytes()[pos:]
|
|
||||||
binary.LittleEndian.PutUint32(newdata, v)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) Write(b []byte) (n int, err error) {
|
func (w *Writer) Write(b []byte) (n int, err error) {
|
||||||
return (*bytes.Buffer)(w).Write(b)
|
return (*orbyte.Item[bytes.Buffer])(w).Pointer().Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) WriteHex(h string) {
|
func (w *Writer) WriteHex(h string) {
|
||||||
@@ -60,7 +30,7 @@ func (w *Writer) WriteHex(h string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) WriteByte(b byte) error {
|
func (w *Writer) WriteByte(b byte) error {
|
||||||
return (*bytes.Buffer)(w).WriteByte(b)
|
return (*orbyte.Item[bytes.Buffer])(w).Pointer().WriteByte(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) WriteUInt16(v uint16) {
|
func (w *Writer) WriteUInt16(v uint16) {
|
||||||
@@ -83,95 +53,25 @@ func (w *Writer) WriteUInt64(v uint64) {
|
|||||||
|
|
||||||
func (w *Writer) WriteString(v string) {
|
func (w *Writer) WriteString(v string) {
|
||||||
//w.WriteUInt32(uint32(len(v) + 4))
|
//w.WriteUInt32(uint32(len(v) + 4))
|
||||||
(*bytes.Buffer)(w).WriteString(v)
|
(*orbyte.Item[bytes.Buffer])(w).Pointer().WriteString(v)
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Writer) WriteStringShort(v string) {
|
|
||||||
w.WriteUInt16(uint16(len(v)))
|
|
||||||
(*bytes.Buffer)(w).WriteString(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Writer) WriteBool(b bool) {
|
|
||||||
if b {
|
|
||||||
w.WriteByte(0x01)
|
|
||||||
} else {
|
|
||||||
w.WriteByte(0x00)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Writer) WriteBytesShort(data []byte) {
|
|
||||||
w.WriteUInt16(uint16(len(data)))
|
|
||||||
w.Write(data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) Len() int {
|
func (w *Writer) Len() int {
|
||||||
return (*bytes.Buffer)(w).Len()
|
return (*orbyte.Item[bytes.Buffer])(w).Pointer().Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) Bytes() []byte {
|
func (w *Writer) UnsafeBytes() []byte {
|
||||||
return (*bytes.Buffer)(w).Bytes()
|
return (*orbyte.Item[bytes.Buffer])(w).Pointer().Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Writer) TransBytes() []byte {
|
||||||
|
return (*orbyte.Item[bytes.Buffer])(w).Trans().Pointer().Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) Reset() {
|
func (w *Writer) Reset() {
|
||||||
(*bytes.Buffer)(w).Reset()
|
(*orbyte.Item[bytes.Buffer])(w).Pointer().Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Writer) Grow(n int) {
|
func (w *Writer) Grow(n int) {
|
||||||
(*bytes.Buffer)(w).Grow(n)
|
(*orbyte.Item[bytes.Buffer])(w).Pointer().Grow(n)
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Writer) Skip(n int) (int, error) {
|
|
||||||
b := (*buffer)(unsafe.Pointer(w))
|
|
||||||
b.lastRead = opInvalid
|
|
||||||
if len(b.buf) <= b.off {
|
|
||||||
// Buffer is empty, reset to recover space.
|
|
||||||
w.Reset()
|
|
||||||
if n == 0 {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
n = minnum(n, len(b.buf[b.off:]))
|
|
||||||
b.off += n
|
|
||||||
if n > 0 {
|
|
||||||
b.lastRead = opRead
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Writer) put() {
|
|
||||||
PutWriter(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
|
|
||||||
// The zero value for Buffer is an empty buffer ready to use.
|
|
||||||
type buffer struct {
|
|
||||||
buf []byte // contents are the bytes buf[off : len(buf)]
|
|
||||||
off int // read at &buf[off], write at &buf[len(buf)]
|
|
||||||
lastRead readOp // last read operation, so that Unread* can work correctly.
|
|
||||||
}
|
|
||||||
|
|
||||||
// The readOp constants describe the last action performed on
|
|
||||||
// the buffer, so that UnreadRune and UnreadByte can check for
|
|
||||||
// invalid usage. opReadRuneX constants are chosen such that
|
|
||||||
// converted to int they correspond to the rune size that was read.
|
|
||||||
type readOp int8
|
|
||||||
|
|
||||||
// Don't use iota for these, as the values need to correspond with the
|
|
||||||
// names and comments, which is easier to see when being explicit.
|
|
||||||
const (
|
|
||||||
opRead readOp = -1 // Any other read operation.
|
|
||||||
opInvalid readOp = 0 // Non-read operation.
|
|
||||||
opReadRune1 readOp = 1 // Read rune of size 1.
|
|
||||||
opReadRune2 readOp = 2 // Read rune of size 2.
|
|
||||||
opReadRune3 readOp = 3 // Read rune of size 3.
|
|
||||||
opReadRune4 readOp = 4 // Read rune of size 4.
|
|
||||||
)
|
|
||||||
|
|
||||||
// minnum 返回两数最小值,该函数将被内联
|
|
||||||
func minnum[T int | int8 | uint8 | int16 | uint16 | int32 | uint32 | int64 | uint64](a, b T) T {
|
|
||||||
if a > b {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import (
|
|||||||
_ "github.com/fumiama/WireGold/gold/p2p/tcp" // support tcp connection
|
_ "github.com/fumiama/WireGold/gold/p2p/tcp" // support tcp connection
|
||||||
_ "github.com/fumiama/WireGold/gold/p2p/udp" // support udp connection
|
_ "github.com/fumiama/WireGold/gold/p2p/udp" // support udp connection
|
||||||
_ "github.com/fumiama/WireGold/gold/p2p/udplite" // support udplite connection
|
_ "github.com/fumiama/WireGold/gold/p2p/udplite" // support udplite connection
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
|
"github.com/fumiama/orbyte/pbuf"
|
||||||
|
|
||||||
"github.com/fumiama/WireGold/config"
|
"github.com/fumiama/WireGold/config"
|
||||||
"github.com/fumiama/WireGold/gold/head"
|
"github.com/fumiama/WireGold/gold/head"
|
||||||
@@ -21,7 +23,7 @@ import (
|
|||||||
type Tunnel struct {
|
type Tunnel struct {
|
||||||
l *link.Link
|
l *link.Link
|
||||||
in chan []byte
|
in chan []byte
|
||||||
out chan *head.Packet
|
out chan *orbyte.Item[head.Packet]
|
||||||
outcache []byte
|
outcache []byte
|
||||||
peerip net.IP
|
peerip net.IP
|
||||||
src uint16
|
src uint16
|
||||||
@@ -33,7 +35,7 @@ func Create(me *link.Me, peer string) (s Tunnel, err error) {
|
|||||||
s.l, err = me.Connect(peer)
|
s.l, err = me.Connect(peer)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
s.in = make(chan []byte, 4)
|
s.in = make(chan []byte, 4)
|
||||||
s.out = make(chan *head.Packet, 4)
|
s.out = make(chan *orbyte.Item[head.Packet], 4)
|
||||||
s.peerip = net.ParseIP(peer)
|
s.peerip = net.ParseIP(peer)
|
||||||
} else {
|
} else {
|
||||||
logrus.Errorln("[tunnel] create err:", err)
|
logrus.Errorln("[tunnel] create err:", err)
|
||||||
@@ -73,12 +75,11 @@ func (s *Tunnel) Read(p []byte) (int, error) {
|
|||||||
if pkt == nil {
|
if pkt == nil {
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
defer pkt.Put()
|
if pkt.Pointer().BodyLen() < 4 {
|
||||||
if pkt.BodyLen() < 4 {
|
logrus.Warnln("[tunnel] unexpected packet data len", pkt.Pointer().BodyLen(), "content", hex.EncodeToString(pkt.Pointer().Body()))
|
||||||
logrus.Warnln("[tunnel] unexpected packet data len", pkt.BodyLen(), "content", hex.EncodeToString(pkt.Body()))
|
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
d = pkt.Body()[4:]
|
d = pkt.Pointer().Body()[4:]
|
||||||
}
|
}
|
||||||
if d != nil {
|
if d != nil {
|
||||||
if len(p) >= len(d) {
|
if len(p) >= len(d) {
|
||||||
@@ -125,8 +126,8 @@ func (s *Tunnel) handleWrite() {
|
|||||||
binary.LittleEndian.PutUint32(buf[:4], seq)
|
binary.LittleEndian.PutUint32(buf[:4], seq)
|
||||||
seq++
|
seq++
|
||||||
copy(buf[4:], b[:s.mtu-4])
|
copy(buf[4:], b[:s.mtu-4])
|
||||||
_, err := s.l.WriteAndPut(
|
_, err := s.l.WritePacket(
|
||||||
head.NewPacket(head.ProtoData, s.src, s.peerip, s.dest, buf), false,
|
head.NewPacketPartial(head.ProtoData, s.src, s.peerip, s.dest, pbuf.ParseBytes(buf...)), false,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorln("[tunnel] seq", seq-1, "write err:", err)
|
logrus.Errorln("[tunnel] seq", seq-1, "write err:", err)
|
||||||
@@ -140,8 +141,8 @@ func (s *Tunnel) handleWrite() {
|
|||||||
binary.LittleEndian.PutUint32(buf[:4], seq)
|
binary.LittleEndian.PutUint32(buf[:4], seq)
|
||||||
seq++
|
seq++
|
||||||
copy(buf[4:], b)
|
copy(buf[4:], b)
|
||||||
_, err := s.l.WriteAndPut(
|
_, err := s.l.WritePacket(
|
||||||
head.NewPacket(head.ProtoData, s.src, s.peerip, s.dest, buf[:len(b)+4]), false,
|
head.NewPacketPartial(head.ProtoData, s.src, s.peerip, s.dest, pbuf.ParseBytes(buf[:len(b)+4]...)), false,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorln("[tunnel] seq", seq-1, "write err:", err)
|
logrus.Errorln("[tunnel] seq", seq-1, "write err:", err)
|
||||||
@@ -155,7 +156,7 @@ func (s *Tunnel) handleWrite() {
|
|||||||
|
|
||||||
func (s *Tunnel) handleRead() {
|
func (s *Tunnel) handleRead() {
|
||||||
seq := uint32(0)
|
seq := uint32(0)
|
||||||
seqmap := make(map[uint32]*head.Packet)
|
seqmap := make(map[uint32]*orbyte.Item[head.Packet])
|
||||||
for {
|
for {
|
||||||
if p, ok := seqmap[seq]; ok {
|
if p, ok := seqmap[seq]; ok {
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
@@ -173,14 +174,15 @@ func (s *Tunnel) handleRead() {
|
|||||||
}
|
}
|
||||||
end := 64
|
end := 64
|
||||||
endl := "..."
|
endl := "..."
|
||||||
if p.BodyLen() < 64 {
|
pp := p.Pointer()
|
||||||
end = p.BodyLen()
|
if pp.BodyLen() < 64 {
|
||||||
|
end = pp.BodyLen()
|
||||||
endl = "."
|
endl = "."
|
||||||
}
|
}
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[tunnel] read recv", hex.EncodeToString(p.Body()[:end]), endl)
|
logrus.Debugln("[tunnel] read recv", hex.EncodeToString(pp.Body()[:end]), endl)
|
||||||
}
|
}
|
||||||
recvseq := binary.LittleEndian.Uint32(p.Body()[:4])
|
recvseq := binary.LittleEndian.Uint32(pp.Body()[:4])
|
||||||
if recvseq == seq {
|
if recvseq == seq {
|
||||||
if config.ShowDebugLog {
|
if config.ShowDebugLog {
|
||||||
logrus.Debugln("[tunnel] dispatch seq", seq)
|
logrus.Debugln("[tunnel] dispatch seq", seq)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
curve "github.com/fumiama/go-x25519"
|
curve "github.com/fumiama/go-x25519"
|
||||||
|
"github.com/fumiama/orbyte"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/fumiama/WireGold/gold/link"
|
"github.com/fumiama/WireGold/gold/link"
|
||||||
@@ -196,7 +197,9 @@ func testTunnel(t *testing.T, nw string, isplain, isbase14 bool, pshk *[32]byte,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendb = make([]byte, 4096)
|
sendb = make([]byte, 4096)
|
||||||
rand.Read(sendb)
|
for i := 0; i < 4096; i++ {
|
||||||
|
sendb[i] = byte(i)
|
||||||
|
}
|
||||||
go tunnme.Write(sendb)
|
go tunnme.Write(sendb)
|
||||||
buf = make([]byte, 4096)
|
buf = make([]byte, 4096)
|
||||||
_, err = io.ReadFull(&tunnpeer, buf)
|
_, err = io.ReadFull(&tunnpeer, buf)
|
||||||
@@ -213,7 +216,9 @@ func testTunnel(t *testing.T, nw string, isplain, isbase14 bool, pshk *[32]byte,
|
|||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
for i := 0; i < 32; i++ {
|
for i := 0; i < 32; i++ {
|
||||||
sendb := make([]byte, 65535)
|
sendb := make([]byte, 65535)
|
||||||
rand.Read(sendb)
|
for j := 0; j < 65535; j++ {
|
||||||
|
sendb[j] = byte(i + j)
|
||||||
|
}
|
||||||
n, _ := tunnme.Write(sendb)
|
n, _ := tunnme.Write(sendb)
|
||||||
sendbufs <- sendb
|
sendbufs <- sendb
|
||||||
logrus.Debugln("loop", i, "write", n, "bytes")
|
logrus.Debugln("loop", i, "write", n, "bytes")
|
||||||
@@ -234,7 +239,9 @@ func testTunnel(t *testing.T, nw string, isplain, isbase14 bool, pshk *[32]byte,
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
rand.Read(sendb)
|
for i := 0; i < 4096; i++ {
|
||||||
|
sendb[i] = ^byte(i)
|
||||||
|
}
|
||||||
tunnme.Write(sendb)
|
tunnme.Write(sendb)
|
||||||
rd := bytes.NewBuffer(nil)
|
rd := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
@@ -420,7 +427,9 @@ type logFormat struct {
|
|||||||
|
|
||||||
// Format implements logrus.Formatter
|
// Format implements logrus.Formatter
|
||||||
func (f logFormat) Format(entry *logrus.Entry) ([]byte, error) {
|
func (f logFormat) Format(entry *logrus.Entry) ([]byte, error) {
|
||||||
buf := helper.SelectWriter() // this writer will not be put back
|
// this writer will not be put back
|
||||||
|
|
||||||
|
buf := (*orbyte.Item[bytes.Buffer])(helper.SelectWriter()).Trans().Pointer()
|
||||||
|
|
||||||
buf.WriteByte('[')
|
buf.WriteByte('[')
|
||||||
if f.enableColor {
|
if f.enableColor {
|
||||||
|
|||||||
Reference in New Issue
Block a user