mirror of
https://github.com/fumiama/WireGold.git
synced 2025-09-26 19:21:11 +08:00
feat: impl. trans & ttl
This commit is contained in:
@@ -19,6 +19,7 @@ type Config struct {
|
||||
SpeedLoop uint16 `yaml:"SpeedLoop"`
|
||||
Mask uint64 `yaml:"Mask"` // Mask 是异或报文所用掩码, 必须保证各端统一
|
||||
Base14 bool `yaml:"Base14"` // Base14 是否将最终报文进行 base16384 编码后再发送
|
||||
MaxTTL uint8 `yaml:"MaxTTL"` // MaxTTL 默认 64
|
||||
Peers []Peer `yaml:"Peers"`
|
||||
}
|
||||
|
||||
|
@@ -17,14 +17,18 @@ import (
|
||||
// PreCRC64 calculate crc64 checksum without idxdatsz.
|
||||
func (p *Packet) PreCRC64() (crc uint64) {
|
||||
w := bin.SelectWriter()
|
||||
// 固定 TTL 为 0 计算
|
||||
if bin.IsLittleEndian {
|
||||
ttl := p.TTL
|
||||
p.TTL = 0
|
||||
w.Write((*[PacketHeadNoCRCLen]byte)(
|
||||
(unsafe.Pointer)(p),
|
||||
)[:])
|
||||
p.TTL = ttl
|
||||
} else {
|
||||
w.WriteUInt32(p.idxdatsz)
|
||||
w.WriteUInt32(uint32(p.randn))
|
||||
w.WriteUInt16((uint16(p.TTL) << 8) | uint16(p.Proto))
|
||||
w.WriteUInt16(uint16(p.Proto)) // TTL is set to 0
|
||||
w.WriteUInt16(p.SrcPort)
|
||||
w.WriteUInt16(p.DstPort)
|
||||
w.WriteUInt16(p.Offset)
|
||||
@@ -46,11 +50,16 @@ func (p *Packet) PreCRC64() (crc uint64) {
|
||||
// WriteHeaderTo write header bytes to buf
|
||||
// with crc64 checksum.
|
||||
func (p *Packet) WriteHeaderTo(buf *bytes.Buffer) {
|
||||
// 固定 TTL 为 0 计算
|
||||
if bin.IsLittleEndian {
|
||||
buf.Write((*[PacketHeadNoCRCLen]byte)(
|
||||
(unsafe.Pointer)(p),
|
||||
)[:])
|
||||
p.md5h8rem = int64(algo.MD5Hash8(buf.Bytes()))
|
||||
pbuf.NewBytes(buf.Len()).V(func(b []byte) {
|
||||
copy(b, buf.Bytes())
|
||||
ClearTTL(b)
|
||||
p.md5h8rem = int64(algo.MD5Hash8(b))
|
||||
})
|
||||
_ = binary.Write(buf, binary.LittleEndian, p.md5h8rem)
|
||||
return
|
||||
}
|
||||
@@ -63,8 +72,12 @@ func (p *Packet) WriteHeaderTo(buf *bytes.Buffer) {
|
||||
w.WriteUInt16(p.Offset)
|
||||
w.Write(p.src[:])
|
||||
w.Write(p.dst[:])
|
||||
w.P(func(b *pbuf.Buffer) {
|
||||
p.md5h8rem = int64(algo.MD5Hash8(b.Bytes()))
|
||||
w.P(func(buf *pbuf.Buffer) {
|
||||
pbuf.NewBytes(buf.Len()).V(func(b []byte) {
|
||||
copy(b, buf.Bytes())
|
||||
ClearTTL(b)
|
||||
p.md5h8rem = int64(algo.MD5Hash8(b))
|
||||
})
|
||||
})
|
||||
w.WriteUInt64(uint64(p.md5h8rem))
|
||||
w.P(func(b *pbuf.Buffer) {
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
const (
|
||||
hasmorebit FlagsProto = 0x20 << iota
|
||||
nofragbit
|
||||
topbit //TODO: 改为 trans 标记
|
||||
topbit
|
||||
)
|
||||
|
||||
const (
|
||||
|
@@ -27,13 +27,13 @@ func TestBuilderNative(t *testing.T) {
|
||||
Split(16384, false)[0]).Trans()
|
||||
s := hex.EncodeToString(dat)
|
||||
if s[:8] != "12004593" {
|
||||
panic("1")
|
||||
panic(s[:8])
|
||||
}
|
||||
if s[16:48] != "03ff05000a0000000102030406070809" {
|
||||
panic("2")
|
||||
panic(s[16:48])
|
||||
}
|
||||
if s[80:] != "30313233343536373839" {
|
||||
panic("3")
|
||||
panic(s[80:])
|
||||
}
|
||||
p, err := ParsePacketHeader(dat)
|
||||
if err != nil {
|
||||
@@ -88,13 +88,13 @@ func TestBuilderBE(t *testing.T) {
|
||||
Split(16384, false)[0]).Trans()
|
||||
s := hex.EncodeToString(dat)
|
||||
if s[:8] != "12004593" {
|
||||
panic("1")
|
||||
panic(s[:8])
|
||||
}
|
||||
if s[16:48] != "03ff05000a0000000102030406070809" {
|
||||
panic("2")
|
||||
panic(s[16:48])
|
||||
}
|
||||
if s[80:] != "30313233343536373839" {
|
||||
panic("3")
|
||||
panic(s[80:])
|
||||
}
|
||||
p, err := ParsePacketHeader(dat)
|
||||
if err != nil {
|
||||
|
20
gold/head/raw.go
Normal file
20
gold/head/raw.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package head
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
ttloffset = unsafe.Offsetof(Packet{}.TTL)
|
||||
)
|
||||
|
||||
// ClearTTL for hash use
|
||||
func ClearTTL(data []byte) {
|
||||
data[ttloffset] = 0
|
||||
}
|
||||
|
||||
// DecTTL on transferring
|
||||
func DecTTL(data []byte) (drop bool) {
|
||||
data[ttloffset]--
|
||||
return data[ttloffset] == 0
|
||||
}
|
@@ -54,7 +54,12 @@ func ParsePacketHeader(data []byte) (pbytes PacketBytes, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
crc := algo.MD5Hash8(data[:PacketHeadNoCRCLen])
|
||||
var crc uint64
|
||||
pbuf.NewBytes(int(PacketHeadNoCRCLen)).V(func(b []byte) {
|
||||
copy(b, data[:PacketHeadNoCRCLen])
|
||||
ClearTTL(b)
|
||||
crc = algo.MD5Hash8(b)
|
||||
})
|
||||
if crc != uint64(pb.DAT.md5h8rem) {
|
||||
err = ErrBadCRCChecksum
|
||||
if config.ShowDebugLog {
|
||||
|
@@ -1,22 +1,22 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/RomiChan/syncx"
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
"github.com/fumiama/orbyte/pbuf"
|
||||
)
|
||||
|
||||
// 事件分发器
|
||||
var dispachers map[uint8]EventDispacher = make(map[uint8]EventDispacher)
|
||||
var dispachers syncx.Map[uint8, Dispacher]
|
||||
|
||||
type EventDispacher func(header *head.Packet, peer *Link, data pbuf.Bytes)
|
||||
type Dispacher func(header *head.Packet, peer *Link, data pbuf.Bytes)
|
||||
|
||||
// AddProto is thread unsafe. Use in init() only.
|
||||
func AddProto(p uint8, d EventDispacher) {
|
||||
_, ok := dispachers[p]
|
||||
if ok {
|
||||
panic("proto " + strconv.Itoa(int(p)) + " has been registered")
|
||||
}
|
||||
dispachers[p] = d
|
||||
// RegisterDispacher of proto
|
||||
func RegisterDispacher(p uint8, d Dispacher) (actual Dispacher, hasexist bool) {
|
||||
return dispachers.LoadOrStore(p, d)
|
||||
}
|
||||
|
||||
// GetDispacher fn, ok
|
||||
func GetDispacher(p uint8) (Dispacher, bool) {
|
||||
return dispachers.Load(p)
|
||||
}
|
||||
|
@@ -6,7 +6,6 @@ import (
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
@@ -14,7 +13,6 @@ import (
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
"github.com/fumiama/WireGold/gold/p2p"
|
||||
"github.com/fumiama/WireGold/internal/algo"
|
||||
"github.com/fumiama/WireGold/internal/bin"
|
||||
"github.com/fumiama/WireGold/internal/file"
|
||||
"github.com/fumiama/orbyte/pbuf"
|
||||
)
|
||||
@@ -76,7 +74,7 @@ func (m *Me) waitordispatch(addr p2p.EndPoint, buf pbuf.Bytes, n int) {
|
||||
atomic.StoreInt64(&m.recvlooptime, now)
|
||||
}
|
||||
buf.V(func(b []byte) {
|
||||
h := m.wait(b[:n])
|
||||
h := m.wait(b[:n], addr)
|
||||
if !h.HasInit() {
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] queue waiting")
|
||||
@@ -100,94 +98,62 @@ func (m *Me) dispatch(header *head.Packet, body []byte, addr p2p.EndPoint) {
|
||||
}
|
||||
srcip := header.Src()
|
||||
dstip := header.Dst()
|
||||
p, ok := m.IsInPeer(srcip.String())
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] recv from endpoint", addr, "src", srcip, "dst", dstip)
|
||||
}
|
||||
if !ok {
|
||||
logrus.Warnln("[listen] packet from", srcip, "to", dstip, "is refused")
|
||||
p := m.extractPeer(srcip, dstip, addr)
|
||||
if p == nil {
|
||||
return
|
||||
}
|
||||
if bin.IsNilInterface(p.endpoint) || !p.endpoint.Euqal(addr) {
|
||||
if m.ep.Network() == "tcp" && !addr.Euqal(p.endpoint) {
|
||||
logrus.Infoln("[listen] set endpoint of peer", p.peerip, "to", addr.String())
|
||||
p.endpoint = addr
|
||||
} else { // others are all no status link
|
||||
logrus.Infoln("[listen] set endpoint of peer", p.peerip, "to", addr.String())
|
||||
p.endpoint = addr
|
||||
}
|
||||
if !p.Accept(srcip) {
|
||||
logrus.Warnln("[listen] refused packet from", srcip.String()+":"+strconv.Itoa(int(header.SrcPort)))
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.lastalive)), unsafe.Pointer(&now))
|
||||
switch {
|
||||
case p.IsToMe(dstip):
|
||||
if !p.Accept(srcip) {
|
||||
logrus.Warnln("[listen] refused packet from", srcip.String()+":"+strconv.Itoa(int(header.SrcPort)))
|
||||
return
|
||||
if !p.IsToMe(dstip) {
|
||||
logrus.Warnln("[listen] unhandled trans packet from", srcip.String()+":"+strconv.Itoa(int(header.SrcPort)))
|
||||
return
|
||||
}
|
||||
addt := header.AdditionalData()
|
||||
var err error
|
||||
data, err := p.decode(header.CipherIndex(), addt, body)
|
||||
if err != nil {
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] drop invalid packet key idx:", header.CipherIndex(), "addt:", addt, "err:", err)
|
||||
}
|
||||
addt := header.AdditionalData()
|
||||
var err error
|
||||
data, err := p.decode(header.CipherIndex(), addt, body)
|
||||
return
|
||||
}
|
||||
if data.Len() < 8 {
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] drop invalid data len packet key idx:", header.CipherIndex(), "addt:", addt, "len", data.Len())
|
||||
}
|
||||
return
|
||||
}
|
||||
ok := false
|
||||
data.V(func(b []byte) {
|
||||
ok = algo.IsVaildBlake2bHash8(header.PreCRC64(), b)
|
||||
})
|
||||
if !ok {
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] drop invalid hash packet")
|
||||
}
|
||||
return
|
||||
}
|
||||
data = data.SliceFrom(8)
|
||||
if p.usezstd {
|
||||
data.V(func(b []byte) {
|
||||
data, err = algo.DecodeZstd(b) // skip hash
|
||||
})
|
||||
if err != nil {
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] drop invalid packet key idx:", header.CipherIndex(), "addt:", addt, "err:", err)
|
||||
logrus.Debugln("[listen] drop invalid zstd packet:", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if data.Len() < 8 {
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] drop invalid data len packet key idx:", header.CipherIndex(), "addt:", addt, "len", data.Len())
|
||||
}
|
||||
return
|
||||
}
|
||||
ok := false
|
||||
data.V(func(b []byte) {
|
||||
ok = algo.IsVaildBlake2bHash8(header.PreCRC64(), b)
|
||||
})
|
||||
if !ok {
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] drop invalid hash packet")
|
||||
}
|
||||
return
|
||||
}
|
||||
data = data.SliceFrom(8)
|
||||
if p.usezstd {
|
||||
data.V(func(b []byte) {
|
||||
data, err = algo.DecodeZstd(b) // skip hash
|
||||
})
|
||||
if err != nil {
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] drop invalid zstd packet:", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] zstd decoded len:", data.Len())
|
||||
}
|
||||
}
|
||||
fn, ok := dispachers[header.Proto.Proto()]
|
||||
if !ok {
|
||||
logrus.Warnln(file.Header(), "unsupported proto", header.Proto.Proto())
|
||||
return
|
||||
}
|
||||
fn(header, p, data)
|
||||
return
|
||||
case p.Accept(dstip): //TODO: 移除此处转发, 将转发放到 wait
|
||||
if !p.allowtrans {
|
||||
logrus.Warnln("[listen] refused to trans packet to", dstip.String()+":"+strconv.Itoa(int(header.DstPort)))
|
||||
return
|
||||
}
|
||||
// 转发
|
||||
lnk := m.router.NextHop(dstip.String())
|
||||
if lnk == nil {
|
||||
logrus.Warnln("[listen] transfer drop packet: nil nexthop")
|
||||
return
|
||||
}
|
||||
lnk.WritePacket(head.ProtoTrans, body)
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] trans", len(body), "bytes body to", dstip.String()+":"+strconv.Itoa(int(header.DstPort)))
|
||||
logrus.Debugln("[listen] zstd decoded len:", data.Len())
|
||||
}
|
||||
default:
|
||||
logrus.Warnln("[listen] packet dst", dstip.String()+":"+strconv.Itoa(int(header.DstPort)), "is not in peers")
|
||||
}
|
||||
fn, ok := GetDispacher(header.Proto.Proto())
|
||||
if !ok {
|
||||
logrus.Warnln(file.Header(), "unsupported proto", header.Proto.Proto())
|
||||
return
|
||||
}
|
||||
fn(header, p, data)
|
||||
}
|
||||
|
@@ -62,6 +62,8 @@ type Me struct {
|
||||
recvloopcnt uintptr
|
||||
// 是否进行 base16384 编码
|
||||
base14 bool
|
||||
// 本机初始 ttl
|
||||
ttl uint8
|
||||
// 本机网络端点初始化配置
|
||||
networkconfigs []any
|
||||
}
|
||||
@@ -76,6 +78,7 @@ type MyConfig struct {
|
||||
SrcPort, DstPort, MTU, SpeedLoop uint16
|
||||
Mask uint64
|
||||
Base14 bool
|
||||
MaxTTL uint8
|
||||
}
|
||||
|
||||
type NICConfig struct {
|
||||
@@ -131,6 +134,11 @@ func NewMe(cfg *MyConfig) (m Me) {
|
||||
m.mask = cfg.Mask
|
||||
m.recvlooptime = time.Now().UnixMilli()
|
||||
m.base14 = cfg.Base14
|
||||
if cfg.MaxTTL == 0 {
|
||||
m.ttl = 64
|
||||
} else {
|
||||
m.ttl = cfg.MaxTTL
|
||||
}
|
||||
var buf [8]byte
|
||||
binary.BigEndian.PutUint64(buf[:], m.mask)
|
||||
logrus.Infoln("[me] xor mask", hex.EncodeToString(buf[:]))
|
||||
@@ -179,6 +187,10 @@ func (m *Me) MTU() uint16 {
|
||||
return m.mtu
|
||||
}
|
||||
|
||||
func (m *Me) TTL() uint8 {
|
||||
return m.ttl
|
||||
}
|
||||
|
||||
func (m *Me) EndPoint() p2p.EndPoint {
|
||||
return m.ep
|
||||
}
|
||||
@@ -298,7 +310,7 @@ func (m *Me) sendAllSameDst(packet []byte) (n int) {
|
||||
copy(b, packet)
|
||||
})
|
||||
go pcp.V(func(b []byte) {
|
||||
lnk.WritePacket(head.ProtoData, b)
|
||||
lnk.WritePacket(head.ProtoData, b, lnk.me.ttl)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ func (l *Link) keepAlive(dur int64) {
|
||||
logrus.Infoln(file.Header(), "re-connect me succeeded")
|
||||
}
|
||||
}
|
||||
l.WritePacket(head.ProtoHello, []byte{byte(head.HelloPing)})
|
||||
l.WritePacket(head.ProtoHello, []byte{byte(head.HelloPing)}, 64)
|
||||
logrus.Infoln(file.Header(), "send keep alive to", l.peerip)
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func (l *Link) sendQuery(tick time.Duration, peers ...string) {
|
||||
}
|
||||
t := time.NewTicker(tick)
|
||||
for range t.C {
|
||||
l.WritePacket(head.ProtoQuery, data)
|
||||
l.WritePacket(head.ProtoQuery, data, l.me.ttl)
|
||||
logrus.Infoln(file.Header(), "send query to", l.peerip)
|
||||
}
|
||||
}
|
||||
|
@@ -2,13 +2,19 @@ package link
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/fumiama/WireGold/gold/p2p"
|
||||
"github.com/fumiama/WireGold/internal/algo"
|
||||
curve "github.com/fumiama/go-x25519"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
|
||||
"github.com/fumiama/WireGold/config"
|
||||
"github.com/fumiama/WireGold/gold/p2p"
|
||||
"github.com/fumiama/WireGold/internal/algo"
|
||||
"github.com/fumiama/WireGold/internal/bin"
|
||||
"github.com/fumiama/WireGold/internal/file"
|
||||
)
|
||||
|
||||
type PeerConfig struct {
|
||||
@@ -123,3 +129,26 @@ func (m *Me) IsInPeer(peer string) (p *Link, ok bool) {
|
||||
m.connmapmu.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
func (m *Me) extractPeer(srcip, dstip net.IP, addr p2p.EndPoint) *Link {
|
||||
p, ok := m.IsInPeer(srcip.String())
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln(file.Header(), "recv from endpoint", addr, "src", srcip, "dst", dstip)
|
||||
}
|
||||
if !ok {
|
||||
logrus.Warnln(file.Header(), "packet from", srcip, "to", dstip, "is refused")
|
||||
return nil
|
||||
}
|
||||
if bin.IsNilInterface(p.endpoint) || !p.endpoint.Euqal(addr) {
|
||||
if m.ep.Network() == "tcp" && !addr.Euqal(p.endpoint) {
|
||||
logrus.Infoln(file.Header(), "set endpoint of peer", p.peerip, "to", addr.String())
|
||||
p.endpoint = addr
|
||||
} else { // others are all no status link
|
||||
logrus.Infoln(file.Header(), "set endpoint of peer", p.peerip, "to", addr.String())
|
||||
p.endpoint = addr
|
||||
}
|
||||
}
|
||||
now := time.Now()
|
||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.lastalive)), unsafe.Pointer(&now))
|
||||
return p
|
||||
}
|
||||
|
@@ -8,8 +8,10 @@ import (
|
||||
|
||||
"github.com/fumiama/WireGold/config"
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
"github.com/fumiama/WireGold/gold/p2p"
|
||||
"github.com/fumiama/WireGold/internal/bin"
|
||||
base14 "github.com/fumiama/go-base16384"
|
||||
"github.com/fumiama/orbyte/pbuf"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -18,8 +20,7 @@ func (l *Link) Read() LinkData {
|
||||
return <-l.pipe
|
||||
}
|
||||
|
||||
// wait TODO: 判断是否为 trans 并提前 call dispatch
|
||||
func (m *Me) wait(data []byte) (h head.PacketBytes) {
|
||||
func (m *Me) wait(data []byte, addr p2p.EndPoint) (h head.PacketBytes) {
|
||||
if len(data) < int(head.PacketHeadLen)+8 { // not a valid packet
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[recv] invalid data len", len(data))
|
||||
@@ -44,7 +45,7 @@ func (m *Me) wait(data []byte) (h head.PacketBytes) {
|
||||
}
|
||||
return
|
||||
}
|
||||
data = w.ToBytes().Trans()
|
||||
data = w.ToBytes().Copy().Trans()
|
||||
if len(data) < bound {
|
||||
bound = len(data)
|
||||
endl = "."
|
||||
@@ -94,6 +95,31 @@ func (m *Me) wait(data []byte) (h head.PacketBytes) {
|
||||
}
|
||||
|
||||
header.B(func(buf []byte, p *head.Packet) {
|
||||
peer := m.extractPeer(p.Src(), p.Dst(), addr)
|
||||
if peer == nil {
|
||||
return
|
||||
}
|
||||
if !peer.IsToMe(p.Dst()) { // 提前处理转发
|
||||
if !peer.allowtrans {
|
||||
logrus.Warnln("[recv] refused to trans packet to", p.Dst().String()+":"+strconv.Itoa(int(p.DstPort)))
|
||||
return
|
||||
}
|
||||
// 转发
|
||||
lnk := m.router.NextHop(p.Dst().String())
|
||||
if lnk == nil {
|
||||
logrus.Warnln("[recv] transfer drop packet: nil nexthop")
|
||||
return
|
||||
}
|
||||
if head.DecTTL(data) { // need drop
|
||||
logrus.Warnln("[recv] transfer drop packet: zero ttl")
|
||||
return
|
||||
}
|
||||
go lnk.write2peer(pbuf.ParseBytes(data...).Copy(), seq)
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[listen] trans", len(data), "bytes packet to", p.Dst().String()+":"+strconv.Itoa(int(p.DstPort)))
|
||||
}
|
||||
return
|
||||
}
|
||||
if !p.Proto.HasMore() {
|
||||
ok := p.WriteDataSegment(data, buf)
|
||||
if !ok {
|
||||
|
@@ -32,7 +32,7 @@ func randseq(i uint16) uint32 {
|
||||
// WritePacket 基于 data 向 peer 发包
|
||||
//
|
||||
// data 可为空, 因为不保证可达所以不返回错误。
|
||||
func (l *Link) WritePacket(proto uint8, data []byte) {
|
||||
func (l *Link) WritePacket(proto uint8, data []byte, ttl uint8) {
|
||||
teatype := l.randkeyidx()
|
||||
sndcnt := uint16(l.incgetsndcnt())
|
||||
mtu := l.mtu
|
||||
@@ -44,7 +44,7 @@ func (l *Link) WritePacket(proto uint8, data []byte) {
|
||||
}
|
||||
pb := head.NewPacketBuilder().
|
||||
Src(l.me.me, l.me.srcport).Dst(l.peerip, l.me.dstport).
|
||||
Proto(proto).TTL(64).With(data)
|
||||
Proto(proto).TTL(ttl).With(data)
|
||||
if l.usezstd {
|
||||
pb.Zstd()
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package proto
|
||||
package data
|
||||
|
||||
import (
|
||||
"github.com/fumiama/orbyte/pbuf"
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
link.AddProto(head.ProtoData, func(header *head.Packet, peer *link.Link, data pbuf.Bytes) {
|
||||
link.RegisterDispacher(head.ProtoData, func(header *head.Packet, peer *link.Link, data pbuf.Bytes) {
|
||||
peer.ToLower(header, data)
|
||||
})
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
package proto
|
||||
|
||||
import (
|
||||
"github.com/fumiama/orbyte/pbuf"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
"github.com/fumiama/WireGold/gold/link"
|
||||
"github.com/fumiama/WireGold/internal/file"
|
||||
)
|
||||
|
||||
func init() {
|
||||
link.AddProto(head.ProtoHello, func(_ *head.Packet, peer *link.Link, data pbuf.Bytes) {
|
||||
onHello(data, peer)
|
||||
})
|
||||
}
|
||||
|
||||
func onHello(data pbuf.Bytes, p *link.Link) {
|
||||
data.V(func(b []byte) {
|
||||
switch {
|
||||
case len(b) == 0:
|
||||
logrus.Warnln(file.Header(), "recv old packet, do nothing")
|
||||
case b[0] == byte(head.HelloPing):
|
||||
go p.WritePacket(head.ProtoHello, []byte{byte(head.HelloPong)})
|
||||
logrus.Infoln(file.Header(), "recv, send ack")
|
||||
default:
|
||||
logrus.Infoln(file.Header(), "recv ack, do nothing")
|
||||
}
|
||||
})
|
||||
}
|
26
gold/proto/hello/hello.go
Normal file
26
gold/proto/hello/hello.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package hello
|
||||
|
||||
import (
|
||||
"github.com/fumiama/orbyte/pbuf"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
"github.com/fumiama/WireGold/gold/link"
|
||||
"github.com/fumiama/WireGold/internal/file"
|
||||
)
|
||||
|
||||
func init() {
|
||||
link.RegisterDispacher(head.ProtoHello, func(_ *head.Packet, peer *link.Link, data pbuf.Bytes) {
|
||||
data.V(func(b []byte) {
|
||||
switch {
|
||||
case len(b) == 0:
|
||||
logrus.Warnln(file.Header(), "recv old packet, do nothing")
|
||||
case b[0] == byte(head.HelloPing):
|
||||
go peer.WritePacket(head.ProtoHello, []byte{byte(head.HelloPong)}, peer.Me().TTL())
|
||||
logrus.Infoln(file.Header(), "recv, send ack")
|
||||
default:
|
||||
logrus.Infoln(file.Header(), "recv ack, do nothing")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
@@ -1,121 +0,0 @@
|
||||
package proto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/fumiama/orbyte/pbuf"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/fumiama/WireGold/config"
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
"github.com/fumiama/WireGold/gold/link"
|
||||
"github.com/fumiama/WireGold/gold/p2p"
|
||||
|
||||
"github.com/fumiama/WireGold/internal/bin"
|
||||
"github.com/fumiama/WireGold/internal/file"
|
||||
)
|
||||
|
||||
func init() {
|
||||
link.AddProto(head.ProtoNotify, func(_ *head.Packet, peer *link.Link, data pbuf.Bytes) {
|
||||
data.V(func(b []byte) {
|
||||
onNotify(peer, b)
|
||||
})
|
||||
})
|
||||
link.AddProto(head.ProtoQuery, func(_ *head.Packet, peer *link.Link, data pbuf.Bytes) {
|
||||
data.V(func(b []byte) {
|
||||
onQuery(peer, b)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 收到通告包的处理函数
|
||||
func onNotify(l *link.Link, packet []byte) {
|
||||
// TODO: 完成data解包与endpoint注册
|
||||
// 1. Data 解包
|
||||
// ---- 使用 head.Notify 解释 packet
|
||||
notify := make(head.Notify, 32)
|
||||
err := json.Unmarshal(packet, ¬ify)
|
||||
if err != nil {
|
||||
logrus.Errorln(file.Header(), "notify json unmarshal err:", err)
|
||||
return
|
||||
}
|
||||
// 2. endpoint注册
|
||||
// ---- 遍历 Notify,注册对方的 endpoint 到
|
||||
// ---- connections,注意使用读写锁connmapmu
|
||||
for peer, ep := range notify {
|
||||
nw, epstr := ep[0], ep[1]
|
||||
if nw != l.Me().EndPoint().Network() {
|
||||
logrus.Warnln(file.Header(), "ignore different network notify", nw, "addr", epstr)
|
||||
continue
|
||||
}
|
||||
addr, err := p2p.NewEndPoint(nw, epstr, l.Me().NetworkConfigs()...)
|
||||
if err == nil {
|
||||
p, ok := l.Me().IsInPeer(peer)
|
||||
if ok {
|
||||
if bin.IsNilInterface(p.EndPoint()) || !p.EndPoint().Euqal(addr) {
|
||||
p.SetEndPoint(addr)
|
||||
logrus.Infoln(file.Header(), "notify set ep of peer", peer, "to", ep)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln(file.Header(), "notify drop invalid peer:", peer, "ep:", ep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 收到询问包的处理函数
|
||||
func onQuery(l *link.Link, packet []byte) {
|
||||
// 完成data解包与notify分发
|
||||
|
||||
// 1. Data 解包
|
||||
// ---- 使用 head.Query 解释 packet
|
||||
// ---- 根据 Query 确定需要封装的 Notify
|
||||
var peers head.Query
|
||||
err := json.Unmarshal(packet, &peers)
|
||||
if err != nil {
|
||||
logrus.Errorln(file.Header(), "query json unmarshal err:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if l == nil || l.Me() == nil {
|
||||
logrus.Errorln(file.Header(), "nil link/me")
|
||||
return
|
||||
}
|
||||
|
||||
// 2. notify分发
|
||||
// ---- 封装 Notify 到 新的 packet
|
||||
// ---- 调用 l.Send 发送到对方
|
||||
notify := make(head.Notify, len(peers))
|
||||
for _, p := range peers {
|
||||
lnk, ok := l.Me().IsInPeer(p)
|
||||
eps := ""
|
||||
if l.Me().EndPoint().Network() == "udp" { // udp has real p2p
|
||||
if bin.IsNilInterface(lnk.EndPoint()) {
|
||||
continue
|
||||
}
|
||||
eps = lnk.EndPoint().String()
|
||||
}
|
||||
if eps == "" {
|
||||
eps = l.RawEndPoint() // use registered ep only
|
||||
}
|
||||
if eps == "" {
|
||||
continue
|
||||
}
|
||||
if ok && bin.IsNonNilInterface(lnk.EndPoint()) {
|
||||
notify[p] = [2]string{
|
||||
lnk.EndPoint().Network(),
|
||||
eps,
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(notify) > 0 {
|
||||
logrus.Infoln(file.Header(), "query wrap", len(notify), "notify")
|
||||
w := bin.SelectWriter()
|
||||
_ = json.NewEncoder(w).Encode(¬ify)
|
||||
w.P(func(b *pbuf.Buffer) {
|
||||
l.WritePacket(head.ProtoNotify, b.Bytes())
|
||||
})
|
||||
}
|
||||
}
|
112
gold/proto/nat/nat.go
Normal file
112
gold/proto/nat/nat.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package nat
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/fumiama/orbyte/pbuf"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/fumiama/WireGold/config"
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
"github.com/fumiama/WireGold/gold/link"
|
||||
"github.com/fumiama/WireGold/gold/p2p"
|
||||
|
||||
"github.com/fumiama/WireGold/internal/bin"
|
||||
"github.com/fumiama/WireGold/internal/file"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 收到通告包的处理
|
||||
link.RegisterDispacher(head.ProtoNotify, func(_ *head.Packet, peer *link.Link, data pbuf.Bytes) {
|
||||
data.V(func(b []byte) {
|
||||
// 1. Data 解包
|
||||
// ---- 使用 head.Notify 解释 packet
|
||||
notify := make(head.Notify, 32)
|
||||
err := json.Unmarshal(b, ¬ify)
|
||||
if err != nil {
|
||||
logrus.Errorln(file.Header(), "notify json unmarshal err:", err)
|
||||
return
|
||||
}
|
||||
// 2. endpoint注册
|
||||
// ---- 遍历 Notify,注册对方的 endpoint 到
|
||||
// ---- connections,注意使用读写锁connmapmu
|
||||
for ps, ep := range notify {
|
||||
nw, epstr := ep[0], ep[1]
|
||||
if nw != peer.Me().EndPoint().Network() {
|
||||
logrus.Warnln(file.Header(), "ignore different network notify", nw, "addr", epstr)
|
||||
continue
|
||||
}
|
||||
addr, err := p2p.NewEndPoint(nw, epstr, peer.Me().NetworkConfigs()...)
|
||||
if err == nil {
|
||||
p, ok := peer.Me().IsInPeer(ps)
|
||||
if ok {
|
||||
if bin.IsNilInterface(p.EndPoint()) || !p.EndPoint().Euqal(addr) {
|
||||
p.SetEndPoint(addr)
|
||||
logrus.Infoln(file.Header(), "notify set ep of peer", ps, "to", ep)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln(file.Header(), "notify drop invalid peer:", ps, "ep:", ep)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
// 收到询问包的处理
|
||||
link.RegisterDispacher(head.ProtoQuery, func(_ *head.Packet, peer *link.Link, data pbuf.Bytes) {
|
||||
data.V(func(b []byte) {
|
||||
// 完成data解包与notify分发
|
||||
|
||||
// 1. Data 解包
|
||||
// ---- 使用 head.Query 解释 packet
|
||||
// ---- 根据 Query 确定需要封装的 Notify
|
||||
var peers head.Query
|
||||
err := json.Unmarshal(b, &peers)
|
||||
if err != nil {
|
||||
logrus.Errorln(file.Header(), "query json unmarshal err:", err)
|
||||
return
|
||||
}
|
||||
|
||||
if peer == nil || peer.Me() == nil {
|
||||
logrus.Errorln(file.Header(), "nil link/me")
|
||||
return
|
||||
}
|
||||
|
||||
// 2. notify分发
|
||||
// ---- 封装 Notify 到 新的 packet
|
||||
// ---- 发送到对方
|
||||
notify := make(head.Notify, len(peers))
|
||||
for _, p := range peers {
|
||||
lnk, ok := peer.Me().IsInPeer(p)
|
||||
eps := ""
|
||||
if peer.Me().EndPoint().Network() == "udp" { // udp has real p2p
|
||||
if bin.IsNilInterface(lnk.EndPoint()) {
|
||||
continue
|
||||
}
|
||||
eps = lnk.EndPoint().String()
|
||||
}
|
||||
if eps == "" {
|
||||
eps = peer.RawEndPoint() // use registered ep only
|
||||
}
|
||||
if eps == "" {
|
||||
continue
|
||||
}
|
||||
if ok && bin.IsNonNilInterface(lnk.EndPoint()) {
|
||||
notify[p] = [2]string{
|
||||
lnk.EndPoint().Network(),
|
||||
eps,
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(notify) > 0 {
|
||||
logrus.Infoln(file.Header(), "query wrap", len(notify), "notify")
|
||||
w := bin.SelectWriter()
|
||||
_ = json.NewEncoder(w).Encode(¬ify)
|
||||
w.P(func(b *pbuf.Buffer) {
|
||||
peer.WritePacket(head.ProtoNotify, b.Bytes(), peer.Me().TTL())
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
@@ -12,7 +12,9 @@ import (
|
||||
_ "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/udplite" // support udplite connection
|
||||
_ "github.com/fumiama/WireGold/gold/proto" // support basic protos
|
||||
_ "github.com/fumiama/WireGold/gold/proto/data" // support data proto
|
||||
_ "github.com/fumiama/WireGold/gold/proto/hello" // support hello proto
|
||||
_ "github.com/fumiama/WireGold/gold/proto/nat" // support nat proto
|
||||
|
||||
"github.com/fumiama/WireGold/config"
|
||||
"github.com/fumiama/WireGold/gold/head"
|
||||
@@ -125,7 +127,7 @@ func (s *Tunnel) handleWrite() {
|
||||
binary.LittleEndian.PutUint32(buf[:4], seq)
|
||||
seq++
|
||||
copy(buf[4:], b[:s.mtu-4])
|
||||
s.l.WritePacket(head.ProtoData, buf)
|
||||
s.l.WritePacket(head.ProtoData, buf, s.l.Me().TTL())
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[tunnel] seq", seq-1, "written")
|
||||
}
|
||||
@@ -134,7 +136,7 @@ func (s *Tunnel) handleWrite() {
|
||||
binary.LittleEndian.PutUint32(buf[:4], seq)
|
||||
seq++
|
||||
copy(buf[4:], b)
|
||||
s.l.WritePacket(head.ProtoData, buf[:len(b)+4])
|
||||
s.l.WritePacket(head.ProtoData, buf[:len(b)+4], s.l.Me().TTL())
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[tunnel] seq", seq-1, "written")
|
||||
}
|
||||
|
@@ -13,7 +13,9 @@ import (
|
||||
_ "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/udplite" // support udplite connection
|
||||
_ "github.com/fumiama/WireGold/gold/proto" // support basic protos
|
||||
_ "github.com/fumiama/WireGold/gold/proto/data" // support data proto
|
||||
_ "github.com/fumiama/WireGold/gold/proto/hello" // support hello proto
|
||||
_ "github.com/fumiama/WireGold/gold/proto/nat" // support nat proto
|
||||
|
||||
"github.com/fumiama/WireGold/config"
|
||||
"github.com/fumiama/WireGold/gold/link"
|
||||
@@ -115,6 +117,7 @@ func (wg *WG) init(srcport, dstport uint16) {
|
||||
SpeedLoop: wg.c.SpeedLoop,
|
||||
Mask: wg.c.Mask,
|
||||
Base14: wg.c.Base14,
|
||||
MaxTTL: wg.c.MaxTTL,
|
||||
})
|
||||
|
||||
for _, peer := range wg.c.Peers {
|
||||
|
Reference in New Issue
Block a user