From c1133c9a69001c9d0757ff3b0de5d7cfac65bee1 Mon Sep 17 00:00:00 2001 From: Kusakabe Si Date: Thu, 2 Dec 2021 17:13:48 +0000 Subject: [PATCH] http based pong_msg --- .vscode/launch.json | 12 +- conn/bind_windows.go | 2 +- conn/bindtest/bindtest.go | 2 +- device/bind_test.go | 2 +- device/cookie.go | 2 +- device/device.go | 64 ++-- device/keypair.go | 2 +- device/noise-protocol.go | 4 +- device/peer.go | 40 +- device/receive.go | 35 +- device/receivesendproc.go | 277 +++++++++----- device/send.go | 14 +- device/sticky_default.go | 4 +- device/sticky_linux.go | 4 +- device/tap.go | 2 +- device/uapi.go | 2 +- example_config/super_mode/n1.yaml | 3 + example_config/super_mode/n100.yaml | 77 ++++ example_config/super_mode/n2.yaml | 2 + example_config/super_mode/s1.yaml | 5 + go.mod | 17 +- ipc/uapi_linux.go | 2 +- ipc/uapi_windows.go | 2 +- ipc/winpipe/winpipe_test.go | 2 +- main.go | 20 +- main_edge.go | 81 ++-- main_httpserver.go | 556 +++++++++++++++++----------- main_super.go | 285 +++++++------- {config => mtypes}/config.go | 64 +++- mtypes/functions.go | 65 ++++ {path => mtypes}/metamessage.go | 73 ++-- path/header.go | 14 +- path/ntp.go | 2 +- path/path.go | 168 +++++---- tap/tap_fd.go | 4 +- tap/tap_linux.go | 8 +- tap/tap_sock.go | 6 +- tap/tap_stdio.go | 4 +- tap/tap_udpsock.go | 4 +- tap/tap_vpp.go | 2 +- tap/tap_vpp_fake.go | 4 +- 41 files changed, 1214 insertions(+), 724 deletions(-) create mode 100644 example_config/super_mode/n100.yaml rename {config => mtypes}/config.go (77%) create mode 100644 mtypes/functions.go rename {path => mtypes}/metamessage.go (70%) diff --git a/.vscode/launch.json b/.vscode/launch.json index b8a1635..6736604 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "name": "Launch Package", + "name": "Launch Super", "type": "go", "request": "launch", "mode": "auto", @@ -13,6 +13,16 @@ "buildFlags": "-tags 'novpp'", "env": {"CGO_CFLAGS":"-I/usr/include/memif"}, "args":["-config","example_config/super_mode/s1.yaml","-mode","super"/*,"-example"*/], + }, + { + "name": "Launch Edge", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}", + "buildFlags": "-tags 'novpp'", + "env": {"CGO_CFLAGS":"-I/usr/include/memif"}, + "args":["-config","example_config/super_mode/n1.yaml","-mode","edge"/*,"-example"*/], } ] } \ No newline at end of file diff --git a/conn/bind_windows.go b/conn/bind_windows.go index 391dfe2..76b35db 100644 --- a/conn/bind_windows.go +++ b/conn/bind_windows.go @@ -16,7 +16,7 @@ import ( "golang.org/x/sys/windows" - "github.com/KusakabeSi/EtherGuardVPN/conn/winrio" + "github.com/KusakabeSi/EtherGuard-VPN/conn/winrio" ) const ( diff --git a/conn/bindtest/bindtest.go b/conn/bindtest/bindtest.go index da6f5ca..4d88bac 100644 --- a/conn/bindtest/bindtest.go +++ b/conn/bindtest/bindtest.go @@ -12,7 +12,7 @@ import ( "os" "strconv" - "github.com/KusakabeSi/EtherGuardVPN/conn" + "github.com/KusakabeSi/EtherGuard-VPN/conn" ) type ChannelBind struct { diff --git a/device/bind_test.go b/device/bind_test.go index 1455a59..999ba28 100644 --- a/device/bind_test.go +++ b/device/bind_test.go @@ -8,7 +8,7 @@ package device import ( "errors" - "github.com/KusakabeSi/EtherGuardVPN/conn" + "github.com/KusakabeSi/EtherGuard-VPN/conn" ) type DummyDatagram struct { diff --git a/device/cookie.go b/device/cookie.go index 50592e7..a0d052d 100644 --- a/device/cookie.go +++ b/device/cookie.go @@ -11,7 +11,7 @@ import ( "sync" "time" - "github.com/KusakabeSi/EtherGuardVPN/path" + "github.com/KusakabeSi/EtherGuard-VPN/path" "golang.org/x/crypto/blake2s" "golang.org/x/crypto/chacha20poly1305" ) diff --git a/device/device.go b/device/device.go index b50d335..9e315f0 100644 --- a/device/device.go +++ b/device/device.go @@ -9,18 +9,19 @@ import ( "bytes" "encoding/base64" "errors" + "fmt" "net" "runtime" "sync" "sync/atomic" "time" - "github.com/KusakabeSi/EtherGuardVPN/config" - "github.com/KusakabeSi/EtherGuardVPN/conn" - "github.com/KusakabeSi/EtherGuardVPN/path" - "github.com/KusakabeSi/EtherGuardVPN/ratelimiter" - "github.com/KusakabeSi/EtherGuardVPN/rwcancel" - "github.com/KusakabeSi/EtherGuardVPN/tap" + "github.com/KusakabeSi/EtherGuard-VPN/conn" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/path" + "github.com/KusakabeSi/EtherGuard-VPN/ratelimiter" + "github.com/KusakabeSi/EtherGuard-VPN/rwcancel" + "github.com/KusakabeSi/EtherGuard-VPN/tap" fixed_time_cache "github.com/KusakabeSi/go-cache" ) @@ -67,7 +68,7 @@ type Device struct { peers struct { sync.RWMutex // protects keyMap keyMap map[NoisePublicKey]*Peer - IDMap map[config.Vertex]*Peer + IDMap map[mtypes.Vertex]*Peer SuperPeer map[NoisePublicKey]*Peer Peer_state [32]byte LocalV4 net.IP @@ -77,13 +78,13 @@ type Device struct { ResetConnInterval float64 EdgeConfigPath string - EdgeConfig *config.EdgeConfig + EdgeConfig *mtypes.EdgeConfig SuperConfigPath string - SuperConfig *config.SuperConfig + SuperConfig *mtypes.SuperConfig - Event_server_register chan path.RegisterMsg - Event_server_pong chan path.PongMsg - Event_save_config chan struct{} + Event_server_register chan mtypes.RegisterMsg + Event_server_pong chan mtypes.PongMsg + Event_save_config chan struct{} Event_Supernode_OK chan struct{} @@ -91,17 +92,20 @@ type Device struct { cookieChecker CookieChecker IsSuperNode bool - ID config.Vertex + ID mtypes.Vertex DefaultTTL uint8 graph *path.IG l2fib sync.Map fibTimeout float64 - LogLevel config.LoggerInfo - DRoute config.DynamicRouteInfo + LogLevel mtypes.LoggerInfo + DRoute mtypes.DynamicRouteInfo DupData fixed_time_cache.Cache Version string AdditionalCost float64 + HttpPostCount uint64 + JWTSecret mtypes.JWTSecret + pool struct { messageBuffers *WaitPool inboundElements *WaitPool @@ -120,12 +124,12 @@ type Device struct { } ipcMutex sync.RWMutex - closed chan struct{} + closed chan int log *Logger } type IdAndTime struct { - ID config.Vertex + ID mtypes.Vertex Time time.Time } @@ -172,7 +176,7 @@ func removePeerLocked(device *Device, peer *Peer, key NoisePublicKey) { // remove from peer map id := peer.ID delete(device.peers.keyMap, key) - if id == config.SuperNodeMessage { + if id == mtypes.SuperNodeMessage { delete(device.peers.SuperPeer, key) } else { delete(device.peers.IDMap, id) @@ -320,10 +324,10 @@ func (device *Device) SetPrivateKey(sk NoisePrivateKey) error { return nil } -func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *Logger, graph *path.IG, IsSuperNode bool, configpath string, econfig *config.EdgeConfig, sconfig *config.SuperConfig, superevents *path.SUPER_Events, version string) *Device { +func NewDevice(tapDevice tap.Device, id mtypes.Vertex, bind conn.Bind, logger *Logger, graph *path.IG, IsSuperNode bool, configpath string, econfig *mtypes.EdgeConfig, sconfig *mtypes.SuperConfig, superevents *mtypes.SUPER_Events, version string) *Device { device := new(Device) device.state.state = uint32(deviceStateDown) - device.closed = make(chan struct{}) + device.closed = make(chan int) device.log = logger device.net.bind = bind device.tap.device = tapDevice @@ -334,12 +338,13 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L } device.tap.mtu = int32(mtu) device.peers.keyMap = make(map[NoisePublicKey]*Peer) - device.peers.IDMap = make(map[config.Vertex]*Peer) + device.peers.IDMap = make(map[mtypes.Vertex]*Peer) device.peers.SuperPeer = make(map[NoisePublicKey]*Peer) device.IsSuperNode = IsSuperNode device.ID = id device.graph = graph device.Version = version + device.JWTSecret = mtypes.ByteSlice2Byte32(mtypes.RandomBytes(32, []byte(fmt.Sprintf("%v", time.Now())))) device.rate.limiter.Init() device.indexTable.Init() @@ -371,8 +376,9 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L go device.RoutineResetConn() go device.RoutineClearL2FIB() go device.RoutineRecalculateNhTable() + go device.RoutinePostPeerInfo() } - + // create queues device.queue.handshake = newHandshakeQueue() @@ -398,9 +404,9 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L return device } -func (device *Device) LookupPeerIDAtConfig(pk NoisePublicKey) (ID config.Vertex, err error) { +func (device *Device) LookupPeerIDAtConfig(pk NoisePublicKey) (ID mtypes.Vertex, err error) { if device.IsSuperNode { - var peerlist []config.SuperPeerInfo + var peerlist []mtypes.SuperPeerInfo if device.SuperConfig == nil { return 0, errors.New("Superconfig is nil") } @@ -412,7 +418,7 @@ func (device *Device) LookupPeerIDAtConfig(pk NoisePublicKey) (ID config.Vertex, } } } else { - var peerlist []config.PeerInfo + var peerlist []mtypes.PeerInfo if device.EdgeConfig == nil { return 0, errors.New("EdgeConfig is nil") } @@ -491,7 +497,7 @@ func Str2PSKey(k string) (pk NoisePresharedKey, err error) { return } -func (device *Device) GetConnurl(v config.Vertex) string { +func (device *Device) GetConnurl(v mtypes.Vertex) string { if peer, has := device.peers.IDMap[v]; has { if peer.endpoint != nil { return peer.endpoint.DstToString() @@ -500,7 +506,7 @@ func (device *Device) GetConnurl(v config.Vertex) string { return "" } -func (device *Device) RemovePeerByID(id config.Vertex) { +func (device *Device) RemovePeerByID(id mtypes.Vertex) { device.peers.Lock() defer device.peers.Unlock() peer, ok := device.peers.IDMap[id] @@ -529,7 +535,7 @@ func (device *Device) RemoveAllPeers() { } device.peers.keyMap = make(map[NoisePublicKey]*Peer) - device.peers.IDMap = make(map[config.Vertex]*Peer) + device.peers.IDMap = make(map[mtypes.Vertex]*Peer) } func (device *Device) Close() { @@ -562,7 +568,7 @@ func (device *Device) Close() { close(device.closed) } -func (device *Device) Wait() chan struct{} { +func (device *Device) Wait() chan int { return device.closed } diff --git a/device/keypair.go b/device/keypair.go index 638d5d6..bb641a0 100644 --- a/device/keypair.go +++ b/device/keypair.go @@ -12,7 +12,7 @@ import ( "time" "unsafe" - "github.com/KusakabeSi/EtherGuardVPN/replay" + "github.com/KusakabeSi/EtherGuard-VPN/replay" ) /* Due to limitations in Go and /x/crypto there is currently diff --git a/device/noise-protocol.go b/device/noise-protocol.go index 6d7174e..87ac674 100644 --- a/device/noise-protocol.go +++ b/device/noise-protocol.go @@ -15,8 +15,8 @@ import ( "golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/poly1305" - "github.com/KusakabeSi/EtherGuardVPN/path" - "github.com/KusakabeSi/EtherGuardVPN/tai64n" + "github.com/KusakabeSi/EtherGuard-VPN/path" + "github.com/KusakabeSi/EtherGuard-VPN/tai64n" ) type handshakeState int diff --git a/device/peer.go b/device/peer.go index e59fa0e..5525a59 100644 --- a/device/peer.go +++ b/device/peer.go @@ -16,9 +16,9 @@ import ( "sync/atomic" "time" - "github.com/KusakabeSi/EtherGuardVPN/config" - "github.com/KusakabeSi/EtherGuardVPN/conn" - "github.com/KusakabeSi/EtherGuardVPN/path" + "github.com/KusakabeSi/EtherGuard-VPN/conn" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/path" "gopkg.in/yaml.v2" ) @@ -45,16 +45,19 @@ func NewEndpoint_trylist(peer *Peer, timeout time.Duration) *endpoint_trylist { } } -func (et *endpoint_trylist) UpdateSuper(urls map[string]float64) { +func (et *endpoint_trylist) UpdateSuper(urls mtypes.API_connurl, UseLocalIP bool) { et.Lock() defer et.Unlock() newmap_super := make(map[string]*endpoint_tryitem) - if len(urls) == 0 { + if urls.IsEmpty() { if et.peer.device.LogLevel.LogInternal { fmt.Println(fmt.Sprintf("Internal: Peer %v : Reset trylist(super) %v", et.peer.ID.ToString(), "nil")) } } - for url, it := range urls { + for url, it := range urls.GetList(UseLocalIP) { + if url == "" { + continue + } _, err := conn.LookupIP(url, 0) if err != nil { if et.peer.device.LogLevel.LogInternal { @@ -149,10 +152,13 @@ type Peer struct { device *Device endpoint conn.Endpoint endpoint_trylist *endpoint_trylist - LastPingReceived time.Time + + LastPacketReceivedAdd1Sec atomic.Value // *time.Time + + SingleWayLatency float64 stopping sync.WaitGroup // routines pending stop - ID config.Vertex + ID mtypes.Vertex AskedForNeighbor bool StaticConn bool //if true, this peer will not write to config file when roaming, and the endpoint will be reset periodically ConnURL string @@ -197,15 +203,15 @@ type Peer struct { persistentKeepaliveInterval uint32 // accessed atomically } -func (device *Device) NewPeer(pk NoisePublicKey, id config.Vertex, isSuper bool) (*Peer, error) { +func (device *Device) NewPeer(pk NoisePublicKey, id mtypes.Vertex, isSuper bool) (*Peer, error) { if isSuper == false { - if id < config.Special_NodeID { + if id < mtypes.Special_NodeID { //pass check } else { return nil, errors.New(fmt.Sprint("ID ", uint32(id), " is a special NodeID")) } } else { - if id == config.SuperNodeMessage { + if id == mtypes.SuperNodeMessage { //pass check } else { return nil, errors.New(fmt.Sprint("ID", uint32(id), "is not a supernode NodeID")) @@ -233,12 +239,14 @@ func (device *Device) NewPeer(pk NoisePublicKey, id config.Vertex, isSuper bool) fmt.Println("Internal: Create peer with ID : " + id.ToString() + " and PubKey:" + pk.ToString()) } peer := new(Peer) + peer.LastPacketReceivedAdd1Sec.Store(&time.Time{}) peer.Lock() defer peer.Unlock() peer.cookieGenerator.Init(pk) peer.device = device peer.endpoint_trylist = NewEndpoint_trylist(peer, path.S2TD(device.DRoute.PeerAliveTimeout)) + peer.SingleWayLatency = path.Infinity peer.queue.outbound = newAutodrainingOutboundQueue(device) peer.queue.inbound = newAutodrainingInboundQueue(device) peer.queue.staged = make(chan *QueueOutboundElement, QueueStagedSize) @@ -264,7 +272,7 @@ func (device *Device) NewPeer(pk NoisePublicKey, id config.Vertex, isSuper bool) peer.endpoint = nil // add - if id == config.SuperNodeMessage { // To communicate with supernode + if id == mtypes.SuperNodeMessage { // To communicate with supernode device.peers.SuperPeer[pk] = peer device.peers.keyMap[pk] = peer } else { // Regular peer, other edgenodes @@ -286,7 +294,7 @@ func (peer *Peer) IsPeerAlive() bool { if peer.endpoint == nil { return false } - if peer.LastPingReceived.Add(PeerAliveTimeout).Before(time.Now()) { + if peer.LastPacketReceivedAdd1Sec.Load().(*time.Time).Add(PeerAliveTimeout).Before(time.Now()) { return false } return true @@ -444,7 +452,7 @@ func (peer *Peer) Stop() { } func (peer *Peer) SetPSK(psk NoisePresharedKey) { - if peer.device.IsSuperNode == false && peer.ID < config.Special_NodeID && peer.device.DRoute.P2P.UseP2P == true { + if peer.device.IsSuperNode == false && peer.ID < mtypes.Special_NodeID && peer.device.DRoute.P2P.UseP2P == true { peer.device.log.Verbosef("Preshared keys disabled in P2P mode.") return } @@ -482,7 +490,7 @@ func (peer *Peer) SetEndpointFromPacket(endpoint conn.Endpoint) { return } peer.Lock() - if peer.ID == config.SuperNodeMessage { + if peer.ID == mtypes.SuperNodeMessage { conn, err := net.Dial("udp", endpoint.DstToString()) defer conn.Close() if err == nil { @@ -545,7 +553,7 @@ func (device *Device) SaveToConfig(peer *Peer, endpoint conn.Endpoint) { } } if !foundInFile { - device.EdgeConfig.Peers = append(device.EdgeConfig.Peers, config.PeerInfo{ + device.EdgeConfig.Peers = append(device.EdgeConfig.Peers, mtypes.PeerInfo{ NodeID: peer.ID, PubKey: pubkeystr, PSKey: pskstr, diff --git a/device/receive.go b/device/receive.go index b772c29..45e1a43 100644 --- a/device/receive.go +++ b/device/receive.go @@ -20,10 +20,10 @@ import ( "github.com/google/gopacket/layers" "golang.org/x/crypto/chacha20poly1305" - "github.com/KusakabeSi/EtherGuardVPN/config" - "github.com/KusakabeSi/EtherGuardVPN/conn" - "github.com/KusakabeSi/EtherGuardVPN/path" - "github.com/KusakabeSi/EtherGuardVPN/tap" + "github.com/KusakabeSi/EtherGuard-VPN/conn" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/path" + "github.com/KusakabeSi/EtherGuard-VPN/tap" ) type QueueHandshakeElement struct { @@ -421,12 +421,17 @@ func (peer *Peer) RoutineSequentialReceiver() { } var EgHeader path.EgHeader var err error - var src_nodeID config.Vertex - var dst_nodeID config.Vertex + var src_nodeID mtypes.Vertex + var dst_nodeID mtypes.Vertex var packet_type path.Usage should_process := false should_receive := false should_transfer := false + currentTime := time.Now() + storeTime := currentTime.Add(time.Second) + if currentTime.After((*peer.LastPacketReceivedAdd1Sec.Load().(*time.Time))) { + peer.LastPacketReceivedAdd1Sec.Store(&storeTime) + } elem.Lock() if elem.packet == nil { // decryption failed @@ -463,26 +468,24 @@ func (peer *Peer) RoutineSequentialReceiver() { dst_nodeID = EgHeader.GetDst() elem.packet = elem.packet[:EgHeader.GetPacketLength()+path.EgHeaderLen] // EG header + true packet packet_type = elem.Type - peer.LastPingReceived = time.Now() if device.IsSuperNode { - peer.LastPingReceived = time.Now() switch dst_nodeID { - case config.ControlMessage: + case mtypes.ControlMessage: should_process = true - case config.SuperNodeMessage: + case mtypes.SuperNodeMessage: should_process = true default: device.log.Errorf("Invalid dst_nodeID received. Check your code for bug") } } else { switch dst_nodeID { - case config.Broadcast: + case mtypes.Broadcast: should_receive = true should_transfer = true - case config.SuperNodeMessage: + case mtypes.SuperNodeMessage: should_process = true - case config.ControlMessage: + case mtypes.ControlMessage: packet := elem.packet[path.EgHeaderLen:] //true packet if device.CheckNoDup(packet) { should_process = true @@ -514,10 +517,10 @@ func (peer *Peer) RoutineSequentialReceiver() { device.log.Verbosef("TTL is 0 %v", dst_nodeID) } else { EgHeader.SetTTL(l2ttl - 1) - if dst_nodeID == config.Broadcast { //Regular transfer algorithm + if dst_nodeID == mtypes.Broadcast { //Regular transfer algorithm device.TransitBoardcastPacket(src_nodeID, peer.ID, elem.Type, elem.packet, MessageTransportOffsetContent) - } else if dst_nodeID == config.ControlMessage { // Control Message will try send to every know node regardless the connectivity - skip_list := make(map[config.Vertex]bool) + } else if dst_nodeID == mtypes.ControlMessage { // Control Message will try send to every know node regardless the connectivity + skip_list := make(map[mtypes.Vertex]bool) skip_list[src_nodeID] = true //Don't send to conimg peer and source peer skip_list[peer.ID] = true device.SpreadPacket(skip_list, elem.Type, elem.packet, MessageTransportOffsetContent) diff --git a/device/receivesendproc.go b/device/receivesendproc.go index e4a6c35..bb6d307 100644 --- a/device/receivesendproc.go +++ b/device/receivesendproc.go @@ -2,6 +2,7 @@ package device import ( "bytes" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -12,11 +13,13 @@ import ( "net/url" "strconv" "strings" + "syscall" "time" - "github.com/KusakabeSi/EtherGuardVPN/config" - "github.com/KusakabeSi/EtherGuardVPN/path" - "github.com/KusakabeSi/EtherGuardVPN/tap" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/path" + "github.com/KusakabeSi/EtherGuard-VPN/tap" + "github.com/golang-jwt/jwt" "github.com/google/gopacket" "github.com/google/gopacket/layers" ) @@ -64,7 +67,7 @@ func (device *Device) SendPacket(peer *Peer, usage path.Usage, packet []byte, of } } -func (device *Device) BoardcastPacket(skip_list map[config.Vertex]bool, usage path.Usage, packet []byte, offset int) { // Send packet to all connected peers +func (device *Device) BoardcastPacket(skip_list map[mtypes.Vertex]bool, usage path.Usage, packet []byte, offset int) { // Send packet to all connected peers send_list := device.graph.GetBoardcastList(device.ID) for node_id, _ := range skip_list { send_list[node_id] = false @@ -79,7 +82,7 @@ func (device *Device) BoardcastPacket(skip_list map[config.Vertex]bool, usage pa device.peers.RUnlock() } -func (device *Device) SpreadPacket(skip_list map[config.Vertex]bool, usage path.Usage, packet []byte, offset int) { // Send packet to all peers no matter it is alive +func (device *Device) SpreadPacket(skip_list map[mtypes.Vertex]bool, usage path.Usage, packet []byte, offset int) { // Send packet to all peers no matter it is alive device.peers.RLock() for peer_id, peer_out := range device.peers.IDMap { if _, ok := skip_list[peer_id]; ok { @@ -93,7 +96,7 @@ func (device *Device) SpreadPacket(skip_list map[config.Vertex]bool, usage path. device.peers.RUnlock() } -func (device *Device) TransitBoardcastPacket(src_nodeID config.Vertex, in_id config.Vertex, usage path.Usage, packet []byte, offset int) { +func (device *Device) TransitBoardcastPacket(src_nodeID mtypes.Vertex, in_id mtypes.Vertex, usage path.Usage, packet []byte, offset int) { node_boardcast_list := device.graph.GetBoardcastThroughList(device.ID, in_id, src_nodeID) device.peers.RLock() for peer_id := range node_boardcast_list { @@ -132,11 +135,11 @@ func (device *Device) process_received(msg_type path.Usage, peer *Peer, body []b if device.IsSuperNode { switch msg_type { case path.Register: - if content, err := path.ParseRegisterMsg(body); err == nil { + if content, err := mtypes.ParseRegisterMsg(body); err == nil { return device.server_process_RegisterMsg(peer, content) } case path.PongPacket: - if content, err := path.ParsePongMsg(body); err == nil { + if content, err := mtypes.ParsePongMsg(body); err == nil { return device.server_process_Pong(peer, content) } default: @@ -145,31 +148,31 @@ func (device *Device) process_received(msg_type path.Usage, peer *Peer, body []b } else { switch msg_type { case path.UpdatePeer: - if content, err := path.ParseUpdatePeerMsg(body); err == nil { + if content, err := mtypes.ParseUpdatePeerMsg(body); err == nil { go device.process_UpdatePeerMsg(peer, content) } case path.UpdateNhTable: - if content, err := path.ParseUpdateNhTableMsg(body); err == nil { + if content, err := mtypes.ParseUpdateNhTableMsg(body); err == nil { go device.process_UpdateNhTableMsg(peer, content) } case path.UpdateError: - if content, err := path.ParseUpdateErrorMsg(body); err == nil { + if content, err := mtypes.ParseUpdateErrorMsg(body); err == nil { device.process_UpdateErrorMsg(peer, content) } case path.PingPacket: - if content, err := path.ParsePingMsg(body); err == nil { + if content, err := mtypes.ParsePingMsg(body); err == nil { return device.process_ping(peer, content) } case path.PongPacket: - if content, err := path.ParsePongMsg(body); err == nil { + if content, err := mtypes.ParsePongMsg(body); err == nil { return device.process_pong(peer, content) } case path.QueryPeer: - if content, err := path.ParseQueryPeerMsg(body); err == nil { + if content, err := mtypes.ParseQueryPeerMsg(body); err == nil { return device.process_RequestPeerMsg(content) } case path.BroadcastPeer: - if content, err := path.ParseBoardcastPeerMsg(body); err == nil { + if content, err := mtypes.ParseBoardcastPeerMsg(body); err == nil { return device.process_BoardcastPeerMsg(peer, content) } default: @@ -182,42 +185,42 @@ func (device *Device) process_received(msg_type path.Usage, peer *Peer, body []b func (device *Device) sprint_received(msg_type path.Usage, body []byte) string { switch msg_type { case path.Register: - if content, err := path.ParseRegisterMsg(body); err == nil { + if content, err := mtypes.ParseRegisterMsg(body); err == nil { return content.ToString() } return "RegisterMsg: Parse failed" case path.UpdatePeer: - if content, err := path.ParseUpdatePeerMsg(body); err == nil { + if content, err := mtypes.ParseUpdatePeerMsg(body); err == nil { return content.ToString() } return "UpdatePeerMsg: Parse failed" case path.UpdateNhTable: - if content, err := path.ParseUpdateNhTableMsg(body); err == nil { + if content, err := mtypes.ParseUpdateNhTableMsg(body); err == nil { return content.ToString() } return "UpdateNhTableMsg: Parse failed" case path.UpdateError: - if content, err := path.ParseUpdateErrorMsg(body); err == nil { + if content, err := mtypes.ParseUpdateErrorMsg(body); err == nil { return content.ToString() } return "UpdateErrorMsg: Parse failed" case path.PingPacket: - if content, err := path.ParsePingMsg(body); err == nil { + if content, err := mtypes.ParsePingMsg(body); err == nil { return content.ToString() } return "PingPacketMsg: Parse failed" case path.PongPacket: - if content, err := path.ParsePongMsg(body); err == nil { + if content, err := mtypes.ParsePongMsg(body); err == nil { return content.ToString() } return "PongPacketMsg: Parse failed" case path.QueryPeer: - if content, err := path.ParseQueryPeerMsg(body); err == nil { + if content, err := mtypes.ParseQueryPeerMsg(body); err == nil { return content.ToString() } return "QueryPeerMsg: Parse failed" case path.BroadcastPeer: - if content, err := path.ParseBoardcastPeerMsg(body); err == nil { + if content, err := mtypes.ParseBoardcastPeerMsg(body); err == nil { return content.ToString() } return "BoardcastPeerMsg: Parse failed" @@ -226,8 +229,8 @@ func (device *Device) sprint_received(msg_type path.Usage, body []byte) string { } } -func (device *Device) GeneratePingPacket(src_nodeID config.Vertex, request_reply int) ([]byte, path.Usage, error) { - body, err := path.GetByte(&path.PingMsg{ +func (device *Device) GeneratePingPacket(src_nodeID mtypes.Vertex, request_reply int) ([]byte, path.Usage, error) { + body, err := mtypes.GetByte(&mtypes.PingMsg{ Src_nodeID: src_nodeID, Time: device.graph.GetCurrentTime(), RequestReply: request_reply, @@ -240,7 +243,7 @@ func (device *Device) GeneratePingPacket(src_nodeID config.Vertex, request_reply if err != nil { return nil, path.PingPacket, err } - header.SetDst(config.ControlMessage) + header.SetDst(mtypes.ControlMessage) header.SetTTL(0) header.SetSrc(device.ID) header.SetPacketLength(uint16(len(body))) @@ -266,31 +269,31 @@ func compareVersion(v1 string, v2 string) bool { return v1 == v2 } -func (device *Device) server_process_RegisterMsg(peer *Peer, content path.RegisterMsg) error { - UpdateErrorMsg := path.UpdateErrorMsg{ +func (device *Device) server_process_RegisterMsg(peer *Peer, content mtypes.RegisterMsg) error { + UpdateErrorMsg := mtypes.ServerCommandMsg{ Node_id: peer.ID, - Action: path.NoAction, + Action: mtypes.NoAction, ErrorCode: 0, ErrorMsg: "", } if peer.ID != content.Node_id { - UpdateErrorMsg = path.UpdateErrorMsg{ + UpdateErrorMsg = mtypes.ServerCommandMsg{ Node_id: peer.ID, - Action: path.Shutdown, - ErrorCode: 401, + Action: mtypes.ThrowError, + ErrorCode: int(syscall.EPERM), ErrorMsg: fmt.Sprintf("Your nodeID: %v is not match with registered nodeID: %v", content.Node_id, peer.ID), } } if compareVersion(content.Version, device.Version) == false { - UpdateErrorMsg = path.UpdateErrorMsg{ + UpdateErrorMsg = mtypes.ServerCommandMsg{ Node_id: peer.ID, - Action: path.Shutdown, - ErrorCode: 400, + Action: mtypes.ThrowError, + ErrorCode: int(syscall.ENOSYS), ErrorMsg: fmt.Sprintf("Your version: \"%v\" is not compatible with our version: \"%v\"", content.Version, device.Version), } } - if UpdateErrorMsg.Action != path.NoAction { - body, err := path.GetByte(&UpdateErrorMsg) + if UpdateErrorMsg.Action != mtypes.NoAction { + body, err := mtypes.GetByte(&UpdateErrorMsg) if err != nil { return err } @@ -300,37 +303,34 @@ func (device *Device) server_process_RegisterMsg(peer *Peer, content path.Regist header.SetTTL(device.DefaultTTL) header.SetPacketLength(uint16(len(body))) copy(buf[path.EgHeaderLen:], body) - header.SetDst(config.SuperNodeMessage) + header.SetDst(mtypes.SuperNodeMessage) device.SendPacket(peer, path.UpdateError, buf, MessageTransportOffsetContent) return nil } - peer.LastPingReceived = time.Now() device.Event_server_register <- content return nil } -func (device *Device) server_process_Pong(peer *Peer, content path.PongMsg) error { - peer.LastPingReceived = time.Now() +func (device *Device) server_process_Pong(peer *Peer, content mtypes.PongMsg) error { device.Event_server_pong <- content return nil } -func (device *Device) process_ping(peer *Peer, content path.PingMsg) error { - peer.LastPingReceived = time.Now() - //peer.Lock() - //remove peer.endpoint_trylist - //peer.Unlock() +func (device *Device) process_ping(peer *Peer, content mtypes.PingMsg) error { + Timediff := device.graph.GetCurrentTime().Sub(content.Time).Seconds() + peer.SingleWayLatency = Timediff - PongMSG := path.PongMsg{ + PongMSG := mtypes.PongMsg{ Src_nodeID: content.Src_nodeID, Dst_nodeID: device.ID, - Timediff: device.graph.GetCurrentTime().Sub(content.Time), + Timediff: Timediff, + TimeToAlive: device.DRoute.PeerAliveTimeout, AdditionalCost: device.AdditionalCost, } if device.DRoute.P2P.UseP2P && time.Now().After(device.graph.NhTableExpire) { - device.graph.UpdateLatency(content.Src_nodeID, device.ID, PongMSG.Timediff, device.AdditionalCost, true, false) + device.graph.UpdateLatency(content.Src_nodeID, device.ID, PongMSG.Timediff, device.DRoute.PeerAliveTimeout, device.AdditionalCost, true, false) } - body, err := path.GetByte(&PongMSG) + body, err := mtypes.GetByte(&PongMSG) if err != nil { return err } @@ -341,27 +341,27 @@ func (device *Device) process_ping(peer *Peer, content path.PingMsg) error { header.SetPacketLength(uint16(len(body))) copy(buf[path.EgHeaderLen:], body) if device.DRoute.SuperNode.UseSuperNode { - header.SetDst(config.SuperNodeMessage) + header.SetDst(mtypes.SuperNodeMessage) device.Send2Super(path.PongPacket, buf, MessageTransportOffsetContent) } if device.DRoute.P2P.UseP2P { - header.SetDst(config.ControlMessage) - device.SpreadPacket(make(map[config.Vertex]bool), path.PongPacket, buf, MessageTransportOffsetContent) + header.SetDst(mtypes.ControlMessage) + device.SpreadPacket(make(map[mtypes.Vertex]bool), path.PongPacket, buf, MessageTransportOffsetContent) } go device.SendPing(peer, content.RequestReply, 0, 3) return nil } -func (device *Device) process_pong(peer *Peer, content path.PongMsg) error { +func (device *Device) process_pong(peer *Peer, content mtypes.PongMsg) error { if device.DRoute.P2P.UseP2P { if time.Now().After(device.graph.NhTableExpire) { - device.graph.UpdateLatency(content.Src_nodeID, content.Dst_nodeID, content.Timediff, content.AdditionalCost, true, false) + device.graph.UpdateLatency(content.Src_nodeID, content.Dst_nodeID, content.Timediff, device.DRoute.PeerAliveTimeout, content.AdditionalCost, true, false) } if !peer.AskedForNeighbor { - QueryPeerMsg := path.QueryPeerMsg{ + QueryPeerMsg := mtypes.QueryPeerMsg{ Request_ID: uint32(device.ID), } - body, err := path.GetByte(&QueryPeerMsg) + body, err := mtypes.GetByte(&QueryPeerMsg) if err != nil { return err } @@ -377,10 +377,10 @@ func (device *Device) process_pong(peer *Peer, content path.PongMsg) error { return nil } -func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerMsg) error { +func (device *Device) process_UpdatePeerMsg(peer *Peer, content mtypes.UpdatePeerMsg) error { var send_signal bool if device.DRoute.SuperNode.UseSuperNode { - if peer.ID != config.SuperNodeMessage { + if peer.ID != mtypes.SuperNodeMessage { if device.LogLevel.LogControl { fmt.Println("Control: Ignored UpdateErrorMsg. Not from supernode.") } @@ -392,7 +392,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM } return nil } - var peer_infos config.API_Peers + var peer_infos mtypes.API_Peers downloadurl := device.DRoute.SuperNode.APIUrl + "/peerinfo?NodeID=" + strconv.Itoa(int(device.ID)) + "&PubKey=" + url.QueryEscape(device.staticIdentity.publicKey.ToString()) + "&State=" + url.QueryEscape(string(content.State_hash[:])) if device.LogLevel.LogControl { @@ -452,17 +452,17 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM } thepeer := device.LookupPeer(sk) if thepeer == nil { //not exist in local - if len(peerinfo.Connurl) == 0 { + if len(peerinfo.Connurl.ExternalV4)+len(peerinfo.Connurl.ExternalV6)+len(peerinfo.Connurl.LocalV4)+len(peerinfo.Connurl.LocalV6) == 0 { continue } if device.LogLevel.LogControl { fmt.Println("Control: Add new peer to local ID:" + peerinfo.NodeID.ToString() + " PubKey:" + PubKey) } if device.graph.Weight(device.ID, peerinfo.NodeID, false) == path.Infinity { // add node to graph - device.graph.UpdateLatency(device.ID, peerinfo.NodeID, path.S2TD(path.Infinity), device.AdditionalCost, true, false) + device.graph.UpdateLatency(device.ID, peerinfo.NodeID, path.Infinity, 0, device.AdditionalCost, true, false) } if device.graph.Weight(peerinfo.NodeID, device.ID, false) == path.Infinity { // add node to graph - device.graph.UpdateLatency(peerinfo.NodeID, device.ID, path.S2TD(path.Infinity), device.AdditionalCost, true, false) + device.graph.UpdateLatency(peerinfo.NodeID, device.ID, path.Infinity, 0, device.AdditionalCost, true, false) } device.NewPeer(sk, peerinfo.NodeID, false) thepeer = device.LookupPeer(sk) @@ -476,7 +476,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM thepeer.SetPSK(pk) } - thepeer.endpoint_trylist.UpdateSuper(peerinfo.Connurl) + thepeer.endpoint_trylist.UpdateSuper(*peerinfo.Connurl, !device.EdgeConfig.DynamicRoute.SuperNode.SkipLocalIP) if !thepeer.IsPeerAlive() { //Peer died, try to switch to this new endpoint send_signal = true @@ -490,9 +490,9 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM return nil } -func (device *Device) process_UpdateNhTableMsg(peer *Peer, content path.UpdateNhTableMsg) error { +func (device *Device) process_UpdateNhTableMsg(peer *Peer, content mtypes.UpdateNhTableMsg) error { if device.DRoute.SuperNode.UseSuperNode { - if peer.ID != config.SuperNodeMessage { + if peer.ID != mtypes.SuperNodeMessage { if device.LogLevel.LogControl { fmt.Println("Control: Ignored UpdateErrorMsg. Not from supernode.") } @@ -505,7 +505,7 @@ func (device *Device) process_UpdateNhTableMsg(peer *Peer, content path.UpdateNh device.graph.NhTableExpire = time.Now().Add(device.graph.SuperNodeInfoTimeout) return nil } - var NhTable config.NextHopTable + var NhTable mtypes.NextHopTable if bytes.Equal(device.graph.NhTableHash[:], content.State_hash[:]) { return nil } @@ -543,27 +543,29 @@ func (device *Device) process_UpdateNhTableMsg(peer *Peer, content path.UpdateNh return nil } -func (device *Device) process_UpdateErrorMsg(peer *Peer, content path.UpdateErrorMsg) error { - if peer.ID != config.SuperNodeMessage { +func (device *Device) process_UpdateErrorMsg(peer *Peer, content mtypes.ServerCommandMsg) error { + if peer.ID != mtypes.SuperNodeMessage { if device.LogLevel.LogControl { fmt.Println("Control: Ignored UpdateErrorMsg. Not from supernode.") } return nil } - device.log.Errorf(strconv.Itoa(content.ErrorCode) + ": " + content.ErrorMsg) - if content.Action == path.Shutdown { - device.closed <- struct{}{} - } else if content.Action == path.Panic { + device.log.Errorf(strconv.Itoa(int(content.ErrorCode)) + ": " + content.ErrorMsg) + if content.Action == mtypes.Shutdown { + device.closed <- 0 + } else if content.Action == mtypes.ThrowError { + device.closed <- content.ErrorCode + } else if content.Action == mtypes.Panic { panic(content.ToString()) } return nil } -func (device *Device) process_RequestPeerMsg(content path.QueryPeerMsg) error { //Send all my peers to all my peers +func (device *Device) process_RequestPeerMsg(content mtypes.QueryPeerMsg) error { //Send all my peers to all my peers if device.DRoute.P2P.UseP2P { device.peers.RLock() for pubkey, peer := range device.peers.keyMap { - if peer.ID >= config.Special_NodeID { + if peer.ID >= mtypes.Special_NodeID { continue } if peer.endpoint == nil { @@ -576,33 +578,33 @@ func (device *Device) process_RequestPeerMsg(content path.QueryPeerMsg) error { } peer.handshake.mutex.RLock() - response := path.BoardcastPeerMsg{ + response := mtypes.BoardcastPeerMsg{ Request_ID: content.Request_ID, NodeID: peer.ID, PubKey: pubkey, ConnURL: peer.endpoint.DstToString(), } peer.handshake.mutex.RUnlock() - body, err := path.GetByte(response) + body, err := mtypes.GetByte(response) if err != nil { device.log.Errorf("Error at receivesendproc.go line221: ", err) continue } buf := make([]byte, path.EgHeaderLen+len(body)) header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen]) - header.SetDst(config.ControlMessage) + header.SetDst(mtypes.ControlMessage) header.SetTTL(device.DefaultTTL) header.SetSrc(device.ID) header.SetPacketLength(uint16(len(body))) copy(buf[path.EgHeaderLen:], body) - device.SpreadPacket(make(map[config.Vertex]bool), path.BroadcastPeer, buf, MessageTransportOffsetContent) + device.SpreadPacket(make(map[mtypes.Vertex]bool), path.BroadcastPeer, buf, MessageTransportOffsetContent) } device.peers.RUnlock() } return nil } -func (device *Device) process_BoardcastPeerMsg(peer *Peer, content path.BoardcastPeerMsg) error { +func (device *Device) process_BoardcastPeerMsg(peer *Peer, content mtypes.BoardcastPeerMsg) error { if device.DRoute.P2P.UseP2P { var pk NoisePublicKey if content.Request_ID == uint32(device.ID) { @@ -618,10 +620,10 @@ func (device *Device) process_BoardcastPeerMsg(peer *Peer, content path.Boardcas fmt.Println("Control: Add new peer to local ID:" + content.NodeID.ToString() + " PubKey:" + pk.ToString()) } if device.graph.Weight(device.ID, content.NodeID, false) == path.Infinity { // add node to graph - device.graph.UpdateLatency(device.ID, content.NodeID, path.S2TD(path.Infinity), device.AdditionalCost, true, false) + device.graph.UpdateLatency(device.ID, content.NodeID, path.Infinity, 0, device.AdditionalCost, true, false) } if device.graph.Weight(content.NodeID, device.ID, false) == path.Infinity { // add node to graph - device.graph.UpdateLatency(content.NodeID, device.ID, path.S2TD(path.Infinity), device.AdditionalCost, true, false) + device.graph.UpdateLatency(content.NodeID, device.ID, path.Infinity, 0, device.AdditionalCost, true, false) } device.NewPeer(pk, content.NodeID, false) } @@ -643,7 +645,7 @@ func (device *Device) RoutineSetEndpoint() { NextRun := false <-device.event_tryendpoint for _, thepeer := range device.peers.IDMap { - if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.PeerAliveTimeout)).After(time.Now()) { + if thepeer.LastPacketReceivedAdd1Sec.Load().(*time.Time).Add(path.S2TD(device.DRoute.PeerAliveTimeout)).After(time.Now()) { //Peer alives continue } else { @@ -701,7 +703,7 @@ func (device *Device) RoutineSendPing() { } for { packet, usage, _ := device.GeneratePingPacket(device.ID, 0) - device.SpreadPacket(make(map[config.Vertex]bool), usage, packet, MessageTransportOffsetContent) + device.SpreadPacket(make(map[mtypes.Vertex]bool), usage, packet, MessageTransportOffsetContent) time.Sleep(path.S2TD(device.DRoute.SendPingInterval)) } } @@ -712,24 +714,17 @@ func (device *Device) RoutineRegister() { } _ = <-device.Event_Supernode_OK for { - - body, _ := path.GetByte(path.RegisterMsg{ + body, _ := mtypes.GetByte(mtypes.RegisterMsg{ Node_id: device.ID, PeerStateHash: device.peers.Peer_state, NhStateHash: device.graph.NhTableHash, Version: device.Version, - LocalV4: net.UDPAddr{ - IP: device.peers.LocalV4, - Port: int(device.net.port), - }, - LocalV6: net.UDPAddr{ - IP: device.peers.LocalV6, - Port: int(device.net.port), - }, + JWTSecret: device.JWTSecret, + HttpPostCount: device.HttpPostCount, }) buf := make([]byte, path.EgHeaderLen+len(body)) header, _ := path.NewEgHeader(buf[0:path.EgHeaderLen]) - header.SetDst(config.SuperNodeMessage) + header.SetDst(mtypes.SuperNodeMessage) header.SetTTL(0) header.SetSrc(device.ID) header.SetPacketLength(uint16(len(body))) @@ -739,6 +734,94 @@ func (device *Device) RoutineRegister() { } } +func (device *Device) RoutinePostPeerInfo() { + if !(device.DRoute.SuperNode.UseSuperNode) { + return + } + if device.DRoute.SuperNode.HttpPostInterval <= 0 { + return + } + for { + // Stat all latency + device.peers.RLock() + pongs := make([]mtypes.PongMsg, 0, len(device.peers.IDMap)) + for id, peer := range device.peers.IDMap { + device.peers.RUnlock() + if peer.IsPeerAlive() { + pong := mtypes.PongMsg{ + RequestID: 0, + Src_nodeID: device.ID, + Dst_nodeID: id, + Timediff: peer.SingleWayLatency, + TimeToAlive: time.Now().Sub(*peer.LastPacketReceivedAdd1Sec.Load().(*time.Time)).Seconds() + device.DRoute.PeerAliveTimeout, + } + pongs = append(pongs, pong) + if device.LogLevel.LogControl { + fmt.Println("Control: Pack to: Post body " + pong.ToString()) + } + } + device.peers.RLock() + } + device.peers.RUnlock() + // Prepare post paramater and post body + LocalV4s := make(map[string]float64) + LocalV6s := make(map[string]float64) + if !device.peers.LocalV4.Equal(net.IP{}) { + LocalV4 := net.UDPAddr{ + IP: device.peers.LocalV4, + Port: int(device.net.port), + } + + LocalV4s[LocalV4.String()] = 100 + } + if !device.peers.LocalV6.Equal(net.IP{}) { + LocalV6 := net.UDPAddr{ + IP: device.peers.LocalV6, + Port: int(device.net.port), + } + LocalV4s[LocalV6.String()] = 100 + } + + body, _ := mtypes.GetByte(mtypes.API_report_peerinfo{ + Pongs: pongs, + LocalV4s: LocalV4s, + LocalV6s: LocalV6s, + }) + body = mtypes.Gzip(body) + bodyhash := base64.StdEncoding.EncodeToString(body) + token := jwt.NewWithClaims(jwt.SigningMethodHS256, mtypes.API_report_peerinfo_jwt_claims{ + PostCount: device.HttpPostCount, + BodyHash: bodyhash, + }) + tokenString, err := token.SignedString(device.JWTSecret[:]) + // Construct post request + client := &http.Client{} + downloadurl := device.DRoute.SuperNode.APIUrl + "/post/nodeinfo" + req, err := http.NewRequest("POST", downloadurl, bytes.NewReader(body)) + q := req.URL.Query() + q.Add("NodeID", device.ID.ToString()) + q.Add("JWTSig", tokenString) + req.URL.RawQuery = q.Encode() + req.Header.Set("Content-Type", "application/binary") + device.HttpPostCount += 1 + if device.LogLevel.LogControl { + fmt.Println("Control: Post to " + req.URL.String()) + } + resp, err := client.Do(req) + if err != nil { + device.log.Errorf("RoutinePostPeerInfo: " + err.Error()) + } else { + if device.LogLevel.LogControl { + res, _ := ioutil.ReadAll(resp.Body) + fmt.Println("Control: Post result " + string(res)) + } + resp.Body.Close() + } + + time.Sleep(mtypes.S2TD(device.DRoute.SuperNode.HttpPostInterval * 0.8)) + } +} + func (device *Device) RoutineRecalculateNhTable() { if device.graph.TimeoutCheckInterval == 0 { return @@ -763,8 +846,8 @@ func (device *Device) RoutineSpreadAllMyNeighbor() { return } for { - device.process_RequestPeerMsg(path.QueryPeerMsg{ - Request_ID: uint32(config.Broadcast), + device.process_RequestPeerMsg(mtypes.QueryPeerMsg{ + Request_ID: uint32(mtypes.Broadcast), }) time.Sleep(path.S2TD(device.DRoute.P2P.SendPeerInterval)) } diff --git a/device/send.go b/device/send.go index ddf05b2..5fc6d1f 100644 --- a/device/send.go +++ b/device/send.go @@ -16,9 +16,9 @@ import ( "sync/atomic" "time" - "github.com/KusakabeSi/EtherGuardVPN/config" - "github.com/KusakabeSi/EtherGuardVPN/path" - "github.com/KusakabeSi/EtherGuardVPN/tap" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/path" + "github.com/KusakabeSi/EtherGuard-VPN/tap" "github.com/google/gopacket" "github.com/google/gopacket/layers" "golang.org/x/crypto/chacha20poly1305" @@ -256,9 +256,9 @@ func (device *Device) RoutineReadFromTUN() { dstMacAddr := tap.GetDstMacAddr(elem.packet[path.EgHeaderLen:]) // lookup peer if tap.IsNotUnicast(dstMacAddr) { - dst_nodeID = config.Broadcast + dst_nodeID = mtypes.Broadcast } else if val, ok := device.l2fib.Load(dstMacAddr); !ok { //Lookup failed - dst_nodeID = config.Broadcast + dst_nodeID = mtypes.Broadcast } else { dst_nodeID = val.(*IdAndTime).ID } @@ -275,7 +275,7 @@ func (device *Device) RoutineReadFromTUN() { continue } - if dst_nodeID != config.Broadcast { + if dst_nodeID != mtypes.Broadcast { var peer *Peer next_id := device.graph.Next(device.ID, dst_nodeID) if next_id != nil { @@ -297,7 +297,7 @@ func (device *Device) RoutineReadFromTUN() { } } } else { - device.BoardcastPacket(make(map[config.Vertex]bool, 0), elem.Type, elem.packet, offset) + device.BoardcastPacket(make(map[mtypes.Vertex]bool, 0), elem.Type, elem.packet, offset) } } diff --git a/device/sticky_default.go b/device/sticky_default.go index 6f46d54..b9ba5d1 100644 --- a/device/sticky_default.go +++ b/device/sticky_default.go @@ -3,8 +3,8 @@ package device import ( - "github.com/KusakabeSi/EtherGuardVPN/conn" - "github.com/KusakabeSi/EtherGuardVPN/rwcancel" + "github.com/KusakabeSi/EtherGuard-VPN/conn" + "github.com/KusakabeSi/EtherGuard-VPN/rwcancel" ) func (device *Device) startRouteListener(bind conn.Bind) (*rwcancel.RWCancel, error) { diff --git a/device/sticky_linux.go b/device/sticky_linux.go index 88df4ce..a8dafe0 100644 --- a/device/sticky_linux.go +++ b/device/sticky_linux.go @@ -20,8 +20,8 @@ import ( "golang.org/x/sys/unix" - "github.com/KusakabeSi/EtherGuardVPN/conn" - "github.com/KusakabeSi/EtherGuardVPN/rwcancel" + "github.com/KusakabeSi/EtherGuard-VPN/conn" + "github.com/KusakabeSi/EtherGuard-VPN/rwcancel" ) func (device *Device) startRouteListener(bind conn.Bind) (*rwcancel.RWCancel, error) { diff --git a/device/tap.go b/device/tap.go index 9edf199..dc7c388 100644 --- a/device/tap.go +++ b/device/tap.go @@ -9,7 +9,7 @@ import ( "fmt" "sync/atomic" - "github.com/KusakabeSi/EtherGuardVPN/tap" + "github.com/KusakabeSi/EtherGuard-VPN/tap" ) const DefaultMTU = 1420 diff --git a/device/uapi.go b/device/uapi.go index bd37e80..335d5f9 100644 --- a/device/uapi.go +++ b/device/uapi.go @@ -18,7 +18,7 @@ import ( "sync/atomic" "time" - "github.com/KusakabeSi/EtherGuardVPN/ipc" + "github.com/KusakabeSi/EtherGuard-VPN/ipc" ) type IPCError struct { diff --git a/example_config/super_mode/n1.yaml b/example_config/super_mode/n1.yaml index b6773fc..64a31ab 100644 --- a/example_config/super_mode/n1.yaml +++ b/example_config/super_mode/n1.yaml @@ -38,6 +38,9 @@ dynamicroute: pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 50 + httppostinterval: 15 + skiplocalip: false + p2p: usep2p: false sendpeerinterval: 20 diff --git a/example_config/super_mode/n100.yaml b/example_config/super_mode/n100.yaml new file mode 100644 index 0000000..51f9dd6 --- /dev/null +++ b/example_config/super_mode/n100.yaml @@ -0,0 +1,77 @@ +interface: + itype: stdio + name: tap1 + vppifaceid: 1 + vppbridgeid: 4242 + macaddrprefix: AA:BB:CC:DD + mtu: 1416 + recvaddr: 127.0.0.1:4001 + sendaddr: 127.0.0.1:5001 + l2headermode: kbdbg +nodeid: 100 +nodename: Node_100 +postscript: example_config/echo.sh test +defaultttl: 200 +l2fibtimeout: 3600 +privkey: IJtpnkm9ytbuCukx4VBMENJKuLngo9KSsS1D60BqonQ= +listenport: 0 +loglevel: + loglevel: normal + logtransit: true + logcontrol: true + lognormal: true + loginternal: true + logntp: true +dynamicroute: + sendpinginterval: 16 + peeralivetimeout: 70 + dupchecktimeout: 40 + conntimeout: 20 + connnexttry: 5 + savenewpeers: true + supernode: + usesupernode: true + pskey: "" + connurlv4: 127.0.0.1:3000 + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= + connurlv6: "" + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= + apiurl: http://127.0.0.1:3000/api + skiplocalip: false + httppostinterval: 15 + supernodeinfotimeout: 50 + p2p: + usep2p: false + sendpeerinterval: 20 + additionalcost: 0 + graphrecalculatesetting: + staticmode: false + jittertolerance: 20 + jittertolerancemultiplier: 1.1 + nodereporttimeout: 40 + timeoutcheckinterval: 5 + recalculatecooldown: 5 + ntpconfig: + usentp: true + maxserveruse: 8 + synctimeinterval: 3600 + ntptimeout: 3 + servers: + - time.google.com + - time1.google.com + - time2.google.com + - time3.google.com + - time4.google.com + - time1.facebook.com + - time2.facebook.com + - time3.facebook.com + - time4.facebook.com + - time5.facebook.com + - time.cloudflare.com + - time.apple.com + - time.asia.apple.com + - time.euro.apple.com + - time.windows.com +nexthoptable: {} +resetconninterval: 86400 +peers: [] \ No newline at end of file diff --git a/example_config/super_mode/n2.yaml b/example_config/super_mode/n2.yaml index 2bb7e2d..30c0637 100644 --- a/example_config/super_mode/n2.yaml +++ b/example_config/super_mode/n2.yaml @@ -38,6 +38,8 @@ dynamicroute: pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 50 + httppostinterval: 15 + skiplocalip: false p2p: usep2p: false sendpeerinterval: 20 diff --git a/example_config/super_mode/s1.yaml b/example_config/super_mode/s1.yaml index 7101b72..44debd4 100644 --- a/example_config/super_mode/s1.yaml +++ b/example_config/super_mode/s1.yaml @@ -40,3 +40,8 @@ peers: pubkey: dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk= pskey: juJMQaGAaeSy8aDsXSKNsPZv/nFiPj4h/1G70tGYygs= additionalcost: 1000 +- nodeid: 100 + name: Node_100 + pubkey: 6SuqwPH9pxGigtZDNp3PABZYfSEzDaBSwuThsUUAcyM= + pskey: "" + additionalcost: 1000 diff --git a/go.mod b/go.mod index f1d15ab..98822c2 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,25 @@ -module github.com/KusakabeSi/EtherGuardVPN +module github.com/KusakabeSi/EtherGuard-VPN -go 1.16 +go 1.17 require ( git.fd.io/govpp.git v0.3.6-0.20210927044411-385ccc0d8ba9 - git.fd.io/govpp.git/extras v0.0.0-20210927044411-385ccc0d8ba9 + git.fd.io/govpp.git/extras v0.0.0-20211129071605-0a0c03d45954 github.com/KusakabeSi/go-cache v0.0.0-20210823132304-22b5b1d22b41 github.com/beevik/ntp v0.3.0 + github.com/golang-jwt/jwt v3.2.2+incompatible github.com/google/gopacket v1.1.19 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/sirupsen/logrus v1.6.0 - golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 + golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 gopkg.in/yaml.v2 v2.2.2 ) + +require ( + github.com/fsnotify/fsnotify v1.4.7 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect + github.com/lunixbochs/struc v0.0.0-20200521075829-a4cb8d33dbbe // indirect + github.com/wk8/go-ordered-map v0.2.0 // indirect + golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect +) diff --git a/ipc/uapi_linux.go b/ipc/uapi_linux.go index 39f2f7f..d6bd485 100644 --- a/ipc/uapi_linux.go +++ b/ipc/uapi_linux.go @@ -10,7 +10,7 @@ import ( "os" "golang.org/x/sys/unix" - "github.com/KusakabeSi/EtherGuardVPN/rwcancel" + "github.com/KusakabeSi/EtherGuard-VPN/rwcancel" ) type UAPIListener struct { diff --git a/ipc/uapi_windows.go b/ipc/uapi_windows.go index 636cd4a..311c6af 100644 --- a/ipc/uapi_windows.go +++ b/ipc/uapi_windows.go @@ -10,7 +10,7 @@ import ( "golang.org/x/sys/windows" - "github.com/KusakabeSi/EtherGuardVPN/ipc/winpipe" + "github.com/KusakabeSi/EtherGuard-VPN/ipc/winpipe" ) // TODO: replace these with actual standard windows error numbers from the win package diff --git a/ipc/winpipe/winpipe_test.go b/ipc/winpipe/winpipe_test.go index a3a207d..27fd552 100644 --- a/ipc/winpipe/winpipe_test.go +++ b/ipc/winpipe/winpipe_test.go @@ -22,7 +22,7 @@ import ( "time" "golang.org/x/sys/windows" - "github.com/KusakabeSi/EtherGuardVPN/ipc/winpipe" + "github.com/KusakabeSi/EtherGuard-VPN/ipc/winpipe" ) func randomPipePath() string { diff --git a/main.go b/main.go index 3fffbfe..29673a6 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows /* SPDX-License-Identifier: MIT @@ -13,10 +14,11 @@ import ( "io/ioutil" "os" "runtime" + "syscall" - "github.com/KusakabeSi/EtherGuardVPN/ipc" - "github.com/KusakabeSi/EtherGuardVPN/path" - "github.com/KusakabeSi/EtherGuardVPN/tap" + "github.com/KusakabeSi/EtherGuard-VPN/ipc" + "github.com/KusakabeSi/EtherGuard-VPN/path" + "github.com/KusakabeSi/EtherGuard-VPN/tap" yaml "gopkg.in/yaml.v2" ) @@ -56,7 +58,7 @@ var ( func main() { flag.Parse() if *version == true { - fmt.Printf("etherguard-go %s\n%s-%s\n%s\n\nA full mesh layer 2 VPN powered by Floyd Warshall algorithm.\nInformation available at https://github.com/KusakabeSi/EtherGuardVPN.\nCopyright (C) Kusakabe Si .\n", Version, runtime.GOOS, runtime.GOARCH, tap.VPP_SUPPORT) + fmt.Printf("etherguard-go %s\n%s-%s\n%s\n\nA full mesh layer 2 VPN powered by Floyd Warshall algorithm.\nInformation available at https://github.com/KusakabeSi/EtherGuard-VPN.\nCopyright (C) Kusakabe Si .\n", Version, runtime.GOOS, runtime.GOARCH, tap.VPP_SUPPORT) return } if *help == true { @@ -81,8 +83,14 @@ func main() { flag.Usage() } if err != nil { - fmt.Fprintf(os.Stderr, "Error :%v\n", err) - os.Exit(1) + switch err.(type) { + case syscall.Errno: + errno, _ := err.(syscall.Errno) + os.Exit(int(errno)) + default: + fmt.Fprintf(os.Stderr, "Error :%v\n", err) + os.Exit(1) + } } return } diff --git a/main_edge.go b/main_edge.go index 04d5b7f..cf0bf13 100644 --- a/main_edge.go +++ b/main_edge.go @@ -16,19 +16,19 @@ import ( "github.com/google/shlex" - "github.com/KusakabeSi/EtherGuardVPN/config" - "github.com/KusakabeSi/EtherGuardVPN/conn" - "github.com/KusakabeSi/EtherGuardVPN/device" - "github.com/KusakabeSi/EtherGuardVPN/path" - "github.com/KusakabeSi/EtherGuardVPN/tap" + "github.com/KusakabeSi/EtherGuard-VPN/conn" + "github.com/KusakabeSi/EtherGuard-VPN/device" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/path" + "github.com/KusakabeSi/EtherGuard-VPN/tap" yaml "gopkg.in/yaml.v2" ) func printExampleEdgeConf() { - v1 := config.Vertex(1) - v2 := config.Vertex(2) - tconfig := config.EdgeConfig{ - Interface: config.InterfaceConf{ + v1 := mtypes.Vertex(1) + v2 := mtypes.Vertex(2) + tconfig := mtypes.EdgeConfig{ + Interface: mtypes.InterfaceConf{ Itype: "stdio", Name: "tap1", VPPIfaceID: 5, @@ -46,7 +46,7 @@ func printExampleEdgeConf() { L2FIBTimeout: 3600, PrivKey: "6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M=", ListenPort: 3001, - LogLevel: config.LoggerInfo{ + LogLevel: mtypes.LoggerInfo{ LogLevel: "error", LogTransit: true, LogControl: true, @@ -54,14 +54,14 @@ func printExampleEdgeConf() { LogInternal: true, LogNTP: false, }, - DynamicRoute: config.DynamicRouteInfo{ + DynamicRoute: mtypes.DynamicRouteInfo{ SendPingInterval: 16, PeerAliveTimeout: 70, DupCheckTimeout: 40, ConnTimeOut: 20, ConnNextTry: 5, SaveNewPeers: true, - SuperNode: config.SuperInfo{ + SuperNode: mtypes.SuperInfo{ UseSuperNode: true, PSKey: "iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI=", ConnURLV4: "127.0.0.1:3000", @@ -70,11 +70,13 @@ func printExampleEdgeConf() { PubKeyV6: "HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=", APIUrl: "http://127.0.0.1:3000/api", SuperNodeInfoTimeout: 50, + SkipLocalIP: false, + HttpPostInterval: 15, }, - P2P: config.P2Pinfo{ + P2P: mtypes.P2Pinfo{ UseP2P: true, SendPeerInterval: 20, - GraphRecalculateSetting: config.GraphRecalculateSetting{ + GraphRecalculateSetting: mtypes.GraphRecalculateSetting{ StaticMode: false, JitterTolerance: 20, JitterToleranceMultiplier: 1.1, @@ -83,7 +85,7 @@ func printExampleEdgeConf() { RecalculateCoolDown: 5, }, }, - NTPconfig: config.NTPinfo{ + NTPconfig: mtypes.NTPinfo{ UseNTP: true, MaxServerUse: 5, SyncTimeInterval: 3600, @@ -105,16 +107,16 @@ func printExampleEdgeConf() { "time.windows.com"}, }, }, - NextHopTable: config.NextHopTable{ - config.Vertex(1): { - config.Vertex(2): &v2, + NextHopTable: mtypes.NextHopTable{ + mtypes.Vertex(1): { + mtypes.Vertex(2): &v2, }, - config.Vertex(2): { - config.Vertex(1): &v1, + mtypes.Vertex(2): { + mtypes.Vertex(1): &v1, }, }, ResetConnInterval: 86400, - Peers: []config.PeerInfo{ + Peers: []mtypes.PeerInfo{ { NodeID: 2, PubKey: "dHeWQtlTPQGy87WdbUARS4CtwVaR2y7IQ1qcX4GKSXk=", @@ -126,18 +128,18 @@ func printExampleEdgeConf() { } g := path.NewGraph(3, false, tconfig.DynamicRoute.P2P.GraphRecalculateSetting, tconfig.DynamicRoute.NTPconfig, tconfig.LogLevel) - g.UpdateLatency(1, 2, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(2, 1, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(2, 3, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(3, 2, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(2, 4, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(4, 2, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(3, 4, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(4, 3, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(5, 3, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(3, 5, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(6, 4, path.S2TD(0.5), 0, false, false) - g.UpdateLatency(4, 6, path.S2TD(0.5), 0, false, false) + g.UpdateLatency(1, 2, 0.5, 99999, 0, false, false) + g.UpdateLatency(2, 1, 0.5, 99999, 0, false, false) + g.UpdateLatency(2, 3, 0.5, 99999, 0, false, false) + g.UpdateLatency(3, 2, 0.5, 99999, 0, false, false) + g.UpdateLatency(2, 4, 0.5, 99999, 0, false, false) + g.UpdateLatency(4, 2, 0.5, 99999, 0, false, false) + g.UpdateLatency(3, 4, 0.5, 99999, 0, false, false) + g.UpdateLatency(4, 3, 0.5, 99999, 0, false, false) + g.UpdateLatency(5, 3, 0.5, 99999, 0, false, false) + g.UpdateLatency(3, 5, 0.5, 99999, 0, false, false) + g.UpdateLatency(6, 4, 0.5, 99999, 0, false, false) + g.UpdateLatency(4, 6, 0.5, 99999, 0, false, false) _, next, _ := g.FloydWarshall(false) tconfig.NextHopTable = next toprint, _ := yaml.Marshal(tconfig) @@ -150,7 +152,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( printExampleEdgeConf() return nil } - var econfig config.EdgeConfig + var econfig mtypes.EdgeConfig //printExampleConf() //return @@ -271,7 +273,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( fmt.Println("Error decode base64 ", err) return err } - peer, err := the_device.NewPeer(pk, config.SuperNodeMessage, true) + peer, err := the_device.NewPeer(pk, mtypes.SuperNodeMessage, true) if err != nil { return err } @@ -292,7 +294,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( fmt.Println("Error decode base64 ", err) return err } - peer, err := the_device.NewPeer(pk, config.SuperNodeMessage, true) + peer, err := the_device.NewPeer(pk, mtypes.SuperNodeMessage, true) if err != nil { return err } @@ -329,6 +331,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( fmt.Printf("PostScript: exec.Command(%v)\n", cmdarg) } cmd := exec.Command(cmdarg[0], cmdarg[1:]...) + out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("exec.Command(%v) failed with %v\n", cmdarg, err) @@ -345,9 +348,11 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( select { case <-term: case <-errs: - case <-the_device.Wait(): + case errcode := <-the_device.Wait(): + if errcode != 0 { + return syscall.Errno(errcode) + } } - logger.Verbosef("Shutting down") return } diff --git a/main_httpserver.go b/main_httpserver.go index 0eb8113..b40c3ce 100644 --- a/main_httpserver.go +++ b/main_httpserver.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/md5" "crypto/sha256" + "encoding/base64" "encoding/hex" "encoding/json" "fmt" @@ -14,15 +15,18 @@ import ( "time" "net/http" + "net/url" - "github.com/KusakabeSi/EtherGuardVPN/config" - "github.com/KusakabeSi/EtherGuardVPN/conn" - "github.com/KusakabeSi/EtherGuardVPN/device" - "github.com/KusakabeSi/EtherGuardVPN/path" + "github.com/golang-jwt/jwt" + "golang.org/x/crypto/sha3" + + "github.com/KusakabeSi/EtherGuard-VPN/device" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/path" yaml "gopkg.in/yaml.v2" ) -var ( +type http_shared_objects struct { http_graph *path.IG http_device4 *device.Device http_device6 *device.Device @@ -30,36 +34,41 @@ var ( http_NhTable_Hash [32]byte http_PeerInfo_hash [32]byte http_NhTableStr []byte - http_PeerInfo config.API_Peers - http_super_chains *path.SUPER_Events + http_PeerInfo mtypes.API_Peers + http_super_chains *mtypes.SUPER_Events - http_passwords config.Passwords + http_passwords mtypes.Passwords http_StateExpire time.Time http_StateString_tmp []byte - http_maps_lock sync.RWMutex - http_PeerID2Info map[config.Vertex]config.SuperPeerInfo + http_PeerID2Info map[mtypes.Vertex]mtypes.SuperPeerInfo http_PeerState map[string]*PeerState //the state hash reported by peer http_PeerIPs map[string]*HttpPeerLocalIP - http_sconfig *config.SuperConfig + http_sconfig *mtypes.SuperConfig http_sconfig_path string - http_econfig_tmp *config.EdgeConfig + http_econfig_tmp *mtypes.EdgeConfig + + sync.RWMutex +} + +var ( + httpobj http_shared_objects ) type HttpPeerLocalIP struct { - IPv4 net.UDPAddr - IPv6 net.UDPAddr + LocalIPv4 map[string]float64 + LocalIPv6 map[string]float64 } type HttpState struct { - PeerInfo map[config.Vertex]HttpPeerInfo + PeerInfo map[mtypes.Vertex]HttpPeerInfo Infinity float64 - Edges map[config.Vertex]map[config.Vertex]float64 - Edges_Nh map[config.Vertex]map[config.Vertex]float64 - NhTable config.NextHopTable - Dist config.DistTable + Edges map[mtypes.Vertex]map[mtypes.Vertex]float64 + Edges_Nh map[mtypes.Vertex]map[mtypes.Vertex]float64 + NhTable mtypes.NextHopTable + Dist mtypes.DistTable } type HttpPeerInfo struct { @@ -70,6 +79,8 @@ type HttpPeerInfo struct { type PeerState struct { NhTableState [32]byte PeerInfoState [32]byte + JETSecret mtypes.JWTSecret + httpPostCount uint64 LastSeen time.Time } @@ -82,38 +93,86 @@ type client struct { notify6 string } -func get_api_peers(old_State_hash [32]byte) (api_peerinfo config.API_Peers, StateHash [32]byte, changed bool) { - api_peerinfo = make(config.API_Peers) - for _, peerinfo := range http_sconfig.Peers { - api_peerinfo[peerinfo.PubKey] = config.API_Peerinfo{ +func extractParamsStr(params url.Values, key string, w http.ResponseWriter) (string, error) { + valA, has := params[key] + if !has { + errstr := fmt.Sprintf("Paramater %v: Missing paramater.", key) + if w != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(errstr)) + } + return "", fmt.Errorf(errstr) + } + return valA[0], nil +} + +func extractParamsFloat(params url.Values, key string, bitSize int, w http.ResponseWriter) (float64, error) { + val, err := extractParamsStr(params, key, w) + if err != nil { + return 0, err + } + ret, err := strconv.ParseFloat(val, 64) + if err != nil { + errstr := fmt.Sprintf("Paramater %v: Can't convert to type float%v", key, bitSize) + if w != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(errstr)) + } + return 0, fmt.Errorf(errstr) + } + return ret, nil +} + +func extractParamsUint(params url.Values, key string, bitSize int, w http.ResponseWriter) (uint64, error) { + val, err := extractParamsStr(params, key, w) + if err != nil { + return 0, err + } + ret, err := strconv.ParseUint(val, 10, bitSize) + if err != nil { + errstr := fmt.Sprintf("Paramater %v: Can't convert to type uint%v", key, bitSize) + if w != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(errstr)) + } + return 0, fmt.Errorf(errstr) + } + return ret, nil +} + +func extractParamsVertex(params url.Values, key string, w http.ResponseWriter) (mtypes.Vertex, error) { + val, err := extractParamsUint(params, key, 16, w) + if err != nil { + return mtypes.BrokenMessage, err + } + return mtypes.Vertex(val), nil +} + +func get_api_peers(old_State_hash [32]byte) (api_peerinfo mtypes.API_Peers, StateHash [32]byte, changed bool) { + // No lock + api_peerinfo = make(mtypes.API_Peers) + for _, peerinfo := range httpobj.http_sconfig.Peers { + api_peerinfo[peerinfo.PubKey] = mtypes.API_Peerinfo{ NodeID: peerinfo.NodeID, PSKey: peerinfo.PSKey, - Connurl: make(map[string]float64), + Connurl: &mtypes.API_connurl{}, } - http_maps_lock.RLock() - if http_PeerState[peerinfo.PubKey].LastSeen.Add(path.S2TD(http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now()) { - connV4 := http_device4.GetConnurl(peerinfo.NodeID) - connV6 := http_device6.GetConnurl(peerinfo.NodeID) - api_peerinfo[peerinfo.PubKey].Connurl[connV4] = 4 - api_peerinfo[peerinfo.PubKey].Connurl[connV6] = 6 - L4Addr := http_PeerIPs[peerinfo.PubKey].IPv4 - L4IP := L4Addr.IP - L4str := L4Addr.String() - if L4str != connV4 && conn.ValidIP(L4IP) { - api_peerinfo[peerinfo.PubKey].Connurl[L4str] = 14 + if httpobj.http_PeerState[peerinfo.PubKey].LastSeen.Add(path.S2TD(httpobj.http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now()) { + connV4 := httpobj.http_device4.GetConnurl(peerinfo.NodeID) + connV6 := httpobj.http_device6.GetConnurl(peerinfo.NodeID) + if connV4 != "" { + api_peerinfo[peerinfo.PubKey].Connurl.ExternalV4 = map[string]float64{connV4: 4} } - L6Addr := http_PeerIPs[peerinfo.PubKey].IPv6 - L6IP := L6Addr.IP - L6str := L6Addr.String() - if L6str != connV6 && conn.ValidIP(L6IP) { - api_peerinfo[peerinfo.PubKey].Connurl[L6str] = 16 + if connV6 != "" { + api_peerinfo[peerinfo.PubKey].Connurl.ExternalV6 = map[string]float64{connV6: 6} } - delete(api_peerinfo[peerinfo.PubKey].Connurl, "") + api_peerinfo[peerinfo.PubKey].Connurl.LocalV4 = httpobj.http_PeerIPs[peerinfo.PubKey].LocalIPv4 + api_peerinfo[peerinfo.PubKey].Connurl.LocalV6 = httpobj.http_PeerIPs[peerinfo.PubKey].LocalIPv6 } - http_maps_lock.RUnlock() + } api_peerinfo_str_byte, _ := json.Marshal(&api_peerinfo) - hash_raw := md5.Sum(append(api_peerinfo_str_byte, http_HashSalt...)) + hash_raw := md5.Sum(append(api_peerinfo_str_byte, httpobj.http_HashSalt...)) hash_str := hex.EncodeToString(hash_raw[:]) copy(StateHash[:], []byte(hash_str)) if bytes.Equal(old_State_hash[:], StateHash[:]) == false { @@ -124,48 +183,33 @@ func get_api_peers(old_State_hash [32]byte) (api_peerinfo config.API_Peers, Stat func get_peerinfo(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() - PubKeyA, has := params["PubKey"] - if !has { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte("Require PubKey.")) - return - } - StateA, has := params["State"] - if !has { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte("Require State.")) - return - } - NIDA, has := params["NodeID"] - if !has { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte("Require NodeID.")) - return - } - NID2, err := strconv.ParseUint(NIDA[0], 10, 16) + PubKey, err := extractParamsStr(params, "PubKey", w) if err != nil { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte(fmt.Sprintf("%v", err))) return } - PubKey := PubKeyA[0] - State := StateA[0] - NodeID := config.Vertex(NID2) - http_maps_lock.RLock() - defer http_maps_lock.RUnlock() - if http_PeerID2Info[NodeID].PubKey != PubKey { + State, err := extractParamsStr(params, "State", w) + if err != nil { + return + } + NodeID, err := extractParamsVertex(params, "NodeID", w) + if err != nil { + return + } + httpobj.RLock() + defer httpobj.RUnlock() + if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey { w.WriteHeader(http.StatusNotFound) w.Write([]byte("NodeID and PunKey are not match")) return } - if bytes.Equal(http_PeerInfo_hash[:], []byte(State)) { - if state := http_PeerState[PubKey]; state != nil { - copy(http_PeerState[PubKey].PeerInfoState[:], State) - http_PeerInfo_2peer := make(config.API_Peers) + if bytes.Equal(httpobj.http_PeerInfo_hash[:], []byte(State)) { + if state := httpobj.http_PeerState[PubKey]; state != nil { + copy(httpobj.http_PeerState[PubKey].PeerInfoState[:], State) + http_PeerInfo_2peer := make(mtypes.API_Peers) - for PeerPubKey, peerinfo := range http_PeerInfo { - if http_sconfig.UsePSKForInterEdge { + for PeerPubKey, peerinfo := range httpobj.http_PeerInfo { + if httpobj.http_sconfig.UsePSKForInterEdge { h := sha256.New() if NodeID > peerinfo.NodeID { h.Write([]byte(PubKey)) @@ -176,7 +220,7 @@ func get_peerinfo(w http.ResponseWriter, r *http.Request) { } else { continue } - h.Write(http_HashSalt) + h.Write(httpobj.http_HashSalt) bs := h.Sum(nil) var psk device.NoisePresharedKey copy(psk[:], bs[:]) @@ -200,47 +244,32 @@ func get_peerinfo(w http.ResponseWriter, r *http.Request) { func get_nhtable(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() - PubKeyA, has := params["PubKey"] - if !has { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte("Require PubKey.")) - return - } - StateA, has := params["State"] - if !has { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte("Require State.")) - return - } - NIDA, has := params["NodeID"] - if !has { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte("Require NodeID.")) - return - } - NID2, err := strconv.ParseUint(NIDA[0], 10, 16) + PubKey, err := extractParamsStr(params, "PubKey", w) if err != nil { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte(fmt.Sprintf("%v", err))) return } - PubKey := PubKeyA[0] - State := StateA[0] - NodeID := config.Vertex(NID2) - http_maps_lock.RLock() - defer http_maps_lock.RUnlock() - if http_PeerID2Info[NodeID].PubKey != PubKey { + State, err := extractParamsStr(params, "State", w) + if err != nil { + return + } + NodeID, err := extractParamsVertex(params, "NodeID", w) + if err != nil { + return + } + httpobj.RLock() + defer httpobj.RUnlock() + if httpobj.http_PeerID2Info[NodeID].PubKey != PubKey { w.WriteHeader(http.StatusNotFound) w.Write([]byte("NodeID and PunKey are not match")) return } - if bytes.Equal(http_NhTable_Hash[:], []byte(State)) { - if state := http_PeerState[PubKey]; state != nil { - copy(http_PeerState[PubKey].NhTableState[:], State) + if bytes.Equal(httpobj.http_NhTable_Hash[:], []byte(State)) { + if state := httpobj.http_PeerState[PubKey]; state != nil { + copy(httpobj.http_PeerState[PubKey].NhTableState[:], State) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - w.Write([]byte(http_NhTableStr)) + w.Write([]byte(httpobj.http_NhTableStr)) return } } @@ -248,103 +277,205 @@ func get_nhtable(w http.ResponseWriter, r *http.Request) { w.Write([]byte("State not correct")) } -func get_info(w http.ResponseWriter, r *http.Request) { +func get_peerstate(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() - PasswordA, has := params["Password"] - if !has { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte("Require Password")) + password, err := extractParamsStr(params, "Password", w) + if err != nil { return } - password := PasswordA[0] - if password != http_passwords.ShowState { + if password != httpobj.http_passwords.ShowState { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte("Wrong password")) return } - if time.Now().After(http_StateExpire) { + httpobj.RLock() + defer httpobj.RUnlock() + if time.Now().After(httpobj.http_StateExpire) { hs := HttpState{ - PeerInfo: make(map[config.Vertex]HttpPeerInfo), - NhTable: http_graph.GetNHTable(false), + PeerInfo: make(map[mtypes.Vertex]HttpPeerInfo), + NhTable: httpobj.http_graph.GetNHTable(false), Infinity: path.Infinity, - Edges: http_graph.GetEdges(false, false), - Edges_Nh: http_graph.GetEdges(true, true), - Dist: http_graph.GetDtst(), + Edges: httpobj.http_graph.GetEdges(false, false), + Edges_Nh: httpobj.http_graph.GetEdges(true, true), + Dist: httpobj.http_graph.GetDtst(), } - http_maps_lock.RLock() - for _, peerinfo := range http_sconfig.Peers { - LastSeenStr := http_PeerState[peerinfo.PubKey].LastSeen.String() + + for _, peerinfo := range httpobj.http_sconfig.Peers { + LastSeenStr := httpobj.http_PeerState[peerinfo.PubKey].LastSeen.String() hs.PeerInfo[peerinfo.NodeID] = HttpPeerInfo{ Name: peerinfo.Name, LastSeen: LastSeenStr, } } - http_maps_lock.RUnlock() - http_StateExpire = time.Now().Add(5 * time.Second) - http_StateString_tmp, _ = json.Marshal(hs) + httpobj.http_StateExpire = time.Now().Add(5 * time.Second) + httpobj.http_StateString_tmp, _ = json.Marshal(hs) } w.WriteHeader(http.StatusOK) - w.Write(http_StateString_tmp) + w.Write(httpobj.http_StateString_tmp) + return +} + +func post_nodeinfo(w http.ResponseWriter, r *http.Request) { + params := r.URL.Query() + + NodeID, err := extractParamsVertex(params, "NodeID", w) + if err != nil { + return + } + JWTSig, err := extractParamsStr(params, "JWTSig", w) + if err != nil { + return + } + + if NodeID >= mtypes.Special_NodeID { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("Paramater NodeID: Can't use special nodeID.")) + return + } + + httpobj.RLock() + defer httpobj.RUnlock() + var PubKey string + if peerconf, has := httpobj.http_PeerID2Info[NodeID]; has { + PubKey = peerconf.PubKey + } else { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("Paramater NodeID: NodeID not exists.")) + return + } + JWTSecret := httpobj.http_PeerState[PubKey].JETSecret + httpPostCount := httpobj.http_PeerState[PubKey].httpPostCount + + client_body, err := ioutil.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf("Request body: Error reading request body: %v", err))) + return + } + + token_claims := mtypes.API_report_peerinfo_jwt_claims{} + + token, err := jwt.ParseWithClaims(string(JWTSig), &token_claims, func(token *jwt.Token) (interface{}, error) { + // Don't forget to validate the alg is what you expect: + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) + } + return JWTSecret[:], nil + }) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf("Paramater JWTSig: Signature verification failed: %v", err))) + return + } + if !token.Valid { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf("Paramater JWTSig: Signature verification failed: Invalid token"))) + return + } + + client_PostCount := token_claims.PostCount + client_body_hash := token_claims.BodyHash + + if client_PostCount < httpPostCount { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf("Request body: postcount too small: %v", httpPostCount))) + return + } + + calculated_body_hash := sha3.Sum512(client_body) + if base64.StdEncoding.EncodeToString(calculated_body_hash[:]) == client_body_hash { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf("Request body: hash not match: %v", client_body_hash))) + return + } + + client_body, err = mtypes.GUzip(client_body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf("Request body: gzip unzip failed"))) + return + } + client_report, err := mtypes.ParseAPI_report_peerinfo(client_body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf("Request body: Error parsing request body: %v", err))) + return + } + + httpobj.http_PeerIPs[PubKey].LocalIPv4 = client_report.LocalV4s + httpobj.http_PeerIPs[PubKey].LocalIPv6 = client_report.LocalV6s + httpobj.http_PeerState[PubKey].httpPostCount = client_PostCount + 1 + + applied_pones := make([]mtypes.PongMsg, 0, len(client_report.Pongs)) + for _, pong_msg := range client_report.Pongs { + if pong_msg.Src_nodeID != NodeID { + continue + } + + if info, has := httpobj.http_PeerID2Info[pong_msg.Dst_nodeID]; !has { + AdditionalCost_use := info.AdditionalCost + + if AdditionalCost_use >= 0 { + pong_msg.AdditionalCost = AdditionalCost_use + } + applied_pones = append(applied_pones, pong_msg) + } + } + changed := httpobj.http_graph.UpdateLatencyMulti(client_report.Pongs, true, true) + if changed { + NhTable := httpobj.http_graph.GetNHTable(true) + NhTablestr, _ := json.Marshal(NhTable) + md5_hash_raw := md5.Sum(append(httpobj.http_NhTableStr, httpobj.http_HashSalt...)) + new_hash_str := hex.EncodeToString(md5_hash_raw[:]) + new_hash_str_byte := []byte(new_hash_str) + copy(httpobj.http_NhTable_Hash[:], new_hash_str_byte) + copy(httpobj.http_graph.NhTableHash[:], new_hash_str_byte) + httpobj.http_NhTableStr = NhTablestr + PushNhTable(false) + } + w.WriteHeader(http.StatusOK) + w.Write([]byte(fmt.Sprintf("OK"))) return } func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test params := r.URL.Query() - PasswordA, has := params["Password"] - if !has { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte("Require Password")) + password, err := extractParamsStr(params, "Password", w) + if err != nil { return } - password := PasswordA[0] - if password != http_passwords.AddPeer { + if password != httpobj.http_passwords.AddPeer { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte("Wrong password")) return } r.ParseForm() - NID, err := strconv.ParseUint(r.Form.Get("nodeid"), 10, 16) + NodeID, err := extractParamsVertex(r.Form, "nodeid", w) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(fmt.Sprintf("Paramater nodeid: Error parse uint16: \"%v\", %v", NID, err))) return } - NodeID := config.Vertex(NID) - if NodeID >= config.Special_NodeID { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("Paramater nodeid: Can't use special nodeID.")) + Name, err := extractParamsStr(r.Form, "name", w) + if err != nil { return } - Name := r.Form.Get("name") - if len(Name) <= 0 || len(Name) >= 15 { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("Paramater name: Name too long or too short.")) - return - } - AdditionalCostStr := r.Form.Get("additionalcost") - AdditionalCost, err := strconv.ParseFloat(AdditionalCostStr, 64) + AdditionalCost, err := extractParamsFloat(r.Form, "additionalcost", 64, w) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(fmt.Sprintf("Paramater additionalcost: Error parse float64: \"%v\", %v", AdditionalCostStr, err))) return } - PubKey := r.Form.Get("pubkey") - _, err = device.Str2PubKey(PubKey) + + PubKey, err := extractParamsStr(r.Form, "pubkey", w) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(fmt.Sprintf("Paramater pubkey: Error parse pubkey: \"%v\", %v", PubKey, err))) return } - PSKey := r.Form.Get("pskey") - _, err = device.Str2PSKey(PSKey) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(fmt.Sprintf("Paramater pskey: Error parse pskey: \"%v\", %v", PSKey, err))) - return - } - for _, peerinfo := range http_sconfig.Peers { + + PSKey, err := extractParamsStr(r.Form, "pskey", nil) + + httpobj.Lock() + defer httpobj.Unlock() + + for _, peerinfo := range httpobj.http_sconfig.Peers { if peerinfo.NodeID == NodeID { w.WriteHeader(http.StatusConflict) w.Write([]byte("Paramater nodeid: NodeID exists")) @@ -361,21 +492,21 @@ func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test return } } - if http_sconfig.GraphRecalculateSetting.StaticMode == true { + if httpobj.http_sconfig.GraphRecalculateSetting.StaticMode == true { NhTableStr := r.Form.Get("nexthoptable") if NhTableStr == "" { w.WriteHeader(http.StatusExpectationFailed) w.Write([]byte("Paramater nexthoptable: Your NextHopTable is in static mode.\nPlease provide your new NextHopTable in \"nexthoptable\" parmater in json format")) return } - var NewNhTable config.NextHopTable + var NewNhTable mtypes.NextHopTable err := json.Unmarshal([]byte(NhTableStr), &NewNhTable) if err != nil { w.WriteHeader(http.StatusExpectationFailed) w.Write([]byte(fmt.Sprintf("Paramater nexthoptable: \"%v\", %v", NhTableStr, err))) return } - err = checkNhTable(NewNhTable, append(http_sconfig.Peers, config.SuperPeerInfo{ + err = checkNhTable(NewNhTable, append(httpobj.http_sconfig.Peers, mtypes.SuperPeerInfo{ NodeID: NodeID, Name: Name, PubKey: PubKey, @@ -387,9 +518,9 @@ func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test w.Write([]byte(fmt.Sprintf("Paramater nexthoptable: \"%v\", %v", NhTableStr, err))) return } - http_graph.SetNHTable(NewNhTable, [32]byte{}) + httpobj.http_graph.SetNHTable(NewNhTable, [32]byte{}) } - err = super_peeradd(config.SuperPeerInfo{ + err = super_peeradd(mtypes.SuperPeerInfo{ NodeID: NodeID, Name: Name, PubKey: PubKey, @@ -401,20 +532,20 @@ func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test w.Write([]byte(fmt.Sprintf("Error creating peer: %v", err))) return } - http_sconfig.Peers = append(http_sconfig.Peers, config.SuperPeerInfo{ + httpobj.http_sconfig.Peers = append(httpobj.http_sconfig.Peers, mtypes.SuperPeerInfo{ NodeID: NodeID, Name: Name, PubKey: PubKey, PSKey: PSKey, AdditionalCost: AdditionalCost, }) - configbytes, _ := yaml.Marshal(http_sconfig) - ioutil.WriteFile(http_sconfig_path, configbytes, 0644) - http_econfig_tmp.NodeID = NodeID - http_econfig_tmp.NodeName = Name - http_econfig_tmp.PrivKey = "Your_Private_Key" - http_econfig_tmp.DynamicRoute.SuperNode.PSKey = PSKey - ret_str_byte, _ := yaml.Marshal(&http_econfig_tmp) + mtypesBytes, _ := yaml.Marshal(httpobj.http_sconfig) + ioutil.WriteFile(httpobj.http_sconfig_path, mtypesBytes, 0644) + httpobj.http_econfig_tmp.NodeID = NodeID + httpobj.http_econfig_tmp.NodeName = Name + httpobj.http_econfig_tmp.PrivKey = "Your_Private_Key" + httpobj.http_econfig_tmp.DynamicRoute.SuperNode.PSKey = PSKey + ret_str_byte, _ := yaml.Marshal(&httpobj.http_econfig_tmp) w.WriteHeader(http.StatusOK) w.Write(ret_str_byte) return @@ -422,55 +553,59 @@ func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test func peerdel(w http.ResponseWriter, r *http.Request) { //Waiting for test params := r.URL.Query() - toDelete := config.Broadcast + toDelete := mtypes.Broadcast - PasswordA, has := params["Password"] - PubKey := "" - if has { - password := PasswordA[0] - if password == http_passwords.DelPeer { - NodeIDA, has := params["nodeid"] - if !has { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("Need NodeID")) - return - } - NID, err := strconv.ParseUint(NodeIDA[0], 10, 16) + var err error + var NodeID mtypes.Vertex + var PrivKey string + var PubKey string + password, pwderr := extractParamsStr(params, "Password", nil) + httpobj.Lock() + defer httpobj.Unlock() + if pwderr == nil { // user provide the password + if password == httpobj.http_passwords.DelPeer { + NodeID, err = extractParamsVertex(params, "nodeid", w) if err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(fmt.Sprint(err))) return } - NodeID := config.Vertex(NID) toDelete = NodeID + if _, has := httpobj.http_PeerID2Info[toDelete]; !has { + w.WriteHeader(http.StatusNotFound) + w.Write([]byte(fmt.Sprintf("Paramater nodeid: \"%v\" not found", PubKey))) + return + } + } else { + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte("Paramater Password: Wrong password")) + return + } + } else { // user don't provide the password + PrivKey, err = extractParamsStr(params, "privkey", w) + if err != nil { + return } - } - - PriKeyA, has := params["privkey"] - if has && PriKeyA[0] != "" { - PrivKey := PriKeyA[0] privk, err := device.Str2PriKey(PrivKey) if err != nil { w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(fmt.Sprint(err))) + w.Write([]byte(fmt.Sprintf("Paramater privkey: %v", err))) return } pubk := privk.PublicKey() PubKey = pubk.ToString() - for _, peerinfo := range http_sconfig.Peers { + for _, peerinfo := range httpobj.http_sconfig.Peers { if peerinfo.PubKey == PubKey { toDelete = peerinfo.NodeID } } - } - if toDelete == config.Broadcast { - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte("Wrong password or private key.")) - return + if toDelete == mtypes.Broadcast { + w.WriteHeader(http.StatusNotFound) + w.Write([]byte(fmt.Sprintf("Paramater privkey: \"%v\" not found", PubKey))) + return + } } - var peers_new []config.SuperPeerInfo - for _, peerinfo := range http_sconfig.Peers { + var peers_new []mtypes.SuperPeerInfo + for _, peerinfo := range httpobj.http_sconfig.Peers { if peerinfo.NodeID == toDelete { super_peerdel(peerinfo.NodeID) } else { @@ -478,9 +613,9 @@ func peerdel(w http.ResponseWriter, r *http.Request) { //Waiting for test } } - http_sconfig.Peers = peers_new - configbytes, _ := yaml.Marshal(http_sconfig) - ioutil.WriteFile(http_sconfig_path, configbytes, 0644) + httpobj.http_sconfig.Peers = peers_new + mtypesBytes, _ := yaml.Marshal(httpobj.http_sconfig) + ioutil.WriteFile(httpobj.http_sconfig_path, mtypesBytes, 0644) w.WriteHeader(http.StatusOK) w.Write([]byte("Node ID: " + toDelete.ToString() + " deleted.")) return @@ -493,7 +628,8 @@ func HttpServer(http_port int, apiprefix string) { } mux.HandleFunc(apiprefix+"/peerinfo", get_peerinfo) mux.HandleFunc(apiprefix+"/nhtable", get_nhtable) - mux.HandleFunc(apiprefix+"/peerstate", get_info) + mux.HandleFunc(apiprefix+"/peerstate", get_peerstate) + mux.HandleFunc(apiprefix+"/post/nodeinfo", post_nodeinfo) mux.HandleFunc(apiprefix+"/peer/add", peeradd) //Waiting for test mux.HandleFunc(apiprefix+"/peer/del", peerdel) //Waiting for test http.ListenAndServe(":"+strconv.Itoa(http_port), mux) diff --git a/main_super.go b/main_super.go index 4b5383a..e028685 100644 --- a/main_super.go +++ b/main_super.go @@ -22,17 +22,17 @@ import ( "github.com/google/shlex" - "github.com/KusakabeSi/EtherGuardVPN/config" - "github.com/KusakabeSi/EtherGuardVPN/conn" - "github.com/KusakabeSi/EtherGuardVPN/device" - "github.com/KusakabeSi/EtherGuardVPN/ipc" - "github.com/KusakabeSi/EtherGuardVPN/path" - "github.com/KusakabeSi/EtherGuardVPN/tap" + "github.com/KusakabeSi/EtherGuard-VPN/conn" + "github.com/KusakabeSi/EtherGuard-VPN/device" + "github.com/KusakabeSi/EtherGuard-VPN/ipc" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/path" + "github.com/KusakabeSi/EtherGuard-VPN/tap" yaml "gopkg.in/yaml.v2" ) -func checkNhTable(NhTable config.NextHopTable, peers []config.SuperPeerInfo) error { - allpeer := make(map[config.Vertex]bool, len(peers)) +func checkNhTable(NhTable mtypes.NextHopTable, peers []mtypes.SuperPeerInfo) error { + allpeer := make(map[mtypes.Vertex]bool, len(peers)) for _, peer1 := range peers { allpeer[peer1.NodeID] = true } @@ -62,16 +62,16 @@ func checkNhTable(NhTable config.NextHopTable, peers []config.SuperPeerInfo) err } func printExampleSuperConf() { - v1 := config.Vertex(1) - v2 := config.Vertex(2) + v1 := mtypes.Vertex(1) + v2 := mtypes.Vertex(2) - sconfig := config.SuperConfig{ + sconfig := mtypes.SuperConfig{ NodeName: "NodeSuper", PostScript: "", PrivKeyV4: "mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk=", PrivKeyV6: "+EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I=", ListenPort: 3000, - LogLevel: config.LoggerInfo{ + LogLevel: mtypes.LoggerInfo{ LogLevel: "normal", LogTransit: true, LogControl: true, @@ -80,12 +80,12 @@ func printExampleSuperConf() { LogNTP: false, }, RePushConfigInterval: 30, - Passwords: config.Passwords{ + Passwords: mtypes.Passwords{ ShowState: "passwd", AddPeer: "passwd_addpeer", DelPeer: "passwd_delpeer", }, - GraphRecalculateSetting: config.GraphRecalculateSetting{ + GraphRecalculateSetting: mtypes.GraphRecalculateSetting{ StaticMode: false, JitterTolerance: 5, JitterToleranceMultiplier: 1.01, @@ -93,17 +93,17 @@ func printExampleSuperConf() { TimeoutCheckInterval: 5, RecalculateCoolDown: 5, }, - NextHopTable: config.NextHopTable{ - config.Vertex(1): { - config.Vertex(2): &v2, + NextHopTable: mtypes.NextHopTable{ + mtypes.Vertex(1): { + mtypes.Vertex(2): &v2, }, - config.Vertex(2): { - config.Vertex(1): &v1, + mtypes.Vertex(2): { + mtypes.Vertex(1): &v1, }, }, EdgeTemplate: "example_config/super_mode/n1.yaml", UsePSKForInterEdge: true, - Peers: []config.SuperPeerInfo{ + Peers: []mtypes.SuperPeerInfo{ { NodeID: 1, Name: "Node_01", @@ -131,15 +131,15 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string) printExampleSuperConf() return nil } - var sconfig config.SuperConfig + var sconfig mtypes.SuperConfig err = readYaml(configPath, &sconfig) if err != nil { fmt.Printf("Error read config: %v\t%v\n", configPath, err) return err } - http_sconfig = &sconfig - err = readYaml(sconfig.EdgeTemplate, &http_econfig_tmp) + httpobj.http_sconfig = &sconfig + err = readYaml(sconfig.EdgeTemplate, &httpobj.http_econfig_tmp) if err != nil { fmt.Printf("Error read config: %v\t%v\n", sconfig.EdgeTemplate, err) return err @@ -170,41 +170,41 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string) fmt.Sprintf("(%s) ", NodeName+"_v6"), ) - http_sconfig_path = configPath - http_PeerState = make(map[string]*PeerState) - http_PeerIPs = make(map[string]*HttpPeerLocalIP) - http_PeerID2Info = make(map[config.Vertex]config.SuperPeerInfo) - http_HashSalt = []byte(config.RandomStr(32, "Salt generate failed")) - http_passwords = sconfig.Passwords + httpobj.http_sconfig_path = configPath + httpobj.http_PeerState = make(map[string]*PeerState) + httpobj.http_PeerIPs = make(map[string]*HttpPeerLocalIP) + httpobj.http_PeerID2Info = make(map[mtypes.Vertex]mtypes.SuperPeerInfo) + httpobj.http_HashSalt = []byte(mtypes.RandomStr(32, fmt.Sprintf("%v", time.Now()))) + httpobj.http_passwords = sconfig.Passwords - http_super_chains = &path.SUPER_Events{ - Event_server_pong: make(chan path.PongMsg, 1<<5), - Event_server_register: make(chan path.RegisterMsg, 1<<5), + httpobj.http_super_chains = &mtypes.SUPER_Events{ + Event_server_pong: make(chan mtypes.PongMsg, 1<<5), + Event_server_register: make(chan mtypes.RegisterMsg, 1<<5), } - http_graph = path.NewGraph(3, true, sconfig.GraphRecalculateSetting, config.NTPinfo{}, sconfig.LogLevel) - http_graph.SetNHTable(http_sconfig.NextHopTable, [32]byte{}) + httpobj.http_graph = path.NewGraph(3, true, sconfig.GraphRecalculateSetting, mtypes.NTPinfo{}, sconfig.LogLevel) + httpobj.http_graph.SetNHTable(httpobj.http_sconfig.NextHopTable, [32]byte{}) if sconfig.GraphRecalculateSetting.StaticMode { - err = checkNhTable(http_sconfig.NextHopTable, sconfig.Peers) + err = checkNhTable(httpobj.http_sconfig.NextHopTable, sconfig.Peers) if err != nil { return err } } thetap4, _ := tap.CreateDummyTAP() - http_device4 = device.NewDevice(thetap4, config.SuperNodeMessage, conn.NewDefaultBind(true, false, bindmode), logger4, http_graph, true, configPath, nil, &sconfig, http_super_chains, Version) - defer http_device4.Close() + httpobj.http_device4 = device.NewDevice(thetap4, mtypes.SuperNodeMessage, conn.NewDefaultBind(true, false, bindmode), logger4, httpobj.http_graph, true, configPath, nil, &sconfig, httpobj.http_super_chains, Version) + defer httpobj.http_device4.Close() thetap6, _ := tap.CreateDummyTAP() - http_device6 = device.NewDevice(thetap6, config.SuperNodeMessage, conn.NewDefaultBind(false, true, bindmode), logger6, http_graph, true, configPath, nil, &sconfig, http_super_chains, Version) - defer http_device6.Close() + httpobj.http_device6 = device.NewDevice(thetap6, mtypes.SuperNodeMessage, conn.NewDefaultBind(false, true, bindmode), logger6, httpobj.http_graph, true, configPath, nil, &sconfig, httpobj.http_super_chains, Version) + defer httpobj.http_device6.Close() if sconfig.PrivKeyV4 != "" { pk4, err := device.Str2PriKey(sconfig.PrivKeyV4) if err != nil { fmt.Println("Error decode base64 ", err) return err } - http_device4.SetPrivateKey(pk4) - http_device4.IpcSet("fwmark=0\n") - http_device4.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n") - http_device4.IpcSet("replace_peers=true\n") + httpobj.http_device4.SetPrivateKey(pk4) + httpobj.http_device4.IpcSet("fwmark=0\n") + httpobj.http_device4.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n") + httpobj.http_device4.IpcSet("replace_peers=true\n") } if sconfig.PrivKeyV6 != "" { @@ -213,10 +213,10 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string) fmt.Println("Error decode base64 ", err) return err } - http_device6.SetPrivateKey(pk6) - http_device6.IpcSet("fwmark=0\n") - http_device6.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n") - http_device6.IpcSet("replace_peers=true\n") + httpobj.http_device6.SetPrivateKey(pk6) + httpobj.http_device6.IpcSet("fwmark=0\n") + httpobj.http_device6.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n") + httpobj.http_device6.IpcSet("replace_peers=true\n") } for _, peerconf := range sconfig.Peers { @@ -231,19 +231,19 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string) errs := make(chan error, 1<<3) term := make(chan os.Signal, 1) if useUAPI { - uapi4, err := startUAPI(NodeName+"_v4", logger4, http_device4, errs) + uapi4, err := startUAPI(NodeName+"_v4", logger4, httpobj.http_device4, errs) if err != nil { return err } defer uapi4.Close() - uapi6, err := startUAPI(NodeName+"_v6", logger6, http_device6, errs) + uapi6, err := startUAPI(NodeName+"_v6", logger6, httpobj.http_device6, errs) if err != nil { return err } defer uapi6.Close() } - go Event_server_event_hendler(http_graph, http_super_chains) + go Event_server_event_hendler(httpobj.http_graph, httpobj.http_super_chains) go RoutinePushSettings(path.S2TD(sconfig.RePushConfigInterval)) go RoutineTimeoutCheck() go HttpServer(sconfig.ListenPort, "/api") @@ -271,22 +271,20 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string) select { case <-term: case <-errs: - case <-http_device4.Wait(): - case <-http_device6.Wait(): + case <-httpobj.http_device4.Wait(): + case <-httpobj.http_device6.Wait(): } logger4.Verbosef("Shutting down") return } -func super_peeradd(peerconf config.SuperPeerInfo) error { +func super_peeradd(peerconf mtypes.SuperPeerInfo) error { + // No lock, lock before call me pk, err := device.Str2PubKey(peerconf.PubKey) if err != nil { return fmt.Errorf("Error decode base64 :%v", err) } - if peerconf.AdditionalCost < 0 { - return fmt.Errorf("AdditionalCost can't smaller than zero!") - } - if http_sconfig.PrivKeyV4 != "" { + if httpobj.http_sconfig.PrivKeyV4 != "" { var psk device.NoisePresharedKey if peerconf.PSKey != "" { psk, err = device.Str2PSKey(peerconf.PSKey) @@ -294,7 +292,7 @@ func super_peeradd(peerconf config.SuperPeerInfo) error { return fmt.Errorf("Error decode base64 :%v", err) } } - peer4, err := http_device4.NewPeer(pk, peerconf.NodeID, false) + peer4, err := httpobj.http_device4.NewPeer(pk, peerconf.NodeID, false) if err != nil { return fmt.Errorf("Error create peer id :%v", err) } @@ -303,7 +301,7 @@ func super_peeradd(peerconf config.SuperPeerInfo) error { peer4.SetPSK(psk) } } - if http_sconfig.PrivKeyV6 != "" { + if httpobj.http_sconfig.PrivKeyV6 != "" { var psk device.NoisePresharedKey if peerconf.PSKey != "" { psk, err = device.Str2PSKey(peerconf.PSKey) @@ -311,7 +309,7 @@ func super_peeradd(peerconf config.SuperPeerInfo) error { return fmt.Errorf("Error decode base64 :%v", err) } } - peer6, err := http_device6.NewPeer(pk, peerconf.NodeID, false) + peer6, err := httpobj.http_device6.NewPeer(pk, peerconf.NodeID, false) if err != nil { return fmt.Errorf("Error create peer id :%v", err) } @@ -320,104 +318,111 @@ func super_peeradd(peerconf config.SuperPeerInfo) error { peer6.SetPSK(psk) } } - http_maps_lock.Lock() - http_PeerID2Info[peerconf.NodeID] = peerconf - http_PeerState[peerconf.PubKey] = &PeerState{} - http_PeerIPs[peerconf.PubKey] = &HttpPeerLocalIP{} - http_maps_lock.Unlock() + httpobj.http_PeerID2Info[peerconf.NodeID] = peerconf + httpobj.http_PeerState[peerconf.PubKey] = &PeerState{} + httpobj.http_PeerIPs[peerconf.PubKey] = &HttpPeerLocalIP{} return nil } -func super_peerdel(toDelete config.Vertex) { - http_maps_lock.RLock() - PubKey := http_PeerID2Info[toDelete].PubKey - http_maps_lock.RUnlock() - UpdateErrorMsg := path.UpdateErrorMsg{ +func super_peerdel(toDelete mtypes.Vertex) { + // No lock, lock before call me + if _, has := httpobj.http_PeerID2Info[toDelete]; !has { + return + } + PubKey := httpobj.http_PeerID2Info[toDelete].PubKey + delete(httpobj.http_PeerState, PubKey) + delete(httpobj.http_PeerIPs, PubKey) + delete(httpobj.http_PeerID2Info, toDelete) + go super_peerdel_notify(toDelete, PubKey) +} + +func super_peerdel_notify(toDelete mtypes.Vertex, PubKey string) { + UpdateErrorMsg := mtypes.ServerCommandMsg{ Node_id: toDelete, - Action: path.Shutdown, - ErrorCode: 410, + Action: mtypes.Shutdown, + ErrorCode: int(syscall.ENOENT), ErrorMsg: "You've been removed from supernode.", } for i := 0; i < 10; i++ { - body, _ := path.GetByte(&UpdateErrorMsg) + body, _ := mtypes.GetByte(&UpdateErrorMsg) buf := make([]byte, path.EgHeaderLen+len(body)) header, _ := path.NewEgHeader(buf[:path.EgHeaderLen]) - header.SetSrc(config.SuperNodeMessage) + header.SetSrc(mtypes.SuperNodeMessage) header.SetTTL(0) header.SetPacketLength(uint16(len(body))) copy(buf[path.EgHeaderLen:], body) header.SetDst(toDelete) - peer4 := http_device4.LookupPeerByStr(PubKey) - http_device4.SendPacket(peer4, path.UpdateError, buf, device.MessageTransportOffsetContent) + peer4 := httpobj.http_device4.LookupPeerByStr(PubKey) + httpobj.http_device4.SendPacket(peer4, path.UpdateError, buf, device.MessageTransportOffsetContent) - peer6 := http_device6.LookupPeerByStr(PubKey) - http_device6.SendPacket(peer6, path.UpdateError, buf, device.MessageTransportOffsetContent) + peer6 := httpobj.http_device6.LookupPeerByStr(PubKey) + httpobj.http_device6.SendPacket(peer6, path.UpdateError, buf, device.MessageTransportOffsetContent) time.Sleep(path.S2TD(0.1)) } - http_device4.RemovePeerByID(toDelete) - http_device6.RemovePeerByID(toDelete) - http_graph.RemoveVirt(toDelete, true, false) - http_maps_lock.Lock() - delete(http_PeerState, PubKey) - delete(http_PeerIPs, PubKey) - delete(http_PeerID2Info, toDelete) - http_maps_lock.Unlock() + httpobj.http_device4.RemovePeerByID(toDelete) + httpobj.http_device6.RemovePeerByID(toDelete) + httpobj.http_graph.RemoveVirt(toDelete, true, false) } -func Event_server_event_hendler(graph *path.IG, events *path.SUPER_Events) { +func Event_server_event_hendler(graph *path.IG, events *mtypes.SUPER_Events) { for { select { case reg_msg := <-events.Event_server_register: var should_push_peer bool var should_push_nh bool - http_maps_lock.RLock() - if reg_msg.Node_id < config.Special_NodeID { - http_PeerState[http_PeerID2Info[reg_msg.Node_id].PubKey].LastSeen = time.Now() - PubKey := http_PeerID2Info[reg_msg.Node_id].PubKey - if bytes.Equal(http_PeerState[PubKey].NhTableState[:], reg_msg.NhStateHash[:]) == false { - copy(http_PeerState[PubKey].NhTableState[:], reg_msg.NhStateHash[:]) + NodeID := reg_msg.Node_id + httpobj.RLock() + PubKey := httpobj.http_PeerID2Info[NodeID].PubKey + if reg_msg.Node_id < mtypes.Special_NodeID { + httpobj.http_PeerState[PubKey].LastSeen = time.Now() + httpobj.http_PeerState[PubKey].JETSecret = reg_msg.JWTSecret + httpobj.http_PeerState[PubKey].httpPostCount = reg_msg.HttpPostCount + if bytes.Equal(httpobj.http_PeerState[PubKey].NhTableState[:], reg_msg.NhStateHash[:]) == false { + copy(httpobj.http_PeerState[PubKey].NhTableState[:], reg_msg.NhStateHash[:]) should_push_nh = true } - if bytes.Equal(http_PeerState[PubKey].PeerInfoState[:], reg_msg.PeerStateHash[:]) == false { - copy(http_PeerState[PubKey].PeerInfoState[:], reg_msg.PeerStateHash[:]) + if bytes.Equal(httpobj.http_PeerState[PubKey].PeerInfoState[:], reg_msg.PeerStateHash[:]) == false { + copy(httpobj.http_PeerState[PubKey].PeerInfoState[:], reg_msg.PeerStateHash[:]) should_push_peer = true } - - http_PeerIPs[PubKey].IPv4 = reg_msg.LocalV4 - http_PeerIPs[PubKey].IPv6 = reg_msg.LocalV6 } var peer_state_changed bool - http_PeerInfo, http_PeerInfo_hash, peer_state_changed = get_api_peers(http_PeerInfo_hash) - http_maps_lock.RUnlock() + + httpobj.http_PeerInfo, httpobj.http_PeerInfo_hash, peer_state_changed = get_api_peers(httpobj.http_PeerInfo_hash) if should_push_peer || peer_state_changed { PushPeerinfo(false) } if should_push_nh { PushNhTable(false) } + httpobj.RUnlock() case pong_msg := <-events.Event_server_pong: var changed bool - http_maps_lock.RLock() - if pong_msg.Src_nodeID < config.Special_NodeID && pong_msg.Dst_nodeID < config.Special_NodeID { - changed = graph.UpdateLatency(pong_msg.Src_nodeID, pong_msg.Dst_nodeID, pong_msg.Timediff, http_PeerID2Info[pong_msg.Dst_nodeID].AdditionalCost, true, true) + httpobj.RLock() + if pong_msg.Src_nodeID < mtypes.Special_NodeID && pong_msg.Dst_nodeID < mtypes.Special_NodeID { + AdditionalCost_use := httpobj.http_PeerID2Info[pong_msg.Dst_nodeID].AdditionalCost + if AdditionalCost_use < 0 { + AdditionalCost_use = pong_msg.AdditionalCost + } + changed = httpobj.http_graph.UpdateLatency(pong_msg.Src_nodeID, pong_msg.Dst_nodeID, pong_msg.Timediff, pong_msg.TimeToAlive, AdditionalCost_use, true, true) } else { - if http_graph.CheckAnyShouldUpdate() { - changed = http_graph.RecalculateNhTable(true) + if httpobj.http_graph.CheckAnyShouldUpdate() { + changed = httpobj.http_graph.RecalculateNhTable(true) } } - http_maps_lock.RUnlock() if changed { NhTable := graph.GetNHTable(true) NhTablestr, _ := json.Marshal(NhTable) - md5_hash_raw := md5.Sum(append(http_NhTableStr, http_HashSalt...)) + md5_hash_raw := md5.Sum(append(httpobj.http_NhTableStr, httpobj.http_HashSalt...)) new_hash_str := hex.EncodeToString(md5_hash_raw[:]) new_hash_str_byte := []byte(new_hash_str) - copy(http_NhTable_Hash[:], new_hash_str_byte) + copy(httpobj.http_NhTable_Hash[:], new_hash_str_byte) copy(graph.NhTableHash[:], new_hash_str_byte) - http_NhTableStr = NhTablestr + httpobj.http_NhTableStr = NhTablestr PushNhTable(false) } + httpobj.RUnlock() } } } @@ -440,22 +445,23 @@ func RoutinePushSettings(interval time.Duration) { func RoutineTimeoutCheck() { for { - http_super_chains.Event_server_register <- path.RegisterMsg{ - Node_id: config.SuperNodeMessage, + httpobj.http_super_chains.Event_server_register <- mtypes.RegisterMsg{ + Node_id: mtypes.SuperNodeMessage, Version: "dummy", } - http_super_chains.Event_server_pong <- path.PongMsg{ + httpobj.http_super_chains.Event_server_pong <- mtypes.PongMsg{ RequestID: 0, - Src_nodeID: config.SuperNodeMessage, - Dst_nodeID: config.SuperNodeMessage, + Src_nodeID: mtypes.SuperNodeMessage, + Dst_nodeID: mtypes.SuperNodeMessage, } - time.Sleep(http_graph.TimeoutCheckInterval) + time.Sleep(httpobj.http_graph.TimeoutCheckInterval) } } func PushNhTable(force bool) { - body, err := path.GetByte(path.UpdateNhTableMsg{ - State_hash: http_NhTable_Hash, + // No lock + body, err := mtypes.GetByte(mtypes.UpdateNhTableMsg{ + State_hash: httpobj.http_NhTable_Hash, }) if err != nil { fmt.Println("Error get byte") @@ -463,32 +469,31 @@ func PushNhTable(force bool) { } buf := make([]byte, path.EgHeaderLen+len(body)) header, _ := path.NewEgHeader(buf[:path.EgHeaderLen]) - header.SetDst(config.SuperNodeMessage) + header.SetDst(mtypes.SuperNodeMessage) header.SetPacketLength(uint16(len(body))) - header.SetSrc(config.SuperNodeMessage) + header.SetSrc(mtypes.SuperNodeMessage) header.SetTTL(0) copy(buf[path.EgHeaderLen:], body) - http_maps_lock.RLock() - for pkstr, peerstate := range http_PeerState { - isAlive := peerstate.LastSeen.Add(path.S2TD(http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now()) + for pkstr, peerstate := range httpobj.http_PeerState { + isAlive := peerstate.LastSeen.Add(path.S2TD(httpobj.http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now()) if !isAlive { continue } - if force || peerstate.NhTableState != http_NhTable_Hash { - if peer := http_device4.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" { - http_device4.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent) + if force || peerstate.NhTableState != httpobj.http_NhTable_Hash { + if peer := httpobj.http_device4.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" { + httpobj.http_device4.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent) } - if peer := http_device6.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" { - http_device6.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent) + if peer := httpobj.http_device6.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" { + httpobj.http_device6.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent) } } } - http_maps_lock.RUnlock() } func PushPeerinfo(force bool) { - body, err := path.GetByte(path.UpdatePeerMsg{ - State_hash: http_PeerInfo_hash, + //No lock + body, err := mtypes.GetByte(mtypes.UpdatePeerMsg{ + State_hash: httpobj.http_PeerInfo_hash, }) if err != nil { fmt.Println("Error get byte") @@ -496,27 +501,25 @@ func PushPeerinfo(force bool) { } buf := make([]byte, path.EgHeaderLen+len(body)) header, _ := path.NewEgHeader(buf[:path.EgHeaderLen]) - header.SetDst(config.SuperNodeMessage) + header.SetDst(mtypes.SuperNodeMessage) header.SetPacketLength(uint16(len(body))) - header.SetSrc(config.SuperNodeMessage) + header.SetSrc(mtypes.SuperNodeMessage) header.SetTTL(0) copy(buf[path.EgHeaderLen:], body) - http_maps_lock.RLock() - for pkstr, peerstate := range http_PeerState { - isAlive := peerstate.LastSeen.Add(path.S2TD(http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now()) + for pkstr, peerstate := range httpobj.http_PeerState { + isAlive := peerstate.LastSeen.Add(path.S2TD(httpobj.http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now()) if !isAlive { continue } - if force || peerstate.PeerInfoState != http_PeerInfo_hash { - if peer := http_device4.LookupPeerByStr(pkstr); peer != nil { - http_device4.SendPacket(peer, path.UpdatePeer, buf, device.MessageTransportOffsetContent) + if force || peerstate.PeerInfoState != httpobj.http_PeerInfo_hash { + if peer := httpobj.http_device4.LookupPeerByStr(pkstr); peer != nil { + httpobj.http_device4.SendPacket(peer, path.UpdatePeer, buf, device.MessageTransportOffsetContent) } - if peer := http_device6.LookupPeerByStr(pkstr); peer != nil { - http_device6.SendPacket(peer, path.UpdatePeer, buf, device.MessageTransportOffsetContent) + if peer := httpobj.http_device6.LookupPeerByStr(pkstr); peer != nil { + httpobj.http_device6.SendPacket(peer, path.UpdatePeer, buf, device.MessageTransportOffsetContent) } } } - http_maps_lock.RUnlock() } func startUAPI(interfaceName string, logger *device.Logger, the_device *device.Device, errs chan error) (net.Listener, error) { diff --git a/config/config.go b/mtypes/config.go similarity index 77% rename from config/config.go rename to mtypes/config.go index c943365..ecaba05 100644 --- a/config/config.go +++ b/mtypes/config.go @@ -1,7 +1,6 @@ -package config +package mtypes import ( - "crypto/rand" "math" "strconv" ) @@ -13,7 +12,8 @@ const ( Broadcast Vertex = math.MaxUint16 - iota // Normal boardcast, boardcast with route table ControlMessage Vertex = math.MaxUint16 - iota // p2p mode: boardcast to every know peer and prevent dup. super mode: send to supernode SuperNodeMessage Vertex = math.MaxUint16 - iota - Special_NodeID Vertex = SuperNodeMessage + BrokenMessage Vertex = math.MaxUint16 - iota + Special_NodeID Vertex = BrokenMessage ) type EdgeConfig struct { @@ -132,6 +132,8 @@ type SuperInfo struct { ConnURLV6 string PubKeyV6 string APIUrl string + SkipLocalIP bool + HttpPostInterval float64 SuperNodeInfoTimeout float64 } @@ -154,26 +156,52 @@ type GraphRecalculateSetting struct { type DistTable map[Vertex]map[Vertex]float64 type NextHopTable map[Vertex]map[Vertex]*Vertex +type API_connurl struct { + ExternalV4 map[string]float64 + ExternalV6 map[string]float64 + LocalV4 map[string]float64 + LocalV6 map[string]float64 +} + +func (Connurl *API_connurl) IsEmpty() bool { + return len(Connurl.ExternalV4)+len(Connurl.ExternalV6)+len(Connurl.LocalV4)+len(Connurl.LocalV6) == 0 +} + +func (Connurl *API_connurl) GetList(UseLocal bool) (ret map[string]float64) { + ret = make(map[string]float64) + if UseLocal { + if Connurl.LocalV4 != nil { + for k, v := range Connurl.LocalV4 { + ret[k] = v + } + } + if Connurl.LocalV6 != nil { + for k, v := range Connurl.LocalV6 { + ret[k] = v + } + } + } + if Connurl.ExternalV4 != nil { + for k, v := range Connurl.ExternalV4 { + ret[k] = v + } + } + if Connurl.ExternalV6 != nil { + for k, v := range Connurl.ExternalV6 { + ret[k] = v + } + } + return +} + type API_Peerinfo struct { NodeID Vertex PSKey string - Connurl map[string]float64 + Connurl *API_connurl } type API_Peers map[string]API_Peerinfo // map[PubKey]API_Peerinfo +type JWTSecret [32]byte + const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - -func RandomStr(length int, defaults string) string { - bytes := make([]byte, length) - - if _, err := rand.Read(bytes); err != nil { - return defaults - } - - for i, b := range bytes { - bytes[i] = chars[b%byte(len(chars))] - } - - return string(bytes) -} diff --git a/mtypes/functions.go b/mtypes/functions.go new file mode 100644 index 0000000..84b1f0c --- /dev/null +++ b/mtypes/functions.go @@ -0,0 +1,65 @@ +package mtypes + +import ( + "bytes" + "compress/gzip" + "crypto/rand" + "fmt" + "io/ioutil" + "time" +) + +func S2TD(secs float64) time.Duration { + return time.Duration(secs * float64(time.Second)) +} + +func RandomStr(length int, defaults string) string { + bytes := make([]byte, length) + + if _, err := rand.Read(bytes); err != nil { + if len(defaults) < length { + defaults = fmt.Sprintf("%*s\n", length, defaults) + } + return defaults[:length] + } + + for i, b := range bytes { + bytes[i] = chars[b%byte(len(chars))] + } + + return string(bytes) +} + +func RandomBytes(length int, defaults []byte) []byte { + bytes := make([]byte, length) + if _, err := rand.Read(bytes); err != nil { + copy(bytes, defaults) + return defaults + } + return bytes +} + +func ByteSlice2Byte32(bytes []byte) (ret [32]byte) { + if len(bytes) != 32 { + fmt.Println("Not a 32 len byte") + } + copy(ret[:], bytes) + return +} + +func Gzip(bytesIn []byte) (ret []byte) { + var b bytes.Buffer + w := gzip.NewWriter(&b) + w.Write([]byte(bytesIn)) + w.Close() + return b.Bytes() +} + +func GUzip(bytesIn []byte) (ret []byte, err error) { + b := bytes.NewReader(bytesIn) + r, err := gzip.NewReader(b) + if err != nil { + return + } + return ioutil.ReadAll(r) +} diff --git a/path/metamessage.go b/mtypes/metamessage.go similarity index 70% rename from path/metamessage.go rename to mtypes/metamessage.go index 97d1387..4eeedaa 100644 --- a/path/metamessage.go +++ b/mtypes/metamessage.go @@ -1,15 +1,14 @@ -package path +package mtypes import ( "bytes" "encoding/base64" "encoding/gob" "fmt" - "net" "strconv" "time" - "github.com/KusakabeSi/EtherGuardVPN/config" + "github.com/golang-jwt/jwt" ) func GetByte(structIn interface{}) (bb []byte, err error) { @@ -23,12 +22,12 @@ func GetByte(structIn interface{}) (bb []byte, err error) { } type RegisterMsg struct { - Node_id config.Vertex + Node_id Vertex Version string PeerStateHash [32]byte NhStateHash [32]byte - LocalV4 net.UDPAddr - LocalV6 net.UDPAddr + JWTSecret JWTSecret + HttpPostCount uint64 } func Hash2Str(h []byte) string { @@ -41,7 +40,7 @@ func Hash2Str(h []byte) string { } func (c *RegisterMsg) ToString() string { - return fmt.Sprint("RegisterMsg Node_id:"+c.Node_id.ToString(), " Version:"+c.Version, " PeerHash:"+Hash2Str(c.PeerStateHash[:]), " NhHash:"+Hash2Str(c.NhStateHash[:]), " LocalV4:"+c.LocalV4.String(), " LocalV6:"+c.LocalV6.String()) + return fmt.Sprint("RegisterMsg Node_id:"+c.Node_id.ToString(), " Version:"+c.Version, " PeerHash:"+Hash2Str(c.PeerStateHash[:]), " NhHash:"+Hash2Str(c.NhStateHash[:])) } func ParseRegisterMsg(bin []byte) (StructPlace RegisterMsg, err error) { @@ -52,31 +51,34 @@ func ParseRegisterMsg(bin []byte) (StructPlace RegisterMsg, err error) { return } -type ErrorAction int +type ServerCommand int const ( - NoAction ErrorAction = iota + NoAction ServerCommand = iota Shutdown + ThrowError Panic ) -func (a *ErrorAction) ToString() string { +func (a *ServerCommand) ToString() string { if *a == Shutdown { - return "shutdown" + return "Shutdown" + } else if *a == ThrowError { + return "ThrowError" } else if *a == Panic { - return "panic" + return "Panic" } - return "unknow" + return "Unknown" } -type UpdateErrorMsg struct { - Node_id config.Vertex - Action ErrorAction +type ServerCommandMsg struct { + Node_id Vertex + Action ServerCommand ErrorCode int ErrorMsg string } -func ParseUpdateErrorMsg(bin []byte) (StructPlace UpdateErrorMsg, err error) { +func ParseUpdateErrorMsg(bin []byte) (StructPlace ServerCommandMsg, err error) { var b bytes.Buffer b.Write(bin) d := gob.NewDecoder(&b) @@ -84,8 +86,8 @@ func ParseUpdateErrorMsg(bin []byte) (StructPlace UpdateErrorMsg, err error) { return } -func (c *UpdateErrorMsg) ToString() string { - return "UpdateErrorMsg Node_id:" + c.Node_id.ToString() + " Action:" + c.Action.ToString() + " ErrorCode:" + strconv.Itoa(c.ErrorCode) + " ErrorMsg " + c.ErrorMsg +func (c *ServerCommandMsg) ToString() string { + return "ServerCommandMsg Node_id:" + c.Node_id.ToString() + " Action:" + c.Action.ToString() + " ErrorCode:" + strconv.Itoa(int(c.ErrorCode)) + " ErrorMsg " + c.ErrorMsg } type UpdatePeerMsg struct { @@ -122,7 +124,7 @@ func ParseUpdateNhTableMsg(bin []byte) (StructPlace UpdateNhTableMsg, err error) type PingMsg struct { RequestID uint32 - Src_nodeID config.Vertex + Src_nodeID Vertex Time time.Time RequestReply int } @@ -141,14 +143,15 @@ func ParsePingMsg(bin []byte) (StructPlace PingMsg, err error) { type PongMsg struct { RequestID uint32 - Src_nodeID config.Vertex - Dst_nodeID config.Vertex - Timediff time.Duration + Src_nodeID Vertex + Dst_nodeID Vertex + Timediff float64 + TimeToAlive float64 AdditionalCost float64 } func (c *PongMsg) ToString() string { - return "PongMsg SID:" + c.Src_nodeID.ToString() + " DID:" + c.Dst_nodeID.ToString() + " Timediff:" + c.Timediff.String() + " RequestID:" + strconv.Itoa(int(c.RequestID)) + return "PongMsg SID:" + c.Src_nodeID.ToString() + " DID:" + c.Dst_nodeID.ToString() + " Timediff:" + S2TD(c.Timediff).String() + " TTL:" + S2TD(c.TimeToAlive).String() + " RequestID:" + strconv.Itoa(int(c.RequestID)) } func ParsePongMsg(bin []byte) (StructPlace PongMsg, err error) { @@ -177,7 +180,7 @@ func ParseQueryPeerMsg(bin []byte) (StructPlace QueryPeerMsg, err error) { type BoardcastPeerMsg struct { Request_ID uint32 - NodeID config.Vertex + NodeID Vertex PubKey [32]byte ConnURL string } @@ -194,6 +197,26 @@ func ParseBoardcastPeerMsg(bin []byte) (StructPlace BoardcastPeerMsg, err error) return } +type API_report_peerinfo struct { + Pongs []PongMsg + LocalV4s map[string]float64 + LocalV6s map[string]float64 +} + +func ParseAPI_report_peerinfo(bin []byte) (StructPlace API_report_peerinfo, err error) { + var b bytes.Buffer + b.Write(bin) + d := gob.NewDecoder(&b) + err = d.Decode(&StructPlace) + return +} + +type API_report_peerinfo_jwt_claims struct { + PostCount uint64 + BodyHash string + jwt.StandardClaims +} + type SUPER_Events struct { Event_server_pong chan PongMsg Event_server_register chan RegisterMsg diff --git a/path/header.go b/path/header.go index af22fad..feafe30 100644 --- a/path/header.go +++ b/path/header.go @@ -4,7 +4,7 @@ import ( "encoding/binary" "errors" - "github.com/KusakabeSi/EtherGuardVPN/config" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" ) const EgHeaderLen = 7 @@ -43,17 +43,17 @@ func NewEgHeader(pac []byte) (e EgHeader, err error) { return } -func (e EgHeader) GetDst() config.Vertex { - return config.Vertex(binary.BigEndian.Uint16(e.buf[0:2])) +func (e EgHeader) GetDst() mtypes.Vertex { + return mtypes.Vertex(binary.BigEndian.Uint16(e.buf[0:2])) } -func (e EgHeader) SetDst(node_ID config.Vertex) { +func (e EgHeader) SetDst(node_ID mtypes.Vertex) { binary.BigEndian.PutUint16(e.buf[0:2], uint16(node_ID)) } -func (e EgHeader) GetSrc() config.Vertex { - return config.Vertex(binary.BigEndian.Uint16(e.buf[2:4])) +func (e EgHeader) GetSrc() mtypes.Vertex { + return mtypes.Vertex(binary.BigEndian.Uint16(e.buf[2:4])) } -func (e EgHeader) SetSrc(node_ID config.Vertex) { +func (e EgHeader) SetSrc(node_ID mtypes.Vertex) { binary.BigEndian.PutUint16(e.buf[2:4], uint16(node_ID)) } diff --git a/path/ntp.go b/path/ntp.go index b8fdb71..01f507d 100644 --- a/path/ntp.go +++ b/path/ntp.go @@ -5,7 +5,7 @@ import ( "sort" "time" - orderedmap "github.com/KusakabeSi/EtherGuardVPN/orderdmap" + orderedmap "github.com/KusakabeSi/EtherGuard-VPN/orderdmap" "github.com/beevik/ntp" ) diff --git a/path/path.go b/path/path.go index c57b63a..2cc9cfa 100644 --- a/path/path.go +++ b/path/path.go @@ -11,8 +11,8 @@ import ( "sync" "time" - "github.com/KusakabeSi/EtherGuardVPN/config" - orderedmap "github.com/KusakabeSi/EtherGuardVPN/orderdmap" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + orderedmap "github.com/KusakabeSi/EtherGuard-VPN/orderdmap" yaml "gopkg.in/yaml.v2" ) @@ -26,36 +26,35 @@ type Latency struct { ping float64 ping_old float64 additionalCost float64 - time time.Time + validUntil time.Time } type Fullroute struct { - Next config.NextHopTable `yaml:"NextHopTable"` - Dist config.DistTable `yaml:"DistanceTable"` + Next mtypes.NextHopTable `yaml:"NextHopTable"` + Dist mtypes.DistTable `yaml:"DistanceTable"` } // IG is a graph of integers that satisfies the Graph interface. type IG struct { - Vert map[config.Vertex]bool - edges map[config.Vertex]map[config.Vertex]*Latency + Vert map[mtypes.Vertex]bool + edges map[mtypes.Vertex]map[mtypes.Vertex]*Latency edgelock *sync.RWMutex StaticMode bool JitterTolerance float64 JitterToleranceMultiplier float64 - NodeReportTimeout time.Duration SuperNodeInfoTimeout time.Duration RecalculateCoolDown time.Duration TimeoutCheckInterval time.Duration recalculateTime time.Time - dlTable config.DistTable - nhTable config.NextHopTable + dlTable mtypes.DistTable + nhTable mtypes.NextHopTable NhTableHash [32]byte NhTableExpire time.Time IsSuperMode bool - loglevel config.LoggerInfo + loglevel mtypes.LoggerInfo ntp_wg sync.WaitGroup - ntp_info config.NTPinfo + ntp_info mtypes.NTPinfo ntp_offset time.Duration ntp_servers orderedmap.OrderedMap // serverurl:lentancy } @@ -64,19 +63,18 @@ func S2TD(secs float64) time.Duration { return time.Duration(secs * float64(time.Second)) } -func NewGraph(num_node int, IsSuperMode bool, theconfig config.GraphRecalculateSetting, ntpinfo config.NTPinfo, loglevel config.LoggerInfo) *IG { +func NewGraph(num_node int, IsSuperMode bool, theconfig mtypes.GraphRecalculateSetting, ntpinfo mtypes.NTPinfo, loglevel mtypes.LoggerInfo) *IG { g := IG{ edgelock: &sync.RWMutex{}, StaticMode: theconfig.StaticMode, JitterTolerance: theconfig.JitterTolerance, JitterToleranceMultiplier: theconfig.JitterToleranceMultiplier, - NodeReportTimeout: S2TD(theconfig.NodeReportTimeout), RecalculateCoolDown: S2TD(theconfig.RecalculateCoolDown), TimeoutCheckInterval: S2TD(theconfig.TimeoutCheckInterval), ntp_info: ntpinfo, } - g.Vert = make(map[config.Vertex]bool, num_node) - g.edges = make(map[config.Vertex]map[config.Vertex]*Latency, num_node) + g.Vert = make(map[mtypes.Vertex]bool, num_node) + g.edges = make(map[mtypes.Vertex]map[mtypes.Vertex]*Latency, num_node) g.IsSuperMode = IsSuperMode g.loglevel = loglevel g.InitNTP() @@ -94,7 +92,7 @@ func (g *IG) GetWeightType(x float64) (y float64) { return y } -func (g *IG) ShouldUpdate(u config.Vertex, v config.Vertex, newval float64) bool { +func (g *IG) ShouldUpdate(u mtypes.Vertex, v mtypes.Vertex, newval float64) bool { oldval := math.Abs(g.OldWeight(u, v, false) * 1000) newval = math.Abs(newval * 1000) if g.IsSuperMode { @@ -157,7 +155,7 @@ func (g *IG) RecalculateNhTable(checkchange bool) (changed bool) { return } -func (g *IG) RemoveVirt(v config.Vertex, recalculate bool, checkchange bool) (changed bool) { //Waiting for test +func (g *IG) RemoveVirt(v mtypes.Vertex, recalculate bool, checkchange bool) (changed bool) { //Waiting for test g.edgelock.Lock() delete(g.Vert, v) delete(g.edges, v) @@ -172,31 +170,49 @@ func (g *IG) RemoveVirt(v config.Vertex, recalculate bool, checkchange bool) (ch return } -func (g *IG) UpdateLatency(u, v config.Vertex, dt time.Duration, additionalCost float64, recalculate bool, checkchange bool) (changed bool) { - if additionalCost < 0 { - additionalCost = 0 - } +func (g *IG) UpdateLatency(src mtypes.Vertex, dst mtypes.Vertex, val float64, TimeToAlive float64, SuperAdditionalCost float64, recalculate bool, checkchange bool) (changed bool) { + return g.UpdateLatencyMulti([]mtypes.PongMsg{{ + Src_nodeID: src, + Dst_nodeID: dst, + Timediff: val, + AdditionalCost: SuperAdditionalCost, + TimeToAlive: TimeToAlive, + }}, recalculate, checkchange) +} + +func (g *IG) UpdateLatencyMulti(pong_info []mtypes.PongMsg, recalculate bool, checkchange bool) (changed bool) { + g.edgelock.Lock() - g.Vert[u] = true - g.Vert[v] = true - w := float64(dt) / float64(time.Second) - if _, ok := g.edges[u]; !ok { - g.recalculateTime = time.Time{} - g.edges[u] = make(map[config.Vertex]*Latency) - } - g.edgelock.Unlock() - should_update := g.ShouldUpdate(u, v, w) - g.edgelock.Lock() - if _, ok := g.edges[u][v]; ok { - g.edges[u][v].ping = w - g.edges[u][v].time = time.Now() - g.edges[u][v].additionalCost = additionalCost / 1000 - } else { - g.edges[u][v] = &Latency{ - ping: w, - ping_old: Infinity, - time: time.Now(), - additionalCost: additionalCost / 1000, + should_update := false + for _, pong_msg := range pong_info { + u := pong_msg.Src_nodeID + v := pong_msg.Dst_nodeID + w := pong_msg.Timediff + additionalCost := pong_msg.AdditionalCost + if additionalCost < 0 { + additionalCost = 0 + } + g.Vert[u] = true + g.Vert[v] = true + if _, ok := g.edges[u]; !ok { + g.recalculateTime = time.Time{} + g.edges[u] = make(map[mtypes.Vertex]*Latency) + } + g.edgelock.Unlock() + should_update = should_update || g.ShouldUpdate(u, v, w) + g.edgelock.Lock() + + if _, ok := g.edges[u][v]; ok { + g.edges[u][v].ping = w + g.edges[u][v].validUntil = time.Now().Add(mtypes.S2TD(pong_msg.TimeToAlive)) + g.edges[u][v].additionalCost = additionalCost / 1000 + } else { + g.edges[u][v] = &Latency{ + ping: w, + ping_old: Infinity, + validUntil: time.Now().Add(mtypes.S2TD(pong_msg.TimeToAlive)), + additionalCost: additionalCost / 1000, + } } } g.edgelock.Unlock() @@ -205,8 +221,8 @@ func (g *IG) UpdateLatency(u, v config.Vertex, dt time.Duration, additionalCost } return } -func (g *IG) Vertices() map[config.Vertex]bool { - vr := make(map[config.Vertex]bool) +func (g *IG) Vertices() map[mtypes.Vertex]bool { + vr := make(map[mtypes.Vertex]bool) g.edgelock.RLock() defer g.edgelock.RUnlock() for k, v := range g.Vert { //copy a new list @@ -214,7 +230,7 @@ func (g *IG) Vertices() map[config.Vertex]bool { } return vr } -func (g IG) Neighbors(v config.Vertex) (vs []config.Vertex) { +func (g IG) Neighbors(v mtypes.Vertex) (vs []mtypes.Vertex) { g.edgelock.RLock() defer g.edgelock.RUnlock() for k := range g.edges[v] { //copy a new list @@ -223,7 +239,7 @@ func (g IG) Neighbors(v config.Vertex) (vs []config.Vertex) { return vs } -func (g *IG) Next(u, v config.Vertex) *config.Vertex { +func (g *IG) Next(u, v mtypes.Vertex) *mtypes.Vertex { if _, ok := g.nhTable[u]; !ok { return nil } @@ -233,7 +249,7 @@ func (g *IG) Next(u, v config.Vertex) *config.Vertex { return g.nhTable[u][v] } -func (g *IG) Weight(u, v config.Vertex, withAC bool) (ret float64) { +func (g *IG) Weight(u, v mtypes.Vertex, withAC bool) (ret float64) { g.edgelock.RLock() defer g.edgelock.RUnlock() //defer func() { fmt.Println(u, v, ret) }() @@ -246,7 +262,7 @@ func (g *IG) Weight(u, v config.Vertex, withAC bool) (ret float64) { if _, ok := g.edges[u][v]; !ok { return Infinity } - if time.Now().After(g.edges[u][v].time.Add(g.NodeReportTimeout)) { + if time.Now().After(g.edges[u][v].validUntil) { return Infinity } ret = g.edges[u][v].ping @@ -259,7 +275,7 @@ func (g *IG) Weight(u, v config.Vertex, withAC bool) (ret float64) { return } -func (g *IG) OldWeight(u, v config.Vertex, withAC bool) (ret float64) { +func (g *IG) OldWeight(u, v mtypes.Vertex, withAC bool) (ret float64) { g.edgelock.RLock() defer g.edgelock.RUnlock() if u == v { @@ -281,7 +297,7 @@ func (g *IG) OldWeight(u, v config.Vertex, withAC bool) (ret float64) { return } -func (g *IG) SetWeight(u, v config.Vertex, weight float64) { +func (g *IG) SetWeight(u, v mtypes.Vertex, weight float64) { g.edgelock.Lock() defer g.edgelock.Unlock() if _, ok := g.edges[u]; !ok { @@ -293,7 +309,7 @@ func (g *IG) SetWeight(u, v config.Vertex, weight float64) { g.edges[u][v].ping = weight } -func (g *IG) SetOldWeight(u, v config.Vertex, weight float64) { +func (g *IG) SetOldWeight(u, v mtypes.Vertex, weight float64) { g.edgelock.Lock() defer g.edgelock.Unlock() if _, ok := g.edges[u]; !ok { @@ -319,7 +335,7 @@ func (g *IG) RemoveAllNegativeValue() { } } -func (g *IG) FloydWarshall(again bool) (dist config.DistTable, next config.NextHopTable, err error) { +func (g *IG) FloydWarshall(again bool) (dist mtypes.DistTable, next mtypes.NextHopTable, err error) { if g.loglevel.LogInternal { if !again { fmt.Println("Internal: Start Floyd Warshall algorithm") @@ -329,11 +345,11 @@ func (g *IG) FloydWarshall(again bool) (dist config.DistTable, next config.NextH } } vert := g.Vertices() - dist = make(config.DistTable) - next = make(config.NextHopTable) + dist = make(mtypes.DistTable) + next = make(mtypes.NextHopTable) for u, _ := range vert { - dist[u] = make(map[config.Vertex]float64) - next[u] = make(map[config.Vertex]*config.Vertex) + dist[u] = make(map[mtypes.Vertex]float64) + next[u] = make(map[mtypes.Vertex]*mtypes.Vertex) for v, _ := range vert { dist[u][v] = Infinity } @@ -372,8 +388,8 @@ func (g *IG) FloydWarshall(again bool) (dist config.DistTable, next config.NextH dist, next, _ = g.FloydWarshall(true) return } else { - dist = make(config.DistTable) - next = make(config.NextHopTable) + dist = make(mtypes.DistTable) + next = make(mtypes.NextHopTable) err = errors.New("negative cycle detected again!") if g.loglevel.LogInternal { fmt.Println("Internal: Error: Negative cycle detected again") @@ -385,11 +401,11 @@ func (g *IG) FloydWarshall(again bool) (dist config.DistTable, next config.NextH return } -func Path(u, v config.Vertex, next config.NextHopTable) (path []config.Vertex) { +func Path(u, v mtypes.Vertex, next mtypes.NextHopTable) (path []mtypes.Vertex) { if next[u][v] == nil { - return []config.Vertex{} + return []mtypes.Vertex{} } - path = []config.Vertex{u} + path = []mtypes.Vertex{u} for u != v { u = *next[u][v] path = append(path, u) @@ -397,28 +413,28 @@ func Path(u, v config.Vertex, next config.NextHopTable) (path []config.Vertex) { return path } -func (g *IG) SetNHTable(nh config.NextHopTable, table_hash [32]byte) { // set nhTable from supernode +func (g *IG) SetNHTable(nh mtypes.NextHopTable, table_hash [32]byte) { // set nhTable from supernode g.nhTable = nh g.NhTableHash = table_hash g.NhTableExpire = time.Now().Add(g.SuperNodeInfoTimeout) } -func (g *IG) GetNHTable(recalculate bool) config.NextHopTable { +func (g *IG) GetNHTable(recalculate bool) mtypes.NextHopTable { if recalculate && time.Now().After(g.NhTableExpire) { g.RecalculateNhTable(false) } return g.nhTable } -func (g *IG) GetDtst() config.DistTable { +func (g *IG) GetDtst() mtypes.DistTable { return g.dlTable } -func (g *IG) GetEdges(isOld bool, withAC bool) (edges map[config.Vertex]map[config.Vertex]float64) { +func (g *IG) GetEdges(isOld bool, withAC bool) (edges map[mtypes.Vertex]map[mtypes.Vertex]float64) { vert := g.Vertices() - edges = make(map[config.Vertex]map[config.Vertex]float64, len(vert)) + edges = make(map[mtypes.Vertex]map[mtypes.Vertex]float64, len(vert)) for src, _ := range vert { - edges[src] = make(map[config.Vertex]float64, len(vert)) + edges[src] = make(map[mtypes.Vertex]float64, len(vert)) for dst, _ := range vert { if src != dst { if isOld { @@ -432,16 +448,16 @@ func (g *IG) GetEdges(isOld bool, withAC bool) (edges map[config.Vertex]map[conf return } -func (g *IG) GetBoardcastList(id config.Vertex) (tosend map[config.Vertex]bool) { - tosend = make(map[config.Vertex]bool) +func (g *IG) GetBoardcastList(id mtypes.Vertex) (tosend map[mtypes.Vertex]bool) { + tosend = make(map[mtypes.Vertex]bool) for _, element := range g.nhTable[id] { tosend[*element] = true } return } -func (g *IG) GetBoardcastThroughList(self_id config.Vertex, in_id config.Vertex, src_id config.Vertex) (tosend map[config.Vertex]bool) { - tosend = make(map[config.Vertex]bool) +func (g *IG) GetBoardcastThroughList(self_id mtypes.Vertex, in_id mtypes.Vertex, src_id mtypes.Vertex) (tosend map[mtypes.Vertex]bool) { + tosend = make(map[mtypes.Vertex]bool) for check_id, _ := range g.GetBoardcastList(self_id) { for _, path_node := range Path(src_id, check_id, g.nhTable) { if path_node == self_id && check_id != in_id { @@ -474,12 +490,12 @@ func a2n(s string) (ret float64) { return } -func a2v(s string) config.Vertex { +func a2v(s string) mtypes.Vertex { ret, err := strconv.ParseUint(s, 10, 16) if err != nil { panic(err) } - return config.Vertex(ret) + return mtypes.Vertex(ret) } func Solve(filePath string, pe bool) error { @@ -488,9 +504,9 @@ func Solve(filePath string, pe bool) error { return nil } - g := NewGraph(3, false, config.GraphRecalculateSetting{ + g := NewGraph(3, false, mtypes.GraphRecalculateSetting{ NodeReportTimeout: 9999, - }, config.NTPinfo{}, config.LoggerInfo{LogInternal: true}) + }, mtypes.NTPinfo{}, mtypes.LoggerInfo{LogInternal: true}) inputb, err := ioutil.ReadFile(filePath) if err != nil { return err @@ -506,7 +522,7 @@ func Solve(filePath string, pe bool) error { val := a2n(sval) dst := a2v(verts[index+1]) if src != dst && val != Infinity { - g.UpdateLatency(src, dst, S2TD(val), 0, false, false) + g.UpdateLatency(src, dst, val, 99999, 0, false, false) } } } diff --git a/tap/tap_fd.go b/tap/tap_fd.go index 37c4ec0..d371b4c 100644 --- a/tap/tap_fd.go +++ b/tap/tap_fd.go @@ -8,7 +8,7 @@ import ( "os" "strconv" - "github.com/KusakabeSi/EtherGuardVPN/config" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" ) type FdTap struct { @@ -20,7 +20,7 @@ type FdTap struct { } // New creates and returns a new TUN interface for the application. -func CreateFdTAP(iconfig config.InterfaceConf, NodeID config.Vertex) (tapdev Device, err error) { +func CreateFdTAP(iconfig mtypes.InterfaceConf, NodeID mtypes.Vertex) (tapdev Device, err error) { // Setup TUN Config fdRXstr, has := os.LookupEnv("EG_FD_RX") if !has { diff --git a/tap/tap_linux.go b/tap/tap_linux.go index 519508a..b4fc777 100644 --- a/tap/tap_linux.go +++ b/tap/tap_linux.go @@ -24,8 +24,8 @@ import ( "golang.org/x/sys/unix" - "github.com/KusakabeSi/EtherGuardVPN/config" - "github.com/KusakabeSi/EtherGuardVPN/rwcancel" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" + "github.com/KusakabeSi/EtherGuard-VPN/rwcancel" ) const ( @@ -453,7 +453,7 @@ func (tap *NativeTap) Close() error { return err2 } -func CreateTAP(iconfig config.InterfaceConf, NodeID config.Vertex) (Device, error) { +func CreateTAP(iconfig mtypes.InterfaceConf, NodeID mtypes.Vertex) (Device, error) { nfd, err := unix.Open(cloneDevicePath, os.O_RDWR, 0) if err != nil { if os.IsNotExist(err) { @@ -496,7 +496,7 @@ func CreateTAP(iconfig config.InterfaceConf, NodeID config.Vertex) (Device, erro return CreateTAPFromFile(fd, iconfig, NodeID) } -func CreateTAPFromFile(file *os.File, iconfig config.InterfaceConf, NodeID config.Vertex) (Device, error) { +func CreateTAPFromFile(file *os.File, iconfig mtypes.InterfaceConf, NodeID mtypes.Vertex) (Device, error) { tap := &NativeTap{ tapFile: file, events: make(chan Event, 5), diff --git a/tap/tap_sock.go b/tap/tap_sock.go index 49bfd5a..f9e9825 100644 --- a/tap/tap_sock.go +++ b/tap/tap_sock.go @@ -6,7 +6,7 @@ import ( "net" "time" - "github.com/KusakabeSi/EtherGuardVPN/config" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" ) type SockServerTap struct { @@ -17,14 +17,14 @@ type SockServerTap struct { connRx *net.Conn connTx *net.Conn static bool - loglevel config.LoggerInfo + loglevel mtypes.LoggerInfo closed bool events chan Event } // New creates and returns a new TUN interface for the application. -func CreateSockTAP(iconfig config.InterfaceConf, protocol string, NodeID config.Vertex, loglevel config.LoggerInfo) (tapdev Device, err error) { +func CreateSockTAP(iconfig mtypes.InterfaceConf, protocol string, NodeID mtypes.Vertex, loglevel mtypes.LoggerInfo) (tapdev Device, err error) { // Setup TUN Config tap := &SockServerTap{ diff --git a/tap/tap_stdio.go b/tap/tap_stdio.go index 0927330..86c121b 100644 --- a/tap/tap_stdio.go +++ b/tap/tap_stdio.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "github.com/KusakabeSi/EtherGuardVPN/config" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" ) type L2MODE uint8 @@ -51,7 +51,7 @@ func Mac2charForm(m []byte) byte { } // New creates and returns a new TUN interface for the application. -func CreateStdIOTAP(iconfig config.InterfaceConf, NodeID config.Vertex) (tapdev Device, err error) { +func CreateStdIOTAP(iconfig mtypes.InterfaceConf, NodeID mtypes.Vertex) (tapdev Device, err error) { // Setup TUN Config if err != nil { diff --git a/tap/tap_udpsock.go b/tap/tap_udpsock.go index c2f13e5..1d5a0ed 100644 --- a/tap/tap_udpsock.go +++ b/tap/tap_udpsock.go @@ -5,7 +5,7 @@ import ( "fmt" "net" - "github.com/KusakabeSi/EtherGuardVPN/config" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" ) type UdpSockTap struct { @@ -19,7 +19,7 @@ type UdpSockTap struct { } // New creates and returns a new TUN interface for the application. -func CreateUDPSockTAP(iconfig config.InterfaceConf, NodeID config.Vertex) (tapdev Device, err error) { +func CreateUDPSockTAP(iconfig mtypes.InterfaceConf, NodeID mtypes.Vertex) (tapdev Device, err error) { // Setup TUN Config tap := &UdpSockTap{ diff --git a/tap/tap_vpp.go b/tap/tap_vpp.go index cc7a7fd..4a8e265 100644 --- a/tap/tap_vpp.go +++ b/tap/tap_vpp.go @@ -22,7 +22,7 @@ import ( "git.fd.io/govpp.git/extras/libmemif" "golang.org/x/sys/unix" - "github.com/KusakabeSi/EtherGuardVPN/config" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" logger "github.com/sirupsen/logrus" ) diff --git a/tap/tap_vpp_fake.go b/tap/tap_vpp_fake.go index 6bc2079..cbe43b3 100644 --- a/tap/tap_vpp_fake.go +++ b/tap/tap_vpp_fake.go @@ -5,7 +5,7 @@ package tap import ( "errors" - "github.com/KusakabeSi/EtherGuardVPN/config" + "github.com/KusakabeSi/EtherGuard-VPN/mtypes" ) const ( @@ -18,7 +18,7 @@ type VppTap struct { } // New creates and returns a new TUN interface for the application. -func CreateVppTAP(iconfig config.InterfaceConf, NodeID config.Vertex, loglevel string) (tapdev Device, err error) { +func CreateVppTAP(iconfig mtypes.InterfaceConf, NodeID mtypes.Vertex, loglevel string) (tapdev Device, err error) { return nil, errors.New("VPP support disabled.") }