228 lines
5.0 KiB
Go
228 lines
5.0 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"os/exec"
|
|
gen "slimming/proto/gen"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/474420502/check"
|
|
"github.com/474420502/perfectshutdown"
|
|
"github.com/songgao/packets/ethernet"
|
|
"github.com/songgao/water"
|
|
"google.golang.org/grpc"
|
|
)
|
|
|
|
type NetTunnel struct {
|
|
ifce *water.Interface
|
|
ifmac net.HardwareAddr
|
|
|
|
shutdown *perfectshutdown.PerfectShutdown
|
|
writer chan []byte
|
|
reader chan []byte
|
|
|
|
clients sync.Map
|
|
ipv4key any
|
|
|
|
gen.UnimplementedFrameServiceServer
|
|
}
|
|
|
|
func NewNetTunnel() *NetTunnel {
|
|
var err error
|
|
nt := &NetTunnel{
|
|
writer: make(chan []byte, 1000),
|
|
reader: make(chan []byte, 1000),
|
|
shutdown: perfectshutdown.New(),
|
|
clients: sync.Map{},
|
|
ipv4key: config.CurrentNodeKey,
|
|
}
|
|
|
|
nt.shutdown.OnClose(func() {
|
|
time.Sleep(time.Second * 1)
|
|
log.Println("OnClose")
|
|
os.Exit(0)
|
|
})
|
|
|
|
for ipv4, address := range config.IPv4Nodes {
|
|
nt.clients.Store(ipv4, NewRPCClient(address))
|
|
}
|
|
|
|
// log.Println(config)
|
|
nt.ifce, err = water.New(water.Config{
|
|
DeviceType: water.TAP,
|
|
PlatformSpecificParams: water.PlatformSpecificParams{
|
|
Name: "stun",
|
|
},
|
|
})
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
cmdstr := fmt.Sprintf("ip addr add %s dev stun", config.Network.Self.Virt)
|
|
log.Println(cmdstr)
|
|
cmd := strings.Split(cmdstr, " ")
|
|
err = exec.Command(cmd[0], cmd[1:]...).Run()
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
cmdstr = "ip link set dev stun up"
|
|
log.Println(cmdstr)
|
|
cmd = strings.Split(cmdstr, " ")
|
|
err = exec.Command(cmd[0], cmd[1:]...).Run()
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
ifas, err := net.Interfaces()
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
for _, ifa := range ifas {
|
|
if ifa.Name == nt.ifce.Name() {
|
|
nt.ifmac = ifa.HardwareAddr
|
|
log.Println(nt.ifmac)
|
|
}
|
|
}
|
|
|
|
go func() {
|
|
|
|
for rbuf := range nt.reader {
|
|
|
|
var frame ethernet.Frame = rbuf
|
|
|
|
// log.Printf("% x len: %d", frame.Ethertype(), len(frame))
|
|
switch frame.Ethertype() {
|
|
case ethernet.ARP:
|
|
arp := ARP(frame)
|
|
log.Printf("bytes len: %d type(arp): % x src: %s(%s) dst: %s(%s)", len(arp), frame.Ethertype(), arp.IPv4Source(), arp.Source(), arp.IPv4Destination(), arp.Destination()) // 数据长度
|
|
|
|
SwapBytes(frame, 0, frame, 6, 6)
|
|
binary.BigEndian.PutUint16(frame[20:22], 2)
|
|
SwapBytes(frame, 22, frame, 32, 10)
|
|
|
|
nt.ifce.Write(frame)
|
|
|
|
//TODO: 解析arp 回应arp
|
|
// nt.clients.Range(func(key, value any) bool {
|
|
// if key == nt.ipv4key {
|
|
// return true
|
|
// }
|
|
|
|
// client := value.(*RPCClient)
|
|
// client.CheckConnect()
|
|
// client.Frame <- frame
|
|
// log.Println(client.realAddr)
|
|
// return true
|
|
// })
|
|
case ethernet.IPv4:
|
|
payload := frame.Payload()
|
|
|
|
// dst := net.IP(payload[16:20]).To4()
|
|
// log.Printf("bytes len: %d type(ipv4): % x", len(rbuf), frame.Ethertype())
|
|
// log.Println(frame.Source(), net.IP(payload[12:16]).To4(), binary.BigEndian.Uint16(payload[20:22]), frame.Destination(), net.IP(payload[16:20]).To4(), binary.BigEndian.Uint16(payload[22:24]))
|
|
|
|
ipv4key := binary.BigEndian.Uint32(payload[16:20])
|
|
if v, ok := nt.clients.Load(ipv4key); ok {
|
|
client := v.(*RPCClient)
|
|
client.CheckConnect()
|
|
client.Push(frame)
|
|
// log.Println(len(frame))
|
|
}
|
|
}
|
|
|
|
// TODO: 判断地址 转入对应的客户端发送数据
|
|
|
|
if nt.shutdown.IsClose() {
|
|
break
|
|
}
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
for wbuf := range nt.writer {
|
|
var frame ethernet.Frame = wbuf
|
|
copy(frame[0:6], nt.ifmac)
|
|
|
|
// payload := frame.Payload()
|
|
|
|
// log.Printf("ifce write %d ", len(frame))
|
|
// log.Println(frame.Source(), net.IP(payload[12:16]).To4(), binary.BigEndian.Uint16(payload[20:22]), frame.Destination(), net.IP(payload[16:20]).To4(), binary.BigEndian.Uint16(payload[22:24]))
|
|
|
|
_, err := nt.ifce.Write(frame)
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
|
|
if nt.shutdown.IsClose() {
|
|
break
|
|
}
|
|
}
|
|
}()
|
|
|
|
return nt
|
|
}
|
|
|
|
func (nt *NetTunnel) Run() {
|
|
var (
|
|
frame ethernet.Frame
|
|
err error
|
|
n int
|
|
)
|
|
|
|
lis, err := net.Listen("tcp", config.Network.Self.Real)
|
|
if err != nil {
|
|
log.Fatalf("failed to listen: %v", err)
|
|
}
|
|
server := grpc.NewServer()
|
|
gen.RegisterFrameServiceServer(server, nt)
|
|
log.Printf("server listening at %v", lis.Addr())
|
|
defer server.Stop()
|
|
|
|
go func() {
|
|
if err := server.Serve(lis); err != nil {
|
|
log.Fatalf("failed to serve: %v", err)
|
|
}
|
|
}()
|
|
|
|
nt.shutdown.Loop(func(index int, ps *perfectshutdown.PerfectShutdown) {
|
|
frame.Resize(1500)
|
|
n, err = nt.ifce.Read(frame)
|
|
check.CheckPanic(err)
|
|
nt.reader <- frame[0:n] // 从网卡里读数据
|
|
})
|
|
}
|
|
|
|
func (nt *NetTunnel) SendFrames(stream gen.FrameService_SendFramesServer) error {
|
|
log.Printf("Start: SendFrames")
|
|
|
|
nt.shutdown.Loop(func(index int, ps *perfectshutdown.PerfectShutdown) {
|
|
request, err := stream.Recv()
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
// buf, err := Decompress(request.GetFrames())
|
|
// if err != nil {
|
|
// log.Panic(err)
|
|
// }
|
|
nt.writer <- request.GetFrames()
|
|
|
|
// frames := Decompress(request.GetFrames())
|
|
// if len(frames) > 0 {
|
|
// for _, frame := range frames {
|
|
// nt.writer <- frame
|
|
// }
|
|
// }
|
|
})
|
|
|
|
return nil
|
|
}
|